Skip to content

Allow @abstractmethod to document Returns/Raises/Yields with cross-file inheritance tracking#8

Merged
alithethird merged 13 commits intomasterfrom
copilot/track-abstract-function-docs
Nov 14, 2025
Merged

Allow @abstractmethod to document Returns/Raises/Yields with cross-file inheritance tracking#8
alithethird merged 13 commits intomasterfrom
copilot/track-abstract-function-docs

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Nov 9, 2025

Abstract Methods Returns and Raises Documentation

This PR addresses the issue where abstract functions should be allowed to keep their return and raises documentation sections, and ensures that implementations of abstract methods also include these sections.

Completed:

  • Add detection for @abstractmethod decorator in function info
  • Skip D031 (extra returns section) check for abstract methods
  • Skip D051 (extra raises section) check for abstract methods
  • Skip D041 (extra yields section) check for abstract methods for consistency
  • Create tests for abstract method handling
  • Verify all existing tests still pass
  • Test the changes with sample files
  • Implement cross-file inheritance tracking
  • Validate concrete implementations match abstract documentation
  • Add comprehensive tests for inheritance tracking
  • Add testing documentation for users
  • Build x64 release executable
  • Fix UTF-8 boundary panic in string slicing
  • Add comprehensive Python test script
  • Implement docstring inheritance for implementations
  • Update README with abstract method rules

Docstring Inheritance Feature:

Implementations of abstract methods can now inherit docstrings from their abstract base methods, avoiding the need to duplicate documentation:

Behavior:

  • Implementation without docstring: Inherits from abstract method

    • No D010 error (missing docstring)
    • No D070/D071/D072 errors (inherits Returns/Raises/Yields documentation)
    • No D030/D050/D040 errors (inherits contract)
  • Implementation with docstring: Normal validation applies

    • Must document Returns/Raises/Yields if abstract method documents them
    • D070/D071/D072 errors triggered if sections missing

Example:

# base.py
from abc import ABC, abstractmethod

class DataProcessor(ABC):
    @abstractmethod
    def process(self, data):
        """Process data.
        
        Returns:
            dict: Result.
        """
        pass

# impl_no_docstring.py
class MyProcessor(DataProcessor):
    def process(self, data):
        # No docstring - inherits from abstract
        # ✅ No errors!
        return {"result": data}

# impl_with_docstring.py  
class MyProcessor2(DataProcessor):
    def process(self, data):
        """Process implementation."""
        # ❌ D070: Missing Returns section
        return {"result": data}

Documentation:

  • README.md: Updated with abstract method support section and new error codes (D070/D071/D072)
  • TESTING_ABSTRACT_METHODS.md: Step-by-step testing guide for new users
  • ISSUE_RESPONSE.md: Quick start summary for the GitHub issue

Test Results:

✅ All 250 unit tests pass
✅ Cross-file inheritance tracking working
✅ Docstring inheritance working as expected
✅ CodeQL security scan clean
✅ No breaking changes

Ready for testing!

Original prompt

This section details on the original issue you should resolve

<issue_title>Abstract functions should keep the return and raises docs.</issue_title>
<issue_description>Abstract functions doesn't have a body so they can not have the return and raises segments.

We need to figure out a way to track abstract functions correctly.</issue_description>

<agent_instructions>We need to make sure if the abstract function has raises one of the implementations of this function has raises too. Same goes for return</agent_instructions>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

…ds sections

Co-authored-by: alithethird <39213991+alithethird@users.noreply.github.com>
Copilot AI changed the title [WIP] Update documentation for abstract functions return and raises Allow @abstractmethod to document Returns/Raises/Yields without triggering false positives Nov 9, 2025
Copilot AI requested a review from alithethird November 9, 2025 15:51
@alithethird
Copy link
Copy Markdown
Owner

@copilot abstrack functions/methods can be implemented in different files, does this code cover this usecase?

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Nov 9, 2025

@copilot abstrack functions/methods can be implemented in different files, does this code cover this usecase?

The current implementation handles abstract methods within individual files but does not track inheritance across files. Here's what's currently covered:

What works:

  • Abstract methods can document Returns/Raises/Yields without triggering D031/D051/D041
  • Concrete methods in the same file are still required to document Returns/Raises/Yields when they actually return/raise/yield (D030/D050/D040)

What's not covered:

  • Cross-file inheritance tracking to ensure implementations match abstract method documentation
  • Verifying that concrete implementations in different files have Returns/Raises when the abstract base documents them

