Skip to content

Commit

Permalink
chore: use strtobool from craft-application (#4875)
Browse files Browse the repository at this point in the history
`strtobool` has been upstreamed to craft-application.

`snapcraft_legacy` uses `distutil.utils.strtobool`, which was removed in
python 3.12

Signed-off-by: Callahan Kovacs <callahan.kovacs@canonical.com>
Co-authored-by: Alex Lowe <alex.lowe@canonical.com>
  • Loading branch information
mr-cal and lengau authored Jun 27, 2024
1 parent 60d3702 commit 676e391
Show file tree
Hide file tree
Showing 10 changed files with 28 additions and 103 deletions.
5 changes: 3 additions & 2 deletions snapcraft/cli.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright 2022-2023 Canonical Ltd.
# Copyright 2022-2024 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
Expand All @@ -27,6 +27,7 @@
import craft_cli
import craft_store
from craft_application.errors import RemoteBuildError
from craft_application.util import strtobool
from craft_cli import ArgumentParsingError, EmitterMode, ProvideHelpException, emit
from craft_providers import ProviderError

Expand Down Expand Up @@ -183,7 +184,7 @@ def get_verbosity() -> EmitterMode:

with contextlib.suppress(ValueError):
# Parse environment variable for backwards compatibility with launchpad
if utils.strtobool(os.getenv("SNAPCRAFT_ENABLE_DEVELOPER_DEBUG", "n").strip()):
if strtobool(os.getenv("SNAPCRAFT_ENABLE_DEVELOPER_DEBUG", "n").strip()):
verbosity = EmitterMode.DEBUG

# if defined, use environmental variable SNAPCRAFT_VERBOSITY_LEVEL
Expand Down
5 changes: 3 additions & 2 deletions snapcraft/commands/core22/lifecycle.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright 2022 Canonical Ltd.
# Copyright 2022,2024 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
Expand All @@ -21,6 +21,7 @@
import os
import textwrap

from craft_application.util import strtobool
from craft_cli import BaseCommand, emit
from overrides import overrides

Expand Down Expand Up @@ -52,7 +53,7 @@ def fill_parser(self, parser: "argparse.ArgumentParser") -> None:
parser.add_argument(
"--enable-manifest", # Deprecated and removed in core24
action="store_true",
default=utils.strtobool(os.getenv("SNAPCRAFT_BUILD_INFO", "n")),
default=strtobool(os.getenv("SNAPCRAFT_BUILD_INFO", "n")),
help=argparse.SUPPRESS,
)
parser.add_argument(
Expand Down
5 changes: 3 additions & 2 deletions snapcraft/services/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@

from craft_application import AppMetadata, PackageService
from craft_application.models import BuildInfo
from craft_application.util import strtobool
from overrides import override

from snapcraft import errors, linters, models, pack, utils
from snapcraft import errors, linters, models, pack
from snapcraft.linters import LinterStatus
from snapcraft.meta import component_yaml, snap_yaml
from snapcraft.parts import extract_metadata as extract
Expand Down Expand Up @@ -147,7 +148,7 @@ def write_metadata(self, path: pathlib.Path) -> None:
meta_dir.mkdir(parents=True, exist_ok=True)
self.metadata.to_yaml_file(meta_dir / "snap.yaml")

enable_manifest = utils.strtobool(os.getenv("SNAPCRAFT_BUILD_INFO", "n"))
enable_manifest = strtobool(os.getenv("SNAPCRAFT_BUILD_INFO", "n"))

# Snapcraft's Lifecycle implementation is what we need to refer to for typing
lifecycle_service = cast(Lifecycle, self._services.lifecycle)
Expand Down
18 changes: 1 addition & 17 deletions snapcraft/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from pathlib import Path
from typing import Iterable, List, Optional

from craft_application.util import strtobool
from craft_cli import emit
from craft_parts.sources.git_source import GitSource

Expand Down Expand Up @@ -161,23 +162,6 @@ def convert_architecture_deb_to_platform(architecture: str) -> str:
return platform_arch


def strtobool(value: str) -> bool:
"""Convert a string representation of truth to true (1) or false (0).
:param value: a True value of 'y', 'yes', 't', 'true', 'on', and '1'
or a False value of 'n', 'no', 'f', 'false', 'off', and '0'.
:raises ValueError: if `value` is not a valid boolean value.
"""
parsed_value = value.lower()

if parsed_value in ("y", "yes", "t", "true", "on", "1"):
return True
if parsed_value in ("n", "no", "f", "false", "off", "0"):
return False

raise ValueError(f"Invalid boolean value of {value!r}")


def is_managed_mode() -> bool:
"""Check if snapcraft is running in a managed environment."""
managed_flag = os.getenv("CRAFT_MANAGED_MODE", "n")
Expand Down
8 changes: 4 additions & 4 deletions snapcraft_legacy/cli/_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import distutils.util
import logging
import os
import shutil
Expand All @@ -23,6 +22,7 @@
from typing import Dict

import click
from craft_application.util import strtobool
import craft_store
from raven import Client as RavenClient
from raven.transport import RequestsHTTPTransport
Expand Down Expand Up @@ -74,7 +74,7 @@
def _is_connected_to_tty() -> bool:
# Used by inner instance, SNAPCRAFT_HAS_TTY is set by outer instance.
if os.getenv("SNAPCRAFT_BUILD_ENVIRONMENT") == "managed-host":
return distutils.util.strtobool(os.getenv("SNAPCRAFT_HAS_TTY", "n")) == 1
return strtobool(os.getenv("SNAPCRAFT_HAS_TTY", "n")) == 1

return sys.stdout.isatty()

Expand Down Expand Up @@ -284,13 +284,13 @@ def _print_trace_output(exc_info, file=sys.stdout) -> None:
def _is_send_to_sentry(exc_info) -> bool: # noqa: C901
# Check to see if error reporting has been disabled
if (
distutils.util.strtobool(os.getenv("SNAPCRAFT_ENABLE_ERROR_REPORTING", "y"))
strtobool(os.getenv("SNAPCRAFT_ENABLE_ERROR_REPORTING", "y"))
== 0
):
return False

# Check the environment to see if we should allow for silent reporting
if distutils.util.strtobool(os.getenv("SNAPCRAFT_ENABLE_SILENT_REPORT", "n")) == 1:
if strtobool(os.getenv("SNAPCRAFT_ENABLE_SILENT_REPORT", "n")) == 1:
click.echo(_MSG_SILENT_REPORT)
return True

Expand Down
8 changes: 4 additions & 4 deletions snapcraft_legacy/cli/_options.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright (C) 2016-2019 Canonical Ltd
# Copyright (C) 2016-2019,2024 Canonical Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
Expand All @@ -14,12 +14,12 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import distutils.util
import os
import sys
from typing import Any, Dict, List, Optional

import click
from craft_application.util import strtobool

from snapcraft_legacy.cli.echo import confirm, prompt, warning
from snapcraft_legacy.internal import common, errors
Expand Down Expand Up @@ -53,13 +53,13 @@ class BoolParamType(click.ParamType):
def convert(self, value, param, ctx):
"""Convert option string to value.
Unlike click's BoolParamType, use distutils.util.strtobool to
Unlike click's BoolParamType, use craft_application.util.strtobool to
convert values.
"""
if isinstance(value, bool):
return value
try:
return bool(distutils.util.strtobool(value))
return strtobool(value)
except ValueError:
self.fail("%r is not a valid boolean" % value, param, ctx)

Expand Down
4 changes: 2 additions & 2 deletions snapcraft_legacy/cli/echo.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@
These methods, which are named after common logging levels, wrap around
click.echo adding the corresponding color codes for each level.
"""
import distutils.util
import os
import shutil
import sys
from typing import Any, Optional

import click
from craft_application.util import strtobool

from snapcraft_legacy.internal import common


def is_tty_connected() -> bool:
"""Check to see if running under TTY."""
if distutils.util.strtobool(os.getenv("SNAPCRAFT_HAS_TTY", "n")) == 1:
if strtobool(os.getenv("SNAPCRAFT_HAS_TTY", "n")) == 1:
return True

return sys.stdin.isatty()
Expand Down
6 changes: 3 additions & 3 deletions snapcraft_legacy/internal/meta/_snap_packaging.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright (C) 2016-2020 Canonical Ltd
# Copyright (C) 2016-2020,2024 Canonical Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
Expand All @@ -16,7 +16,6 @@

import contextlib
import copy
import distutils.util
import itertools
import logging
import os
Expand All @@ -28,6 +27,7 @@
from typing import Any, Dict, Optional, Set

import requests
from craft_application.util import strtobool

from snapcraft_legacy import (
extractors,
Expand Down Expand Up @@ -631,7 +631,7 @@ def _record_manifest_and_source_snapcraft_yaml(self):
os.unlink(manifest_file_path)

# FIXME hide this functionality behind a feature flag for now
if distutils.util.strtobool(os.environ.get("SNAPCRAFT_BUILD_INFO", "n")):
if strtobool(os.environ.get("SNAPCRAFT_BUILD_INFO", "n")):
os.makedirs(prime_snap_dir, exist_ok=True)
shutil.copy2(self._snapcraft_yaml_path, recorded_snapcraft_yaml_path)
annotated_snapcraft = _manifest.annotate_snapcraft(
Expand Down
9 changes: 5 additions & 4 deletions snapcraft_legacy/internal/xattrs.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright (C) 2019 Canonical Ltd
# Copyright (C) 2019,2024 Canonical Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
Expand All @@ -14,11 +14,12 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import distutils.util
import os
import sys
from typing import Optional

from craft_application.util import strtobool

from snapcraft_legacy.internal.errors import XAttributeError, XAttributeTooLongError


Expand Down Expand Up @@ -77,7 +78,7 @@ def read_origin_stage_package(path: str) -> Optional[str]:
return _read_snapcraft_xattr(path, "origin_stage_package")
except XAttributeError:
# Ignore error if origin stage package not required.
if distutils.util.strtobool(os.environ.get("SNAPCRAFT_BUILD_INFO", "n")):
if strtobool(os.environ.get("SNAPCRAFT_BUILD_INFO", "n")):
raise
return None

Expand All @@ -88,5 +89,5 @@ def write_origin_stage_package(path: str, value: str) -> None:
_write_snapcraft_xattr(path, "origin_stage_package", value)
except XAttributeError:
# Ignore error if origin stage package not required.
if distutils.util.strtobool(os.environ.get("SNAPCRAFT_BUILD_INFO", "n")):
if strtobool(os.environ.get("SNAPCRAFT_BUILD_INFO", "n")):
raise
63 changes: 0 additions & 63 deletions tests/unit/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,69 +40,6 @@ def mock_is_managed_mode(mocker):
yield mocker.patch("snapcraft.utils.is_managed_mode", return_value=False)


@pytest.mark.parametrize(
"value",
[
"y",
"Y",
"yes",
"YES",
"Yes",
"t",
"T",
"true",
"TRUE",
"True",
"On",
"ON",
"oN",
"1",
],
)
def test_strtobool_true(value: str):
assert utils.strtobool(value) is True


@pytest.mark.parametrize(
"value",
[
"n",
"N",
"no",
"NO",
"No",
"f",
"F",
"false",
"FALSE",
"False",
"off",
"OFF",
"oFF",
"0",
],
)
def test_strtobool_false(value: str):
assert utils.strtobool(value) is False


@pytest.mark.parametrize(
"value",
[
"not",
"yup",
"negative",
"positive",
"whatever",
"2",
"3",
],
)
def test_strtobool_value_error(value: str):
with pytest.raises(ValueError):
utils.strtobool(value)


#####################
# Get Host Platform #
#####################
Expand Down

0 comments on commit 676e391

Please sign in to comment.