Bug 1934111 - Remove usage of six in python/mach r=firefox-build-system-reviewers,ahochheiden

Leveraged pyupgrade to remove usage of six as well as modernize some code that no longer needs to be compatible with Python 2.

Differential Revision: https://phabricator.services.mozilla.com/D230612
This commit is contained in:
Logan Rosen
2024-12-12 02:29:30 +00:00
parent b6b36f97db
commit 56c7b3d205
20 changed files with 49 additions and 64 deletions

View File

@@ -3,7 +3,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
class CommandContext(object): class CommandContext:
"""Holds run-time state so it can easily be passed to command providers.""" """Holds run-time state so it can easily be passed to command providers."""
def __init__( def __init__(

View File

@@ -458,7 +458,7 @@ def load_commands_from_file(path: Union[str, Path], module_name=None):
try: try:
load_source(module_name, str(path)) load_source(module_name, str(path))
except IOError as e: except OSError as e:
if e.errno != errno.ENOENT: if e.errno != errno.ENOENT:
raise raise
@@ -472,7 +472,7 @@ def load_commands_from_spec(
Takes a dictionary mapping command names to their metadata. Takes a dictionary mapping command names to their metadata.
""" """
modules = set(spec[command].module for command in spec) modules = {spec[command].module for command in spec}
for path in modules: for path in modules:
try: try:

View File

@@ -18,7 +18,7 @@ COMPLETION_TEMPLATES_DIR = Path(__file__).resolve().parent / "completion_templat
@attr.s @attr.s
class CommandInfo(object): class CommandInfo:
name = attr.ib(type=str) name = attr.ib(type=str)
description = attr.ib(type=str) description = attr.ib(type=str)
subcommands = attr.ib(type=list) subcommands = attr.ib(type=list)

View File

@@ -28,14 +28,14 @@ def run_settings(command_context, short=None):
wrapper = TextWrapper(initial_indent="# ", subsequent_indent="# ") wrapper = TextWrapper(initial_indent="# ", subsequent_indent="# ")
for i, section in enumerate(sorted(command_context._mach_context.settings)): for i, section in enumerate(sorted(command_context._mach_context.settings)):
if not short: if not short:
print("%s[%s]" % ("" if i == 0 else "\n", section)) print("{}[{}]".format("" if i == 0 else "\n", section))
for option in sorted(command_context._mach_context.settings[section]._settings): for option in sorted(command_context._mach_context.settings[section]._settings):
meta = command_context._mach_context.settings[section].get_meta(option) meta = command_context._mach_context.settings[section].get_meta(option)
desc = meta["description"] desc = meta["description"]
if short: if short:
print("%s.%s -- %s" % (section, option, desc.splitlines()[0])) print("{}.{} -- {}".format(section, option, desc.splitlines()[0]))
continue continue
if option == "*": if option == "*":
@@ -47,4 +47,4 @@ def run_settings(command_context, short=None):
value = "<%s>" % types[meta["type_cls"]] value = "<%s>" % types[meta["type_cls"]]
print(wrapper.fill(desc)) print(wrapper.fill(desc))
print(";%s=%s" % (option, value)) print(";{}={}".format(option, value))

View File

@@ -17,20 +17,17 @@ settings are available.
import collections import collections
import collections.abc import collections.abc
import sys import sys
from configparser import NoSectionError, RawConfigParser
from functools import wraps from functools import wraps
from pathlib import Path from pathlib import Path
from typing import List, Union from typing import List, Union
import six
from six import string_types
from six.moves.configparser import NoSectionError, RawConfigParser
class ConfigException(Exception): class ConfigException(Exception):
pass pass
class ConfigType(object): class ConfigType:
"""Abstract base class for config values.""" """Abstract base class for config values."""
@staticmethod @staticmethod
@@ -63,7 +60,7 @@ class ConfigType(object):
class StringType(ConfigType): class StringType(ConfigType):
@staticmethod @staticmethod
def validate(value): def validate(value):
if not isinstance(value, string_types): if not isinstance(value, str):
raise TypeError() raise TypeError()
@staticmethod @staticmethod
@@ -110,7 +107,7 @@ class PositiveIntegerType(IntegerType):
class PathType(StringType): class PathType(StringType):
@staticmethod @staticmethod
def validate(value): def validate(value):
if not isinstance(value, string_types): if not isinstance(value, str):
raise TypeError() raise TypeError()
@staticmethod @staticmethod
@@ -127,7 +124,7 @@ TYPE_CLASSES = {
} }
class DefaultValue(object): class DefaultValue:
pass pass
@@ -142,7 +139,7 @@ def reraise_attribute_error(func):
return func(*args, **kwargs) return func(*args, **kwargs)
except KeyError: except KeyError:
exc_class, exc, tb = sys.exc_info() exc_class, exc, tb = sys.exc_info()
six.reraise(AttributeError().__class__, exc, tb) raise exc.with_traceback(tb)
return _ return _
@@ -193,7 +190,7 @@ class ConfigSettings(collections.abc.Mapping):
will result in exceptions being raised. will result in exceptions being raised.
""" """
class ConfigSection(collections.abc.MutableMapping, object): class ConfigSection(collections.abc.MutableMapping):
"""Represents an individual config section.""" """Represents an individual config section."""
def __init__(self, config, name, settings): def __init__(self, config, name, settings):
@@ -300,7 +297,7 @@ class ConfigSettings(collections.abc.Mapping):
""" """
filtered = [f for f in filenames if f.exists()] filtered = [f for f in filenames if f.exists()]
fps = [open(f, "rt") for f in filtered] fps = [open(f) for f in filtered]
self.load_fps(fps) self.load_fps(fps)
for fp in fps: for fp in fps:
fp.close() fp.close()
@@ -334,7 +331,7 @@ class ConfigSettings(collections.abc.Mapping):
extra -- A dict of additional key/value pairs to add to the extra -- A dict of additional key/value pairs to add to the
setting metadata. setting metadata.
""" """
if isinstance(type_cls, string_types): if isinstance(type_cls, str):
type_cls = TYPE_CLASSES[type_cls] type_cls = TYPE_CLASSES[type_cls]
meta = {"description": description, "type_cls": type_cls} meta = {"description": description, "type_cls": type_cls}
@@ -363,7 +360,7 @@ class ConfigSettings(collections.abc.Mapping):
if option in config_settings[section]: if option in config_settings[section]:
raise ConfigException( raise ConfigException(
"Setting has already been registered: %s.%s" % (section, option) "Setting has already been registered: {}.{}".format(section, option)
) )
meta = self._format_metadata(*setting[1:]) meta = self._format_metadata(*setting[1:])
@@ -375,7 +372,7 @@ class ConfigSettings(collections.abc.Mapping):
for k, v in settings.items(): for k, v in settings.items():
if k in section: if k in section:
raise ConfigException( raise ConfigException(
"Setting already registered: %s.%s" % (section_name, k) "Setting already registered: {}.{}".format(section_name, k)
) )
section[k] = v section[k] = v

View File

@@ -13,7 +13,7 @@ from .base import MachError
from .registrar import Registrar from .registrar import Registrar
class _MachCommand(object): class _MachCommand:
"""Container for mach command metadata.""" """Container for mach command metadata."""
__slots__ = ( __slots__ = (
@@ -160,7 +160,7 @@ class _MachCommand(object):
parent.subcommand_handlers[self.subcommand] = self parent.subcommand_handlers[self.subcommand] = self
class Command(object): class Command:
"""Decorator for functions or methods that provide a mach command. """Decorator for functions or methods that provide a mach command.
The decorator accepts arguments that define basic attributes of the The decorator accepts arguments that define basic attributes of the
@@ -198,7 +198,7 @@ class Command(object):
return func return func
class SubCommand(object): class SubCommand:
"""Decorator for functions or methods that provide a sub-command. """Decorator for functions or methods that provide a sub-command.
Mach commands can have sub-commands. e.g. ``mach command foo`` or Mach commands can have sub-commands. e.g. ``mach command foo`` or
@@ -249,7 +249,7 @@ class SubCommand(object):
return func return func
class CommandArgument(object): class CommandArgument:
"""Decorator for additional arguments to mach subcommands. """Decorator for additional arguments to mach subcommands.
This decorator should be used to add arguments to mach commands. Arguments This decorator should be used to add arguments to mach commands. Arguments
@@ -285,7 +285,7 @@ class CommandArgument(object):
return func return func
class CommandArgumentGroup(object): class CommandArgumentGroup:
"""Decorator for additional argument groups to mach commands. """Decorator for additional argument groups to mach commands.
This decorator should be used to add arguments groups to mach commands. This decorator should be used to add arguments groups to mach commands.

View File

@@ -14,7 +14,6 @@ import sys
import time import time
import blessed import blessed
import six
from mozbuild.buildversion import mozilla_build_version from mozbuild.buildversion import mozilla_build_version
from packaging.version import Version from packaging.version import Version
@@ -62,10 +61,7 @@ def _wrap_stdstream(fh):
if fh in (sys.stderr, sys.stdout): if fh in (sys.stderr, sys.stdout):
encoding = sys.getdefaultencoding() encoding = sys.getdefaultencoding()
encoding = "utf-8" if encoding in ("ascii", "charmap") else encoding encoding = "utf-8" if encoding in ("ascii", "charmap") else encoding
if six.PY2: return codecs.getwriter(encoding)(fh.buffer, errors="replace")
return codecs.getwriter(encoding)(fh, errors="replace")
else:
return codecs.getwriter(encoding)(fh.buffer, errors="replace")
else: else:
return fh return fh
@@ -251,7 +247,7 @@ def formatted_stack_trace(record, formatter):
return rv return rv
class LoggingManager(object): class LoggingManager:
"""Holds and controls global logging state. """Holds and controls global logging state.
An application should instantiate one of these and configure it as needed. An application should instantiate one of these and configure it as needed.

View File

@@ -133,7 +133,7 @@ class ArgumentParser(argparse.ArgumentParser):
return text return text
class ContextWrapper(object): class ContextWrapper:
def __init__(self, context, handler): def __init__(self, context, handler):
object.__setattr__(self, "_context", context) object.__setattr__(self, "_context", context)
object.__setattr__(self, "_handler", handler) object.__setattr__(self, "_handler", handler)
@@ -155,7 +155,7 @@ class ContextWrapper(object):
setattr(object.__getattribute__(self, "_context"), key, value) setattr(object.__getattribute__(self, "_context"), key, value)
class Mach(object): class Mach:
"""Main mach driver type. """Main mach driver type.
This type is responsible for holding global mach state and dispatching This type is responsible for holding global mach state and dispatching

View File

@@ -5,7 +5,7 @@
import logging import logging
class LoggingMixin(object): class LoggingMixin:
"""Provides functionality to control logging.""" """Provides functionality to control logging."""
def populate_logger(self, name=None): def populate_logger(self, name=None):

View File

@@ -7,8 +7,6 @@ from copy import deepcopy
from cProfile import Profile from cProfile import Profile
from pathlib import Path from pathlib import Path
import six
from .base import MachError from .base import MachError
INVALID_COMMAND_CONTEXT = r""" INVALID_COMMAND_CONTEXT = r"""
@@ -19,7 +17,7 @@ Run |mach help| to show a list of all commands available to the current context.
""".lstrip() """.lstrip()
class MachRegistrar(object): class MachRegistrar:
"""Container for mach command and config providers.""" """Container for mach command and config providers."""
def __init__(self): def __init__(self):
@@ -141,7 +139,7 @@ class MachRegistrar(object):
print(f"python3 -m snakeviz {profile_file.name}") print(f"python3 -m snakeviz {profile_file.name}")
result = result or 0 result = result or 0
assert isinstance(result, six.integer_types) assert isinstance(result, int)
if not debug_command: if not debug_command:
postrun = getattr(context, "post_dispatch_handler", None) postrun = getattr(context, "post_dispatch_handler", None)

View File

@@ -157,7 +157,7 @@ def _parse_mach_env_requirements(
requirements_output.requirements_paths.append(str(requirements_path)) requirements_output.requirements_paths.append(str(requirements_path))
with open(requirements_path, "r") as requirements_file: with open(requirements_path) as requirements_file:
lines = [line for line in requirements_file] lines = [line for line in requirements_file]
for number, line in enumerate(lines, start=1): for number, line in enumerate(lines, start=1):

View File

@@ -15,7 +15,6 @@ from mozversioncontrol import (
MissingVCSTool, MissingVCSTool,
get_repository_object, get_repository_object,
) )
from six import string_types
from mach.telemetry import is_telemetry_enabled from mach.telemetry import is_telemetry_enabled
from mach.util import get_state_dir from mach.util import get_state_dir
@@ -26,7 +25,7 @@ _SENTRY_DSN = (
) )
class ErrorReporter(object): class ErrorReporter:
@abc.abstractmethod @abc.abstractmethod
def report_exception(self, exception): def report_exception(self, exception):
"""Report the exception to remote error-tracking software.""" """Report the exception to remote error-tracking software."""
@@ -133,7 +132,7 @@ def _patch_absolute_paths(sentry_event, topsrcdir: Path):
key = needle.sub(replacement, key) key = needle.sub(replacement, key)
value[key] = recursive_patch(next_value, needle, replacement) value[key] = recursive_patch(next_value, needle, replacement)
return value return value
elif isinstance(value, string_types): elif isinstance(value, str):
return needle.sub(replacement, value) return needle.sub(replacement, value)
else: else:
return value return value

View File

@@ -192,7 +192,7 @@ class MozSiteMetadata:
f'The virtualenv at "{prefix}" is out-of-date.' f'The virtualenv at "{prefix}" is out-of-date.'
) )
try: try:
with open(metadata_path, "r") as file: with open(metadata_path) as file:
raw = json.load(file) raw = json.load(file)
if not raw.get("is_finalized", False): if not raw.get("is_finalized", False):

View File

@@ -124,7 +124,7 @@ def resolve_setting_from_arcconfig(topsrcdir: Path, setting):
topsrcdir / ".arcconfig", topsrcdir / ".arcconfig",
]: ]:
try: try:
with open(arcconfig_path, "r") as arcconfig_file: with open(arcconfig_path) as arcconfig_file:
arcconfig = json.load(arcconfig_file) arcconfig = json.load(arcconfig_file)
except (json.JSONDecodeError, FileNotFoundError): except (json.JSONDecodeError, FileNotFoundError):
continue continue
@@ -141,7 +141,7 @@ def resolve_is_employee_by_credentials(topsrcdir: Path):
return None return None
try: try:
with open(arcrc_path(), "r") as arcrc_file: with open(arcrc_path()) as arcrc_file:
arcrc = json.load(arcrc_file) arcrc = json.load(arcrc_file)
except (json.JSONDecodeError, FileNotFoundError): except (json.JSONDecodeError, FileNotFoundError):
return None return None

