summaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
authorMurilo Ijanc <[email protected]>2026-07-27 20:32:01 -0300
committerMurilo Ijanc <[email protected]>2026-07-27 20:32:01 -0300
commitb199ae044f8f9cd4b745214cd5e5495f86b5eb54 (patch)
treea8e7a134e77381b11091126a8946208e2e6afbcb /README.md
parenta82459630e957a8d94c375394dae66734f3c90c1 (diff)
downloadpython-0.2.0.tar.gz
Carry the municipality of a CEP that does not existHEADv0.2.0main
A failing CEP is rarely random: it is someone who knows the city and guessed the number, and the classic guess is the -000 that 957 municipalities never received. The API now answers those 404s with a faixa block naming the municipality the CEP would have belonged to, so a caller can ask "did you mean somewhere in Areal/RJ?" instead of "invalid CEP". CEPNotFound gains faixa, defaulting to None. It stays a 404 and stays an exception — the field is context for the error, never a demotion of it into a partial success. Parsing is deliberately total: anything missing, empty or malformed under faixa yields None, because turning a clean not-found into a parse failure over an optional courtesy field would be strictly worse than not having the field at all. Faixa's cep_ini/cep_fim are the smallest and largest CEP that actually exist there, not the bounds the Correios publish, and the range in between is sparse — hence ceps, so the pair is never read as a list of valid numbers.
Diffstat (limited to 'README.md')
-rw-r--r--README.md40
1 files changed, 40 insertions, 0 deletions
diff --git a/README.md b/README.md
index dba6aa2..20f2cfa 100644
--- a/README.md
+++ b/README.md
@@ -184,6 +184,46 @@ except CepisError:
so code already handling those types during input validation keeps working
without knowing this library exists.
+### Which municipality the CEP would have been in
+
+A CEP that fails is rarely random: it is usually someone who knows the city and
+guessed the number — and the classic guess is the `-000` that 957
+municipalities never received. So `CEPNotFound` carries `faixa`, the
+municipality that CEP would have belonged to, when the API can work it out:
+
+```python
+try:
+ address = cepis.lookup("25845-000")
+except CEPNotFound as exc:
+ if exc.faixa:
+ f = exc.faixa
+ f.localidade # 'Areal'
+ f.uf # 'RJ'
+ f.estado # 'Rio de Janeiro'
+ f.regiao # 'Sudeste'
+ f.ibge # '3300225'
+ f.label # 'Areal/RJ'
+ f.cep_ini # '25845001'
+ f.cep_fim # '25849899'
+ f.ceps # 118
+ print(f"That CEP does not exist. Did you mean somewhere in {f.label}?")
+```
+
+Three things about it:
+
+- **It is still a 404.** `faixa` is context for the error, never an address.
+ `lookup` raises exactly as before; nothing here says the CEP exists.
+- **`cep_ini` and `cep_fim` are the CEPs that really exist**, not the bounds
+ the Correios publish. The DNE's own start for Areal is `25845000` — precisely
+ the CEP that just failed, which is why the range starts one above it.
+- **The range is sparse.** Areal's 118 CEPs are scattered across the ~4,900
+ numbers between `25845001` and `25849899`. That is what `ceps` is for: never
+ read the pair as a list of valid CEPs, and do not iterate it.
+
+`faixa` is `None` when the CEP falls in a band no municipality owns — the API
+**omits** the field there rather than sending null — and also when talking to
+an API older than the field. Always test it before use.
+
`InvalidResponse` almost always means something between you and the API is
answering instead of it — a captive Wi-Fi portal, a corporate proxy, an HTML
error page. Useful as a diagnosis: the problem is not in your code.