Source code for brazilcep.client

"""
brazilcep.client
~~~~~~~~~~~~~~~~~

This module implements the BrazilCEP client, which provides functionality
to query address information based on Brazilian postal codes (CEP) using
various web services.

Main Features:
- Synchronous and asynchronous methods to fetch address data.
- Support for multiple web services: ViaCEP, ApiCEP, and OpenCEP.
- Automatic formatting of CEP input to ensure valid queries.
- Customizable timeout and proxy support for HTTP requests.

:copyright: (c) 2023 by Michell Stuttgart.
:license: MIT, see LICENSE for more details.
"""

import enum
import re
from typing import Callable, Optional

from . import apicep, opencep, viacep

NUMBERS = re.compile(r"[^0-9]")
DEFAULT_TIMEOUT: int = 5  # in seconds


class WebService(enum.Enum):
    """Enum representing the available web services for CEP queries.

    Attributes:
        VIACEP: ViaCEP web service.
        APICEP: ApiCEP web service.
        OPENCEP: OpenCEP web service.
    """

    VIACEP = 1
    APICEP = 2
    OPENCEP = 3


services: dict[WebService, Callable] = {
    WebService.VIACEP: viacep.fetch_address,
    WebService.APICEP: apicep.fetch_address,
    WebService.OPENCEP: opencep.fetch_address,
}

async_services: dict[WebService, Callable] = {
    WebService.VIACEP: viacep.async_fetch_address,
    WebService.APICEP: apicep.async_fetch_address,
    WebService.OPENCEP: opencep.async_fetch_address,
}


[docs] def get_address_from_cep( cep: str, webservice: WebService = WebService.OPENCEP, timeout: Optional[int] = DEFAULT_TIMEOUT, proxies: Optional[dict] = None, ) -> dict: """ This function queries a specified web service to retrieve address information based on the provided CEP. It supports multiple web services and allows customization of request parameters such as timeout and proxy settings. Args: cep (str): The CEP (Brazilian postal code) to query. Must be a valid 8-digit string. webservice (WebService, optional): The web service to use for the query. Defaults to WebService.OPENCEP. Supported values are: - WebService.OPENCEP - WebService.VIACEP - WebService.APICEP timeout (Optional[int]): Timeout in seconds for the request. Defaults to 5 seconds. timeout (Optional[int], optional): The maximum time, in seconds, to wait for a response. Defaults to 5 seconds. proxies (Optional[dict], optional): A dictionary mapping protocols (e.g., "http", "https") to proxy URLs. Raises: ValueError: If the provided CEP is invalid (e.g., not properly formatted or not 8 digits). KeyError: If the specified webservice is not a valid WebService enum value. Returns: dict: A dictionary containing the address data corresponding to the queried CEP. Examples: >>> address = get_address_from_cep("01001000", webservice=WebService.VIACEP) >>> print(address) { "cep": "01001000", "street": "Praça da Sé", "complement": "lado ímpar", "disctric": "Sé", "city": "São Paulo", "uf": "SP", } """ return services[webservice](_format_cep(cep), timeout=timeout, proxies=proxies)
[docs] async def async_get_address_from_cep( cep: str, webservice: WebService = WebService.OPENCEP, timeout: Optional[int] = DEFAULT_TIMEOUT, proxies: Optional[dict] = None, ) -> dict: """ Asynchronously fetch the address associated with a given CEP (Brazilian postal code). This function queries a specified web service to retrieve address information based on the provided CEP. It supports multiple web services and allows customization of request parameters such as timeout and proxy settings. Args: cep (str): The CEP (Brazilian postal code) to query. Must be a valid 8-digit string. webservice (WebService, optional): The web service to use for the query. Defaults to WebService.OPENCEP. Supported values are: - WebService.OPENCEP - WebService.VIACEP - WebService.APICEP timeout (Optional[int], optional): The maximum time, in seconds, to wait for a response. Defaults to 5 seconds. proxies (Optional[dict], optional): A dictionary mapping protocols (e.g., "http", "https") to proxy URLs. Raises: ValueError: If the provided CEP is invalid (e.g., not properly formatted or not 8 digits). KeyError: If the specified webservice is not a valid WebService enum value. Returns: dict: A dictionary containing the address data corresponding to the queried CEP. Examples: >>> address = await async_get_address_from_cep("01001000", webservice=WebService.VIACEP) >>> print(address) { "cep": "01001000", "street": "Praça da Sé", "complement": "lado ímpar", "disctric": "Sé", "city": "São Paulo", "uf": "SP", } """ return await async_services[webservice](_format_cep(cep), timeout=timeout, proxies=proxies)
def _format_cep(cep: str) -> str: """ Format a Brazilian postal code (CEP) by removing non-numeric characters and validating its structure. This function ensures that the input is a valid CEP by stripping out any characters that are not digits. Args: cep (str): CEP to be formatted. Raises: ValueError: If the input is not a string or is empty. Returns: str: A string containing the formatted CEP. """ if not isinstance(cep, str) or not cep.strip(): raise ValueError("CEP must be a non-empty string.") return NUMBERS.sub("", cep)