Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added

- Script PowerShell `setup_windows.ps1` que instala automaticamente o Poetry e configura as dependências no Windows. [#639](https://github.com/brazilian-utils/python/issues/639)
- Utilitário `convert_name_to_uf`
- Utilitário `is_valid_legal_nature` [#641](https://github.com/brazilian-utils/python/issues/641)
- Utilitário `get_legal_nature_description` [#641](https://github.com/brazilian-utils/python/issues/641)
Expand Down
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,33 @@ desenvolvimento de aplicações para o business Brasileiro.
pip install brutils
```

## Instalação para Usuários Windows 🪟

Atualmente, o **Brazilian Utils** não possui suporte nativo completo para Windows. Para simplificar a instalação e execução do projeto, criamos um **script PowerShell (`setup_windows.ps1`)** que cuida de toda a configuração necessária.

### Requisitos

Antes de rodar o script, o usuário precisa ter:

- **Sistema Operacional:** Windows 11
- **Python 3.9 ou superior**
- Pode ser a versão instalada via Microsoft Store ou a versão tradicional baixada do site oficial
- **Poetry:** será instalado automaticamente pelo script, caso ainda não esteja presente

> Não é necessário instalar Makefile, Chocolatey ou usar WSL. O script faz toda a detecção, instalação e configuração automaticamente.

### Passos para Instalação e Configuração

1. Clone o repositório:
```bash
git clone <URL_DO_REPO>
cd brazilian-utils
```
2. Execute o script PowerShell:
```powershell
.\setup_windows.ps1
```

# Utilização

Para usar um de nossos utilitários, basta importar a função necessária, como no exemplo abaixo:
Expand Down
29 changes: 29 additions & 0 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,35 @@ the development of applications for the Brazilian business.
pip install brutils
```

## Installation for Windows Users 🪟

Currently, **Brazilian Utils** does not have full native support for Windows.
To simplify the setup and execution of the project, we created a **PowerShell script (`setup_windows.ps1`)** that handles all the required configuration automatically.

### Requirements

Before running the script, make sure you have:

- **Operating System:** Windows 11
- **Python 3.9 or higher**
- You can use either the version installed via Microsoft Store or the standard one downloaded from the official website
- **Poetry:** it will be automatically installed by the script if not already present

> There’s no need to install Makefile, Chocolatey, or use WSL.
> The script automatically detects your environment, installs the required dependencies, and sets up everything for you.

### Installation and Setup Steps

1. Clone the repository:
```bash
git clone <REPO_URL>
cd brazilian-utils
```
2. Run the PowerShell script:
```powershell
.\setup_windows.ps1
```

# Usage

To use one of our utilities you just need to import the required function as in the example below:
Expand Down
205 changes: 205 additions & 0 deletions brutils/boleto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
from random import randint

# FORMATTING
############


def sieve(dirty: str) -> str:
"""
Removes specific symbols from a CPF (Brazilian Individual Taxpayer Number)
string.

This function takes a CPF string as input and removes all occurrences of
the '.', '-' characters from it.

Args:
cpf (str): The CPF string containing symbols to be removed.

Returns:
str: A new string with the specified symbols removed.

Example:
>>> sieve("123.456.789-01")
'12345678901'
>>> sieve("987-654-321.01")
'98765432101'

.. note::
This method should not be used in new code and is only provided for
backward compatibility.
"""

return "".join(filter(lambda char: char not in ".-", dirty))


def remove_symbols(dirty: str) -> str:
"""
Alias for the `sieve` function. Better naming.

Args:
cpf (str): The CPF string containing symbols to be removed.

Returns:
str: A new string with the specified symbols removed.
"""

return sieve(dirty)


def display(boleto: str) -> str:
boleto = remove_symbols(boleto)

if not boleto.isdigit() or len(boleto) != 47 or len(set(boleto)) == 1:
return None

return "{}.{} {}.{} {}.{} {} {}".format(boleto[:5], boleto[5:10], boleto[10:15], boleto[15:21], boleto[21:26], boleto[26:32], boleto[32:33], boleto[33:])


def format_boleto(boleto: str) -> str:

if not is_valid(boleto):
return None

return "{}.{} {}.{} {}.{} {} {}".format(boleto[:5], boleto[5:10], boleto[10:15], boleto[15:21], boleto[21:26], boleto[26:32], boleto[32:33], boleto[33:])



# OPERATIONS
############


def validate(boleto: str) -> bool:
"""
Validate the checksum digits of a CPF.

This function checks whether the verifying checksum digits of the given CPF
match its base number. The input should be a digit string of the proper
length.

Args:
cpf (str): A numbers-only CPF string.

Returns:
bool: True if the checksum digits are valid, False otherwise.

Example:
>>> validate("82178537464")
True
>>> validate("55550207753")
True

.. note::
This method should not be used in new code and is only provided for
backward compatibility.
"""

if not cpf.isdigit() or len(cpf) != 11 or len(set(cpf)) == 1:
return False

return all(_hashdigit(cpf, i + 10) == int(v) for i, v in enumerate(cpf[9:]))


def is_valid(cpf: str) -> bool:
"""
Returns whether or not the verifying checksum digits of the given `˜CPF`
match its base number.

This function does not verify the existence of the CPF; it only
validates the format of the string.

Args:
cpf (str): The CPF to be validated, a 11-digit string

Returns:
bool: True if the checksum digits match the base number,
False otherwise.

Example:
>>> is_valid("82178537464")
True
>>> is_valid("55550207753")
True
"""

return isinstance(cpf, str) and validate(cpf)


def generate() -> str:
"""
Generate a random valid CPF digit string.

This function generates a random valid CPF string.

Returns:
str: A random valid CPF string.

Example:
>>> generate()
"10895948109"
>>> generate()
"52837606502"
"""

base = str(randint(1, 999999998)).zfill(9)

return base + _checksum(base)


def _hashdigit(cpf: str, position: int) -> int:
"""
Compute the given position checksum digit for a CPF.

This function computes the specified position checksum digit for the CPF
input.
The input needs to contain all elements previous to the position, or the
computation will yield the wrong result.

Args:
cpf (str): A CPF string.
position (int): The position to calculate the checksum digit for.

Returns:
int: The calculated checksum digit.

Example:
>>> _hashdigit("52599927765", 11)
5
>>> _hashdigit("52599927765", 10)
6
"""

val = (
sum(
int(digit) * weight
for digit, weight in zip(cpf, range(position, 1, -1))
)
% 11
)

return 0 if val < 2 else 11 - val


def _checksum(basenum: str) -> str:
"""
Compute the checksum digits for a given CPF base number.

This function calculates the checksum digits for a given CPF base number.
The base number should be a digit string of adequate length.

Args:
basenum (str): A digit string of adequate length.

Returns:
str: The calculated checksum digits.

Example:
>>> _checksum("335451269")
'51'
>>> _checksum("382916331")
'26'
"""

verifying_digits = str(_hashdigit(basenum, 10))
verifying_digits += str(_hashdigit(basenum + verifying_digits, 11))

return verifying_digits
66 changes: 66 additions & 0 deletions setup_windows.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
Write-Host "Verificando Python disponivel..." -ForegroundColor Cyan

# - Procura todos os executáveis python no PATH
$pythonPaths = Get-Command python* -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Source

# - Filtra versões >= 3.9
$pythonPaths = $pythonPaths | ForEach-Object {
$versionOutput = & $_ --version 2>&1
if ($versionOutput -match "Python (\d+)\.(\d+)\.(\d+)") {
$major = [int]$matches[1]
$minor = [int]$matches[2]
if ($major -eq 3 -and $minor -ge 9) { $_ }
}
}

# Pega a versão mais alta disponível
$pythonPath = $pythonPaths | Sort-Object -Descending | Select-Object -First 1

if (-not $pythonPath) {
Write-Host " Nenhum Python 3.9+ encontrado. Instale o Python e tente novamente." -ForegroundColor Red
exit 1
}

Write-Host " Python encontrado em $pythonPath" -ForegroundColor Green

# - Verifica se o Poetry já está instalado
$possiblePoetryPaths = @(
"$env:APPDATA\Python\Scripts\poetry.exe",
"$env:APPDATA\Roaming\Python\Scripts\poetry.exe",
"$env:LOCALAPPDATA\pypoetry\venv\Scripts\poetry.exe"
)

$poetryPath = $possiblePoetryPaths | Where-Object { Test-Path $_ } | Select-Object -First 1

# - Instala o Poetry se não encontrado
if (-not $poetryPath) {
Write-Host " Poetry nao encontrado. Instalando..." -ForegroundColor Yellow
try {
(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | & $pythonPath -
Start-Sleep -Seconds 5

# tenta localizar após instalação
$poetryPath = $possiblePoetryPaths | Where-Object { Test-Path $_ } | Select-Object -First 1

if ($poetryPath) {
Write-Host " Poetry instalado com sucesso em $poetryPath" -ForegroundColor Green
} else {
Write-Host " Erro: instalacao do Poetry parece ter falhado." -ForegroundColor Red
exit 1
}
} catch {
Write-Host " Erro durante a instalacao do Poetry: $_" -ForegroundColor Red
exit 1
}
} else {
Write-Host " Poetry ja esta instalado em $poetryPath" -ForegroundColor Green
}

# - Adiciona ao PATH temporariamente
$env:PATH += ";" + (Split-Path $poetryPath)

# - Instala dependências e roda projeto
Write-Host " Instalando dependencias do projeto..." -ForegroundColor Cyan
& $poetryPath install

Write-Host " instalacao finalizada!" -ForegroundColor Green
Loading