clickhouse-driver 0.2.1__cp39-cp39-win_amd64.whl → 0.2.10__cp39-cp39-win_amd64.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.
Files changed (85) hide show
  1. clickhouse_driver/__init__.py +9 -9
  2. clickhouse_driver/block.py +227 -195
  3. clickhouse_driver/blockstreamprofileinfo.py +22 -22
  4. clickhouse_driver/bufferedreader.cp39-win_amd64.pyd +0 -0
  5. clickhouse_driver/bufferedwriter.cp39-win_amd64.pyd +0 -0
  6. clickhouse_driver/client.py +812 -666
  7. clickhouse_driver/clientinfo.py +119 -80
  8. clickhouse_driver/columns/arraycolumn.py +161 -150
  9. clickhouse_driver/columns/base.py +221 -147
  10. clickhouse_driver/columns/boolcolumn.py +7 -0
  11. clickhouse_driver/columns/datecolumn.py +108 -49
  12. clickhouse_driver/columns/datetimecolumn.py +203 -207
  13. clickhouse_driver/columns/decimalcolumn.py +116 -118
  14. clickhouse_driver/columns/enumcolumn.py +129 -119
  15. clickhouse_driver/columns/exceptions.py +12 -12
  16. clickhouse_driver/columns/floatcolumn.py +34 -34
  17. clickhouse_driver/columns/intcolumn.py +157 -157
  18. clickhouse_driver/columns/intervalcolumn.py +33 -33
  19. clickhouse_driver/columns/ipcolumn.py +118 -118
  20. clickhouse_driver/columns/jsoncolumn.py +37 -0
  21. clickhouse_driver/columns/largeint.cp39-win_amd64.pyd +0 -0
  22. clickhouse_driver/columns/lowcardinalitycolumn.py +142 -123
  23. clickhouse_driver/columns/mapcolumn.py +73 -58
  24. clickhouse_driver/columns/nestedcolumn.py +10 -0
  25. clickhouse_driver/columns/nothingcolumn.py +13 -13
  26. clickhouse_driver/columns/nullablecolumn.py +7 -7
  27. clickhouse_driver/columns/nullcolumn.py +15 -15
  28. clickhouse_driver/columns/numpy/base.py +47 -14
  29. clickhouse_driver/columns/numpy/boolcolumn.py +8 -0
  30. clickhouse_driver/columns/numpy/datecolumn.py +19 -12
  31. clickhouse_driver/columns/numpy/datetimecolumn.py +146 -145
  32. clickhouse_driver/columns/numpy/floatcolumn.py +24 -13
  33. clickhouse_driver/columns/numpy/intcolumn.py +43 -43
  34. clickhouse_driver/columns/numpy/lowcardinalitycolumn.py +96 -83
  35. clickhouse_driver/columns/numpy/service.py +58 -80
  36. clickhouse_driver/columns/numpy/stringcolumn.py +78 -76
  37. clickhouse_driver/columns/numpy/tuplecolumn.py +37 -0
  38. clickhouse_driver/columns/service.py +185 -131
  39. clickhouse_driver/columns/simpleaggregatefunctioncolumn.py +7 -7
  40. clickhouse_driver/columns/stringcolumn.py +73 -73
  41. clickhouse_driver/columns/tuplecolumn.py +63 -65
  42. clickhouse_driver/columns/util.py +61 -0
  43. clickhouse_driver/columns/uuidcolumn.py +64 -64
  44. clickhouse_driver/compression/__init__.py +32 -28
  45. clickhouse_driver/compression/base.py +87 -52
  46. clickhouse_driver/compression/lz4.py +21 -55
  47. clickhouse_driver/compression/lz4hc.py +9 -9
  48. clickhouse_driver/compression/zstd.py +20 -51
  49. clickhouse_driver/connection.py +825 -632
  50. clickhouse_driver/context.py +36 -36
  51. clickhouse_driver/dbapi/__init__.py +62 -62
  52. clickhouse_driver/dbapi/connection.py +99 -96
  53. clickhouse_driver/dbapi/cursor.py +370 -368
  54. clickhouse_driver/dbapi/errors.py +40 -40
  55. clickhouse_driver/dbapi/extras.py +73 -0
  56. clickhouse_driver/defines.py +58 -42
  57. clickhouse_driver/errors.py +453 -446
  58. clickhouse_driver/log.py +48 -44
  59. clickhouse_driver/numpy/block.py +8 -8
  60. clickhouse_driver/numpy/helpers.py +28 -25
  61. clickhouse_driver/numpy/result.py +123 -123
  62. clickhouse_driver/opentelemetry.py +43 -0
  63. clickhouse_driver/progress.py +44 -32
  64. clickhouse_driver/protocol.py +130 -105
  65. clickhouse_driver/queryprocessingstage.py +8 -8
  66. clickhouse_driver/reader.py +69 -69
  67. clickhouse_driver/readhelpers.py +26 -26
  68. clickhouse_driver/result.py +144 -144
  69. clickhouse_driver/settings/available.py +405 -405
  70. clickhouse_driver/settings/types.py +50 -50
  71. clickhouse_driver/settings/writer.py +34 -29
  72. clickhouse_driver/streams/compressed.py +88 -88
  73. clickhouse_driver/streams/native.py +108 -90
  74. clickhouse_driver/util/compat.py +39 -0
  75. clickhouse_driver/util/escape.py +94 -55
  76. clickhouse_driver/util/helpers.py +173 -57
  77. clickhouse_driver/varint.cp39-win_amd64.pyd +0 -0
  78. clickhouse_driver/writer.py +67 -67
  79. clickhouse_driver-0.2.10.dist-info/METADATA +215 -0
  80. clickhouse_driver-0.2.10.dist-info/RECORD +89 -0
  81. {clickhouse_driver-0.2.1.dist-info → clickhouse_driver-0.2.10.dist-info}/WHEEL +1 -1
  82. {clickhouse_driver-0.2.1.dist-info → clickhouse_driver-0.2.10.dist-info/licenses}/LICENSE +21 -21
  83. clickhouse_driver-0.2.1.dist-info/METADATA +0 -24
  84. clickhouse_driver-0.2.1.dist-info/RECORD +0 -80
  85. {clickhouse_driver-0.2.1.dist-info → clickhouse_driver-0.2.10.dist-info}/top_level.txt +0 -0
