tests packageΒΆ
SubmodulesΒΆ
tests.test_agent_data moduleΒΆ
Test all agent definitions, detection and agent-specific groups.
- tests.test_agent_data.test_agent_presence_var_escalates_unrecognized(env_var, monkeypatch, caplog)[source]ΒΆ
Each generic presence variable raises an unrecognized agent to a warning.
Covers every member of
_AGENT_PRESENCE_ENV_VARS, so a variable added there without being read by the gate fails here.
tests.test_architecture_data moduleΒΆ
Test all architecture definitions, detection and architecture-specific groups.
- tests.test_architecture_data.test_architecture_logical_grouping()[source]ΒΆ
Check partitions specific to architectures.
Family partitions and canonical flags are enforced generically in
test_trait_data.pyandtest_group_data.py. Bitness and endianness are non-canonical groups, so their partition of all architectures is only checked here.
tests.test_ci_data moduleΒΆ
Test all CI definitions, detection and CI-specific groups.
- tests.test_ci_data.test_github_runner_detection()[source]ΒΆ
Test GitHub runner OS.
List of available GitHub runner images: https://github.com/actions/runner-images#available-images
tests.test_detection moduleΒΆ
- tests.test_detection.test_detection_trait_functions(obj)[source]ΒΆ
Every trait and group has a cached detection function in the module.
A trait heuristic is written by hand, a group one is generated, and both are registered and exported at the package root.
- tests.test_detection.test_group_detection_reads_its_members_alone(fresh_caches, monkeypatch)[source]ΒΆ
A group detection function runs the heuristics of its own members only.
Checking a platform group never runs a shell heuristic, whose fallback walks the parent process tree through a
pssubprocess on macOS.
- tests.test_detection.DETECTION_SECTIONS = ('Architecture detection heuristics', 'Platform detection heuristics', 'Shell detection heuristics', 'Terminal detection heuristics', 'CI/CD detection heuristics', 'Agent detection heuristics')ΒΆ
Comment headers splitting
detection.py, in trait category order.
- tests.test_detection.test_detection_heuristics_sorting()[source]ΒΆ
Each section sorts its heuristics by ID, then closes on its generic one.
- tests.test_detection.test_is_arm_depends_on_arm_variants(monkeypatch, fresh_caches)[source]ΒΆ
Test that is_arm() is a fallback excluded by specific ARM variants.
- tests.test_detection.test_opensuse_channel_folding(monkeypatch, distro_id, fresh_caches)[source]ΒΆ
Any openSUSE release channel is detected as the OPENSUSE platform.
- tests.test_detection.test_oracle_raw_id_detection(monkeypatch, fresh_caches)[source]ΒΆ
Oracle Linux is detected from its raw
olos-release ID.
- tests.test_detection.test_x86_64_machine_aliases(monkeypatch, machine, fresh_caches)[source]ΒΆ
Every string reported for 64-bit x86 resolves to X86_64.
Solaris and illumos answer
i86pc, which names the machine family and not the ISA, mirroring thesun4uandsun4valiasesis_sparc64()already accepts. Captured on OpenIndiana Hipster 2026.04.
- tests.test_detection.PLATFORM_HOST_SIGNALS = frozenset({'Path', 'environ', 'os_release_id', 'platform.platform', 'platform.release', 'platform.uname', 'sys.platform'})ΒΆ
Every host signal the platform detection heuristics read.
mock_platform_host()controls exactly these, andtest_platform_signals_are_all_mocked()keeps the two in step.
- tests.test_detection.test_platform_signals_are_all_mocked()[source]ΒΆ
Every signal a platform heuristic reads is one the host mock pins.
current_platform()evaluates all platform heuristics and raises as soon as two match. A signal left reading the real host therefore makes the result depend on where the suite runs. A heuristic added with a new signal fails here untilmock_platform_host()controls that signal too.
- tests.test_detection.mock_platform_host(monkeypatch, *, sys_platform, os_release='', platform_string='', release='', uname=None)[source]ΒΆ
Make every
PLATFORM_HOST_SIGNALSentry answer for one host.A test asserting on
current_platform()must set every signal, not only the ones its own heuristic reads: the resolver runs all of them, and a second match raises. Leavingos_release_id()on the real host is what madetest_illumos_excludes_solarismatch UBUNTU next to ILLUMOS on the Linux runners, while it passed on the macOS and Windows ones, which carry no os-release file.Each default is the value an absent signal produces, so a caller states only what its simulated host reports.
- Parameters:
monkeypatch β Fixture undoing every patch at the end of the test.
sys_platform (
str) β Value ofsys.platform.os_release (
str) β Distribution ID fromos_release_id(), empty on a host with no os-release file.platform_string (
str) β Return value ofplatform.platform().release (
str) β Return value ofplatform.release().uname (
SimpleNamespace|None) β Return value ofplatform.uname(), defaulting to a record whose every field is empty.
- Return type:
- tests.test_detection.test_illumos_excludes_solaris(monkeypatch, fresh_caches)[source]ΒΆ
An illumos distribution matches ILLUMOS alone, never SOLARIS as well.
illumos inherits the SunOS 5.11 release string from OpenSolaris, so
platform.platform()answersSolaris-2.11there. Both heuristics used to match at once, which madecurrent_platform()raise on every illumos host. Values captured on OpenIndiana Hipster 2026.04.
- tests.test_detection.test_detection_functions_cached(fresh_caches)[source]ΒΆ
Test that detection functions are cached with @cache decorator.
- tests.test_detection.test_environment_variable_ci_detection(monkeypatch, fresh_caches)[source]ΒΆ
Test CI detection based on environment variables.
- tests.test_detection.test_detection_no_circular_dependencies(fresh_caches)[source]ΒΆ
Every detection function runs without a circular dependency.
- tests.test_detection.unset_shell_startup_vars(monkeypatch)[source]ΒΆ
Unset the variables shells set at startup,
PSModulePathincluded.SHELLand the parent process tree are then the only shell signals, so the shell running the suite cannot leak into the test.- Parameters:
monkeypatch β Fixture undoing every patch at the end of the test.
- Return type:
- tests.test_detection.test_shell_detected_by_every_executable_name(monkeypatch, shell, executable, source, fresh_caches)[source]ΒΆ
Each file name a shellβs binary goes by detects it, as its ID does.
- tests.test_detection.test_current_shell_prefers_a_running_pwsh_over_configured_shell(monkeypatch, fresh_caches)[source]ΒΆ
A
pwshparent process names PowerShell, whose ID is not its binary name.
- tests.test_detection.test_shell_from_path(path, expected_id)[source]ΒΆ
A shell path resolves to its catalog entry by name, or to the unknown shell.
- tests.test_detection.test_shell_from_path_resolves_symlinks(tmp_path)[source]ΒΆ
shlinking tobashnames bash: the implementation, not the interface.
- tests.test_detection.test_shell_from_path_resolves_multicall_binary(tmp_path, target, link, expected_id)[source]ΒΆ
A link to a multi-call binary names the program the link name picks.
- tests.test_detection.test_current_shell_path(monkeypatch, fresh_caches)[source]ΒΆ
current_shell_path() prefers the running binary, then falls back to SHELL.
- tests.test_detection.test_shell_info_path_ignores_another_login_shell(monkeypatch, fresh_caches)[source]ΒΆ
Shell.info()reports no path rather than the path of another shell.
- tests.test_detection.test_current_shell_prefers_running_shell_over_configured_shell(monkeypatch, fresh_caches)[source]ΒΆ
A running shell (process tree) wins over a different configured
SHELL.Regression guard for the macOS Terminal.app case where the app launches a login fish (
-fish) while$SHELLis still zsh (nochsh): the running shell (fish) must win, not the configured login shell (zsh).
- tests.test_detection.test_nested_ancestor_shells_all_detected(monkeypatch, fresh_caches)[source]ΒΆ
A session shell above the running shell chain is detected in parallel.
Regression guard for openSUSE OBS chroot builds run from a fish terminal: the
/procwalk escapes the build root into the packagerβs desktop session, so fish sits in the ancestor tree above the bash chain running the build. Both shells are detected, and the primary shell stays the nearest running one.
tests.test_group moduleΒΆ
- tests.test_group.test_set_operation(method, first, others, expected)[source]ΒΆ
A set operation acts on the members, keeping the first groupβs metadata.
- tests.test_group.test_remove()[source]ΒΆ
Test remove() method for removing a trait with error checking.
- tests.test_group.test_in_place_operators()[source]ΒΆ
Test in-place operators that return new instances.
- tests.test_group.test_set_operations_with_new_methods()[source]ΒΆ
Test combining new methods with existing set operations.
- tests.test_group.test_group_operations_with_empty_groups()[source]ΒΆ
Test group operations with empty groups.
- tests.test_group.test_group_contains_with_wrong_trait_object()[source]ΒΆ
Test that Group.__contains__ checks object identity, not just ID.
- tests.test_group.test_unique_ids()[source]ΒΆ
Group IDs are unique, and no trait shares one.
No check of the trait IDs belongs here: a group keys its members by ID, so
ALL_TRAITShides a duplicate.test_trait_data.pychecks them instead.
- tests.test_group.randomize_case(strings)[source]ΒΆ
Generate variations of strings with different case.
Sorted, so every xdist worker collects the same parameters in the same order.
- tests.test_group.test_traits_from_ids(trait_id)[source]ΒΆ
Test traits_from_ids with various case variations.
- tests.test_group.test_alias_resolves_with_warning(resolve, alias, trait)[source]ΒΆ
An alias resolves to its trait, with a warning naming the canonical ID.
The warning points at the caller, whatever call chain inside the package reached the resolution.
- tests.test_group.test_traits_from_ids_group_resolve(group_id)[source]ΒΆ
traits_from_ids() can also resolve group IDs.
- tests.test_group.test_groups_from_ids(group_id)[source]ΒΆ
Test groups_from_ids with various case variations.
- tests.test_group.test_reduction(items, expected)[source]ΒΆ
Test reduce function with various inputs.
- tests.test_group.test_reduce_custom_targets(items, expected)[source]ΒΆ
Test reduce with custom target pool.
- tests.test_group.test_reduce_skips_empty_groups()[source]ΒΆ
An empty group covers nothing, so the reduction never picks it.
- tests.test_group.test_from_ids_edge_cases(from_ids, message)[source]ΒΆ
No ID resolves to nothing, and an unknown ID raises.
- tests.test_group.test_traits_from_ids_with_multiple_valid_ids()[source]ΒΆ
Test that traits_from_ids works with multiple valid IDs.
- tests.test_group.test_groups_from_ids_with_multiple_valid_ids()[source]ΒΆ
Test that groups_from_ids works with multiple valid IDs.
- tests.test_group.test_all_ids_constant()[source]ΒΆ
Test that ALL_IDS constant contains all trait and group IDs.
tests.test_group_data moduleΒΆ
- tests.test_group_data.test_group_data_ordering()[source]ΒΆ
Group instances follow logical order, not alphabetical.
- tests.test_group_data.test_unknown_group()[source]ΒΆ
All members of the UNKNOWN group are unknown traits.
- tests.test_group_data.test_sets_of_groups()[source]ΒΆ
Test properties of sets of groups, as well as individual groups.
- tests.test_group_data.test_each_trait_in_exactly_one_canonical_group()[source]ΒΆ
Check each trait belongs to exactly one canonical group.
With the per-group checks of
test_group_definitions(no empty group, andcanonicalset exactly on the members ofCANONICAL_GROUPS), this also proves the canonical groups are disjoint, cover every trait, and that each non-canonical group overlaps one of them.
tests.test_main moduleΒΆ
Test the command-line interface and its rendering helpers.
- tests.test_main.CURRENT_FUNCS = {'agent': <functools._lru_cache_wrapper object>, 'architecture': <functools._lru_cache_wrapper object>, 'ci': <functools._lru_cache_wrapper object>, 'platform': <functools._lru_cache_wrapper object>, 'shell': <functools._lru_cache_wrapper object>, 'terminal': <functools._lru_cache_wrapper object>}ΒΆ
The trait each section of the report covers, in report order.
- tests.test_main.test_trait_header_spans_separator_width(trait, capsys)[source]ΒΆ
Each trait header rules out to the separator width, whatever its icon width.
tests.test_platform_data moduleΒΆ
Test all platform definitions and platform-specific groups.
- tests.test_platform_data.test_platform_mutual_exclusion()[source]ΒΆ
A single platform matches, apart from documented compatibility layers.
WSL and ChromeOS legitimately match alongside the Linux distribution they host, as documented in
current_platform().
- tests.test_platform_data.test_generic_linux_fallback(monkeypatch, marker, os_release, generic, fresh_caches)[source]ΒΆ
A Linux kernel is generic until a platform identifies its distribution.
- tests.test_platform_data.test_unrecognized_linux_distribution(monkeypatch, caplog, os_release, strict_raises, fresh_caches)[source]ΒΆ
An unrecognized distribution is generic Linux, so it stays in
LINUX.
- tests.test_platform_data.test_platform_logical_grouping()[source]ΒΆ
Check set relationships specific to platform groups.
Family partitions and canonical flags are enforced generically in
test_trait_data.pyandtest_group_data.py. The relationships below involve the non-canonicalUNIX,LINUX_LIKEand*_WITHOUT_MACOSgroups, so they are only checked here.
- tests.test_platform_data.test_nerdfont_icons_documented_in_source()[source]ΒΆ
Every platform with a NerdFont icon embeds that glyph in its docstring.
NerdFont glyphs live in the Unicode Private Use Area and render as an invisible or placeholder character without a patched font, so each such platform carries an attribute docstring warning about the font requirement, whose icon link repeats the glyph. Because the glyph is invisible in an editor, it is easy to drop from that link by accident, which then renders as broken plaintext instead of a hyperlink. Lock the invariant by parsing the source: every NerdFont-icon platform must have an attribute docstring, and that docstring must contain the glyph itself.
tests.test_platform_info moduleΒΆ
Test os-release parsing and platform information gathering.
- tests.test_platform_info.HOSTNAMECTL_CLOUDLINUX = ' Static hostname: web.illinois.edu\n Icon name: computer-vm\n Chassis: vm\n Boot ID: 5b5b8c522ccd4974808f192aea001491\n Virtualization: kvm\n Operating System: CloudLinux 7.6 (Vladimir Lyakhov)\n CPE OS Name: cpe:/o:cloudlinux:cloudlinux:7.6:GA:server\n Kernel: Linux 3.10.0-962.3.2.lve1.5.24.9.el7.x86_64\n Architecture: x86-64\n'ΒΆ
Status output of the CloudLinux VM reported in python-distro/distro#240, where no os-release file is readable.
- tests.test_platform_info.CLOUDLINUX_OS_RELEASE = {'cpe_name': 'cpe:/o:cloudlinux:cloudlinux:7.6:GA:server', 'id': 'cloudlinux', 'pretty_name': 'CloudLinux 7.6 (Vladimir Lyakhov)', 'version_codename': 'Vladimir Lyakhov', 'version_id': '7.6'}ΒΆ
The os-release fields rebuilt from
HOSTNAMECTL_CLOUDLINUX.
- tests.test_platform_info.fresh_os_release_caches()[source]ΒΆ
Clear derived os-release caches around a test.
The test patches
_parse_os_release.Only the caches of
os_release_id()andlinux_info()are cleared:_parse_os_release()itself is replaced bymonkeypatch, whose teardown runs after this fixtureβs, so the patched stand-in (a plain lambda) has no cache to clear.
- tests.test_platform_info.fresh_hostnamectl_caches()[source]ΒΆ
Clear the caches a
hostnamectl-driving test fills._parse_os_release()memoizes whatever the fallback answered, so it is cleared next to_hostnamectl_os_release(). Both are cleared on entry and exit, whichfresh_os_release_cachescannot do for_parse_os_release(): no test using this fixture replaces either function, so the realcache_clear()stays reachable on both sides.
- tests.test_platform_info.test_parse_os_release_content(content, expected)[source]ΒΆ
Parsing os-release content produces the exact expected mapping.
- tests.test_platform_info.test_os_release_id_sanitization(raw_id, expected, monkeypatch, fresh_os_release_caches)[source]ΒΆ
IDs are lowercased but otherwise preserved, sub-variants included.
- tests.test_platform_info.test_os_release_id_empty(monkeypatch, fresh_os_release_caches)[source]ΒΆ
Return empty string when no ID field is present.
- tests.test_platform_info.test_linux_info_structure(monkeypatch, fresh_os_release_caches)[source]ΒΆ
Return dict has expected keys and version_parts structure.
- tests.test_platform_info.test_linux_info_empty_version(monkeypatch, fresh_os_release_caches)[source]ΒΆ
Version parts are None when version_id is absent.
- tests.test_platform_info.test_parse_cpe_name_matches_os_release_id(cpe_name, distro_id)[source]ΒΆ
A CPE name derives the
IDthe same system declares in its os-release.Both fields of each case are read from one real os-release file, as collected in python-distroβs test resources. That covers every
vendor:productpair those fixtures carry, so a new entry inCPE_ID_OVERRIDESthat contradicts a released distribution fails here.
- tests.test_platform_info.test_parse_cpe_name(cpe_name, expected)[source]ΒΆ
Parsing a CPE name produces the exact expected mapping.
- tests.test_platform_info.test_parse_hostnamectl_content(content, expected)[source]ΒΆ
Parsing hostnamectl output produces the exact expected mapping.
- tests.test_platform_info.test_hostnamectl_os_release_skips_missing_binary(monkeypatch, fresh_hostnamectl_caches)[source]ΒΆ
No subprocess is spawned on a system shipping no
hostnamectl.
- tests.test_platform_info.test_hostnamectl_os_release_degrades(error, monkeypatch, fresh_hostnamectl_caches)[source]ΒΆ
Every failure to reach the bus degrades to an empty result.
- tests.test_platform_info.test_parse_os_release_falls_back_to_hostnamectl(monkeypatch, fresh_hostnamectl_caches, fresh_os_release_caches)[source]ΒΆ
A system hiding both os-release files is identified through the bus.
- tests.test_platform_info.test_parse_os_release_prefers_files_over_hostnamectl(monkeypatch, fresh_hostnamectl_caches, fresh_os_release_caches)[source]ΒΆ
A readable os-release file is never second-guessed through the bus.
- tests.test_platform_info.test_parse_os_release_skips_unreadable_file(unreadable, expected, monkeypatch, fresh_hostnamectl_caches)[source]ΒΆ
An os-release file that exists but cannot be read is skipped, not raised.
- tests.test_platform_info.test_parse_os_release_replaces_invalid_bytes(monkeypatch, fresh_hostnamectl_caches)[source]ΒΆ
A byte that is not UTF-8 spoils its own value, not the whole file.
- tests.test_platform_info.test_invalidate_os_release_cache_clears_hostnamectl(monkeypatch, fresh_hostnamectl_caches)[source]ΒΆ
The hostnamectl result is re-read after a cache invalidation.
- tests.test_platform_info.macos_sonoma(monkeypatch)[source]ΒΆ
Report the macOS version the way a macOS 14.2.1 host does.
- tests.test_platform_info.test_macos_info(macos_sonoma)[source]ΒΆ
The version splits into its parts, and its major part names the release.
- tests.test_platform_info.test_get_macos_codename(major, minor, codename)[source]ΒΆ
Every version the table lists resolves to its own codename.
- tests.test_platform_info.test_get_macos_codename_unknown_version()[source]ΒΆ
A version no codename covers raises, like the
16of some Tahoe betas.
- tests.test_platform_info.test_macos_codenames_key_each_major_one_way()[source]ΒΆ
A major version keys its codenames either alone or with its minor versions.
Both ways at once would make a version match two codenames.
- tests.test_platform_info.windows_11(monkeypatch)[source]ΒΆ
Report the Windows version the way a Windows 11 24H2 guest does.
- tests.test_platform_info.test_windows_info(windows_11)[source]ΒΆ
The version is the NT one, build number included; the release names it.
- tests.test_platform_info.test_windows_platform_info_release(monkeypatch, windows_11, fresh_caches)[source]ΒΆ
Platform.info()carries the Windows release beside the NT version.
- tests.test_platform_info.test_release_is_windows_only(plat, version, monkeypatch, macos_sonoma, fresh_caches)[source]ΒΆ
No other platform fills
release.On macOS, CPythonβs own
platform.release()names the Darwin kernel, another meaning.Each platform is forced current, since
info()fills nothing for a platform that is not.
tests.test_process_tree moduleΒΆ
Test the walk of the parent process tree.
- tests.test_process_tree.test_tree_from_ps(table, links, expected, monkeypatch)[source]ΒΆ
The ps-based walk (macOS/BSD) climbs from the current process to root.
The pairs come nearest-first.
- tests.test_process_tree.test_tree_from_ps_tolerates_mocked_run(monkeypatch)[source]ΒΆ
A globally mocked subprocess.run must not break the walk.
- tests.test_process_tree.test_interpreter_shell_specs_includes_xonsh()[source]ΒΆ
Xonsh declares python as its interpreter, so it appears in the specs.
- tests.test_process_tree.test_interpreter_shell(tmp_path)[source]ΒΆ
An interpreter running a launcher file named after a shell is detected.
- tests.test_process_tree.test_tree_from_ps_detects_interpreter_shell(tmp_path, monkeypatch)[source]ΒΆ
The ps walk surfaces xonsh when python runs its launcher script.
- tests.test_process_tree.test_tree_from_ps_uses_portable_flags(monkeypatch)[source]ΒΆ
The ps invocation avoids BSD-only flags so System V ps (Solaris) works.
- tests.test_process_tree.test_tree_from_ps_replaces_undecodable_bytes(tmp_path, monkeypatch)[source]ΒΆ
A byte that is no UTF-8, in the arguments of another process, is replaced.
The fake
pslists the current process, and a second one whose argument is a Latin-1piΓ±a.
- tests.test_process_tree.test_pairs_from_process_busybox(executable, argv, expected)[source]ΒΆ
BusyBoxβs sh and ash applets both run its Almquist shell.
- tests.test_process_tree.test_ppid_from_proc_tolerates_binary_status(monkeypatch)[source]ΒΆ
System V /proc/<pid>/status is a binary pstatus_t; reading must not raise.
- tests.test_process_tree.test_ppid_from_proc_netbsd_stat(monkeypatch)[source]ΒΆ
NetBSD /proc/<pid>/stat is Linux-compatible: ksh detected as parent.
Regression test for the scenario in https://github.com/sarugaku/shellingham/issues/99 where shellingham fails on NetBSDβs procfs but extra-platforms walks it correctly.
- tests.test_process_tree.test_ppid_from_proc_netbsd_status_fallback(monkeypatch)[source]ΒΆ
When NetBSDβs stat is unreadable, the BSD-style status fallback parses.
- tests.test_process_tree.test_parent_process_tree_falls_back_to_ps_when_proc_empty(monkeypatch, fresh_caches)[source]ΒΆ
System V /proc (illumos, Solaris) yields nothing, so fall back to ps.
- tests.test_process_tree.test_parent_process_names(fresh_caches)[source]ΒΆ
The dispatcher returns a clean frozenset on every platform.
- tests.test_process_tree.test_walk_process_map()[source]ΒΆ
The Windows-style map walk climbs nearest-first and resolves paths.
- tests.test_process_tree.test_windows_helpers_noop_off_windows()[source]ΒΆ
The _windows module imports cleanly and no-ops on non-Windows platforms.
- tests.test_process_tree.test_tree_from_windows_smoke()[source]ΒΆ
On Windows the tree is populated and includes the python interpreter.
tests.test_pytest moduleΒΆ
- tests.test_pytest.test_type_annotations()[source]ΒΆ
Check all @skip_*/@unless_* annotations are defined and sorted.
- tests.test_pytest.test_generated_decorators(obj)[source]ΒΆ
Each trait and group gets a skip and an unless decorator.
Both read the detection function of their object, with opposite outcomes.
- tests.test_pytest.test_skip_all_architectures()[source]ΒΆ
A skip decorator keeps the test from running at all.
tests.test_root moduleΒΆ
- tests.test_root.PROJECT_ROOT = PosixPath('/home/runner/work/extra-platforms/extra-platforms')ΒΆ
The root path of the project.
- tests.test_root.PYPROJECT_PATH = PosixPath('/home/runner/work/extra-platforms/extra-platforms/pyproject.toml')ΒΆ
The path to the
pyproject.tomlfile.
- tests.test_root.PYPROJECT = {'build-system': {'build-backend': 'uv_build', 'requires': ['uv-build>=0.8']}, 'dependency-groups': {'docs': ['click-extra[sphinx]>=9.4', 'furo>=2025.12.19', 'myst-parser>=5.1', 'pytest>=8.4', 'sphinx>=9.1', 'sphinx-autodoc-typehints>=2', 'sphinx-copybutton>=0.5', 'sphinx-design>=0.7', 'sphinxcontrib-mermaid>=1.2.3', 'sphinxext-opengraph>=0.11'], 'test': ['coverage[toml]>=7.13', 'pytest>=9', 'pytest-github-actions-annotate-failures>=0.3', 'pytest-randomly>=4', 'pytest-xdist[psutil]>=3.7', 'requests>=2.34']}, 'project': {'authors': [{'email': 'kevin@deldycke.com', 'name': 'Kevin Deldycke'}], 'classifiers': ['Development Status :: 5 - Production/Stable', 'Environment :: Console', 'Environment :: MacOS X', 'Environment :: WebAssembly', 'Environment :: WebAssembly :: Emscripten', 'Environment :: WebAssembly :: WASI', 'Environment :: Win32 (MS Windows)', 'Framework :: Pytest', 'Intended Audience :: Developers', 'Operating System :: Android', 'Operating System :: BeOS', 'Operating System :: iOS', 'Operating System :: MacOS', 'Operating System :: MacOS :: MacOS 9', 'Operating System :: MacOS :: MacOS X', 'Operating System :: Microsoft', 'Operating System :: Microsoft :: MS-DOS', 'Operating System :: Microsoft :: Windows', 'Operating System :: Microsoft :: Windows :: Windows 3.1 or Earlier', 'Operating System :: Microsoft :: Windows :: Windows 7', 'Operating System :: Microsoft :: Windows :: Windows 8', 'Operating System :: Microsoft :: Windows :: Windows 8.1', 'Operating System :: Microsoft :: Windows :: Windows 10', 'Operating System :: Microsoft :: Windows :: Windows 11', 'Operating System :: Microsoft :: Windows :: Windows 95/98/2000', 'Operating System :: Microsoft :: Windows :: Windows CE', 'Operating System :: Microsoft :: Windows :: Windows NT/2000', 'Operating System :: Microsoft :: Windows :: Windows Server 2003', 'Operating System :: Microsoft :: Windows :: Windows Server 2008', 'Operating System :: Microsoft :: Windows :: Windows Vista', 'Operating System :: Microsoft :: Windows :: Windows XP', 'Operating System :: OS Independent', 'Operating System :: OS/2', 'Operating System :: Other OS', 'Operating System :: PalmOS', 'Operating System :: PDA Systems', 'Operating System :: POSIX', 'Operating System :: POSIX :: AIX', 'Operating System :: POSIX :: BSD', 'Operating System :: POSIX :: BSD :: BSD/OS', 'Operating System :: POSIX :: BSD :: FreeBSD', 'Operating System :: POSIX :: BSD :: NetBSD', 'Operating System :: POSIX :: BSD :: OpenBSD', 'Operating System :: POSIX :: GNU Hurd', 'Operating System :: POSIX :: HP-UX', 'Operating System :: POSIX :: IRIX', 'Operating System :: POSIX :: Linux', 'Operating System :: POSIX :: Other', 'Operating System :: POSIX :: SCO', 'Operating System :: POSIX :: SunOS/Solaris', 'Operating System :: RISC OS', 'Operating System :: Unix', 'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', 'Programming Language :: Python :: 3.13', 'Programming Language :: Python :: 3.14', 'Programming Language :: Python :: 3.15', 'Programming Language :: Python :: Implementation :: CPython', 'Topic :: Software Development :: Libraries :: Python Modules', 'Topic :: System :: Hardware', 'Topic :: System :: Operating System', 'Topic :: System :: Operating System Kernels', 'Topic :: System :: Operating System Kernels :: BSD', 'Topic :: System :: Operating System Kernels :: GNU Hurd', 'Topic :: System :: Operating System Kernels :: Linux', 'Topic :: Utilities', 'Typing :: Typed'], 'description': 'π Detect architectures, platforms, shells, terminals, CI systems and agents, grouped by family', 'entry-points': {'pytest11': {'extra-platforms': 'extra_platforms.pytest'}}, 'keywords': ['Agent detection', 'AIX', 'Alacritty', 'AlmaLinux', 'Almquist Shell', 'Alpine Linux', 'ALT Linux', 'Amazon Linux', 'Android', 'Apple Terminal', 'Arch Linux', 'Architecture detection', 'ARM (32-bit)', 'ARM64 (AArch64)', 'ARMv5TE (little-endian)', 'ARMv6 (little-endian)', 'ARMv7 (little-endian)', 'ARMv8 (32-bit, little-endian)', 'Artix Linux', 'AT&T System Five', 'Azure Pipelines', 'Bamboo', 'Bash', 'Bourne Shell', 'Buildkite', 'Buildroot', 'C shell', 'CachyOS', 'CentOS', 'ChromeOS', 'CI detection', 'Circle CI', 'Cirrus CI', 'Claude Code', 'Clear Linux OS', 'Cline', 'CloudLinux OS', 'CodeBuild', 'Command Prompt', 'Contour', 'CPU architecture', 'Crush', 'CRUX', 'Cursor', 'Cygwin', 'Dash', 'Debian', 'Distro detection', 'DragonFly BSD', 'EndeavourOS', 'Exherbo Linux', 'Fedora', 'Fish', 'foot', 'FreeBSD', 'Gemini CLI', 'Generic Linux', 'Gentoo Linux', 'Ghostty', 'GitHub Actions runner', 'GitHub Copilot CLI', 'GitLab CI', 'GNOME Terminal', 'GNU Screen', 'GNU/Hurd', 'Guix System', 'Haiku', 'Hardware detection', 'Hermetic Build', 'Heroku CI', 'Hurd', 'Hyper', 'IBM AIX', 'IBM i', 'IBM PowerKVM', 'IBM z/Architecture (s390x)', 'illumos', 'Intel 80386 (i386)', 'Intel Pentium (i586)', 'Intel Pentium Pro (i686)', 'iTerm2', 'Kali Linux', 'Kitty', 'Konsole', 'Korn shell', 'KVM for IBM z Systems', 'Linux distribution', 'Linux Mint', 'LoongArch (64-bit)', 'macOS', 'Mageia', 'Mandriva Linux', 'Manjaro Linux', 'MidnightBSD', 'MIPS (32-bit, big-endian)', 'MIPS (32-bit, little-endian)', 'MIPS64 (big-endian)', 'MIPS64 (little-endian)', 'multiplatform', 'NetBSD', 'NixOS', 'Nobara', 'Nushell', 'NuTyX', 'OpenAI Codex', 'OpenBSD', 'openSUSE', 'OpenWrt', 'Oracle Linux', 'OS detection', 'OS info', 'Parallels', 'Pi', 'Pidora', 'PikaOS', 'Platform', 'Platform detection', 'PowerPC (32-bit)', 'PowerPC 64-bit (big-endian)', 'PowerPC 64-bit (little-endian)', 'PowerShell', 'Pytest', 'Pytest fixtures', 'Pytest plugin', 'Raspbian', 'RedHat Enterprise Linux', 'Rio', 'RISC-V (32-bit)', 'RISC-V (64-bit)', 'Rocky Linux', 'Scientific Linux', 'Shell detection', 'Slackware', 'SliTaz GNU/Linux', 'Solaris', 'Solus', 'Source Mage GNU/Linux', 'SPARC (32-bit)', 'SPARC (64-bit)', 'SunOS', 'SUSE Linux Enterprise Server', 'sysinfo', 'System information', 'Tabby', 'tcsh', 'TeamCity', 'Terminal detection', 'Tilix', 'tmux', 'Travis CI', 'Tuxedo OS', 'Ubuntu', 'Ultramarine', 'Unix', 'Void Linux', 'VS Code Terminal', 'WebAssembly (32-bit)', 'WebAssembly (64-bit)', 'WezTerm', 'Windows', 'Windows Subsystem for Linux', 'Windows Terminal', 'x86-64 (AMD64)', 'XenServer', 'Xonsh', 'xterm', 'Zellij', 'Zsh'], 'license': 'Apache-2.0', 'license-files': ['license'], 'name': 'extra-platforms', 'optional-dependencies': {'pytest': ['pytest>=8.4']}, 'readme': 'readme.md', 'requires-python': '>=3.11', 'scripts': {'extra-platforms': 'extra_platforms.__main__:main'}, 'urls': {'Changelog': 'https://github.com/kdeldycke/extra-platforms/blob/main/changelog.md', 'Documentation': 'https://kdeldycke.github.io/extra-platforms', 'Download': 'https://github.com/kdeldycke/extra-platforms/releases/tag/v14.0.2.dev0', 'Funding': 'https://github.com/sponsors/kdeldycke', 'Homepage': 'https://github.com/kdeldycke/extra-platforms', 'Issues': 'https://github.com/kdeldycke/extra-platforms/issues', 'Repository': 'https://github.com/kdeldycke/extra-platforms'}, 'version': '14.0.2.dev0'}, 'tool': {'bumpversion': {'allow_dirty': True, 'current_version': '14.0.2.dev0', 'files': [{'glob': './**/__init__.py', 'ignore_missing_version': True}, {'filename': './pyproject.toml', 'regex': True, 'replace': 'version = "{new_version}"', 'search': '(?m)^version = "{current_version}"'}, {'filename': './pyproject.toml', 'replace': 'releases/tag/v{new_version}', 'search': 'releases/tag/v{current_version}'}, {'filename': './pyproject.toml', 'ignore_missing_version': True, 'replace': '-version = "{new_version}"', 'search': '-version = "{current_version}"', 'serialize': ['{major}.{minor}.{patch}']}, {'filename': './changelog.md', 'replace': '## [`{new_version}` (unreleased)](', 'search': '## [`{current_version}` (unreleased)]('}, {'filename': './citation.cff', 'regex': True, 'replace': 'version: {new_version}', 'search': '(?m)^version: {current_version}'}, {'filename': './citation.cff', 'regex': True, 'replace': 'date-released: {utcnow:%Y-%m-%d}', 'search': 'date-released: \\d{{4}}-\\d{{2}}-\\d{{2}}'}], 'ignore_missing_files': True, 'parse': '(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\.dev(?P<dev>\\d+))?', 'parts': {'dev': {'optional_value': 'release', 'values': ['0', 'release']}}, 'serialize': ['{major}.{minor}.{patch}.dev{dev}', '{major}.{minor}.{patch}']}, 'coverage': {'report': {'fail_under': 86.5, 'precision': 2}, 'run': {'branch': True, 'omit': ['*/extra_platforms/_types.py'], 'parallel': True, 'patch': ['subprocess'], 'source': ['extra_platforms']}}, 'lychee': {'exclude': ['^https://github.com/.+/issues/[0-9]+#issuecomment-.*$', '^https://github.com/.+/releases/.+/download/.*$', '^https://doi.org/.+/zenodo.*$', 'archive\\.ph', 'sci-hub\\.st', 'ycombinator\\.com', '^https://(www\\.)?x\\.com(/.*)?$', '^https://www\\.virustotal\\.com/gui/.*$', 'bitdefender\\.com', '^https://www\\.npmjs\\.com/package/.*$', 'githubstatus\\.com', '^https://claude\\.ai/.*$']}, 'mypy': {'check_untyped_defs': True, 'overrides': [{'ignore_missing_imports': True, 'module': 'click_extra.*'}, {'follow_imports': 'skip', 'ignore_missing_imports': True, 'module': ['sphinx.*']}], 'pretty': True, 'warn_redundant_casts': True, 'warn_return_any': True, 'warn_unreachable': True, 'warn_unused_configs': True, 'warn_unused_ignores': True}, 'pytest': {'addopts': ['--durations=10', '--import-mode=importlib'], 'markers': ["benchmark: Tests that budget wall-clock time (excluded with -m 'not benchmark').", "network: Tests that require network access (excluded with -m 'not network').", 'xdist_group: Tests sharing one pytest-xdist worker (declared for runs without pytest-xdist).'], 'strict_config': True, 'strict_markers': True, 'testpaths': ['tests'], 'xfail_strict': True}, 'repomatic': {'abandoned-versions': ['1.0.1'], 'docs': {'update-script': ''}, 'lint-repo': {'declined': {'pytest': {'addopts': {'--cov-report=term': 'The tests workflow runs pytest under coverage run, which also counts the lines the pytest11 plugin imports before pytest-cov could start.', '--dist=loadgroup': 'The tests workflow passes all xdist flags, so a from-source build runs plain pytest without pytest-xdist.', '--numprocesses=logical': 'The tests workflow passes all xdist flags, so a from-source build runs plain pytest without pytest-xdist.'}, 'markers': {'once: Tests that only need to run once, not across the full CI matrix.': 'No test here is matrix-insensitive yet: nearly every test checks platform-specific behavior on each cell.'}}, 'ruff': {'lint': {'extend-select': {'PLC0415': 'Function-level imports are deliberate here: they break the import cycle around the data registries and keep rare modules off the import path of the package. See Imports in AGENTS.md.'}}}}}, 'nuitka': {'enabled': False}, 'test-matrix': {'variations': {'os': ['ubuntu-24.04', 'ubuntu-22.04-arm', 'ubuntu-22.04', 'macos-15', 'macos-15-intel', 'macos-14', 'windows-2022']}}, 'workflow': {'extra-paths': ['AGENTS.md', 'docs/**', 'readme.md']}}, 'ruff': {'extend-include': ['*.{markdown,mdown,mkdn,mdwn,mkd,md,mdtxt,mdtext,mdx}'], 'fix': True, 'format': {'docstring-code-format': True}, 'lint': {'extend-select': ['D205', 'D209', 'E501', 'PLW1514', 'RUF100', 'RUF102', 'RUF103', 'RUF104', 'TC'], 'future-annotations': True, 'ignore': ['D301', 'D400', 'ERA001', 'LOG015'], 'isort': {'combine-as-imports': True}}, 'output-prefer-rule-codes': True, 'preview': True, 'show-fixes': True, 'unsafe-fixes': False}, 'typos': {'default': {'extend-identifiers': {'Github': 'GitHub', 'IOS': 'iOS', 'Javascript': 'JavaScript', 'MacOS': 'macOS', 'PATCHed': 'PATCHed', 'PNGs': 'PNGs', 'PyPi': 'PyPI', 'Typescript': 'TypeScript'}, 'extend-ignore-identifiers-re': ['Tru64', 'PASE', 'Sur'], 'extend-ignore-re': ['(?s)<!-- typos:off -->.*?<!-- typos:on -->'], 'extend-words': {'astroid': 'astroid', 'certifi': 'certifi', 'oject': 'oject', 'sur': 'sur'}}, 'files': {'extend-exclude': ['.git', '.gitignore', '.mailmap'], 'ignore-hidden': False}, 'type': {'svg': {'check-file': False}}}, 'uv': {'build-backend': {'module-root': '', 'source-exclude': ['**/*.bak', '**/.DS_Store', '**/__pycache__', 'docs/_build', 'docs/_linkcheck', 'docs/html', 'tests/.coverage'], 'source-include': ['.github/code-of-conduct.md', 'AGENTS.md', 'changelog.md', 'docs/**', 'tests/**']}, 'dependency-groups': {'docs': {'requires-python': '>= 3.12'}}, 'exclude-newer': '1 week', 'required-version': '>=0.12.22'}}}ΒΆ
The parsed content of the
pyproject.tomlfile.
- tests.test_root.test_pyproject_keywords()[source]ΒΆ
Check that keywords in
pyproject.tomlare correct.
- tests.test_root.test_pyproject_classifiers()[source]ΒΆ
Check that Trove classifiers in
pyproject.tomlare correct.
- tests.test_root.test_current_strict_mode(current_func, all_collection, unknown_constant, trait_type, error_message, monkeypatch, fresh_caches)[source]ΒΆ
Test that
current_*(strict=True)raises an error when unrecognized.
- tests.test_root.test_group_detection_type_stubs()[source]ΒΆ
Check all is_*() group detection type stubs are defined and sorted.
- tests.test_root.test_invalidate_caches()[source]ΒΆ
invalidate_caches()empties every cache that detection fills.
- tests.test_root.test_multiple_traits_match(traits, current_func, message, monkeypatch, fresh_caches)[source]ΒΆ
A category whose traits all match at once raises, instead of picking one.
Shells take their own test: their resolver breaks ties through running processes before it gives up.
- tests.test_root.test_multiple_shells_match(monkeypatch, fresh_caches)[source]ΒΆ
Test RuntimeError when multiple shells match.
- tests.test_root.test_unrecognized_message_format()[source]ΒΆ
Test that _unrecognized_message contains expected fields.
- tests.test_root.test_category_env_signals_gating_var(category, gating_var)[source]ΒΆ
The primary signal of each env-gated category is its
expected=gate var.
- tests.test_root.test_unrecognized_message_reports_set_category_vars(monkeypatch, category)[source]ΒΆ
A set category variable, and its value, appear in that categoryβs report.
- tests.test_root.test_unrecognized_message_hides_unset_secondary_vars(monkeypatch)[source]ΒΆ
Unset non-primary category variables are omitted, keeping the report concise.
- tests.test_root.test_unrecognized_message_without_category_omits_env_block(monkeypatch)[source]ΒΆ
Architecture and platform reports carry only the system primitives.
- tests.test_root.test_invalidate_caches_python_314(monkeypatch)[source]ΒΆ
Test that invalidate_caches calls platform.invalidate_caches on Python 3.14+.
- tests.test_root.test_import_time()[source]ΒΆ
Guard against import time regressions.
Spawns fresh subprocesses to measure cold import time, avoiding
sys.modulescache effects from pytestβs own imports.Asserts on the fastest of several samples. One sample on a shared CI runner measures that runnerβs worst moment rather than the code: the budget was doubled from 1000 ms to 2000 ms in the 13.3.0 cycle after macos-15-intel measured ~1088 ms on py3.14 with no code-level regression, and that same runner still reached 2236 ms on a single sample afterwards. Sampling targets the variance instead, because a real regression slows every sample while a scheduling stall slows one.
The 2000 ms budget stays deliberately loose to absorb slower architectures (on i586 cold import measured ~340 ms in 11.x and ~613 ms in 12.0.0), against a local cold import of ~22 ms. This will not catch small drifts, but reliably prevents reintroducing expensive import-time operations (like the ~120 ms regression from redundant AST parsing that was fixed by caching in
_docstrings.py).Carries the
benchmarkmarker because no budget can hold on every machine: an emulated architecture fails it with no code regression, as Alpineβs loongarch64 builder did at 2176 ms. A distribution build excludes the class with-m "not benchmark"rather than deselecting this node by name.
- tests.test_root.test_docstrings_are_generated_on_first_read(flags)[source]ΒΆ
Importing the package generates no docstring: the first read does.
Runs in a fresh interpreter, because an earlier test of the session may have read a docstring already. The interpreter flags do not change the result: a generated docstring does not depend on the class docstring.
- tests.test_root.test_typing_is_not_imported()[source]ΒΆ
The package loads no
typingitself, which nothing needs at runtime.Annotations need
typingunderTYPE_CHECKINGonly. A dataclass reads aClassVarfield at runtime, so the class metadata of traits and groups goes through class keyword arguments instead.Runs in a fresh interpreter, and only counts the modules the package import adds: a coverage hook started with the interpreter may load
typingfirst.The count also starts after
dataclassesloads.dataclassesimportsinspect, which importstypingfrom CPython 3.13.13 on the 3.13 branch (python/cpython#146491). On these releases the test misses atypingimport by the package. Every other Python version still catches it.
- tests.test_root.test_subprocess_and_shutil_are_not_imported_at_module_level()[source]ΒΆ
No module of the package imports
subprocessorshutilwhen it loads.Both serve only the detection paths that spawn a process, which import them in the function body. The check reads the source rather than
sys.modules, so it also covers the modules the package loads lazily, like_windows.py.
tests.test_shell_data moduleΒΆ
Test all shell definitions, detection and shell-specific groups.
tests.test_sphinx_crossrefs moduleΒΆ
Tests for Sphinx cross-reference rendering in the real documentation.
These tests verify that cross-references in the built documentation (./docs/_build/) resolve to actual links with correct href attributes. Unlike mock-based tests, these catch real regressions in the actual documentation.
- tests.test_sphinx_crossrefs.importable(module)[source]ΒΆ
Tell whether
moduleresolves in the running interpreter.- Return type:
- tests.test_sphinx_crossrefs.built_docs()[source]ΒΆ
Ensure the documentation is built and return the path to the HTML directory.
This fixture builds the documentation if it doesnβt exist or is outdated.
- Return type:
- tests.test_sphinx_crossrefs.read_html(built_docs, filename)[source]ΒΆ
Read an HTML file from the built documentation, once per session.
Only the top level of the build is read:
_modules/holds viewcode pages sharing the basenames of the real pages, likedetection.html.- Return type:
- tests.test_sphinx_crossrefs.find_links_with_text(html, link_text)[source]ΒΆ
Find all href values for links whose text is exactly the given text.
Returns a list of href values for <a> tags whose plain text equals the specified text, so a link to
LINUX_LIKEnever stands in for one toLINUX. The function handles nested tags, like <a href=ββ¦β><code><span>text</span></code></a>.
- tests.test_sphinx_crossrefs.has_linked_reference(html, text, expected_href_fragment)[source]ΒΆ
Check that the HTML links the given text to the expected href.
- Parameters:
html (
str) β The HTML content to search.text (
str) β The link text to find (like"AARCH64","is_linux()").expected_href_fragment (
str) β The end of the expected href (like"architectures.html#extra_platforms.AARCH64"), so an anchor that only starts with it, like#extra_platforms.ARMV6LforARM, does not match.
- Return type:
- Returns:
Trueif a matching link is found.
- tests.test_sphinx_crossrefs.test_rendered_links_point_to_correct_targets(built_docs, page, link_text, href_fragment)[source]ΒΆ
Smoke test: verify that specific rendered links point to expected targets.
- tests.test_sphinx_crossrefs.get_expected_page_for_symbol(role, symbol)[source]ΒΆ
Determine the expected HTML page for a given symbol.
- tests.test_sphinx_crossrefs.test_reference_matrix_links(built_docs, myst, expected_text, expected_link)[source]ΒΆ
Parametrized check: the MyST directive in column 1 renders to a link in column 2.
mystis the literal MyST role example as shown in the first column of the Reference matrix.expected_linkis the expected href target used in the rendered Rendering column.
- tests.test_sphinx_crossrefs.test_get_expected_page_for_symbol_handles_public_api(symbol_name)[source]ΒΆ
Test that get_expected_page_for_symbol correctly handles each public symbol.
This test validates that our logic correctly maps every symbol exposed in the public API from both extra_platforms and extra_platforms.pytest modules to the correct documentation page.
- Parameters:
symbol_name β The symbol name (like
"UBUNTU","is_linux","pytest.skip_ubuntu").
- tests.test_sphinx_crossrefs.collect_all_refs()[source]ΒΆ
Collect all cross-reference tuples (role, symbol, source_file).
This helper is intentionally executed at collection time to generate parametrization values for the comprehensive cross-reference test. A file citing the same reference twice yields one tuple, and the tuples are sorted, so the order does not depend on the file system.
- tests.test_sphinx_crossrefs.test_all_crossreferences_point_to_correct_pages(built_docs, role, symbol, source_file)[source]ΒΆ
Parametrized check that a single cross-reference points to the expected page.
The previous monolithic test iterated over all refs; this parametrized variant runs the same checks per-reference so failures are reported per-item.
- tests.test_sphinx_crossrefs.extract_docstring_from_html(html, symbol_id)[source]ΒΆ
Extract the docstring text for a symbol from HTML content.
This function is used to verify that custom docstrings are properly rendered in the generated HTML documentation, particularly for frozenset collections where Sphinxβs autodoc would normally show the generic frozenset description.
- tests.test_sphinx_crossrefs.test_frozenset_docstrings_are_custom(built_docs, symbol_name, expected_text_fragment)[source]ΒΆ
Test that frozenset collections have custom docstrings, not the generic one.
This test verifies that the frozenset collections (ALL_GROUPS, ALL_TRAIT_IDS, etc.) are documented with their custom docstrings extracted from #: comments rather than the generic frozenset description.
The canonical location for these symbols is
groups.html.
- tests.test_sphinx_crossrefs.SPECIALIZED_PAGES = ('agents.html', 'architectures.html', 'ci.html', 'detection.html', 'groups.html', 'platforms.html', 'pytest.html', 'shells.html', 'sphinx.html', 'terminals.html', 'trait.html')ΒΆ
Specialized documentation pages that should never leak links to the generic auto-generated
extra_platforms.htmlpage.
- tests.test_sphinx_crossrefs.test_no_links_to_generic_api_page(built_docs, page)[source]ΒΆ
Test that specialized doc pages never link to the generic extra_platforms.html.
All cross-references from hand-written documentation pages should resolve to other specialized pages (like
architectures.html,groups.htmlordetection.html), never to the catch-allextra_platforms.htmlproduced byautomodule.
- tests.test_sphinx_crossrefs.test_generic_api_page_no_stolen_targets(built_docs)[source]ΒΆ
The extra_platforms.html page steals no target from a specialized page.
The
docs/extra_platforms.mdpage uses:noindex:and:no-members:on all submoduleautomoduledirectives to prevent members documented in specialized pages from appearing on the generic page. This test checks both anchors (id=) and rendered member signatures (sig-name) to catch leaks even when:noindex:suppresses the anchor.
tests.test_suite_hygiene moduleΒΆ
Checks on the test suite itself, rather than on the package.
- tests.test_suite_hygiene.PROJECT_ROOT = PosixPath('/home/runner/work/extra-platforms/extra-platforms')ΒΆ
The root path of the project.
- tests.test_suite_hygiene.ENCODING_ARGUMENT = re.compile('encoding=(["\'])(?P<name>utf-?8)\\1', re.IGNORECASE)ΒΆ
An
encodingkeyword argument naming UTF-8, in any spelling.
- tests.test_suite_hygiene.test_collection_order_ignores_hash_seed()[source]ΒΆ
Every xdist worker must collect the same tests in the same order.
Each worker is a fresh interpreter with its own hash seed. A parametrize source that iterates a
setor afrozensetthen yields its cases in a different order on each worker, and xdist aborts the session with Different tests were collected. pytest-randomly hides the problem, because it re-sorts the collected items: a packager build that disables it does not.
tests.test_terminal_data moduleΒΆ
Test all terminal definitions, detection and terminal-specific groups.
tests.test_trait moduleΒΆ
- tests.test_trait.test_subclass_rejects_empty_metadata(attribute, in_body)[source]ΒΆ
A subclass setting empty class metadata fails at definition.
The subclass derives from
Group: a failedTraitsubclass would linger inTrait.__subclasses__(), which_all_group_suffix_to_type_id()reads.
- tests.test_trait.test_subclass_rejects_unknown_metadata_keyword()[source]ΒΆ
A class keyword argument naming no metadata fails at definition.
- tests.test_trait.test_subclass_metadata_derives_from_type_id()[source]ΒΆ
Metadata a subclass sets overrides the derived one, and seeds the others.
A class keyword argument wins over an attribute of the class body.
- tests.test_trait.test_trait_rejects_invalid_field(klass, fields, message)[source]ΒΆ
A trait with an invalid field fails at construction.
- tests.test_trait.test_docstring_outside_registries_is_class_docstring(kind)[source]ΒΆ
An instance outside
ALL_TRAITSandALL_GROUPSreads its class docstring.A generated docstring describes a predefined object. On any other instance it would name a detection function that does not exist, and a derived group would borrow the attribute docstring of the predefined group whose ID it carries.
- tests.test_trait.test_generate_docstring_of_class_defined_outside_package(kind)[source]ΒΆ
generate_docstring()works for a class defined outside the package.The package holds no data module for such a class, so there is no attribute docstring to fold in: the result is the metadata alone.
- tests.test_trait.test_attribute_docstrings_without_source(kind, expected, tmp_path, monkeypatch)[source]ΒΆ
A data module without readable source yields no attribute docstring.
Frozen and compiled builds load modules without a source file, or without a
__file__at all: reading the docstring of a trait there must not raise.
- tests.test_trait.test_aliases_do_not_conflict_with_trait_ids()[source]ΒΆ
Verify no alias conflicts with a canonical trait ID.
- tests.test_trait.test_aliases_do_not_conflict_with_group_ids()[source]ΒΆ
Verify no alias conflicts with a group ID.
- tests.test_trait.test_aliases_are_unique_across_traits()[source]ΒΆ
Verify no alias is defined by multiple traits.
- tests.test_trait.test_shell_executables_are_lowercase_and_distinct_from_ids()[source]ΒΆ
A shellβs executables are lowercase file names no shell claims as its ID.
- tests.test_trait.test_shell_executables_are_unique_across_shells()[source]ΒΆ
No file name is claimed by two shells.
Icons are unique across traits and groups, with two exceptions.
A canonical group may share its icon with its members, but only when all of them carry it. Traits may also share an icon between themselves, provided no group uses that icon and every sharer belongs to the same canonical group (
π©is both Fedora and RHEL).
- tests.test_trait.test_doc_roster_covers_its_population(page)[source]ΒΆ
Each roster table of the documentation names its whole population.
These tables are written by hand, and nothing reads them back, so a trait added without touching them leaves a hole no build reports: the page just lists one platform fewer. The reverse direction matters as much, a row outliving its trait pointing at a symbol that no longer resolves.
- tests.test_trait.test_doc_roster_repeats_icon_and_name(page)[source]ΒΆ
The rosters carrying an Icon and a Name column repeat what the code says.
Copying either into a table forks it, so a renamed trait or a swapped icon would otherwise leave the page stating the old value for good.
- tests.test_trait.test_readme_roster_covers_its_population(region)[source]ΒΆ
Each roster region of the readme names its whole population.
These regions are pasted by hand and nothing reads them back, so a trait added without touching the readme leaves a hole no build reports. The reverse direction matters as much, an entry outliving the trait it names.
- tests.test_trait.test_readme_mindmap_matches_its_generator()[source]ΒΆ
The platform mindmap of the readme still matches what produces it.
The readme pastes the output of
generate_traits_mindmap()under amirror-srccomment holding the call that produced it. Comparing the block against a fresh call catches what a roster check cannot: a swapped icon, a renamed group, or a trait that moved between groups.
tests.test_trait_data moduleΒΆ
Test trait data sorting and group coverage across all trait types.
- tests.test_trait_data.test_trait_data_sorting(klass)[source]ΒΆ
Trait instances must be sorted alphabetically in their data module.
- tests.test_trait_data.test_current_trait_is_consistent(klass)[source]ΒΆ
current_*(),is_any_*()and theALL_*group agree on the current trait.current_*()raises when two traits of its category match, so this also checks that the traits of each category exclude each other.
tests.test_utils moduleΒΆ
- tests.test_utils.test_recursive_update(a, b, expected)[source]ΒΆ
The second dict updates the first one in place, at every depth.