Skip to content

Commit

Permalink
added benchmarks and more documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
davidpeckham committed Feb 19, 2024
1 parent 23b0520 commit a2bec87
Show file tree
Hide file tree
Showing 15 changed files with 266 additions and 648 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## v0.3.0 (2024-02-19)

[GitHub release](https://github.com/davidpeckham/vin/releases/tag/v0.3.0)

### New Features

* Decode the make, model, series, and trim
* Supports passenger cars, multipurpose vehicles, and light trucks manufactured since 1980
* Performance benchmarks

### Fixes

* Correctly determines the model year for older vehicles

## v0.2.0 (2024-02-03)

[GitHub release](https://github.com/davidpeckham/vin/releases/tag/v0.2.0)
Expand Down
54 changes: 32 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,52 @@

-----

**Contents**

- [Why use VIN?](#why-use-vin)
- [Vehicle Identification Number](#vehicle-identification-number)
- [Vehicle Data](#vehicle-data)
- [Installation](#installation)
- [License](#license)

VIN validates Vehicle Identification Numbers and decodes the vehicle's manufacturer, make, model, and model year.
``VIN`` validates Vehicle Identification Numbers and decodes the vehicle's manufacturer, make, model, series, trim, and model year.

>>> from vin import VIN

>>> VIN('KNDCE3LG2L5073161').description
'2020 Kia Niro EX Premium'

>>> vin("5FNYF5H59HB011946").manufacturer
Honda

>>> vin("5FNYF5H59HB011946").model_year
2017

>>> vin("YT9NN1U14KA007175").manufacturer
Koenigsegg

>>> vin("5FNYF5H59HB011946").model_year
2017
``VIN`` supports passenger vehicles manufactured since 1980:

* Passenger Cars
* Multipurpose Passenger Vehicle (MPV)
* Light Trucks

``VIN`` does not currently support:

* Buses
* Heavy Trucks
* Incomplete Vehicles
* Low Speed Vehicles (LSV)
* Motorcycles
* Off Road Vehicles
* Trailers

## Why use VIN?

- **Accurate** — Vehicle information is provided by the National Highway Traffic Safety Administration.
- **Fast** — Vehicle data is included and periodically updated, so validation and decoding are fast.
- **Accurate** — Uses U.S. National Highway Traffic Safety Administration vehicle data.
- **Fast** — Validate and decode 1,500 VINs per second.

## Installation

Use ``pip`` to install the library:

$ pip install vin

## Vehicle Identification Number

A ``VIN`` is a unique 17-character Vehicle Identification Number.
A ```VIN``` is a unique 17-character Vehicle Identification Number.

* Uniquely identifies vehicles manufactured for sale or use in the United States since 1980
* Assigned by vehicle manufacturers
Expand Down Expand Up @@ -65,17 +82,10 @@ plant where the vehicle was made, and the vehicle's serial number.

For more information, see the [VIN specification](https://www.ecfr.gov/current/title-49/subtitle-B/chapter-V/part-565).

Installation
------------

Use ``pip`` to install the library:

$ pip install vin

## Vehicle Data

Vehicle data is provided by the U.S. National Highway Traffic Safety Administration (NHTSA) [Product Information Catalog and Vehicle Listing (vPIC)](https://vpic.nhtsa.dot.gov).

## License

`VIN` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
``VIN`` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
3 changes: 2 additions & 1 deletion docs/hooks.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import shutil


def copy_history(*args, **kwargs):
def copy_docs(*args, **kwargs):
shutil.copy("CHANGELOG.md", "docs/changelog.md")
shutil.copy("README.md", "docs/index.md")
49 changes: 33 additions & 16 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,55 @@

-----

VIN validates Vehicle Identification Numbers and decodes the vehicle's manufacturer, make, model, and model year.
``VIN`` validates Vehicle Identification Numbers and decodes the vehicle's manufacturer, make, model, series, trim, and model year.

>>> from vin import VIN

>>> VIN('KNDCE3LG2L5073161').description
'2020 Kia Niro EX Premium'

>>> vin("5FNYF5H59HB011946").manufacturer
Honda

>>> vin("5FNYF5H59HB011946").model_year
2017

>>> vin("YT9NN1U14KA007175").manufacturer
Koenigsegg

>>> vin("5FNYF5H59HB011946").model_year
2017
``VIN`` supports passenger vehicles manufactured since 1980:

* Passenger Cars
* Multipurpose Passenger Vehicle (MPV)
* Light Trucks

``VIN`` does not currently support:

* Buses
* Heavy Trucks
* Incomplete Vehicles
* Low Speed Vehicles (LSV)
* Motorcycles
* Off Road Vehicles
* Trailers

## Why use VIN?

- **Accurate** — Vehicle information is provided by the National Highway Traffic Safety Administration.
- **Fast** — Vehicle data is included and periodically updated, so validation and decoding are fast.
- **Accurate** — Uses U.S. National Highway Traffic Safety Administration vehicle data.
- **Fast** — Validate and decode 1,500 VINs per second.

## Installation

Use ``pip`` to install the library:

$ pip install vin

## Vehicle Identification Number

A ``VIN`` is a unique 17-character Vehicle Identification Number.
A ```VIN``` is a unique 17-character Vehicle Identification Number.

* Assigned by vehicle manufacturers
* Uniquely identifies vehicles manufactured for sale or use in the United States since 1980
* Assigned by vehicle manufacturers
* Governed by the U.S. National Highway Traffic Safety Administration (NHTSA)

The structure of the VIN is:
Expand All @@ -57,18 +82,10 @@ plant where the vehicle was made, and the vehicle's serial number.

For more information, see the [VIN specification](https://www.ecfr.gov/current/title-49/subtitle-B/chapter-V/part-565).

Installation
------------

Use ``pip`` to install the library:

$ pip install vin

## Vehicle Data

Vehicle data is provided by the U.S. National Highway Traffic Safety Administration (NHTSA) [Product Information Catalog and Vehicle Listing (vPIC)](https://vpic.nhtsa.dot.gov).

## License

VIN is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.

``VIN`` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
4 changes: 3 additions & 1 deletion hatch.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
dependencies = [
"freezegun==1.2.*",
"pytest-cov==4.1.*",
"pytest-benchmark==4.0.*",
"pytest==7.3.*",
"parametrize_from_file"
]

[envs.default.scripts]
test = "pytest {args:.}"
test = "pytest {args:.} --benchmark-autosave"
cov-test = "pytest --cov {args:vin} --cov-report=term-missing --cov-report=xml"

[envs.lint]
Expand Down Expand Up @@ -49,6 +50,7 @@ dependencies = [
# Validation
# https://github.com/linkchecker/linkchecker/pull/669#issuecomment-1267236287
"linkchecker @ git+https://github.com/linkchecker/linkchecker.git@d9265bb71c2054bf57b8c5734a4825d62505c779",
"black"
]
[envs.docs.scripts]
build = "mkdocs build --clean --strict"
Expand Down
2 changes: 1 addition & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ plugins:
merge_init_into_class: true
mkdocs-simple-hooks:
hooks:
on_pre_build: 'docs.hooks:copy_history'
on_pre_build: 'docs.hooks:copy_docs'

markdown_extensions:
- admonition
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ path = "src/vin/__about__.py"
[tool.hatch.envs.default]
dependencies = [
"coverage[toml]>=6.5",
"pytest",
"pytest"
]
[tool.hatch.envs.default.scripts]
test = "pytest {args:tests}"
Expand Down
2 changes: 1 addition & 1 deletion src/vin/__about__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2024-present David Peckham <[email protected]>
#
# SPDX-License-Identifier: MIT
__version__ = "0.2.0"
__version__ = "0.3.0"
42 changes: 13 additions & 29 deletions src/vin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
# ruff: noqa: TRY003, EM101, EM102

from datetime import date
from importlib.resources import files
from typing import Final

from vin.constants import CARS_AND_LIGHT_TRUCKS
from vin.constants import VIN_CHARACTER_VALUES
from vin.constants import VIN_CHARACTERS
from vin.constants import VIN_CHECK_DIGIT_CHARACTERS
Expand Down Expand Up @@ -74,13 +73,8 @@ class VIN:
"""

CARS_AND_LIGHT_TRUCKS: Final[list[str]] = (
files("vin").joinpath("cars-and-light-trucks.csv").read_text().splitlines()
)
"""WMI that make cars and light trucks (used to determine model year)"""

def __init__(self, vin: str, decode=True, fix_check_digit=False) -> None:
"""Initialize a VIN.
def __init__(self, vin: str, decode: bool = True, fix_check_digit: bool = False) -> None:
"""Validates the VIN and decodes vehicle information.
Args:
vin: The 17-digit Vehicle Identification Number.
Expand Down Expand Up @@ -160,11 +154,9 @@ def calculate_check_digit(cls, vin: str) -> str:
"""
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]
for position, letter in enumerate(vin):
if position != VIN_CHECK_DIGIT_POSITION:
total += VIN_CHARACTER_VALUES[letter] * VIN_POSITION_WEIGHTS[position]
return VIN_CHECK_DIGIT_CHARACTERS[total % 11]

@property
Expand Down Expand Up @@ -371,18 +363,10 @@ def descriptor(self) -> str:
"""The part of the VIN used to lookup make, model, and other
vehicle attributes in NHTSA vPIC.
The descriptor is 11 characters for a mass-market manufacturer.
For specialized manufacturers, the descriptor is 14 characters so
that it includes the second half of the WMI.
Returns:
str: the 11- or 14-character descriptor for this VIN
str: the 14-character descriptor for this VIN
"""
return f"{self._vin[3:8]}|{self._vin[9:]}"
# if self._vin[2] == "9":
# return descriptor[:14]
# else:
# return descriptor[:11]

def _decode_model_year(self) -> int:
"""The model year as encoded in the VIN.
Expand All @@ -394,11 +378,11 @@ def _decode_model_year(self) -> int:
uses information from NHTSA vPIC to determine the actual model year.
Returns:
The vehicle model year. May be negative if the VIN alone isn't
sufficient to determine the model year. When this happens, the
actual model year is likely the absolute value of this model year,
or 30 years earlier. To find the actual model year, look up the VIN
VIN details first with the later model year and then the earlier
The vehicle model year. May be negative if the VIN alone isn't \
sufficient to determine the model year. When this happens, the \
actual model year is likely the absolute value of this model year, \
or 30 years earlier. To find the actual model year, look up the VIN \
VIN details first with the later model year and then the earlier \
model year -- only one of these is likely to return a result.
Examples:
Expand Down Expand Up @@ -428,7 +412,7 @@ def _decode_model_year(self) -> int:

assert model_year > 0

if self.wmi in self.CARS_AND_LIGHT_TRUCKS:
if self.wmi in CARS_AND_LIGHT_TRUCKS:
if self._vin[6].isdigit():
# cars and light trucks manufactured on or before April 30, 2009 (1980 to 2009)
model_year -= 30
Expand Down
Loading

0 comments on commit a2bec87

Please sign in to comment.