VinDecoder.load() opens the vPIC database this release of Relativities
pins: NHTSA’s Product Information Catalog, as packaged by @cardog/corgi <https://github.com/cardog-ai/corgi>_. The first load downloads it (about 26 MB)
into the cache, checks its SHA-256, and every later load reads it offline.
Decoding runs locally, in Python, and gives the same answer for the same VIN
on every machine for one release.
::
from relativities.ppa import vin
with vin.VinDecoder.load() as decoder:
decoder.decode([“1HGCV1F31LA123456”]) # make Honda, model Accord, model_year 2020
book = decoder.enrich(book) # fills blank vehicle facts from each VIN
enrich takes a book and returns one, so it is a @scenario or a step
before Program.rate. vin.COLUMNS declares the facts it writes, for
Schema.with_columns.
COLUMNS
Columns by name: make, model, model_year, and build facts such as body_class, drive_type, fuel_type and engine_cylinders. VinDecoder.decode returns one column for each, and VinDecoder.enrich writes them. Declare the ones you keep with Schema.with_columns, leaving out make, model and model_year, which ppa.SCHEMA already declares.
VPIC
VinDecoder.load() reads it.
VinDecoder
load opens it. Close it with close or a with block. Decoding
reads only the database, so a decoder gives one fixed answer for each VIN.
VinDecoder.load
path.
By default, the first load downloads VPIC from its pinned URL,
anonymously, checks its SHA-256 and caches it; later loads check the
cached copy and open it offline. local_files_only, or
EFFECTIVE_OFFLINE=1, reads only the cache. A failed download, a
cache that lacks the file offline, or a cached file that fails its
check raises relativities.CatalogError. cache_dir sets the
cache directory.
path opens a vPIC database you have, such as a newer corgi
vpic.lite.db, as it is.
VinDecoder.download
path, a new file, and return it.
VinDecoder.load(path) then opens it on an offline machine.
local_files_only and cache_dir work as in load. Raises
FileExistsError when path exists.
VinDecoder.release
NHTSA vPIC 2026-04-01 (@cardog/corgi 2.0.4).
VinDecoder.decode
vin is the value given. status is decoded; invalid
(something other than 17 VIN characters); unknown_wmi (a
manufacturer code outside vPIC); unknown_year (vPIC lacks the
model year position 10 encodes); or no_match (a known
manufacturer, with every pattern missing). check_digit_ok says
whether position 9 holds the check digit. Then each fact in
COLUMNS, blank where the VIN is silent. Decoding ignores case and
surrounding space.
VinDecoder.enrich
columns names the facts to write, by default every one in
COLUMNS; ppa.SCHEMA already declares make, model and
model_year. A fact the book holds stays as given: only blank cells
change, so reported data always wins. A fact the table
lacks becomes a new column, typed when the schema declares it (see
COLUMNS). A row whose VIN fails to decode, with any status other than
decoded, stays as it is.
As a study scenario::
@scenario(“Decoded VINs”)
def decoded(book):
return decoder.enrich(book)
VinDecoder.close
check_digit
ValueError unless vin is 17 VIN characters: letters other than
I, O and Q, and digits.
is_valid
vin is 17 VIN characters with the check digit they require.
North American VINs carry a check digit. Many others use position 9 for
something else, and still decode.