cinchdb 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 (68) hide show
  1. cinchdb/__init__.py +7 -0
  2. cinchdb/__main__.py +6 -0
  3. cinchdb/api/__init__.py +5 -0
  4. cinchdb/api/app.py +76 -0
  5. cinchdb/api/auth.py +290 -0
  6. cinchdb/api/main.py +137 -0
  7. cinchdb/api/routers/__init__.py +25 -0
  8. cinchdb/api/routers/auth.py +135 -0
  9. cinchdb/api/routers/branches.py +368 -0
  10. cinchdb/api/routers/codegen.py +164 -0
  11. cinchdb/api/routers/columns.py +290 -0
  12. cinchdb/api/routers/data.py +479 -0
  13. cinchdb/api/routers/databases.py +177 -0
  14. cinchdb/api/routers/projects.py +133 -0
  15. cinchdb/api/routers/query.py +156 -0
  16. cinchdb/api/routers/tables.py +349 -0
  17. cinchdb/api/routers/tenants.py +216 -0
  18. cinchdb/api/routers/views.py +219 -0
  19. cinchdb/cli/__init__.py +0 -0
  20. cinchdb/cli/commands/__init__.py +1 -0
  21. cinchdb/cli/commands/branch.py +479 -0
  22. cinchdb/cli/commands/codegen.py +176 -0
  23. cinchdb/cli/commands/column.py +308 -0
  24. cinchdb/cli/commands/database.py +212 -0
  25. cinchdb/cli/commands/query.py +136 -0
  26. cinchdb/cli/commands/remote.py +144 -0
  27. cinchdb/cli/commands/table.py +289 -0
  28. cinchdb/cli/commands/tenant.py +173 -0
  29. cinchdb/cli/commands/view.py +189 -0
  30. cinchdb/cli/handlers/__init__.py +5 -0
  31. cinchdb/cli/handlers/codegen_handler.py +189 -0
  32. cinchdb/cli/main.py +137 -0
  33. cinchdb/cli/utils.py +182 -0
  34. cinchdb/config.py +177 -0
  35. cinchdb/core/__init__.py +5 -0
  36. cinchdb/core/connection.py +175 -0
  37. cinchdb/core/database.py +537 -0
  38. cinchdb/core/maintenance.py +73 -0
  39. cinchdb/core/path_utils.py +153 -0
  40. cinchdb/managers/__init__.py +26 -0
  41. cinchdb/managers/branch.py +167 -0
  42. cinchdb/managers/change_applier.py +414 -0
  43. cinchdb/managers/change_comparator.py +194 -0
  44. cinchdb/managers/change_tracker.py +182 -0
  45. cinchdb/managers/codegen.py +523 -0
  46. cinchdb/managers/column.py +579 -0
  47. cinchdb/managers/data.py +455 -0
  48. cinchdb/managers/merge_manager.py +429 -0
  49. cinchdb/managers/query.py +214 -0
  50. cinchdb/managers/table.py +383 -0
  51. cinchdb/managers/tenant.py +258 -0
  52. cinchdb/managers/view.py +252 -0
  53. cinchdb/models/__init__.py +27 -0
  54. cinchdb/models/base.py +44 -0
  55. cinchdb/models/branch.py +26 -0
  56. cinchdb/models/change.py +47 -0
  57. cinchdb/models/database.py +20 -0
  58. cinchdb/models/project.py +20 -0
  59. cinchdb/models/table.py +86 -0
  60. cinchdb/models/tenant.py +19 -0
  61. cinchdb/models/view.py +15 -0
  62. cinchdb/utils/__init__.py +15 -0
  63. cinchdb/utils/sql_validator.py +137 -0
  64. cinchdb-0.1.0.dist-info/METADATA +195 -0
  65. cinchdb-0.1.0.dist-info/RECORD +68 -0
  66. cinchdb-0.1.0.dist-info/WHEEL +4 -0
  67. cinchdb-0.1.0.dist-info/entry_points.txt +3 -0
  68. cinchdb-0.1.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,182 @@
