oxyde-postgres 0.1.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.
Files changed (66) hide show
  1. oxyde/__init__.py +151 -0
  2. oxyde/_msgpack.py +3 -0
  3. oxyde/cli/__init__.py +7 -0
  4. oxyde/cli/app.py +107 -0
  5. oxyde/cli/codegen.py +66 -0
  6. oxyde/cli/config.py +84 -0
  7. oxyde/cli/migrations.py +536 -0
  8. oxyde/codegen/__init__.py +15 -0
  9. oxyde/codegen/stub_generator.py +1229 -0
  10. oxyde/core/__init__.py +90 -0
  11. oxyde/core/column_types.py +367 -0
  12. oxyde/core/ir.py +380 -0
  13. oxyde/core/types.py +69 -0
  14. oxyde/core/wrapper.py +242 -0
  15. oxyde/db/__init__.py +230 -0
  16. oxyde/db/pool.py +305 -0
  17. oxyde/db/registry.py +113 -0
  18. oxyde/db/schema.py +51 -0
  19. oxyde/db/transaction.py +392 -0
  20. oxyde/exceptions.py +89 -0
  21. oxyde/migrations/__init__.py +49 -0
  22. oxyde/migrations/config.py +187 -0
  23. oxyde/migrations/context.py +598 -0
  24. oxyde/migrations/executor.py +456 -0
  25. oxyde/migrations/extract.py +316 -0
  26. oxyde/migrations/generator.py +534 -0
  27. oxyde/migrations/replay.py +367 -0
  28. oxyde/migrations/squash.py +109 -0
  29. oxyde/migrations/tracker.py +162 -0
  30. oxyde/migrations/utils.py +145 -0
  31. oxyde/models/__init__.py +83 -0
  32. oxyde/models/base.py +871 -0
  33. oxyde/models/decorators.py +111 -0
  34. oxyde/models/field.py +204 -0
  35. oxyde/models/lookups.py +667 -0
  36. oxyde/models/metadata.py +174 -0
  37. oxyde/models/registry.py +170 -0
  38. oxyde/models/serializers.py +144 -0
  39. oxyde/models/utils.py +116 -0
  40. oxyde/py.typed +0 -0
  41. oxyde/queries/__init__.py +79 -0
  42. oxyde/queries/aggregates.py +145 -0
  43. oxyde/queries/base.py +249 -0
  44. oxyde/queries/conditions.py +92 -0
  45. oxyde/queries/expressions.py +171 -0
  46. oxyde/queries/insert.py +124 -0
  47. oxyde/queries/joins.py +66 -0
  48. oxyde/queries/manager.py +409 -0
  49. oxyde/queries/mixins/__init__.py +68 -0
  50. oxyde/queries/mixins/aggregation.py +335 -0
  51. oxyde/queries/mixins/debug.py +154 -0
  52. oxyde/queries/mixins/execution.py +701 -0
  53. oxyde/queries/mixins/filtering.py +144 -0
  54. oxyde/queries/mixins/joining.py +160 -0
  55. oxyde/queries/mixins/mutation.py +508 -0
  56. oxyde/queries/mixins/pagination.py +145 -0
  57. oxyde/queries/q.py +250 -0
  58. oxyde/queries/raw.py +114 -0
  59. oxyde/queries/select.py +345 -0
  60. oxyde/queries/typed.py +213 -0
  61. oxyde_postgres-0.1.0.dist-info/METADATA +141 -0
  62. oxyde_postgres-0.1.0.dist-info/RECORD +66 -0
  63. oxyde_postgres-0.1.0.dist-info/WHEEL +5 -0
  64. oxyde_postgres-0.1.0.dist-info/entry_points.txt +2 -0
  65. oxyde_postgres-0.1.0.dist-info/licenses/LICENSE +21 -0
  66. oxyde_postgres-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,187 @@
