codeupipe 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. codeupipe/__init__.py +39 -0
  2. codeupipe/cli.py +1502 -0
  3. codeupipe/converter/__init__.py +9 -0
  4. codeupipe/converter/config.py +119 -0
  5. codeupipe/converter/filters/__init__.py +21 -0
  6. codeupipe/converter/filters/analyze.py +60 -0
  7. codeupipe/converter/filters/classify.py +52 -0
  8. codeupipe/converter/filters/classify_files.py +61 -0
  9. codeupipe/converter/filters/generate_export.py +187 -0
  10. codeupipe/converter/filters/generate_import.py +229 -0
  11. codeupipe/converter/filters/parse_config.py +26 -0
  12. codeupipe/converter/filters/scan_project.py +52 -0
  13. codeupipe/converter/pipelines/__init__.py +8 -0
  14. codeupipe/converter/pipelines/export_pipeline.py +40 -0
  15. codeupipe/converter/pipelines/import_pipeline.py +40 -0
  16. codeupipe/converter/taps/__init__.py +7 -0
  17. codeupipe/converter/taps/conversion_log.py +46 -0
  18. codeupipe/core/__init__.py +20 -0
  19. codeupipe/core/filter.py +27 -0
  20. codeupipe/core/hook.py +34 -0
  21. codeupipe/core/payload.py +94 -0
  22. codeupipe/core/pipeline.py +231 -0
  23. codeupipe/core/state.py +78 -0
  24. codeupipe/core/stream_filter.py +33 -0
  25. codeupipe/core/tap.py +27 -0
  26. codeupipe/core/valve.py +52 -0
  27. codeupipe/linter/__init__.py +57 -0
  28. codeupipe/linter/assemble_doc_report.py +97 -0
  29. codeupipe/linter/assemble_report.py +140 -0
  30. codeupipe/linter/check_bundle.py +47 -0
  31. codeupipe/linter/check_index.py +88 -0
  32. codeupipe/linter/check_naming.py +47 -0
  33. codeupipe/linter/check_protocols.py +73 -0
  34. codeupipe/linter/check_structure.py +41 -0
  35. codeupipe/linter/check_symbols.py +116 -0
  36. codeupipe/linter/check_tests.py +48 -0
  37. codeupipe/linter/coverage_pipeline.py +39 -0
  38. codeupipe/linter/detect_drift.py +44 -0
  39. codeupipe/linter/detect_orphans.py +106 -0
  40. codeupipe/linter/doc_check_pipeline.py +28 -0
  41. codeupipe/linter/git_history.py +130 -0
  42. codeupipe/linter/lint_pipeline.py +51 -0
  43. codeupipe/linter/map_coverage.py +84 -0
  44. codeupipe/linter/report_gaps.py +68 -0
  45. codeupipe/linter/report_pipeline.py +49 -0
  46. codeupipe/linter/resolve_refs.py +48 -0
  47. codeupipe/linter/scan_components.py +95 -0
  48. codeupipe/linter/scan_directory.py +123 -0
  49. codeupipe/linter/scan_docs.py +62 -0
  50. codeupipe/linter/scan_tests.py +104 -0
  51. codeupipe/py.typed +1 -0
  52. codeupipe/testing.py +344 -0
  53. codeupipe/utils/__init__.py +10 -0
  54. codeupipe/utils/error_handling.py +68 -0
  55. codeupipe-0.1.0.dist-info/METADATA +216 -0
  56. codeupipe-0.1.0.dist-info/RECORD +60 -0
  57. codeupipe-0.1.0.dist-info/WHEEL +5 -0
  58. codeupipe-0.1.0.dist-info/entry_points.txt +2 -0
  59. codeupipe-0.1.0.dist-info/licenses/LICENSE +190 -0
  60. codeupipe-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,68 @@
