pyrsql 0.0.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.
Files changed (134) hide show
  1. pyrsql-0.0.1/PKG-INFO +72 -0
  2. pyrsql-0.0.1/README.md +43 -0
  3. pyrsql-0.0.1/docs/architecture.md +461 -0
  4. pyrsql-0.0.1/docs/pyguide.md +3709 -0
  5. pyrsql-0.0.1/docs/quality.md +94 -0
  6. pyrsql-0.0.1/docs/reference.md +199 -0
  7. pyrsql-0.0.1/docs/testing.md +228 -0
  8. pyrsql-0.0.1/docs/usage.md +631 -0
  9. pyrsql-0.0.1/pyproject.toml +117 -0
  10. pyrsql-0.0.1/src/pyrsql/__init__.py +63 -0
  11. pyrsql-0.0.1/src/pyrsql/adapters/__init__.py +3 -0
  12. pyrsql-0.0.1/src/pyrsql/adapters/fastapi/__init__.py +15 -0
  13. pyrsql-0.0.1/src/pyrsql/adapters/fastapi/config.py +76 -0
  14. pyrsql-0.0.1/src/pyrsql/adapters/fastapi/criteria.py +56 -0
  15. pyrsql-0.0.1/src/pyrsql/adapters/fastapi/dependency.py +217 -0
  16. pyrsql-0.0.1/src/pyrsql/adapters/fastapi/errors.py +107 -0
  17. pyrsql-0.0.1/src/pyrsql/api.py +76 -0
  18. pyrsql-0.0.1/src/pyrsql/core/__init__.py +45 -0
  19. pyrsql-0.0.1/src/pyrsql/core/compiler.py +81 -0
  20. pyrsql-0.0.1/src/pyrsql/core/conversion.py +206 -0
  21. pyrsql-0.0.1/src/pyrsql/core/custom.py +14 -0
  22. pyrsql-0.0.1/src/pyrsql/core/field_policy.py +97 -0
  23. pyrsql-0.0.1/src/pyrsql/core/joins.py +11 -0
  24. pyrsql-0.0.1/src/pyrsql/core/json/__init__.py +19 -0
  25. pyrsql-0.0.1/src/pyrsql/core/json/options.py +31 -0
  26. pyrsql-0.0.1/src/pyrsql/core/json/path.py +35 -0
  27. pyrsql-0.0.1/src/pyrsql/core/json/query.py +39 -0
  28. pyrsql-0.0.1/src/pyrsql/core/json/values.py +72 -0
  29. pyrsql-0.0.1/src/pyrsql/core/options.py +416 -0
  30. pyrsql-0.0.1/src/pyrsql/core/page.py +115 -0
  31. pyrsql-0.0.1/src/pyrsql/core/procedure_policy.py +61 -0
  32. pyrsql-0.0.1/src/pyrsql/core/query.py +160 -0
  33. pyrsql-0.0.1/src/pyrsql/core/sort.py +153 -0
  34. pyrsql-0.0.1/src/pyrsql/integrations/__init__.py +8 -0
  35. pyrsql-0.0.1/src/pyrsql/integrations/fastapi/__init__.py +8 -0
  36. pyrsql-0.0.1/src/pyrsql/integrations/fastapi/sqlalchemy.py +251 -0
  37. pyrsql-0.0.1/src/pyrsql/orms/__init__.py +15 -0
  38. pyrsql-0.0.1/src/pyrsql/orms/base.py +99 -0
  39. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/__init__.py +39 -0
  40. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/coercion.py +57 -0
  41. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/compiled.py +56 -0
  42. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/compiled_page.py +40 -0
  43. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/compiled_sort.py +56 -0
  44. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/custom.py +25 -0
  45. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/errors.py +17 -0
  46. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/introspection.py +107 -0
  47. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/json_path.py +351 -0
  48. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/orm.py +65 -0
  49. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/resolver.py +202 -0
  50. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/sorter.py +173 -0
  51. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/statement.py +40 -0
  52. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/translator.py +560 -0
  53. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/type_inference.py +27 -0
  54. pyrsql-0.0.1/src/pyrsql/orms/sqlalchemy/types.py +64 -0
  55. pyrsql-0.0.1/src/pyrsql/parsing/__init__.py +32 -0
  56. pyrsql-0.0.1/src/pyrsql/parsing/ast.py +61 -0
  57. pyrsql-0.0.1/src/pyrsql/parsing/errors.py +25 -0
  58. pyrsql-0.0.1/src/pyrsql/parsing/lexer.py +264 -0
  59. pyrsql-0.0.1/src/pyrsql/parsing/limits.py +15 -0
  60. pyrsql-0.0.1/src/pyrsql/parsing/operators.py +201 -0
  61. pyrsql-0.0.1/src/pyrsql/parsing/parser.py +292 -0
  62. pyrsql-0.0.1/src/pyrsql/parsing/source.py +48 -0
  63. pyrsql-0.0.1/src/pyrsql/parsing/tokens.py +30 -0
  64. pyrsql-0.0.1/src/pyrsql/py.typed +0 -0
  65. pyrsql-0.0.1/src/pyrsql/selector/__init__.py +30 -0
  66. pyrsql-0.0.1/src/pyrsql/selector/analyzer.py +58 -0
  67. pyrsql-0.0.1/src/pyrsql/selector/ast.py +31 -0
  68. pyrsql-0.0.1/src/pyrsql/selector/parser.py +130 -0
  69. pyrsql-0.0.1/src/pyrsql/selector/semantic.py +34 -0
  70. pyrsql-0.0.1/src/pyrsql/semantic/__init__.py +23 -0
  71. pyrsql-0.0.1/src/pyrsql/semantic/analyzer.py +116 -0
  72. pyrsql-0.0.1/src/pyrsql/semantic/ast.py +35 -0
  73. pyrsql-0.0.1/src/pyrsql/semantic/errors.py +40 -0
  74. pyrsql-0.0.1/src/pyrsql/sorting/__init__.py +26 -0
  75. pyrsql-0.0.1/src/pyrsql/sorting/analyzer.py +74 -0
  76. pyrsql-0.0.1/src/pyrsql/sorting/ast.py +46 -0
  77. pyrsql-0.0.1/src/pyrsql/sorting/errors.py +21 -0
  78. pyrsql-0.0.1/src/pyrsql/sorting/limits.py +15 -0
  79. pyrsql-0.0.1/src/pyrsql/sorting/parser.py +150 -0
  80. pyrsql-0.0.1/src/pyrsql/sorting/semantic.py +15 -0
  81. pyrsql-0.0.1/tests/conftest.py +31 -0
  82. pyrsql-0.0.1/tests/fixtures/__init__.py +1 -0
  83. pyrsql-0.0.1/tests/fixtures/orms.py +1 -0
  84. pyrsql-0.0.1/tests/fixtures/query_samples.py +1 -0
  85. pyrsql-0.0.1/tests/fixtures/sqlalchemy_models.py +1 -0
  86. pyrsql-0.0.1/tests/functional/__init__.py +1 -0
  87. pyrsql-0.0.1/tests/functional/fastapi_adapter/__init__.py +1 -0
  88. pyrsql-0.0.1/tests/functional/fastapi_adapter/test_dependency.py +196 -0
  89. pyrsql-0.0.1/tests/functional/fastapi_sqlalchemy/__init__.py +1 -0
  90. pyrsql-0.0.1/tests/functional/fastapi_sqlalchemy/test_integration.py +126 -0
  91. pyrsql-0.0.1/tests/functional/test_public_api.py +80 -0
  92. pyrsql-0.0.1/tests/integration/__init__.py +1 -0
  93. pyrsql-0.0.1/tests/integration/sqlalchemy/__init__.py +1 -0
  94. pyrsql-0.0.1/tests/integration/sqlalchemy/test_page_pipeline.py +65 -0
  95. pyrsql-0.0.1/tests/integration/sqlalchemy/test_query_pipeline.py +521 -0
  96. pyrsql-0.0.1/tests/integration/sqlalchemy/test_sort_pipeline.py +177 -0
  97. pyrsql-0.0.1/tests/performance/__init__.py +1 -0
  98. pyrsql-0.0.1/tests/performance/test_conversion_bench.py +40 -0
  99. pyrsql-0.0.1/tests/performance/test_json_bench.py +55 -0
  100. pyrsql-0.0.1/tests/performance/test_parser_bench.py +35 -0
  101. pyrsql-0.0.1/tests/performance/test_selector_bench.py +27 -0
  102. pyrsql-0.0.1/tests/performance/test_semantic_bench.py +36 -0
  103. pyrsql-0.0.1/tests/performance/test_sqlalchemy_translation_bench.py +68 -0
  104. pyrsql-0.0.1/tests/unit/adapters/fastapi_adapter/__init__.py +1 -0
  105. pyrsql-0.0.1/tests/unit/adapters/fastapi_adapter/test_config.py +40 -0
  106. pyrsql-0.0.1/tests/unit/adapters/fastapi_adapter/test_criteria.py +83 -0
  107. pyrsql-0.0.1/tests/unit/core/__init__.py +1 -0
  108. pyrsql-0.0.1/tests/unit/core/json/__init__.py +1 -0
  109. pyrsql-0.0.1/tests/unit/core/json/test_options.py +32 -0
  110. pyrsql-0.0.1/tests/unit/core/json/test_path.py +20 -0
  111. pyrsql-0.0.1/tests/unit/core/json/test_query.py +28 -0
  112. pyrsql-0.0.1/tests/unit/core/json/test_values.py +21 -0
  113. pyrsql-0.0.1/tests/unit/core/test_conversion.py +109 -0
  114. pyrsql-0.0.1/tests/unit/core/test_options.py +160 -0
  115. pyrsql-0.0.1/tests/unit/core/test_page.py +99 -0
  116. pyrsql-0.0.1/tests/unit/core/test_query.py +87 -0
  117. pyrsql-0.0.1/tests/unit/core/test_sort.py +62 -0
  118. pyrsql-0.0.1/tests/unit/integrations/__init__.py +1 -0
  119. pyrsql-0.0.1/tests/unit/integrations/fastapi/__init__.py +1 -0
  120. pyrsql-0.0.1/tests/unit/integrations/fastapi_sqlalchemy/__init__.py +1 -0
  121. pyrsql-0.0.1/tests/unit/integrations/fastapi_sqlalchemy/test_integration.py +136 -0
  122. pyrsql-0.0.1/tests/unit/orms/__init__.py +1 -0
  123. pyrsql-0.0.1/tests/unit/orms/sqlalchemy/__init__.py +1 -0
  124. pyrsql-0.0.1/tests/unit/orms/sqlalchemy/test_resolver.py +187 -0
  125. pyrsql-0.0.1/tests/unit/parsing/__init__.py +1 -0
  126. pyrsql-0.0.1/tests/unit/parsing/test_lexer.py +78 -0
  127. pyrsql-0.0.1/tests/unit/parsing/test_parser.py +108 -0
  128. pyrsql-0.0.1/tests/unit/selector/__init__.py +1 -0
  129. pyrsql-0.0.1/tests/unit/selector/test_parser.py +13 -0
  130. pyrsql-0.0.1/tests/unit/semantic/__init__.py +1 -0
  131. pyrsql-0.0.1/tests/unit/semantic/test_analyzer.py +93 -0
  132. pyrsql-0.0.1/tests/unit/sorting/__init__.py +1 -0
  133. pyrsql-0.0.1/tests/unit/sorting/test_analyzer.py +80 -0
  134. pyrsql-0.0.1/tests/unit/sorting/test_parser.py +81 -0
