init
This commit is contained in:
commit
a39858932a
|
|
@ -0,0 +1,7 @@
|
||||||
|
.git
|
||||||
|
.venv
|
||||||
|
.pytest_cache
|
||||||
|
.Python
|
||||||
|
*.tgz
|
||||||
|
*/__pycache__
|
||||||
|
*/*.egg-info
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,60 @@
|
||||||
|
SHELL := /bin/bash
|
||||||
|
MIN_PYTHON_VERSION = 3.11.0
|
||||||
|
INSTALLED_PYTHON := $(shell python -V | grep -Po '(?<=Python)(.+)')
|
||||||
|
MIN_VERSION_MET := $(shell if awk "BEGIN {exit !($(INSTALLED_PYTHON) >= $(MIN_PYTHON_VERSION))}"; then echo true; else echo false; fi)
|
||||||
|
LOCAL_PYTHON_PATH = .Python/bin/python$(shell echo $(MIN_PYTHON_VERSION)|grep -Po '[0-9]{1,2}.[0-9]{1,2}')
|
||||||
|
MINIMUM_COVERAGE = 80
|
||||||
|
WD = $(shell pwd)
|
||||||
|
|
||||||
|
define venv_run
|
||||||
|
source .venv/bin/activate && $1
|
||||||
|
endef
|
||||||
|
|
||||||
|
all: init standards test
|
||||||
|
|
||||||
|
create-environment:
|
||||||
|
ifeq ($(MIN_VERSION_MET), true)
|
||||||
|
python -m venv .venv
|
||||||
|
else
|
||||||
|
ifeq (,$(wildcard $(LOCAL_PYTHON_PATH)))
|
||||||
|
mkdir -p .Python
|
||||||
|
wget https://www.python.org/ftp/python/$(MIN_PYTHON_VERSION)/Python-$(MIN_PYTHON_VERSION).tgz -O Python-$(MIN_PYTHON_VERSION).tgz
|
||||||
|
tar -xvzf Python-$(MIN_PYTHON_VERSION).tgz
|
||||||
|
cd Python-$(MIN_PYTHON_VERSION) && ./configure --prefix $(WD)/.Python && make && make install
|
||||||
|
rm Python-$(MIN_PYTHON_VERSION).tgz
|
||||||
|
rm -R Python-$(MIN_PYTHON_VERSION)
|
||||||
|
endif
|
||||||
|
$(LOCAL_PYTHON_PATH) -m venv .venv
|
||||||
|
endif
|
||||||
|
|
||||||
|
install-dev:
|
||||||
|
$(call venv_run, pip install --upgrade pip)
|
||||||
|
$(call venv_run, pip install .[dev])
|
||||||
|
$(call venv_run, pip install -e .)
|
||||||
|
install:
|
||||||
|
$(call venv_run, pip install --upgrade pip)
|
||||||
|
$(call venv_run, pip install .)
|
||||||
|
|
||||||
|
dev-init: create-environment install-dev
|
||||||
|
init: create-environment install
|
||||||
|
|
||||||
|
# testing / standards
|
||||||
|
pytest:
|
||||||
|
$(call venv_run, pytest -v)
|
||||||
|
safety:
|
||||||
|
$(call venv_run, safety check)
|
||||||
|
bandit:
|
||||||
|
$(call venv_run, bandit -r src/)
|
||||||
|
flake:
|
||||||
|
$(call venv_run, flake8 src/)
|
||||||
|
coverage:
|
||||||
|
$(call venv_run, coverage run --omit .venv -m pytest && coverage report -m --fail-under=$(MINIMUM_COVERAGE))
|
||||||
|
autopep8:
|
||||||
|
$(call venv_run, autopep8 --in-place --recursive src/*)
|
||||||
|
pkg_size:
|
||||||
|
test/package_size.sh
|
||||||
|
test: pytest coverage pkg_size
|
||||||
|
standards: autopep8 bandit flake safety
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -Rf build dist .pytest_cache .coverage src/droppii/__pycache__ test/__pycache__
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
[project]
|
||||||
|
name = "uk_plate_reader"
|
||||||
|
version = "0.0.0"
|
||||||
|
description = ""
|
||||||
|
readme = ""
|
||||||
|
requires-python = ">=3.11"
|
||||||
|
dependencies = []
|
||||||
|
classifiers = [
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"License :: OSI Approved :: Apache Software License",
|
||||||
|
"Operating System :: Unix",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
dev = ["pytest"]
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["setuptools>=65.0"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
with open("./data/area_codes.json", "r") as f:
|
||||||
|
areas = json.load(f)
|
||||||
|
|
||||||
|
def get_legacy_year(plate:str):
|
||||||
|
base_year = 1983
|
||||||
|
try:
|
||||||
|
year_indicator = plate[0]
|
||||||
|
except IndexError:
|
||||||
|
return False
|
||||||
|
year_offset = ord(year_indicator.upper()) - ord("A")
|
||||||
|
year = base_year + year_offset
|
||||||
|
if year < 1983 or year >= 2001:
|
||||||
|
year = False
|
||||||
|
return year
|
||||||
|
|
||||||
|
def get_year(plate:str)->int:
|
||||||
|
year_indicator = int(plate[2:4])
|
||||||
|
if year_indicator >= 50:
|
||||||
|
year_indicator = year_indicator - 50
|
||||||
|
return year_indicator + 2000
|
||||||
|
|
||||||
|
def get_legacy_area(plate:str):
|
||||||
|
if len(plate.replace(" ","")) == 5:
|
||||||
|
area_code = plate[-1]
|
||||||
|
elif len(plate.replace(" ", "")) == 6:
|
||||||
|
area_code = plate[-2:]
|
||||||
|
return areas.get("legacy_style").get(area_code)
|
||||||
|
|
||||||
|
def get_area(plate:str):
|
||||||
|
area_code = plate[0:2]
|
||||||
|
area, _ = areas.get("modern_style").get(area_code)
|
||||||
|
return area
|
||||||
|
|
||||||
|
def is_legacy(plate):
|
||||||
|
try:
|
||||||
|
return int(plate[1])
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def read_licence_plate(plate:str):
|
||||||
|
if is_legacy(plate):
|
||||||
|
area = get_legacy_area(plate)
|
||||||
|
year = get_legacy_year(plate)
|
||||||
|
else:
|
||||||
|
area = get_area(plate)
|
||||||
|
year = get_year(plate)
|
||||||
|
if not area or not year:
|
||||||
|
raise Exception("Not a valid licence plate")
|
||||||
|
return [area, year]
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
print(read_licence_plate(sys.argv[1]))
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
from uk_plate_reader import read_licence_plate
|
||||||
|
import pytest # type: ignore
|
||||||
|
|
||||||
|
def test_old_plate_returns_correct_area():
|
||||||
|
assert read_licence_plate("N12 ANA")[0] == "Manchester"
|
||||||
|
assert read_licence_plate("L12 AOE")[0] == "Birmingham"
|
||||||
|
assert read_licence_plate("L12 AP")[0] == "Surrey"
|
||||||
|
|
||||||
|
def test_new_plate_returns_correct_area():
|
||||||
|
assert read_licence_plate("LL07 XYZ")[0] == "London"
|
||||||
|
assert read_licence_plate("OJ57 XYZ")[0] == "Oxford"
|
||||||
|
assert read_licence_plate("BB62 XYZ")[0] == "Birmingham"
|
||||||
|
|
||||||
|
def test_old_plate_returns_correct_year():
|
||||||
|
assert read_licence_plate("N12 AOE")[1] in [1995, 1996]
|
||||||
|
assert read_licence_plate("L12 AOE")[1] in [1993, 1994]
|
||||||
|
|
||||||
|
def test_new_plate_returns_correct_year():
|
||||||
|
assert read_licence_plate("AB07 XYZ")[1] == 2007
|
||||||
|
assert read_licence_plate("AB57 XYZ")[1] in [2007, 2008]
|
||||||
|
assert read_licence_plate("AB62 XYZ")[1] in [2012, 2013]
|
||||||
|
|
||||||
|
def test_invalid_plate_returns_error():
|
||||||
|
for plate in ["A", "ZZ07 LMA", "Z12 ANA", "Y12 ZZZ"]:
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
read_licence_plate(plate)
|
||||||
|
|
||||||
|
def test_empty_input_returns_error():
|
||||||
|
with pytest.raises(IndexError):
|
||||||
|
read_licence_plate("")
|
||||||
|
|
||||||
|
def test_legacy_single_char_area():
|
||||||
|
assert read_licence_plate("N12 AM")[0] == "Cheshire"
|
||||||
Loading…
Reference in New Issue