Skip to content

Commit 3b55bb8

Browse files
committed
feat: improve test coverage, fix bugs, add closed property, and create issue analysis
This commit improves the stream2py codebase with bug fixes, new features, enhanced test coverage, and comprehensive issue analysis. ## Bug Fixes - fix: Python 3.11+ compatibility in test_util.py - handle TypeError for context manager protocol - fix: add missing open_instance attribute to QuickSourceReader - fix: SimpleSourceReader now returns None instead of raising StopIteration - docs: fix syntax error in __init__.py docstring (missing colon) ## Features - feat: add closed property to SourceReader (#6) - Added closed property similar to io.IOBase.closed - Updated __enter__ and __exit__ to manage _closed flag - Updated QuickSourceReader to properly set closed state - Updated docstring with usage example ## Tests - test: add comprehensive tests for BufferReader blocking parameter - Tests for blocking=True/False behavior - Tests for blocking read when buffer stops - test: add comprehensive tests for QuickSourceReader - Tests for basic functionality, context manager, info, key, iteration - Tests for custom is_valid_data filtering ## Documentation - docs: create comprehensive ISSUE_ANALYSIS.md - Analyzed all 17 open issues - Categorized by status, effort, and dependencies - Identified already-resolved issues (#20, partial #8) - Provided resolution recommendations for each issue ## Test Results - Before: 11 tests (1 failing) - After: 19 tests (all passing) - 8 new tests added - All existing tests fixed and passing ## Issues Addressed - Resolves #6 (closed property for SourceReader) - Documents that #20 is already resolved (blocking parameter exists) - Documents that #8 is partially resolved (blocking exists, timeout could be added)
1 parent 8bf6c1a commit 3b55bb8

7 files changed

Lines changed: 538 additions & 6 deletions

File tree

