Robot Framework
argumentspec.py
Go to the documentation of this file.
1 # Copyright 2008-2015 Nokia Networks
2 # Copyright 2016- Robot Framework Foundation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 import sys
17 from enum import Enum
18 
19 from robot.utils import is_union, safe_str, setter, type_repr
20 
21 from .argumentconverter import ArgumentConverter
22 from .argumentmapper import ArgumentMapper
23 from .argumentresolver import ArgumentResolver
24 from .typevalidator import TypeValidator
25 
26 
28 
29  def __init__(self, name=None, type='Keyword', positional_only=None,
30  positional_or_named=None, var_positional=None, named_only=None,
31  var_named=None, defaults=None, types=None):
32  self.namename = name
33  self.typetype = type
34  self.positional_onlypositional_only = positional_only or []
35  self.positional_or_namedpositional_or_named = positional_or_named or []
36  self.var_positionalvar_positional = var_positional
37  self.named_onlynamed_only = named_only or []
38  self.var_namedvar_named = var_named
39  self.defaultsdefaults = defaults or {}
40  self.typestypestypes = types
41 
42  @setter
43  def types(self, types):
44  return TypeValidator(self).validate(types)
45 
46  @property
47  positional = property
48 
49  def positional(self):
50  return self.positional_onlypositional_only + self.positional_or_namedpositional_or_named
51 
52  @property
53  minargs = property
54 
55  def minargs(self):
56  return len([arg for arg in self.positionalpositionalpositional if arg not in self.defaultsdefaults])
57 
58  @property
59  maxargs = property
60 
61  def maxargs(self):
62  return len(self.positionalpositionalpositional) if not self.var_positionalvar_positional else sys.maxsize
63 
64  @property
65  argument_names = property
66 
67  def argument_names(self):
68  return (self.positional_onlypositional_only +
69  self.positional_or_namedpositional_or_named +
70  ([self.var_positionalvar_positional] if self.var_positionalvar_positional else []) +
71  self.named_onlynamed_only +
72  ([self.var_namedvar_named] if self.var_namedvar_named else []))
73 
74  def resolve(self, arguments, variables=None, converters=None,
75  resolve_named=True, resolve_variables_until=None,
76  dict_to_kwargs=False, languages=None):
77  resolver = ArgumentResolver(self, resolve_named,
78  resolve_variables_until, dict_to_kwargs)
79  positional, named = resolver.resolve(arguments, variables)
80  return self.convertconvert(positional, named, converters, dry_run=not variables,
81  languages=languages)
82 
83  def convert(self, positional, named, converters=None, dry_run=False, languages=None):
84  if self.typestypestypes or self.defaultsdefaults:
85  converter = ArgumentConverter(self, converters, dry_run, languages)
86  positional, named = converter.convert(positional, named)
87  return positional, named
88 
89  def map(self, positional, named, replace_defaults=True):
90  mapper = ArgumentMapper(self)
91  return mapper.map(positional, named, replace_defaults)
92 
93  def __iter__(self):
94  notset = ArgInfo.NOTSET
95  get_type = (self.typestypestypes or {}).get
96  get_default = self.defaultsdefaults.get
97  for arg in self.positional_onlypositional_only:
98  yield ArgInfo(ArgInfo.POSITIONAL_ONLY, arg,
99  get_type(arg, notset), get_default(arg, notset))
100  if self.positional_onlypositional_only:
101  yield ArgInfo(ArgInfo.POSITIONAL_ONLY_MARKER)
102  for arg in self.positional_or_namedpositional_or_named:
103  yield ArgInfo(ArgInfo.POSITIONAL_OR_NAMED, arg,
104  get_type(arg, notset), get_default(arg, notset))
105  if self.var_positionalvar_positional:
106  yield ArgInfo(ArgInfo.VAR_POSITIONAL, self.var_positionalvar_positional,
107  get_type(self.var_positionalvar_positional, notset))
108  elif self.named_onlynamed_only:
109  yield ArgInfo(ArgInfo.NAMED_ONLY_MARKER)
110  for arg in self.named_onlynamed_only:
111  yield ArgInfo(ArgInfo.NAMED_ONLY, arg,
112  get_type(arg, notset), get_default(arg, notset))
113  if self.var_namedvar_named:
114  yield ArgInfo(ArgInfo.VAR_NAMED, self.var_namedvar_named,
115  get_type(self.var_namedvar_named, notset))
116 
117  def __bool__(self):
118  return any([self.positional_onlypositional_only, self.positional_or_namedpositional_or_named, self.var_positionalvar_positional,
119  self.named_onlynamed_only, self.var_namedvar_named])
120 
121  def __str__(self):
122  return ', '.join(str(arg) for arg in self)
123 
124 
125 class ArgInfo:
126  NOTSET = object()
127  POSITIONAL_ONLY = 'POSITIONAL_ONLY'
128  POSITIONAL_ONLY_MARKER = 'POSITIONAL_ONLY_MARKER'
129  POSITIONAL_OR_NAMED = 'POSITIONAL_OR_NAMED'
130  VAR_POSITIONAL = 'VAR_POSITIONAL'
131  NAMED_ONLY_MARKER = 'NAMED_ONLY_MARKER'
132  NAMED_ONLY = 'NAMED_ONLY'
133  VAR_NAMED = 'VAR_NAMED'
134 
135  def __init__(self, kind, name='', types=NOTSET, default=NOTSET):
136  self.kindkind = kind
137  self.namename = name
138  self.typestypestypes = types
139  self.defaultdefault = default
140 
141  @setter
142  def types(self, typ):
143  if not typ or typ is self.NOTSETNOTSET:
144  return tuple()
145  if isinstance(typ, tuple):
146  return typ
147  if is_union(typ):
148  return typ.__args__
149  return (typ,)
150 
151  @property
152  required = property
153 
154  def required(self):
155  if self.kindkind in (self.POSITIONAL_ONLYPOSITIONAL_ONLY,
156  self.POSITIONAL_OR_NAMEDPOSITIONAL_OR_NAMED,
157  self.NAMED_ONLYNAMED_ONLY):
158  return self.defaultdefault is self.NOTSETNOTSET
159  return False
160 
161  @property
162  types_reprs = property
163 
164  def types_reprs(self):
165  return [type_repr(t) for t in self.typestypestypes]
166 
167  @property
168  default_repr = property
169 
170  def default_repr(self):
171  if self.defaultdefault is self.NOTSETNOTSET:
172  return None
173  if isinstance(self.defaultdefault, Enum):
174  return self.defaultdefault.name
175  return safe_str(self.defaultdefault)
176 
177  def __str__(self):
178  if self.kindkind == self.POSITIONAL_ONLY_MARKERPOSITIONAL_ONLY_MARKER:
179  return '/'
180  if self.kindkind == self.NAMED_ONLY_MARKERNAMED_ONLY_MARKER:
181  return '*'
182  ret = self.namename
183  if self.kindkind == self.VAR_POSITIONALVAR_POSITIONAL:
184  ret = '*' + ret
185  elif self.kindkind == self.VAR_NAMEDVAR_NAMED:
186  ret = '**' + ret
187  if self.typestypestypes:
188  ret = '%s: %s' % (ret, ' | '.join(self.types_reprstypes_reprstypes_reprs))
189  default_sep = ' = '
190  else:
191  default_sep = '='
192  if self.defaultdefault is not self.NOTSETNOTSET:
193  ret = '%s%s%s' % (ret, default_sep, self.default_reprdefault_reprdefault_repr)
194  return ret
def __init__(self, kind, name='', types=NOTSET, default=NOTSET)
def __init__(self, name=None, type='Keyword', positional_only=None, positional_or_named=None, var_positional=None, named_only=None, var_named=None, defaults=None, types=None)
Definition: argumentspec.py:31
def map(self, positional, named, replace_defaults=True)
Definition: argumentspec.py:89
def resolve(self, arguments, variables=None, converters=None, resolve_named=True, resolve_variables_until=None, dict_to_kwargs=False, languages=None)
Definition: argumentspec.py:76
def convert(self, positional, named, converters=None, dry_run=False, languages=None)
Definition: argumentspec.py:83
def type_repr(typ)
Return string representation for types.
Definition: robottypes.py:116
def is_union(item, allow_tuple=False)
Definition: robottypes.py:76
def safe_str(item)
Definition: unic.py:21