View File

@@ -10,7 +10,7 @@ from unittest.mock import Mock
from mach.site import MozSiteMetadata, SitePackagesSource from mach.site import MozSiteMetadata, SitePackagesSource
class NoopTelemetry(object): class NoopTelemetry:
def __init__(self, failed_glean_import): def __init__(self, failed_glean_import):
self._failed_glean_import = failed_glean_import self._failed_glean_import = failed_glean_import
@@ -40,7 +40,7 @@ class NoopTelemetry(object):
) )
class GleanTelemetry(object): class GleanTelemetry:
"""Records and sends Telemetry using Glean. """Records and sends Telemetry using Glean.
Metrics are defined in python/mozbuild/metrics.yaml. Metrics are defined in python/mozbuild/metrics.yaml.

View File

@@ -11,8 +11,6 @@ one place, away from code that is commonly looked at.
import logging import logging
import sys import sys
from six.moves import range
class LoggingHandler(logging.Handler): class LoggingHandler(logging.Handler):
"""Custom logging handler that works with terminal window dressing. """Custom logging handler that works with terminal window dressing.
@@ -53,7 +51,7 @@ class LoggingHandler(logging.Handler):
self.flush() self.flush()
class TerminalFooter(object): class TerminalFooter:
"""Represents something drawn on the bottom of a terminal.""" """Represents something drawn on the bottom of a terminal."""
def __init__(self, terminal): def __init__(self, terminal):