@@ -1,131 +1,185 @@
1
- from .. import errors
2
- from .arraycolumn import create_array_column
3
- from .datecolumn import DateColumn
4
- from .datetimecolumn import create_datetime_column
5
- from .decimalcolumn import create_decimal_column
6
- from . import exceptions as column_exceptions
7
- from .enumcolumn import create_enum_column
8
- from .floatcolumn import Float32Column, Float64Column
9
- from .intcolumn import (
10
- Int8Column, Int16Column, Int32Column, Int64Column,
11
- Int128Column, UInt128Column, Int256Column, UInt256Column,
12
- UInt8Column, UInt16Column, UInt32Column, UInt64Column
13
- )
14
- from .lowcardinalitycolumn import create_low_cardinality_column
15
- from .mapcolumn import create_map_column
16
- from .nothingcolumn import NothingColumn
17
- from .nullcolumn import NullColumn
18
- from .nullablecolumn import create_nullable_column
19
- from .simpleaggregatefunctioncolumn import (
20
- create_simple_aggregate_function_column
21
- )
22
- from .stringcolumn import create_string_column
23
- from .tuplecolumn import create_tuple_column
24
- from .uuidcolumn import UUIDColumn
25
- from .intervalcolumn import (
26
- IntervalYearColumn, IntervalMonthColumn, IntervalWeekColumn,
27
- IntervalDayColumn, IntervalHourColumn, IntervalMinuteColumn,
28
- IntervalSecondColumn
29
- )
30
- from .ipcolumn import IPv4Column, IPv6Column
31
-
32
-
33
- column_by_type = {c.ch_type: c for c in [
34
- DateColumn, Float32Column, Float64Column,
35
- Int8Column, Int16Column, Int32Column, Int64Column,
36
- Int128Column, UInt128Column, Int256Column, UInt256Column,
37
- UInt8Column, UInt16Column, UInt32Column, UInt64Column,
38
- NothingColumn, NullColumn, UUIDColumn,
39
- IntervalYearColumn, IntervalMonthColumn, IntervalWeekColumn,
40
- IntervalDayColumn, IntervalHourColumn, IntervalMinuteColumn,
41
- IntervalSecondColumn, IPv4Column, IPv6Column
42
- ]}
43
-
44
-
45
- def get_column_by_spec(spec, column_options):
46
- context = column_options['context']
47
- use_numpy = context.client_settings['use_numpy'] if context else False
48
-
49
- if use_numpy:
50
- from .numpy.service import get_numpy_column_by_spec
51
- return get_numpy_column_by_spec(spec, column_options)
52
-
53
- def create_column_with_options(x):
54
- return get_column_by_spec(x, column_options)
55
-
56
- if spec == 'String' or spec.startswith('FixedString'):
57
- return create_string_column(spec, column_options)
58
-
59
- elif spec.startswith('Enum'):
60
- return create_enum_column(spec, column_options)
61
-
62
- elif spec.startswith('DateTime'):
63
- return create_datetime_column(spec, column_options)
64
-
65
- elif spec.startswith('Decimal'):
66
- return create_decimal_column(spec, column_options)
67
-
68
- elif spec.startswith('Array'):
69
- return create_array_column(spec, create_column_with_options)
70
-
71
- elif spec.startswith('Tuple'):
72
- return create_tuple_column(spec, create_column_with_options)
73
-
74
- elif spec.startswith('Nullable'):
75
- return create_nullable_column(spec, create_column_with_options)
76
-
77
- elif spec.startswith('LowCardinality'):
78
- return create_low_cardinality_column(spec, create_column_with_options)
79
-
80
- elif spec.startswith('SimpleAggregateFunction'):
81
- return create_simple_aggregate_function_column(
82
- spec, create_column_with_options)
83
-
84
- elif spec.startswith('Map'):
85
- return create_map_column(spec, create_column_with_options)
86
-
87
- else:
88
- try:
89
- cls = column_by_type[spec]
90
- return cls(**column_options)
91
-
92
- except KeyError as e:
93
- raise errors.UnknownTypeError('Unknown type {}'.format(e.args[0]))
94
-
95
-
96
- def read_column(context, column_spec, n_items, buf):
97
- column_options = {'context': context}
98
- column = get_column_by_spec(column_spec, column_options)
99
- column.read_state_prefix(buf)
100
- return column.read_data(n_items, buf)
101
-
102
-
103
- def write_column(context, column_name, column_spec, items, buf,
104
- types_check=False):
105
- column_options = {
106
- 'context': context,
107
- 'types_check': types_check
108
- }
109
- column = get_column_by_spec(column_spec, column_options)
110
-
111
- try:
112
- column.write_state_prefix(buf)
113
- column.write_data(items, buf)
114
-
115
- except column_exceptions.ColumnTypeMismatchException as e:
116
- raise errors.TypeMismatchError(
117
- 'Type mismatch in VALUES section. '
118
- 'Expected {} got {}: {} for column "{}".'.format(
119
- column_spec, type(e.args[0]), e.args[0], column_name
120
- )
121
- )
122
-
123
- except (column_exceptions.StructPackException, OverflowError) as e:
124
- error = e.args[0]
125
- raise errors.TypeMismatchError(
126
- 'Type mismatch in VALUES section. '
127
- 'Repeat query with types_check=True for detailed info. '
128
- 'Column {}: {}'.format(
129
- column_name, str(error)
130
- )
131
- )
1
+ import logging
2
+
3
+ from .. import errors
4
+ from .arraycolumn import create_array_column
5
+ from .boolcolumn import BoolColumn
6
+ from .datecolumn import DateColumn, Date32Column
7
+ from .datetimecolumn import create_datetime_column
8
+ from .decimalcolumn import create_decimal_column
9
+ from . import exceptions as column_exceptions
10
+ from .enumcolumn import create_enum_column
11
+ from .floatcolumn import Float32Column, Float64Column
12
+ from .intcolumn import (
13
+ Int8Column, Int16Column, Int32Column, Int64Column,
14
+ Int128Column, UInt128Column, Int256Column, UInt256Column,
15
+ UInt8Column, UInt16Column, UInt32Column, UInt64Column
16
+ )
17
+ from .lowcardinalitycolumn import create_low_cardinality_column
18
+ from .jsoncolumn import create_json_column
19
+ from .mapcolumn import create_map_column
20
+ from .nothingcolumn import NothingColumn
21
+ from .nullcolumn import NullColumn
22
+ from .nullablecolumn import create_nullable_column
23
+ from .simpleaggregatefunctioncolumn import (
24
+ create_simple_aggregate_function_column
25
+ )
26
+ from .stringcolumn import create_string_column
27
+ from .tuplecolumn import create_tuple_column
28
+ from .nestedcolumn import create_nested_column
29
+ from .uuidcolumn import UUIDColumn
30
+ from .intervalcolumn import (
31
+ IntervalYearColumn, IntervalMonthColumn, IntervalWeekColumn,
32
+ IntervalDayColumn, IntervalHourColumn, IntervalMinuteColumn,
33
+ IntervalSecondColumn
34
+ )
35
+ from .ipcolumn import IPv4Column, IPv6Column
36
+
37
+
38
+ column_by_type = {c.ch_type: c for c in [
39
+ DateColumn, Date32Column, Float32Column, Float64Column,
40
+ Int8Column, Int16Column, Int32Column, Int64Column,
41
+ Int128Column, UInt128Column, Int256Column, UInt256Column,
42
+ UInt8Column, UInt16Column, UInt32Column, UInt64Column,
43
+ NothingColumn, NullColumn, UUIDColumn,
44
+ IntervalYearColumn, IntervalMonthColumn, IntervalWeekColumn,
45
+ IntervalDayColumn, IntervalHourColumn, IntervalMinuteColumn,
46
+ IntervalSecondColumn, IPv4Column, IPv6Column, BoolColumn
47
+ ]}
48
+
49
+ logger = logging.getLogger(__name__)
50
+
51
+
52
+ aliases = [
53
+ # Begin Geo types
54
+ ('Point', 'Tuple(Float64, Float64)'),
55
+ ('Ring', 'Array(Point)'),
56
+ ('Polygon', 'Array(Ring)'),
57
+ ('MultiPolygon', 'Array(Polygon)')
58
+ # End Geo types
59
+ ]
60
+
61
+
62
+ def get_column_by_spec(spec, column_options, use_numpy=None):
63
+ context = column_options['context']
64
+
65
+ if use_numpy is None:
66
+ use_numpy = context.client_settings['use_numpy'] if context else False
67
+
68
+ if use_numpy:
69
+ from .numpy.service import get_numpy_column_by_spec
70
+
71
+ try:
72
+ return get_numpy_column_by_spec(spec, column_options)
73
+ except errors.UnknownTypeError:
74
+ use_numpy = False
75
+ logger.warning('NumPy support is not implemented for %s. '
76
+ 'Using generic column', spec)
77
+
78
+ def create_column_with_options(x):
79
+ return get_column_by_spec(x, column_options, use_numpy=use_numpy)
80
+
81
+ if spec == 'String' or spec.startswith('FixedString'):
82
+ return create_string_column(spec, column_options)
83
+
84
+ elif spec.startswith('Enum'):
85
+ return create_enum_column(spec, column_options)
86
+
87
+ elif spec.startswith('DateTime'):
88
+ return create_datetime_column(spec, column_options)
89
+
90
+ elif spec.startswith('Decimal'):
91
+ return create_decimal_column(spec, column_options)
92
+
93
+ elif spec.startswith('Array'):
94
+ return create_array_column(
95
+ spec, create_column_with_options, column_options
96
+ )
97
+
98
+ elif spec.startswith('Tuple'):
99
+ return create_tuple_column(
100
+ spec, create_column_with_options, column_options
101
+ )
102
+
103
+ elif spec.startswith('Nested'):
104
+ return create_nested_column(
105
+ spec, create_column_with_options, column_options
106
+ )
107
+
108
+ elif spec.startswith('Nullable'):
109
+ return create_nullable_column(spec, create_column_with_options)
110
+
111
+ elif spec.startswith('LowCardinality'):
112
+ return create_low_cardinality_column(
113
+ spec, create_column_with_options, column_options
114
+ )
115
+
116
+ elif spec.startswith('SimpleAggregateFunction'):
117
+ return create_simple_aggregate_function_column(
118
+ spec, create_column_with_options
119
+ )
120
+
121
+ elif spec.startswith('Map'):
122
+ return create_map_column(
123
+ spec, create_column_with_options, column_options
124
+ )
125
+
126
+ elif spec.startswith("Object('json')"):
127
+ return create_json_column(
128
+ spec, create_column_with_options, column_options
129
+ )
130
+
131
+ else:
132
+ for alias, primitive in aliases:
133
+ if spec.startswith(alias):
134
+ return create_column_with_options(
135
+ primitive + spec[len(alias):]
136
+ )
137
+
138
+ try:
139
+ cls = column_by_type[spec]
140
+ return cls(**column_options)
141
+
142
+ except KeyError:
143
+ raise errors.UnknownTypeError('Unknown type {}'.format(spec))
144
+
145
+
146
+ def read_column(context, column_spec, n_items, buf, use_numpy=None,
147
+ has_custom_serialization=False):
148
+ column_options = {
149
+ 'context': context,
150
+ 'has_custom_serialization': has_custom_serialization
151
+ }
152
+ col = get_column_by_spec(column_spec, column_options, use_numpy=use_numpy)
153
+ col.read_state_prefix(buf)
154
+ return col.read_data(n_items, buf)
155
+
156
+
157
+ def write_column(context, column_name, column_spec, items, buf,
158
+ types_check=False):
159
+ column_options = {
160
+ 'context': context,
161
+ 'types_check': types_check
162
+ }
163
+ column = get_column_by_spec(column_spec, column_options)
164
+
165
+ try:
166
+ column.write_state_prefix(buf)
167
+ column.write_data(items, buf)
168
+
169
+ except column_exceptions.ColumnTypeMismatchException as e:
170
+ raise errors.TypeMismatchError(
171
+ 'Type mismatch in VALUES section. '
172
+ 'Expected {} got {}: {} for column "{}".'.format(
173
+ column_spec, type(e.args[0]), e.args[0], column_name
174
+ )
175
+ )
176
+
177
+ except (column_exceptions.StructPackException, OverflowError) as e:
178
+ error = e.args[0]
179
+ raise errors.TypeMismatchError(
180
+ 'Type mismatch in VALUES section. '
181
+ 'Repeat query with types_check=True for detailed info. '
182
+ 'Column {}: {}'.format(
183
+ column_name, str(error)
184
+ )
185
+ )
@@ -1,7 +1,7 @@
1
-
2
-
3
- def create_simple_aggregate_function_column(spec, column_by_spec_getter):
4
- # SimpleAggregateFunction(Func, Type) -> Type
5
- inner = spec[24:-1].split(',', 1)[1].strip()
6
- nested = column_by_spec_getter(inner)
7
- return nested
1
+
2
+
3
+ def create_simple_aggregate_function_column(spec, column_by_spec_getter):
4
+ # SimpleAggregateFunction(Func, Type) -> Type
5
+ inner = spec[24:-1].split(',', 1)[1].strip()
6
+ nested = column_by_spec_getter(inner)
7
+ return nested
@@ -1,73 +1,73 @@
1
-
2
- from .. import defines
3
- from .base import Column
4
-
5
-
6
- class String(Column):
7
- ch_type = 'String'
8
- py_types = (str, )
9
- null_value = ''
10
-
11
- default_encoding = defines.STRINGS_ENCODING
12
-
13
- def __init__(self, encoding=default_encoding, **kwargs):
14
- self.encoding = encoding
15
- super(String, self).__init__(**kwargs)
16
-
17
- def write_items(self, items, buf):
18
- buf.write_strings(items, encoding=self.encoding)
19
-
20
- def read_items(self, n_items, buf):
21
- return buf.read_strings(n_items, encoding=self.encoding)
22
-
23
-
24
- class ByteString(String):
25
- py_types = (bytes, )
26
- null_value = b''
27
-
28
- def write_items(self, items, buf):
29
- buf.write_strings(items)
30
-
31
- def read_items(self, n_items, buf):
32
- return buf.read_strings(n_items)
33
-
34
-
35
- class FixedString(String):
36
- ch_type = 'FixedString'
37
-
38
- def __init__(self, length, **kwargs):
39
- self.length = length
40
- super(FixedString, self).__init__(**kwargs)
41
-
42
- def read_items(self, n_items, buf):
43
- return buf.read_fixed_strings(
44
- n_items, self.length, encoding=self.encoding
45
- )
46
-
47
- def write_items(self, items, buf):
48
- buf.write_fixed_strings(items, self.length, encoding=self.encoding)
49
-
50
-
51
- class ByteFixedString(FixedString):
52
- py_types = (bytearray, bytes)
53
- null_value = b''
54
-
55
- def read_items(self, n_items, buf):
56
- return buf.read_fixed_strings(n_items, self.length)
57
-
58
- def write_items(self, items, buf):
59
- buf.write_fixed_strings(items, self.length)
60
-
61
-
62
- def create_string_column(spec, column_options):
63
- client_settings = column_options['context'].client_settings
64
- strings_as_bytes = client_settings['strings_as_bytes']
65
- encoding = client_settings.get('strings_encoding', String.default_encoding)
66
-
67
- if spec == 'String':
68
- cls = ByteString if strings_as_bytes else String
69
- return cls(encoding=encoding, **column_options)
70
- else:
71
- length = int(spec[12:-1])
72
- cls = ByteFixedString if strings_as_bytes else FixedString
73
- return cls(length, encoding=encoding, **column_options)
1
+
2
+ from .. import defines
3
+ from .base import Column
4
+
5
+
6
+ class String(Column):
7
+ ch_type = 'String'
8
+ py_types = (str, )
9
+ null_value = ''
10
+
11
+ default_encoding = defines.STRINGS_ENCODING
12
+
13
+ def __init__(self, encoding=default_encoding, **kwargs):
14
+ self.encoding = encoding
15
+ super(String, self).__init__(**kwargs)
16
+
17
+ def write_items(self, items, buf):
18
+ buf.write_strings(items, encoding=self.encoding)
19
+
20
+ def read_items(self, n_items, buf):
21
+ return buf.read_strings(n_items, encoding=self.encoding)
22
+
23
+
24
+ class ByteString(String):
25
+ py_types = (bytes, )
26
+ null_value = b''
27
+
28
+ def write_items(self, items, buf):
29
+ buf.write_strings(items)
30
+
31
+ def read_items(self, n_items, buf):
32
+ return buf.read_strings(n_items)
33
+
34
+
35
+ class FixedString(String):
36
+ ch_type = 'FixedString'
37
+
38
+ def __init__(self, length, **kwargs):
39
+ self.length = length
40
+ super(FixedString, self).__init__(**kwargs)
41
+
42
+ def read_items(self, n_items, buf):
43
+ return buf.read_fixed_strings(
44
+ n_items, self.length, encoding=self.encoding
45
+ )
46
+
47
+ def write_items(self, items, buf):
48
+ buf.write_fixed_strings(items, self.length, encoding=self.encoding)
49
+
50
+
51
+ class ByteFixedString(FixedString):
52
+ py_types = (bytearray, bytes)
53
+ null_value = b''
54
+
55
+ def read_items(self, n_items, buf):
56
+ return buf.read_fixed_strings(n_items, self.length)
57
+
58
+ def write_items(self, items, buf):
59
+ buf.write_fixed_strings(items, self.length)
60
+
61
+
62
+ def create_string_column(spec, column_options):
63
+ client_settings = column_options['context'].client_settings
64
+ strings_as_bytes = client_settings['strings_as_bytes']
65
+ encoding = client_settings.get('strings_encoding', String.default_encoding)
66
+
67
+ if spec == 'String':
68
+ cls = ByteString if strings_as_bytes else String
69
+ return cls(encoding=encoding, **column_options)
70
+ else:
71
+ length = int(spec[12:-1])
72
+ cls = ByteFixedString if strings_as_bytes else FixedString
73
+ return cls(length, encoding=encoding, **column_options)
@@ -1,65 +1,63 @@
1
-
2
- from .base import Column
3
-
4
-
5
- class TupleColumn(Column):
6
- py_types = (list, tuple)
7
-
8
- def __init__(self, nested_columns, **kwargs):
9
- self.nested_columns = nested_columns
10
- super(TupleColumn, self).__init__(**kwargs)
11
-
12
- def write_data(self, items, buf):
13
- items = list(zip(*items))
14
-
15
- for i, x in enumerate(self.nested_columns):
16
- x.write_data(list(items[i]), buf)
17
-
18
- def write_items(self, items, buf):
19
- return self.write_data(items, buf)
20
-
21
- def read_data(self, n_items, buf):
22
- rv = [x.read_data(n_items, buf) for x in self.nested_columns]
23
- return list(zip(*rv))
24
-
25
- def read_items(self, n_items, buf):
26
- return self.read_data(n_items, buf)
27
-
28
-
29
- def create_tuple_column(spec, column_by_spec_getter):
30
- brackets = 0
31
- column_begin = 0
32
-
33
- inner_spec = get_inner_spec(spec)
34
- nested_columns = []
35
- for i, x in enumerate(inner_spec + ','):
36
- if x == ',':
37
- if brackets == 0:
38
- nested_columns.append(inner_spec[column_begin:i])
39
- column_begin = i + 1
40
- elif x == '(':
41
- brackets += 1
42
- elif x == ')':
43
- brackets -= 1
44
- elif x == ' ':
45
- if brackets == 0:
46
- column_begin = i + 1
47
-
48
- return TupleColumn([column_by_spec_getter(x) for x in nested_columns])
49
-
50
-
51
- def get_inner_spec(spec):
52
- brackets = 1
53
- offset = len('Tuple(')
54
- i = offset
55
- for i, ch in enumerate(spec[offset:], offset):
56
- if brackets == 0:
57
- break
58
-
59
- if ch == '(':
60
- brackets += 1
61
-
62
- elif ch == ')':
63
- brackets -= 1
64
-
65
- return spec[offset:i]
1
+
2
+ from .base import Column
3
+ from .util import get_inner_spec, get_inner_columns_with_types
4
+
5
+
6
+ class TupleColumn(Column):
7
+ py_types = (list, tuple)
8
+
9
+ def __init__(self, names, nested_columns, **kwargs):
10
+ self.names = names
11
+ self.nested_columns = nested_columns
12
+ client_settings = kwargs['context'].client_settings
13
+ settings = kwargs['context'].settings
14
+ self.namedtuple_as_json = (
15
+ settings.get('allow_experimental_object_type', False) and
16
+ client_settings.get('namedtuple_as_json', True)
17
+ )
18
+
19
+ super(TupleColumn, self).__init__(**kwargs)
20
+ self.null_value = tuple(x.null_value for x in nested_columns)
21
+
22
+ def write_data(self, items, buf):
23
+ items = self.prepare_items(items)
24
+ items = list(zip(*items))
25
+
26
+ for i, x in enumerate(self.nested_columns):
27
+ x.write_data(list(items[i]), buf)
28
+
29
+ def write_items(self, items, buf):
30
+ return self.write_data(items, buf)
31
+
32
+ def read_data(self, n_items, buf):
33
+ rv = [x.read_data(n_items, buf) for x in self.nested_columns]
34
+ rv = list(zip(*rv))
35
+
36
+ if self.names[0] and self.namedtuple_as_json:
37
+ return [dict(zip(self.names, x)) for x in rv]
38
+ else:
39
+ return rv
40
+
41
+ def read_items(self, n_items, buf):
42
+ return self.read_data(n_items, buf)
43
+
44
+ def read_state_prefix(self, buf):
45
+ super(TupleColumn, self).read_state_prefix(buf)
46
+
47
+ for x in self.nested_columns:
48
+ x.read_state_prefix(buf)
49
+
50
+ def write_state_prefix(self, buf):
51
+ super(TupleColumn, self).write_state_prefix(buf)
52
+
53
+ for x in self.nested_columns:
54
+ x.write_state_prefix(buf)
55
+
56
+
57
+ def create_tuple_column(spec, column_by_spec_getter, column_options):
58
+ inner_spec = get_inner_spec('Tuple', spec)
59
+ columns_with_types = get_inner_columns_with_types(inner_spec)
60
+ names, types = zip(*columns_with_types)
61
+
62
+ return TupleColumn(names, [column_by_spec_getter(x) for x in types],
63
+ **column_options)