diff options
| author | Murilo Ijanc <[email protected]> | 2026-07-27 20:32:01 -0300 |
|---|---|---|
| committer | Murilo Ijanc <[email protected]> | 2026-07-27 20:32:01 -0300 |
| commit | b199ae044f8f9cd4b745214cd5e5495f86b5eb54 (patch) | |
| tree | a8e7a134e77381b11091126a8946208e2e6afbcb /README.md | |
| parent | a82459630e957a8d94c375394dae66734f3c90c1 (diff) | |
| download | python-5295ba01f58987277c1e8531fc62619658f17eb8.tar.gz | |
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.md | 40 |
1 files changed, 40 insertions, 0 deletions
@@ -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. |