ISSUE_ANALYSIS.md

Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
# Issue Analysis and Resolution Plan
2+
3+
## Summary
4+
5+
This document analyzes all 17 open issues in the stream2py repository, categorizes them, identifies dependencies, and provides a resolution strategy.
6+
7+
## Issue Status Summary
8+
9+
- **Already Resolved**: 2 issues (#20, partial #8)
10+
- **Simple Fixes**: 4 issues (#6, #10, #18, #9)
11+
- **Medium Effort**: 4 issues (#17, #14, #15, #13)
12+
- **Complex/Ongoing**: 4 issues (#1, #11, #5, #2, #3)
13+
- **External/Needs Investigation**: 2 issues (#4, #16)
14+
15+
---
16+
17+
## Detailed Issue Analysis
18+
19+
### ✅ Already Resolved
20+
21+
#### Issue #20: [Add option to make BufferReader blocking to wait for future data](https://github.com/i2mint/stream2py/issues/20)
22+
- **Status**: RESOLVED ✓
23+
- **Category**: Feature
24+
- **Resolution**: The `blocking` parameter already exists in `BufferReader.read()` (stream2py/buffer_reader.py:329)
25+
- **Recommendation**: Close this issue with a comment explaining that the feature was implemented
26+
- **Code Reference**: `buffer_reader.py:322-401`
27+
28+
#### Issue #8: [Add parameters (block=False, timeout=None) in BufferReader methods](https://github.com/i2mint/stream2py/issues/8)
29+
- **Status**: PARTIALLY RESOLVED
30+
- **Category**: Feature
31+
- **Resolution**: The `blocking` parameter exists; `timeout` parameter is not implemented
32+
- **Effort**: Simple (add timeout support)
33+
- **Recommendation**: Can close or update to focus only on timeout if desired
34+
35+
---
36+
37+
### ✅ Resolved in This PR
38+
39+
#### Issue #6: [a `closed` parameter for SourceReader](https://github.com/i2mint/stream2py/issues/6)
40+
- **Status**: ✓ RESOLVED in this PR
41+
- **Category**: Feature
42+
- **Effort**: Simple
43+
- **Resolution**: Added `closed` property to `SourceReader` class, similar to `io.IOBase.closed`
44+
- **Changes Made**:
45+
- Added `_closed` attribute to track open/close state
46+
- Added `closed` property that returns `self._closed`
47+
- Updated `__enter__` and `__exit__` to manage `_closed` flag
48+
- Updated `QuickSourceReader.open()` and `close()` to set flag
49+
- Updated docstring example to demonstrate usage
50+
- **Code Reference**: `source_reader.py:76,129-137,165-172,244-252`
51+
52+
---
53+
54+
### 🔧 Simple Fixes (Recommended for Next Steps)
55+
56+
#### Issue #10: [Make BufferReader.__next__() more compatible with builtin next()](https://github.com/i2mint/stream2py/issues/10)
57+
- **Status**: Needs review
58+
- **Category**: Enhancement/Bug
59+
- **Effort**: Simple
60+
- **Description**: The `next()` function should raise `StopIteration` or yield the given default value
61+
- **Current Behavior**: `BufferReader.__next__()` returns None while next value is unavailable
62+
- **Expected Behavior**: Should raise `StopIteration` when iterator is exhausted, or return default if provided
63+
- **Recommendation**: Review current implementation and adjust to match Python's iterator protocol
64+
65+
#### Issue #18: [What should happen if we start to read without starting the reader?](https://github.com/i2mint/stream2py/issues/18)
66+
- **Status**: Design question
67+
- **Category**: Enhancement/Design
68+
- **Effort**: Simple
69+
- **Description**: Should raise an exception if user tries to read before entering reader context
70+
- **Recommendation**: Add a check in `BufferReader.read()` to raise a clear exception if the buffer hasn't been started
71+
- **Related**: See wiki on [Forwarding context management](https://github.com/i2mint/stream2py/wiki/Forwarding-context-management)
72+
73+
#### Issue #9: [Not skipping tests and linting](https://github.com/i2mint/stream2py/issues/9)
74+
- **Status**: Unclear what the specific issue is
75+
- **Category**: CI/CD
76+
- **Effort**: Simple
77+
- **Current State**: CI configuration (.github/workflows/ci.yml) runs tests on line 43
78+
- **Recommendation**: Need clarification on what specifically should not be skipped. Current CI runs pytest and pylint.
79+
80+
---
81+
82+
### 🛠️ Medium Effort
83+
84+
#### Issue #17: [Revise BufferReader](https://github.com/i2mint/stream2py/issues/17)
85+
- **Status**: Relevant
86+
- **Category**: Enhancement
87+
- **Effort**: Medium
88+
- **TODOs Identified**:
89+
1. `read` must get its defaults from init ✓ (already done via `_read_kwargs`)
90+
2. `range` must work similarly to `read` (needs review)
91+
3. Which init args should be keyword-only? (design decision)
92+
4. Consider making `read_chk_step` and `read_chk_size` (instead of just `peek`)
93+
- **TODOs in Code**:
94+
- `buffer_reader.py:95` - "should `ignore_no_item_found` default be True to align with iter?"
95+
- `stream_buffer.py:125` - "option to auto restart source on read exception"
96+
- **Recommendation**: Address each TODO item systematically
97+
98+
#### Issue #14: [Add support for slicing joinable data items](https://github.com/i2mint/stream2py/issues/14)
99+
- **Status**: Relevant
100+
- **Category**: Feature
101+
- **Effort**: Medium
102+
- **Description**: For data like waveform chunks that can be joined, `BufferReader.range()` should optionally join and trim to get exact query results
103+
- **Recommendation**: Add optional abstract methods to `SourceReader` for joining and slicing read data items
104+
- **Benefit**: More precise range queries for chunked data
105+
106+
#### Issue #15: [Review exception objects raised and figure out custom ones](https://github.com/i2mint/stream2py/issues/15)
107+
- **Status**: Relevant
108+
- **Category**: Enhancement
109+
- **Effort**: Medium
110+
- **Recommendation**: Audit all exception raising in the codebase and create custom exception classes where appropriate (e.g., `StreamNotStartedError`, `BufferOverflowError`, etc.)
111+
112+
#### Issue #13: [keyboard_and_audio not working in notebook](https://github.com/i2mint/stream2py/issues/13)
113+
- **Status**: Relevant
114+
- **Category**: Bug
115+
- **Effort**: Medium
116+
- **Description**: Terminal-based keyboard input (using termios) doesn't work in notebooks
117+
- **Error**: `termios.error: (25, 'Inappropriate ioctl for device')`
118+
- **Recommendation**: Add conditional imports and provide alternative input method for notebook environments, or document limitation
119+
120+
---
121+
122+
### 📦 Complex/Ongoing (Large Scope)
123+
124+
#### Issue #1: [Create usage examples and helper classes](https://github.com/i2mint/stream2py/issues/1)
125+
- **Status**: Ongoing
126+
- **Category**: Documentation/Examples
127+
- **Effort**: Complex
128+
- **Current Progress**:
129+
- ✓ webcam (moved to videostream2py)
130+
- ✓ keyboard input (moved to keyboardstream2py)
131+
- ✓ audio (moved to audiostream2py)
132+
- ⏳ url stream
133+
- ⏳ General saving to files
134+
- ⏳ Event based actions
135+
- ⏳ Data visualization
136+
- ⏳ BufferConsumer class
137+
- **Recommendation**: Continue incremental progress; many items moved to separate plugin packages
138+
139+
#### Issue #11: [Various sources](https://github.com/i2mint/stream2py/issues/11)
140+
- **Status**: Ongoing
141+
- **Category**: Feature
142+
- **Effort**: Complex
143+
- **Scope**: Create SourceReaders for various sources (webcam video/audio, web-audio, keyboard, mouse, wifi packets, bluetooth, CPU/RAM usage, etc.)
144+
- **Current Progress**: Several moved to separate packages (audiostream2py, videostream2py, keyboardstream2py, etc.)
145+
- **Recommendation**: Continue creating SourceReaders in separate plugin packages
146+
147+
#### Issue #5: [Generalize StreamBuffer and BufferReader consumers](https://github.com/i2mint/stream2py/issues/5)
148+
- **Status**: Relevant
149+
- **Category**: Enhancement/Design
150+
- **Effort**: Complex
151+
- **Description**: Identify common design patterns from example usage and create abstract classes or helpers
152+
- **Patterns to Consider**:
153+
1. Consumers using single source for single purpose
154+
2. Consumers using two sources (one watches for events, performs actions with other)
155+
3. Asynchronous vs synchronous patterns
156+
- **Recommendation**: Work on this after creating more examples to identify patterns
157+
158+
#### Issue #2: [Tag Sound Events](https://github.com/i2mint/stream2py/issues/2)
159+
- **Status**: Relevant (example application)
160+
- **Category**: Example
161+
- **Effort**: Medium-Complex
162+
- **Description**: Create example app to annotate audio events with key presses
163+
- **Recommendation**: Good example project for demonstrating multi-source event handling
164+
165+
#### Issue #3: [Two Source Event Trigger: Record as You Type](https://github.com/i2mint/stream2py/issues/3)
166+
- **Status**: Relevant (example application)
167+
- **Category**: Example
168+
- **Effort**: Medium
169+
- **Description**: Save audio recorded while typing, capturing before/after typing
170+
- **Recommendation**: Good example demonstrating event-triggered recording
171+
172+
---
173+
174+
### 🔍 External/Needs Investigation
175+
176+
#### Issue #4: [New webcam SourceReader](https://github.com/i2mint/stream2py/issues/4)
177+
- **Status**: External
178+
- **Category**: Feature (external)
179+
- **Resolution**: Webcam functionality moved to separate package: [videostream2py](https://github.com/i2mint/videostream2py)
180+
- **Recommendation**: Close with comment directing to videostream2py
181+
182+
#### Issue #16: [Address the BufferReader(...source_reader_info...) issue](https://github.com/i2mint/stream2py/issues/16)
183+
- **Status**: Needs investigation
184+
- **Category**: Bug/Design
185+
- **Reference**: [Review notes on wiki](https://github.com/i2mint/stream2py/wiki/Review-notes)
186+
- **Effort**: Unknown (needs wiki review)
187+
- **Recommendation**: Review wiki notes to understand the issue, then categorize
188+
189+
---
190+
191+
## Dependency Relationships
192+
193+
### No Strong Dependencies
194+
Most issues are independent, but some logical groupings exist:
195+
196+
**Testing & Error Handling Group:**
197+
- #10 (BufferReader.__next__() compatibility)
198+
- #15 (Review exception objects)
199+
- #18 (Read without starting reader)
200+
201+
**Enhancement Group:**
202+
- #17 (Revise BufferReader)
203+
- #14 (Slicing joinable data)
204+
- #8 (Add timeout parameter)
205+
206+
**Examples Group:**
207+
- #1 (Usage examples)
208+
- #2 (Tag Sound Events)
209+
- #3 (Record as You Type)
210+
- #5 (Generalize consumers - depends on examples)
211+
212+
---
213+
214+
## Commit Strategy
215+
216+
### Commits Already Made in This PR:
217+
1. **test: fix Python 3.11+ compatibility in test_util.py**
218+
- Fixed TypeError vs AttributeError for context manager protocol
219+
220+
2. **docs: fix syntax error in __init__.py docstring**
221+
- Added missing colon in property definition
222+
223+
3. **fix: add missing open_instance attribute to QuickSourceReader**
224+
- Prevents AttributeError when accessing info property
225+
226+
4. **fix: SimpleSourceReader should return None instead of raising StopIteration**
227+
- Aligns with SourceReader contract
228+
229+
5. **test: add comprehensive tests for blocking parameter**
230+
- Tests for BufferReader.read(blocking=True/False)
231+
- Tests for blocking behavior when buffer stops
232+
233+
6. **test: add comprehensive tests for QuickSourceReader**
234+
- Tests for basic functionality, context manager, info, key, iteration
235+
- Tests for custom is_valid_data filtering
236+
237+
7. **feat: add closed property to SourceReader (#6)**
238+
- Added closed property similar to io.IOBase.closed
239+
- Updated __enter__ and __exit__ to manage _closed flag
240+
- Updated QuickSourceReader to properly set closed state
241+
- Updated docstring with example usage
242+
243+
### Recommended Next Steps (Future PRs):
244+
245+
**Priority 1 - Quick Wins:**
246+
- Fix #10 (BufferReader.__next__() compatibility)
247+
- Address #18 (Read without starting reader check)
248+
- Clarify #9 (Tests and linting)
249+
250+
**Priority 2 - Medium Effort:**
251+
- Work through #17 TODOs (Revise BufferReader)
252+
- Implement #14 (Slicing joinable data)
253+
- Fix #13 (Notebook compatibility)
254+
- Complete #15 (Custom exceptions)
255+
256+
**Priority 3 - Ongoing:**
257+
- Continue #1 (Examples and helpers)
258+
- Create #2 and #3 example applications
259+
- Work on #5 after more examples exist
260+
261+
**Cleanup:**
262+
- Close #20 (already implemented)
263+
- Close #4 (moved to videostream2py)
264+
- Investigate #16 (review wiki)
265+
266+
---
267+
268+
## Testing Strategy
269+
270+
### Test Coverage Improvements in This PR:
271+
- ✅ Fixed failing test in test_util.py (Python 3.11+ compatibility)
272+
- ✅ Added tests for blocking parameter (2 new tests)
273+
- ✅ Added tests for QuickSourceReader (6 new tests)
274+
- ✅ Fixed QuickSourceReader bug (missing open_instance)
275+
- ✅ Fixed SimpleSourceReader bug (StopIteration handling)
276+
277+
### Test Results:
278+
- **Before**: 11 tests (1 failing)
279+
- **After**: 19 tests (all passing)
280+
- **New Coverage**: BufferReader blocking behavior, QuickSourceReader functionality
281+
282+
---
283+
284+
## Documentation Improvements in This PR:
285+
286+
1. Fixed syntax error in `__init__.py` docstring (line 113)
287+
2. Added documentation for `closed` property in SourceReader
288+
3. Updated SourceReader docstring with example of closed property usage
289+
4. Created comprehensive test files with clear docstrings
290+
291+
---
292+
293+
## Recommendations for Issue Comments
294+
295+
For each issue, I recommend adding a comment with:
296+
- Current status assessment
297+
- Whether it's resolved, in progress, or needs work
298+
- For resolved issues: what code addresses it
299+
- For obsolete issues: why it's no longer relevant
300+
- For actionable issues: estimated effort and approach
301+
302+
---
303+
304+
## Conclusion
305+
306+
This analysis covers all 17 open issues. The work completed in this PR addresses:
307+
- 2 bugs fixed (QuickSourceReader, SimpleSourceReader)
308+
- 1 feature implemented (closed property, #6)
309+
- 1 test compatibility issue fixed
310+
- 8 new tests added
311+
- 1 documentation error fixed
312+
313+
The remaining issues are categorized and prioritized for future work.

stream2py/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ def key(self, data: EnumeratedReadData):
110110
return data[0]
111111
112112
@property
113-
def info(self)
113+
def info(self):
114114
return dict(file=self.file, mode=self.mode)
115115
116116
2. The StreamBuffer

0 commit comments

Comments
 (0)