Robot Framework
datatypes.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 from inspect import isclass
17 from enum import Enum
18 
19 from robot.utils import getdoc, Sortable, typeddict_types, type_name
20 from robot.running import TypeConverter
21 
22 from .standardtypes import STANDARD_TYPE_DOCS
23 
24 
25 EnumType = type(Enum)
26 
27 
28 class TypeDoc(Sortable):
29  ENUM = 'Enum'
30  TYPED_DICT = 'TypedDict'
31  CUSTOM = 'Custom'
32  STANDARD = 'Standard'
33 
34  def __init__(self, type, name, doc, accepts=(), usages=None,
35  members=None, items=None):
36  self.typetype = type
37  self.namename = name
38  self.docdoc = doc or '' # doc parsed from XML can be None.
39  self.acceptsaccepts = [type_name(t) if not isinstance(t, str) else t for t in accepts]
40  self.usagesusages = usages or []
41  # Enum members and TypedDict items are used only with appropriate types.
42  self.membersmembers = members
43  self.itemsitems = items
44 
45  @property
46  _sort_key = property
47 
48  def _sort_key(self):
49  return self.namename.lower()
50 
51  @classmethod
52  def for_type(cls, type_hint, converters):
53  if isinstance(type_hint, EnumType):
54  return cls.for_enumfor_enum(type_hint)
55  if isinstance(type_hint, typeddict_types):
56  return cls.for_typed_dictfor_typed_dict(type_hint)
57  converter = TypeConverter.converter_for(type_hint, converters)
58  if not converter:
59  return None
60  elif not converter.type:
61  return cls(cls.CUSTOMCUSTOM, converter.type_name, converter.doc,
62  converter.value_types)
63  else:
64  # Get `type_name` from class, not from instance, to get the original
65  # name with generics like `list[int]` that override it in instance.
66  return cls(cls.STANDARDSTANDARD, type(converter).type_name,
67  STANDARD_TYPE_DOCS[converter.type], converter.value_types)
68 
69  @classmethod
70  def for_enum(cls, enum):
71  accepts = (str, int) if issubclass(enum, int) else (str,)
72  return cls(cls.ENUMENUM, enum.__name__, getdoc(enum), accepts,
73  members=[EnumMember(name, str(member.value))
74  for name, member in enum.__members__.items()])
75 
76  @classmethod
77  def for_typed_dict(cls, typed_dict):
78  items = []
79  required_keys = list(getattr(typed_dict, '__required_keys__', []))
80  optional_keys = list(getattr(typed_dict, '__optional_keys__', []))
81  for key, value in typed_dict.__annotations__.items():
82  typ = value.__name__ if isclass(value) else str(value)
83  required = key in required_keys if required_keys or optional_keys else None
84  items.append(TypedDictItem(key, typ, required))
85  return cls(cls.TYPED_DICTTYPED_DICT, typed_dict.__name__, getdoc(typed_dict),
86  accepts=(str,), items=items)
87 
88  def to_dictionary(self, legacy=False):
89  data = {
90  'type': self.typetype,
91  'name': self.namename,
92  'doc': self.docdoc,
93  }
94  if not legacy:
95  data['usages'] = self.usagesusages
96  data['accepts'] = self.acceptsaccepts
97  if self.membersmembers is not None:
98  data['members'] = [m.to_dictionary() for m in self.membersmembers]
99  if self.itemsitems is not None:
100  data['items'] = [i.to_dictionary() for i in self.itemsitems]
101  return data
102 
103 
105 
106  def __init__(self, key, type, required=None):
107  self.keykey = key
108  self.typetype = type
109  self.requiredrequired = required
110 
111  def to_dictionary(self):
112  return {'key': self.keykey, 'type': self.typetype, 'required': self.requiredrequired}
113 
114 
116 
117  def __init__(self, name, value):
118  self.namename = name
119  self.valuevalue = value
120 
121  def to_dictionary(self):
122  return {'name': self.namename, 'value': self.valuevalue}
def __init__(self, name, value)
Definition: datatypes.py:117
def for_typed_dict(cls, typed_dict)
Definition: datatypes.py:77
def to_dictionary(self, legacy=False)
Definition: datatypes.py:88
def for_type(cls, type_hint, converters)
Definition: datatypes.py:52
def __init__(self, type, name, doc, accepts=(), usages=None, members=None, items=None)
Definition: datatypes.py:35
def __init__(self, key, type, required=None)
Definition: datatypes.py:106
def type_name(item, capitalize=False)
Return "non-technical" type name for objects and types.
Definition: robottypes.py:86
def getdoc(item)
Definition: text.py:180