Skip to content

Add CST-based script to complete missing async methods#36

Merged
jason810496 merged 8 commits intomainfrom
ci/add-ast-based-script-for-async-methods
Jan 6, 2026
Merged

Add CST-based script to complete missing async methods#36
jason810496 merged 8 commits intomainfrom
ci/add-ast-based-script-for-async-methods

Conversation

@jason810496
Copy link
Copy Markdown
Owner

No description provided.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @jason810496, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the pgmq-sqlalchemy library by introducing a robust system for managing and generating asynchronous method implementations. It leverages Concrete Syntax Tree (CST) parsing to automate the creation of _async counterparts for existing synchronous methods, ensuring a complete and consistent asynchronous API. This change also includes pre-commit hooks to enforce the presence of these async methods, improving code quality and developer experience by reducing manual boilerplate.

Highlights

  • Automated Asynchronous Method Generation: A new CST-based script (scripts/compelete_missing_async_methods.py) has been introduced to automatically identify and generate missing _async versions of synchronous methods within the pgmq_sqlalchemy/queue.py file, streamlining the development of asynchronous APIs.
  • Pre-commit Hooks for Async Method Enforcement: Two new pre-commit hooks (check_sync_async_method_for_queue.py and check_sync_async_method_for_operation.py) have been added to the .pre-commit-config.yaml. These hooks ensure that all public synchronous methods in PGMQueue and PGMQOperation classes have corresponding asynchronous implementations, maintaining API consistency.
  • Refactored Asynchronous Execution Logic: The pgmq_sqlalchemy/queue.py file has been refactored to separate synchronous and asynchronous operation execution. A new _execute_async_operation method now specifically handles asynchronous calls, while the existing _execute_operation is dedicated to synchronous tasks, improving clarity and maintainability.
  • Expanded Asynchronous API: Numerous _async versions of existing synchronous methods (e.g., create_queue_async, read_async, send_async, delete_async, archive_async, metrics_async) have been added to pgmq_sqlalchemy/queue.py, providing a comprehensive asynchronous interface for interacting with PGMQ queues.
  • CST Library Integration: The libcst library has been added as a development dependency in pyproject.toml. This library is crucial for the static analysis and code transformation capabilities of the newly introduced scripts that automate async method generation.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a great step towards improving maintainability by introducing a CST-based script to automatically generate missing asynchronous methods. The refactoring to separate synchronous and asynchronous execution logic in PGMQueue is a solid design choice. However, I've identified a few critical issues in pgmq_sqlalchemy/queue.py where synchronous methods are incorrectly used in asynchronous contexts, which would cause runtime failures. I've provided detailed comments and code suggestions to address these. Additionally, I've pointed out a minor typo in a docstring. With these fixes, this will be an excellent contribution.

Comment thread pgmq_sqlalchemy/queue.py Outdated
Comment on lines +126 to +128
def _check_pgmq_ext(self) -> None:
"""Check if the pgmq extension exists."""
if self.is_async:
return self.loop.run_until_complete(self._check_pgmq_ext_async())
return self._check_pgmq_ext_sync()

async def _check_pg_partman_ext_async(self) -> None:
"""Check if the pg_partman extension exists."""
async with self.session_maker() as session:
await PGMQOperation.check_pg_partman_ext_async(session=session, commit=True)

def _check_pg_partman_ext_sync(self) -> None:
"""Check if the pg_partman extension exists."""
with self.session_maker() as session:
PGMQOperation.check_pg_partman_ext(session=session, commit=True)
self._execute_operation(PGMQOperation.check_pgmq_ext, session=None, commit=True)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This implementation of _check_pgmq_ext is synchronous and will fail when PGMQueue is used with an async engine, as it's called from __init__. It should handle both sync and async cases to prevent a TypeError when trying to use an async session maker in a synchronous context.

Suggested change
def _check_pgmq_ext(self) -> None:
"""Check if the pgmq extension exists."""
if self.is_async:
return self.loop.run_until_complete(self._check_pgmq_ext_async())
return self._check_pgmq_ext_sync()
async def _check_pg_partman_ext_async(self) -> None:
"""Check if the pg_partman extension exists."""
async with self.session_maker() as session:
await PGMQOperation.check_pg_partman_ext_async(session=session, commit=True)
def _check_pg_partman_ext_sync(self) -> None:
"""Check if the pg_partman extension exists."""
with self.session_maker() as session:
PGMQOperation.check_pg_partman_ext(session=session, commit=True)
self._execute_operation(PGMQOperation.check_pgmq_ext, session=None, commit=True)
def _check_pgmq_ext(self) -> None:
"""Check if the pgmq extension exists."""
if self.is_async:
self.loop.run_until_complete(self._execute_async_operation(PGMQOperation.check_pgmq_ext_async, session=None, commit=True))
else:
self._execute_operation(PGMQOperation.check_pgmq_ext, session=None, commit=True)

