xdjango-postgres-extra 2.0.9rc5__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.0.9rc5/LICENSE +21 -0
  2. xdjango_postgres_extra-2.0.9rc5/PKG-INFO +202 -0
  3. xdjango_postgres_extra-2.0.9rc5/README.md +112 -0
  4. xdjango_postgres_extra-2.0.9rc5/psqlextra/__init__.py +15 -0
  5. xdjango_postgres_extra-2.0.9rc5/psqlextra/_version.py +1 -0
  6. xdjango_postgres_extra-2.0.9rc5/psqlextra/apps.py +9 -0
  7. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/__init__.py +0 -0
  8. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/base.py +123 -0
  9. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/base_impl.py +112 -0
  10. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/introspection.py +327 -0
  11. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/__init__.py +3 -0
  12. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/__init__.py +33 -0
  13. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/add_default_partition.py +35 -0
  14. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/add_hash_partition.py +74 -0
  15. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/add_list_partition.py +60 -0
  16. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/add_range_partition.py +72 -0
  17. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/apply_state.py +41 -0
  18. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/create_materialized_view_model.py +81 -0
  19. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/create_partitioned_model.py +87 -0
  20. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/create_view_model.py +71 -0
  21. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/delete_default_partition.py +24 -0
  22. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/delete_hash_partition.py +29 -0
  23. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/delete_list_partition.py +26 -0
  24. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/delete_materialized_view_model.py +28 -0
  25. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/delete_partition.py +29 -0
  26. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/delete_partitioned_model.py +28 -0
  27. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/delete_range_partition.py +29 -0
  28. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/delete_view_model.py +28 -0
  29. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/operations/partition.py +32 -0
  30. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/patched_autodetector.py +329 -0
  31. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/patched_migrations.py +18 -0
  32. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/patched_project_state.py +66 -0
  33. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/state/__init__.py +19 -0
  34. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/state/materialized_view.py +16 -0
  35. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/state/model.py +127 -0
  36. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/state/partitioning.py +136 -0
  37. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/migrations/state/view.py +54 -0
  38. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/operations.py +23 -0
  39. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/schema.py +1210 -0
  40. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/side_effects/__init__.py +7 -0
  41. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/side_effects/hstore_required.py +184 -0
  42. xdjango_postgres_extra-2.0.9rc5/psqlextra/backend/side_effects/hstore_unique.py +180 -0
  43. xdjango_postgres_extra-2.0.9rc5/psqlextra/compiler.py +491 -0
  44. xdjango_postgres_extra-2.0.9rc5/psqlextra/contrib/__init__.py +11 -0
  45. xdjango_postgres_extra-2.0.9rc5/psqlextra/contrib/expressions.py +47 -0
  46. xdjango_postgres_extra-2.0.9rc5/psqlextra/contrib/model_data_migrator.py +352 -0
  47. xdjango_postgres_extra-2.0.9rc5/psqlextra/contrib/static_row.py +97 -0
  48. xdjango_postgres_extra-2.0.9rc5/psqlextra/contrib/transaction.py +33 -0
  49. xdjango_postgres_extra-2.0.9rc5/psqlextra/error.py +62 -0
  50. xdjango_postgres_extra-2.0.9rc5/psqlextra/expressions.py +235 -0
  51. xdjango_postgres_extra-2.0.9rc5/psqlextra/fields/__init__.py +3 -0
  52. xdjango_postgres_extra-2.0.9rc5/psqlextra/fields/hstore_field.py +78 -0
  53. xdjango_postgres_extra-2.0.9rc5/psqlextra/indexes/__init__.py +9 -0
  54. xdjango_postgres_extra-2.0.9rc5/psqlextra/indexes/case_insensitive_unique_index.py +38 -0
  55. xdjango_postgres_extra-2.0.9rc5/psqlextra/indexes/conditional_unique_index.py +58 -0
  56. xdjango_postgres_extra-2.0.9rc5/psqlextra/indexes/unique_index.py +18 -0
  57. xdjango_postgres_extra-2.0.9rc5/psqlextra/introspect/__init__.py +8 -0
  58. xdjango_postgres_extra-2.0.9rc5/psqlextra/introspect/fields.py +21 -0
  59. xdjango_postgres_extra-2.0.9rc5/psqlextra/introspect/models.py +175 -0
  60. xdjango_postgres_extra-2.0.9rc5/psqlextra/locking.py +104 -0
  61. xdjango_postgres_extra-2.0.9rc5/psqlextra/lookups.py +34 -0
  62. xdjango_postgres_extra-2.0.9rc5/psqlextra/management/__init__.py +0 -0
  63. xdjango_postgres_extra-2.0.9rc5/psqlextra/management/commands/__init__.py +0 -0
  64. xdjango_postgres_extra-2.0.9rc5/psqlextra/management/commands/pgmakemigrations.py +13 -0
  65. xdjango_postgres_extra-2.0.9rc5/psqlextra/management/commands/pgpartition.py +134 -0
  66. xdjango_postgres_extra-2.0.9rc5/psqlextra/management/commands/pgrefreshmv.py +49 -0
  67. xdjango_postgres_extra-2.0.9rc5/psqlextra/manager/__init__.py +8 -0
  68. xdjango_postgres_extra-2.0.9rc5/psqlextra/manager/manager.py +72 -0
  69. xdjango_postgres_extra-2.0.9rc5/psqlextra/models/__init__.py +10 -0
  70. xdjango_postgres_extra-2.0.9rc5/psqlextra/models/base.py +16 -0
  71. xdjango_postgres_extra-2.0.9rc5/psqlextra/models/options.py +33 -0
  72. xdjango_postgres_extra-2.0.9rc5/psqlextra/models/partitioned.py +236 -0
  73. xdjango_postgres_extra-2.0.9rc5/psqlextra/models/view.py +138 -0
  74. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/__init__.py +30 -0
  75. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/config.py +21 -0
  76. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/constants.py +8 -0
  77. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/current_time_strategy.py +81 -0
  78. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/error.py +6 -0
  79. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/manager.py +156 -0
  80. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/partition.py +38 -0
  81. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/plan.py +116 -0
  82. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/range_partition.py +46 -0
  83. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/range_strategy.py +9 -0
  84. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/shorthands.py +77 -0
  85. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/strategy.py +24 -0
  86. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/time_partition.py +61 -0
  87. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/time_partition_size.py +119 -0
  88. xdjango_postgres_extra-2.0.9rc5/psqlextra/partitioning/time_strategy.py +23 -0
  89. xdjango_postgres_extra-2.0.9rc5/psqlextra/py.typed +0 -0
  90. xdjango_postgres_extra-2.0.9rc5/psqlextra/query.py +633 -0
  91. xdjango_postgres_extra-2.0.9rc5/psqlextra/schema.py +227 -0
  92. xdjango_postgres_extra-2.0.9rc5/psqlextra/settings.py +121 -0
  93. xdjango_postgres_extra-2.0.9rc5/psqlextra/sql.py +224 -0
  94. xdjango_postgres_extra-2.0.9rc5/psqlextra/type_assertions.py +29 -0
  95. xdjango_postgres_extra-2.0.9rc5/psqlextra/types.py +41 -0
  96. xdjango_postgres_extra-2.0.9rc5/psqlextra/util.py +24 -0
  97. xdjango_postgres_extra-2.0.9rc5/pyproject.toml +86 -0
  98. xdjango_postgres_extra-2.0.9rc5/setup.cfg +16 -0
  99. xdjango_postgres_extra-2.0.9rc5/setup.py +116 -0
  100. xdjango_postgres_extra-2.0.9rc5/tests/benchmarks/__init__.py +0 -0
  101. xdjango_postgres_extra-2.0.9rc5/tests/benchmarks/test_insert_nothing.py +51 -0
  102. xdjango_postgres_extra-2.0.9rc5/tests/benchmarks/test_upsert.py +51 -0
  103. xdjango_postgres_extra-2.0.9rc5/tests/benchmarks/test_upsert_bulk.py +68 -0
  104. xdjango_postgres_extra-2.0.9rc5/tests/psqlextra_test_backend/__init__.py +0 -0
  105. xdjango_postgres_extra-2.0.9rc5/tests/psqlextra_test_backend/base.py +23 -0
  106. xdjango_postgres_extra-2.0.9rc5/tests/test_append_caller_to_sql.py +81 -0
  107. xdjango_postgres_extra-2.0.9rc5/tests/test_case_insensitive_unique_index.py +70 -0
  108. xdjango_postgres_extra-2.0.9rc5/tests/test_conditional_unique_index.py +151 -0
  109. xdjango_postgres_extra-2.0.9rc5/tests/test_db_backend.py +12 -0
  110. xdjango_postgres_extra-2.0.9rc5/tests/test_hstore_autodetect.py +99 -0
  111. xdjango_postgres_extra-2.0.9rc5/tests/test_hstore_field.py +34 -0
  112. xdjango_postgres_extra-2.0.9rc5/tests/test_hstore_required.py +139 -0
  113. xdjango_postgres_extra-2.0.9rc5/tests/test_hstore_unique.py +183 -0
  114. xdjango_postgres_extra-2.0.9rc5/tests/test_insert.py +141 -0
  115. xdjango_postgres_extra-2.0.9rc5/tests/test_introspect.py +498 -0
  116. xdjango_postgres_extra-2.0.9rc5/tests/test_locking.py +106 -0
  117. xdjango_postgres_extra-2.0.9rc5/tests/test_lookups.py +102 -0
  118. xdjango_postgres_extra-2.0.9rc5/tests/test_make_migrations.py +245 -0
  119. xdjango_postgres_extra-2.0.9rc5/tests/test_management_command_partition.py +175 -0
  120. xdjango_postgres_extra-2.0.9rc5/tests/test_manager.py +106 -0
  121. xdjango_postgres_extra-2.0.9rc5/tests/test_manager_context.py +20 -0
  122. xdjango_postgres_extra-2.0.9rc5/tests/test_materialized_view_model.py +34 -0
  123. xdjango_postgres_extra-2.0.9rc5/tests/test_migration_operations.py +260 -0
  124. xdjango_postgres_extra-2.0.9rc5/tests/test_on_conflict.py +460 -0
  125. xdjango_postgres_extra-2.0.9rc5/tests/test_on_conflict_nothing.py +195 -0
  126. xdjango_postgres_extra-2.0.9rc5/tests/test_on_conflict_update.py +170 -0
  127. xdjango_postgres_extra-2.0.9rc5/tests/test_partitioned_model.py +265 -0
  128. xdjango_postgres_extra-2.0.9rc5/tests/test_partitioned_model_state.py +110 -0
  129. xdjango_postgres_extra-2.0.9rc5/tests/test_partitioning_manager.py +111 -0
  130. xdjango_postgres_extra-2.0.9rc5/tests/test_partitioning_time.py +646 -0
  131. xdjango_postgres_extra-2.0.9rc5/tests/test_query.py +192 -0
  132. xdjango_postgres_extra-2.0.9rc5/tests/test_query_values.py +75 -0
  133. xdjango_postgres_extra-2.0.9rc5/tests/test_schema.py +200 -0
  134. xdjango_postgres_extra-2.0.9rc5/tests/test_schema_editor_alter_schema.py +44 -0
  135. xdjango_postgres_extra-2.0.9rc5/tests/test_schema_editor_clone_model_to_schema.py +334 -0
  136. xdjango_postgres_extra-2.0.9rc5/tests/test_schema_editor_partitioning.py +413 -0
  137. xdjango_postgres_extra-2.0.9rc5/tests/test_schema_editor_storage_settings.py +47 -0
  138. xdjango_postgres_extra-2.0.9rc5/tests/test_schema_editor_vacuum.py +147 -0
  139. xdjango_postgres_extra-2.0.9rc5/tests/test_schema_editor_view.py +176 -0
  140. xdjango_postgres_extra-2.0.9rc5/tests/test_settings.py +93 -0
  141. xdjango_postgres_extra-2.0.9rc5/tests/test_unique_index.py +33 -0
  142. xdjango_postgres_extra-2.0.9rc5/tests/test_upsert.py +507 -0
  143. xdjango_postgres_extra-2.0.9rc5/tests/test_view_models.py +115 -0
  144. xdjango_postgres_extra-2.0.9rc5/xdjango_postgres_extra.egg-info/PKG-INFO +202 -0
  145. xdjango_postgres_extra-2.0.9rc5/xdjango_postgres_extra.egg-info/SOURCES.txt +147 -0
  146. xdjango_postgres_extra-2.0.9rc5/xdjango_postgres_extra.egg-info/dependency_links.txt +1 -0
  147. xdjango_postgres_extra-2.0.9rc5/xdjango_postgres_extra.egg-info/requires.txt +89 -0
  148. xdjango_postgres_extra-2.0.9rc5/xdjango_postgres_extra.egg-info/top_level.txt +2 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Sector Labs
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,202 @@
1
+ Metadata-Version: 2.4
2
+ Name: xdjango-postgres-extra
3
+ Version: 2.0.9rc5
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: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python
16
+ Classifier: Programming Language :: Python :: 3.6
17
+ Classifier: Programming Language :: Python :: 3.7
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Topic :: Internet :: WWW/HTTP
23
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
24
+ Requires-Python: >=3.6
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: Django<=6.0.4,>=2.0
28
+ Requires-Dist: python-dateutil<=3.0.0,>=2.8.0
29
+ Requires-Dist: dataclasses; python_version <= "3.6"
30
+ Provides-Extra: dev
31
+ Requires-Dist: poethepoet==0.34.0; python_version >= "3.9" and extra == "dev"
32
+ Requires-Dist: poethepoet==0.30.0; (python_version >= "3.8" and python_version < "3.9") and extra == "dev"
33
+ Requires-Dist: poethepoet==0.19.0; (python_version >= "3.7" and python_version < "3.8") and extra == "dev"
34
+ Requires-Dist: poethepoet==0.13.1; (python_version >= "3.6" and python_version < "3.7") and extra == "dev"
35
+ Provides-Extra: test
36
+ Requires-Dist: psycopg2==2.9.10; python_version >= "3.8" and extra == "test"
37
+ Requires-Dist: psycopg2==2.9.9; (python_version >= "3.7" and python_version < "3.8") and extra == "test"
38
+ Requires-Dist: psycopg2==2.9.8; (python_version >= "3.6" and python_version < "3.7") and extra == "test"
39
+ Requires-Dist: types-psycopg2==2.9.21.20250516; python_version >= "3.9" and extra == "test"
40
+ Requires-Dist: types-psycopg2==2.9.8; (python_version >= "3.6" and python_version < "3.9") and extra == "test"
41
+ Requires-Dist: pytest==8.4.0; python_version > "3.8" and extra == "test"
42
+ Requires-Dist: pytest==7.0.1; python_version <= "3.8" and extra == "test"
43
+ Requires-Dist: pytest-benchmark==5.1.0; python_version > "3.8" and extra == "test"
44
+ Requires-Dist: pytest-benchmark==3.4.1; python_version <= "3.8" and extra == "test"
45
+ Requires-Dist: pytest-django==4.11.1; python_version > "3.7" and extra == "test"
46
+ Requires-Dist: pytest-django==4.5.2; python_version <= "3.7" and extra == "test"
47
+ Requires-Dist: pytest-cov==6.1.1; python_version > "3.8" and extra == "test"
48
+ Requires-Dist: pytest-cov==4.0.0; python_version <= "3.8" and extra == "test"
49
+ Requires-Dist: coverage==7.8.2; python_version > "3.8" and extra == "test"
50
+ Requires-Dist: coverage==7.6.1; (python_version >= "3.8" and python_version <= "3.8") and extra == "test"
51
+ Requires-Dist: coverage==6.2; python_version <= "3.7" and extra == "test"
52
+ Requires-Dist: tox==4.26.0; python_version > "3.8" and extra == "test"
53
+ Requires-Dist: tox==3.28.0; python_version <= "3.8" and extra == "test"
54
+ Requires-Dist: freezegun==1.5.2; python_version > "3.7" and extra == "test"
55
+ Requires-Dist: freezegun==1.2.2; python_version <= "3.7" and extra == "test"
56
+ Requires-Dist: syrupy==4.9.1; python_version >= "3.9" and extra == "test"
57
+ Requires-Dist: syrupy==2.3.1; python_version <= "3.8" and extra == "test"
58
+ Provides-Extra: test-report
59
+ Requires-Dist: coveralls==4.0.1; extra == "test-report"
60
+ Provides-Extra: analysis
61
+ Requires-Dist: black==22.3.0; extra == "analysis"
62
+ Requires-Dist: flake8==7.2.0; extra == "analysis"
63
+ Requires-Dist: autoflake==2.3.1; extra == "analysis"
64
+ Requires-Dist: autopep8==2.3.2; extra == "analysis"
65
+ Requires-Dist: isort==6.0.1; extra == "analysis"
66
+ Requires-Dist: docformatter==1.7.7; extra == "analysis"
67
+ Requires-Dist: mypy==1.16.0; extra == "analysis"
68
+ Requires-Dist: django-stubs==4.2.7; extra == "analysis"
69
+ Requires-Dist: typing-extensions==4.14.0; extra == "analysis"
70
+ Requires-Dist: types-dj-database-url==1.3.0.4; extra == "analysis"
71
+ Requires-Dist: types-python-dateutil==2.9.0.20250516; extra == "analysis"
72
+ Provides-Extra: docs
73
+ Requires-Dist: Sphinx==8.2.3; extra == "docs"
74
+ Requires-Dist: sphinx-rtd-theme==3.0.2; extra == "docs"
75
+ Requires-Dist: docutils==0.21.2; extra == "docs"
76
+ Requires-Dist: Jinja2==3.1.6; extra == "docs"
77
+ Provides-Extra: publish
78
+ Requires-Dist: build==0.7.0; extra == "publish"
79
+ Requires-Dist: twine==3.7.1; extra == "publish"
80
+ Dynamic: author
81
+ Dynamic: author-email
82
+ Dynamic: classifier
83
+ Dynamic: description
84
+ Dynamic: description-content-type
85
+ Dynamic: home-page
86
+ Dynamic: keywords
87
+ Dynamic: license
88
+ Dynamic: license-file
89
+ Dynamic: provides-extra
90
+ Dynamic: requires-dist
91
+ Dynamic: requires-python
92
+ Dynamic: summary
93
+
94
+
95
+ | | | |
96
+ |--------------------|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
97
+ | :white_check_mark: | **Tests** | [![CircleCI](https://circleci.com/gh/SectorLabs/django-postgres-extra/tree/master.svg?style=svg)](https://circleci.com/gh/SectorLabs/django-postgres-extra/tree/master) |
98
+ | :memo: | **License** | [![License](https://img.shields.io/:license-mit-blue.svg)](http://doge.mit-license.org) |
99
+ | :package: | **PyPi** | [![PyPi](https://badge.fury.io/py/django-postgres-extra.svg)](https://pypi.python.org/pypi/django-postgres-extra) |
100
+ | :four_leaf_clover: | **Code coverage** | [![Coverage Status](https://coveralls.io/repos/github/SectorLabs/django-postgres-extra/badge.svg?branch=coveralls)](https://coveralls.io/github/SectorLabs/django-postgres-extra?branch=master) |
101
+ | <img src="https://cdn.iconscout.com/icon/free/png-256/django-1-282754.png" width="22px" height="22px" align="center" /> | **Django Versions** | 2.0, 2.1, 2.2, 3.0, 3.1, 3.2, 4.0, 4.1, 4.2, 5.0, 5.1, 5.2 |
102
+ | <img src="https://cdn3.iconfinder.com/data/icons/logos-and-brands-adobe/512/267_Python-512.png" width="22px" height="22px" align="center" /> | **Python Versions** | 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13 |
103
+ | <img src="https://pbs.twimg.com/profile_images/1152122059/psycopg-100_400x400.png" width="22px" height="22px" align="center" /> | **Psycopg Versions** | 2, 3 |
104
+ | :book: | **Documentation** | [Read The Docs](https://django-postgres-extra.readthedocs.io/en/master/) |
105
+ | :warning: | **Upgrade** | [Upgrade from v1.x](https://django-postgres-extra.readthedocs.io/en/master/major_releases.html#new-features)
106
+ | :checkered_flag: | **Installation** | [Installation Guide](https://django-postgres-extra.readthedocs.io/en/master/installation.html) |
107
+ | :fire: | **Features** | [Features & Documentation](https://django-postgres-extra.readthedocs.io/en/master/index.html#features) |
108
+ | :droplet: | **Future enhancements** | [Potential features](https://github.com/SectorLabs/django-postgres-extra/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement) |
109
+
110
+ `django-postgres-extra` aims to make all of PostgreSQL's awesome features available through the Django ORM. We do this by taking care of all the hassle. As opposed to the many small packages that are available to try to bring a single feature to Django with minimal effort. ``django-postgres-extra`` goes the extra mile, with well tested implementations, seamless migrations and much more.
111
+
112
+ With seamless we mean that any features we add will work truly seamlessly. You should not have to manually modify your migrations to work with fields and objects provided by this package.
113
+
114
+ ---
115
+
116
+ :warning: **This README is for v2. See the `v1` branch for v1.x.**
117
+
118
+ ---
119
+
120
+ ## Major features
121
+
122
+ [See the full list](http://django-postgres-extra.readthedocs.io/#features)
123
+
124
+ * **Conflict handling (atomic upsert)**
125
+
126
+ Adds support for PostgreSQL's `ON CONFLICT` syntax for inserts. Supports `DO UPDATE` and `DO NOTHING`. Single statement, atomic and concurrency safe upserts. Supports conditional updates as well.
127
+
128
+ * **Table partitioning**
129
+
130
+ Adds support for PostgreSQL 11.x declarative table partitioning. Integrated into Django migrations. Supports all types of partitioning. Includes a command to automatically create time-based partitions.
131
+
132
+ * **Views & materialized views**
133
+
134
+ Adds support for creating views & materialized views as any other model. Integrated into Django migrations.
135
+
136
+ * **Locking models & tables**
137
+
138
+ Support for explicit table-level locks.
139
+
140
+ * **Creating/dropping schemas**
141
+
142
+ Support for managing PostgreSQL schemas.
143
+
144
+ * **Truncating tables**
145
+
146
+ Support for ``TRUNCATE TABLE`` statements (including cascading).
147
+
148
+ For Django 3.1 and older:
149
+
150
+ * **Conditional unique index**
151
+ * **Case insensitive index**
152
+
153
+ For Django 2.2 and older:
154
+
155
+ * **Unique index**
156
+ * **HStore unique and required constraints on specific HStore keys**
157
+
158
+ ## Working with the code
159
+ ### Prerequisites
160
+
161
+ * PostgreSQL 14 or newer.
162
+ * Django 5.x or newer.
163
+ * Python 3.11 or newer.
164
+
165
+ These are just for local development. CI for code analysis etc runs against these. Tests will pass on all Python, Django and PostgreSQL versions documented. Linting, formatting and type-checking the code might not work on other Python and/or Django versions.
166
+
167
+ ### Getting started
168
+
169
+ 1. Clone the repository:
170
+
171
+ λ git clone https://github.com/SectorLabs/django-postgres-extra.git
172
+
173
+ 2. Create a virtual environment:
174
+
175
+ λ cd django-postgres-extra
176
+ λ virtualenv env
177
+ λ source env/bin/activate
178
+
179
+ 3. Create a postgres user for use in tests (skip if your default user is a postgres superuser):
180
+
181
+ λ createuser --superuser psqlextra --pwprompt
182
+ λ export DATABASE_URL=postgres://psqlextra:<password>@localhost/psqlextra
183
+
184
+ Hint: if you're using virtualenvwrapper, you might find it beneficial to put
185
+ the ``export`` line in ``$VIRTUAL_ENV/bin/postactivate`` so that it's always
186
+ available when using this virtualenv.
187
+
188
+ 4. Install the development/test dependencies:
189
+
190
+ λ pip install -r requirements-test.txt
191
+
192
+ 5. Run the tests:
193
+
194
+ λ poe test
195
+
196
+ 6. Run the benchmarks:
197
+
198
+ λ poe benchmark
199
+
200
+ 7. Auto-format code, sort imports and auto-fix linting errors:
201
+
202
+ λ poe fix
@@ -0,0 +1,112 @@
1
+ <h1 align="center">
2
+ <img width="400" src="https://i.imgur.com/79S6OVM.png" alt="django-postgres-extra">
3
+ </h1>
4
+
5
+ | | | |
6
+ |--------------------|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
7
+ | :white_check_mark: | **Tests** | [![CircleCI](https://circleci.com/gh/SectorLabs/django-postgres-extra/tree/master.svg?style=svg)](https://circleci.com/gh/SectorLabs/django-postgres-extra/tree/master) |
8
+ | :memo: | **License** | [![License](https://img.shields.io/:license-mit-blue.svg)](http://doge.mit-license.org) |
9
+ | :package: | **PyPi** | [![PyPi](https://badge.fury.io/py/django-postgres-extra.svg)](https://pypi.python.org/pypi/django-postgres-extra) |
10
+ | :four_leaf_clover: | **Code coverage** | [![Coverage Status](https://coveralls.io/repos/github/SectorLabs/django-postgres-extra/badge.svg?branch=coveralls)](https://coveralls.io/github/SectorLabs/django-postgres-extra?branch=master) |
11
+ | <img src="https://cdn.iconscout.com/icon/free/png-256/django-1-282754.png" width="22px" height="22px" align="center" /> | **Django Versions** | 2.0, 2.1, 2.2, 3.0, 3.1, 3.2, 4.0, 4.1, 4.2, 5.0, 5.1, 5.2 |
12
+ | <img src="https://cdn3.iconfinder.com/data/icons/logos-and-brands-adobe/512/267_Python-512.png" width="22px" height="22px" align="center" /> | **Python Versions** | 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13 |
13
+ | <img src="https://pbs.twimg.com/profile_images/1152122059/psycopg-100_400x400.png" width="22px" height="22px" align="center" /> | **Psycopg Versions** | 2, 3 |
14
+ | :book: | **Documentation** | [Read The Docs](https://django-postgres-extra.readthedocs.io/en/master/) |
15
+ | :warning: | **Upgrade** | [Upgrade from v1.x](https://django-postgres-extra.readthedocs.io/en/master/major_releases.html#new-features)
16
+ | :checkered_flag: | **Installation** | [Installation Guide](https://django-postgres-extra.readthedocs.io/en/master/installation.html) |
17
+ | :fire: | **Features** | [Features & Documentation](https://django-postgres-extra.readthedocs.io/en/master/index.html#features) |
18
+ | :droplet: | **Future enhancements** | [Potential features](https://github.com/SectorLabs/django-postgres-extra/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement) |
19
+
20
+ `django-postgres-extra` aims to make all of PostgreSQL's awesome features available through the Django ORM. We do this by taking care of all the hassle. As opposed to the many small packages that are available to try to bring a single feature to Django with minimal effort. ``django-postgres-extra`` goes the extra mile, with well tested implementations, seamless migrations and much more.
21
+
22
+ With seamless we mean that any features we add will work truly seamlessly. You should not have to manually modify your migrations to work with fields and objects provided by this package.
23
+
24
+ ---
25
+
26
+ :warning: **This README is for v2. See the `v1` branch for v1.x.**
27
+
28
+ ---
29
+
30
+ ## Major features
31
+
32
+ [See the full list](http://django-postgres-extra.readthedocs.io/#features)
33
+
34
+ * **Conflict handling (atomic upsert)**
35
+
36
+ Adds support for PostgreSQL's `ON CONFLICT` syntax for inserts. Supports `DO UPDATE` and `DO NOTHING`. Single statement, atomic and concurrency safe upserts. Supports conditional updates as well.
37
+
38
+ * **Table partitioning**
39
+
40
+ Adds support for PostgreSQL 11.x declarative table partitioning. Integrated into Django migrations. Supports all types of partitioning. Includes a command to automatically create time-based partitions.
41
+
42
+ * **Views & materialized views**
43
+
44
+ Adds support for creating views & materialized views as any other model. Integrated into Django migrations.
45
+
46
+ * **Locking models & tables**
47
+
48
+ Support for explicit table-level locks.
49
+
50
+ * **Creating/dropping schemas**
51
+
52
+ Support for managing PostgreSQL schemas.
53
+
54
+ * **Truncating tables**
55
+
56
+ Support for ``TRUNCATE TABLE`` statements (including cascading).
57
+
58
+ For Django 3.1 and older:
59
+
60
+ * **Conditional unique index**
61
+ * **Case insensitive index**
62
+
63
+ For Django 2.2 and older:
64
+
65
+ * **Unique index**
66
+ * **HStore unique and required constraints on specific HStore keys**
67
+
68
+ ## Working with the code
69
+ ### Prerequisites
70
+
71
+ * PostgreSQL 14 or newer.
72
+ * Django 5.x or newer.
73
+ * Python 3.11 or newer.
74
+
75
+ These are just for local development. CI for code analysis etc runs against these. Tests will pass on all Python, Django and PostgreSQL versions documented. Linting, formatting and type-checking the code might not work on other Python and/or Django versions.
76
+
77
+ ### Getting started
78
+
79
+ 1. Clone the repository:
80
+
81
+ λ git clone https://github.com/SectorLabs/django-postgres-extra.git
82
+
83
+ 2. Create a virtual environment:
84
+
85
+ λ cd django-postgres-extra
86
+ λ virtualenv env
87
+ λ source env/bin/activate
88
+
89
+ 3. Create a postgres user for use in tests (skip if your default user is a postgres superuser):
90
+
91
+ λ createuser --superuser psqlextra --pwprompt
92
+ λ export DATABASE_URL=postgres://psqlextra:<password>@localhost/psqlextra
93
+
94
+ Hint: if you're using virtualenvwrapper, you might find it beneficial to put
95
+ the ``export`` line in ``$VIRTUAL_ENV/bin/postactivate`` so that it's always
96
+ available when using this virtualenv.
97
+
98
+ 4. Install the development/test dependencies:
99
+
100
+ λ pip install -r requirements-test.txt
101
+
102
+ 5. Run the tests:
103
+
104
+ λ poe test
105
+
106
+ 6. Run the benchmarks:
107
+
108
+ λ poe benchmark
109
+
110
+ 7. Auto-format code, sort imports and auto-fix linting errors:
111
+
112
+ λ poe fix
@@ -0,0 +1,15 @@
1
+ import django
2
+
3
+ from ._version import __version__
4
+
5
+ if django.VERSION < (3, 2): # pragma: no cover
6
+ default_app_config = "psqlextra.apps.PostgresExtraAppConfig"
7
+
8
+ __all__ = [
9
+ "default_app_config",
10
+ "__version__",
11
+ ]
12
+ else:
13
+ __all__ = [
14
+ "__version__",
15
+ ]
@@ -0,0 +1 @@
1
+ __version__ = "2.0.9rc5"
@@ -0,0 +1,9 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class PostgresExtraAppConfig(AppConfig):
5
+ name = "psqlextra"
6
+ verbose_name = "PostgreSQL Extra"
7
+
8
+ def ready(self) -> None:
9
+ from .lookups import InValuesLookup # noqa
@@ -0,0 +1,123 @@
1
+ import logging
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from django import VERSION
6
+ from django.conf import settings
7
+ from django.contrib.postgres.signals import (
8
+ get_hstore_oids,
9
+ register_type_handlers,
10
+ )
11
+ from django.db import ProgrammingError
12
+
13
+ from . import base_impl
14
+ from .introspection import PostgresIntrospection
15
+ from .operations import PostgresOperations
16
+ from .schema import PostgresSchemaEditor
17
+
18
+ from django.db.backends.postgresql.base import ( # isort:skip
19
+ DatabaseWrapper as PostgresDatabaseWrapper,
20
+ )
21
+
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ if TYPE_CHECKING:
27
+
28
+ class Wrapper(PostgresDatabaseWrapper):
29
+ pass
30
+
31
+ else:
32
+ Wrapper = base_impl.backend()
33
+
34
+
35
+ class DatabaseWrapper(Wrapper):
36
+ """Wraps the standard PostgreSQL database back-end.
37
+
38
+ Overrides the schema editor with our custom schema editor and makes
39
+ sure the `hstore` extension is enabled.
40
+ """
41
+
42
+ SchemaEditorClass = PostgresSchemaEditor # type: ignore[assignment]
43
+ introspection_class = PostgresIntrospection
44
+ ops_class = PostgresOperations
45
+
46
+ def __init__(self, *args, **kwargs):
47
+ super().__init__(*args, **kwargs)
48
+
49
+ if VERSION >= (5, 0):
50
+ return
51
+
52
+ # Some base back-ends such as the PostGIS back-end don't properly
53
+ # set `ops_class` and `introspection_class` and initialize these
54
+ # classes themselves.
55
+ #
56
+ # This can lead to broken functionality. We fix this automatically.
57
+
58
+ if not isinstance(self.introspection, self.introspection_class):
59
+ self.introspection = self.introspection_class(self)
60
+
61
+ if not isinstance(self.ops, self.ops_class):
62
+ self.ops = self.ops_class(self)
63
+
64
+ for expected_compiler_class in self.ops.compiler_classes:
65
+ compiler_class = self.ops.compiler(expected_compiler_class.__name__)
66
+
67
+ if not issubclass(compiler_class, expected_compiler_class):
68
+ logger.warning(
69
+ "Compiler '%s.%s' is not properly deriving from '%s.%s'."
70
+ % (
71
+ compiler_class.__module__,
72
+ compiler_class.__name__,
73
+ expected_compiler_class.__module__,
74
+ expected_compiler_class.__name__,
75
+ )
76
+ )
77
+
78
+ def prepare_database(self):
79
+ """Ran to prepare the configured database.
80
+
81
+ This is where we enable the `hstore` extension if it wasn't
82
+ enabled yet.
83
+ """
84
+
85
+ super().prepare_database()
86
+
87
+ setup_ext = getattr(
88
+ settings, "POSTGRES_EXTRA_AUTO_EXTENSION_SET_UP", True
89
+ )
90
+ if not setup_ext:
91
+ return False
92
+
93
+ with self.cursor() as cursor:
94
+ try:
95
+ cursor.execute("CREATE EXTENSION IF NOT EXISTS hstore")
96
+ except ProgrammingError: # permission denied
97
+ logger.warning(
98
+ 'Failed to create "hstore" extension. '
99
+ "Tables with hstore columns may fail to migrate. "
100
+ "If hstore is needed, make sure you are connected "
101
+ "to the database as a superuser "
102
+ "or add the extension manually.",
103
+ exc_info=True,
104
+ )
105
+ return
106
+
107
+ # Clear old (non-existent), stale oids.
108
+ get_hstore_oids.cache_clear()
109
+
110
+ # Verify that we (and Django) can find the OIDs
111
+ # for hstore.
112
+ oids, _ = get_hstore_oids(self.alias)
113
+ if not oids:
114
+ logger.warning(
115
+ '"hstore" extension was created, but we cannot find the oids'
116
+ "in the database. Something went wrong.",
117
+ )
118
+ return
119
+
120
+ # We must trigger Django into registering the type handlers now
121
+ # so that any subsequent code can properly use the newly
122
+ # registered types.
123
+ register_type_handlers(self)
@@ -0,0 +1,112 @@
1
+ import importlib
2
+
3
+ from django.conf import settings
4
+ from django.core.exceptions import ImproperlyConfigured
5
+ from django.db import DEFAULT_DB_ALIAS, connections
6
+ from django.db.backends.postgresql.base import DatabaseWrapper
7
+ from django.db.backends.postgresql.introspection import ( # type: ignore[import]
8
+ DatabaseIntrospection,
9
+ )
10
+ from django.db.backends.postgresql.operations import DatabaseOperations
11
+ from django.db.backends.postgresql.schema import ( # type: ignore[import]
12
+ DatabaseSchemaEditor,
13
+ )
14
+
15
+ from django.db.backends.postgresql.base import ( # isort:skip
16
+ DatabaseWrapper as Psycopg2DatabaseWrapper,
17
+ )
18
+
19
+
20
+ def base_backend_instance():
21
+ """Gets an instance of the base class for the custom database back-end.
22
+
23
+ This should be the Django PostgreSQL back-end. However,
24
+ some people are already using a custom back-end from
25
+ another package. We are nice people and expose an option
26
+ that allows them to configure the back-end we base upon.
27
+
28
+ As long as the specified base eventually also has
29
+ the PostgreSQL back-end as a base, then everything should
30
+ work as intended.
31
+
32
+ We create an instance to inspect what classes to subclass
33
+ because not all back-ends set properties such as `ops_class`
34
+ properly. The PostGIS back-end is a good example.
35
+ """
36
+ base_class_name = getattr(
37
+ settings,
38
+ "POSTGRES_EXTRA_DB_BACKEND_BASE",
39
+ "django.db.backends.postgresql",
40
+ )
41
+
42
+ base_class_module = importlib.import_module(base_class_name + ".base")
43
+ base_class = getattr(base_class_module, "DatabaseWrapper", None)
44
+
45
+ if not base_class:
46
+ raise ImproperlyConfigured(
47
+ (
48
+ "'%s' is not a valid database back-end."
49
+ " The module does not define a DatabaseWrapper class."
50
+ " Check the value of POSTGRES_EXTRA_DB_BACKEND_BASE."
51
+ )
52
+ % base_class_name
53
+ )
54
+
55
+ if isinstance(base_class, Psycopg2DatabaseWrapper):
56
+ raise ImproperlyConfigured(
57
+ (
58
+ "'%s' is not a valid database back-end."
59
+ " It does inherit from the PostgreSQL back-end."
60
+ " Check the value of POSTGRES_EXTRA_DB_BACKEND_BASE."
61
+ )
62
+ % base_class_name
63
+ )
64
+
65
+ base_instance = base_class(connections.databases[DEFAULT_DB_ALIAS])
66
+ if base_instance.connection:
67
+ raise ImproperlyConfigured(
68
+ (
69
+ "'%s' establishes a connection during initialization."
70
+ " This is not expected and can lead to more connections"
71
+ " being established than neccesarry."
72
+ )
73
+ % base_class_name
74
+ )
75
+
76
+ return base_instance
77
+
78
+
79
+ def backend() -> DatabaseWrapper:
80
+ """Gets the base class for the database back-end."""
81
+
82
+ return base_backend_instance().__class__
83
+
84
+
85
+ def schema_editor() -> DatabaseSchemaEditor:
86
+ """Gets the base class for the schema editor.
87
+
88
+ We have to use the configured base back-end's schema editor for
89
+ this.
90
+ """
91
+
92
+ return base_backend_instance().SchemaEditorClass
93
+
94
+
95
+ def introspection() -> DatabaseIntrospection:
96
+ """Gets the base class for the introspection class.
97
+
98
+ We have to use the configured base back-end's introspection class
99
+ for this.
100
+ """
101
+
102
+ return base_backend_instance().introspection.__class__
103
+
104
+
105
+ def operations() -> DatabaseOperations:
106
+ """Gets the base class for the operations class.
107
+
108
+ We have to use the configured base back-end's operations class for
109
+ this.
110
+ """
111
+
112
+ return base_backend_instance().ops.__class__