From fad37b2450d42769e296aaa79c438d5c07bd398b Mon Sep 17 00:00:00 2001 From: Tim Van Campenhout <45393594+vancamti@users.noreply.github.com> Date: Mon, 21 Oct 2024 08:01:41 +0200 Subject: [PATCH] Feature/28 gh actions (#29) * #28 update backend * #28 update backend --------- Co-authored-by: Tim Van Campenhout --- .github/pr-labeler.yml | 3 + .github/workflows/housenum_parser.yml | 38 ++++ .github/workflows/pr-labeler.yml | 22 ++ .pre-commit-config.yaml | 26 +++ .travis.yml | 19 -- docs/source/conf.py | 23 +-- housenumparser/element.py | 200 ++++++++++-------- housenumparser/merger.py | 84 ++++---- housenumparser/reader.py | 34 ++-- pyproject.toml | 57 ++++++ requirements-dev.txt | 76 ++++++- setup.py | 43 ---- tests/test_merge.py | 104 +++++----- tests/test_split.py | 278 +++++++++++++------------- tox.ini | 21 -- 15 files changed, 601 insertions(+), 427 deletions(-) create mode 100644 .github/pr-labeler.yml create mode 100644 .github/workflows/housenum_parser.yml create mode 100644 .github/workflows/pr-labeler.yml create mode 100644 .pre-commit-config.yaml delete mode 100644 .travis.yml create mode 100644 pyproject.toml delete mode 100755 setup.py delete mode 100644 tox.ini diff --git a/.github/pr-labeler.yml b/.github/pr-labeler.yml new file mode 100644 index 0000000..8888cd4 --- /dev/null +++ b/.github/pr-labeler.yml @@ -0,0 +1,3 @@ +feature: ['feature/*', 'feat/*'] +fix: ['bugfix/*', 'fix/*'] +test: test/* diff --git a/.github/workflows/housenum_parser.yml b/.github/workflows/housenum_parser.yml new file mode 100644 index 0000000..27bb9c8 --- /dev/null +++ b/.github/workflows/housenum_parser.yml @@ -0,0 +1,38 @@ +name: housenumparser backend tests +on: + push: + paths: + - housenumparser/** + - tests/** + - housenumparser.yaml + - pyproject.toml + - requirements*.txt +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [ "3.10", "3.11", "3.12" ] + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + # You can test your matrix by printing the current Python version + - name: Display Python version + run: python -c "import sys; print(sys.version)" + + - name: Install python requirements + env: + HATCH_BUILD_NO_HOOKS: true + working-directory: ./ + run: | + pip --version + pip install pip-tools + pip-sync requirements-dev.txt + pip install -e . + + - name: Python tests + run: pytest tests --exitfirst --capture=no -vvv --full-trace diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml new file mode 100644 index 0000000..ca9b94f --- /dev/null +++ b/.github/workflows/pr-labeler.yml @@ -0,0 +1,22 @@ +name: PR Labeler +on: + pull_request: + types: [opened] + branches: + - "develop" + - "epic" + +permissions: + contents: read + +jobs: + pr-labeler: + permissions: + contents: read # for TimonVS/pr-labeler-action to read config file + pull-requests: write # for TimonVS/pr-labeler-action to add labels in PR + runs-on: ubuntu-latest + steps: + - uses: TimonVS/pr-labeler-action@v4 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + configuration-path: .github/pr-labeler.yml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..7e98fc2 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,26 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + types: [python] + - id: trailing-whitespace + types: [python] +- repo: https://github.com/psf/black + rev: 24.8.0 + hooks: + - id: black + types: [python] + args: [--preview] +- repo: https://github.com/PyCQA/flake8 + rev: 7.1.1 + hooks: + - id: flake8 + additional_dependencies: [ + 'flake8-import-order==0.18.2' + ] + types: [python] + args: [--max-line-length=90] + exclude: .venv|./venv|__pycache__ + \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 57aec7d..0000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -sudo: false -language: python -os: linux -dist: focal -python: - - 3.7 - - 3.8 - - 3.9 - - 3.10 - - 3.11 -before_install: - - pip install -U setuptools pip -install: - - pip install -r requirements-dev.txt - - python setup.py develop -script: - - py.test --cov housenumparser --cov-report term-missing tests -after_success: - coveralls diff --git a/docs/source/conf.py b/docs/source/conf.py index fcb9742..ccd4f95 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -17,12 +17,12 @@ # -- Project information ----------------------------------------------------- -project = 'housenum-be-r-parser' -copyright = '2019 Onroerend Erfgoed' # noqa: A001 shadowed builtin -author = 'Onroerend Erfgoed' +project = "housenum-be-r-parser" +copyright = "2019 Onroerend Erfgoed" # noqa: A001 shadowed builtin +author = "Onroerend Erfgoed" # The full version, including alpha/beta/rc tags -release = '0.1.0' +release = "0.1.0" # -- General configuration --------------------------------------------------- @@ -30,15 +30,12 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.intersphinx' -] +extensions = ["sphinx.ext.autodoc", "sphinx.ext.intersphinx"] nitpicky = True # Add any paths that contain templates here, relative to this directory. -templates_path = [''] +templates_path = [""] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -52,7 +49,7 @@ # a list of builtin themes. # -html_theme = 'sphinx_rtd_theme' +html_theme = "sphinx_rtd_theme" # the oe theme doesn't look good for API documentation imo. # import oe_sphinx_theme # html_theme_path = [oe_sphinx_theme.get_theme_dir()] @@ -63,12 +60,12 @@ html_static_path = [] # -- intersphinx -intersphinx_mapping = {'py': ('https://docs.python.org/3.6', None)} +intersphinx_mapping = {"py": ("https://docs.python.org/3.6", None)} # -- autodoc -autoclass_content = 'both' # This adds __init__ documentation. +autoclass_content = "both" # This adds __init__ documentation. # -- rtd theme html_theme_options = { - 'navigation_depth': 6, + "navigation_depth": 6, } diff --git a/housenumparser/element.py b/housenumparser/element.py index fa87d2f..00b9c99 100644 --- a/housenumparser/element.py +++ b/housenumparser/element.py @@ -10,10 +10,19 @@ class Element: This can be a house number, a house number series, readingerror, etc. """ - def __init__(self, first_house_number, first_bis_number=-1, - first_bis_letter=-1, first_bus_number=-1, first_bus_letter=-1, - last_house_number=-1, last_bis_number=-1, last_bis_letter=-1, - last_bus_number=-1, last_bus_letter=-1): + def __init__( + self, + first_house_number, + first_bis_number=-1, + first_bis_letter=-1, + first_bus_number=-1, + first_bus_letter=-1, + last_house_number=-1, + last_bis_number=-1, + last_bis_letter=-1, + last_bus_number=-1, + last_bus_letter=-1, + ): """ :type first_house_number: int :param first_house_number: First house_number. @@ -73,6 +82,7 @@ class Action(Enum): """ Enum of possible actions to take when encountering bad input. """ + RAISE = 1 # Raises exception on bad input ERROR_MSG = 2 # An error message will return KEEP_ORIGINAL = 3 # The original data will return @@ -91,8 +101,8 @@ def __str__(self): if self.on_exc == ReadException.Action.KEEP_ORIGINAL: return self.data if self.on_exc == ReadException.Action.ERROR_MSG: - return f'{self.error}: {self.data}' - return ' Not implemented on_exc: ' + str(self.on_exc) + return f"{self.error}: {self.data}" + return " Not implemented on_exc: " + str(self.on_exc) class SequenceElement(Element): @@ -109,7 +119,8 @@ class HouseNumberSequence(SequenceElement): - "33, 34, 35, 36" -> "33-36" - "32, 33, 34, 35, 36"-> "32, 33-36" """ - regex = re.compile(r'^(\d+)-(\d+)$') + + regex = re.compile(r"^(\d+)-(\d+)$") def __init__(self, first_house_number, last_house_number, step=None): """ @@ -122,13 +133,10 @@ def __init__(self, first_house_number, last_house_number, step=None): :type step: int :param step: Step to take between first and last element. """ - self.step = step or self._default_step(first_house_number, - last_house_number) - super().__init__( - first_house_number, last_house_number=last_house_number - ) + self.step = step or self._default_step(first_house_number, last_house_number) + super().__init__(first_house_number, last_house_number=last_house_number) if self.first_house_number > self.last_house_number: - raise ValueError('Incorrect range') + raise ValueError("Incorrect range") def _default_step(self, first, last): """ @@ -145,17 +153,20 @@ def _default_step(self, first, last): return 2 if first % 2 == last % 2 else 1 def __str__(self): - return ('{first_house}-{last_house}' - .format(first_house=self.first_house_number, - last_house=self.last_house_number)) + return "{first_house}-{last_house}".format( + first_house=self.first_house_number, last_house=self.last_house_number + ) def split(self): """ - :returns: A list of :class:`HouseNumber` + :returns: A list of :class:`HouseNumber` """ - return [HouseNumber(number) for number - in range(self.first_house_number, self.last_house_number + 1, - self.step)] + return [ + HouseNumber(number) + for number in range( + self.first_house_number, self.last_house_number + 1, self.step + ) + ] class BisNumberSequence(SequenceElement): @@ -164,9 +175,12 @@ class BisNumberSequence(SequenceElement): eg: "33/1, 32/2, 33/3" -> "33/1-3" """ - regex = re.compile(r'^(\d+)[/_](\d+)-(\d+)$') - def __init__(self, house_number, first_bis_number, last_bis_number, original_string): + regex = re.compile(r"^(\d+)[/_](\d+)-(\d+)$") + + def __init__( + self, house_number, first_bis_number, last_bis_number, original_string + ): """ :type house_number: int :param house_number: House number. @@ -181,24 +195,27 @@ def __init__(self, house_number, first_bis_number, last_bis_number, original_str :param original_string: Original string """ super().__init__( - house_number, first_bis_number=first_bis_number, - last_bis_number=last_bis_number + house_number, + first_bis_number=first_bis_number, + last_bis_number=last_bis_number, ) self.original_string = original_string if self.first_bis_number > self.last_bis_number: - raise ValueError('Incorrect range') + raise ValueError("Incorrect range") def __str__(self): - if '_' in self.original_string: - return ('{house_number}_{first_bis}-{last_bis}' - .format(house_number=self.house_number, - first_bis=self.first_bis_number, - last_bis=self.last_bis_number)) + if "_" in self.original_string: + return "{house_number}_{first_bis}-{last_bis}".format( + house_number=self.house_number, + first_bis=self.first_bis_number, + last_bis=self.last_bis_number, + ) else: - return ('{house_number}/{first_bis}-{last_bis}' - .format(house_number=self.house_number, - first_bis=self.first_bis_number, - last_bis=self.last_bis_number)) + return "{house_number}/{first_bis}-{last_bis}".format( + house_number=self.house_number, + first_bis=self.first_bis_number, + last_bis=self.last_bis_number, + ) def split(self): """ @@ -214,7 +231,8 @@ class BisLetterSequence(SequenceElement): """ A series of bis letters. """ - regex = re.compile(r'^(\d+)/?([a-zA-Z]+)-([a-zA-Z]+)$') + + regex = re.compile(r"^(\d+)/?([a-zA-Z]+)-([a-zA-Z]+)$") def __init__(self, house_number, first_bis_letter, last_bis_letter): """ @@ -228,19 +246,21 @@ def __init__(self, house_number, first_bis_letter, last_bis_letter): :param last_bis_letter: Last letter of the series. """ super().__init__( - house_number, first_bis_letter=first_bis_letter, - last_bis_letter=last_bis_letter + house_number, + first_bis_letter=first_bis_letter, + last_bis_letter=last_bis_letter, ) start = ord(self.first_bis_letter) end = ord(self.last_bis_letter) if start > end: - raise ValueError('Incorrect range') + raise ValueError("Incorrect range") def __str__(self): - return ('{house_number}{first_letter}-{last_letter}' - .format(house_number=self.house_number, - first_letter=self.first_bis_letter, - last_letter=self.last_bis_letter)) + return "{house_number}{first_letter}-{last_letter}".format( + house_number=self.house_number, + first_letter=self.first_bis_letter, + last_letter=self.last_bis_letter, + ) def split(self): """ @@ -248,8 +268,7 @@ def split(self): """ start = ord(self.first_bis_letter) end = ord(self.last_bis_letter) - return [BisLetter(self.house_number, chr(i)) for i - in range(start, end + 1)] + return [BisLetter(self.house_number, chr(i)) for i in range(start, end + 1)] class BusNumberSequence(SequenceElement): @@ -258,7 +277,8 @@ class BusNumberSequence(SequenceElement): eg: "33 bus 1, 32 bus 2, 33 bus 3" -> "33 bus 1-3" """ - regex = re.compile(r'^(\d+)bus(\d+)-(\d+)$') + + regex = re.compile(r"^(\d+)bus(\d+)-(\d+)$") def __init__(self, house_number, first_bus_number, last_bus_number): """ @@ -272,24 +292,28 @@ def __init__(self, house_number, first_bus_number, last_bus_number): :param last_bus_number: Last number of the series. """ super().__init__( - house_number, first_bus_number=first_bus_number, - last_bus_number=last_bus_number + house_number, + first_bus_number=first_bus_number, + last_bus_number=last_bus_number, ) if self.first_bus_number > self.last_bus_number: - raise ValueError('Incorrect range') + raise ValueError("Incorrect range") def __str__(self): - return ('{house_number} bus {first_bus}-{last_bus}' - .format(house_number=self.house_number, - first_bus=self.first_bus_number, - last_bus=self.last_bus_number)) + return "{house_number} bus {first_bus}-{last_bus}".format( + house_number=self.house_number, + first_bus=self.first_bus_number, + last_bus=self.last_bus_number, + ) def split(self): """ :returns: A list of :class:`BusNumber` """ - return [BusNumber(self.house_number, bus_number) for bus_number - in range(self.first_bus_number, self.last_bus_number + 1)] + return [ + BusNumber(self.house_number, bus_number) + for bus_number in range(self.first_bus_number, self.last_bus_number + 1) + ] class BusLetterSequence(SequenceElement): @@ -298,7 +322,8 @@ class BusLetterSequence(SequenceElement): eg: "33 bus A, 32 bus B, 33 bus C" -> "33 bus A-C" """ - regex = re.compile(r'^(\d+)bus([a-zA-Z]+)-([a-zA-Z]+)$') + + regex = re.compile(r"^(\d+)bus([a-zA-Z]+)-([a-zA-Z]+)$") def __init__(self, house_number, first_bus_letter, last_bus_letter): """ @@ -312,27 +337,30 @@ def __init__(self, house_number, first_bus_letter, last_bus_letter): :param last_bus_letter: Last letter of the series. """ super().__init__( - house_number, first_bus_letter=first_bus_letter, - last_bus_letter=last_bus_letter + house_number, + first_bus_letter=first_bus_letter, + last_bus_letter=last_bus_letter, ) start = ord(self.first_bus_letter) end = ord(self.last_bus_letter) if start > end: - raise ValueError('Incorrect range') + raise ValueError("Incorrect range") def __str__(self): - return ('{house_number} bus {first_letter}-{last_letter}' - .format(house_number=self.house_number, - first_letter=self.first_bus_letter, - last_letter=self.last_bus_letter)) + return "{house_number} bus {first_letter}-{last_letter}".format( + house_number=self.house_number, + first_letter=self.first_bus_letter, + last_letter=self.last_bus_letter, + ) def split(self): """ :returns: A list of :class:`BusLetter` """ - return [BusLetter(self.house_number, chr(i)) for i - in range(ord(self.first_bus_letter), - ord(self.last_bus_letter) + 1)] + return [ + BusLetter(self.house_number, chr(i)) + for i in range(ord(self.first_bus_letter), ord(self.last_bus_letter) + 1) + ] class SingleElement(Element): @@ -348,8 +376,9 @@ class HouseNumber(SingleElement): """ A simple house number. eg: 13 or 15. """ + sequence_class = HouseNumberSequence - regex = re.compile(r'^(\d+)$') + regex = re.compile(r"^(\d+)$") def __str__(self): return str(self.house_number) @@ -361,8 +390,9 @@ class BisNumber(SingleElement): eg: "3/1" or "21/5" """ + sequence_class = BisNumberSequence - regex = re.compile(r'^(\d+)[/_](\d+)$') + regex = re.compile(r"^(\d+)[/_](\d+)$") def __init__(self, house_number, bis_number, original_string): """ @@ -386,12 +416,14 @@ def bis_number(self): return self.first_bis_number def __str__(self): - if '_' in self.original_string: - return '{house}_{bis_number}'.format(house=self.house_number, - bis_number=self.bis_number) + if "_" in self.original_string: + return "{house}_{bis_number}".format( + house=self.house_number, bis_number=self.bis_number + ) else: - return '{house}/{bis_number}'.format(house=self.house_number, - bis_number=self.bis_number) + return "{house}/{bis_number}".format( + house=self.house_number, bis_number=self.bis_number + ) class BusNumber(SingleElement): @@ -400,8 +432,9 @@ class BusNumber(SingleElement): eg: "3 bus 1" or "53 bus 5" """ + sequence_class = BusNumberSequence - regex = re.compile(r'^(\d+)bus(\d+)$') + regex = re.compile(r"^(\d+)bus(\d+)$") def __init__(self, house_number, bus_number): """ @@ -418,8 +451,9 @@ def bus_number(self): return self.first_bus_number def __str__(self): - return '{house} bus {bus_number}'.format(house=self.house_number, - bus_number=self.bus_number) + return "{house} bus {bus_number}".format( + house=self.house_number, bus_number=self.bus_number + ) class BusLetter(SingleElement): @@ -428,8 +462,9 @@ class BusLetter(SingleElement): eg: "3 bus A" or "53 bus D" """ + sequence_class = BusLetterSequence - regex = re.compile(r'^(\d+)bus([a-zA-Z])$') + regex = re.compile(r"^(\d+)bus([a-zA-Z])$") def __init__(self, house_number, bus_letter): """ @@ -446,8 +481,9 @@ def bus_letter(self): return self.first_bus_letter def __str__(self): - return '{house} bus {bus_letter}'.format(house=self.house_number, - bus_letter=self.bus_letter) + return "{house} bus {bus_letter}".format( + house=self.house_number, bus_letter=self.bus_letter + ) class BisLetter(SingleElement): @@ -456,8 +492,9 @@ class BisLetter(SingleElement): eg: "3A" or "53D" """ + sequence_class = BisLetterSequence - regex = re.compile(r'^(\d+)[/_]?([a-zA-Z])$') + regex = re.compile(r"^(\d+)[/_]?([a-zA-Z])$") def __init__(self, house_number, bis_letter): """ @@ -474,5 +511,6 @@ def bis_letter(self): return self.first_bis_letter def __str__(self): - return '{house}{bis_letter}'.format(house=self.house_number, - bis_letter=self.bis_letter) + return "{house}{bis_letter}".format( + house=self.house_number, bis_letter=self.bis_letter + ) diff --git a/housenumparser/merger.py b/housenumparser/merger.py index 9a6e3d1..fe3b41d 100644 --- a/housenumparser/merger.py +++ b/housenumparser/merger.py @@ -28,26 +28,26 @@ def group(data): :results: A dictionary containing lists of :class:`.element.SingleElement`. """ result = { - 'house_numbers': [], - 'bis_numbers': [], - 'bis_letters': [], - 'bus_numbers': [], - 'bus_letters': [], - 'bad_data': [], + "house_numbers": [], + "bis_numbers": [], + "bis_letters": [], + "bus_numbers": [], + "bus_letters": [], + "bad_data": [], } for x in data: if isinstance(x, HouseNumber): - result['house_numbers'].append(x) + result["house_numbers"].append(x) elif isinstance(x, BisNumber): - result['bis_numbers'].append(x) + result["bis_numbers"].append(x) elif isinstance(x, BisLetter): - result['bis_letters'].append(x) + result["bis_letters"].append(x) elif isinstance(x, BusNumber): - result['bus_numbers'].append(x) + result["bus_numbers"].append(x) elif isinstance(x, BusLetter): - result['bus_letters'].append(x) + result["bus_letters"].append(x) elif isinstance(x, ReadException): - result['bad_data'].append(x) + result["bad_data"].append(x) return result @@ -66,69 +66,79 @@ def merge_data(data, on_exc=ReadException.Action.ERROR_MSG): """ merged_data = [] merged_data.extend( - merge_numbers([obj.house_number for obj in data['house_numbers']], - lambda num: HouseNumber(num), - lambda first, last: HouseNumberSequence(first, last), - (1, 2)) + merge_numbers( + [obj.house_number for obj in data["house_numbers"]], + lambda num: HouseNumber(num), + lambda first, last: HouseNumberSequence(first, last), + (1, 2), + ) ) # For anything else below here, we must first "group by" the data # per house number numbers_per_house = collections.defaultdict(list) original_strings = {} - for element in data['bis_numbers']: + for element in data["bis_numbers"]: numbers_per_house[element.house_number].append(element.bis_number) original_strings[element.house_number] = element.original_string for house_number, numbers in numbers_per_house.items(): merged_data.extend( merge_numbers( - numbers, lambda num: BisNumber( + numbers, + lambda num: BisNumber( house_number, num, original_strings[house_number] ), lambda first, last: BisNumberSequence( house_number, first, last, original_strings[house_number] ), - (1,)) + (1,), + ) ) numbers_per_house = collections.defaultdict(list) - for element in data['bus_numbers']: + for element in data["bus_numbers"]: numbers_per_house[element.house_number].append(element.bus_number) for house_number, numbers in numbers_per_house.items(): merged_data.extend( merge_numbers( - numbers, lambda num: BusNumber(house_number, num), - lambda first, last: BusNumberSequence(house_number, first, - last), - (1,)) + numbers, + lambda num: BusNumber(house_number, num), + lambda first, last: BusNumberSequence(house_number, first, last), + (1,), + ) ) # Treat letters the same as numbers, use `ord` and `chr` to turn the # letters into numbers and back into letters. letters_per_house = collections.defaultdict(list) - for element in data['bis_letters']: + for element in data["bis_letters"]: letters_per_house[element.house_number].append(ord(element.bis_letter)) for house_number, numbers in letters_per_house.items(): merged_data.extend( merge_numbers( - numbers, lambda num: BisLetter(house_number, chr(num)), - lambda first, last: BisLetterSequence(house_number, chr(first), - chr(last)), - (1,)) + numbers, + lambda num: BisLetter(house_number, chr(num)), + lambda first, last: BisLetterSequence( + house_number, chr(first), chr(last) + ), + (1,), + ) ) letters_per_house = collections.defaultdict(list) - for element in data['bus_letters']: + for element in data["bus_letters"]: letters_per_house[element.house_number].append(ord(element.bus_letter)) for house_number, numbers in letters_per_house.items(): merged_data.extend( merge_numbers( - numbers, lambda num: BusLetter(house_number, chr(num)), - lambda first, last: BusLetterSequence(house_number, chr(first), - chr(last)), - (1,)) + numbers, + lambda num: BusLetter(house_number, chr(num)), + lambda first, last: BusLetterSequence( + house_number, chr(first), chr(last) + ), + (1,), + ) ) # raise wouldn't have reached this point, drop needs no action. - if on_exc in (ReadException.Action.ERROR_MSG, - ReadException.Action.KEEP_ORIGINAL): - merged_data.extend(data['bad_data']) + if on_exc in (ReadException.Action.ERROR_MSG, ReadException.Action.KEEP_ORIGINAL): + merged_data.extend(data["bad_data"]) return merged_data diff --git a/housenumparser/reader.py b/housenumparser/reader.py index 4590af6..2bb21b2 100644 --- a/housenumparser/reader.py +++ b/housenumparser/reader.py @@ -41,8 +41,7 @@ def read_data(data, step=None, on_exc=ReadException.Action.ERROR_MSG): :returns: A list from of the data. """ - return read_iterable(str(data).split(","), step=step, - on_exc=on_exc) + return read_iterable(str(data).split(","), step=step, on_exc=on_exc) def read_iterable(inputs, step=None, on_exc=ReadException.Action.ERROR_MSG): @@ -91,22 +90,32 @@ def read_element(data, step=None, on_exc=ReadException.Action.ERROR_MSG): :returns: A :class:`.element.Element` OR an exception in case of incorrect data. """ - element_classes = [BusNumberSequence, BusLetterSequence, BisNumberSequence, - BisLetterSequence, BusNumber, BusLetter, BisNumber, - BisLetter, HouseNumberSequence, HouseNumber] - stripped_data = re.sub(r'\s', '', data) + element_classes = [ + BusNumberSequence, + BusLetterSequence, + BisNumberSequence, + BisLetterSequence, + BusNumber, + BusLetter, + BisNumber, + BisLetter, + HouseNumberSequence, + HouseNumber, + ] + stripped_data = re.sub(r"\s", "", data) exception = None try: for element_class in element_classes: match = element_class.regex.match(stripped_data) if match: - args = [int(group) if group.isdigit() else group - for group in match.groups()] + args = [ + int(group) if group.isdigit() else group for group in match.groups() + ] kwargs = {} if element_class == HouseNumberSequence: - kwargs['step'] = step + kwargs["step"] = step if element_class in [BisNumber, BisNumberSequence]: - kwargs['original_string'] = stripped_data + kwargs["original_string"] = stripped_data return element_class(*args, **kwargs) except ValueError as e: exception = e @@ -115,11 +124,10 @@ def read_element(data, step=None, on_exc=ReadException.Action.ERROR_MSG): msg = str(exception) else: msg = "Could not parse/understand" - raise ValueError(msg + ': ' + data) + raise ValueError(msg + ": " + data) elif on_exc == ReadException.Action.DROP: return None - elif on_exc in (ReadException.Action.ERROR_MSG, - ReadException.Action.KEEP_ORIGINAL): + elif on_exc in (ReadException.Action.ERROR_MSG, ReadException.Action.KEEP_ORIGINAL): if exception: msg = str(exception) else: diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..e3d94f1 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,57 @@ +[build-system] +requires = ["hatchling", "hatch-fancy-pypi-readme"] +build-backend = "hatchling.build" + +[project] +version = "0.2.0" +name = "housenumparser" +dynamic = ["readme"] +authors = [ + { name = "Flanders Heritage Agency", email = "ict@onroerenderfgoed.be" }, +] +license = "MIT" +description = "housenum_be_r_parser" +requires-python = ">=3.10,<3.13" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Programming Language :: Python", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] +dependencies = [ +] + +[project.urls] +History = "https://github.com/OnroerendErfgoed/housenum-be-r-parser/blob/master/CHANGES.txt" +Tracker = "https://github.com/OnroerendErfgoed/housenum-be-r-parser/issues" +Source = "https://github.com/OnroerendErfgoed/housenum-be-r-parser" + +[project.optional-dependencies] +dev = [ + "uv==0.4.1", + "pytest==8.3.3", + "pytest-cov==5.0.0", + "coveralls==4.0.1", + "sphinx==8.0.2", +] + +## +# Build tool specific +## +[tool.hatch.build.targets.wheel] +# In the wheel we want to have housenumparser in the root as python module. +only-include = [ + "/housenumparser", +] + +[tool.hatch.metadata] +# This allows us to use github links as dependencies +allow-direct-references = true + +[tool.hatch.metadata.hooks.fancy-pypi-readme] +content-type = "text/x-rst" +fragments = [ + { path = "README.rst" }, + { path = "CHANGES.txt" }, +] diff --git a/requirements-dev.txt b/requirements-dev.txt index 058b651..c476f36 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,10 +1,66 @@ -# Runtime requirements ---requirement requirements.txt - -# Testing -pytest==6.2.5 -pytest-cov==3.0.0 -coveralls==3.3.1 - -# Documentation -Sphinx==4.3.2 +alabaster==1.0.0 + # via sphinx +babel==2.16.0 + # via sphinx +certifi==2024.8.30 + # via requests +charset-normalizer==3.3.2 + # via requests +coverage==7.6.1 + # via + # coveralls + # pytest-cov +coveralls==4.0.1 + # via housenumparser (pyproject.toml) +docopt==0.6.2 + # via coveralls +docutils==0.21.2 + # via sphinx +idna==3.10 + # via requests +imagesize==1.4.1 + # via sphinx +iniconfig==2.0.0 + # via pytest +jinja2==3.1.4 + # via sphinx +markupsafe==2.1.5 + # via jinja2 +packaging==24.1 + # via + # pytest + # sphinx +pluggy==1.5.0 + # via pytest +pygments==2.18.0 + # via sphinx +pytest==8.3.3 + # via + # housenumparser (pyproject.toml) + # pytest-cov +pytest-cov==5.0.0 + # via housenumparser (pyproject.toml) +requests==2.32.3 + # via + # coveralls + # sphinx +snowballstemmer==2.2.0 + # via sphinx +sphinx==8.0.2 + # via housenumparser (pyproject.toml) +sphinxcontrib-applehelp==2.0.0 + # via sphinx +sphinxcontrib-devhelp==2.0.0 + # via sphinx +sphinxcontrib-htmlhelp==2.1.0 + # via sphinx +sphinxcontrib-jsmath==1.0.1 + # via sphinx +sphinxcontrib-qthelp==2.0.0 + # via sphinx +sphinxcontrib-serializinghtml==2.0.0 + # via sphinx +urllib3==2.2.3 + # via requests +uv==0.4.1 + # via housenumparser (pyproject.toml) diff --git a/setup.py b/setup.py deleted file mode 100755 index 5122543..0000000 --- a/setup.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python - -import os - -from setuptools import find_packages -from setuptools import setup - -here = os.path.abspath(os.path.dirname(__file__)) -README = open(os.path.join(here, 'README.rst')).read() - - -requires = [] - -setup( - name='housenumparser', - version='0.2.0', - description='housenum_be_r_parser', - long_description=README, - author='Onroerend Erfgoed', - author_email='ict@onroerenderfgoed.be', - url='http://github.com/onroerenderfgoed/housenum-be-r-parser', - packages=find_packages(), - package_data={'': ['LICENSE']}, - package_dir={'housenumparser': 'housenumparser'}, - include_package_data=True, - install_requires=requires, - license='MIT', - zip_safe=False, - classifiers=[ - 'Development Status :: 4 - Beta', - 'Intended Audience :: Developers', - 'Natural Language :: English', - 'License :: OSI Approved :: MIT License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', - ], - test_suite='tox' -) diff --git a/tests/test_merge.py b/tests/test_merge.py index 9000e01..c9b0d97 100644 --- a/tests/test_merge.py +++ b/tests/test_merge.py @@ -5,103 +5,107 @@ def test_all_forms(): - label = ('32-36, 25-31, 1A-F, 2/1-10, 4 bus 1-30, 43, 44 bus 1, 45/1, ' - '46A, 33 bus A-C, 132_1') + label = ( + "32-36, 25-31, 1A-F, 2/1-10, 4 bus 1-30, 43, 44 bus 1, 45/1, " + "46A, 33 bus A-C, 132_1" + ) house_numbers = housenumparser.merge(label) assert isinstance(house_numbers, list) assert 11 == len(house_numbers) house_numbers = [str(house_number) for house_number in house_numbers] - assert '25-31' in house_numbers - assert '32-36' in house_numbers - assert '43' in house_numbers - assert '2/1-10' in house_numbers - assert '45/1' in house_numbers - assert '1A-F' in house_numbers - assert '46A' in house_numbers - assert '44 bus 1' in house_numbers - assert '4 bus 1-30' in house_numbers - assert '33 bus A-C' in house_numbers - assert '132_1' in house_numbers + assert "25-31" in house_numbers + assert "32-36" in house_numbers + assert "43" in house_numbers + assert "2/1-10" in house_numbers + assert "45/1" in house_numbers + assert "1A-F" in house_numbers + assert "46A" in house_numbers + assert "44 bus 1" in house_numbers + assert "4 bus 1-30" in house_numbers + assert "33 bus A-C" in house_numbers + assert "132_1" in house_numbers def test_none(): - label = [None, '1'] + label = [None, "1"] house_numbers = housenumparser.merge( label, on_exc=ReadException.Action.KEEP_ORIGINAL ) house_numbers = [str(house_number) for house_number in house_numbers] - assert 'None' in house_numbers - assert '1' in house_numbers + assert "None" in house_numbers + assert "1" in house_numbers label = None house_numbers = housenumparser.merge( label, on_exc=ReadException.Action.KEEP_ORIGINAL ) house_numbers = [str(house_number) for house_number in house_numbers] - assert 'None' in house_numbers + assert "None" in house_numbers def test_house_number_sequences(): - label = ('32, 34, 36, 38, 25, 27, 29, 31, 39, 40, 41, 42, 43, 44, 46, ' - '47, 48, 49, 50, 52, 54') + label = ( + "32, 34, 36, 38, 25, 27, 29, 31, 39, 40, 41, 42, 43, 44, 46, " + "47, 48, 49, 50, 52, 54" + ) house_numbers = housenumparser.merge(label) assert isinstance(house_numbers, list) assert 5 == len(house_numbers) house_numbers = [str(house_number) for house_number in house_numbers] - assert '25-31' in house_numbers - assert '32-38' in house_numbers - assert '39-44' in house_numbers - assert '46-49' in house_numbers - assert '50-54' in house_numbers + assert "25-31" in house_numbers + assert "32-38" in house_numbers + assert "39-44" in house_numbers + assert "46-49" in house_numbers + assert "50-54" in house_numbers def test_combination_house_number_sequences(): - label = '25-31, 18-26' + label = "25-31, 18-26" house_numbers = housenumparser.merge(label) assert isinstance(house_numbers, list) assert 3 == len(house_numbers) house_numbers = [str(house_number) for house_number in house_numbers] - assert '18-24' in house_numbers - assert '25-26' in house_numbers - assert '27-31' in house_numbers + assert "18-24" in house_numbers + assert "25-26" in house_numbers + assert "27-31" in house_numbers def test_list_combination_house_number_sequences(): - label = ['25-31', '18-26'] + label = ["25-31", "18-26"] house_numbers = housenumparser.merge(label) assert isinstance(house_numbers, list) assert 3 == len(house_numbers) house_numbers = [str(house_number) for house_number in house_numbers] - assert '18-24' in house_numbers - assert '25-26' in house_numbers - assert '27-31' in house_numbers + assert "18-24" in house_numbers + assert "25-26" in house_numbers + assert "27-31" in house_numbers def test_bis_number_sequences(): - label = '10/1-3, 10/4, 15/3-7, 15/8-10' + label = "10/1-3, 10/4, 15/3-7, 15/8-10" house_numbers = housenumparser.merge(label) assert isinstance(house_numbers, list) assert 2 == len(house_numbers) house_numbers = [str(house_number) for house_number in house_numbers] - assert '10/1-4' in house_numbers - assert '15/3-10' in house_numbers + assert "10/1-4" in house_numbers + assert "15/3-10" in house_numbers def test_house_number_no_sequences(): - label = '32, 37' + label = "32, 37" house_numbers = housenumparser.merge(label) assert isinstance(house_numbers, list) assert 2 == len(house_numbers) house_numbers = [str(house_number) for house_number in house_numbers] - assert '32' in house_numbers - assert '37' in house_numbers + assert "32" in house_numbers + assert "37" in house_numbers def test_overlapping_ranges(): - label = '1-11, 5-9' + label = "1-11, 5-9" house_numbers = housenumparser.merge(label) assert isinstance(house_numbers, list) assert 1 == len(house_numbers) - assert '1-11' == str(house_numbers[0]) + assert "1-11" == str(house_numbers[0]) def test_special_characters(): @@ -111,28 +115,26 @@ def test_special_characters(): The 'proper way' is dependant on the `on_exc` parameter. """ - label = '1ëâB, 1-11' - house_numbers = housenumparser.merge(label, - on_exc=ReadException.Action.DROP) + label = "1ëâB, 1-11" + house_numbers = housenumparser.merge(label, on_exc=ReadException.Action.DROP) assert isinstance(house_numbers, list) assert 1 == len(house_numbers) - assert '1-11' == str(house_numbers[0]) + assert "1-11" == str(house_numbers[0]) with pytest.raises(ValueError) as e: housenumparser.merge(label, on_exc=ReadException.Action.RAISE) - assert 'Could not parse/understand: 1ëâB' == str(e.value) + assert "Could not parse/understand: 1ëâB" == str(e.value) house_numbers = housenumparser.merge( label, on_exc=ReadException.Action.KEEP_ORIGINAL ) assert isinstance(house_numbers, list) assert 2 == len(house_numbers) - assert '1-11' == str(house_numbers[0]) - assert '1ëâB' == str(house_numbers[1]) + assert "1-11" == str(house_numbers[0]) + assert "1ëâB" == str(house_numbers[1]) - house_numbers = housenumparser.merge(label, - on_exc=ReadException.Action.ERROR_MSG) + house_numbers = housenumparser.merge(label, on_exc=ReadException.Action.ERROR_MSG) assert isinstance(house_numbers, list) assert 2 == len(house_numbers) - assert '1-11' == str(house_numbers[0]) - assert 'Could not parse/understand: 1ëâB' == str(house_numbers[1]) + assert "1-11" == str(house_numbers[0]) + assert "Could not parse/understand: 1ëâB" == str(house_numbers[1]) diff --git a/tests/test_split.py b/tests/test_split.py index 323c91b..3baae13 100644 --- a/tests/test_split.py +++ b/tests/test_split.py @@ -10,358 +10,358 @@ def test_single_number(): - label = '25' + label = "25" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert 1 == len(house_numbers) hnr = house_numbers[0] assert isinstance(hnr, HouseNumber) - assert str(hnr) == '25' + assert str(hnr) == "25" def test_list_single_number(): - label = ['25'] + label = ["25"] house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert 1 == len(house_numbers) hnr = house_numbers[0] assert isinstance(hnr, HouseNumber) - assert str(hnr) == '25' + assert str(hnr) == "25" def test_single_bis_letter(): - label = '25A' + label = "25A" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 1 hnr = house_numbers[0] assert isinstance(hnr, BisLetter) - assert str(hnr) == '25A' + assert str(hnr) == "25A" def test_double_bis_letter(): - label = '25AB' + label = "25AB" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 1 hnr = house_numbers[0] assert isinstance(hnr, ReadException) - assert str(hnr) == 'Could not parse/understand: 25AB' + assert str(hnr) == "Could not parse/understand: 25AB" def test_single_bis_number(): - label = '25/1' + label = "25/1" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 1 hnr = house_numbers[0] assert isinstance(hnr, BisNumber) - assert str(hnr) == '25/1' + assert str(hnr) == "25/1" def test_bis_number_underscore(): - label = '111_1' + label = "111_1" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 1 hnr = house_numbers[0] assert isinstance(hnr, BisNumber) - assert str(hnr) == '111_1' + assert str(hnr) == "111_1" def test_bus_number(): - label = '25 bus 3' + label = "25 bus 3" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 1 hnr = house_numbers[0] assert isinstance(hnr, BusNumber) - assert str(hnr) == '25 bus 3' + assert str(hnr) == "25 bus 3" def test_bus_letter(): - label = '25 bus A' + label = "25 bus A" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 1 hnr = house_numbers[0] assert isinstance(hnr, BusLetter) - assert str(hnr) == '25 bus A' + assert str(hnr) == "25 bus A" def test_double_bus_letter(): - label = '25 bus AB' + label = "25 bus AB" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 1 hnr = house_numbers[0] assert isinstance(hnr, ReadException) - assert str(hnr) == 'Could not parse/understand: 25 bus AB' + assert str(hnr) == "Could not parse/understand: 25 bus AB" def test_house_number_sequence(): - label = '25,27,29,31' + label = "25,27,29,31" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 4 - assert str(house_numbers[0]) == '25' - assert str(house_numbers[1]) == '27' - assert str(house_numbers[2]) == '29' - assert str(house_numbers[3]) == '31' + assert str(house_numbers[0]) == "25" + assert str(house_numbers[1]) == "27" + assert str(house_numbers[2]) == "29" + assert str(house_numbers[3]) == "31" def test_list_house_number_sequence_2(): - label = ['25', '27', '29', '31'] + label = ["25", "27", "29", "31"] house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 4 - assert str(house_numbers[0]) == '25' - assert str(house_numbers[1]) == '27' - assert str(house_numbers[2]) == '29' - assert str(house_numbers[3]) == '31' + assert str(house_numbers[0]) == "25" + assert str(house_numbers[1]) == "27" + assert str(house_numbers[2]) == "29" + assert str(house_numbers[3]) == "31" def test_string_house_number_sequence(): - label = '25-31' + label = "25-31" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 4 - assert str(house_numbers[0]) == '25' - assert str(house_numbers[1]) == '27' - assert str(house_numbers[2]) == '29' - assert str(house_numbers[3]) == '31' + assert str(house_numbers[0]) == "25" + assert str(house_numbers[1]) == "27" + assert str(house_numbers[2]) == "29" + assert str(house_numbers[3]) == "31" def test_string_house_number_sequence_2(): - label = '25-32' + label = "25-32" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 8 - assert '25' == str(house_numbers[0]) - assert '26' == str(house_numbers[1]) - assert '27' == str(house_numbers[2]) - assert '28' == str(house_numbers[3]) - assert '29' == str(house_numbers[4]) - assert '30' == str(house_numbers[5]) - assert '31' == str(house_numbers[6]) - assert '32' == str(house_numbers[7]) + assert "25" == str(house_numbers[0]) + assert "26" == str(house_numbers[1]) + assert "27" == str(house_numbers[2]) + assert "28" == str(house_numbers[3]) + assert "29" == str(house_numbers[4]) + assert "30" == str(house_numbers[5]) + assert "31" == str(house_numbers[6]) + assert "32" == str(house_numbers[7]) def test_house_number_sequence_special(): - label = '25,26-31' + label = "25,26-31" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 7 - assert '25' == str(house_numbers[0]) - assert '26' == str(house_numbers[1]) - assert '27' == str(house_numbers[2]) - assert '28' == str(house_numbers[3]) - assert '29' == str(house_numbers[4]) - assert '30' == str(house_numbers[5]) - assert '31' == str(house_numbers[6]) + assert "25" == str(house_numbers[0]) + assert "26" == str(house_numbers[1]) + assert "27" == str(house_numbers[2]) + assert "28" == str(house_numbers[3]) + assert "29" == str(house_numbers[4]) + assert "30" == str(house_numbers[5]) + assert "31" == str(house_numbers[6]) def test_combination_house_number_sequences(): - label = '25-31,18-26' + label = "25-31,18-26" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 9 - assert '25' == str(house_numbers[0]) - assert '27' == str(house_numbers[1]) - assert '29' == str(house_numbers[2]) - assert '31' == str(house_numbers[3]) - assert '18' == str(house_numbers[4]) - assert '20' == str(house_numbers[5]) - assert '22' == str(house_numbers[6]) - assert '24' == str(house_numbers[7]) - assert '26' == str(house_numbers[8]) + assert "25" == str(house_numbers[0]) + assert "27" == str(house_numbers[1]) + assert "29" == str(house_numbers[2]) + assert "31" == str(house_numbers[3]) + assert "18" == str(house_numbers[4]) + assert "20" == str(house_numbers[5]) + assert "22" == str(house_numbers[6]) + assert "24" == str(house_numbers[7]) + assert "26" == str(house_numbers[8]) def test_bus_number_sequence(): - label = '25 bus 3-7' + label = "25 bus 3-7" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 5 - assert '25 bus 3' == str(house_numbers[0]) - assert '25 bus 4' == str(house_numbers[1]) - assert '25 bus 5' == str(house_numbers[2]) - assert '25 bus 6' == str(house_numbers[3]) - assert '25 bus 7' == str(house_numbers[4]) + assert "25 bus 3" == str(house_numbers[0]) + assert "25 bus 4" == str(house_numbers[1]) + assert "25 bus 5" == str(house_numbers[2]) + assert "25 bus 6" == str(house_numbers[3]) + assert "25 bus 7" == str(house_numbers[4]) def test_bus_letter_sequence(): - label = '25 bus C-F' + label = "25 bus C-F" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 4 - assert '25 bus C' == str(house_numbers[0]) - assert '25 bus D' == str(house_numbers[1]) - assert '25 bus E' == str(house_numbers[2]) - assert '25 bus F' == str(house_numbers[3]) + assert "25 bus C" == str(house_numbers[0]) + assert "25 bus D" == str(house_numbers[1]) + assert "25 bus E" == str(house_numbers[2]) + assert "25 bus F" == str(house_numbers[3]) def test_bis_letter_sequence(): - label = '25C-F' + label = "25C-F" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 4 - assert '25C' == str(house_numbers[0]) - assert '25D' == str(house_numbers[1]) - assert '25E' == str(house_numbers[2]) - assert '25F' == str(house_numbers[3]) + assert "25C" == str(house_numbers[0]) + assert "25D" == str(house_numbers[1]) + assert "25E" == str(house_numbers[2]) + assert "25F" == str(house_numbers[3]) def test_bis_letter_sequence_wrong(): - label = '25F-C' + label = "25F-C" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert len(house_numbers) == 1 - assert 'Incorrect range: 25F-C' == str(house_numbers[0]) + assert "Incorrect range: 25F-C" == str(house_numbers[0]) def test_bis_number_sequence(): - label = '25/3-7' + label = "25/3-7" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert 5 == len(house_numbers) - assert '25/3' == str(house_numbers[0]) - assert '25/4' == str(house_numbers[1]) - assert '25/5' == str(house_numbers[2]) - assert '25/6' == str(house_numbers[3]) - assert '25/7' == str(house_numbers[4]) + assert "25/3" == str(house_numbers[0]) + assert "25/4" == str(house_numbers[1]) + assert "25/5" == str(house_numbers[2]) + assert "25/6" == str(house_numbers[3]) + assert "25/7" == str(house_numbers[4]) def test_combination_sequences(): - label = '25C-F,28-32,29 bus 2-5' + label = "25C-F,28-32,29 bus 2-5" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert 11 == len(house_numbers) - assert '25C' == str(house_numbers[0]) - assert '25D' == str(house_numbers[1]) - assert '25E' == str(house_numbers[2]) - assert '25F' == str(house_numbers[3]) - assert '28' == str(house_numbers[4]) - assert '30' == str(house_numbers[5]) - assert '32' == str(house_numbers[6]) - assert '29 bus 2' == str(house_numbers[7]) - assert '29 bus 3' == str(house_numbers[8]) - assert '29 bus 4' == str(house_numbers[9]) - assert '29 bus 5' == str(house_numbers[10]) + assert "25C" == str(house_numbers[0]) + assert "25D" == str(house_numbers[1]) + assert "25E" == str(house_numbers[2]) + assert "25F" == str(house_numbers[3]) + assert "28" == str(house_numbers[4]) + assert "30" == str(house_numbers[5]) + assert "32" == str(house_numbers[6]) + assert "29 bus 2" == str(house_numbers[7]) + assert "29 bus 3" == str(house_numbers[8]) + assert "29 bus 4" == str(house_numbers[9]) + assert "29 bus 5" == str(house_numbers[10]) def test_bis_number_and_house_number_sequence(): - label = '2A,7-11' + label = "2A,7-11" house_numbers = housenumparser.split(label) assert isinstance(house_numbers, list) assert 4 == len(house_numbers) - assert '2A' == str(house_numbers[0]) - assert '7' == str(house_numbers[1]) - assert '9' == str(house_numbers[2]) - assert '11' == str(house_numbers[3]) + assert "2A" == str(house_numbers[0]) + assert "7" == str(house_numbers[1]) + assert "9" == str(house_numbers[2]) + assert "11" == str(house_numbers[3]) def test_invalid_input_keep_original(): - label = 'A,1/3,?' + label = "A,1/3,?" house_numbers = housenumparser.split( label, on_exc=ReadException.Action.KEEP_ORIGINAL ) assert isinstance(house_numbers, list) assert 3 == len(house_numbers) - assert 'A' == str(house_numbers[0]) - assert '1/3' == str(house_numbers[1]) - assert '?' == str(house_numbers[2]) + assert "A" == str(house_numbers[0]) + assert "1/3" == str(house_numbers[1]) + assert "?" == str(house_numbers[2]) def test_invalid_input_ignore_errors(): - house_numbers = housenumparser.split('A,1/3,?', - on_exc=ReadException.Action.ERROR_MSG) + house_numbers = housenumparser.split( + "A,1/3,?", on_exc=ReadException.Action.ERROR_MSG + ) assert isinstance(house_numbers, list) assert 3 == len(house_numbers) - assert 'Could not parse/understand: A' == str(house_numbers[0]) - assert '1/3' == str(house_numbers[1]) - assert 'Could not parse/understand: ?' == str(house_numbers[2]) + assert "Could not parse/understand: A" == str(house_numbers[0]) + assert "1/3" == str(house_numbers[1]) + assert "Could not parse/understand: ?" == str(house_numbers[2]) def test_bogus_input_drop_errors(): - house_numbers = housenumparser.split('A,1/3,?', - on_exc=ReadException.Action.DROP) + house_numbers = housenumparser.split("A,1/3,?", on_exc=ReadException.Action.DROP) assert isinstance(house_numbers, list) assert 1 == len(house_numbers) - assert '1/3' == str(house_numbers[0]) + assert "1/3" == str(house_numbers[0]) def test_bogus_input_raise_errors(): with pytest.raises(ValueError): - housenumparser.split('A,1/3,?', on_exc=ReadException.Action.RAISE) + housenumparser.split("A,1/3,?", on_exc=ReadException.Action.RAISE) def test_split_wrong_on_exc(): - label = 'A,1/3,?' + label = "A,1/3,?" with pytest.raises(ValueError) as e: - housenumparser.split(label, on_exc='invalid') - assert 'Not implemented on_exc: invalid' == str(e.value) + housenumparser.split(label, on_exc="invalid") + assert "Not implemented on_exc: invalid" == str(e.value) def test_input_with_spaces(): - label = ' A , 1/3 , 5 - 7 ' + label = " A , 1/3 , 5 - 7 " house_numbers = housenumparser.split( label, on_exc=ReadException.Action.KEEP_ORIGINAL ) assert isinstance(house_numbers, list) assert 4 == len(house_numbers) - assert 'A' == str(house_numbers[0]) - assert '1/3' == str(house_numbers[1]) - assert '5' == str(house_numbers[2]) - assert '7' == str(house_numbers[3]) + assert "A" == str(house_numbers[0]) + assert "1/3" == str(house_numbers[1]) + assert "5" == str(house_numbers[2]) + assert "7" == str(house_numbers[3]) def test_house_numbers_with_step_1(): - label = '10-12' + label = "10-12" house_numbers = housenumparser.split(label, step=1) assert isinstance(house_numbers, list) assert 3 == len(house_numbers) - assert '10' == str(house_numbers[0]) - assert '11' == str(house_numbers[1]) - assert '12' == str(house_numbers[2]) + assert "10" == str(house_numbers[0]) + assert "11" == str(house_numbers[1]) + assert "12" == str(house_numbers[2]) def test_house_numbers_with_step_2(): - label = '10-12' + label = "10-12" house_numbers = housenumparser.split(label, step=2) assert isinstance(house_numbers, list) assert 2 == len(house_numbers) - assert '10' == str(house_numbers[0]) - assert '12' == str(house_numbers[1]) + assert "10" == str(house_numbers[0]) + assert "12" == str(house_numbers[1]) def test_split_wrong_house_number_range(): - label = '10-5' + label = "10-5" with pytest.raises(ValueError) as e: housenumparser.split(label, on_exc=ReadException.Action.RAISE) - assert 'Incorrect range: 10-5' == str(e.value) + assert "Incorrect range: 10-5" == str(e.value) def test_split_wrong_bus_number_range(): - label = '1 bus 6-2' + label = "1 bus 6-2" with pytest.raises(ValueError) as e: housenumparser.split(label, on_exc=ReadException.Action.RAISE) - assert 'Incorrect range: 1 bus 6-2' == str(e.value) + assert "Incorrect range: 1 bus 6-2" == str(e.value) def test_split_wrong_bis_number_range(): - label = '1/6-2' + label = "1/6-2" with pytest.raises(ValueError) as e: housenumparser.split(label, on_exc=ReadException.Action.RAISE) - assert 'Incorrect range: 1/6-2' == str(e.value) + assert "Incorrect range: 1/6-2" == str(e.value) def test_split_wrong_bus_letter_range(): - label = '1 bus D-A' + label = "1 bus D-A" with pytest.raises(ValueError) as e: housenumparser.split(label, on_exc=ReadException.Action.RAISE) - assert 'Incorrect range: 1 bus D-A' == str(e.value) + assert "Incorrect range: 1 bus D-A" == str(e.value) def test_wrong_on_exc(): - element = ReadException('error_msg', on_exc='ïnvalid') - assert ' Not implemented on_exc: ïnvalid' == str(element) + element = ReadException("error_msg", on_exc="ïnvalid") + assert " Not implemented on_exc: ïnvalid" == str(element) diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 4b53c2c..0000000 --- a/tox.ini +++ /dev/null @@ -1,21 +0,0 @@ -[tox] -envlist = py27, py35, py36, cover - - -[testenv] -deps = - --requirement - {toxinidir}/requirements-dev.txt -commands = - python setup.py develop - py.test tests/ - - -[testenv:cover] -basepython = python -deps = - --requirement - {toxinidir}/requirements-dev.txt -commands = - python setup.py develop - py.test --cov housenumparser --cov-report term-missing tests