Skip to content
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
22 changes: 21 additions & 1 deletion test/vin_parser_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,28 @@ def manufs ():

return True

def invalid ():
vinl = ["", "AAA", "JM1BL1M72C158742", "1FTEW1CM9BFA745571",
"VIN6135B660801530", "IOQZZZSNZY1063363"]

for vin in vinl:

cont = vp.continent(vin)
assert cont == False, f"continent({vin}) == False. Got {cont}"
count = vp.country(vin)
assert count == False, f"country({vin}) == False. Got {count}"
year = vp.year(vin)
assert year == False, f"year({vin}) == False. False {year}"
manuf = vp.manuf(vin)
assert manuf == False, f"manuf({vin}) == False. Got {manuf}"
wmi = vp.wmi(vin)
assert wmi == False, f"wmi({vin}) == False. Got {wmi}"
vis = vp.vis(vin)
assert vis == False, f"vis({vin}) == False. Got {vis}"
assert vp.is_valid(vin) == False, f"is_valid({vin})"
return True
if __name__ == "__main__":
ALL_TESTS = [vin1, vin2, vin3, vin4, years, manufs]
ALL_TESTS = [vin1, vin2, vin3, vin4, years, manufs, invalid]
i = 0
for t in ALL_TESTS:
if not t():
Expand Down
28 changes: 28 additions & 0 deletions vin_parser/core.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from functools import reduce
from operator import add
import csv
import re
from pkg_resources import resource_filename
from datetime import datetime as dt

Expand All @@ -13,12 +14,29 @@ def wrapped(vin):
wrapped.__doc__ = func.__doc__
return wrapped

def valid(func):
def wrapped(vin):
# cant be empty
if type(vin) != str:
return False
# len should be 17
if len(vin) != 17:
return False
# cant have letters IOQ
if re.search('[IOQ]',vin) != None:
return False

return func(vin)
wrapped.__doc__ = func.__doc__
return wrapped

@upper
def check_no(vin):
'''Returns the VIN check digit (9th position)'''
return vin[8] # Is only meaningful for NA and China market cars.

@upper
@valid
def check_valid (vin):
'''Returns True if VIN check digit is valid or False otherwise'''
vals = {k:v for k, v in zip(CHARS, list(range(1,9)) + list(range(1,6)) + [7, 9] + list(range(2,10)) + list(range(1,10)) + [0])}
Expand All @@ -30,6 +48,7 @@ def check_valid (vin):
return str(check_digit) == check_no(vin)

@upper
@valid
def continent (vin):
'''Returns the continent associated with the VIN or None'''
x = vin[0]
Expand All @@ -47,6 +66,7 @@ def continent (vin):
return "South America"

@upper
@valid
def country (vin):
'''Returns the country associated with the VIN or `unassigned`.
Returns None if first two characters in VIN contain illegal characters'''
Expand Down Expand Up @@ -291,6 +311,7 @@ def country (vin):
return "unassigned"

@upper
@valid
def year (vin):
'''Returns the vehicle model year'''
year_ch = (c for c in CHARS if c not in "UZ0")
Expand All @@ -312,6 +333,7 @@ def year (vin):
return c[1]

@upper
@valid
def is_valid (vin):
'''Returns True if VIN is valid'''
if continent(vin) == "North America":
Expand All @@ -327,6 +349,7 @@ def is_valid (vin):
country(vin) != "unassigned"

@upper
@valid
def small_manuf (vin):
'''Returns True if manufacturer builds a limited number of vehicles a year.
The limit varies globally.'''
Expand All @@ -336,6 +359,7 @@ def small_manuf (vin):
return False

@upper
@valid
def wmi (vin):
'''Returns the World Manufacturer Identifier.'''
if vin[2] == "9":
Expand All @@ -344,11 +368,13 @@ def wmi (vin):
return vin[:3]

@upper
@valid
def vds (vin):
'''Returns the Vehicle Descriptor Section.'''
return vin[3:9]

@upper
@valid
def vis (vin):
'''Returns the Vehicle Identifier Section.'''
return vin[9:]
Expand All @@ -360,13 +386,15 @@ def _get_wmicsv():
return {ml[i][0].strip(): ml[i][1].strip() for i in range(1,len(ml))}

@upper
@valid
def manuf (vin):
'''Returns the manufacturer.'''
manfs = _get_wmicsv()
w = wmi (vin)
return manfs.get(w[:2]) or manfs.get(w)

@upper
@valid
def seq_no (vin):
'''Returns the vehicle sequence number.'''
if small_manuf(vin):
Expand Down