Skip to content

Commit dc478bf

Browse files
CopilotArchmonger
andauthored
Improve robustness of database name parsing in dbbackup command (#600)
- Enhanced `_get_database_keys()` method to filter empty strings and strip whitespace --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Archmonger <16909269+Archmonger@users.noreply.github.com>
1 parent 61f1edf commit dc478bf

File tree

7 files changed

+42
-13
lines changed

7 files changed

+42
-13
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* text=auto eol=lf

.github/copilot-instructions.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Always reference these instructions first and fallback to search or bash command
66

77
**IMPORTANT**: This package has been fully migrated to modern Python tooling using Hatch. Always use Hatch commands for development workflows.
88

9+
**BUG INVESTIGATION**: When investigating whether a bug was already resolved in a previous version, always prioritize searching through `CHANGELOG.md` first before using Git history. Only search through Git history when no relevant changelog entries are found.
10+
911
## Working Effectively
1012

1113
Bootstrap, build, and test the repository:

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Don't forget to remove deprecated code on each major release!
3131

3232
### Fixed
3333

34+
- Fix issues with parsing excess whitespace within `dbbackup -d "<COMMA_SEPARATED_ARGS>"`
3435
- Fix encryption support when using `gnupg==5.x`.
3536
- Resolve SQLite backup temporary file locking issues on Windows.
3637

dbbackup/management/commands/dbbackup.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ class Command(BaseDbBackupCommand):
2626
make_option(
2727
"-d",
2828
"--database",
29-
help="Database(s) to backup specified by key separated by"
30-
" commas(default: all)",
29+
help="Database(s) to backup specified by key separated by commas(default: all)",
3130
),
3231
make_option(
3332
"-s",
@@ -48,18 +47,14 @@ class Command(BaseDbBackupCommand):
4847
default=False,
4948
help="Encrypt the backup files",
5049
),
51-
make_option(
52-
"-o", "--output-filename", default=None, help="Specify filename on storage"
53-
),
50+
make_option("-o", "--output-filename", default=None, help="Specify filename on storage"),
5451
make_option(
5552
"-O",
5653
"--output-path",
5754
default=None,
5855
help="Specify where to store on local filesystem",
5956
),
60-
make_option(
61-
"-x", "--exclude-tables", default=None, help="Exclude tables from backup"
62-
),
57+
make_option("-x", "--exclude-tables", default=None, help="Exclude tables from backup"),
6358
make_option(
6459
"-n",
6560
"--schema",
@@ -92,9 +87,7 @@ def handle(self, **options):
9287
for database_key in self._get_database_keys():
9388
self.connector = get_connector(database_key)
9489
if self.connector and self.exclude_tables:
95-
self.connector.exclude.extend(
96-
list(self.exclude_tables.replace(" ", "").split(","))
97-
)
90+
self.connector.exclude.extend(list(self.exclude_tables.replace(" ", "").split(",")))
9891
database = self.connector.settings
9992
try:
10093
self._save_new_backup(database)
@@ -104,7 +97,18 @@ def handle(self, **options):
10497
raise CommandError(err) from err
10598

10699
def _get_database_keys(self):
107-
return self.database.split(",") if self.database else settings.DATABASES
100+
"""
101+
Get the list of database keys to backup.
102+
103+
Returns the databases specified by the -d/--database option,
104+
or falls back to the DBBACKUP_DATABASES setting if no option is provided.
105+
"""
106+
if self.database:
107+
# Split by comma and filter out empty strings to prevent
108+
# get_connector('') from being called, which would fall back
109+
# to the 'default' database and ignore DBBACKUP_DATABASES
110+
return [key.strip() for key in self.database.split(",") if key.strip()]
111+
return settings.DATABASES
108112

109113
def _save_new_backup(self, database):
110114
"""

docs/src/dictionary.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,4 @@ config
3939
dumpable
4040
schemas
4141
redistributions
42+
whitespace

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,9 @@ lint.extend-ignore = []
221221
addopts = ["--strict-config", "--strict-markers"]
222222

223223
[tool.coverage]
224-
paths.source = ["dbbackup"]
225224
run.relative_files = true
226225
run.branch = true
227226
run.parallel = true
228227
run.source = ["dbbackup/"]
228+
paths.source = ["dbbackup/"]
229229
report.show_missing = true

tests/commands/test_dbbackup.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,26 @@ def test_get_database_keys(self):
7474
self.command.database = ""
7575
self.assertEqual(self.command._get_database_keys(), ["db-from-settings"])
7676

77+
with self.subTest("multiple databases"):
78+
self.command.database = "db1,db2"
79+
self.assertEqual(self.command._get_database_keys(), ["db1", "db2"])
80+
81+
with self.subTest("multiple databases with whitespace"):
82+
self.command.database = " db1 , db2 "
83+
self.assertEqual(self.command._get_database_keys(), ["db1", "db2"])
84+
85+
with self.subTest("filter out empty strings to prevent get_connector('') bug"):
86+
self.command.database = "db1,,db2"
87+
self.assertEqual(self.command._get_database_keys(), ["db1", "db2"])
88+
89+
with self.subTest("just comma returns empty list"):
90+
self.command.database = ","
91+
self.assertEqual(self.command._get_database_keys(), [])
92+
93+
with self.subTest("just spaces returns empty list"):
94+
self.command.database = " "
95+
self.assertEqual(self.command._get_database_keys(), [])
96+
7797

7898
@patch("dbbackup.settings.GPG_RECIPIENT", "test@test")
7999
@patch("sys.stdout", DEV_NULL)

0 commit comments

Comments
 (0)