{"id":13800461,"url":"https://github.com/bojiang/typing_utils","last_synced_at":"2025-09-02T06:32:36.488Z","repository":{"id":42046019,"uuid":"314578864","full_name":"bojiang/typing_utils","owner":"bojiang","description":"Backport Python 3.8+ typing utils \u0026 add issubtype \u0026 more","archived":false,"fork":false,"pushed_at":"2022-11-09T04:50:26.000Z","size":34,"stargazers_count":12,"open_issues_count":2,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-12T04:39:46.787Z","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":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bojiang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-11-20T14:32:44.000Z","updated_at":"2024-06-04T08:37:13.000Z","dependencies_parsed_at":"2023-01-21T14:31:06.422Z","dependency_job_id":null,"html_url":"https://github.com/bojiang/typing_utils","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/bojiang/typing_utils","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bojiang%2Ftyping_utils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bojiang%2Ftyping_utils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bojiang%2Ftyping_utils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bojiang%2Ftyping_utils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bojiang","download_url":"https://codeload.github.com/bojiang/typing_utils/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bojiang%2Ftyping_utils/sbom","scorecard":{"id":247092,"data":{"date":"2025-08-11","repo":{"name":"github.com/bojiang/typing_utils","commit":"2e475058f3bd5bb84b393f49b1204c7084312acc"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.6,"checks":[{"name":"Code-Review","score":2,"reason":"Found 3/15 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/py36.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/bojiang/typing_utils/py36.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/py36.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/bojiang/typing_utils/py36.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/py37.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/bojiang/typing_utils/py37.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/py37.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/bojiang/typing_utils/py37.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/py38.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/bojiang/typing_utils/py38.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/py38.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/bojiang/typing_utils/py38.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/py39.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/bojiang/typing_utils/py39.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/py39.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/bojiang/typing_utils/py39.yml/main?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/py36.yml:29","Warn: pipCommand not pinned by hash: .github/workflows/py37.yml:29","Warn: pipCommand not pinned by hash: .github/workflows/py38.yml:29","Warn: pipCommand not pinned by hash: .github/workflows/py39.yml:29","Info:   0 out of   8 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/py36.yml:1","Warn: no topLevel permission defined: .github/workflows/py37.yml:1","Warn: no topLevel permission defined: .github/workflows/py38.yml:1","Warn: no topLevel permission defined: .github/workflows/py39.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 23 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T07:47:54.628Z","repository_id":42046019,"created_at":"2025-08-17T07:47:54.628Z","updated_at":"2025-08-17T07:47:54.628Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273244301,"owners_count":25070958,"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","status":"online","status_checked_at":"2025-09-02T02:00:09.530Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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-08-04T00:01:12.838Z","updated_at":"2025-09-02T06:32:36.218Z","avatar_url":"https://github.com/bojiang.png","language":"Python","readme":"# typing-utils\n\nBackport Python3.8+ typing utils \u0026amp; issubtype \u0026amp; more\n\n- [Install](#install)\n- [API](#api)\n    - [issubtype](#issubtype)\n    - [get_origin](#get_origin)\n    - [get_args](#get_args)\n    - [get_type_hints](#get_type_hints)\n\n\n\n[![Downloads](https://img.shields.io/badge/dynamic/json.svg?label=Downloads%2FWeek\u0026url=https%3A%2F%2Fpypistats.org%2Fapi%2Fpackages%2Ftyping_utils%2Frecent\u0026query=data.last_week\u0026colorB=blue\u0026suffix=%20)](https://pypistats.org/packages/typing_utils)  \n[![Python 3.6](https://github.com/bojiang/typing_utils/workflows/Python%203.6/badge.svg)](https://github.com/bojiang/typing_utils/actions/workflows/py36.yml)\n[![Python 3.7](https://github.com/bojiang/typing_utils/workflows/Python%203.7/badge.svg)](https://github.com/bojiang/typing_utils/actions/workflows/py37.yml)\n[![Python 3.8](https://github.com/bojiang/typing_utils/workflows/Python%203.8/badge.svg)](https://github.com/bojiang/typing_utils/actions/workflows/py38.yml)\n[![Python 3.9](https://github.com/bojiang/typing_utils/workflows/Python%203.9/badge.svg)](https://github.com/bojiang/typing_utils/actions/workflows/py39.yml)\n\n\n## Install\n\n``` bash\npip install typing_utils\n```\n\n\n## API\n\n- [issubtype](#issubtype)\n- [get_origin](#get_origin)\n- [get_args](#get_args)\n- [get_type_hints](#get_type_hints)\n\n\n### issubtype\n\nCheck that the left argument is a subtype of the right.\n\nFor unions, check if the type arguments of the left is a subset of the right.\nAlso works for nested types including ForwardRefs.\n\nExamples:\n\n```python\nfrom typing_utils import issubtype\n\nissubtype(typing.List, typing.Any) == True\nissubtype(list, list) == True\nissubtype(list, typing.List) == True\nissubtype(list, typing.Sequence) == True\nissubtype(typing.List[int], list) == True\nissubtype(typing.List[typing.List], list) == True\nissubtype(list, typing.List[int]) == False\nissubtype(list, typing.Union[typing.Tuple, typing.Set]) == False\nissubtype(typing.List[typing.List], typing.List[typing.Sequence]) == True\nJSON = typing.Union[\n    int, float, bool, str, None, typing.Sequence[\"JSON\"],\n    typing.Mapping[str, \"JSON\"]\n]\nissubtype(str, JSON, forward_refs={'JSON': JSON}) == True\nissubtype(typing.Dict[str, str], JSON, forward_refs={'JSON': JSON}) == True\nissubtype(typing.Dict[str, bytes], JSON, forward_refs={'JSON': JSON}) == False\n```\n\n\n### get_origin\n\nGet the unsubscripted version of a type.\n\nThis supports generic types, Callable, Tuple, Union, Literal, Final and ClassVar.\nReturn None for unsupported types.\n\nExamples:\n\n```python\nfrom typing_utils import get_origin\n\nget_origin(Literal[42]) is Literal\nget_origin(int) is None\nget_origin(ClassVar[int]) is ClassVar\nget_origin(Generic) is Generic\nget_origin(Generic[T]) is Generic\nget_origin(Union[T, int]) is Union\nget_origin(List[Tuple[T, T]][int]) == list\n```\n\n\n### get_args\n\nGet type arguments with all substitutions performed.\n\nFor unions, basic simplifications used by Union constructor are performed.\n\nExamples:\n\n```python\nfrom typing_utils import get_args\n\nget_args(Dict[str, int]) == (str, int)\nget_args(int) == ()\nget_args(Union[int, Union[T, int], str][int]) == (int, str)\nget_args(Union[int, Tuple[T, int]][str]) == (int, Tuple[str, int])\nget_args(Callable[[], T][int]) == ([], int)\n```\n\n\n### get_type_hints\n\nReturn type hints for an object.\n\n\nThis is often the same as obj.__annotations__, but it handles\nforward references encoded as string literals, and if necessary\nadds Optional[t] if a default value equal to None is set.\n\nThe argument may be a module, class, method, or function. The annotations\nare returned as a dictionary. For classes, annotations include also\ninherited members.\n\nTypeError is raised if the argument is not of a type that can contain\nannotations, and an empty dictionary is returned if no annotations are\npresent.\n\nBEWARE -- the behavior of globalns and localns is counterintuitive\n(unless you are familiar with how eval() and exec() work).  The\nsearch order is locals first, then globals.\n\n- If no dict arguments are passed, an attempt is made to use the\n  globals from obj (or the respective module's globals for classes),\n  and these are also used as the locals.  If the object does not appear\n  to have globals, an empty dictionary is used.\n\n- If one dict argument is passed, it is used for both globals and\n  locals.\n\n- If two dict arguments are passed, they specify globals and\n  locals, respectively.\n","funding_links":[],"categories":["Backports and improvements"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbojiang%2Ftyping_utils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbojiang%2Ftyping_utils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbojiang%2Ftyping_utils/lists"}