antenati 6.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.
Files changed (35) hide show
  1. antenati-6.0/.gitignore +201 -0
  2. antenati-6.0/CHANGELOG.md +123 -0
  3. antenati-6.0/LICENSE +21 -0
  4. antenati-6.0/PKG-INFO +127 -0
  5. antenati-6.0/README.md +63 -0
  6. antenati-6.0/pyproject.toml +113 -0
  7. antenati-6.0/src/antenati/__init__.py +51 -0
  8. antenati-6.0/src/antenati/__main__.py +5 -0
  9. antenati-6.0/src/antenati/_version.py +24 -0
  10. antenati-6.0/src/antenati/cli.py +97 -0
  11. antenati-6.0/src/antenati/downloader.py +197 -0
  12. antenati-6.0/src/antenati/errors.py +34 -0
  13. antenati-6.0/src/antenati/gui/__init__.py +17 -0
  14. antenati-6.0/src/antenati/gui/__main__.py +10 -0
  15. antenati-6.0/src/antenati/gui/app.py +208 -0
  16. antenati-6.0/src/antenati/gui/progress.py +45 -0
  17. antenati-6.0/src/antenati/gui/worker.py +138 -0
  18. antenati-6.0/src/antenati/http.py +124 -0
  19. antenati-6.0/src/antenati/iiif.py +182 -0
  20. antenati-6.0/tests/__init__.py +0 -0
  21. antenati-6.0/tests/conftest.py +78 -0
  22. antenati-6.0/tests/fixtures/__init__.py +0 -0
  23. antenati-6.0/tests/fixtures/gallery.html +15 -0
  24. antenati-6.0/tests/fixtures/manifest_minimal.json +65 -0
  25. antenati-6.0/tests/integration/__init__.py +0 -0
  26. antenati-6.0/tests/integration/test_live_download.py +42 -0
  27. antenati-6.0/tests/test_check_dir.py +28 -0
  28. antenati-6.0/tests/test_download_run.py +234 -0
  29. antenati-6.0/tests/test_gui_worker.py +162 -0
  30. antenati-6.0/tests/test_http.py +111 -0
  31. antenati-6.0/tests/test_iiif_defensive.py +53 -0
  32. antenati-6.0/tests/test_iiif_parsing.py +209 -0
  33. antenati-6.0/tests/test_metadata.py +43 -0
  34. antenati-6.0/tests/test_smoke.py +31 -0
  35. antenati-6.0/tests/test_url_manipulation.py +31 -0