pyrsql-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,72 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyrsql
3
+ Version: 0.0.1
4
+ Summary: ORM-oriented RSQL support for Python applications.
5
+ Keywords: rsql,orm,sqlalchemy,fastapi,query-language,rest
6
+ License-Expression: MIT
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Classifier: Framework :: FastAPI
15
+ Classifier: Topic :: Database
16
+ Requires-Dist: ciso8601>=2.3,<3.0
17
+ Requires-Dist: msgspec>=0.18,<1.0
18
+ Requires-Dist: typing-extensions>=4.10.0 ; python_full_version < '3.11'
19
+ Requires-Dist: fastapi>=0.110,<1.0 ; extra == 'fastapi'
20
+ Requires-Dist: sqlalchemy>=2.0,<3.0 ; extra == 'sqlalchemy'
21
+ Requires-Python: >=3.10
22
+ Project-URL: Homepage, https://github.com/wskr00/pyrsql
23
+ Project-URL: Repository, https://github.com/wskr00/pyrsql
24
+ Project-URL: Issues, https://github.com/wskr00/pyrsql/issues
25
+ Project-URL: Documentation, https://github.com/wskr00/pyrsql/blob/main/README.md
26
+ Provides-Extra: fastapi
27
+ Provides-Extra: sqlalchemy
28
+ Description-Content-Type: text/markdown
29
+
30
+ ## pyrsql
31
+
32
+ `pyrsql` is an ORM-oriented RSQL library for Python.
33
+
34
+ The project is being designed to support multiple ORMs, starting with
35
+ `SQLAlchemy 2.0`. The core package remains ORM-neutral, while ORM
36
+ implementations live in `orms`, and framework-specific integration lives
37
+ in `adapters`.
38
+
39
+ Current `SQLAlchemy` support includes:
40
+
41
+ - filters
42
+ - sorting
43
+ - pagination
44
+ - `distinct`
45
+ - `join_hints`
46
+ - PostgreSQL-style JSON / JSONB path support
47
+ - temporal JSON path semantics via `JSONOptions(use_datetime=True)`
48
+
49
+ Current adapter support includes:
50
+
51
+ - `FastAPI` request extraction via dependencies
52
+ - configurable `filter`, `sort`, `page`, and `size` parameters
53
+ - class-based and factory-based FastAPI dependencies
54
+ - `HTTP 422` translation for pyrsql parse and semantic failures
55
+
56
+ ## Development Principles
57
+
58
+ - Object-oriented design
59
+ - SOLID principles
60
+ - Google Python Style Guide
61
+ - Strong typing
62
+ - ORM-neutral public API
63
+
64
+ ## Documentation
65
+
66
+ - [Architecture](docs/architecture.md)
67
+ - [Usage](docs/usage.md)
68
+ - [Reference](docs/reference.md)
69
+ - [FastAPI Adapter Usage](docs/usage.md#fastapi-adapter)
70
+ - [Google Python Style Guide](docs/pyguide.md)
71
+ - [Quality and Tooling](docs/quality.md)
72
+ - [Testing](docs/testing.md)
pyrsql-0.0.1/README.md ADDED
@@ -0,0 +1,43 @@
1
+ ## pyrsql
2
+
3
+ `pyrsql` is an ORM-oriented RSQL library for Python.
4
+
5
+ The project is being designed to support multiple ORMs, starting with
6
+ `SQLAlchemy 2.0`. The core package remains ORM-neutral, while ORM
7
+ implementations live in `orms`, and framework-specific integration lives
8
+ in `adapters`.
9
+
10
+ Current `SQLAlchemy` support includes:
11
+
12
+ - filters
13
+ - sorting
14
+ - pagination
15
+ - `distinct`
16
+ - `join_hints`
17
+ - PostgreSQL-style JSON / JSONB path support
18
+ - temporal JSON path semantics via `JSONOptions(use_datetime=True)`
19
+
20
+ Current adapter support includes:
21
+
22
+ - `FastAPI` request extraction via dependencies
23
+ - configurable `filter`, `sort`, `page`, and `size` parameters
24
+ - class-based and factory-based FastAPI dependencies
25
+ - `HTTP 422` translation for pyrsql parse and semantic failures
26
+
27
+ ## Development Principles
28
+
29
+ - Object-oriented design
30
+ - SOLID principles
31
+ - Google Python Style Guide
32
+ - Strong typing
33
+ - ORM-neutral public API
34
+
35
+ ## Documentation
36
+
37
+ - [Architecture](docs/architecture.md)
38
+ - [Usage](docs/usage.md)
39
+ - [Reference](docs/reference.md)
40
+ - [FastAPI Adapter Usage](docs/usage.md#fastapi-adapter)
41
+ - [Google Python Style Guide](docs/pyguide.md)
42
+ - [Quality and Tooling](docs/quality.md)
43
+ - [Testing](docs/testing.md)
@@ -0,0 +1,461 @@
1
+ # pyrsql Architecture and Project Decisions
2
+
3
+ ## Purpose
4
+
5
+ `pyrsql` is a Python library that translates RSQL-like queries into
6
+ ORM-specific query objects.
7
+
8
+ The project is being designed from the start to support multiple ORMs in
9
+ the future, such as:
10
+
11
+ - `SQLAlchemy`
12
+ - `Django ORM`
13
+ - other ORMs if they fit the abstraction model
14
+
15
+ The initial implementation target is `SQLAlchemy 2.0`.
16
+
17
+ ## Current Scope
18
+
19
+ The current focus is:
20
+
21
+ - define the project architecture correctly before implementation
22
+ - keep the core ORM-oriented
23
+ - implement the first production ORM for `SQLAlchemy 2.0`
24
+
25
+ The following items are intentionally out of the MVP:
26
+
27
+ - `JSON` / `JSONB`
28
+ - additional ORMs
29
+ - exact feature parity with `rsql-jpa`
30
+
31
+ ## High-Level Product Direction
32
+
33
+ `pyrsql` should be:
34
+
35
+ - object-oriented
36
+ - strongly typed
37
+ - extensible
38
+ - safe by default
39
+ - performant
40
+ - easy to understand and maintain
41
+
42
+ The API should use clean, stable, high-level names. ORM-specific behavior
43
+ must not leak into the public API naming unnecessarily.
44
+
45
+ ## Core Architecture Principle
46
+
47
+ The project must be split into:
48
+
49
+ - a ORM-oriented core
50
+ - one or more ORM implementations
51
+ - one or more framework adapters
52
+
53
+ The core must not import or depend on `SQLAlchemy` or any other ORM
54
+ implementation.
55
+
56
+ ORMs depend on the core, not the other way around.
57
+
58
+ Framework adapters also depend on the core, and may depend on one or more
59
+ ORMs.
60
+
61
+ This separation is required so that:
62
+
63
+ - `pip install pyrsql` installs only the core
64
+ - `pip install pyrsql[sqlalchemy]` enables SQLAlchemy integration
65
+ - `pip install pyrsql[fastapi,sqlalchemy]` enables HTTP adapter plus query
66
+ ORM
67
+ - future ORMs can be added without restructuring the project
68
+
69
+ ## Architectural Style
70
+
71
+ The project will follow:
72
+
73
+ - object-oriented design
74
+ - SOLID principles
75
+ - Google Python Style Guide
76
+
77
+ ### SOLID Interpretation for `pyrsql`
78
+
79
+ #### Single Responsibility Principle
80
+
81
+ Each major concern must live in its own component. For example:
82
+
83
+ - lexical analysis
84
+ - parsing
85
+ - AST modeling
86
+ - semantic validation
87
+ - type coercion
88
+ - ORM translation
89
+ - ORM application to a query object
90
+ - framework request and error adaptation
91
+
92
+ #### Open/Closed Principle
93
+
94
+ The system must be open for extension through new ORMs, adapters, and
95
+ custom strategies, while avoiding modification of the core design when new
96
+ capabilities are introduced.
97
+
98
+ #### Liskov Substitution Principle
99
+
100
+ ORM integrations must honor clear behavioral contracts so one ORM implementation
101
+ can be replaced by another without breaking the API semantics.
102
+
103
+ #### Interface Segregation Principle
104
+
105
+ Interfaces must remain small and focused. Avoid one oversized abstraction that
106
+ handles parsing, semantic analysis, translation, and execution concerns at
107
+ once.
108
+
109
+ #### Dependency Inversion Principle
110
+
111
+ The core must depend on abstractions, such as `Protocol` or `ABC` contracts,
112
+ rather than concrete ORM implementations.
113
+
114
+ ## Public API Direction
115
+
116
+ The public API should remain small, expressive, and orm-neutral.
117
+
118
+ Preferred public names:
119
+
120
+ - `parse(...)`
121
+ - `compile(...)`
122
+ - `apply(...)`
123
+
124
+ The naming of public functions should not vary by orm. For example, avoid
125
+ names such as:
126
+
127
+ - `apply_sqlalchemy(...)`
128
+ - `compile_django(...)`
129
+
130
+ Instead, ORM specialization should happen through injected ORM objects
131
+ or ORM-specific configured objects.
132
+
133
+ ## Object-Oriented API Direction
134
+
135
+ The project should prefer high-level object-oriented composition over a purely
136
+ procedural style.
137
+
138
+ Representative domain objects may include:
139
+
140
+ - `Query`
141
+ - `QueryOptions`
142
+ - `CompilationResult`
143
+ - `ORM`
144
+
145
+ Potential style directions include:
146
+
147
+ ```python
148
+ query = Query.parse("name==john")
149
+ compiled = query.compile(orm=orm)
150
+ stmt = compiled.apply(stmt, model=User)
151
+ ```
152
+
153
+ or:
154
+
155
+ ```python
156
+ stmt = apply(stmt, User, "name==john", orm=orm)
157
+ ```
158
+
159
+ The exact public surface can still be refined, but it must stay:
160
+
161
+ - cohesive
162
+ - orm-neutral in naming
163
+ - explicit in contracts
164
+
165
+ ## Parser Strategy
166
+
167
+ The parser will be built in-house rather than relying on an external RSQL
168
+ parser package.
169
+
170
+ ### Parser goals
171
+
172
+ - high performance
173
+ - memory efficiency
174
+ - strong control over syntax and error handling
175
+ - secure behavior under malformed or adversarial input
176
+
177
+ ### Parser design direction
178
+
179
+ - custom lexer
180
+ - custom parser
181
+ - immutable AST nodes
182
+ - configurable safety limits
183
+
184
+ Possible safety controls include:
185
+
186
+ - maximum query length
187
+ - maximum nesting depth
188
+ - maximum AST node count
189
+ - maximum argument count
190
+
191
+ ## ORM Strategy
192
+
193
+ The first ORM is `SQLAlchemy 2.0`.
194
+
195
+ Important constraints:
196
+
197
+ - use the `2.0` query model
198
+ - target `select(...)` workflows
199
+ - do not design around legacy `Query`
200
+
201
+ Future ORMs are expected, including `django`, but the current
202
+ implementation work should optimize for `SQLAlchemy` first without
203
+ contaminating the core abstractions.
204
+
205
+ ## Adapter Strategy
206
+
207
+ Framework-specific integration should live in adapters rather than ORMs.
208
+
209
+ Examples:
210
+
211
+ - `adapters.fastapi`
212
+ - `adapters.django`
213
+
214
+ The adapter layer is responsible for:
215
+
216
+ - request extraction
217
+ - transport-specific validation behavior
218
+ - transport-specific error conversion
219
+ - convenient binding to framework primitives
220
+
221
+ Adapters must not own the query language semantics. They orchestrate the core
222
+ and selected ORM for a specific runtime environment.
223
+
224
+ ## Packaging Strategy
225
+
226
+ The package name is `pyrsql`.
227
+
228
+ The project should support optional ORM installations through extras:
229
+
230
+ ```text
231
+ pip install pyrsql[sqlalchemy]
232
+ ```
233
+
234
+ Future examples:
235
+
236
+ ```text
237
+ pip install pyrsql[django]
238
+ pip install pyrsql[fastapi,sqlalchemy]
239
+ ```
240
+
241
+ ### Packaging rules
242
+
243
+ - base package contains only the core and shared abstractions
244
+ - ORM dependencies are optional
245
+ - adapter dependencies are optional
246
+ - development tooling lives in a separate extra
247
+
248
+ Representative `pyproject.toml` direction:
249
+
250
+ ```toml
251
+ [project.optional-dependencies]
252
+ sqlalchemy = ["sqlalchemy>=2.0"]
253
+ fastapi = ["fastapi>=0.110"]
254
+ django = ["django>=5.0"]
255
+ dev = ["pytest", "pylint", "mypy", "black", "isort"]
256
+ ```
257
+
258
+ ## Project Structure Direction
259
+
260
+ The package should be prepared for multiple ORMs from the beginning.
261
+
262
+ Suggested structure:
263
+
264
+ ```text
265
+ src/pyrsql/
266
+ __init__.py
267
+ api/
268
+ core/
269
+ parsing/
270
+ orms/
271
+ base.py
272
+ sqlalchemy/
273
+ __init__.py
274
+ orm.py
275
+ translator.py
276
+ resolver.py
277
+ django/
278
+ __init__.py
279
+ orm.py
280
+ translator.py
281
+ resolver.py
282
+ adapters/
283
+ fastapi/
284
+ __init__.py
285
+ dependency.py
286
+ errors.py
287
+ django/
288
+ __init__.py
289
+ request.py
290
+ errors.py
291
+ errors.py
292
+
293
+ docs/
294
+ tests/
295
+ unit/
296
+ integration/
297
+ ```
298
+
299
+ This structure can still evolve, but the major boundaries should remain stable.
300
+
301
+ ## Core Components
302
+
303
+ The ORM-oriented core is expected to contain:
304
+
305
+ - operators and operator metadata
306
+ - lexer
307
+ - parser
308
+ - AST
309
+ - semantic validation
310
+ - property remapping support
311
+ - whitelist and blacklist support
312
+ - type coercion infrastructure
313
+ - shared exceptions
314
+ - query and compilation abstractions
315
+
316
+ ## ORM Components
317
+
318
+ The `SQLAlchemy` ORM is expected to contain:
319
+
320
+ - path resolution
321
+ - relationship and join planning
322
+ - AST to predicate translation
323
+ - application of compiled output to a `Select`
324
+
325
+ The ORM layer should handle ORM-specific behavior without leaking those
326
+ details into the core model.
327
+
328
+ Future ORMs are expected to follow the same responsibility split,
329
+ including `django` as a query orm.
330
+
331
+ ## Adapter Components
332
+
333
+ Adapters are separate from ORM implementations.
334
+
335
+ Examples:
336
+
337
+ - `adapters.fastapi`
338
+ - `adapters.django`
339
+
340
+ Adapters should contain framework-facing concerns such as:
341
+
342
+ - extracting query text from requests
343
+ - mapping parsing and validation failures to framework errors
344
+ - offering convenience helpers for framework-native usage
345
+
346
+ An adapter may depend on a orm, but an ORM must not depend on an
347
+ adapter.
348
+
349
+ ## Quality Standards
350
+
351
+ The project must be built with strict quality gates from the beginning.
352
+
353
+ Required tooling direction:
354
+
355
+ - `pytest`
356
+ - `pylint`
357
+ - `mypy`
358
+ - `black`
359
+ - `isort`
360
+
361
+ Additional quality expectations:
362
+
363
+ - strong unit coverage for core logic
364
+ - integration tests for ORM behavior
365
+ - clear exception model
366
+ - good internal naming
367
+ - minimal accidental complexity
368
+
369
+ ## Code Style and Language Conventions
370
+
371
+ The baseline style reference is the Google Python Style Guide.
372
+
373
+ Key practical implications:
374
+
375
+ - clear names
376
+ - readable structure
377
+ - explicit responsibilities
378
+ - consistent docstrings
379
+ - predictable formatting
380
+ - typed interfaces where useful
381
+
382
+ Python features should be used when they improve correctness, readability,
383
+ architecture, or performance.
384
+
385
+ Examples of acceptable advanced usage:
386
+
387
+ - `dataclasses`
388
+ - `slots`
389
+ - `Protocol`
390
+ - `ABC`
391
+ - generics
392
+ - immutable value objects where appropriate
393
+
394
+ These features must be used deliberately, not performatively.
395
+
396
+ ## Design Preferences
397
+
398
+ The project should avoid:
399
+
400
+ - giant procedural helper modules
401
+ - ORM-specific logic in the core
402
+ - adapter-specific transport logic in the core
403
+ - unstable or overly clever APIs
404
+ - naming that changes by ORM
405
+ - unnecessary exact compatibility constraints with `rsql-jpa`
406
+
407
+ The project should favor:
408
+
409
+ - explicit domain objects
410
+ - narrow contracts
411
+ - composition
412
+ - immutability where it helps
413
+ - extension points that do not distort the core model
414
+
415
+ ## MVP Functional Direction
416
+
417
+ The first implementation phase should focus on:
418
+
419
+ - query parsing
420
+ - AST generation
421
+ - semantic validation
422
+ - SQLAlchemy 2.0 translation
423
+ - high-quality tests
424
+
425
+ Representative operator coverage for the MVP:
426
+
427
+ - equality and inequality
428
+ - comparison operators
429
+ - `IN` / `NOT IN`
430
+ - null checks
431
+ - `LIKE` / case-insensitive `LIKE`
432
+ - boolean composition with `AND` / `OR`
433
+ - parentheses
434
+
435
+ The operator set does not need to be a perfect clone of the Java project as
436
+ long as the model is coherent and useful.
437
+
438
+ ## Deferred Features
439
+
440
+ These items are intentionally postponed:
441
+
442
+ - `JSON` / `JSONB`
443
+ - secondary ORMs
444
+ - advanced ORM-specific features that would distort the initial
445
+ architecture
446
+
447
+ ## Documentation Direction
448
+
449
+ The project should keep a dedicated `docs/` folder.
450
+
451
+ Documentation should capture:
452
+
453
+ - architecture decisions
454
+ - public API decisions
455
+ - packaging decisions
456
+ - coding standards
457
+ - testing standards
458
+ - implementation phases
459
+
460
+ This file is the initial consolidation of the decisions made before coding
461
+ begins.