1
+ """Configuration loading from oxyde_config.py."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import importlib
6
+ import sys
7
+ from dataclasses import dataclass, field
8
+ from pathlib import Path
9
+
10
+ import typer
11
+
12
+
13
+ @dataclass
14
+ class OxydeConfig:
15
+ """Oxyde configuration."""
16
+
17
+ models: list[str] = field(default_factory=list)
18
+ dialect: str = "postgres"
19
+ migrations_dir: str = "migrations"
20
+ databases: dict[str, str] = field(default_factory=dict)
21
+
22
+ def __post_init__(self) -> None:
23
+ from oxyde.migrations.utils import validate_dialect
24
+
25
+ validate_dialect(self.dialect)
26
+
27
+
28
+ def load_config() -> OxydeConfig | None:
29
+ """Load configuration from oxyde_config.py.
30
+
31
+ Returns:
32
+ OxydeConfig if oxyde_config.py exists and is valid, None otherwise.
33
+ """
34
+ config_path = Path("oxyde_config.py")
35
+
36
+ if not config_path.exists():
37
+ return None
38
+
39
+ # Add current directory to path for import
40
+ if "." not in sys.path:
41
+ sys.path.insert(0, ".")
42
+
43
+ try:
44
+ # Import the config module
45
+ if "oxyde_config" in sys.modules:
46
+ # Reload if already imported
47
+ importlib.reload(sys.modules["oxyde_config"])
48
+ config_module = sys.modules["oxyde_config"]
49
+ else:
50
+ config_module = importlib.import_module("oxyde_config")
51
+
52
+ # Extract config values
53
+ models = getattr(config_module, "MODELS", [])
54
+ dialect = getattr(config_module, "DIALECT", "postgres")
55
+ migrations_dir = getattr(config_module, "MIGRATIONS_DIR", "migrations")
56
+ databases = getattr(config_module, "DATABASES", {})
57
+
58
+ return OxydeConfig(
59
+ models=models,
60
+ dialect=dialect,
61
+ migrations_dir=migrations_dir,
62
+ databases=databases,
63
+ )
64
+
65
+ except Exception:
66
+ return None
67
+
68
+
69
+ def import_models(modules: list[str]) -> int:
70
+ """Import modules to register models.
71
+
72
+ Args:
73
+ modules: List of module names to import.
74
+
75
+ Returns:
76
+ Number of successfully imported modules.
77
+ """
78
+ # Add current directory to path for local imports
79
+ if "." not in sys.path:
80
+ sys.path.insert(0, ".")
81
+
82
+ imported = 0
83
+ for module_name in modules:
84
+ try:
85
+ importlib.import_module(module_name)
86
+ imported += 1
87
+ except ImportError as e:
88
+ typer.secho(
89
+ f" ⚠️ Failed to import '{module_name}': {e}",
90
+ fg=typer.colors.YELLOW,
91
+ )
92
+
93
+ return imported
94
+
95
+
96
+ def generate_config_file(
97
+ models: list[str],
98
+ dialect: str = "postgres",
99
+ migrations_dir: str = "migrations",
100
+ databases: dict[str, str] | None = None,
101
+ ) -> str:
102
+ """Generate oxyde_config.py content.
103
+
104
+ Args:
105
+ models: List of model modules.
106
+ dialect: Database dialect.
107
+ migrations_dir: Migrations directory.
108
+ databases: Database connection URLs.
109
+
110
+ Returns:
111
+ Generated Python file content.
112
+ """
113
+ from oxyde.migrations.utils import detect_dialect, validate_dialect
114
+
115
+ validate_dialect(dialect)
116
+ for url in (databases or {}).values():
117
+ detect_dialect(url)
118
+ if databases is None:
119
+ databases = {"default": "postgresql://localhost/mydb"}
120
+
121
+ models_str = ", ".join(f'"{m}"' for m in models)
122
+
123
+ # Format databases dict
124
+ db_lines = []
125
+ for name, url in databases.items():
126
+ db_lines.append(f' "{name}": "{url}",')
127
+ databases_str = "\n".join(db_lines)
128
+
129
+ return f'''"""Oxyde ORM configuration."""
130
+
131
+ # List of Python modules containing Model classes
132
+ MODELS = [{models_str}]
133
+
134
+ # Database dialect: "postgres"
135
+ DIALECT = "{dialect}"
136
+
137
+ # Directory for migration files
138
+ MIGRATIONS_DIR = "{migrations_dir}"
139
+
140
+ # Database connections
141
+ # Keys are connection aliases, values are connection URLs
142
+ DATABASES = {{
143
+ {databases_str}
144
+ }}
145
+ '''
146
+
147
+
148
+ def save_config(
149
+ models: list[str],
150
+ dialect: str = "postgres",
151
+ migrations_dir: str = "migrations",
152
+ databases: dict[str, str] | None = None,
153
+ path: Path | None = None,
154
+ ) -> Path:
155
+ """Save configuration to oxyde_config.py.
156
+
157
+ Args:
158
+ models: List of model modules.
159
+ dialect: Database dialect.
160
+ migrations_dir: Migrations directory.
161
+ databases: Database connection URLs.
162
+ path: Path to config file. If None, uses current directory.
163
+
164
+ Returns:
165
+ Path to the created config file.
166
+ """
167
+ if path is None:
168
+ path = Path("oxyde_config.py")
169
+
170
+ content = generate_config_file(
171
+ models=models,
172
+ dialect=dialect,
173
+ migrations_dir=migrations_dir,
174
+ databases=databases,
175
+ )
176
+
177
+ path.write_text(content, encoding="utf-8")
178
+ return path
179
+
180
+
181
+ __all__ = [
182
+ "OxydeConfig",
183
+ "load_config",
184
+ "import_models",
185
+ "generate_config_file",
186
+ "save_config",
187
+ ]