Skip to content
Merged
Show file tree
Hide file tree
Changes from 53 commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
8de9d89
test case
Aug 5, 2025
0263fda
readme
Aug 5, 2025
90b7c83
readme
Aug 5, 2025
1d1bd2b
readme
Aug 5, 2025
c44e18a
comment the xfail flag
Aug 7, 2025
26080f2
uncomment the xfail flag
Aug 7, 2025
2f551f7
add dependencies cache for the tests CI workflow
Aug 8, 2025
783e363
up coverage
Aug 8, 2025
35db597
get coverage down
Aug 8, 2025
ce6f897
empty line
Aug 8, 2025
8ae5f47
Add workflow name to pip cache key
Aug 8, 2025
1c41335
Add pip dependency caching to the lint workflow
Aug 10, 2025
2d6007f
empty line
Aug 10, 2025
3405dba
gitignore
Aug 10, 2025
4ee6dff
some typing shit
Aug 11, 2025
1e63db8
delete empty line
Aug 11, 2025
0c979c6
another typing shit
Aug 11, 2025
1e425a1
another typing shit
Aug 11, 2025
4e31e57
another typing shit
Aug 11, 2025
0a11352
add mypy to CI
Aug 11, 2025
5b07682
some typing shit
Aug 11, 2025
cf29bf2
some typing shit
Aug 11, 2025
58b6568
some typing shit
Aug 11, 2025
268eaf4
some typing shit
Aug 11, 2025
9d5fdd0
some typing shit
Aug 11, 2025
9f58555
Add `--check` flag to mypy in lint workflow
Aug 11, 2025
df68f99
new version tag
Aug 11, 2025
672fdfe
pragma comment
Aug 11, 2025
df11456
Add @ prefix to dual‑use decorator error message
Aug 11, 2025
fa84004
Add test for non‑@ usage of transfunction decorator
Aug 11, 2025
a3685c2
Add tests that disallow calling superfunction without @
Aug 11, 2025
b2489df
delete extra code
Aug 11, 2025
4d63dfd
Add automated Ollama code review workflow
Aug 11, 2025
38ad864
Remove unused AliasedDecoratorSyntaxError import
Aug 11, 2025
c5e37a6
Improve some typing
Aug 11, 2025
4cd9330
rename a workflow
Aug 11, 2025
95a857f
Use local ollama‑code‑review action in workflow
Aug 12, 2025
e4cc5a2
Remove obsolete Ollama code review action and workflow
Aug 12, 2025
c3c65a6
Add Code Review workflow with Ollama LLM
Aug 12, 2025
caed76a
Update code_review workflow to run on pull request to main
Aug 12, 2025
1548ce9
Add node_modules to .gitignore
Aug 12, 2025
f65f7ec
Update code review prompt for style and security
Aug 12, 2025
7d4ce30
Cache and pull codellama model in CI workflow
Aug 12, 2025
2754d4a
Update code review prompt to focus on vulnerabilities
Aug 12, 2025
bb19e92
Update code_review.yml
Aug 12, 2025
7bd1757
Update code review workflow to use Qwen 2.5 Coder Tools model
Aug 12, 2025
6725beb
Refine code review prompt for safety
Aug 12, 2025
3341155
Add model env and bot name to code review
Aug 12, 2025
5e3b4f8
Update code review workflow to use local LLM
Aug 12, 2025
a1a60be
Use MODEL env var for cache key in code_review
Aug 12, 2025
ccd864d
Remove explicit bot author from PR comments
Aug 12, 2025
c197b17
Update CI workflows to newer action versions and correct cache paths
Aug 13, 2025
ccd69c7
Update CODE REVIEW workflow to use new Qwen3 model
Aug 13, 2025
e36aa31
Add detailed code review prompt to workflow
Aug 13, 2025
1cdac79
Remove BOT_NAME from workflow environment variables
Aug 13, 2025
dff2135
Add comment about prompt source to code_review workflow
Aug 13, 2025
dd8a1b1
Update code_review.yml
Aug 13, 2025
6941cc1
Add guidance for “everything fine” comment in Code Review workflow
Aug 13, 2025
e0bd4d8
Add senior developer role to code review prompt
Aug 13, 2025
7a5eb30
Show PROMPT during code review workflow
Aug 13, 2025
469270e
Add workflow dispatch with reason input
Aug 13, 2025
df250c9
Update code review workflow input description to English
Aug 13, 2025
0ec0fe9
try python 3.14 in the CI
Aug 19, 2025
082066b
Update lint workflow to include 3.14‑dev Python version in matrix
Aug 19, 2025
54fc281
Add Python 3.14‑dev to CI matrix
Aug 19, 2025
f16cbbe
Clarify removal/addition wording in README
Oct 16, 2025
a5639b2
Fix typo in issue template labels
Feb 9, 2026
3808361
Update Python versions in CI workflows to remove "3.14-dev" and add
Feb 9, 2026
d9aee0a
Add Python Free Threading classifiers
Feb 9, 2026
2d0ff37
Remove code review workflow using local LLM
Feb 9, 2026
5ff8e91
Bump displayhooks to 0.0.5
Feb 9, 2026
742a077
Add check_decorators parameter to superfunction and transfunction
Feb 9, 2026
bc0064c
Move Ruff config from .ruff.toml to pyproject.toml
Feb 9, 2026
e83d906
Lint issues
Feb 9, 2026
08caaee
Some lint issues
Feb 9, 2026
382b832
Lint issues
Feb 9, 2026
b662ae6
Lint issues
Feb 9, 2026
76fb2f4
Add venv3 to .gitignore
Feb 9, 2026
d0fb1aa
Fix version check for Python 3.10+ compatibility
Feb 9, 2026
9fc6d9e
Lint ignore
Feb 9, 2026
874ea83
Add usage note for yield_from_it replacement
Feb 10, 2026
31c7a8d
Hide badges in readme
Feb 10, 2026
7715c63
Refactor transfunction decorator to support variadic args
Feb 10, 2026
7fae349
Mypy strict mode
Feb 10, 2026
d27729d
Add type ignore comments to suppress type checker warnings in AST
Feb 10, 2026
9494a19
Add overload definitions for transfunction decorator
Feb 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions .github/workflows/code_review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# This workflow runs a locally‑hosted LLM inside the runner to generate critical comments on pull requests
# Based on: https://remarkablemark.org/blog/2025/02/23/run-ollama-large-language-models-on-github-actions/
name: A very stupid code review

