-
Notifications
You must be signed in to change notification settings - Fork 34
Support test_code to add pyright-config comment #98
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
base: main
Are you sure you want to change the base?
Conversation
|
I should rewrite the test to make it pass |
|
Could you describe what problems you're trying to solve, and what other ways you have considered (if any)? Thanks. |
class MyClass:
def __init__(self, x: int) -> None:
self.x = x
# TODO: Fix the type hints of `copy` to make it type check
def copy(self):
copied_object = MyClass(x=self.x)
return copied_objectIt can pass the challenge unexpectedly without return_value annoating and you said |
|
Thanks for the PR. Surely there's value in enabling the configs, however it also brings more complexity. At this point, I don't think it's worth adding it just to fix a tiny problem. With that said, in the future it might become more useful, so I'll keep this open and re-evaluate when the time comes. Hope you can understand. |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
📝 WalkthroughWalkthroughThis PR introduces test code partitioning to separate user-written test code from Pyright configuration directives. A new Changes
Sequence DiagramsequenceDiagram
participant User as Challenge Code
participant CM as ChallengeManager
participant Part as _partition_test_code()
participant PR as Pyright
participant Map as Error Mapper
participant Report as Error Report
User->>CM: run_type_check(test_code)
CM->>Part: _partition_test_code(test_code)
Part-->>CM: (user_code, config_block)
CM->>CM: Merge config + BASIC_CONFIG
CM->>PR: Execute Pyright on augmented code
PR-->>CM: Error diagnostics with line numbers
CM->>Map: Map line numbers to sections
Map->>Map: Identify user code / test code / config lines
Map-->>CM: Mapped errors with source origin
CM->>Report: Categorize errors (config errors non-failing)
Report-->>User: Unified error count & diagnostics
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Warning Tools execution failed with the following error: Failed to run tools: Ping-pong health check failed Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Note Docstrings generation - SUCCESS |
Docstrings generation was requested by @laike9m. * #98 (comment) The following files were modified: * `tests/assets/challenges/basic-foo-pyright-config/question.py` * `tests/conftest.py` * `tests/test_identical.py` * `views/challenge.py` * `views/views.py`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @docs/Contribute.md:
- Line 45: The sentence fragment should be rewritten so it reads as a complete
instruction: change the line that currently reads about the optional comment
marker and pyright config to something like: "Optionally add a comment `## End
of test code ##`. You may also include pyright configuration options using the
format `# pyright: <config_name>=<value>`." Update the wording around the `##
End of test code ##` marker and the `# pyright: <config_name>=<value>` example
so the two clauses form complete, grammatical sentences.
In @tests/test_identical.py:
- Around line 11-24: get_test_code currently ignores its path arg and always
reads solution_file, so both solution_test and question_test come from the same
file; open and read the provided path parameter instead of solution_file inside
get_test_code (fix the file open call used when building challenge_code and test
extraction), keeping the rest of the function logic the same so solution_test
and question_test are derived from their respective paths.
In @views/challenge.py:
- Around line 261-268: The error count currently includes non-blocking
pyright-config lines and the singular/plural grammar is wrong; filter out lines
starting with "[pyright-config]" into a blocking_errors list and use that to
determine passed (set passed = True when len(blocking_errors) == 0) and to build
the summary message, e.g., append f"\nFound {n} error" vs "errors" based on n
where n = len(blocking_errors), or include both totals like "Found X errors (Y
blocking)"; update references to error_lines and the append call to use the new
counts.
🧹 Nitpick comments (2)
tests/conftest.py (1)
26-29: LGTM!The fixture correctly creates a
ChallengeManagerinstance using the test assets directory.Consider adding
scope="module"orscope="session"if theChallengeManageris stateless and reads from disk, to avoid recreating it for each test function:♻️ Optional optimization
-@pytest.fixture() +@pytest.fixture(scope="module") def mgr(assets_dir: Path): return ChallengeManager(assets_dir / "challenges")views/challenge.py (1)
175-186: Clarify the pyright config override behavior.The comment on line 179 states the goal is to "limit user to modify the config." However, appending
pyright_configafterPYRIGHT_BASIC_CONFIG(line 185) allows challenge authors to override the basic settings, since later pyright inline comments take precedence.If this is intentional (challenge authors can customize, but end-users submitting code cannot), consider updating the comment to clarify this distinction.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
challenges/advanced-forward/question.pydocs/Contribute.mdtests/assets/challenges/basic-foo-pyright-config/question.pytests/conftest.pytests/test_challenge.pytests/test_identical.pytests/test_questions.pyviews/challenge.pyviews/views.py
💤 Files with no reviewable changes (1)
- tests/test_questions.py
🔇 Additional comments (7)
challenges/advanced-forward/question.py (1)
17-19: LGTM!The test scaffolding correctly demonstrates the new pyright-config feature with the
## End of test code ##marker followed by a valid pyright directive.views/views.py (1)
62-62: LGTM!The
partition()approach handles both cases correctly: it returns the substring before the marker when present, or the full string if absent. The newline-wrapped marker"\n## End of test code ##\n"ensures exact matching of the standalone comment line.tests/assets/challenges/basic-foo-pyright-config/question.py (1)
10-11: Verify the test expectation forfoo(1).
foo()is defined without parameters, so bothfoo(1)andfoo(1, 2)should produce type errors. However, only line 11 is marked with# expect-type-error. Is this intentional for testing specific pyright config behavior, or should line 10 also be marked?tests/test_challenge.py (1)
16-22: LGTM!The test correctly verifies the
_partition_test_codebehavior by checking that the returned pyright config ends with the expected configuration line fromPYRIGHT_BASIC_CONFIG.views/challenge.py (3)
14-36: LGTM!The pyright configuration covers appropriate strictness settings for a type-checking challenge platform.
244-251: LGTM!The error line mapping correctly translates absolute line numbers from the merged code back to their respective sections (user code, test code, or pyright-config).
255-259: Verify: Line number adjustment assumes missing expected errors are always in test code.Line 258 unconditionally subtracts
user_code_lines_lenfrom the line number. If anexpect-type-errorcomment could appear in user code (line numbers ≤user_code_lines_len), this would produce incorrect (zero or negative) line numbers in the error message.If
expect-type-erroris only valid in test code, this is fine. Otherwise, consider applying the same section-based mapping used for other errors (lines 246-251).
| - Describe the challenge, make sure people understand what they need to accomplish (i.e. the `TODO:` part) | ||
| - A comment `## End of your code ##`. This is mandatory, just copy and paste it. | ||
| - Several test cases. Add a comment `# expect-type-error` after the lines where type errors should be thrown. | ||
| - (Optional) Add a comment `## End of test code ##`. Several [pyright-config](https://github.com/microsoft/pyright/blob/main/docs/configuration.md#type-check-diagnostics-settings) with the format `# pyright: <config_name>=<value>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor grammatical issue in the documentation.
The sentence structure is incomplete. After describing the comment marker, it reads "Several [pyright-config]..." which doesn't form a complete sentence.
📝 Suggested fix
- - (Optional) Add a comment `## End of test code ##`. Several [pyright-config](https://github.com/microsoft/pyright/blob/main/docs/configuration.md#type-check-diagnostics-settings) with the format `# pyright: <config_name>=<value>`
+ - (Optional) Add a comment `## End of test code ##`, followed by [pyright-config](https://github.com/microsoft/pyright/blob/main/docs/configuration.md#type-check-diagnostics-settings) directives with the format `# pyright: <config_name>=<value>`📝 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.
| - (Optional) Add a comment `## End of test code ##`. Several [pyright-config](https://github.com/microsoft/pyright/blob/main/docs/configuration.md#type-check-diagnostics-settings) with the format `# pyright: <config_name>=<value>` | |
| - (Optional) Add a comment `## End of test code ##`, followed by [pyright-config](https://github.com/microsoft/pyright/blob/main/docs/configuration.md#type-check-diagnostics-settings) directives with the format `# pyright: <config_name>=<value>` |
🤖 Prompt for AI Agents
In @docs/Contribute.md at line 45, The sentence fragment should be rewritten so
it reads as a complete instruction: change the line that currently reads about
the optional comment marker and pyright config to something like: "Optionally
add a comment `## End of test code ##`. You may also include pyright
configuration options using the format `# pyright: <config_name>=<value>`."
Update the wording around the `## End of test code ##` marker and the `#
pyright: <config_name>=<value>` example so the two clauses form complete,
grammatical sentences.
| def get_test_code(path: Path): | ||
| TEST_SPLITTER = "\n## End of test code ##\n" | ||
| level, challenge_name = path.parent.name.split("-", maxsplit=1) | ||
|
|
||
| with solution_file.open() as f: | ||
| challenge_code = f.read() | ||
| challenge = Challenge( | ||
| name=challenge_name, level=Level(level), code=challenge_code | ||
| ) | ||
|
|
||
| return challenge.test_code.partition(TEST_SPLITTER)[0] | ||
|
|
||
| solution_test = get_test_code(solution_file) | ||
| question_test = get_test_code(solution_file.parent / "question.py") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical bug: get_test_code always reads from solution_file regardless of the path argument.
Line 15 opens solution_file instead of the path parameter. This means both solution_test and question_test are derived from the same file, causing the test to always pass trivially without actually verifying that solution and question test codes are identical.
🐛 Proposed fix
def get_test_code(path: Path):
TEST_SPLITTER = "\n## End of test code ##\n"
level, challenge_name = path.parent.name.split("-", maxsplit=1)
- with solution_file.open() as f:
+ with path.open() as f:
challenge_code = f.read()
challenge = Challenge(
name=challenge_name, level=Level(level), code=challenge_code
)
return challenge.test_code.partition(TEST_SPLITTER)[0]🤖 Prompt for AI Agents
In @tests/test_identical.py around lines 11 - 24, get_test_code currently
ignores its path arg and always reads solution_file, so both solution_test and
question_test come from the same file; open and read the provided path parameter
instead of solution_file inside get_test_code (fix the file open call used when
building challenge_code and test extraction), keeping the rest of the function
logic the same so solution_test and question_test are derived from their
respective paths.
| # Error for pyright-config will not fail the challenge | ||
| passed = True | ||
| for error_line in error_lines: | ||
| if error_line.startswith("[pyright-config]"): | ||
| continue | ||
| passed = False | ||
|
|
||
| error_lines.append(f"\nFound {len(error_lines)} errors") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: Error count includes non-failing pyright-config errors, which may confuse users.
A user might see "Found 1 errors" but still pass the challenge if the only error is from pyright-config. Consider either:
- Excluding pyright-config errors from the count, or
- Clarifying in the message (e.g., "Found 1 errors (0 blocking)")
Also, minor grammar nit: "Found 1 errors" should be "Found 1 error" for singular.
💡 Suggested improvement
- error_lines.append(f"\nFound {len(error_lines)} errors")
+ blocking_count = sum(1 for e in error_lines if not e.startswith("[pyright-config]"))
+ error_lines.append(f"\nFound {blocking_count} error{'s' if blocking_count != 1 else ''}")🤖 Prompt for AI Agents
In @views/challenge.py around lines 261 - 268, The error count currently
includes non-blocking pyright-config lines and the singular/plural grammar is
wrong; filter out lines starting with "[pyright-config]" into a blocking_errors
list and use that to determine passed (set passed = True when
len(blocking_errors) == 0) and to build the summary message, e.g., append
f"\nFound {n} error" vs "errors" based on n where n = len(blocking_errors), or
include both totals like "Found X errors (Y blocking)"; update references to
error_lines and the append call to use the new counts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well I don't agree
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@laike9m Understood! I'll defer to your judgment on this. Thanks for the feedback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The suggested solution seems complicated. Can you work on a better solution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@laike9m Sure! Here's a simpler approach that adds a counter to the existing loop where you're already checking for pyright-config errors:
# Error for pyright-config will not fail the challenge
passed = True
blocking_errors = 0
for error_line in error_lines:
if error_line.startswith("[pyright-config]"):
continue
blocking_errors += 1
passed = False
error_word = "error" if blocking_errors == 1 else "errors"
error_lines.append(f"\nFound {blocking_errors} {error_word}")This reuses the loop you already have, so there's no extra iteration. It counts only the blocking errors and fixes the singular/plural grammar issue. Does this work better for you?
New feature
support test_code to add pyright-config as below.
Bug fix
disable user to modify pyright-config.
Summary by CodeRabbit
New Features
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.