@@ -0,0 +1,201 @@
1
+ # Created by https://www.toptal.com/developers/gitignore/api/python,visualstudiocode
2
+ # Edit at https://www.toptal.com/developers/gitignore?templates=python,visualstudiocode
3
+
4
+ ### Python ###
5
+ # Byte-compiled / optimized / DLL files
6
+ __pycache__/
7
+ *.py[cod]
8
+ *$py.class
9
+
10
+ # C extensions
11
+ *.so
12
+
13
+ # Distribution / packaging
14
+ .Python
15
+ build/
16
+ develop-eggs/
17
+ dist/
18
+ downloads/
19
+ eggs/
20
+ .eggs/
21
+ lib/
22
+ lib64/
23
+ parts/
24
+ sdist/
25
+ var/
26
+ wheels/
27
+ share/python-wheels/
28
+ *.egg-info/
29
+ .installed.cfg
30
+ *.egg
31
+ MANIFEST
32
+
33
+ # Auto-generated by hatch-vcs at build time
34
+ src/antenati/_version.py
35
+
36
+ # PyInstaller
37
+ # Usually these files are written by a python script from a template
38
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
39
+ *.manifest
40
+ *.spec
41
+
42
+ # Installer logs
43
+ pip-log.txt
44
+ pip-delete-this-directory.txt
45
+
46
+ # Unit test / coverage reports
47
+ htmlcov/
48
+ .tox/
49
+ .nox/
50
+ .coverage
51
+ .coverage.*
52
+ .cache
53
+ nosetests.xml
54
+ coverage.xml
55
+ *.cover
56
+ *.py,cover
57
+ .hypothesis/
58
+ .pytest_cache/
59
+ cover/
60
+
61
+ # Translations
62
+ *.mo
63
+ *.pot
64
+
65
+ # Django stuff:
66
+ *.log
67
+ local_settings.py
68
+ db.sqlite3
69
+ db.sqlite3-journal
70
+
71
+ # Flask stuff:
72
+ instance/
73
+ .webassets-cache
74
+
75
+ # Scrapy stuff:
76
+ .scrapy
77
+
78
+ # Sphinx documentation
79
+ docs/_build/
80
+
81
+ # PyBuilder
82
+ .pybuilder/
83
+ target/
84
+
85
+ # Jupyter Notebook
86
+ .ipynb_checkpoints
87
+
88
+ # IPython
89
+ profile_default/
90
+ ipython_config.py
91
+
92
+ # pyenv
93
+ # For a library or package, you might want to ignore these files since the code is
94
+ # intended to run in multiple environments; otherwise, check them in:
95
+ # .python-version
96
+
97
+ # pipenv
98
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
99
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
100
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
101
+ # install all needed dependencies.
102
+ #Pipfile.lock
103
+
104
+ # poetry
105
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
106
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
107
+ # commonly ignored for libraries.
108
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
109
+ #poetry.lock
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ #pdm.lock
114
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
115
+ # in version control.
116
+ # https://pdm.fming.dev/#use-with-ide
117
+ .pdm.toml
118
+
119
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
120
+ __pypackages__/
121
+
122
+ # Celery stuff
123
+ celerybeat-schedule
124
+ celerybeat.pid
125
+
126
+ # SageMath parsed files
127
+ *.sage.py
128
+
129
+ # Environments
130
+ .env
131
+ .venv
132
+ env/
133
+ venv/
134
+ ENV/
135
+ env.bak/
136
+ venv.bak/
137
+
138
+ # uv (not the project's package manager — only used ad-hoc locally)
139
+ uv.lock
140
+
141
+ # Spyder project settings
142
+ .spyderproject
143
+ .spyproject
144
+
145
+ # Rope project settings
146
+ .ropeproject
147
+
148
+ # mkdocs documentation
149
+ /site
150
+
151
+ # mypy
152
+ .mypy_cache/
153
+ .dmypy.json
154
+ dmypy.json
155
+
156
+ # Pyre type checker
157
+ .pyre/
158
+
159
+ # pytype static type analyzer
160
+ .pytype/
161
+
162
+ # Cython debug symbols
163
+ cython_debug/
164
+
165
+ # PyCharm
166
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
167
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
168
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
169
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
170
+ #.idea/
171
+
172
+ ### Python Patch ###
173
+ # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
174
+ poetry.toml
175
+
176
+ # ruff
177
+ .ruff_cache/
178
+
179
+ # LSP config files
180
+ pyrightconfig.json
181
+
182
+ ### VisualStudioCode ###
183
+ .vscode/*
184
+ !.vscode/settings.json
185
+ !.vscode/tasks.json
186
+ !.vscode/launch.json
187
+ !.vscode/extensions.json
188
+ !.vscode/*.code-snippets
189
+
190
+ # Local History for Visual Studio Code
191
+ .history/
192
+
193
+ # Built Visual Studio Code Extensions
194
+ *.vsix
195
+
196
+ ### VisualStudioCode Patch ###
197
+ # Ignore all local history of files
198
+ .history
199
+ .ionide
200
+
201
+ # End of https://www.toptal.com/developers/gitignore/api/python,visualstudiocode
@@ -0,0 +1,123 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+
9
+ ## [6.0] - 2026-06-11
10
+
11
+ ### Added
12
+ - Comprehensive test suite (15+ test modules) covering IIIF parsing, HTTP handling, download orchestration, filesystem operations, and end-to-end flows with mocked HTTP
13
+ - Typed exception hierarchy (`ManifestError`, `WafChallengeError`, `ThreadError`) replacing generic `RuntimeError`
14
+ - `--verbose` / `-vv` flags to control log verbosity (WARNING → INFO → DEBUG)
15
+ - Automatic exponential backoff retry policy for transient 5xx and rate-limit (429) responses
16
+
17
+ ### Changed
18
+ - Dropped Intel macOS (macOS 13) binary artifacts: GitHub Actions no longer provides Intel macOS runners; only Apple Silicon (macOS 14, arm64) is now built
19
+ - Refactored monolithic `antenati.py` into a modular package structure under `src/antenati/`:
20
+ - `downloader.py`: core `Downloader` class with thread-pool orchestration
21
+ - `iiif.py`: pure IIIF manifest parsing helpers (no I/O, offline-testable)
22
+ - `http.py`: HTTP session building and request handling
23
+ - `errors.py`: typed exception hierarchy
24
+ - `cli.py`: CLI entry point with logging configuration
25
+ - CI/CD pipeline updated with linting (ruff), type checking (mypy), and offline test runs
26
+
27
+ ## [5.0] - 2025-11-01
28
+
29
+ ### Added
30
+ - Restored support for full/resolution image size downloads
31
+
32
+ ### Changed
33
+ - Default requested size is now `0` (maximum available size) instead of 1000 pixels; use `--size N` to limit size
34
+
35
+ ### Fixed
36
+ - Graceful handling of server denials (403 or WAF challenge)
37
+
38
+
39
+ ## [4.0] - 2025-07-27
40
+
41
+ ### Changed
42
+ - Updated implementation to comply with recent SAN server filter requirements:
43
+ - Full-resolution downloads are no longer supported; this may be revisited in future releases
44
+ - Users must now specify the maximum image size using the `-s/--size` option (default: 1000 px); requests for larger images will result in a 403 error
45
+ - Download logic now detects AWS WAF challenges and provides a clear error message, replacing the previous generic 202 error; no workaround is currently available
46
+ - Reduced default number of threads and connections to minimize server load
47
+ - Updated the user agent string to a modern value
48
+ - Replaced the use of the `urllib3` Python module with the more flexible `requests` library
49
+ - Removed the `-c/--nconn` parameter; connection management now relies on the defaults provided by the `requests` library
50
+
51
+ ## [3.2] - 2025-07-14
52
+
53
+ ### Fixed
54
+ - Access to IIIF manifest with proper HTTP headers to address recent changes in SAN server filters that broke v3.1
55
+
56
+ ### Changed
57
+ - Download size now reported in binary format (MiB rather than MB)
58
+ - Update Python dependencies
59
+
60
+ ## [3.1] - 2025-02-08
61
+
62
+ ### Added
63
+ - Pyinstaller artifacts now built with Python 3.12
64
+ - Support for multiple platforms:
65
+ - Ubuntu 22.04 (x86_64)
66
+ - macOS 13 (Intel)
67
+ - macOS 14 (arm64)
68
+ - Windows 2022
69
+
70
+ ### Changed
71
+ - Minimum Python version moved to 3.9
72
+ - Improved README documentation
73
+
74
+ ## [3.0] - 2024-10-14
75
+
76
+ ### Added
77
+ - New GUI available with `antenati_gui.py`
78
+ - GUI standalone executables generated by pyinstaller
79
+ - Support for Windows, macOS and Linux standalone executables
80
+
81
+ ## [2.5] - 2023-01-22
82
+
83
+ ### Fixed
84
+ - Support for new URL [antenati.cultura.gov.it](https://antenati.cultura.gov.it/)
85
+
86
+ ## [2.4] - 2022-12-28
87
+
88
+ ### Added
89
+ - Possibility to set range of pages to download using `-f` and `-l` options
90
+ - Type hints throughout the codebase
91
+
92
+ ### Fixed
93
+ - Removed usage of deprecated `cgi.parse_header`
94
+
95
+ ## [2.3] - 2022-05-21
96
+
97
+ ### Added
98
+ - HTTP headers to get around SAN server filters
99
+
100
+ ## [2.2] - 2022-02-16
101
+
102
+ ### Changed
103
+ - Several minor improvements
104
+
105
+ ## [2.1] - 2021-11-20
106
+
107
+ ### Changed
108
+ - Code restyle with argument parsing to specify number of threads and number of connections
109
+
110
+ ## [2.0] - 2021-11-19
111
+
112
+ ### Added
113
+ - Support for new Portale Antenati (Fall 2021)
114
+
115
+ ## [1.1] - 2019-10-12
116
+
117
+ ### Changed
118
+ - Upgraded to Python 3 using 2to3 tool
119
+
120
+ ## [1.0] - 2019-04-14
121
+
122
+ ### Added
123
+ - First stable release
antenati-6.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Giovanni Cerretani
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.
antenati-6.0/PKG-INFO ADDED
@@ -0,0 +1,127 @@
1
+ Metadata-Version: 2.4
2
+ Name: antenati
3
+ Version: 6.0
4
+ Summary: Download data from the Portale Antenati, the italian state genealogy archive
5
+ Project-URL: Homepage, https://gcerretani.github.io/antenati/
6
+ Project-URL: Repository, https://github.com/gcerretani/antenati
7
+ Project-URL: Issues, https://github.com/gcerretani/antenati/issues
8
+ Project-URL: Changelog, https://github.com/gcerretani/antenati/blob/master/CHANGELOG.md
9
+ Author: Giovanni Cerretani
10
+ License: MIT License
11
+
12
+ Copyright (c) 2018 Giovanni Cerretani
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ Keywords: antenati,downloader,genealogy,iiif,portale-antenati
33
+ Classifier: Development Status :: 5 - Production/Stable
34
+ Classifier: Environment :: Console
35
+ Classifier: Environment :: X11 Applications
36
+ Classifier: Intended Audience :: End Users/Desktop
37
+ Classifier: License :: OSI Approved :: MIT License
38
+ Classifier: Natural Language :: English
39
+ Classifier: Natural Language :: Italian
40
+ Classifier: Operating System :: OS Independent
41
+ Classifier: Programming Language :: Python :: 3
42
+ Classifier: Programming Language :: Python :: 3 :: Only
43
+ Classifier: Programming Language :: Python :: 3.10
44
+ Classifier: Programming Language :: Python :: 3.11
45
+ Classifier: Programming Language :: Python :: 3.12
46
+ Classifier: Programming Language :: Python :: 3.13
47
+ Classifier: Programming Language :: Python :: 3.14
48
+ Classifier: Topic :: Internet :: WWW/HTTP
49
+ Classifier: Topic :: Multimedia :: Graphics
50
+ Requires-Python: >=3.10
51
+ Requires-Dist: click~=8.3.0
52
+ Requires-Dist: humanize~=4.14.0
53
+ Requires-Dist: python-slugify~=8.0.4
54
+ Requires-Dist: requests~=2.32.5
55
+ Requires-Dist: tqdm~=4.67.1
56
+ Provides-Extra: dev
57
+ Requires-Dist: mypy==1.19.1; extra == 'dev'
58
+ Requires-Dist: pre-commit; extra == 'dev'
59
+ Requires-Dist: pytest==9.0.3; extra == 'dev'
60
+ Requires-Dist: responses==0.25.8; extra == 'dev'
61
+ Requires-Dist: ruff==0.15.8; extra == 'dev'
62
+ Requires-Dist: types-requests; extra == 'dev'
63
+ Description-Content-Type: text/markdown
64
+
65
+ # antenati
66
+ A tool to download data from the *[Portale Antenati](http://antenati.cultura.gov.it/)*, the genealogy digital archive maintained by the italian **Ministero per i beni e le attività culturali**.
67
+
68
+ Since the website tends to be pretty slow in the evening, we present a script to help the retrieval of the documents for your family tree. The script allows you to download **all the images of any archive at the same time**, without any human action. Just launch the script and have a coffee while it downloads all the stuff for you.
69
+
70
+ ## GUI version
71
+
72
+ Just get the executable from the [release artifacts](https://github.com/gcerretani/antenati/releases/latest), and have fun!
73
+
74
+ ![GUI Screenshot](docs/gui_screenshot.png)
75
+
76
+ #### Example:
77
+ In the website, navigate to the archive you want to download. For example, for the people born in Viareggio in 1807 you should find the page:
78
+
79
+ [https://antenati.cultura.gov.it/ark:/12657/an_ua19944535/w9DWR8x](https://antenati.cultura.gov.it/ark:/12657/an_ua19944535/w9DWR8x)
80
+
81
+ Copy the link to the first page, and paste it in the Archive URL field of the window. Then, specify a destination folder: the results will be placed there, in a new subfolder named *archivio-di-stato-di-lucca-stato-civile-napoleonico-viareggio-1807-nati-19944549*.
82
+
83
+ ## CLI version
84
+
85
+ ### Requirements
86
+ The software is written in Python 3 and requires Python 3.10 or newer. On Windows the version on the Microsoft Store is fine, on Linux use your distribution package manager.
87
+
88
+ ### Install
89
+ From a checkout of this repository:
90
+
91
+ pip install .
92
+
93
+ This installs an `antenati` command on your `PATH` (and an `antenati-gui` one for the GUI).
94
+
95
+ ### Run
96
+ To download the images of a gallery, pass the URL of the gallery page:
97
+
98
+ antenati <URL of the album>
99
+
100
+ You can also invoke the package directly without installing the script:
101
+
102
+ python3 -m antenati <URL of the album>
103
+
104
+ The files will be downloaded to a new folder named as *ARCHIVE-PLACE-YEAR-TYPE-ID* of the downloaded archive. For more options, see the help:
105
+
106
+ antenati -h
107
+
108
+ #### Example:
109
+ In the website, navigate to the archive you want to download. For example, for the people born in Viareggio in 1807 you should find the page:
110
+
111
+ [https://antenati.cultura.gov.it/ark:/12657/an_ua19944535/w9DWR8x](https://antenati.cultura.gov.it/ark:/12657/an_ua19944535/w9DWR8x)
112
+
113
+ Then, copy the link to the first page, and call the script with that link as argument:
114
+
115
+ antenati https://antenati.cultura.gov.it/ark:/12657/an_ua19944535/w9DWR8x
116
+
117
+ The results will be placed in a folder named *archivio-di-stato-di-lucca-stato-civile-napoleonico-viareggio-1807-nati-19944549*.
118
+
119
+ To include the archive and image IDs in the saved file names (e.g. `pag-1+an_ua19944535+w9DWR8x.jpg` instead of `pag-1.jpg`), add the `-d`/`--descriptive-names` flag.
120
+
121
+ ## AWS WAF challenge
122
+
123
+ Outside Italy, the Portale Antenati gallery pages are often protected by an AWS WAF challenge that this tool cannot solve, and the download fails with an *AWS WAF challenge cannot be bypassed* error (see [#25](https://github.com/gcerretani/antenati/issues/25)). The IIIF manifest and the images themselves are **not** behind the WAF, so you can work around it:
124
+
125
+ 1. open the gallery page in your browser;
126
+ 2. copy the **IIIF manifest** link at the bottom of the left side panel (it looks like `https://dam-antenati.cultura.gov.it/antenati/containers/.../manifest`);
127
+ 3. pass that URL to the tool (both CLI and GUI) instead of the gallery page URL.
antenati-6.0/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # antenati
2
+ A tool to download data from the *[Portale Antenati](http://antenati.cultura.gov.it/)*, the genealogy digital archive maintained by the italian **Ministero per i beni e le attività culturali**.
3
+
4
+ Since the website tends to be pretty slow in the evening, we present a script to help the retrieval of the documents for your family tree. The script allows you to download **all the images of any archive at the same time**, without any human action. Just launch the script and have a coffee while it downloads all the stuff for you.
5
+
6
+ ## GUI version
7
+
8
+ Just get the executable from the [release artifacts](https://github.com/gcerretani/antenati/releases/latest), and have fun!
9
+
10
+ ![GUI Screenshot](docs/gui_screenshot.png)
11
+
12
+ #### Example:
13
+ In the website, navigate to the archive you want to download. For example, for the people born in Viareggio in 1807 you should find the page:
14
+
15
+ [https://antenati.cultura.gov.it/ark:/12657/an_ua19944535/w9DWR8x](https://antenati.cultura.gov.it/ark:/12657/an_ua19944535/w9DWR8x)
16
+
17
+ Copy the link to the first page, and paste it in the Archive URL field of the window. Then, specify a destination folder: the results will be placed there, in a new subfolder named *archivio-di-stato-di-lucca-stato-civile-napoleonico-viareggio-1807-nati-19944549*.
18
+
19
+ ## CLI version
20
+
21
+ ### Requirements
22
+ The software is written in Python 3 and requires Python 3.10 or newer. On Windows the version on the Microsoft Store is fine, on Linux use your distribution package manager.
23
+
24
+ ### Install
25
+ From a checkout of this repository:
26
+
27
+ pip install .
28
+
29
+ This installs an `antenati` command on your `PATH` (and an `antenati-gui` one for the GUI).
30
+
31
+ ### Run
32
+ To download the images of a gallery, pass the URL of the gallery page:
33
+
34
+ antenati <URL of the album>
35
+
36
+ You can also invoke the package directly without installing the script:
37
+
38
+ python3 -m antenati <URL of the album>
39
+
40
+ The files will be downloaded to a new folder named as *ARCHIVE-PLACE-YEAR-TYPE-ID* of the downloaded archive. For more options, see the help:
41
+
42
+ antenati -h
43
+
44
+ #### Example:
45
+ In the website, navigate to the archive you want to download. For example, for the people born in Viareggio in 1807 you should find the page:
46
+
47
+ [https://antenati.cultura.gov.it/ark:/12657/an_ua19944535/w9DWR8x](https://antenati.cultura.gov.it/ark:/12657/an_ua19944535/w9DWR8x)
48
+
49
+ Then, copy the link to the first page, and call the script with that link as argument:
50
+
51
+ antenati https://antenati.cultura.gov.it/ark:/12657/an_ua19944535/w9DWR8x
52
+
53
+ The results will be placed in a folder named *archivio-di-stato-di-lucca-stato-civile-napoleonico-viareggio-1807-nati-19944549*.
54
+
55
+ To include the archive and image IDs in the saved file names (e.g. `pag-1+an_ua19944535+w9DWR8x.jpg` instead of `pag-1.jpg`), add the `-d`/`--descriptive-names` flag.
56
+
57
+ ## AWS WAF challenge
58
+
59
+ Outside Italy, the Portale Antenati gallery pages are often protected by an AWS WAF challenge that this tool cannot solve, and the download fails with an *AWS WAF challenge cannot be bypassed* error (see [#25](https://github.com/gcerretani/antenati/issues/25)). The IIIF manifest and the images themselves are **not** behind the WAF, so you can work around it:
60
+
61
+ 1. open the gallery page in your browser;
62
+ 2. copy the **IIIF manifest** link at the bottom of the left side panel (it looks like `https://dam-antenati.cultura.gov.it/antenati/containers/.../manifest`);
63
+ 3. pass that URL to the tool (both CLI and GUI) instead of the gallery page URL.
@@ -0,0 +1,113 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.21", "hatch-vcs>=0.4"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "antenati"
7
+ description = "Download data from the Portale Antenati, the italian state genealogy archive"
8
+ readme = "README.md"
9
+ license = { file = "LICENSE" }
10
+ requires-python = ">=3.10"
11
+ authors = [
12
+ { name = "Giovanni Cerretani" },
13
+ ]
14
+ keywords = ["antenati", "genealogy", "iiif", "downloader", "portale-antenati"]
15
+ classifiers = [
16
+ "Development Status :: 5 - Production/Stable",
17
+ "Environment :: Console",
18
+ "Environment :: X11 Applications",
19
+ "Intended Audience :: End Users/Desktop",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Natural Language :: English",
22
+ "Natural Language :: Italian",
23
+ "Operating System :: OS Independent",
24
+ "Programming Language :: Python :: 3",
25
+ "Programming Language :: Python :: 3 :: Only",
26
+ "Programming Language :: Python :: 3.10",
27
+ "Programming Language :: Python :: 3.11",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Programming Language :: Python :: 3.13",
30
+ "Programming Language :: Python :: 3.14",
31
+ "Topic :: Internet :: WWW/HTTP",
32
+ "Topic :: Multimedia :: Graphics",
33
+ ]
34
+ dependencies = [
35
+ "click~=8.3.0",
36
+ "humanize~=4.14.0",
37
+ "python-slugify~=8.0.4",
38
+ "requests~=2.32.5",
39
+ "tqdm~=4.67.1",
40
+ ]
41
+ dynamic = ["version"]
42
+
43
+ [project.optional-dependencies]
44
+ # Pinned dev tooling. Install with: pip install -e ".[dev]"
45
+ dev = [
46
+ "mypy==1.19.1",
47
+ "pre-commit",
48
+ "pytest==9.0.3",
49
+ "responses==0.25.8",
50
+ "ruff==0.15.8",
51
+ "types-requests",
52
+ ]
53
+
54
+ [project.urls]
55
+ Homepage = "https://gcerretani.github.io/antenati/"
56
+ Repository = "https://github.com/gcerretani/antenati"
57
+ Issues = "https://github.com/gcerretani/antenati/issues"
58
+ Changelog = "https://github.com/gcerretani/antenati/blob/master/CHANGELOG.md"
59
+
60
+ [project.scripts]
61
+ antenati = "antenati.cli:main"
62
+
63
+ [project.gui-scripts]
64
+ antenati-gui = "antenati.gui:main"
65
+
66
+ [tool.hatch.version]
67
+ source = "vcs"
68
+
69
+ [tool.hatch.build.hooks.vcs]
70
+ version-file = "src/antenati/_version.py"
71
+
72
+ [tool.hatch.build.targets.wheel]
73
+ packages = ["src/antenati"]
74
+
75
+ [tool.hatch.build.targets.sdist]
76
+ include = [
77
+ "src/antenati",
78
+ "tests",
79
+ "README.md",
80
+ "CHANGELOG.md",
81
+ "LICENSE",
82
+ "pyproject.toml",
83
+ ]
84
+
85
+ [tool.ruff]
86
+ line-length = 160
87
+ target-version = "py310"
88
+ extend-exclude = ["build", "dist", "src/antenati/_version.py"]
89
+
90
+ [tool.ruff.lint]
91
+ # Conservative starting set: enabled rules already pass on the current
92
+ # codebase. Stricter rules (PTH, ANN, D, etc.) will be turned on as the
93
+ # refactor lands and the affected code is rewritten.
94
+ select = ["E", "F", "W", "I", "B", "UP", "SIM", "RUF", "RET", "TID"]
95
+
96
+ [tool.ruff.format]
97
+ quote-style = "single"
98
+ exclude = ["src/antenati/_version.py"]
99
+
100
+ [tool.mypy]
101
+ python_version = "3.10"
102
+ ignore_missing_imports = true
103
+ warn_redundant_casts = true
104
+ warn_unreachable = true
105
+ check_untyped_defs = true
106
+
107
+ [tool.pytest.ini_options]
108
+ minversion = "7.0"
109
+ testpaths = ["tests"]
110
+ addopts = "-ra --strict-markers"
111
+ markers = [
112
+ "integration: tests that hit the live Portale Antenati (opt-in, slow, may flake)",
113
+ ]