{"id":42194626,"url":"https://github.com/scientific-python/spatch","last_synced_at":"2026-01-27T00:01:56.835Z","repository":{"id":242979304,"uuid":"811116823","full_name":"scientific-python/spatch","owner":"scientific-python","description":"Scientific Python diSPATCHing","archived":false,"fork":false,"pushed_at":"2025-11-17T07:36:02.000Z","size":69,"stargazers_count":11,"open_issues_count":15,"forks_count":5,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-11-17T09:19:14.847Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://scientific-python.github.io/spatch/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scientific-python.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-06-06T01:04:11.000Z","updated_at":"2025-11-17T07:36:00.000Z","dependencies_parsed_at":"2024-06-06T02:40:02.673Z","dependency_job_id":"96c9a122-69c3-4c90-aeb8-2e71e5e3141c","html_url":"https://github.com/scientific-python/spatch","commit_stats":null,"previous_names":["scientific-python/spatch"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/scientific-python/spatch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scientific-python%2Fspatch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scientific-python%2Fspatch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scientific-python%2Fspatch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scientific-python%2Fspatch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scientific-python","download_url":"https://codeload.github.com/scientific-python/spatch/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scientific-python%2Fspatch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28792638,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-26T21:49:50.245Z","status":"ssl_error","status_checked_at":"2026-01-26T21:48:29.455Z","response_time":59,"last_error":"SSL_read: 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-27T00:01:55.964Z","updated_at":"2026-01-27T00:01:56.829Z","avatar_url":"https://github.com/scientific-python.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# spatch\n\n**`spatch` is still exploratory and design/API may change significantly\nbased on feedback.**\n\n\u003c!-- SPHINX-START --\u003e\n\nSpatch is a dispatching tool with a focus on scientific python libraries.\nIt integrates two forms of dispatching into a single backend system:\n\n- Type dispatching for the main type used by a library.\n  In the scientific python world, this is often the array object.\n- Backend selection to offer alternative implementations to users.\n  These may be faster or less precise, but using them should typically\n  not change code behavior drastically.\n\nSpatch is opinionated about these points being two different, but related,\nuse-cases.\nIt thus combines machinery to do both, but keeps the related choices\nseparate for the user (and library/backend authors).\n\n## Type dispatching\n\nMany libraries are written for NumPy, but users may wish to use them\nwith other types, for example because code needs to scale from an experiment\nto a large scale deployment.\n\nUnfortunately, providing code for a host of such types isn't easy\nand the original library authors usually have neither the bandwidth nor\nexpertise to do it. Additionally, such layers would have to be optional\ncomponents of the library.\n\n`spatch` allows for a solution to this dilemma by allowing a third party\nto enable library functions to work with alternative types.\n\nIt should be noted that spatch is not a generic multiple dispatching\nlibrary. It is opinionated about being strictly typed (we can and probably\nwill support subclasses in the future, though).\nIt also considers all arguments identically. I.e. if a function takes\ntwo inputs (of the kind we dispatch for), there is no distinction for\ntheir order.\nBesides these two things, `spatch` is however a typical type dispatching\nlibrary.\n\nType dispatching mostly _extends_ functionality to cover function inputs\nthat it did not cover before.\nUsers may choose to work with a specific type explicitly but in many cases\nthe input types decide the use here.\n\n## Backend selection\n\nThe type dispatching functionality extends a library to support new types.\nAnother use-case is to not change which types we work with, but to\nprovide alternative implementations.\n\nFor example, we may have a faster algorithm that is parallelized while the\nold one was not. Or an implementation that dispatches to the GPU but still\nreturns NumPy arrays (as the library always did).\n\nBackend selection _modifies_ behavior rather than extending it. In some\ncases those modifications may be small (maybe it is really only faster).\nFor the user, backend _selection_ often means that they should explicitly\nselect a preferred backend (e.g. over the default implementation).\nThis could be for example via a context manager:\n\n```python\nwith backend_opts(prioritize=\"gpu_backend\"):\n    library.function()  # now running on the GPU\n```\n\n\u003c!-- SPHINX-STOP --\u003e\n\n# Development status\n\n(Please bear in mind that this section may get outdated)\n\n`spatch` is functional but not complete at this point and\nit should be considered a prototype when it comes to API stability.\n\nSome examples for missing things we are still working on:\n\n- No way to conveniently see which backends may be used when calling a\n  function (rather than actually calling it). And probably more inspection\n  utilities.\n- We have implemented the ability for a backend to defer and not run,\n  but not the ability to run anyway if there is no alternative.\n- The main library implementation currently can't distinguish fallback\n  and default path easily. It should be easy to do this (two functions,\n  `should_run`, or just via `uses_context`).\n- `spatch` is very much designed to be fast but that doesn't mean it\n  is particularly fast yet. We may need to optimize parts (potentially\n  lowering parts to a compiled language).\n- We have not implemented tools to test backends, e.g. against parts\n  of the original library. We expect that \"spatch\" actually includes most\n  tools to do this. For example, we could define a `convert` function\n  that backends can implement to convert arguments in tests as needed.\n\nThere are also many smaller or bigger open questions and those include whether\nthe API proposed here is actually quite what we want.\nOther things are for example whether we want API like:\n\n- `dispatchable.invoke(type=, backend=)`.\n- Maybe libraries should use `like=` in functions that take no dispatchable\n  arguments.\n- How do we do classes such as scikit-learn estimators. A simple solution might\n  a `get_backend(...)` dispatching explicitly once. But we could use more involved\n  schemes, rather remembering the dispatching state of the `.fit()`.\n\nWe can also see many small conveniences, for example:\n\n- Extract the dispatchable arguments from type annotations.\n- Support a magic `Defer` return, rather than the `should_run` call.\n\n# Usage examples\n\nPlease see the example readme for a (very minimal) usage example.\n\n# For library and backend authors\n\nPlease see our small example for how to use `spatch` in a library and how to\nimplement backends for a library that uses `spatch`.\n\nWe would like to note that while `spatch` is designed in a way that tries\nto ensure that simply installing a backend will not modify library behavior,\nin practice it must be the backend author who ensures this.\n\nThus, backend authors must review library documentation and when in doubt\ncontact the library authors about acceptable behavior.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscientific-python%2Fspatch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscientific-python%2Fspatch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscientific-python%2Fspatch/lists"}