fraiseql-uuid 0.1.1__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.
- fraiseql_uuid-0.1.1/.gitignore +67 -0
- fraiseql_uuid-0.1.1/PKG-INFO +235 -0
- fraiseql_uuid-0.1.1/README.md +209 -0
- fraiseql_uuid-0.1.1/pyproject.toml +50 -0
- fraiseql_uuid-0.1.1/src/fraiseql_uuid/__init__.py +22 -0
- fraiseql_uuid-0.1.1/src/fraiseql_uuid/cache.py +37 -0
- fraiseql_uuid-0.1.1/src/fraiseql_uuid/cli/__init__.py +1 -0
- fraiseql_uuid-0.1.1/src/fraiseql_uuid/cli/main.py +124 -0
- fraiseql_uuid-0.1.1/src/fraiseql_uuid/decoder.py +26 -0
- fraiseql_uuid-0.1.1/src/fraiseql_uuid/generator.py +45 -0
- fraiseql_uuid-0.1.1/src/fraiseql_uuid/patterns/__init__.py +7 -0
- fraiseql_uuid-0.1.1/src/fraiseql_uuid/patterns/base.py +61 -0
- fraiseql_uuid-0.1.1/src/fraiseql_uuid/patterns/pattern.py +113 -0
- fraiseql_uuid-0.1.1/src/fraiseql_uuid/validator.py +47 -0
- fraiseql_uuid-0.1.1/tests/__init__.py +1 -0
- fraiseql_uuid-0.1.1/tests/integration/__init__.py +1 -0
- fraiseql_uuid-0.1.1/tests/integration/test_pattern_workflow.py +382 -0
- fraiseql_uuid-0.1.1/tests/unit/__init__.py +1 -0
- fraiseql_uuid-0.1.1/tests/unit/patterns/__init__.py +1 -0
- fraiseql_uuid-0.1.1/tests/unit/patterns/test_pattern.py +285 -0
- fraiseql_uuid-0.1.1/tests/unit/test_cache.py +227 -0
- fraiseql_uuid-0.1.1/tests/unit/test_decoder.py +268 -0
- fraiseql_uuid-0.1.1/tests/unit/test_generator.py +279 -0
- fraiseql_uuid-0.1.1/tests/unit/test_validator.py +281 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
MANIFEST
|
|
23
|
+
|
|
24
|
+
# Virtual environments
|
|
25
|
+
.env
|
|
26
|
+
.venv
|
|
27
|
+
env/
|
|
28
|
+
venv/
|
|
29
|
+
ENV/
|
|
30
|
+
env.bak/
|
|
31
|
+
venv.bak/
|
|
32
|
+
|
|
33
|
+
# IDEs
|
|
34
|
+
.vscode/
|
|
35
|
+
.idea/
|
|
36
|
+
*.swp
|
|
37
|
+
*.swo
|
|
38
|
+
*~
|
|
39
|
+
|
|
40
|
+
# Testing
|
|
41
|
+
.pytest_cache/
|
|
42
|
+
.coverage
|
|
43
|
+
htmlcov/
|
|
44
|
+
.tox/
|
|
45
|
+
.nox/
|
|
46
|
+
|
|
47
|
+
# Type checking
|
|
48
|
+
.mypy_cache/
|
|
49
|
+
.dmypy.json
|
|
50
|
+
dmypy.json
|
|
51
|
+
.pyre/
|
|
52
|
+
.pytype/
|
|
53
|
+
.ty_cache/
|
|
54
|
+
|
|
55
|
+
# Linting
|
|
56
|
+
.ruff_cache/
|
|
57
|
+
|
|
58
|
+
# uv
|
|
59
|
+
# uv.lock is committed for reproducible installs
|
|
60
|
+
|
|
61
|
+
# Development planning
|
|
62
|
+
.phases/
|
|
63
|
+
|
|
64
|
+
# OS
|
|
65
|
+
.DS_Store
|
|
66
|
+
Thumbs.db
|
|
67
|
+
node_modules/
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fraiseql-uuid
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Structured UUID pattern library with encode/decode support
|
|
5
|
+
Project-URL: Homepage, https://github.com/fraiseql/fraiseql-seed
|
|
6
|
+
Project-URL: Documentation, https://fraiseql-seed.readthedocs.io
|
|
7
|
+
Project-URL: Repository, https://github.com/fraiseql/fraiseql-seed
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/fraiseql/fraiseql-seed/issues
|
|
9
|
+
Author-email: Lionel Hamayon <lionel.hamayon@evolution-digitale.fr>
|
|
10
|
+
License: MIT
|
|
11
|
+
Keywords: database,encoding,pattern,testing,uuid
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Database
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: pydantic>=2.5.0
|
|
21
|
+
Requires-Dist: pyyaml>=6.0
|
|
22
|
+
Provides-Extra: cli
|
|
23
|
+
Requires-Dist: click>=8.1.0; extra == 'cli'
|
|
24
|
+
Requires-Dist: rich>=13.7.0; extra == 'cli'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# fraiseql-uuid
|
|
28
|
+
|
|
29
|
+
UUID v4 compliant pattern with encoded metadata for the FraiseQL ecosystem.
|
|
30
|
+
|
|
31
|
+
[](https://github.com/fraiseql/fraiseql-seed/actions/workflows/quality-gate.yml)
|
|
32
|
+
[](https://codecov.io/gh/fraiseql/fraiseql-seed?flag=fraiseql-uuid)
|
|
33
|
+
[](https://www.python.org/downloads/)
|
|
34
|
+
[](https://opensource.org/licenses/MIT)
|
|
35
|
+
|
|
36
|
+
**Status**: ✅ v0.1.0 Production-Ready | 🔒 Type-Safe (ty strict) | 📋 SBOM Available
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install fraiseql-uuid
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from fraiseql_uuid import Pattern, UUIDGenerator
|
|
48
|
+
|
|
49
|
+
# Create pattern
|
|
50
|
+
pattern = Pattern()
|
|
51
|
+
|
|
52
|
+
# Generate UUID
|
|
53
|
+
gen = UUIDGenerator(pattern, table_code="012345")
|
|
54
|
+
uuid = gen.generate(instance=1)
|
|
55
|
+
print(uuid) # → "01234521-0000-4000-8000-000000000001"
|
|
56
|
+
|
|
57
|
+
# Decode UUID
|
|
58
|
+
decoded = pattern.decode(uuid)
|
|
59
|
+
print(decoded["table_code"]) # → "012345"
|
|
60
|
+
print(decoded["instance"]) # → 1
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## UUID Format
|
|
64
|
+
|
|
65
|
+
**Code notation:** `{table:6}{type:2}-{func:4}-4{scen:3}-8{scen:1}{test:2}-{inst:12}`
|
|
66
|
+
**Docs notation:** `TTTTTTDD-FFFF-4SSS-8STT-IIIIIIIIIIII`
|
|
67
|
+
|
|
68
|
+
### Components
|
|
69
|
+
|
|
70
|
+
| Symbol | Component | Length | Default | Description |
|
|
71
|
+
|--------|-----------|--------|---------|-------------|
|
|
72
|
+
| T | table_code | 6 | - | Table/Entity code (required) |
|
|
73
|
+
| D | seed_dir | 2 | 21 | Seed directory (21=general, 22=mutation, 23=query) |
|
|
74
|
+
| F | function | 4 | 0 | Function code |
|
|
75
|
+
| 4 | version | 1 | 4 | UUID v4 version bit (fixed) |
|
|
76
|
+
| S | scenario | 4 | 0 | Test scenario (split 3+1 for v4 compliance) |
|
|
77
|
+
| 8 | variant | 1 | 8 | UUID variant bit (fixed) |
|
|
78
|
+
| T | test_case | 2 | 0 | Test case number |
|
|
79
|
+
| I | instance | 12 | - | Instance number (required) |
|
|
80
|
+
|
|
81
|
+
### Example
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
01234521-0042-4100-8015-000000000001
|
|
85
|
+
│ │ │ │ │ │ │ │ └─ instance: 1
|
|
86
|
+
│ │ │ │ │ │ └─── test_case: 15
|
|
87
|
+
│ │ │ │ │ └───── scenario: 1000 (split as 100 + 0)
|
|
88
|
+
│ │ │ │ └──────── variant: 8
|
|
89
|
+
│ │ │ └─────────── version: 4
|
|
90
|
+
│ │ └────────────── function: 42
|
|
91
|
+
│ └──────────────── table: 012345
|
|
92
|
+
└─────────────────────── seed_dir: 21
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Usage Examples
|
|
96
|
+
|
|
97
|
+
### Basic Generation
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from fraiseql_uuid import Pattern
|
|
101
|
+
|
|
102
|
+
pattern = Pattern()
|
|
103
|
+
|
|
104
|
+
# Minimal - uses defaults
|
|
105
|
+
uuid = pattern.generate(table_code="012345", instance=1)
|
|
106
|
+
# → "01234521-0000-4000-8000-000000000001"
|
|
107
|
+
|
|
108
|
+
# Full parameters
|
|
109
|
+
uuid = pattern.generate(
|
|
110
|
+
table_code="123456",
|
|
111
|
+
seed_dir=22, # mutation tests
|
|
112
|
+
function=42,
|
|
113
|
+
scenario=1000,
|
|
114
|
+
test_case=5,
|
|
115
|
+
instance=999
|
|
116
|
+
)
|
|
117
|
+
# → "12345622-0042-4100-8005-000000000999"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Batch Generation
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from fraiseql_uuid import Pattern, UUIDGenerator
|
|
124
|
+
|
|
125
|
+
pattern = Pattern()
|
|
126
|
+
gen = UUIDGenerator(pattern, table_code="012345", scenario=1000)
|
|
127
|
+
|
|
128
|
+
# Generate batch
|
|
129
|
+
uuids = gen.generate_batch(count=5)
|
|
130
|
+
# → ["01234521-0000-4100-8000-000000000001",
|
|
131
|
+
# "01234521-0000-4100-8000-000000000002",
|
|
132
|
+
# ...]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Decoding
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from fraiseql_uuid import Pattern
|
|
139
|
+
|
|
140
|
+
pattern = Pattern()
|
|
141
|
+
decoded = pattern.decode("01234521-0042-4100-8015-000000000001")
|
|
142
|
+
|
|
143
|
+
print(decoded["table_code"]) # → "012345"
|
|
144
|
+
print(decoded["seed_dir"]) # → 21
|
|
145
|
+
print(decoded["function"]) # → 42
|
|
146
|
+
print(decoded["scenario"]) # → 1000
|
|
147
|
+
print(decoded["test_case"]) # → 15
|
|
148
|
+
print(decoded["instance"]) # → 1
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Validation
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from fraiseql_uuid import Pattern, UUIDValidator
|
|
155
|
+
|
|
156
|
+
pattern = Pattern()
|
|
157
|
+
validator = UUIDValidator(pattern)
|
|
158
|
+
|
|
159
|
+
result = validator.validate("01234521-0000-4000-8000-000000000001")
|
|
160
|
+
print(result.valid) # → True
|
|
161
|
+
|
|
162
|
+
result = validator.validate("not-a-uuid")
|
|
163
|
+
print(result.valid) # → False
|
|
164
|
+
print(result.error) # → "Invalid UUID format: not-a-uuid"
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Caching
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
from fraiseql_uuid import UUIDCache
|
|
171
|
+
|
|
172
|
+
cache = UUIDCache()
|
|
173
|
+
|
|
174
|
+
# Store generated UUIDs
|
|
175
|
+
cache.set("users", instance=1, uuid="01234521-0000-4000-8000-000000000001")
|
|
176
|
+
cache.set("users", instance=2, uuid="01234521-0000-4000-8000-000000000002")
|
|
177
|
+
|
|
178
|
+
# Retrieve from cache
|
|
179
|
+
uuid = cache.get("users", instance=1)
|
|
180
|
+
print(uuid) # → "01234521-0000-4000-8000-000000000001"
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## CLI Usage
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# Generate UUID
|
|
187
|
+
fraiseql-uuid generate --table 012345 --instance 1
|
|
188
|
+
|
|
189
|
+
# Generate batch
|
|
190
|
+
fraiseql-uuid generate --table 012345 --count 10
|
|
191
|
+
|
|
192
|
+
# Decode UUID
|
|
193
|
+
fraiseql-uuid decode 01234521-0000-4000-8000-000000000001
|
|
194
|
+
|
|
195
|
+
# Validate UUID
|
|
196
|
+
fraiseql-uuid validate 01234521-0000-4000-8000-000000000001
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## UUID v4 Compliance
|
|
200
|
+
|
|
201
|
+
All generated UUIDs are **UUID v4 compliant**:
|
|
202
|
+
- Version bit `4` in the correct position
|
|
203
|
+
- Variant bit `8` in the correct position
|
|
204
|
+
- Can be used anywhere standard UUIDs are expected
|
|
205
|
+
- Compatible with database UUID columns
|
|
206
|
+
- Parseable by standard UUID libraries
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
import uuid
|
|
210
|
+
|
|
211
|
+
# Works with standard UUID library
|
|
212
|
+
generated = pattern.generate(table_code="012345", instance=1)
|
|
213
|
+
parsed = uuid.UUID(generated)
|
|
214
|
+
print(parsed.version) # → 4
|
|
215
|
+
print(parsed.variant) # → uuid.RFC_4122
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Development
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
# Install for development
|
|
222
|
+
git clone https://github.com/fraiseql/fraiseql-seed
|
|
223
|
+
cd fraiseql-seed
|
|
224
|
+
uv sync
|
|
225
|
+
|
|
226
|
+
# Run tests
|
|
227
|
+
uv run pytest packages/fraiseql-uuid/tests -v
|
|
228
|
+
|
|
229
|
+
# Type check
|
|
230
|
+
uv run ty check packages/fraiseql-uuid/src
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## License
|
|
234
|
+
|
|
235
|
+
MIT
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# fraiseql-uuid
|
|
2
|
+
|
|
3
|
+
UUID v4 compliant pattern with encoded metadata for the FraiseQL ecosystem.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/fraiseql/fraiseql-seed/actions/workflows/quality-gate.yml)
|
|
6
|
+
[](https://codecov.io/gh/fraiseql/fraiseql-seed?flag=fraiseql-uuid)
|
|
7
|
+
[](https://www.python.org/downloads/)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
|
|
10
|
+
**Status**: ✅ v0.1.0 Production-Ready | 🔒 Type-Safe (ty strict) | 📋 SBOM Available
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install fraiseql-uuid
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
from fraiseql_uuid import Pattern, UUIDGenerator
|
|
22
|
+
|
|
23
|
+
# Create pattern
|
|
24
|
+
pattern = Pattern()
|
|
25
|
+
|
|
26
|
+
# Generate UUID
|
|
27
|
+
gen = UUIDGenerator(pattern, table_code="012345")
|
|
28
|
+
uuid = gen.generate(instance=1)
|
|
29
|
+
print(uuid) # → "01234521-0000-4000-8000-000000000001"
|
|
30
|
+
|
|
31
|
+
# Decode UUID
|
|
32
|
+
decoded = pattern.decode(uuid)
|
|
33
|
+
print(decoded["table_code"]) # → "012345"
|
|
34
|
+
print(decoded["instance"]) # → 1
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## UUID Format
|
|
38
|
+
|
|
39
|
+
**Code notation:** `{table:6}{type:2}-{func:4}-4{scen:3}-8{scen:1}{test:2}-{inst:12}`
|
|
40
|
+
**Docs notation:** `TTTTTTDD-FFFF-4SSS-8STT-IIIIIIIIIIII`
|
|
41
|
+
|
|
42
|
+
### Components
|
|
43
|
+
|
|
44
|
+
| Symbol | Component | Length | Default | Description |
|
|
45
|
+
|--------|-----------|--------|---------|-------------|
|
|
46
|
+
| T | table_code | 6 | - | Table/Entity code (required) |
|
|
47
|
+
| D | seed_dir | 2 | 21 | Seed directory (21=general, 22=mutation, 23=query) |
|
|
48
|
+
| F | function | 4 | 0 | Function code |
|
|
49
|
+
| 4 | version | 1 | 4 | UUID v4 version bit (fixed) |
|
|
50
|
+
| S | scenario | 4 | 0 | Test scenario (split 3+1 for v4 compliance) |
|
|
51
|
+
| 8 | variant | 1 | 8 | UUID variant bit (fixed) |
|
|
52
|
+
| T | test_case | 2 | 0 | Test case number |
|
|
53
|
+
| I | instance | 12 | - | Instance number (required) |
|
|
54
|
+
|
|
55
|
+
### Example
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
01234521-0042-4100-8015-000000000001
|
|
59
|
+
│ │ │ │ │ │ │ │ └─ instance: 1
|
|
60
|
+
│ │ │ │ │ │ └─── test_case: 15
|
|
61
|
+
│ │ │ │ │ └───── scenario: 1000 (split as 100 + 0)
|
|
62
|
+
│ │ │ │ └──────── variant: 8
|
|
63
|
+
│ │ │ └─────────── version: 4
|
|
64
|
+
│ │ └────────────── function: 42
|
|
65
|
+
│ └──────────────── table: 012345
|
|
66
|
+
└─────────────────────── seed_dir: 21
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Usage Examples
|
|
70
|
+
|
|
71
|
+
### Basic Generation
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from fraiseql_uuid import Pattern
|
|
75
|
+
|
|
76
|
+
pattern = Pattern()
|
|
77
|
+
|
|
78
|
+
# Minimal - uses defaults
|
|
79
|
+
uuid = pattern.generate(table_code="012345", instance=1)
|
|
80
|
+
# → "01234521-0000-4000-8000-000000000001"
|
|
81
|
+
|
|
82
|
+
# Full parameters
|
|
83
|
+
uuid = pattern.generate(
|
|
84
|
+
table_code="123456",
|
|
85
|
+
seed_dir=22, # mutation tests
|
|
86
|
+
function=42,
|
|
87
|
+
scenario=1000,
|
|
88
|
+
test_case=5,
|
|
89
|
+
instance=999
|
|
90
|
+
)
|
|
91
|
+
# → "12345622-0042-4100-8005-000000000999"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Batch Generation
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from fraiseql_uuid import Pattern, UUIDGenerator
|
|
98
|
+
|
|
99
|
+
pattern = Pattern()
|
|
100
|
+
gen = UUIDGenerator(pattern, table_code="012345", scenario=1000)
|
|
101
|
+
|
|
102
|
+
# Generate batch
|
|
103
|
+
uuids = gen.generate_batch(count=5)
|
|
104
|
+
# → ["01234521-0000-4100-8000-000000000001",
|
|
105
|
+
# "01234521-0000-4100-8000-000000000002",
|
|
106
|
+
# ...]
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Decoding
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from fraiseql_uuid import Pattern
|
|
113
|
+
|
|
114
|
+
pattern = Pattern()
|
|
115
|
+
decoded = pattern.decode("01234521-0042-4100-8015-000000000001")
|
|
116
|
+
|
|
117
|
+
print(decoded["table_code"]) # → "012345"
|
|
118
|
+
print(decoded["seed_dir"]) # → 21
|
|
119
|
+
print(decoded["function"]) # → 42
|
|
120
|
+
print(decoded["scenario"]) # → 1000
|
|
121
|
+
print(decoded["test_case"]) # → 15
|
|
122
|
+
print(decoded["instance"]) # → 1
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Validation
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
from fraiseql_uuid import Pattern, UUIDValidator
|
|
129
|
+
|
|
130
|
+
pattern = Pattern()
|
|
131
|
+
validator = UUIDValidator(pattern)
|
|
132
|
+
|
|
133
|
+
result = validator.validate("01234521-0000-4000-8000-000000000001")
|
|
134
|
+
print(result.valid) # → True
|
|
135
|
+
|
|
136
|
+
result = validator.validate("not-a-uuid")
|
|
137
|
+
print(result.valid) # → False
|
|
138
|
+
print(result.error) # → "Invalid UUID format: not-a-uuid"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Caching
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from fraiseql_uuid import UUIDCache
|
|
145
|
+
|
|
146
|
+
cache = UUIDCache()
|
|
147
|
+
|
|
148
|
+
# Store generated UUIDs
|
|
149
|
+
cache.set("users", instance=1, uuid="01234521-0000-4000-8000-000000000001")
|
|
150
|
+
cache.set("users", instance=2, uuid="01234521-0000-4000-8000-000000000002")
|
|
151
|
+
|
|
152
|
+
# Retrieve from cache
|
|
153
|
+
uuid = cache.get("users", instance=1)
|
|
154
|
+
print(uuid) # → "01234521-0000-4000-8000-000000000001"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## CLI Usage
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# Generate UUID
|
|
161
|
+
fraiseql-uuid generate --table 012345 --instance 1
|
|
162
|
+
|
|
163
|
+
# Generate batch
|
|
164
|
+
fraiseql-uuid generate --table 012345 --count 10
|
|
165
|
+
|
|
166
|
+
# Decode UUID
|
|
167
|
+
fraiseql-uuid decode 01234521-0000-4000-8000-000000000001
|
|
168
|
+
|
|
169
|
+
# Validate UUID
|
|
170
|
+
fraiseql-uuid validate 01234521-0000-4000-8000-000000000001
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## UUID v4 Compliance
|
|
174
|
+
|
|
175
|
+
All generated UUIDs are **UUID v4 compliant**:
|
|
176
|
+
- Version bit `4` in the correct position
|
|
177
|
+
- Variant bit `8` in the correct position
|
|
178
|
+
- Can be used anywhere standard UUIDs are expected
|
|
179
|
+
- Compatible with database UUID columns
|
|
180
|
+
- Parseable by standard UUID libraries
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
import uuid
|
|
184
|
+
|
|
185
|
+
# Works with standard UUID library
|
|
186
|
+
generated = pattern.generate(table_code="012345", instance=1)
|
|
187
|
+
parsed = uuid.UUID(generated)
|
|
188
|
+
print(parsed.version) # → 4
|
|
189
|
+
print(parsed.variant) # → uuid.RFC_4122
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Development
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Install for development
|
|
196
|
+
git clone https://github.com/fraiseql/fraiseql-seed
|
|
197
|
+
cd fraiseql-seed
|
|
198
|
+
uv sync
|
|
199
|
+
|
|
200
|
+
# Run tests
|
|
201
|
+
uv run pytest packages/fraiseql-uuid/tests -v
|
|
202
|
+
|
|
203
|
+
# Type check
|
|
204
|
+
uv run ty check packages/fraiseql-uuid/src
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
MIT
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# fraiseql-uuid - Structured UUID Pattern Library
|
|
2
|
+
|
|
3
|
+
[project]
|
|
4
|
+
name = "fraiseql-uuid"
|
|
5
|
+
version = "0.1.1"
|
|
6
|
+
description = "Structured UUID pattern library with encode/decode support"
|
|
7
|
+
authors = [
|
|
8
|
+
{name = "Lionel Hamayon", email = "lionel.hamayon@evolution-digitale.fr"}
|
|
9
|
+
]
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
requires-python = ">=3.11"
|
|
13
|
+
keywords = ["uuid", "pattern", "encoding", "database", "testing"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3.11",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
21
|
+
"Topic :: Database",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
# Package dependencies
|
|
25
|
+
dependencies = [
|
|
26
|
+
"pyyaml>=6.0",
|
|
27
|
+
"pydantic>=2.5.0",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
cli = [
|
|
32
|
+
"click>=8.1.0",
|
|
33
|
+
"rich>=13.7.0",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://github.com/fraiseql/fraiseql-seed"
|
|
38
|
+
Documentation = "https://fraiseql-seed.readthedocs.io"
|
|
39
|
+
Repository = "https://github.com/fraiseql/fraiseql-seed"
|
|
40
|
+
"Bug Tracker" = "https://github.com/fraiseql/fraiseql-seed/issues"
|
|
41
|
+
|
|
42
|
+
[project.scripts]
|
|
43
|
+
fraiseql-uuid = "fraiseql_uuid.cli.main:cli [cli]"
|
|
44
|
+
|
|
45
|
+
[build-system]
|
|
46
|
+
requires = ["hatchling"]
|
|
47
|
+
build-backend = "hatchling.build"
|
|
48
|
+
|
|
49
|
+
[tool.hatch.build.targets.wheel]
|
|
50
|
+
packages = ["src/fraiseql_uuid"]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
fraiseql-uuid - Structured UUID Pattern Library
|
|
3
|
+
|
|
4
|
+
UUID v4 compliant pattern encoding/decoding for FraiseQL ecosystem.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from fraiseql_uuid.cache import UUIDCache
|
|
8
|
+
from fraiseql_uuid.decoder import UUIDDecoder
|
|
9
|
+
from fraiseql_uuid.generator import UUIDGenerator
|
|
10
|
+
from fraiseql_uuid.patterns import Pattern
|
|
11
|
+
from fraiseql_uuid.validator import UUIDValidator, ValidationResult
|
|
12
|
+
|
|
13
|
+
__version__ = "0.1.0"
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"Pattern",
|
|
17
|
+
"UUIDCache",
|
|
18
|
+
"UUIDDecoder",
|
|
19
|
+
"UUIDGenerator",
|
|
20
|
+
"UUIDValidator",
|
|
21
|
+
"ValidationResult",
|
|
22
|
+
]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""UUID generation cache for performance."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class UUIDCache:
|
|
5
|
+
"""Cache for generated UUIDs."""
|
|
6
|
+
|
|
7
|
+
def __init__(self) -> None:
|
|
8
|
+
"""Initialize cache."""
|
|
9
|
+
self._cache: dict[str, dict[int, str]] = {}
|
|
10
|
+
|
|
11
|
+
def get(self, table: str, instance: int) -> str | None:
|
|
12
|
+
"""Get cached UUID.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
table: Table name
|
|
16
|
+
instance: Instance number
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
Cached UUID or None
|
|
20
|
+
"""
|
|
21
|
+
return self._cache.get(table, {}).get(instance)
|
|
22
|
+
|
|
23
|
+
def set(self, table: str, instance: int, uuid: str) -> None:
|
|
24
|
+
"""Set cached UUID.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
table: Table name
|
|
28
|
+
instance: Instance number
|
|
29
|
+
uuid: UUID to cache
|
|
30
|
+
"""
|
|
31
|
+
if table not in self._cache:
|
|
32
|
+
self._cache[table] = {}
|
|
33
|
+
self._cache[table][instance] = uuid
|
|
34
|
+
|
|
35
|
+
def clear(self) -> None:
|
|
36
|
+
"""Clear cache."""
|
|
37
|
+
self._cache.clear()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""CLI package for fraiseql-uuid."""
|