unctools 0.2.0__tar.gz → 0.2.2__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 (49) hide show
  1. unctools-0.2.2/PKG-INFO +226 -0
  2. unctools-0.2.2/README.md +177 -0
  3. {unctools-0.2.0 → unctools-0.2.2}/examples/basic_usage.py +16 -26
  4. {unctools-0.2.0 → unctools-0.2.2}/pyproject.toml +5 -1
  5. {unctools-0.2.0 → unctools-0.2.2}/tests/test_detector.py +15 -15
  6. {unctools-0.2.0 → unctools-0.2.2}/tests/test_framework.py +4 -0
  7. {unctools-0.2.0 → unctools-0.2.2}/tests/test_import_stability.py +15 -2
  8. {unctools-0.2.0 → unctools-0.2.2}/tests/test_operations.py +2 -0
  9. {unctools-0.2.0 → unctools-0.2.2}/tests/test_win32net_warning.py +48 -44
  10. {unctools-0.2.0 → unctools-0.2.2}/tests/test_windows_imports.py +4 -6
  11. unctools-0.2.2/tests/test_wnet_enrichment.py +101 -0
  12. {unctools-0.2.0 → unctools-0.2.2}/unctools/__init__.py +1 -1
  13. unctools-0.2.2/unctools/_version.py +92 -0
  14. {unctools-0.2.0 → unctools-0.2.2}/unctools/converter.py +66 -3
  15. unctools-0.2.2/unctools.egg-info/PKG-INFO +226 -0
  16. {unctools-0.2.0 → unctools-0.2.2}/unctools.egg-info/SOURCES.txt +2 -1
  17. unctools-0.2.0/PKG-INFO +0 -189
  18. unctools-0.2.0/README.md +0 -140
  19. unctools-0.2.0/examples/batch_operations.py +0 -302
  20. unctools-0.2.0/unctools.egg-info/PKG-INFO +0 -189
  21. {unctools-0.2.0 → unctools-0.2.2}/LICENSE +0 -0
  22. {unctools-0.2.0 → unctools-0.2.2}/MANIFEST.in +0 -0
  23. {unctools-0.2.0 → unctools-0.2.2}/docs/api-stability.md +0 -0
  24. {unctools-0.2.0 → unctools-0.2.2}/docs/implementation-guide.md +0 -0
  25. {unctools-0.2.0 → unctools-0.2.2}/docs/implementation-summary.md +0 -0
  26. {unctools-0.2.0 → unctools-0.2.2}/docs/integration-guide.md +0 -0
  27. {unctools-0.2.0 → unctools-0.2.2}/examples/windows_zone_fix.py +0 -0
  28. {unctools-0.2.0 → unctools-0.2.2}/setup.cfg +0 -0
  29. {unctools-0.2.0 → unctools-0.2.2}/setup.py +0 -0
  30. {unctools-0.2.0 → unctools-0.2.2}/tests/__init__.py +0 -0
  31. {unctools-0.2.0 → unctools-0.2.2}/tests/basic_functionality_test.py +0 -0
  32. {unctools-0.2.0 → unctools-0.2.2}/tests/conftest.py +0 -0
  33. {unctools-0.2.0 → unctools-0.2.2}/tests/test_converter.py +0 -0
  34. {unctools-0.2.0 → unctools-0.2.2}/tests/test_converter_v2.py +0 -0
  35. {unctools-0.2.0 → unctools-0.2.2}/tests/test_windows.py +0 -0
  36. {unctools-0.2.0 → unctools-0.2.2}/unctools/detector.py +0 -0
  37. {unctools-0.2.0 → unctools-0.2.2}/unctools/operations.py +0 -0
  38. {unctools-0.2.0 → unctools-0.2.2}/unctools/utils/__init__.py +0 -0
  39. {unctools-0.2.0 → unctools-0.2.2}/unctools/utils/compat.py +0 -0
  40. {unctools-0.2.0 → unctools-0.2.2}/unctools/utils/logger.py +0 -0
  41. {unctools-0.2.0 → unctools-0.2.2}/unctools/utils/validation.py +0 -0
  42. {unctools-0.2.0 → unctools-0.2.2}/unctools/windows/__init__.py +0 -0
  43. {unctools-0.2.0 → unctools-0.2.2}/unctools/windows/network.py +0 -0
  44. {unctools-0.2.0 → unctools-0.2.2}/unctools/windows/registry.py +0 -0
  45. {unctools-0.2.0 → unctools-0.2.2}/unctools/windows/security.py +0 -0
  46. {unctools-0.2.0 → unctools-0.2.2}/unctools.egg-info/dependency_links.txt +0 -0
  47. {unctools-0.2.0 → unctools-0.2.2}/unctools.egg-info/not-zip-safe +0 -0
  48. {unctools-0.2.0 → unctools-0.2.2}/unctools.egg-info/requires.txt +0 -0
  49. {unctools-0.2.0 → unctools-0.2.2}/unctools.egg-info/top_level.txt +0 -0
