Skip to content

Commit 376ce65

Browse files
fix(cli): support binary files with @ notation
Support binary files being used in the CLI with arguments using the `@` notation. For example `--avatar @/path/to/avatar.png` Also explicitly catch the common FileNotFoundError and PermissionError exceptions. Remove the bare exception handling. We would rather have the full traceback of any exceptions that we don't know about and add them later if needed. Closes: #2752
1 parent b8824a6 commit 376ce65

File tree

4 files changed

+19
-12
lines changed

4 files changed

+19
-12
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ jobs:
5656
- name: Run tests
5757
env:
5858
TOXENV: ${{ matrix.python.toxenv }}
59-
run: tox --skip-missing-interpreters false
59+
run: tox --skip-missing-interpreters false -- -vv
6060

6161
functional:
6262
runs-on: ubuntu-22.04

gitlab/cli.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import argparse
22
import functools
33
import os
4+
import pathlib
45
import re
56
import sys
67
import textwrap
@@ -299,11 +300,15 @@ def _parse_value(v: Any) -> Any:
299300
if isinstance(v, str) and v.startswith("@"):
300301
# If the user-provided value starts with @, we try to read the file
301302
# path provided after @ as the real value. Exit on any error.
303+
filepath = pathlib.Path(v[1:]).expanduser().resolve()
302304
try:
303-
with open(v[1:], encoding="utf-8") as f:
305+
with open(filepath, encoding="utf-8") as f:
304306
return f.read()
305-
except Exception as e:
306-
sys.stderr.write(f"{e}\n")
307+
except UnicodeDecodeError:
308+
with open(filepath, "rb") as f:
309+
return f.read()
310+
except (FileNotFoundError, PermissionError) as exc:
311+
sys.stderr.write(f"{exc}\n")
307312
sys.exit(1)
308313

309314
return v

tests/functional/cli/test_cli_v4.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,12 +540,15 @@ def test_update_application_settings(gitlab_cli):
540540
assert ret.success
541541

542542

543-
def test_create_project_with_values_from_file(gitlab_cli, tmpdir):
543+
def test_create_project_with_values_from_file(gitlab_cli, fixture_dir, tmpdir):
544544
name = "gitlab-project-from-file"
545545
description = "Multiline\n\nData\n"
546546
from_file = tmpdir.join(name)
547547
from_file.write(description)
548548
from_file_path = f"@{str(from_file)}"
549+
avatar_file = fixture_dir / "avatar.png"
550+
assert avatar_file.exists()
551+
avatar_file_path = f"@{avatar_file}"
549552

550553
cmd = [
551554
"-v",
@@ -555,6 +558,8 @@ def test_create_project_with_values_from_file(gitlab_cli, tmpdir):
555558
name,
556559
"--description",
557560
from_file_path,
561+
"--avatar",
562+
avatar_file_path,
558563
]
559564
ret = gitlab_cli(cmd)
560565

tests/unit/test_cli.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import argparse
2+
import contextlib
23
import io
34
import os
45
import sys
56
import tempfile
6-
from contextlib import redirect_stderr # noqa: H302
77
from unittest import mock
88

99
import pytest
@@ -62,7 +62,7 @@ def test_cls_to_gitlab_resource(class_name, expected_gitlab_resource):
6262
)
6363
def test_die(message, error, expected):
6464
fl = io.StringIO()
65-
with redirect_stderr(fl):
65+
with contextlib.redirect_stderr(fl):
6666
with pytest.raises(SystemExit) as test:
6767
cli.die(message, error)
6868
assert fl.getvalue() == expected
@@ -90,13 +90,10 @@ def test_parse_value():
9090
os.unlink(temp_path)
9191

9292
fl = io.StringIO()
93-
with redirect_stderr(fl):
93+
with contextlib.redirect_stderr(fl):
9494
with pytest.raises(SystemExit) as exc:
9595
cli._parse_value("@/thisfileprobablydoesntexist")
96-
assert (
97-
fl.getvalue() == "[Errno 2] No such file or directory:"
98-
" '/thisfileprobablydoesntexist'\n"
99-
)
96+
assert fl.getvalue().startswith("[Errno 2] No such file or directory:")
10097
assert exc.value.code == 1
10198

10299

0 commit comments

Comments
 (0)