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.
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/PKG-INFO +7 -7
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/__init__.py +1 -1
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/django.py +8 -4
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/postgresql.py +12 -1
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/_base.py +13 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/storage.py +13 -1
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/pyproject.toml +14 -14
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/.gitignore +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/LICENSE.md +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/README.md +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/apps.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/checks.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/__init__.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/base.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/exceptions.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/mongodb.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/mysql.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/db/sqlite.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/log.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/__init__.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/__init__.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/dbbackup.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/dbrestore.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/listbackups.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/mediabackup.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/mediarestore.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/settings.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/signals.py +0 -0
- {django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/utils.py +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: django-dbbackup
|
|
3
|
-
Version: 5.
|
|
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
|
|
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.
|
|
35
|
-
Requires-Dist: django>=
|
|
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-->
|
|
@@ -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
|
-
|
|
39
|
-
|
|
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
|
-
|
|
112
|
-
return
|
|
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"
|
|
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.
|
|
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>=
|
|
46
|
+
dependencies = ["django>=5.0"]
|
|
47
47
|
dynamic = ["version"]
|
|
48
|
-
urls.Changelog = "https://archmonger.github.io/django-dbbackup
|
|
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 = [
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_dbbackup-5.2.0 → django_dbbackup-5.3.1}/dbbackup/management/commands/mediarestore.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|