This repository has been archived by the owner on Jan 13, 2024. It is now read-only.
/
magic_parser.py
118 lines (100 loc) · 3.96 KB
/
magic_parser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#-*- coding: utf-8 -*-
"""
@file
@brief Magic command to handle files
"""
import argparse
import shlex
from ..loghelper.flog import noLOG
class MagicCommandParser (argparse.ArgumentParser):
"""
add method ``parse_cmd`` to
`argparse.ArgumentParser <https://docs.python.org/3.4/library/argparse.html#argumentparser-objects>`_
.. versionadded:: 0.9
"""
def __init__(self, *l, **p):
"""
custom constructor, see `ArgumentParser <https://docs.python.org/3.4/library/argparse.html>`_
"""
argparse.ArgumentParser.__init__(self, *l, **p)
self._keep_args = {}
@staticmethod
def _private_get_name(*args):
"""
guesses the name of a parameter knowning the argument
given to @see me add_argument
"""
for i, a in enumerate(args):
if isinstance(a, str):
if a[0] != "-":
return a
elif a.startswith("--"):
return a[2:].replace("-", "_")
raise KeyError("unable to find parameter name in: " + str(args))
def add_argument(self, *args, **kwargs):
"""
overloads the methods, see `ArgumentParser <https://docs.python.org/3.4/library/argparse.html>`_
"""
super(argparse.ArgumentParser, self).add_argument(*args, **kwargs)
if args != ('-h', '--help'):
name = MagicCommandParser._private_get_name(*args)
self._keep_args[name] = (args, kwargs)
def has_choices(self, name):
"""
tells if a parameter has choises
@param name parameter name
@return boolean
"""
if name not in self._keep_args:
raise KeyError("unable to find parameter name: {0} in {1}".format(
name, list(self._keep_args.keys())))
return "choices" in self._keep_args[name][1]
def parse_cmd(self, line, context=None, fLOG=noLOG):
"""
split line using `shlex <https://docs.python.org/3.4/library/shlex.html>`_
and call `parse_args <https://docs.python.org/3.4/library/argparse.html#argparse.ArgumentParser.parse_args>`_
@param line string
@param context if not None, tries to evaluate expression the command may contain
@param fLOG logging function
@return list of strings
"""
args = shlex.split(line, posix=False)
res = self.parse_args(args)
if context is not None:
up = {}
for k, v in res.__dict__.items():
if self.has_choices(k):
up[k] = v
else:
ev = self.eval(v, context=context, fLOG=fLOG)
if ev != v:
up[k] = ev
if len(up) > 0:
for k, v in up.items():
res.__dict__[k] = v
return res
def eval(self, value, context, fLOG=noLOG):
"""
Evaluate a string knowing the context,
it returns *value* if it does not belong to the context
or if it contains brackets or symbols (+, *),
if the value cannot be evaluated (with function `eval <https://docs.python.org/3.4/library/functions.html#eval>`_),
it returns the value value
@param value string
@param context something like ``self.shell.user_ns``
@return *value* or its evaluation
"""
if value in context:
return context[value]
if isinstance(value, str) and (
"[" in value or "]" in value or "+" in value or "*" in value or
value.split(".")[0] in context):
try:
res = eval(value, {}, context)
return res
except Exception as e:
fLOG(
"unable to interpret: " + str(value), " exception ", str(e))
return value
else:
return value