1
+ """
2
+ Error Handling: The Resilience Layer
3
+
4
+ Handle errors comprehensively, with retry logic and proper error propagation.
5
+ """
6
+
7
+ import inspect
8
+ from typing import Callable, Optional, List, Tuple
9
+ from codeupipe.core.payload import Payload
10
+ from codeupipe.core.filter import Filter
11
+
12
+ __all__ = ["ErrorHandlingMixin", "RetryFilter"]
13
+
14
+
15
+ class ErrorHandlingMixin:
16
+ """
17
+ Mixin for pipelines to handle errors with routing.
18
+ """
19
+
20
+ def __init__(self):
21
+ self.error_connections: List[Tuple[str, str, Callable[[Exception], bool]]] = []
22
+
23
+ def on_error(self, source: str, handler: str, condition: Callable[[Exception], bool]) -> None:
24
+ """Add error routing."""
25
+ self.error_connections.append((source, handler, condition))
26
+
27
+ async def _handle_error(self, filter_name: str, error: Exception, payload: Payload) -> Optional[Payload]:
28
+ """Find and call the matching error handler."""
29
+ for src, hdl, cond in self.error_connections:
30
+ if src == filter_name and cond(error):
31
+ handler = getattr(self, 'filters', {}).get(hdl)
32
+ if handler and hasattr(handler, 'call'):
33
+ result = handler.call(payload.insert("error", str(error)))
34
+ if inspect.isawaitable(result):
35
+ result = await result
36
+ return result
37
+ return None
38
+
39
+
40
+ class RetryFilter:
41
+ """Retry wrapper — wraps a filter with retry logic for resilience."""
42
+
43
+ def __init__(self, inner_filter: Filter, max_retries: int = 3):
44
+ self.inner = inner_filter
45
+ self.max_retries = max(0, max_retries)
46
+
47
+ @staticmethod
48
+ async def _invoke(fn, *args):
49
+ """Call fn(*args), awaiting the result only if it is a coroutine."""
50
+ result = fn(*args)
51
+ if inspect.isawaitable(result):
52
+ result = await result
53
+ return result
54
+
55
+ async def call(self, payload: Payload) -> Payload:
56
+ if self.max_retries == 0:
57
+ try:
58
+ return await self._invoke(self.inner.call, payload)
59
+ except Exception as e:
60
+ return payload.insert("error", f"Max retries: {e}")
61
+
62
+ for attempt in range(self.max_retries):
63
+ try:
64
+ return await self._invoke(self.inner.call, payload)
65
+ except Exception as e:
66
+ if attempt == self.max_retries - 1:
67
+ return payload.insert("error", f"Max retries: {e}")
68
+ return payload
@@ -0,0 +1,216 @@
1
+ Metadata-Version: 2.4
2
+ Name: codeupipe
3
+ Version: 0.1.0
4
+ Summary: Python pipeline framework — composable Payload-Filter-Pipeline pattern
5
+ Author: Joshua Wink
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/codeuchain/codeupipe
8
+ Project-URL: Repository, https://github.com/codeuchain/codeupipe
9
+ Project-URL: Issues, https://github.com/codeuchain/codeupipe/issues
10
+ Keywords: pipeline,filter,payload,etl,workflow,streaming
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Dynamic: license-file
26
+
27
+ # codeupipe
28
+
29
+ <!-- cup:ref file=codeupipe/__init__.py hash=afd4ab5 -->
30
+
31
+ Python pipeline framework — composable **Payload → Filter → Pipeline** pattern with streaming support. Zero external dependencies.
32
+
33
+ Experimental successor to [codeuchain](https://github.com/codeuchain/codeuchain) (Python only).
34
+
35
+ <!-- /cup:ref -->
36
+
37
+ ## Core Concepts
38
+
39
+ <!-- cup:ref file=codeupipe/core/__init__.py hash=e3e2418 -->
40
+ | Concept | Role |
41
+ |---|---|
42
+ | **Payload** | Immutable data container flowing through the pipeline |
43
+ | **MutablePayload** | Mutable sibling for performance-critical bulk edits |
44
+ | **Filter** | Processing unit — takes a Payload in, returns a transformed Payload out (sync or async) |
45
+ | **StreamFilter** | Streaming processing unit — receives one chunk, yields 0, 1, or N output chunks |
46
+ | **Pipeline** | Orchestrator — `.run()` for batch, `.stream()` for streaming |
47
+ | **Valve** | Conditional flow control — gates a Filter with a predicate |
48
+ | **Tap** | Non-modifying observation point — inspect without changing (sync or async) |
49
+ | **State** | Pipeline execution metadata — tracks what ran, what was skipped, errors, chunk counts |
50
+ | **Hook** | Lifecycle hooks — before/after/on_error for pipeline execution (sync or async) |
51
+ | **RetryFilter** | Resilience wrapper — retries a Filter up to N times before giving up |
52
+ <!-- /cup:ref -->
53
+
54
+ ## Install
55
+
56
+ ```bash
57
+ pip install -e .
58
+ ```
59
+
60
+ ## Quick Start
61
+
62
+ ```python
63
+ import asyncio
64
+ from codeupipe import Payload, Pipeline
65
+
66
+ # Filters can be sync or async — both work
67
+ class CleanInput:
68
+ def call(self, payload):
69
+ return payload.insert("text", payload.get("text", "").strip())
70
+
71
+ class Validate:
72
+ def call(self, payload):
73
+ if not payload.get("text"):
74
+ raise ValueError("Empty input")
75
+ return payload
76
+
77
+ # Build and run
78
+ pipeline = Pipeline()
79
+ pipeline.add_filter(CleanInput(), name="clean")
80
+ pipeline.add_filter(Validate(), name="validate")
81
+
82
+ result = asyncio.run(pipeline.run(Payload({"text": " hello "})))
83
+ print(result.get("text")) # "hello"
84
+ ```
85
+
86
+ ## Valve (Conditional Flow)
87
+
88
+ ```python
89
+ from codeupipe import Valve
90
+
91
+ class DiscountFilter:
92
+ def call(self, payload):
93
+ price = payload.get("price", 0)
94
+ return payload.insert("price", price * 0.9)
95
+
96
+ # Only applies when predicate returns True
97
+ pipeline.add_filter(
98
+ Valve("discount", DiscountFilter(), lambda p: p.get("tier") == "premium"),
99
+ name="discount",
100
+ )
101
+ ```
102
+
103
+ ## Tap (Observation)
104
+
105
+ ```python
106
+ class AuditTap:
107
+ async def observe(self, payload):
108
+ print(f"Payload at this point: {payload.to_dict()}")
109
+
110
+ pipeline.add_tap(AuditTap(), name="audit")
111
+ ```
112
+
113
+ ## Streaming
114
+
115
+ Process an async stream of chunks through the same pipeline at constant memory.
116
+
117
+ ```python
118
+ from codeupipe import Payload, Pipeline
119
+
120
+ class UppercaseFilter:
121
+ def call(self, payload):
122
+ return payload.insert("name", payload.get("name", "").upper())
123
+
124
+ async def names():
125
+ for n in ["alice", "bob", "charlie"]:
126
+ yield Payload({"name": n})
127
+
128
+ async def main():
129
+ pipeline = Pipeline()
130
+ pipeline.add_filter(UppercaseFilter(), name="upper")
131
+
132
+ async for result in pipeline.stream(names()):
133
+ print(result.get("name")) # ALICE, BOB, CHARLIE
134
+
135
+ asyncio.run(main())
136
+ ```
137
+
138
+ Use `StreamFilter` to drop, fan-out, or batch:
139
+
140
+ ```python
141
+ from typing import AsyncIterator
142
+
143
+ class DropEmpty:
144
+ async def stream(self, chunk: Payload) -> AsyncIterator[Payload]:
145
+ if chunk.get("line", "").strip():
146
+ yield chunk
147
+
148
+ class SplitWords:
149
+ async def stream(self, chunk: Payload) -> AsyncIterator[Payload]:
150
+ for word in chunk.get("text", "").split():
151
+ yield Payload({"word": word})
152
+ ```
153
+
154
+ ## Execution State
155
+
156
+ ```python
157
+ result = await pipeline.run(payload)
158
+ print(pipeline.state.executed) # ['clean', 'validate']
159
+ print(pipeline.state.skipped) # ['admin_only']
160
+ print(pipeline.state.chunks_processed) # {'upper': 3} (streaming mode)
161
+ ```
162
+
163
+ ## Docs
164
+
165
+ | Document | Purpose |
166
+ |----------|---------|
167
+ | [INDEX.md](INDEX.md) | Project structure map (verified by `cup doc-check`) |
168
+ | [CONCEPTS.md](CONCEPTS.md) | Full API reference with runnable examples |
169
+ | [BEST_PRACTICES.md](BEST_PRACTICES.md) | Project structure, naming, testing strategy |
170
+ | [SKILL.md](SKILL.md) | Agent skill reference — types, patterns, conversion |
171
+
172
+ ## CLI (`cup`)
173
+
174
+ <!-- cup:ref file=codeupipe/cli.py symbols=main,scaffold,bundle,lint,coverage,report,doc_check hash=1e63d0e -->
175
+ The `cup` command-line tool scaffolds, lints, and analyzes CUP projects:
176
+
177
+ ```bash
178
+ cup new filter validate_email src/signup # Scaffold a filter + test
179
+ cup new pipeline signup src/signup --steps validate_email hash_password
180
+ cup list # Show available component types
181
+ cup bundle src/signup # Generate __init__.py re-exports
182
+ cup lint src/signup # Check CUP conventions (CUP000–CUP008)
183
+ cup coverage src/signup # Map component↔test coverage gaps
184
+ cup report src/signup # Health report with scores, orphans, staleness
185
+ cup doc-check . # Verify doc freshness (cup:ref markers)
186
+ ```
187
+ <!-- /cup:ref -->
188
+
189
+ ## Testing Utilities
190
+
191
+ <!-- cup:ref file=codeupipe/testing.py symbols=run_filter,assert_payload,mock_filter hash=c119f9c -->
192
+ `codeupipe.testing` provides zero-boilerplate test helpers:
193
+
194
+ ```python
195
+ from codeupipe.testing import run_filter, assert_payload, mock_filter
196
+
197
+ def test_my_filter():
198
+ result = run_filter(MyFilter(), {"input": "data"})
199
+ assert_payload(result, output="expected")
200
+
201
+ def test_with_mock():
202
+ f = mock_filter(status="ok")
203
+ result = run_filter(f, {"x": 1})
204
+ assert f.call_count == 1
205
+ ```
206
+ <!-- /cup:ref -->
207
+
208
+ ## Test
209
+
210
+ ```bash
211
+ pytest # 909 tests
212
+ ```
213
+
214
+ ## License
215
+
216
+ Apache 2.0
@@ -0,0 +1,60 @@
1
+ codeupipe/__init__.py,sha256=r9SrW3xhMlkYv319tjrw3Bo75C9_vI4LkKFGe8DV6J8,1693
2
+ codeupipe/cli.py,sha256=HmPQ4ODJt2jEM2knkOseAp-YGY2nrjOHUVwiQZGX0YQ,44383
3
+ codeupipe/py.typed,sha256=q6n3HRnk8qP3ZQEZ6rlHfzcbJHLhoCbNBdY6edgwavo,58
4
+ codeupipe/testing.py,sha256=wRn5xjtHUe9O7u8SIp3Lzo2ozZ_44YNXwdyKfrYy0EM,9875
5
+ codeupipe/converter/__init__.py,sha256=EXQw70YUwxy7eIMTGweCaCZpeI3ZRaB2KbM7iU9p6RE,277
6
+ codeupipe/converter/config.py,sha256=GnqX1b9wtEAQT8KBl8qR2W9mIIEAwYN15gH3opQWHxQ,3775
7
+ codeupipe/converter/filters/__init__.py,sha256=kDtpvv1Zj91RMP0mcA59POffhNtBI4ZXaqel47SujvE,605
8
+ codeupipe/converter/filters/analyze.py,sha256=jUJ95juVFV6raQ98MYGZwLSIU2wg5GQlfmGhuOpoeE0,1901
9
+ codeupipe/converter/filters/classify.py,sha256=v4pjttb6DCvwaDWWdAzrBQDiWf3RZTaBqG06W9q4bF8,1721
10
+ codeupipe/converter/filters/classify_files.py,sha256=7XBi0_PK066KT3EhyMEaZrZyE2sMLtH7_lGQmb148N8,1968
11
+ codeupipe/converter/filters/generate_export.py,sha256=SQk_ubA9OnBorGhAGOptx6_GvHOKbB63O_ES-NZfW4o,6401
12
+ codeupipe/converter/filters/generate_import.py,sha256=x2eYitYhuJR79WhRH2qOkaQ7o79EBGGvt-FI8opq-2c,7101
13
+ codeupipe/converter/filters/parse_config.py,sha256=KKpeS2EXTWU3YzVM8Vv2PvN0uNhdAsENGaQi3u2-uzk,778
14
+ codeupipe/converter/filters/scan_project.py,sha256=e36ZDIOt4bNmgbeGda1NyXWzGGTxbsAWmW-0mJzcvI0,1751
15
+ codeupipe/converter/pipelines/__init__.py,sha256=9wTDQTr7A42hWpf8LHEWZjA7BpeQ6fBLywEI1F-x0oE,241
16
+ codeupipe/converter/pipelines/export_pipeline.py,sha256=TMn4jTpUJYz3YKsVQP23r7p3Md2bSe02zW3izeMHRaA,1568
17
+ codeupipe/converter/pipelines/import_pipeline.py,sha256=rhgn0Nk_7lsNvN_7wXgoI9_akYYLZGOTSxgqalJBOcs,1569
18
+ codeupipe/converter/taps/__init__.py,sha256=fmz16CMS9DVcvxWwuw8dxvgxzqxQ0f94GxOk0ZrC3co,150
19
+ codeupipe/converter/taps/conversion_log.py,sha256=22G_j_3A4pb-z1F4vKsH_o0T8O7mEwmVJzk68YkhGvI,1467
20
+ codeupipe/core/__init__.py,sha256=4-JBg2oQirHYcxV5bdFMAA7bViDL4kL2dSJDlKf5pCk,489
21
+ codeupipe/core/filter.py,sha256=GADRJIIQkH9smw1mq269q1UyuhSovuwNkrV3oHiqAgE,826
22
+ codeupipe/core/hook.py,sha256=hjOfSGObWCM7_JvCVcQ3MSUJ6oJa_obrGKYcJwSJq-M,1033
23
+ codeupipe/core/payload.py,sha256=CjOxJMUlJ2SSykIRtmvPbWUh_dGwOm0zkWsLg7atIis,3072
24
+ codeupipe/core/pipeline.py,sha256=gMDE67qPloXHGFkUv7BbZoKykiv1_RCkWn_lFvUQ-B0,8546
25
+ codeupipe/core/state.py,sha256=LO6E3uvCXA_qXmTHCEYYkvhJCNQfWQfz_-SWWmHVrxU,2527
26
+ codeupipe/core/stream_filter.py,sha256=ZrQ3TRdee3BbpT4dySe2hTT2ebW_eti6mVRLS3ZafXc,1097
27
+ codeupipe/core/tap.py,sha256=w0QHjj5e5c8VWC4JJHDWah3OlnbqwBpvNuE8TMMfaZI,705
28
+ codeupipe/core/valve.py,sha256=-vZCcM-HtEKx1RlKd7gnbkalLN6jQVcPsSqRW-wSuVM,1603
29
+ codeupipe/linter/__init__.py,sha256=hObwecsaWW-rCfTycVKIUHVdke_K8E7tF6Jxng4Ypnk,1613
30
+ codeupipe/linter/assemble_doc_report.py,sha256=hRjz7NcAn4ptclCibEkazqFtAZw8IZnRhkPDYemKI6E,3175
31
+ codeupipe/linter/assemble_report.py,sha256=h0D8BVq0lHvjjcirkF9RcRKK7vWIlGdq2_Xjh7GzohI,4699
32
+ codeupipe/linter/check_bundle.py,sha256=lOYLEMzu3qrh-AwGy73bmvuQ_AROpKqPZpZxd-a8bk0,1437
33
+ codeupipe/linter/check_index.py,sha256=_8vMhpPRXxNbSKMJ-PZ1rjDs7tUhc0c4txRuuNLZwHI,3021
34
+ codeupipe/linter/check_naming.py,sha256=DVDgwqfIdRbhPRFgdFnuprnmbQKrGr2l3n61-fS2sN8,1306
35
+ codeupipe/linter/check_protocols.py,sha256=wY2VCguYZsqDH-1aU7jjue3T09hmqVF6jguE0JJJp4Y,2500
36
+ codeupipe/linter/check_structure.py,sha256=y62mk85A272UFj0t2EUsEA9Fc4Q2Y_Bso8MDpzB8quU,1209
37
+ codeupipe/linter/check_symbols.py,sha256=4Z6_O1xvrdNeAyUub6_RpX_KXYq2OO8olWpNwQSjkFI,4377
38
+ codeupipe/linter/check_tests.py,sha256=JNZLX3I6o0eY_fnp3Z12W6911HpGQdanJiUyCumU2iw,1418
39
+ codeupipe/linter/coverage_pipeline.py,sha256=AE97iUioYM1Ujj_zaY3PZI4zRBHTgq8SBdqjHe36imY,1115
40
+ codeupipe/linter/detect_drift.py,sha256=TZIN_Pl0KPwzCFQY4-1a9IbjOBqb3Pg5eHYFdR3lRhA,1358
41
+ codeupipe/linter/detect_orphans.py,sha256=FMS23rKW25vsz7Zi6dQKJ_zs1eFN2C4h4wZnTzZcpiU,4083
42
+ codeupipe/linter/doc_check_pipeline.py,sha256=AOYtxvIbTmYNjzwo6d8LliThT8RLQiyOaedX_akuZVc,974
43
+ codeupipe/linter/git_history.py,sha256=0pq-eRBUe45ShJ1XS4qmboOwLCu76B_KAV8PuUUUN0o,4143
44
+ codeupipe/linter/lint_pipeline.py,sha256=zP9JPXkt7zmh7ofsy6QnwlOQ84ssP3depAmXR0bBWLo,1614
45
+ codeupipe/linter/map_coverage.py,sha256=jQAuoOMAxQjNxsf8fVcJooC5idguJr1zTzbfZRSuOxc,3154
46
+ codeupipe/linter/report_gaps.py,sha256=IGgaIDvpZfHPZKEFO3TCTfT_tuWujfUKYVoUt-OCrt4,2379
47
+ codeupipe/linter/report_pipeline.py,sha256=FfYcVQmz0rp2rgB4LHW127_imhNVX6gyAnkHzjQnIBk,1706
48
+ codeupipe/linter/resolve_refs.py,sha256=470dUAJJLD6QzHVAtAt1CbbQ3Lwx6v4CIFxVM6usibU,1364
49
+ codeupipe/linter/scan_components.py,sha256=9OUv09x_vMXHA-1JFKb4Qz6Azc38Uqe0i-QdYCe6stc,3158
50
+ codeupipe/linter/scan_directory.py,sha256=POuwrnL67-KbPOSl6P99asPmgzr1ObsoqDTbVPX-kxE,3428
51
+ codeupipe/linter/scan_docs.py,sha256=ubRPWgpVvkL6UMOIAvkeM5bjJs40-8O6ySm7SMKGlR0,1742
52
+ codeupipe/linter/scan_tests.py,sha256=0e2HbD1Yorl-3-NVZjnoOzqbkytWPTmf8LSeU4J00JQ,3649
53
+ codeupipe/utils/__init__.py,sha256=nD-GI0Aa3jRI9IkeO1h0_pLrpCkk560KwFFpYPBrZOw,251
54
+ codeupipe/utils/error_handling.py,sha256=3A9ezyAnpPBk7bmvrhE9jDDFNJu0p-LihekqxVFl3y0,2454
55
+ codeupipe-0.1.0.dist-info/licenses/LICENSE,sha256=hXeUgDoSFz7VEJRRuNN06YrixVVVebx3_tvykHFGnfU,11423
56
+ codeupipe-0.1.0.dist-info/METADATA,sha256=eNwec1PM4W9FSNfiY5mtMTpeFb1UNK6KuX2v6p5I8zQ,6857
57
+ codeupipe-0.1.0.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
58
+ codeupipe-0.1.0.dist-info/entry_points.txt,sha256=tlNGKAcEvZvHZIVSiPw0Y9FSHZkY6xTf5IMmp0-7zkg,43
59
+ codeupipe-0.1.0.dist-info/top_level.txt,sha256=Wk0Sn2Lrx_OmF4pXZORMCRSk7-ycNX1nGlXmsW1uyfA,10
60
+ codeupipe-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ cup = codeupipe.cli:main
@@ -0,0 +1,190 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity granting the License,
13
+ including any individual or entity that controls, is controlled by, or is
14
+ under common control with such entity. For the purposes of this License,
15
+ "control" means (i) the power, direct or indirect, to cause the direction
16
+ or management of such entity, whether by contract or otherwise, or (ii)
17
+ ownership of fifty percent (50%) or more of the outstanding shares, or
18
+ (iii) beneficial ownership of such entity.
19
+
20
+ "You" (or "Your") shall mean an individual or legal entity exercising
21
+ permissions granted by this License.
22
+
23
+ "Source" form shall mean the preferred form for making modifications,
24
+ including but not limited to software source code, documentation source,
25
+ and configuration files.
26
+
27
+ "Object" form shall mean any form resulting from mechanical transformation
28
+ or translation of a Source form, including but not limited to compiled
29
+ object code, generated documentation, and conversions to other media types.
30
+
31
+ "Work" shall mean the work of authorship, whether in Source or Object form,
32
+ made available under the terms of this License, as indicated by a copyright
33
+ notice that is included in or attached to the work (which, for the purposes
34
+ of this License, shall not be modified except as required by this License).
35
+
36
+ "Derivative Works" shall mean any work, whether in Source or Object form,
37
+ that is based upon (or derived from) the Work and for which the editorial
38
+ revisions, annotations, elaborations, or other modifications represent, as
39
+ a whole, an original work of authorship. For the purposes of this License,
40
+ Derivative Works shall not include works that remain separable from, or
41
+ merely link (or bind by name) to the interfaces of, the Work and derivative
42
+ works thereof.
43
+
44
+ "Contribution" shall mean any work of authorship, including the original
45
+ version of the Work and any modifications or additions to that Work or
46
+ Derivative Works thereof, that is intentionally submitted to Licensor for
47
+ inclusion in the Work by the copyright owner or by an individual or legal
48
+ entity authorized to submit on behalf of the copyright owner. For the
49
+ purposes of this definition, "submitted" means any form of electronic,
50
+ verbal, or written communication sent to the Licensor or its
51
+ representatives, including but not limited to communication on electronic
52
+ mailing lists, source code control systems, and issue tracking systems that
53
+ are managed by, or on behalf of, the Licensor for the purpose of discussing
54
+ and improving the Work, but excluding communication that is conspicuously
55
+ marked or otherwise designated in writing by the copyright owner as "Not a
56
+ Contribution."
57
+
58
+ "Contributor" shall mean Licensor and any individual or legal entity on
59
+ behalf of whom a Contribution has been received by Licensor and subsequently
60
+ incorporated within the Work.
61
+
62
+ 2. Grant of Copyright License. Subject to the terms and conditions of this
63
+ License, each Contributor hereby grants to You a perpetual, worldwide,
64
+ non-exclusive, no-charge, royalty-free, irrevocable copyright license to
65
+ use, reproduce, modify, merge, publish, distribute, sublicense, and/or
66
+ sell copies of the Work, and to permit persons to whom the Work is
67
+ furnished to do so, subject to the following conditions:
68
+
69
+ The above copyright notice and this permission notice shall be included in
70
+ all copies or substantial portions of the Work.
71
+
72
+ 3. Grant of Patent License. Subject to the terms and conditions of this
73
+ License, each Contributor hereby grants to You a perpetual, worldwide,
74
+ non-exclusive, no-charge, royalty-free, irrevocable (except as stated in
75
+ this section) patent license to make, have made, use, offer to sell, sell,
76
+ import, and otherwise transfer the Work, where such license applies only to
77
+ those patent claims licensable by such Contributor that are necessarily
78
+ infringed by their Contribution(s) alone or by combination of their
79
+ Contribution(s) with the Work to which such Contribution(s) was submitted.
80
+ If You institute patent litigation against any entity (including a
81
+ cross-claim or counterclaim in a lawsuit) alleging that the Work or a
82
+ Contribution incorporated within the Work constitutes direct or
83
+ contributory patent infringement, then any patent licenses granted to You
84
+ under this License for that Work shall terminate as of the date such
85
+ litigation is filed.
86
+
87
+ 4. Redistribution. You may reproduce and distribute copies of the Work or
88
+ Derivative Works thereof in any medium, with or without modifications, and
89
+ in Source or Object form, provided that You meet the following conditions:
90
+
91
+ (a) You must give any other recipients of the Work or Derivative Works a
92
+ copy of this License; and
93
+
94
+ (b) You must cause any modified files to carry prominent notices stating
95
+ that You changed the files; and
96
+
97
+ (c) You must retain, in the Source form of any Derivative Works that You
98
+ distribute, all copyright, trademark, patent, attribution and other
99
+ notices from the Source form of the Work, excluding those notices that
100
+ do not pertain to any part of the Derivative Works; and
101
+
102
+ (d) If the Work includes a "NOTICE" file as part of its distribution, then
103
+ any Derivative Works that You distribute must include a readable copy
104
+ of the attribution notices contained within such NOTICE file, excluding
105
+ those notices that do not pertain to any part of the Derivative Works,
106
+ in at least one of the following places: within a NOTICE file
107
+ distributed as part of the Derivative Works; within the Source form or
108
+ documentation, if provided along with the Derivative Works; or, within
109
+ a display generated by the Derivative Works, if and wherever such
110
+ third-party notices normally appear. The contents of the NOTICE file
111
+ are for informational purposes only and do not modify the License. You
112
+ may add Your own attribution notices within Derivative Works that You
113
+ distribute, alongside or as an addendum to the NOTICE text from the
114
+ Work, provided that such additional attribution notices cannot be
115
+ construed as modifying the License.
116
+
117
+ You may add Your own copyright notice to Your modifications and may provide
118
+ additional or different license terms and conditions for use, reproduction,
119
+ or distribution of Your modifications, or for any such Derivative Works as a
120
+ whole, provided Your use, reproduction, and distribution of the Work
121
+ otherwise complies with the conditions stated in this License.
122
+
123
+ 5. Submission of Contributions. Unless You explicitly state otherwise, any
124
+ Contribution intentionally submitted for inclusion in the Work by You to
125
+ the Licensor shall be under the terms and conditions of this License,
126
+ without any additional terms or conditions. Notwithstanding the above,
127
+ nothing herein shall supersede or modify the terms of any separate license
128
+ agreement you may have executed with Licensor regarding such Contributions.
129
+
130
+ 6. Trademarks. This License does not grant permission to use the trade names,
131
+ trademarks, service marks, or product names of the Licensor, except as
132
+ required for reasonable and customary use in describing the origin of the
133
+ Work and reproducing the content of the NOTICE file.
134
+
135
+ 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in
136
+ writing, Licensor provides the Work (and each Contributor provides its
137
+ Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
138
+ KIND, either express or implied, including, without limitation, any
139
+ warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or
140
+ FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for
141
+ determining the appropriateness of using or redistributing the Work and
142
+ assume any risks associated with Your exercise of permissions under this
143
+ License.
144
+
145
+ 8. Limitation of Liability. In no event and under no legal theory, whether in
146
+ tort (including negligence), contract, or otherwise, unless required by
147
+ applicable law (such as deliberate and grossly negligent acts) or agreed
148
+ to in writing, shall any Contributor be liable to You for damages,
149
+ including any direct, indirect, special, incidental, or consequential
150
+ damages of any character arising as a result of this License or out of the
151
+ use or inability to use the Work (including but not limited to damages for
152
+ loss of goodwill, work stoppage, computer failure or malfunction, or any
153
+ and all other commercial damages or losses), even if such Contributor has
154
+ been advised of the possibility of such damages.
155
+
156
+ 9. Accepting Support, Warranty or Additional Liability. While redistributing
157
+ the Work or Derivative Works thereof, You may choose to offer, and charge
158
+ a fee for, acceptance of support, warranty, indemnity, or other liability
159
+ obligations and/or rights consistent with this License. However, in
160
+ accepting such obligations, You may act only on Your own behalf and on Your
161
+ sole responsibility, not on behalf of any other Contributor, and only if
162
+ You agree to indemnify, defend, and hold each Contributor harmless for any
163
+ liability incurred by, or claims asserted against, such Contributor by
164
+ reason of your accepting any such warranty or additional liability.
165
+
166
+ END OF TERMS AND CONDITIONS
167
+
168
+ APPENDIX: How to apply the Apache License to your work.
169
+
170
+ To apply the Apache License to your work, attach the following boilerplate
171
+ notice, with the fields enclosed by brackets "[]" replaced with your own
172
+ identifying information. (Don't include the brackets!) The text should be
173
+ enclosed in the appropriate comment syntax for the file format. We also
174
+ recommend that a file or class name and description of purpose be included
175
+ on the same "page" as the copyright notice for easier identification within
176
+ third-party archives.
177
+
178
+ Copyright 2025 Orchestrate LLC (Joshua @orchestrate.solutions)
179
+
180
+ Licensed under the Apache License, Version 2.0 (the "License");
181
+ you may not use this file except in compliance with the License.
182
+ You may obtain a copy of the License at
183
+
184
+ http://www.apache.org/licenses/LICENSE-2.0
185
+
186
+ Unless required by applicable law or agreed to in writing, software
187
+ distributed under the License is distributed on an "AS IS" BASIS,
188
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
189
+ See the License for the specific language governing permissions and
190
+ limitations under the License.
@@ -0,0 +1 @@
1
+ codeupipe