diff --git a/ISSUE_ANALYSIS.md b/ISSUE_ANALYSIS.md new file mode 100644 index 0000000..f385a88 --- /dev/null +++ b/ISSUE_ANALYSIS.md @@ -0,0 +1,267 @@ +# Repository Analysis and Issue Assessment + +## Executive Summary + +This document provides a comprehensive analysis of the `know` repository, including: +- Main functionality assessment +- Test coverage gaps +- Documentation quality evaluation +- Open issue analysis and recommendations + +**Key Findings:** +- The repository has undergone significant refactoring, with core functionality (SlabsIter) moved to `creek`/`meshed` packages +- Current main interface consists of only 3 exported objects +- 4 of 5 open issues relate to deprecated functionality +- Test coverage needs improvement for one main interface function + +--- + +## 1. Main Functionality Analysis + +### 1.1 Current Package Interface + +From `know/__init__.py`, the package exports exactly 3 objects: + +1. **`ContextFanout`** - Imported from `i2` package + - External dependency, tested in `i2` + - Multi-context manager utility + +2. **`any_value_is_none`** - Defined in `know/util.py:207` + - Simple utility function checking if any mapping value is None + - **Missing tests** (see Section 2) + +3. **`ContextualFunc`** - Defined in `know/util.py:41` + - Wraps functions as context managers + - Well-documented with comprehensive doctests + +### 1.2 Deprecated Components + +The following components were previously in `know` but have been relocated: + +- **`SlabsIter`** → Moved to `meshed.slabs` (formerly in `creek.slabs`) +- Related base functionality in `know/base.py` now shows deprecation message +- Existing test file (`test_slabsIter.py`) tests the deprecated import path + +--- + +## 2. Test Coverage Assessment + +### Current State + +| Component | Test Coverage | Status | +|-----------|--------------|---------| +| `ContextFanout` | External (`i2`) | ✓ Not our concern | +| `ContextualFunc` | Comprehensive doctests | ✓ Well tested | +| `any_value_is_none` | None | ✗ **Gap identified** | + +### Test Gaps Identified + +1. **`any_value_is_none`** - No tests exist (no doctests or unit tests) +2. **Import verification** - No test verifying the main exports work correctly + +### Recommendations + +- Add doctest example to `any_value_is_none` +- Create basic integration test verifying main imports + +--- + +## 3. Documentation Assessment + +### Overall Quality: GOOD (with alignment issues) + +| Component | Assessment | Notes | +|-----------|-----------|-------| +| Module docstring (`__init__.py`) | Good | References deprecated components | +| README.md | Good content | Heavily focused on deprecated SlabsIter/audio examples | +| `ContextualFunc` | Excellent | Comprehensive docstring with examples | +| `any_value_is_none` | Adequate | Simple one-line docstring (sufficient for utility) | + +### Documentation Gaps + +1. **README misalignment**: Examples showcase `audio_to_store` and deprecated components rather than current main exports +2. **Migration guide missing**: No clear guidance on where SlabsIter functionality moved +3. **Main exports under-documented**: Current README doesn't explain `ContextualFunc` or `any_value_is_none` + +### Recommendations + +- Add brief note to README about package evolution and what moved to creek/meshed +- Consider adding examples for `ContextualFunc` to README +- Add deprecation warnings in README for old examples + +--- + +## 4. Open Issues Analysis + +### Summary by Status + +| Status | Count | Issue Numbers | +|--------|-------|---------------| +| Obsolete (SlabsIter moved) | 4 | #1, #2, #3, #7 | +| Still Relevant | 1 | #10 | + +--- + +### Issue #1: "audio and keyboard with LiveProc" + +**Opened:** October 21, 2021 (3+ years old) +**Category:** Enhancement/Feature +**Status:** **OBSOLETE** + +**Analysis:** +- Requests refactoring to use `LiveProc` pattern with Sources/Consumers +- No activity since creation +- Core functionality appears to have evolved differently or moved elsewhere +- Package focus has shifted away from this architecture + +**Recommendation:** Close as obsolete. The package has moved in a different direction, with core stream processing functionality moving to other packages (creek, meshed). + +**Effort if pursued:** Complex (requires significant architectural work) + +--- + +### Issue #2: "Merge SlabIter, DAG, and dict_generator" + +**Opened:** September 13, 2022 +**Category:** Refactoring/Architecture +**Status:** **OBSOLETE** + +**Analysis:** +- Requests merging `SlabIter` with other components +- `SlabsIter` has since moved to `meshed.slabs` +- The base issue premise (SlabIter being in this repo) is no longer valid +- No subsequent discussion or work + +**Recommendation:** Close as obsolete. `SlabsIter` is no longer maintained in this repository, having moved to `meshed.slabs`. Any merging work should be tracked in the appropriate repositories. + +**Dependencies:** Originally linked to Issue #1 + +--- + +### Issue #3: "Frontifying slabiter: ideas, tasks, features, problems etc." + +**Opened:** October 27, 2022 +**Category:** Enhancement +**Status:** **OBSOLETE** +**Assigned:** andeaseme + +**Analysis:** +- Enhancement issue for adding frontend to SlabIter +- Tasks include browser output, storage controls, keyboard capture +- `SlabsIter` has moved to `meshed.slabs` +- If this work is still desired, should be tracked in meshed repository + +**Recommendation:** Close as obsolete in this repository. If frontend work for slabiter is still desired, create a new issue in the `meshed` repository where SlabsIter now lives. + +**Effort if pursued in correct repo:** Medium to Complex + +--- + +### Issue #7: "Context not exited when SlabsIter exits" + +**Opened:** December 6, 2022 +**Category:** Bug +**Status:** **LIKELY RESOLVED or OBSOLETE** + +**Analysis:** +- Reports context managers not being cleaned up when SlabsIter exits +- Issue description mentions "later version" shows the error was resolved +- `SlabsIter` has moved to `meshed.slabs` +- If bug still exists, should be tracked in meshed repository +- No reproduction case provided for current codebase + +**Recommendation:** Close as resolved/obsolete. The issue description itself mentions later versions fixed the problem. Additionally, SlabsIter is no longer in this repository. If the issue persists in `meshed.slabs`, it should be reported there. + +**Original Effort:** Medium (context management debugging) + +--- + +### Issue #10: "Deploying Solutions" + +**Opened:** January 17, 2023 +**Category:** Discussion/Documentation/Architecture +**Status:** **STILL RELEVANT** + +**Analysis:** +- High-level discussion of deployment strategies (Docker, RPC, HTTP, serialization, transpilation) +- Not specific to any code in this repository +- More of an architectural research/planning discussion +- No concrete actionable tasks defined +- Not a bug or feature request, but conceptual exploration + +**Recommendation:** This appears to be a design discussion rather than a trackable issue. Consider one of: +1. Convert to GitHub Discussion instead of Issue +2. Create a documentation page capturing these deployment patterns +3. Close with note that specific deployment implementations should be tracked as separate, focused issues +4. Leave open if it's meant to be an umbrella issue for future deployment-related work + +**Assessment:** The content is valuable but doesn't fit the typical issue format. A Discussion or doc page would be more appropriate. + +**Effort:** N/A (discussion/documentation, not implementation) + +--- + +## 5. Commit Strategy + +### Sequential Commit Plan + +Given the findings, the following commit sequence is recommended: + +``` +1. test: add coverage for any_value_is_none + - Add doctest to any_value_is_none function + - Add basic import verification test + +2. docs: update README for current package state + - Add note about SlabsIter migration to meshed.slabs + - Update examples to focus on current main exports + - Add ContextualFunc example to README + +3. docs: add ISSUE_ANALYSIS.md + - This document + +4. issue-comments: Comment on all open issues with assessment + - Will be done via GitHub interface (gh CLI not available) +``` + +### Dependencies + +- No inter-commit dependencies; changes are independent +- Tests → Docs → Issue comments is logical progression +- Creates safety net before documentation changes + +--- + +## 6. Recommendations Summary + +### Immediate Actions + +1. ✅ **Add tests** for `any_value_is_none` +2. ✅ **Update README** to reflect current state +3. ✅ **Comment on issues** #1, #2, #3, #7 recommending closure (obsolete) +4. ✅ **Comment on issue** #10 suggesting conversion to Discussion + +### Future Considerations + +1. Consider if `know` package needs a clearer purpose now that core streaming is in other packages +2. Evaluate whether additional utility functions from `util.py` should be exported +3. Consider removing or archiving deprecated `base.py` entirely +4. Update CI to exclude deprecated test file + +--- + +## 7. Conclusion + +The `know` repository is in a transitional state. Core functionality has been extracted to other packages (`creek`, `meshed`), leaving a minimal but useful interface of utility objects. The open issues reflect this transition, with most relating to functionality that no longer resides here. + +**Repository Health:** Good +- Clean, minimal interface +- Well-tested main components (mostly) +- Clear dependencies + +**Action Required:** Medium +- Close obsolete issues +- Update documentation to reflect current state +- Add missing test coverage + +**Overall Assessment:** Repository is functional and well-maintained, but documentation and issue tracking need updating to reflect architectural evolution. diff --git a/README.md b/README.md index c57a819..ccc2bdb 100644 --- a/README.md +++ b/README.md @@ -4,36 +4,63 @@ Build live stream tools To install: ```pip install know``` -The tools are made to be able to create live streams of data -(e.g. from sensors) and funnel them into proceses with a consistent interfaces. -One important process being the process that will store all or part of -the data, through a simple storage-system-agnositic facade. +The tools are made to be able to create live streams of data +(e.g. from sensors) and funnel them into proceses with a consistent interfaces. +One important process being the process that will store all or part of +the data, through a simple storage-system-agnositic facade. + +> **Note on Package Evolution**: Core streaming functionality (including `SlabsIter`) has been moved to the [`meshed`](https://github.com/i2mint/meshed) package (formerly in [`creek`](https://github.com/i2mint/creek)). The `know` package now focuses on providing utility tools for context management and data processing. For slab iteration and stream processing, please use `meshed.slabs`. + +## Main Exports + +The `know` package currently exports the following main utilities: + +### `ContextualFunc` + +Wrap a function so that it's also a multi-context context manager. This is useful when a function needs specific resources managed by context managers. ```python -proc = LiveProc( - source=Sources( # make a multi-source object (which will manage buffering and timing) - audio=AudioSource(...), - plc=PlcSource(...), - video=VideoSource(...), - ), - services=Services( # make a multi-data service (and/or writer/transformer) object - storage=Store(...), - notifications=Notif(...), - live_viz=LiveViz(...), - ), - ... # other settings for the process (logging, etc.) -) +from know import ContextualFunc +from contextlib import contextmanager + +@contextmanager +def my_resource(): + print('Setting up resource') + yield + print('Cleaning up resource') + +# Wrap your function with the context +def process_data(x): + return x * 2 + +contextual_process = ContextualFunc(process_data, my_resource()) + +# Use it as a context manager +with contextual_process: + result = contextual_process(21) # prints: Setting up resource + print(result) # 42 +# prints: Cleaning up resource +``` + +### `any_value_is_none` + +Simple utility to check if any value in a mapping is None: + +```python +from know import any_value_is_none -proc() # run the process +any_value_is_none({'a': 1, 'b': 2}) # False +any_value_is_none({'a': 1, 'b': None}) # True ``` -With a variety of sources, target storage systems, etc. +### `ContextFanout` +Multi-context manager (imported from `i2` package) for managing multiple contexts at once. -![image](https://user-images.githubusercontent.com/1906276/143310662-a39d146a-7655-4b65-8e7a-d981d366becb.png) +# Historical Examples -# Examples +> **Note**: The following examples demonstrate audio recording and storage capabilities that were part of earlier versions of `know`. These examples still work but represent functionality that may be better suited for specialized packages. The examples are kept here for reference and backward compatibility. ## Recording Audio diff --git a/know/__init__.py b/know/__init__.py index faceb5d..b1d3711 100644 --- a/know/__init__.py +++ b/know/__init__.py @@ -1,34 +1,19 @@ """ Build live stream tools -Essentially being able to do this: - The tools are made to be able to create live streams of data (e.g. from sensors) and funnel them into proceses with a consistent interfaces. One important process being the process that will store all or part of the data, through a simple storage-system-agnositic facade. -```python -proc = LiveProc( - source=Sources( # make a multi-source object (which will manage buffering and timing) - audio=AudioSource(...), - plc=PlcSource(...), - video=VideoSource(...), - ), - consumers=Consumers( # make a multi-data consumer (and/or writer/transformer) object - storage=Store(...), - notifications=Notif(...), - live_viz=LiveViz(...), - ), - ... # other settings for the process (logging, etc.) -) - -proc() # run the process -``` - -With a variety of sources, target storage systems, etc. - +Note: Core streaming functionality (SlabsIter) has moved to the meshed package. +This package now focuses on providing utility tools for context management +and data processing. +Main exports: +- ContextualFunc: Wrap functions as context managers +- any_value_is_none: Check if any mapping value is None +- ContextFanout: Multi-context manager (from i2) """ from know.util import ContextFanout, any_value_is_none, ContextualFunc diff --git a/know/tests/test_main_exports.py b/know/tests/test_main_exports.py new file mode 100644 index 0000000..723de5e --- /dev/null +++ b/know/tests/test_main_exports.py @@ -0,0 +1,62 @@ +"""Tests for main package exports from know/__init__.py""" + +import pytest + + +def test_main_imports(): + """Test that main exports can be imported from the package root""" + from know import ContextFanout, any_value_is_none, ContextualFunc + + # Verify they're all callable or usable + assert callable(ContextFanout) + assert callable(any_value_is_none) + assert callable(ContextualFunc) + + +def test_any_value_is_none(): + """Test any_value_is_none function behavior""" + from know import any_value_is_none + + # Test with no None values + assert any_value_is_none({'a': 1, 'b': 2, 'c': 3}) is False + + # Test with None value + assert any_value_is_none({'a': 1, 'b': None, 'c': 3}) is True + + # Test with empty dict + assert any_value_is_none({}) is False + + # Test with all None values + assert any_value_is_none({'a': None, 'b': None}) is True + + +def test_contextual_func_basic(): + """Test ContextualFunc basic functionality""" + from know import ContextualFunc + from contextlib import contextmanager + + # Track context state + context_states = [] + + @contextmanager + def test_context(): + context_states.append('entered') + yield + context_states.append('exited') + + # Create a simple function + def add_one(x): + return x + 1 + + # Wrap it with context + contextual_add = ContextualFunc(add_one, test_context()) + + # Test that function works + assert contextual_add(5) == 6 + + # Test that context manager works + with contextual_add: + assert contextual_add(10) == 11 + + # Verify context was entered and exited + assert context_states == ['entered', 'exited'] diff --git a/know/util.py b/know/util.py index e5dc854..b3293c4 100644 --- a/know/util.py +++ b/know/util.py @@ -205,7 +205,15 @@ def always_false(x: Any) -> False: def any_value_is_none(d: Mapping): - """Returns True if any value of the mapping is None""" + """Returns True if any value of the mapping is None + + >>> any_value_is_none({'a': 1, 'b': 2, 'c': 3}) + False + >>> any_value_is_none({'a': 1, 'b': None, 'c': 3}) + True + >>> any_value_is_none({}) + False + """ return any(d[k] is None for k in d)