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
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 |
||
|---|---|---|---|---|
🧠 |
All AI coding agents |
⬥ |
||
🏛️ |
All architectures |
|||
📱 |
ARM architectures |
⬥ |
||
♺ |
All CI systems |
⬥ |
||
🔲 |
MIPS architectures |
⬥ |
||
⚙️ |
All platforms |
|||
🐚 |
All shells |
|||
☀️ |
SPARC architectures |
⬥ |
||
💻 |
All terminals |
|||
⁕ |
All architectures, platforms, shells, terminals, CI systems, and agents |
|||
🪟 |
All Windows |
⬥ |
||
³² |
32-bit architectures |
|||
⁶⁴ |
64-bit architectures |
|||
⬆️ |
Big-endian architectures |
|||
💲 |
Bourne-compatible shells |
⬥ |
||
Ⓑ |
All BSD |
⬥ |
||
🅱️ |
All BSD excluding macOS |
|||
🅲 |
C shells |
⬥ |
||
🎮 |
GPU-accelerated terminals |
⬥ |
||
🏢 |
IBM mainframe |
⬥ |
||
🐧 |
Linux distributions |
⬥ |
||
≚ |
Linux compatibility layers |
⬥ |
||
🐣 |
All Linux & compatibility layers |
|||
⬇️ |
Little-endian architectures |
|||
🐉 |
LoongArch |
⬥ |
||
⧉ |
Terminal multiplexers |
⬥ |
||
▦ |
Native terminal emulators |
⬥ |
||
🅟 |
Other POSIX-compliant platforms |
⬥ |
||
◇ |
Other shells |
⬥ |
||
⚡ |
PowerPC family |
⬥ |
||
Ⅴ |
RISC-V family |
⬥ |
||
𝐕 |
AT&T System Five |
⬥ |
||
⨷ |
All Unix |
|||
≛ |
Unix compatibility layers |
⬥ |
||
⨂ |
All Unix excluding macOS |
|||
❓ |
Unknown |
⬥ |
||
⬢ |
Web-based terminals |
⬥ |
||
🌐 |
WebAssembly |
⬥ |
||
⌨️ |
Windows shells |
⬥ |
||
𝘅 |
x86 family |
⬥ |
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_AGENTtrait.ID:
all_agentsName: All AI coding agents
Icon: 🧠
Canonical:
True⬥Detection function:
is_any_agent()Pytest decorators:
@skip_all_agents/@unless_any_agentMembers (8
Agent):CLAUDE_CODE,CLINE,CODEX,COPILOT_CLI,CRUSH,CURSOR,GEMINI_CLI,PI
- extra_platforms.ALL_ARCHITECTURES = Group(id='all_architectures', name='All architectures')¶
All recognized architectures.
Caution
This group does not contain the
UNKNOWN_ARCHITECTUREtrait.ID:
all_architecturesName: All architectures
Icon: 🏛️
Canonical:
FalseDetection function:
is_any_architecture()Pytest decorators:
@skip_all_architectures/@unless_any_architectureMembers (25
Architecture):AARCH64,ARM,ARMV5TEL,ARMV6L,ARMV7L,ARMV8L,I386,I586,I686,LOONGARCH64,MIPS,MIPS64,MIPS64EL,MIPSEL,PPC,PPC64,PPC64LE,RISCV32,RISCV64,S390X,SPARC,SPARC64,WASM32,WASM64,X86_64
- extra_platforms.ALL_ARM = Group(id='all_arm', name='ARM architectures')¶
All ARM-based architectures.
ID:
all_armName: ARM architectures
Icon: 📱
Canonical:
True⬥Detection function:
is_any_arm()Pytest decorators:
@skip_all_arm/@unless_any_armMembers (6
Architecture):AARCH64,ARM,ARMV5TEL,ARMV6L,ARMV7L,ARMV8L
- 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_CItrait.See also
ID:
all_ciName: All CI systems
Icon: ♺
Canonical:
True⬥Detection function:
is_any_ci()Pytest decorators:
@skip_all_ci/@unless_any_ciMembers (12
CI):AZURE_PIPELINES,BAMBOO,BUILDKITE,CIRCLE_CI,CIRRUS_CI,CODEBUILD,GITHUB_CI,GITLAB_CI,HERMETIC_BUILD,HEROKU_CI,TEAMCITY,TRAVIS_CI
- extra_platforms.ALL_MIPS = Group(id='all_mips', name='MIPS architectures')¶
All MIPS-based architectures.
ID:
all_mipsName: MIPS architectures
Icon: 🔲
Canonical:
True⬥Detection function:
is_any_mips()Pytest decorators:
@skip_all_mips/@unless_any_mipsMembers (4
Architecture):MIPS,MIPS64,MIPS64EL,MIPSEL
- extra_platforms.ALL_PLATFORMS = Group(id='all_platforms', name='All platforms')¶
All recognized platforms.
Caution
This group does not contain the
UNKNOWN_PLATFORMtrait.ID:
all_platformsName: All platforms
Icon: ⚙️
Canonical:
FalseDetection function:
is_any_platform()Pytest decorators:
@skip_all_platforms/@unless_any_platformMembers (69
Platform):AIX,ALMALINUX,ALPINE,ALTLINUX,AMZN,ANDROID,ARCH,ARTIX,BUILDROOT,CACHYOS,CENTOS,CHROMEOS,CLEARLINUX,CLOUDLINUX,CRUX,CYGWIN,DEBIAN,DRAGONFLY_BSD,ENDEAVOUROS,EXHERBO,FEDORA,FREEBSD,GENERIC_LINUX,GENTOO,GUIX,HAIKU,HURD,IBM_POWERKVM,ILLUMOS,KALI,KVMIBM,LINUXMINT,MACOS,MAGEIA,MANDRIVA,MANJARO,MIDNIGHTBSD,NETBSD,NIXOS,NOBARA,NUTYX,OPENBSD,OPENSUSE,OPENWRT,ORACLE,OS400,PARALLELS,PIDORA,PIKAOS,RASPBIAN,RHEL,ROCKY,SCIENTIFIC,SLACKWARE,SLES,SLITAZ,SOLARIS,SOLUS,SOURCEMAGE,SUNOS,TUXEDO,UBUNTU,ULTRAMARINE,VOID,WEBOS,WINDOWS,WSL1,WSL2,XENSERVER
- extra_platforms.ALL_SHELLS = Group(id='all_shells', name='All shells')¶
All recognized shells.
Caution
This group does not contain the
UNKNOWN_SHELLtrait.ID:
all_shellsName: All shells
Icon: 🐚
Canonical:
FalseDetection function:
is_any_shell()Pytest decorators:
@skip_all_shells/@unless_any_shellMembers (13
Shell):ASH,BASH,CMD,CSH,DASH,FISH,KSH,NUSHELL,POWERSHELL,SH,TCSH,XONSH,ZSH
- extra_platforms.ALL_SPARC = Group(id='all_sparc', name='SPARC architectures')¶
All SPARC-based architectures.
ID:
all_sparcName: SPARC architectures
Icon: ☀️
Canonical:
True⬥Detection function:
is_any_sparc()Pytest decorators:
@skip_all_sparc/@unless_any_sparcMembers (2
Architecture):SPARC,SPARC64
- extra_platforms.ALL_TERMINALS = Group(id='all_terminals', name='All terminals')¶
All recognized terminals.
Caution
This group does not contain the
UNKNOWN_TERMINALtrait.ID:
all_terminalsName: All terminals
Icon: 💻
Canonical:
FalseDetection function:
is_any_terminal()Pytest decorators:
@skip_all_terminals/@unless_any_terminalMembers (20
Terminal):ALACRITTY,APPLE_TERMINAL,CONTOUR,FOOT,GHOSTTY,GNOME_TERMINAL,GNU_SCREEN,HYPER,ITERM2,KITTY,KONSOLE,RIO,TABBY,TILIX,TMUX,VSCODE_TERMINAL,WEZTERM,WINDOWS_TERMINAL,XTERM,ZELLIJ
- 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.ID:
all_traitsName: All architectures, platforms, shells, terminals, CI systems, and agents
Icon: ⁕
Canonical:
FalseDetection function:
is_any_trait()Pytest decorators:
@skip_all_traits/@unless_any_traitMembers (9
Agent, 26Architecture, 13CI, 70Platform, 14Shell, 21Terminal):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,UNKNOWN_AGENT,UNKNOWN_ARCHITECTURE,UNKNOWN_CI,UNKNOWN_PLATFORM,UNKNOWN_SHELL,UNKNOWN_TERMINAL,VOID,VSCODE_TERMINAL,WASM32,WASM64,WEBOS,WEZTERM,WINDOWS,WINDOWS_TERMINAL,WSL1,WSL2,X86_64,XENSERVER,XONSH,XTERM,ZELLIJ,ZSH
- extra_platforms.ALL_WINDOWS = Group(id='all_windows', name='All Windows')¶
All Windows operating systems.
ID:
all_windowsName: All Windows
Icon: 🪟
Canonical:
True⬥Detection function:
is_any_windows()Pytest decorators:
@skip_all_windows/@unless_any_windows
- extra_platforms.ARCH_32_BIT = Group(id='arch_32_bit', name='32-bit architectures')¶
All 32-bit architectures.
ID:
arch_32_bitName: 32-bit architectures
Icon: ³²
Canonical:
FalseDetection function:
is_arch_32_bit()Pytest decorators:
@skip_arch_32_bit/@unless_arch_32_bitMembers (14
Architecture):ARM,ARMV5TEL,ARMV6L,ARMV7L,ARMV8L,I386,I586,I686,MIPS,MIPSEL,PPC,RISCV32,SPARC,WASM32
- extra_platforms.ARCH_64_BIT = Group(id='arch_64_bit', name='64-bit architectures')¶
All 64-bit architectures.
ID:
arch_64_bitName: 64-bit architectures
Icon: ⁶⁴
Canonical:
FalseDetection function:
is_arch_64_bit()Pytest decorators:
@skip_arch_64_bit/@unless_arch_64_bitMembers (11
Architecture):AARCH64,LOONGARCH64,MIPS64,MIPS64EL,PPC64,PPC64LE,RISCV64,S390X,SPARC64,WASM64,X86_64
- extra_platforms.BIG_ENDIAN = Group(id='big_endian', name='Big-endian architectures')¶
All big-endian architectures.
ID:
big_endianName: Big-endian architectures
Icon: ⬆️
Canonical:
FalseDetection function:
is_big_endian()Pytest decorators:
@skip_big_endian/@unless_big_endianMembers (7
Architecture):MIPS,MIPS64,PPC,PPC64,S390X,SPARC,SPARC64
- extra_platforms.BOURNE_SHELLS = Group(id='bourne_shells', name='Bourne-compatible shells')¶
All Bourne-compatible shells.
ID:
bourne_shellsName: Bourne-compatible shells
Icon: 💲
Canonical:
True⬥Detection function:
is_bourne_shells()Pytest decorators:
@skip_bourne_shells/@unless_bourne_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)NeXTSTEPDarwin(macOS,iOS,audioOS,iPadOS,tvOS,watchOS,bridgeOS)SunOSUltrix
ID:
bsdName: All BSD
Icon: Ⓑ
Canonical:
True⬥Detection function:
is_bsd()Pytest decorators:
@skip_bsd/@unless_bsdMembers (7
Platform):DRAGONFLY_BSD,FREEBSD,MACOS,MIDNIGHTBSD,NETBSD,OPENBSD,SUNOS
- 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.
ID:
bsd_without_macosName: All BSD excluding macOS
Icon: 🅱️
Canonical:
FalseDetection function:
is_bsd_not_macos()Pytest decorators:
@skip_bsd_not_macos/@unless_bsd_not_macosMembers (6
Platform):DRAGONFLY_BSD,FREEBSD,MIDNIGHTBSD,NETBSD,OPENBSD,SUNOS
- extra_platforms.C_SHELLS = Group(id='c_shells', name='C shells')¶
C shell family.
ID:
c_shellsName: C shells
Icon: 🅲
Canonical:
True⬥Detection function:
is_c_shells()Pytest decorators:
@skip_c_shells/@unless_c_shells
- extra_platforms.GPU_TERMINALS = Group(id='gpu_terminals', name='GPU-accelerated terminals')¶
GPU-accelerated terminal emulators.
ID:
gpu_terminalsName: GPU-accelerated terminals
Icon: 🎮
Canonical:
True⬥Detection function:
is_gpu_terminals()Pytest decorators:
@skip_gpu_terminals/@unless_gpu_terminalsMembers (7
Terminal):ALACRITTY,CONTOUR,FOOT,GHOSTTY,KITTY,RIO,WEZTERM
- extra_platforms.IBM_MAINFRAME = Group(id='ibm_mainframe', name='IBM mainframe')¶
IBM mainframe architectures.
ID:
ibm_mainframeName: IBM mainframe
Icon: 🏢
Canonical:
True⬥Detection function:
is_ibm_mainframe()Pytest decorators:
@skip_ibm_mainframe/@unless_ibm_mainframeMembers (1
Architecture):S390X
- extra_platforms.LINUX = Group(id='linux', name='Linux distributions')¶
All distributions based on a Linux kernel.
ID:
linuxName: Linux distributions
Icon: 🐧
Canonical:
True⬥Detection function:
is_linux()Pytest decorators:
@skip_linux/@unless_linuxMembers (52
Platform):ALMALINUX,ALPINE,ALTLINUX,AMZN,ANDROID,ARCH,ARTIX,BUILDROOT,CACHYOS,CENTOS,CHROMEOS,CLEARLINUX,CLOUDLINUX,CRUX,DEBIAN,ENDEAVOUROS,EXHERBO,FEDORA,GENERIC_LINUX,GENTOO,GUIX,IBM_POWERKVM,KALI,KVMIBM,LINUXMINT,MAGEIA,MANDRIVA,MANJARO,NIXOS,NOBARA,NUTYX,OPENSUSE,OPENWRT,ORACLE,PARALLELS,PIDORA,PIKAOS,RASPBIAN,RHEL,ROCKY,SCIENTIFIC,SLACKWARE,SLES,SLITAZ,SOLUS,SOURCEMAGE,TUXEDO,UBUNTU,ULTRAMARINE,VOID,WEBOS,XENSERVER
- extra_platforms.LINUX_LAYERS = Group(id='linux_layers', name='Linux compatibility layers')¶
Interfaces that allows Linux binaries to run on a different host system.
ID:
linux_layersName: Linux compatibility layers
Icon: ≚
Canonical:
True⬥Detection function:
is_linux_layers()Pytest decorators:
@skip_linux_layers/@unless_linux_layers
- extra_platforms.LINUX_LIKE = Group(id='linux_like', name='All Linux & compatibility layers')¶
Sum of all Linux distributions and Linux compatibility layers.
ID:
linux_likeName: All Linux & compatibility layers
Icon: 🐣
Canonical:
FalseDetection function:
is_linux_like()Pytest decorators:
@skip_linux_like/@unless_linux_likeMembers (54
Platform):ALMALINUX,ALPINE,ALTLINUX,AMZN,ANDROID,ARCH,ARTIX,BUILDROOT,CACHYOS,CENTOS,CHROMEOS,CLEARLINUX,CLOUDLINUX,CRUX,DEBIAN,ENDEAVOUROS,EXHERBO,FEDORA,GENERIC_LINUX,GENTOO,GUIX,IBM_POWERKVM,KALI,KVMIBM,LINUXMINT,MAGEIA,MANDRIVA,MANJARO,NIXOS,NOBARA,NUTYX,OPENSUSE,OPENWRT,ORACLE,PARALLELS,PIDORA,PIKAOS,RASPBIAN,RHEL,ROCKY,SCIENTIFIC,SLACKWARE,SLES,SLITAZ,SOLUS,SOURCEMAGE,TUXEDO,UBUNTU,ULTRAMARINE,VOID,WEBOS,WSL1,WSL2,XENSERVER
- extra_platforms.LITTLE_ENDIAN = Group(id='little_endian', name='Little-endian architectures')¶
All little-endian architectures.
ID:
little_endianName: Little-endian architectures
Icon: ⬇️
Canonical:
FalseDetection function:
is_little_endian()Pytest decorators:
@skip_little_endian/@unless_little_endianMembers (18
Architecture):AARCH64,ARM,ARMV5TEL,ARMV6L,ARMV7L,ARMV8L,I386,I586,I686,LOONGARCH64,MIPS64EL,MIPSEL,PPC64LE,RISCV32,RISCV64,WASM32,WASM64,X86_64
- extra_platforms.LOONGARCH = Group(id='loongarch', name='LoongArch')¶
LoongArch architecture.
ID:
loongarchName: LoongArch
Icon: 🐉
Canonical:
True⬥Detection function:
is_loongarch()Pytest decorators:
@skip_loongarch/@unless_loongarchMembers (1
Architecture):LOONGARCH64
- extra_platforms.MULTIPLEXERS = Group(id='multiplexers', name='Terminal multiplexers')¶
Terminal multiplexers that can host other terminals.
ID:
multiplexersName: Terminal multiplexers
Icon: ⧉
Canonical:
True⬥Detection function:
is_multiplexers()Pytest decorators:
@skip_multiplexers/@unless_multiplexersMembers (3
Terminal):GNU_SCREEN,TMUX,ZELLIJ
- extra_platforms.NATIVE_TERMINALS = Group(id='native_terminals', name='Native terminal emulators')¶
Platform-native terminal emulators built with traditional GUI toolkits.
ID:
native_terminalsName: Native terminal emulators
Icon: ▦
Canonical:
True⬥Detection function:
is_native_terminals()Pytest decorators:
@skip_native_terminals/@unless_native_terminalsMembers (7
Terminal):APPLE_TERMINAL,GNOME_TERMINAL,ITERM2,KONSOLE,TILIX,WINDOWS_TERMINAL,XTERM
- 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):
CoherentGNU/HurdHarmonyOSLiteOSLynxOSMinixMOSOSF/1QNXBlackBerry 10Research UnixSerenityOS
ID:
other_posixName: Other POSIX-compliant platforms
Icon: 🅟
Canonical:
True⬥Detection function:
is_other_posix()Pytest decorators:
@skip_other_posix/@unless_other_posix
- extra_platforms.OTHER_SHELLS = Group(id='other_shells', name='Other shells')¶
Other non-traditional shells.
ID:
other_shellsName: Other shells
Icon: ◇
Canonical:
True⬥Detection function:
is_other_shells()Pytest decorators:
@skip_other_shells/@unless_other_shells
- extra_platforms.POWERPC = Group(id='powerpc', name='PowerPC family')¶
All PowerPC-based architectures.
ID:
powerpcName: PowerPC family
Icon: ⚡
Canonical:
True⬥Detection function:
is_powerpc()Pytest decorators:
@skip_powerpc/@unless_powerpcMembers (3
Architecture):PPC,PPC64,PPC64LE
- extra_platforms.RISCV = Group(id='riscv', name='RISC-V family')¶
All RISC-V-based architectures.
ID:
riscvName: RISC-V family
Icon: Ⅴ
Canonical:
True⬥Detection function:
is_riscv()Pytest decorators:
@skip_riscv/@unless_riscvMembers (2
Architecture):RISCV32,RISCV64
- 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/UXAIXHP-UXIRIXOpenServerSolarisOpenSolarisIllumosTru64UNIXUnixWare
ID:
system_vName: AT&T System Five
Icon: 𝐕
Canonical:
True⬥Detection function:
is_system_v()Pytest decorators:
@skip_system_v/@unless_system_v
- extra_platforms.UNIX = Group(id='unix', name='All Unix')¶
All Unix-like operating systems and compatibility layers.
ID:
unixName: All Unix
Icon: ⨷
Canonical:
FalseDetection function:
is_unix()Pytest decorators:
@skip_unix/@unless_unixMembers (68
Platform):AIX,ALMALINUX,ALPINE,ALTLINUX,AMZN,ANDROID,ARCH,ARTIX,BUILDROOT,CACHYOS,CENTOS,CHROMEOS,CLEARLINUX,CLOUDLINUX,CRUX,CYGWIN,DEBIAN,DRAGONFLY_BSD,ENDEAVOUROS,EXHERBO,FEDORA,FREEBSD,GENERIC_LINUX,GENTOO,GUIX,HAIKU,HURD,IBM_POWERKVM,ILLUMOS,KALI,KVMIBM,LINUXMINT,MACOS,MAGEIA,MANDRIVA,MANJARO,MIDNIGHTBSD,NETBSD,NIXOS,NOBARA,NUTYX,OPENBSD,OPENSUSE,OPENWRT,ORACLE,OS400,PARALLELS,PIDORA,PIKAOS,RASPBIAN,RHEL,ROCKY,SCIENTIFIC,SLACKWARE,SLES,SLITAZ,SOLARIS,SOLUS,SOURCEMAGE,SUNOS,TUXEDO,UBUNTU,ULTRAMARINE,VOID,WEBOS,WSL1,WSL2,XENSERVER
- 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):
CygwinDarlingEuniceGNVInterixMachTenMicrosoft POSIX subsystemMKS ToolkitPASEP.I.P.S.PWS/VSE-AFUNIX System ServicesUserLAnd TechnologiesWindows Services for UNIX
ID:
unix_layersName: Unix compatibility layers
Icon: ≛
Canonical:
True⬥Detection function:
is_unix_layers()Pytest decorators:
@skip_unix_layers/@unless_unix_layers
- 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.
ID:
unix_without_macosName: All Unix excluding macOS
Icon: ⨂
Canonical:
FalseDetection function:
is_unix_not_macos()Pytest decorators:
@skip_unix_not_macos/@unless_unix_not_macosMembers (67
Platform):AIX,ALMALINUX,ALPINE,ALTLINUX,AMZN,ANDROID,ARCH,ARTIX,BUILDROOT,CACHYOS,CENTOS,CHROMEOS,CLEARLINUX,CLOUDLINUX,CRUX,CYGWIN,DEBIAN,DRAGONFLY_BSD,ENDEAVOUROS,EXHERBO,FEDORA,FREEBSD,GENERIC_LINUX,GENTOO,GUIX,HAIKU,HURD,IBM_POWERKVM,ILLUMOS,KALI,KVMIBM,LINUXMINT,MAGEIA,MANDRIVA,MANJARO,MIDNIGHTBSD,NETBSD,NIXOS,NOBARA,NUTYX,OPENBSD,OPENSUSE,OPENWRT,ORACLE,OS400,PARALLELS,PIDORA,PIKAOS,RASPBIAN,RHEL,ROCKY,SCIENTIFIC,SLACKWARE,SLES,SLITAZ,SOLARIS,SOLUS,SOURCEMAGE,SUNOS,TUXEDO,UBUNTU,ULTRAMARINE,VOID,WEBOS,WSL1,WSL2,XENSERVER
- extra_platforms.UNKNOWN = Group(id='unknown', name='Unknown')¶
Unknown or unrecognized traits.
ID:
unknownName: Unknown
Icon: ❓
Canonical:
True⬥Detection function:
is_unknown()Pytest decorators:
@skip_unknown/@unless_unknownMembers (1
Agent, 1Architecture, 1CI, 1Platform, 1Shell, 1Terminal):UNKNOWN_AGENT,UNKNOWN_ARCHITECTURE,UNKNOWN_CI,UNKNOWN_PLATFORM,UNKNOWN_SHELL,UNKNOWN_TERMINAL
- extra_platforms.WEB_TERMINALS = Group(id='web_terminals', name='Web-based terminals')¶
Terminal emulators built on web technologies (Electron, xterm.js).
ID:
web_terminalsName: Web-based terminals
Icon: ⬢
Canonical:
True⬥Detection function:
is_web_terminals()Pytest decorators:
@skip_web_terminals/@unless_web_terminalsMembers (3
Terminal):HYPER,TABBY,VSCODE_TERMINAL
- extra_platforms.WEBASSEMBLY = Group(id='webassembly', name='WebAssembly')¶
WebAssembly architectures.
ID:
webassemblyName: WebAssembly
Icon: 🌐
Canonical:
True⬥Detection function:
is_webassembly()Pytest decorators:
@skip_webassembly/@unless_webassemblyMembers (2
Architecture):WASM32,WASM64
- extra_platforms.WINDOWS_SHELLS = Group(id='windows_shells', name='Windows shells')¶
Windows-native shells.
ID:
windows_shellsName: Windows shells
Icon: ⌨️
Canonical:
True⬥Detection function:
is_windows_shells()Pytest decorators:
@skip_windows_shells/@unless_windows_shellsMembers (2
Shell):CMD,POWERSHELL
- extra_platforms.X86 = Group(id='x86', name='x86 family')¶
All x86-based architectures (Intel-compatible).
ID:
x86Name: x86 family
Icon: 𝘅
Canonical:
True⬥Detection function:
is_x86()Pytest decorators:
@skip_x86/@unless_x86Members (4
Architecture):I386,I586,I686,X86_64
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_GROUPSandALL_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_GROUPSandALL_PLATFORM_GROUPS.
- extra_platforms.group_data.ALL_PLATFORM_GROUPS: frozenset[Group]¶
All groups whose members are
Platform.
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
frozensetof all recognized group IDs.Attention
This collection does not contain the
UNKNOWNgroup.
- 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
frozensetof all recognized traits and group IDs.Attention
This collection does not contain all the
UNKNOWN_*traits and theUNKNOWNgroup.
- 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
frozensetof 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.othercan be an arbitrarily nestedIterableofGroup,Trait, or their IDs.Nonevalues and empty iterables are silently ignored.Caution
Can return duplicates.
- extra_platforms.traits_from_ids(*trait_and_group_ids)[source]¶
Returns a deduplicated
tupleof traits matching the provided IDs.IDs are case-insensitive, and can refer to any traits or groups. Matching groups will be expanded to the
Traitinstances 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.
- extra_platforms.groups_from_ids(*group_ids)[source]¶
Returns a deduplicated
tupleof groups matching the provided IDs.IDs are case-insensitive.
Order of the returned
Groupinstances 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.
- extra_platforms.reduce(items, target_pool=None)[source]¶
Reduce a collection of traits to a minimal set.
Returns a deduplicated set of
GroupandTraitthat 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_poolare 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.
Group implementation¶
- class extra_platforms.Group(id, name, icon='❓', members=tuple())[source]¶
Bases:
_IdentifiableA
Groupnames a collection of traits.Its members are
Traitinstances.In addition to the common fields inherited from
_Identifiable, each group provides:members: An iterable ofTraitinstances that belong to this group.member_ids: Afrozensetof member IDs for quick lookup.canonical: Aboolindicating if the group is canonical (non-overlapping).various
set-like operations (union, intersection, difference, etc.).
Its unknown symbol is
UNKNOWN, instead of the derivedUNKNOWN_GROUP.- members: Iterable[Trait]¶
Traits in this group.
Normalized to
MappingProxyTypeat 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,
_LazyDocstringgenerates it on the first read of__doc__, once every module is imported.- Return type:
- property _members: MappingProxyType[str, Trait]¶
Typed access to members as
MappingProxyType.Warning
The
membersfield is typed asIterableto accept any iterable at construction time. After__post_init__, it is always aMappingProxyType, which this property tells the type checker.
- property _any_stem: str[source]¶
The ID, or
any_<type>for a group namedall_*.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_architecturesgivesany_architecture.
- property detection_func_id: str[source]¶
ID of the detection function for this group.
Named
is_<id>(),is_any_<type>()for a group namedall_*, and with_not_in place of_without_for more natural names, likeis_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 namedall_*, and with_not_in place of_without_.
- property member_ids: frozenset[str][source]¶
A
frozensetof 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.
- property canonical: bool[source]¶
Return
Trueif 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.
- __len__()[source]¶
Return the number of members in the group.
An empty group is falsy, like an empty
set.- Return type:
- __contains__(item)[source]¶
Test if a
Traitor 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:
- isdisjoint(other)[source]¶
Return
Trueif the group has no members in common withother.Groups are disjoint if and only if their intersection is an empty
set.othercan be an arbitrarily nestedIterableofGroupandTrait.- Return type:
- fullyintersects(other)[source]¶
Return
Trueif the group has all members in common withother.This is the member-level equality test: the equivalent of
==between plainsetobjects.Note
The name follows the
issubset()/issuperset()/isdisjoint()naming style of nativesetmethods. Python sets express this operation with the==operator, whichGroupreserves for full identity comparison (ID, name, icon, and members).- Return type:
- __lt__(other)[source]¶
Test whether every member in the group is in other, but not all.
- Return type:
- __gt__(other)[source]¶
Test whether every member in other is in the group, but not all.
- Return type:
- union(*others)[source]¶
Return a new
Groupwith members of all groups.Caution
The new
Groupinherits the metadata of the first one. All other groups’ metadata is ignored.- Return type:
- __or__(*others)¶
Return a new
Groupwith members of all groups.Caution
The new
Groupinherits the metadata of the first one. All other groups’ metadata is ignored.- Return type:
- intersection(*others)[source]¶
Return a new
Groupwith the shared members.A member is kept when the group and all others contain it.
Caution
The new
Groupinherits the metadata of the first one. All other groups’ metadata is ignored.- Return type:
- __and__(*others)¶
Return a new
Groupwith the shared members.A member is kept when the group and all others contain it.
Caution
The new
Groupinherits the metadata of the first one. All other groups’ metadata is ignored.- Return type:
- difference(*others)[source]¶
Return a new
Groupwithout the others’ members.A member is kept when the group contains it and no other does.
Caution
The new
Groupinherits the metadata of the first one. All other groups’ metadata is ignored.- Return type:
- __sub__(*others)¶
Return a new
Groupwithout the others’ members.A member is kept when the group contains it and no other does.
Caution
The new
Groupinherits the metadata of the first one. All other groups’ metadata is ignored.- Return type:
- symmetric_difference(other)[source]¶
Return a new
Groupwith unshared members.A member is kept when either the group or other contains it, but not both.
Caution
The new
Groupinherits the metadata of the first one. All other groups’ metadata is ignored.- Return type:
- __xor__(other)¶
Return a new
Groupwith unshared members.A member is kept when either the group or other contains it, but not both.
Caution
The new
Groupinherits the metadata of the first one. All other groups’ metadata is ignored.- Return type:
- 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:
- add(member)[source]¶
Return a new
Groupwith the specified trait added.If the trait is already in the group, returns a copy unchanged.
- discard(member)[source]¶
Return a new
Groupwithout the trait, if present.Unlike
remove(), this does not raise an error if the trait is not found.
- pop(member_id=None)[source]¶
Remove and return a trait from the group.
- __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.