django-datalog 0.1.0__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.
@@ -0,0 +1,51 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.pyc
6
+ *.pyo
7
+
8
+ # Django
9
+ *.log
10
+ db.sqlite3
11
+ db.sqlite3-journal
12
+ local_settings.py
13
+
14
+ # Testing and coverage
15
+ .pytest_cache/
16
+ .coverage
17
+ htmlcov/
18
+ .hypothesis/
19
+
20
+ # Virtual environments
21
+ .venv/
22
+ venv/
23
+ env/
24
+
25
+ # Package management
26
+
27
+ # Type checkers
28
+ .mypy_cache/
29
+ .ruff_cache/
30
+
31
+ # IDEs
32
+ .vscode/
33
+ .idea/
34
+
35
+ # Claude Code
36
+ .claude/
37
+
38
+ # macOS
39
+ .DS_Store
40
+
41
+ # Project debug files
42
+ debug_*.py
43
+ minimal_debug.py
44
+ simple_debug.py
45
+ test_fact_equality.py
46
+ test_rule_deduplication.py
47
+
48
+ # Distribution
49
+ build/
50
+ dist/
51
+ *.egg-info/
@@ -0,0 +1,44 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2025-01-21
9
+
10
+ Initial release of django-datalog - a complete datalog inference engine for Django applications.
11
+
12
+ ### Added
13
+ - Django Datalog engine with fact-based data modeling
14
+ - Logic programming with inference rules using Python syntax
15
+ - Query system with variable binding and constraint support
16
+ - Q object integration for filtering query results
17
+ - Performance optimizations including query reordering and batch hydration
18
+ - Modular architecture with separate facts, query, and rules modules
19
+ - Comprehensive test suite with family relationship examples
20
+ - Conditional test model loading for package testing
21
+ - Support for both hydrated objects and PK-only queries
22
+
23
+ ### Features
24
+ - **Fact Definition**: Define facts as Python dataclasses with Django model integration
25
+ - **Inference Rules**: Write rules to derive new facts from existing ones
26
+ - **Query Engine**: Query facts with variable binding and automatic inference
27
+ - **Django Q Objects**: Use Django's Q objects to add constraints to query variables
28
+ - **Performance**: Intelligent query planning and batch operations
29
+ - **Testing**: Built-in test framework with example models and facts
30
+
31
+ ### Performance
32
+ - Query reordering based on selectivity and variable constraints
33
+ - Batch hydration of model instances to reduce database queries
34
+ - PK-only query mode for improved performance when full objects aren't needed
35
+ - Cached model type metadata to avoid runtime type introspection
36
+
37
+ ### Technical
38
+ - Modular package structure separating facts, queries, and rules
39
+ - Automatic Django model generation from fact definitions
40
+ - Django app integration with proper migrations and settings
41
+ - Type hints throughout with support for Union types (Model | Var)
42
+ - Comprehensive error handling and validation
43
+
44
+ [0.1.0]: https://github.com/edelvalle/django-datalog/releases/tag/v0.1.0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Your Name
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.
@@ -0,0 +1,324 @@
1
+ Metadata-Version: 2.4
2
+ Name: django-datalog
3
+ Version: 0.1.0
4
+ Summary: Django Datalog - Logic programming and inference engine for Django applications
5
+ Project-URL: Homepage, https://github.com/edelvalle/django-datalog
6
+ Project-URL: Documentation, https://django-datalog.readthedocs.io/
7
+ Project-URL: Repository, https://github.com/edelvalle/django-datalog.git
8
+ Project-URL: Issues, https://github.com/edelvalle/django-datalog/issues
9
+ Project-URL: Changelog, https://github.com/edelvalle/django-datalog/blob/main/CHANGELOG.md
10
+ Author-email: Eddy Ernesto del Valle Pino <eddy@edelvalle.me>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: datalog,django,facts,inference-engine,logic-programming,query,rules
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Environment :: Web Environment
16
+ Classifier: Framework :: Django
17
+ Classifier: Framework :: Django :: 5.0
18
+ Classifier: Intended Audience :: Developers
19
+ Classifier: License :: OSI Approved :: MIT License
20
+ Classifier: Operating System :: OS Independent
21
+ Classifier: Programming Language :: Python
22
+ Classifier: Programming Language :: Python :: 3
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
26
+ Classifier: Programming Language :: Python :: 3.13
27
+ Classifier: Topic :: Internet :: WWW/HTTP
28
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
29
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
30
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
31
+ Requires-Python: >=3.10
32
+ Requires-Dist: django>=5
33
+ Requires-Dist: uuid6>=2024.1.12
34
+ Provides-Extra: dev
35
+ Requires-Dist: basedpyright>=1.12; extra == 'dev'
36
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
37
+ Requires-Dist: pytest-django>=4.5; extra == 'dev'
38
+ Requires-Dist: pytest>=7.0; extra == 'dev'
39
+ Requires-Dist: ruff>=0.1; extra == 'dev'
40
+ Provides-Extra: docs
41
+ Requires-Dist: mkdocs-material>=9.0; extra == 'docs'
42
+ Requires-Dist: mkdocs>=1.5; extra == 'docs'
43
+ Requires-Dist: mkdocstrings[python]>=0.24; extra == 'docs'
44
+ Provides-Extra: test
45
+ Requires-Dist: pytest-cov>=4.0; extra == 'test'
46
+ Requires-Dist: pytest-django>=4.5; extra == 'test'
47
+ Requires-Dist: pytest>=7.0; extra == 'test'
48
+ Description-Content-Type: text/markdown
49
+
50
+ # django-datalog
51
+
52
+ Django Datalog - A logic programming and inference engine for Django applications.
53
+
54
+ ## Features
55
+
56
+ - **Fact-based data modeling**: Define facts as Python classes that integrate seamlessly with Django models
57
+ - **Logic programming**: Write inference rules using a familiar Python syntax
58
+ - **Query system**: Query facts and derived conclusions with variable binding
59
+ - **Q object constraints**: Filter query results using Django Q objects for powerful filtering
60
+ - **Performance optimized**: Intelligent query reordering and batch hydration for optimal performance
61
+ - **Django integration**: Seamless integration with existing Django models and ORM
62
+
63
+ ## Quick Start
64
+
65
+ ### Installation
66
+
67
+ ```bash
68
+ pip install django-datalog
69
+ ```
70
+
71
+ Add `django_datalog` to your `INSTALLED_APPS`:
72
+
73
+ ```python
74
+ INSTALLED_APPS = [
75
+ # ... your other apps
76
+ 'django_datalog',
77
+ ]
78
+ ```
79
+
80
+ Run migrations to create the datalog fact tables:
81
+
82
+ ```bash
83
+ python manage.py migrate
84
+ ```
85
+
86
+ ### Basic Example: Company Employee Management
87
+
88
+ Let's start with a realistic business scenario - managing employees in a company:
89
+
90
+ ```python
91
+ # models.py
92
+ from django.db import models
93
+ from django.contrib.auth.models import User
94
+ from django_datalog.models import Fact, Var
95
+
96
+ class Company(models.Model):
97
+ name = models.CharField(max_length=100)
98
+
99
+ class Department(models.Model):
100
+ name = models.CharField(max_length=100)
101
+ company = models.ForeignKey(Company, on_delete=models.CASCADE)
102
+
103
+ class Employee(models.Model):
104
+ user = models.OneToOneField(User, on_delete=models.CASCADE)
105
+ company = models.ForeignKey(Company, on_delete=models.CASCADE)
106
+ department = models.ForeignKey(Department, on_delete=models.CASCADE)
107
+ is_manager = models.BooleanField(default=False)
108
+
109
+ # Define Facts - Note: No @dataclass decorator needed!
110
+ class WorksFor(Fact):
111
+ """Employee works for a company."""
112
+ subject: Employee | Var # Employee
113
+ object: Company | Var # Company
114
+
115
+ class MemberOf(Fact):
116
+ """Employee is member of a department."""
117
+ subject: Employee | Var # Employee
118
+ object: Department | Var # Department
119
+
120
+ class ColleaguesOf(Fact):
121
+ """Two employees are colleagues (inferred from working at same company)."""
122
+ subject: Employee | Var # Employee 1
123
+ object: Employee | Var # Employee 2
124
+
125
+ class TeamMates(Fact):
126
+ """Two employees are teammates (inferred from same department)."""
127
+ subject: Employee | Var # Employee 1
128
+ object: Employee | Var # Employee 2
129
+ ```
130
+
131
+ ```python
132
+ # rules.py - Define inference logic
133
+ from django_datalog.rules import rule
134
+ from django_datalog.models import Var
135
+ from .models import WorksFor, MemberOf, ColleaguesOf, TeamMates
136
+
137
+ # Rule: Employees are colleagues if they work for the same company
138
+ rule(
139
+ ColleaguesOf(Var("emp1"), Var("emp2")),
140
+ WorksFor(Var("emp1"), Var("company")),
141
+ WorksFor(Var("emp2"), Var("company")),
142
+ )
143
+
144
+ # Rule: Employees are teammates if they work in the same department
145
+ rule(
146
+ TeamMates(Var("emp1"), Var("emp2")),
147
+ MemberOf(Var("emp1"), Var("department")),
148
+ MemberOf(Var("emp2"), Var("department")),
149
+ )
150
+ ```
151
+
152
+ ```python
153
+ # Usage in views.py or management commands
154
+ from django_datalog.models import query, store_facts
155
+ from django.db.models import Q
156
+
157
+ # Store some facts
158
+ tech_corp = Company.objects.create(name="Tech Corp")
159
+ engineering = Department.objects.create(name="Engineering", company=tech_corp)
160
+
161
+ alice_user = User.objects.create(username="alice")
162
+ bob_user = User.objects.create(username="bob")
163
+
164
+ alice = Employee.objects.create(user=alice_user, company=tech_corp, department=engineering, is_manager=True)
165
+ bob = Employee.objects.create(user=bob_user, company=tech_corp, department=engineering)
166
+
167
+ # Store facts about work relationships
168
+ store_facts(
169
+ WorksFor(subject=alice, object=tech_corp),
170
+ WorksFor(subject=bob, object=tech_corp),
171
+ MemberOf(subject=alice, object=engineering),
172
+ MemberOf(subject=bob, object=engineering),
173
+ )
174
+
175
+ # Query: Find all of Alice's colleagues (inferred automatically!)
176
+ colleagues = list(query(ColleaguesOf(alice, Var("colleague"))))
177
+ for result in colleagues:
178
+ colleague = result["colleague"]
179
+ print(f"Alice works with {colleague.user.username}")
180
+
181
+ # Query: Find all teammates in engineering
182
+ teammates = list(query(TeamMates(Var("emp1"), Var("emp2"))))
183
+ for result in teammates:
184
+ emp1, emp2 = result["emp1"], result["emp2"]
185
+ print(f"{emp1.user.username} and {emp2.user.username} are teammates")
186
+
187
+ # Query with constraints: Find managers who work for Tech Corp
188
+ managers = list(query(WorksFor(Var("employee", where=Q(is_manager=True)), tech_corp)))
189
+ for result in managers:
190
+ manager = result["employee"]
191
+ print(f"{manager.user.username} is a manager at {tech_corp.name}")
192
+ ```
193
+
194
+ ## Advanced Features
195
+
196
+ ### Q Object Constraints
197
+
198
+ Use Django Q objects to add powerful filtering to your queries:
199
+
200
+ ```python
201
+ from django.db.models import Q
202
+
203
+ # Find senior employees (with complex constraints)
204
+ senior_employees = query(
205
+ WorksFor(
206
+ Var("employee", where=Q(user__date_joined__year__lt=2020) & Q(is_manager=True)),
207
+ Var("company")
208
+ )
209
+ )
210
+
211
+ # Find employees in specific departments
212
+ engineering_employees = query(
213
+ MemberOf(Var("employee"), Var("dept", where=Q(name__icontains="engineering")))
214
+ )
215
+ ```
216
+
217
+ ### Hydration Control
218
+
219
+ Control whether to fetch full model instances or just PKs for better performance:
220
+
221
+ ```python
222
+ # Get full objects (default) - includes all related data
223
+ results = list(query(WorksFor(Var("employee"), tech_corp), hydrate=True))
224
+ employee = results[0]["employee"]
225
+ print(employee.user.username) # Full Employee object with related User
226
+
227
+ # Get PKs only (better performance for large datasets)
228
+ results = list(query(WorksFor(Var("employee"), tech_corp), hydrate=False))
229
+ employee_id = results[0]["employee"] # Just the employee ID (integer)
230
+ ```
231
+
232
+ ### Family Relationships Example
233
+
234
+ Django-datalog also works great for modeling family relationships:
235
+
236
+ ```python
237
+ class Person(models.Model):
238
+ name = models.CharField(max_length=100)
239
+ age = models.IntegerField()
240
+
241
+ class ParentOf(Fact):
242
+ """Person is parent of another person."""
243
+ subject: Person | Var # Parent
244
+ object: Person | Var # Child
245
+
246
+ class GrandparentOf(Fact):
247
+ """Person is grandparent of another person (inferred)."""
248
+ subject: Person | Var # Grandparent
249
+ object: Person | Var # Grandchild
250
+
251
+ class SiblingOf(Fact):
252
+ """Person is sibling of another person (inferred)."""
253
+ subject: Person | Var # Sibling 1
254
+ object: Person | Var # Sibling 2
255
+
256
+ # Define family rules
257
+ rule(
258
+ GrandparentOf(Var("grandparent"), Var("grandchild")),
259
+ ParentOf(Var("grandparent"), Var("parent")),
260
+ ParentOf(Var("parent"), Var("grandchild")),
261
+ )
262
+
263
+ rule(
264
+ SiblingOf(Var("person1"), Var("person2")),
265
+ ParentOf(Var("parent"), Var("person1")),
266
+ ParentOf(Var("parent"), Var("person2")),
267
+ )
268
+
269
+ # Usage
270
+ john = Person.objects.create(name="John", age=65)
271
+ alice = Person.objects.create(name="Alice", age=40)
272
+ bob = Person.objects.create(name="Bob", age=15)
273
+
274
+ store_facts(
275
+ ParentOf(subject=john, object=alice),
276
+ ParentOf(subject=alice, object=bob)
277
+ )
278
+
279
+ # Query: Find Bob's grandparents (automatically inferred!)
280
+ grandparents = list(query(GrandparentOf(Var("grandparent"), bob)))
281
+ print(f"Bob's grandparent: {grandparents[0]['grandparent'].name}") # John
282
+ ```
283
+
284
+ ## Key Benefits
285
+
286
+ - **No complex SQL**: Express complex relationship logic in simple Python rules
287
+ - **Automatic inference**: New facts are derived automatically from your rules
288
+ - **Performance optimized**: Query reordering and batch loading for optimal performance
289
+ - **Django native**: Works seamlessly with your existing Django models and admin
290
+ - **Type safe**: Full type hints and IDE support with modern Python syntax
291
+
292
+ ## Fact Retraction
293
+
294
+ Remove facts when relationships change:
295
+
296
+ ```python
297
+ from django_datalog.models import retract_facts
298
+
299
+ # Remove a work relationship
300
+ retract_facts(WorksFor(subject=alice, object=tech_corp))
301
+
302
+ # The system will automatically update inferred facts like ColleaguesOf
303
+ ```
304
+
305
+ ## Requirements
306
+
307
+ - Python 3.10+
308
+ - Django 5.0+
309
+
310
+ ## Documentation
311
+
312
+ For detailed examples, API reference, and advanced usage, see the [repository documentation](https://github.com/edelvalle/django-datalog) and [CHANGELOG.md](CHANGELOG.md).
313
+
314
+ ## Contributing
315
+
316
+ We welcome contributions! Please see our repository on [GitHub](https://github.com/edelvalle/django-datalog) for details.
317
+
318
+ ## License
319
+
320
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
321
+
322
+ ## Changelog
323
+
324
+ See [CHANGELOG.md](CHANGELOG.md) for version history and changes.