mirror-url 3.1.14__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 (56) hide show
  1. mirror_url-3.1.14/LICENSE +21 -0
  2. mirror_url-3.1.14/PKG-INFO +171 -0
  3. mirror_url-3.1.14/README.md +98 -0
  4. mirror_url-3.1.14/pyproject.toml +143 -0
  5. mirror_url-3.1.14/setup.cfg +4 -0
  6. mirror_url-3.1.14/src/mirror_url/__init__.py +48 -0
  7. mirror_url-3.1.14/src/mirror_url/__main__.py +21 -0
  8. mirror_url-3.1.14/src/mirror_url/_core/__init__.py +9 -0
  9. mirror_url-3.1.14/src/mirror_url/_core/_base.py +1289 -0
  10. mirror_url-3.1.14/src/mirror_url/_core/cleanup.py +335 -0
  11. mirror_url-3.1.14/src/mirror_url/_core/compare.py +705 -0
  12. mirror_url-3.1.14/src/mirror_url/_core/downloads.py +306 -0
  13. mirror_url-3.1.14/src/mirror_url/_core/report.py +762 -0
  14. mirror_url-3.1.14/src/mirror_url/_core/scan.py +340 -0
  15. mirror_url-3.1.14/src/mirror_url/_core/urls.py +306 -0
  16. mirror_url-3.1.14/src/mirror_url/_version.py +12 -0
  17. mirror_url-3.1.14/src/mirror_url/async_connection.py +1331 -0
  18. mirror_url-3.1.14/src/mirror_url/cache.py +457 -0
  19. mirror_url-3.1.14/src/mirror_url/circuit_breaker.py +388 -0
  20. mirror_url-3.1.14/src/mirror_url/cli.py +1665 -0
  21. mirror_url-3.1.14/src/mirror_url/compat.py +81 -0
  22. mirror_url-3.1.14/src/mirror_url/concurrency.py +300 -0
  23. mirror_url-3.1.14/src/mirror_url/config.py +756 -0
  24. mirror_url-3.1.14/src/mirror_url/connection.py +850 -0
  25. mirror_url-3.1.14/src/mirror_url/constants.py +212 -0
  26. mirror_url-3.1.14/src/mirror_url/core.py +39 -0
  27. mirror_url-3.1.14/src/mirror_url/decorators.py +105 -0
  28. mirror_url-3.1.14/src/mirror_url/download.py +1709 -0
  29. mirror_url-3.1.14/src/mirror_url/enums.py +79 -0
  30. mirror_url-3.1.14/src/mirror_url/exceptions.py +155 -0
  31. mirror_url-3.1.14/src/mirror_url/health.py +272 -0
  32. mirror_url-3.1.14/src/mirror_url/metrics.py +433 -0
  33. mirror_url-3.1.14/src/mirror_url/models.py +195 -0
  34. mirror_url-3.1.14/src/mirror_url/monitoring.py +294 -0
  35. mirror_url-3.1.14/src/mirror_url/parsing.py +176 -0
  36. mirror_url-3.1.14/src/mirror_url/primitives.py +411 -0
  37. mirror_url-3.1.14/src/mirror_url/progress.py +355 -0
  38. mirror_url-3.1.14/src/mirror_url/queue.py +137 -0
  39. mirror_url-3.1.14/src/mirror_url/rate_limiter.py +335 -0
  40. mirror_url-3.1.14/src/mirror_url/scanner.py +254 -0
  41. mirror_url-3.1.14/src/mirror_url/security.py +620 -0
  42. mirror_url-3.1.14/src/mirror_url/storage.py +631 -0
  43. mirror_url-3.1.14/src/mirror_url/transport.py +312 -0
  44. mirror_url-3.1.14/src/mirror_url/tuner.py +123 -0
  45. mirror_url-3.1.14/src/mirror_url/utils.py +410 -0
  46. mirror_url-3.1.14/src/mirror_url.egg-info/PKG-INFO +171 -0
  47. mirror_url-3.1.14/src/mirror_url.egg-info/SOURCES.txt +54 -0
  48. mirror_url-3.1.14/src/mirror_url.egg-info/dependency_links.txt +1 -0
  49. mirror_url-3.1.14/src/mirror_url.egg-info/entry_points.txt +2 -0
  50. mirror_url-3.1.14/src/mirror_url.egg-info/requires.txt +29 -0
  51. mirror_url-3.1.14/src/mirror_url.egg-info/top_level.txt +1 -0
  52. mirror_url-3.1.14/tests/test_integration.py +53 -0
  53. mirror_url-3.1.14/tests/test_security.py +119 -0
  54. mirror_url-3.1.14/tests/test_smoke.py +47 -0
  55. mirror_url-3.1.14/tests/test_subsystems.py +302 -0
  56. mirror_url-3.1.14/tests/test_utils.py +33 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 BP
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,171 @@
1
+ Metadata-Version: 2.4
2
+ Name: mirror-url
3
+ Version: 3.1.14
4
+ Summary: Enterprise-grade remote directory mirroring tool with adaptive concurrency, integrity checks, and SSRF-hardened transport.
5
+ Author: BP
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 BP
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/bpodlipnik/mirror-url
29
+ Project-URL: Repository, https://github.com/bpodlipnik/mirror-url
30
+ Project-URL: Issues, https://github.com/bpodlipnik/mirror-url/issues
31
+ Keywords: mirror,download,http,scraper,directory,async,httpx
32
+ Classifier: Development Status :: 4 - Beta
33
+ Classifier: Environment :: Console
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: Intended Audience :: System Administrators
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Operating System :: OS Independent
38
+ Classifier: Programming Language :: Python :: 3
39
+ Classifier: Programming Language :: Python :: 3.9
40
+ Classifier: Programming Language :: Python :: 3.10
41
+ Classifier: Programming Language :: Python :: 3.11
42
+ Classifier: Programming Language :: Python :: 3.12
43
+ Classifier: Topic :: Internet :: WWW/HTTP
44
+ Classifier: Topic :: System :: Archiving :: Mirroring
45
+ Requires-Python: >=3.9
46
+ Description-Content-Type: text/markdown
47
+ License-File: LICENSE
48
+ Requires-Dist: httpx>=0.24
49
+ Requires-Dist: pydantic>=2.0
50
+ Requires-Dist: PyYAML>=6.0
51
+ Provides-Extra: fast
52
+ Requires-Dist: stringzilla>=3.0; extra == "fast"
53
+ Requires-Dist: lxml>=4.9; extra == "fast"
54
+ Provides-Extra: progress
55
+ Requires-Dist: tqdm>=4.65; extra == "progress"
56
+ Provides-Extra: monitor
57
+ Requires-Dist: psutil>=5.9; extra == "monitor"
58
+ Provides-Extra: all
59
+ Requires-Dist: stringzilla>=3.0; extra == "all"
60
+ Requires-Dist: lxml>=4.9; extra == "all"
61
+ Requires-Dist: tqdm>=4.65; extra == "all"
62
+ Requires-Dist: psutil>=5.9; extra == "all"
63
+ Provides-Extra: dev
64
+ Requires-Dist: pytest>=7.4; extra == "dev"
65
+ Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
66
+ Requires-Dist: pytest-cov>=4.1; extra == "dev"
67
+ Requires-Dist: ruff>=0.4; extra == "dev"
68
+ Requires-Dist: black>=24.0; extra == "dev"
69
+ Requires-Dist: mypy>=1.8; extra == "dev"
70
+ Requires-Dist: types-PyYAML>=6.0; extra == "dev"
71
+ Requires-Dist: pre-commit>=3.5; extra == "dev"
72
+ Dynamic: license-file
73
+
74
+ # MirrorURL
75
+
76
+ [![CI](https://github.com/bpodlipnik/mirror-url/actions/workflows/ci.yml/badge.svg)](https://github.com/bpodlipnik/mirror-url/actions/workflows/ci.yml)
77
+ [![Python](https://img.shields.io/badge/python-3.9%E2%80%933.12-blue)](https://www.python.org)
78
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](./LICENSE)
79
+
80
+ Enterprise-grade remote directory mirroring tool. MirrorURL recursively
81
+ discovers files behind an HTTP(S) directory listing and mirrors them locally
82
+ with adaptive concurrency, resumable/partial downloads, integrity verification,
83
+ and an SSRF-hardened transport layer.
84
+
85
+ > **Status:** Refactor complete. The full implementation now lives in the
86
+ > [`src/mirror_url/`](./src/mirror_url) package (30 modules), migrated verbatim
87
+ > from the original single-file script per [`REFACTORING_PLAN.md`](./REFACTORING_PLAN.md).
88
+ > The legacy [`mirror_url.py`](./mirror_url.py) is retained only as a frozen
89
+ > reference and can be deleted once you've run the test suite against the package
90
+ > in an environment with the runtime dependencies installed (see Development).
91
+
92
+ ## Features
93
+
94
+ - **Recursive discovery** of remote directory trees (BFS, depth/exclude limits, cycle-safe).
95
+ - **True parallel downloads** — multiple files and multiple chunks per file concurrently.
96
+ - **Adaptive async concurrency** that tunes itself to server RTT, throughput, and error rate.
97
+ - **Resumable & partial downloads** with HTTP range requests and chunk assembly.
98
+ - **Integrity checks** — size/timestamp comparison, ETag handling, content hashing.
99
+ - **Resilience** — per-domain circuit breakers, exponential backoff, rate limiting.
100
+ - **Security** — path-traversal and symlink-bomb defenses, private-IP/SSRF guards, URL-scope enforcement.
101
+ - **Operability** — metrics collection, multi-level progress, optional HTTP health-check server.
102
+ - **Caching** — filesystem and disk-backed indexes to skip unchanged content.
103
+
104
+ ## Installation
105
+
106
+ ```bash
107
+ # From source (editable, recommended during the refactor)
108
+ pip install -e ".[all,dev]"
109
+ ```
110
+
111
+ Python 3.9+ is required. Core dependencies: `httpx`, `pydantic` (v2), `PyYAML`.
112
+ Optional extras: `fast` (stringzilla, lxml), `progress` (tqdm), `monitor` (psutil).
113
+
114
+ ## Usage
115
+
116
+ Run via the console entry point or the module:
117
+
118
+ ```bash
119
+ mirror-url https://example.com/files/ --output ./mirror
120
+ # or
121
+ python -m mirror_url https://example.com/files/ --output ./mirror
122
+ ```
123
+
124
+ Run `mirror-url --help` for the full option list.
125
+
126
+ Configuration can also be supplied via a YAML file (see `MirrorConfig` /
127
+ `load_config_from_args`).
128
+
129
+ 📖 **Full documentation:** see the [User Guide](./docs/USER_GUIDE.md)
130
+ ([HTML version](./docs/USER_GUIDE.html)) for detailed installation, CLI
131
+ reference, config-file format, download modes, security notes, the Python API,
132
+ and troubleshooting.
133
+
134
+ ## Development
135
+
136
+ ```bash
137
+ pip install -e ".[dev]"
138
+ pre-commit install
139
+
140
+ ruff check . # lint
141
+ black --check . # format check
142
+ mypy # type-check the new package
143
+ pytest -m "not integration" # fast test lane
144
+ pytest # full suite (includes integration)
145
+ ```
146
+
147
+ Continuous integration runs lint + tests across Python 3.9–3.12 (see
148
+ `.github/workflows/ci.yml`).
149
+
150
+ ## Project layout
151
+
152
+ ```
153
+ src/mirror_url/ # the package (30 modules, dependency-layered)
154
+ tests/ # pytest suite
155
+ mirror_url.py # legacy monolith (frozen reference, pending removal)
156
+ REFACTORING_PLAN.md # module breakdown + migration roadmap
157
+ CHANGELOG.md # notable changes (Keep a Changelog format)
158
+ CONTRIBUTING.md # dev setup, checks, conventions
159
+ pyproject.toml # packaging, deps, tool config
160
+ ```
161
+
162
+ ## Contributing
163
+
164
+ Contributions are welcome — see [CONTRIBUTING.md](./CONTRIBUTING.md) for the dev
165
+ setup, the checks CI runs, and the project conventions (dependency layering,
166
+ lint policy, behavior-preserving refactors). Notable changes are tracked in
167
+ [CHANGELOG.md](./CHANGELOG.md).
168
+
169
+ ## License
170
+
171
+ [MIT](./LICENSE) © BP
@@ -0,0 +1,98 @@
1
+ # MirrorURL
2
+
3
+ [![CI](https://github.com/bpodlipnik/mirror-url/actions/workflows/ci.yml/badge.svg)](https://github.com/bpodlipnik/mirror-url/actions/workflows/ci.yml)
4
+ [![Python](https://img.shields.io/badge/python-3.9%E2%80%933.12-blue)](https://www.python.org)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](./LICENSE)
6
+
7
+ Enterprise-grade remote directory mirroring tool. MirrorURL recursively
8
+ discovers files behind an HTTP(S) directory listing and mirrors them locally
9
+ with adaptive concurrency, resumable/partial downloads, integrity verification,
10
+ and an SSRF-hardened transport layer.
11
+
12
+ > **Status:** Refactor complete. The full implementation now lives in the
13
+ > [`src/mirror_url/`](./src/mirror_url) package (30 modules), migrated verbatim
14
+ > from the original single-file script per [`REFACTORING_PLAN.md`](./REFACTORING_PLAN.md).
15
+ > The legacy [`mirror_url.py`](./mirror_url.py) is retained only as a frozen
16
+ > reference and can be deleted once you've run the test suite against the package
17
+ > in an environment with the runtime dependencies installed (see Development).
18
+
19
+ ## Features
20
+
21
+ - **Recursive discovery** of remote directory trees (BFS, depth/exclude limits, cycle-safe).
22
+ - **True parallel downloads** — multiple files and multiple chunks per file concurrently.
23
+ - **Adaptive async concurrency** that tunes itself to server RTT, throughput, and error rate.
24
+ - **Resumable & partial downloads** with HTTP range requests and chunk assembly.
25
+ - **Integrity checks** — size/timestamp comparison, ETag handling, content hashing.
26
+ - **Resilience** — per-domain circuit breakers, exponential backoff, rate limiting.
27
+ - **Security** — path-traversal and symlink-bomb defenses, private-IP/SSRF guards, URL-scope enforcement.
28
+ - **Operability** — metrics collection, multi-level progress, optional HTTP health-check server.
29
+ - **Caching** — filesystem and disk-backed indexes to skip unchanged content.
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ # From source (editable, recommended during the refactor)
35
+ pip install -e ".[all,dev]"
36
+ ```
37
+
38
+ Python 3.9+ is required. Core dependencies: `httpx`, `pydantic` (v2), `PyYAML`.
39
+ Optional extras: `fast` (stringzilla, lxml), `progress` (tqdm), `monitor` (psutil).
40
+
41
+ ## Usage
42
+
43
+ Run via the console entry point or the module:
44
+
45
+ ```bash
46
+ mirror-url https://example.com/files/ --output ./mirror
47
+ # or
48
+ python -m mirror_url https://example.com/files/ --output ./mirror
49
+ ```
50
+
51
+ Run `mirror-url --help` for the full option list.
52
+
53
+ Configuration can also be supplied via a YAML file (see `MirrorConfig` /
54
+ `load_config_from_args`).
55
+
56
+ 📖 **Full documentation:** see the [User Guide](./docs/USER_GUIDE.md)
57
+ ([HTML version](./docs/USER_GUIDE.html)) for detailed installation, CLI
58
+ reference, config-file format, download modes, security notes, the Python API,
59
+ and troubleshooting.
60
+
61
+ ## Development
62
+
63
+ ```bash
64
+ pip install -e ".[dev]"
65
+ pre-commit install
66
+
67
+ ruff check . # lint
68
+ black --check . # format check
69
+ mypy # type-check the new package
70
+ pytest -m "not integration" # fast test lane
71
+ pytest # full suite (includes integration)
72
+ ```
73
+
74
+ Continuous integration runs lint + tests across Python 3.9–3.12 (see
75
+ `.github/workflows/ci.yml`).
76
+
77
+ ## Project layout
78
+
79
+ ```
80
+ src/mirror_url/ # the package (30 modules, dependency-layered)
81
+ tests/ # pytest suite
82
+ mirror_url.py # legacy monolith (frozen reference, pending removal)
83
+ REFACTORING_PLAN.md # module breakdown + migration roadmap
84
+ CHANGELOG.md # notable changes (Keep a Changelog format)
85
+ CONTRIBUTING.md # dev setup, checks, conventions
86
+ pyproject.toml # packaging, deps, tool config
87
+ ```
88
+
89
+ ## Contributing
90
+
91
+ Contributions are welcome — see [CONTRIBUTING.md](./CONTRIBUTING.md) for the dev
92
+ setup, the checks CI runs, and the project conventions (dependency layering,
93
+ lint policy, behavior-preserving refactors). Notable changes are tracked in
94
+ [CHANGELOG.md](./CHANGELOG.md).
95
+
96
+ ## License
97
+
98
+ [MIT](./LICENSE) © BP
@@ -0,0 +1,143 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "mirror-url"
7
+ version = "3.1.14"
8
+ description = "Enterprise-grade remote directory mirroring tool with adaptive concurrency, integrity checks, and SSRF-hardened transport."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { file = "LICENSE" }
12
+ authors = [{ name = "BP" }]
13
+ keywords = ["mirror", "download", "http", "scraper", "directory", "async", "httpx"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Environment :: Console",
17
+ "Intended Audience :: Developers",
18
+ "Intended Audience :: System Administrators",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Topic :: Internet :: WWW/HTTP",
27
+ "Topic :: System :: Archiving :: Mirroring",
28
+ ]
29
+
30
+ # Core runtime dependencies (imported unconditionally by the package).
31
+ dependencies = [
32
+ "httpx>=0.24",
33
+ "pydantic>=2.0",
34
+ "PyYAML>=6.0",
35
+ ]
36
+
37
+ [project.optional-dependencies]
38
+ # Optional accelerators / niceties — guarded by try/except in the code.
39
+ fast = ["stringzilla>=3.0", "lxml>=4.9"]
40
+ progress = ["tqdm>=4.65"]
41
+ monitor = ["psutil>=5.9"]
42
+ all = ["stringzilla>=3.0", "lxml>=4.9", "tqdm>=4.65", "psutil>=5.9"]
43
+
44
+ # Development / CI toolchain.
45
+ dev = [
46
+ "pytest>=7.4",
47
+ "pytest-asyncio>=0.21",
48
+ "pytest-cov>=4.1",
49
+ "ruff>=0.4",
50
+ "black>=24.0",
51
+ "mypy>=1.8",
52
+ "types-PyYAML>=6.0", # type stubs for the yaml import (silences import-untyped)
53
+ "pre-commit>=3.5",
54
+ ]
55
+
56
+ [project.urls]
57
+ Homepage = "https://github.com/bpodlipnik/mirror-url"
58
+ Repository = "https://github.com/bpodlipnik/mirror-url"
59
+ Issues = "https://github.com/bpodlipnik/mirror-url/issues"
60
+
61
+ # Console entry point: the `mirror-url` command runs mirror_url.cli:main.
62
+ [project.scripts]
63
+ mirror-url = "mirror_url.cli:main"
64
+
65
+ [tool.setuptools]
66
+ package-dir = { "" = "src" }
67
+
68
+ [tool.setuptools.packages.find]
69
+ where = ["src"]
70
+
71
+ # ---------------------------------------------------------------------------
72
+ # Tooling configuration
73
+ # ---------------------------------------------------------------------------
74
+ [tool.black]
75
+ line-length = 100
76
+ target-version = ["py39", "py310", "py311", "py312"]
77
+
78
+ [tool.ruff]
79
+ line-length = 100
80
+ target-version = "py39"
81
+ src = ["src", "tests"]
82
+ # The legacy monolith is a frozen reference (and read-only in some checkouts):
83
+ # exclude it from BOTH linting and formatting. `per-file-ignores` below only
84
+ # affects lint, so this top-level exclude is what keeps `ruff format` from
85
+ # trying to rewrite it.
86
+ extend-exclude = ["mirror_url.py"]
87
+
88
+ [tool.ruff.lint]
89
+ # Correctness-focused rule set. UP (pyupgrade) and SIM are intentionally
90
+ # omitted: this package is a verbatim port of working code that supports
91
+ # Python 3.9 with classic typing (Dict/Optional), and we don't want to churn
92
+ # ~350 lines of audited logic to modernize syntax or rewrite control flow.
93
+ # Bump requires-python to >=3.10 and re-enable UP if/when 3.9 is dropped.
94
+ select = ["E", "F", "W", "I", "B", "C4"]
95
+ ignore = [
96
+ "E501", # line length is handled by the formatter
97
+ "B008", # function call in argument defaults (intentional in a few places)
98
+ # The following bugbear rules fire only on code carried over verbatim from
99
+ # the original single-file script; they are deliberately preserved here so
100
+ # the port stays behavior-identical. Revisit during the optional core/
101
+ # mixin refactor (see REFACTORING_PLAN.md §4.1).
102
+ "B904", # raise ... from err — only affects traceback chaining, not control flow
103
+ "B007", # unused loop control variable
104
+ "B019", # lru_cache on a method (MirrorURL._parse_url_cached): a real latent
105
+ # leak inherited from the monolith — preserved, not silently rewritten
106
+ ]
107
+
108
+ [tool.ruff.lint.per-file-ignores]
109
+ "tests/*" = ["B"]
110
+ # The legacy monolith is excluded from lint (frozen reference, pending deletion).
111
+ "mirror_url.py" = ["ALL"]
112
+
113
+ [tool.mypy]
114
+ # Advisory, lenient type-checking. This package is a verbatim port of working,
115
+ # largely-untyped code, so mypy is run as a signal (CI uses continue-on-error),
116
+ # not a gate. The settings below surface genuine type mismatches without
117
+ # demanding annotations on every function or descending into untyped bodies.
118
+ # Tightening (disallow_untyped_defs, check_untyped_defs, strict) is a good
119
+ # incremental follow-up, ideally alongside the core/ mixin refactor.
120
+ python_version = "3.9"
121
+ files = ["src/mirror_url"]
122
+ ignore_missing_imports = true # optional deps (stringzilla, lxml, tqdm, psutil) have no stubs
123
+ follow_imports = "silent"
124
+ disallow_untyped_defs = false
125
+ check_untyped_defs = false
126
+ # The original code predates strict implicit-Optional enforcement and relies on
127
+ # `param: T = None` in a few signatures. Restore the permissive behavior rather
128
+ # than churn the verbatim port; tighten alongside a dedicated typing pass.
129
+ no_implicit_optional = false
130
+ warn_unused_ignores = false
131
+ warn_redundant_casts = true
132
+ warn_unreachable = false
133
+ # The legacy monolith is not part of the package and is not type-checked.
134
+ exclude = ["mirror_url\\.py$", "tests/"]
135
+
136
+ [tool.pytest.ini_options]
137
+ minversion = "7.0"
138
+ testpaths = ["tests"]
139
+ asyncio_mode = "auto"
140
+ addopts = "-ra --strict-markers"
141
+ markers = [
142
+ "integration: end-to-end tests that exercise real I/O (deselect with -m 'not integration')",
143
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,48 @@
1
+ """MirrorURL — enterprise-grade remote directory mirroring tool.
2
+
3
+ This package is the modular successor to the single-file ``mirror_url.py``
4
+ script. During the refactor the monolith remains the runnable source of truth;
5
+ the submodules here are being populated incrementally (see
6
+ ``REFACTORING_PLAN.md``).
7
+
8
+ Public API (intended, once migration completes)::
9
+
10
+ from mirror_url import MirrorURL, MirrorConfig, main
11
+
12
+ The re-exports below are commented out until the corresponding modules are
13
+ populated, so that ``import mirror_url`` succeeds at every step of the migration.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from ._version import __author__, __version__
19
+
20
+ # --- Public API --------------------------------------------------------------
21
+ from .cli import main
22
+ from .config import MirrorConfig, load_config_from_args
23
+ from .core import MirrorURL
24
+ from .exceptions import (
25
+ ConfigError,
26
+ DownloadError,
27
+ MirrorConnectionError,
28
+ MirrorError,
29
+ PathTraversalError,
30
+ SecurityError,
31
+ URLScopeError,
32
+ )
33
+
34
+ __all__ = [
35
+ "__version__",
36
+ "__author__",
37
+ "MirrorURL",
38
+ "MirrorConfig",
39
+ "load_config_from_args",
40
+ "main",
41
+ "MirrorError",
42
+ "MirrorConnectionError",
43
+ "PathTraversalError",
44
+ "URLScopeError",
45
+ "ConfigError",
46
+ "SecurityError",
47
+ "DownloadError",
48
+ ]
@@ -0,0 +1,21 @@
1
+ """Enable ``python -m mirror_url``.
2
+
3
+ Delegates to the CLI entry point once ``cli`` is populated.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+
9
+ def _run() -> None:
10
+ try:
11
+ from .cli import main
12
+ except ImportError as exc: # pragma: no cover - pre-migration guard
13
+ raise SystemExit(
14
+ "mirror_url.cli is not populated yet. During the refactor, run the "
15
+ "original script directly: `python mirror_url.py ...`"
16
+ ) from exc
17
+ main()
18
+
19
+
20
+ if __name__ == "__main__":
21
+ _run()
@@ -0,0 +1,9 @@
1
+ """Private implementation subpackage for the ``MirrorURL`` orchestrator.
2
+
3
+ ``MirrorURL`` is composed from the mixins in this package (one responsibility
4
+ per module) by ``mirror_url.core``. Import the public class from there:
5
+
6
+ from mirror_url.core import MirrorURL # or: from mirror_url import MirrorURL
7
+
8
+ See ``REFACTORING_PLAN.md`` §4.1 for the split rationale.
9
+ """