{"id":37067911,"url":"https://github.com/n2cholas/shapecheck","last_synced_at":"2026-01-14T07:58:57.234Z","repository":{"id":57466605,"uuid":"324430796","full_name":"n2cholas/shapecheck","owner":"n2cholas","description":"Framework-agnostic library for checking array/tensor shapes at runtime.","archived":false,"fork":false,"pushed_at":"2021-05-04T22:46:45.000Z","size":149,"stargazers_count":46,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-27T20:08:32.350Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://pypi.org/project/shapecheck/","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/n2cholas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-25T20:45:48.000Z","updated_at":"2025-03-22T18:57:35.000Z","dependencies_parsed_at":"2022-09-19T08:41:33.688Z","dependency_job_id":null,"html_url":"https://github.com/n2cholas/shapecheck","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/n2cholas/shapecheck","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n2cholas%2Fshapecheck","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n2cholas%2Fshapecheck/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n2cholas%2Fshapecheck/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n2cholas%2Fshapecheck/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/n2cholas","download_url":"https://codeload.github.com/n2cholas/shapecheck/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n2cholas%2Fshapecheck/sbom","scorecard":{"id":672059,"data":{"date":"2025-08-11","repo":{"name":"github.com/n2cholas/shapecheck","commit":"9a19fe5d0783615f7bf7baaf0b19469d17626ffd"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.7,"checks":[{"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":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","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":"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":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"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":"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/format-code.yml:1","Warn: no topLevel permission defined: .github/workflows/python-package.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":"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/format-code.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/n2cholas/shapecheck/format-code.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/format-code.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/n2cholas/shapecheck/format-code.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-package.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/n2cholas/shapecheck/python-package.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-package.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/n2cholas/shapecheck/python-package.yml/main?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/format-code.yml:26","Warn: pipCommand not pinned by hash: .github/workflows/python-package.yml:30","Warn: pipCommand not pinned by hash: .github/workflows/python-package.yml:31","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 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":"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: 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":"Vulnerabilities","score":2,"reason":"8 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2022-238 / GHSA-h3qr-fjhm-jphw","Warn: Project is vulnerable to: PYSEC-2018-34 / GHSA-2fc2-6r4j-p65h","Warn: Project is vulnerable to: PYSEC-2021-856 / GHSA-5545-2q6w-2gh6","Warn: Project is vulnerable to: PYSEC-2019-108 / GHSA-9fq2-x9r6-wfmf","Warn: Project is vulnerable to: PYSEC-2018-33 / GHSA-cw6w-4rcx-xphc","Warn: Project is vulnerable to: PYSEC-2021-857 / GHSA-f7c7-j99h-c22f","Warn: Project is vulnerable to: GHSA-fpfv-jqm9-f5jm","Warn: Project is vulnerable to: PYSEC-2017-1 / GHSA-frgw-fgh6-9g52"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-21T20:27:18.002Z","repository_id":57466605,"created_at":"2025-08-21T20:27:18.002Z","updated_at":"2025-08-21T20:27:18.002Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28413527,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T05:26:33.345Z","status":"ssl_error","status_checked_at":"2026-01-14T05:21:57.251Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":"2026-01-14T07:58:56.681Z","updated_at":"2026-01-14T07:58:57.226Z","avatar_url":"https://github.com/n2cholas.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# ShapeCheck\n\n![Build \u0026 Tests](https://github.com/n2cholas/shapecheck/workflows/Build%20and%20Tests/badge.svg)\n[![codecov](https://codecov.io/gh/n2cholas/shapecheck/branch/main/graph/badge.svg?token=KAW5F029PM)](https://codecov.io/gh/n2cholas/shapecheck)\n\nFramework-agnostic library for checking array/tensor shapes at runtime.\n\nFinding the root of shape mismatches can be troublesome, especially with\nbroadcasting rules and mutable arrays. Comments documenting shapes can easily\nbecome out of date as code evolves. This library aims to solve both of those\nproblems by ensuring function input/output shape expectations are met. The\nconcise syntax for expressing shapes serves to document code as well, so new\nusers can quickly understand what's going on.\n\nThis library has minimal overhead, and can be easily disabled globally after\nprototyping if desired. With frameworks like JAX or TensorFlow, \"runtime\" is\nactually \"compile\" or \"trace\" time, so you don't pay any cost during execution.\nFor frameworks like PyTorch, asynchronous execution will hide the cost of shape\nchecking. You only pay a small overhead with synchronous, eager frameworks like\nnumpy.\n\nThis library was inspired by many other tools, including\n[nptyping](https://github.com/ramonhagenaars/nptyping),\n[einops](https://github.com/arogozhnikov/einops),\n[shapecheck](https://github.com/rosshemsley/shapecheck), [torch named\ntensors](https://pytorch.org/docs/stable/named_tensor.html),\n[tensorcheck](https://github.com/bodin-e/tensorcheck).\n\n## Install Library\n\nFrom PyPI:\n\n```bash\npip install --upgrade shapecheck\n```\n\nTo install the latest version:\n\n```bash\npip install --upgrade git+https://github.com/n2cholas/shapecheck.git\n```\n\n## Usage\n\n```python\nimport numpy as np\nfrom shapecheck import check_shapes\n\n@check_shapes({'imgs': 'N,W,W,-1', 'labels': 'N,1'}, 'N', out_='')\ndef loss_fn(batch, weights):\n    diff = (batch['imgs'].mean((1, 2, 3)) - batch['labels'].squeeze())\n    return np.mean(weights * diff**2)\n\nloss_fn({'imgs': np.ones((3, 2, 2, 1)), 'labels': np.ones((3, 1))},\n        weights=np.ones(3))  # succeeds\nloss_fn({'imgs': np.ones((5, 3, 3, 4)), 'labels': np.ones((5, 1))},\n        weights=np.ones(5))  # succeeds\nloss_fn({'imgs': np.ones((3, 5, 2, 1)), 'labels': np.ones((3, 1))},\n        weights=np.ones(3))  # fails\n```\n\nError message:\n\n```\nShapeError: in function loss_fn.\nNamed Dimensions: {'N': 3, 'W': 5}.\nInput:\n    Argument: batch  Type: \u003cclass 'dict'\u003e\n        MisMatch: Key: imgs Expected Shape: ('N', 'W', 'W', -1) Actual Shape: (3, 5, 2, 1).\n        Match:    Key: labels Expected Shape: ('N', 1) Actual Shape: (3, 1).\n    Match:    Argument: weights Expected Shape: ('N',) Actual Shape: (3,).\n```\n\nIn the above example, we compute the \"loss\" with a batch of data, which is a\ndictionary with `'imgs'` and `'labels'`. We specify that `'imgs'` should be of\nshape `N,W,W,-1`, i.e., `N` square images which can have any number of\nchannels (indicated by the `-1`).  We want the `'labels'` to have shape `N,1`,\nand `weights` to be a vector of size `N`.\n\nFinally, we specify the output shape should be a scalar via `out_=''`. All\nnon-input shape arguments to `check_shape` have an underscore after them so\nthey don't conflict with the decorated function's arguments (for now, just\n`out_` and `match_callees_`).\n\nInputs to `check_shape` can be arbitrarily nested dicts/lists/tuples, as long\nas the structure of the shape specification matches the structure of the inputs\nto the decorated function.\n\nThe shapes can be specified as positional arguments (like in the example), or\nas key word arguments. For example, the following two are equivalent to the\nexample above:\n\n```python\n@check_shapes(batch={'imgs': 'N,W,W,-1', 'labels': 'N,1'},\n              weights='N', out_='')\ndef loss_fn(batch, weights):\n    ...\n\n@check_shapes({'imgs': 'N,W,W,-1', 'labels': 'N,1'},\n              weights='N', out_='')\ndef loss_fn(batch, weights):\n    ...\n```\n\n### Skipping Arguments\n\nIf you want to not check an argument (e.g. if it's not an array), you can\nexclude that argument, or specify that the shape is `None`. For example, the\nfollowing two are equivalent:\n\n```python\n@check_shapes(None, 'N,2')\ndef fn(arg1_that_isnt_checked, arg2):\n    ...\n\n@check_shapes(arg2='N,2')\ndef fn(arg1_that_isnt_checked, arg2):\n    ...\n```\n\n### Consistent Shapes between Functionc Calls\n\nIf you have a function with shape-checking that calls other functions with\nshape-checking, you can optionally enforce that dimensions with the same letter\nname in the caller correspond to the same sized dimension in the callees via\n`match_callees_=True`.  That is, you can check that named dimensions are\nconsistent between functions on the call stack.\n\n```python\n@check_shapes('M')\ndef fn2(x):\n    return x\n\n@check_shapes('M', 'N', match_callees_=True)\ndef fn1(x, y):\n    return fn2(y)\n\nfn1(np.ones(5), np.ones(6))  # fails\n```\n\nHere, we (mistakenly) used `y` instead of `x` when calling `fn2`.  When\n`match_callees_=False`, this function would work just fine.  When\n`match_callees_=True`, we get the following error:\n\n```\nShapeError: in function fn2.\nNamed Dimensions: {'M': 5, 'N': 6}.\nInput:\n    MisMatch: Argument: a Expected Shape: ('M',) Actual Shape: (6,).\n```\n\n### Variadic Dimensions\n\nThis library also supports variadic dimensions. You can use `'...'` to indicate\n0 or more dimensions (the spaces in the example strings are optional):\n\n```python\n@check_shapes('dim, ..., 1', '..., dim, 1')\ndef g(a, b):\n    pass\n\ng(np.ones((2, 3, 4, 1)), np.ones((5, 2, 1)))  # succeeds\ng(np.ones((3, 1)), np.ones((3, 1)))  # succeeds\ng(np.ones((2, 3, 4, 1)), np.ones((1, 1)))  # fails\n```\n\nThe last statement fails with the following error, since `dim` doesn't match:\n\n```\nShapeError: in function g.\nNamed Dimensions: {'dim': 2}.\nInput:\n    Match:    Argument: a Expected Shape: ('dim', '...', 1) Actual Shape: (2, 3, 4, 1).\n    MisMatch: Argument: b Expected Shape: ('...', 'dim', 1) Actual Shape: (1, 1).\n```\n\nYou can also name the variadic dimensions, to ensure that a contiguous sequence\nof dimensions match between arguments. For example:\n\n```python\n@check_shapes('batch,variadic...', 'variadic...')\ndef h(a, b):\n    pass\n\nh(np.ones((7, 1, 2)), np.ones((1, 2)))  # succeeds\nh(np.ones((6, 2, 1)), np.ones((1, 1)))  # fails\nh(np.ones((6, 2)), np.ones((1)))  # fails\n```\n\nThe error message for the first fail would be:\n\n```\nShapeError: in function h.\nNamed Dimensions: {'batch': 6, 'variadic...': (2, 1)}.\nInput:\n    Match:    Argument: a Expected Shape: ('batch', 'variadic...') Actual Shape: (6, 2, 1).\n    MisMatch: Argument: b Expected Shape: ('variadic...',) Actual Shape: (1, 1).\n```\n\n### Toggling Checking Globally\n\nYou can enable/disable shapechecking globally as shown below:\n\n```python\nfrom shapecheck import is_checking_enabled, set_checking_enabled\n\nassert is_checking_enabled()\nset_checking_enabled(False)\nassert not is_checking_enabled()\nset_checking_enabled(True)\nassert is_checking_enabled()\n```\n\nOr via a context manager:\n\n```python\nassert is_checking_enabled()\nwith set_checking_enabled(False):\n    assert not is_checking_enabled()\nassert is_checking_enabled()\n```\n\nIf you have any questions or issues with the library, please raise an issue on\n[GitHub](https://github.com/n2cholas/shapecheck/issues). Hope you enjoy using\nthe library!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fn2cholas%2Fshapecheck","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fn2cholas%2Fshapecheck","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fn2cholas%2Fshapecheck/lists"}