1
+ """Change tracking for CinchDB."""
2
+
3
+ import json
4
+ from pathlib import Path
5
+ from typing import List
6
+ from datetime import datetime, timezone
7
+
8
+ from cinchdb.models import Change
9
+ from cinchdb.core.path_utils import get_branch_path
10
+
11
+
12
+ class ChangeTracker:
13
+ """Tracks schema changes within a branch."""
14
+
15
+ def __init__(self, project_root: Path, database: str, branch: str):
16
+ """Initialize change tracker.
17
+
18
+ Args:
19
+ project_root: Path to project root
20
+ database: Database name
21
+ branch: Branch name
22
+ """
23
+ self.project_root = Path(project_root)
24
+ self.database = database
25
+ self.branch = branch
26
+ self.branch_path = get_branch_path(self.project_root, database, branch)
27
+ self.changes_file = self.branch_path / "changes.json"
28
+
29
+ def get_changes(self) -> List[Change]:
30
+ """Get all changes for the branch.
31
+
32
+ Returns:
33
+ List of Change objects
34
+ """
35
+ if not self.changes_file.exists():
36
+ return []
37
+
38
+ with open(self.changes_file, "r") as f:
39
+ changes_data = json.load(f)
40
+
41
+ changes = []
42
+ for data in changes_data:
43
+ # Convert string dates back to datetime
44
+ if data.get("created_at"):
45
+ data["created_at"] = datetime.fromisoformat(data["created_at"])
46
+ if data.get("updated_at"):
47
+ data["updated_at"] = datetime.fromisoformat(data["updated_at"])
48
+
49
+ change = Change(**data)
50
+ changes.append(change)
51
+
52
+ return changes
53
+
54
+ def add_change(self, change: Change) -> Change:
55
+ """Add a new change to the branch.
56
+
57
+ Args:
58
+ change: Change object to add
59
+
60
+ Returns:
61
+ The added Change object with ID and timestamp
62
+ """
63
+ # Get existing changes
64
+ changes = self.get_changes()
65
+
66
+ # Ensure change has required fields
67
+ if not change.id:
68
+ import uuid
69
+
70
+ change.id = str(uuid.uuid4())
71
+
72
+ if not change.created_at:
73
+ change.created_at = datetime.now(timezone.utc)
74
+
75
+ # Add to list
76
+ changes.append(change)
77
+
78
+ # Save
79
+ self._save_changes(changes)
80
+
81
+ return change
82
+
83
+ def get_unapplied_changes(self) -> List[Change]:
84
+ """Get all unapplied changes.
85
+
86
+ Returns:
87
+ List of unapplied Change objects
88
+ """
89
+ changes = self.get_changes()
90
+ return [c for c in changes if not c.applied]
91
+
92
+ def mark_change_applied(self, change_id: str) -> None:
93
+ """Mark a change as applied.
94
+
95
+ Args:
96
+ change_id: ID of change to mark as applied
97
+ """
98
+ changes = self.get_changes()
99
+
100
+ for change in changes:
101
+ if change.id == change_id:
102
+ change.applied = True
103
+ change.updated_at = datetime.now(timezone.utc)
104
+ break
105
+
106
+ self._save_changes(changes)
107
+
108
+ def get_changes_since(self, change_id: str) -> List[Change]:
109
+ """Get all changes after a specific change.
110
+
111
+ Args:
112
+ change_id: ID of change to start after
113
+
114
+ Returns:
115
+ List of Change objects after the specified change
116
+ """
117
+ changes = self.get_changes()
118
+
119
+ # Find the index of the specified change
120
+ start_index = None
121
+ for i, change in enumerate(changes):
122
+ if change.id == change_id:
123
+ start_index = i + 1
124
+ break
125
+
126
+ if start_index is None:
127
+ return []
128
+
129
+ return changes[start_index:]
130
+
131
+ def clear_changes(self) -> None:
132
+ """Clear all changes from the branch."""
133
+ self._save_changes([])
134
+
135
+ def has_change_id(self, change_id: str) -> bool:
136
+ """Check if a change ID exists.
137
+
138
+ Args:
139
+ change_id: ID to check
140
+
141
+ Returns:
142
+ True if change exists
143
+ """
144
+ changes = self.get_changes()
145
+ return any(c.id == change_id for c in changes)
146
+
147
+ def remove_change(self, change_id: str) -> bool:
148
+ """Remove a change from the branch.
149
+
150
+ Args:
151
+ change_id: ID of change to remove
152
+
153
+ Returns:
154
+ True if change was removed, False if not found
155
+ """
156
+ changes = self.get_changes()
157
+
158
+ # Find and remove the change
159
+ for i, change in enumerate(changes):
160
+ if change.id == change_id:
161
+ changes.pop(i)
162
+ self._save_changes(changes)
163
+ return True
164
+
165
+ return False
166
+
167
+ def _save_changes(self, changes: List[Change]) -> None:
168
+ """Save changes to disk.
169
+
170
+ Args:
171
+ changes: List of Change objects to save
172
+ """
173
+ # Convert to JSON-serializable format
174
+ changes_data = []
175
+ for change in changes:
176
+ # model_dump with mode='json' handles datetime serialization
177
+ data = change.model_dump(mode="json")
178
+ changes_data.append(data)
179
+
180
+ # Save to file
181
+ with open(self.changes_file, "w") as f:
182
+ json.dump(changes_data, f, indent=2)