Package: simplecep
simpleCEPReliably resolve Brazilian CEP addresses using multiple APIs.WhyECT (Correios Company) doesn't open their CEP (Brazilian Zip Codes) data, requiring
systems to fetch CEP data individually through their API or buying the full
database from their website.Correios API (SIGEPWeb) is known for its outages, which impacts systems which
relies on resolving CEPs as addresses, as e-commerces.This library addresses the problem using alternative CEP data APIs as fallbacks
when Correios API doesn't respond in time and caching all received results.How it worksThe library uses the configured CEP data providers to fetch the CEP address.
Each installed provider is used until the data is successfully fetched.It will try to get the CEP address using Correios official API and if
it fails it will use third-party API as fallbacks.By default, it uses the following CEP APIs:https://www.republicavirtual.com.brhttps://viacep.com.br/Both APIs are queried concurrently using threads, and the first received result is used.After fetched, the retrieved address data is cached so any address-retrieval
attempt for the same CEP is resolved immediately and won't use external
providers.The used providers, their order, and the cache mechanism can be fully
customized.If the CEP data isn't cached and all providers fail to retrieve it,
theCouldNotResolveCepErrorexception is raised.UsageInstallationInstall from PyPIpip install simplecepUsing the default configThe package provides a ready-to-useresolve_cepfunction which will
try to, in order:Get the CEP address from the internal cacheGet the CEP address from the official Correios APIGet the CEP address, in parallel, from third-party CEP APIs:https://www.republicavirtual.com.brhttps://viacep.com.br/It will stop on success, and the subsequent steps won't be executed.
By default, it will wait 2 seconds for each provider.Example:>>fromsimplecepimportresolve_cep>>address=resolve_cep('59615350')>>address<CEPAddress59615-350>>>address.to_dict(){'cep':'59615-350','street':'Rua João Simão do Nascimento','district':'Santa Delmira','city':'Mossoró','state':'RN'}TheCEPAddressclass provides the address fields in both English and
Brazilian Portuguese names:>>address<CEPAddress59615-350>>>address.street'Rua João Simão do Nascimento'>>address.rua'Rua João Simão do Nascimento'>>address.city==address.cidadeTrue>>address.to_dict(br_names=True){'cep':'59615-350','rua':'Rua João Simão do Nascimento','bairro':'Santa Delmira','cidade':'Mossoró','estado':'RN'}CustomizationIf you need to use the providers in a different order, a custom
provider, a different cache mechanism or change the timeout, a new
resolver instance can be created using theCEPResolverclass.Here's how the defaultresolve_cepfunction is created:fromsimplecepimport(CEPResolver,correios_sigep_cep_provider,republicavirtual_cep_provider,viacep_cep_provider)resolve_cep=CEPResolver(providers=[# this resolver will first try to use the Correios API,{correios_sigep_cep_provider},# if it fails it will fall back to the RepublicaVirtual and ViaCEP APIs# it will spawn two threads and will query both APIs at the same time# the result from the first one to reply will be used{republicavirtual_cep_provider,viacep_cep_provider},],# by default it will wait for each provider for 1 secondtimeout=2,# all fetched CEP data will be stored in the# cache object which is a dict but can be any dict-like objectcache={})Providers OrderTheprovidersargument should be a list of sets specifying which
providers should be used, and the order they should be called.When called, the resolver iterate over the list calling all providers in
each set concurrently using threads.When the CEP is successfully resolved by a provider, the iteration stops
and the following provider sets are not executed.Here's an example ofprovidersparam which will query all APIs
concurrently and use the first received result:brute_resolver=CEPResolver(providers=[{correios_sigep_cep_provider,republicavirtual_cep_provider,viacep_cep_provider}])Custom providersCustom providers can be used to fetch CEP data from different sources.The provider should be a callable which acceptscepandtimeoutas
parameters and returns aCEPAddressobject when a CEP is found andNonewhen the CEP doesn't exist:defmy_custom_provder(cep:str,timeout:float)->Optional[CEPAdress]:pass# my implementation hereCustom providers should raise theCEPProviderUnavailableErrorerror
when they fail to contact their data source or if the data source
doesn't reply before the specifiedtimeoutinterval.Provider-auxiliary functions are available in thesimplecep.providers.commonsmodule.Custom cacheBy default, a dict object is used as cache, it's good enough to avoid
querying for the same CEP twice in the same process, but it has limitations as:Different processes can't share the cache (i.e. web-workers)The cache is destroyed when the process is killedSo a custom object can be used as cache, it needs to be a dict-like object
(i.e. implements__getitem__and__setitem__).A good example is theredis-dictproject which creates a dict-like object
which stores the values on Redis:https://pypi.org/project/redis-dict/TestingTests are found in thetestsfolder. Install the requirements in
thedev_requirements.txtfile and runmake testto run the tests.LicenseSeeLicense.History0.1.1 (2021-03-29)CEPAddress now supports Brazilian address fields names (estado, cidade, bairro, rua)Updatecapture_real_responses.pytest-script to not double-request providersClean RepublicVirtual provider "address" field0.1.0 (2021-03-12)First release on PyPI