on:
pull_request:
branches:
- main

permissions:
contents: read
pull-requests: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add actions: write permission so cache can be saved

actions/cache won’t be able to save the cache with current token permissions. Add actions: write (read is implied) to make the caching step effective.

 permissions:
   contents: read
   pull-requests: write
+  actions: write
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
permissions:
contents: read
pull-requests: write
permissions:
contents: read
pull-requests: write
actions: write
🤖 Prompt for AI Agents
In .github/workflows/code_review.yml around lines 9 to 12, the workflow
permissions block only grants contents: read and pull-requests: write which
prevents actions/cache from saving caches; update the permissions block to
include actions: write (read is implied) so the cache step can persist data —
i.e., add an actions: write permission entry alongside the existing permissions.

env:
MODEL: kirito1/qwen3-coder:4b
BOT_NAME: Stupid bot

jobs:
code-review:
runs-on: ubuntu-latest
steps:
- name: Restore the model cache
uses: actions/cache@v4
with:
path: ~/.ollama
key: ${{ runner.os }}-${{ env.MODEL }}
restore-keys: |
${{ runner.os }}-${{ env.MODEL }}

# Install ollama
- name: Setup ollama
uses: ai-action/setup-ollama@v1

# Pull the model if it hasn't been cached yet
- name: Download the model
run: ollama pull ${{ env.MODEL }}

