Platform detection#

OS families#

All platforms are grouped in sets of non-overlpaping families:

flowchart subgraph <code>click_extra.platforms.ALL_LINUX</code><br/><em>Any Linux</em> all_linux_linux(<code>linux</code><br/><em>Linux</em>) end subgraph <code>click_extra.platforms.ALL_WINDOWS</code><br/><em>Any Windows</em> all_windows_windows(<code>windows</code><br/><em>Windows</em>) end subgraph <code>click_extra.platforms.BSD</code><br/><em>Any BSD</em> bsd_freebsd(<code>freebsd</code><br/><em>FreeBSD</em>) bsd_macos(<code>macos</code><br/><em>macOS</em>) bsd_netbsd(<code>netbsd</code><br/><em>NetBSD</em>) bsd_openbsd(<code>openbsd</code><br/><em>OpenBSD</em>) bsd_sunos(<code>sunos</code><br/><em>SunOS</em>) end subgraph <code>click_extra.platforms.LINUX_LAYERS</code><br/><em>Any Linux compatibility layers</em> linux_layers_wsl1(<code>wsl1</code><br/><em>Windows Subsystem for Linux v1</em>) linux_layers_wsl2(<code>wsl2</code><br/><em>Windows Subsystem for Linux v2</em>) end subgraph <code>click_extra.platforms.OTHER_UNIX</code><br/><em>Any other Unix</em> other_unix_hurd(<code>hurd</code><br/><em>GNU/Hurd</em>) end subgraph <code>click_extra.platforms.SYSTEM_V</code><br/><em>Any Unix derived from AT&T System Five</em> system_v_aix(<code>aix</code><br/><em>AIX</em>) system_v_solaris(<code>solaris</code><br/><em>Solaris</em>) end subgraph <code>click_extra.platforms.UNIX_LAYERS</code><br/><em>Any Unix compatibility layers</em> unix_layers_cygwin(<code>cygwin</code><br/><em>Cygwin</em>) end

click_extra.platforms.NON_OVERLAPPING_GROUPS - Non-overlapping groups.#

Other groups#

Other groups are available for convenience, but these overlaps:

