path-link 0.2.0__py3-none-any.whl
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.
- path_link-0.2.0.dist-info/METADATA +643 -0
- path_link-0.2.0.dist-info/RECORD +20 -0
- path_link-0.2.0.dist-info/WHEEL +5 -0
- path_link-0.2.0.dist-info/entry_points.txt +2 -0
- path_link-0.2.0.dist-info/licenses/LICENSE +23 -0
- path_link-0.2.0.dist-info/top_level.txt +1 -0
- project_paths/__init__.py +165 -0
- project_paths/builder.py +84 -0
- project_paths/builtin_validators/__init__.py +6 -0
- project_paths/builtin_validators/sandbox.py +159 -0
- project_paths/builtin_validators/strict.py +126 -0
- project_paths/cli.py +201 -0
- project_paths/docs/ai_guidelines.md +668 -0
- project_paths/docs/developer_guide.md +399 -0
- project_paths/docs/metadata.json +119 -0
- project_paths/get_paths.py +104 -0
- project_paths/main.py +2 -0
- project_paths/model.py +76 -0
- project_paths/project_paths_static.py +14 -0
- project_paths/validation.py +94 -0
@@ -0,0 +1,643 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: path-link
|
3
|
+
Version: 0.2.0
|
4
|
+
Summary: Type-safe path and URL configuration for Python projects with validation, static models, and IDE autocompletion. Currently supports local paths, URL support coming in v0.3.0.
|
5
|
+
Author-email: Lasse Tammilehto <lasse@jaahdytyspalvelu.fi>
|
6
|
+
License: MIT
|
7
|
+
Project-URL: Homepage, http://jaahdytyspalvelu.fi
|
8
|
+
Project-URL: Documentation, https://github.com/jaahdytyspalvelu/path-link#readme
|
9
|
+
Project-URL: Issue Tracker, https://github.com/jaahdytyspalvelu/path-link/issues
|
10
|
+
Project-URL: AI Guidelines, https://github.com/jaahdytyspalvelu/path-link/blob/main/assistant_context.md
|
11
|
+
Project-URL: Developer Guide, https://github.com/jaahdytyspalvelu/path-link/blob/main/CLAUDE.md
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
13
|
+
Classifier: Intended Audience :: Developers
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
19
|
+
Classifier: Topic :: Utilities
|
20
|
+
Classifier: Typing :: Typed
|
21
|
+
Requires-Python: >=3.11
|
22
|
+
Description-Content-Type: text/markdown
|
23
|
+
License-File: LICENSE
|
24
|
+
Requires-Dist: pydantic>=2.11.0
|
25
|
+
Requires-Dist: python-dotenv>=1.0.1
|
26
|
+
Provides-Extra: test
|
27
|
+
Requires-Dist: pytest>=8.4.2; extra == "test"
|
28
|
+
Requires-Dist: pytest-cov>=7.0.0; extra == "test"
|
29
|
+
Provides-Extra: dev
|
30
|
+
Requires-Dist: mypy>=1.18.2; extra == "dev"
|
31
|
+
Requires-Dist: ruff>=0.8.0; extra == "dev"
|
32
|
+
Dynamic: license-file
|
33
|
+
|
34
|
+
# path-link
|
35
|
+
|
36
|
+
Type-safe path and URL configuration for Python projects with validation, static models, and IDE autocompletion.
|
37
|
+
|
38
|
+
**Current:** Local path management ✅
|
39
|
+
**Coming in v0.3.0:** URL support (API endpoints, external resources)
|
40
|
+
|
41
|
+
## 🚀 Features
|
42
|
+
|
43
|
+
- **Dynamic Path Management**: Load paths from `pyproject.toml` or custom `.paths` files
|
44
|
+
- **Type-Safe Static Models**: Generate static dataclasses for IDE autocomplete and type checking
|
45
|
+
- **Extensible Validation**: Protocol-based validator system with built-in and custom validators
|
46
|
+
- **Cross-Platform**: Works on Linux, Windows, and macOS
|
47
|
+
- **Zero Runtime Dependencies**: Only requires `pydantic` and `python-dotenv`
|
48
|
+
- **Developer Friendly**: Full type hints, comprehensive testing, and clear error messages
|
49
|
+
|
50
|
+
## 📦 Installation
|
51
|
+
|
52
|
+
### Using pip
|
53
|
+
```bash
|
54
|
+
pip install path-link
|
55
|
+
```
|
56
|
+
|
57
|
+
### Using uv (recommended)
|
58
|
+
```bash
|
59
|
+
uv add path-link
|
60
|
+
```
|
61
|
+
|
62
|
+
### From source
|
63
|
+
```bash
|
64
|
+
git clone https://github.com/jaahdytyspalvelu/path-link.git
|
65
|
+
cd path-link
|
66
|
+
uv sync
|
67
|
+
```
|
68
|
+
|
69
|
+
## 🎯 Quick Start
|
70
|
+
|
71
|
+
### Basic Usage
|
72
|
+
|
73
|
+
```python
|
74
|
+
from project_paths import ProjectPaths
|
75
|
+
|
76
|
+
# Load paths from pyproject.toml
|
77
|
+
paths = ProjectPaths.from_pyproject()
|
78
|
+
|
79
|
+
# Access paths
|
80
|
+
print(paths.base_dir) # Project root directory
|
81
|
+
print(paths.config) # config directory path
|
82
|
+
print(paths.icons) # icons directory path
|
83
|
+
|
84
|
+
# Dictionary-style access
|
85
|
+
config_path = paths["config"]
|
86
|
+
|
87
|
+
# Get all paths as dictionary
|
88
|
+
all_paths = paths.to_dict()
|
89
|
+
```
|
90
|
+
|
91
|
+
### Configuration in pyproject.toml
|
92
|
+
|
93
|
+
```toml
|
94
|
+
[tool.project_paths.paths]
|
95
|
+
config = "config"
|
96
|
+
icons = "icons"
|
97
|
+
data = "data"
|
98
|
+
cache = ".cache"
|
99
|
+
logs = "logs"
|
100
|
+
|
101
|
+
[tool.project_paths.files]
|
102
|
+
settings = "config/settings.json"
|
103
|
+
database = "data/app.db"
|
104
|
+
```
|
105
|
+
|
106
|
+
### Using Custom Configuration Files
|
107
|
+
|
108
|
+
```python
|
109
|
+
# Load from custom .paths file
|
110
|
+
paths = ProjectPaths.from_config(".paths")
|
111
|
+
|
112
|
+
# Load from specific location
|
113
|
+
paths = ProjectPaths.from_config("configs/my.paths")
|
114
|
+
```
|
115
|
+
|
116
|
+
### Environment Variable Expansion
|
117
|
+
|
118
|
+
Path configurations support environment variable expansion and home directory expansion (`~`). This is useful for creating portable configurations that adapt to different environments.
|
119
|
+
|
120
|
+
```python
|
121
|
+
# .paths file
|
122
|
+
# data_dir = ${DATA_ROOT}/files
|
123
|
+
# cache_dir = ~/my_app/cache
|
124
|
+
# config = ${APP_CONFIG:-/etc/myapp}
|
125
|
+
|
126
|
+
# Environment variables are expanded automatically
|
127
|
+
import os
|
128
|
+
os.environ["DATA_ROOT"] = "/custom/data"
|
129
|
+
|
130
|
+
paths = ProjectPaths.from_config(".paths")
|
131
|
+
print(paths.data_dir) # /custom/data/files
|
132
|
+
print(paths.cache_dir) # /home/username/my_app/cache
|
133
|
+
```
|
134
|
+
|
135
|
+
**Supported patterns:**
|
136
|
+
- `${VAR}` - Expands to environment variable value (empty string if undefined)
|
137
|
+
- `$VAR` - Alternative syntax for environment variables
|
138
|
+
- `~` - Expands to user's home directory
|
139
|
+
- `~/path` - Expands to path under user's home directory
|
140
|
+
|
141
|
+
**Example `.paths` file:**
|
142
|
+
```bash
|
143
|
+
# Production paths
|
144
|
+
data_dir = ${DATA_ROOT}/app_data
|
145
|
+
logs_dir = ${LOG_DIR:-/var/log/myapp}
|
146
|
+
cache_dir = /tmp/${USER}_cache
|
147
|
+
|
148
|
+
# User-specific paths
|
149
|
+
config_dir = ~/.config/myapp
|
150
|
+
```
|
151
|
+
|
152
|
+
**Example `pyproject.toml`:**
|
153
|
+
```toml
|
154
|
+
[tool.project_paths.paths]
|
155
|
+
data_dir = "${DATA_ROOT}/files"
|
156
|
+
config_dir = "~/.config/myapp"
|
157
|
+
```
|
158
|
+
|
159
|
+
## 🖥️ Command Line Interface
|
160
|
+
|
161
|
+
ptool-serena includes a `ptool` CLI for quick operations without writing Python code.
|
162
|
+
|
163
|
+
### Available Commands
|
164
|
+
|
165
|
+
```bash
|
166
|
+
# Print all configured paths as JSON
|
167
|
+
ptool print
|
168
|
+
|
169
|
+
# Validate project structure
|
170
|
+
ptool validate
|
171
|
+
|
172
|
+
# Generate static dataclass model
|
173
|
+
ptool gen-static
|
174
|
+
|
175
|
+
# Show help
|
176
|
+
ptool --help
|
177
|
+
```
|
178
|
+
|
179
|
+
### Command Reference
|
180
|
+
|
181
|
+
#### `ptool print` - Display Paths
|
182
|
+
|
183
|
+
Prints all configured paths as formatted JSON.
|
184
|
+
|
185
|
+
```bash
|
186
|
+
# Print from pyproject.toml (default)
|
187
|
+
ptool print
|
188
|
+
|
189
|
+
# Print from custom .paths file
|
190
|
+
ptool print --source config --config my.paths
|
191
|
+
|
192
|
+
# Output example:
|
193
|
+
# {
|
194
|
+
# "base_dir": "/home/user/project",
|
195
|
+
# "config_dir": "/home/user/project/config",
|
196
|
+
# "data_dir": "/home/user/project/data",
|
197
|
+
# ...
|
198
|
+
# }
|
199
|
+
```
|
200
|
+
|
201
|
+
**Options:**
|
202
|
+
- `--source {pyproject,config}` - Configuration source (default: pyproject)
|
203
|
+
- `--config PATH` - Path to .paths file (default: .paths)
|
204
|
+
|
205
|
+
#### `ptool validate` - Validate Paths
|
206
|
+
|
207
|
+
Validates that your project structure matches the configuration.
|
208
|
+
|
209
|
+
```bash
|
210
|
+
# Basic validation (check paths can be loaded)
|
211
|
+
ptool validate
|
212
|
+
|
213
|
+
# Strict validation (check paths exist, no symlinks)
|
214
|
+
ptool validate --strict
|
215
|
+
|
216
|
+
# Raise exception on validation failure
|
217
|
+
ptool validate --strict --raise
|
218
|
+
|
219
|
+
# Validate from custom config
|
220
|
+
ptool validate --source config --config production.paths
|
221
|
+
```
|
222
|
+
|
223
|
+
**Options:**
|
224
|
+
- `--source {pyproject,config}` - Configuration source (default: pyproject)
|
225
|
+
- `--config PATH` - Path to .paths file (default: .paths)
|
226
|
+
- `--strict` - Enable strict validation (paths must exist, correct types)
|
227
|
+
- `--raise` - Raise exception on validation failure (for CI/scripts)
|
228
|
+
|
229
|
+
**Exit codes:**
|
230
|
+
- `0` - Validation passed
|
231
|
+
- `1` - Validation failed or error occurred
|
232
|
+
|
233
|
+
#### `ptool gen-static` - Generate Static Model
|
234
|
+
|
235
|
+
Generates a static dataclass for IDE autocomplete and type checking.
|
236
|
+
|
237
|
+
```bash
|
238
|
+
# Generate at default location (src/project_paths/project_paths_static.py)
|
239
|
+
ptool gen-static
|
240
|
+
|
241
|
+
# Generate at custom location
|
242
|
+
ptool gen-static --out custom/path/static_paths.py
|
243
|
+
```
|
244
|
+
|
245
|
+
**Options:**
|
246
|
+
- `--out PATH` - Output path for static model
|
247
|
+
|
248
|
+
**When to use:** After modifying `[tool.project_paths]` in `pyproject.toml` to keep static model in sync.
|
249
|
+
|
250
|
+
### CLI Usage Examples
|
251
|
+
|
252
|
+
**Quick project validation:**
|
253
|
+
```bash
|
254
|
+
cd your-project/
|
255
|
+
ptool validate --strict
|
256
|
+
# ✅ All paths valid (strict mode)
|
257
|
+
```
|
258
|
+
|
259
|
+
**View all configured paths:**
|
260
|
+
```bash
|
261
|
+
ptool print
|
262
|
+
# Outputs JSON with all resolved paths
|
263
|
+
```
|
264
|
+
|
265
|
+
**Generate static model for IDE support:**
|
266
|
+
```bash
|
267
|
+
ptool gen-static
|
268
|
+
# ✅ Static model generated successfully
|
269
|
+
```
|
270
|
+
|
271
|
+
**CI/CD integration:**
|
272
|
+
```bash
|
273
|
+
# In your CI script
|
274
|
+
ptool validate --strict --raise || exit 1
|
275
|
+
```
|
276
|
+
|
277
|
+
**Multiple environments:**
|
278
|
+
```bash
|
279
|
+
# Development
|
280
|
+
ptool validate --source config --config .paths.dev
|
281
|
+
|
282
|
+
# Production
|
283
|
+
ptool validate --source config --config .paths.prod
|
284
|
+
```
|
285
|
+
|
286
|
+
### With Validation
|
287
|
+
|
288
|
+
You can validate your project's structure by using one of the built-in validators.
|
289
|
+
|
290
|
+
```python
|
291
|
+
from project_paths import ProjectPaths, validate_or_raise, PathValidationError
|
292
|
+
from project_paths.builtin_validators import StrictPathValidator
|
293
|
+
|
294
|
+
# 1. Load your paths
|
295
|
+
paths = ProjectPaths.from_pyproject()
|
296
|
+
|
297
|
+
# 2. Configure a validator
|
298
|
+
# This example ensures a 'config' directory and a 'database' file exist.
|
299
|
+
validator = StrictPathValidator(
|
300
|
+
required=["config", "database"],
|
301
|
+
must_be_dir=["config"],
|
302
|
+
must_be_file=["database"]
|
303
|
+
)
|
304
|
+
|
305
|
+
# 3. Validate and raise an exception on failure
|
306
|
+
try:
|
307
|
+
validate_or_raise(paths, validator)
|
308
|
+
print("✅ Project structure is valid.")
|
309
|
+
except PathValidationError as e:
|
310
|
+
print(f"❌ Invalid project structure:\n{e}")
|
311
|
+
|
312
|
+
# Or, to handle results manually without raising an exception:
|
313
|
+
result = validator.validate(paths)
|
314
|
+
if not result.ok():
|
315
|
+
for error in result.errors():
|
316
|
+
print(f"Error: {error.message} (Code: {error.code})")
|
317
|
+
```
|
318
|
+
|
319
|
+
### Security: Sandbox Validation
|
320
|
+
|
321
|
+
The `SandboxPathValidator` prevents path traversal attacks by ensuring all paths stay within your project's base directory. This is crucial for applications that handle user input or load paths from external sources.
|
322
|
+
|
323
|
+
```python
|
324
|
+
from project_paths import ProjectPaths
|
325
|
+
from project_paths.builtin_validators import SandboxPathValidator
|
326
|
+
|
327
|
+
paths = ProjectPaths.from_pyproject()
|
328
|
+
|
329
|
+
# Create sandbox validator with security settings
|
330
|
+
validator = SandboxPathValidator(
|
331
|
+
base_dir_key="base_dir", # Key representing the base directory
|
332
|
+
allow_absolute=False, # Block absolute paths (recommended)
|
333
|
+
strict_mode=True, # Block '..' patterns (recommended)
|
334
|
+
check_paths=[] # Empty = check all paths
|
335
|
+
)
|
336
|
+
|
337
|
+
result = validator.validate(paths)
|
338
|
+
if not result.ok():
|
339
|
+
for error in result.errors():
|
340
|
+
print(f"🔒 Security issue: {error.message}")
|
341
|
+
print(f" Field: {error.field}, Code: {error.code}")
|
342
|
+
```
|
343
|
+
|
344
|
+
**Security Features:**
|
345
|
+
|
346
|
+
- **Path Traversal Protection**: Detects and blocks `..` patterns in strict mode
|
347
|
+
- **Absolute Path Control**: Can block or allow absolute paths
|
348
|
+
- **Sandbox Verification**: Ensures resolved paths stay within base directory
|
349
|
+
- **Symlink Resolution**: Properly resolves symlinks before validation
|
350
|
+
|
351
|
+
**Error Codes:**
|
352
|
+
|
353
|
+
- `PATH_TRAVERSAL_ATTEMPT`: Path contains `..` pattern (strict mode)
|
354
|
+
- `ABSOLUTE_PATH_BLOCKED`: Absolute path not allowed
|
355
|
+
- `PATH_ESCAPES_SANDBOX`: Path resolves outside base directory
|
356
|
+
- `SANDBOX_BASE_MISSING`: Base directory key not found
|
357
|
+
- `SANDBOX_BASE_UNRESOLVABLE`: Cannot resolve base directory
|
358
|
+
- `PATH_UNRESOLVABLE`: Cannot resolve path (warning)
|
359
|
+
|
360
|
+
**Example Use Cases:**
|
361
|
+
|
362
|
+
```python
|
363
|
+
# 1. Maximum security - block everything suspicious
|
364
|
+
strict_sandbox = SandboxPathValidator(
|
365
|
+
allow_absolute=False,
|
366
|
+
strict_mode=True
|
367
|
+
)
|
368
|
+
|
369
|
+
# 2. Allow absolute paths within sandbox
|
370
|
+
permissive_sandbox = SandboxPathValidator(
|
371
|
+
allow_absolute=True,
|
372
|
+
strict_mode=False
|
373
|
+
)
|
374
|
+
|
375
|
+
# 3. Check specific paths only
|
376
|
+
targeted_sandbox = SandboxPathValidator(
|
377
|
+
check_paths=["user_uploads", "temp_files"],
|
378
|
+
strict_mode=True
|
379
|
+
)
|
380
|
+
```
|
381
|
+
|
382
|
+
## 🛠️ Advanced Features
|
383
|
+
|
384
|
+
### Static Model Generation
|
385
|
+
|
386
|
+
Generate a static dataclass for better IDE support:
|
387
|
+
|
388
|
+
```python
|
389
|
+
from project_paths import write_dataclass_file
|
390
|
+
|
391
|
+
# Generate src/project_paths/project_paths_static.py
|
392
|
+
write_dataclass_file()
|
393
|
+
```
|
394
|
+
|
395
|
+
This creates a fully typed dataclass that can be imported:
|
396
|
+
|
397
|
+
```python
|
398
|
+
from project_paths.project_paths_static import ProjectPathsStatic
|
399
|
+
|
400
|
+
paths = ProjectPathsStatic()
|
401
|
+
# Now you get full IDE autocomplete!
|
402
|
+
```
|
403
|
+
|
404
|
+
### Custom Validators
|
405
|
+
|
406
|
+
Create your own validators by creating a class with a `validate` method that returns a `ValidationResult`.
|
407
|
+
|
408
|
+
```python
|
409
|
+
from dataclasses import dataclass
|
410
|
+
from project_paths import Finding, Severity, ValidationResult, ProjectPaths
|
411
|
+
|
412
|
+
@dataclass
|
413
|
+
class MyCustomValidator:
|
414
|
+
"""A custom validator to check for a specific file."""
|
415
|
+
required_file: str
|
416
|
+
|
417
|
+
def validate(self, paths: ProjectPaths) -> ValidationResult:
|
418
|
+
result = ValidationResult()
|
419
|
+
# Assume 'config_dir' is a defined path in your ProjectPaths
|
420
|
+
config_path = paths.to_dict().get("config_dir")
|
421
|
+
|
422
|
+
if not config_path or not (config_path / self.required_file).exists():
|
423
|
+
result.add(Finding(
|
424
|
+
severity=Severity.ERROR,
|
425
|
+
code="CUSTOM_FILE_MISSING",
|
426
|
+
field="config_dir",
|
427
|
+
message=f"Required file '{self.required_file}' not found in config directory."
|
428
|
+
))
|
429
|
+
return result
|
430
|
+
|
431
|
+
# Use the custom validator
|
432
|
+
paths = ProjectPaths.from_pyproject()
|
433
|
+
custom_validator = MyCustomValidator(required_file="user_settings.json")
|
434
|
+
validation_result = custom_validator.validate(paths)
|
435
|
+
|
436
|
+
if not validation_result.ok():
|
437
|
+
print("Custom validation failed!")
|
438
|
+
```
|
439
|
+
|
440
|
+
### Composite Validators
|
441
|
+
|
442
|
+
Combine multiple validators to run them as a single pipeline.
|
443
|
+
|
444
|
+
```python
|
445
|
+
# Assuming MyCustomValidator is defined as in the previous example
|
446
|
+
from project_paths.builtin_validators import CompositeValidator, StrictPathValidator
|
447
|
+
|
448
|
+
# 1. Load paths
|
449
|
+
paths = ProjectPaths.from_pyproject()
|
450
|
+
|
451
|
+
# 2. Configure validators
|
452
|
+
strict_check = StrictPathValidator(required=["config_dir"])
|
453
|
+
custom_check = MyCustomValidator(required_file="user_settings.json")
|
454
|
+
|
455
|
+
# 3. Combine them
|
456
|
+
composite_validator = CompositeValidator(parts=[strict_check, custom_check])
|
457
|
+
|
458
|
+
# 4. Run all checks at once
|
459
|
+
final_result = composite_validator.validate(paths)
|
460
|
+
|
461
|
+
if not final_result.ok():
|
462
|
+
print("Composite validation failed!")
|
463
|
+
for error in final_result.errors():
|
464
|
+
print(f"- {error.message}")
|
465
|
+
```
|
466
|
+
|
467
|
+
### Programmatic Documentation Access
|
468
|
+
|
469
|
+
The package includes bundled documentation that can be accessed programmatically, even in offline or airgapped environments. This is especially useful for AI assistants helping users with the package.
|
470
|
+
|
471
|
+
```python
|
472
|
+
from project_paths import get_ai_guidelines, get_developer_guide, get_metadata
|
473
|
+
import json
|
474
|
+
|
475
|
+
# Get AI assistant guidelines (comprehensive usage patterns and best practices)
|
476
|
+
ai_docs = get_ai_guidelines()
|
477
|
+
print(f"AI Guidelines: {len(ai_docs)} characters")
|
478
|
+
|
479
|
+
# Get developer guide (architecture, development setup, contribution guidelines)
|
480
|
+
dev_docs = get_developer_guide()
|
481
|
+
print(f"Developer Guide: {len(dev_docs)} characters")
|
482
|
+
|
483
|
+
# Get machine-readable metadata (version, APIs, validators, CLI commands)
|
484
|
+
metadata_json = get_metadata()
|
485
|
+
metadata = json.loads(metadata_json)
|
486
|
+
print(f"Version: {metadata['version']}")
|
487
|
+
print(f"Public APIs: {metadata['public_api']}")
|
488
|
+
```
|
489
|
+
|
490
|
+
**Use Cases:**
|
491
|
+
- **AI Assistants**: Provide context to AI agents helping users with the package
|
492
|
+
- **Offline Environments**: Access documentation without internet connection
|
493
|
+
- **Enterprise/Airgapped**: Full documentation in restricted environments
|
494
|
+
- **Automation**: Build tools that need package metadata programmatically
|
495
|
+
|
496
|
+
**Available Functions:**
|
497
|
+
- `get_ai_guidelines()` → Comprehensive AI assistant usage guide
|
498
|
+
- `get_developer_guide()` → Architecture and development documentation
|
499
|
+
- `get_metadata()` → Machine-readable project metadata (JSON)
|
500
|
+
|
501
|
+
## 📁 Project Structure
|
502
|
+
|
503
|
+
```
|
504
|
+
project_root/
|
505
|
+
├── pyproject.toml # Configuration file
|
506
|
+
├── src/
|
507
|
+
│ └── project_paths/ # Main package
|
508
|
+
│ ├── model.py # Core ProjectPaths class
|
509
|
+
│ ├── factory.py # Factory functions
|
510
|
+
│ ├── validators.py # Built-in validators
|
511
|
+
│ └── ...
|
512
|
+
└── tests/ # Test suite
|
513
|
+
```
|
514
|
+
|
515
|
+
## 🧪 Testing
|
516
|
+
|
517
|
+
Run the test suite:
|
518
|
+
|
519
|
+
```bash
|
520
|
+
# Run all tests
|
521
|
+
uv run pytest
|
522
|
+
|
523
|
+
# With coverage
|
524
|
+
uv run pytest --cov=src --cov-report=term-missing
|
525
|
+
|
526
|
+
# Run specific test
|
527
|
+
uv run pytest tests/test_validators.py
|
528
|
+
```
|
529
|
+
|
530
|
+
## 🔧 Development
|
531
|
+
|
532
|
+
### Setup Development Environment
|
533
|
+
|
534
|
+
```bash
|
535
|
+
# Clone the repository
|
536
|
+
git clone https://github.com/yourusername/ptool-serena.git
|
537
|
+
cd ptool-serena
|
538
|
+
|
539
|
+
# Install with uv
|
540
|
+
uv sync
|
541
|
+
|
542
|
+
# Run tests
|
543
|
+
uv run pytest
|
544
|
+
|
545
|
+
# Format code
|
546
|
+
uv run ruff format .
|
547
|
+
|
548
|
+
# Lint
|
549
|
+
uv run ruff check .
|
550
|
+
|
551
|
+
# Type check
|
552
|
+
uv run mypy src/
|
553
|
+
```
|
554
|
+
|
555
|
+
### Code Quality Standards
|
556
|
+
|
557
|
+
This project follows strict quality standards defined in `CLAUDE.md`:
|
558
|
+
|
559
|
+
- **Minimal Compliance**: For prototypes and quick fixes
|
560
|
+
- **Standard Compliance**: For production code (80% test coverage)
|
561
|
+
- **Strict Compliance**: For critical systems (90% test coverage)
|
562
|
+
|
563
|
+
## 📚 API Reference
|
564
|
+
|
565
|
+
### ProjectPaths
|
566
|
+
|
567
|
+
Main class for path management.
|
568
|
+
|
569
|
+
#### Methods
|
570
|
+
|
571
|
+
- `from_config(config_path: str | Path) -> ProjectPaths`: Load from custom config
|
572
|
+
- `to_dict() -> dict[str, Path]`: Get all paths as dictionary
|
573
|
+
- `get_paths() -> dict[str, Path]`: Get only Path fields
|
574
|
+
|
575
|
+
### Factory Functions
|
576
|
+
|
577
|
+
- `create_project_paths(validator=None, raise_on_error=False)`: Create with validation
|
578
|
+
|
579
|
+
### Documentation Functions
|
580
|
+
|
581
|
+
- `get_ai_guidelines() -> str`: Return AI assistant guidelines for working with this package
|
582
|
+
- `get_developer_guide() -> str`: Return developer guide for contributing to this package
|
583
|
+
- `get_metadata() -> str`: Return machine-readable project metadata (JSON)
|
584
|
+
|
585
|
+
### Validators
|
586
|
+
|
587
|
+
#### Built-in Validators
|
588
|
+
|
589
|
+
- `StrictPathValidator`: Ensures all paths exist and match expected types (file/directory)
|
590
|
+
- `SandboxPathValidator`: Prevents path traversal attacks and enforces base directory sandbox
|
591
|
+
- `CompositeValidator`: Combines multiple validators into a single validation pipeline
|
592
|
+
|
593
|
+
#### Validator Protocol
|
594
|
+
|
595
|
+
```python
|
596
|
+
class PathValidatorProtocol(Protocol):
|
597
|
+
def validate(self, paths: Any) -> None: ...
|
598
|
+
def add_error(self, message: str) -> None: ...
|
599
|
+
def add_warning(self, message: str) -> None: ...
|
600
|
+
def add_info(self, key: str, value: Any) -> None: ...
|
601
|
+
@property
|
602
|
+
def has_errors(self) -> bool: ...
|
603
|
+
def clear(self) -> None: ...
|
604
|
+
```
|
605
|
+
|
606
|
+
## 🤝 Contributing
|
607
|
+
|
608
|
+
Contributions are welcome! Please read our contributing guidelines and follow the code style defined in `CLAUDE.md`.
|
609
|
+
|
610
|
+
1. Fork the repository
|
611
|
+
2. Create a feature branch
|
612
|
+
3. Make your changes
|
613
|
+
4. Run tests and linting
|
614
|
+
5. Submit a pull request
|
615
|
+
|
616
|
+
## 📄 License
|
617
|
+
|
618
|
+
MIT License - see LICENSE file for details.
|
619
|
+
|
620
|
+
## 🔗 Links
|
621
|
+
|
622
|
+
- [Documentation](https://github.com/yourusername/ptool-serena/docs)
|
623
|
+
- [Issue Tracker](https://github.com/yourusername/ptool-serena/issues)
|
624
|
+
- [Changelog](CHANGELOG.md)
|
625
|
+
|
626
|
+
## 💡 Examples
|
627
|
+
|
628
|
+
Check out the `tests/examples/` directory for more usage examples:
|
629
|
+
|
630
|
+
- Basic configuration loading
|
631
|
+
- Custom validator implementation
|
632
|
+
- Static model generation
|
633
|
+
- Integration with existing projects
|
634
|
+
|
635
|
+
## 🛟 Support
|
636
|
+
|
637
|
+
- Open an issue for bug reports
|
638
|
+
- Start a discussion for feature requests
|
639
|
+
- Check existing issues before creating new ones
|
640
|
+
|
641
|
+
---
|
642
|
+
|
643
|
+
Made with ❤️ for Python developers who value type safety and clean configuration management.
|
@@ -0,0 +1,20 @@
|
|
1
|
+
path_link-0.2.0.dist-info/licenses/LICENSE,sha256=aA7G9nVFO_aZED5c8AfjAIlwvLH09zkdwmYefc070r4,1158
|
2
|
+
project_paths/__init__.py,sha256=1zVkmr-8iQGJ71HMHMJhPw9bkode5pFTtH0g4_K2IW0,5103
|
3
|
+
project_paths/builder.py,sha256=yMFNDg51MG4jHIDTKcMzzcN5YU2wLBtB5crYkq0jhWU,2675
|
4
|
+
project_paths/cli.py,sha256=0K_2nQZOE2uFMmbcNmA1VEv13oB-YV_ad36Qy9Z1dAw,6644
|
5
|
+
project_paths/get_paths.py,sha256=U_hnGKxa14-om1RLUbKpkoTgp9-hgguVLJkbGc8_h40,4270
|
6
|
+
project_paths/main.py,sha256=HxvBm4gr44u42HBfhwLOP1w4ZKGKGj9Ke_-4uQ-31QY,70
|
7
|
+
project_paths/model.py,sha256=4qrm72Fh0NRuid3i3X0G_tT_lOz06PM5vQxYyi85R9o,2812
|
8
|
+
project_paths/project_paths_static.py,sha256=0K-Vi2RIrHHJJ56N3C6CCTEYUHzzcHnGx-FTEuHUKuE,558
|
9
|
+
project_paths/validation.py,sha256=JBKu2-NmU_x5jomLFrXy0sT87SiL9w1CpvWGq0QvOhc,2674
|
10
|
+
project_paths/builtin_validators/__init__.py,sha256=2fvsBGxrpo5YHI8D5aDFtb73PuXg86gzw23Um_rQf_A,201
|
11
|
+
project_paths/builtin_validators/sandbox.py,sha256=7rki6esWVVLhOIt7xmfyCWNzUxqX81qxzBBcrZra7FY,5601
|
12
|
+
project_paths/builtin_validators/strict.py,sha256=mKLjjn5Y_HEfL_aLL8_ZlC4r_hZMS4MfMGKrR2BYJCs,4082
|
13
|
+
project_paths/docs/ai_guidelines.md,sha256=fUVd7h2ChO5YJ3zPUoQ5DLNcSEpKAHVwSSTYoIj8K1M,19802
|
14
|
+
project_paths/docs/developer_guide.md,sha256=e-s-8kMHEiApZurwc6Gvc6P1SIe1crfOf00-hZyjndU,12361
|
15
|
+
project_paths/docs/metadata.json,sha256=Pgo1Xa8dDOItJaYLP16UTztFd-1ensI3tIRc5c4-8qA,4233
|
16
|
+
path_link-0.2.0.dist-info/METADATA,sha256=uYoiksSeA6Xq4kpRyDFgBoJXMmhYdiE5hygQvLbkCF0,18065
|
17
|
+
path_link-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
18
|
+
path_link-0.2.0.dist-info/entry_points.txt,sha256=-9RmhjQTx5GtiJ2YLyUWRIaLlHQperuSrniLiq8yT2M,49
|
19
|
+
path_link-0.2.0.dist-info/top_level.txt,sha256=iW2KR0fh0Zp23tT_drLikfiZ1Imr5tJpCdZKmg42dA4,14
|
20
|
+
path_link-0.2.0.dist-info/RECORD,,
|
@@ -0,0 +1,23 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Lasse Tammilehto and AI contributors
|
4
|
+
Organization: Jäähdytyspalvelu
|
5
|
+
URL: http://jaahdytyspalvely.fi
|
6
|
+
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
9
|
+
in the Software without restriction, including without limitation the rights
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
12
|
+
furnished to do so, subject to the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
15
|
+
copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
SOFTWARE.
|
@@ -0,0 +1 @@
|
|
1
|
+
project_paths
|