Skip to content

Conversation

jaysheeldodia
Copy link

Description

This PR resolves issue #174 by implementing intelligent handling of mixed-style docstrings, allowing docformatter to wrap long description lines while preserving the formatting of argument lists (Args/Returns sections). Additionally, it includes critical bug fixes for URL handling and adds definition list detection.

Related Issues

Fixes #174

Problem

Previously, docformatter would not wrap long lines in docstrings when argument lists were present, unless --force-wrap was used. However, --force-wrap would incorrectly wrap the argument lists themselves, making them unreadable:

Before (no wrapping):

"""Split audio at silences to keep under the size limit.

It's important to split near the middle of a silent section to prevent splitting on a spoken word and causing
issues with transcription and diarization.

Args:
    silent_sections: list of silent sections in ms.
    duration: total length of audio in ms
    audio_size: total size of audio file in bytes
    max_file_size: maximum file size that may exist after splits

Returns:
    List of points in ms to use to split the audio file into chunks.
"""

Before (with --force-wrap - incorrect):

"""Split audio at silences to keep under the size limit.

It's important to split near the middle of a silent section to prevent splitting on
a spoken word and causing issues with transcription and diarization.

Args:     silent_sections: list of silent sections in ms.     duration: total length
of audio in ms     audio_size: total size of audio file in bytes     max_file_size:
maximum file size that may exist after splits

Returns:     List of points in ms to use to split the audio file into chunks.
"""

Solution

After (with this fix):

"""Split audio at silences to keep under the size limit.

It's important to split near the middle of a silent section to prevent splitting on
a spoken word and causing issues with transcription and diarization.

Args:
    silent_sections: list of silent sections in ms.
    duration: total length of audio in ms
    audio_size: total size of audio file in bytes
    max_file_size: maximum file size that may exist after splits

Returns:
    List of points in ms to use to split the audio file into chunks.
"""

Changes Made

1. Enhanced Field List Detection (src/docformatter/patterns/fields.py)

  • Mixed-style docstring support: Added logic to detect and preserve Google/NumPy-style sections (Args:, Returns:, etc.) even when using Sphinx/Epytext styles
  • Smart parameter wrapping: Set _wrap_parameters = False for section-based styles to preserve their formatting
  • Cross-style compatibility: When no field lists are found for the current style, check for field lists from other styles and preserve them as-is
  • Comprehensive section detection: Added regex pattern for all common Google-style sections (Args, Returns, Raises, Examples, etc.)

2. Improved List Pattern Recognition (src/docformatter/patterns/lists.py)

  • Style-aware handling: Distinguish between field-based styles (Sphinx/Epytext) and section-based styles (Google/NumPy)
  • Definition list detection: Added sophisticated detection for definition lists with markup (24 lines of new logic)
  • Conservative approach: Only detects definition lists with special markup (like `term`) to avoid false positives
  • Edge case handling: Properly handles inline link continuations, various list markers, and URL patterns
  • Preserved backward compatibility: Maintain existing behavior for pure style docstrings

3. Enhanced Description Wrapping (src/docformatter/strings.py)

  • Selective wrapping: Wrap only the description text before preserved sections, then preserve field lists as-is
  • Improved logic: Enhanced do_split_description() to handle mixed-style scenarios
  • Field section preservation: Added logic to preserve field sections exactly as written while wrapping descriptions

4. Force Wrap Enhancement (src/docformatter/wrappers/description.py)

  • Dedicated shortcut path: Added force_wrap logic that bypasses field list detection entirely
  • Consistent behavior: Ensures --force-wrap always wraps everything as regular text
  • Performance optimization: Avoids unnecessary field list processing when force wrapping

