1+ # Copied from https://github.com/nexB/scancode-toolkit/blob/b4ea9c640f8ee4ed8851b5618c6d223bb1c02d47/src/commoncode/datautils.py
2+ #
3+ # Copyright (c) 2018 nexB Inc. and others. All rights reserved.
4+ # http://nexb.com and https://github.com/nexB/scancode-toolkit/
5+ # The ScanCode software is licensed under the Apache License version 2.0.
6+ # Data generated with ScanCode require an acknowledgment.
7+ # ScanCode is a trademark of nexB Inc.
8+ #
9+ # You may not use this software except in compliance with the License.
10+ # You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0
11+ # Unless required by applicable law or agreed to in writing, software distributed
12+ # under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
13+ # CONDITIONS OF ANY KIND, either express or implied. See the License for the
14+ # specific language governing permissions and limitations under the License.
15+ #
16+ # When you publish or redistribute any data created with ScanCode or any ScanCode
17+ # derivative work, you must accompany this data with the following acknowledgment:
18+ #
19+ # Generated with ScanCode and provided on an "AS IS" BASIS, WITHOUT WARRANTIES
20+ # OR CONDITIONS OF ANY KIND, either express or implied. No content created from
21+ # ScanCode should be considered or used as legal advice. Consult an Attorney
22+ # for any legal advice.
23+ # ScanCode is a free software code scanning tool from nexB Inc. and others.
24+ # Visit https://github.com/nexB/scancode-toolkit/ for support and download.
25+
26+ from __future__ import absolute_import
27+ from __future__ import print_function
28+ from __future__ import unicode_literals
29+
30+ from collections import OrderedDict
31+
32+ import attr
33+ from attr.validators import in_ as choices # NOQA
34+ import typing
35+
36+
37+ """
38+ Utilities and helpers for data classes.
39+ """
40+
41+
42+ HELP_METADATA = '__field_help'
43+ LABEL_METADATA = '__field_label'
44+
45+
46+ def attribute(default=attr.NOTHING, validator=None,
47+ repr=False, eq=True, order=True, # NOQA
48+ init=True, type=None, converter=None, # NOQA
49+ help=None, label=None, metadata=None,): # NOQA
50+ """
51+ A generic attribute with help metadata and that is not included in the
52+ representation by default.
53+ """
54+ metadata = metadata or dict()
55+ if help:
56+ metadata[HELP_METADATA] = help
57+
58+ if label:
59+ metadata[LABEL_METADATA] = label
60+
61+ return attr.attrib(
62+ default=default,
63+ validator=validator,
64+ repr=repr,
65+ eq=eq,
66+ order=order,
67+ init=init,
68+ metadata=metadata,
69+ type=type,
70+ converter=converter
71+ )
72+
73+
74+ def Boolean(default=False, validator=None, repr=False, eq=True, order=True, # NOQA
75+ converter=None, label=None, help=None,): # NOQA
76+ """
77+ A boolean attribute.
78+ """
79+ return attribute(
80+ default=default,
81+ validator=validator,
82+ repr=repr,
83+ eq=eq,
84+ order=order,
85+ init=True,
86+ type=bool,
87+ converter=converter,
88+ help=help,
89+ label=label,
90+ )
91+
92+
93+ def TriBoolean(default=None, validator=None, repr=False, eq=True, order=True, # NOQA
94+ converter=None, label=None, help=None,): # NOQA
95+ """
96+ A tri-boolean attribute with possible values of None, True and False.
97+ """
98+ return attribute(
99+ default=default,
100+ validator=validator,
101+ repr=repr,
102+ eq=eq,
103+ order=order,
104+ init=True,
105+ type=bool,
106+ converter=converter,
107+ help=help,
108+ label=label,
109+ )
110+
111+
112+ def String(default=None, validator=None, repr=False, eq=True, order=True, # NOQA
113+ converter=None, label=None, help=None,): # NOQA
114+ """
115+ A string attribute.
116+ """
117+ return attribute(
118+ default=default,
119+ validator=validator,
120+ repr=repr,
121+ eq=eq,
122+ order=order,
123+ init=True,
124+ type=str,
125+ converter=converter,
126+ help=help,
127+ label=label,
128+ )
129+
130+
131+ def Integer(default=0, validator=None, repr=False, eq=True, order=True, # NOQA
132+ converter=None, label=None, help=None,): # NOQA
133+ """
134+ An integer attribute.
135+ """
136+ converter = converter or attr.converters.optional(int)
137+ return attribute(
138+ default=default,
139+ validator=validator,
140+ repr=repr,
141+ eq=eq,
142+ order=order,
143+ init=True,
144+ type=int,
145+ converter=converter,
146+ help=help,
147+ label=label,
148+ )
149+
150+
151+ def Float(default=0.0, validator=None, repr=False, eq=True, order=True, # NOQA
152+ converter=None, label=None, help=None,): # NOQA
153+ """
154+ A float attribute.
155+ """
156+ return attribute(
157+ default=default,
158+ validator=validator,
159+ repr=repr,
160+ eq=eq,
161+ order=order,
162+ init=True,
163+ type=float,
164+ converter=converter,
165+ help=help,
166+ label=label,
167+ )
168+
169+
170+ def List(item_type=typing.Any, default=attr.NOTHING, validator=None,
171+ repr=False, eq=True, order=True, # NOQA
172+ converter=None, label=None, help=None,): # NOQA
173+ """
174+ A list attribute: the optional item_type defines the type of items it stores.
175+ """
176+ if default is attr.NOTHING:
177+ default = attr.Factory(list)
178+
179+ return attribute(
180+ default=default,
181+ validator=validator,
182+ repr=repr,
183+ eq=eq,
184+ order=order,
185+ init=True,
186+ type=typing.List[item_type],
187+ converter=converter,
188+ help=help,
189+ label=label,
190+ )
191+
192+
193+ def Mapping(value_type=typing.Any, default=attr.NOTHING, validator=None,
194+ repr=False, eq=True, order=True, # NOQA
195+ converter=None, help=None, label=None): # NOQA
196+ """
197+ A mapping attribute: the optional value_type defines the type of values it
198+ stores. The key is always a string.
199+
200+ Notes: in Python 2 the type is Dict as there is no typing available for
201+ OrderedDict for now.
202+ """
203+ if default is attr.NOTHING:
204+ default = attr.Factory(OrderedDict)
205+
206+ return attribute(
207+ default=default,
208+ validator=validator,
209+ repr=repr,
210+ eq=eq,
211+ order=order,
212+ init=True,
213+ type=typing.Dict[str, value_type],
214+ converter=converter,
215+ help=help,
216+ label=label,
217+ )
218+
219+
220+ ##################################################
221+ # FIXME: add proper support for dates!!!
222+ ##################################################
223+
224+ def Date(default=None, validator=None, repr=False, eq=True, order=True, # NOQA
225+ converter=None, label=None, help=None,): # NOQA
226+ """
227+ A date attribute. It always serializes to an ISO date string.
228+ Behavior is TBD and for now this is exactly a string.
229+ """
230+ return String(
231+ default=default,
232+ validator=validator,
233+ repr=repr,
234+ eq=eq,
235+ order=order,
236+ converter=converter,
237+ help=help,
238+ label=label,
239+ )
0 commit comments