flowchart subgraph <code>click_extra.platforms.ALL_PLATFORMS</code><br/><em>Any platforms</em> all_platforms_aix(<code>aix</code><br/><em>AIX</em>) all_platforms_cygwin(<code>cygwin</code><br/><em>Cygwin</em>) all_platforms_freebsd(<code>freebsd</code><br/><em>FreeBSD</em>) all_platforms_hurd(<code>hurd</code><br/><em>GNU/Hurd</em>) all_platforms_linux(<code>linux</code><br/><em>Linux</em>) all_platforms_macos(<code>macos</code><br/><em>macOS</em>) all_platforms_netbsd(<code>netbsd</code><br/><em>NetBSD</em>) all_platforms_openbsd(<code>openbsd</code><br/><em>OpenBSD</em>) all_platforms_solaris(<code>solaris</code><br/><em>Solaris</em>) all_platforms_sunos(<code>sunos</code><br/><em>SunOS</em>) all_platforms_windows(<code>windows</code><br/><em>Windows</em>) all_platforms_wsl1(<code>wsl1</code><br/><em>Windows Subsystem for Linux v1</em>) all_platforms_wsl2(<code>wsl2</code><br/><em>Windows Subsystem for Linux v2</em>) end subgraph <code>click_extra.platforms.BSD_WITHOUT_MACOS</code><br/><em>Any BSD but macOS</em> bsd_without_macos_freebsd(<code>freebsd</code><br/><em>FreeBSD</em>) bsd_without_macos_netbsd(<code>netbsd</code><br/><em>NetBSD</em>) bsd_without_macos_openbsd(<code>openbsd</code><br/><em>OpenBSD</em>) bsd_without_macos_sunos(<code>sunos</code><br/><em>SunOS</em>) end subgraph <code>click_extra.platforms.UNIX</code><br/><em>Any Unix</em> unix_aix(<code>aix</code><br/><em>AIX</em>) unix_cygwin(<code>cygwin</code><br/><em>Cygwin</em>) unix_freebsd(<code>freebsd</code><br/><em>FreeBSD</em>) unix_hurd(<code>hurd</code><br/><em>GNU/Hurd</em>) unix_linux(<code>linux</code><br/><em>Linux</em>) unix_macos(<code>macos</code><br/><em>macOS</em>) unix_netbsd(<code>netbsd</code><br/><em>NetBSD</em>) unix_openbsd(<code>openbsd</code><br/><em>OpenBSD</em>) unix_solaris(<code>solaris</code><br/><em>Solaris</em>) unix_sunos(<code>sunos</code><br/><em>SunOS</em>) unix_wsl1(<code>wsl1</code><br/><em>Windows Subsystem for Linux v1</em>) unix_wsl2(<code>wsl2</code><br/><em>Windows Subsystem for Linux v2</em>) end subgraph <code>click_extra.platforms.UNIX_WITHOUT_MACOS</code><br/><em>Any Unix but macOS</em> unix_without_macos_aix(<code>aix</code><br/><em>AIX</em>) unix_without_macos_cygwin(<code>cygwin</code><br/><em>Cygwin</em>) unix_without_macos_freebsd(<code>freebsd</code><br/><em>FreeBSD</em>) unix_without_macos_hurd(<code>hurd</code><br/><em>GNU/Hurd</em>) unix_without_macos_linux(<code>linux</code><br/><em>Linux</em>) unix_without_macos_netbsd(<code>netbsd</code><br/><em>NetBSD</em>) unix_without_macos_openbsd(<code>openbsd</code><br/><em>OpenBSD</em>) unix_without_macos_solaris(<code>solaris</code><br/><em>Solaris</em>) unix_without_macos_sunos(<code>sunos</code><br/><em>SunOS</em>) unix_without_macos_wsl1(<code>wsl1</code><br/><em>Windows Subsystem for Linux v1</em>) unix_without_macos_wsl2(<code>wsl2</code><br/><em>Windows Subsystem for Linux v2</em>) end

click_extra.platforms.EXTRA_GROUPS - Overlapping groups, defined for convenience.#

Important

All the graphs above would be better off and user-friendly if merged together. Unfortunately Graphviz is not capable of producing Euler diagrams. Only non-overlapping clusters can be rendered.

There’s still a chance to have them supported by Mermaid so we can switch to that if the feature materialize.

click_extra.platforms API#

Helpers and utilities to identify platforms.

Everything here can be aggressively cached and frozen, as it’s only compute platform-dependent values.

See also

A nice alternative would be to use the excellent distro package, but it does not yet support detection of macOS and Windows.

click_extra.platforms.is_aix()[source]#

Return True only if current platform is of the AIX family.

Return type:

bool

click_extra.platforms.is_cygwin()[source]#

Return True only if current platform is of the Cygwin family.

Return type:

bool

click_extra.platforms.is_freebsd()[source]#

Return True only if current platform is of the FreeBSD family.

Return type:

bool

click_extra.platforms.is_hurd()[source]#

Return True only if current platform is of the GNU/Hurd family.

Return type:

bool

click_extra.platforms.is_linux()[source]#

Return True only if current platform is of the Linux family.

Excludes WSL1 and WSL2 from this check to avoid false positives.

Return type:

bool

click_extra.platforms.is_macos()[source]#

Return True only if current platform is of the macOS family.

Return type:

bool

click_extra.platforms.is_netbsd()[source]#

Return True only if current platform is of the NetBSD family.

Return type:

bool

click_extra.platforms.is_openbsd()[source]#

Return True only if current platform is of the OpenBSD family.

Return type:

bool

click_extra.platforms.is_solaris()[source]#

Return True only if current platform is of the Solaris family.

Return type:

