Skip to content

Commit 9acfa3c

Browse files
committed
Remove arg_encoding
1 parent 179ed13 commit 9acfa3c

File tree

10 files changed

+36
-102
lines changed

10 files changed

+36
-102
lines changed

beets/test/helper.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -117,20 +117,9 @@ def capture_stdout():
117117
print(capture.getvalue())
118118

119119

120-
def _convert_args(args):
121-
"""Convert args to bytestrings for Python 2 and convert them to strings
122-
on Python 3.
123-
"""
124-
for i, elem in enumerate(args):
125-
if isinstance(elem, bytes):
126-
args[i] = elem.decode(util.arg_encoding())
127-
128-
return args
129-
130-
131120
def has_program(cmd, args=["--version"]):
132121
"""Returns `True` if `cmd` can be executed."""
133-
full_cmd = _convert_args([cmd] + args)
122+
full_cmd = [cmd] + args
134123
try:
135124
with open(os.devnull, "wb") as devnull:
136125
subprocess.check_call(
@@ -385,7 +374,7 @@ def run_command(self, *args, **kwargs):
385374
if hasattr(self, "lib"):
386375
lib = self.lib
387376
lib = kwargs.get("lib", lib)
388-
beets.ui._raw_main(_convert_args(list(args)), lib)
377+
beets.ui._raw_main(list(args), lib)
389378

390379
def run_with_output(self, *args):
391380
with capture_stdout() as out:

beets/ui/commands.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,13 +1359,8 @@ def import_func(lib, opts, args):
13591359
# what we need. On Python 3, we need to undo the "helpful"
13601360
# conversion to Unicode strings to get the real bytestring
13611361
# filename.
1362-
paths = [
1363-
p.encode(util.arg_encoding(), "surrogateescape") for p in paths
1364-
]
1365-
paths_from_logfiles = [
1366-
p.encode(util.arg_encoding(), "surrogateescape")
1367-
for p in paths_from_logfiles
1368-
]
1362+
paths = [os.fsencode(p) for p in paths]
1363+
paths_from_logfiles = [os.fsencode(p) for p in paths_from_logfiles]
13691364

13701365
# Check the user-specified directories.
13711366
for path in paths:

beets/util/__init__.py

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -369,13 +369,6 @@ def components(path: AnyStr) -> list[AnyStr]:
369369
return comps
370370

371371

372-
def arg_encoding() -> str:
373-
"""Get the encoding for command-line arguments (and other OS
374-
locale-sensitive strings).
375-
"""
376-
return sys.getfilesystemencoding()
377-
378-
379372
def bytestring_path(path: PathLike) -> bytes:
380373
"""Given a path, which is either a bytes or a unicode, returns a str
381374
path (ensuring that we never deal with Unicode pathnames). Path should be
@@ -832,19 +825,6 @@ def plurality(objs: Sequence[T]) -> tuple[T, int]:
832825
return c.most_common(1)[0]
833826

834827

835-
def convert_command_args(args: list[BytesOrStr]) -> list[str]:
836-
"""Convert command arguments, which may either be `bytes` or `str`
837-
objects, to uniformly surrogate-escaped strings."""
838-
assert isinstance(args, list)
839-
840-
def convert(arg) -> str:
841-
if isinstance(arg, bytes):
842-
return os.fsdecode(arg)
843-
return arg
844-
845-
return [convert(a) for a in args]
846-
847-
848828
# stdout and stderr as bytes
849829
class CommandOutput(NamedTuple):
850830
stdout: bytes
@@ -869,7 +849,7 @@ def command_output(cmd: list[BytesOrStr], shell: bool = False) -> CommandOutput:
869849
This replaces `subprocess.check_output` which can have problems if lots of
870850
output is sent to stderr.
871851
"""
872-
converted_cmd = convert_command_args(cmd)
852+
converted_cmd = [os.fsdecode(a) for a in cmd]
873853

874854
devnull = subprocess.DEVNULL
875855

beetsplug/convert.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from beets import art, config, plugins, ui, util
2929
from beets.library import Item, parse_query_string
3030
from beets.plugins import BeetsPlugin
31-
from beets.util import arg_encoding, par_map
31+
from beets.util import par_map
3232
from beets.util.artresizer import ArtResizer
3333
from beets.util.m3u import M3UFile
3434

@@ -284,7 +284,7 @@ def encode(self, command, source, dest, pretend=False):
284284
if not quiet and not pretend:
285285
self._log.info("Encoding {0}", util.displayable_path(source))
286286

287-
command = command.decode(arg_encoding(), "surrogateescape")
287+
command = os.fsdecode(command)
288288
source = os.fsdecode(source)
289289
dest = os.fsdecode(dest)
290290

@@ -298,7 +298,7 @@ def encode(self, command, source, dest, pretend=False):
298298
"dest": dest,
299299
}
300300
)
301-
encode_cmd.append(args[i].encode(util.arg_encoding()))
301+
encode_cmd.append(os.fsdecode(args[i]))
302302

