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