Skip to content

Commit

Permalink
refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
davidpeckham committed Feb 1, 2024
1 parent b09db7b commit 7e29e96
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 24 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ Added
Changed
~~~~~~~
* Renamed GitHub workflows as .yml (from .yaml)
* The method :meth:`.VIN.is_vin_character` now returns False instead of raising ValueError
* Fixed VIN_CHARACTERS assignment in constants.py
* Inlined :meth:`.VIN.is_vin_character` in the default constructor
* Converted property :meth:`.VIN.check_digit` to class method :meth:`.VIN.calculate_check_digit`
* Converted ``constants.VIN_CHARACTERS`` from list to string

`0.0.1`_ - 2024-01-31
---------------------
Expand Down
36 changes: 16 additions & 20 deletions src/vin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,29 @@ class VIN:
"""

def __init__(self, vehicle_identification_number: str) -> None:
def __init__(self, vin: str) -> None:
"""create a VIN"""
if not isinstance(vehicle_identification_number, str):
if not isinstance(vin, str):
raise TypeError("VIN must be a string")
self.vin: str = vehicle_identification_number
if len(self.vin) != VIN_LENGTH:
if len(vin) != VIN_LENGTH:
raise ValueError(f"VIN must be exactly {VIN_LENGTH} characters long")
if self.is_vin_character(self.vin):
if not all(c in VIN_CHARACTERS for c in vin):
raise ValueError(f"VIN must have only these characters {VIN_CHARACTERS}")
if self.vin[8:9] != self.check_digit:
if vin[8:9] != self.calculate_check_digit(vin):
raise ValueError("VIN check digit is incorrect")
self.vin: str = vin
return

def is_vin_character(self, vin) -> bool:
""" "return True if vin only has VIN characters"""
return all(c in VIN_CHARACTERS for c in vin)
@classmethod
def calculate_check_digit(cls, vin: str) -> str:
"""Calculate and return the VIN check digit"""
total = 0
for n in range(VIN_LENGTH):
if n == VIN_CHECK_DIGIT_POSITION:
continue
letter = vin[n]
total = total + VIN_CHARACTER_VALUES[letter] * VIN_POSITION_WEIGHTS[n]
return VIN_CHECK_DIGIT_CHARACTERS[total % 11]

@property
def wmi(self) -> str:
Expand Down Expand Up @@ -189,17 +196,6 @@ def model_year(self):

return model_year

@property
def check_digit(self) -> str:
"""Calculate and return the VIN check digit"""
total = 0
for n in range(VIN_LENGTH):
if n == VIN_CHECK_DIGIT_POSITION:
continue
letter = self.vin[n]
total = total + VIN_CHARACTER_VALUES[letter] * VIN_POSITION_WEIGHTS[n]
return VIN_CHECK_DIGIT_CHARACTERS[total % 11]

def __repr__(self) -> str:
return f"VIN({self!s})"

Expand Down
2 changes: 1 addition & 1 deletion src/vin/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"Z": 9,
}

VIN_CHARACTERS: list[str] = list(VIN_CHARACTER_VALUES.keys())
VIN_CHARACTERS: str = "".join(VIN_CHARACTER_VALUES.keys())

VIN_POSITION_WEIGHTS: list[int] = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2]

Expand Down
4 changes: 3 additions & 1 deletion tests/test_vin.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,7 @@ def test_model_year(vehicle: dict) -> None:


def test_raises_error_when_not_a_string() -> None:
with pytest.raises(ValueError, match="VIN contains non-VIN characters"):
with pytest.raises(
ValueError, match="VIN must have only these characters 0123456789ABCDEFGHJKLMNPRSTUVWXYZ"
):
VIN("5FQYF5H59HBO1I946")

0 comments on commit 7e29e96

Please sign in to comment.