fraiseql-confiture 0.3.4__cp311-cp311-win_amd64.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.
Files changed (119) hide show
  1. confiture/__init__.py +48 -0
  2. confiture/_core.cp311-win_amd64.pyd +0 -0
  3. confiture/cli/__init__.py +0 -0
  4. confiture/cli/dry_run.py +116 -0
  5. confiture/cli/lint_formatter.py +193 -0
  6. confiture/cli/main.py +1656 -0
  7. confiture/config/__init__.py +0 -0
  8. confiture/config/environment.py +263 -0
  9. confiture/core/__init__.py +51 -0
  10. confiture/core/anonymization/__init__.py +0 -0
  11. confiture/core/anonymization/audit.py +485 -0
  12. confiture/core/anonymization/benchmarking.py +372 -0
  13. confiture/core/anonymization/breach_notification.py +652 -0
  14. confiture/core/anonymization/compliance.py +617 -0
  15. confiture/core/anonymization/composer.py +298 -0
  16. confiture/core/anonymization/data_subject_rights.py +669 -0
  17. confiture/core/anonymization/factory.py +319 -0
  18. confiture/core/anonymization/governance.py +737 -0
  19. confiture/core/anonymization/performance.py +1092 -0
  20. confiture/core/anonymization/profile.py +284 -0
  21. confiture/core/anonymization/registry.py +195 -0
  22. confiture/core/anonymization/security/kms_manager.py +547 -0
  23. confiture/core/anonymization/security/lineage.py +888 -0
  24. confiture/core/anonymization/security/token_store.py +686 -0
  25. confiture/core/anonymization/strategies/__init__.py +41 -0
  26. confiture/core/anonymization/strategies/address.py +359 -0
  27. confiture/core/anonymization/strategies/credit_card.py +374 -0
  28. confiture/core/anonymization/strategies/custom.py +161 -0
  29. confiture/core/anonymization/strategies/date.py +218 -0
  30. confiture/core/anonymization/strategies/differential_privacy.py +398 -0
  31. confiture/core/anonymization/strategies/email.py +141 -0
  32. confiture/core/anonymization/strategies/format_preserving_encryption.py +310 -0
  33. confiture/core/anonymization/strategies/hash.py +150 -0
  34. confiture/core/anonymization/strategies/ip_address.py +235 -0
  35. confiture/core/anonymization/strategies/masking_retention.py +252 -0
  36. confiture/core/anonymization/strategies/name.py +298 -0
  37. confiture/core/anonymization/strategies/phone.py +119 -0
  38. confiture/core/anonymization/strategies/preserve.py +85 -0
  39. confiture/core/anonymization/strategies/redact.py +101 -0
  40. confiture/core/anonymization/strategies/salted_hashing.py +322 -0
  41. confiture/core/anonymization/strategies/text_redaction.py +183 -0
  42. confiture/core/anonymization/strategies/tokenization.py +334 -0
  43. confiture/core/anonymization/strategy.py +241 -0
  44. confiture/core/anonymization/syncer_audit.py +357 -0
  45. confiture/core/blue_green.py +683 -0
  46. confiture/core/builder.py +500 -0
  47. confiture/core/checksum.py +358 -0
  48. confiture/core/connection.py +132 -0
  49. confiture/core/differ.py +522 -0
  50. confiture/core/drift.py +564 -0
  51. confiture/core/dry_run.py +182 -0
  52. confiture/core/health.py +313 -0
  53. confiture/core/hooks/__init__.py +87 -0
  54. confiture/core/hooks/base.py +232 -0
  55. confiture/core/hooks/context.py +146 -0
  56. confiture/core/hooks/execution_strategies.py +57 -0
  57. confiture/core/hooks/observability.py +220 -0
  58. confiture/core/hooks/phases.py +53 -0
  59. confiture/core/hooks/registry.py +295 -0
  60. confiture/core/large_tables.py +775 -0
  61. confiture/core/linting/__init__.py +70 -0
  62. confiture/core/linting/composer.py +192 -0
  63. confiture/core/linting/libraries/__init__.py +17 -0
  64. confiture/core/linting/libraries/gdpr.py +168 -0
  65. confiture/core/linting/libraries/general.py +184 -0
  66. confiture/core/linting/libraries/hipaa.py +144 -0
  67. confiture/core/linting/libraries/pci_dss.py +104 -0
  68. confiture/core/linting/libraries/sox.py +120 -0
  69. confiture/core/linting/schema_linter.py +491 -0
  70. confiture/core/linting/versioning.py +151 -0
  71. confiture/core/locking.py +389 -0
  72. confiture/core/migration_generator.py +298 -0
  73. confiture/core/migrator.py +793 -0
  74. confiture/core/observability/__init__.py +44 -0
  75. confiture/core/observability/audit.py +323 -0
  76. confiture/core/observability/logging.py +187 -0
  77. confiture/core/observability/metrics.py +174 -0
  78. confiture/core/observability/tracing.py +192 -0
  79. confiture/core/pg_version.py +418 -0
  80. confiture/core/pool.py +406 -0
  81. confiture/core/risk/__init__.py +39 -0
  82. confiture/core/risk/predictor.py +188 -0
  83. confiture/core/risk/scoring.py +248 -0
  84. confiture/core/rollback_generator.py +388 -0
  85. confiture/core/schema_analyzer.py +769 -0
  86. confiture/core/schema_to_schema.py +590 -0
  87. confiture/core/security/__init__.py +32 -0
  88. confiture/core/security/logging.py +201 -0
  89. confiture/core/security/validation.py +416 -0
  90. confiture/core/signals.py +371 -0
  91. confiture/core/syncer.py +540 -0
  92. confiture/exceptions.py +192 -0
  93. confiture/integrations/__init__.py +0 -0
  94. confiture/models/__init__.py +0 -0
  95. confiture/models/lint.py +193 -0
  96. confiture/models/migration.py +180 -0
  97. confiture/models/schema.py +203 -0
  98. confiture/scenarios/__init__.py +36 -0
  99. confiture/scenarios/compliance.py +586 -0
  100. confiture/scenarios/ecommerce.py +199 -0
  101. confiture/scenarios/financial.py +253 -0
  102. confiture/scenarios/healthcare.py +315 -0
  103. confiture/scenarios/multi_tenant.py +340 -0
  104. confiture/scenarios/saas.py +295 -0
  105. confiture/testing/FRAMEWORK_API.md +722 -0
  106. confiture/testing/__init__.py +38 -0
  107. confiture/testing/fixtures/__init__.py +11 -0
  108. confiture/testing/fixtures/data_validator.py +229 -0
  109. confiture/testing/fixtures/migration_runner.py +167 -0
  110. confiture/testing/fixtures/schema_snapshotter.py +352 -0
  111. confiture/testing/frameworks/__init__.py +10 -0
  112. confiture/testing/frameworks/mutation.py +587 -0
  113. confiture/testing/frameworks/performance.py +479 -0
  114. confiture/testing/utils/__init__.py +0 -0
  115. fraiseql_confiture-0.3.4.dist-info/METADATA +438 -0
  116. fraiseql_confiture-0.3.4.dist-info/RECORD +119 -0
  117. fraiseql_confiture-0.3.4.dist-info/WHEEL +4 -0
  118. fraiseql_confiture-0.3.4.dist-info/entry_points.txt +2 -0
  119. fraiseql_confiture-0.3.4.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,438 @@
