-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/compat ray #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…orator - Replaced all instances of the @as_actor decorator with @Remote in documentation files, including API references, guides, and examples. - Updated code snippets to demonstrate the new usage patterns with the @Remote decorator, ensuring consistency across all documentation. - Enhanced examples to include initialization and shutdown processes, aligning with the new actor creation workflow. - Adjusted translations in Chinese documentation to match the updated terminology and examples.
…nt loops - Enhanced the `ray` compatibility module to allow `ray.init()` to function correctly when called from within an existing event loop, such as in Jupyter or pytest-asyncio environments. - Introduced a background thread to manage a dedicated event loop, ensuring compatibility with asynchronous operations. - Added a new test to validate the behavior of the `ray` module under these conditions, confirming that actor creation and interaction work as expected. - Refactored existing methods to utilize the new event loop management, improving overall robustness and usability.
- Cleaned up whitespace in the `README.md`, `remote_actor_example.py`, and `ray.py` files to enhance code clarity. - Adjusted list comprehensions and threading initialization for better formatting and alignment. - Added a blank line in the test file `test_new_api.py` to improve separation of code sections. - Removed unnecessary blank lines in `test_ray_compat_running_loop.py` to streamline the code structure.
| _system = None | ||
| _loop = None | ||
| _thread = None | ||
| _loop_ready = None |
Check notice
Code scanning / CodeQL
Unused global variable Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 5 days ago
In general, an unused global variable should either be removed or renamed to make its intentionally-unused nature clear. Here, _loop_ready is not used for any behavior; it merely mirrors the local variable ready inside _start_background_loop. Removing it does not change the synchronization logic, because the code already waits on ready directly.
The best fix without changing functionality is:
- Remove
_loop_readyfrom the module-level “Global state” declarations. - Remove
_loop_readyfrom theglobalstatement in_start_background_loop. - Remove the assignment
_loop_ready = ready.
All changes occur in python/pulsing/compat/ray.py in the snippet around lines 47–52 and 67–73. No new imports or helper methods are needed.
-
Copy modified line R66
| @@ -48,7 +48,6 @@ | ||
| _system = None | ||
| _loop = None | ||
| _thread = None | ||
| _loop_ready = None | ||
|
|
||
|
|
||
| def _ensure_not_initialized(ignore_reinit_error: bool) -> None: | ||
| @@ -64,12 +63,11 @@ | ||
|
|
||
| This is required when the caller is already inside a running event loop. | ||
| """ | ||
| global _thread, _loop, _loop_ready | ||
| global _thread, _loop | ||
| if _thread is not None: | ||
| return | ||
|
|
||
| ready = threading.Event() | ||
| _loop_ready = ready | ||
|
|
||
| def _thread_main(): | ||
| global _loop |
| return | ||
|
|
||
| ready = threading.Event() | ||
| _loop_ready = ready |
Check notice
Code scanning / CodeQL
Unused global variable Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 5 days ago
To fix the problem, we should remove the unused global variable rather than keep writing to it. That means deleting both the module-level declaration _loop_ready = None and the assignment _loop_ready = ready inside _start_background_loop. The rest of the code already uses the local ready to block until the loop is initialized (ready.wait()), so removing _loop_ready does not change behavior.
Concretely, in python/pulsing/compat/ray.py:
- Remove the line defining
_loop_ready = Nonein the “Global state” block. - In
_start_background_loop, remove_loop_readyfrom theglobalstatement and delete the line_loop_ready = ready. - No imports, methods, or other definitions are needed to support this change, since
_loop_readywas never read.
-
Copy modified line R66
| @@ -48,7 +48,6 @@ | ||
| _system = None | ||
| _loop = None | ||
| _thread = None | ||
| _loop_ready = None | ||
|
|
||
|
|
||
| def _ensure_not_initialized(ignore_reinit_error: bool) -> None: | ||
| @@ -64,12 +63,11 @@ | ||
|
|
||
| This is required when the caller is already inside a running event loop. | ||
| """ | ||
| global _thread, _loop, _loop_ready | ||
| global _thread, _loop | ||
| if _thread is not None: | ||
| return | ||
|
|
||
| ready = threading.Event() | ||
| _loop_ready = ready | ||
|
|
||
| def _thread_main(): | ||
| global _loop |
| if _system is not None: | ||
| try: | ||
| _run_coro_sync(_system.shutdown()) | ||
| except Exception: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 5 days ago
In general, the fix is to avoid empty except blocks: either narrow the caught exceptions and handle them explicitly, or at least log them with enough context. For a shutdown routine that is intended not to raise, the safest minimal-change approach is to keep catching Exception but log the error rather than pass.
Concretely for python/pulsing/compat/ray.py:
- Add an import for the standard
loggingmodule near the existing imports. - Replace each
except Exception: passinshutdown()withexcept Exception as exc:followed by alogging.getLogger(__name__).warning(...)(orerror) call that records what failed and includesexc_info=Trueso the traceback is logged. - Do not change the function’s external behavior:
shutdown()should still not propagate these exceptions and should still reset_system,_thread,_loop_ready, and_loopas it currently does.
All changes are confined to this file and require only the standard library logging module; no new external dependencies are needed.
-
Copy modified line R43 -
Copy modified lines R264-R267 -
Copy modified lines R272-R277 -
Copy modified lines R280-R285
| @@ -40,6 +40,7 @@ | ||
| import concurrent.futures | ||
| import inspect | ||
| import threading | ||
| import logging | ||
| from typing import Any, TypeVar | ||
|
|
||
| T = TypeVar("T") | ||
| @@ -260,18 +261,28 @@ | ||
| if _system is not None: | ||
| try: | ||
| _run_coro_sync(_system.shutdown()) | ||
| except Exception: | ||
| pass | ||
| except Exception as exc: | ||
| logging.getLogger(__name__).warning( | ||
| "Error during Pulsing system shutdown: %s", exc, exc_info=True | ||
| ) | ||
| _system = None | ||
| if _thread is not None and _loop is not None: | ||
| try: | ||
| _loop.call_soon_threadsafe(_loop.stop) | ||
| except Exception: | ||
| pass | ||
| except Exception as exc: | ||
| logging.getLogger(__name__).warning( | ||
| "Error while stopping Pulsing background event loop: %s", | ||
| exc, | ||
| exc_info=True, | ||
| ) | ||
| try: | ||
| _thread.join(timeout=2.0) | ||
| except Exception: | ||
| pass | ||
| except Exception as exc: | ||
| logging.getLogger(__name__).warning( | ||
| "Error while joining Pulsing background thread: %s", | ||
| exc, | ||
| exc_info=True, | ||
| ) | ||
| _thread = None | ||
| _loop_ready = None | ||
| _loop = None |
| if _thread is not None and _loop is not None: | ||
| try: | ||
| _loop.call_soon_threadsafe(_loop.stop) | ||
| except Exception: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 5 days ago
In general, empty except blocks should be replaced with logic that either (a) handles specific, expected exceptions or (b) logs unexpected exceptions while optionally re-raising or suppressing them with a clear rationale. For shutdown/cleanup paths where we want to be robust and not raise, logging and then suppressing is usually appropriate.
For this file, the best fix that preserves behavior (shutdown remains non-throwing) is to keep catching Exception but log the exception instead of silently passing. Since we cannot assume any project-specific logging utilities, we can safely use the standard-library logging module. We will:
- Add an import for
loggingnear the top ofpython/pulsing/compat/ray.py. - In
shutdown(), replace eachexcept Exception: passwithexcept Exception as exc:and calllogging.getLogger(__name__).exception("...")with a message indicating which shutdown step failed.logger.exceptionincludes the stack trace, preserving debugging information while maintaining the current non-raising behavior.
Specific changes:
- At the imports region (around line 39–43), add
import logging. - Around line 261–264, replace:
with a version that logs the exception.
try: _run_coro_sync(_system.shutdown()) except Exception: pass
- Around line 267–270, replace:
with a version that logs the exception.
try: _loop.call_soon_threadsafe(_loop.stop) except Exception: pass
- Around line 271–274, replace:
with a version that logs the exception.
try: _thread.join(timeout=2.0) except Exception: pass
This keeps external behavior (no exceptions propagated from shutdown()) while ensuring exceptions are no longer silently ignored.
-
Copy modified line R43 -
Copy modified lines R264-R267 -
Copy modified lines R272-R275 -
Copy modified lines R278-R281
| @@ -40,6 +40,7 @@ | ||
| import concurrent.futures | ||
| import inspect | ||
| import threading | ||
| import logging | ||
| from typing import Any, TypeVar | ||
|
|
||
| T = TypeVar("T") | ||
| @@ -260,18 +261,24 @@ | ||
| if _system is not None: | ||
| try: | ||
| _run_coro_sync(_system.shutdown()) | ||
| except Exception: | ||
| pass | ||
| except Exception as exc: | ||
| logging.getLogger(__name__).exception( | ||
| "Error while shutting down Pulsing actor system", exc_info=exc | ||
| ) | ||
| _system = None | ||
| if _thread is not None and _loop is not None: | ||
| try: | ||
| _loop.call_soon_threadsafe(_loop.stop) | ||
| except Exception: | ||
| pass | ||
| except Exception as exc: | ||
| logging.getLogger(__name__).exception( | ||
| "Error while stopping background event loop", exc_info=exc | ||
| ) | ||
| try: | ||
| _thread.join(timeout=2.0) | ||
| except Exception: | ||
| pass | ||
| except Exception as exc: | ||
| logging.getLogger(__name__).exception( | ||
| "Error while joining background thread", exc_info=exc | ||
| ) | ||
| _thread = None | ||
| _loop_ready = None | ||
| _loop = None |
| pass | ||
| try: | ||
| _thread.join(timeout=2.0) | ||
| except Exception: |
Check notice
Code scanning / CodeQL
Empty except Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 5 days ago
In general, the fix is to avoid empty except blocks: either narrow the exception type and handle it explicitly, or at least record what went wrong (e.g., via logging) while still preventing the exception from propagating if that’s desired.
For this specific shutdown function, the best low-impact fix is to add simple logging in each except Exception clause. That way, shutdown remains non-throwing (so existing callers’ behavior doesn’t change), but any failures in _system.shutdown(), stopping the loop, or joining the thread are visible during debugging. We can use Python’s standard logging module, which is a well-known library and doesn’t add external dependencies. Concretely:
- Add
import loggingnear the top ofpython/pulsing/compat/ray.pyalongside the other imports. - Replace each
except Exception: passinshutdownwith anexcept Exception as exc:block that callslogging.getLogger(__name__).exception("...")with a message indicating which shutdown step failed. Using.exceptionlogs the full traceback, which is valuable for debugging.
No new helper methods or non-standard imports are needed; just the standard library logging and the updated except blocks, all within the shown file.
-
Copy modified line R44 -
Copy modified lines R264-R267 -
Copy modified lines R272-R275 -
Copy modified lines R278-R281
| @@ -41,6 +41,7 @@ | ||
| import inspect | ||
| import threading | ||
| from typing import Any, TypeVar | ||
| import logging | ||
|
|
||
| T = TypeVar("T") | ||
|
|
||
| @@ -260,18 +261,24 @@ | ||
| if _system is not None: | ||
| try: | ||
| _run_coro_sync(_system.shutdown()) | ||
| except Exception: | ||
| pass | ||
| except Exception as exc: | ||
| logging.getLogger(__name__).exception( | ||
| "Error while shutting down Pulsing system", exc_info=exc | ||
| ) | ||
| _system = None | ||
| if _thread is not None and _loop is not None: | ||
| try: | ||
| _loop.call_soon_threadsafe(_loop.stop) | ||
| except Exception: | ||
| pass | ||
| except Exception as exc: | ||
| logging.getLogger(__name__).exception( | ||
| "Error while stopping background event loop", exc_info=exc | ||
| ) | ||
| try: | ||
| _thread.join(timeout=2.0) | ||
| except Exception: | ||
| pass | ||
| except Exception as exc: | ||
| logging.getLogger(__name__).exception( | ||
| "Error while joining background thread", exc_info=exc | ||
| ) | ||
| _thread = None | ||
| _loop_ready = None | ||
| _loop = None |
| except Exception: | ||
| pass | ||
| _thread = None | ||
| _loop_ready = None |
Check notice
Code scanning / CodeQL
Unused global variable Note
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 5 days ago
In general, to fix an unused global variable that is not intentionally unused, remove the variable: delete its definition, remove it from any global declarations, and remove any assignments to it. This eliminates dead state and the associated CodeQL warning without affecting program behavior, as long as the variable truly is never read.
For this specific case in python/pulsing/compat/ray.py, the best fix is:
- Remove the module-level declaration
_loop_ready = None(line 51). - Remove
_loop_readyfrom theglobalstatement inshutdown(line 258), leaving only the actually used globals. - Remove the assignment
_loop_ready = Noneinshutdown(line 276).
No new imports or methods are needed. These changes are fully localized to the shown file and only touch _loop_ready, which, per the snippet, has no reads, so they do not change existing functionality.
-
Copy modified line R257
| @@ -48,7 +48,6 @@ | ||
| _system = None | ||
| _loop = None | ||
| _thread = None | ||
| _loop_ready = None | ||
|
|
||
|
|
||
| def _ensure_not_initialized(ignore_reinit_error: bool) -> None: | ||
| @@ -255,7 +254,7 @@ | ||
|
|
||
| def shutdown() -> None: | ||
| """Shutdown Pulsing (Ray-compatible)""" | ||
| global _system, _loop, _thread, _loop_ready | ||
| global _system, _loop, _thread | ||
|
|
||
| if _system is not None: | ||
| try: | ||
| @@ -273,7 +272,6 @@ | ||
| except Exception: | ||
| pass | ||
| _thread = None | ||
| _loop_ready = None | ||
| _loop = None | ||
| else: | ||
| _loop = None |
Codecov Report❌ Patch coverage is
... and 2 files with indirect coverage changes 🚀 New features to boost your workflow:
|
Overview:
Details:
Where should the reviewer start?
Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)