Legacy
validate_into_flag ¶
Awkward handling procedure to raise an error if two consecutive flags are both
-i/--into, i.e. if the pop-then-append operations will overwrite the previous
one's.
Source code in src/mvdef/legacy/cli.py
agenda_util ¶
pprint_agenda_desc ¶
Pretty print an edit agenda entry according to the agenda category. The 7 categories are: move, keep, copy, lose, take, echo, stay.
Source code in src/mvdef/legacy/agenda_util.py
describe_def_name_dict ¶
Wrapper function that returns a string presenting the content of a dict entry
with import statement indexes, line number, and import source path. These
fields are instantiated within get_def_names, which in turn is assigned to
the variable mvdef_names within parse_mv_funcs.
The output of parse_mv_funcs gets passed to process_ast, which iterates over
the subsets within the output of parse_mv_funcs, at which stage it's
necessary to produce a nice readable output, calling describe_mvdef_name_dict.
Source code in src/mvdef/legacy/agenda_util.py
ast_tokens ¶
get_imports ¶
Using the asttokens-tokenised AST tree body ("trunk"), get the
top-level import statements. Alternatively, get imports at any
level by walking the full tree rather than just the trunk.
Source code in src/mvdef/legacy/ast_tokens.py
get_defs_and_classes ¶
List the funcdefs and classdefs of the AST top-level trunk (tr), walking it if
trunk_only is False (default: True), else just list top-level trunk nodes.
Source code in src/mvdef/legacy/ast_tokens.py
get_to_node ¶
Annotate the parsed into_path with a .node attribute, which will be used later
when determining the line to insert the newly moved funcdef at in the DstFile.
Source code in src/mvdef/legacy/ast_tokens.py
set_defs_to_move ¶
Using the asttokens-tokenised AST tree body ("trunk"), get the top-level
function definition statements. Alternatively, get function definitions
at any level by walking the full tree rather than just the trunk.
Source code in src/mvdef/legacy/ast_tokens.py
ast_util ¶
PathGetterMixin ¶
Used in all Def classes (FuncDef, ClsDef and all subclasses) to provide
a generic way to retrieve the inner funcdef/clsdef so as to retrieve a path
to a leaf funcdef/clsdef.
(I don't think this even needs to be mixed in but it's handy to access if it is)
retrieve_def ¶
Attempt to retrieve the next funcdef/clsdef indicated by path_part
(an instance one of the PathPart classes iterated over via reduce
in check_against_linkedfile from one of the Path classes).
Source code in src/mvdef/legacy/ast_util.py
retrieve_def_from_body ¶
Attempt to retrieve the next funcdef/clsdef indicated by path_part
(an instance one of the PathPart classes iterated over via reduce
in check_against_linkedfile from one of the Path classes). Use the
body rather than intra_classes and intra_funcs
Source code in src/mvdef/legacy/ast_util.py
FuncPath ¶
Bases: FuncDefPathStr, LinkFileCheckerMixin
A FuncDefPathStr for a top-level function definition
Source code in src/mvdef/legacy/ast_util.py
InnerFuncPath ¶
Bases: InnerFuncDefPathStr, LinkFileCheckerMixin
An InnerFuncDefPathStr which has a top level funcdef, an 'intradef' inner func (checked on super().init), and potentially one or more inner functions below that, which must be reachable as direct descendants of the AST at each step (i.e. no intervening nodes between descendant inner functions in the path when checking against the LinkedFile AST).
Source code in src/mvdef/legacy/ast_util.py
ClassPath ¶
Bases: ClassDefPathStr, LinkFileCheckerMixin
A ClassDefPathStr for a top-level class
Source code in src/mvdef/legacy/ast_util.py
InnerClassPath ¶
Bases: InnerClassDefPathStr, LinkFileCheckerMixin
A ClassDefPathStr for a class within another class.
Source code in src/mvdef/legacy/ast_util.py
HigherOrderClassPath ¶
Bases: HigherOrderClassDefPathStr, LinkFileCheckerMixin
A ClassDefPathStr for a class within another class.
Source code in src/mvdef/legacy/ast_util.py
MethodPath ¶
Bases: MethodDefPathStr, LinkFileCheckerMixin
A MethodDefPathStr which has a top level class, which contains a method (checked on super().init), and potentially one or more inner functions below that, which must be reachable as direct descendants of the AST at each step (i.e. no intervening nodes between descendant inner functions in the path when checking against the LinkedFile AST). [TODO: confirm against finished implementation if this is the case RE: inner funcs]
Source code in src/mvdef/legacy/ast_util.py
RecursiveIdSetterMixin ¶
Mixin class to provide a common interface method for both ClsDef and FuncDef
(and by extension all inheriting subclasses).
Note that methods have been omitted (but are trivial to obtain from the result)
ClsDef ¶
Bases: ClassDef, RecursiveIdSetterMixin, PathGetterMixin
Wrap ast.ClassDef to permit recursive search for methods and inner classes
upon creation in parse_mv_funcs.
Source code in src/mvdef/legacy/ast_util.py
HOClsDef ¶
Bases: ClsDef, NamespaceIdSetterMixin
Wrap ClsDef (in turn wrapping ast.ClassDef) to store a reference to the
parent classdef's line range on a higher order class (i.e. a class in a funcdef.
Source code in src/mvdef/legacy/ast_util.py
InnerClsDef ¶
Bases: ClsDef, NamespaceIdSetterMixin
Wrap ClsDef (in turn wrapping ast.ClassDef) to store a reference to the
parent classdef's line range on an inner class.
Source code in src/mvdef/legacy/ast_util.py
FuncDef ¶
Bases: FunctionDef, RecursiveIdSetterMixin, PathGetterMixin
Wrap ast.FunctionDef to permit recursive search for inner functions upon
creation in parse_mv_funcs.
Source code in src/mvdef/legacy/ast_util.py
MethodDef ¶
Bases: FuncDef
Wrap FuncDef (in turn wrapping ast.FunctionDef) to store a reference to the
parent classdef's line range on a method.
Source code in src/mvdef/legacy/ast_util.py
InnerFuncDef ¶
Bases: FuncDef
Wrap FuncDef (in turn wrapping ast.FunctionDef) to store a reference to the
parent funcdef's line range on an inner function.
Source code in src/mvdef/legacy/ast_util.py
retrieve_ast_agenda ¶
Build and parse the Abstract Syntax Tree (AST) of a Python file, and either return
a report of what changes would be required to move the mvdefs subset of all
function definitions out of it, or a report of the imports and funcdefs in general
if no linkfile.mvdefs is provided (taken to indicate that the file is the target funcdefs
are moving to), or make changes to the file (either newly creating one if no such
file exists, or editing in place according to the reported import statement
differences).
If the Python file linkfile.path doesn't exist (which can be checked directly as it's a
Path object), it's being newly created by the move and obviously no report can
be made on it: it has no funcdefs and no import statements, so all the ones being
moved will be newly created.
mvdefs should be given if the file is the source of moved functions, and left
empty (default: None which --> []) if the file is the destination to move them to.
If linkfile.report is True, returns a string describing the changes
to be made (if False, nothing is returned).
If backup is True, files will be changed in place by calling mvdef.backup.backup
(obviously, be careful switching this setting off if report is True, as any
changes made cannot be restored afterwards from this backup file).
Source code in src/mvdef/legacy/ast_util.py
process_ast ¶
Handle the hand-off to dedicated functions to go from the mvdefs of functions
to move, first deriving lists of imported names which belong to the mvdefs and
the non-mvdefs functions (using parse_mv_funcs), then constructing an
'edit agenda' (using process_ast) which describes [and optionally
reports] the changes to be made at the file level, in terms of move/keep/copy
operations on individual import statements between the source and destination
Python files.
mvdefs: List of functions to be moved trunk: Tree body of the file's AST, which will be separated into function definitions, import statements, and anything else. transfers: List of transfers already determined to be made from the src to the dst file (from the first call to ast_parse) report: Whether to print a report during the program (default: True)
First, given the lists of mvdef names (linkfile.mvdef_names) and non-mvdef names (linkfile.nonmvdef_names), construct the subsets:
mv_imps: imported names used by the functions to move (only in mvdef_names), nm_imps: imported names used by the functions not to move (only in nonmvdef_names), mu_imps: imported names used by both the functions to move and the functions not to move (in both mvdef_names and nonmvdef_names)
Potentially 'as a dry run' (if this is being called by process_ast and its parameter edit is False), report how to remove the import statements or statement sections which import mv_inames, do nothing to the import statements which import nonmv_inames, and copy the import statements which import mutual_inames (as both src and dst need them).
Additionally, accept 'transfers' from a previously determined edit agenda, so as to "take" the "move" names, and "echo" the "copy" names (i.e. when receiving names marked by "move" and "copy", distinguish them to indicate they are being received by transfer [from src⇒dst file], for clarity).
For clarity, note that this function does not edit anything itself, it just describes how it would be possible to carry out the required edits at the level of Python file changes. As such it is computed even on a 'dry run'.
Source code in src/mvdef/legacy/ast_util.py
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | |
find_assigned_args ¶
Produce a list of the names in a function definition fd which are created
by assignment operations (as identified via the function definition's AST).
Source code in src/mvdef/legacy/ast_util.py
set_extradef_names ¶
Return the names used in the AST trunk nodes which are outside of both function definitions and import statements, so as to distinguish the unused names from those which are just used outside of function definitions.
Source code in src/mvdef/legacy/ast_util.py
get_base_type_name ¶
Take a type name from the IntraDefTypeEnum names and return the name of the base type, e.g. input the MethodDef type and get out the name "Func", indicating that a method is a function
Source code in src/mvdef/legacy/ast_util.py
get_def_names ¶
Given the def_list list of strings (must be empty in the negative case rather
than None, and is prepared as such from LinkedFile.mvdefs in parse_mv_funcs),
return a dict from its keys whose entries are the names of its descendant AST nodes.
Source code in src/mvdef/legacy/ast_util.py
parse_mv_funcs ¶
mvdefs: the list of functions to move (string list of function names)
trunk: AST body for the file (via ast.parse(fc).body)
report: whether to print [minimal, readable] 'reporting' output
Produce a dictionary, mvdef_names, whose keys are the list of functions
to move (i.e. the list mvdefs becomes the list of keys of mvdef_names),
and the value of which at each key (for a key m which indicates the name
of one of the functions given in mvdefs to move) is another dictionary,
keyed by the full set of names used in that function (m) which rely upon
import statements (i.e. are not builtin names nor passed as parameters to
the function, nor assigned in the body of the function), and the value
of which at each name is a final nested dictionary whose keys are always:
n: The [0-based] index of the name's source import statement in the
AST list of all ast.Import and ast.ImportFrom.
n_i: The [0-based] index of the name's source import statement within
the one or more names imported by the source import statement at
index n (e.g. for pi in from numpy import e, pi, n_i = 1).
line: The [1-based] line number of the import statement as given in its
corresponding AST entry, which indicates the line number of the
import call, not [necessarily] that of the name (i.e. the name
may not be located there in the file for multi-line imports).
import: The path of the import statement, which may contain multiple
parts conjoined by . (e.g. matplotlib.pyplot)
I.e. the dictionary with entries accessed as mvdef_names.get(m).get(k)
for m in mvdefs and k in the subset of AST-identified imported names
in the function with if f.name not in mvdefs name m in the list of
function definitions defs. This access is handed off to the helper
function get_def_names.
For the names that were imported but not used, the dictionary is not keyed
by function (as there are no associated functions), and instead the entries
are accessed as nondef_names.get(k) for k in unused_names. This access
is handed off to the helper function set_nondef_names.
Source code in src/mvdef/legacy/ast_util.py
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 | |
backup ¶
backup ¶
Given a filename, copy it to a backup before making changes and confirm success to
allow an in place edit to proceed safely. If a file with the same name exists, add
an incrementing integer. If dry_run is True, all the checks for the possibility of
creating the backup will be run, but no files will be opened or touched. (To report
on the funcdef/import statements to be moved without having to adhere to these
requirements, don't call mvdef.backup.backup before calling mvdef.ast_util.run_ast_parse).
Source code in src/mvdef/legacy/backup.py
cli ¶
validate_into_flag ¶
Awkward handling procedure to raise an error if two consecutive flags are both
-i/--into, i.e. if the pop-then-append operations will overwrite the previous
one's.
Source code in src/mvdef/legacy/cli.py
colours ¶
get_colour_codes ¶
Return a dictionary of ANSI colour codes if no colour specified, if a colour is given then check it is in the list of keys and return a start and end ANSI code.
Source code in src/mvdef/legacy/colours.py
get_effect_codes ¶
Return a dictionary of ANSI text effect codes if no effect specified, if a text effect is given then check it is in the list of keys and return a start and end ANSI code.
Source code in src/mvdef/legacy/colours.py
colour_str ¶
Apply the ANSI colour code to a string, and optionally append the end code.
Only use end=False when combining ANSI codes (i.e. in which case the end
code would apply to all modifiers so as to prevent their combination).
Source code in src/mvdef/legacy/colours.py
effect_str ¶
Apply the ANSI effect code to a string, and optionally append the end code.
Only use end=False when combining ANSI codes (i.e. in which case the end
code would apply to all modifiers so as to prevent their combination).
Source code in src/mvdef/legacy/colours.py
underline ¶
colour_effect_str ¶
Apply multiple ANSI colour codes to a string, ending only the outer one, e.g. to both underline and colour, or underline and bold, etc.
The effect must be applied after a colour code, otherwise it will be 'overridden' by the colour code (as far as I have tested).
Note that multiple effects seem to cancel out (with the latter ANSI code taking priority, 'overriding' the other), i.e. multi-effect not possible.
Source code in src/mvdef/legacy/colours.py
def_helpers ¶
def_path_util ¶
TokenisedStr ¶
Source code in src/mvdef/legacy/def_path_util.py
NullPathStr ¶
Bases: TokenisedStr, UntypedMixin
The empty path, used for moving into the global namespace.
Source code in src/mvdef/legacy/def_path_util.py
UntypedPathStr ¶
Bases: UntypedMixin, TokenisedStr
A path without type checks (only to be used when determining path type).
Source code in src/mvdef/legacy/def_path_util.py
FuncDefPathStr ¶
Bases: TokenisedStr, LeafMixin
A path denoting an AST path to a function (which may be nested as an inner function in a funcdef; or as a method in a classdef), or any further nesting therein (e.g. the inner function of an inner function, etc.).
Subclasses should be used to indicate such nested classes, this class itself should only be instantiated for a 'top-level' funcdef, i.e. in the trunk of the AST.
Source code in src/mvdef/legacy/def_path_util.py
InnerFuncDefPathStr ¶
Bases: FuncDefPathStr, ParentedMixin
A FuncDefPathStr in which both the leaf and the leaf's parent are funcdefs. This is checked on init.
This class should be subclassed for checking against the (separate) ASTs used in
either ast_util or asttokens (the first for generating the inner function
indexes, the latter for line numbering associated with the AST nodes).
Source code in src/mvdef/legacy/def_path_util.py
ClassDefPathStr ¶
Bases: TokenisedStr, LeafMixin
A path denoting an AST path to a class (which may be nested as an inner class in a classdef; or as a higher order class in a funcdef), or any further nesting therein (e.g. the inner class of an inner class, etc.). Subclasses should be used to indicate such nested classes, this class itself should only be instantiated for a 'top-level' classdef, i.e. in the trunk of the AST.
Source code in src/mvdef/legacy/def_path_util.py
HigherOrderClassDefPathStr ¶
Bases: ClassDefPathStr, ParentedMixin
A ClassDefPathStr whose leaf is a classdef and whose leaf's parent is a funcdef. This is checked on init.
This class should be subclassed for checking against the (separate) ASTs used in
either ast_util or asttokens.
Source code in src/mvdef/legacy/def_path_util.py
InnerClassDefPathStr ¶
Bases: ClassDefPathStr, ParentedMixin
A ClassDefPathStr in which both the leaf and the leaf's parent are classdefs. This is checked on init.
This class should be subclassed for checking against the (separate) ASTs used in
either ast_util or asttokens (the first for generating the inner function
indexes, the latter for line numbering associated with the AST nodes).
Source code in src/mvdef/legacy/def_path_util.py
MethodDefPathStr ¶
Bases: FuncDefPathStr, ParentedMixin
A FuncDefPathStr whose leaf's parent is a class (and whose leaf is the method func). These are checked on init.
This class should be subclassed for checking against the (separate) ASTs used in
either ast_util or asttokens (the first for generating the inner function
indexes, the latter for line numbering associated with the AST nodes).
Source code in src/mvdef/legacy/def_path_util.py
editor ¶
nix_surplus_imports ¶
Remove imports marked in the agenda as "lose" (src/dst) or "move" (src only).
Bound as a method of SrcFile/DstFile classes, and used within transfer_mvdefs
in step 1 part 1 (dst: removed_import_n) & step 5 part 1 (src: no removed_import_n).
Source code in src/mvdef/legacy/editor.py
shorten_imports ¶
Shorten the imports based on the annotations set by nix_surplus_imports
(potentially removing an import statement entirely if its list of imported
names becomes shortened to 0).
Bound as a method of SrcFile/DstFile classes, and used within transfer_mvdefs
in step 1 part 2 (dst: removed_import_n) & step 5 part 2 (src: no removed_import_n).
Source code in src/mvdef/legacy/editor.py
receive_imports ¶
Receive imports marked in the link.dst.rcv_agenda.
Bound as a method of the FileLink class, and used in step 2 of transfer_mvdefs.
Source code in src/mvdef/legacy/editor.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | |
copy_src_defs_to_dst ¶
Transfer mvdef into the destination file i.e. 'receive mvdef', where mvdef is an
ast.FunctionDefinition node with start/end position annotations using the line
numbers of link.src.trunk, computed as link.src.defs_to_move by
.ast_tokens.get_defs (in the hasattr check block of the
.transfer.SrcFile.defs_to_move property itself). This is an append operation, so
line numbers from link.src.trunk remain valid.
Bound as a method of the FileLink class, and used in step 3 of transfer_mvdefs.
Source code in src/mvdef/legacy/editor.py
remove_copied_defs ¶
Remove function definitions marked as to move from the source file, i.e. after copying them in step 3.
Bound as a method of the SrcFile class, and used within transfer_mvdefs.
Source code in src/mvdef/legacy/editor.py
editor_util ¶
get_defrange ¶
An ast.FunctionDefinition node with start/end position annotations
from the asttokens library.
Source code in src/mvdef/legacy/editor_util.py
get_defstring ¶
An ast.FunctionDefinition node with start/end position annotations
from the asttokens library.
file_lines: A list from readlines (should contain the appropriate file system newlines, the list will be joined with a blank string).
Source code in src/mvdef/legacy/editor_util.py
append_def_to_file ¶
Insert the lines of a function defintion into a file (in future this function may permit insertion at a certain order position in the file's function definitions).
defstring must be a string containing appropriate newlines for a Python file.
Source code in src/mvdef/legacy/editor_util.py
get_def_lines ¶
Get the list of lines of a func. def. suitable to be appended to a set of lines.
deflines must be a list of strings containing appropriate newlines for a Python
file (the lines will not be joined with newlines, they must be already supplied).
Source code in src/mvdef/legacy/editor_util.py
excise_def_from_file ¶
Either cut or delete a function definition using its AST node (via asttokens).
If return_def is True, modify the file at py_path to remove the lines from
def_node.first_token.start[0] to def_node.last_token.end[0], and return the
string read from the lines from py_path which contained it (i.e. a "cut" operation).
If return_def is False, modify the file at py_path to remove the lines that
contain the function called def_name, return None (i.e. a delete operation).
Source code in src/mvdef/legacy/editor_util.py
excise_def_lines ¶
Delete a function definition using its AST node (via asttokens) from a list of lines which originated from a single, entire, Python file.
If the deleted function was the only element in the body of its parent, then replace
it with a pass statement to ensure the file remains valid.
Ensure 2 lines between global-level nodes, and 1 line between inner nodes.
Source code in src/mvdef/legacy/editor_util.py
get_borders ¶
Given the range corresponding to a function definition, and the list of lines
this range is in reference to, and the "window size" of the number of lines
to compare on each [out]side of this range, return the list of indices of
lines which are not None.
This is necessary when some lines have been 'nullified' by replacing the string
at that index with None, so as to conserve the line numbering while removing
lines (i.e. after excising import names and/or function definitions).
The expected value of the range is to follow Python's convention for ranges,
i.e. "inclusive start, exclusive end" - mathematically written as [).
Will return two lists of integers which represent the line indexes of the pre-
and post-function definition non-None lines (i.e. the lines above and below,
ignoring any lines which have previously been removed). If the window_size
of lines above and/or below is not found, the maximum number of lines will be
given (i.e. returns empty lists if nothing is found above/below the defrange).
Source code in src/mvdef/legacy/editor_util.py
overwrite_import ¶
Similar to excise_def_from_lines, this function overwrites the line or lines
which correspond to an import statement (the AST node of which is given as
imp_node), either replacing each line with the equivalent of replacement_str
(the replacement import statement string generated by get_import_stmt_str)
if the replacement is the same number of lines long, or if the number of lines
has changed, it will not split the lines and simply place the entire replacement
import statement string in one entry of the lines list, and set the "spare"
entries over the range previously occupied by the import statement to None.
Source code in src/mvdef/legacy/editor_util.py
example ¶
test ¶
test_demo ¶
list_failing_tests ¶
Returns None if no failing tests, otherwise returns a list of the names of the functions whose tests failed (N.B. not the name of the functions doing the testing, but the ones they test).
Source code in src/mvdef/legacy/example/test/test_demo.py
test_report ¶
Give an error if any tests are failing, otherwise return None.
Source code in src/mvdef/legacy/example/test/test_demo.py
import_util ¶
get_import_stmt_str ¶
Construct an import statement by building an AST, convert it to source using astor.to_source, and then return the string.
alias_list: List of strings to use as ast.alias name, and optionally also
asname entries. If only one name is listed per item in the
alias_list, theasnamewill be instantiated as None.
import_src: If provided, the import statement will be use theast.ImportFromclass, otherwise it will useast.Import.
Relative imports are permitted for "import from" statements
(such asfrom ..foo import bar) however absolute imports
(such asfrom foo import bar) are recommended in PEP8.
max_linechars: Maximum linewidth, beyond which the import statement string will
be multilined withmultilinify_import_stmt_str`.
Source code in src/mvdef/legacy/import_util.py
multilinify_import_stmt_str ¶
Takes a single line import statement and turns it into a multiline string.
Will raise a ValueError if given a multiline string (a newline at the end
of the string is permitted).
This function is written in expectation of the output of get_import_stmt_str,
and is not intended to process all potential ways of writing an import statement.
import_stmt_str: String of Python code carrying out an import statement.
indent_spaces: Number of spaces to indent by in multiline format.
trailing_comma: Whether to add a trailing comma to the final alias in a
multiline list of import aliases (default: True)
Source code in src/mvdef/legacy/import_util.py
colour_imp_stmt ¶
Summary: get a string which when printed will show the separate parts of an import statement in different colours (preamble in blue, alias names in red, alias asnames in purple, the word "as" itself in yellow, commas between import aliases in light green, and post-matter (a bracket) in light red.
For an import statement within an asttokens-annotated AST, which comes with all subnodes annotated with first and last token start/end positional information, access all the tokens corresponding to the import statement name(s) and asname(s).
Do this using a list of lines (i.e. a list of strings, each of which is a line),
the subset of which corresponding to the import statement imp_stmt are given
by its first_token.start and last_token.end attributes (in each case, the
attribute is a tuple of (line, column) numbers, and it is conventional to store
these as a 1-based index, so to cross-reference to a 0-based index of the list
of lines we decrement this value and store as imp_startln and imp_endln).
The subset of lines corresponding to imp_stmt is then assigned as nodelines,
and we join this into a single string as nodestring.
Then a new ASTTokens object, tko, can be made by parsing nodestring, on which
the find_tokens method provides access to each name/asname one at a time, when
matched to the name/asname string. These name/asname strings are available
within the imp_stmt object via its names attribute, which is a list of
ast.alias class instances, each of which has both a name and asname attribute
(the latter of which is None if no asname is given for the import name).
find_tokens returns a token with attribute type of value 1 for a name (1 is
the index of "NAME" in the token.tok_name dictionary), and startpos/endpos
attributes (integers which indicate the string offsets within nodestring).
These startpos integers are an efficient way to store this list of tokens
(the "NAME" tokens corresponding to import statement alias names and asnames),
and so even though it would be possible to store all tokens, I choose to simply
re-access them with the tko.get_token_from_offset(startpos) method.
At the moment, I only re-access these tokens to retrieve their endpos (end
position offset), which is also an integer and could also be stored easily
without much problem, however for the sake of clarity I prefer to re-access
the entire token and not have to construct an arbitrary data structure for
storing the start and end positions (which could get confusing).
Lastly, I construct a colourful string representation of the import statement
by using these start positions and re-retrieved end positions to pull out
and modify (using the mvdef.colours⠶colour_str function) the names and asnames
(names are coloured red, asnames are coloured purple), and use string slicing
to swap the ranges that the names and asnames were in in the original
nodestring for these colourful replacements.
The end result, modified_nodestring is then returned, which will then
display in colour on Linux and OSX (I don't think Windows supports ANSI codes,
so I made colour_str only apply on these platforms).
Source code in src/mvdef/legacy/import_util.py
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | |
count_imported_names ¶
Return an integer for a single node (0 if not an import statement), else return a list of integers for a list of AST nodes.
Source code in src/mvdef/legacy/import_util.py
annotate_imports ¶
Produce two data structures from the list of import statements (the statements
of type ast.Import and ast.ImportFrom in the source program's AST),
imp_name_linedict: A dictionary whose keys are all the names imported by the
program (i.e. the names which they are imported as: the
asname if one is used), and whose value for each name
is a dictionary of keys (n, line):
n: [0-based] index of the import statement importing
the name, over the set of all import statements.
line: [1-based] line number of the file of the import
statement importing the name. Note that it may
not correspond to the line number on which the
name is given, only to the import function call.
imp_name_dict_list: List of one dict per import statement, whose keys
are the full import path (with multi-part paths conjoined
by a period .) and the values of which are the names
that these import paths are imported as (either the asname
or else just the terminal part of the import path). The
dict preserves the per-line order of the imported
names.
Source code in src/mvdef/legacy/import_util.py
imp_def_subsets ¶
Given the list of mvdef_names and nonmvdef_names, construct the subsets: mv_imports: imported names used by the functions to move, nonmv_imports: imported names used by the functions not to move, mutual_imports: imported names used by both the functions to move and the functions not to move
Source code in src/mvdef/legacy/import_util.py
io_util ¶
terminal_whitespace ¶
Return the number of whitespace newlines in the file.
If the file contains no newlines, returns 0.
Source code in src/mvdef/legacy/io_util.py
transfer ¶
LinkedFile ¶
Source code in src/mvdef/legacy/transfer.py
undef_names
property
writable
¶
undef_names contains only those names that are imported but never used
ast_parse ¶
Create edit agendas from the parsed AST of source and destination files
Source code in src/mvdef/legacy/transfer.py
get_merged_dicts ¶
Return the first item in each agenda category (without list expanding). Used when we no longer need to keep a record of a name's annotation.
Source code in src/mvdef/legacy/transfer.py
SrcFile ¶
Bases: LinkedFile
Source code in src/mvdef/legacy/transfer.py
set_rm_agenda ¶
DstFile ¶
Bases: LinkedFile
Source code in src/mvdef/legacy/transfer.py
FileLink ¶
FileLink(mvdefs, into_paths, src_p, dst_p, report, nochange, test_func, use_backup, copy_only, classes_only)
Source code in src/mvdef/legacy/transfer.py
parse_transfer ¶
parse_transfer(mvdefs, into_paths, src_p, dst_p, report=True, nochange=True, test_func=None, use_backup=True, copy_only=False, classes_only=False)
Execute the transfer of function definitions and import statements, optionally (if test_func is specified) also calls that afterwards to confirm functionality remains intact.
If test_func is specified, it must only use AssertionError (i.e. you are free to have the test_func call other functions, but it must catch any errors therein and only raise errors from assert statements). This is to simplify this step. My example would be to list one or more failing tests, then assert that this list is None, else raise an AssertionError of these tests' definition names (see example.test.test_demo⠶test_report for an example of such a function).
If nochange is False, files will be changed in place (i.e. setting it to False is equivalent to setting the edit parameter to True). - Note: this was unimplemented...
This parameter is used as a sanity check to prevent wasted computation, as if neither report is True nor nochange is False, there is nothing to do.
Source code in src/mvdef/legacy/transfer.py
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 | |