Skip to content

Commit

Permalink
Explicitely declare package-wide elements
Browse files Browse the repository at this point in the history
  • Loading branch information
kdeldycke committed Aug 20, 2024
1 parent a6ed9ff commit 2bdcede
Show file tree
Hide file tree
Showing 2 changed files with 275 additions and 3 deletions.
232 changes: 229 additions & 3 deletions extra_platforms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,115 @@ def cache(user_function):
# XXX Exposing everything at package level motivates platforms and groups to have a
# unique and unambiguous ID. This constraint is enforced at the data-level and checked
# in unittests.
from .detection import *
from .groups import *
from .platforms import *
from .detection import ( # noqa: E402
is_aix,
is_altlinux,
is_amzn,
is_android,
is_arch,
is_buildroot,
is_centos,
is_cloudlinux,
is_cygwin,
is_debian,
is_exherbo,
is_fedora,
is_freebsd,
is_gentoo,
is_guix,
is_hurd,
is_ibm_powerkvm,
is_kvmibm,
is_linuxmint,
is_macos,
is_mageia,
is_mandriva,
is_midnightbsd,
is_netbsd,
is_openbsd,
is_opensuse,
is_oracle,
is_parallels,
is_pidora,
is_raspbian,
is_rhel,
is_rocky,
is_scientific,
is_slackware,
is_sles,
is_solaris,
is_sunos,
is_ubuntu,
is_unknown_linux,
is_windows,
is_wsl1,
is_wsl2,
is_xenserver,
)
from .groups import ( # noqa: E402
ALL_GROUPS,
ALL_LINUX,
ALL_PLATFORMS,
ALL_WINDOWS,
BSD,
BSD_WITHOUT_MACOS,
EXTRA_GROUPS,
LINUX_LAYERS,
NON_OVERLAPPING_GROUPS,
OTHER_UNIX,
SYSTEM_V,
UNIX,
UNIX_LAYERS,
UNIX_WITHOUT_MACOS,
Group,
reduce,
)
from .platforms import ( # noqa: E402
AIX,
ALTLINUX,
AMZN,
ANDROID,
ARCH,
BUILDROOT,
CENTOS,
CLOUDLINUX,
CYGWIN,
DEBIAN,
EXHERBO,
FEDORA,
FREEBSD,
GENTOO,
GUIX,
HURD,
IBM_POWERKVM,
KVMIBM,
LINUXMINT,
MACOS,
MAGEIA,
MANDRIVA,
MIDNIGHTBSD,
NETBSD,
OPENBSD,
OPENSUSE,
ORACLE,
PARALLELS,
PIDORA,
RASPBIAN,
RHEL,
ROCKY,
SCIENTIFIC,
SLACKWARE,
SLES,
SOLARIS,
SUNOS,
UBUNTU,
UNKNOWN_LINUX,
WINDOWS,
WSL1,
WSL2,
XENSERVER,
Platform,
)

# XXX Not imported at package level so dependency on Pytest can stay optional.
# from .pytest import *
Expand Down Expand Up @@ -92,3 +198,123 @@ def current_os() -> Platform:
CURRENT_OS_ID: str = current_os().id
CURRENT_OS_LABEL: str = current_os().name
"""Constants about the current platform."""