Full inheritance tracking across files would require significant architectural changes (building a class hierarchy across all files, tracking method overrides, etc.). This could be considered as a future enhancement.

For now, the tool processes files independently, so it will correctly flag missing Returns/Raises sections on any concrete method that actually returns/raises, regardless of whether it implements an abstract method.

@alithethird
Copy link
Copy Markdown
Owner

@copilot ok I think we can go for the cross-file inheritance tracking

Co-authored-by: alithethird <39213991+alithethird@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Nov 9, 2025

@copilot ok I think we can go for the cross-file inheritance tracking

Implemented cross-file inheritance tracking in commit 5c9b20b.

The tool now uses a two-pass approach:

  1. Pass 1: Collects all abstract methods and concrete implementations across all scanned files
  2. Pass 2: Validates that concrete implementations document Returns/Raises/Yields when their abstract base methods require it

New error codes:

  • D070: Missing Returns section in implementation when abstract documents it
  • D071: Missing Raises section in implementation when abstract documents it
  • D072: Missing Yields section in implementation when abstract documents it

Example output scanning multiple files:

🐍 Scanning path: /tmp/inheritance_test/
🐍 Scan result:
  🚨 /tmp/inheritance_test/impl_bad.py:
  - 7:0 D070 method 'validate' implements abstract method from 'DataProcessor' 
         which documents a return value, but missing Returns section
  - 7:0 D071 method 'validate' implements abstract method from 'DataProcessor' 
         which documents exceptions, but missing Raises section

All 250 tests pass (244 existing + 6 new inheritance tests).

Copilot AI changed the title Allow @abstractmethod to document Returns/Raises/Yields without triggering false positives Allow @abstractmethod to document Returns/Raises/Yields with cross-file inheritance tracking Nov 9, 2025
@alithethird
Copy link
Copy Markdown
Owner

@copilot ok lets build the x64 executable, write some howto and reply to the issue. I will ping one of my friends who requested this feature to test it out. He doesn't have any prior knowledge of this project he just knows it exists but never used so make sure to explain to him how to test out this feature in short

Co-authored-by: alithethird <39213991+alithethird@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Nov 9, 2025

@copilot ok lets build the x64 executable, write some howto and reply to the issue. I will ping one of my friends who requested this feature to test it out. He doesn't have any prior knowledge of this...

Done! Here's what's ready:

x64 Executable Built:

  • Located at: target/x86_64-unknown-linux-gnu/release/vipyrdocs (7.1 MB)
  • Linux x86-64 ELF executable

Testing Documentation Added (commit 159ae70):

  1. TESTING_ABSTRACT_METHODS.md - Complete step-by-step guide with:

    • Installation instructions (pre-built binary or build from source)
    • Three test files to create (base.py, good_impl.py, bad_impl.py)
    • Expected output showing the new D070/D071/D072 errors
    • Single-file test example
    • Troubleshooting tips
  2. ISSUE_RESPONSE.md - Summary for the GitHub issue with:

    • Quick test instructions
    • What's fixed
    • Example test files
    • Expected output

For Your Friend:
The TESTING_ABSTRACT_METHODS.md is designed for someone with no prior knowledge - just needs to:

  1. Get the vipyrdocs executable (download or build)
  2. Create the 3 test Python files (copy-paste from the guide)
  3. Run ./vipyrdocs ~/vipyrdocs_test
  4. See the new inheritance tracking errors (D070/D071/D072) in action

Everything is in the PR and ready to share with the issue!

@alithethird
Copy link
Copy Markdown
Owner

@copilot great! share with the issue

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Nov 9, 2025

@copilot great! share with the issue

Posted to issue #2:


Abstract Method Documentation Feature - Ready for Testing! 🎉

The feature requested in this issue is now complete and ready for testing!

What's Fixed

  1. Abstract methods can now document Returns/Raises/Yields without triggering false positive errors (D031/D051/D041)
  2. Cross-file inheritance tracking ensures concrete implementations properly document the contracts defined by their abstract base methods
  3. New error codes (D070/D071/D072) specifically for inheritance violations

Quick Test

Build from Source

git clone https://github.com/alithethird/vipyrdocs.git
cd vipyrdocs
git checkout copilot/track-abstract-function-docs
cargo build --release

Binary location: target/release/vipyrdocs (or target/x86_64-unknown-linux-gnu/release/vipyrdocs)

Create Test Files

base.py:

from abc import ABC, abstractmethod

