Skip to content

Extend file stream#12

Closed
kaliv0 wants to merge 3 commits into
mainfrom
extend-file-stream
Closed

Extend file stream#12
kaliv0 wants to merge 3 commits into
mainfrom
extend-file-stream

Conversation

@kaliv0

@kaliv0 kaliv0 commented Jan 26, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added rich, configurable file option classes for CSV, JSON, YAML, XML, and plain text; exposes unified option objects and .yaml/.yml alias support.
  • Chores

    • CI linting switched to check-only modes (no auto-fix).
    • Added an optional dependency for enhanced dict/alias handling.
    • Minor import reorganizations to consolidate module exports.
  • Tests

    • Reorganized tests into class-based suites and greatly expanded coverage for file IO and option behaviors.
  • Documentation

    • Added examples showing usage of the new file option classes.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Jan 26, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a new file-options module and option classes, exposes them via public packages, replaces plain dict file-format mappings with AliasDict (including aliases like .yaml→.yml), adds FileStream option normalization, updates CI lint checks, and restructures/expands tests and test fixtures.

Changes

Cohort / File(s) Summary
CI & Metadata
\.github/workflows/ci.yml, pyproject.toml
CI lint commands switched to non-fixing checks (--no-fix, --check); aldict>=1.1.1 added to optional fs extras.
Public package exports
pyrio/__init__.py, pyrio/utils/__init__.py
Re-exported new option types (e.g., FileOpts, CsvReadOpts, JsonWriteOpts, TextWriteOpts, Mappable) to top-level modules.
New file options module
pyrio/utils/file_options.py
New module adding Mappable base plus classes: FileOpts, CsvReadOpts, CsvWriteOpts, JsonReadOpts, JsonWriteOpts, YamlReadOpts, YamlWriteOpts, XmlReadOpts, XmlWriteOpts, TextWriteOpts and factory helpers.
FileStream changes
pyrio/streams/file_stream.py
Replaced plain dict configs with AliasDict-backed MAPPING_READ_CONFIG/MAPPING_WRITE_CONFIG and DSV_CONFIG; added FileStream._normalize_options helper and updated call sites to normalize option objects.
Small import consolidations
pyrio/decorators/__init__.py, pyrio/exceptions/__init__.py
Grouped/condensed import statements; no API or behavioral changes.
Tests & fixtures
tests/resources/*, tests/test_*.py (multiple)
Added YAML fixtures and extensive new tests for option classes and file-stream behaviors; restructured many test modules from function-based to class-based tests and expanded coverage.
Docs / README
README.md, docs/quickstart.md
Added example NB blocks demonstrating use of the new option classes with FileStream save examples.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant FileStream
    participant Options as FileOpts / FormatOpts
    participant AliasDictConfig as AliasDictConfig
    participant FS as Filesystem

    Caller->>FileStream: save(path, data, options)
    FileStream->>Options: receive options (obj|dict|None)
    Options-->>FileStream: (if object) to_dict via Mappable
    FileStream->>AliasDictConfig: lookup config by path.suffix (handles aliases)
    AliasDictConfig-->>FileStream: format config (delimiter, handler, etc.)
    FileStream->>FS: open + write using normalized options and format config
    FS-->>FileStream: write result / error
    FileStream-->>Caller: success / raise
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I nibble options, tidy and neat,
AliasDict hops to make suffixes meet.
JSON, CSV, YAML in a row,
Normalized choices help data flow.
Tests bundled and shining—hip, hop, repeat! 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Extend file stream' is partially related to the changeset. While it reflects one aspect of the changes (API extensions via new option classes), it does not capture the main changes: adding comprehensive file format option classes (FileOpts, CsvReadOpts, JsonWriteOpts, etc.), introducing the Mappable base class, refactoring file stream configuration to use AliasDict, updating CI workflow linting commands, adding aldict dependency, reorganizing test structure, and updating documentation. The title is overly broad and vague. Consider a more specific title that reflects the primary changes, such as 'Add file format option classes with AliasDict-based configuration' or 'Introduce structured file options and refactor file stream configuration'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pyrio/streams/file_stream.py (1)

170-177: Bug: Wrong config mapping used for write operation.

Line 172 checks suffix in MAPPING_READ_CONFIG but this is within the save() method which should use MAPPING_WRITE_CONFIG. This could cause incorrect behavior when writing files with formats that have different read/write configurations.

🐛 Proposed fix
         if (suffix := path.suffix) in DSV_TYPES:
             return self._write_dsv(path, tmp_path, f_open_options, f_write_options, null_handler)
-        elif suffix in MAPPING_READ_CONFIG:
+        elif suffix in MAPPING_WRITE_CONFIG:
             return self._write_mapping(
                 path, tmp_path, f_open_options, f_write_options, null_handler, **kwargs
             )
🤖 Fix all issues with AI agents
In `@pyrio/streams/file_stream.py`:
- Around line 38-39: In save() in file_stream.py, the suffix check is using the
wrong mapping: replace the condition that tests "suffix in MAPPING_READ_CONFIG"
with "suffix in MAPPING_WRITE_CONFIG" so the write-path uses the write
configuration; ensure the check references the local suffix variable and then
proceeds to use MAPPING_WRITE_CONFIG to look up writer behavior (keep the rest
of save() unchanged).

In `@tests/test_file_stream.py`:
- Around line 442-452: The test currently calls _raise(IOError(...)) during
argument evaluation so the exception fires before FileStream.save runs; instead
defer invocation by passing a callable (e.g., null_handler=lambda:
_raise(IOError("Ooops Mr White...")) or null_handler=functools.partial(_raise,
IOError("Ooops Mr White..."))) so the exception is raised inside
FileStream.save's null handling path; update the test_update_fails to pass the
callable rather than calling _raise directly.
🧹 Nitpick comments (2)
pyrio/utils/file_options.py (1)

1-11: Consider removing ABC inheritance since there are no abstract methods.

Mappable inherits from ABC but defines no @abstractmethod. The ABC base class is typically used to enforce that subclasses implement certain methods. Since Mappable provides concrete implementations of to_dict() and __repr__(), it could be a regular base class.

♻️ Suggested simplification
-from abc import ABC
-
-
-class Mappable(ABC):
+class Mappable:
     def to_dict(self):
         """Returns dict with only non-None values"""
         return {attr: val for attr, val in vars(self).items() if val is not None}
tests/test_stream.py (1)

882-910: Consider moving standalone tests into the TestStream class for consistency.

The test_hackerrank and test_leetcode functions remain as standalone tests while the rest are organized in TestStream. For consistency, these could be moved into the class or into a separate TestExamples class.

Comment thread pyrio/streams/file_stream.py
Comment thread tests/test_file_stream.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@pyrio/utils/file_options.py`:
- Around line 215-232: The static method pretty in class XmlWriteOpts conflicts
with the instance attribute self.pretty set in __init__, causing instance.pretty
to reference the method instead of the boolean; rename the static factory method
(e.g., to pretty_opts or pretty_options) or make it a `@classmethod` with a
different name so it no longer shadows the instance attribute, update its
docstring accordingly and ensure it still returns XmlWriteOpts(pretty=True,
indent=indent).

Comment on lines +215 to +232
class XmlWriteOpts(Mappable):
"""Options for writing XML files"""

def __init__(
self,
pretty=None,
indent=None,
short_empty_elements=None,
):
self.pretty = pretty
self.indent = indent
self.short_empty_elements = short_empty_elements

@staticmethod
def pretty(indent=4):
"""Creates XmlWriteOptions for pretty-printed output"""
return XmlWriteOpts(pretty=True, indent=indent)

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 | 🟠 Major

Static method pretty shadows instance attribute self.pretty.

The static method pretty(indent=4) at line 228 shadows the instance attribute self.pretty set in __init__ at line 224. After instantiation, accessing instance.pretty will return the static method instead of the boolean value.

Consider renaming the static method to avoid the conflict:

🔧 Suggested fix
     `@staticmethod`
-    def pretty(indent=4):
+    def pretty_print(indent=4):
         """Creates XmlWriteOptions for pretty-printed output"""
         return XmlWriteOpts(pretty=True, indent=indent)
🤖 Prompt for AI Agents
In `@pyrio/utils/file_options.py` around lines 215 - 232, The static method pretty
in class XmlWriteOpts conflicts with the instance attribute self.pretty set in
__init__, causing instance.pretty to reference the method instead of the
boolean; rename the static factory method (e.g., to pretty_opts or
pretty_options) or make it a `@classmethod` with a different name so it no longer
shadows the instance attribute, update its docstring accordingly and ensure it
still returns XmlWriteOpts(pretty=True, indent=indent).

@kaliv0 kaliv0 closed this Jan 27, 2026
@kaliv0 kaliv0 deleted the extend-file-stream branch January 27, 2026 22:03
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.

1 participant