django-nova 0.2.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.
- django_nova-0.2.0/.github/workflows/python-publish.yml +70 -0
- django_nova-0.2.0/.gitignore +0 -0
- django_nova-0.2.0/.idea/.gitignore +5 -0
- django_nova-0.2.0/.idea/django-nova.iml +11 -0
- django_nova-0.2.0/.idea/inspectionProfiles/Project_Default.xml +24 -0
- django_nova-0.2.0/.idea/inspectionProfiles/profiles_settings.xml +6 -0
- django_nova-0.2.0/.idea/markdown.xml +8 -0
- django_nova-0.2.0/.idea/misc.xml +7 -0
- django_nova-0.2.0/.idea/modules.xml +8 -0
- django_nova-0.2.0/.idea/shelf/Uncommitted_changes_before_Update_at_12_06_2026,_08_36_[Changes]/shelved.patch +31 -0
- django_nova-0.2.0/.idea/shelf/Uncommitted_changes_before_Update_at_12_06_2026__08_36__Changes_.xml +4 -0
- django_nova-0.2.0/.idea/vcs.xml +6 -0
- django_nova-0.2.0/.idea/workspace.xml +147 -0
- django_nova-0.2.0/CHANGELOG.md +14 -0
- django_nova-0.2.0/PKG-INFO +214 -0
- django_nova-0.2.0/README.RU.md +161 -0
- django_nova-0.2.0/README.md +161 -0
- django_nova-0.2.0/docs/architecture.md +34 -0
- django_nova-0.2.0/docs/index.md +60 -0
- django_nova-0.2.0/docs/index.svg +1 -0
- django_nova-0.2.0/docs/installation.md +15 -0
- django_nova-0.2.0/docs/installation.svg +1 -0
- django_nova-0.2.0/example_project/models.py +81 -0
- django_nova-0.2.0/pyproject.toml +89 -0
- django_nova-0.2.0/release.txt +134 -0
- django_nova-0.2.0/schemas.txt +49 -0
- django_nova-0.2.0/src/__init__.py +0 -0
- django_nova-0.2.0/src/nova/__init__.py +42 -0
- django_nova-0.2.0/src/nova/admin/__init__.py +0 -0
- django_nova-0.2.0/src/nova/admin/api.py +50 -0
- django_nova-0.2.0/src/nova/admin/components.py +37 -0
- django_nova-0.2.0/src/nova/async_orm/__init__.py +0 -0
- django_nova-0.2.0/src/nova/async_orm/manager.py +30 -0
- django_nova-0.2.0/src/nova/async_orm/queryset.py +42 -0
- django_nova-0.2.0/src/nova/cache/__init__.py +0 -0
- django_nova-0.2.0/src/nova/cache/invalidation.py +45 -0
- django_nova-0.2.0/src/nova/cache/queryset_cache.py +167 -0
- django_nova-0.2.0/src/nova/core/__init__.py +0 -0
- django_nova-0.2.0/src/nova/core/config.py +58 -0
- django_nova-0.2.0/src/nova/core/exceptions.py +69 -0
- django_nova-0.2.0/src/nova/core/observability.py +40 -0
- django_nova-0.2.0/src/nova/core/tracing.py +53 -0
- django_nova-0.2.0/src/nova/db/__init__.py +0 -0
- django_nova-0.2.0/src/nova/db/splitter.py +43 -0
- django_nova-0.2.0/src/nova/db/zero_downtime.py +58 -0
- django_nova-0.2.0/src/nova/ecosystem/__init__.py +0 -0
- django_nova-0.2.0/src/nova/ecosystem/drf.py +91 -0
- django_nova-0.2.0/src/nova/ecosystem/fastapi.py +151 -0
- django_nova-0.2.0/src/nova/tasks/__init__.py +0 -0
- django_nova-0.2.0/src/nova/tasks/decorators.py +31 -0
- django_nova-0.2.0/src/nova/tasks/engine.py +89 -0
- django_nova-0.2.0/src/nova/typing/__init__.py +0 -0
- django_nova-0.2.0/src/nova/typing/fields.py +33 -0
- django_nova-0.2.0/src/nova/typing/models.py +192 -0
- django_nova-0.2.0/src/nova/typing/querysets.py +33 -0
- django_nova-0.2.0/src/nova/validation/__init__.py +0 -0
- django_nova-0.2.0/src/nova/validation/pydantic_bridge.py +84 -0
- django_nova-0.2.0/src/nova/validation/unified.py +51 -0
- django_nova-0.2.0/tests/__init__.py +0 -0
- django_nova-0.2.0/tests/apps.py +5 -0
- django_nova-0.2.0/tests/cache/test_queryset_cache.py +94 -0
- django_nova-0.2.0/tests/conftest.py +24 -0
- django_nova-0.2.0/tests/core/__init__.py +0 -0
- django_nova-0.2.0/tests/core/test_observability.py +46 -0
- django_nova-0.2.0/tests/core/test_tracing.py +64 -0
- django_nova-0.2.0/tests/db/test_migrations.py +71 -0
- django_nova-0.2.0/tests/ecosystem/__init__.py +0 -0
- django_nova-0.2.0/tests/ecosystem/test_drf_integration.py +85 -0
- django_nova-0.2.0/tests/ecosystem/test_fastapi_bridge.py +68 -0
- django_nova-0.2.0/tests/models.py +57 -0
- django_nova-0.2.0/tests/test_full_integration.py +54 -0
- django_nova-0.2.0/tests/typing/test_typed_models.py +79 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# This workflow will upload a Python Package to PyPI when a release is created
|
|
2
|
+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
|
|
3
|
+
|
|
4
|
+
# This workflow uses actions that are not certified by GitHub.
|
|
5
|
+
# They are provided by a third-party and are governed by
|
|
6
|
+
# separate terms of service, privacy policy, and support
|
|
7
|
+
# documentation.
|
|
8
|
+
|
|
9
|
+
name: Upload Python Package
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
release:
|
|
13
|
+
types: [published]
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
release-build:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.x"
|
|
28
|
+
|
|
29
|
+
- name: Build release distributions
|
|
30
|
+
run: |
|
|
31
|
+
# NOTE: put your own distribution build steps here.
|
|
32
|
+
python -m pip install build
|
|
33
|
+
python -m build
|
|
34
|
+
|
|
35
|
+
- name: Upload distributions
|
|
36
|
+
uses: actions/upload-artifact@v4
|
|
37
|
+
with:
|
|
38
|
+
name: release-dists
|
|
39
|
+
path: dist/
|
|
40
|
+
|
|
41
|
+
pypi-publish:
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
needs:
|
|
44
|
+
- release-build
|
|
45
|
+
permissions:
|
|
46
|
+
# IMPORTANT: this permission is mandatory for trusted publishing
|
|
47
|
+
id-token: write
|
|
48
|
+
|
|
49
|
+
# Dedicated environments with protections for publishing are strongly recommended.
|
|
50
|
+
# For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules
|
|
51
|
+
environment:
|
|
52
|
+
name: pypi
|
|
53
|
+
# OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status:
|
|
54
|
+
# url: https://pypi.org/p/YOURPROJECT
|
|
55
|
+
#
|
|
56
|
+
# ALTERNATIVE: if your GitHub Release name is the PyPI project version string
|
|
57
|
+
# ALTERNATIVE: exactly, uncomment the following line instead:
|
|
58
|
+
url: https://test.pypi.org/project/django-nova/0.1.0/${{ Artem Alimpiev }}
|
|
59
|
+
|
|
60
|
+
steps:
|
|
61
|
+
- name: Retrieve release distributions
|
|
62
|
+
uses: actions/download-artifact@v4
|
|
63
|
+
with:
|
|
64
|
+
name: release-dists
|
|
65
|
+
path: dist/
|
|
66
|
+
|
|
67
|
+
- name: Publish release distributions to PyPI
|
|
68
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
69
|
+
with:
|
|
70
|
+
packages-dir: dist/
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<module type="PYTHON_MODULE" version="4">
|
|
3
|
+
<component name="NewModuleRootManager">
|
|
4
|
+
<content url="file://$MODULE_DIR$">
|
|
5
|
+
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
|
6
|
+
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
|
7
|
+
</content>
|
|
8
|
+
<orderEntry type="jdk" jdkName="Python 3.12 (django-nova) (2)" jdkType="Python SDK" />
|
|
9
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
|
10
|
+
</component>
|
|
11
|
+
</module>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<component name="InspectionProjectProfileManager">
|
|
2
|
+
<profile version="1.0">
|
|
3
|
+
<option name="myName" value="Project Default" />
|
|
4
|
+
<inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
|
5
|
+
<option name="ourVersions">
|
|
6
|
+
<value>
|
|
7
|
+
<list size="2">
|
|
8
|
+
<item index="0" class="java.lang.String" itemvalue="2.7" />
|
|
9
|
+
<item index="1" class="java.lang.String" itemvalue="3.14" />
|
|
10
|
+
</list>
|
|
11
|
+
</value>
|
|
12
|
+
</option>
|
|
13
|
+
</inspection_tool>
|
|
14
|
+
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
|
15
|
+
<option name="ignoredPackages">
|
|
16
|
+
<list>
|
|
17
|
+
<option value="pytest-asyn" />
|
|
18
|
+
<option value="cio" />
|
|
19
|
+
<option value="langchain-openai" />
|
|
20
|
+
</list>
|
|
21
|
+
</option>
|
|
22
|
+
</inspection_tool>
|
|
23
|
+
</profile>
|
|
24
|
+
</component>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="MarkdownSettings">
|
|
4
|
+
<option name="previewPanelProviderInfo">
|
|
5
|
+
<ProviderInfo name="Mermaid Studio (Chromium browser)" className="MermaidStudio_z.MermaidStudio_R.MermaidStudio_n.MermaidStudio_Q.MermaidStudio_U.MermaidStudio__.JCEFHtmlPanelProvider" />
|
|
6
|
+
</option>
|
|
7
|
+
</component>
|
|
8
|
+
</project>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="Black">
|
|
4
|
+
<option name="sdkName" value="Python 3.12 (django-nova) (2)" />
|
|
5
|
+
</component>
|
|
6
|
+
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (django-nova) (2)" project-jdk-type="Python SDK" />
|
|
7
|
+
</project>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="ProjectModuleManager">
|
|
4
|
+
<modules>
|
|
5
|
+
<module fileurl="file://$PROJECT_DIR$/.idea/django-nova.iml" filepath="$PROJECT_DIR$/.idea/django-nova.iml" />
|
|
6
|
+
</modules>
|
|
7
|
+
</component>
|
|
8
|
+
</project>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Index: run_fastapi.py
|
|
2
|
+
IDEA additional info:
|
|
3
|
+
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
|
4
|
+
<+>UTF-8
|
|
5
|
+
===================================================================
|
|
6
|
+
diff --git a/run_fastapi.py b/run_fastapi.py
|
|
7
|
+
new file mode 100644
|
|
8
|
+
--- /dev/null (date 1781207527557)
|
|
9
|
+
+++ b/run_fastapi.py (date 1781207527557)
|
|
10
|
+
@@ -0,0 +1,20 @@
|
|
11
|
+
+import django
|
|
12
|
+
+from django.conf import settings
|
|
13
|
+
+
|
|
14
|
+
+if not settings.configured:
|
|
15
|
+
+ settings.configure(
|
|
16
|
+
+ DEBUG=True,
|
|
17
|
+
+ DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}},
|
|
18
|
+
+ INSTALLED_APPS=['django.contrib.contenttypes', 'django.contrib.auth', 'nova', 'tests.apps.TestsConfig'],
|
|
19
|
+
+ SECRET_KEY='test', USE_TZ=True,
|
|
20
|
+
+ )
|
|
21
|
+
+django.setup()
|
|
22
|
+
+
|
|
23
|
+
+from fastapi import FastAPI
|
|
24
|
+
+from nova.ecosystem.fastapi import to_fastapi_router
|
|
25
|
+
+from tests.models import Lab
|
|
26
|
+
+
|
|
27
|
+
+app = FastAPI(title="Django Nova OpenAPI Demo", version="0.1.0")
|
|
28
|
+
+app.include_router(to_fastapi_router(Lab, prefix="/api/labs"))
|
|
29
|
+
+
|
|
30
|
+
+# ะะฐะฟััะบ: uvicorn run_fastapi:app --reload
|
|
31
|
+
|
django_nova-0.2.0/.idea/shelf/Uncommitted_changes_before_Update_at_12_06_2026__08_36__Changes_.xml
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<changelist name="Uncommitted_changes_before_Update_at_12_06_2026,_08_36_[Changes]" date="1781242616719" recycled="false" toDelete="true">
|
|
2
|
+
<option name="PATH" value="$PROJECT_DIR$/.idea/shelf/Uncommitted_changes_before_Update_at_12_06_2026,_08_36_[Changes]/shelved.patch" />
|
|
3
|
+
<option name="DESCRIPTION" value="Uncommitted changes before Update at 12.06.2026, 08:36 [Changes]" />
|
|
4
|
+
</changelist>
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="AutoImportSettings">
|
|
4
|
+
<option name="autoReloadType" value="SELECTIVE" />
|
|
5
|
+
</component>
|
|
6
|
+
<component name="ChangeListManager">
|
|
7
|
+
<list default="true" id="2040f54d-711a-4dfd-88d1-7c5051d4a070" name="Changes" comment="Release v0.2.0: Enterprise Observability, DRF & FastAPI Ecosystem">
|
|
8
|
+
<change beforePath="$PROJECT_DIR$/dist/django_nova-0.2.0-py3-none-any.whl" beforeDir="false" />
|
|
9
|
+
<change beforePath="$PROJECT_DIR$/dist/django_nova-0.2.0.tar.gz" beforeDir="false" />
|
|
10
|
+
</list>
|
|
11
|
+
<option name="SHOW_DIALOG" value="false" />
|
|
12
|
+
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
13
|
+
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
|
14
|
+
<option name="LAST_RESOLUTION" value="IGNORE" />
|
|
15
|
+
</component>
|
|
16
|
+
<component name="FileTemplateManagerImpl">
|
|
17
|
+
<option name="RECENT_TEMPLATES">
|
|
18
|
+
<list>
|
|
19
|
+
<option value="Python Script" />
|
|
20
|
+
</list>
|
|
21
|
+
</option>
|
|
22
|
+
</component>
|
|
23
|
+
<component name="Git.Settings">
|
|
24
|
+
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
|
25
|
+
</component>
|
|
26
|
+
<component name="GitHubPullRequestSearchHistory">{
|
|
27
|
+
"lastFilter": {
|
|
28
|
+
"state": "OPEN",
|
|
29
|
+
"assignee": "Artem7898"
|
|
30
|
+
}
|
|
31
|
+
}</component>
|
|
32
|
+
<component name="GithubPullRequestsUISettings">{
|
|
33
|
+
"selectedUrlAndAccountId": {
|
|
34
|
+
"url": "https://github.com/Artem7898/django-nova.git",
|
|
35
|
+
"accountId": "c08155fe-f126-45fc-acbd-91240ab8f3c1"
|
|
36
|
+
}
|
|
37
|
+
}</component>
|
|
38
|
+
<component name="McpProjectServerCommands">
|
|
39
|
+
<commands />
|
|
40
|
+
<urls />
|
|
41
|
+
</component>
|
|
42
|
+
<component name="ProjectColorInfo">{
|
|
43
|
+
"customColor": "",
|
|
44
|
+
"associatedIndex": 2
|
|
45
|
+
}</component>
|
|
46
|
+
<component name="ProjectId" id="3CCEcBOjDYLt0mtxULic5GNBsHq" />
|
|
47
|
+
<component name="ProjectViewState">
|
|
48
|
+
<option name="hideEmptyMiddlePackages" value="true" />
|
|
49
|
+
<option name="showLibraryContents" value="true" />
|
|
50
|
+
</component>
|
|
51
|
+
<component name="PropertiesComponent">{
|
|
52
|
+
"keyToString": {
|
|
53
|
+
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
|
54
|
+
"RunOnceActivity.MCP Project settings loaded": "true",
|
|
55
|
+
"RunOnceActivity.ShowReadmeOnStart": "true",
|
|
56
|
+
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
|
57
|
+
"RunOnceActivity.git.unshallow": "true",
|
|
58
|
+
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
|
59
|
+
"codeWithMe.voiceChat.enabledByDefault": "false",
|
|
60
|
+
"git-widget-placeholder": "main",
|
|
61
|
+
"last_opened_file_path": "/home/atrem/PycharmProjects/django-nova",
|
|
62
|
+
"node.js.detected.package.eslint": "true",
|
|
63
|
+
"node.js.detected.package.tslint": "true",
|
|
64
|
+
"node.js.selected.package.eslint": "(autodetect)",
|
|
65
|
+
"node.js.selected.package.tslint": "(autodetect)",
|
|
66
|
+
"nodejs_package_manager_path": "npm",
|
|
67
|
+
"settings.editor.selected.configurable": "com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable"
|
|
68
|
+
}
|
|
69
|
+
}</component>
|
|
70
|
+
<component name="SharedIndexes">
|
|
71
|
+
<attachedChunks>
|
|
72
|
+
<set>
|
|
73
|
+
<option value="bundled-python-sdk-024ed6589d45-c2ffad84badb-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-261.23567.174" />
|
|
74
|
+
</set>
|
|
75
|
+
</attachedChunks>
|
|
76
|
+
</component>
|
|
77
|
+
<component name="TaskManager">
|
|
78
|
+
<task active="true" id="Default" summary="Default task">
|
|
79
|
+
<changelist id="2040f54d-711a-4dfd-88d1-7c5051d4a070" name="Changes" comment="" />
|
|
80
|
+
<created>1775881230494</created>
|
|
81
|
+
<option name="number" value="Default" />
|
|
82
|
+
<option name="presentableId" value="Default" />
|
|
83
|
+
<updated>1775881230494</updated>
|
|
84
|
+
</task>
|
|
85
|
+
<task id="LOCAL-00001" summary="Migration Safety Hardening">
|
|
86
|
+
<option name="closed" value="true" />
|
|
87
|
+
<created>1781242256699</created>
|
|
88
|
+
<option name="number" value="00001" />
|
|
89
|
+
<option name="presentableId" value="LOCAL-00001" />
|
|
90
|
+
<option name="project" value="LOCAL" />
|
|
91
|
+
<updated>1781242256699</updated>
|
|
92
|
+
</task>
|
|
93
|
+
<task id="LOCAL-00002" summary="Migration Safety Hardening">
|
|
94
|
+
<option name="closed" value="true" />
|
|
95
|
+
<created>1781243330688</created>
|
|
96
|
+
<option name="number" value="00002" />
|
|
97
|
+
<option name="presentableId" value="LOCAL-00002" />
|
|
98
|
+
<option name="project" value="LOCAL" />
|
|
99
|
+
<updated>1781243330688</updated>
|
|
100
|
+
</task>
|
|
101
|
+
<task id="LOCAL-00003" summary="Release v0.2.0: Enterprise Observability, DRF & FastAPI Ecosystem">
|
|
102
|
+
<option name="closed" value="true" />
|
|
103
|
+
<created>1781246810674</created>
|
|
104
|
+
<option name="number" value="00003" />
|
|
105
|
+
<option name="presentableId" value="LOCAL-00003" />
|
|
106
|
+
<option name="project" value="LOCAL" />
|
|
107
|
+
<updated>1781246810674</updated>
|
|
108
|
+
</task>
|
|
109
|
+
<task id="LOCAL-00004" summary="Release v0.2.0: Enterprise Observability, DRF & FastAPI Ecosystem">
|
|
110
|
+
<option name="closed" value="true" />
|
|
111
|
+
<created>1781255936367</created>
|
|
112
|
+
<option name="number" value="00004" />
|
|
113
|
+
<option name="presentableId" value="LOCAL-00004" />
|
|
114
|
+
<option name="project" value="LOCAL" />
|
|
115
|
+
<updated>1781255936367</updated>
|
|
116
|
+
</task>
|
|
117
|
+
<task id="LOCAL-00005" summary="Release v0.2.0: Enterprise Observability, DRF & FastAPI Ecosystem">
|
|
118
|
+
<option name="closed" value="true" />
|
|
119
|
+
<created>1781256186897</created>
|
|
120
|
+
<option name="number" value="00005" />
|
|
121
|
+
<option name="presentableId" value="LOCAL-00005" />
|
|
122
|
+
<option name="project" value="LOCAL" />
|
|
123
|
+
<updated>1781256186897</updated>
|
|
124
|
+
</task>
|
|
125
|
+
<option name="localTasksCounter" value="6" />
|
|
126
|
+
<servers />
|
|
127
|
+
</component>
|
|
128
|
+
<component name="TypeScriptGeneratedFilesManager">
|
|
129
|
+
<option name="version" value="3" />
|
|
130
|
+
</component>
|
|
131
|
+
<component name="Vcs.Log.Tabs.Properties">
|
|
132
|
+
<option name="TAB_STATES">
|
|
133
|
+
<map>
|
|
134
|
+
<entry key="MAIN">
|
|
135
|
+
<value>
|
|
136
|
+
<State />
|
|
137
|
+
</value>
|
|
138
|
+
</entry>
|
|
139
|
+
</map>
|
|
140
|
+
</option>
|
|
141
|
+
</component>
|
|
142
|
+
<component name="VcsManagerConfiguration">
|
|
143
|
+
<MESSAGE value="Migration Safety Hardening" />
|
|
144
|
+
<MESSAGE value="Release v0.2.0: Enterprise Observability, DRF & FastAPI Ecosystem" />
|
|
145
|
+
<option name="LAST_COMMIT_MESSAGE" value="Release v0.2.0: Enterprise Observability, DRF & FastAPI Ecosystem" />
|
|
146
|
+
</component>
|
|
147
|
+
</project>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
## [0.2.0] - 2025-05-06 - "Enterprise & Ecosystem"
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
- **Structured Observability:** Integrated `structlog` for machine-readable JSON logging. Cache miss/hit events now include ISO-timestamps and execution timings.
|
|
5
|
+
- **Distributed Tracing:** Added OpenTelemetry integration (`nova.core.tracing`). Automatic spans for `Model.save()` and `QuerySetCache` operations. Uses "Safe Import" pattern (0 overhead if OTEL is not installed).
|
|
6
|
+
- **Migration Safety:** Implemented `AddFieldConcurrently` and `CreateIndexConcurrently` for true zero-downtime schema changes on PostgreSQL.
|
|
7
|
+
- **DRF Auto-Serializer:** Added `to_drf_serializer()`. Dynamically generates Django Rest Framework `ModelSerializer` that delegates business logic validation strictly to Pydantic schemas.
|
|
8
|
+
- **FastAPI Auto-Router:** Added `to_fastapi_router()`. Dynamically generates FastAPI endpoints (`GET/POST`) bound to Django ORM.
|
|
9
|
+
- **Native OpenAPI:** FastAPI routers automatically generate perfect Swagger/OpenAPI schemas using runtime signature injection (`inspect.Signature`), bypassing PEP 563 limitations.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- `QuerySetCache` now uses SQL Compiler for deterministic cache key hashing (safe across all Django 5.x versions).
|
|
13
|
+
- `QuerySetCache` invalidation moved from hash-search to O(1) reverse index mapping.
|
|
14
|
+
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-nova
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Next-generation Django toolkit: typed ORM, unified validation, async-first, smart caching
|
|
5
|
+
Author-email: Artem Alimpiev <alimpievne@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Framework :: Django :: 5.0
|
|
9
|
+
Classifier: Framework :: Django :: 5.1
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering
|
|
13
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
14
|
+
Requires-Python: >=3.12
|
|
15
|
+
Requires-Dist: asyncpg>=0.30; extra == 'async'
|
|
16
|
+
Requires-Dist: cachetools>=5.4
|
|
17
|
+
Requires-Dist: django<6.0,>=5.0
|
|
18
|
+
Requires-Dist: pydantic-settings<3.0,>=2.5
|
|
19
|
+
Requires-Dist: pydantic<3.0,>=2.8
|
|
20
|
+
Requires-Dist: redis>=5.0; extra == 'cache'
|
|
21
|
+
Requires-Dist: typing-extensions>=4.12
|
|
22
|
+
Provides-Extra: async
|
|
23
|
+
Requires-Dist: asyncpg>=0.30; extra == 'async'
|
|
24
|
+
Requires-Dist: databases[asyncpg]>=0.9; extra == 'async'
|
|
25
|
+
Provides-Extra: cache
|
|
26
|
+
Requires-Dist: hiredis>=3.0; extra == 'cache'
|
|
27
|
+
Requires-Dist: redis>=5.0; extra == 'cache'
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: coverage>=7.6; extra == 'dev'
|
|
30
|
+
Requires-Dist: djangorestframework>=3.15; extra == 'dev'
|
|
31
|
+
Requires-Dist: fastapi>=0.115; extra == 'dev'
|
|
32
|
+
Requires-Dist: hatch>=1.12; extra == 'dev'
|
|
33
|
+
Requires-Dist: httpx>=0.27; extra == 'dev'
|
|
34
|
+
Requires-Dist: opentelemetry-api>=1.20; extra == 'dev'
|
|
35
|
+
Requires-Dist: pyright>=1.1; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest-django>=4.9; extra == 'dev'
|
|
38
|
+
Requires-Dist: pytest>=8.3; extra == 'dev'
|
|
39
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
40
|
+
Requires-Dist: structlog>=24.0; extra == 'dev'
|
|
41
|
+
Provides-Extra: drf
|
|
42
|
+
Requires-Dist: djangorestframework>=3.15; extra == 'drf'
|
|
43
|
+
Provides-Extra: fastapi
|
|
44
|
+
Requires-Dist: fastapi>=0.115; extra == 'fastapi'
|
|
45
|
+
Requires-Dist: uvicorn>=0.30; extra == 'fastapi'
|
|
46
|
+
Provides-Extra: observability
|
|
47
|
+
Requires-Dist: structlog>=24.0; extra == 'observability'
|
|
48
|
+
Provides-Extra: tasks
|
|
49
|
+
Requires-Dist: asyncio-throttle>=1.0; extra == 'tasks'
|
|
50
|
+
Provides-Extra: tracing
|
|
51
|
+
Requires-Dist: opentelemetry-api>=1.20; extra == 'tracing'
|
|
52
|
+
Description-Content-Type: text/markdown
|
|
53
|
+
|
|
54
|
+
<div align="center">
|
|
55
|
+
|
|
56
|
+
# ๐ Django Nova
|
|
57
|
+
|
|
58
|
+
**Typed, unified, and async-first toolkit for Django 5+**
|
|
59
|
+
|
|
60
|
+
[](https://www.python.org/downloads/)
|
|
61
|
+
[](https://www.djangoproject.com/)
|
|
62
|
+
[](https://pypi.org/project/django-nova/)
|
|
63
|
+
[](https://github.com/astral-sh/ruff)
|
|
64
|
+
[](https://opensource.org/licenses/MIT)
|
|
65
|
+
|
|
66
|
+
*Django Nova eliminates fundamental architectural flaws in Django that lead to data corruption, runtime errors, and maintainability issues in scientific and enterprise software.*
|
|
67
|
+
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## ๐ Key Innovations
|
|
73
|
+
|
|
74
|
+
- โ
**Single Source of Truth:** Define validation once in Pydantic. Django Models, Forms, and APIs automatically read from it. No more duplication.
|
|
75
|
+
- ๐ **Strict Type Safety:** Full `pyright --strict` compatibility for ORM, QuerySets, and Models using modern PEP 695 syntax.
|
|
76
|
+
- โก **Smart QuerySet Cache:** Automatic O(1) cache invalidation on write via Django signals. Zero percent stale data in research pipelines.
|
|
77
|
+
- ๐ **Zero-Downtime Migrations:** Native PostgreSQL `CONCURRENTLY` operations for locked tables containing millions of rows.
|
|
78
|
+
- ๐ **Structured Observability:** Built-in `structlog` integration emitting machine-readable JSON logs with ISO-timestamps for Datadog/ELK.
|
|
79
|
+
- ๐ **Distributed Tracing:** OpenTelemetry spans for `Model.save()` and Cache operations. Zero overhead if OTEL is not installed.
|
|
80
|
+
- ๐ **DRF Auto-Serializer:** Generate Django Rest Framework Serializers dynamically from Pydantic schemas. Pydantic validation overrides DRF.
|
|
81
|
+
- ๐ **FastAPI Auto-Router:** Generate fully documented FastAPI routers with native OpenAPI/Swagger from Django models.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## ๐ Quick Start
|
|
86
|
+
|
|
87
|
+
### Installation
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Core library
|
|
91
|
+
pip install django-nova
|
|
92
|
+
|
|
93
|
+
# With DRF support
|
|
94
|
+
pip install django-nova[drf]
|
|
95
|
+
|
|
96
|
+
# With FastAPI support
|
|
97
|
+
pip install django-nova[fastapi]
|
|
98
|
+
|
|
99
|
+
# With full enterprise stack (tracing, logging)
|
|
100
|
+
pip install django-nova[tracing,observability]
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## ๐ก Usage Example
|
|
106
|
+
|
|
107
|
+
### Define your rules once, use them everywhere:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
# models.py
|
|
111
|
+
from pydantic import BaseModel, field_validator
|
|
112
|
+
from django.db import models
|
|
113
|
+
from nova import NovaModel, NovaConfig
|
|
114
|
+
|
|
115
|
+
# 1. Define validation rules (ONCE)
|
|
116
|
+
class ResearcherSchema(BaseModel):
|
|
117
|
+
name: str
|
|
118
|
+
h_index: int = 0
|
|
119
|
+
|
|
120
|
+
@field_validator("h_index")
|
|
121
|
+
@classmethod
|
|
122
|
+
def validate_h_index(cls, v: int) -> int:
|
|
123
|
+
if v < 0:
|
|
124
|
+
raise ValueError("h-index cannot be negative")
|
|
125
|
+
return v
|
|
126
|
+
|
|
127
|
+
# 2. Link to Django
|
|
128
|
+
class Researcher(NovaModel):
|
|
129
|
+
name = models.CharField(max_length=300)
|
|
130
|
+
h_index = models.IntegerField(default=0)
|
|
131
|
+
|
|
132
|
+
_nova_config = NovaConfig(
|
|
133
|
+
pydantic_schema=ResearcherSchema,
|
|
134
|
+
cache_enabled=True,
|
|
135
|
+
strict_validation=True
|
|
136
|
+
)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Now, any attempt to save invalid data is blocked at the ORM level, and the schema is automatically reused in DRF and FastAPI!**
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## ๐ Ecosystem Integration
|
|
144
|
+
|
|
145
|
+
Django Nova acts as a universal hub between Python frameworks.
|
|
146
|
+
|
|
147
|
+
### Django Rest Framework
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from nova.ecosystem.drf import to_drf_serializer
|
|
151
|
+
|
|
152
|
+
# Dynamically generates a ModelSerializer that delegates business logic to Pydantic
|
|
153
|
+
ResearcherSerializer = to_drf_serializer(Researcher)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### FastAPI
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
from fastapi import FastAPI
|
|
160
|
+
from nova.ecosystem.fastapi import to_fastapi_router
|
|
161
|
+
|
|
162
|
+
app = FastAPI()
|
|
163
|
+
# Generates GET/POST endpoints with native OpenAPI/Swagger documentation
|
|
164
|
+
app.include_router(to_fastapi_router(Researcher, prefix="/api/researchers"))
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## ๐๏ธ Architecture
|
|
170
|
+
|
|
171
|
+
Django Nova intercepts standard processes at the core level:
|
|
172
|
+
|
|
173
|
+
```text
|
|
174
|
+
Request -> View -> Model.save() -> [Pydantic Validation -> Django Fields -> Business Logic] -> DB
|
|
175
|
+
|
|
|
176
|
+
+-> Cache Invalidation Signal -> Evict stale QuerySets
|
|
177
|
+
|
|
|
178
|
+
+-> OpenTelemetry Span -> Metrics & Traces
|
|
179
|
+
|
|
|
180
|
+
+-> Structlog -> JSON Logs to Datadog/ELK
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Core Tech Stack:
|
|
184
|
+
|
|
185
|
+
- **PEP 562:** Lazy imports bypassing AppRegistryNotReady.
|
|
186
|
+
- **PEP 695:** Modern generic syntax (`class Cache[T]:`).
|
|
187
|
+
- **SQL Compiler:** Deterministic cache hash key generation (safe across any Django version).
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## ๐งช Testing
|
|
192
|
+
|
|
193
|
+
The project is tested on the bleeding-edge stack (Python 3.14 + Django 5.2).
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
pip install -e ".[dev]"
|
|
197
|
+
pytest tests/ -v # 39 passed
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## ๐ค Author
|
|
203
|
+
|
|
204
|
+
**Artem Alimpiev**
|
|
205
|
+
|
|
206
|
+
- ORCID: [0009-0007-6740-7242](https://orcid.org/0009-0007-6740-7242)
|
|
207
|
+
- DOI: [10.5281/zenodo.20057443](https://doi.org/10.5281/zenodo.20057443)
|
|
208
|
+
- DOI: [10.5281/zenodo.20659647](https://doi.org/10.5281/zenodo.20659647)
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## ๐ License
|
|
213
|
+
|
|
214
|
+
This project is licensed under the terms of the MIT License. See the [LICENSE](LICENSE) file for details.
|