bool

click_extra.platforms.is_sunos()[source]#

Return True only if current platform is of the SunOS family.

Return type:

bool

click_extra.platforms.is_windows()[source]#

Return True only if current platform is of the Windows family.

Return type:

bool

click_extra.platforms.is_wsl1()[source]#

Return True only if current platform is Windows Subsystem for Linux v1. :rtype: bool

Caution

The only difference between WSL1 and WSL2 is the case of the kernel release version:

  • WSL 1:

    $ uname -r
    4.4.0-22572-Microsoft
    
  • WSL 2:

    $ uname -r
    5.10.102.1-microsoft-standard-WSL2
    
click_extra.platforms.is_wsl2()[source]#

Return True only if current platform is Windows Subsystem for Linux v2.

Return type:

bool

class click_extra.platforms.Platform(id, name)[source]#

Bases: object

A platform can identify multiple distributions or OSes with the same characteristics.

It has a unique ID, a human-readable name, and boolean to flag current platform.

id: str#

Unique ID of the platform.

name: str#

User-friendly name of the platform.

current: bool#

True if current environment runs on this platform.

click_extra.platforms.AIX = Platform(id='aix', name='AIX', current=False)#

Identify distributions of the AIX family.

click_extra.platforms.CYGWIN = Platform(id='cygwin', name='Cygwin', current=False)#

Identify distributions of the Cygwin family.

click_extra.platforms.FREEBSD = Platform(id='freebsd', name='FreeBSD', current=False)#

Identify distributions of the FreeBSD family.

click_extra.platforms.HURD = Platform(id='hurd', name='GNU/Hurd', current=False)#

Identify distributions of the GNU/Hurd family.

click_extra.platforms.LINUX = Platform(id='linux', name='Linux', current=True)#

Identify distributions of the Linux family.

click_extra.platforms.MACOS = Platform(id='macos', name='macOS', current=False)#

Identify distributions of the macOS family.

click_extra.platforms.NETBSD = Platform(id='netbsd', name='NetBSD', current=False)#

Identify distributions of the NetBSD family.

click_extra.platforms.OPENBSD = Platform(id='openbsd', name='OpenBSD', current=False)#

Identify distributions of the OpenBSD family.

click_extra.platforms.SOLARIS = Platform(id='solaris', name='Solaris', current=False)#

Identify distributions of the Solaris family.

click_extra.platforms.SUNOS = Platform(id='sunos', name='SunOS', current=False)#

Identify distributions of the SunOS family.

click_extra.platforms.WINDOWS = Platform(id='windows', name='Windows', current=False)#

Identify distributions of the Windows family.

click_extra.platforms.WSL1 = Platform(id='wsl1', name='Windows Subsystem for Linux v1', current=False)#

Identify Windows Subsystem for Linux v1.

click_extra.platforms.WSL2 = Platform(id='wsl2', name='Windows Subsystem for Linux v2', current=False)#

Identify Windows Subsystem for Linux v2.

class click_extra.platforms.Group(id, name, platforms=<factory>, platform_ids=<factory>, icon=None)[source]#

Bases: object

A Group identify a collection of Platform.

Used to group platforms of the same family.

id: str#

Unique ID of the group.

name: str#

User-friendly description of a group.

platforms: tuple[Platform, ...]#

Sorted list of platforms that belong to this group.

platform_ids: frozenset[str]#

Set of platform IDs that belong to this group.

Used to test platform overlaps between groups.

icon: str | None = None#

Optional icon of the group.

isdisjoint(other)[source]#

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

Return type:

bool

fullyintersects(other)[source]#

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

We cannot just compare Groups with the == equality operator as the latter takes all attributes into account, as per dataclass default behavior.

Return type:

bool

issubset(other)[source]#
Return type:

bool

issuperset(other)[source]#
Return type:

bool