class DataProcessor(ABC):
    @abstractmethod
    def process(self, data):
        """Process data.
        
        Args:
            data: Input data.
            
        Returns:
            dict: Processed result.
        """
        pass

impl.py:

from base import DataProcessor

class MyProcessor(DataProcessor):
    def process(self, data):
        """Process implementation.
        
        Args:
            data: Input data.
        """
        # Missing Returns section!
        return {"result": data}

Run & Expected Output

./vipyrdocs .

Output:

🐍 Scanning path: .
🐍 Scan result:
  🚨 impl.py:
  - 11:8 D030 function/ method that returns a value should have the returns section in the docstring
  - 4:0 D070 method 'process' in class 'MyProcessor' implements abstract method from 'DataProcessor' which documents a return value, but this implementation is missing a Returns section in the docstring

Key observations:

  • base.py has NO errors - abstract methods can document Returns without implementation
  • impl.py gets D030 (regular check) + D070 (new inheritance check)

Full Documentation

See TESTING_ABSTRACT_METHODS.md in the PR for complete step-by-step guide with more examples.

Technical Details

  • Two-pass scanning: collects inheritance info from all files, then validates
  • Works across files: tracks abstract methods and implementations in different modules
  • All 250 tests passing
  • No breaking changes

Ready to test! Let me know if you have any questions.

@alithethird
Copy link
Copy Markdown
Owner

@copilot ok I tested this in a codebase and it crashed. Are you capable of downloading a github repository and running vipyrdocs against it? If so I will give you the repo name and you can see for yourself.

BTW it was not crashing before this feature.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Nov 11, 2025

@copilot ok I tested this in a codebase and it crashed. Are you capable of downloading a github repository and running vipyrdocs against it? If so I will give you the repo name and you can see for you...

Yes, I can clone and test against a GitHub repository. Please provide the repository name and I'll investigate the crash.

If you have any additional details about the crash (error message, panic output, or which files it was processing when it crashed), that would also be helpful for debugging.

@copilot ok I tested this in a codebase and it crashed. Are you capable of downloading a github repository and running vipyrdocs against it? If so I will give you the repo name and you can see for you...

Fixed in commit 20bcb6b.

The crash was caused by unsafe UTF-8 string slicing in the find_string_in_text_range function. When the AST provides byte indices that don't align with UTF-8 character boundaries (common with multi-byte characters), direct string indexing s[start..end] would panic.

Solution:

  • Replaced all unsafe s[start..end] slicing with safe .get(start..end)
  • Added boundary validation
  • Return empty results instead of panicking on invalid boundaries

Tested on canonical/repo-policy-compliance:

  • Successfully scanned all 48 Python files
  • Found 330 issues
  • No crashes

All 250 tests still pass. The tool now handles files with any UTF-8 characters safely.

@alithethird
Copy link
Copy Markdown
Owner

@copilot ok this is good, now I don't want to copy the docstring to every implementation I have, can we do somehtihng abotu this? I want it to not error out when the docstring is not there for an implemented function but I also don't want it the docstring to be not there in the implementations.

Also write python code to test this feature fully.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Nov 12, 2025

@copilot ok this is good, now I don't want to copy the docstring to every implementation I have, can we do somehtihng abotu this? I want it to not error out when the docstring is not there for an impl...

I need clarification on the docstring requirement. You mentioned:

  • "I don't want to copy the docstring to every implementation"
  • "I want it to not error out when the docstring is not there"
  • "I also don't want the docstring to be not there in the implementations"

These seem contradictory. Here are some options - which matches your intention?

Option 1: Inherit docstring from abstract method

  • Implementations without docstrings inherit the abstract method's docstring
  • No D070/D071/D072 errors if implementation has no docstring (inherits from abstract)
  • Still errors if implementation has a docstring but missing Returns/Raises sections

Option 2: Make D070/D071/D072 errors warnings only

  • Still report missing sections but don't fail the check
  • You'd see the issues but tool exits successfully

Option 3: Skip D070/D071/D072 checks entirely

  • Only check that implementations actually return/raise (D030/D050)
  • Don't validate against abstract contracts

Which approach do you prefer? I'll also create comprehensive Python test code once I understand the desired behavior.

Created test_abstract_inheritance.py with 10 test cases covering:
- Abstract methods with Returns/Raises/Yields sections
- Cross-file inheritance tracking
- Single-file scenarios
- Multiple base classes
- Different decorator styles (abstractmethod, abc.abstractmethod)
- D070/D071/D072 error validation

Test results show core functionality working correctly (D070/D071/D072 errors properly detected).