5. Critical URL Regex Fix (src/docformatter/constants.py)

  • Bug fix: Corrected malformed URL_REGEX pattern that was causing incorrect URL splitting
  • Specific fix: Fixed invalid regex syntax [.|\.\. _?[\w. :]+|\.\. _[\w. :]+
  • Prevents URL breaking: Ensures URLs in docstrings are preserved intact across lines

6. Code Quality Improvements

  • Trailing whitespace cleanup: Removed trailing whitespace for code cleanliness
  • Consistent formatting: Improved code consistency across modified files

7. Test Updates

  • Updated expectations: Modified test data to reflect new preservation behavior
  • Behavioral changes: Changed list_patterns.toml expectation from true to false for NumPy sections in Sphinx docs
  • URL test corrections: Updated test_docformatter.py to reflect corrected URL handling
  • Description wrapping: Updated description_wrappers.toml to show new wrapping behavior for mixed-content docstrings

Technical Details

The solution works by:

  1. Multi-style detection: When processing a docstring, the code now checks for field lists from multiple styles, not just the specified style
  2. Selective preservation: Google/NumPy-style sections are marked as non-wrappable (_wrap_parameters = False)
  3. Smart wrapping: Only the description text before these sections gets wrapped, while the sections themselves are preserved exactly as written
  4. Definition list handling: Added conservative detection for definition lists to prevent unwanted wrapping of structured content
  5. URL protection: Fixed regex ensures URLs are properly detected and preserved
  6. Style compatibility: The changes work regardless of the docstring style being used, enabling mixed-style docstrings

Testing

  • ✅ Verified with the exact example from issue Wrapping doesn't work at all when there is an argument list? #174
  • ✅ Confirmed default behavior wraps descriptions but preserves argument lists
  • ✅ Confirmed --force-wrap still works as expected for complete wrapping
  • ✅ All existing tests pass with updated expectations
  • ✅ URL handling regression
  • ✅ Definition list detection prevents false positive wrapping

Behavioral Impact

This change modifies the default behavior for mixed-style docstrings:

  • Before: Mixed-style docstrings would either not wrap at all or wrap incorrectly with --force-wrap
  • After: Descriptions wrap appropriately while preserving structured sections regardless of style mixing
  • Test changes: Several test expectations updated to reflect the improved behavior
  • URL handling: Improved URL detection prevents incorrect line breaking

Backward Compatibility

This change maintains full backward compatibility:

  • Pure-style docstrings continue to work exactly as before
  • The --force-wrap option behavior is unchanged (but improved)
  • No breaking changes to the API or configuration
  • Enhanced functionality is additive, not replacing existing behavior

Files Modified

  • src/docformatter/constants.py - Fixed URL regex pattern
  • src/docformatter/patterns/fields.py - Enhanced field list detection, code cleanup
  • src/docformatter/patterns/lists.py - Added definition list detection, improved style handling
  • src/docformatter/strings.py - Enhanced description splitting logic
  • src/docformatter/wrappers/description.py - Added force wrap shortcut
  • tests/test_docformatter.py - Updated URL handling test expectations
  • tests/_data/string_files/description_wrappers.toml - Updated wrapping expectations
  • tests/_data/string_files/list_patterns.toml - Updated list detection expectations

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update

…-style docstrings

Improve handling of field and section lists for mixed-style docstrings

- Refactor field list detection to preserve Google/NumPy sections when using Sphinx/Epytext styles.
- Update list pattern recognition to distinguish between field-based and section-based styles.
- Ensure only the appropriate sections are wrapped, preserving formatting for others.
- Update description splitting logic to wrap only the description before a preserved section.
- Add force_wrap shortcut to always wrap as regular text.
- Update test data to reflect new logic (NumPy sections in Sphinx-style docs are now preserved).
- Improves compliance with requirements for mixed-style docstrings and prevents unwanted wrapping.
- Fixed malformed URL_REGEX pattern to properly match inline and reference links
- Added conservative detection for definition lists with markup to prevent wrapping
- Removed trailing whitespace for code cleanliness
- Updated test expectations to reflect corrected link handling behavior

This resolves incorrect URL splitting and improves preservation of structured docstring elements.
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.

Wrapping doesn't work at all when there is an argument list?
1 participant