ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Tools
PyUtils
python
acmdlib.py
Go to the documentation of this file.
1
# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3
# @file PyUtils.acmdlib
4
# @purpose a library to ease the writing of sub-command scripts
5
# @author Sebastien Binet
6
# @date January 2010
7
8
__doc__ =
"a library to ease the writing of sub-command scripts"
9
__author__ =
"Sebastien Binet"
10
11
__all__ = [
12
'Command'
,
13
'command'
,
14
'argument'
,
15
'register'
,
16
]
17
18
19
import
argparse
20
import
textwrap
21
import
importlib
22
23
24
ACMD_GROUPNAME =
'acmdlib.commands'
25
"""The name under which all commands are grouped
26
"""
27
28
ACMD_PARSER = argparse.ArgumentParser(
29
prog=
"acmd"
,
30
description=
"a general script interface with sub-commands"
,
31
)
32
33
ACMD_SUBPARSERS = ACMD_PARSER.add_subparsers(
34
dest=
'command'
,
35
title=
'commands'
,
36
metavar=
'COMMAND'
,
37
required=
True
,
38
)
39
40
41
class
Command
(object):
42
"""A wrapper class to manage the creation of commands and their arguments
43
44
this is very heavily inspired from:
45
http://pypi.python.org/pypi/django-boss (MIT licence)
46
"""
47
48
def
__init__
(self, fct, **kwargs):
49
object.__init__(self)
50
self.
fct
= fct
51
self.
parser
= self.
_make_parser
(**kwargs)
52
self.
_init_arguments
()
53
plugin_name = kwargs.get(
'name'
)
or
self.
name
54
register
(plugin_name, self.
fct
.__module__)
55
56
@property
57
def
name
(self):
58
return
self.
fct
.__name__.replace(
'_'
,
'-'
)
59
60
@property
61
def
help
(self):
62
if
getattr(self.
fct
,
'__doc__'
,
None
):
63
# just the first line of the doc string
64
return
self.
fct
.__doc__.splitlines()[0]
65
66
@property
67
def
description
(self):
68
if
getattr(self.
fct
,
'__doc__'
,
None
):
69
return
textwrap.dedent(self.
fct
.__doc__)
70
71
@property
72
def
add_argument
(self):
73
return
self.
parser
.add_argument
74
75
def
__call__
(self, *args, **kwargs):
76
return
self.
fct
(*args, **kwargs)
77
78
def
_make_parser
(self, **kwargs):
79
"""Create and register a subparser for this command."""
80
81
kwargs.setdefault(
'help'
, self.
help
)
82
kwargs.setdefault(
'formatter_class'
,argparse.RawDescriptionHelpFormatter)
83
kwargs.setdefault(
'description'
, self.
description
)
84
kwargs.setdefault(
'name'
, self.
name
)
85
names = (kwargs.get(
'name'
)
or
self.
name
).
split
(
'.'
)
86
87
def
_get_subparser(a):
88
if
a._subparsers:
89
for
action
in
a._subparsers._actions:
90
if
isinstance(action, argparse._SubParsersAction):
91
return
action
92
raise
RuntimeError(
'could not find adequate subparser'
)
93
return
a.add_subparsers(dest=
'command'
,
94
title=
'commands'
,
95
metavar=
'COMMAND'
,
96
required=
True
,
97
)
98
def
_get_parser(node, name):
99
if
name
in
node.choices:
100
return
node.choices[name]
101
args = {
102
'name'
: name,
103
'help'
:
'a group of sub-commands'
,
104
}
105
return
node.add_parser(**args)
106
107
parser = ACMD_PARSER
108
for
name
in
names[:-1]:
109
node = _get_subparser(parser)
110
parser = _get_parser(node, name)
111
112
node = _get_subparser(parser)
113
kwargs[
'name'
] = names[-1]
114
parser = node.add_parser(**kwargs)
115
return
parser
116
117
def
add_mutually_exclusive_group
(self, **kwargs):
118
return
self.
parser
.
add_mutually_exclusive_group
(**kwargs)
119
120
def
_init_arguments
(self):
121
if
hasattr(self.
fct
,
'_acmdlib_arguments'
):
122
while
self.
fct
._acmdlib_arguments:
123
args, kwargs = self.
fct
._acmdlib_arguments.pop()
124
self.
add_argument
(*args, **kwargs)
125
126
if
hasattr(self.
fct
,
'_acmdlib_arguments_mutual'
):
127
if
not
hasattr(self,
'_acmdlib_mutual_group'
):
128
self.
_acmdlib_mutual_group
= self.
add_mutually_exclusive_group
()
129
while
self.
fct
._acmdlib_arguments_mutual:
130
args, kwargs = self.
fct
._acmdlib_arguments_mutual.pop()
131
self.
_acmdlib_mutual_group
.
add_argument
(*args, **kwargs)
132
133
pass
# Command
134
135
class
Plugins
(object):
136
"""A simple plugin registration.
137
"""
138
_plugins = {}
139
140
@classmethod
141
def
register
(cls, name, value):
142
"""Register plugin
143
"""
144
cls.
_plugins
[name] = value
145
146
@classmethod
147
def
exists
(cls, name):
148
"""Check if plugin exists
149
"""
150
return
name
in
cls.
_plugins
151
152
@classmethod
153
def
load
(cls, name):
154
"""Load given plugin and return it
155
"""
156
try
:
157
return
importlib.import_module(cls.
_plugins
[name])
158
except
Exception
as
err:
159
print
(
"** could not load command [%s]:\n%s"
% (name, err))
160
161
@classmethod
162
def
loadAll
(cls):
163
"""Load all plugins
164
"""
165
for
k
in
cls.
_plugins
.keys():
166
cls.
load
(k)
167
168
169
170
def
command
(*args, **kwargs):
171
"""Decorator to declare that a function is a command.
172
"""
173
def
deco(fct):
174
return
Command
(fct, **kwargs)
175
if
args:
176
return
deco(*args)
177
return
deco
178
179
def
argument
(*args, **kwargs):
180
"""Decorator to add an argument to a command.
181
Use the `mutual=True` keyword to specify that the argument should belong to a mutual exclusion group.
182
"""
183
is_mutual = kwargs.pop(
'mutual'
,
False
)
184
185
def
deco(fct):
186
if
isinstance(fct, Command):
187
cmd = fct
188
if
is_mutual:
189
if
not
hasattr(cmd,
'_acmdlib_mutual_group'
):
190
cmd._acmdlib_mutual_group = cmd.add_mutually_exclusive_group()
191
cmd._acmdlib_mutual_group.add_argument(*args, **kwargs)
192
else
:
193
cmd.add_argument(*args, **kwargs)
194
else
:
195
store_as =
'_acmdlib_arguments_mutual'
if
is_mutual
else
'_acmdlib_arguments'
196
if
not
hasattr(fct, store_as):
197
setattr(fct, store_as, [])
198
getattr(fct, store_as).append((args, kwargs))
199
#print "===",args,kwargs,type(fct),fct
200
return
fct
201
return
deco
202
203
def
register
(name, value):
204
"""Registers a plugin, given a name and value.
205
206
ex: register('check-file', 'PyUtils.CheckFileLib:fct')
207
"""
208
209
return
Plugins.register(name, value)
print
void print(char *figname, TCanvas *c1)
Definition
TRTCalib_StrawStatusPlots.cxx:26
python.acmdlib.Command
classes ----------------------------------------------------------------—
Definition
acmdlib.py:41
python.acmdlib.Command.name
name
Definition
acmdlib.py:84
python.acmdlib.Command.add_mutually_exclusive_group
add_mutually_exclusive_group(self, **kwargs)
Definition
acmdlib.py:117
python.acmdlib.Command.description
description
Definition
acmdlib.py:83
python.acmdlib.Command.__call__
__call__(self, *args, **kwargs)
Definition
acmdlib.py:75
python.acmdlib.Command.fct
fct
Definition
acmdlib.py:50
python.acmdlib.Command._make_parser
_make_parser(self, **kwargs)
Definition
acmdlib.py:78
python.acmdlib.Command._acmdlib_mutual_group
_acmdlib_mutual_group
Definition
acmdlib.py:128
python.acmdlib.Command.parser
parser
Definition
acmdlib.py:51
python.acmdlib.Command.help
help
Definition
acmdlib.py:81
python.acmdlib.Command._init_arguments
_init_arguments(self)
Definition
acmdlib.py:120
python.acmdlib.Command.add_argument
add_argument(self)
Definition
acmdlib.py:72
python.acmdlib.Command.__init__
__init__(self, fct, **kwargs)
Definition
acmdlib.py:48
python.acmdlib.Plugins
Definition
acmdlib.py:135
python.acmdlib.Plugins.load
load(cls, name)
Definition
acmdlib.py:153
python.acmdlib.Plugins.register
register(cls, name, value)
Definition
acmdlib.py:141
python.acmdlib.Plugins._plugins
dict _plugins
Definition
acmdlib.py:138
python.acmdlib.Plugins.exists
exists(cls, name)
Definition
acmdlib.py:147
python.acmdlib.Plugins.loadAll
loadAll(cls)
Definition
acmdlib.py:162
split
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition
hcg.cxx:179
python.acmdlib.argument
argument(*args, **kwargs)
Definition
acmdlib.py:179
python.acmdlib.register
register(name, value)
Definition
acmdlib.py:203
python.acmdlib.command
command(*args, **kwargs)
Definition
acmdlib.py:170
Generated on
for ATLAS Offline Software by
1.17.0