{"id":24738087,"url":"https://github.com/zen-xu/sunray","last_synced_at":"2025-10-10T07:32:30.510Z","repository":{"id":221156707,"uuid":"753602007","full_name":"zen-xu/sunray","owner":"zen-xu","description":"More robust and elegant ray","archived":false,"fork":false,"pushed_at":"2025-09-29T19:27:27.000Z","size":496,"stargazers_count":17,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-02T16:44:05.580Z","etag":null,"topics":["pythonic","ray","typing"],"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/zen-xu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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},"funding":{"github":["zen-xu"]}},"created_at":"2024-02-06T12:56:48.000Z","updated_at":"2025-08-24T09:18:55.000Z","dependencies_parsed_at":"2024-04-24T12:46:55.830Z","dependency_job_id":"0e9aa8d1-a508-48aa-86a9-bb09a421066e","html_url":"https://github.com/zen-xu/sunray","commit_stats":null,"previous_names":["zen-xu/sunray"],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/zen-xu/sunray","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zen-xu%2Fsunray","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zen-xu%2Fsunray/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zen-xu%2Fsunray/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zen-xu%2Fsunray/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zen-xu","download_url":"https://codeload.github.com/zen-xu/sunray/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zen-xu%2Fsunray/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279003189,"owners_count":26083533,"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-10-10T02:00:06.843Z","response_time":62,"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":["pythonic","ray","typing"],"created_at":"2025-01-27T22:35:13.274Z","updated_at":"2025-10-10T07:32:30.504Z","avatar_url":"https://github.com/zen-xu.png","language":"Python","funding_links":["https://github.com/sponsors/zen-xu"],"categories":[],"sub_categories":[],"readme":"# Sunray\n\n[![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n[![Tests](https://github.com/zen-xu/sunray/actions/workflows/test.yaml/badge.svg?branch=main)](https://github.com/zen-xu/sunray/actions/workflows/test.yaml)\n[![Mypy](https://github.com/zen-xu/sunray/actions/workflows/test-mypy.yaml/badge.svg?branch=main)](https://github.com/zen-xu/sunray/actions/workflows/test-mypy.yaml)\n[![codecov](https://codecov.io/gh/zen-xu/sunray/graph/badge.svg?token=NkaEIVRqk6)](https://codecov.io/gh/zen-xu/sunray)\n![GitHub License](https://img.shields.io/github/license/zen-xu/sunray)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/sunray)\n![PyPI - Version](https://img.shields.io/pypi/v/sunray)\n![Static Badge](https://img.shields.io/badge/RMV-2.20.0-blue)\n\n[Ray](https://github.com/ray-project/ray) is a unified framework for scaling AI and Python applications. However, it falls short in offering friendly type hints, particularly when it comes to working with the `Actor`.\n\nTo address this shortfall, sunray provides enhanced and more robust type hints.\n\n## install\n\n```shell\npip install sunray\n```\n\n## Let's vs.\n\n### Round 1: Build an actor\n\n|                                   sunray                                    |                                   ray                                    |\n| :-------------------------------------------------------------------------: | :----------------------------------------------------------------------: |\n| ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/sunray_actor.jpg) | ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/ray_actor.jpg) |\n\n- sunray returns `Actor[Demo]`, but ray returns `ObjectRef[Demo]`\n- ray mypy raise error `Type[Demo] has no attribute \"remote\"`\n\n### Round 2: Get actor remote methods\n|                                       sunray                                        |                                       ray                                        |\n| :---------------------------------------------------------------------------------: | :------------------------------------------------------------------------------: |\n| ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/sunray_actor_methods.jpg) | ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/ray_actor_methods.jpg) |\n\n- sunray list all remote methods\n- ray list nothing\n\n### Round 3: Actor remote method call\n|                                          sunray                                          |                                          ray                                          |\n| :--------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------: |\n| ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/sunray_method_remote_call.jpg) | ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/ray_method_remote_call.jpg) |\n\n- sunray correctly provided parameter hints.\n- ray ...\n\n### Round 4: Annotate with Actor\n|                                         sunray                                         |                                         ray                                         |\n| :------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------: |\n| ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/sunray_actor_annotation.jpg) | ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/ray_actor_annotation.jpg) |\n\n- with sunray, just annotate it with `Actor[Demo]`.\n- with ray, I don't known.\n\n### Round 5: Stream\n|                                    sunray                                    |                                    ray                                    |\n| :--------------------------------------------------------------------------: | :-----------------------------------------------------------------------: |\n| ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/sunray_stream.jpg) | ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/ray_stream.jpg) |\n\n- sunray correctly identified that `stream` returns a generator.\n- ray still returns ObjectRef.\n\n### Round 6: Unpack result\n|                                    sunray                                    |                                    ray                                    |\n| :--------------------------------------------------------------------------: | :-----------------------------------------------------------------------: |\n| ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/sunray_unpack.jpg) | ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/ray_unpack.jpg) |\n\n- sunray will auto unpack tuple result if options specify `unpack=True`.\n- ray need to specify how many return numbers, so you need to count it.\n- ray mypy raise error 'RemoteFunctionNoArgs has no attribute \"options\"'.\n\n### Round 7: Get actor\n|                                     sunray                                      |                                     ray                                      |\n| :-----------------------------------------------------------------------------: | :--------------------------------------------------------------------------: |\n| ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/sunray_get_actor.jpg) | ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/ray_get_actor.jpg) |\n\n- sunray get_actor will return `ActorHandle`, and return `Actor[Demo]` if you specify with generic type.\n- ray just return `Any`.\n\n### Round 8: Call self remote method\n|                                            sunray                                             |                                            ray                                             |\n| :-------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------: |\n| ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/sunray_call_self_remote_method.jpg) | ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/ray_call_self_remote_method.jpg) |\n\n- sunray maintains a consistent calling convention, whether it's from internal or external functions.\n- ray, you need to first obtain the current actor from the running context, and then call through the actor.\n\n### Round 9: Lazy Computation\n|                                   sunray                                   |                                   ray                                   |\n| :------------------------------------------------------------------------: | :---------------------------------------------------------------------: |\n| ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/sunray_bind.jpg) | ![](https://zenxu-github-asset.s3.us-east-2.amazonaws.com/ray_bind.jpg) |\n\n- sunray can successfully track the input parameter types and output types.\n- ray does not have this capability.\n\n## API\n\n`sunray` re-export all apis from `ray.core` with friendly type hints. In addition, `sunray` provides `ActorMixin` which is used to help creating more robust actors.\n\n### ActorMixin\n\n`ActorMixin` is a mixin, and provides a classmethod `new_actor`\n\n```python\nimport sunray\n\n\nclass Demo(\n                       # Here to specify default actor options\n    sunray.ActorMixin, name=\"DemoActor\", num_cpus=1, concurrency_groups={\"g1\": 1}\n):\n    def __init__(self, init_v: int):\n        self.init_v = init_v\n\n    # annotate `add` is a remote_method\n    @sunray.remote_method\n    def add(self, v: int) -\u003e int:\n        return self.init_v + v\n\n    # support directly call remote_method\n    @sunray.remote_method\n    def calculate(self, v: int) -\u003e int:\n        return self.add(v)\n\n    # support specify remote method options\n    @sunray.remote_method(concurrency_group=\"g1\")\n    async def sleep(self): ...\n\n\n# construct the actor\nactor = Demo.new_actor().remote(1)\n\n# call remote method\nref = actor.methods.add.remote(1)\nprint(sunray.get(ref))\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzen-xu%2Fsunray","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzen-xu%2Fsunray","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzen-xu%2Fsunray/lists"}