View File

@@ -7,7 +7,6 @@ from pathlib import Path
from mozfile.mozfile import NamedTemporaryFile from mozfile.mozfile import NamedTemporaryFile
from mozunit import main from mozunit import main
from six import string_types
from mach.config import ( from mach.config import (
BooleanType, BooleanType,
@@ -35,7 +34,7 @@ bar = value2
@SettingsProvider @SettingsProvider
class Provider1(object): class Provider1:
config_settings = [ config_settings = [
("foo.bar", StringType, "desc"), ("foo.bar", StringType, "desc"),
("foo.baz", PathType, "desc"), ("foo.baz", PathType, "desc"),
@@ -43,7 +42,7 @@ class Provider1(object):
@SettingsProvider @SettingsProvider
class ProviderDuplicate(object): class ProviderDuplicate:
config_settings = [ config_settings = [
("dupesect.foo", StringType, "desc"), ("dupesect.foo", StringType, "desc"),
("dupesect.foo", StringType, "desc"), ("dupesect.foo", StringType, "desc"),
@@ -51,7 +50,7 @@ class ProviderDuplicate(object):
@SettingsProvider @SettingsProvider
class Provider2(object): class Provider2:
config_settings = [ config_settings = [
("a.string", StringType, "desc"), ("a.string", StringType, "desc"),
("a.boolean", BooleanType, "desc"), ("a.boolean", BooleanType, "desc"),
@@ -62,7 +61,7 @@ class Provider2(object):
@SettingsProvider @SettingsProvider
class Provider3(object): class Provider3:
@classmethod @classmethod
def config_settings(cls): def config_settings(cls):
return [ return [
@@ -75,7 +74,7 @@ class Provider3(object):
@SettingsProvider @SettingsProvider
class Provider4(object): class Provider4:
config_settings = [ config_settings = [
("foo.abc", StringType, "desc", "a", {"choices": set("abc")}), ("foo.abc", StringType, "desc", "a", {"choices": set("abc")}),
("foo.xyz", StringType, "desc", "w", {"choices": set("xyz")}), ("foo.xyz", StringType, "desc", "w", {"choices": set("xyz")}),
@@ -83,7 +82,7 @@ class Provider4(object):
@SettingsProvider @SettingsProvider
class Provider5(object): class Provider5:
config_settings = [ config_settings = [
("foo.*", "string", "desc"), ("foo.*", "string", "desc"),
("foo.bar", "string", "desc"), ("foo.bar", "string", "desc"),
@@ -189,11 +188,11 @@ class TestConfigSettings(unittest.TestCase):
a.int = -4 a.int = -4
a.path = "./foo/bar" a.path = "./foo/bar"
self.assertIsInstance(a.string, string_types) self.assertIsInstance(a.string, (str,))
self.assertIsInstance(a.boolean, bool) self.assertIsInstance(a.boolean, bool)
self.assertIsInstance(a.pos_int, int) self.assertIsInstance(a.pos_int, int)
self.assertIsInstance(a.int, int) self.assertIsInstance(a.int, int)
self.assertIsInstance(a.path, string_types) self.assertIsInstance(a.path, (str,))
def test_retrieval_type(self): def test_retrieval_type(self):
self.retrieval_type_helper(Provider2) self.retrieval_type_helper(Provider2)

View File

@@ -8,7 +8,6 @@ from pathlib import Path
import pytest import pytest
from mozunit import main from mozunit import main
from six import string_types
from mach.base import CommandContext from mach.base import CommandContext
from mach.registrar import Registrar from mach.registrar import Registrar
@@ -25,7 +24,7 @@ class TestDispatcher(unittest.TestCase):
mach.settings.register_provider(provider) mach.settings.register_provider(provider)
if config: if config:
if isinstance(config, string_types): if isinstance(config, str):
config = StringIO(config) config = StringIO(config)
mach.settings.load_fps([config]) mach.settings.load_fps([config])

View File

@@ -81,7 +81,7 @@ class PackageCache:
if vendor_path in self._cache: if vendor_path in self._cache:
return self._cache[vendor_path] return self._cache[vendor_path]
if not any((p for p in vendor_path.iterdir() if p.name.endswith(".dist-info"))): if not any(p for p in vendor_path.iterdir() if p.name.endswith(".dist-info")):
# This vendored package is not a wheel. It may be a source package (with # This vendored package is not a wheel. It may be a source package (with
# a setup.py), or just some Python code that was manually copied into the # a setup.py), or just some Python code that was manually copied into the
# tree. If it's a source package, the setup.py file may be up a few levels # tree. If it's a source package, the setup.py file may be up a few levels

View File

@@ -32,7 +32,6 @@ setup(
"blessed", "blessed",
"mozfile", "mozfile",
"mozprocess", "mozprocess",
"six",
], ],
tests_require=["mock"], tests_require=["mock"],
) )