# Checkout repository
- name: Checkout repository
uses: actions/checkout@v4

Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
# Run code review and comment on PR
- name: Code review comment
run: |
PROMPT="you are given a code (diff from github to be exact). Assume that it's ok by default and answer with 'No problems has been found' if you don't see any critical problems. If you are sure that you spotted a 100% problem, please double-check if you are correct, then give a short answer as to what the problem is. Rarely, you may spot multiple problems. If so, use markdown blocks for each item. Specify extra details only if critically nesseccery. Here's the code given:"
RESPONSE=$(ollama run ${{ env.MODEL }} "$PROMPT\n$(gh pr diff $PR_NUMBER)")
gh pr comment $PR_NUMBER --body "$RESPONSE"
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
60 changes: 37 additions & 23 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -1,36 +1,50 @@
name: Lint

on:
push
on: push

jobs:
build:

runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
shell: bash
run: pip install -r requirements_dev.txt

- name: Install the library
shell: bash
run: pip install .

- name: Run ruff
shell: bash
run: ruff check transfunctions

- name: Run ruff for tests
shell: bash
run: ruff check tests
- name: Cache pip dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ github.workflow }}-${{ hashFiles('requirements_dev.txt') }}
restore-keys: |
${{ runner.os }}-pip-${{ github.workflow }}-

- name: Install dependencies
shell: bash
run: pip install -r requirements_dev.txt

- name: Install the library
shell: bash
run: pip install .

- name: Run ruff
shell: bash
run: ruff check transfunctions

- name: Run ruff for tests
shell: bash
run: ruff check tests

- name: Run mypy
shell: bash
run: mypy transfunctions

- name: Run mypy for tests
shell: bash
run: mypy tests --exclude typing
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ jobs:
# IMPORTANT: this permission is mandatory for trusted publishing
id-token: write
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
python-version: ${{ matrix.python-version }}
Comment on lines 20 to +23
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix undefined matrix variable for setup-python (actionlint error) and pin a concrete Python version

This job does not define a matrix, yet references matrix.python-version. setup-python will receive an empty version and fail. Also, consider enabling built-in pip cache for speed.

-      - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v5
-        with:
-          python-version: ${{ matrix.python-version }}
+      - name: Set up Python
+        uses: actions/setup-python@v5
+        with:
+          python-version: '3.12'
+          cache: 'pip'
+          cache-dependency-path: 'requirements_dev.txt'

Actionlint hints:

  • Line 20/23: property "python-version" is not defined in object type {} — caused by the undefined matrix variable.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
python-version: ${{ matrix.python-version }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
cache-dependency-path: 'requirements_dev.txt'
🧰 Tools
🪛 actionlint (1.7.7)

20-20: property "python-version" is not defined in object type {}

(expression)


23-23: property "python-version" is not defined in object type {}

(expression)

🤖 Prompt for AI Agents
.github/workflows/release.yml lines 20-23: the workflow references
matrix.python-version but no matrix is defined, causing setup-python to receive
an empty value and actionlint to error; fix by replacing the undefined matrix
reference with a concrete python-version (e.g. "3.11") or add a matrix strategy
that defines python-version, and enable actions/setup-python's built-in pip
cache by adding cache: "pip" under the with: block to speed installs.


- name: Install dependencies
shell: bash
Expand Down
78 changes: 42 additions & 36 deletions .github/workflows/tests_and_coverage.yml
Original file line number Diff line number Diff line change
@@ -1,49 +1,55 @@
name: Tests

on:
push
on: push

jobs:
build:

runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install the library
shell: bash
run: pip install .

- name: Install dependencies
shell: bash
run: pip install -r requirements_dev.txt

- name: Print all libs
shell: bash
run: pip list

- name: Run tests and show coverage on the command line
run: |
coverage run --source=transfunctions --omit="*tests*" -m pytest --cache-clear --assert=plain && coverage report -m --fail-under=90
coverage xml

- name: Upload coverage to Coveralls
if: runner.os == 'Linux'
env:
COVERALLS_REPO_TOKEN: ${{secrets.COVERALLS_REPO_TOKEN}}
uses: coverallsapp/github-action@v2
with:
format: cobertura
file: coverage.xml

- name: Run tests and show the branch coverage on the command line
run: coverage run --branch --source=transfunctions --omit="*tests*" -m pytest --cache-clear --assert=plain && coverage report -m --fail-under=90
- name: Install the library
shell: bash
run: pip install .

- name: Cache pip dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ github.workflow }}-${{ hashFiles('requirements_dev.txt') }}
restore-keys: |
${{ runner.os }}-pip-${{ github.workflow }}-

