Groups

Group usage

A Group is a collection of Trait instances (architectures, platforms, shells, terminals, CI systems, or agents). Groups support membership testing, iteration, and set-like operations.

Membership testing

Check whether the current environment matches any member of a group:

>>> from extra_platforms import is_linux
>>> is_linux()
True

Test if a specific trait belongs to a group. You can use both Trait instances and their string IDs:

>>> from extra_platforms import LINUX, UBUNTU, MACOS
>>> UBUNTU in LINUX
True
>>> MACOS in LINUX
False
>>> "ubuntu" in LINUX
True

Iteration

Groups are iterable and sized:

>>> from extra_platforms import BSD
>>> len(BSD)
7
>>> for platform in BSD:
...     print(platform.id)
dragonfly_bsd
freebsd
macos
midnightbsd
netbsd
openbsd
sunos

Set operations

Groups support standard set operations, returning new Group instances:

>>> from extra_platforms import BSD, BSD_WITHOUT_MACOS, LINUX, MACOS
>>> only_macos = BSD.difference(BSD_WITHOUT_MACOS)
>>> only_macos.member_ids
frozenset({'macos'})
>>> combined = BSD.union(LINUX)
>>> MACOS in combined
True

Set operations also have operator overloads for more concise syntax:

>>> from extra_platforms import BSD, BSD_WITHOUT_MACOS, LINUX, MACOS
>>> only_macos = BSD - BSD_WITHOUT_MACOS
>>> only_macos.member_ids
frozenset({'macos'})
>>> combined = BSD | LINUX
>>> MACOS in combined
True

Available operations: union() (|), intersection() (&), difference() (-), symmetric_difference() (^), issubset(), issuperset(), and isdisjoint().

Mutating-style operations

Groups are immutable (frozen dataclasses), but provide methods that return new instances:

>>> from extra_platforms import BSD, AIX
>>> extended = BSD.add(AIX)
>>> AIX in extended
True
>>> AIX in BSD
False
>>> shrunk = BSD.remove("macos")
>>> "macos" in shrunk
False

See also: discard(), pop(), clear(), and copy().

Creating custom groups

Build new groups from scratch or by combining existing ones:

>>> from extra_platforms import Group, UBUNTU, DEBIAN, MACOS
>>> my_targets = Group("my_targets", "My Targets", "🎯", (UBUNTU, DEBIAN, MACOS))
>>> len(my_targets)
3

Hint

You can check my other Meta Package Manager project for a real life example, where I use Group to manage families of target platforms for software packaging.

Reducing traits to groups

The reduce() function finds the minimal set of groups and traits that covers a given collection:

>>> from extra_platforms import (
...     reduce,
...     DRAGONFLY_BSD,
...     FREEBSD,
...     MACOS,
...     MIDNIGHTBSD,
...     NETBSD,
...     OPENBSD,
...     SUNOS,
... )
>>> reduce([DRAGONFLY_BSD, FREEBSD, MACOS, MIDNIGHTBSD, NETBSD, OPENBSD, SUNOS])
frozenset({Group(id='bsd', name='All BSD')})

All groups

All recognized groups and their properties:

Icon

Symbol

Description

Detection

Canonical

🧠

ALL_AGENTS

All AI coding agents

is_any_agent()

⬥

🏛️

ALL_ARCHITECTURES

All architectures

is_any_architecture()

📱

ALL_ARM

ARM architectures

is_any_arm()

⬥

♺

ALL_CI

All CI systems

is_any_ci()

⬥

🔲

ALL_MIPS

MIPS architectures

is_any_mips()

⬥

⚙️

ALL_PLATFORMS

All platforms

is_any_platform()

🐚

ALL_SHELLS

All shells

is_any_shell()

☀️

ALL_SPARC

SPARC architectures

is_any_sparc()

⬥

💻

ALL_TERMINALS

All terminals

is_any_terminal()

⁕

ALL_TRAITS

All architectures, platforms, shells, terminals, CI systems, and agents

is_any_trait()

🪟

ALL_WINDOWS

All Windows

is_any_windows()

⬥

³²

ARCH_32_BIT

32-bit architectures

is_arch_32_bit()

⁶⁴

ARCH_64_BIT

64-bit architectures

is_arch_64_bit()

⬆️

BIG_ENDIAN

Big-endian architectures

is_big_endian()

💲

BOURNE_SHELLS

Bourne-compatible shells

is_bourne_shells()

⬥

Ⓑ

BSD

All BSD

is_bsd()

⬥

🅱️

BSD_WITHOUT_MACOS

All BSD excluding macOS

is_bsd_not_macos()

🅲

C_SHELLS

C shells

is_c_shells()

⬥

🎮

GPU_TERMINALS

GPU-accelerated terminals

is_gpu_terminals()

⬥

🏢

IBM_MAINFRAME

IBM mainframe

is_ibm_mainframe()

⬥

🐧

LINUX

Linux distributions

is_linux()

⬥

≚

LINUX_LAYERS

Linux compatibility layers

is_linux_layers()

⬥

🐣

LINUX_LIKE

All Linux & compatibility layers

is_linux_like()

⬇️

LITTLE_ENDIAN

Little-endian architectures

is_little_endian()

🐉

LOONGARCH

LoongArch

is_loongarch()

⬥

⧉

MULTIPLEXERS

Terminal multiplexers

is_multiplexers()

⬥

▦

NATIVE_TERMINALS

Native terminal emulators

is_native_terminals()

⬥

🅟

OTHER_POSIX

Other POSIX-compliant platforms

is_other_posix()

⬥

◇

OTHER_SHELLS

Other shells

is_other_shells()

⬥

⚡

POWERPC

PowerPC family

is_powerpc()

⬥

Ⅴ

RISCV

RISC-V family

is_riscv()

⬥

𝐕

SYSTEM_V

AT&T System Five

is_system_v()

⬥

⨷

UNIX

All Unix

is_unix()

≛

UNIX_LAYERS

Unix compatibility layers

is_unix_layers()

⬥

⨂

UNIX_WITHOUT_MACOS

All Unix excluding macOS

is_unix_not_macos()

❓

UNKNOWN

Unknown

is_unknown()

⬥

⬢

WEB_TERMINALS

Web-based terminals

is_web_terminals()

⬥

🌐

WEBASSEMBLY

WebAssembly

is_webassembly()

⬥

⌨️

WINDOWS_SHELLS

Windows shells

is_windows_shells()

⬥

𝘅

X86

x86 family

is_x86()

⬥

Hint

Canonical groups are non-overlapping groups that together cover all recognized traits. They are marked with a ⬥ icon in the table above.

Other groups are provided for convenience, but overlap with each other or with canonical groups.

Predefined groups

extra_platforms.ALL_AGENTS = Group(id='all_agents', name='All AI coding agents')

All recognized AI coding agents.

Caution

This group does not contain the UNKNOWN_AGENT trait.

extra_platforms.ALL_ARCHITECTURES = Group(id='all_architectures', name='All architectures')

All recognized architectures.

Caution

This group does not contain the UNKNOWN_ARCHITECTURE trait.

extra_platforms.ALL_ARM = Group(id='all_arm', name='ARM architectures')

All ARM-based architectures.

extra_platforms.ALL_CI = Group(id='all_ci', name='All CI systems')

All recognized Continuous Integration systems.

Caution

This group does not contain the UNKNOWN_CI trait.

extra_platforms.ALL_MIPS = Group(id='all_mips', name='MIPS architectures')

All MIPS-based architectures.

extra_platforms.ALL_PLATFORMS = Group(id='all_platforms', name='All platforms')

All recognized platforms.

Caution

This group does not contain the UNKNOWN_PLATFORM trait.

extra_platforms.ALL_SHELLS = Group(id='all_shells', name='All shells')

All recognized shells.

Caution

This group does not contain the UNKNOWN_SHELL trait.

extra_platforms.ALL_SPARC = Group(id='all_sparc', name='SPARC architectures')

All SPARC-based architectures.

extra_platforms.ALL_TERMINALS = Group(id='all_terminals', name='All terminals')

All recognized terminals.

Caution

This group does not contain the UNKNOWN_TERMINAL trait.

extra_platforms.ALL_TRAITS = Group(id='all_traits', name='All architectures, platforms, shells, terminals, CI systems, and agents')

All predefined architectures, platforms, shells, terminals, CI systems, and agents.

Hint

This group includes all UNKNOWN_* traits.

extra_platforms.ALL_WINDOWS = Group(id='all_windows', name='All Windows')

All Windows operating systems.

extra_platforms.ARCH_32_BIT = Group(id='arch_32_bit', name='32-bit architectures')

All 32-bit architectures.

extra_platforms.ARCH_64_BIT = Group(id='arch_64_bit', name='64-bit architectures')

All 64-bit architectures.

extra_platforms.BIG_ENDIAN = Group(id='big_endian', name='Big-endian architectures')

All big-endian architectures.

extra_platforms.BOURNE_SHELLS = Group(id='bourne_shells', name='Bourne-compatible shells')

All Bourne-compatible shells.

extra_platforms.BSD = Group(id='bsd', name='All BSD')

All BSD platforms.

Note

Are considered of this family (according Wikipedia):

  • 386BSD (FreeBSD, NetBSD, OpenBSD, DragonFly BSD)

  • NeXTSTEP

  • Darwin (macOS, iOS, audioOS, iPadOS, tvOS, watchOS, bridgeOS)

  • SunOS

  • Ultrix

extra_platforms.BSD_WITHOUT_MACOS = Group(id='bsd_without_macos', name='All BSD excluding macOS')

All BSD platforms, without macOS.

This is useful to avoid macOS-specific workarounds on BSD platforms.

extra_platforms.C_SHELLS = Group(id='c_shells', name='C shells')

C shell family.

extra_platforms.GPU_TERMINALS = Group(id='gpu_terminals', name='GPU-accelerated terminals')

GPU-accelerated terminal emulators.

extra_platforms.IBM_MAINFRAME = Group(id='ibm_mainframe', name='IBM mainframe')

IBM mainframe architectures.

extra_platforms.LINUX = Group(id='linux', name='Linux distributions')

All distributions based on a Linux kernel.

Note

Are considered of this family (according Wikipedia):

  • Android

  • ChromeOS

  • any other distribution

extra_platforms.LINUX_LAYERS = Group(id='linux_layers', name='Linux compatibility layers')

Interfaces that allows Linux binaries to run on a different host system.

Note

Are considered of this family (according Wikipedia):

  • Windows Subsystem for Linux

extra_platforms.LINUX_LIKE = Group(id='linux_like', name='All Linux & compatibility layers')

Sum of all Linux distributions and Linux compatibility layers.

extra_platforms.LITTLE_ENDIAN = Group(id='little_endian', name='Little-endian architectures')

All little-endian architectures.

extra_platforms.LOONGARCH = Group(id='loongarch', name='LoongArch')

LoongArch architecture.

extra_platforms.MULTIPLEXERS = Group(id='multiplexers', name='Terminal multiplexers')

Terminal multiplexers that can host other terminals.

extra_platforms.NATIVE_TERMINALS = Group(id='native_terminals', name='Native terminal emulators')

Platform-native terminal emulators built with traditional GUI toolkits.

extra_platforms.OTHER_POSIX = Group(id='other_posix', name='Other POSIX-compliant platforms')

All other UNIX-like or POSIX-compliant platforms.

Note

Are considered of this family (according Wikipedia):

  • Coherent

  • GNU/Hurd

  • HarmonyOS

  • LiteOS

  • LynxOS

  • Minix

  • MOS

  • OSF/1

  • QNX

  • BlackBerry 10

  • Research Unix

  • SerenityOS

extra_platforms.OTHER_SHELLS = Group(id='other_shells', name='Other shells')

Other non-traditional shells.

extra_platforms.POWERPC = Group(id='powerpc', name='PowerPC family')

All PowerPC-based architectures.

extra_platforms.RISCV = Group(id='riscv', name='RISC-V family')

All RISC-V-based architectures.

extra_platforms.SYSTEM_V = Group(id='system_v', name='AT&T System Five')

All Unix platforms derived from AT&T System Five.

Note

Are considered of this family (according Wikipedia):

  • A/UX

  • AIX

  • HP-UX

  • IRIX

  • OpenServer

  • Solaris

  • OpenSolaris

  • Illumos

  • Tru64

  • UNIX

  • UnixWare

extra_platforms.UNIX = Group(id='unix', name='All Unix')

All Unix-like operating systems and compatibility layers.

extra_platforms.UNIX_LAYERS = Group(id='unix_layers', name='Unix compatibility layers')

Interfaces that allows Unix binaries to run on a different host system.

Note

Are considered of this family (according Wikipedia):

  • Cygwin

  • Darling

  • Eunice

  • GNV

  • Interix

  • MachTen

  • Microsoft POSIX subsystem

  • MKS Toolkit

  • PASE

  • P.I.P.S.

  • PWS/VSE-AF

  • UNIX System Services

  • UserLAnd Technologies

  • Windows Services for UNIX

extra_platforms.UNIX_WITHOUT_MACOS = Group(id='unix_without_macos', name='All Unix excluding macOS')

All Unix platforms, without macOS.

This is useful to avoid macOS-specific workarounds on Unix platforms.

extra_platforms.UNKNOWN = Group(id='unknown', name='Unknown')

Unknown or unrecognized traits.

extra_platforms.WEB_TERMINALS = Group(id='web_terminals', name='Web-based terminals')

Terminal emulators built on web technologies (Electron, xterm.js).

extra_platforms.WEBASSEMBLY = Group(id='webassembly', name='WebAssembly')

WebAssembly architectures.

extra_platforms.WINDOWS_SHELLS = Group(id='windows_shells', name='Windows shells')

Windows-native shells.

extra_platforms.X86 = Group(id='x86', name='x86 family')

All x86-based architectures (Intel-compatible).

Group collections

extra_platforms.group_data.ALL_AGENT_GROUPS: frozenset[Group]

All groups whose members are Agent.

Note

Not that useful as there is only one agent group, but provided for symmetry with ALL_ARCHITECTURE_GROUPS and ALL_PLATFORM_GROUPS.

extra_platforms.group_data.ALL_ARCHITECTURE_GROUPS: frozenset[Group]

All groups whose members are Architecture.

extra_platforms.group_data.ALL_CI_GROUPS: frozenset[Group]

All groups whose members are CI.

Note

Not that useful as there is only one CI group, but provided for symmetry with ALL_ARCHITECTURE_GROUPS and ALL_PLATFORM_GROUPS.

extra_platforms.group_data.ALL_GROUPS: frozenset[Group]

All predefined groups.

Hint

This collection contains both canonical and non-canonical groups, including the UNKNOWN group.

extra_platforms.group_data.ALL_PLATFORM_GROUPS: frozenset[Group]

All groups whose members are Platform.

extra_platforms.group_data.ALL_SHELL_GROUPS: frozenset[Group]

All groups whose members are Shell.

extra_platforms.group_data.ALL_TERMINAL_GROUPS: frozenset[Group]

All groups whose members are Terminal.

extra_platforms.group_data.CANONICAL_GROUPS: frozenset[Group]

Canonical, non-overlapping groups.

Hint

These groups together cover all Architecture, Platform, Shell, Terminal, CI, and Agent traits, including traits from the UNKNOWN group.

All groups in this collection are marked as canonical.

extra_platforms.group_data.NON_CANONICAL_GROUPS: frozenset[Group]

Non-canonical, overlapping groups, defined for convenience.

Hint

None of these groups are marked as canonical.

ID collections

extra_platforms.group_data.ALL_GROUP_IDS: frozenset[str] = frozenset({'all_agents', 'all_architectures', 'all_arm', 'all_ci', 'all_mips', 'all_platforms', 'all_shells', 'all_sparc', 'all_terminals', 'all_traits', 'all_windows', 'arch_32_bit', 'arch_64_bit', 'big_endian', 'bourne_shells', 'bsd', 'bsd_without_macos', 'c_shells', 'gpu_terminals', 'ibm_mainframe', 'linux', 'linux_layers', 'linux_like', 'little_endian', 'loongarch', 'multiplexers', 'native_terminals', 'other_posix', 'other_shells', 'powerpc', 'riscv', 'system_v', 'unix', 'unix_layers', 'unix_without_macos', 'web_terminals', 'webassembly', 'windows_shells', 'x86'})

A frozenset of all recognized group IDs.

Attention

This collection does not contain the UNKNOWN group.

extra_platforms.group_data.ALL_IDS: frozenset[str] = frozenset({'aarch64', 'aix', 'alacritty', 'all_agents', 'all_architectures', 'all_arm', 'all_ci', 'all_mips', 'all_platforms', 'all_shells', 'all_sparc', 'all_terminals', 'all_traits', 'all_windows', 'almalinux', 'alpine', 'altlinux', 'amzn', 'android', 'apple_terminal', 'arch', 'arch_32_bit', 'arch_64_bit', 'arm', 'armv5tel', 'armv6l', 'armv7l', 'armv8l', 'artix', 'ash', 'azure_pipelines', 'bamboo', 'bash', 'big_endian', 'bourne_shells', 'bsd', 'bsd_without_macos', 'buildkite', 'buildroot', 'c_shells', 'cachyos', 'centos', 'chromeos', 'circle_ci', 'cirrus_ci', 'claude_code', 'clearlinux', 'cline', 'cloudlinux', 'cmd', 'codebuild', 'codex', 'contour', 'copilot_cli', 'crush', 'crux', 'csh', 'cursor', 'cygwin', 'dash', 'debian', 'dragonfly_bsd', 'endeavouros', 'exherbo', 'fedora', 'fish', 'foot', 'freebsd', 'gemini_cli', 'generic_linux', 'gentoo', 'ghostty', 'github_ci', 'gitlab_ci', 'gnome_terminal', 'gnu_screen', 'gpu_terminals', 'guix', 'haiku', 'hermetic_build', 'heroku_ci', 'hurd', 'hyper', 'i386', 'i586', 'i686', 'ibm_mainframe', 'ibm_powerkvm', 'illumos', 'iterm2', 'kali', 'kitty', 'konsole', 'ksh', 'kvmibm', 'linux', 'linux_layers', 'linux_like', 'linuxmint', 'little_endian', 'loongarch', 'loongarch64', 'macos', 'mageia', 'mandriva', 'manjaro', 'midnightbsd', 'mips', 'mips64', 'mips64el', 'mipsel', 'multiplexers', 'native_terminals', 'netbsd', 'nixos', 'nobara', 'nushell', 'nutyx', 'openbsd', 'opensuse', 'openwrt', 'oracle', 'os400', 'other_posix', 'other_shells', 'parallels', 'pi', 'pidora', 'pikaos', 'powerpc', 'powershell', 'ppc', 'ppc64', 'ppc64le', 'raspbian', 'rhel', 'rio', 'riscv', 'riscv32', 'riscv64', 'rocky', 's390x', 'scientific', 'sh', 'slackware', 'sles', 'slitaz', 'solaris', 'solus', 'sourcemage', 'sparc', 'sparc64', 'sunos', 'system_v', 'tabby', 'tcsh', 'teamcity', 'tilix', 'tmux', 'travis_ci', 'tuxedo', 'ubuntu', 'ultramarine', 'unix', 'unix_layers', 'unix_without_macos', 'void', 'vscode_terminal', 'wasm32', 'wasm64', 'web_terminals', 'webassembly', 'webos', 'wezterm', 'windows', 'windows_shells', 'windows_terminal', 'wsl1', 'wsl2', 'x86', 'x86_64', 'xenserver', 'xonsh', 'xterm', 'zellij', 'zsh'})

A frozenset of all recognized traits and group IDs.

Attention

This collection does not contain all the UNKNOWN_* traits and the UNKNOWN group.

extra_platforms.group_data.ALL_TRAIT_IDS: frozenset[str] = frozenset({'aarch64', 'aix', 'alacritty', 'almalinux', 'alpine', 'altlinux', 'amzn', 'android', 'apple_terminal', 'arch', 'arm', 'armv5tel', 'armv6l', 'armv7l', 'armv8l', 'artix', 'ash', 'azure_pipelines', 'bamboo', 'bash', 'buildkite', 'buildroot', 'cachyos', 'centos', 'chromeos', 'circle_ci', 'cirrus_ci', 'claude_code', 'clearlinux', 'cline', 'cloudlinux', 'cmd', 'codebuild', 'codex', 'contour', 'copilot_cli', 'crush', 'crux', 'csh', 'cursor', 'cygwin', 'dash', 'debian', 'dragonfly_bsd', 'endeavouros', 'exherbo', 'fedora', 'fish', 'foot', 'freebsd', 'gemini_cli', 'generic_linux', 'gentoo', 'ghostty', 'github_ci', 'gitlab_ci', 'gnome_terminal', 'gnu_screen', 'guix', 'haiku', 'hermetic_build', 'heroku_ci', 'hurd', 'hyper', 'i386', 'i586', 'i686', 'ibm_powerkvm', 'illumos', 'iterm2', 'kali', 'kitty', 'konsole', 'ksh', 'kvmibm', 'linuxmint', 'loongarch64', 'macos', 'mageia', 'mandriva', 'manjaro', 'midnightbsd', 'mips', 'mips64', 'mips64el', 'mipsel', 'netbsd', 'nixos', 'nobara', 'nushell', 'nutyx', 'openbsd', 'opensuse', 'openwrt', 'oracle', 'os400', 'parallels', 'pi', 'pidora', 'pikaos', 'powershell', 'ppc', 'ppc64', 'ppc64le', 'raspbian', 'rhel', 'rio', 'riscv32', 'riscv64', 'rocky', 's390x', 'scientific', 'sh', 'slackware', 'sles', 'slitaz', 'solaris', 'solus', 'sourcemage', 'sparc', 'sparc64', 'sunos', 'tabby', 'tcsh', 'teamcity', 'tilix', 'tmux', 'travis_ci', 'tuxedo', 'ubuntu', 'ultramarine', 'void', 'vscode_terminal', 'wasm32', 'wasm64', 'webos', 'wezterm', 'windows', 'windows_terminal', 'wsl1', 'wsl2', 'x86_64', 'xenserver', 'xonsh', 'xterm', 'zellij', 'zsh'})