1
+ Metadata-Version: 2.4
2
+ Name: fraiseql-confiture
3
+ Version: 0.3.4
4
+ Classifier: Development Status :: 4 - Beta
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.11
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Topic :: Database
12
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
13
+ Requires-Dist: typer>=0.12.0
14
+ Requires-Dist: rich>=13.7.0
15
+ Requires-Dist: pydantic>=2.5.0
16
+ Requires-Dist: pyyaml>=6.0.1
17
+ Requires-Dist: psycopg[binary,pool]>=3.1.0
18
+ Requires-Dist: sqlparse>=0.5.0
19
+ Requires-Dist: cryptography>=42.0.0
20
+ Requires-Dist: pytest>=8.0.0 ; extra == 'testing'
21
+ Requires-Dist: pytest-asyncio>=0.23.0 ; extra == 'testing'
22
+ Requires-Dist: pytest-cov>=4.1.0 ; extra == 'testing'
23
+ Requires-Dist: pytest-json-report>=1.5.0 ; extra == 'testing'
24
+ Requires-Dist: pytest>=8.0.0 ; extra == 'dev'
25
+ Requires-Dist: pytest-asyncio>=0.23.0 ; extra == 'dev'
26
+ Requires-Dist: pytest-cov>=4.1.0 ; extra == 'dev'
27
+ Requires-Dist: pytest-watch>=4.2.0 ; extra == 'dev'
28
+ Requires-Dist: pytest-json-report>=1.5.0 ; extra == 'dev'
29
+ Requires-Dist: ruff>=0.6.0 ; extra == 'dev'
30
+ Requires-Dist: ty>=0.0.7 ; extra == 'dev'
31
+ Requires-Dist: maturin>=1.7.0 ; extra == 'dev'
32
+ Provides-Extra: testing
33
+ Provides-Extra: dev
34
+ Provides-Extra: fraiseql
35
+ License-File: LICENSE
36
+ Summary: PostgreSQL migrations, sweetly done 🍓
37
+ Keywords: postgresql,migration,database,schema,ddl
38
+ Home-Page: https://github.com/fraiseql/confiture
39
+ Author-email: evoludigit <lionel@fraiseql.com>
40
+ License: MIT
41
+ Requires-Python: >=3.11
42
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
43
+ Project-URL: Homepage, https://github.com/fraiseql/confiture
44
+ Project-URL: Documentation, https://github.com/fraiseql/confiture
45
+ Project-URL: Repository, https://github.com/fraiseql/confiture
46
+ Project-URL: Issues, https://github.com/fraiseql/confiture/issues
47
+ Project-URL: FraiseQL, https://github.com/fraiseql/fraiseql
48
+
49
+ # Confiture 🍓
50
+
51
+ **PostgreSQL migrations, sweetly done**
52
+
53
+ Confiture is the official migration tool for [FraiseQL](https://github.com/fraiseql/fraiseql), designed with a **build-from-scratch philosophy** and **4 migration strategies** to handle every scenario from local development to zero-downtime production deployments.
54
+
55
+ > **Part of the FraiseQL ecosystem** - While Confiture works standalone for any PostgreSQL project, it's designed to integrate seamlessly with FraiseQL's GraphQL-first approach.
56
+
57
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
58
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
59
+ [![PostgreSQL 12+](https://img.shields.io/badge/PostgreSQL-12%2B-blue?logo=postgresql&logoColor=white)](https://www.postgresql.org/)
60
+ [![CI](https://img.shields.io/github/actions/workflow/status/fraiseql/confiture/ci.yml?branch=main&label=CI&logo=github)](https://github.com/fraiseql/confiture/actions/workflows/ci.yml)
61
+ [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
62
+ [![Made with Rust](https://img.shields.io/badge/Made%20with-Rust-orange?logo=rust)](https://www.rust-lang.org/)
63
+ [![Part of FraiseQL](https://img.shields.io/badge/Part%20of-FraiseQL-ff69b4)](https://github.com/fraiseql/fraiseql)
64
+ [![Status: Beta](https://img.shields.io/badge/status-beta-yellow)](https://github.com/fraiseql/confiture)
65
+
66
+ ---
67
+
68
+ ## 🍓 Part of the FraiseQL Ecosystem
69
+
70
+ **confiture** accelerates PostgreSQL schema evolution across the FraiseQL stack:
71
+
72
+ ### **Server Stack (PostgreSQL + Python/Rust)**
73
+
74
+ | Tool | Purpose | Status | Performance Gain |
75
+ |------|---------|--------|------------------|
76
+ | **[pg_tviews](https://github.com/fraiseql/pg_tviews)** | Incremental materialized views | Beta | **100-500× faster** |
77
+ | **[jsonb_delta](https://github.com/evoludigit/jsonb_delta)** | JSONB surgical updates | Stable | **2-7× faster** |
78
+ | **[pgGit](https://pggit.dev)** | Database version control | Stable | Git for databases |
79
+ | **[confiture](https://github.com/fraiseql/confiture)** | PostgreSQL migrations | **Beta** | **300-600× faster** (theoretical) |
80
+ | **[fraiseql](https://fraiseql.dev)** | GraphQL framework | Stable | **7-10× faster** |
81
+ | **[fraiseql-data](https://github.com/fraiseql/fraiseql-seed)** | Seed data generation | Phase 6 | Auto-dependency resolution |
82
+
83
+ ### **Client Libraries (TypeScript/JavaScript)**
84
+
85
+ | Library | Purpose | Framework Support |
86
+ |---------|---------|-------------------|
87
+ | **[graphql-cascade](https://github.com/graphql-cascade/graphql-cascade)** | Automatic cache invalidation | Apollo, React Query, Relay, URQL |
88
+
89
+ **How confiture fits:**
90
+ - **Build from DDL** → Fresh DB in <1s for **fraiseql** GraphQL testing
91
+ - **pgGit** automatically tracks confiture migrations
92
+ - Manage **pg_tviews** schema evolution with 4 migration strategies
93
+ - **fraiseql-data** seeds the schema confiture built
94
+
95
+ **Intended workflow:**
96
+ ```bash
97
+ # Build schema from DDL files
98
+ confiture build --env test
99
+
100
+ # Seed test data
101
+ fraiseql-data add tb_user --count 100
102
+
103
+ # Run GraphQL tests
104
+ pytest
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Why Confiture?
110
+
111
+ ### The Problem with Migration History
112
+
113
+ Traditional migration tools (Alembic, Django migrations, Flyway) use **migration history replay**: every time you build a database, the tool executes every migration file in order. This works, but it's **slow and brittle**:
114
+
115
+ - **Slow**: Fresh database builds take 5-10 minutes (replaying hundreds of operations)
116
+ - **Brittle**: One broken migration breaks everything - your database history is fragile
117
+ - **Complicated**: Developers maintain two things: current schema AND migration history
118
+ - **Messy**: Technical debt accumulates as migrations pile up over months/years
119
+
120
+ ### The Confiture Approach
121
+
122
+ Confiture flips the model: **DDL source files are the single source of truth**. To build a database:
123
+
124
+ 1. Read all `.sql` files in `db/schema/`
125
+ 2. Execute them once (in order)
126
+ 3. Done ✅
127
+
128
+ No migration history to replay. No accumulated technical debt. Just your actual, current schema. **Fresh databases in <1 second.**
129
+
130
+ ### Intended Advantages Over Alembic
131
+
132
+ | Feature | Confiture | Alembic | Notes |
133
+ |---------|-----------|---------|-------|
134
+ | **Fresh DB setup** | Direct DDL execution | Migration replay | Theoretically faster |
135
+ | **Zero-downtime migrations** | Via FDW (planned) | Not built-in | Not yet production-tested |
136
+ | **Production data sync** | Built-in (with PII anonymization) | Not available | Not yet production-tested |
137
+ | **Schema diffs** | Auto-generated | Manual | Implemented |
138
+ | **Conceptual simplicity** | DDL-first | Migration-first | Different philosophy |
139
+
140
+ ### What's Implemented
141
+
142
+ - ✅ **4 migration strategies** (Build from DDL, ALTER, Production Sync, FDW)
143
+ - ✅ **Python + optional Rust extension**
144
+ - ✅ **PII anonymization strategies**
145
+ - ✅ **Comprehensive test suite** (3,200+ tests)
146
+ - ⚠️ **Not yet used in production** - Beta software
147
+
148
+ ---
149
+
150
+ ## The Four Mediums
151
+
152
+ ### 1️⃣ Build from DDL
153
+ ```bash
154
+ confiture build --env production
155
+ ```
156
+ Build fresh database from `db/schema/` DDL files in <1 second.
157
+
158
+ ### 2️⃣ Incremental Migrations (ALTER)
159
+ ```bash
160
+ confiture migrate up
161
+ ```
162
+ Apply migrations to existing database (simple schema changes).
163
+
164
+ ### 3️⃣ Production Data Sync
165
+ ```bash
166
+ confiture sync --from production --anonymize users.email
167
+ ```
168
+ Copy production data to local/staging with PII anonymization.
169
+
170
+ ### 4️⃣ Schema-to-Schema Migration (Zero-Downtime)
171
+ ```bash
172
+ confiture migrate schema-to-schema --strategy fdw
173
+ ```
174
+ Complex migrations via FDW with 0-5 second downtime.
175
+
176
+ ---
177
+
178
+ ## Quick Start
179
+
180
+ ### Installation
181
+
182
+ ```bash
183
+ pip install fraiseql-confiture
184
+
185
+ # Or with FraiseQL integration
186
+ pip install fraiseql-confiture[fraiseql]
187
+ ```
188
+
189
+ ### Initialize Project
190
+
191
+ ```bash
192
+ confiture init
193
+ ```
194
+
195
+ Creates:
196
+ ```
197
+ db/
198
+ ├── schema/ # DDL: CREATE TABLE, views, functions
199
+ │ ├── 00_common/
200
+ │ ├── 10_tables/
201
+ │ └── 20_views/
202
+ ├── seeds/ # INSERT: Environment-specific test data
203
+ │ ├── common/
204
+ │ ├── development/
205
+ │ └── test/
206
+ ├── migrations/ # Generated migration files
207
+ └── environments/ # Environment configurations
208
+ ├── local.yaml
209
+ ├── test.yaml
210
+ └── production.yaml
211
+ ```
212
+
213
+ ### Build Schema
214
+
215
+ ```bash
216
+ # Build local database
217
+ confiture build --env local
218
+
219
+ # Build production schema
220
+ confiture build --env production
221
+ ```
222
+
223
+ ### Create Migration
224
+
225
+ ```bash
226
+ # Edit schema
227
+ vim db/schema/10_tables/users.sql
228
+
229
+ # Generate migration
230
+ confiture migrate generate --name "add_user_bio"
231
+
232
+ # Apply migration
233
+ confiture migrate up
234
+ ```
235
+
236
+ ### Test Migrations Before Applying (Dry-Run)
237
+
238
+ Analyze migrations without executing them:
239
+
240
+ ```bash
241
+ # Analyze pending migrations
242
+ confiture migrate up --dry-run
243
+
244
+ # Test in SAVEPOINT (guaranteed rollback)
245
+ confiture migrate up --dry-run-execute
246
+
247
+ # Save analysis to file
248
+ confiture migrate up --dry-run --format json --output report.json
249
+
250
+ # Analyze rollback impact
251
+ confiture migrate down --dry-run --steps 2
252
+ ```
253
+
254
+ For more details, see **[Dry-Run Guide](docs/guides/cli-dry-run.md)**.
255
+
256
+ ---
257
+
258
+ ## Documentation
259
+
260
+ ### User Guides
261
+
262
+ **Core Concepts**:
263
+ - **[Build from DDL](docs/guides/01-build-from-ddl.md)** - Execute DDL files directly
264
+ - **[Incremental Migrations](docs/guides/02-incremental-migrations.md)** - ALTER-based changes
265
+ - **[Production Data Sync](docs/guides/03-production-sync.md)** - Copy and anonymize data
266
+ - **[Zero-Downtime Migrations](docs/guides/04-schema-to-schema.md)** - Schema-to-schema via FDW
267
+ - **[Migration Decision Tree](docs/guides/migration-decision-tree.md)** - Choose the right strategy
268
+
269
+ **Advanced**:
270
+ - **[Dry-Run Mode](docs/guides/dry-run.md)** - Test migrations before applying
271
+ - **[Migration Hooks](docs/guides/hooks.md)** - Execute custom logic before/after migrations
272
+ - **[Anonymization](docs/guides/anonymization.md)** - PII data masking strategies
273
+ - **[Compliance](docs/guides/compliance.md)** - HIPAA, SOX, PCI-DSS, GDPR
274
+ - **[Integrations](docs/guides/integrations.md)** - Slack, GitHub Actions, monitoring
275
+
276
+ ### API Reference
277
+
278
+ - **[CLI Reference](docs/reference/cli.md)** - All commands documented
279
+ - **[Configuration](docs/reference/configuration.md)** - Environment configuration
280
+ - **[Schema Builder API](docs/api/builder.md)** - Building schemas programmatically
281
+ - **[Migrator API](docs/api/migrator.md)** - Migration execution
282
+ - **[Syncer API](docs/api/syncer.md)** - Production data sync
283
+ - **[Hook API](docs/api/hooks.md)** - Migration lifecycle hooks
284
+ - **[Anonymization API](docs/api/anonymization.md)** - PII data masking
285
+ - **[Linting API](docs/api/linting.md)** - Schema validation rules
286
+
287
+ ### Examples
288
+ - **[Examples Overview](examples/)** - Complete examples
289
+ - **[Basic Migration](examples/01-basic-migration/)** - Learn the fundamentals
290
+ - **[FraiseQL Integration](examples/02-fraiseql-integration/)** - GraphQL workflow
291
+ - **[Zero-Downtime](examples/03-zero-downtime-migration/)** - FDW-based migration
292
+ - **[Production Sync](examples/04-production-sync-anonymization/)** - PII anonymization
293
+
294
+ ---
295
+
296
+ ## Features
297
+
298
+ ### Core Migration System (Implemented)
299
+
300
+ - ✅ **Build from DDL** (Medium 1) - Execute DDL files directly
301
+ - ✅ **Incremental migrations** (Medium 2) - ALTER-based changes
302
+ - ✅ **Production data sync** (Medium 3) - Copy with PII anonymization
303
+ - ✅ **Zero-downtime migrations** (Medium 4) - Schema-to-schema via FDW
304
+
305
+ ### Additional Features (Implemented)
306
+
307
+ - ✅ Optional Rust extension for performance
308
+ - ✅ Schema diff detection with auto-generation
309
+ - ✅ CLI with rich terminal output
310
+ - ✅ Multi-environment configuration
311
+ - ✅ Migration hooks (pre/post execution)
312
+ - ✅ Schema linting with multiple rules
313
+ - ✅ PII anonymization strategies
314
+ - ✅ Dry-run mode for testing
315
+
316
+ ### Documentation (Comprehensive)
317
+
318
+ - ✅ User guides for all 4 migration strategies
319
+ - ✅ API reference documentation
320
+ - ✅ Integration guides (Slack, GitHub Actions, monitoring)
321
+ - ✅ Compliance guides (HIPAA, SOX, PCI-DSS, GDPR)
322
+
323
+ ---
324
+
325
+ ## Comparison
326
+
327
+ | Feature | Alembic | pgroll | **Confiture** |
328
+ |---------|---------|--------|---------------|
329
+ | **Philosophy** | Migration replay | Multi-version schema | **Build-from-DDL** |
330
+ | **Fresh DB setup** | Minutes | Minutes | **<1 second** |
331
+ | **Zero-downtime** | ❌ No | ✅ Yes | **✅ Yes (FDW)** |
332
+ | **Production sync** | ❌ No | ❌ No | **✅ Built-in** |
333
+ | **Language** | Python | Go | **Python + Rust** |
334
+
335
+ ---
336
+
337
+ ## Current Version
338
+
339
+ **v0.3.4**
340
+
341
+ > **⚠️ Beta Software**: Confiture has not yet been used in production. While the codebase includes comprehensive tests and documentation, real-world usage may reveal issues. Use with caution in production environments.
342
+
343
+ ### What's Implemented
344
+ - ✅ All 4 migration strategies (Build from DDL, ALTER, Production Sync, FDW)
345
+ - ✅ Comprehensive test suite (3,200+ tests passing)
346
+ - ✅ Documentation and guides
347
+ - ✅ Python 3.11, 3.12, 3.13 support
348
+ - ✅ Optional Rust extension
349
+ - ✅ Migration hooks, schema linting, anonymization strategies
350
+
351
+ ### What's NOT Validated
352
+ - ❌ Production usage (never deployed to production)
353
+ - ❌ Performance claims (benchmarks only, not real-world)
354
+ - ❌ Edge cases and failure recovery (not battle-tested)
355
+ - ❌ Large-scale data migrations (theoretical only)
356
+
357
+ ---
358
+
359
+ ## Contributing
360
+
361
+ Contributions welcome! We'd love your help making Confiture even better.
362
+
363
+ **Quick Start**:
364
+ ```bash
365
+ # Clone repository
366
+ git clone https://github.com/fraiseql/confiture.git
367
+ cd confiture
368
+
369
+ # Install dependencies (includes Rust build)
370
+ uv sync --all-extras
371
+
372
+ # Build Rust extension
373
+ uv run maturin develop
374
+
375
+ # Run tests
376
+ uv run pytest --cov=confiture
377
+
378
+ # Format code
379
+ uv run ruff format .
380
+
381
+ # Type checking
382
+ uv run mypy python/confiture/
383
+ ```
384
+
385
+ **Resources**:
386
+ - **[CONTRIBUTING.md](CONTRIBUTING.md)** - Contributing guidelines
387
+ - **[CLAUDE.md](CLAUDE.md)** - AI-assisted development guide
388
+ - **[PHASES.md](PHASES.md)** - Detailed roadmap
389
+
390
+ **What to contribute**:
391
+ - 🐛 Bug fixes
392
+ - ✨ New features
393
+ - 📖 Documentation improvements
394
+ - 💡 New examples
395
+ - 🧪 Test coverage improvements
396
+
397
+ ---
398
+
399
+ ## Author
400
+
401
+ **Vibe-engineered by [Lionel Hamayon](https://github.com/LionelHamayon)** 🍓
402
+
403
+ Confiture was crafted with care as the migration tool for the FraiseQL ecosystem, combining the elegance of Python with the performance of Rust, and the sweetness of strawberry jam.
404
+
405
+ ---
406
+
407
+ ## License
408
+
409
+ MIT License - see [LICENSE](LICENSE) for details.
410
+
411
+ Copyright (c) 2025 Lionel Hamayon
412
+
413
+ ---
414
+
415
+ ## Acknowledgments
416
+
417
+ - Inspired by printoptim_backend's build-from-scratch approach
418
+ - Built for [FraiseQL](https://github.com/fraiseql/fraiseql) GraphQL framework
419
+ - Influenced by pgroll, Alembic, and Reshape
420
+ - Developed with AI-assisted vibe engineering ✨
421
+
422
+ ---
423
+
424
+ ## FraiseQL Ecosystem
425
+
426
+ Confiture is part of the FraiseQL family:
427
+
428
+ - **[FraiseQL](https://github.com/fraiseql/fraiseql)** - Modern GraphQL framework for Python
429
+ - **[Confiture](https://github.com/fraiseql/confiture)** - PostgreSQL migration tool (you are here)
430
+
431
+ ---
432
+
433
+ *Making jam from strawberries, one migration at a time.* 🍓→🍯
434
+
435
+ *Vibe-engineered with ❤️ by Lionel Hamayon*
436
+
437
+ **[Documentation](https://github.com/fraiseql/confiture)** • **[GitHub](https://github.com/fraiseql/confiture)** • **[PyPI](https://pypi.org/project/fraiseql-confiture/)**
438
+
@@ -0,0 +1,119 @@
1
+ confiture/__init__.py,sha256=yrsRVGGEZ1Vv4BZcSet_OUnf2w3iNatawdIHkC6mUwQ,1279
2
+ confiture/_core.cp311-win_amd64.pyd,sha256=-6JQR8ZN4vbdw6Co2V6q02-EtQnJDxiBUPy2RoX0F5I,343552
3
+ confiture/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ confiture/cli/dry_run.py,sha256=lSVqIwjU78X2Xu9rp1m49a5jYcBAGXPA4n97nf7BG5s,3542
5
+ confiture/cli/lint_formatter.py,sha256=IWrTqewcOdEVwIBgJ2-N3PF6_21azSQlg92LglvnFyc,5861
6
+ confiture/cli/main.py,sha256=9Chh880Kx74-XjMfXavg7TwgcjgddKlupKRlGmsaeMM,60840
7
+ confiture/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ confiture/config/environment.py,sha256=1FUW_bxW5iWDQW_nMzX2oX0X3VHBs3mE8IxOC5hEIus,9406
9
+ confiture/core/__init__.py,sha256=2sY3n-yAOth_ldJMDIG4Gs_NjpfAyrTZzY2BflVZRAk,1127
10
+ confiture/core/anonymization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ confiture/core/anonymization/audit.py,sha256=0CcosTtE99UHhFzYpqVFm1XuLvYjuU7Z1IdAgJiriNs,17183
12
+ confiture/core/anonymization/benchmarking.py,sha256=M9NSTLw26BjrRN_trPzPY5k44hjIwK_sDqeWodaKEVM,12034
13
+ confiture/core/anonymization/breach_notification.py,sha256=J9asCIPHwUHCxrjkbhn10LlGITkWCYTJaak5g2gBsSQ,22382
14
+ confiture/core/anonymization/compliance.py,sha256=fWa6e0UdJnJhMI6wrkj6o3-jjV2N_bq7hIbdHq0lOGM,22468
15
+ confiture/core/anonymization/composer.py,sha256=lCNHgSpr55BcbXfovPh7WcydHQT_2Y5axYfOPEMgTwA,9270
16
+ confiture/core/anonymization/data_subject_rights.py,sha256=Qh0Q5tYao0K8IaDFUMxlMgVa67klqHkdJQ54eJ6C47c,22084
17
+ confiture/core/anonymization/factory.py,sha256=TGfgs_Suytmt7bFbbAAMFso-fsYq7K5lZIVuNSgmUXM,10361
18
+ confiture/core/anonymization/governance.py,sha256=s9zk1sEoJPetK6brAiZf0vVQ9mTa0vBcMNUdIoQYksE,23528
19
+ confiture/core/anonymization/performance.py,sha256=ZMW0YalIr06tOCcyzyypzgzsXtMAZjvKxGugeZEnObg,36503
20
+ confiture/core/anonymization/profile.py,sha256=T7SKEziJAlpmYop5i1z0ZBh440HLwSfbtgOguTQwyYc,9093
21
+ confiture/core/anonymization/registry.py,sha256=tvPIaSYxsNUl9kJgEb3M1DzGIhGJea0c_QCT2Ax4kjQ,5944
22
+ confiture/core/anonymization/security/kms_manager.py,sha256=G9lIMR50bjqCIIyKtC-jv3YLC-IwU011_6EdcJ0IPfc,16587
23
+ confiture/core/anonymization/security/lineage.py,sha256=dfm5fhFsRwyXfeoT6AjlOITOGxWUjocdAnsdJvUgGDA,32458
24
+ confiture/core/anonymization/security/token_store.py,sha256=yYqlvjhsJXBn5gb3Qinvf05pHtcF99g3i1FHOUwGSNI,23557
25
+ confiture/core/anonymization/strategies/__init__.py,sha256=ORM1ChVW4Mw7ypbNYVH74V7sxYs5Zw2onG0vnbiV3WE,1758
26
+ confiture/core/anonymization/strategies/address.py,sha256=0MWk0R4UYJTOQmZnurGN3sb5eZ4o9A6myxfkv5cN7-8,9788
27
+ confiture/core/anonymization/strategies/credit_card.py,sha256=KS60AkcLSlsE52lKIZLwr06tcoDP_SwtXMZZlw6-S_E,12451
28
+ confiture/core/anonymization/strategies/custom.py,sha256=gprYGHUSjKYJS2FJdqf8YuogFPKQBcprjGCIHHAdIVQ,4848
29
+ confiture/core/anonymization/strategies/date.py,sha256=Nb5RV8NfUfh8OZ2GNmTB85S1Tf8gkKEsunCYFRbD4Mk,7006
30
+ confiture/core/anonymization/strategies/differential_privacy.py,sha256=SOhKfW6b6XZBXv5mCpMdhZaYoKkBn7nAM0iPHwsZvgY,13642
31
+ confiture/core/anonymization/strategies/email.py,sha256=EARiKFBfHjoK-zGrXikFZCIhkYS3Izl-jxKz8yeyuCs,4492
32
+ confiture/core/anonymization/strategies/format_preserving_encryption.py,sha256=AvyipCSQBDzVfKJRHX45vkiAHxCKhl-Ec5v6a7hgIbw,10542
33
+ confiture/core/anonymization/strategies/hash.py,sha256=noZ85ZJrfoS3dasIA8E1arij8cHjpuhgQSvBiSmq92w,4901
34
+ confiture/core/anonymization/strategies/ip_address.py,sha256=q52Q3WGfMjlebCoSjR2HY9jrisA90lgz11n-oJPdW44,7763
35
+ confiture/core/anonymization/strategies/masking_retention.py,sha256=1yaHqrzqVWjWal3XdpJXZKilhW66msQiF4aNS6vIg5k,8526
36
+ confiture/core/anonymization/strategies/name.py,sha256=PPIm0HdpESVFbaTgmA-c5dz1Aa7Ejq78W6VSgwhSvng,7575
37
+ confiture/core/anonymization/strategies/phone.py,sha256=D5Y7CJRDJhQO0OH2FnpKzH48L_Ni7-aAn4rFHcrnfvI,3716
38
+ confiture/core/anonymization/strategies/preserve.py,sha256=G0JXnKp9nVyeTI1mumAgyjBP5ESBjV6Zdu9rQy8acpw,2278
39
+ confiture/core/anonymization/strategies/redact.py,sha256=yJaEULkJuxNpQGV80IpU3jwwHwYHKKaG4uMlkbC2D0s,3100
40
+ confiture/core/anonymization/strategies/salted_hashing.py,sha256=QA6Gg7IQJsDwyA_6mtogklLoSwinXRCHOv_cBQGPPWc,10971
41
+ confiture/core/anonymization/strategies/text_redaction.py,sha256=PvPo74fQIkbR3F7vHO6Zhs-QLO8gHPjyMTsR2pqSzag,6135
42
+ confiture/core/anonymization/strategies/tokenization.py,sha256=3EBClzEi0dC6phJjJanUDBbJbj3lYsAWwerBUuU-Hl0,12600
43
+ confiture/core/anonymization/strategy.py,sha256=6ntiv-YDIj5uDEVUWB2rh2nQB1smQ0EYIwvPaYaU4QI,8099
44
+ confiture/core/anonymization/syncer_audit.py,sha256=CaemJJjVxWgTx-lKHbdApMwuVnOp9GdDR591arZRpr4,11806
45
+ confiture/core/blue_green.py,sha256=xVFMUyGFZVYU3vjtJlVh3uiWwgCbDMEZF1RCdqlQyVo,24132
46
+ confiture/core/builder.py,sha256=kqIRgjlafWUt0OkxAmuZ4PHPK-0ZztgwaeV9HSSEAd0,18627
47
+ confiture/core/checksum.py,sha256=VW2Lzj_yow-iu1WbPtw7JpMOk4WtmmhuePP0yU1CkbE,11454
48
+ confiture/core/connection.py,sha256=EldhMxmApDjIWSIz7UDAnhQ8IrD-xj7KTx2YgoXEoms,4205
49
+ confiture/core/differ.py,sha256=VSxFqUSaU526lcw3KhxmiBAvjQ_lhDx2nvSYvG4x2Jg,18546
50
+ confiture/core/drift.py,sha256=Ar6VfA7j7UN-fs7ky72Yq26qG_xethK8xkR3E18RNmE,19502
51
+ confiture/core/dry_run.py,sha256=gLI0M-GDdZ5QIlpjroeWsa3kzwSrqioyUDAS2KiwfL8,5822
52
+ confiture/core/health.py,sha256=NBRKJo5nTqdZk4lY4R2UMsrobUdx_oES0FlUjFh8TYE,10155
53
+ confiture/core/hooks/__init__.py,sha256=wd4PfHkqAi6Ysw_RSOSpdtqIDh-8o0ZnrV-2F3AYA_Y,2090
54
+ confiture/core/hooks/base.py,sha256=yi-GFIlUe4QHXw_403GhlcVwudVaRPpNJyEJsw3cCJs,7316
55
+ confiture/core/hooks/context.py,sha256=_Kcusb9y-jzx-Bk3EH57HdRZfUQCrdzL2w0_4ZJ5JVQ,4399
56
+ confiture/core/hooks/execution_strategies.py,sha256=xgKOVJsAHP32tO1BGKSnDpqH0HEwqQOrvEv1XMFKJak,2050
57
+ confiture/core/hooks/observability.py,sha256=aAiwjWzMPFQXwzpG751PtruP799guuuCRnbHA70rkXI,7158
58
+ confiture/core/hooks/phases.py,sha256=Iss7l6bKFXqwEC7j-k_BIQ0iVq5JoWkJvVsLtrHtsT0,1871
59
+ confiture/core/hooks/registry.py,sha256=6ivQI8iLVEYno3fzq3fvRkobeITjvtDcYw0q1Jhy2BA,11370
60
+ confiture/core/large_tables.py,sha256=JdS3GPu3ND_I7DcX90HBmAoOAsJfjw1WN7ZhB5ikaBk,26444
61
+ confiture/core/linting/__init__.py,sha256=1YyodbUn6y35hgX6SblmdR6RnjlfgSdDRp52A36dQvo,1382
62
+ confiture/core/linting/composer.py,sha256=PrUgqoHaZGvVZmqDR2CpUIr4ZFE8lFQGHy4SjGm8hcI,6628
63
+ confiture/core/linting/libraries/__init__.py,sha256=oVjlnolufbzYwSxywROJ-vMI4W8KxTb5cI2ZecfNv8w,384
64
+ confiture/core/linting/libraries/gdpr.py,sha256=v59dU7v1Tadus4IRVwbLRntzyBo0lWAg88aAbIZmXwg,6568
65
+ confiture/core/linting/libraries/general.py,sha256=x6Z6SLEfsjbQ7dfUUgvar0sS7CpsT1qCqJ-eeYWs0IM,7329
66
+ confiture/core/linting/libraries/hipaa.py,sha256=d6fHJcRe6X-kA3qPEjRRLo2nJNsaq1Owc2MBvKtGvVQ,5564
67
+ confiture/core/linting/libraries/pci_dss.py,sha256=xg5nb5UwtR4gkoKnm7ZyVt3A7lk4TzZj47lipw_pcrk,4061
68
+ confiture/core/linting/libraries/sox.py,sha256=lqwCMo8mc738tNl7PAYtE-Pea9cZSC6LJ1cxcUIWf6g,4575
69
+ confiture/core/linting/schema_linter.py,sha256=Zg6z95IRQ5Ljn-WQeg8NJR5tAPIP_9O8kzxQAzkCJvI,17185
70
+ confiture/core/linting/versioning.py,sha256=2syzZqY2lg-_HjRtjbResNAEBqhpAP1y80GO7aFl1dE,4315
71
+ confiture/core/locking.py,sha256=XTO-vGMNOMsSi_txbsKjglBnwM9VkyOj6ohIeS6wpgo,13339
72
+ confiture/core/migration_generator.py,sha256=OLZdEqLKB4uncIX8mjdy2X5P9mYu1T-9SDVolnW7uno,10030
73
+ confiture/core/migrator.py,sha256=bFjB9yrjrfUBxM8hqtgFTrouZuMZm8JOFp32yrnbmro,30317
74
+ confiture/core/observability/__init__.py,sha256=hNueuVL_E_IidJGAtr8i9aV1dFW6hwD-Vbnw_uRY3yY,925
75
+ confiture/core/observability/audit.py,sha256=_eRzRWbAz8UQf-ItUIv_0kR-sWZgzlcBg8GJ92PrnFc,10185
76
+ confiture/core/observability/logging.py,sha256=8RGYhX11QSuS2rCQB6tnzizfL5ksa8Cd8CRoDpOdNBc,5698
77
+ confiture/core/observability/metrics.py,sha256=ODakRxFmLLZt_S1m-mUemHbuhKbqdWrKALWbLLaYX5w,5491
78
+ confiture/core/observability/tracing.py,sha256=Cxkjg1tTCot_1BjE73tdAAvG4X33MGeUee2CeKqGNcc,5717
79
+ confiture/core/pg_version.py,sha256=P2yk6NeimscVHwOEUhS1UjzKuk-W0G6HFfqkumyTWfA,12421
80
+ confiture/core/pool.py,sha256=_fK3wRmTZaMBz-e4o4WFoX3oHrcQuToqNf8R3FhRCJk,14590
81
+ confiture/core/risk/__init__.py,sha256=ZewN8T6HnJy0zM6xSE4kiaBDjrYtYp8A3NDpE9vO0is,792
82
+ confiture/core/risk/predictor.py,sha256=r2kIqi0VxVC4WGJESyTE0xQR3NnosZwrsxoE5m_82c8,6449
83
+ confiture/core/risk/scoring.py,sha256=VSkEMJRPnZ5iGxJFixo-yg3b5YYdiC9aJeuA64Y936U,7552
84
+ confiture/core/rollback_generator.py,sha256=8bHRbxE2ShbLAoxLlUAfjmkldlmFMq3mEU5b03rkuZc,12988
85
+ confiture/core/schema_analyzer.py,sha256=a48twZ7p1Uk-vdNzMcWoulXtbp-IVIZQi6r-T6JVSzE,27917
86
+ confiture/core/schema_to_schema.py,sha256=BVZu8vVkKArK4rSSbnCR0SJsmbLV2V6LGzAnZhBldBw,22832
87
+ confiture/core/security/__init__.py,sha256=iUAGWWBQpkQ6zb9zhZAWrL8BzZ8rMBPVk5iE_k2cKss,850
88
+ confiture/core/security/logging.py,sha256=pOWHanIkFTCuNlUdMYLXhd0HzxHy_ZhcVTGwgbN3lz0,6403
89
+ confiture/core/security/validation.py,sha256=OgoQ6RpYo7U1WP96Aa279WGKbWo5LHzyhvKZlaKhySY,12636
90
+ confiture/core/signals.py,sha256=hzJnBbNwFEqUK4bKYfCytHszDshU4Ww6d6oxwLgIQ18,11999
91
+ confiture/core/syncer.py,sha256=A3GGhWughWd06itc1ls_ejLG7ZgQiub4xCPdV6l8b2A,18938
92
+ confiture/exceptions.py,sha256=bhsNjPPmkzo-jrktM2vgwOFaZA1BMlGg_6W_o7v3X0c,4933
93
+ confiture/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
+ confiture/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
95
+ confiture/models/lint.py,sha256=MRZj4zYDZp3IalqgArSDz2-QfZiarQhsn088zp7sd4s,6089
96
+ confiture/models/migration.py,sha256=TO37spws1KxPZ1zQJ8TZlzEfIpXib6rk9Bow3WXpONA,6570
97
+ confiture/models/schema.py,sha256=d2hpI12KutleAho94lxIwx1h_utITnX_K09tQTkAF-k,6112
98
+ confiture/scenarios/__init__.py,sha256=X_qTKh6SywXq2PtEB3CmSijHFBFyjysHPKPnun_rNFk,1291
99
+ confiture/scenarios/compliance.py,sha256=Nc6aYc5y-fPDgAj7oiZ26IKFUpX9AyGU5pEZvXBay8Q,21148
100
+ confiture/scenarios/ecommerce.py,sha256=OIoMq5sYT_s1rMEkDm58ldz31TY3gH6NkezgzAMAQOM,7008
101
+ confiture/scenarios/financial.py,sha256=oyXlplwZQwiF39H0NDpYn3_-5cWHrl9AZySi21GFaQ4,9698
102
+ confiture/scenarios/healthcare.py,sha256=47JhS6d6h1GsqLJKjNOxWaH4KFNP_VzIew0WVUTyCws,12421
103
+ confiture/scenarios/multi_tenant.py,sha256=lr6l8-60_iPb5CD3OepLUnWebyvn6NUZ-GdRg_GWHl4,12913
104
+ confiture/scenarios/saas.py,sha256=zl2xr0vUJ_PEN2_6L6J15WIfl5_CHkHYHd5S-RkAR9o,11445
105
+ confiture/testing/FRAMEWORK_API.md,sha256=AsR4x_fobgJW2NPj9nf2LSnObGkwp1bvR7fmPLAgcYE,19719
106
+ confiture/testing/__init__.py,sha256=zACm_wN_AF2D0HzJGwm8ctw2Z6lbK8uDyVHz-4qd6Tw,991
107
+ confiture/testing/fixtures/__init__.py,sha256=EK8VwokScIGJ4t8jS3R4Zg42RLklNpMONo7KPYrrQL8,379
108
+ confiture/testing/fixtures/data_validator.py,sha256=NzDVYXbq35gJaD65xt_QBrBnkyEHEfQRD3EWqStB94k,7785
109
+ confiture/testing/fixtures/migration_runner.py,sha256=wOp8oKn8w73WY42iL38E2AU_Oj3DZ8RTBQeClYwEXJM,5552
110
+ confiture/testing/fixtures/schema_snapshotter.py,sha256=TmX8uZ-riWZhdy7jnK_PlapdD5OyVKfX9JeMnEeDzxU,12269
111
+ confiture/testing/frameworks/__init__.py,sha256=C_qDMK4ArmCsZuhXKcb4NlE38eD9Ox7Rr5cS9wu1On0,334
112
+ confiture/testing/frameworks/mutation.py,sha256=NwhJgE2-uopB6SVv1BRDzT0E9ZTHGiEsAN6sHm364QI,22198
113
+ confiture/testing/frameworks/performance.py,sha256=0OeAzkEuFfY4ffDwiKJ8oRmEBe_0BFu9iCWqcC2YbAY,17693
114
+ confiture/testing/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
115
+ fraiseql_confiture-0.3.4.dist-info/METADATA,sha256=8FkoRrTU14voVSb6dZbdPNHZNtwy0WMYYxmcEU31k90,15753
116
+ fraiseql_confiture-0.3.4.dist-info/WHEEL,sha256=bNaa2-XeaoMXnkzV391Sm2NgCjpJ3A2VmfN6ZUnNTZA,96
117
+ fraiseql_confiture-0.3.4.dist-info/entry_points.txt,sha256=nRq8YKFFl7Pr0462GxN2Y1PAe77UJVXC0xrw92qnZks,51
118
+ fraiseql_confiture-0.3.4.dist-info/licenses/LICENSE,sha256=KaGyYH3D_2KxkWWeix-_GcYMg7hfEgNYTyxJGkzYh8U,1092
119
+ fraiseql_confiture-0.3.4.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.9.6)
3
+ Root-Is-Purelib: false
4
+ Tag: cp311-cp311-win_amd64
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ confiture=confiture.cli.main:app
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Lionel Hamayon
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.