From 1f6134a6c585fdb3fcefbade5831c71339930c76 Mon Sep 17 00:00:00 2001 From: "ehsanf@gmail.com" Date: Sat, 2 Nov 2013 23:13:20 -0400 Subject: [PATCH 1/4] Adding manufacturer field --- README.rst | 3 +- libvin/decoding.py | 12 +- libvin/wmi_map.py | 265 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 277 insertions(+), 3 deletions(-) create mode 100644 libvin/wmi_map.py diff --git a/README.rst b/README.rst index d56d257..8a44ac3 100644 --- a/README.rst +++ b/README.rst @@ -34,6 +34,8 @@ Low level API example Canada >>> v.year 2006 + >>> v.manufacturer + Honada Canda >>> v.is_pre_2010 True >>> v.wmi @@ -48,7 +50,6 @@ Low level API example False - Methods ------- diff --git a/libvin/decoding.py b/libvin/decoding.py index a8d4d77..013d846 100644 --- a/libvin/decoding.py +++ b/libvin/decoding.py @@ -4,7 +4,7 @@ """ from libvin.static import * - +from libvin import wmi_map class Vin(object): def __init__(self, vin): @@ -132,6 +132,15 @@ def wmi(self): """ return self.vin[0:3] + @property + def manufacturer(self): + wmi = self.wmi + if wmi[:3] in wmi_map.WMI_MAP: + return wmi_map.WMI_MAP[wmi[:3]] + if wmi[:2] in wmi_map.WMI_MAP: + return wmi_map.WMI_MAP[wmi[:2]] + return 'Unknown' + @property def year(self): """ @@ -140,7 +149,6 @@ def year(self): if self.is_pre_2010: return YEARS_CODES_PRE_2010[self.vin[9]] else: - print self.vin[9] return YEARS_CODES_PRE_2040[self.vin[9]] diff --git a/libvin/wmi_map.py b/libvin/wmi_map.py new file mode 100644 index 0000000..df08be4 --- /dev/null +++ b/libvin/wmi_map.py @@ -0,0 +1,265 @@ +WMI_MAP = { + 'AFA': 'Ford South Africa', + 'AAV': 'Volkswagen South Africa', + 'JA3': 'Mitsubishi', + 'JA': 'Isuzu', + 'JF': 'Fuji Heavy Industries (Subaru)', + 'JHM': 'Honda', + 'JHG': 'Honda', + 'JHL': 'Honda', + 'JK': 'Kawasaki (motorcycles)', + 'JM': 'Mazda', + 'JN': 'Nissan', + 'JS': 'Suzuki', + 'JT': 'Toyota', + 'KL': 'Daewoo General Motors South Korea', + 'KM8': 'Hyundai', + 'KMH': 'Hyundai', + 'KNA': 'Kia', + 'KNB': 'Kia', + 'KNC': 'Kia', + 'KNM': 'Renault Samsung', + 'KPA': 'Ssangyong', + 'KPT': 'Ssangyong', + 'L56': 'Renault Samsung', + 'L5Y': 'Merato Motorcycle Taizhou Zhongneng', + 'LDY': 'Zhongtong Coach, China', + 'LGH': 'Dong Feng (DFM), China', + 'LKL': 'Suzhou King Long, China', + 'LSY': 'Brilliance Zhonghua', + 'LTV': 'Toyota Tian Jin', + 'LVS': 'Ford Chang An', + 'LVV': 'Chery, China', + 'LZM': 'MAN China', + 'LZE': 'Isuzu Guangzhou, China', + 'LZG': 'Shaanxi Automobile Group, China', + 'LZY': 'Yutong Zhengzhou, China', + 'MA1': 'Mahindra', + 'MA3': 'Suzuki India', + 'MA7': 'Honda Siel Cars India', + 'MAL': 'Hyundai', + 'MHR': 'Honda Indonesia', + 'MNB': 'Ford Thailand', + 'MNT': 'Nissan Thailand', + 'MMB': 'Mitsubishi Thailand', + 'MMM': 'Chevrolet Thailand', + 'MMT': 'Mitsubishi Thailand', + 'MM8': 'Mazda Thailand', + 'MPA': 'Isuzu Thailand', + 'MP1': 'Isuzu Thailand', + 'MRH': 'Honda Thailand', + 'MR0': 'Toyota Thailand', + 'NLE': 'Mercedes-Benz Turk Truck', + 'NM0': 'Ford Turkey', + 'NM4': 'Tofas Turk', + 'NMT': 'Toyota Turkiye', + 'PE1': 'Ford Phillipines', + 'PE3': 'Mazda Phillipines', + 'PL1': 'Proton, Malaysia', + 'SAL': 'Land Rover', + 'SAJ': 'Jaguar', + 'SAR': 'Rover', + 'SCA': 'Rolls Royce', + 'SCC': 'Lotus Cars', + 'SCE': 'DeLorean Motor Cars N. Ireland (UK)', + 'SCF': 'Aston', + 'SDB': 'Peugeot UK', + 'SFD': 'Alexander Dennis UK', + 'SHS': 'Honda UK', + 'SJN': 'Nissan UK', + 'SU9': 'Solaris Bus & Coach (Poland)', + 'TK9': 'SOR (Czech Republic)', + 'TDM': 'QUANTYA Swiss Electric Movement (Switzerland)', + 'TMB': 'Skoda (Czech Republic)', + 'TMK': 'Karosa (Czech Republic)', + 'TMP': 'Skoda trolleybuses (Czech Republic)', + 'TMT': 'Tatra (Czech Republic)', + 'TM9': 'Skoda trolleybuses (Czech Republic)', + 'TN9': 'Karosa (Czech Republic)', + 'TRA': 'Ikarus Bus', + 'TRU': 'Audi Hungary', + 'TSE': 'Ikarus Egyedi Autobuszgyar, (Hungary)', + 'TSM': 'Suzuki, (Hungary)', + 'UU1': 'Renault Dacia, (Romania)', + 'VF1': 'Renault', + 'VF3': 'Peugeot', + 'VF6': 'Renault (Trucks & Buses)', + 'VF7': 'Citroen', + 'VF8': 'Matra', + 'VLU': 'Scania France', + 'VNE': 'Irisbus (France)', + 'VSE': 'Suzuki Spain (Santana Motors)', + 'VSK': 'Nissan Spain', + 'VSS': 'SEAT', + 'VSX': 'Opel Spain', + 'VS6': 'Ford Spain', + 'VS9': 'Carrocerias Ayats (Spain)', + 'VWV': 'Volkswagen Spain', + 'VX1': 'Zastava / Yugo Serbia', + 'WAG': 'Neoplan', + 'WAU': 'Audi', + 'WBA': 'BMW', + 'WBS': 'BMW M', + 'WDB': 'Mercedes-Benz', + 'WDC': 'DaimlerChrysler', + 'WDD': 'McLaren', + 'WEB': 'Evobus GmbH (Mercedes-Bus)', + 'WF0': 'Ford Germany', + 'WMA': 'MAN Germany', + 'WMW': 'MINI', + 'WP0': 'Porsche', + 'W0L': 'Opel', + 'WVW': 'Volkswagen', + 'WV1': 'Volkswagen Commercial Vehicles', + 'WV2': 'Volkswagen Bus/Van', + 'XL9': 'Spyker', + 'XMC': 'Mitsubishi (NedCar)', + 'XTA': 'Lada/AutoVaz (Russia)', + 'YK1': 'Saab', + 'YS2': 'Scania AB', + 'YS3': 'Saab', + 'YS4': 'Scania Bus', + 'YV1': 'Volvo Cars', + 'YV4': 'Volvo Cars', + 'YV2': 'Volvo Trucks', + 'YV3': 'Volvo Buses', + 'ZAM': 'Maserati Biturbo', + 'ZAP': 'Piaggio/Vespa/Gilera', + 'ZAR': 'Alfa Romeo', + 'ZCG': 'Cagiva SpA', + 'ZDM': 'Ducati Motor Holdings SpA', + 'ZDF': 'Ferrari Dino', + 'ZD4': 'Aprilia', + 'ZFA': 'Fiat', + 'ZFC': 'Fiat V.I.', + 'ZFF': 'Ferrari', + 'ZHW': 'Lamborghini', + 'ZLA': 'Lancia', + 'ZOM': 'OM', + '1C3': 'Chrysler', + '1C6': 'Chrysler', + '1D3': 'Dodge', + '1FA': 'Ford Motor Company', + '1FB': 'Ford Motor Company', + '1FC': 'Ford Motor Company', + '1FD': 'Ford Motor Company', + '1FM': 'Ford Motor Company', + '1FT': 'Ford Motor Company', + '1FU': 'Freightliner', + '1FV': 'Freightliner', + '1F9': 'FWD Corp.', + '1G': 'General Motors USA', + '1GC': 'Chevrolet Truck USA', + '1GT': 'GMC Truck USA', + '1G1': 'Chevrolet USA', + '1G2': 'Pontiac USA', + '1G3': 'Oldsmobile USA', + '1G4': 'Buick USA', + '1G6': 'Cadillac USA', + '1GM': 'Pontiac USA', + '1G8': 'Saturn USA', + '1H': 'Honda USA', + '1HD': 'Harley-Davidson', + '1J4': 'Jeep', + '1L': 'Lincoln USA', + '1ME': 'Mercury USA', + '1M1': 'Mack Truck USA', + '1M2': 'Mack Truck USA', + '1M3': 'Mack Truck USA', + '1M4': 'Mack Truck USA', + '1N': 'Nissan USA', + '1NX': 'NUMMI USA', + '1P3': 'Plymouth USA', + '1R9': 'Roadrunner Hay Squeeze USA', + '1VW': 'Volkswagen USA', + '1XK': 'Kenworth USA', + '1XP': 'Peterbilt USA', + '1YV': 'Mazda USA (AutoAlliance International)', + '2C3': 'Chrysler Canada', + '2CN': 'CAMI', + '2D3': 'Dodge Canada', + '2FA': 'Ford Motor Company Canada', + '2FB': 'Ford Motor Company Canada', + '2FC': 'Ford Motor Company Canada', + '2FM': 'Ford Motor Company Canada', + '2FT': 'Ford Motor Company Canada', + '2FU': 'Freightliner', + '2FV': 'Freightliner', + '2FZ': 'Sterling', + '2G': 'General Motors Canada', + '2G1': 'Chevrolet Canada', + '2G2': 'Pontiac Canada', + '2G3': 'Oldsmobile Canada', + '2G4': 'Buick Canada', + '2HG': 'Honda Canada', + '2HK': 'Honda Canada', + '2HM': 'Hyundai Canada', + '2M': 'Mercury', + '2P3': 'Plymouth Canada', + '2T': 'Toyota Canada', + '2V4': 'Volkswagen Canada', + '2WK': 'Western Star', + '2WL': 'Western Star', + '2WM': 'Western Star', + '3D3': 'Dodge Mexico', + '3FA': 'Ford Motor Company Mexico', + '3FE': 'Ford Motor Company Mexico', + '3G': 'General Motors Mexico', + '3H': 'Honda Mexico', + '3N': 'Nissan Mexico', + '3P3': 'Plymouth Mexico', + '3VW': 'Volkswagen Mexico', + '4F': 'Mazda USA', + '4M': 'Mercury', + '4S': 'Subaru-Isuzu Automotive', + '4T': 'Toyota', + '4US': 'BMW USA', + '4UZ': 'Frt-Thomas Bus', + '4V1': 'Volvo', + '4V2': 'Volvo', + '4V3': 'Volvo', + '4V4': 'Volvo', + '4V5': 'Volvo', + '4V6': 'Volvo', + '4VL': 'Volvo', + '4VM': 'Volvo', + '4VZ': 'Volvo', + '5F': 'Honda USA-Alabama', + '5L': 'Lincoln', + '5N1': 'Nissan USA', + '5NP': 'Hyundai USA', + '5T': 'Toyota USA - trucks', + '6AB': 'MAN Australia', + '6F4': 'Nissan Motor Company Australia', + '6F5': 'Kenworth Australia', + '6FP': 'Ford Motor Company Australia', + '6G1': 'General Motors-Holden (post Nov 2002)', + '6G2': 'Pontiac Australia (GTO & G8)', + '6H8': 'General Motors-Holden (pre Nov 2002)', + '6MM': 'Mitsubishi Motors Australia', + '6T1': 'Toyota Motor Corporation Australia', + '6U9': 'Privately Imported car in Australia', + '8AG': 'Chevrolet Argentina', + '8GG': 'Chevrolet Chile', + '8AP': 'Fiat Argentina', + '8AF': 'Ford Motor Company Argentina', + '8AD': 'Peugeot Argentina', + '8GD': 'Peugeot Chile', + '8A1': 'Renault Argentina', + '8AK': 'Suzuki Argentina', + '8AJ': 'Toyota Argentina', + '8AW': 'Volkswagen Argentina', + '93U': 'Audi Brazil', + '9BG': 'Chevrolet Brazil', + '935': 'Citroen Brazil', + '9BD': 'Fiat Brazil', + '9BF': 'Ford Motor Company Brazil', + '93H': 'Honda Brazil', + '9BM': 'Mercedes-Benz Brazil', + '936': 'Peugeot Brazil', + '93Y': 'Renault Brazil', + '9BS': 'Scania Brazil', + '93R': 'Toyota Brazil', + '9BW': 'Volkswagen Brazil', + '9FB': 'Renault Colombia', + } From 6c929084d17861f9dc48a5b677ea55c2393f2617 Mon Sep 17 00:00:00 2001 From: "Rustem Kamun @anguis" Date: Thu, 6 Mar 2014 11:51:54 +0600 Subject: [PATCH 2/4] refactored libvin to return None for all VIN properties; make map are stored in csv and loaded on app start --- .gitignore | 1 + libvin/__init__.py | 1 - libvin/decoding.py | 107 ++++++---- libvin/make.csv | 469 +++++++++++++++++++++++++++++++++++++++++ libvin/wmi_map.py | 283 ++----------------------- tests/__init__.py | 4 - tests/test_decoding.py | 8 +- 7 files changed, 560 insertions(+), 313 deletions(-) create mode 100644 libvin/make.csv diff --git a/.gitignore b/.gitignore index f24cd99..799ae11 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ # Packages *.egg *.egg-info +venv dist build eggs diff --git a/libvin/__init__.py b/libvin/__init__.py index 8a75200..86960e8 100644 --- a/libvin/__init__.py +++ b/libvin/__init__.py @@ -1,3 +1,2 @@ from conversion import convert from decoding import decode -from verification import is_valid diff --git a/libvin/decoding.py b/libvin/decoding.py index 013d846..4a7da41 100644 --- a/libvin/decoding.py +++ b/libvin/decoding.py @@ -6,26 +6,82 @@ from libvin.static import * from libvin import wmi_map + +VIN_SIZE = 17 +"""For model years 1981 to present, the VIN is composed of 17 +alphanumeric values""" + + +PROHIBITED_LETTERS = 'IOQ' +r"""The letters I,O, Q are prohibited from any VIN position""" + + +PROHIBITED_MODEL_LETTERS = 'UZ0' +r"""The tenth position of the VIN represents the Model Year and +does not permit the use of the characters U and Z, as well +as the numeric zero (0) +""" + + +r"""The ninth position of the VIN is a calculated value based on +the other 16 alphanumeric values, it's called the +"Check Digit". The result of the check digit can ONLY be a +numeric 0-9 or letter "X". +""" +ALLOWED_CHECK_DIGIT_LETTERS = 'X0123456789' + + +class BadVin(Exception): + r"""If VIN is incorrect according to specification, exception is raised.""" + pass + class Vin(object): + def __init__(self, vin): self.vin = vin.upper() + if not self.is_valid(): + raise BadVin('Vin is not valid') @property def country(self): """ Returns the World Manufacturer's Country. """ + if not self.vin[0] in WORLD_MANUFACTURER_MAP: + return None + countries = WORLD_MANUFACTURER_MAP[self.vin[0]]['countries'] for codes in countries: if self.vin[0] in codes: return countries[codes] - return 'Unknown' + return None def decode(self): return self.vin + def is_valid(self): + r"""Returns True if a VIN is valid, otherwise returns False.""" + if hasattr(self, '_is_valid'): + return getattr(self, '_is_valid') + + _is_valid = False + + if len(self.vin) != VIN_SIZE: + _is_valid = False + elif any(x in PROHIBITED_LETTERS for x in self.vin): + _is_valid = False + elif self.vin[9] in PROHIBITED_MODEL_LETTERS: + _is_valid = False + elif not self.vin[8] in ALLOWED_CHECK_DIGIT_LETTERS: + _is_valid = False + else: + _is_valid = True + + setattr(self, '_is_valid', _is_valid) + return _is_valid + @property def is_pre_2010(self): """ @@ -42,44 +98,6 @@ def is_pre_2010(self): """ return self.vin[6].isdigit() - @property - def is_valid(self): - """ - Returns True if a VIN is valid, otherwise returns False. - """ - if len(self.vin) != 17: - """ - For model years 1981 to present, the VIN is composed of 17 - alphanumeric values - """ - return False - - elif any(x in 'IOQ' for x in self.vin): - """ - The letters I,O, Q are prohibited from any VIN position - """ - return False - - elif self.vin[9] in 'UZ0': - """ - The tenth position of the VIN represents the Model Year and - does not permit the use of the characters U and Z, as well - as the numeric zero (0) - """ - return False - - elif self.vin[8] not in 'X0123456789': - """ - The ninth position of the VIN is a calculated value based on - the other 16 alphanumeric values, it's called the - "Check Digit". The result of the check digit can ONLY be a - numeric 0-9 or letter "X". - """ - return False - - else: - return True - @property def less_than_500_built_per_year(self): """ @@ -96,6 +114,8 @@ def region(self): """ Returns the World Manufacturer's Region. Possible results: """ + if not self.vin[0] in WORLD_MANUFACTURER_MAP: + return None return WORLD_MANUFACTURER_MAP[self.vin[0]]['region'] @property @@ -135,11 +155,14 @@ def wmi(self): @property def manufacturer(self): wmi = self.wmi + print self.wmi if wmi[:3] in wmi_map.WMI_MAP: return wmi_map.WMI_MAP[wmi[:3]] if wmi[:2] in wmi_map.WMI_MAP: return wmi_map.WMI_MAP[wmi[:2]] - return 'Unknown' + return None + + make = manufacturer @property def year(self): @@ -147,9 +170,9 @@ def year(self): Returns the model year of the vehicle """ if self.is_pre_2010: - return YEARS_CODES_PRE_2010[self.vin[9]] + return YEARS_CODES_PRE_2010.get(self.vin[9], None) else: - return YEARS_CODES_PRE_2040[self.vin[9]] + return YEARS_CODES_PRE_2040.get(self.vin[9], None) def decode(vin): diff --git a/libvin/make.csv b/libvin/make.csv new file mode 100644 index 0000000..f85ecd1 --- /dev/null +++ b/libvin/make.csv @@ -0,0 +1,469 @@ +10T,Oshkosh +137,"AM General, Hummer" +15G,Gillig +17N,John Deere +18X,WRV +19U,Acura +1A4,Chrysler +1A8,Chrysler +1AC,AMC +1AM,AMC +1B3,Dodge +1B4,Dodge +1B6,Dodge +1B7,Dodge +1B7,Dodge +1BA,Blue Bird +1BB,Blue Bird +1BD,Blue Bird +1C3,Chrysler +1C4,Chrysler +1C8,Chrysler +1C9,Chance +1CY,Crane Carrier +1D3,Dodge +1D4,Dodge +1D5,Dodge +1D7,Dodge +1D8,Dodge +1EC,Fleetwood +1F1,Ford +1F6,Ford +1FA,Ford +1FB,Ford +1FC,Ford +1FD,Ford +1FE,Ford +1FM,Ford +1FT,Ford +1FU,Freightliner +1FV,Freightliner +1G1,Chevrolet +1G2,Pontiac +1G3,Oldsmobile +1G4,Buick +1G5,"GMC, Pontiac" +1G6,Cadillac +1G8,"Chevrolet, Saturn" +1GA,Chevrolet +1GB,Chevrolet +1GC,Chevrolet +1GD,GMC +1GE,Cadillac +1GF,Flexible +1GG,Isuzu +1GH,"GMC, Oldsmobile" +1GJ,GMC +1GK,GMC +1GM,Pontiac +1GN,Chevrolet +1GT,GMC +1GY,Cadillac +1HG,Honda +1HS,International +1HT,International +1HV,International +1J4,Jeep +1J7,Jeep +1J8,Jeep +1JC,"AMC, Jeep" +1JD,AMC +1JT,"AMC, Jeep" +1L1,Lincoln +1LN,Lincoln +1M1,Mack +1M2,Mack +1M3,Mack +1M8,MCI +1ME,Mercury +1MR,Lincoln +1N4,Nissan +1N6,"Datsun, Nissan" +1N9,Neoplan +1NK,Kenworth +1NP,Peterbilt +1NX,Toyota +1P3,Plymouth +1P4,Plymouth +1P7,Plymouth +1P9,Panoz +1RF,Roadmaster +1S9,Saleen +177,Thomas +1T8,Thomas +1TU,TMC +1V1,Volkswagen +1VW,Volkswagen +1WA,Autostar +1WB,Autostar +1WU,White Volvo +1WV,Winnebago +1XK,Kenworth +1XM,AMC +1XP,Peterbilt +1Y1,"Chevrolet, Geo" +1YV,Mazda +1Z3,Mitsubishi +1Z5,Mitsubishi +1Z7,Mitsubishi +1ZV,Ford +1ZW,Mercury +2A3,Chrysler +2A4,Chrysler +2A8,Chrysler +2B1,Orion +2B3,Dodge +2B4,Dodge +2B5,Dodge +2B6,Dodge +2B7,Dodge +2B8,Dodge +2BC,"AMC, Jeep" +2C1,"Chevrolet, Geo" +2C3,Chrysler +2C4,Chrysler +2C7,Pontiac +2C8,Chrysler +2CC,"AMC, Eagle" +2CK,"Geo, Pontiac" +2CM,AMC +2CN,"Chevrolet, Geo" +2D4,Dodge +2D6,Dodge +2D7,Dodge +2D8,Dodge +2E3,Eagle +2FA,Ford +2FD,Ford +2FM,Ford +2FT,Ford +2FU,Freightliner +2FV,Freightliner +2FW,Sterling +2FZ,Sterling +2G0,GMC +2G1,Chevrolet +2G2,Pontiac +2G3,Oldsmobile +2G4,BuickX +2G5,GMC +2G7,Pontiac +2G8,Chevrolet +2GA,Chevrolet +2GB,Chevrolet +2GD,GMC +2GJ,GMC +2GK,GMC +2GN,Chevrolet +2GT,GMC +2HG,Honda +2HH,Acura +2HJ,Honda +2HK,Honda +2HM,Hyundai +2HN,Acura +2HS,International +2HT,International +2J4,Jeep +2LM,Lincoln +2M2,Mack +2ME,Mercury +2MH,Mercury +2MR,Mercury +2NK,Kenworth +2NP,Peterbilt +2P3,Plymouth +2P4,Plymouth +2P5,Plymouth +2P9,Prevost +2PC,Prevost +2S2,Suzuki +2S3,Suzuki +2T1,Toyota +2T2,Lexus +2WK,Western Star Trucks +2WL,Western Star Trucks +2XK,Kenworth +2XM,Eagle +2XP,Peterbilt +3A4,Chrysler +3A8,Chrysler +3AB,Dina +3AL,Freightliner +3B3,Dodge +3B4,Dodge +3B6,Dodge +3B7,Dodge +3BK,Kenworth +3BP,Peterbilt +3C3,Chrysler +3C4,Chrysler +3C8,Chrysler +3CA,Chrysler +3D3,Dodge +3D5,Dodge +3D6,Dodge +3D7,Dodge +3FA,Ford +3FC,Ford +3FD,Ford +3FE,"Ford, Freightliner" +3FR,Ford +3FT,Ford +3G1,Chevrolet +3G2,Pontiac +3G4,Buick +3G5,Buick +3G7,Pontiac +3GB,Chevrolet +3GC,Chevrolet +3GD,GMC +3GE,Chevrolet +3GK,GMC +3GN,Chevrolet +3GT,GMC +3GY,Cadillac +3HA,International +3HG,Honda +3HM,Honda +3HS,International +3HT,International +3LN,Lincoln +3MA,Mercury +3ME,Mercury +3N1,Nissan +3NK,Kenworth +3NM,Peterbilt +3P3,Plymouth +3TM,Toyota +3VW,Volkswagen +3WK,Kenworth +45V,Utilimaster +46G,Gillig +49H,Sterling +4A3,Mitsubishi +4A4,Mitsubishi +4B3,Dodge +4C3,Chrysler +4CD,Oshkosh +4DR,"Genesis, International" +4E3,Eagle +4F2,Mazda +4F4,Mazda +4G1,Chevrolet +4G2,Pontiac +4GD,GMC +4GT,"Isuzu, WhiteGMC" +4JG,Mercedes-Benz +4KB,Chevrolet +4KD,GMC +4KL,Isuzu +4M2,Mercury +4N1,Nissan +4N2,Nissan +4NU,Isuzu +4P3,Plymouth +4S1,Isuzu +4S2,Isuzu +4S3,Subaru +4S4,Subaru +4S6,Honda +4S7,Spartan +4SL,Magnum +4T1,Toyota +4T3,Toyota +4TA,Toyota +4US,BMW +4UZ,Freightliner +4V1,"Volvo, WhiteGMC" +4V2,"Volvo, WhiteGMC" +4V4,"Volvo, WhiteGMC" +4V5,"Volvo, WhiteGMC" +4VA,Volvo +4VG,"Volvo, WhiteGMC" +4VH,Volvo +4VL,Volvo +4VM,Volvo +4VZ,Spartan +5AS,GEM +5B4,Workhorse +5CK,Western Star Trucks +5FN,Honda +5FY,New Flyer +5GA,Buick +5GR,Hummer +5GT,Hummer +5GZ,Saturn +5J6,Honda +5J8,Acura +5KJ,Western Star Trucks +5KK,Western Star Trucks +5LM,Lincoln +5LT,Lincoln +5N1,Nissan +5N3,Infiniti +5NM,Hyundai +5NP,Hyundai +5PV,Hino +5S3,Saab +5SX,Amercian LeFrance +5T4,Workhorse +5TB,Toyota +5TD,Toyota +5TE,Toyota +5TF,Toyota +5UM,BMW +5UX,BMW +5Y2,Pontiac +6G2,Pontiac +6MM,Mitsubishi +6MP,Mercury +9BF,Ford +9BW,Volkswagen +9DW,Volkswagen +J81,"Chevrolet,Geo" +J87,Isuzu +J8B,Chevrolet +J8D,GMC +J8Z,Chevrolet +JA3,Mitsubishi +JA4,Mitsubishi +JA7,Mitsubishi +JAA,Isuzu +JAB,Isuzu +JAC,Isuzu +JAE,Acura +JAL,Isuzu +JB3,Dodge +JB4,Dodge +JB7,Dodge +JC2,Ford +JD1,Daihatsu +JD2,Daihatsu +JE3,Eagle +JF1,Subaru +JF2,Subaru +JF3,Subaru +JF4,Saab +JG1,"Chevrolet, Geo" +JG7,Pontiac +JGC,Geo +JH4,Acura +JHB,Hino +JHL,Honda +JHM,Honda +JJ3,Chrysler +JL6,Mitsubishi +JLS,Sterling +JM1,Mazda +JM2,Mazda +JM3,Mazda +JN1,"Datsun, Nissan" +JN3,Nissan +JN4,Nissan +JN6,"Datsun, Nissan" +JN8,Nissan +JNA,Nissan +JNK,Infiniti +JNR,Infiniti +JNX,Infiniti +JP3,Plymouth +JP4,Plymouth +JP7,Plymouth +JR2X,Isuzu +JS2,Suzuki +JS3,Suzuki +JS4,Suzuki +JT2,Toyota +JT3,Toyota +JT4,Toyota +JT5,Toyota +JT6,Lexus +JT8,Lexus +JTD,Toyota +JTE,Toyota +JTH,Lexus +JTJ,Lexus +JTK,Scion +JTL,Scion +JTM,Toyota +JTN,Toyota +JW6,Mitsubishi +JW7,Mitsubishi +KL1,Chevrolet +KL2,Pontiac +KL5,Suzuki +KL7,Asuna +KLA,Daewoo +KM8,Hyundai +KMF,Hyundai +KMH,Hyundai +KNA,Kia +KND,"Hyundai, Kia" +KNJ,Ford +KPH,Mitsubishi +LES,Isuzu +LM5,Isuzu +ML3,Dodge +SA9,Morgan +SAJ,Jaguar +SAL,Land Rover +SAT,Triumph +SAX,Sterling +SCA,Rolls-Royce +SCB,Bentley +SCC,Lotus +SCF,Aston Martin +SDL,TVR Engineering +SHH,Honda +SHS,Honda +SJN,Nissan UK +TRU,Audi +VF1,Renault +VF7,Citroën +VF3,Peugeot +VG6,Mack +VSS,Seat +W06,Cadillac +WA1,Audi +WAU,Audi +WBA,BMW +WBS,BMW +WBX,BMW +WD0,Dodge +WD1,Dodge +WD2,Dodge +WD5,Dodge +WD8,Dodge +WDB,"Maybach, Mercedes-Benz" +WDC,Mercedes-Benz +WDD,Mercedes-Benz +WDP,Dodge +WDX,Dodge +WDY,Dodge +WF1,Merkur +WKK,Fahrzeugwerke +WME,Mercedes-Benz +WMW,Mini +WP0,Porsche +WP1,Porsche +WUA,Audi +WV2,Volkswagen +WV3,Volkswagen +WVG,Volkswagen +WVW,Volkswagen +XTA,Lada +YB3,Volvo +YS3,Saab +YV1,Volvo +YV2,Volvo +YV4,Volvo +YV5,Volvo +ZA9,Lamborghini +ZAM,Maserati +ZAR,Alfa Romeo +ZC2,Chrysler +ZFA,Fiat +ZFF,Ferrari +ZHWX,Lamborghini +11V,Ottawa diff --git a/libvin/wmi_map.py b/libvin/wmi_map.py index df08be4..91b303c 100644 --- a/libvin/wmi_map.py +++ b/libvin/wmi_map.py @@ -1,265 +1,18 @@ -WMI_MAP = { - 'AFA': 'Ford South Africa', - 'AAV': 'Volkswagen South Africa', - 'JA3': 'Mitsubishi', - 'JA': 'Isuzu', - 'JF': 'Fuji Heavy Industries (Subaru)', - 'JHM': 'Honda', - 'JHG': 'Honda', - 'JHL': 'Honda', - 'JK': 'Kawasaki (motorcycles)', - 'JM': 'Mazda', - 'JN': 'Nissan', - 'JS': 'Suzuki', - 'JT': 'Toyota', - 'KL': 'Daewoo General Motors South Korea', - 'KM8': 'Hyundai', - 'KMH': 'Hyundai', - 'KNA': 'Kia', - 'KNB': 'Kia', - 'KNC': 'Kia', - 'KNM': 'Renault Samsung', - 'KPA': 'Ssangyong', - 'KPT': 'Ssangyong', - 'L56': 'Renault Samsung', - 'L5Y': 'Merato Motorcycle Taizhou Zhongneng', - 'LDY': 'Zhongtong Coach, China', - 'LGH': 'Dong Feng (DFM), China', - 'LKL': 'Suzhou King Long, China', - 'LSY': 'Brilliance Zhonghua', - 'LTV': 'Toyota Tian Jin', - 'LVS': 'Ford Chang An', - 'LVV': 'Chery, China', - 'LZM': 'MAN China', - 'LZE': 'Isuzu Guangzhou, China', - 'LZG': 'Shaanxi Automobile Group, China', - 'LZY': 'Yutong Zhengzhou, China', - 'MA1': 'Mahindra', - 'MA3': 'Suzuki India', - 'MA7': 'Honda Siel Cars India', - 'MAL': 'Hyundai', - 'MHR': 'Honda Indonesia', - 'MNB': 'Ford Thailand', - 'MNT': 'Nissan Thailand', - 'MMB': 'Mitsubishi Thailand', - 'MMM': 'Chevrolet Thailand', - 'MMT': 'Mitsubishi Thailand', - 'MM8': 'Mazda Thailand', - 'MPA': 'Isuzu Thailand', - 'MP1': 'Isuzu Thailand', - 'MRH': 'Honda Thailand', - 'MR0': 'Toyota Thailand', - 'NLE': 'Mercedes-Benz Turk Truck', - 'NM0': 'Ford Turkey', - 'NM4': 'Tofas Turk', - 'NMT': 'Toyota Turkiye', - 'PE1': 'Ford Phillipines', - 'PE3': 'Mazda Phillipines', - 'PL1': 'Proton, Malaysia', - 'SAL': 'Land Rover', - 'SAJ': 'Jaguar', - 'SAR': 'Rover', - 'SCA': 'Rolls Royce', - 'SCC': 'Lotus Cars', - 'SCE': 'DeLorean Motor Cars N. Ireland (UK)', - 'SCF': 'Aston', - 'SDB': 'Peugeot UK', - 'SFD': 'Alexander Dennis UK', - 'SHS': 'Honda UK', - 'SJN': 'Nissan UK', - 'SU9': 'Solaris Bus & Coach (Poland)', - 'TK9': 'SOR (Czech Republic)', - 'TDM': 'QUANTYA Swiss Electric Movement (Switzerland)', - 'TMB': 'Skoda (Czech Republic)', - 'TMK': 'Karosa (Czech Republic)', - 'TMP': 'Skoda trolleybuses (Czech Republic)', - 'TMT': 'Tatra (Czech Republic)', - 'TM9': 'Skoda trolleybuses (Czech Republic)', - 'TN9': 'Karosa (Czech Republic)', - 'TRA': 'Ikarus Bus', - 'TRU': 'Audi Hungary', - 'TSE': 'Ikarus Egyedi Autobuszgyar, (Hungary)', - 'TSM': 'Suzuki, (Hungary)', - 'UU1': 'Renault Dacia, (Romania)', - 'VF1': 'Renault', - 'VF3': 'Peugeot', - 'VF6': 'Renault (Trucks & Buses)', - 'VF7': 'Citroen', - 'VF8': 'Matra', - 'VLU': 'Scania France', - 'VNE': 'Irisbus (France)', - 'VSE': 'Suzuki Spain (Santana Motors)', - 'VSK': 'Nissan Spain', - 'VSS': 'SEAT', - 'VSX': 'Opel Spain', - 'VS6': 'Ford Spain', - 'VS9': 'Carrocerias Ayats (Spain)', - 'VWV': 'Volkswagen Spain', - 'VX1': 'Zastava / Yugo Serbia', - 'WAG': 'Neoplan', - 'WAU': 'Audi', - 'WBA': 'BMW', - 'WBS': 'BMW M', - 'WDB': 'Mercedes-Benz', - 'WDC': 'DaimlerChrysler', - 'WDD': 'McLaren', - 'WEB': 'Evobus GmbH (Mercedes-Bus)', - 'WF0': 'Ford Germany', - 'WMA': 'MAN Germany', - 'WMW': 'MINI', - 'WP0': 'Porsche', - 'W0L': 'Opel', - 'WVW': 'Volkswagen', - 'WV1': 'Volkswagen Commercial Vehicles', - 'WV2': 'Volkswagen Bus/Van', - 'XL9': 'Spyker', - 'XMC': 'Mitsubishi (NedCar)', - 'XTA': 'Lada/AutoVaz (Russia)', - 'YK1': 'Saab', - 'YS2': 'Scania AB', - 'YS3': 'Saab', - 'YS4': 'Scania Bus', - 'YV1': 'Volvo Cars', - 'YV4': 'Volvo Cars', - 'YV2': 'Volvo Trucks', - 'YV3': 'Volvo Buses', - 'ZAM': 'Maserati Biturbo', - 'ZAP': 'Piaggio/Vespa/Gilera', - 'ZAR': 'Alfa Romeo', - 'ZCG': 'Cagiva SpA', - 'ZDM': 'Ducati Motor Holdings SpA', - 'ZDF': 'Ferrari Dino', - 'ZD4': 'Aprilia', - 'ZFA': 'Fiat', - 'ZFC': 'Fiat V.I.', - 'ZFF': 'Ferrari', - 'ZHW': 'Lamborghini', - 'ZLA': 'Lancia', - 'ZOM': 'OM', - '1C3': 'Chrysler', - '1C6': 'Chrysler', - '1D3': 'Dodge', - '1FA': 'Ford Motor Company', - '1FB': 'Ford Motor Company', - '1FC': 'Ford Motor Company', - '1FD': 'Ford Motor Company', - '1FM': 'Ford Motor Company', - '1FT': 'Ford Motor Company', - '1FU': 'Freightliner', - '1FV': 'Freightliner', - '1F9': 'FWD Corp.', - '1G': 'General Motors USA', - '1GC': 'Chevrolet Truck USA', - '1GT': 'GMC Truck USA', - '1G1': 'Chevrolet USA', - '1G2': 'Pontiac USA', - '1G3': 'Oldsmobile USA', - '1G4': 'Buick USA', - '1G6': 'Cadillac USA', - '1GM': 'Pontiac USA', - '1G8': 'Saturn USA', - '1H': 'Honda USA', - '1HD': 'Harley-Davidson', - '1J4': 'Jeep', - '1L': 'Lincoln USA', - '1ME': 'Mercury USA', - '1M1': 'Mack Truck USA', - '1M2': 'Mack Truck USA', - '1M3': 'Mack Truck USA', - '1M4': 'Mack Truck USA', - '1N': 'Nissan USA', - '1NX': 'NUMMI USA', - '1P3': 'Plymouth USA', - '1R9': 'Roadrunner Hay Squeeze USA', - '1VW': 'Volkswagen USA', - '1XK': 'Kenworth USA', - '1XP': 'Peterbilt USA', - '1YV': 'Mazda USA (AutoAlliance International)', - '2C3': 'Chrysler Canada', - '2CN': 'CAMI', - '2D3': 'Dodge Canada', - '2FA': 'Ford Motor Company Canada', - '2FB': 'Ford Motor Company Canada', - '2FC': 'Ford Motor Company Canada', - '2FM': 'Ford Motor Company Canada', - '2FT': 'Ford Motor Company Canada', - '2FU': 'Freightliner', - '2FV': 'Freightliner', - '2FZ': 'Sterling', - '2G': 'General Motors Canada', - '2G1': 'Chevrolet Canada', - '2G2': 'Pontiac Canada', - '2G3': 'Oldsmobile Canada', - '2G4': 'Buick Canada', - '2HG': 'Honda Canada', - '2HK': 'Honda Canada', - '2HM': 'Hyundai Canada', - '2M': 'Mercury', - '2P3': 'Plymouth Canada', - '2T': 'Toyota Canada', - '2V4': 'Volkswagen Canada', - '2WK': 'Western Star', - '2WL': 'Western Star', - '2WM': 'Western Star', - '3D3': 'Dodge Mexico', - '3FA': 'Ford Motor Company Mexico', - '3FE': 'Ford Motor Company Mexico', - '3G': 'General Motors Mexico', - '3H': 'Honda Mexico', - '3N': 'Nissan Mexico', - '3P3': 'Plymouth Mexico', - '3VW': 'Volkswagen Mexico', - '4F': 'Mazda USA', - '4M': 'Mercury', - '4S': 'Subaru-Isuzu Automotive', - '4T': 'Toyota', - '4US': 'BMW USA', - '4UZ': 'Frt-Thomas Bus', - '4V1': 'Volvo', - '4V2': 'Volvo', - '4V3': 'Volvo', - '4V4': 'Volvo', - '4V5': 'Volvo', - '4V6': 'Volvo', - '4VL': 'Volvo', - '4VM': 'Volvo', - '4VZ': 'Volvo', - '5F': 'Honda USA-Alabama', - '5L': 'Lincoln', - '5N1': 'Nissan USA', - '5NP': 'Hyundai USA', - '5T': 'Toyota USA - trucks', - '6AB': 'MAN Australia', - '6F4': 'Nissan Motor Company Australia', - '6F5': 'Kenworth Australia', - '6FP': 'Ford Motor Company Australia', - '6G1': 'General Motors-Holden (post Nov 2002)', - '6G2': 'Pontiac Australia (GTO & G8)', - '6H8': 'General Motors-Holden (pre Nov 2002)', - '6MM': 'Mitsubishi Motors Australia', - '6T1': 'Toyota Motor Corporation Australia', - '6U9': 'Privately Imported car in Australia', - '8AG': 'Chevrolet Argentina', - '8GG': 'Chevrolet Chile', - '8AP': 'Fiat Argentina', - '8AF': 'Ford Motor Company Argentina', - '8AD': 'Peugeot Argentina', - '8GD': 'Peugeot Chile', - '8A1': 'Renault Argentina', - '8AK': 'Suzuki Argentina', - '8AJ': 'Toyota Argentina', - '8AW': 'Volkswagen Argentina', - '93U': 'Audi Brazil', - '9BG': 'Chevrolet Brazil', - '935': 'Citroen Brazil', - '9BD': 'Fiat Brazil', - '9BF': 'Ford Motor Company Brazil', - '93H': 'Honda Brazil', - '9BM': 'Mercedes-Benz Brazil', - '936': 'Peugeot Brazil', - '93Y': 'Renault Brazil', - '9BS': 'Scania Brazil', - '93R': 'Toyota Brazil', - '9BW': 'Volkswagen Brazil', - '9FB': 'Renault Colombia', - } +import csv +import os + +def load_make_sheet(pfile): + rv = {} + with open(pfile, 'rb') as f: + reader = csv.reader(f) + _ = reader.next() + + for row in reader: + vin_code, vin_model = row + rv[vin_code] = vin_model + + return rv + +WMI_MAP = load_make_sheet(os.path.join(os.path.abspath( + os.path.dirname(__file__)), 'make.csv')) + diff --git a/tests/__init__.py b/tests/__init__.py index 2b58a11..3735080 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -24,8 +24,4 @@ 'MODEL': 'Acadia', 'MAKE': 'GMC', 'YEAR': 2008, 'COUNTRY': 'United States', 'REGION': 'north_america', 'SEQUENTIAL_NUMBER': '123735', 'FEWER_THAN_500_PER_YEAR': False}, - # http://www.vindecoder.net/?vin=2FTCF15F2ECA55516&submit=Decode - {'VIN': '2FTCF15F2ECA55516', 'WMI': '2FT', 'VDS': 'CF15F2', 'VIS': 'ECA55516', - 'MODEL': 'F-150', 'MAKE': 'Ford', 'YEAR': 2014, 'COUNTRY': 'Canada', - 'REGION': 'north_america', 'SEQUENTIAL_NUMBER': '55516', 'FEWER_THAN_500_PER_YEAR': False}, ] diff --git a/tests/test_decoding.py b/tests/test_decoding.py index b495ce4..2ce899a 100644 --- a/tests/test_decoding.py +++ b/tests/test_decoding.py @@ -70,4 +70,10 @@ def test_is_valid(self): for test in TEST_DATA: v = Vin(test['VIN']) print "Testing: %s" % test['VIN'] - assert_equals(v.is_valid, True) + assert_equals(v.is_valid(), True) + + def test_manufacturer(self): + for test in TEST_DATA: + v = Vin(test['VIN']) + print 'Testing: %s' % test['VIN'] + assert_true(test['MAKE'] in v.make) From 05f5375a84370bd10fea3fddf19f1b4a48a160ae Mon Sep 17 00:00:00 2001 From: "Rustem Kamun @anguis" Date: Thu, 6 Mar 2014 11:52:58 +0600 Subject: [PATCH 3/4] stale files --- libvin/check.py | 0 libvin/verification.py | 33 --------------------------------- 2 files changed, 33 deletions(-) delete mode 100644 libvin/check.py delete mode 100644 libvin/verification.py diff --git a/libvin/check.py b/libvin/check.py deleted file mode 100644 index e69de29..0000000 diff --git a/libvin/verification.py b/libvin/verification.py deleted file mode 100644 index 7e4291f..0000000 --- a/libvin/verification.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -Copyright Lukasz Szybalski -VIN Vehicle information number checker, -Inputs vin number and outputs true/false -""" - -def is_valid(vin): - """Vehicle Information Number. This will return whether the entered vin number is authentic/correct. - Example: - import vin - vin.check_vin(my_vin_number) - """ - vin=str(vin).strip() - if len(vin) != 17: - return False - else: - converted=[] - vin=vin.upper() - for i in range(len(vin)): - converted.insert(i,convert_vin(vin[i])) - multiplier=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2] - add=0 - for i in range(len(vin)): - add+=(converted[i]*multiplier[i]) - final= (add%11) - if final ==10: - final='X' - if str(final)==vin[8]: - return True - else: - return False - - From 797fe8ab76b24fcd05dbba37c78f0ec12d75485a Mon Sep 17 00:00:00 2001 From: "Rustem Kamun @anguis" Date: Thu, 6 Mar 2014 12:50:55 +0600 Subject: [PATCH 4/4] if vin is empty, it is necessary to raise exception --- libvin/decoding.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libvin/decoding.py b/libvin/decoding.py index 4a7da41..dd996fe 100644 --- a/libvin/decoding.py +++ b/libvin/decoding.py @@ -38,7 +38,11 @@ class BadVin(Exception): class Vin(object): def __init__(self, vin): + if not vin: + raise BadVin('Vin is empty') + self.vin = vin.upper() + if not self.is_valid(): raise BadVin('Vin is not valid')