Comment thread pgmq_sqlalchemy/queue.py Outdated
Comment on lines +130 to +134
def _check_pg_partman_ext(self) -> None:
"""Check if the pg_partman extension exists."""
if self.is_pg_partman_ext_checked:
return
self.is_pg_partman_ext_checked

if self.is_async:
return self.loop.run_until_complete(self._check_pg_partman_ext_async())
return self._check_pg_partman_ext_sync()
self._execute_operation(
PGMQOperation.check_pg_partman_ext, session=None, commit=True
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This synchronous method is called from async methods (create_partitioned_queue_async on line 345, drop_queue_async on line 453), which will cause issues with async engines. An asynchronous version of this check is needed.

I suggest adding an _check_pg_partman_ext_async method. You will then need to update create_partitioned_queue_async and drop_queue_async to call await self._check_pg_partman_ext_async().

    def _check_pg_partman_ext(self) -> None:
        """Check if the pg_partman extension exists."""
        self._execute_operation(
            PGMQOperation.check_pg_partman_ext, session=None, commit=True
        )

    async def _check_pg_partman_ext_async(self) -> None:
        """Check if the pg_partman extension exists (async)."""
        await self._execute_async_operation(
            PGMQOperation.check_pg_partman_ext_async, session=None, commit=True
        )

Comment thread pgmq_sqlalchemy/queue.py Outdated

"""
# check if the pg_partman extension exists before creating a partitioned queue at runtime
self._check_pg_partman_ext()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This synchronous call will fail in an async context. You should await the asynchronous version of this check, _check_pg_partman_ext_async.

        await self._check_pg_partman_ext_async()

Comment thread pgmq_sqlalchemy/queue.py Outdated
"""
# check if the pg_partman extension exists before dropping a partitioned queue at runtime
if partitioned:
self._check_pg_partman_ext()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This synchronous call will fail in an async context. You should await the asynchronous version of this check, _check_pg_partman_ext_async.

            await self._check_pg_partman_ext_async()

Comment thread pgmq_sqlalchemy/queue.py

# set exponential backoff retry
await pgmq_client.set_vt_async(
queue_name=query_name,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There's a typo in the example code. query_name should be queue_name.

                        queue_name=queue_name,

Copy link
Copy Markdown
Owner Author

@jason810496 jason810496 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Add compelete_missing_async_methods_for_operation.py and take scripts/compelete_missing_async_methods_for_queue.py as reference.

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 5, 2026

@jason810496 I've opened a new pull request, #37, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Copy Markdown
Owner Author

@jason810496 jason810496 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Add compelete_missing_test_for_queue.py and take scripts/compelete_missing_async_methods_for_queue.py as reference and use CST-based approach.

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 5, 2026

@jason810496 I've opened a new pull request, #38, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Copy Markdown
Owner Author

@jason810496 jason810496 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Add compelete_missing_test_for_operation.py and take scripts/compelete_missing_async_methods_for_queue.py as reference and use CST-based approach.

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 5, 2026

@jason810496 I've opened a new pull request, #39, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Copy Markdown
Owner Author

@jason810496 jason810496 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 6, 2026

@jason810496 I've opened a new pull request, #40, to work on those changes. Once the pull request is ready, I'll request review from you.

@jason810496
Copy link
Copy Markdown
Owner Author

@copilot Make pgmq_all_variants fixture async driver awareness. The pgmq_all_variants is only for sync driver, we need to add another pgmq_all_async_variants fixture for async test cases.

Or for the pgmq_all_variants fixture, skip the test if current driver is async.

Check which approach have the minimum change.

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 6, 2026

@jason810496 I've opened a new pull request, #41, to work on those changes. Once the pull request is ready, I'll request review from you.

@jason810496 jason810496 force-pushed the ci/add-ast-based-script-for-async-methods branch from 145ba4b to da8aba2 Compare January 6, 2026 09:11
@codecov
Copy link
Copy Markdown

codecov Bot commented Jan 6, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
pgmq_sqlalchemy/queue.py 100.00% <100.00%> (+12.50%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

jason810496 and others added 4 commits January 6, 2026 17:25
Distinguish sync and async operations in PGMQueue

- Introduced a pre-commit hook to check for missing async methods in PGMQueue.
- Added scripts to identify and generate missing async methods.
- Created utility functions for AST manipulation and method transformation.
- Established configuration for project paths and console output.
* Initial plan

* Refactor AST-based code to use libcst for better code transformation

Co-authored-by: jason810496 <[email protected]>

* Fix: only wrap call expressions in await, not literals

Co-authored-by: jason810496 <[email protected]>

* Ask whether to apply change

* Apply missing async methods

* Correct files for check-sync-async-method-for-queue pre-commit

* Add check for operation as well

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: jason810496 <[email protected]>
Co-authored-by: LIU ZHE YOU <[email protected]>
* Initial plan

* Add compelete_missing_async_methods_for_operation.py script and operation_ast helper

Co-authored-by: jason810496 <[email protected]>

* Fix path resolution bug in operation_ast.py

Co-authored-by: jason810496 <[email protected]>

* Address code review feedback: improve docstring handling and remove unnecessary method

Co-authored-by: jason810496 <[email protected]>

* Improve docstring handling robustness with better length checks

Co-authored-by: jason810496 <[email protected]>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: jason810496 <[email protected]>
@jason810496 jason810496 force-pushed the ci/add-ast-based-script-for-async-methods branch from da8aba2 to 9e76606 Compare January 6, 2026 09:25
Copilot AI and others added 4 commits January 6, 2026 18:10
#39)

* Add pre-commit hooks and scripts for async method checks in PGMQueue

Distinguish sync and async operations in PGMQueue

- Introduced a pre-commit hook to check for missing async methods in PGMQueue.
- Added scripts to identify and generate missing async methods.
- Created utility functions for AST manipulation and method transformation.
- Established configuration for project paths and console output.

* Refactor code transformation scripts from ast to libcst (#35)

* Initial plan

* Refactor AST-based code to use libcst for better code transformation

Co-authored-by: jason810496 <[email protected]>

* Fix: only wrap call expressions in await, not literals

Co-authored-by: jason810496 <[email protected]>

* Ask whether to apply change

* Apply missing async methods

* Correct files for check-sync-async-method-for-queue pre-commit

* Add check for operation as well

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: jason810496 <[email protected]>
Co-authored-by: LIU ZHE YOU <[email protected]>

* Initial plan

* Add compelete_missing_test_for_operation.py script with CST-based approach

Co-authored-by: jason810496 <[email protected]>

* Fix code review feedback: remove redundant code and use Tuple from typing

Co-authored-by: jason810496 <[email protected]>

* Finalize test_operation

* Fix _check_pg_partman_ext naming

---------

Co-authored-by: LIU ZHE YOU <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: jason810496 <[email protected]>
…38)

* Add pre-commit hooks and scripts for async method checks in PGMQueue

Distinguish sync and async operations in PGMQueue

- Introduced a pre-commit hook to check for missing async methods in PGMQueue.
- Added scripts to identify and generate missing async methods.
- Created utility functions for AST manipulation and method transformation.
- Established configuration for project paths and console output.

* Refactor code transformation scripts from ast to libcst (#35)

* Initial plan

* Refactor AST-based code to use libcst for better code transformation

Co-authored-by: jason810496 <[email protected]>

* Fix: only wrap call expressions in await, not literals

Co-authored-by: jason810496 <[email protected]>

* Ask whether to apply change

* Apply missing async methods

* Correct files for check-sync-async-method-for-queue pre-commit

* Add check for operation as well

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: jason810496 <[email protected]>
Co-authored-by: LIU ZHE YOU <[email protected]>

* Initial plan

* Add complete_missing_test_for_queue.py script with CST-based approach

Co-authored-by: jason810496 <[email protected]>

* Apply ruff formatting to test generation scripts

Co-authored-by: jason810496 <[email protected]>

* Address code review feedback: fix path resolution, type hints, and documentation

Co-authored-by: jason810496 <[email protected]>

* Fix missing async replacment for compelete test queue

* Fix imports for async fixtures

---------

Co-authored-by: LIU ZHE YOU <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: jason810496 <[email protected]>
@jason810496 jason810496 merged commit 8a63206 into main Jan 6, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants