pyflyby 1.10.4__cp311-cp311-macosx_11_0_arm64.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.
- pyflyby/__init__.py +61 -0
- pyflyby/__main__.py +9 -0
- pyflyby/_autoimp.py +2228 -0
- pyflyby/_cmdline.py +591 -0
- pyflyby/_comms.py +221 -0
- pyflyby/_dbg.py +1383 -0
- pyflyby/_dynimp.py +154 -0
- pyflyby/_fast_iter_modules.cpython-311-darwin.so +0 -0
- pyflyby/_file.py +771 -0
- pyflyby/_flags.py +230 -0
- pyflyby/_format.py +186 -0
- pyflyby/_idents.py +227 -0
- pyflyby/_import_sorting.py +165 -0
- pyflyby/_importclns.py +658 -0
- pyflyby/_importdb.py +535 -0
- pyflyby/_imports2s.py +643 -0
- pyflyby/_importstmt.py +723 -0
- pyflyby/_interactive.py +2113 -0
- pyflyby/_livepatch.py +793 -0
- pyflyby/_log.py +107 -0
- pyflyby/_modules.py +646 -0
- pyflyby/_parse.py +1396 -0
- pyflyby/_py.py +2165 -0
- pyflyby/_saveframe.py +1145 -0
- pyflyby/_saveframe_reader.py +471 -0
- pyflyby/_util.py +458 -0
- pyflyby/_version.py +8 -0
- pyflyby/autoimport.py +20 -0
- pyflyby/etc/pyflyby/canonical.py +10 -0
- pyflyby/etc/pyflyby/common.py +27 -0
- pyflyby/etc/pyflyby/forget.py +10 -0
- pyflyby/etc/pyflyby/mandatory.py +10 -0
- pyflyby/etc/pyflyby/numpy.py +156 -0
- pyflyby/etc/pyflyby/std.py +335 -0
- pyflyby/importdb.py +19 -0
- pyflyby/libexec/pyflyby/colordiff +34 -0
- pyflyby/libexec/pyflyby/diff-colorize +148 -0
- pyflyby/share/emacs/site-lisp/pyflyby.el +112 -0
- pyflyby-1.10.4.data/scripts/collect-exports +76 -0
- pyflyby-1.10.4.data/scripts/collect-imports +58 -0
- pyflyby-1.10.4.data/scripts/find-import +38 -0
- pyflyby-1.10.4.data/scripts/prune-broken-imports +34 -0
- pyflyby-1.10.4.data/scripts/pyflyby-diff +34 -0
- pyflyby-1.10.4.data/scripts/reformat-imports +27 -0
- pyflyby-1.10.4.data/scripts/replace-star-imports +37 -0
- pyflyby-1.10.4.data/scripts/saveframe +299 -0
- pyflyby-1.10.4.data/scripts/tidy-imports +170 -0
- pyflyby-1.10.4.data/scripts/transform-imports +47 -0
- pyflyby-1.10.4.dist-info/METADATA +605 -0
- pyflyby-1.10.4.dist-info/RECORD +53 -0
- pyflyby-1.10.4.dist-info/WHEEL +6 -0
- pyflyby-1.10.4.dist-info/entry_points.txt +4 -0
- pyflyby-1.10.4.dist-info/licenses/LICENSE.txt +19 -0
pyflyby/_comms.py
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
|
|
2
|
+
from __future__ import print_function
|
|
3
|
+
|
|
4
|
+
from pyflyby._imports2s import (SourceToSourceFileImportsTransformation,
|
|
5
|
+
SourceToSourceImportBlockTransformation,
|
|
6
|
+
fix_unused_and_missing_imports,
|
|
7
|
+
replace_star_imports,
|
|
8
|
+
reformat_import_statements)
|
|
9
|
+
from pyflyby._importstmt import Import
|
|
10
|
+
from pyflyby._log import logger
|
|
11
|
+
|
|
12
|
+
from typing import Dict, Any
|
|
13
|
+
|
|
14
|
+
# These are comm targets that the frontend (lab/notebook) is expected to
|
|
15
|
+
# open. At this point, we handle only missing imports and
|
|
16
|
+
# formatting imports
|
|
17
|
+
|
|
18
|
+
MISSING_IMPORTS = "pyflyby.missing_imports"
|
|
19
|
+
FORMATTING_IMPORTS = "pyflyby.format_imports"
|
|
20
|
+
INIT_COMMS = "pyflyby.init_comms"
|
|
21
|
+
TIDY_IMPORTS = "pyflyby.tidy_imports"
|
|
22
|
+
PYFLYBY_START_MSG = "# THIS CELL WAS AUTO-GENERATED BY PYFLYBY\n"
|
|
23
|
+
PYFLYBY_END_MSG = "# END AUTO-GENERATED BLOCK\n"
|
|
24
|
+
|
|
25
|
+
pyflyby_comm_targets= [MISSING_IMPORTS, FORMATTING_IMPORTS, TIDY_IMPORTS]
|
|
26
|
+
|
|
27
|
+
# A map of the comms opened with a given target name.
|
|
28
|
+
comms:Dict[str, Any] = {}
|
|
29
|
+
|
|
30
|
+
# TODO: Document the expected contract for the different
|
|
31
|
+
# custom comm messages
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def in_jupyter():
|
|
35
|
+
from IPython.core.getipython import get_ipython
|
|
36
|
+
ip = get_ipython()
|
|
37
|
+
if ip is None:
|
|
38
|
+
logger.debug("get_ipython() doesn't exist. Comm targets can only"
|
|
39
|
+
"be added in an Jupyter notebook/lab/console environment")
|
|
40
|
+
return False
|
|
41
|
+
else:
|
|
42
|
+
try:
|
|
43
|
+
ip.kernel.comm_manager
|
|
44
|
+
except AttributeError:
|
|
45
|
+
logger.debug("Comm targets can only be added in Jupyter "
|
|
46
|
+
"notebook/lab/console environment")
|
|
47
|
+
return False
|
|
48
|
+
else:
|
|
49
|
+
return True
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _register_target(target_name):
|
|
53
|
+
from IPython.core.getipython import get_ipython
|
|
54
|
+
ip = get_ipython()
|
|
55
|
+
comm_manager = ip.kernel.comm_manager
|
|
56
|
+
comm_manager.register_target(target_name, comm_open_handler)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def initialize_comms():
|
|
60
|
+
if in_jupyter():
|
|
61
|
+
for target in pyflyby_comm_targets:
|
|
62
|
+
_register_target(target)
|
|
63
|
+
from ipykernel.comm import Comm
|
|
64
|
+
comm = Comm(target_name=INIT_COMMS)
|
|
65
|
+
msg = {"type": INIT_COMMS}
|
|
66
|
+
logger.debug("Requesting frontend to (re-)initialize comms")
|
|
67
|
+
comm.send(msg)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def remove_comms():
|
|
71
|
+
for target_name, comm in comms.items():
|
|
72
|
+
comm.close()
|
|
73
|
+
logger.debug("Closing comm for " + target_name)
|
|
74
|
+
|
|
75
|
+
def send_comm_message(target_name, msg):
|
|
76
|
+
if in_jupyter():
|
|
77
|
+
try:
|
|
78
|
+
comm = comms[target_name]
|
|
79
|
+
except KeyError:
|
|
80
|
+
logger.debug("Comm with target_name " + target_name + " hasn't been opened")
|
|
81
|
+
else:
|
|
82
|
+
# Help the frontend distinguish between multiple types
|
|
83
|
+
# of custom comm messages
|
|
84
|
+
msg["type"] = target_name
|
|
85
|
+
comm.send(msg)
|
|
86
|
+
logger.debug("Sending comm message for target " + target_name)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def comm_close_handler(comm, message):
|
|
90
|
+
comm_id = message["comm_id"]
|
|
91
|
+
for target, comm in comms.keys():
|
|
92
|
+
if comm.comm_id == comm_id:
|
|
93
|
+
comms.pop(target)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _reformat_helper(input_code, imports):
|
|
97
|
+
if PYFLYBY_START_MSG in input_code:
|
|
98
|
+
before, bmarker, middle = input_code.partition(PYFLYBY_START_MSG)
|
|
99
|
+
else:
|
|
100
|
+
before, bmarker, middle = "", "", input_code
|
|
101
|
+
|
|
102
|
+
if PYFLYBY_END_MSG in middle:
|
|
103
|
+
middle, emarker, after = middle.partition(PYFLYBY_END_MSG)
|
|
104
|
+
else:
|
|
105
|
+
middle, emarker, after = middle, "", ""
|
|
106
|
+
|
|
107
|
+
if imports is not None:
|
|
108
|
+
transform = SourceToSourceFileImportsTransformation(middle)
|
|
109
|
+
|
|
110
|
+
if isinstance(imports, str):
|
|
111
|
+
imports = [imports]
|
|
112
|
+
|
|
113
|
+
for imp in imports:
|
|
114
|
+
assert isinstance(imp, str)
|
|
115
|
+
if not imp.strip():
|
|
116
|
+
continue
|
|
117
|
+
transform.add_import(Import(imp))
|
|
118
|
+
middle = str(transform.output())
|
|
119
|
+
|
|
120
|
+
return reformat_import_statements(before + bmarker + middle + emarker + after)
|
|
121
|
+
|
|
122
|
+
def extract_import_statements(text):
|
|
123
|
+
"""This is a util for notebook interactions and extracts import statements
|
|
124
|
+
from some python code. This function also re-orders imports.
|
|
125
|
+
Args:
|
|
126
|
+
code (str): The code from which import statements have to be extracted
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
(str, str): The first returned value contains all the import statements.
|
|
130
|
+
The second returned value is the remaining code after
|
|
131
|
+
extracting the import statements.
|
|
132
|
+
"""
|
|
133
|
+
transformer = SourceToSourceFileImportsTransformation(text)
|
|
134
|
+
imports = '\n'.join([str(im.pretty_print()).strip() for im in transformer.import_blocks])
|
|
135
|
+
remaining_code = "\n".join([str(st.pretty_print()).strip() if not isinstance(st, SourceToSourceImportBlockTransformation) else "" for st in transformer.blocks])
|
|
136
|
+
return imports, remaining_code
|
|
137
|
+
|
|
138
|
+
def collect_code_with_imports_on_top(imports: str, cell_array):
|
|
139
|
+
return (
|
|
140
|
+
imports
|
|
141
|
+
+ "\n"
|
|
142
|
+
+ "\n".join(
|
|
143
|
+
[
|
|
144
|
+
cell["text"] if cell["type"] == "code" and not cell.get("ignore", False) else ""
|
|
145
|
+
for cell in cell_array
|
|
146
|
+
]
|
|
147
|
+
)
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
def run_tidy_imports(code):
|
|
151
|
+
return str(
|
|
152
|
+
reformat_import_statements(
|
|
153
|
+
fix_unused_and_missing_imports(
|
|
154
|
+
replace_star_imports(code)
|
|
155
|
+
)
|
|
156
|
+
)
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def comm_open_handler(comm, message):
|
|
160
|
+
"""
|
|
161
|
+
Handles comm_open message for pyflyby custom comm messages.
|
|
162
|
+
https://jupyter-client.readthedocs.io/en/stable/messaging.html#opening-a-comm.
|
|
163
|
+
|
|
164
|
+
Handler for all PYFLYBY custom comm messages that are opened by the frontend
|
|
165
|
+
(at this point, just the jupyterlab frontend does this).
|
|
166
|
+
|
|
167
|
+
"""
|
|
168
|
+
|
|
169
|
+
comm.on_close(comm_close_handler)
|
|
170
|
+
comms[message["content"]["target_name"]] = comm
|
|
171
|
+
|
|
172
|
+
@comm.on_msg
|
|
173
|
+
def _recv(msg):
|
|
174
|
+
data = msg["content"]["data"]
|
|
175
|
+
if data["type"] == FORMATTING_IMPORTS:
|
|
176
|
+
msg_id = data.get("msg_id", None)
|
|
177
|
+
imports = data.get("imports", None)
|
|
178
|
+
fmt_code = _reformat_helper(data["input_code"], imports)
|
|
179
|
+
comm.send(
|
|
180
|
+
{
|
|
181
|
+
"msg_id": msg_id,
|
|
182
|
+
"formatted_code": str(fmt_code),
|
|
183
|
+
"type": FORMATTING_IMPORTS,
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
elif data["type"] == TIDY_IMPORTS:
|
|
187
|
+
checksum = data.get("checksum", '')
|
|
188
|
+
cell_array = data.get("cellArray", [])
|
|
189
|
+
# import_statements is a string because when
|
|
190
|
+
# SourceToSourceFileImportsTransformation is run on a piece of code
|
|
191
|
+
# it will club similar imports together and re-order the imports
|
|
192
|
+
# by making the imports a string, all the imports are processed
|
|
193
|
+
# together making sure tidy-imports has context on all the imports
|
|
194
|
+
# while clubbing similar imports and re-ordering them.
|
|
195
|
+
import_statements, processed_cell_array = "", []
|
|
196
|
+
for cell in cell_array:
|
|
197
|
+
ignore = False
|
|
198
|
+
text = cell.get("text")
|
|
199
|
+
cell_type = cell.get("type")
|
|
200
|
+
if cell_type == "code":
|
|
201
|
+
try:
|
|
202
|
+
imports, text = extract_import_statements(text)
|
|
203
|
+
import_statements += (imports + "\n")
|
|
204
|
+
except SyntaxError:
|
|
205
|
+
# If a cell triggers Syntax Error, we set ignore to
|
|
206
|
+
# True and don't include it when running tidy-imports
|
|
207
|
+
# For eg. this is triggered due to cells with magic
|
|
208
|
+
# commands
|
|
209
|
+
ignore = True
|
|
210
|
+
processed_cell_array.append({"text": text, "type": cell_type, "ignore": ignore})
|
|
211
|
+
code_with_collected_imports = collect_code_with_imports_on_top(import_statements, processed_cell_array)
|
|
212
|
+
code_post_tidy_imports = run_tidy_imports(code_with_collected_imports)
|
|
213
|
+
import_statements, _ = extract_import_statements(code_post_tidy_imports)
|
|
214
|
+
comm.send(
|
|
215
|
+
{
|
|
216
|
+
"checksum": checksum,
|
|
217
|
+
"type": TIDY_IMPORTS,
|
|
218
|
+
"cells": processed_cell_array,
|
|
219
|
+
"imports": import_statements,
|
|
220
|
+
}
|
|
221
|
+
)
|