xdjango-postgres-extra 2.1.1__tar.gz → 2.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.
Files changed (148) hide show
  1. xdjango_postgres_extra-2.2.0/PKG-INFO +209 -0
  2. xdjango_postgres_extra-2.2.0/README.md +111 -0
  3. xdjango_postgres_extra-2.2.0/psqlextra/_version.py +1 -0
  4. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/introspection.py +16 -2
  5. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/create_partitioned_model.py +10 -4
  6. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/schema.py +10 -2
  7. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/setup.py +2 -1
  8. xdjango_postgres_extra-2.2.0/tests/test_django_61_compatibility.py +79 -0
  9. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_make_migrations.py +6 -1
  10. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_schema_editor_clone_model_to_schema.py +11 -3
  11. xdjango_postgres_extra-2.2.0/xdjango_postgres_extra.egg-info/PKG-INFO +209 -0
  12. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/xdjango_postgres_extra.egg-info/SOURCES.txt +1 -0
  13. xdjango_postgres_extra-2.1.1/PKG-INFO +0 -206
  14. xdjango_postgres_extra-2.1.1/README.md +0 -112
  15. xdjango_postgres_extra-2.1.1/psqlextra/_version.py +0 -1
  16. xdjango_postgres_extra-2.1.1/xdjango_postgres_extra.egg-info/PKG-INFO +0 -206
  17. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/LICENSE +0 -0
  18. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/__init__.py +0 -0
  19. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/apps.py +0 -0
  20. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/__init__.py +0 -0
  21. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/base.py +0 -0
  22. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/base_impl.py +0 -0
  23. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/__init__.py +0 -0
  24. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/__init__.py +0 -0
  25. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/add_default_partition.py +0 -0
  26. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/add_hash_partition.py +0 -0
  27. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/add_list_partition.py +0 -0
  28. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/add_range_partition.py +0 -0
  29. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/apply_state.py +0 -0
  30. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/create_materialized_view_model.py +0 -0
  31. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/create_view_model.py +0 -0
  32. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_default_partition.py +0 -0
  33. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_hash_partition.py +0 -0
  34. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_list_partition.py +0 -0
  35. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_materialized_view_model.py +0 -0
  36. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_partition.py +0 -0
  37. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_partitioned_model.py +0 -0
  38. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_range_partition.py +0 -0
  39. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_view_model.py +0 -0
  40. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/partition.py +0 -0
  41. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/patched_autodetector.py +0 -0
  42. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/patched_migrations.py +0 -0
  43. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/patched_project_state.py +0 -0
  44. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/state/__init__.py +0 -0
  45. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/state/materialized_view.py +0 -0
  46. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/state/model.py +0 -0
  47. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/state/partitioning.py +0 -0
  48. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/state/view.py +0 -0
  49. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/operations.py +0 -0
  50. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/side_effects/__init__.py +0 -0
  51. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/side_effects/hstore_required.py +0 -0
  52. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/side_effects/hstore_unique.py +0 -0
  53. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/compiler.py +0 -0
  54. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/contrib/__init__.py +0 -0
  55. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/contrib/expressions.py +0 -0
  56. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/contrib/model_data_migrator.py +0 -0
  57. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/contrib/static_row.py +0 -0
  58. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/contrib/transaction.py +0 -0
  59. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/error.py +0 -0
  60. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/expressions.py +0 -0
  61. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/fields/__init__.py +0 -0
  62. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/fields/hstore_field.py +0 -0
  63. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/indexes/__init__.py +0 -0
  64. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/indexes/case_insensitive_unique_index.py +0 -0
  65. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/indexes/conditional_unique_index.py +0 -0
  66. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/indexes/unique_index.py +0 -0
  67. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/introspect/__init__.py +0 -0
  68. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/introspect/fields.py +0 -0
  69. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/introspect/models.py +0 -0
  70. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/locking.py +0 -0
  71. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/lookups.py +0 -0
  72. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/management/__init__.py +0 -0
  73. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/management/commands/__init__.py +0 -0
  74. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/management/commands/pgmakemigrations.py +0 -0
  75. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/management/commands/pgpartition.py +0 -0
  76. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/management/commands/pgrefreshmv.py +0 -0
  77. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/manager/__init__.py +0 -0
  78. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/manager/manager.py +0 -0
  79. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/models/__init__.py +0 -0
  80. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/models/base.py +0 -0
  81. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/models/options.py +0 -0
  82. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/models/partitioned.py +0 -0
  83. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/models/view.py +0 -0
  84. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/__init__.py +0 -0
  85. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/config.py +0 -0
  86. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/constants.py +0 -0
  87. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/current_time_strategy.py +0 -0
  88. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/error.py +0 -0
  89. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/manager.py +0 -0
  90. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/partition.py +0 -0
  91. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/plan.py +0 -0
  92. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/range_partition.py +0 -0
  93. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/range_strategy.py +0 -0
  94. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/shorthands.py +0 -0
  95. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/strategy.py +0 -0
  96. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/time_partition.py +0 -0
  97. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/time_partition_size.py +0 -0
  98. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/time_strategy.py +0 -0
  99. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/py.typed +0 -0
  100. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/query.py +0 -0
  101. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/schema.py +0 -0
  102. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/settings.py +0 -0
  103. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/sql.py +0 -0
  104. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/type_assertions.py +0 -0
  105. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/types.py +0 -0
  106. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/util.py +0 -0
  107. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/pyproject.toml +0 -0
  108. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/setup.cfg +0 -0
  109. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_append_caller_to_sql.py +0 -0
  110. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_case_insensitive_unique_index.py +0 -0
  111. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_conditional_unique_index.py +0 -0
  112. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_db_backend.py +0 -0
  113. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_django_6_compatibility.py +0 -0
  114. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_hstore_autodetect.py +0 -0
  115. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_hstore_field.py +0 -0
  116. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_hstore_required.py +0 -0
  117. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_hstore_unique.py +0 -0
  118. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_insert.py +0 -0
  119. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_introspect.py +0 -0
  120. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_locking.py +0 -0
  121. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_lookups.py +0 -0
  122. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_management_command_partition.py +0 -0
  123. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_manager.py +0 -0
  124. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_manager_context.py +0 -0
  125. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_materialized_view_model.py +0 -0
  126. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_migration_operations.py +0 -0
  127. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_on_conflict.py +0 -0
  128. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_on_conflict_nothing.py +0 -0
  129. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_on_conflict_update.py +0 -0
  130. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_partitioned_model.py +0 -0
  131. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_partitioned_model_state.py +0 -0
  132. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_partitioning_manager.py +0 -0
  133. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_partitioning_time.py +0 -0
  134. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_query.py +0 -0
  135. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_query_values.py +0 -0
  136. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_schema.py +0 -0
  137. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_schema_editor_alter_schema.py +0 -0
  138. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_schema_editor_partitioning.py +0 -0
  139. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_schema_editor_storage_settings.py +0 -0
  140. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_schema_editor_vacuum.py +0 -0
  141. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_schema_editor_view.py +0 -0
  142. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_settings.py +0 -0
  143. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_unique_index.py +0 -0
  144. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_upsert.py +0 -0
  145. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_view_models.py +0 -0
  146. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/xdjango_postgres_extra.egg-info/dependency_links.txt +0 -0
  147. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/xdjango_postgres_extra.egg-info/requires.txt +0 -0
  148. {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/xdjango_postgres_extra.egg-info/top_level.txt +0 -0
@@ -0,0 +1,209 @@
1
+ Metadata-Version: 2.4
2
+ Name: xdjango-postgres-extra
3
+ Version: 2.2.0
4
+ Summary: Bringing all of PostgreSQL's awesomeness to Django.
5
+ Home-page: https://github.com/SectorLabs/django-postgres-extra
6
+ Author: Sector Labs
7
+ Author-email: open-source@sectorlabs.ro
8
+ License: MIT License
9
+ Keywords: django,postgres,extra,hstore,upsert,partioning,materialized,view
10
+ Classifier: Environment :: Web Environment
11
+ Classifier: Framework :: Django
12
+ Classifier: Framework :: Django :: 6.0
13
+ Classifier: Framework :: Django :: 6.1
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python
18
+ Classifier: Programming Language :: Python :: 3.6
19
+ Classifier: Programming Language :: Python :: 3.7
20
+ Classifier: Programming Language :: Python :: 3.8
21
+ Classifier: Programming Language :: Python :: 3.9
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
26
+ Classifier: Programming Language :: Python :: 3.14
27
+ Classifier: Topic :: Internet :: WWW/HTTP
28
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
29
+ Requires-Python: >=3.6
30
+ Description-Content-Type: text/markdown
31
+ License-File: LICENSE
32
+ Requires-Dist: Django<7.0,>=2.0
33
+ Requires-Dist: python-dateutil<=3.0.0,>=2.8.0
34
+ Requires-Dist: dataclasses; python_version <= "3.6"
35
+ Provides-Extra: dev
36
+ Requires-Dist: poethepoet==0.34.0; python_version >= "3.9" and extra == "dev"
37
+ Requires-Dist: poethepoet==0.30.0; (python_version >= "3.8" and python_version < "3.9") and extra == "dev"
38
+ Requires-Dist: poethepoet==0.19.0; (python_version >= "3.7" and python_version < "3.8") and extra == "dev"
39
+ Requires-Dist: poethepoet==0.13.1; (python_version >= "3.6" and python_version < "3.7") and extra == "dev"
40
+ Provides-Extra: test
41
+ Requires-Dist: psycopg2==2.9.10; python_version >= "3.8" and extra == "test"
42
+ Requires-Dist: psycopg2==2.9.9; (python_version >= "3.7" and python_version < "3.8") and extra == "test"
43
+ Requires-Dist: psycopg2==2.9.8; (python_version >= "3.6" and python_version < "3.7") and extra == "test"
44
+ Requires-Dist: types-psycopg2==2.9.21.20250516; python_version >= "3.9" and extra == "test"
45
+ Requires-Dist: types-psycopg2==2.9.8; (python_version >= "3.6" and python_version < "3.9") and extra == "test"
46
+ Requires-Dist: pytest==8.4.0; python_version > "3.8" and extra == "test"
47
+ Requires-Dist: pytest==7.0.1; python_version <= "3.8" and extra == "test"
48
+ Requires-Dist: pytest-benchmark==5.1.0; python_version > "3.8" and extra == "test"
49
+ Requires-Dist: pytest-benchmark==3.4.1; python_version <= "3.8" and extra == "test"
50
+ Requires-Dist: pytest-django==4.11.1; python_version > "3.7" and extra == "test"
51
+ Requires-Dist: pytest-django==4.5.2; python_version <= "3.7" and extra == "test"
52
+ Requires-Dist: pytest-cov==6.1.1; python_version > "3.8" and extra == "test"
53
+ Requires-Dist: pytest-cov==4.0.0; python_version <= "3.8" and extra == "test"
54
+ Requires-Dist: coverage==7.8.2; python_version > "3.8" and extra == "test"
55
+ Requires-Dist: coverage==7.6.1; (python_version >= "3.8" and python_version <= "3.8") and extra == "test"
56
+ Requires-Dist: coverage==6.2; python_version <= "3.7" and extra == "test"
57
+ Requires-Dist: tox==4.26.0; python_version > "3.8" and extra == "test"
58
+ Requires-Dist: tox==3.28.0; python_version <= "3.8" and extra == "test"
59
+ Requires-Dist: freezegun==1.5.2; python_version > "3.7" and extra == "test"
60
+ Requires-Dist: freezegun==1.2.2; python_version <= "3.7" and extra == "test"
61
+ Requires-Dist: syrupy==4.9.1; python_version >= "3.9" and extra == "test"
62
+ Requires-Dist: syrupy==2.3.1; python_version <= "3.8" and extra == "test"
63
+ Provides-Extra: test-report
64
+ Requires-Dist: coveralls==4.0.1; extra == "test-report"
65
+ Provides-Extra: analysis
66
+ Requires-Dist: black==22.3.0; extra == "analysis"
67
+ Requires-Dist: flake8==7.2.0; extra == "analysis"
68
+ Requires-Dist: autoflake==2.3.1; extra == "analysis"
69
+ Requires-Dist: autopep8==2.3.2; extra == "analysis"
70
+ Requires-Dist: isort==6.0.1; extra == "analysis"
71
+ Requires-Dist: docformatter==1.7.7; extra == "analysis"
72
+ Requires-Dist: mypy==1.16.0; extra == "analysis"
73
+ Requires-Dist: django-stubs==4.2.7; extra == "analysis"
74
+ Requires-Dist: typing-extensions==4.14.0; extra == "analysis"
75
+ Requires-Dist: types-dj-database-url==1.3.0.4; extra == "analysis"
76
+ Requires-Dist: types-python-dateutil==2.9.0.20250516; extra == "analysis"
77
+ Provides-Extra: docs
78
+ Requires-Dist: Sphinx==8.2.3; extra == "docs"
79
+ Requires-Dist: sphinx-rtd-theme==3.0.2; extra == "docs"
80
+ Requires-Dist: docutils==0.21.2; extra == "docs"
81
+ Requires-Dist: Jinja2==3.1.6; extra == "docs"
82
+ Provides-Extra: publish
83
+ Requires-Dist: build<2.0.0,>=1.2.0; extra == "publish"
84
+ Requires-Dist: twine<7.0.0,>=6.0.0; extra == "publish"
85
+ Dynamic: author
86
+ Dynamic: author-email
87
+ Dynamic: classifier
88
+ Dynamic: description
89
+ Dynamic: description-content-type
90
+ Dynamic: home-page
91
+ Dynamic: keywords
92
+ Dynamic: license
93
+ Dynamic: license-file
94
+ Dynamic: provides-extra
95
+ Dynamic: requires-dist
96
+ Dynamic: requires-python
97
+ Dynamic: summary
98
+
99
+ # xdjango-postgres-extra
100
+
101
+ [![PyPI version](https://img.shields.io/pypi/v/xdjango-postgres-extra.svg)](https://pypi.org/project/xdjango-postgres-extra/)
102
+ [![Python versions](https://img.shields.io/pypi/pyversions/xdjango-postgres-extra.svg)](https://pypi.org/project/xdjango-postgres-extra/)
103
+ [![Django 6](https://img.shields.io/badge/Django-6.0-0C4B33.svg)](https://docs.djangoproject.com/en/6.0/)
104
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
105
+
106
+ `xdjango-postgres-extra` is a maintained fork of
107
+ [`django-postgres-extra`](https://github.com/SectorLabs/django-postgres-extra).
108
+ It extends Django's PostgreSQL backend with features such as atomic upserts,
109
+ table partitioning, views, materialized views, schema management, and explicit
110
+ table locking.
111
+
112
+ The PyPI distribution is named `xdjango-postgres-extra`. The Python package
113
+ and existing imports remain named `psqlextra`.
114
+
115
+ ## Compatibility
116
+
117
+ - Django: 2.0 through 6.x (`Django>=2.0,<7.0`)
118
+ - Python: 3.6 through 3.14
119
+ - PostgreSQL: 11 or newer
120
+ - Psycopg: 2 and 3
121
+
122
+ Django 6 requires Python 3.12 or newer. The 2.1.x release line was verified with
123
+ Django 6.0.6 and Python 3.14.
124
+
125
+ ## Installation
126
+
127
+ ```bash
128
+ python -m pip install xdjango-postgres-extra
129
+ ```
130
+
131
+ Use the `psqlextra` database backend in your Django settings:
132
+
133
+ ```python
134
+ DATABASES = {
135
+ "default": {
136
+ "ENGINE": "psqlextra.backend",
137
+ "NAME": "my_database",
138
+ "USER": "my_user",
139
+ "PASSWORD": "my_password",
140
+ "HOST": "localhost",
141
+ "PORT": "5432",
142
+ }
143
+ }
144
+ ```
145
+
146
+ Add the application when using features that require app registration:
147
+
148
+ ```python
149
+ INSTALLED_APPS = [
150
+ # ...
151
+ "django.contrib.postgres",
152
+ "psqlextra",
153
+ ]
154
+ ```
155
+
156
+ Existing application code continues to use `psqlextra` imports:
157
+
158
+ ```python
159
+ from psqlextra.models import PostgresModel
160
+ ```
161
+
162
+ ## Features
163
+
164
+ - Atomic `INSERT ... ON CONFLICT` handling with `DO UPDATE` and `DO NOTHING`
165
+ - Bulk inserts and upserts
166
+ - PostgreSQL range, list, hash, and default table partitions
167
+ - Time-based partition management
168
+ - Database views and materialized views integrated with migrations
169
+ - PostgreSQL schema creation, deletion, and temporary schemas
170
+ - Explicit model and table locks
171
+ - `TRUNCATE TABLE`, including cascading truncation
172
+ - HStore constraints and expressions
173
+ - PostgreSQL-specific indexes and introspection
174
+
175
+ The upstream documentation remains the primary API reference:
176
+
177
+ - [Documentation](https://django-postgres-extra.readthedocs.io/en/master/)
178
+ - [Installation guide](https://django-postgres-extra.readthedocs.io/en/master/installation.html)
179
+ - [Feature reference](https://django-postgres-extra.readthedocs.io/en/master/index.html#features)
180
+
181
+ When following upstream installation instructions, install
182
+ `xdjango-postgres-extra` instead of `django-postgres-extra`.
183
+
184
+ ## Development
185
+
186
+ Create a virtual environment and install the development extras:
187
+
188
+ ```bash
189
+ python -m venv .venv
190
+ source .venv/bin/activate
191
+ python -m pip install -e ".[dev,test]"
192
+ ```
193
+
194
+ Set a PostgreSQL test database URL:
195
+
196
+ ```bash
197
+ export DATABASE_URL="postgres://psqlextra:password@localhost/psqlextra"
198
+ ```
199
+
200
+ Run the available Poe tasks:
201
+
202
+ ```bash
203
+ poe test
204
+ poe verify
205
+ ```
206
+
207
+ ## License
208
+
209
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,111 @@
1
+ # xdjango-postgres-extra
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/xdjango-postgres-extra.svg)](https://pypi.org/project/xdjango-postgres-extra/)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/xdjango-postgres-extra.svg)](https://pypi.org/project/xdjango-postgres-extra/)
5
+ [![Django 6](https://img.shields.io/badge/Django-6.0-0C4B33.svg)](https://docs.djangoproject.com/en/6.0/)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
+
8
+ `xdjango-postgres-extra` is a maintained fork of
9
+ [`django-postgres-extra`](https://github.com/SectorLabs/django-postgres-extra).
10
+ It extends Django's PostgreSQL backend with features such as atomic upserts,
11
+ table partitioning, views, materialized views, schema management, and explicit
12
+ table locking.
13
+
14
+ The PyPI distribution is named `xdjango-postgres-extra`. The Python package
15
+ and existing imports remain named `psqlextra`.
16
+
17
+ ## Compatibility
18
+
19
+ - Django: 2.0 through 6.x (`Django>=2.0,<7.0`)
20
+ - Python: 3.6 through 3.14
21
+ - PostgreSQL: 11 or newer
22
+ - Psycopg: 2 and 3
23
+
24
+ Django 6 requires Python 3.12 or newer. The 2.1.x release line was verified with
25
+ Django 6.0.6 and Python 3.14.
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ python -m pip install xdjango-postgres-extra
31
+ ```
32
+
33
+ Use the `psqlextra` database backend in your Django settings:
34
+
35
+ ```python
36
+ DATABASES = {
37
+ "default": {
38
+ "ENGINE": "psqlextra.backend",
39
+ "NAME": "my_database",
40
+ "USER": "my_user",
41
+ "PASSWORD": "my_password",
42
+ "HOST": "localhost",
43
+ "PORT": "5432",
44
+ }
45
+ }
46
+ ```
47
+
48
+ Add the application when using features that require app registration:
49
+
50
+ ```python
51
+ INSTALLED_APPS = [
52
+ # ...
53
+ "django.contrib.postgres",
54
+ "psqlextra",
55
+ ]
56
+ ```
57
+
58
+ Existing application code continues to use `psqlextra` imports:
59
+
60
+ ```python
61
+ from psqlextra.models import PostgresModel
62
+ ```
63
+
64
+ ## Features
65
+
66
+ - Atomic `INSERT ... ON CONFLICT` handling with `DO UPDATE` and `DO NOTHING`
67
+ - Bulk inserts and upserts
68
+ - PostgreSQL range, list, hash, and default table partitions
69
+ - Time-based partition management
70
+ - Database views and materialized views integrated with migrations
71
+ - PostgreSQL schema creation, deletion, and temporary schemas
72
+ - Explicit model and table locks
73
+ - `TRUNCATE TABLE`, including cascading truncation
74
+ - HStore constraints and expressions
75
+ - PostgreSQL-specific indexes and introspection
76
+
77
+ The upstream documentation remains the primary API reference:
78
+
79
+ - [Documentation](https://django-postgres-extra.readthedocs.io/en/master/)
80
+ - [Installation guide](https://django-postgres-extra.readthedocs.io/en/master/installation.html)
81
+ - [Feature reference](https://django-postgres-extra.readthedocs.io/en/master/index.html#features)
82
+
83
+ When following upstream installation instructions, install
84
+ `xdjango-postgres-extra` instead of `django-postgres-extra`.
85
+
86
+ ## Development
87
+
88
+ Create a virtual environment and install the development extras:
89
+
90
+ ```bash
91
+ python -m venv .venv
92
+ source .venv/bin/activate
93
+ python -m pip install -e ".[dev,test]"
94
+ ```
95
+
96
+ Set a PostgreSQL test database URL:
97
+
98
+ ```bash
99
+ export DATABASE_URL="postgres://psqlextra:password@localhost/psqlextra"
100
+ ```
101
+
102
+ Run the available Poe tasks:
103
+
104
+ ```bash
105
+ poe test
106
+ poe verify
107
+ ```
108
+
109
+ ## License
110
+
111
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1 @@
1
+ __version__ = "2.2.0"
@@ -1,6 +1,8 @@
1
1
  from dataclasses import dataclass
2
2
  from typing import TYPE_CHECKING, Dict, List, Optional, Tuple
3
3
 
4
+ import django
5
+
4
6
  from django.db.backends.postgresql.introspection import ( # type: ignore[import]
5
7
  DatabaseIntrospection,
6
8
  )
@@ -305,13 +307,16 @@ class PostgresIntrospection(Introspection):
305
307
  """Gets a dictionary {field_name: (field_name_other_table,
306
308
  other_table)} representing all relations in the specified table.
307
309
 
310
+ Django 6.1 and newer expect a third element in the value tuple
311
+ that describes the database-level ON DELETE behaviour.
312
+
308
313
  This is overriden because the query in Django does not handle
309
314
  relations between tables in different schemas properly.
310
315
  """
311
316
 
312
317
  cursor.execute(
313
318
  """
314
- SELECT a1.attname, c2.relname, a2.attname
319
+ SELECT a1.attname, c2.relname, a2.attname, con.confdeltype
315
320
  FROM pg_constraint con
316
321
  LEFT JOIN pg_class c1 ON con.conrelid = c1.oid
317
322
  LEFT JOIN pg_class c2 ON con.confrelid = c2.oid
@@ -324,4 +329,13 @@ class PostgresIntrospection(Introspection):
324
329
  """,
325
330
  [table_name],
326
331
  )
327
- return {row[0]: (row[2], row[1]) for row in cursor.fetchall()}
332
+
333
+ rows = cursor.fetchall()
334
+
335
+ if django.VERSION >= (6, 1):
336
+ return {
337
+ row[0]: (row[2], row[1], self.on_delete_types.get(row[3]))
338
+ for row in rows
339
+ }
340
+
341
+ return {row[0]: (row[2], row[1]) for row in rows}
@@ -74,13 +74,19 @@ class PostgresCreatePartitionedModel(CreateModel):
74
74
  result = super().reduce(*args, **kwargs)
75
75
 
76
76
  # replace CreateModel operation with PostgresCreatePartitionedModel
77
+ #
78
+ # Django >= 6.0 reduces through `copy.replace()`, which rebuilds the
79
+ # operation as its own class, partitioning options included. Only a
80
+ # plain CreateModel still has to be converted.
77
81
  if isinstance(result, list) and result:
78
82
  for i, op in enumerate(result):
79
- if isinstance(op, CreateModel):
80
- _, args, kwargs = op.deconstruct()
83
+ if isinstance(op, CreateModel) and not isinstance(
84
+ op, PostgresCreatePartitionedModel
85
+ ):
86
+ _, op_args, op_kwargs = op.deconstruct()
81
87
  result[i] = PostgresCreatePartitionedModel(
82
- *args,
83
- **kwargs,
88
+ *op_args,
89
+ **op_kwargs,
84
90
  partitioning_options=self.partitioning_options
85
91
  )
86
92
 
@@ -295,8 +295,7 @@ class PostgresSchemaEditor(SchemaEditor):
295
295
  model, [field.column], foreign_key=True
296
296
  )
297
297
 
298
- sql = Statement(
299
- self.sql_create_fk_not_valid,
298
+ fk_parts = dict(
300
299
  table=self.quote_name(model._meta.db_table),
301
300
  name=self.quote_name(fk_name),
302
301
  column=self.quote_name(field.column),
@@ -307,6 +306,15 @@ class PostgresSchemaEditor(SchemaEditor):
307
306
  deferrable=self.connection.ops.deferrable_sql(),
308
307
  )
309
308
 
309
+ # Django 6.1 added a database-level ON DELETE clause to
310
+ # the foreign key statement we borrow the template from.
311
+ if django.VERSION >= (6, 1):
312
+ fk_parts["on_delete_db"] = self._create_on_delete_sql( # type: ignore[attr-defined]
313
+ model, field
314
+ )
315
+
316
+ sql = Statement(self.sql_create_fk_not_valid, **fk_parts)
317
+
310
318
  self.execute(sql)
311
319
 
312
320
  # It's hard to alter a field's check because it is defined
@@ -7,7 +7,7 @@ exec(open("psqlextra/_version.py").read())
7
7
  with open(
8
8
  os.path.join(os.path.dirname(__file__), "README.md"), encoding="utf-8"
9
9
  ) as readme:
10
- README = readme.read().split("h1>\n", 2)[1]
10
+ README = readme.read()
11
11
 
12
12
 
13
13
  setup(
@@ -37,6 +37,7 @@ setup(
37
37
  "Environment :: Web Environment",
38
38
  "Framework :: Django",
39
39
  "Framework :: Django :: 6.0",
40
+ "Framework :: Django :: 6.1",
40
41
  "Intended Audience :: Developers",
41
42
  "License :: OSI Approved :: MIT License",
42
43
  "Operating System :: OS Independent",
@@ -0,0 +1,79 @@
1
+ import io
2
+
3
+ import django
4
+ import pytest
5
+
6
+ from django.core.management import call_command
7
+ from django.db import models
8
+
9
+ from . import db_introspection
10
+ from .fake_model import delete_fake_model, get_fake_model
11
+
12
+ pytestmark = pytest.mark.skipif(
13
+ django.VERSION < (6, 1),
14
+ reason="Django < 6.1 does not report database level ON DELETE behaviour",
15
+ )
16
+
17
+
18
+ @pytest.fixture
19
+ def fk_target():
20
+ model = get_fake_model({"name": models.TextField()})
21
+
22
+ yield model
23
+
24
+ delete_fake_model(model)
25
+
26
+
27
+ @pytest.fixture
28
+ def fk_source(fk_target):
29
+ model = get_fake_model(
30
+ {
31
+ "python_cascade": models.ForeignKey(
32
+ fk_target, on_delete=models.CASCADE, related_name="+"
33
+ ),
34
+ "db_cascade": models.ForeignKey(
35
+ fk_target, on_delete=models.DB_CASCADE, related_name="+"
36
+ ),
37
+ }
38
+ )
39
+
40
+ yield model
41
+
42
+ delete_fake_model(model)
43
+
44
+
45
+ def test_get_relations_reports_db_on_delete(fk_target, fk_source):
46
+ """Django 6.1 and newer expect the values of the dict returned by
47
+ `get_relations` to carry the database level ON DELETE behaviour as a third
48
+ element."""
49
+
50
+ relations = db_introspection.get_relations(fk_source._meta.db_table)
51
+
52
+ assert relations == {
53
+ # a Python level on_delete leaves no ON DELETE clause behind
54
+ "python_cascade_id": (
55
+ "id",
56
+ fk_target._meta.db_table,
57
+ models.DO_NOTHING,
58
+ ),
59
+ "db_cascade_id": (
60
+ "id",
61
+ fk_target._meta.db_table,
62
+ models.DB_CASCADE,
63
+ ),
64
+ }
65
+
66
+
67
+ def test_inspectdb_unpacks_relations(fk_target, fk_source):
68
+ """`inspectdb` is the one command that unpacks the value tuples returned by
69
+ `get_relations`, so it breaks loudly when their shape is wrong."""
70
+
71
+ stdout = io.StringIO()
72
+ call_command(
73
+ "inspectdb",
74
+ fk_target._meta.db_table,
75
+ fk_source._meta.db_table,
76
+ stdout=stdout,
77
+ )
78
+
79
+ assert "ForeignKey" in stdout.getvalue()
@@ -174,7 +174,12 @@ def test_make_migration_field_operations_view_models(
174
174
  last_name_field = models.TextField(null=True)
175
175
  last_name_field.contribute_to_class(model, "last_name")
176
176
 
177
- migration = make_migration(model._meta.app_label, from_state=state_1)
177
+ # a clone, because Django >= 6.0 strips `indexes`/`constraints` out of
178
+ # the options of the state it detects changes against, and `state_1` is
179
+ # re-used as the target state further down
180
+ migration = make_migration(
181
+ model._meta.app_label, from_state=state_1.clone()
182
+ )
178
183
  assert len(migration.operations) == 1
179
184
  assert isinstance(migration.operations[0], operations.ApplyState)
180
185
  assert isinstance(migration.operations[0].state_operation, AddField)
@@ -156,6 +156,16 @@ def fake_model_fk_target_2():
156
156
 
157
157
  @pytest.fixture
158
158
  def fake_model(fake_model_fk_target_1, fake_model_fk_target_2):
159
+ # `check` was renamed to `condition` in Django 5.1 and dropped in 6.0
160
+ if django.VERSION >= (5, 1):
161
+ age_height_check = models.CheckConstraint(
162
+ condition=Q(age__gt=0, height__gt=0), name="age_height_check"
163
+ )
164
+ else:
165
+ age_height_check = models.CheckConstraint(
166
+ check=Q(age__gt=0, height__gt=0), name="age_height_check"
167
+ )
168
+
159
169
  meta_options = {
160
170
  "indexes": [
161
171
  models.Index(fields=["age", "height"]),
@@ -167,9 +177,7 @@ def fake_model(fake_model_fk_target_1, fake_model_fk_target_2):
167
177
  fields=["first_name", "last_name"],
168
178
  name="first_last_name_uniq",
169
179
  ),
170
- models.CheckConstraint(
171
- check=Q(age__gt=0, height__gt=0), name="age_height_check"
172
- ),
180
+ age_height_check,
173
181
  ],
174
182
  "unique_together": (
175
183
  "first_name",