Comment thread
coderabbitai[bot] marked this conversation as resolved.
- name: Install dependencies
shell: bash
run: pip install -r requirements_dev.txt

Comment on lines +24 to +35
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Reorder installs to leverage cache and prevent double-installs

Currently you install your package before caching and before installing dev deps, which can trigger unnecessary network hits and duplicate dependency resolution. Install dev deps first (after enabling cache), then install the package (preferably editable for test workflows).

-      - name: Install the library
-        shell: bash
-        run: pip install .
-
-      - name: Cache pip dependencies
-        uses: actions/cache@v4
-        with:
-          path: ~/.cache/pip
-          key: ${{ runner.os }}-pip-${{ github.workflow }}-${{ hashFiles('requirements_dev.txt') }}
-          restore-keys: |
-            ${{ runner.os }}-pip-${{ github.workflow }}-
+      # setup-python's built-in cache is enabled above; remove the manual cache step
+
+      - name: Install dependencies
+        shell: bash
+        run: pip install -r requirements_dev.txt
+
+      - name: Install the library (editable)
+        shell: bash
+        run: pip install -e .

Notes:

  • setup-python’s pip cache is cross-platform; the previous ~/.cache/pip path doesn’t help on Windows and is no longer needed.
  • Installing editable eases local imports and speeds iterative testing.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In .github/workflows/tests_and_coverage.yml around lines 24–35, the workflow
currently caches and installs pip deps in the wrong order and uses a hardcoded
~/.cache/pip path; reorder steps so the cache is enabled first (use the
setup-python pip cache mechanism instead of the platform-specific ~/.cache/pip),
then run pip install -r requirements_dev.txt to install dev dependencies, and
only after that install the package in editable mode (pip install -e .) for test
jobs to avoid duplicate dependency resolution and speed iterations; update cache
key/restore-keys accordingly and remove the ~/.cache/pip path entry.

- name: Print all libs
shell: bash
run: pip list

- name: Run tests and show coverage on the command line
run: |
coverage run --source=transfunctions --omit="*tests*" -m pytest --cache-clear --assert=plain && coverage report -m --fail-under=94
coverage xml

Comment on lines +40 to +44
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Run tests once with branch coverage to save CI time

You run the entire test suite twice. Combine into a single run using --branch and produce both the console report and XML.

-      - name: Run tests and show coverage on the command line
-        run: |
-          coverage run --source=transfunctions --omit="*tests*" -m pytest --cache-clear --assert=plain && coverage report -m --fail-under=94
-          coverage xml
+      - name: Run tests and show coverage on the command line (branch coverage)
+        run: |
+          coverage run --branch --source=transfunctions --omit="*tests*" -m pytest --cache-clear --assert=plain
+          coverage report -m --fail-under=94
+          coverage xml
@@
-      - name: Run tests and show the branch coverage on the command line
-        run: coverage run --branch --source=transfunctions --omit="*tests*" -m pytest --cache-clear --assert=plain && coverage report -m --fail-under=94
+      # Removed duplicate full test run; branch coverage is already collected above

Also applies to: 54-55

🤖 Prompt for AI Agents
.github/workflows/tests_and_coverage.yml lines 40-44 (and similarly 54-55): the
workflow currently runs tests twice to produce console coverage and XML; instead
run pytest once with branch coverage and then produce both reports. Replace the
two-step runs with a single command that uses coverage run --branch
--source=transfunctions --omit="*tests*" -m pytest --cache-clear --assert=plain
&& coverage report -m --fail-under=94 && coverage xml so tests execute only once
and both console report and XML are generated.

