{"id":20603532,"url":"https://github.com/galacticdynamics/optional_dependencies","last_synced_at":"2025-04-15T02:01:07.066Z","repository":{"id":256246056,"uuid":"813720980","full_name":"GalacticDynamics/optional_dependencies","owner":"GalacticDynamics","description":"Construct Checks for Optional Dependencies","archived":false,"fork":false,"pushed_at":"2025-04-07T19:51:15.000Z","size":50,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-07T20:41:09.803Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GalacticDynamics.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-11T15:55:04.000Z","updated_at":"2025-03-01T18:18:34.000Z","dependencies_parsed_at":"2025-01-02T03:19:26.524Z","dependency_job_id":"e748c040-5ce3-4b17-8ad3-12ae4d0b3669","html_url":"https://github.com/GalacticDynamics/optional_dependencies","commit_stats":null,"previous_names":["galacticdynamics/optional_deps"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GalacticDynamics%2Foptional_dependencies","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GalacticDynamics%2Foptional_dependencies/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GalacticDynamics%2Foptional_dependencies/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GalacticDynamics%2Foptional_dependencies/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GalacticDynamics","download_url":"https://codeload.github.com/GalacticDynamics/optional_dependencies/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248991546,"owners_count":21194894,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-16T09:17:42.312Z","updated_at":"2025-04-15T02:01:07.016Z","avatar_url":"https://github.com/GalacticDynamics.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align='center'\u003e optional_dependencies \u003c/h1\u003e\n\u003ch3 align=\"center\"\u003eConstruct Checks for Optional Dependencies\u003c/h3\u003e\n\n## Installation\n\n[![PyPI version][pypi-version]][pypi-link]\n[![PyPI platforms][pypi-platforms]][pypi-link]\n\n\u003c!-- [![Conda-Forge][conda-badge]][conda-link] --\u003e\n\n```bash\npip install optional_dependencies\n```\n\n## Documentation\n\n### High-Level API\n\nThis package allows for easy construction of checks for optional dependencies.\nAs every Python project can have its own unique set of optional dependencies,\n`optional_dependencies` provides the [`enum.Enum`][Enum-link] base class\n`OptionalDependencyEnum` for enumerating the optional dependencies.\n\nA constructed `OptionalDependencyEnum` [`enum.Enum`][Enum-link] has members that\nare the package names with values that are either a\n[`packaging.Version`][Version-link] or a `NOT_INSTALLED` sentinel value.\n\nAs an example:\n\n```python\n# Note that `auto` is a convenience re-export of enum.auto\nfrom optional_dependencies import OptionalDependencyEnum, auto\n\n\nclass OptDeps(OptionalDependencyEnum):\n    PACKAGING = auto()\n    THIS_IS_NOT_INSTALLED = auto()\n\n\nOptDeps.PACKAGING\n# \u003cOptDeps.PACKAGING: \u003cVersion('...')\u003e\u003e\n\nOptDeps.PACKAGING.installed\n# True\n\nOptDeps.PACKAGING.version\n# \u003cVersion('...')\u003e\n\nOptDeps.THIS_IS_NOT_INSTALLED\n# \u003cOptDeps.THIS_IS_NOT_A_PACKAGE: \u003cInstalledState.NOT_INSTALLED: False\u003e\u003e\n```\n\n`enum.auto` on a `OptionalDependencyEnum` passes version parsing to\n[`packaging.utils.canonicalize_name`](https://packaging.pypa.io/en/stable/utils.html#packaging.utils.canonicalize_name)\nthen\n[`importlib.metadata.version`](https://docs.python.org/3/library/importlib.metadata.html)\nthen [`packaging.version.parse`][Version-link]. If the package cannot be found\nthen it is considered `InstalledState.NOT_INSTALLED`\n\n`InstalledState.NOT_INSTALLED` is an [`enum.Enum`][Enum-link] member that has a\ntruthy value of `False`. This can be useful for boolean checks, as\n[`packaging.Version`][Version-link] always has a truthy value of `True`.\n\n```python\nif not OptDeps.THIS_IS_NOT_INSTALLED:\n    print(\"NOT_INSTALLED has a truthy value of False\")\n# NOT_INSTALLED has a truthy value of False\n\nif OptDeps.PACKAGING:  # truthy value of `True`\n    print(OptDeps.PACKAGING)\n# OptDeps.PACKAGING\n```\n\n### Low-Level API\n\nSometimes the high-level API is insufficient to determine whether an optional\ndependency is present. For example, this can sometimes happen with compiled\npackages, where the package appears to be installed, but something is wrong. In\nthese cases you can customize the enum members using the low-level API.\n\nThe low-level functions are:\n\n- `optional_dependencies.utils.is_installed(pkg_name: str, /) -\u003e bool`: a\n  regularized form of\n  [`importlib.util.find_spec`](https://docs.python.org/3/library/importlib.html#importlib.util.find_spec).\n\n- `optional_dependencies.utils.get_version(pkg_name: str, /) -\u003e Version | Literal[InstalledState.NOT_INSTALLED]`:\n  for getting the [`packaging.Version`][Version-link] of a package if it is\n  installed, or returning `NOT_INSTALLED` otherwise.\n\n- `optional_dependencies.utils.chain_checks(version: Version, /, *checks: bool)`:\n  for chaining checks together and ensuring the returned value is still a\n  [`packaging.Version`][Version-link] or `NOT_INSTALLED`.\n\nAs a pseudo-code example of a package with c-compiled code that :\n\n```python\nfrom optional_dependencies.utils import is_installed, get_version, chain_checks\n\n# A subpackage needs to be checked.\nchain_checks(get_version(\"package1\"), is_installed(\"package1.subpackage\"))\n# \u003cVersion('...')\u003e\n\n# This package is not installed correctly\nchain_checks(get_version(\"package2\"), is_installed(\"package2.subpackage\"))\n# \u003cInstalledState.NOT_INSTALLED: False\u003e\n```\n\nThe low-level API can be used with `OptionalDependencyEnum`\n\n```python\nclass OptDeps(OptionalDependencyEnum):\n    PACKAGING = auto()\n    THIS_IS_NOT_INSTALLED = chain_checks(\n        get_version(\"package2\"), is_installed(\"package2.subpackage\")\n    )\n```\n\n## Citation\n\n[![DOI][zenodo-badge]][zenodo-link]\n\nIf you found this library to be useful and want to support the development and\nmaintenance of lower-level code libraries for the scientific community, please\nconsider citing this work.\n\n## Development\n\n[![codecov][codecov-badge]][codecov-link]\n[![Actions Status][actions-badge]][actions-link]\n\nWe welcome contributions!\n\n\u003c!-- prettier-ignore-start --\u003e\n\n[Enum-link]: https://docs.python.org/3/library/enum.html\n[Version-link]: https://packaging.pypa.io/en/stable/version.html#packaging.version.Version\n\n[actions-badge]:            https://github.com/GalacticDynamics/optional_dependencies/workflows/CI/badge.svg\n[actions-link]:             https://github.com/GalacticDynamics/optional_dependencies/actions\n[codecov-badge]:            https://codecov.io/gh/GalacticDynamics/optional_dependencies/graph/badge.svg\n[codecov-link]:             https://codecov.io/gh/GalacticDynamics/optional_dependencies\n[pypi-link]:                https://pypi.org/project/optional_dependencies/\n[pypi-platforms]:           https://img.shields.io/pypi/pyversions/optional_dependencies\n[pypi-version]:             https://img.shields.io/pypi/v/optional_dependencies\n[zenodo-badge]:             https://zenodo.org/badge/DOI/10.5281/zenodo.13738124.svg\n[zenodo-link]:              https://zenodo.org/doi/10.5281/zenodo.13738123\n\n\u003c!-- prettier-ignore-end --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgalacticdynamics%2Foptional_dependencies","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgalacticdynamics%2Foptional_dependencies","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgalacticdynamics%2Foptional_dependencies/lists"}