parkapi-sources 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- parkapi_sources-0.2.0/.github/dependabot.yml +14 -0
- parkapi_sources-0.2.0/.github/workflows/build-publish.yml +92 -0
- parkapi_sources-0.2.0/.github/workflows/lint.yml +43 -0
- parkapi_sources-0.2.0/.gitignore +19 -0
- parkapi_sources-0.2.0/LICENCE.txt +21 -0
- parkapi_sources-0.2.0/Makefile +23 -0
- parkapi_sources-0.2.0/PKG-INFO +256 -0
- parkapi_sources-0.2.0/README.md +222 -0
- parkapi_sources-0.2.0/data/freiburg.geojson +424 -0
- parkapi_sources-0.2.0/data/heidelberg.geojson +455 -0
- parkapi_sources-0.2.0/data/mannheim.geojson +442 -0
- parkapi_sources-0.2.0/data/ulm.geojson +213 -0
- parkapi_sources-0.2.0/dev/parkapi.py +17 -0
- parkapi_sources-0.2.0/dev/test-pull-converter.py +73 -0
- parkapi_sources-0.2.0/dev/test-push-converter.py +107 -0
- parkapi_sources-0.2.0/pyproject.toml +139 -0
- parkapi_sources-0.2.0/requirements-dev.txt +6 -0
- parkapi_sources-0.2.0/requirements.txt +6 -0
- parkapi_sources-0.2.0/setup.cfg +4 -0
- parkapi_sources-0.2.0/src/parkapi_sources/__init__.py +6 -0
- parkapi_sources-0.2.0/src/parkapi_sources/_version.py +16 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/__init__.py +19 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/bahn_v2/__init__.py +6 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/bahn_v2/converter.py +72 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/bahn_v2/mapper.py +38 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/bahn_v2/validators.py +131 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/__init__.py +6 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/base_converter.py +26 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/pull/__init__.py +8 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/pull/pull_converter.py +20 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/pull/pull_scraper_mixin.py +74 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/pull/static_geojson_data_mixin/__init__.py +7 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/pull/static_geojson_data_mixin/mixin.py +69 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/pull/static_geojson_data_mixin/models.py +63 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/push/__init__.py +12 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/push/csv_converter.py +39 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/push/json_converter.py +19 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/push/normalized_xlsx_converter.py +105 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/push/push_converter.py +12 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/push/xlsx_converter.py +47 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/base_converter/push/xml_converter.py +21 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/bfrk_bw/__init__.py +7 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/bfrk_bw/base_converter.py +56 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/bfrk_bw/base_models.py +57 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/bfrk_bw/bike_converter.py +50 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/bfrk_bw/bike_models.py +56 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/bfrk_bw/car_converter.py +49 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/bfrk_bw/car_models.py +46 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/freiburg/__init__.py +6 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/freiburg/converter.py +65 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/freiburg/models.py +43 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/heidelberg/__init__.py +6 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/heidelberg/converter.py +74 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/heidelberg/validators.py +56 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/karlsruhe/__init__.py +6 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/karlsruhe/converter.py +89 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/karlsruhe/files/ca.crt.pem +49 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/karlsruhe/models.py +103 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/mannheim/__init__.py +6 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/mannheim/converter.py +54 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/neckarsulm/__init__.py +6 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/neckarsulm/converter.py +70 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/neckarsulm/models.py +71 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/pbw/__init__.py +6 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/pbw/converter.py +117 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/pbw/mapper.py +53 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/pbw/validation.py +279 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/pforzheim/__init__.py +6 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/pforzheim/converter.py +62 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/pforzheim/validation.py +43 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/reutlingen/__init__.py +6 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/reutlingen/converter.py +73 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/reutlingen/validation.py +53 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/stuttgart/__init__.py +6 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/stuttgart/converter.py +132 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/ulm/__init__.py +6 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/ulm/converter.py +52 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/vrs_p_r/__init__.py +6 -0
- parkapi_sources-0.2.0/src/parkapi_sources/converters/vrs_p_r/vrs_p_r.py +56 -0
- parkapi_sources-0.2.0/src/parkapi_sources/exceptions.py +47 -0
- parkapi_sources-0.2.0/src/parkapi_sources/models/__init__.py +8 -0
- parkapi_sources-0.2.0/src/parkapi_sources/models/enums.py +65 -0
- parkapi_sources-0.2.0/src/parkapi_sources/models/parking_site_inputs.py +136 -0
- parkapi_sources-0.2.0/src/parkapi_sources/models/source_info.py +23 -0
- parkapi_sources-0.2.0/src/parkapi_sources/models/xlsx_inputs.py +80 -0
- parkapi_sources-0.2.0/src/parkapi_sources/parkapi_sources.py +88 -0
- parkapi_sources-0.2.0/src/parkapi_sources/scripts/parkapi.py +210 -0
- parkapi_sources-0.2.0/src/parkapi_sources/util/__init__.py +8 -0
- parkapi_sources-0.2.0/src/parkapi_sources/util/config_helper.py +16 -0
- parkapi_sources-0.2.0/src/parkapi_sources/util/encoding.py +37 -0
- parkapi_sources-0.2.0/src/parkapi_sources/util/xml_helper.py +279 -0
- parkapi_sources-0.2.0/src/parkapi_sources/validators/__init__.py +13 -0
- parkapi_sources-0.2.0/src/parkapi_sources/validators/boolean_validators.py +24 -0
- parkapi_sources-0.2.0/src/parkapi_sources/validators/date_validator.py +26 -0
- parkapi_sources-0.2.0/src/parkapi_sources/validators/datetime_validator.py +32 -0
- parkapi_sources-0.2.0/src/parkapi_sources/validators/decimal_validators.py +18 -0
- parkapi_sources-0.2.0/src/parkapi_sources/validators/integer_validators.py +42 -0
- parkapi_sources-0.2.0/src/parkapi_sources/validators/noneable.py +23 -0
- parkapi_sources-0.2.0/src/parkapi_sources/validators/string_validators.py +32 -0
- parkapi_sources-0.2.0/src/parkapi_sources/validators/time_validators.py +17 -0
- parkapi_sources-0.2.0/src/parkapi_sources.egg-info/PKG-INFO +256 -0
- parkapi_sources-0.2.0/src/parkapi_sources.egg-info/SOURCES.txt +169 -0
- parkapi_sources-0.2.0/src/parkapi_sources.egg-info/dependency_links.txt +1 -0
- parkapi_sources-0.2.0/src/parkapi_sources.egg-info/requires.txt +13 -0
- parkapi_sources-0.2.0/src/parkapi_sources.egg-info/top_level.txt +1 -0
- parkapi_sources-0.2.0/tests/conftest.py +14 -0
- parkapi_sources-0.2.0/tests/converters/bahn_v2_test.py +48 -0
- parkapi_sources-0.2.0/tests/converters/bfrk_bw_test.py +52 -0
- parkapi_sources-0.2.0/tests/converters/conftest.py +26 -0
- parkapi_sources-0.2.0/tests/converters/data/bahn_v2.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/bfrk_bw_bike.csv +2002 -0
- parkapi_sources-0.2.0/tests/converters/data/bfrk_bw_car.csv +1556 -0
- parkapi_sources-0.2.0/tests/converters/data/freiburg.json +506 -0
- parkapi_sources-0.2.0/tests/converters/data/heidelberg.json +176 -0
- parkapi_sources-0.2.0/tests/converters/data/karlsruhe.json +1902 -0
- parkapi_sources-0.2.0/tests/converters/data/mannheim.html +744 -0
- parkapi_sources-0.2.0/tests/converters/data/neckarsulm.csv +42 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/catalog-city.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-10.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-11.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-12.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-15.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-17.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-18.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-19.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-31.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-32.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-33.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-34.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-4.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-42.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-48.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-49.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-51.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-52.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-60.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-61.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-7.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-71.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-by-city-9.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pbw/object-dynamic-all.json +1 -0
- parkapi_sources-0.2.0/tests/converters/data/pforzheim.json +422 -0
- parkapi_sources-0.2.0/tests/converters/data/reutlingen.csv +115 -0
- parkapi_sources-0.2.0/tests/converters/data/stuttgart-realtime.xml +1 -0
- parkapi_sources-0.2.0/tests/converters/data/stuttgart-static.xml +1 -0
- parkapi_sources-0.2.0/tests/converters/data/ulm.html +822 -0
- parkapi_sources-0.2.0/tests/converters/data/vrs_p_r.xlsx +0 -0
- parkapi_sources-0.2.0/tests/converters/freiburg_test.py +45 -0
- parkapi_sources-0.2.0/tests/converters/heidelberg_test.py +54 -0
- parkapi_sources-0.2.0/tests/converters/helper.py +60 -0
- parkapi_sources-0.2.0/tests/converters/karlsruhe_test.py +51 -0
- parkapi_sources-0.2.0/tests/converters/mannheim_test.py +45 -0
- parkapi_sources-0.2.0/tests/converters/neckarsulm_test.py +32 -0
- parkapi_sources-0.2.0/tests/converters/pbw_test.py +81 -0
- parkapi_sources-0.2.0/tests/converters/pforzheim_test.py +32 -0
- parkapi_sources-0.2.0/tests/converters/reutlingen_test.py +32 -0
- parkapi_sources-0.2.0/tests/converters/stuttgart_test.py +45 -0
- parkapi_sources-0.2.0/tests/converters/ulm_test.py +44 -0
- parkapi_sources-0.2.0/tests/converters/vrs_p_r_test.py +31 -0
- parkapi_sources-0.2.0/tests/models/xlsx_inputs_test.py +71 -0
- parkapi_sources-0.2.0/tests/util/data_xml_helper.py +164 -0
- parkapi_sources-0.2.0/tests/util/encoding_test.py +70 -0
- parkapi_sources-0.2.0/tests/util/xml_helper_test.py +160 -0
- parkapi_sources-0.2.0/tests/validators/boolean_validators_test.py +42 -0
- parkapi_sources-0.2.0/tests/validators/date_validators_test.py +41 -0
- parkapi_sources-0.2.0/tests/validators/datetime_validators_test.py +70 -0
- parkapi_sources-0.2.0/tests/validators/integer_validators_test.py +38 -0
- parkapi_sources-0.2.0/tests/validators/noneable_tests.py +48 -0
- parkapi_sources-0.2.0/tests/validators/string_validators_test.py +23 -0
- parkapi_sources-0.2.0/tests/validators/time_validators_test.py +22 -0
- parkapi_sources-0.2.0/tox.ini +33 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: github-actions
|
|
4
|
+
directory: '/'
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
- package-ecosystem: pip
|
|
8
|
+
directory: '/'
|
|
9
|
+
schedule:
|
|
10
|
+
interval: weekly
|
|
11
|
+
- package-ecosystem: docker
|
|
12
|
+
directory: '/'
|
|
13
|
+
schedule:
|
|
14
|
+
interval: weekly
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# GitHub Actions workflow to build, test and publish Python packages to PyPI everytime a new release is created.
|
|
2
|
+
|
|
3
|
+
name: Publish release
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
release:
|
|
7
|
+
types:
|
|
8
|
+
- published
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
name: Build package
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
# We use Python 3.10 here because it's the minimum Python version supported by this library.
|
|
19
|
+
- name: Setup Python 3.10
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: '3.10'
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: pip install --upgrade pip build
|
|
26
|
+
|
|
27
|
+
- name: Build package
|
|
28
|
+
run: python -m build
|
|
29
|
+
|
|
30
|
+
- name: Upload build artifacts
|
|
31
|
+
uses: actions/upload-artifact@v4
|
|
32
|
+
with:
|
|
33
|
+
name: dist_packages
|
|
34
|
+
path: dist/
|
|
35
|
+
|
|
36
|
+
test:
|
|
37
|
+
# This job tests the built package by installing it via pip and running unit tests (without tox).
|
|
38
|
+
name: Test package
|
|
39
|
+
needs: build
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
|
|
45
|
+
- name: Set timezone to Europe/Berlin
|
|
46
|
+
uses: szenius/set-timezone@v1.2
|
|
47
|
+
with:
|
|
48
|
+
timezoneLinux: "Europe/Berlin"
|
|
49
|
+
|
|
50
|
+
- name: Setup Python 3.10
|
|
51
|
+
uses: actions/setup-python@v4
|
|
52
|
+
with:
|
|
53
|
+
python-version: '3.10'
|
|
54
|
+
|
|
55
|
+
- name: Download build artifacts
|
|
56
|
+
uses: actions/download-artifact@v4
|
|
57
|
+
with:
|
|
58
|
+
name: dist_packages
|
|
59
|
+
path: dist/
|
|
60
|
+
|
|
61
|
+
- name: Install test dependencies
|
|
62
|
+
run: pip install -r requirements.txt -r requirements-dev.txt
|
|
63
|
+
|
|
64
|
+
- name: Install built package
|
|
65
|
+
run: pip install dist/parkapi_sources-*.whl
|
|
66
|
+
|
|
67
|
+
- name: Run unit tests
|
|
68
|
+
run: python -m pytest
|
|
69
|
+
|
|
70
|
+
publish:
|
|
71
|
+
name: Publish package
|
|
72
|
+
needs: test
|
|
73
|
+
runs-on: ubuntu-latest
|
|
74
|
+
|
|
75
|
+
steps:
|
|
76
|
+
- name: Download build artifacts
|
|
77
|
+
uses: actions/download-artifact@v4
|
|
78
|
+
with:
|
|
79
|
+
name: dist_packages
|
|
80
|
+
path: dist/
|
|
81
|
+
|
|
82
|
+
- name: Upload package to GitHub release assets
|
|
83
|
+
uses: AButler/upload-release-assets@v3.0
|
|
84
|
+
with:
|
|
85
|
+
files: dist/*
|
|
86
|
+
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
87
|
+
|
|
88
|
+
- name: Publish package to PyPI
|
|
89
|
+
uses: pypa/gh-action-pypi-publish@v1.8.14
|
|
90
|
+
with:
|
|
91
|
+
user: __token__
|
|
92
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: lint
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- '*'
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- '*'
|
|
10
|
+
# make workflow "callable" by others
|
|
11
|
+
workflow_call:
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
lint:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
matrix:
|
|
18
|
+
python-version:
|
|
19
|
+
- '3'
|
|
20
|
+
steps:
|
|
21
|
+
- name: checkout
|
|
22
|
+
uses: actions/checkout@v4
|
|
23
|
+
- name: setup Python v${{ matrix.python-version }}
|
|
24
|
+
uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: ${{ matrix.python-version }}
|
|
27
|
+
cache: 'pip'
|
|
28
|
+
|
|
29
|
+
- name: pip install
|
|
30
|
+
run: pip install -r requirements.txt -r requirements-dev.txt
|
|
31
|
+
|
|
32
|
+
- name: lint using ruff
|
|
33
|
+
# We could also use the official GitHub Actions integration.
|
|
34
|
+
# https://beta.ruff.rs/docs/usage/#github-action
|
|
35
|
+
# uses: chartboost/ruff-action@v1
|
|
36
|
+
run: ruff check --output-format github ./src ./tests
|
|
37
|
+
|
|
38
|
+
- name: format using black
|
|
39
|
+
# We could also use the official GitHub Actions integration.
|
|
40
|
+
# https://black.readthedocs.io/en/stable/integrations/github_actions.html
|
|
41
|
+
# uses: uses: psf/black@stable
|
|
42
|
+
run: |
|
|
43
|
+
black -S --check --diff ./src ./tests
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024, binary butterfly GmbH
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
.PHONY: test
|
|
3
|
+
test:
|
|
4
|
+
python -m pytest tests --cov=src --cov-report=html:reports/coverage_html/
|
|
5
|
+
|
|
6
|
+
.PHONY: open-coverage
|
|
7
|
+
open-coverage:
|
|
8
|
+
@test -f ./reports/coverage_html/index.html || make test
|
|
9
|
+
$(or $(BROWSER),firefox) ./reports/coverage_html/index.html
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
.PHONY: lint
|
|
13
|
+
lint: black ruff
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
.PHONY: black
|
|
17
|
+
black:
|
|
18
|
+
black ./src ./tests
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
.PHONY: ruff
|
|
22
|
+
ruff:
|
|
23
|
+
ruff check --fix ./src ./tests
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: parkapi_sources
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: ParkAPI Sources is a collection of converters from several different data sources to normalized ParkAPI data.
|
|
5
|
+
Author-email: "Ernesto Ruge, binary butterfly GmbH" <ernesto.ruge@binary-butterfly.de>
|
|
6
|
+
Maintainer-email: "Ernesto Ruge, binary butterfly GmbH" <ernesto.ruge@binary-butterfly.de>
|
|
7
|
+
Keywords: data,parking,converter,mobility,car,bike
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Classifier: Topic :: Utilities
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENCE.txt
|
|
22
|
+
Requires-Dist: validataclass~=0.9.0
|
|
23
|
+
Requires-Dist: pyproj~=3.6.1
|
|
24
|
+
Requires-Dist: lxml~=5.2.1
|
|
25
|
+
Requires-Dist: openpyxl~=3.1.2
|
|
26
|
+
Requires-Dist: requests~=2.31.0
|
|
27
|
+
Requires-Dist: beautifulsoup4~=4.12.3
|
|
28
|
+
Provides-Extra: testing
|
|
29
|
+
Requires-Dist: black~=24.3.0; extra == "testing"
|
|
30
|
+
Requires-Dist: ruff~=0.3.5; extra == "testing"
|
|
31
|
+
Requires-Dist: pytest~=8.1.1; extra == "testing"
|
|
32
|
+
Requires-Dist: pytest-cov~=5.0.0; extra == "testing"
|
|
33
|
+
Requires-Dist: requests-mock~=1.12.1; extra == "testing"
|
|
34
|
+
|
|
35
|
+
# ParkAPI Sources
|
|
36
|
+
|
|
37
|
+
ParkAPI Sources is a collection of converters from several different data sources to normalized ParkAPI data. ParkAPI does support parking
|
|
38
|
+
for cars, for bikes and lockers. The data model is based on the original ParkAPI project and tries to stay compatible to DATEX II Parking
|
|
39
|
+
Publication Light at any extension of the model.
|
|
40
|
+
|
|
41
|
+
We support following data sources:
|
|
42
|
+
|
|
43
|
+
| name | purpose | type | uid | realtime |
|
|
44
|
+
|-----------------------------------------------------------------------------------|---------|-------------|----------------------|----------|
|
|
45
|
+
| Deutsche Bahn | car | pull | `bahn_v2` | no |
|
|
46
|
+
| Barrierefreie Reisekette Baden-Württemberg: PKW-Parkplätze an Bahnhöfen | car | push (csv) | `bfrk_bw_oepnv_car` | no |
|
|
47
|
+
| Barrierefreie Reisekette Baden-Württemberg: PKW-Parkplätze an Bushaltestellen | car | push (csv) | `bfrk_bw_spnv_car` | no |
|
|
48
|
+
| Barrierefreie Reisekette Baden-Württemberg: Fahrrad-Parkplätze an Bahnhöfen | bike | push (csv) | `bfrk_bw_oepnv_bike` | no |
|
|
49
|
+
| Barrierefreie Reisekette Baden-Württemberg: Fahrrad-Parkplätze an Bushaltestellen | bike | push (csv) | `bfrk_bw_spnv_bike` | no |
|
|
50
|
+
| Stadt Freiburg | car | pull | `freiburg` | yes |
|
|
51
|
+
| Stadt Heidelberg | car | pull | `heidelberg` | yes |
|
|
52
|
+
| Stadt Karlsruhe | car | pull | `karlsruhe` | yes |
|
|
53
|
+
| Stadt Mannheim | car | pull | `mannheim` | yes |
|
|
54
|
+
| Stadt Karlsruhe | car | push (csv) | `neckarsulm` | no |
|
|
55
|
+
| Parkraumgesellschaft Baden-Württemberg | car | pull | `pbw` | yes |
|
|
56
|
+
| Stadt Pforzheim | car | push (csv) | `pforzheim` | no |
|
|
57
|
+
| Stadt Reutlingen | car | push (csv) | `reutlingen` | no |
|
|
58
|
+
| Stadt Stuttgart | car | push (json) | `stuttgart` | yes |
|
|
59
|
+
| Stadt Ulm | car | pull | `ulm` | yes |
|
|
60
|
+
| Verband Region Stuttgart: Park and Ride | car | pull | `vrs_p_r` | yes |
|
|
61
|
+
|
|
62
|
+
New converters for new sources are always welcome, please have a look at "Contribute" below.
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
## Install
|
|
66
|
+
|
|
67
|
+
ParkAPI Sources is a python module published at [PyPI](https://pypi.org/project/parkapi-sources/). Therefore, you can install it by
|
|
68
|
+
|
|
69
|
+
```shell
|
|
70
|
+
pip install parkapi-sources
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
If you use parkapi-sources in a project, we recommend to fix the version. As long as parkapi-sources is beta, breaking changes might be
|
|
74
|
+
introduced on minor version level (like: change from 0.1.1 to 0.2.0). As soon as 1.0 is released, we will follow
|
|
75
|
+
[Semantic Versioning](https://semver.org), which means that breaking changes will just appear on major version changes (like: change from 1.1.2 to 2.0.0).
|
|
76
|
+
You can expect a lot of changes in the minor version level, as any new converter is a new feature.
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
## Usage
|
|
80
|
+
|
|
81
|
+
Your starting point is always the `ParkAPISources` where all Sources are registered.
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from parkapi_sources import ParkAPISources
|
|
85
|
+
|
|
86
|
+
my_sources = ParkAPISources()
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`ParkAPISources` accepts following parameters:
|
|
90
|
+
|
|
91
|
+
- `config: Optional[dict] = None` is a dictionary for config values, especially secrets.
|
|
92
|
+
- `converter_uids: Optional[list[str]] = None` is used for loading just the converter uids you want to load
|
|
93
|
+
- `no_pull_converter: bool = False` is used for limiting converters to pull converters
|
|
94
|
+
- `no_push_converter: bool = False` is used for limiting converters to push converters
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
### Configuration
|
|
98
|
+
|
|
99
|
+
Config values are mostly individual for specific converters: if there are required config values, they are defined at the converter
|
|
100
|
+
definition right at the top:
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
required_config_keys = ['MY_SECRET']
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`ParkAPISources` offers a method to check if all config values are set:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from parkapi_sources import ParkAPISources
|
|
110
|
+
|
|
111
|
+
my_sources = ParkAPISources()
|
|
112
|
+
my_sources.check_credentials()
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
If not all config values are set, a `MissingConfigException` is thrown. It's recommended to run this check after initializing the module
|
|
116
|
+
to prevent exceptions during runtime.
|
|
117
|
+
|
|
118
|
+
Besides converter-individual config values, there are two global values which can be used to configure the source of GeoJSON files. Per
|
|
119
|
+
default, static GeoJSON files are fetched from this repository. This behaviour can be changed:
|
|
120
|
+
|
|
121
|
+
- `STATIC_GEOJSON_BASE_URL` defines another base URL for GeoJSON files
|
|
122
|
+
- `STATIC_GEOJSON_BASE_PATH` defines a lokal path instead, so the application will load files locally without network requests
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
### Use converters
|
|
126
|
+
|
|
127
|
+
After initializing, you will find all initialized converters at `ParkAPISources.converter_by_uid`. As the input is very different, so are
|
|
128
|
+
the methods you have to use. In general, you can differ between two major strategies:
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
### Pull converters
|
|
132
|
+
|
|
133
|
+
Pull converters are responsible for getting data from an external data source. This can be an REST endpoints as well as HTML which is
|
|
134
|
+
scraped. Pull converters always split up in static and realtime data, because at most sources, this is not the same. Each pull converter
|
|
135
|
+
has two methods:
|
|
136
|
+
|
|
137
|
+
1) `get_static_parking_sites(self) -> tuple[list[StaticParkingSiteInput], list[ImportParkingSiteException]]:`
|
|
138
|
+
2) `def get_realtime_parking_sites(self) -> tuple[list[RealtimeParkingSiteInput], list[ImportParkingSiteException]]:`
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
### Push converters
|
|
142
|
+
|
|
143
|
+
Push converters are responsible to handle data which is pushed to the service using defined endpoints. Usually, these converters are used
|
|
144
|
+
as a handler behind HTTP endpoints, but of course you can use them in other ways, too, for example command line scripts.
|
|
145
|
+
|
|
146
|
+
Push converters always handle specific formats, therefore, there are multiple types of push converters. All push converters return a
|
|
147
|
+
`tuple[list[StaticParkingSiteInput | RealtimeParkingSiteInput], list[ImportParkingSiteException]]`, therefore they decided based on the
|
|
148
|
+
given data if it's static or realtime data they got - or even both, then each dataset ends up in two entries in the first list.
|
|
149
|
+
|
|
150
|
+
1) A `CsvConverter` handles CSV files: `handle_csv_string(self, data: StringIO)`
|
|
151
|
+
2) A `JsonConverter` handles JSON based data: `handle_json(self, data: dict | list)`
|
|
152
|
+
3) A `XlsxConverter` handles XMLX data: `def handle_xlsx(self, workbook: Workbook)` parsed by `openpyxl`
|
|
153
|
+
4) A `XmlConverter` handles XML data: `def handle_xml(self, root: Element)` parsed by `lxml`
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
### Results
|
|
157
|
+
|
|
158
|
+
At `webapp/models/parking_site_inputs.py`, you can find the definition of `StaticParkingSiteInput` and `RealtimeParkingSiteInput`. These
|
|
159
|
+
`dataclasses` are also [`validataclasses`](https://pypi.org/project/validataclass/), so you can be sure that the data you get is validated.
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
## Contribute
|
|
163
|
+
|
|
164
|
+
We are happy about any contributions. We do not expect that yoy can develop Python, but of course things might speed up if
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
### Report bugs
|
|
168
|
+
|
|
169
|
+
As ParkAPI-Sources integrates a lot of external data sources, sometimes without a proper definition, converters might run into issues
|
|
170
|
+
because of changes on the data source side. If you see that happening, please add a bug report at the
|
|
171
|
+
[issues](https://github.com/ParkenDD/parkapi-sources-v3/issues). If possible, please add the data which fails.
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
### Contribute new source data
|
|
175
|
+
|
|
176
|
+
If you see a nice data source which is not covered by ParkAPI-sources, you can always create a feature request at our
|
|
177
|
+
[issues](https://github.com/ParkenDD/parkapi-sources-v3/issues). If you do so, please add the data you found, so we can actually build
|
|
178
|
+
the converter. If possible, please try to find out a licence, too.
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
### Write a new Converters
|
|
182
|
+
|
|
183
|
+
We always welcome merge requests with new converters. A merge request should contain the following:
|
|
184
|
+
|
|
185
|
+
* MIT licenced code
|
|
186
|
+
* A converter which validates the input in a way that the output follows the data model
|
|
187
|
+
* A test with example data to ensure that the converter works with current data
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
## Write a new converter
|
|
191
|
+
|
|
192
|
+
First you have to determine which type of converter you need. If you get the data from an endpoint, you will need a `PushConverter`, if
|
|
193
|
+
you have a file you want to push via HTTP or CLI, you need a `PullConverter`.
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
### Write the converter
|
|
197
|
+
|
|
198
|
+
In order to write a converter, you need a directory at `converters`. Please name your directory in a way that it points to the actual
|
|
199
|
+
converter you will write. If it's just one converter, the `uid` is usually the best approach.
|
|
200
|
+
|
|
201
|
+
At `converters/your-converter`, you will at least need a `converter.py` and an `__init__.py`. In most cases, you will also need some
|
|
202
|
+
`validataclasses` you can put in `models.py`. Validation is crucial in this library, because the users of this library should not think
|
|
203
|
+
invalid data. Additionally, if you have very specific new data types, you can write new `validataclass` validators you can usually put in
|
|
204
|
+
`validators.py`.
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
### Testing the converter
|
|
208
|
+
|
|
209
|
+
In order to proof that the validator works, we need to test the basic functionality. In order to do this, we need a snapshot of the data
|
|
210
|
+
which should be integrated. Common place for this data is `tests/converters/data/filename-starting-with-uid.ending`. This data should be
|
|
211
|
+
used in one or multiple tests (in several cases two tests, one for static, one for realtime data) stored at `tests/converters/uid_test.py`.
|
|
212
|
+
|
|
213
|
+
If you test a `PullConverter`, you will need no mock requests. This can be done using the fantastic
|
|
214
|
+
[`requests_mock`](https://pypi.org/project/requests-mock/) library.
|
|
215
|
+
|
|
216
|
+
If you created new validators, these should be tested with different inputs. Usually, `pytest.parametrize` is a nice approach to do this.
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
### Linting
|
|
220
|
+
|
|
221
|
+
As we try to keep a consistent code style, please lint your code before creating the merge request. We use `black` and `ruff` for linting.
|
|
222
|
+
There is Makefile target to do both: `make lint`. It runs the following commands:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
black ./src ./tests
|
|
226
|
+
ruff check --fix ./src ./tests
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
If you don't have `black` and `ruff` installed globally, you can create a virtual environment for these tools:
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
virtualenv venv
|
|
233
|
+
source venv/bin/activate
|
|
234
|
+
pip install -r requirements.txt -r requirements-dev.txt
|
|
235
|
+
|
|
236
|
+
black ./src ./tests
|
|
237
|
+
ruff check --fix ./src ./tests
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
### Make your new converter available
|
|
242
|
+
|
|
243
|
+
All available converters should be registered at the `ParkAPISources` class in order to make them accessible for users of this library, so
|
|
244
|
+
please register your converter there. The new converter should also be added to the table in this README.md file.
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
### Release process
|
|
248
|
+
|
|
249
|
+
If you created a merge request, the maintainers will review your code. If everything is fine, it will be merged to `main`, and a new
|
|
250
|
+
release will be created soon. As written above, we follow SemVer, so any new converter will add plus one to the minor version. In order to
|
|
251
|
+
use this new release, please keep in mind to update your `requirements.txt` / update the dependency manager you use.
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
## Licence
|
|
255
|
+
|
|
256
|
+
This library is under MIT licence. Please look at `LICENCE.txt` for details.
|