A frozenset of all recognized traits IDs.

Attention

This collection does not contain all the UNKNOWN_* traits.

Trait and group operations

extra_platforms.NestedReferences

Type for arbitrary nested references to traits and groups. A reference is a trait, a group, a trait or group ID, or None. Any iterable can nest references, to any depth.

extra_platforms.extract_members(*other)[source]

Returns all traits found in other.

other can be an arbitrarily nested Iterable of Group, Trait, or their IDs. None values and empty iterables are silently ignored.

Caution

Can return duplicates.

Return type:

Iterator[Trait]

extra_platforms.traits_from_ids(*trait_and_group_ids)[source]

Returns a deduplicated tuple of traits matching the provided IDs.

IDs are case-insensitive, and can refer to any traits or groups. Matching groups will be expanded to the Trait instances they contain.

Aliases are automatically resolved to their canonical IDs, with a warning emitted to encourage using the canonical ID directly.

Order of the returned traits matches the order of the provided IDs.

Tip

If you want to reduce the returned set and remove as much overlap as possible, you can use the reduce() function on the results.

Return type:

tuple[Trait, ...]

extra_platforms.groups_from_ids(*group_ids)[source]

Returns a deduplicated tuple of groups matching the provided IDs.

IDs are case-insensitive.

Order of the returned Group instances matches the order of the provided IDs.

Tip

If you want to reduce the returned set and remove as much overlap as possible, you can use the reduce() function on the results.

Return type:

tuple[Group, ...]

extra_platforms.reduce(items, target_pool=None)[source]

Reduce a collection of traits to a minimal set.

Returns a deduplicated set of Group and Trait that covers the same exact traits as the original input, but group as much traits as possible, to reduce the number of items.

Only the groups defined in the target_pool are considered for the reduction. If no reference pool is provided, use all known groups. Empty groups cover nothing, and are never picked.

Note

The algorithm is a variant of the Set Cover Problem, which is NP-hard. This implementation uses a greedy approximation that iteratively selects the largest group fitting the remaining uncovered traits.

Return type:

frozenset[Group | Trait]

Group implementation

class extra_platforms.Group(id, name, icon='❓', members=tuple())[source]

Bases: _Identifiable

A Group names a collection of traits.

Its members are Trait instances.

In addition to the common fields inherited from _Identifiable, each group provides:

  • members: An iterable of Trait instances that belong to this group.

  • member_ids: A frozenset of member IDs for quick lookup.

  • canonical: A bool indicating if the group is canonical (non-overlapping).

  • various set-like operations (union, intersection, difference, etc.).

Its unknown symbol is UNKNOWN, instead of the derived UNKNOWN_GROUP.

members: Iterable[Trait]

Traits in this group.

Normalized to MappingProxyType at init, providing O(1) lookup by ID.

__post_init__()[source]

Normalize members to a mapping of deduplicated traits, sorted by ID.

Hint

The docstring is not built here. For a predefined group, _LazyDocstring generates it on the first read of __doc__, once every module is imported.

Return type:

None

property _members: MappingProxyType[str, Trait]

Typed access to members as MappingProxyType.

Warning

The members field is typed as Iterable to accept any iterable at construction time. After __post_init__, it is always a MappingProxyType, which this property tells the type checker.

property _traits: frozenset[Trait][source]

The members, as a frozenset the set operations work on.

property _any_stem: str[source]

The ID, or any_<type> for a group named all_*.

The detection function and the unless decorator of a group named all_* read “any member matches”: is_any_arm() and @unless_any_arm. A group named after every trait of a type takes that type’s singular ID: all_architectures gives any_architecture.

property detection_func_id: str[source]

ID of the detection function for this group.

Named is_<id>(), is_any_<type>() for a group named all_*, and with _not_ in place of _without_ for more natural names, like is_unix_not_macos().

property skip_decorator_id: str[source]

ID of the Pytest skip decorator for this group.

Named @skip_<id>, with _not_ in place of _without_.

property unless_decorator_id: str[source]

ID of the Pytest unless decorator for this group.

Named @unless_<id>, @unless_any_<type> for a group named all_*, and with _not_ in place of _without_.

_metadata_lines()[source]

The metadata list closing the generated docstring of the group.

Return type:

list[str]

property member_ids: frozenset[str][source]

A frozenset of member IDs that belong to this group.

Computed once: the members never change after __post_init__, and every trait asks each group for it when its docstring is generated.

__hash__()[source]

Hash based on group ID and member IDs.

Return type:

int

property canonical: bool[source]

Return True if the group is canonical (non-overlapping).

A canonical group is one that does not share any members with other canonical groups. All canonical groups are non-overlapping.

Non-canonical groups are provided for convenience, but overlap with each other or with canonical groups.

Hint

Canonical groups are denoted with a ⬥ symbol in the documentation and tables.

__iter__()[source]

Iterate over the members of the group.

Return type:

Iterator[Trait]

__len__()[source]

Return the number of members in the group.

An empty group is falsy, like an empty set.

Return type:

int

__contains__(item)[source]

Test if a Trait or its ID is in the group.

A trait must equal the member of the same ID: one sharing the ID alone is not in the group.

Return type:

bool

__getitem__(member_id)[source]

Return the trait whose ID is member_id.

Return type:

Trait

items()[source]

Iterate over the traits of the group as key-value pairs.

Return type:

Iterator[tuple[str, Trait]]

isdisjoint(other)[source]

Return True if the group has no members in common with other.

Groups are disjoint if and only if their intersection is an empty set.

other can be an arbitrarily nested Iterable of Group and Trait.

Return type:

bool

fullyintersects(other)[source]

Return True if the group has all members in common with other.

This is the member-level equality test: the equivalent of == between plain set objects.

Note

The name follows the issubset() / issuperset() / isdisjoint() naming style of native set methods. Python sets express this operation with the == operator, which Group reserves for full identity comparison (ID, name, icon, and members).

Return type:

bool

issubset(other)[source]

Test whether every member in the group is in other.

Return type:

bool

__le__(other)

Test whether every member in the group is in other.

Return type:

bool

__lt__(other)[source]

Test whether every member in the group is in other, but not all.

Return type:

bool

issuperset(other)[source]

Test whether every member in other is in the group.

Return type:

bool

__ge__(other)

Test whether every member in other is in the group.

Return type:

bool

__gt__(other)[source]

Test whether every member in other is in the group, but not all.

Return type:

bool

union(*others)[source]

Return a new Group with members of all groups.

Caution

The new Group inherits the metadata of the first one. All other groups’ metadata is ignored.

Return type:

Self

__or__(*others)

Return a new Group with members of all groups.

Caution

The new Group inherits the metadata of the first one. All other groups’ metadata is ignored.

Return type:

Self

intersection(*others)[source]

Return a new Group with the shared members.

A member is kept when the group and all others contain it.

Caution

The new Group inherits the metadata of the first one. All other groups’ metadata is ignored.

Return type:

Self

__and__(*others)

Return a new Group with the shared members.

A member is kept when the group and all others contain it.

Caution

The new Group inherits the metadata of the first one. All other groups’ metadata is ignored.

Return type:

Self

difference(*others)[source]

Return a new Group without the others’ members.

A member is kept when the group contains it and no other does.

Caution

The new Group inherits the metadata of the first one. All other groups’ metadata is ignored.

Return type:

Self

__sub__(*others)

Return a new Group without the others’ members.

A member is kept when the group contains it and no other does.

Caution

The new Group inherits the metadata of the first one. All other groups’ metadata is ignored.

Return type:

Self

symmetric_difference(other)[source]

Return a new Group with unshared members.

A member is kept when either the group or other contains it, but not both.

Caution

The new Group inherits the metadata of the first one. All other groups’ metadata is ignored.

Return type:

Self

__xor__(other)

Return a new Group with unshared members.

A member is kept when either the group or other contains it, but not both.

Caution

The new Group inherits the metadata of the first one. All other groups’ metadata is ignored.

Return type:

Self

copy(id=None, name=None, icon=None, members=None)[source]

Return a shallow copy of the group.

Fields can be overridden by passing new values as arguments.

Return type:

Self

add(member)[source]

Return a new Group with the specified trait added.

If the trait is already in the group, returns a copy unchanged.

Parameters:

member (Trait | str) – A Trait object or trait ID string to add. A trait ID is case-insensitive, and can be an alias.

Return type:

Self

Returns:

A new Group instance with the trait added.

Raises:

ValueError – If the string is not the ID of a trait, like the ID of a group.

_member(member)[source]

Return the member that member designates.

Parameters:

member (Trait | str) – A Trait object, or a trait ID in any case, or an alias.

Raises:

KeyError – If the trait is not in the group.

Return type:

Trait

remove(member)[source]

Return a new Group without the given trait.

Parameters:

member (Trait | str) – A Trait object or trait ID string to remove. A trait ID is case-insensitive, and can be an alias.

Return type:

Self

Returns:

A new Group instance with the trait removed.

Raises:

KeyError – If the trait is not in the group.

discard(member)[source]

Return a new Group without the trait, if present.

Unlike remove(), this does not raise an error if the trait is not found.

Parameters:

member (Trait | str) – A Trait object or trait ID string to remove. A trait ID is case-insensitive, and can be an alias.

Return type:

Self

Returns:

A new Group instance with the trait removed, or a copy if not present.

pop(member_id=None)[source]

Remove and return a trait from the group.

Parameters:

member_id (str | None) – Optional trait ID to remove, case-insensitive, or an alias. If not provided, removes an arbitrary trait (specifically, the first one in iteration order).

Return type:

tuple[Trait, Self]

Returns:

A tuple of (removed Trait, new Group).

Raises:
  • KeyError – If member_id is provided but not found in the group.

  • KeyError – If the group is empty.

clear()[source]

Return a new empty Group with the same metadata.

Return type:

Self

Returns:

A new Group instance with no members but same id, name, and icon.

__annotate_func__ = None
__annotations__ = {'members': 'Iterable[Trait]'}
__dataclass_fields__ = {'icon': Field(name='icon',type='str',default='❓',default_factory=<dataclasses._MISSING_TYPE object>,init=True,repr=False,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,doc=None,_field_type=_FIELD), 'id': Field(name='id',type='str',default=<dataclasses._MISSING_TYPE object>,default_factory=<dataclasses._MISSING_TYPE object>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,doc=None,_field_type=_FIELD), 'members': Field(name='members',type='Iterable[Trait]',default=<dataclasses._MISSING_TYPE object>,default_factory=<class 'tuple'>,init=True,repr=False,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,doc=None,_field_type=_FIELD), 'name': Field(name='name',type='str',default=<dataclasses._MISSING_TYPE object>,default_factory=<dataclasses._MISSING_TYPE object>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,doc=None,_field_type=_FIELD)}
__dataclass_params__ = _DataclassParams(init=True,repr=True,eq=True,order=False,unsafe_hash=False,frozen=True,match_args=True,kw_only=False,slots=False,weakref_slot=False)
__delattr__(name)

Implement delattr(self, name).

__eq__(other)

Return self==value.

__firstlineno__ = 100
__init__(id, name, icon='❓', members=<factory>)
__match_args__ = ('id', 'name', 'icon', 'members')
__module__ = 'extra_platforms.group'
__replace__(**changes)
__repr__()

Return repr(self).

__setattr__(name, value)

Implement setattr(self, name, value).

__static_attributes__ = ()
all_group = 'ALL_GROUPS'

The symbol name for the group containing all instances of this type.

data_module_id = 'group_data'

The module name where instances of this type are defined.

doc_page = 'groups.md'

The documentation page filename.

type_id = 'group'

Machine-readable type identifier used to derive module and symbol names.

type_name = 'group'

Human-readable type name for documentation, like "CI system".

unknown_symbol = 'UNKNOWN'

The symbol name for the unknown instance of this type.

        classDiagram
  _Identifiable <|-- Group
    

Group a collection of traits. Also referred as families.

Definitions of ready-to-use groups.

This module contains all predefined Group instances and frozenset collections that organize traits into logical categories.