@@ -0,0 +1,226 @@
1
+ Metadata-Version: 2.4
2
+ Name: unctools
3
+ Version: 0.2.2
4
+ Summary: A comprehensive toolkit for handling UNC paths, network drives, and substituted drives
5
+ Home-page: https://github.com/djdacy/unctools
6
+ Author: Dustin Darcy
7
+ Author-email: Dustin Darcy <your.email@example.com>
8
+ License: MIT
9
+ Project-URL: Homepage, https://github.com/djdarcy/unctools
10
+ Project-URL: Bug Reports, https://github.com/djdarcy/unctools/issues
11
+ Project-URL: Source, https://github.com/djdarcy/unctools
12
+ Project-URL: Documentation, https://github.com/djdarcy/unctools#readme
13
+ Keywords: unc,network,windows,path,file,share,subst
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.6
19
+ Classifier: Programming Language :: Python :: 3.7
20
+ Classifier: Programming Language :: Python :: 3.8
21
+ Classifier: Programming Language :: Python :: 3.9
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Operating System :: Microsoft :: Windows
24
+ Classifier: Operating System :: POSIX :: Linux
25
+ Classifier: Operating System :: MacOS :: MacOS X
26
+ Classifier: Topic :: System :: Filesystems
27
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
28
+ Requires-Python: >=3.6
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Requires-Dist: pathlib; python_version < "3.4"
32
+ Provides-Extra: windows
33
+ Requires-Dist: pywin32>=223; extra == "windows"
34
+ Requires-Dist: pypiwin32>=223; extra == "windows"
35
+ Provides-Extra: dev
36
+ Requires-Dist: pytest>=6.0.0; extra == "dev"
37
+ Requires-Dist: pytest-cov>=2.10.0; extra == "dev"
38
+ Requires-Dist: flake8>=3.8.0; extra == "dev"
39
+ Requires-Dist: black>=20.8b1; extra == "dev"
40
+ Requires-Dist: tox>=3.20.0; extra == "dev"
41
+ Provides-Extra: docs
42
+ Requires-Dist: sphinx>=4.0.0; extra == "docs"
43
+ Requires-Dist: sphinx-rtd-theme>=0.5.0; extra == "docs"
44
+ Requires-Dist: myst-parser>=0.15.0; extra == "docs"
45
+ Dynamic: author
46
+ Dynamic: home-page
47
+ Dynamic: license-file
48
+ Dynamic: requires-python
49
+
50
+ # UNCtools
51
+
52
+ [![PyPI](https://img.shields.io/pypi/v/unctools?color=green)](https://pypi.org/project/unctools/)
53
+ [![Release Date](https://img.shields.io/github/release-date/DazzleLib/UNCtools?color=green)](https://github.com/DazzleLib/UNCtools/releases)
54
+ [![Python 3.6+](https://img.shields.io/badge/python-3.6+-blue.svg)](https://www.python.org/downloads/)
55
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
56
+ [![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)](#platform-compatibility)
57
+
58
+ **Windows UNC path handling and network drive utilities: convert between `\\server\share` and mapped drives, classify where paths come from, and probe what's actually reachable.**
59
+
60
+ ## The Problem
61
+
62
+ On Windows, the same file often has two names: the UNC form (`\\server\share\folder\file.txt`) and a mapped-drive form (`Z:\folder\file.txt`). Tools break when handed the one they didn't expect -- network drives disconnect, `subst` drives masquerade as real ones, security zones silently block UNC access, and scripts that worked on one machine fail on another because the drive mappings differ.
63
+
64
+ **UNCtools** answers the identity questions: *is this path UNC / network / subst / local -- and what is its other name?* It converts between path forms using the system's live mappings, classifies path origins, probes accessibility across both name variants, and (on Windows) manages the security zones and drive mappings themselves.
65
+
66
+ > [!NOTE]
67
+ > UNCtools is the **L0 path-identity layer** of the [DazzleLib stack](https://github.com/DazzleLib/.github/blob/main/docs/STACK-MAP.md): it may probe the filesystem read-only to answer identity questions; it never mutates or transfers content (file operations live in [dazzle-filekit](https://github.com/DazzleLib/dazzle-filekit)). The public surface is locked and machine-checked -- see [docs/api-stability.md](docs/api-stability.md).
68
+
69
+ ## Quick Start
70
+
71
+ ```bash
72
+ pip install unctools # or equivalently: dazzle-unctools
73
+ ```
74
+
75
+ ```python
76
+ from unctools import convert_to_local, classify_path_origin
77
+
78
+ local = convert_to_local(r"\\server\share\project") # -> Z:\project (if mapped)
79
+ origin = classify_path_origin(local) # -> "network"
80
+ ```
81
+
82
+ ## Features
83
+
84
+ - **Path conversion**: UNC ↔ mapped-drive translation from the system's live network mappings (win32net with `net use` fallback)
85
+ - **Origin classification**: `classify_path_origin` -- `unc` / `network` / `subst` / `local` / `removable` / `cdrom` / `ramdisk`
86
+ - **Identity probes**: existence and accessibility checks that try *both* name variants of a path
87
+ - **UNC path algebra**: parse and build `\\server\share\rest` components
88
+ - **Issue detection**: MAX_PATH violations, broken mappings, servers missing from the Intranet security zone
89
+ - **Windows management** (optional extra): security zones, share enumeration, drive mapping create/remove
90
+ - **Cross-platform safe**: imports everywhere; Windows-specific features degrade gracefully on Unix
91
+
92
+ ## Installation
93
+
94
+ ```bash
95
+ pip install unctools # standard (or: dazzle-unctools)
96
+ pip install unctools[windows] # + pywin32 for the rich Windows APIs
97
+ ```
98
+
99
+ ```bash
100
+ # Development
101
+ git clone https://github.com/DazzleLib/UNCtools.git
102
+ cd UNCtools
103
+ pip install -e .[dev]
104
+ ```
105
+
106
+ ## Usage
107
+
108
+ ### Basic Path Conversion
109
+
110
+ ```python
111
+ from unctools import convert_to_local, convert_to_unc
112
+
113
+ # Convert UNC path to local drive path
114
+ local_path = convert_to_local("\\\\server\\share\\folder\\file.txt")
115
+ # Result (if mapped): "Z:\\folder\\file.txt"
116
+
117
+ # Convert local drive path back to UNC
118
+ unc_path = convert_to_unc("Z:\\folder\\file.txt")
119
+ # Result: "\\\\server\\share\\folder\\file.txt"
120
+ ```
121
+
122
+ ### Path Detection
123
+
124
+ ```python
125
+ from unctools import is_unc_path, is_network_drive, is_subst_drive, classify_path_origin
126
+
127
+ # Check if a path is a UNC path
128
+ if is_unc_path("\\\\server\\share\\file.txt"):
129
+ print("This is a UNC path")
130
+
131
+ # Check if a drive is a network drive
132
+ if is_network_drive("Z:"):
133
+ print("Z: is a network drive")
134
+
135
+ # Classify WHERE a path comes from
136
+ origin = classify_path_origin("C:\\Users\\")
137
+ # Result: "local", "network", "subst", "unc", etc.
138
+ ```
139
+
140
+ ### Identity Probes & Batch Conversion
141
+
142
+ ```python
143
+ from unctools import file_exists, find_accessible_path, batch_convert
144
+
145
+ # Does the file exist under EITHER of its names (UNC or mapped)?
146
+ if file_exists("\\\\server\\share\\file.txt"):
147
+ print("Reachable under at least one name")
148
+
149
+ # Which name variant actually works right now?
150
+ usable = find_accessible_path("\\\\server\\share\\file.txt")
151
+ # Result: Path("Z:\\file.txt"), Path("\\\\server\\share\\file.txt"), or None
152
+
153
+ # Convert multiple paths at once
154
+ paths = ["\\\\server\\share\\file1.txt", "\\\\server\\share\\file2.txt"]
155
+ converted = batch_convert(paths, to_unc=False)
156
+ ```
157
+
158
+ ### UNC Path Algebra
159
+
160
+ ```python
161
+ from unctools import get_unc_path_elements, build_unc_path
162
+
163
+ server, share, rest = get_unc_path_elements("\\\\server\\share\\folder\\file.txt")
164
+ # Result: ("server", "share", "folder\\file.txt")
165
+
166
+ unc = build_unc_path("server", "share", "folder/file.txt")
167
+ # Result: "\\\\server\\share\\folder/file.txt"
168
+ ```
169
+
170
+ ### Windows Security Zones
171
+
172
+ ```python
173
+ from unctools.windows import fix_security_zone, add_to_intranet_zone
174
+
175
+ # Fix security zone issues for a server
176
+ fix_security_zone("server")
177
+
178
+ # Add a server to the Local Intranet zone
179
+ add_to_intranet_zone("server")
180
+ ```
181
+
182
+ ### Network Drive Management
183
+
184
+ ```python
185
+ from unctools.windows import create_network_mapping, remove_network_mapping
186
+
187
+ # Create a network drive mapping
188
+ success, drive = create_network_mapping("\\\\server\\share", "Z:")
189
+
190
+ # Remove a network drive mapping
191
+ remove_network_mapping("Z:")
192
+ ```
193
+
194
+ ## Platform Compatibility
195
+
196
+ | Platform | Status |
197
+ |----------|--------|
198
+ | Windows | Full functionality: conversion, classification, probes, security zones, drive management |
199
+ | Linux / macOS | Path algebra and syntax checks work; mapping-dependent features degrade gracefully (no-ops / passthrough) |
200
+
201
+ ## Requirements
202
+
203
+ - **Python 3.6+** (3.9-3.13 tested in CI)
204
+ - **pywin32** (optional, via `unctools[windows]`) for the rich Windows APIs -- core features fall back to `net use` parsing without it
205
+
206
+ ## Development
207
+
208
+ ```bash
209
+ python -m pytest tests/ # 50+ tests; includes the api-stability import canary
210
+ black unctools
211
+ flake8 unctools
212
+ ```
213
+
214
+ The public API surface is locked: see **[docs/api-stability.md](docs/api-stability.md)** for the policy, the active deprecation shims (`get_path_type` -> `classify_path_origin`, removed in 0.3.0), and known consumers. Changes follow the [stack's](https://github.com/DazzleLib/.github/blob/main/docs/STACK-MAP.md) noisy-shim deprecation policy -- never silent.
215
+
216
+ ## Contributing
217
+
218
+ Contributions welcome! Please open an issue or submit a pull request.
219
+
220
+ Like the project?
221
+
222
+ [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/djdarcy)
223
+
224
+ ## License
225
+
226
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,177 @@
1
+ # UNCtools
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/unctools?color=green)](https://pypi.org/project/unctools/)
4
+ [![Release Date](https://img.shields.io/github/release-date/DazzleLib/UNCtools?color=green)](https://github.com/DazzleLib/UNCtools/releases)
5
+ [![Python 3.6+](https://img.shields.io/badge/python-3.6+-blue.svg)](https://www.python.org/downloads/)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7
+ [![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)](#platform-compatibility)
8
+
9
+ **Windows UNC path handling and network drive utilities: convert between `\\server\share` and mapped drives, classify where paths come from, and probe what's actually reachable.**
10
+
11
+ ## The Problem
12
+
13
+ On Windows, the same file often has two names: the UNC form (`\\server\share\folder\file.txt`) and a mapped-drive form (`Z:\folder\file.txt`). Tools break when handed the one they didn't expect -- network drives disconnect, `subst` drives masquerade as real ones, security zones silently block UNC access, and scripts that worked on one machine fail on another because the drive mappings differ.
14
+
15
+ **UNCtools** answers the identity questions: *is this path UNC / network / subst / local -- and what is its other name?* It converts between path forms using the system's live mappings, classifies path origins, probes accessibility across both name variants, and (on Windows) manages the security zones and drive mappings themselves.
16
+
17
+ > [!NOTE]
18
+ > UNCtools is the **L0 path-identity layer** of the [DazzleLib stack](https://github.com/DazzleLib/.github/blob/main/docs/STACK-MAP.md): it may probe the filesystem read-only to answer identity questions; it never mutates or transfers content (file operations live in [dazzle-filekit](https://github.com/DazzleLib/dazzle-filekit)). The public surface is locked and machine-checked -- see [docs/api-stability.md](docs/api-stability.md).
19
+
20
+ ## Quick Start
21
+
22
+ ```bash
23
+ pip install unctools # or equivalently: dazzle-unctools
24
+ ```
25
+
26
+ ```python
27
+ from unctools import convert_to_local, classify_path_origin
28
+
29
+ local = convert_to_local(r"\\server\share\project") # -> Z:\project (if mapped)
30
+ origin = classify_path_origin(local) # -> "network"
31
+ ```
32
+
33
+ ## Features
34
+
35
+ - **Path conversion**: UNC ↔ mapped-drive translation from the system's live network mappings (win32net with `net use` fallback)
36
+ - **Origin classification**: `classify_path_origin` -- `unc` / `network` / `subst` / `local` / `removable` / `cdrom` / `ramdisk`
37
+ - **Identity probes**: existence and accessibility checks that try *both* name variants of a path
38
+ - **UNC path algebra**: parse and build `\\server\share\rest` components
39
+ - **Issue detection**: MAX_PATH violations, broken mappings, servers missing from the Intranet security zone
40
+ - **Windows management** (optional extra): security zones, share enumeration, drive mapping create/remove
41
+ - **Cross-platform safe**: imports everywhere; Windows-specific features degrade gracefully on Unix
42
+
43
+ ## Installation
44
+
45
+ ```bash
46
+ pip install unctools # standard (or: dazzle-unctools)
47
+ pip install unctools[windows] # + pywin32 for the rich Windows APIs
48
+ ```
49
+
50
+ ```bash
51
+ # Development
52
+ git clone https://github.com/DazzleLib/UNCtools.git
53
+ cd UNCtools
54
+ pip install -e .[dev]
55
+ ```
56
+
57
+ ## Usage
58
+
59
+ ### Basic Path Conversion
60
+
61
+ ```python
62
+ from unctools import convert_to_local, convert_to_unc
63
+
64
+ # Convert UNC path to local drive path
65
+ local_path = convert_to_local("\\\\server\\share\\folder\\file.txt")
66
+ # Result (if mapped): "Z:\\folder\\file.txt"
67
+
68
+ # Convert local drive path back to UNC
69
+ unc_path = convert_to_unc("Z:\\folder\\file.txt")
70
+ # Result: "\\\\server\\share\\folder\\file.txt"
71
+ ```
72
+
73
+ ### Path Detection
74
+
75
+ ```python
76
+ from unctools import is_unc_path, is_network_drive, is_subst_drive, classify_path_origin
77
+
78
+ # Check if a path is a UNC path
79
+ if is_unc_path("\\\\server\\share\\file.txt"):
80
+ print("This is a UNC path")
81
+
82
+ # Check if a drive is a network drive
83
+ if is_network_drive("Z:"):
84
+ print("Z: is a network drive")
85
+
86
+ # Classify WHERE a path comes from
87
+ origin = classify_path_origin("C:\\Users\\")
88
+ # Result: "local", "network", "subst", "unc", etc.
89
+ ```
90
+
91
+ ### Identity Probes & Batch Conversion
92
+
93
+ ```python
94
+ from unctools import file_exists, find_accessible_path, batch_convert
95
+
96
+ # Does the file exist under EITHER of its names (UNC or mapped)?
97
+ if file_exists("\\\\server\\share\\file.txt"):
98
+ print("Reachable under at least one name")
99
+
100
+ # Which name variant actually works right now?
101
+ usable = find_accessible_path("\\\\server\\share\\file.txt")
102
+ # Result: Path("Z:\\file.txt"), Path("\\\\server\\share\\file.txt"), or None
103
+
104
+ # Convert multiple paths at once
105
+ paths = ["\\\\server\\share\\file1.txt", "\\\\server\\share\\file2.txt"]
106
+ converted = batch_convert(paths, to_unc=False)
107
+ ```
108
+
109
+ ### UNC Path Algebra
110
+
111
+ ```python
112
+ from unctools import get_unc_path_elements, build_unc_path
113
+
114
+ server, share, rest = get_unc_path_elements("\\\\server\\share\\folder\\file.txt")
115
+ # Result: ("server", "share", "folder\\file.txt")
116
+
117
+ unc = build_unc_path("server", "share", "folder/file.txt")
118
+ # Result: "\\\\server\\share\\folder/file.txt"
119
+ ```
120
+
121
+ ### Windows Security Zones
122
+
123
+ ```python
124
+ from unctools.windows import fix_security_zone, add_to_intranet_zone
125
+
126
+ # Fix security zone issues for a server
127
+ fix_security_zone("server")
128
+
129
+ # Add a server to the Local Intranet zone
130
+ add_to_intranet_zone("server")
131
+ ```
132
+
133
+ ### Network Drive Management
134
+
135
+ ```python
136
+ from unctools.windows import create_network_mapping, remove_network_mapping
137
+
138
+ # Create a network drive mapping
139
+ success, drive = create_network_mapping("\\\\server\\share", "Z:")
140
+
141
+ # Remove a network drive mapping
142
+ remove_network_mapping("Z:")
143
+ ```
144
+
145
+ ## Platform Compatibility
146
+
147
+ | Platform | Status |
148
+ |----------|--------|
149
+ | Windows | Full functionality: conversion, classification, probes, security zones, drive management |
150
+ | Linux / macOS | Path algebra and syntax checks work; mapping-dependent features degrade gracefully (no-ops / passthrough) |
151
+
152
+ ## Requirements
153
+
154
+ - **Python 3.6+** (3.9-3.13 tested in CI)
155
+ - **pywin32** (optional, via `unctools[windows]`) for the rich Windows APIs -- core features fall back to `net use` parsing without it
156
+
157
+ ## Development
158
+
159
+ ```bash
160
+ python -m pytest tests/ # 50+ tests; includes the api-stability import canary
161
+ black unctools
162
+ flake8 unctools
163
+ ```
164
+
165
+ The public API surface is locked: see **[docs/api-stability.md](docs/api-stability.md)** for the policy, the active deprecation shims (`get_path_type` -> `classify_path_origin`, removed in 0.3.0), and known consumers. Changes follow the [stack's](https://github.com/DazzleLib/.github/blob/main/docs/STACK-MAP.md) noisy-shim deprecation policy -- never silent.
166
+
167
+ ## Contributing
168
+
169
+ Contributions welcome! Please open an issue or submit a pull request.
170
+
171
+ Like the project?
172
+
173
+ [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/djdarcy)
174
+
175
+ ## License
176
+
177
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -17,9 +17,9 @@ logging.basicConfig(level=logging.INFO,
17
17
  # Import UNCtools
18
18
  import unctools
19
19
  from unctools import (
20
- convert_to_local, convert_to_unc, normalize_path,
21
- is_unc_path, is_network_drive, is_subst_drive, get_path_type,
22
- safe_open, safe_copy, batch_convert, process_files
20
+ convert_to_local, convert_to_unc,
21
+ is_unc_path, is_network_drive, is_subst_drive, classify_path_origin,
22
+ file_exists, find_accessible_path, batch_convert
23
23
  )
24
24
 
25
25
  def print_section(title):
@@ -43,7 +43,8 @@ def demonstrate_path_conversion():
43
43
  # Show network mappings if on Windows
44
44
  if os.name == 'nt':
45
45
  print("\nNetwork Mappings:")
46
- mappings = unctools.get_mappings()
46
+ from unctools.converter import get_mappings
47
+ mappings = get_mappings()
47
48
  for unc, drive in mappings.items():
48
49
  print(f" {unc} -> {drive}")
49
50
 
@@ -52,10 +53,11 @@ def demonstrate_path_conversion():
52
53
  print(f" UNC -> Local: {unc_path} -> {convert_to_local(unc_path)}")
53
54
  print(f" Local -> UNC: {local_path} -> {convert_to_unc(local_path)}")
54
55
 
55
- # Normalize paths
56
- print("\nPath Normalization:")
57
- print(f" Normalize (prefer local): {normalize_path(unc_path, prefer_unc=False)}")
58
- print(f" Normalize (prefer UNC): {normalize_path(local_path, prefer_unc=True)}")
56
+ # Round-trip explicitly (normalize_path was removed in 0.2.0 -- the
57
+ # explicit converts ARE the API)
58
+ print("\nExplicit round-trip:")
59
+ print(f" To local: {convert_to_local(unc_path)}")
60
+ print(f" To UNC: {convert_to_unc(local_path)}")
59
61
 
60
62
  def demonstrate_path_detection():
61
63
  """Demonstrate path detection functionality."""
@@ -72,7 +74,7 @@ def demonstrate_path_detection():
72
74
 
73
75
  print("Path Type Detection:")
74
76
  for path in paths:
75
- path_type = get_path_type(path)
77
+ path_type = classify_path_origin(path)
76
78
  is_unc = is_unc_path(path)
77
79
  print(f" {path}:")
78
80
  print(f" Type: {path_type}")
@@ -112,14 +114,11 @@ def demonstrate_file_operations():
112
114
  with open(temp_file, "w") as f:
113
115
  f.write("Hello, UNCtools!")
114
116
 
115
- # Safe open
116
- print("\nSafe Open:")
117
- try:
118
- with safe_open(temp_file, "r") as f:
119
- content = f.read()
120
- print(f" Content: {content}")
121
- except Exception as e:
122
- print(f" Error: {e}")
117
+ # Identity probes (safe_open was removed in 0.2.0 -- I/O lives in
118
+ # dazzle-filekit; unctools answers identity questions)
119
+ print("\nIdentity probes:")
120
+ print(f" file_exists: {file_exists(temp_file)}")
121
+ print(f" accessible variant: {find_accessible_path(temp_file)}")
123
122
 
124
123
  # Batch operations
125
124
  print("\nBatch Operations:")
@@ -129,15 +128,6 @@ def demonstrate_file_operations():
129
128
  with open(os.path.join(temp_dir, f"temp_file_{i}.txt"), "w") as f:
130
129
  f.write(f"Test file {i}")
131
130
 
132
- # Process files
133
- print(" Processing files:")
134
- def process_callback(path):
135
- return path.stat().st_size
136
-
137
- results = process_files(temp_dir, process_callback, pattern="temp_file*.txt")
138
- for path, size in results.items():
139
- print(f" {path}: {size} bytes")
140
-
141
131
  # Batch convert
142
132
  print("\n Batch conversion:")
143
133
  paths = [os.path.join(temp_dir, f"temp_file_{i}.txt") for i in range(3)]
@@ -63,7 +63,11 @@ include = ["unctools*"]
63
63
  exclude = ["tests*"]
64
64
 
65
65
  [tool.setuptools.dynamic]
66
- version = {attr = "unctools.__version__"}
66
+ version = {attr = "unctools._version.PIP_VERSION"}
67
+
68
+ [tool.repokit-common]
69
+ version-source = "unctools/_version.py"
70
+ repo-url = "https://github.com/DazzleLib/UNCtools"
67
71
 
68
72
  [tool.setuptools.package-data]
69
73
  unctools = ["py.typed"]
@@ -26,7 +26,7 @@ from tests.test_framework import (
26
26
  import unctools
27
27
  from unctools.detector import (
28
28
  is_unc_path, is_network_drive, is_subst_drive,
29
- get_path_type, detect_path_issues, get_network_mappings,
29
+ classify_path_origin, detect_path_issues, get_network_mappings,
30
30
  get_subst_target, get_network_target, is_server_in_intranet_zone,
31
31
  PATH_TYPE_UNC, PATH_TYPE_NETWORK, PATH_TYPE_SUBST,
32
32
  PATH_TYPE_LOCAL, PATH_TYPE_UNKNOWN, PATH_TYPE_REMOVABLE,
@@ -177,8 +177,8 @@ def test_get_network_target():
177
177
  assert_is_none(get_network_target("Q:"),
178
178
  "Non-existent drive should return None")
179
179
 
180
- def test_get_path_type():
181
- """Test get_path_type function."""
180
+ def test_classify_path_origin():
181
+ """Test classify_path_origin function."""
182
182
  # Mock the underlying functions
183
183
  def mock_is_unc_path(path):
184
184
  return str(path).startswith("\\\\") or str(path).startswith("//")
@@ -204,37 +204,37 @@ def test_get_path_type():
204
204
  mock.patch('unctools.detector.get_drive_type', side_effect=mock_get_drive_type):
205
205
 
206
206
  # Test with UNC path
207
- assert_equal(get_path_type(TEST_UNC_PATH), PATH_TYPE_UNC,
207
+ assert_equal(classify_path_origin(TEST_UNC_PATH), PATH_TYPE_UNC,
208
208
  "UNC path should be detected as UNC type")
209
209
 
210
210
  # Test with local path
211
- assert_equal(get_path_type(TEST_LOCAL_PATH), PATH_TYPE_LOCAL,
211
+ assert_equal(classify_path_origin(TEST_LOCAL_PATH), PATH_TYPE_LOCAL,
212
212
  "Local path should be detected as local type")
213
213
 
214
214
  # Test with network drive path
215
- assert_equal(get_path_type(TEST_NETWORK_PATH), PATH_TYPE_NETWORK,
215
+ assert_equal(classify_path_origin(TEST_NETWORK_PATH), PATH_TYPE_NETWORK,
216
216
  "Network drive path should be detected as network type")
217
217
 
218
218
  # Test with subst drive path
219
- assert_equal(get_path_type(TEST_SUBST_PATH), PATH_TYPE_SUBST,
219
+ assert_equal(classify_path_origin(TEST_SUBST_PATH), PATH_TYPE_SUBST,
220
220
  "Subst drive path should be detected as subst type")
221
221
 
222
222
  # Test with removable drive path
223
- assert_equal(get_path_type("E:\\file.txt"), PATH_TYPE_REMOVABLE,
223
+ assert_equal(classify_path_origin("E:\\file.txt"), PATH_TYPE_REMOVABLE,
224
224
  "Removable drive path should be detected as removable type")
225
225
 
226
226
  # Test with CD-ROM drive path
227
- assert_equal(get_path_type("D:\\file.txt"), PATH_TYPE_CDROM,
227
+ assert_equal(classify_path_origin("D:\\file.txt"), PATH_TYPE_CDROM,
228
228
  "CD-ROM drive path should be detected as cdrom type")
229
229
 
230
230
  # Test with RAM disk path
231
- assert_equal(get_path_type("R:\\file.txt"), PATH_TYPE_RAMDISK,
231
+ assert_equal(classify_path_origin("R:\\file.txt"), PATH_TYPE_RAMDISK,
232
232
  "RAM disk path should be detected as ramdisk type")
233
233
 
234
234
  # Test with invalid path
235
- assert_equal(get_path_type(""), PATH_TYPE_UNKNOWN,
235
+ assert_equal(classify_path_origin(""), PATH_TYPE_UNKNOWN,
236
236
  "Empty string should be detected as unknown type")
237
- assert_equal(get_path_type(None), PATH_TYPE_UNKNOWN,
237
+ assert_equal(classify_path_origin(None), PATH_TYPE_UNKNOWN,
238
238
  "None should be detected as unknown type")
239
239
 
240
240
  @pytest.mark.skipif(os.name != 'nt', reason="Windows-specific test - tests security zone functionality")
@@ -244,7 +244,7 @@ def test_detect_path_issues():
244
244
  def mock_is_unc_path(path):
245
245
  return str(path).startswith("\\\\") or str(path).startswith("//")
246
246
 
247
- def mock_get_path_type(path):
247
+ def mock_classify_path_origin(path):
248
248
  if mock_is_unc_path(path):
249
249
  return PATH_TYPE_UNC
250
250
  elif str(path).startswith("Z:"):
@@ -268,7 +268,7 @@ def test_detect_path_issues():
268
268
  return None
269
269
 
270
270
  with mock.patch('unctools.detector.is_unc_path', side_effect=mock_is_unc_path), \
271
- mock.patch('unctools.detector.get_path_type', side_effect=mock_get_path_type), \
271
+ mock.patch('unctools.detector.classify_path_origin', side_effect=mock_classify_path_origin), \
272
272
  mock.patch('unctools.detector.is_server_in_intranet_zone', side_effect=mock_is_server_in_intranet_zone), \
273
273
  mock.patch('unctools.detector.get_network_target', side_effect=mock_get_network_target), \
274
274
  mock.patch('unctools.detector.get_subst_target', side_effect=mock_get_subst_target), \
@@ -373,7 +373,7 @@ def run_tests():
373
373
  suite.add_test(test_is_subst_drive)
374
374
  suite.add_test(test_get_subst_target)
375
375
  suite.add_test(test_get_network_target)
376
- suite.add_test(test_get_path_type)
376
+ suite.add_test(test_classify_path_origin)
377
377
  suite.add_test(test_detect_path_issues)
378
378
  suite.add_test(test_is_server_in_intranet_zone)
379
379
  suite.add_test(test_get_network_mappings)
@@ -16,6 +16,8 @@ logging.basicConfig(level=logging.INFO,
16
16
 
17
17
  class TestResult:
18
18
  """Container for test results."""
19
+
20
+ __test__ = False # custom-runner container, not a pytest test class
19
21
 
20
22
  def __init__(self):
21
23
  self.passed = []
@@ -59,6 +61,8 @@ class TestResult:
59
61
 
60
62
  class TestSuite:
61
63
  """A suite of tests."""
64
+
65
+ __test__ = False # custom standalone runner, not a pytest test class
62
66
 
63
67
  def __init__(self, name: str):
64
68
  self.name = name
@@ -92,6 +92,19 @@ def test_operations_facade_warns_on_import():
92
92
  import unctools.operations # noqa: F401
93
93
 
94
94
 
95
- def test_version_is_0_2_0():
95
+ def test_version_is_wired_and_consistent():
96
+ # Version plumbing is correct WITHOUT pinning a literal version -- a bump
97
+ # (editing MAJOR/MINOR/PATCH in _version.py) never requires touching this
98
+ # test. We assert the constants drive a well-formed base and that every
99
+ # derived value agrees with it. This still catches a DESYNCED __version__
100
+ # (e.g. constants bumped but the autobump hook hasn't regenerated the
101
+ # string), which is the real failure mode worth guarding.
96
102
  import unctools
97
- assert unctools.__version__ == "0.2.0"
103
+ from unctools import _version
104
+ assert isinstance(_version.MAJOR, int)
105
+ assert isinstance(_version.MINOR, int)
106
+ assert isinstance(_version.PATCH, int)
107
+ base = f"{_version.MAJOR}.{_version.MINOR}.{_version.PATCH}"
108
+ assert _version.get_base_version().startswith(base)
109
+ assert _version.PIP_VERSION.startswith(base)
110
+ assert unctools.__version__.startswith(base)
@@ -44,6 +44,8 @@ TEST_LOCAL_PATH = "C:\\Users\\username\\Documents\\file.txt"
44
44
 
45
45
  class TestEnvironment:
46
46
  """Manages a temporary test environment with files."""
47
+
48
+ __test__ = False # fixture helper (see conftest `env`), not a pytest test class
47
49
 
48
50
  def __init__(self):
49
51
  """Initialize the test environment."""