Replace py3_path and cpu_count implementations with builtins (#5227)

Replace py3_path by standard os.fsdecode and use native os.cpu_count.

These functions had been written before builtins achieving the same have
been made available (in Python 3.2 and 3.4). 

Now that they are available though, this PR updates the codebase to use
builtin implementations rather than the custom ones.
This commit is contained in:
Šarūnas Nejus 2024-06-16 11:50:27 +01:00 committed by GitHub
commit 0e87389994
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 79 additions and 129 deletions

View file

@ -51,7 +51,7 @@ from typing import (
from unidecode import unidecode from unidecode import unidecode
import beets import beets
from beets.util import functemplate, py3_path from beets.util import functemplate
from ..util.functemplate import Template from ..util.functemplate import Template
from . import types from . import types
@ -1059,9 +1059,9 @@ class Database:
""" """
# Make a new connection. The `sqlite3` module can't use # Make a new connection. The `sqlite3` module can't use
# bytestring paths here on Python 3, so we need to # bytestring paths here on Python 3, so we need to
# provide a `str` using `py3_path`. # provide a `str` using `os.fsdecode`.
conn = sqlite3.connect( conn = sqlite3.connect(
py3_path(self.path), os.fsdecode(self.path),
timeout=self.timeout, timeout=self.timeout,
# We have our own same-thread checks in _connection(), but need to # We have our own same-thread checks in _connection(), but need to
# call conn.close() in _close() # call conn.close() in _close()

View file

@ -1136,7 +1136,7 @@ class ArchiveImportTask(SentinelImportTask):
return False return False
for path_test, _ in cls.handlers(): for path_test, _ in cls.handlers():
if path_test(util.py3_path(path)): if path_test(os.fsdecode(path)):
return True return True
return False return False
@ -1186,11 +1186,11 @@ class ArchiveImportTask(SentinelImportTask):
`toppath` to that directory. `toppath` to that directory.
""" """
for path_test, handler_class in self.handlers(): for path_test, handler_class in self.handlers():
if path_test(util.py3_path(self.toppath)): if path_test(os.fsdecode(self.toppath)):
break break
extract_to = mkdtemp() extract_to = mkdtemp()
archive = handler_class(util.py3_path(self.toppath), mode="r") archive = handler_class(os.fsdecode(self.toppath), mode="r")
try: try:
archive.extractall(extract_to) archive.extractall(extract_to)

View file

@ -209,19 +209,19 @@ class TestCase(unittest.TestCase, Assertions):
# temporary directory. # temporary directory.
self.temp_dir = util.bytestring_path(tempfile.mkdtemp()) self.temp_dir = util.bytestring_path(tempfile.mkdtemp())
beets.config["statefile"] = util.py3_path( beets.config["statefile"] = os.fsdecode(
os.path.join(self.temp_dir, b"state.pickle") os.path.join(self.temp_dir, b"state.pickle")
) )
beets.config["library"] = util.py3_path( beets.config["library"] = os.fsdecode(
os.path.join(self.temp_dir, b"library.db") os.path.join(self.temp_dir, b"library.db")
) )
beets.config["directory"] = util.py3_path( beets.config["directory"] = os.fsdecode(
os.path.join(self.temp_dir, b"libdir") os.path.join(self.temp_dir, b"libdir")
) )
# Set $HOME, which is used by Confuse to create directories. # Set $HOME, which is used by Confuse to create directories.
self._old_home = os.environ.get("HOME") self._old_home = os.environ.get("HOME")
os.environ["HOME"] = util.py3_path(self.temp_dir) os.environ["HOME"] = os.fsdecode(self.temp_dir)
# Initialize, but don't install, a DummyIO. # Initialize, but don't install, a DummyIO.
self.io = DummyIO() self.io = DummyIO()

View file

@ -166,7 +166,7 @@ class TestHelper:
Make sure you call ``teardown_beets()`` afterwards. Make sure you call ``teardown_beets()`` afterwards.
""" """
self.create_temp_dir() self.create_temp_dir()
os.environ["BEETSDIR"] = util.py3_path(self.temp_dir) os.environ["BEETSDIR"] = os.fsdecode(self.temp_dir)
self.config = beets.config self.config = beets.config
self.config.clear() self.config.clear()
@ -179,7 +179,7 @@ class TestHelper:
self.libdir = os.path.join(self.temp_dir, b"libdir") self.libdir = os.path.join(self.temp_dir, b"libdir")
os.mkdir(syspath(self.libdir)) os.mkdir(syspath(self.libdir))
self.config["directory"] = util.py3_path(self.libdir) self.config["directory"] = os.fsdecode(self.libdir)
if disk: if disk:
dbpath = util.bytestring_path(self.config["library"].as_filename()) dbpath = util.bytestring_path(self.config["library"].as_filename())

View file

@ -1633,7 +1633,7 @@ def _load_plugins(options, config):
log.debug("plugin paths: {0}", util.displayable_path(paths)) log.debug("plugin paths: {0}", util.displayable_path(paths))
# On Python 3, the search paths need to be unicode. # On Python 3, the search paths need to be unicode.
paths = [util.py3_path(p) for p in paths] paths = [os.fsdecode(p) for p in paths]
# Extend the `beetsplug` package to include the plugin paths. # Extend the `beetsplug` package to include the plugin paths.
import beetsplug import beetsplug

View file

@ -803,21 +803,6 @@ def legalize_path(
return second_stage_path, retruncated return second_stage_path, retruncated
def py3_path(path: Union[bytes, str]) -> str:
"""Convert a bytestring path to Unicode.
This helps deal with APIs on Python 3 that *only* accept Unicode
(i.e., `str` objects). I philosophically disagree with this
decision, because paths are sadly bytes on Unix, but that's the way
it is. So this function helps us "smuggle" the true bytes data
through APIs that took Python 3's Unicode mandate too seriously.
"""
if isinstance(path, str):
return path
assert isinstance(path, bytes)
return os.fsdecode(path)
def str2bool(value: str) -> bool: def str2bool(value: str) -> bool:
"""Returns a boolean reflecting a human-entered string.""" """Returns a boolean reflecting a human-entered string."""
return value.lower() in ("yes", "1", "true", "t", "y") return value.lower() in ("yes", "1", "true", "t", "y")
@ -848,41 +833,6 @@ def plurality(objs: Sequence[T]) -> T:
return c.most_common(1)[0] return c.most_common(1)[0]
def cpu_count() -> int:
"""Return the number of hardware thread contexts (cores or SMT
threads) in the system.
"""
# Adapted from the soundconverter project:
# https://github.com/kassoulet/soundconverter
if sys.platform == "win32":
try:
num = int(os.environ["NUMBER_OF_PROCESSORS"])
except (ValueError, KeyError):
num = 0
elif sys.platform == "darwin":
try:
num = int(
command_output(
[
"/usr/sbin/sysctl",
"-n",
"hw.ncpu",
]
).stdout
)
except (ValueError, OSError, subprocess.CalledProcessError):
num = 0
else:
try:
num = os.sysconf("SC_NPROCESSORS_ONLN")
except (ValueError, OSError, AttributeError):
num = 0
if num >= 1:
return num
else:
return 1
def convert_command_args(args: List[bytes]) -> List[str]: def convert_command_args(args: List[bytes]) -> List[str]:
"""Convert command arguments, which may either be `bytes` or `str` """Convert command arguments, which may either be `bytes` or `str`
objects, to uniformly surrogate-escaped strings.""" objects, to uniformly surrogate-escaped strings."""

View file

@ -26,7 +26,7 @@ from tempfile import NamedTemporaryFile
from urllib.parse import urlencode from urllib.parse import urlencode
from beets import logging, util from beets import logging, util
from beets.util import bytestring_path, displayable_path, py3_path, syspath from beets.util import bytestring_path, displayable_path, syspath
PROXY_URL = "https://images.weserv.nl/" PROXY_URL = "https://images.weserv.nl/"
@ -53,7 +53,7 @@ def temp_file_for(path):
specified path. specified path.
""" """
ext = os.path.splitext(path)[1] ext = os.path.splitext(path)[1]
with NamedTemporaryFile(suffix=py3_path(ext), delete=False) as f: with NamedTemporaryFile(suffix=os.fsdecode(ext), delete=False) as f:
return bytestring_path(f.name) return bytestring_path(f.name)
@ -386,7 +386,7 @@ class PILBackend(LocalBackend):
# progressive=False only affects JPEGs and is the default, # progressive=False only affects JPEGs and is the default,
# but we include it here for explicitness. # but we include it here for explicitness.
im.save(py3_path(path_out), quality=quality, progressive=False) im.save(os.fsdecode(path_out), quality=quality, progressive=False)
if max_filesize > 0: if max_filesize > 0:
# If maximum filesize is set, we attempt to lower the quality # If maximum filesize is set, we attempt to lower the quality
@ -410,7 +410,7 @@ class PILBackend(LocalBackend):
lower_qual = 10 lower_qual = 10
# Use optimize flag to improve filesize decrease # Use optimize flag to improve filesize decrease
im.save( im.save(
py3_path(path_out), os.fsdecode(path_out),
quality=lower_qual, quality=lower_qual,
optimize=True, optimize=True,
progressive=False, progressive=False,
@ -447,7 +447,7 @@ class PILBackend(LocalBackend):
try: try:
im = Image.open(syspath(path_in)) im = Image.open(syspath(path_in))
im.save(py3_path(path_out), progressive=False) im.save(os.fsdecode(path_out), progressive=False)
return path_out return path_out
except OSError: except OSError:
# FIXME: Should probably issue a warning? # FIXME: Should probably issue a warning?
@ -473,7 +473,7 @@ class PILBackend(LocalBackend):
try: try:
with Image.open(syspath(source)) as im: with Image.open(syspath(source)) as im:
im.save(py3_path(target), progressive=not deinterlaced) im.save(os.fsdecode(target), progressive=not deinterlaced)
return target return target
except ( except (
ValueError, ValueError,
@ -506,7 +506,7 @@ class PILBackend(LocalBackend):
meta = PngImagePlugin.PngInfo() meta = PngImagePlugin.PngInfo()
for k, v in metadata.items(): for k, v in metadata.items():
meta.add_text(k, v, 0) meta.add_text(k, v, 0)
im.save(py3_path(file), "PNG", pnginfo=meta) im.save(os.fsdecode(file), "PNG", pnginfo=meta)
class Shareable(type): class Shareable(type):

View file

@ -15,11 +15,10 @@
"""An AURA server using Flask.""" """An AURA server using Flask."""
import os.path import os
import re import re
from dataclasses import dataclass from dataclasses import dataclass
from mimetypes import guess_type from mimetypes import guess_type
from os.path import getsize, isfile
from typing import ClassVar, Mapping, Type from typing import ClassVar, Mapping, Type
from flask import ( from flask import (
@ -46,7 +45,6 @@ from beets.dbcore.query import (
from beets.library import Album, Item, LibModel, Library from beets.library import Album, Item, LibModel, Library
from beets.plugins import BeetsPlugin from beets.plugins import BeetsPlugin
from beets.ui import Subcommand, _open_library from beets.ui import Subcommand, _open_library
from beets.util import py3_path
# Constants # Constants
@ -482,7 +480,7 @@ class AlbumDocument(AURADocument):
} }
# Add images relationship if album has associated images # Add images relationship if album has associated images
if album.artpath: if album.artpath:
path = py3_path(album.artpath) path = os.fsdecode(album.artpath)
filename = path.split("/")[-1] filename = path.split("/")[-1]
image_id = f"album-{album.id}-{filename}" image_id = f"album-{album.id}-{filename}"
relationships["images"] = { relationships["images"] = {
@ -660,7 +658,7 @@ class ImageDocument(AURADocument):
# Cut the filename off of artpath # Cut the filename off of artpath
# This is in preparation for supporting images in the same # This is in preparation for supporting images in the same
# directory that are not tracked by beets. # directory that are not tracked by beets.
artpath = py3_path(album.artpath) artpath = os.fsdecode(album.artpath)
dir_path = "/".join(artpath.split("/")[:-1]) dir_path = "/".join(artpath.split("/")[:-1])
else: else:
# Images for other resource types are not supported # Images for other resource types are not supported
@ -668,7 +666,7 @@ class ImageDocument(AURADocument):
img_path = os.path.join(dir_path, img_filename) img_path = os.path.join(dir_path, img_filename)
# Check the image actually exists # Check the image actually exists
if isfile(img_path): if os.path.isfile(img_path):
return img_path return img_path
else: else:
return None return None
@ -690,7 +688,7 @@ class ImageDocument(AURADocument):
attributes = { attributes = {
"role": "cover", "role": "cover",
"mimetype": guess_type(image_path)[0], "mimetype": guess_type(image_path)[0],
"size": getsize(image_path), "size": os.path.getsize(image_path),
} }
try: try:
from PIL import Image from PIL import Image
@ -781,8 +779,8 @@ def audio_file(track_id):
), ),
) )
path = py3_path(track.path) path = os.fsdecode(track.path)
if not isfile(path): if not os.path.isfile(path):
return AURADocument.error( return AURADocument.error(
"404 Not Found", "404 Not Found",
"No audio file for the requested track.", "No audio file for the requested track.",

View file

@ -114,7 +114,7 @@ class ConvertPlugin(BeetsPlugin):
"pretend": False, "pretend": False,
"link": False, "link": False,
"hardlink": False, "hardlink": False,
"threads": util.cpu_count(), "threads": os.cpu_count(),
"format": "mp3", "format": "mp3",
"id3v23": "inherit", "id3v23": "inherit",
"formats": { "formats": {
@ -636,8 +636,8 @@ class ConvertPlugin(BeetsPlugin):
# Create a temporary file for the conversion. # Create a temporary file for the conversion.
tmpdir = self.config["tmpdir"].get() tmpdir = self.config["tmpdir"].get()
if tmpdir: if tmpdir:
tmpdir = util.py3_path(util.bytestring_path(tmpdir)) tmpdir = os.fsdecode(util.bytestring_path(tmpdir))
fd, dest = tempfile.mkstemp(util.py3_path(b"." + ext), dir=tmpdir) fd, dest = tempfile.mkstemp(os.fsdecode(b"." + ext), dir=tmpdir)
os.close(fd) os.close(fd)
dest = util.bytestring_path(dest) dest = util.bytestring_path(dest)
_temp_files.append(dest) # Delete the transcode later. _temp_files.append(dest) # Delete the transcode later.

View file

@ -26,7 +26,7 @@ import requests
from mediafile import image_mime_type from mediafile import image_mime_type
from beets import config, importer, plugins, ui, util from beets import config, importer, plugins, ui, util
from beets.util import bytestring_path, py3_path, sorted_walk, syspath from beets.util import bytestring_path, sorted_walk, syspath
from beets.util.artresizer import ArtResizer from beets.util.artresizer import ArtResizer
try: try:
@ -381,7 +381,7 @@ class RemoteArtSource(ArtSource):
ext, ext,
) )
suffix = py3_path(ext) suffix = os.fsdecode(ext)
with NamedTemporaryFile(suffix=suffix, delete=False) as fh: with NamedTemporaryFile(suffix=suffix, delete=False) as fh:
# write the first already loaded part of the image # write the first already loaded part of the image
fh.write(header) fh.write(header)

View file

@ -49,13 +49,7 @@ from beets import ui
from beets.importer import ImportSession, ImportTask from beets.importer import ImportSession, ImportTask
from beets.library import Album, Item, Library from beets.library import Album, Item, Library
from beets.plugins import BeetsPlugin from beets.plugins import BeetsPlugin
from beets.util import ( from beets.util import command_output, displayable_path, syspath
command_output,
cpu_count,
displayable_path,
py3_path,
syspath,
)
# Utilities. # Utilities.
@ -942,7 +936,7 @@ class GStreamerBackend(Backend):
self._file = self._files.pop(0) self._file = self._files.pop(0)
self._pipe.set_state(self.Gst.State.NULL) self._pipe.set_state(self.Gst.State.NULL)
self._src.set_property("location", py3_path(syspath(self._file))) self._src.set_property("location", os.fsdecode(syspath(self._file)))
self._pipe.set_state(self.Gst.State.PLAYING) self._pipe.set_state(self.Gst.State.PLAYING)
return True return True
@ -972,7 +966,7 @@ class GStreamerBackend(Backend):
# Set a new file on the filesrc element, can only be done in the # Set a new file on the filesrc element, can only be done in the
# READY state # READY state
self._src.set_state(self.Gst.State.READY) self._src.set_state(self.Gst.State.READY)
self._src.set_property("location", py3_path(syspath(self._file))) self._src.set_property("location", os.fsdecode(syspath(self._file)))
self._decbin.link(self._conv) self._decbin.link(self._conv)
self._pipe.set_state(self.Gst.State.READY) self._pipe.set_state(self.Gst.State.READY)
@ -1050,7 +1044,9 @@ class AudioToolsBackend(Backend):
file format is not supported file format is not supported
""" """
try: try:
audiofile = self._mod_audiotools.open(py3_path(syspath(item.path))) audiofile = self._mod_audiotools.open(
os.fsdecode(syspath(item.path))
)
except OSError: except OSError:
raise ReplayGainError(f"File {item.path} was not found") raise ReplayGainError(f"File {item.path} was not found")
except self._mod_audiotools.UnsupportedFile: except self._mod_audiotools.UnsupportedFile:
@ -1226,7 +1222,7 @@ class ReplayGainPlugin(BeetsPlugin):
"overwrite": False, "overwrite": False,
"auto": True, "auto": True,
"backend": "command", "backend": "command",
"threads": cpu_count(), "threads": os.cpu_count(),
"parallel_on_import": False, "parallel_on_import": False,
"per_disc": False, "per_disc": False,
"peak": "true", "peak": "true",

View file

@ -222,7 +222,7 @@ class PathlibURI(URIGetter):
name = "Python Pathlib" name = "Python Pathlib"
def uri(self, path): def uri(self, path):
return PurePosixPath(util.py3_path(path)).as_uri() return PurePosixPath(os.fsdecode(path)).as_uri()
def copy_c_string(c_string): def copy_c_string(c_string):

View file

@ -312,7 +312,7 @@ def item_file(item_id):
if os.name == "nt": if os.name == "nt":
item_path = util.syspath(item.path) item_path = util.syspath(item.path)
else: else:
item_path = util.py3_path(item.path) item_path = os.fsdecode(item.path)
base_filename = os.path.basename(item_path) base_filename = os.path.basename(item_path)
# FIXME: Arguably, this should just use `displayable_path`: The latter # FIXME: Arguably, this should just use `displayable_path`: The latter

View file

@ -33,7 +33,7 @@ import confuse
import yaml import yaml
from beets.test.helper import TestHelper from beets.test.helper import TestHelper
from beets.util import bluelet, py3_path from beets.util import bluelet
from beetsplug import bpd from beetsplug import bpd
gstplayer = importlib.util.module_from_spec( gstplayer = importlib.util.module_from_spec(
@ -313,7 +313,7 @@ class BPDTestHelper(unittest.TestCase, TestHelper):
""" """
# Create a config file: # Create a config file:
config = { config = {
"pluginpath": [py3_path(self.temp_dir)], "pluginpath": [os.fsdecode(self.temp_dir)],
"plugins": "bpd", "plugins": "bpd",
# use port 0 to let the OS choose a free port # use port 0 to let the OS choose a free port
"bpd": {"host": host, "port": 0, "control_port": 0}, "bpd": {"host": host, "port": 0, "control_port": 0},
@ -321,7 +321,10 @@ class BPDTestHelper(unittest.TestCase, TestHelper):
if password: if password:
config["bpd"]["password"] = password config["bpd"]["password"] = password
config_file = tempfile.NamedTemporaryFile( config_file = tempfile.NamedTemporaryFile(
mode="wb", dir=py3_path(self.temp_dir), suffix=".yaml", delete=False mode="wb",
dir=os.fsdecode(self.temp_dir),
suffix=".yaml",
delete=False,
) )
config_file.write( config_file.write(
yaml.dump(config, Dumper=confuse.Dumper, encoding="utf-8") yaml.dump(config, Dumper=confuse.Dumper, encoding="utf-8")
@ -337,9 +340,9 @@ class BPDTestHelper(unittest.TestCase, TestHelper):
"--library", "--library",
self.config["library"].as_filename(), self.config["library"].as_filename(),
"--directory", "--directory",
py3_path(self.libdir), os.fsdecode(self.libdir),
"--config", "--config",
py3_path(config_file.name), os.fsdecode(config_file.name),
"bpd", "bpd",
], ],
assigned_port, assigned_port,
@ -399,7 +402,11 @@ class BPDTestHelper(unittest.TestCase, TestHelper):
"""Add the given item to the BPD playlist or queue.""" """Add the given item to the BPD playlist or queue."""
paths = [ paths = [
"/".join( "/".join(
[item.artist, item.album, py3_path(os.path.basename(item.path))] [
item.artist,
item.album,
os.fsdecode(os.path.basename(item.path)),
]
) )
for item in items for item in items
] ]

View file

@ -14,7 +14,7 @@
import unittest import unittest
from os import path, remove from os import fsdecode, path, remove
from shutil import rmtree from shutil import rmtree
from tempfile import mkdtemp from tempfile import mkdtemp
from unittest.mock import MagicMock, Mock, PropertyMock from unittest.mock import MagicMock, Mock, PropertyMock
@ -26,7 +26,7 @@ from beets.library import Album, Item, parse_query_string
from beets.test import _common from beets.test import _common
from beets.test.helper import TestHelper from beets.test.helper import TestHelper
from beets.ui import UserError from beets.ui import UserError
from beets.util import CHAR_REPLACE, bytestring_path, py3_path, syspath from beets.util import CHAR_REPLACE, bytestring_path, syspath
from beetsplug.smartplaylist import SmartPlaylistPlugin from beetsplug.smartplaylist import SmartPlaylistPlugin
@ -173,7 +173,7 @@ class SmartPlaylistTest(_common.TestCase):
dir = bytestring_path(mkdtemp()) dir = bytestring_path(mkdtemp())
config["smartplaylist"]["relative_to"] = False config["smartplaylist"]["relative_to"] = False
config["smartplaylist"]["playlist_dir"] = py3_path(dir) config["smartplaylist"]["playlist_dir"] = fsdecode(dir)
try: try:
spl.update_playlists(lib) spl.update_playlists(lib)
except Exception: except Exception:
@ -218,7 +218,7 @@ class SmartPlaylistTest(_common.TestCase):
config["smartplaylist"]["output"] = "extm3u" config["smartplaylist"]["output"] = "extm3u"
config["smartplaylist"]["prefix"] = "http://beets:8337/files" config["smartplaylist"]["prefix"] = "http://beets:8337/files"
config["smartplaylist"]["relative_to"] = False config["smartplaylist"]["relative_to"] = False
config["smartplaylist"]["playlist_dir"] = py3_path(dir) config["smartplaylist"]["playlist_dir"] = fsdecode(dir)
try: try:
spl.update_playlists(lib) spl.update_playlists(lib)
except Exception: except Exception:
@ -269,7 +269,7 @@ class SmartPlaylistTest(_common.TestCase):
dir = bytestring_path(mkdtemp()) dir = bytestring_path(mkdtemp())
config["smartplaylist"]["output"] = "extm3u" config["smartplaylist"]["output"] = "extm3u"
config["smartplaylist"]["relative_to"] = False config["smartplaylist"]["relative_to"] = False
config["smartplaylist"]["playlist_dir"] = py3_path(dir) config["smartplaylist"]["playlist_dir"] = fsdecode(dir)
config["smartplaylist"]["fields"] = ["id", "genre"] config["smartplaylist"]["fields"] = ["id", "genre"]
try: try:
spl.update_playlists(lib) spl.update_playlists(lib)
@ -316,7 +316,7 @@ class SmartPlaylistTest(_common.TestCase):
dir = bytestring_path(mkdtemp()) dir = bytestring_path(mkdtemp())
tpl = "http://beets:8337/item/$id/file" tpl = "http://beets:8337/item/$id/file"
config["smartplaylist"]["uri_format"] = tpl config["smartplaylist"]["uri_format"] = tpl
config["smartplaylist"]["playlist_dir"] = py3_path(dir) config["smartplaylist"]["playlist_dir"] = fsdecode(dir)
# The following options should be ignored when uri_format is set # The following options should be ignored when uri_format is set
config["smartplaylist"]["relative_to"] = "/data" config["smartplaylist"]["relative_to"] = "/data"
config["smartplaylist"]["prefix"] = "/prefix" config["smartplaylist"]["prefix"] = "/prefix"
@ -350,7 +350,7 @@ class SmartPlaylistCLITest(_common.TestCase, TestHelper):
{"name": "all.m3u", "query": ""}, {"name": "all.m3u", "query": ""},
] ]
) )
config["smartplaylist"]["playlist_dir"].set(py3_path(self.temp_dir)) config["smartplaylist"]["playlist_dir"].set(fsdecode(self.temp_dir))
self.load_plugins("smartplaylist") self.load_plugins("smartplaylist")
def tearDown(self): def tearDown(self):

View file

@ -41,7 +41,7 @@ from beets.test.helper import (
capture_log, capture_log,
has_program, has_program,
) )
from beets.util import bytestring_path, displayable_path, py3_path, syspath from beets.util import bytestring_path, displayable_path, syspath
class ScrubbedImportTest(_common.TestCase, ImportHelper): class ScrubbedImportTest(_common.TestCase, ImportHelper):
@ -261,10 +261,10 @@ class NonAutotaggedImportTest(_common.TestCase, ImportHelper):
def create_archive(session): def create_archive(session):
(handle, path) = mkstemp(dir=py3_path(session.temp_dir)) (handle, path) = mkstemp(dir=os.fsdecode(session.temp_dir))
path = bytestring_path(path) path = bytestring_path(path)
os.close(handle) os.close(handle)
archive = ZipFile(py3_path(path), mode="w") archive = ZipFile(os.fsdecode(path), mode="w")
archive.write(syspath(os.path.join(_common.RSRC, b"full.mp3")), "full.mp3") archive.write(syspath(os.path.join(_common.RSRC, b"full.mp3")), "full.mp3")
archive.close() archive.close()
path = bytestring_path(path) path = bytestring_path(path)
@ -319,7 +319,7 @@ class ImportTarTest(ImportZipTest):
(handle, path) = mkstemp(dir=syspath(self.temp_dir)) (handle, path) = mkstemp(dir=syspath(self.temp_dir))
path = bytestring_path(path) path = bytestring_path(path)
os.close(handle) os.close(handle)
archive = TarFile(py3_path(path), mode="w") archive = TarFile(os.fsdecode(path), mode="w")
archive.add( archive.add(
syspath(os.path.join(_common.RSRC, b"full.mp3")), "full.mp3" syspath(os.path.join(_common.RSRC, b"full.mp3")), "full.mp3"
) )

View file

@ -22,7 +22,6 @@ from datetime import datetime
from beets.library import Item from beets.library import Item
from beets.test import _common from beets.test import _common
from beets.test.helper import TestHelper from beets.test.helper import TestHelper
from beets.util import py3_path
def _parsetime(s): def _parsetime(s):
@ -46,11 +45,11 @@ class MetaSyncTest(_common.TestCase, TestHelper):
self.config["metasync"]["source"] = "itunes" self.config["metasync"]["source"] = "itunes"
if _is_windows(): if _is_windows():
self.config["metasync"]["itunes"]["library"] = py3_path( self.config["metasync"]["itunes"]["library"] = os.fsdecode(
self.itunes_library_windows self.itunes_library_windows
) )
else: else:
self.config["metasync"]["itunes"]["library"] = py3_path( self.config["metasync"]["itunes"]["library"] = os.fsdecode(
self.itunes_library_unix self.itunes_library_unix
) )

View file

@ -852,11 +852,11 @@ class ConfigTest(unittest.TestCase, TestHelper, _common.Assertions):
# directory there. Some tests will set `BEETSDIR` themselves. # directory there. Some tests will set `BEETSDIR` themselves.
del os.environ["BEETSDIR"] del os.environ["BEETSDIR"]
self._old_home = os.environ.get("HOME") self._old_home = os.environ.get("HOME")
os.environ["HOME"] = util.py3_path(self.temp_dir) os.environ["HOME"] = os.fsdecode(self.temp_dir)
# Also set APPDATA, the Windows equivalent of setting $HOME. # Also set APPDATA, the Windows equivalent of setting $HOME.
self._old_appdata = os.environ.get("APPDATA") self._old_appdata = os.environ.get("APPDATA")
os.environ["APPDATA"] = util.py3_path( os.environ["APPDATA"] = os.fsdecode(
os.path.join(self.temp_dir, b"AppData", b"Roaming") os.path.join(self.temp_dir, b"AppData", b"Roaming")
) )
@ -992,7 +992,7 @@ class ConfigTest(unittest.TestCase, TestHelper, _common.Assertions):
self.assertEqual(config["anoption"].get(), "cli overwrite") self.assertEqual(config["anoption"].get(), "cli overwrite")
def test_cli_config_file_overwrites_beetsdir_defaults(self): def test_cli_config_file_overwrites_beetsdir_defaults(self):
os.environ["BEETSDIR"] = util.py3_path(self.beetsdir) os.environ["BEETSDIR"] = os.fsdecode(self.beetsdir)
env_config_path = os.path.join(self.beetsdir, b"config.yaml") env_config_path = os.path.join(self.beetsdir, b"config.yaml")
with open(env_config_path, "w") as file: with open(env_config_path, "w") as file:
file.write("anoption: value") file.write("anoption: value")
@ -1054,7 +1054,7 @@ class ConfigTest(unittest.TestCase, TestHelper, _common.Assertions):
) )
def test_cli_config_paths_resolve_relative_to_beetsdir(self): def test_cli_config_paths_resolve_relative_to_beetsdir(self):
os.environ["BEETSDIR"] = util.py3_path(self.beetsdir) os.environ["BEETSDIR"] = os.fsdecode(self.beetsdir)
cli_config_path = os.path.join(self.temp_dir, b"config.yaml") cli_config_path = os.path.join(self.temp_dir, b"config.yaml")
with open(cli_config_path, "w") as file: with open(cli_config_path, "w") as file:
@ -1089,7 +1089,7 @@ class ConfigTest(unittest.TestCase, TestHelper, _common.Assertions):
self.assertTrue(plugins.find_plugins()[0].is_test_plugin) self.assertTrue(plugins.find_plugins()[0].is_test_plugin)
def test_beetsdir_config(self): def test_beetsdir_config(self):
os.environ["BEETSDIR"] = util.py3_path(self.beetsdir) os.environ["BEETSDIR"] = os.fsdecode(self.beetsdir)
env_config_path = os.path.join(self.beetsdir, b"config.yaml") env_config_path = os.path.join(self.beetsdir, b"config.yaml")
with open(env_config_path, "w") as file: with open(env_config_path, "w") as file:
@ -1101,11 +1101,11 @@ class ConfigTest(unittest.TestCase, TestHelper, _common.Assertions):
def test_beetsdir_points_to_file_error(self): def test_beetsdir_points_to_file_error(self):
beetsdir = os.path.join(self.temp_dir, b"beetsfile") beetsdir = os.path.join(self.temp_dir, b"beetsfile")
open(beetsdir, "a").close() open(beetsdir, "a").close()
os.environ["BEETSDIR"] = util.py3_path(beetsdir) os.environ["BEETSDIR"] = os.fsdecode(beetsdir)
self.assertRaises(ConfigError, self.run_command, "test") self.assertRaises(ConfigError, self.run_command, "test")
def test_beetsdir_config_does_not_load_default_user_config(self): def test_beetsdir_config_does_not_load_default_user_config(self):
os.environ["BEETSDIR"] = util.py3_path(self.beetsdir) os.environ["BEETSDIR"] = os.fsdecode(self.beetsdir)
with open(self.user_config_path, "w") as file: with open(self.user_config_path, "w") as file:
file.write("anoption: value") file.write("anoption: value")
@ -1114,7 +1114,7 @@ class ConfigTest(unittest.TestCase, TestHelper, _common.Assertions):
self.assertFalse(config["anoption"].exists()) self.assertFalse(config["anoption"].exists())
def test_default_config_paths_resolve_relative_to_beetsdir(self): def test_default_config_paths_resolve_relative_to_beetsdir(self):
os.environ["BEETSDIR"] = util.py3_path(self.beetsdir) os.environ["BEETSDIR"] = os.fsdecode(self.beetsdir)
config.read() config.read()
self.assert_equal_path( self.assert_equal_path(
@ -1127,7 +1127,7 @@ class ConfigTest(unittest.TestCase, TestHelper, _common.Assertions):
) )
def test_beetsdir_config_paths_resolve_relative_to_beetsdir(self): def test_beetsdir_config_paths_resolve_relative_to_beetsdir(self):
os.environ["BEETSDIR"] = util.py3_path(self.beetsdir) os.environ["BEETSDIR"] = os.fsdecode(self.beetsdir)
env_config_path = os.path.join(self.beetsdir, b"config.yaml") env_config_path = os.path.join(self.beetsdir, b"config.yaml")
with open(env_config_path, "w") as file: with open(env_config_path, "w") as file:

View file

@ -131,7 +131,7 @@ class InitTest(_common.LibTestCase):
class ParentalDirCreation(_common.TestCase): class ParentalDirCreation(_common.TestCase):
def test_create_yes(self): def test_create_yes(self):
non_exist_path = _common.util.py3_path( non_exist_path = _common.os.fsdecode(
os.path.join(self.temp_dir, b"nonexist", str(random()).encode()) os.path.join(self.temp_dir, b"nonexist", str(random()).encode())
) )
# Deepcopy instead of recovering because exceptions might # Deepcopy instead of recovering because exceptions might
@ -143,10 +143,10 @@ class ParentalDirCreation(_common.TestCase):
lib._close() lib._close()
def test_create_no(self): def test_create_no(self):
non_exist_path_parent = _common.util.py3_path( non_exist_path_parent = _common.os.fsdecode(
os.path.join(self.temp_dir, b"nonexist") os.path.join(self.temp_dir, b"nonexist")
) )
non_exist_path = _common.util.py3_path( non_exist_path = _common.os.fsdecode(
os.path.join(non_exist_path_parent.encode(), str(random()).encode()) os.path.join(non_exist_path_parent.encode(), str(random()).encode())
) )
test_config = deepcopy(config) test_config = deepcopy(config)