- name: Upload coverage to Coveralls
if: runner.os == 'Linux'
env:
COVERALLS_REPO_TOKEN: ${{secrets.COVERALLS_REPO_TOKEN}}
uses: coverallsapp/github-action@v2
with:
format: cobertura
file: coverage.xml

- name: Run tests and show the branch coverage on the command line
run: coverage run --branch --source=transfunctions --omit="*tests*" -m pytest --cache-clear --assert=plain && coverage report -m --fail-under=94
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ uv.lock
.history
.vscode/
.idea/
temp*
.ropeproject
node_modules
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ This library is designed to solve one of the most important problems in python p
- [**Code generation**](#code-generation)
- [**Markers**](#markers)
- [**Superfunctions**](#superfunctions)
- [**Typing**](#typing)


## Quick start
Expand Down Expand Up @@ -297,3 +298,15 @@ However, it is not completely free. The fact is that this mode uses a special tr
- Exceptions will not work normally inside this function. Rather, they can be picked up and intercepted in [`sys.unraisablehook`](https://docs.python.org/3/library/sys.html#sys.unraisablehook), but they will not go up the stack above this function. This is due to a feature of CPython: exceptions that occur inside callbacks for finalizing objects are completely escaped.

This mode is well suited for functions such as logging or sending statistics from your code: simple functions from which no exceptions or return values are expected. In all other cases, I recommend using the tilde syntax.


## Typing

Typing is the most difficult problem we faced when developing this library. In most situations, it has already been solved, but in some cases you may still notice flaws when using `mypy` or other static type analyzers. If you encounter similar problems, please [report](https://github.com/pomponchik/transfunctions/issues) them.

There are 2 main difficulties in developing typing here:

- Code generation creates code in runtime that is not in the source files of your project. Whereas most type analyzers look at your code statically, at what is actually present in your files.
- We mix several types of syntax in a single template function, but the static analyzer does not know that this is a template and part of the code will be deleted from here. In its opinion, this is the final function that will continue to be used in your project.

As you can see, typing in Python is not well suited for metaprogramming. However, in this project, almost all the problems with typing turned out to be solved in one way or another. The main reason why this is so is that we mostly remove code from functions, but hardly add it there during code generation. In other words, we almost never encounter the problem of how to type the *added* code. This makes the solution to most typing problems accessible. However! Unfortunately, we were not able to completely hide all the typing problems under the hood, but you should still be aware of some of them if you use `mypy` or another analyzer.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "transfunctions"
version = "0.0.8"
version = "0.0.9"
authors = [
{ name="Evgeniy Blinov", email="zheni-b@yandex.ru" },
]
Expand Down
1 change: 1 addition & 0 deletions tests/typing/decorators/test_superfunction_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
Что нужно проверить:

1. Что await_it, yield_from_it и yield_it типизированы.
2. Нельзя сохранять возвращаемое значение суперфункции в переменную.

Что проверено:

Expand Down
18 changes: 18 additions & 0 deletions tests/units/decorators/test_superfunction.py
Original file line number Diff line number Diff line change
Expand Up @@ -763,3 +763,21 @@ def function(number=global_variable):
yield number

assert list(function()) == ['kek']


def test_use_decorator_without_at():
def template():
pass

with pytest.raises(WrongDecoratorSyntaxError, match=full_match("The @superfunction decorator can only be used with the '@' symbol. Don't use it as a regular function. Also, don't rename it.")):
function = superfunction(template)
~function()


with pytest.raises(WrongDecoratorSyntaxError, match=full_match("The @superfunction decorator can only be used with the '@' symbol. Don't use it as a regular function. Also, don't rename it.")):
function = superfunction(template)
run(function())

with pytest.raises(WrongDecoratorSyntaxError, match=full_match("The @superfunction decorator can only be used with the '@' symbol. Don't use it as a regular function. Also, don't rename it.")):
function = superfunction(template)
list(function())
16 changes: 16 additions & 0 deletions tests/units/decorators/test_transfunction.py
Original file line number Diff line number Diff line change
Expand Up @@ -1532,3 +1532,19 @@ def template(number=SOME_GLOBAL):
function = template.get_generator_function()

assert list(function()) == ['kek']


def test_use_decorator_without_at():
def template():
pass

template = transfunction(template)

with pytest.raises(WrongDecoratorSyntaxError, match=full_match("The @transfunction decorator can only be used with the '@' symbol. Don't use it as a regular function. Also, don't rename it.")):
template.get_usual_function()

with pytest.raises(WrongDecoratorSyntaxError, match=full_match("The @transfunction decorator can only be used with the '@' symbol. Don't use it as a regular function. Also, don't rename it.")):
template.get_async_function()

with pytest.raises(WrongDecoratorSyntaxError, match=full_match("The @transfunction decorator can only be used with the '@' symbol. Don't use it as a regular function. Also, don't rename it.")):
template.get_generator_function()
Comment on lines +1546 to +1559
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove duplicate test function

This test function test_use_decorator_without_at is an exact duplicate of the one at lines 327-337. Having duplicate tests adds unnecessary maintenance burden and confusion.

-def test_use_decorator_without_at():
-    def template():
-        pass
-
-    template = transfunction(template)
-
-    with pytest.raises(WrongDecoratorSyntaxError, match=full_match("The @transfunction decorator can only be used with the '@' symbol. Don't use it as a regular function. Also, don't rename it.")):
-        template.get_usual_function()
-
-    with pytest.raises(WrongDecoratorSyntaxError, match=full_match("The @transfunction decorator can only be used with the '@' symbol. Don't use it as a regular function. Also, don't rename it.")):
-        template.get_async_function()
-
-    with pytest.raises(WrongDecoratorSyntaxError, match=full_match("The @transfunction decorator can only be used with the '@' symbol. Don't use it as a regular function. Also, don't rename it.")):
-        template.get_generator_function()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_use_decorator_without_at():
def template():
pass
template = transfunction(template)
with pytest.raises(WrongDecoratorSyntaxError, match=full_match("The @transfunction decorator can only be used with the '@' symbol. Don't use it as a regular function. Also, don't rename it.")):
template.get_usual_function()
with pytest.raises(WrongDecoratorSyntaxError, match=full_match("The @transfunction decorator can only be used with the '@' symbol. Don't use it as a regular function. Also, don't rename it.")):
template.get_async_function()
with pytest.raises(WrongDecoratorSyntaxError, match=full_match("The @transfunction decorator can only be used with the '@' symbol. Don't use it as a regular function. Also, don't rename it.")):
template.get_generator_function()
🤖 Prompt for AI Agents
In tests/units/decorators/test_transfunction.py around lines 1537 to 1550, there
is an exact duplicate test function test_use_decorator_without_at that already
exists at lines ~327-337; remove the duplicate block (lines 1537-1550) entirely
so only the original test remains, and run the test suite to confirm no other
references to the removed function exist.

10 changes: 5 additions & 5 deletions transfunctions/decorators/superfunction.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
from ast import AST, NodeTransformer, Return
from functools import wraps
from inspect import currentframe
from typing import Any, Dict, Generic, List, Optional, Union, overload
from typing import Any, Dict, Generic, List, Optional, Union, Type, overload, cast
from types import FrameType, TracebackType

from displayhooks import not_display

Expand Down Expand Up @@ -60,7 +61,7 @@ def __invert__(self) -> ReturnType:
def send(self, value: Any) -> Any:
return self.coroutine.send(value)

def throw(self, exception_type: Any, value: Any = None, traceback: Any = None) -> None: # pragma: no cover
def throw(self, exception_type: Type[BaseException], value: Optional[BaseException] = None, traceback: Optional[TracebackType] = None) -> None: # type: ignore[override] # pragma: no cover
pass

def close(self) -> None: # pragma: no cover
Expand Down Expand Up @@ -111,13 +112,12 @@ def superfunction( # type: ignore[misc]
def decorator(function: Callable[FunctionParams, ReturnType]) -> Callable[FunctionParams, UsageTracer[FunctionParams, ReturnType]]:
transformer = FunctionTransformer(
function,
currentframe().f_back.f_lineno, # type: ignore[union-attr]
cast(FrameType, cast(FrameType, currentframe()).f_back).f_lineno,
"superfunction",
currentframe().f_back,
cast(FrameType, cast(FrameType, currentframe()).f_back),
)

if not tilde_syntax:

class NoReturns(NodeTransformer):
def visit_Return(self, node: Return) -> Optional[Union[AST, List[AST]]]:
raise WrongTransfunctionSyntaxError('A superfunction cannot contain a return statement.')
Expand Down
9 changes: 8 additions & 1 deletion transfunctions/decorators/transfunction.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from inspect import currentframe
from typing import cast
from types import FrameType

from transfunctions.transformer import FunctionTransformer
from transfunctions.typing import Callable, FunctionParams, ReturnType
Expand All @@ -7,4 +9,9 @@
def transfunction(
function: Callable[FunctionParams, ReturnType],
) -> FunctionTransformer[FunctionParams, ReturnType]:
return FunctionTransformer(function, currentframe().f_back.f_lineno, "transfunction", currentframe().f_back) # type: ignore[union-attr]
return FunctionTransformer(
function,
cast(FrameType, cast(FrameType, currentframe()).f_back).f_lineno,
"transfunction",
cast(FrameType, cast(FrameType, currentframe()).f_back),
)
2 changes: 1 addition & 1 deletion transfunctions/markers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ def create_generator_context() -> Generator[NoReturn, None, None]:
def await_it(some_expression: Any) -> Any:
pass # pragma: no cover

def yield_from_it(some_iterable: IterableWithResults) -> NoReturn: # type: ignore[misc]
def yield_from_it(some_iterable: IterableWithResults) -> NoReturn: # type: ignore[misc, type-arg]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Clarify the type ignore comment extension.

The addition of type-arg to the type ignore comment is reasonable for handling generic type parameter issues, but it would be helpful to understand what specific typing issue this addresses to ensure it's the minimal necessary suppression.


🏁 Script executed:

#!/bin/bash
# Description: Check if there are any mypy errors related to this function without the type ignore comments

# Remove the type ignore comment temporarily and run mypy to see the original error
sed 's/# type: ignore\[misc, type-arg\]//' transfunctions/markers.py > temp_markers.py
mypy temp_markers.py --show-error-codes 2>&1 || true
rm -f temp_markers.py

Length of output: 238


Clarify suppressed MyPy error

The # type: ignore[misc, type-arg] on line 28 is there to silence MyPy’s “Missing type parameters for generic type IterableWithResults” error. To make this explicit and as narrow as possible, you could:

  • Drop the misc flag if it isn’t needed elsewhere.
  • Add an inline comment explaining that it suppresses the missing-generic-type-arg error.

For example, in transfunctions/markers.py at line 28:

- def yield_from_it(some_iterable: IterableWithResults) -> NoReturn:  # type: ignore[misc, type-arg]
+ def yield_from_it(some_iterable: IterableWithResults) -> NoReturn:  # type: ignore[type-arg]  # suppresses “Missing type parameters for generic type IterableWithResults”
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def yield_from_it(some_iterable: IterableWithResults) -> NoReturn: # type: ignore[misc, type-arg]
def yield_from_it(some_iterable: IterableWithResults) -> NoReturn: # type: ignore[type-arg] # suppresses "Missing type parameters for generic type IterableWithResults"
🤖 Prompt for AI Agents
In transfunctions/markers.py around line 28, the current `# type: ignore[misc,
type-arg]` is too broad; replace it with a narrowly scoped suppression and
document why: drop the `misc` flag if no other misc suppression is required
(keep only `type-arg`), and add an inline comment after the ignore explaining
that it silences MyPy’s "Missing type parameters for generic type
IterableWithResults" error (or alternatively fully parameterize
IterableWithResults if feasible); this keeps the suppression minimal and
documents the reason for future readers.

for value in some_iterable: # pragma: no cover
return value # type: ignore[misc]
Loading
Loading