click_extra.platforms.ALL_PLATFORMS: Group = Group(id='all_platforms', name='Any platforms', platform_ids=frozenset({'linux', 'macos', 'wsl1', 'windows', 'openbsd', 'freebsd', 'hurd', 'solaris', 'sunos', 'netbsd', 'wsl2', 'aix', 'cygwin'}))#

All recognized platforms.

click_extra.platforms.ALL_WINDOWS = Group(id='all_windows', name='Any Windows', platform_ids=frozenset({'windows'}))#

All Windows operating systems.

click_extra.platforms.UNIX = Group(id='unix', name='Any Unix', platform_ids=frozenset({'linux', 'macos', 'wsl1', 'openbsd', 'freebsd', 'hurd', 'solaris', 'sunos', 'netbsd', 'wsl2', 'aix', 'cygwin'}))#

All Unix-like operating systems and compatibility layers.

click_extra.platforms.UNIX_WITHOUT_MACOS = Group(id='unix_without_macos', name='Any Unix but macOS', platform_ids=frozenset({'linux', 'wsl1', 'openbsd', 'freebsd', 'hurd', 'solaris', 'sunos', 'netbsd', 'wsl2', 'aix', 'cygwin'}))#

All Unix platforms, without macOS.

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

click_extra.platforms.BSD = Group(id='bsd', name='Any BSD', platform_ids=frozenset({'sunos', 'macos', 'openbsd', 'netbsd', 'freebsd'}))#

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

click_extra.platforms.BSD_WITHOUT_MACOS = Group(id='bsd_without_macos', name='Any BSD but macOS', platform_ids=frozenset({'openbsd', 'netbsd', 'freebsd', 'sunos'}))#

All BSD platforms, without macOS.

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

click_extra.platforms.ALL_LINUX = Group(id='all_linux', name='Any Linux', platform_ids=frozenset({'linux'}))#

All Unix platforms based on a Linux kernel.

Note

Are considered of this family (according Wikipedia):

  • Android

  • ChromeOS

  • any other distribution

click_extra.platforms.LINUX_LAYERS = Group(id='linux_layers', name='Any Linux compatibility layers', platform_ids=frozenset({'wsl1', 'wsl2'}))#

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

Note

Are considered of this family (according Wikipedia):

  • Windows Subsystem for Linux

click_extra.platforms.SYSTEM_V = Group(id='system_v', name='Any Unix derived from AT&T System Five', platform_ids=frozenset({'aix', 'solaris'}))#

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

click_extra.platforms.UNIX_LAYERS = Group(id='unix_layers', name='Any Unix compatibility layers', platform_ids=frozenset({'cygwin'}))#

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

click_extra.platforms.OTHER_UNIX = Group(id='other_unix', name='Any other Unix', platform_ids=frozenset({'hurd'}))#

All other Unix 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

click_extra.platforms.NON_OVERLAPPING_GROUPS: frozenset[click_extra.platforms.Group] = frozenset({Group(id='system_v', name='Any Unix derived from AT&T System Five', platform_ids=frozenset({'aix', 'solaris'})), Group(id='other_unix', name='Any other Unix', platform_ids=frozenset({'hurd'})), Group(id='unix_layers', name='Any Unix compatibility layers', platform_ids=frozenset({'cygwin'})), Group(id='all_windows', name='Any Windows', platform_ids=frozenset({'windows'})), Group(id='all_linux', name='Any Linux', platform_ids=frozenset({'linux'})), Group(id='linux_layers', name='Any Linux compatibility layers', platform_ids=frozenset({'wsl1', 'wsl2'})), Group(id='bsd', name='Any BSD', platform_ids=frozenset({'sunos', 'macos', 'openbsd', 'netbsd', 'freebsd'}))})#

Non-overlapping groups.

click_extra.platforms.EXTRA_GROUPS: frozenset[click_extra.platforms.Group] = frozenset({Group(id='unix', name='Any Unix', platform_ids=frozenset({'linux', 'macos', 'wsl1', 'openbsd', 'freebsd', 'hurd', 'solaris', 'sunos', 'netbsd', 'wsl2', 'aix', 'cygwin'})), Group(id='bsd_without_macos', name='Any BSD but macOS', platform_ids=frozenset({'openbsd', 'netbsd', 'freebsd', 'sunos'})), Group(id='all_platforms', name='Any platforms', platform_ids=frozenset({'linux', 'macos', 'wsl1', 'windows', 'openbsd', 'freebsd', 'hurd', 'solaris', 'sunos', 'netbsd', 'wsl2', 'aix', 'cygwin'})), Group(id='unix_without_macos', name='Any Unix but macOS', platform_ids=frozenset({'linux', 'wsl1', 'openbsd', 'freebsd', 'hurd', 'solaris', 'sunos', 'netbsd', 'wsl2', 'aix', 'cygwin'}))})#

Overlapping groups, defined for convenience.

click_extra.platforms.ALL_GROUPS: frozenset[click_extra.platforms.Group] = frozenset({Group(id='system_v', name='Any Unix derived from AT&T System Five', platform_ids=frozenset({'aix', 'solaris'})), Group(id='other_unix', name='Any other Unix', platform_ids=frozenset({'hurd'})), Group(id='bsd_without_macos', name='Any BSD but macOS', platform_ids=frozenset({'openbsd', 'netbsd', 'freebsd', 'sunos'})), Group(id='unix_layers', name='Any Unix compatibility layers', platform_ids=frozenset({'cygwin'})), Group(id='all_windows', name='Any Windows', platform_ids=frozenset({'windows'})), Group(id='unix_without_macos', name='Any Unix but macOS', platform_ids=frozenset({'linux', 'wsl1', 'openbsd', 'freebsd', 'hurd', 'solaris', 'sunos', 'netbsd', 'wsl2', 'aix', 'cygwin'})), Group(id='all_linux', name='Any Linux', platform_ids=frozenset({'linux'})), Group(id='unix', name='Any Unix', platform_ids=frozenset({'linux', 'macos', 'wsl1', 'openbsd', 'freebsd', 'hurd', 'solaris', 'sunos', 'netbsd', 'wsl2', 'aix', 'cygwin'})), Group(id='linux_layers', name='Any Linux compatibility layers', platform_ids=frozenset({'wsl1', 'wsl2'})), Group(id='all_platforms', name='Any platforms', platform_ids=frozenset({'linux', 'macos', 'wsl1', 'windows', 'openbsd', 'freebsd', 'hurd', 'solaris', 'sunos', 'netbsd', 'wsl2', 'aix', 'cygwin'})), Group(id='bsd', name='Any BSD', platform_ids=frozenset({'sunos', 'macos', 'openbsd', 'netbsd', 'freebsd'}))})#

All groups.

click_extra.platforms.ALL_OS_LABELS: frozenset[str] = frozenset({'AIX', 'Cygwin', 'FreeBSD', 'GNU/Hurd', 'Linux', 'NetBSD', 'OpenBSD', 'Solaris', 'SunOS', 'Windows', 'Windows Subsystem for Linux v1', 'Windows Subsystem for Linux v2', 'macOS'})#

Sets of all recognized labels.

click_extra.platforms.reduce(items)[source]#

Reduce a collection of Group and Platform to a minimal set.

Returns a deduplicated set of Group and Platform that covers the same exact platforms as the original input, but group as much platforms as possible, to reduce the number of items. :rtype: set[Group | Platform]

Hint

Maybe this could be solved with some Euler diagram algorithms, like those implemented in eule.

This is being discussed upstream at trouchet/eule#120.

click_extra.platforms.os_label(os_id)[source]#

Return platform label for user-friendly output.

Return type:

str | None

click_extra.platforms.current_os()[source]#

Return the current platform.

Return type:

Platform

click_extra.platforms.CURRENT_OS_LABEL: str = 'Linux'#

Constants about the current platform.