From efa81d40d2015e7bdae11f66324fb1fe81ead39f Mon Sep 17 00:00:00 2001 From: Samuel Scully Date: Sat, 2 May 2026 19:58:40 +0100 Subject: [PATCH] Extract CLI to separate opencage-cli package Remove command_line.py, batch.py, their tests/fixtures, and the example batch.py + addresses.csv. The CLI now lives in its own repository and PyPI package (opencage-cli). Drop tqdm and certifi (only used by the batch CLI) and the [project.scripts] entry point. Bump to 3.4.0. --- Changes.txt | 3 + README.md | 35 +- batch-progress.gif | Bin 164483 -> 0 bytes examples/addresses.csv | 595 --------------------- examples/batch.py | 139 ----- opencage/batch.py | 376 ------------- opencage/command_line.py | 234 -------- opencage/version.py | 2 +- pyproject.toml | 5 - test/cli/test_cli_args.py | 200 ------- test/cli/test_cli_run.py | 193 ------- test/fixtures/cli/forward.csv | 3 - test/fixtures/cli/forward_noresult.csv | 2 - test/fixtures/cli/forward_with_headers.csv | 4 - test/fixtures/cli/output.csv2 | 2 - test/fixtures/cli/reverse.csv | 1 - test/fixtures/cli/reverse_with_errors.csv | 4 - test/fixtures/input.txt | 0 test/test_batch.py | 25 - 19 files changed, 5 insertions(+), 1818 deletions(-) delete mode 100644 batch-progress.gif delete mode 100644 examples/addresses.csv delete mode 100755 examples/batch.py delete mode 100644 opencage/batch.py delete mode 100644 opencage/command_line.py delete mode 100644 test/cli/test_cli_args.py delete mode 100644 test/cli/test_cli_run.py delete mode 100644 test/fixtures/cli/forward.csv delete mode 100644 test/fixtures/cli/forward_noresult.csv delete mode 100644 test/fixtures/cli/forward_with_headers.csv delete mode 100644 test/fixtures/cli/output.csv2 delete mode 100644 test/fixtures/cli/reverse.csv delete mode 100644 test/fixtures/cli/reverse_with_errors.csv delete mode 100644 test/fixtures/input.txt delete mode 100644 test/test_batch.py diff --git a/Changes.txt b/Changes.txt index 4f81137..6debe66 100644 --- a/Changes.txt +++ b/Changes.txt @@ -1,3 +1,6 @@ +v3.4.0 Sat May 2 2026 + CLI tool extracted to separate `opencage-cli` package and repository (https://github.com/OpenCageData/opencage-cli) + v3.3.1 Sun Mar 29 2026 Validate the host domain parameter. Should be opencagedata.com subdomain or localhost Set explicit timeout for HTTP requests diff --git a/README.md b/README.md index 3d79629..e502a11 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,6 @@ You can find a [comprehensive tutorial for using this module on the OpenCage sit There are two brief video tutorials on YouTube, one [covering forward geocoding](https://www.youtube.com/watch?v=9bXu8-LPr5c), one [covering reverse geocoding](https://www.youtube.com/watch?v=u-kkE4yA-z0). -The module installs an `opencage` CLI tool for geocoding files. Check `opencage --help` or the [CLI tutorial](https://opencagedata.com/tutorials/geocode-commandline). - ## Working with AI / Agent Skill There is an [Agent Skill for working with the OpenCage Geocoding API](https://github.com/OpenCageData/opencage-skills/) which includes a reference file for developing in Python using this module. @@ -100,9 +98,6 @@ async with OpenCageGeocode(key) as geocoder: results = await geocoder.geocode_async(address) ``` -For a more complete example and links to futher tutorials on asyncronous IO see -`batch.py` in the `examples` directory. - ### Non-SSL API use If you have trouble accesing the OpenCage API with https, e.g. issues with OpenSSL @@ -125,35 +120,7 @@ If anything goes wrong, then an exception will be raised: ## Command-line batch geocoding -Use `opencage forward` or `opencage reverse` - -``` -opencage forward --help - -options: - -h, --help show this help message and exit - --api-key API_KEY Your OpenCage API key - --input FILENAME Input file name - --output FILENAME Output file name - --headers If the first row should be treated as a header row - --input-columns Comma-separated list of integers (default '1') - --add-columns Comma-separated list of output columns (default 'lat,lng,_type,_category,country_code,country,state,county,_normalized_city,postcode,road,house_number,confidence,formatted,json,status') - --workers Number of parallel geocoding requests (default 1) - --timeout Timeout in seconds (default 10) - --retries Number of retries (default 5) - --api-domain API domain (default api.opencagedata.com) - --optional-api-params - Extra parameters for each request (e.g. language=fr,no_dedupe=1) - --unordered Allow the output lines to be in different order (can be faster) - --limit Stop after this number of lines in the input - --dry-run Read the input file but no geocoding - --no-progress Display no progress bar - --quiet No progress bar and no messages - --overwrite Delete the output file first if it exists - --verbose Display debug information for each request -``` - - +The `opencage` CLI now lives in its own package. See [opencage-cli](https://github.com/OpenCageData/opencage-cli) — install with `pip install opencage-cli`. ## Copyright & License diff --git a/batch-progress.gif b/batch-progress.gif deleted file mode 100644 index 030c24c0946612396d5655ab2a15f8c482052567..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 164483 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
RdT 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 XQRp9QvkSD&ejj-zc>o_dV?OyG6;(mN diff --git a/examples/addresses.csv b/examples/addresses.csv deleted file mode 100644 index 619b94d..0000000 --- a/examples/addresses.csv +++ /dev/null @@ -1,595 +0,0 @@ -id, address -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" -1, "Via Allende 8, Cascina, Toscana, Italia" -2, "Via Coppi, 17, Formigine, Emilia-Romagna, Italia" -3, "Via Dei Salici 20, Gallarate, Lombardia, Italia" -4, "Via Vittorio Veneto N7, San Giuliano Terme, Toscana, Italia" -5, "Via Tiro A Segno 8, Gallarate, Lombardia, Italia" -6, "Urne Di Sopra 3, Bagnolo Mella, Lombardia, Italia" -7, "Via San Francesco D'assisi 84, Nichelino, Piemonte, Italia" -8, "Via Corletto, 10/A, Formigine, Emilia-Romagna, Italia" -9, "Via Beppe Fenoglio 17, Canale D'alba, Piemonte, Italia" -10, "Via 2 Giugno 19, Ponsacco, Toscana, Italia" -11, "Via Per Sassuolo, 74, Formigine, Emilia-Romagna, Italia" diff --git a/examples/batch.py b/examples/batch.py deleted file mode 100755 index 71502e0..0000000 --- a/examples/batch.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python3 - -# Example script we used between 2021 and 2023. It's now being replaced by -# the much more powerful CLI tool (see README.md file). -# -# Git version history will show how we kept adding features. Below is a -# version with less features, on purpose, for better readability. -# -# Background tutorial on async programming with Python -# https://realpython.com/async-io-python/ -# -# Requires Python 3.7 or newer. Tested with 3.8 and 3.9. -# -# Installation: -# pip3 install opencage -# - -import sys -import csv -import asyncio -from opencage.geocoder import OpenCageGeocode - -API_KEY = '' -INFILE = 'file_to_geocode.csv' -OUTFILE = 'file_geocoded.csv' -MAX_ITEMS = 100 # Set to 0 for unlimited -NUM_WORKERS = 3 # For 10 requests per second try 2-5 - -csv_writer = csv.writer(open(OUTFILE, 'w', encoding='utf8', newline='')) - -async def write_one_geocoding_result(geocoding_result, address, address_id): - if geocoding_result is not None: - geocoding_result = geocoding_result[0] - row = [ - address_id, - geocoding_result['geometry']['lat'], - geocoding_result['geometry']['lng'], - # Any of these components might be empty : - geocoding_result['components'].get('country', ''), - geocoding_result['components'].get('county', ''), - geocoding_result['components'].get('city', ''), - geocoding_result['components'].get('postcode', ''), - geocoding_result['components'].get('road', ''), - geocoding_result['components'].get('house_number', ''), - geocoding_result['confidence'], - geocoding_result['formatted'] - ] - - else: - row = [ - address_id, - 0, # not to be confused with https://en.wikipedia.org/wiki/Null_Island - 0, - '', - '', - '', - '', - '', - '', - -1, # confidence values are 1-10 (lowest to highest), use -1 for unknown - '' - ] - sys.stderr.write(f"not found, writing empty result: ${address}\n") - csv_writer.writerow(row) - - -async def geocode_one_address(address, address_id): - async with OpenCageGeocode(API_KEY) as geocoder: - geocoding_result = await geocoder.geocode_async(address) - try: - await write_one_geocoding_result(geocoding_result, address, address_id) - except Exception as e: - sys.stderr.write(e) - - - -async def run_worker(worker_name, queue): - sys.stderr.write(f"Worker ${worker_name} starts...\n") - while True: - work_item = await queue.get() - address_id = work_item['id'] - address = work_item['address'] - await geocode_one_address(address, address_id) - queue.task_done() - - - - -async def main(): - assert sys.version_info >= (3, 7), "Script requires Python 3.7+." - - ## 1. Read CSV into a Queue - ## Each work_item is an address and id. The id will be part of the output, - ## easy to add more settings. Named 'work_item' to avoid the words - ## 'address' or 'task' which are used elsewhere - ## - ## https://docs.python.org/3/library/asyncio-queue.html - ## - queue = asyncio.Queue(maxsize=MAX_ITEMS) - - csv_reader = csv.reader(open(INFILE, 'r', encoding='utf8')) - - for row in csv_reader: - work_item = {'id': row[0], 'address': row[1]} - await queue.put(work_item) - if queue.full(): - break - - sys.stderr.write(f"${queue.qsize()} work_items in queue\n") - - - ## 2. Create tasks workers. That is coroutines, each taks take work_items - ## from the queue until it's empty. Tasks run in parallel - ## - ## https://docs.python.org/3/library/asyncio-task.html#creating-tasks - ## https://docs.python.org/3/library/asyncio-task.html#coroutine - ## - sys.stderr.write(f"Creating ${NUM_WORKERS} task workers...\n") - tasks = [] - for i in range(NUM_WORKERS): - task = asyncio.create_task(run_worker(f'worker {i}', queue)) - tasks.append(task) - - - ## 3. Now workers do the geocoding - ## - sys.stderr.write("Now waiting for workers to finish processing queue...\n") - await queue.join() - - - ## 4. Cleanup - ## - for task in tasks: - task.cancel() - - sys.stderr.write("All done.\n") - - -asyncio.run(main()) diff --git a/opencage/batch.py b/opencage/batch.py deleted file mode 100644 index 9385065..0000000 --- a/opencage/batch.py +++ /dev/null @@ -1,376 +0,0 @@ -import sys -import ssl -import asyncio -import traceback -import threading -import random -import json - -from contextlib import suppress -from urllib.parse import urlencode -from tqdm import tqdm -import certifi -import backoff -from opencage.geocoder import ( - OpenCageGeocode, - OpenCageGeocodeError, - _query_for_reverse_geocoding, - floatify_latlng -) - - -class OpenCageBatchGeocoder(): - """Batch geocoder that processes CSV files using the OpenCage API. - - Reads rows from a CSV input, geocodes each address using async workers, - and writes results to a CSV output. - - Args: - options: Parsed command-line options from argparse. - """ - - def __init__(self, options): - self.options = options - self.sslcontext = ssl.create_default_context(cafile=certifi.where()) - self.user_agent_comment = 'OpenCage CLI' - self.write_counter = 1 - - def __call__(self, *args, **kwargs): - """Run the batch geocoder synchronously via asyncio.run.""" - asyncio.run(self.geocode(*args, **kwargs)) - - async def geocode(self, csv_input, csv_output): - """Process a CSV input, geocode each row, and write results. - - Args: - csv_input: CSV reader for input rows. - csv_output: CSV writer for output rows. - """ - if not self.options.dry_run: - test = await self.test_request() - if test['error']: - self.log(test['error']) - return - if test['free'] is True and self.options.workers > 1: - sys.stderr.write("Free trial account detected. Resetting number of workers to 1.\n") - self.options.workers = 1 - - if self.options.headers: - header_columns = next(csv_input, None) - if header_columns is None: - return - - queue = asyncio.Queue(maxsize=self.options.limit) - - read_warnings = await self.read_input(csv_input, queue) - - if self.options.dry_run: - if not read_warnings: - print('All good.') - return - - if self.options.headers: - csv_output.writerow(header_columns + self.options.add_columns) - - progress_bar = not (self.options.no_progress or self.options.quiet) and \ - tqdm(total=queue.qsize(), position=0, desc="Addresses geocoded", dynamic_ncols=True) - - tasks = [] - for _ in range(self.options.workers): - task = asyncio.create_task(self.worker(csv_output, queue, progress_bar)) - tasks.append(task) - - # This starts the workers and waits until all are finished - await queue.join() - - # All tasks done - for task in tasks: - task.cancel() - - if progress_bar: - progress_bar.close() - - async def test_request(self): - """Send a test geocoding request to verify the API key. - - Returns: - Dict with 'error' (None or exception) and 'free' (bool indicating - whether a free trial account is being used). - """ - try: - async with OpenCageGeocode( - self.options.api_key, - domain=self.options.api_domain, - sslcontext=self.sslcontext, - user_agent_comment=self.user_agent_comment - ) as geocoder: - result = await geocoder.geocode_async('Kendall Sq, Cambridge, MA', raw_response=True) - - free = False - with suppress(KeyError): - free = result['rate']['limit'] == 2500 - - return {'error': None, 'free': free} - except Exception as exc: - return {'error': exc} - - async def read_input(self, csv_input, queue): - """Read all rows from CSV input and add them to the work queue. - - Args: - csv_input: CSV reader for input rows. - queue: Async queue to populate with parsed input items. - - Returns: - True if any warnings were encountered while reading, False otherwise. - """ - any_warnings = False - for index, row in enumerate(csv_input): - line_number = index + 1 - - if len(row) == 0: - self.log(f"Line {line_number} - Empty line") - any_warnings = True - row = [''] - - item = await self.read_one_line(row, line_number) - if item['warnings'] is True: - any_warnings = True - await queue.put(item) - - if queue.full(): - break - - return any_warnings - - async def read_one_line(self, row, row_id): - """Parse a single CSV row into a work item for geocoding. - - Args: - row: List of column values from the CSV reader. - row_id: 1-based line number of the row in the input. - - Returns: - Dict with keys 'row_id', 'address', 'original_columns', - and 'warnings'. - """ - warnings = False - - if self.options.input_columns: - input_columns = self.options.input_columns - elif self.options.command == 'reverse': - input_columns = [1, 2] - else: - input_columns = None - - if input_columns: - address = [] - try: - for column in input_columns: - # input_columns option uses 1-based indexing - address.append(row[column - 1]) - except IndexError: - self.log(f"Line {row_id} - Missing input column {column} in {row}") - warnings = True - else: - address = row - - if self.options.command == 'reverse': - - if len(address) != 2: - self.log( - f"Line {row_id} - Expected two comma-separated values for reverse geocoding, got {address}") - else: - # _query_for_reverse_geocoding attempts to convert into numbers. We rather have it fail - # now than during the actual geocoding - try: - _query_for_reverse_geocoding(address[0], address[1]) - except BaseException: - self.log( - f"Line {row_id} - Does not look like latitude and longitude: '{address[0]}' and '{address[1]}'") - warnings = True - address = [] - - return {'row_id': row_id, 'address': ','.join(address), 'original_columns': row, 'warnings': warnings} - - async def worker(self, csv_output, queue, progress): - """Consume items from the queue and geocode each one. - - Args: - csv_output: CSV writer for output rows. - queue: Async queue of work items to process. - progress: tqdm progress bar, or False if disabled. - """ - while True: - item = await queue.get() - - try: - await self.geocode_one_address(csv_output, item['row_id'], item['address'], item['original_columns']) - - if progress: - progress.update(1) - except Exception as exc: - traceback.print_exception(exc, file=sys.stderr) - finally: - queue.task_done() - - async def geocode_one_address(self, csv_output, row_id, address, original_columns): - """Geocode a single address and write the result to the output. - - Args: - csv_output: CSV writer for output rows. - row_id: 1-based line number of the row in the input. - address: Address string (or lat,lng for reverse geocoding). - original_columns: Original CSV row columns to preserve in output. - """ - def on_backoff(details): - if not self.options.quiet: - sys.stderr.write("Backing off {wait:0.1f} seconds afters {tries} tries " - "calling function {target} with args {args} and kwargs " - "{kwargs}\n".format(**details)) - - @backoff.on_exception(backoff.expo, - asyncio.TimeoutError, - max_time=self.options.timeout, - max_tries=self.options.retries, - on_backoff=on_backoff) - async def _geocode_one_address(): - async with OpenCageGeocode( - self.options.api_key, - domain=self.options.api_domain, - sslcontext=self.sslcontext, - user_agent_comment=self.user_agent_comment - ) as geocoder: - geocoding_results = None - response = None - params = {'no_annotations': 1, 'raw_response': True, **self.options.optional_api_params} - - try: - if self.options.command == 'reverse': - if ',' in address: - lon, lat = address.split(',') - response = await geocoder.reverse_geocode_async(lon, lat, **params) - geocoding_results = floatify_latlng(response['results']) - else: - response = await geocoder.geocode_async(address, **params) - geocoding_results = floatify_latlng(response['results']) - except OpenCageGeocodeError as exc: - self.log(str(exc)) - except Exception as exc: - traceback.print_exception(exc, file=sys.stderr) - - try: - if geocoding_results is not None and len(geocoding_results): - geocoding_result = geocoding_results[0] - else: - geocoding_result = None - - if self.options.verbose: - self.log({ - 'row_id': row_id, - 'thread_id': threading.get_native_id(), - 'request': geocoder.url + '?' + urlencode(geocoder._parse_request(address, params)), - 'response': response - }) - - await self.write_one_geocoding_result( - csv_output, - row_id, - geocoding_result, - response, - original_columns - ) - except Exception as exc: - traceback.print_exception(exc, file=sys.stderr) - - await _geocode_one_address() - - async def write_one_geocoding_result( - self, - csv_output, - row_id, - geocoding_result, - raw_response, - original_columns): - """Write a single geocoding result row to the CSV output. - - Appends the requested output columns to the original CSV columns. - Rows are written in order unless the --unordered option is set. - - Args: - csv_output: CSV writer for output rows. - row_id: 1-based line number of the row in the input. - geocoding_result: First result dict from the API, or None. - raw_response: Full API response dict. - original_columns: Original CSV row columns to preserve in output. - """ - row = original_columns - - for column in self.options.add_columns: - if column == 'status': - row.append(self.deep_get_result_value(raw_response, ['status', 'message'])) - elif geocoding_result is None: - row.append('') - elif column in geocoding_result: - row.append(self.deep_get_result_value(geocoding_result, [column], '')) - elif column in geocoding_result['components']: - row.append(self.deep_get_result_value(geocoding_result, ['components', column], '')) - elif column in geocoding_result['geometry']: - row.append(self.deep_get_result_value(geocoding_result, ['geometry', column], '')) - elif column == 'FIPS': - row.append( - self.deep_get_result_value( - geocoding_result, [ - 'annotations', 'FIPS', 'county'], '')) - elif column == 'json': - row.append(json.dumps(geocoding_result, separators=(',', ':'))) # Compact JSON - else: - row.append('') - - # Enforce that row are written ordered. That means we might wait for other threads - # to finish a task and make the overall process slower. Alternative would be to - # use a second queue, or keep some results in memory. - if not self.options.unordered: - while row_id > self.write_counter: - if self.options.verbose: - self.log(f"Want to write row {row_id}, but write_counter is at {self.write_counter}") - await asyncio.sleep(random.uniform(0.01, 0.1)) - - if self.options.verbose: - self.log(f"Writing row {row_id}") - csv_output.writerow(row) - self.write_counter = self.write_counter + 1 - - def log(self, message): - """Write a message to stderr unless quiet mode is enabled. - - Args: - message: Message string to display. - """ - if not self.options.quiet: - sys.stderr.write(f"{message}\n") - - def deep_get_result_value(self, data, keys, default=None): - """Retrieve a nested value from a dict using a list of keys. - - Args: - data: Dict to traverse. - keys: List of keys to follow in sequence. - default: Value to return if any key is missing. - - Returns: - The nested value, or default if the path doesn't exist. - - Example: - >>> data = {'status': {'code': 200, 'message': 'OK'}} - >>> self.deep_get_result_value(data, ['status', 'message']) - 'OK' - >>> self.deep_get_result_value(data, ['missing', 'key'], '') - '' - """ - for key in keys: - if isinstance(data, dict): - data = data.get(key, default) - else: - return default - return data diff --git a/opencage/command_line.py b/opencage/command_line.py deleted file mode 100644 index 3ffee99..0000000 --- a/opencage/command_line.py +++ /dev/null @@ -1,234 +0,0 @@ -import argparse -import sys -import io -from pathlib import Path -import re -import csv - -from opencage.batch import OpenCageBatchGeocoder -from opencage.version import __version__ - - -def main(args=sys.argv[1:]): - """Entry point for the OpenCage CLI. - - Args: - args: Command-line arguments (defaults to sys.argv[1:]). - """ - options = parse_args(args) - - geocoder = OpenCageBatchGeocoder(options) - - with options.input as input_filename: - with (io.StringIO() if options.dry_run else open(options.output, 'x', encoding='utf-8')) as output_io: - reader = csv.reader(input_filename, strict=True, skipinitialspace=True) - writer = csv.writer(output_io) - - geocoder(csv_input=reader, csv_output=writer) - - -def parse_args(args): - """Parse and validate command-line arguments. - - Args: - args: List of command-line argument strings. - - Returns: - Parsed argparse.Namespace with all options set. - """ - if len(args) == 0: - print("To display help use 'opencage -h', 'opencage forward -h' or 'opencage reverse -h'", file=sys.stderr) - sys.exit(1) - - parser = argparse.ArgumentParser(description=f'OpenCage CLI {__version__}') - parser.add_argument('--version', action='version', version=f'%(prog)s {__version__}') - - subparsers = parser.add_subparsers(dest='command') - subparsers.required = True - - subparser_forward = subparsers.add_parser( - 'forward', help="Forward geocode a file (input is address, add coordinates)") - subparser_reverse = subparsers.add_parser( - 'reverse', help="Reverse geocode a file (input is coordinates, add full address)") - - for subparser in [subparser_forward, subparser_reverse]: - subparser.add_argument("--api-key", required=True, type=api_key_type, help="Your OpenCage API key") - subparser.add_argument( - "--input", - required=True, - type=argparse.FileType( - 'r', - encoding='utf-8'), - help="Input file name", - metavar='FILENAME') - subparser.add_argument( - "--output", - required=True, - type=str, - help="Output file name", - metavar='FILENAME') - - add_optional_arguments(subparser) - - options = parser.parse_args(args) - - if Path(options.output).exists() and not options.dry_run: - if options.overwrite: - Path(options.output).unlink() - else: - print( - f"Error: The output file '{options.output}' already exists. You can add --overwrite to your command.", - file=sys.stderr) - sys.exit(1) - - if 0 in options.input_columns: - print("Error: A column 0 in --input-columns does not exist. The lowest possible number is 1.", file=sys.stderr) - sys.exit(1) - - return options - - -def add_optional_arguments(parser): - """Add optional arguments shared by forward and reverse subcommands. - - Args: - parser: argparse subparser to add arguments to. - - Returns: - The parser with arguments added. - """ - parser.add_argument( - "--headers", - action="store_true", - help="If the first row should be treated as a header row") - default_input_cols = '1,2' if re.match(r'.*reverse', parser.prog) else '1' - parser.add_argument( - "--input-columns", - type=comma_separated_type(int), - default=default_input_cols, - help=f"Comma-separated list of integers (default '{default_input_cols}')", - metavar='') - default_add_cols = ( - 'lat,lng,_type,_category,country_code,country,state,county,_normalized_city,' - 'postcode,road,house_number,confidence,formatted' - ) - parser.add_argument( - "--add-columns", - type=comma_separated_type(str), - default=default_add_cols, - help=f"Comma-separated list of output columns (default '{default_add_cols}')", - metavar='') - parser.add_argument("--workers", type=ranged_type(int, 1, 20), default=1, - help="Number of parallel geocoding requests (default 1)", metavar='') - parser.add_argument("--timeout", type=ranged_type(int, 1, 60), default=10, - help="Timeout in seconds (default 10)", metavar='') - parser.add_argument("--retries", type=ranged_type(int, 1, 60), default=10, - help="Number of retries (default 5)", metavar='') - parser.add_argument("--api-domain", type=str, default="api.opencagedata.com", - help="API domain (default api.opencagedata.com)", metavar='') - parser.add_argument("--optional-api-params", type=comma_separated_dict_type, default="", - help="Extra parameters for each request (e.g. language=fr,no_dedupe=1)", metavar='') - parser.add_argument( - "--limit", - type=int, - default=0, - help="Stop after this number of lines in the input", - metavar='') - parser.add_argument( - "--unordered", - action="store_true", - help="Allow the output lines to be in different order (can be faster)") - parser.add_argument("--dry-run", action="store_true", help="Read the input file but no geocoding") - parser.add_argument("--no-progress", action="store_true", help="Display no progress bar") - parser.add_argument("--quiet", action="store_true", help="No progress bar and no messages") - parser.add_argument("--overwrite", action="store_true", help="Delete the output file first if it exists") - parser.add_argument("--verbose", action="store_true", help="Display debug information for each request") - - return parser - - -def api_key_type(apikey): - """Validate an OpenCage API key format. - - Expects a 32-character lowercase hex string, optionally prefixed - with ``oc_gc_`` (e.g. ``oc_gc_1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d`` - or ``1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d``). - - Args: - apikey: API key string to validate. - - Returns: - The validated API key string. - - Raises: - argparse.ArgumentTypeError: If the key doesn't match the expected format. - """ - pattern = re.compile(r"^(oc_gc_)?[0-9a-f]{32}$") - - if not pattern.match(apikey): - raise argparse.ArgumentTypeError("invalid API key") - - return apikey - - -def ranged_type(value_type, min_value, max_value): - """Create an argparse type function that enforces a value range. - - Args: - value_type: Type to convert the argument to (e.g. int, float). - min_value: Minimum allowed value (inclusive). - max_value: Maximum allowed value (inclusive). - - Returns: - A type-checking function suitable for argparse's type parameter. - """ - def range_checker(arg: str): - try: - f = value_type(arg) - except ValueError as exc: - raise argparse.ArgumentTypeError(f'must be a valid {value_type}') from exc - if f < min_value or f > max_value: - raise argparse.ArgumentTypeError(f'must be within [{min_value}, {max_value}]') - return f - - # Return function handle to checking function - return range_checker - - -def comma_separated_type(value_type): - """Create an argparse type function that parses comma-separated values. - - Args: - value_type: Type to convert each element to (e.g. int, str). - - Returns: - A type-checking function suitable for argparse's type parameter. - """ - def comma_separated(arg: str): - if not arg: - return [] - - return [value_type(x) for x in arg.split(',')] - - return comma_separated - - -def comma_separated_dict_type(arg): - """Parse a comma-separated list of key=value pairs into a dict. - - Args: - arg: String like "key1=val1,key2=val2". - - Returns: - Dict of parsed key-value pairs, or empty dict if arg is empty. - - Raises: - argparse.ArgumentTypeError: If the string is not valid key=value format. - """ - if not arg: - return {} - - try: - return dict([x.split('=') for x in arg.split(',')]) - except ValueError as exc: - raise argparse.ArgumentTypeError("must be a valid comma separated list of key=value pairs") from exc diff --git a/opencage/version.py b/opencage/version.py index 310a75d..f631007 100644 --- a/opencage/version.py +++ b/opencage/version.py @@ -1 +1 @@ -__version__ = '3.3.1' +__version__ = '3.4.0' diff --git a/pyproject.toml b/pyproject.toml index b182c35..46fdcfd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,8 +29,6 @@ classifiers = [ dependencies = [ "Requests>=2.31.0", "backoff>=2.2.1", - "tqdm>=4.66.4", - "certifi>=2024.07.04", "aiohttp>=3.10.5", ] @@ -43,9 +41,6 @@ dev = [ "pytest-cov>=4.1.0", ] -[project.scripts] -opencage = "opencage.command_line:main" - [project.urls] Repository = "https://github.com/OpenCageData/python-opencage-geocoder" Download = "https://github.com/OpenCageData/python-opencage-geocoder" diff --git a/test/cli/test_cli_args.py b/test/cli/test_cli_args.py deleted file mode 100644 index 43011f4..0000000 --- a/test/cli/test_cli_args.py +++ /dev/null @@ -1,200 +0,0 @@ -import pathlib -import pytest -from opencage.version import __version__ - -from opencage.command_line import parse_args - - -@pytest.fixture(autouse=True) -def around(): - yield - try: - pathlib.Path("test/fixtures/output.csv").unlink() - except FileNotFoundError: - pass - - -def assert_parse_args_error(args, message, capfd): - with pytest.raises(SystemExit): - parse_args(args) - - _, err = capfd.readouterr() - assert message in err - - -def test_required_arguments(capfd): - assert_parse_args_error( - [], - 'To display help use', - capfd - ) - - -def test_invalid_command(capfd): - assert_parse_args_error( - [ - "singasong" - ], - 'argument command: invalid choice', - capfd - ) - - -def test_version_number(capfd): - with pytest.raises(SystemExit): - parse_args(['--version']) - out, _ = capfd.readouterr() - - assert __version__ in out - - -def test_invalid_api_key(capfd): - assert_parse_args_error( - [ - "forward", - "--api-key", "invalid", - "--input", "test/fixtures/input.txt", - "--output", "test/fixtures/output.csv" - ], - 'invalid API key', - capfd - ) - - -def test_existing_output_file(capfd): - assert_parse_args_error( - [ - "forward", - "--api-key", "oc_gc_12345678901234567890123456789012", - "--input", "test/fixtures/input.txt", - "--output", "test/fixtures/input.txt" - ], - 'already exists', - capfd - ) - - -def test_argument_range(capfd): - assert_parse_args_error( - [ - "forward", - "--api-key", "oc_gc_12345678901234567890123456789012", - "--input", "test/fixtures/input.txt", - "--output", "test/fixtures/output.csv", - "--workers", "200" - ], - 'must be within [1, 20]', - capfd - ) - - -def test_zero_based_list(capfd): - assert_parse_args_error( - [ - "forward", - "--api-key", "oc_gc_12345678901234567890123456789012", - "--input", "test/fixtures/input.txt", - "--output", "test/fixtures/output.csv", - "--input-columns", "0,1,2" - ], - 'The lowest possible number is 1', - capfd - ) - - -def test_full_argument_list(): - args = parse_args([ - "reverse", - "--api-key", "oc_gc_12345678901234567890123456789012", - "--input", "test/fixtures/input.txt", - "--output", "test/fixtures/output.csv", - "--headers", - "--input-columns", "1,2", - "--add-columns", "city,postcode", - "--limit", "4", - "--workers", "3", - "--timeout", "2", - "--retries", "1", - "--dry-run", - "--unordered", - "--api-domain", "bulk.opencagedata.com", - "--optional-api-params", "extra=1", - "--no-progress", - "--quiet" - ]) - - assert args.command == "reverse" - assert args.api_key == "oc_gc_12345678901234567890123456789012" - assert args.input.name == "test/fixtures/input.txt" - assert args.output == "test/fixtures/output.csv" - assert args.headers is True - assert args.input_columns == [1, 2] - assert args.add_columns == ["city", "postcode"] - assert args.limit == 4 - assert args.workers == 3 - assert args.timeout == 2 - assert args.retries == 1 - assert args.dry_run is True - assert args.unordered is True - assert args.api_domain == "bulk.opencagedata.com" - assert args.optional_api_params == {"extra": "1"} - assert args.no_progress is True - assert args.quiet is True - - -def test_defaults(): - args = parse_args([ - "forward", - "--api-key", "12345678901234567890123456789012", - "--input", "test/fixtures/input.txt", - "--output", "test/fixtures/output.csv" - ]) - - assert args.command == "forward" - assert args.limit == 0 - assert args.headers is False - assert args.input_columns == [1] - assert args.add_columns == [ - "lat", - "lng", - "_type", - "_category", - "country_code", - "country", - "state", - "county", - "_normalized_city", - "postcode", - "road", - "house_number", - "confidence", - "formatted"] - assert args.workers == 1 - assert args.timeout == 10 - assert args.retries == 10 - assert args.dry_run is False - assert args.unordered is False - assert args.api_domain == "api.opencagedata.com" - assert args.optional_api_params == {} - assert args.no_progress is False - assert args.quiet is False - - -def test_reverse_input_columns(): - args = parse_args([ - "reverse", - "--api-key", "12345678901234567890123456789012", - "--input", "test/fixtures/input.txt", - "--output", "test/fixtures/output.csv" - ]) - assert args.input_columns == [1, 2] - - args = parse_args([ - "reverse", - "--api-key", "12345678901234567890123456789012", - "--input", "test/fixtures/input.txt", - "--output", "test/fixtures/output.csv", - "--input-columns", '2,1' - ]) - - assert args.input_columns == [2, 1] diff --git a/test/cli/test_cli_run.py b/test/cli/test_cli_run.py deleted file mode 100644 index 89fbb27..0000000 --- a/test/cli/test_cli_run.py +++ /dev/null @@ -1,193 +0,0 @@ -import pathlib -import os -import pytest - -from opencage.command_line import main - -# NOTE: Testing keys https://opencagedata.com/api#testingkeys -TEST_APIKEY_200 = '6d0e711d72d74daeb2b0bfd2a5cdfdba' # always returns same address -TEST_APIKEY_401 = '11111111111111111111111111111111' # invalid key - - -@pytest.fixture(autouse=True) -def around(): - yield - try: - pathlib.Path("test/fixtures/cli/output.csv").unlink() - except FileNotFoundError: - pass - - -def assert_output(path, length, lines): - assert pathlib.Path(path).exists() - - with open(path, "r", encoding="utf-8") as f: - actual = f.readlines() - # print(actual, file=sys.stderr) - assert len(actual) == length - - for i, expected in enumerate(lines): - assert actual[i].strip() == expected - - -def test_forward(): - main([ - "forward", - "--api-key", TEST_APIKEY_200, - "--input", "test/fixtures/cli/forward.csv", - "--output", "test/fixtures/cli/output.csv", - "--input-columns", "2,3,4", - "--add-columns", "country_code,country,postcode,city" - ]) - - assert_output( - path="test/fixtures/cli/output.csv", - length=3, - lines=['Rathausmarkt 1,Hamburg,20095,Germany,de,Germany,48153,Münster'] - ) - - -def test_reverse(): - main([ - "reverse", - "--api-key", TEST_APIKEY_200, - "--input", "test/fixtures/cli/reverse.csv", - "--output", "test/fixtures/cli/output.csv", - "--add-columns", "country_code,country,postcode" - ]) - - assert_output( - path="test/fixtures/cli/output.csv", - length=1, - lines=['51.9526622,7.6324709,de,Germany,48153'] - ) - - -def test_headers(): - main([ - "forward", - "--api-key", TEST_APIKEY_200, - "--input", "test/fixtures/cli/forward_with_headers.csv", - "--output", "test/fixtures/cli/output.csv", - "--input-columns", "1,2,3,4", - "--headers", - "--add-columns", "lat,lng,postcode" - ]) - - assert_output( - path="test/fixtures/cli/output.csv", - length=4, - lines=[ - 'street and number,town,postcode,country,lat,lng,postcode', - 'Rathausmarkt 1,Hamburg,20095,Germany,51.9526622,7.6324709,48153' - ] - ) - - -def test_input_errors(capfd): - main([ - "reverse", - "--api-key", TEST_APIKEY_200, - "--input", "test/fixtures/cli/reverse_with_errors.csv", - "--output", "test/fixtures/cli/output.csv", - "--add-columns", "country_code,postcode", - "--no-progress" - ]) - - _, err = capfd.readouterr() - # assert err == '' - assert err.count("\n") == 7 - assert "Line 1 - Missing input column 2 in ['50.101010']" in err - assert "Line 1 - Expected two comma-separated values for reverse geocoding, got ['50.101010']" in err - assert "Line 3 - Empty line" in err - assert "Line 3 - Missing input column 2 in ['']" in err - assert "Line 3 - Expected two comma-separated values for reverse geocoding, got ['']" in err - assert "Line 4 - Does not look like latitude and longitude: 'a' and 'b'" in err - - assert_output( - path="test/fixtures/cli/output.csv", - length=4, - lines=[ - '50.101010,,', - '-100,60.1,,', - ',,', - 'a,b,,' - ] - ) - - -def test_empty_result(): - # 'NOWHERE-INTERESTING' is guaranteed to return no result - # https://opencagedata.com/api#testingkeys - main([ - "forward", - "--api-key", TEST_APIKEY_200, - "--input", "test/fixtures/cli/forward_noresult.csv", - "--output", "test/fixtures/cli/output.csv", - "--input-columns", "2", - "--headers", - "--verbose", - "--add-columns", "lat,lng,postcode" - ]) - - assert_output( - path="test/fixtures/cli/output.csv", - length=2, - lines=[ - 'id,full_address,lat,lng,postcode', - '123,NOWHERE-INTERESTING,,,' - ] - ) - - -def test_invalid_api_key(capfd): - main([ - "forward", - "--api-key", TEST_APIKEY_401, - "--input", "test/fixtures/cli/forward_with_headers.csv", - "--output", "test/fixtures/cli/output.csv" - ]) - - _, err = capfd.readouterr() - assert 'Your API key is not authorized' in err - - -def test_dryrun(capfd): - main([ - "forward", - "--api-key", TEST_APIKEY_200, - "--input", "test/fixtures/cli/forward_with_headers.csv", - "--output", "test/fixtures/cli/output.csv", - "--dry-run" - ]) - - assert not os.path.isfile("test/fixtures/cli/output.csv") - - out, _ = capfd.readouterr() - assert out.count("\n") == 1 - assert "All good." in out - - -def test_invalid_domain(capfd): - main([ - "forward", - "--api-key", TEST_APIKEY_200, - "--input", "test/fixtures/cli/forward.csv", - "--output", "test/fixtures/cli/output.csv", - "--api-domain", "invalid73585348.opencagedata.com" - ]) - - _, err = capfd.readouterr() - assert 'Cannot connect to host' in err - - # with dry-run no request will be made - main([ - "forward", - "--api-key", TEST_APIKEY_200, - "--input", "test/fixtures/cli/forward.csv", - "--output", "test/fixtures/cli/output.csv", - "--api-domain", "invalid73585348.opencagedata.com", - "--dry-run" - ]) - _, err = capfd.readouterr() - assert err == '' diff --git a/test/fixtures/cli/forward.csv b/test/fixtures/cli/forward.csv deleted file mode 100644 index 64283bd..0000000 --- a/test/fixtures/cli/forward.csv +++ /dev/null @@ -1,3 +0,0 @@ -"Rathausmarkt 1",Hamburg,20095,Germany -"10 Downing Street",London,"SW1A 2AA","United Kingdom" -"C/ de Mallorca 401",Barcelona,08013,Spain \ No newline at end of file diff --git a/test/fixtures/cli/forward_noresult.csv b/test/fixtures/cli/forward_noresult.csv deleted file mode 100644 index 1d4dceb..0000000 --- a/test/fixtures/cli/forward_noresult.csv +++ /dev/null @@ -1,2 +0,0 @@ -id,full_address -123,NOWHERE-INTERESTING \ No newline at end of file diff --git a/test/fixtures/cli/forward_with_headers.csv b/test/fixtures/cli/forward_with_headers.csv deleted file mode 100644 index feaa784..0000000 --- a/test/fixtures/cli/forward_with_headers.csv +++ /dev/null @@ -1,4 +0,0 @@ -street and number,town,postcode,country -"Rathausmarkt 1",Hamburg,20095,Germany -"10 Downing Street",London,"SW1A 2AA","United Kingdom" -"C/ de Mallorca 401",Barcelona,08013,Spain \ No newline at end of file diff --git a/test/fixtures/cli/output.csv2 b/test/fixtures/cli/output.csv2 deleted file mode 100644 index 30942f9..0000000 --- a/test/fixtures/cli/output.csv2 +++ /dev/null @@ -1,2 +0,0 @@ -id,full_address,lat,lng,postcode -123,NOWHERE-INTERESTING,51.9526622,7.6324709,48153 diff --git a/test/fixtures/cli/reverse.csv b/test/fixtures/cli/reverse.csv deleted file mode 100644 index 95ab1fd..0000000 --- a/test/fixtures/cli/reverse.csv +++ /dev/null @@ -1 +0,0 @@ -51.9526622,7.6324709 \ No newline at end of file diff --git a/test/fixtures/cli/reverse_with_errors.csv b/test/fixtures/cli/reverse_with_errors.csv deleted file mode 100644 index e85bebd..0000000 --- a/test/fixtures/cli/reverse_with_errors.csv +++ /dev/null @@ -1,4 +0,0 @@ -50.101010 --100,60.1 - -a,b \ No newline at end of file diff --git a/test/fixtures/input.txt b/test/fixtures/input.txt deleted file mode 100644 index e69de29..0000000 diff --git a/test/test_batch.py b/test/test_batch.py deleted file mode 100644 index 3139dd5..0000000 --- a/test/test_batch.py +++ /dev/null @@ -1,25 +0,0 @@ -from opencage.batch import OpenCageBatchGeocoder - -batch = OpenCageBatchGeocoder({}) - - -def test_deep_get_result_value(): - result = { - 'annotations': { - 'FIPS': { - 'state': 'CA' - } - }, - 'components': { - 'street': 'Main Road' - } - } - - assert batch.deep_get_result_value(result, ['hello', 'world']) is None - - assert batch.deep_get_result_value(result, ['components', 'street']) == 'Main Road' - assert batch.deep_get_result_value(result, ['components', 'city']) is None - assert batch.deep_get_result_value(result, ['components', 'city'], '') == '' - - assert batch.deep_get_result_value([], ['hello', 'world']) is None - assert batch.deep_get_result_value(None, ['hello', 'world']) is None