__all__ = [
"AIX", # noqa: F405
"ALL_GROUPS", # noqa: F405
"ALL_LINUX", # noqa: F405
"ALL_OS_LABELS", # noqa: F405
"ALL_PLATFORMS", # noqa: F405
"ALL_WINDOWS", # noqa: F405
"ALTLINUX", # noqa: F405
"AMZN", # noqa: F405
"ANDROID", # noqa: F405
"ARCH", # noqa: F405
"BSD", # noqa: F405
"BSD_WITHOUT_MACOS", # noqa: F405
"BUILDROOT", # noqa: F405
"CENTOS", # noqa: F405
"CLOUDLINUX", # noqa: F405
"current_os", # noqa: F405
"CURRENT_OS_ID", # noqa: F405
"CURRENT_OS_LABEL", # noqa: F405
"CYGWIN", # noqa: F405
"DEBIAN", # noqa: F405
"EXHERBO", # noqa: F405
"EXTRA_GROUPS", # noqa: F405
"FEDORA", # noqa: F405
"FREEBSD", # noqa: F405
"GENTOO", # noqa: F405
"Group", # noqa: F405
"GUIX", # noqa: F405
"HURD", # noqa: F405
"IBM_POWERKVM", # noqa: F405
"is_aix", # noqa: F405
"is_altlinux", # noqa: F405
"is_amzn", # noqa: F405
"is_android", # noqa: F405
"is_arch", # noqa: F405
"is_buildroot", # noqa: F405
"is_centos", # noqa: F405
"is_cloudlinux", # noqa: F405
"is_cygwin", # noqa: F405
"is_debian", # noqa: F405
"is_exherbo", # noqa: F405
"is_fedora", # noqa: F405
"is_freebsd", # noqa: F405
"is_gentoo", # noqa: F405
"is_guix", # noqa: F405
"is_hurd", # noqa: F405
"is_ibm_powerkvm", # noqa: F405
"is_kvmibm", # noqa: F405
"is_linuxmint", # noqa: F405
"is_macos", # noqa: F405
"is_mageia", # noqa: F405
"is_mandriva", # noqa: F405
"is_midnightbsd", # noqa: F405
"is_netbsd", # noqa: F405
"is_openbsd", # noqa: F405
"is_opensuse", # noqa: F405
"is_oracle", # noqa: F405
"is_parallels", # noqa: F405
"is_pidora", # noqa: F405
"is_raspbian", # noqa: F405
"is_rhel", # noqa: F405
"is_rocky", # noqa: F405
"is_scientific", # noqa: F405
"is_slackware", # noqa: F405
"is_sles", # noqa: F405
"is_solaris", # noqa: F405
"is_sunos", # noqa: F405
"is_ubuntu", # noqa: F405
"is_unknown_linux", # noqa: F405
"is_windows", # noqa: F405
"is_wsl1", # noqa: F405
"is_wsl2", # noqa: F405
"is_xenserver", # noqa: F405
"KVMIBM", # noqa: F405
"LINUX_LAYERS", # noqa: F405
"LINUXMINT", # noqa: F405
"MACOS", # noqa: F405
"MAGEIA", # noqa: F405
"MANDRIVA", # noqa: F405
"MIDNIGHTBSD", # noqa: F405
"NETBSD", # noqa: F405
"NON_OVERLAPPING_GROUPS", # noqa: F405
"OPENBSD", # noqa: F405
"OPENSUSE", # noqa: F405
"ORACLE", # noqa: F405
"OTHER_UNIX", # noqa: F405
"PARALLELS", # noqa: F405
"PIDORA", # noqa: F405
"Platform", # noqa: F405
"RASPBIAN", # noqa: F405
"reduce", # noqa: F405
"RHEL", # noqa: F405
"ROCKY", # noqa: F405
"SCIENTIFIC", # noqa: F405
"SLACKWARE", # noqa: F405
"SLES", # noqa: F405
"SOLARIS", # noqa: F405
"SUNOS", # noqa: F405
"SYSTEM_V", # noqa: F405
"UBUNTU", # noqa: F405
"UNIX", # noqa: F405
"UNIX_LAYERS", # noqa: F405
"UNIX_WITHOUT_MACOS", # noqa: F405
"UNKNOWN_LINUX", # noqa: F405
"WINDOWS", # noqa: F405
"WSL1", # noqa: F405
"WSL2", # noqa: F405
"XENSERVER", # noqa: F405
]
"""Expose all package-wide elements.
.. note::
The content of ``__all__`` is checked and enforced in unittests.
.. todo::
Test ruff __all__ formatting capabilities. And if good enough, remove ``__all__``
checks in unittests.
"""
46 changes: 46 additions & 0 deletions tests/test_platforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import pytest

import extra_platforms
from extra_platforms import (
AIX,
ALL_GROUPS,
Expand Down Expand Up @@ -146,6 +147,51 @@
)


def test_module_root_declarations():
def fetch_module_implements(module) -> set[str]:
"""Fetch all methods, classes and constants implemented locally in a module's file."""
members = set()
tree = ast.parse(Path(inspect.getfile(module)).read_bytes())
for node in tree.body:
if isinstance(node, ast.Assign):
for target in node.targets:
members.add(target.id)
elif isinstance(node, ast.AnnAssign):
members.add(node.target.id)
elif isinstance(node, ast.FunctionDef):
members.add(node.name)
elif isinstance(node, ast.ClassDef):
members.add(node.name)
return {m for m in members if not m.startswith("_")}

detection_members = fetch_module_implements(detection_module)
groups_members = fetch_module_implements(groups_module)
platforms_members = fetch_module_implements(platforms_module)
root_members = fetch_module_implements(extra_platforms)

# Check all members are exposed at the module root.
tree = ast.parse(Path(inspect.getfile(extra_platforms)).read_bytes())
extra_platforms_members = []
for node in tree.body:
if isinstance(node, ast.Assign):
for target in node.targets:
if target.id == "__all__":
for element in node.value.elts:
extra_platforms_members.append(element.s)

assert detection_members <= set(extra_platforms_members)
assert groups_members <= set(extra_platforms_members)
assert platforms_members <= set(extra_platforms_members)

expected_members = sorted(
detection_members.union(groups_members)
.union(platforms_members)
.union(root_members),
key=lambda m: (m.lower(), m),
)
assert expected_members == extra_platforms_members


def test_mutual_exclusion():
"""Only directly tests OSes on which the test suite is running via GitHub
actions."""
Expand Down

0 comments on commit 2bdcede

Please sign in to comment.