django-dbbackup 5.2.0__tar.gz → 5.3.1__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 (29) hide show
  1. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/PKG-INFO +7 -7
  2. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/__init__.py +1 -1
  3. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/django.py +8 -4
  4. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/postgresql.py +12 -1
  5. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/_base.py +13 -0
  6. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/storage.py +13 -1
  7. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/pyproject.toml +14 -14
  8. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/.gitignore +0 -0
  9. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/LICENSE.md +0 -0
  10. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/README.md +0 -0
  11. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/apps.py +0 -0
  12. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/checks.py +0 -0
  13. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/__init__.py +0 -0
  14. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/base.py +0 -0
  15. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/exceptions.py +0 -0
  16. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/mongodb.py +0 -0
  17. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/mysql.py +0 -0
  18. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/sqlite.py +0 -0
  19. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/log.py +0 -0
  20. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/__init__.py +0 -0
  21. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/__init__.py +0 -0
  22. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/dbbackup.py +0 -0
  23. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/dbrestore.py +0 -0
  24. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/listbackups.py +0 -0
  25. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/mediabackup.py +0 -0
  26. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/mediarestore.py +0 -0
  27. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/settings.py +0 -0
  28. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/signals.py +0 -0
  29. {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/utils.py +0 -0
@@ -1,8 +1,8 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: django-dbbackup
3
- Version: 5.2.0
3
+ Version: 5.3.1
4
4
  Summary: Management commands to help backup and restore a project database and media.
5
- Project-URL: Changelog, https://archmonger.github.io/django-dbbackup /latest/changelog/
5
+ Project-URL: Changelog, https://archmonger.github.io/django-dbbackup/latest/changelog/
6
6
  Project-URL: Documentation, https://archmonger.github.io/django-dbbackup
7
7
  Project-URL: Source, https://github.com/Archmonger/django-dbbackup
8
8
  Author-email: Mark Bakhit <archiethemonger@gmail.com>
@@ -12,27 +12,27 @@ Keywords: amazon,backup,database,django,dropbox,media,s3,sqlite
12
12
  Classifier: Development Status :: 5 - Production/Stable
13
13
  Classifier: Environment :: Console
14
14
  Classifier: Environment :: Web Environment
15
- Classifier: Framework :: Django :: 4.2
16
15
  Classifier: Framework :: Django :: 5.0
17
16
  Classifier: Framework :: Django :: 5.1
18
17
  Classifier: Framework :: Django :: 5.2
18
+ Classifier: Framework :: Django :: 6.0
19
19
  Classifier: Intended Audience :: Developers
20
20
  Classifier: Intended Audience :: System Administrators
21
21
  Classifier: License :: OSI Approved :: BSD License
22
22
  Classifier: Natural Language :: English
23
23
  Classifier: Operating System :: OS Independent
24
24
  Classifier: Programming Language :: Python
25
- Classifier: Programming Language :: Python :: 3.9
26
25
  Classifier: Programming Language :: Python :: 3.10
27
26
  Classifier: Programming Language :: Python :: 3.11
28
27
  Classifier: Programming Language :: Python :: 3.12
29
28
  Classifier: Programming Language :: Python :: 3.13
29
+ Classifier: Programming Language :: Python :: 3.14
30
30
  Classifier: Topic :: Database
31
31
  Classifier: Topic :: System :: Archiving
32
32
  Classifier: Topic :: System :: Archiving :: Backup
33
33
  Classifier: Topic :: System :: Archiving :: Compression
34
- Requires-Python: >=3.9
35
- Requires-Dist: django>=4.2
34
+ Requires-Python: >=3.10
35
+ Requires-Dist: django>=5.0
36
36
  Description-Content-Type: text/markdown
37
37
 
38
38
  <!--docs-top-start-->
@@ -1,3 +1,3 @@
1
1
  """Management commands to help backup and restore a project database and media"""
2
2
 
3
- __version__ = "5.2.0"
3
+ __version__ = "5.3.1"
@@ -6,6 +6,7 @@ for database-agnostic backup and restore operations. It works with
6
6
  any Django-supported database backend.
7
7
  """
8
8
 
9
+ import codecs
9
10
  import contextlib
10
11
  import os
11
12
  import tempfile
@@ -35,8 +36,11 @@ class DjangoConnector(BaseDBConnector):
35
36
  Returns a file-like object containing the serialized database data
36
37
  in JSON format.
37
38
  """
38
- # Create a SpooledTemporaryFile in text mode for direct use with dumpdata
39
- dump_file = SpooledTemporaryFile(mode="w+t", encoding="utf-8")
39
+
40
+ binary_dump_file = SpooledTemporaryFile(mode="w+b")
41
+
42
+ # Wrap Binary SpooledTemporaryFile in text mode for direct use with dumpdata
43
+ dump_file = codecs.getwriter("utf-8")(binary_dump_file)
40
44
 
41
45
  # Prepare arguments for dumpdata command
42
46
  dump_args = []
@@ -108,8 +112,8 @@ class DjangoConnector(BaseDBConnector):
108
112
  call_command("dumpdata", *dump_args, **dump_kwargs)
109
113
 
110
114
  # Reset file position to beginning for reading
111
- dump_file.seek(0)
112
- return dump_file
115
+ binary_dump_file.seek(0)
116
+ return binary_dump_file
113
117
 
114
118
  def _restore_dump(self, dump):
115
119
  """
@@ -10,6 +10,13 @@ from dbbackup.db.base import BaseCommandDBConnector
10
10
  logger = logging.getLogger("dbbackup.command")
11
11
 
12
12
 
13
+ def _host_requires_uri_quoting(host: str) -> bool:
14
+ # Match *nix paths (e.g. /run/postgres) and Windows paths (e.g. C:\path\to\socket)
15
+ return host.startswith(("/", "@")) or (
16
+ len(host) >= 3 and host[0].isalpha() and host[1] == ":" and host[2] in ("/", "\\")
17
+ )
18
+
19
+
13
20
  def parse_postgres_settings(connector: PgDumpBinaryConnector | PgDumpConnector) -> tuple[str, dict[Any, Any]]:
14
21
  """
15
22
  Parse the common Postgres connectors settings and
@@ -22,7 +29,11 @@ def parse_postgres_settings(connector: PgDumpBinaryConnector | PgDumpConnector)
22
29
  Returns:
23
30
  tuple: (cmd_part, environment_dict)
24
31
  """
25
- host = connector.settings.get("HOST", "localhost")
32
+ host = connector.settings.get("HOST")
33
+ if host is None:
34
+ host = "localhost"
35
+ elif _host_requires_uri_quoting(host):
36
+ host = quote(host, safe="")
26
37
  cmd_part = connector.settings.get("NAME", "")
27
38
  user = quote(connector.settings.get("USER") or "")
28
39
  password = connector.settings.get("PASSWORD", -1)
@@ -85,6 +85,19 @@ class BaseDbBackupCommand(BaseCommand):
85
85
  level = 60 if self.quiet else LOGGING_VERBOSITY[int(self.verbosity)]
86
86
  self.logger.setLevel(level)
87
87
 
88
+ # Find or create a StreamHandler for console output so that
89
+ # --verbosity works regardless of the user's Django LOGGING
90
+ # configuration. Only add one handler to avoid duplicates.
91
+ for handler in self.logger.handlers:
92
+ if isinstance(handler, logging.StreamHandler):
93
+ handler.setLevel(level)
94
+ break
95
+ else:
96
+ handler = logging.StreamHandler(sys.stderr)
97
+ handler.setLevel(level)
98
+ handler.setFormatter(logging.Formatter("%(levelname)s %(message)s"))
99
+ self.logger.addHandler(handler)
100
+
88
101
  def _ask_confirmation(self):
89
102
  answer = input("Are you sure you want to continue? [Y/n] ")
90
103
  if answer.lower().startswith("n"):
@@ -76,7 +76,7 @@ class Storage:
76
76
  self.storage.delete(name=filepath)
77
77
 
78
78
  def list_directory(self, path=""):
79
- return self.storage.listdir(path)[1]
79
+ return [self._normalize_listed_name(name) for name in self.storage.listdir(path)[1]]
80
80
 
81
81
  def write_file(self, filehandle, filename):
82
82
  self.logger.debug("Writing file %s", filename)
@@ -295,6 +295,18 @@ class Storage:
295
295
  return file_date.replace(tzinfo=timezone.utc)
296
296
  return file_date
297
297
 
298
+ def _normalize_listed_name(self, name: str) -> str:
299
+ location = getattr(self.storage, "location", "") or ""
300
+ if not location:
301
+ return name
302
+
303
+ normalized_location = location.replace("\\", "/").strip("/")
304
+ normalized_name = name.replace("\\", "/")
305
+ prefix = f"{normalized_location}/"
306
+ if normalized_location and normalized_name.startswith(prefix):
307
+ return normalized_name[len(prefix) :]
308
+ return name
309
+
298
310
 
299
311
  def get_storage_class(path=None):
300
312
  """
@@ -18,34 +18,34 @@ keywords = [
18
18
  ]
19
19
  license = "BSD-3-Clause"
20
20
  authors = [{ name = "Mark Bakhit", email = "archiethemonger@gmail.com" }]
21
- requires-python = ">=3.9"
21
+ requires-python = ">=3.10"
22
22
  classifiers = [
23
23
  "Development Status :: 5 - Production/Stable",
24
24
  "Environment :: Web Environment",
25
25
  "Environment :: Console",
26
- "Framework :: Django :: 4.2",
27
26
  "Framework :: Django :: 5.0",
28
27
  "Framework :: Django :: 5.1",
29
28
  "Framework :: Django :: 5.2",
29
+ "Framework :: Django :: 6.0",
30
30
  "Intended Audience :: Developers",
31
31
  "Intended Audience :: System Administrators",
32
32
  "License :: OSI Approved :: BSD License",
33
33
  "Natural Language :: English",
34
34
  "Operating System :: OS Independent",
35
35
  "Programming Language :: Python",
36
- "Programming Language :: Python :: 3.9",
37
36
  "Programming Language :: Python :: 3.10",
38
37
  "Programming Language :: Python :: 3.11",
39
38
  "Programming Language :: Python :: 3.12",
40
39
  "Programming Language :: Python :: 3.13",
40
+ "Programming Language :: Python :: 3.14",
41
41
  "Topic :: Database",
42
42
  "Topic :: System :: Archiving",
43
43
  "Topic :: System :: Archiving :: Backup",
44
44
  "Topic :: System :: Archiving :: Compression",
45
45
  ]
46
- dependencies = ["django>=4.2"]
46
+ dependencies = ["django>=5.0"]
47
47
  dynamic = ["version"]
48
- urls.Changelog = "https://archmonger.github.io/django-dbbackup /latest/changelog/"
48
+ urls.Changelog = "https://archmonger.github.io/django-dbbackup/latest/changelog/"
49
49
  urls.Documentation = "https://archmonger.github.io/django-dbbackup"
50
50
  urls.Source = "https://github.com/Archmonger/django-dbbackup"
51
51
 
@@ -80,11 +80,6 @@ matrix-name-format = "{variable}-{value}"
80
80
  [tool.hatch.envs.hatch-test.env-vars]
81
81
  DJANGO_SETTINGS_MODULE = "tests.settings"
82
82
 
83
- # Django 4.2
84
- [[tool.hatch.envs.hatch-test.matrix]]
85
- python = ["3.9", "3.10", "3.11", "3.12"]
86
- django = ["4.2"]
87
-
88
83
  # Django 5.0
89
84
  [[tool.hatch.envs.hatch-test.matrix]]
90
85
  python = ["3.10", "3.11", "3.12"]
@@ -100,11 +95,13 @@ django = ["5.1"]
100
95
  python = ["3.10", "3.11", "3.12", "3.13"]
101
96
  django = ["5.2"]
102
97
 
98
+ # Django 6.0
99
+ [[tool.hatch.envs.hatch-test.matrix]]
100
+ python = ["3.12", "3.13", "3.14"]
101
+ django = ["6.0"]
102
+
103
103
  [tool.hatch.envs.hatch-test.overrides]
104
104
  matrix.django.dependencies = [
105
- { if = [
106
- "4.2",
107
- ], value = "django>=4.2,<4.3" },
108
105
  { if = [
109
106
  "5.0",
110
107
  ], value = "django>=5.0,<5.1" },
@@ -114,6 +111,9 @@ matrix.django.dependencies = [
114
111
  { if = [
115
112
  "5.2",
116
113
  ], value = "django>=5.2,<5.3" },
114
+ { if = [
115
+ "6.0",
116
+ ], value = "django>=6.0,<6.1" },
117
117
  ]
118
118
 
119
119
  # >>> Documentation Scripts <<<
@@ -133,6 +133,7 @@ dependencies = [
133
133
  "mkdocs-git-authors-plugin",
134
134
  "mkdocs-minify-plugin",
135
135
  "mike",
136
+ "click==8.2.1", # Newer versions of click do not work with mkdocs<2.0
136
137
  ]
137
138
 
138
139
  [tool.hatch.envs.docs.scripts]
@@ -191,7 +192,6 @@ postgres = ["python scripts/postgres_live_test.py {args}"]
191
192
 
192
193
  [tool.ruff]
193
194
  line-length = 120
194
- target-version = "py39"
195
195
  extend-exclude = [".eggs/*", ".tox/*", ".venv/*", "build/*", "*/migrations/*"]
196
196
  format.preview = true
197
197
  lint.extend-ignore = [