vhatable 1.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
vhatable/__init__.py ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env python
2
+ """TODO"""
3
+
4
+
5
+ # This file is part of Vhatable api.
6
+ #
7
+ # Vhatable api is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # Vhatable api is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with Vhatable api. If not, see <http://www.gnu.org/licenses/>.
19
+ #
20
+ # Copyright 2014-2016 Frédéric MARTIN
21
+ #
22
+ # Contributors list :
23
+ #
24
+ # Frédéric MARTIN frederic.martin.fma@gmail.com
25
+ #
26
+
27
+ __all__ = ["cell", "core", "filters"]
vhatable/cell.py ADDED
@@ -0,0 +1,344 @@
1
+ #! /usr/bin/env python
2
+ """TODO"""
3
+
4
+
5
+ # This file is part of Vhatable cli.
6
+ #
7
+ # Vhatable cli is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # Vhatable cli is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with Vhatable cli. If not, see <http://www.gnu.org/licenses/>.
19
+ #
20
+ # Copyright 2019 Frédéric MARTIN
21
+ #
22
+ # Contributors list :
23
+ #
24
+ # Frédéric MARTIN frederic.martin.fma@gmail.com
25
+ #
26
+
27
+ import datetime
28
+ import logging
29
+
30
+ from humanfriendly import format_size
31
+
32
+
33
+ class CellFactory:
34
+ """TODO"""
35
+
36
+ # pylint: disable=too-few-public-methods
37
+ # pylint: disable=too-many-instance-attributes
38
+
39
+ def __init__(self, raw=False, vertical=False, debug=0):
40
+ self.raw = raw
41
+ self.debug = debug
42
+ self.vertical = vertical
43
+ classname = str(self.__class__.__name__.lower())
44
+ self.log = logging.getLogger("vhatablecli.cell." + classname)
45
+ self.date_cells = ["creationDate", "modificationDate", "expirationDate", "uploadDate"]
46
+ self.size_cells = ["size"]
47
+ self.custom_cells = {}
48
+
49
+ def __call__(self, name, value, row=None):
50
+ if name in self.custom_cells:
51
+ clazz = self.custom_cells.get(name)
52
+ elif name in self.date_cells:
53
+ clazz = DateCell
54
+ elif name in self.size_cells:
55
+ clazz = SizeCell
56
+ elif isinstance(value, bool):
57
+ clazz = BCell
58
+ elif isinstance(value, int):
59
+ clazz = ICell
60
+ elif isinstance(value, (list, dict)):
61
+ clazz = ComplexCell
62
+ else:
63
+ clazz = SCell
64
+ if self.debug >= 2:
65
+ self.log.debug("building cell ...")
66
+ self.log.debug("property: %s", name)
67
+ self.log.debug("value type: %s", type(value))
68
+ self.log.debug("value: %s", value)
69
+ self.log.debug("raw: %s", self.raw)
70
+ self.log.debug("vertical: %s", self.vertical)
71
+ cell = clazz(value)
72
+ cell.name = name
73
+ cell.raw = self.raw
74
+ cell.vertical = self.vertical
75
+ if row is not None:
76
+ cell.row = row
77
+ if self.debug >= 3:
78
+ self.log.debug("cell type: %s", type(cell))
79
+ # str method from all cell must return encoded strings
80
+ self.log.debug("cell rendering: %s", str(cell))
81
+ self.log.debug("cell built.")
82
+ return cell
83
+
84
+
85
+ class BaseCell:
86
+ """TODO"""
87
+
88
+ value = None
89
+ raw = False
90
+ row = {}
91
+ vertical = False
92
+ extended = False
93
+ hidden = False
94
+ name = None
95
+ _format = None
96
+ _format_vertical = None
97
+ _format_filter = None
98
+ none = "-"
99
+
100
+ def __init__(self, value):
101
+ self.value = value
102
+
103
+ @property
104
+ def formatt(self):
105
+ """TODO"""
106
+ return self._format
107
+
108
+ @formatt.setter
109
+ def formatt(self, formatt):
110
+ """TODO"""
111
+ self._format = formatt
112
+
113
+ @property
114
+ def formatv(self):
115
+ """TODO"""
116
+ return self._format_vertical
117
+
118
+ @formatv.setter
119
+ def formatv(self, formatv):
120
+ """TODO"""
121
+ self._format_vertical = formatv
122
+
123
+ @property
124
+ def formatf(self):
125
+ """TODO"""
126
+ return self._format_filter
127
+
128
+ @formatf.setter
129
+ def formatf(self, formatf):
130
+ """TODO"""
131
+ self._format_filter = formatf
132
+
133
+ def match(self, regex):
134
+ """Apply the input regext to the current object"""
135
+ if self._format_filter and regex.match(self._format_filter.format(**self.value)):
136
+ return True
137
+ return bool(regex.match(str(self)))
138
+
139
+ def __unicode__(self):
140
+ """TODO"""
141
+ if self.raw:
142
+ return str(self.value)
143
+ return str(self.value)
144
+
145
+ def __str__(self):
146
+ """TODO"""
147
+ return self.__unicode__()
148
+
149
+ def __eq__(self, item):
150
+ return self.value == item
151
+
152
+ def __lt__(self, value):
153
+ if value is None:
154
+ return True
155
+ if self.value is None:
156
+ return True
157
+ return self.value < value
158
+
159
+ def __le__(self, value):
160
+ if value is None:
161
+ return True
162
+ if self.value is None:
163
+ return True
164
+ return self.value <= value
165
+
166
+ def __gt__(self, value):
167
+ if value is None:
168
+ return False
169
+ if self.value is None:
170
+ return False
171
+ return self.value > value
172
+
173
+ def __ge__(self, value):
174
+ if value is None:
175
+ return False
176
+ if self.value is None:
177
+ return False
178
+ return self.value >= value
179
+
180
+
181
+ class SCell(BaseCell):
182
+ """This class is used to emulate str type for veryprettytable.
183
+ VeryPrettyTable will call the __str__ method on non-unicode objects.
184
+ It requires that the __str__ output is utf-8 encoded."""
185
+
186
+ # pylint: disable=too-few-public-methods
187
+ # pylint: disable=too-many-instance-attributes
188
+
189
+ def __unicode__(self):
190
+ """TODO"""
191
+ if self.raw:
192
+ if self.value is None:
193
+ return "None"
194
+ return str(self.value)
195
+ if self.value is None:
196
+ return self.none
197
+ if self.vertical and self._format_vertical:
198
+ return self._format_vertical.format(value=self.value)
199
+ if self._format:
200
+ return self._format.format(value=self.value)
201
+ return str(self.value)
202
+
203
+ def __add__(self, item):
204
+ return self.value + item
205
+
206
+ def lower(self):
207
+ """return a lower case version of the current value"""
208
+ return self.value.lower()
209
+
210
+
211
+ class DateCell(BaseCell):
212
+ """TODO"""
213
+
214
+ millisecond = True
215
+
216
+ # pylint: disable=too-few-public-methods
217
+ def __init__(self, value):
218
+ super().__init__(value)
219
+ fmt = "{da:%Y-%m-%d %H:%M:%S}"
220
+ self._format = fmt
221
+ self._format_vertical = fmt
222
+ # self._format_filter = fmt
223
+
224
+ def __unicode__(self):
225
+ if self.raw:
226
+ return str(self.value)
227
+ if self.value is not None:
228
+ fmt = self._format
229
+ if self.vertical:
230
+ fmt = self._format_vertical
231
+ div = 1
232
+ if self.millisecond:
233
+ div = 1000
234
+ return fmt.format(da=datetime.datetime.fromtimestamp(self.value / div))
235
+ return self.none
236
+
237
+ def __div__(self, value):
238
+ return self.value / value
239
+
240
+
241
+ class ICell(int, BaseCell):
242
+ """TODO"""
243
+
244
+ # pylint: disable=too-few-public-methods
245
+
246
+ def __init__(self, value):
247
+ super().__init__(value)
248
+ self.value = value
249
+
250
+ def __unicode__(self):
251
+ if self.raw:
252
+ return str(self.value)
253
+ return str(self.value)
254
+
255
+
256
+ class BCell(BaseCell):
257
+ """TODO"""
258
+
259
+ # pylint: disable=too-few-public-methods
260
+
261
+ def __unicode__(self):
262
+ if self.raw:
263
+ return str(self.value)
264
+ return str(self.value)
265
+
266
+
267
+ class SizeCell(BaseCell):
268
+ """TODO"""
269
+
270
+ # pylint: disable=too-few-public-methods
271
+
272
+ def __div__(self, value):
273
+ return self.value / value
274
+
275
+ def __unicode__(self):
276
+ if self.raw:
277
+ return str(self.value)
278
+ if self.value is None:
279
+ return self.none
280
+ return format_size(self.value)
281
+
282
+
283
+ class TypeCell(BaseCell):
284
+ """TODO"""
285
+
286
+ def __str__(self):
287
+ return str(type(self.value))
288
+
289
+
290
+ class ComplexCell(BaseCell):
291
+ """TODO"""
292
+
293
+ # pylint: disable=too-few-public-methods
294
+ # pylint: disable=too-many-instance-attributes
295
+
296
+ def __unicode__(self):
297
+ if self.raw:
298
+ return str(self.value)
299
+ if self.value is None:
300
+ return self.none
301
+ if self.vertical and self._format_vertical:
302
+ return self._format_vertical.format(**self.value)
303
+ if self._format:
304
+ return self._format.format(**self.value)
305
+ return str(self.value)
306
+
307
+ def keys(self):
308
+ """TODO"""
309
+ return list(self.value.keys())
310
+
311
+ def __getitem__(self, key):
312
+ return self.value[key]
313
+
314
+
315
+ class CellBuilder:
316
+ """wrapper to build a Cell with extra parameters."""
317
+
318
+ # pylint: disable=too-few-public-methods
319
+
320
+ def __init__(self, formatt, formatv=None, formatf=None, cell=SCell):
321
+ self._format = formatt
322
+ self._formatv = formatt
323
+ self._formatf = None
324
+ if formatv:
325
+ self._formatv = formatv
326
+ if formatf:
327
+ self._formatf = formatf
328
+ self.clazz = cell
329
+
330
+ def __call__(self, value):
331
+ cell = self.clazz(value)
332
+ cell.formatt = self._format
333
+ cell.formatv = self._formatv
334
+ cell.formatf = self._formatf
335
+ return cell
336
+
337
+
338
+ class ComplexCellBuilder(CellBuilder):
339
+ """wrapper to build a ComplexCell with extra parameters."""
340
+
341
+ # pylint: disable=too-few-public-methods
342
+
343
+ def __init__(self, formatt, formatv=None, formatf=None):
344
+ super().__init__(formatt, formatv, formatf, cell=ComplexCell)
vhatable/cellv2.py ADDED
@@ -0,0 +1,227 @@
1
+ #! /usr/bin/env python
2
+ """Contains cell builders and factory to handle rendering in a table."""
3
+
4
+
5
+ # This file is part of Vhatable cli.
6
+ #
7
+ # Vhatable cli is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # Vhatable cli is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with Vhatable cli. If not, see <http://www.gnu.org/licenses/>.
19
+ #
20
+ # Copyright 2019 Frédéric MARTIN
21
+ #
22
+ # Contributors list :
23
+ #
24
+ # Frédéric MARTIN frederic.martin.fma@gmail.com
25
+ #
26
+
27
+ import logging
28
+
29
+ from .cell import BCell, ComplexCell, DateCell, ICell, SCell, SizeCell, TypeCell
30
+
31
+
32
+ class CellBuilder:
33
+ """A helper to configure and build a cell."""
34
+
35
+ # pylint: disable=too-few-public-methods
36
+ # pylint: disable=[too-many-arguments]
37
+
38
+ clazz = None
39
+
40
+ def __init__(self, cell_name, fmt=None, fmtv=None, fmtf=None, none="-", clazz=None):
41
+ """Create a builder:
42
+
43
+ :param str cell_name: coucou
44
+ :param str none: giggiggigi
45
+ """
46
+ self.none = none
47
+ self.cell_name = cell_name
48
+ if clazz is not None:
49
+ self.clazz = clazz
50
+ self.fmt = fmt
51
+ self.fmt_vertical = fmtv
52
+ self.fmt_for_filtering = fmtf
53
+
54
+ def __call__(
55
+ self,
56
+ cell_value,
57
+ raw_display=False,
58
+ vertical=False,
59
+ extended=False,
60
+ hidden=False,
61
+ context=None,
62
+ ):
63
+ """Build and return a new cell"""
64
+ cell = self.clazz(cell_value)
65
+ cell.name = self.cell_name
66
+ if self.fmt is not None:
67
+ cell.formatt = self.fmt
68
+ if self.fmt_vertical is not None:
69
+ cell.formatv = self.fmt_vertical
70
+ if self.fmt_for_filtering is not None:
71
+ cell.formatf = self.fmt_for_filtering
72
+ cell.raw = raw_display
73
+ cell.vertical = vertical
74
+ cell.extended = extended
75
+ cell.hidden = hidden
76
+ if context is not None:
77
+ cell.row = context
78
+ return self._post_build(cell)
79
+
80
+ def _post_build(self, cell):
81
+ """Hook use to enhance cell with extra property once created."""
82
+ # pylint: disable=no-self-use
83
+ return cell
84
+
85
+
86
+ class StringCellBuilder(CellBuilder):
87
+ """Builder for a StringCell (SCell)"""
88
+
89
+ # pylint: disable=too-few-public-methods
90
+
91
+ clazz = SCell
92
+
93
+
94
+ class IntCellBuilder(CellBuilder):
95
+ """Builder for a ICell"""
96
+
97
+ # pylint: disable=too-few-public-methods
98
+
99
+ clazz = ICell
100
+
101
+
102
+ class BoolCellBuilder(CellBuilder):
103
+ """Builder for a BCell"""
104
+
105
+ # pylint: disable=too-few-public-methods
106
+
107
+ clazz = BCell
108
+
109
+
110
+ class DateCellBuilder(CellBuilder):
111
+ """Builder for a DateCell"""
112
+
113
+ # pylint: disable=too-few-public-methods
114
+
115
+ clazz = DateCell
116
+
117
+ def __init__(self, *args, millisecond=True, **kwargs):
118
+ super().__init__(*args, **kwargs)
119
+ self.millisecond = millisecond
120
+
121
+ def _post_build(self, cell):
122
+ """TODO"""
123
+ cell.millisecond = self.millisecond
124
+ return cell
125
+
126
+
127
+ class SizeCellBuilder(CellBuilder):
128
+ """Builder for a SizeCell"""
129
+
130
+ # pylint: disable=too-few-public-methods
131
+
132
+ clazz = SizeCell
133
+
134
+
135
+ class TypeCellBuilder(CellBuilder):
136
+ """Builder for a TypeCell.
137
+ It will just render type of the content of the cell.
138
+ Could be used for debug."""
139
+
140
+ # pylint: disable=too-few-public-methods
141
+
142
+ clazz = TypeCell
143
+
144
+
145
+ class ComplexCellBuilder(CellBuilder):
146
+ """Builder for a ComplexCell.
147
+ A complex cell is a json."""
148
+
149
+ # pylint: disable=too-few-public-methods
150
+
151
+ clazz = ComplexCell
152
+
153
+
154
+ class CellBuilderFactory:
155
+ """TODO"""
156
+
157
+ # pylint: disable=too-few-public-methods
158
+ # pylint: disable=too-many-instance-attributes
159
+
160
+ def __init__(self):
161
+ self.raw_display = False
162
+ self.debug = 0
163
+ self.vertical = False
164
+ classname = str(self.__class__.__name__.lower())
165
+ self.log = logging.getLogger("vhatablecli.cellv2." + classname)
166
+ self.date_cells = ["creationDate", "modificationDate", "expirationDate", "uploadDate"]
167
+ self.size_cells = ["size"]
168
+ self.custom_cells = {}
169
+
170
+ def get_cell_builder(self, cell_name, cell_value):
171
+ """Return the cell builder accoring the configuration or type of
172
+ the input cell_value.
173
+ """
174
+ builder_clazz = None
175
+ if cell_name in self.date_cells:
176
+ builder_clazz = DateCellBuilder
177
+ elif cell_name in self.size_cells:
178
+ builder_clazz = SizeCellBuilder
179
+ elif isinstance(cell_value, bool):
180
+ builder_clazz = BoolCellBuilder
181
+ elif isinstance(cell_value, int):
182
+ builder_clazz = IntCellBuilder
183
+ elif isinstance(cell_value, (list, dict)):
184
+ builder_clazz = ComplexCellBuilder
185
+ else:
186
+ builder_clazz = StringCellBuilder
187
+ return builder_clazz(cell_name)
188
+
189
+ def __call__(
190
+ self,
191
+ cell_name,
192
+ cell_value,
193
+ context=None,
194
+ extended=False,
195
+ vertical=None,
196
+ hidden=False,
197
+ raw_display=None,
198
+ ):
199
+ if vertical is not None:
200
+ self.vertical = vertical
201
+ if raw_display is not None:
202
+ self.raw_display = raw_display
203
+ if cell_name in self.custom_cells:
204
+ builder = self.custom_cells.get(cell_name)
205
+ else:
206
+ builder = self.get_cell_builder(cell_name, cell_value)
207
+ if self.debug >= 2:
208
+ self.log.debug("building cell ...")
209
+ self.log.debug("builder: %s", builder)
210
+ self.log.debug("name: %s, type: %s", cell_name, type(cell_value))
211
+ self.log.debug("cell_value: %s", cell_value)
212
+ self.log.debug("raw_display: %s", self.raw_display)
213
+ self.log.debug("vertical: %s", self.vertical)
214
+ cell = builder(
215
+ cell_value,
216
+ raw_display=self.raw_display,
217
+ vertical=self.vertical,
218
+ extended=extended,
219
+ hidden=hidden,
220
+ context=context,
221
+ )
222
+ if self.debug >= 3:
223
+ self.log.debug("cell type: %s", type(cell))
224
+ # str method from all cell must return encoded strings
225
+ self.log.debug("cell rendering: %s", str(cell))
226
+ self.log.debug("cell built.")
227
+ return cell