Skip to content

adicionado a função de verificação do rg #498

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Utilitário `get_municipality_by_code` [412](https://github.com/brazilian-utils/brutils-python/pull/412)
- Utilitário `get_code_by_municipality_name` [#399](https://github.com/brazilian-utils/brutils-python/issues/399)
- Utilitário `format_currency` [#426](https://github.com/brazilian-utils/brutils-python/issues/426)
- Utilitário `is_valid_rg` [#428](https://github.com/brazilian-utils/brutils-python/issues/428)


## [2.2.0] - 2024-09-12

Expand Down
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1254,6 +1254,43 @@ Exemplo:
None
```

## RG
### is_valid_rg

Valida o Registro Geral (RG) brasileiro, considerando o estado (UF) de emissão.
Esta função recebe uma string de RG e uma Unidade Federativa (UF), e verifica se o
RG está no formato correto para o estado especificado. Cada estado pode ter um formato
diferente de RG, com variações na quantidade de dígitos e a presença de caracteres especiais.
A função também lida com casos como dígitos repetidos ou formatos malformados.

Parâmetros:
rg (str): A string do RG a ser validada.
uf (str): A Unidade Federativa (UF) onde o RG foi emitido.

Retorna:
bool: True se o RG for válido, False caso contrário.

Exemplo:
```python
>>> from brutils import is_valid_rg
>>> is_valid_rg('12.345.678-9', 'SP')
True
>>> is_valid_rg('MG-12.345.678', 'MG')
True
>>> is_valid_rg('123456789', 'RJ')
False
>>> is_valid_rg('A12345678', 'SP')
False
>>> is_valid_rg('12.345.678', 'SP') # Missing verifier digit
False
>>> is_valid_rg('111111111', 'SP') # Repeated digits
False
>>> is_valid_rg('', 'SP') # Empty string
False
>>> is_valid_rg('12.345.678-9', 'XX') # Invalid UF
False


# Novos Utilitários e Reportar Bugs

Caso queira sugerir novas funcionalidades ou reportar bugs, basta criar
Expand Down
36 changes: 36 additions & 0 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,42 @@ Example:
None
```

## RG
### is_valid_rg

Validates the Brazilian Identity Card number (RG) based on the state (UF) of issuance.
This function takes a string of RG and a Federal Unit (UF) and checks if the RG is in the correct format
for the specified state. Each state may have a different RG format, with variations in the number of digits
and the presence of special characters. The function also handles cases such as repeated digits or malformed formats.

Parameters:
rg (str): The RG string to be validated.
uf (str): The Federal Unit (UF) where the RG was issued.

Returns:
bool: True if the RG is valid, False otherwise.

Example:
```python
>>> from brutils import is_valid_rg
>>> is_valid_rg('12.345.678-9', 'SP')
True
>>> is_valid_rg('MG-12.345.678', 'MG')
True
>>> is_valid_rg('123456789', 'RJ')
False
>>> is_valid_rg('A12345678', 'SP')
False
>>> is_valid_rg('12.345.678', 'SP') # Missing verifier digit
False
>>> is_valid_rg('111111111', 'SP') # Repeated digits
False
>>> is_valid_rg('', 'SP') # Empty string
False
>>> is_valid_rg('12.345.678-9', 'XX') # Invalid UF
False


# Feature Request and Bug Report

If you want to suggest new features or report bugs, simply create
Expand Down
5 changes: 5 additions & 0 deletions brutils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
from brutils.voter_id import generate as generate_voter_id
from brutils.voter_id import is_valid as is_valid_voter_id

# RG Imports
from brutils.rg import is_valid_rg

# Defining __all__ to expose the public methods
__all__ = [
# CEP
Expand Down Expand Up @@ -133,4 +136,6 @@
"is_holiday",
# Currency
"format_currency",
# RG
"is_valid_rg",
]
74 changes: 74 additions & 0 deletions brutils/rg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import re

def is_valid_rg(rg: str, uf: str) -> bool:
"""
Validates a Brazilian RG (Registro Geral) based on the state (UF).

This function checks whether a given RG is valid for a specific state in Brazil.
Each state may have its own RG format, and this function handles these differences.

Args:
rg (str): The RG number to be validated.
uf (str): The state (UF) where the RG was issued.

Returns:
bool: Returns True if the RG is valid, False otherwise.

Example:
>>> is_valid_rg("12.345.678-9", "SP")
True
>>> is_valid_rg("MG-12.345.678", "MG")
True
>>> is_valid_rg("12345678-9", "RJ")
False
>>> is_valid_rg("A12345678", "SP")
False
>>> is_valid_rg("12.345.678", "SP")
False
"""
if not isinstance(rg, str) or not isinstance(uf, str):
return False

uf = uf.upper()
rg = re.sub(r'[^0-9A-Za-z]', '', rg) # Remove special characters

uf_rg_formats = {
"AC": r"^\d{2}\.?\d{3}\.?\d{3}-?[0-9Xx]$",
"AL": r"^\d{2}\.?\d{3}\.?\d{3}$",
"AP": r"^\d{9}$",
"AM": r"^\d{2}\.?\d{3}\.?\d{3}$",
"BA": r"^\d{2}\.?\d{3}\.?\d{3}$",
"CE": r"^\d{2}\.?\d{3}\.?\d{3}-?[0-9Xx]$",
"DF": r"^\d{7}$",
"ES": r"^\d{2}\.?\d{3}\.?\d{3}$",
"GO": r"^\d{2}\.?\d{3}\.?\d{3}$",
"MA": r"^\d{2}\.?\d{3}\.?\d{3}$",
"MT": r"^\d{2}\.?\d{3}\.?\d{3}$",
"MS": r"^\d{2}\.?\d{3}\.?\d{3}$",
"MG": r"^MG-\d{2}\.?\d{3}\.?\d{3}$",
"PA": r"^\d{2}\.?\d{3}\.?\d{3}$",
"PB": r"^\d{2}\.?\d{3}\.?\d{3}$",
"PR": r"^\d{2}\.?\d{3}\.?\d{3}-?[0-9Xx]$",
"PE": r"^\d{9}$",
"PI": r"^\d{2}\.?\d{3}\.?\d{3}$",
"RJ": r"^\d{2}\.?\d{3}\.?\d{3}$",
"RN": r"^\d{2}\.?\d{3}\.?\d{3}$",
"RS": r"^\d{1,2}\.\d{3}\.\d{3}$",
"RO": r"^\d{2}\.?\d{3}\.?\d{3}$",
"RR": r"^\d{9}$",
"SC": r"^\d{2}\.?\d{3}\.?\d{3}$",
"SP": r"^\d{2}\.?\d{3}\.?\d{3}-?[0-9Xx]$",
"SE": r"^\d{2}\.?\d{3}\.?\d{3}$",
"TO": r"^\d{2}\.?\d{3}\.?\d{3}$",
}

if uf not in uf_rg_formats:
return False # Invalid or unsupported UF

if not re.match(uf_rg_formats[uf], rg):
return False # Invalid format for the UF

if len(set(rg)) == 1:
return False # Avoid repetitive sequences (e.g., 111111111)

return True
56 changes: 56 additions & 0 deletions tests/test_rg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import unittest
from brutils.rg import is_valid_rg

class TestIsValidRG(unittest.TestCase):
"""
Unit tests for the is_valid_rg function.

This test suite checks the validity of different RG formats
for all Brazilian states.
"""

def test_is_valid_rg(self):
valid_rgs = {
"AC": "12.345.678-9", "AL": "12.345.678", "AP": "123456789", "AM": "12.345.678",
"BA": "12.345.678", "CE": "12.345.678-9", "DF": "1234567", "ES": "12.345.678",
"GO": "12.345.678", "MA": "12.345.678", "MT": "12.345.678", "MS": "12.345.678",
"MG": "MG-12.345.678", "PA": "12.345.678", "PB": "12.345.678", "PR": "12.345.678-9",
"PE": "123456789", "PI": "12.345.678", "RJ": "12.345.678", "RN": "12.345.678",
"RS": "1.234.567", "RO": "12.345.678", "RR": "123456789", "SC": "12.345.678",
"SP": "12.345.678-9", "SE": "12.345.678", "TO": "12.345.678"
}
for uf, rg in valid_rgs.items():
with self.subTest(uf=uf):
self.assertTrue(is_valid_rg(rg, uf))

def test_invalid_rg_format(self):
self.assertFalse(is_valid_rg("A12345678", "SP"))
self.assertFalse(is_valid_rg("1234567890", "SP"))
self.assertFalse(is_valid_rg("12.345.678-10", "SP"))
self.assertFalse(is_valid_rg("", "SP"))
self.assertFalse(is_valid_rg("12.345.678", "SP"))
self.assertFalse(is_valid_rg("12 345 678", "SP"))
self.assertFalse(is_valid_rg("12.345.678 9", "SP"))

def test_invalid_rg_state(self):
self.assertFalse(is_valid_rg("12.345.678-9", "XX"))

def test_repeated_digits(self):
for uf in ["SP", "RJ", "MG", "BA", "PR"]:
with self.subTest(uf=uf):
self.assertFalse(is_valid_rg("111111111", uf))
self.assertFalse(is_valid_rg("222222222", uf))

def test_edge_cases(self):
self.assertFalse(is_valid_rg(None, "SP"))
self.assertFalse(is_valid_rg(123456789, "SP"))
self.assertFalse(is_valid_rg("12.345.678-9", None))
self.assertFalse(is_valid_rg("12.345.678-9", 123))

def test_invalid_digit_verifier(self):
self.assertFalse(is_valid_rg("12.345.678-0", "SP"))
self.assertFalse(is_valid_rg("MG-12.345.679", "MG"))

def test_rg_with_special_characters(self):
self.assertTrue(is_valid_rg("12.345.678-9", "SP"))
self.assertTrue(is_valid_rg("12/345.678-9", "SP"))
Loading