Co-authored-by: alithethird <39213991+alithethird@users.noreply.github.com>
@alithethird
Copy link
Copy Markdown
Owner

@copilot ok I still get docstring not provided in an implemented function, I don't want to get that

ali-ugur@ali-ugur-pc ~/work/github-runner-operator/github-runner-manager/src/github_runner_manager[14:49:22]

$ vipyrdocs platform [±main ●]
🐍 Scanning path: platform
🐍 Scan result:
🚨 platform/github_provider.py:

  • 86:4 D010 docstring should be defined for a function/ method/ classd010
    📊 Summary: scanned 5 files; 1 had issues; 1 issue total.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Nov 13, 2025

@copilot ok I still get docstring not provided in an implemented function, I don't want to get that

...

The D010 error you're seeing is the basic "missing docstring" check, which is separate from the abstract method inheritance tracking (D070/D071/D072).

Are you asking for implementations of abstract methods to automatically inherit the docstring from the abstract method, so they don't need their own docstring?

If so, this would mean:

  • Implementation has no docstring → inherits from abstract method → no D010 error
  • Implementation has a docstring → must include Returns/Raises sections if abstract documents them → D070/D071/D072 errors apply

Is this the behavior you want? This would be a significant change to how the tool works (currently D010 applies to all functions/methods regardless of whether they implement abstract methods).

@alithethird
Copy link
Copy Markdown
Owner

@copilot yes, this is what I want

Implementations without docstrings now inherit from their abstract base methods:
- No D010 error (missing docstring) for implementations without docstrings
- No D070/D071/D072 errors for implementations without docstrings (inherit contract)
- Implementations WITH docstrings are still validated normally

This allows developers to avoid duplicating documentation while maintaining contracts.

Co-authored-by: alithethird <39213991+alithethird@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Nov 13, 2025

@copilot yes, this is what I want

Implemented in commit ae14b2a.

Implementations without docstrings now inherit from their abstract base methods:

No docstring = inherits everything:

  • ✅ No D010 (missing docstring)
  • ✅ No D070/D071/D072 (inherits Returns/Raises/Yields)
  • ✅ No D030/D050 (inherits documentation contract)

Has docstring = must document properly:

  • ❌ Still gets D070/D071/D072 if missing Returns/Raises/Yields sections

Example:

# base.py
class Base(ABC):
    @abstractmethod
    def process(self):
        """Process. Returns: str"""
        pass

# No docstring - inherits, no errors
class Impl1(Base):
    def process(self):
        return "done"  # ✅ No errors

# Has docstring - must document Returns
class Impl2(Base):
    def process(self):
        """Implementation."""  # ❌ D070: Missing Returns
        return "done"

This lets you avoid duplicating docstrings while maintaining contracts.

@alithethird
Copy link
Copy Markdown
Owner

@copilot Awesome! Now explain these rules in the README correctly. Also I made some commits to this branch unrelated to new rules

Added comprehensive documentation for:
- Abstract method support and docstring inheritance
- New error codes D070/D071/D072
- Example usage showing inheritance behavior
- Clarified that D031/D051/D041 are skipped for abstract methods

Co-authored-by: alithethird <39213991+alithethird@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Nov 14, 2025

@copilot Awesome! Now explain these rules in the README correctly. Also I made some commits to this branch unrelated to new rules

Updated README in commit 1da3b42.

Added documentation for:

  • Abstract method support with detailed examples
  • Docstring inheritance behavior (no docstring vs. has docstring)
  • New error codes D070/D071/D072 in the rules list
  • Clarified that D031/D051/D041 are skipped for abstract methods

The README now has a complete "Abstract Method Support" section under Usage that explains:

  • How abstract methods can document Returns/Raises/Yields
  • How implementations inherit documentation when they have no docstring
  • How implementations with docstrings are still validated (D070/D071/D072)

@alithethird alithethird marked this pull request as ready for review November 14, 2025 11:27
@alithethird alithethird merged commit c5a6e6a into master Nov 14, 2025
1 check passed
@alithethird alithethird deleted the copilot/track-abstract-function-docs branch November 28, 2025 07:41
alithethird added a commit that referenced this pull request Dec 3, 2025
…n-docs

Allow @AbstractMethod to document Returns/Raises/Yields with cross-file inheritance tracking
alithethird added a commit that referenced this pull request Dec 19, 2025
…n-docs

Allow @AbstractMethod to document Returns/Raises/Yields with cross-file inheritance tracking
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.

Abstract functions should keep the return and raises docs.

2 participants