303303
if pretend:
304304
self._log.info("{0}", " ".join(ui.decargs(args)))

beetsplug/hook.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
import shlex
1818
import string
1919
import subprocess
20+
import sys
2021

2122
from beets.plugins import BeetsPlugin
22-
from beets.util import arg_encoding
2323

2424

2525
class CodingFormatter(string.Formatter):
@@ -73,7 +73,7 @@ def hook_function(**kwargs):
7373

7474
# For backwards compatibility, use a string formatter that decodes
7575
# bytes (in particular, paths) to unicode strings.
76-
formatter = CodingFormatter(arg_encoding())
76+
formatter = CodingFormatter(sys.getfilesystemencoding())
7777
command_pieces = [
7878
formatter.format(piece, event=event, **kwargs)
7979
for piece in shlex.split(command)

test/plugins/test_convert.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -143,18 +143,13 @@ class ConvertCommand:
143143
in tests.
144144
"""
145145

146-
def run_convert_path(self, path, *args):
146+
def run_convert_path(self, item, *args):
147147
"""Run the `convert` command on a given path."""
148-
# The path is currently a filesystem bytestring. Convert it to
149-
# an argument bytestring.
150-
path = os.fsencode(os.fsdecode(path))
151-
152-
args = args + (b"path:" + path,)
153-
return self.run_command("convert", *args)
148+
return self.run_command("convert", *args, f"path:{item.filepath}")
154149

155150
def run_convert(self, *args):
156151
"""Run the `convert` command on `self.item`."""
157-
return self.run_convert_path(self.item.path, *args)
152+
return self.run_convert_path(self.item, *args)
158153

159154

160155
@_common.slow_test()
@@ -320,22 +315,22 @@ def setUp(self):
320315
def test_transcode_from_lossless(self):
321316
[item] = self.add_item_fixtures(ext="flac")
322317
with control_stdin("y"):
323-
self.run_convert_path(item.path)
318+
self.run_convert_path(item)
324319
converted = os.path.join(self.convert_dest, b"converted.mp3")
325320
self.assertFileTag(converted, "mp3")
326321

327322
def test_transcode_from_lossy(self):
328323
self.config["convert"]["never_convert_lossy_files"] = False
329324
[item] = self.add_item_fixtures(ext="ogg")
330325
with control_stdin("y"):
331-
self.run_convert_path(item.path)
326+
self.run_convert_path(item)
332327
converted = os.path.join(self.convert_dest, b"converted.mp3")
333328
self.assertFileTag(converted, "mp3")
334329

335330
def test_transcode_from_lossy_prevented(self):
336331
[item] = self.add_item_fixtures(ext="ogg")
337332
with control_stdin("y"):
338-
self.run_convert_path(item.path)
333+
self.run_convert_path(item)
339334
converted = os.path.join(self.convert_dest, b"converted.ogg")
340335
self.assertNoFileTag(converted, "mp3")
341336

test/plugins/test_thumbnails.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,10 @@ def exists(path):
100100

101101
@patch("beetsplug.thumbnails.ThumbnailsPlugin._check_local_ok", Mock())
102102
@patch("beetsplug.thumbnails.ArtResizer")
103-
@patch("beetsplug.thumbnails.util")
103+
@patch("beets.util.syspath", Mock(side_effect=lambda x: x))
104104
@patch("beetsplug.thumbnails.os")
105105
@patch("beetsplug.thumbnails.shutil")
106-
def test_make_cover_thumbnail(
107-
self, mock_shutils, mock_os, mock_util, mock_artresizer
108-
):
106+
def test_make_cover_thumbnail(self, mock_shutils, mock_os, mock_artresizer):
109107
thumbnail_dir = os.path.normpath(b"/thumbnail/dir")
110108
md5_file = os.path.join(thumbnail_dir, b"md5")
111109
path_to_art = os.path.normpath(b"/path/to/art")
@@ -116,7 +114,6 @@ def test_make_cover_thumbnail(
116114
plugin.add_tags = Mock()
117115

118116
album = Mock(artpath=path_to_art)
119-
mock_util.syspath.side_effect = lambda x: x
120117
plugin.thumbnail_file_name = Mock(return_value=b"md5")
121118
mock_os.path.exists.return_value = False
122119

test/rsrc/convert_stub.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,9 @@
44
a specified text tag.
55
"""
66

7-
import locale
87
import sys
98

109

11-
# From `beets.util`.
12-
def arg_encoding():
13-
try:
14-
return locale.getdefaultlocale()[1] or "utf-8"
15-
except ValueError:
16-
return "utf-8"
17-
18-
1910
def convert(in_file, out_file, tag):
2011
"""Copy `in_file` to `out_file` and append the string `tag`."""
2112
if not isinstance(tag, bytes):

test/test_ui.py

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,9 @@ def setUp(self):
865865

866866
# Custom BEETSDIR
867867
self.beetsdir = os.path.join(self.temp_dir, b"beetsdir")
868+
self.cli_config_path = os.path.join(
869+
os.fsdecode(self.temp_dir), "config.yaml"
870+
)
868871
os.makedirs(syspath(self.beetsdir))
869872
self.env_patcher = patch(
870873
"os.environ",
@@ -952,20 +955,18 @@ def test_multiple_replacements_parsed(self):
952955
assert repls == [("[xy]", "z"), ("foo", "bar")]
953956

954957
def test_cli_config_option(self):
955-
config_path = os.path.join(self.temp_dir, b"config.yaml")
956-
with open(config_path, "w") as file:
958+
with open(self.cli_config_path, "w") as file:
957959
file.write("anoption: value")
958-
self.run_command("--config", config_path, "test", lib=None)
960+
self.run_command("--config", self.cli_config_path, "test", lib=None)
959961
assert config["anoption"].get() == "value"
960962

961963
def test_cli_config_file_overwrites_user_defaults(self):
962964
with open(self.user_config_path, "w") as file:
963965
file.write("anoption: value")
964966

965-
cli_config_path = os.path.join(self.temp_dir, b"config.yaml")
966-
with open(cli_config_path, "w") as file:
967+
with open(self.cli_config_path, "w") as file:
967968
file.write("anoption: cli overwrite")
968-
self.run_command("--config", cli_config_path, "test", lib=None)
969+
self.run_command("--config", self.cli_config_path, "test", lib=None)
969970
assert config["anoption"].get() == "cli overwrite"
970971

971972
def test_cli_config_file_overwrites_beetsdir_defaults(self):
@@ -974,10 +975,9 @@ def test_cli_config_file_overwrites_beetsdir_defaults(self):
974975
with open(env_config_path, "w") as file:
975976
file.write("anoption: value")
976977

977-
cli_config_path = os.path.join(self.temp_dir, b"config.yaml")
978-
with open(cli_config_path, "w") as file:
978+
with open(self.cli_config_path, "w") as file:
979979
file.write("anoption: cli overwrite")
980-
self.run_command("--config", cli_config_path, "test", lib=None)
980+
self.run_command("--config", self.cli_config_path, "test", lib=None)
981981
assert config["anoption"].get() == "cli overwrite"
982982

983983
# @unittest.skip('Difficult to implement with optparse')
@@ -998,29 +998,27 @@ def test_cli_config_file_overwrites_beetsdir_defaults(self):
998998
#
999999
# @unittest.skip('Difficult to implement with optparse')
10001000
# def test_multiple_cli_config_overwrite(self):
1001-
# cli_config_path = os.path.join(self.temp_dir, b'config.yaml')
10021001
# cli_overwrite_config_path = os.path.join(self.temp_dir,
10031002
# b'overwrite_config.yaml')
10041003
#
1005-
# with open(cli_config_path, 'w') as file:
1004+
# with open(self.cli_config_path, 'w') as file:
10061005
# file.write('anoption: value')
10071006
#
10081007
# with open(cli_overwrite_config_path, 'w') as file:
10091008
# file.write('anoption: overwrite')
10101009
#
1011-
# self.run_command('--config', cli_config_path,
1010+
# self.run_command('--config', self.cli_config_path,
10121011
# '--config', cli_overwrite_config_path, 'test')
10131012
# assert config['anoption'].get() == 'cli overwrite'
10141013

10151014
# FIXME: fails on windows
10161015
@unittest.skipIf(sys.platform == "win32", "win32")
10171016
def test_cli_config_paths_resolve_relative_to_user_dir(self):
1018-
cli_config_path = os.path.join(self.temp_dir, b"config.yaml")
1019-
with open(cli_config_path, "w") as file:
1017+
with open(self.cli_config_path, "w") as file:
10201018
file.write("library: beets.db\n")
10211019
file.write("statefile: state")
10221020

1023-
self.run_command("--config", cli_config_path, "test", lib=None)
1021+
self.run_command("--config", self.cli_config_path, "test", lib=None)
10241022
self.assert_equal_path(
10251023
util.bytestring_path(config["library"].as_filename()),
10261024
os.path.join(self.user_config_dir, b"beets.db"),
@@ -1033,12 +1031,11 @@ def test_cli_config_paths_resolve_relative_to_user_dir(self):
10331031
def test_cli_config_paths_resolve_relative_to_beetsdir(self):
10341032
os.environ["BEETSDIR"] = os.fsdecode(self.beetsdir)
10351033

1036-
cli_config_path = os.path.join(self.temp_dir, b"config.yaml")
1037-
with open(cli_config_path, "w") as file:
1034+
with open(self.cli_config_path, "w") as file:
10381035
file.write("library: beets.db\n")
10391036
file.write("statefile: state")
10401037

1041-
self.run_command("--config", cli_config_path, "test", lib=None)
1038+
self.run_command("--config", self.cli_config_path, "test", lib=None)
10421039
self.assert_equal_path(
10431040
util.bytestring_path(config["library"].as_filename()),
10441041
os.path.join(self.beetsdir, b"beets.db"),
@@ -1057,12 +1054,11 @@ def test_command_line_option_relative_to_working_dir(self):
10571054
)
10581055

10591056
def test_cli_config_file_loads_plugin_commands(self):
1060-
cli_config_path = os.path.join(self.temp_dir, b"config.yaml")
1061-
with open(cli_config_path, "w") as file:
1057+
with open(self.cli_config_path, "w") as file:
10621058
file.write("pluginpath: %s\n" % _common.PLUGINPATH)
10631059
file.write("plugins: test")
10641060

1065-
self.run_command("--config", cli_config_path, "plugin", lib=None)
1061+
self.run_command("--config", self.cli_config_path, "plugin", lib=None)
10661062
assert plugins.find_plugins()[0].is_test_plugin
10671063
self.unload_plugins()
10681064

@@ -1483,9 +1479,7 @@ def test_format_option(self):
14831479
assert output == "the album artist\n"
14841480

14851481
def test_format_option_unicode(self):
1486-
output = self.run_with_output(
1487-
b"ls", b"-f", "caf\xe9".encode(util.arg_encoding())
1488-
)
1482+
output = self.run_with_output("ls", "-f", "caf\xe9")
14891483
assert output == "caf\xe9\n"
14901484

14911485
def test_root_format_option(self):

test/test_util.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,6 @@ def test_sanitize_empty_component(self):
9797
p = util.sanitize_path("foo//bar", [(re.compile(r"^$"), "_")])
9898
assert p == "foo/_/bar"
9999

100-
@unittest.skipIf(sys.platform == "win32", "win32")
101-
def test_convert_command_args_keeps_undecodeable_bytes(self):
102-
arg = b"\x82" # non-ascii bytes
103-
cmd_args = util.convert_command_args([arg])
104-
105-
assert cmd_args[0] == arg.decode(util.arg_encoding(), "surrogateescape")
106-
107100
@patch("beets.util.subprocess.Popen")
108101
def test_command_output(self, mock_popen):
109102
def popen_fail(*args, **kwargs):

0 commit comments

Comments
 (0)