pipescript 0.0.1__tar.gz

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.
@@ -0,0 +1,4 @@
1
+ include README.md docs/HISTORY.rst
2
+ recursive-exclude test *
3
+ include versioneer.py
4
+ include pipescript/_version.py
@@ -0,0 +1,256 @@
1
+ Metadata-Version: 2.4
2
+ Name: pipescript
3
+ Version: 0.0.1
4
+ Summary: Powerful pipeline syntax for IPython and Jupyter
5
+ Home-page: https://github.com/smacke/pipescript
6
+ Author: Stephen Macke
7
+ Author-email: stephen.macke@gmail.com
8
+ License: BSD-3-Clause
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: BSD License
12
+ Classifier: Natural Language :: English
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown; charset=UTF-8
21
+ License-File: docs/LICENSE.txt
22
+ Requires-Dist: ipyflow-core>=0.0.221
23
+ Requires-Dist: pyccolo>=0.0.77
24
+ Provides-Extra: test
25
+ Requires-Dist: black; extra == "test"
26
+ Requires-Dist: hypothesis; extra == "test"
27
+ Requires-Dist: isort; extra == "test"
28
+ Requires-Dist: mypy; extra == "test"
29
+ Requires-Dist: pytest; extra == "test"
30
+ Requires-Dist: pytest-cov; extra == "test"
31
+ Requires-Dist: ruff; extra == "test"
32
+ Provides-Extra: dev
33
+ Requires-Dist: build; extra == "dev"
34
+ Requires-Dist: pycln; extra == "dev"
35
+ Requires-Dist: twine; extra == "dev"
36
+ Requires-Dist: versioneer; extra == "dev"
37
+ Requires-Dist: black; extra == "dev"
38
+ Requires-Dist: hypothesis; extra == "dev"
39
+ Requires-Dist: isort; extra == "dev"
40
+ Requires-Dist: mypy; extra == "dev"
41
+ Requires-Dist: pytest; extra == "dev"
42
+ Requires-Dist: pytest-cov; extra == "dev"
43
+ Requires-Dist: ruff; extra == "dev"
44
+ Dynamic: license-file
45
+
46
+ pipescript
47
+ =======
48
+
49
+ [![CI Status](https://github.com/smacke/pipescript/workflows/pipescript/badge.svg)](https://github.com/smacke/pipescript/actions)
50
+ [![Checked with mypy](http://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/)
51
+ [![License: BSD3](https://img.shields.io/badge/License-BSD3-maroon.svg)](https://opensource.org/licenses/BSD-3-Clause)
52
+ [![Python Versions](https://img.shields.io/pypi/pyversions/pipescript.svg)](https://pypi.org/project/pipescript)
53
+ [![PyPI Version](https://img.shields.io/pypi/v/pipescript.svg)](https://pypi.org/project/pipescript)
54
+
55
+ pipescript is an IPython extension that brings a pipe operator `|>` and
56
+ powerful placeholder syntax extensions to IPython and Jupyter. It is:
57
+ - Just a library you can install from PyPI, compatible with a wide range of Python 3
58
+ versions -- no fancy installation instructions, no complicated language distribution
59
+ to install
60
+ - Intended for Jupyter notebooks, for the IPython REPL, or for any interactive
61
+ Python environment built on top of IPython
62
+ - Fully compatible with all existing Python standard and third-party libraries that
63
+ you already know and love
64
+
65
+ If you're familiar with the [magrittr](https://magrittr.tidyverse.org/) package
66
+ for R, then you'll be right at home with pipescript.
67
+
68
+
69
+ ## Getting Started
70
+
71
+ Run the following in IPython or Jupyter to install pipescript and load
72
+ the extension:
73
+
74
+ ```python
75
+ %pip install pipescript
76
+ %load_ext pipescript
77
+ ```
78
+
79
+ The `%load_ext pipescript` invocation is what enables the new pipe syntax
80
+ in your current session.
81
+
82
+ ## Features by Example
83
+
84
+ Let's look at a few examples to give a flavor of what you can do with pipescript:
85
+
86
+ ```python
87
+ # Display a sorted version of a tuple
88
+ >>> tup = (3, 4, 1, 5, 6)
89
+ >>> tup |> sorted |> tuple
90
+ (1, 3, 4, 5, 6)
91
+ ```
92
+ The above example showcases the `|>`, or "pipe", operator, which is a much-loved
93
+ feature of functional programming that has become increasingly mainstream. Its
94
+ primary benefit is that the flow of execution follows natural left-to-right
95
+ reading / writing order of the code. Whether or not such pipeline syntax is
96
+ available, it's not uncommon for programmers to execute pipelines like the above
97
+ multiple times during to verify the computation at each step, particularly in
98
+ interactive programming environments like Jupyter. With `|>`, this type of
99
+ incremental verification becomes a breeze: first execute `tup |> sorted`, then
100
+ append ` |> tuple` to execute the full chain `tup |> sorted |> tuple`, each time
101
+ using the last-expression rendering capabilities of the notebook or REPL to
102
+ inspect and verify the result.
103
+
104
+ ### Placeholders
105
+
106
+ The power of the `|>` operator is amplified via placeholder syntax for implicit
107
+ lambda construction: for pipescript, we use `$` to stand in for function arguments
108
+ and induce function creation:
109
+
110
+ ```python
111
+ # Sort a list in reverse order
112
+ >>> lst = [3, 4, 1, 5, 6]
113
+ >>> lst |> sorted($, reverse=True)
114
+ [6, 5, 4, 3, 1]
115
+ ```
116
+
117
+ `$` is analogous to magrittr's `.` placeholder. It can also be used outside
118
+ of pipeline contexts:
119
+
120
+ ```python
121
+ # Sort a list in reverse order and print the result
122
+ lst = [3, 4, 1, 5, 6]
123
+ reverse_sorter = sorted($, reverse=True)
124
+
125
+ # The following are equivalent:
126
+ print(reverse_sorter(lst))
127
+ lst |> reverse_sorter |> print
128
+ ```
129
+
130
+ Each time `$` appears, it represents a new argument, so `sorted($, reverse=$)`
131
+ represents a function with two arguments:
132
+
133
+ ```python
134
+ import random
135
+
136
+ # Sort a list in either ascending or descending order with probablility 0.5:
137
+ lst = [3, 4, 1, 5, 6]
138
+ sorter = sorted($, reverse=$)
139
+ reverse = random.random() < 0.5
140
+
141
+ # The following are equivalent:
142
+ print(sorter(lst, reverse))
143
+ lst |> sorter($, reverse) |> print
144
+ ```
145
+
146
+ Placeholders can appear anywhere -- not just as arguments to function calls:
147
+
148
+ ```python
149
+ # Sort a list and find the position of element 4:
150
+ >>> lst = [3, 4, 1, 5, 6]
151
+ >>> lst |> sorted |> $.index(3)
152
+ 1
153
+ ```
154
+
155
+ ### Named Placeholders
156
+
157
+ There are situations that would benefit from referencing the same placeholder multiple times, for which
158
+ pipescript permits *named placeholders* by prefixing `$` to an identifier:
159
+
160
+ ```python
161
+ # Pair even entries from a range with their adjacent odd entry
162
+ range(6) |> list |> zip($v[::2], $v[1::2]) |> list
163
+ >>> [(0, 1), (2, 3), (4, 5)]
164
+ ```
165
+
166
+ In the above example, we could have used any name for `$v`, the important
167
+ thing is that the same name was used -- otherwise pipescript would have
168
+ induced a function with two arguments instead of one.
169
+
170
+ ### Undetermined Pipelines
171
+
172
+ Similar to magrittr's behavior, if any number of placeholders appear in the first
173
+ step of an pipescript pipeline, this *undetermined pipeline* will represent a function:
174
+
175
+ ```python
176
+ >>> second_largest_value = $ |> sorted($, reverse=True) |> $[1]
177
+ >>> [3, 8, 1, 5, 6] |> second_largest_value
178
+ 6
179
+ ```
180
+
181
+ ### Macros and Curry Syntax
182
+
183
+ ### Helper Utilities
184
+
185
+ ### Additional Operators
186
+
187
+ ## Placeholder Scope
188
+
189
+ A natural question is: how does pipescript know what part of the code should
190
+ be included in the body of the function induced by placeholder use? The
191
+ rules are as follows:
192
+
193
+ 1. If there is a macro or pipeline step enclosing the placeholder, the induced
194
+ function body includes the "smallest" such enclosing macro or pipeline step.
195
+ 2. Otherwise, the function body expands to include the nearest "chain"
196
+ of function calls, attribute accesses, and / or subscript accesses.
197
+
198
+ An example of a "chain" would be something like `np.array($).T.astype(int)`,
199
+ which induces a lambda that converts its argument to a numpy array,
200
+ transposes it, and then converts the result to use `int64` dtype. That is,
201
+ the lambda body expands to include not just `np.array($)`, but the entire
202
+ "chain" in the expression.
203
+
204
+ To see a concrete example of where this matters, consider the following
205
+ two placeholder expressions:
206
+
207
+ ```python
208
+ # The following sorters do different things!
209
+ sorter1 = sorted($, key=$[1])
210
+ sorter2 = sorted($, key=f[$[1]])
211
+ ```
212
+
213
+ `sorter1` is a function that takes two arguments: a sequence, and a list of
214
+ functions, the second of which will be used to compute the sort key, which it then
215
+ uses to sort the first argument.
216
+ `sorter2`, on the other hand, is a function that takes a single argument, which
217
+ is a sequence that it sorts using the second element of each value in said
218
+ sequence value as sort key. In most cases, `sorter2` probably gives the desired
219
+ behavior.
220
+
221
+ ## Performance Overhead
222
+
223
+ ## More Examples
224
+ I developed pipescript while working on
225
+ [Advent of Code 2025](https://adventofcode.com/2025) in parallel,
226
+ and used it for most of the input processesing portions of my solutions,
227
+ which you can find at https://github.com/smacke/aoc2025.
228
+
229
+ ## What pipescript is and is not
230
+
231
+ pipescript is not a general purpose functional programming language on top of
232
+ Python. It is very much not intended for production use cases, and instead
233
+ caters toward quick-and-dirty one-off / scratchpad type computations in IPython
234
+ and Jupyter specifically. In short, pipescript aims to provide simple but powerful
235
+ pipeline and placeholder syntax to interactive Python programming environments.
236
+
237
+ All the different pipeline operators like `|>`, `<|`, `*|>`, etc. essentially
238
+ transpile down to an instrumented variant of the bitwise-or (`|`) operator, and
239
+ therefore every new operator left-associates at the same level of precedence,
240
+ meaning that pipeline steps run from left to right in the order that they
241
+ appear. pipescript aims to optimize for simplicity, readability / writability, and
242
+ predictability over feature completeness (though I'd like to think it strikes a
243
+ fairly good balance in this regard).
244
+
245
+ ## How it works
246
+
247
+ ## Inspiration
248
+
249
+ pipescript draws inspiration largely from
250
+ [magrittr](https://magrittr.tidyverse.org/), but also from efforts like
251
+ [coconut](https://coconut-lang.org/) (a functional superset of Python),
252
+ as well as from libraries like [Pipe](https://github.com/JulienPalard/Pipe) which
253
+ take a different approach to fill Python's pipe gap with operator overloading hacks.
254
+
255
+ ## License
256
+ Code in this project licensed under the [BSD-3-Clause License](https://opensource.org/licenses/BSD-3-Clause).
@@ -0,0 +1,211 @@
1
+ pipescript
2
+ =======
3
+
4
+ [![CI Status](https://github.com/smacke/pipescript/workflows/pipescript/badge.svg)](https://github.com/smacke/pipescript/actions)
5
+ [![Checked with mypy](http://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/)
6
+ [![License: BSD3](https://img.shields.io/badge/License-BSD3-maroon.svg)](https://opensource.org/licenses/BSD-3-Clause)
7
+ [![Python Versions](https://img.shields.io/pypi/pyversions/pipescript.svg)](https://pypi.org/project/pipescript)
8
+ [![PyPI Version](https://img.shields.io/pypi/v/pipescript.svg)](https://pypi.org/project/pipescript)
9
+
10
+ pipescript is an IPython extension that brings a pipe operator `|>` and
11
+ powerful placeholder syntax extensions to IPython and Jupyter. It is:
12
+ - Just a library you can install from PyPI, compatible with a wide range of Python 3
13
+ versions -- no fancy installation instructions, no complicated language distribution
14
+ to install
15
+ - Intended for Jupyter notebooks, for the IPython REPL, or for any interactive
16
+ Python environment built on top of IPython
17
+ - Fully compatible with all existing Python standard and third-party libraries that
18
+ you already know and love
19
+
20
+ If you're familiar with the [magrittr](https://magrittr.tidyverse.org/) package
21
+ for R, then you'll be right at home with pipescript.
22
+
23
+
24
+ ## Getting Started
25
+
26
+ Run the following in IPython or Jupyter to install pipescript and load
27
+ the extension:
28
+
29
+ ```python
30
+ %pip install pipescript
31
+ %load_ext pipescript
32
+ ```
33
+
34
+ The `%load_ext pipescript` invocation is what enables the new pipe syntax
35
+ in your current session.
36
+
37
+ ## Features by Example
38
+
39
+ Let's look at a few examples to give a flavor of what you can do with pipescript:
40
+
41
+ ```python
42
+ # Display a sorted version of a tuple
43
+ >>> tup = (3, 4, 1, 5, 6)
44
+ >>> tup |> sorted |> tuple
45
+ (1, 3, 4, 5, 6)
46
+ ```
47
+ The above example showcases the `|>`, or "pipe", operator, which is a much-loved
48
+ feature of functional programming that has become increasingly mainstream. Its
49
+ primary benefit is that the flow of execution follows natural left-to-right
50
+ reading / writing order of the code. Whether or not such pipeline syntax is
51
+ available, it's not uncommon for programmers to execute pipelines like the above
52
+ multiple times during to verify the computation at each step, particularly in
53
+ interactive programming environments like Jupyter. With `|>`, this type of
54
+ incremental verification becomes a breeze: first execute `tup |> sorted`, then
55
+ append ` |> tuple` to execute the full chain `tup |> sorted |> tuple`, each time
56
+ using the last-expression rendering capabilities of the notebook or REPL to
57
+ inspect and verify the result.
58
+
59
+ ### Placeholders
60
+
61
+ The power of the `|>` operator is amplified via placeholder syntax for implicit
62
+ lambda construction: for pipescript, we use `$` to stand in for function arguments
63
+ and induce function creation:
64
+
65
+ ```python
66
+ # Sort a list in reverse order
67
+ >>> lst = [3, 4, 1, 5, 6]
68
+ >>> lst |> sorted($, reverse=True)
69
+ [6, 5, 4, 3, 1]
70
+ ```
71
+
72
+ `$` is analogous to magrittr's `.` placeholder. It can also be used outside
73
+ of pipeline contexts:
74
+
75
+ ```python
76
+ # Sort a list in reverse order and print the result
77
+ lst = [3, 4, 1, 5, 6]
78
+ reverse_sorter = sorted($, reverse=True)
79
+
80
+ # The following are equivalent:
81
+ print(reverse_sorter(lst))
82
+ lst |> reverse_sorter |> print
83
+ ```
84
+
85
+ Each time `$` appears, it represents a new argument, so `sorted($, reverse=$)`
86
+ represents a function with two arguments:
87
+
88
+ ```python
89
+ import random
90
+
91
+ # Sort a list in either ascending or descending order with probablility 0.5:
92
+ lst = [3, 4, 1, 5, 6]
93
+ sorter = sorted($, reverse=$)
94
+ reverse = random.random() < 0.5
95
+
96
+ # The following are equivalent:
97
+ print(sorter(lst, reverse))
98
+ lst |> sorter($, reverse) |> print
99
+ ```
100
+
101
+ Placeholders can appear anywhere -- not just as arguments to function calls:
102
+
103
+ ```python
104
+ # Sort a list and find the position of element 4:
105
+ >>> lst = [3, 4, 1, 5, 6]
106
+ >>> lst |> sorted |> $.index(3)
107
+ 1
108
+ ```
109
+
110
+ ### Named Placeholders
111
+
112
+ There are situations that would benefit from referencing the same placeholder multiple times, for which
113
+ pipescript permits *named placeholders* by prefixing `$` to an identifier:
114
+
115
+ ```python
116
+ # Pair even entries from a range with their adjacent odd entry
117
+ range(6) |> list |> zip($v[::2], $v[1::2]) |> list
118
+ >>> [(0, 1), (2, 3), (4, 5)]
119
+ ```
120
+
121
+ In the above example, we could have used any name for `$v`, the important
122
+ thing is that the same name was used -- otherwise pipescript would have
123
+ induced a function with two arguments instead of one.
124
+
125
+ ### Undetermined Pipelines
126
+
127
+ Similar to magrittr's behavior, if any number of placeholders appear in the first
128
+ step of an pipescript pipeline, this *undetermined pipeline* will represent a function:
129
+
130
+ ```python
131
+ >>> second_largest_value = $ |> sorted($, reverse=True) |> $[1]
132
+ >>> [3, 8, 1, 5, 6] |> second_largest_value
133
+ 6
134
+ ```
135
+
136
+ ### Macros and Curry Syntax
137
+
138
+ ### Helper Utilities
139
+
140
+ ### Additional Operators
141
+
142
+ ## Placeholder Scope
143
+
144
+ A natural question is: how does pipescript know what part of the code should
145
+ be included in the body of the function induced by placeholder use? The
146
+ rules are as follows:
147
+
148
+ 1. If there is a macro or pipeline step enclosing the placeholder, the induced
149
+ function body includes the "smallest" such enclosing macro or pipeline step.
150
+ 2. Otherwise, the function body expands to include the nearest "chain"
151
+ of function calls, attribute accesses, and / or subscript accesses.
152
+
153
+ An example of a "chain" would be something like `np.array($).T.astype(int)`,
154
+ which induces a lambda that converts its argument to a numpy array,
155
+ transposes it, and then converts the result to use `int64` dtype. That is,
156
+ the lambda body expands to include not just `np.array($)`, but the entire
157
+ "chain" in the expression.
158
+
159
+ To see a concrete example of where this matters, consider the following
160
+ two placeholder expressions:
161
+
162
+ ```python
163
+ # The following sorters do different things!
164
+ sorter1 = sorted($, key=$[1])
165
+ sorter2 = sorted($, key=f[$[1]])
166
+ ```
167
+
168
+ `sorter1` is a function that takes two arguments: a sequence, and a list of
169
+ functions, the second of which will be used to compute the sort key, which it then
170
+ uses to sort the first argument.
171
+ `sorter2`, on the other hand, is a function that takes a single argument, which
172
+ is a sequence that it sorts using the second element of each value in said
173
+ sequence value as sort key. In most cases, `sorter2` probably gives the desired
174
+ behavior.
175
+
176
+ ## Performance Overhead
177
+
178
+ ## More Examples
179
+ I developed pipescript while working on
180
+ [Advent of Code 2025](https://adventofcode.com/2025) in parallel,
181
+ and used it for most of the input processesing portions of my solutions,
182
+ which you can find at https://github.com/smacke/aoc2025.
183
+
184
+ ## What pipescript is and is not
185
+
186
+ pipescript is not a general purpose functional programming language on top of
187
+ Python. It is very much not intended for production use cases, and instead
188
+ caters toward quick-and-dirty one-off / scratchpad type computations in IPython
189
+ and Jupyter specifically. In short, pipescript aims to provide simple but powerful
190
+ pipeline and placeholder syntax to interactive Python programming environments.
191
+
192
+ All the different pipeline operators like `|>`, `<|`, `*|>`, etc. essentially
193
+ transpile down to an instrumented variant of the bitwise-or (`|`) operator, and
194
+ therefore every new operator left-associates at the same level of precedence,
195
+ meaning that pipeline steps run from left to right in the order that they
196
+ appear. pipescript aims to optimize for simplicity, readability / writability, and
197
+ predictability over feature completeness (though I'd like to think it strikes a
198
+ fairly good balance in this regard).
199
+
200
+ ## How it works
201
+
202
+ ## Inspiration
203
+
204
+ pipescript draws inspiration largely from
205
+ [magrittr](https://magrittr.tidyverse.org/), but also from efforts like
206
+ [coconut](https://coconut-lang.org/) (a functional superset of Python),
207
+ as well as from libraries like [Pipe](https://github.com/JulienPalard/Pipe) which
208
+ take a different approach to fill Python's pipe gap with operator overloading hacks.
209
+
210
+ ## License
211
+ Code in this project licensed under the [BSD-3-Clause License](https://opensource.org/licenses/BSD-3-Clause).
@@ -0,0 +1,6 @@
1
+ History
2
+ =======
3
+
4
+ 0.0.1 (2025-12-30)
5
+ ------------------
6
+ * Initial placeholder release;
@@ -0,0 +1,11 @@
1
+ Copyright 2025 Stephen Macke
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
+
5
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
+
7
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
+
9
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
+
11
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,47 @@
1
+ """
2
+ pipescript: powerful pipeline syntax for IPython and Jupyter.
3
+ Just run `%load_ext pipescript` to begin using pipe operators, placeholders, and more.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from IPython.core.interactiveshell import InteractiveShell
9
+
10
+ from . import _version # noqa: E402
11
+ from .completion_patch import patch_completer, unpatch_completer
12
+
13
+ __version__ = _version.get_versions()["version"]
14
+
15
+
16
+ def load_ipython_extension(shell: InteractiveShell) -> None:
17
+ from ipyflow.shell.interactiveshell import IPyflowInteractiveShell
18
+
19
+ from pipescript.macro_tracer import MacroTracer
20
+ from pipescript.pipeline_tracer import PipelineTracer
21
+
22
+ if not isinstance(shell, IPyflowInteractiveShell):
23
+ shell.run_line_magic("load_ext", "ipyflow.shell")
24
+ shell.run_line_magic("flow", "deregister all")
25
+ assert isinstance(shell, IPyflowInteractiveShell)
26
+ shell.run_line_magic(
27
+ "flow", f"register {PipelineTracer.__module__}.{PipelineTracer.__name__}"
28
+ )
29
+ shell.run_line_magic(
30
+ "flow",
31
+ f"register {MacroTracer.__module__}.{MacroTracer.__name__}",
32
+ )
33
+ patch_completer(shell.Completer)
34
+
35
+
36
+ def unload_ipython_extension(shell: InteractiveShell) -> None:
37
+ from pipescript.macro_tracer import MacroTracer
38
+ from pipescript.pipeline_tracer import PipelineTracer
39
+
40
+ unpatch_completer(shell.Completer)
41
+ shell.run_line_magic(
42
+ "flow",
43
+ f"deregister {MacroTracer.__module__}.{MacroTracer.__name__}",
44
+ )
45
+ shell.run_line_magic(
46
+ "flow", f"deregister {PipelineTracer.__module__}.{PipelineTracer.__name__}"
47
+ )