clickhouse-driver 0.2.5__cp311-cp311-musllinux_1_1_aarch64.whl → 0.2.9__cp311-cp311-musllinux_1_1_aarch64.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 (39) hide show
  1. clickhouse_driver/__init__.py +1 -1
  2. clickhouse_driver/block.py +3 -2
  3. clickhouse_driver/bufferedreader.cpython-311-aarch64-linux-musl.so +0 -0
  4. clickhouse_driver/bufferedwriter.cpython-311-aarch64-linux-musl.so +0 -0
  5. clickhouse_driver/client.py +119 -99
  6. clickhouse_driver/clientinfo.py +2 -2
  7. clickhouse_driver/columns/arraycolumn.py +15 -6
  8. clickhouse_driver/columns/base.py +71 -7
  9. clickhouse_driver/columns/datecolumn.py +52 -13
  10. clickhouse_driver/columns/datetimecolumn.py +3 -2
  11. clickhouse_driver/columns/enumcolumn.py +27 -17
  12. clickhouse_driver/columns/jsoncolumn.py +37 -0
  13. clickhouse_driver/columns/largeint.cpython-311-aarch64-linux-musl.so +0 -0
  14. clickhouse_driver/columns/lowcardinalitycolumn.py +23 -4
  15. clickhouse_driver/columns/mapcolumn.py +9 -2
  16. clickhouse_driver/columns/nestedcolumn.py +2 -13
  17. clickhouse_driver/columns/numpy/datetimecolumn.py +21 -18
  18. clickhouse_driver/columns/numpy/lowcardinalitycolumn.py +2 -2
  19. clickhouse_driver/columns/service.py +12 -2
  20. clickhouse_driver/columns/tuplecolumn.py +31 -5
  21. clickhouse_driver/columns/util.py +2 -1
  22. clickhouse_driver/columns/uuidcolumn.py +1 -1
  23. clickhouse_driver/connection.py +117 -19
  24. clickhouse_driver/defines.py +12 -1
  25. clickhouse_driver/log.py +7 -3
  26. clickhouse_driver/numpy/helpers.py +5 -2
  27. clickhouse_driver/progress.py +15 -3
  28. clickhouse_driver/protocol.py +19 -3
  29. clickhouse_driver/settings/writer.py +7 -2
  30. clickhouse_driver/streams/native.py +24 -6
  31. clickhouse_driver/util/compat.py +12 -0
  32. clickhouse_driver/util/escape.py +36 -8
  33. clickhouse_driver/util/helpers.py +114 -0
  34. clickhouse_driver/varint.cpython-311-aarch64-linux-musl.so +0 -0
  35. {clickhouse_driver-0.2.5.dist-info → clickhouse_driver-0.2.9.dist-info}/METADATA +8 -8
  36. {clickhouse_driver-0.2.5.dist-info → clickhouse_driver-0.2.9.dist-info}/RECORD +71 -70
  37. {clickhouse_driver-0.2.5.dist-info → clickhouse_driver-0.2.9.dist-info}/WHEEL +1 -1
  38. {clickhouse_driver-0.2.5.dist-info → clickhouse_driver-0.2.9.dist-info}/LICENSE +0 -0
  39. {clickhouse_driver-0.2.5.dist-info → clickhouse_driver-0.2.9.dist-info}/top_level.txt +0 -0
@@ -1,20 +1,24 @@
1
1
  from enum import Enum
2
+ from collections import OrderedDict
2
3
 
3
4
  from .. import errors
4
5
  from .intcolumn import IntColumn
5
6
 
7
+ invalid_names_for_python_enum = frozenset(['mro', ''])
8
+
6
9
 
7
10
  class EnumColumn(IntColumn):
8
11
  py_types = (Enum, int, str)
9
12
 
10
- def __init__(self, enum_cls, **kwargs):
11
- self.enum_cls = enum_cls
13
+ def __init__(self, name_by_value, value_by_name, **kwargs):
14
+ self.name_by_value = name_by_value
15
+ self.value_by_name = value_by_name
12
16
  super(EnumColumn, self).__init__(**kwargs)
13
17
 
14
18
  def before_write_items(self, items, nulls_map=None):
15
19
  null_value = self.null_value
16
-
17
- enum_cls = self.enum_cls
20
+ name_by_value = self.name_by_value
21
+ value_by_name = self.value_by_name
18
22
 
19
23
  for i, item in enumerate(items):
20
24
  if nulls_map and nulls_map[i]:
@@ -26,15 +30,15 @@ class EnumColumn(IntColumn):
26
30
  # Check real enum value
27
31
  try:
28
32
  if isinstance(source_value, str):
29
- items[i] = enum_cls[source_value].value
33
+ items[i] = value_by_name[source_value]
30
34
  else:
31
- items[i] = enum_cls(source_value).value
35
+ items[i] = value_by_name[name_by_value[source_value]]
32
36
  except (ValueError, KeyError):
33
37
  choices = ', '.join(
34
- "'{}' = {}".format(x.name.replace("'", r"\'"), x.value)
35
- for x in enum_cls
38
+ "'{}' = {}".format(name.replace("'", r"\'"), value)
39
+ for name, value in value_by_name.items()
36
40
  )
37
- enum_str = '{}({})'.format(enum_cls.__name__, choices)
41
+ enum_str = '{}({})'.format(self.ch_type, choices)
38
42
 
39
43
  raise errors.LogicalError(
40
44
  "Unknown element '{}' for type {}"
@@ -42,13 +46,13 @@ class EnumColumn(IntColumn):
42
46
  )
43
47
 
44
48
  def after_read_items(self, items, nulls_map=None):
45
- enum_cls = self.enum_cls
49
+ name_by_value = self.name_by_value
46
50
 
47
51
  if nulls_map is None:
48
- return tuple(enum_cls(item).name for item in items)
52
+ return tuple(name_by_value[item] for item in items)
49
53
  else:
50
54
  return tuple(
51
- (None if is_null else enum_cls(items[i]).name)
55
+ (None if is_null else name_by_value[items[i]])
52
56
  for i, is_null in enumerate(nulls_map)
53
57
  )
54
58
 
@@ -73,11 +77,13 @@ def create_enum_column(spec, column_options):
73
77
  params = spec[7:-1]
74
78
  cls = Enum16Column
75
79
 
76
- return cls(Enum(cls.ch_type, _parse_options(params)), **column_options)
80
+ name_by_value, value_by_name = _parse_options(params)
81
+
82
+ return cls(name_by_value, value_by_name, **column_options)
77
83
 
78
84
 
79
85
  def _parse_options(option_string):
80
- options = dict()
86
+ name_by_value, value_by_name = {}, OrderedDict()
81
87
  after_name = False
82
88
  escaped = False
83
89
  quote_character = None
@@ -93,7 +99,9 @@ def _parse_options(option_string):
93
99
  if ch in (' ', '='):
94
100
  pass
95
101
  elif ch == ',':
96
- options[name] = int(value)
102
+ value = int(value)
103
+ name_by_value[value] = name
104
+ value_by_name[name] = value
97
105
  after_name = False
98
106
  name = ''
99
107
  value = '' # reset before collecting new option
@@ -114,6 +122,8 @@ def _parse_options(option_string):
114
122
  quote_character = ch
115
123
 
116
124
  if after_name:
117
- options.setdefault(name, int(value)) # append word after last comma
125
+ value = int(value)
126
+ name_by_value[value] = name
127
+ value_by_name[name] = value
118
128
 
119
- return options
129
+ return name_by_value, value_by_name
@@ -0,0 +1,37 @@
1
+ from .base import Column
2
+ from .stringcolumn import String
3
+ from ..reader import read_binary_uint8, read_binary_str
4
+ from ..util.compat import json
5
+ from ..writer import write_binary_uint8
6
+
7
+
8
+ class JsonColumn(Column):
9
+ py_types = (dict, )
10
+
11
+ # No NULL value actually
12
+ null_value = {}
13
+
14
+ def __init__(self, column_by_spec_getter, **kwargs):
15
+ self.column_by_spec_getter = column_by_spec_getter
16
+ self.string_column = String(**kwargs)
17
+ super(JsonColumn, self).__init__(**kwargs)
18
+
19
+ def write_state_prefix(self, buf):
20
+ # Read in binary format.
21
+ # Write in text format.
22
+ write_binary_uint8(1, buf)
23
+
24
+ def read_items(self, n_items, buf):
25
+ read_binary_uint8(buf)
26
+ spec = read_binary_str(buf)
27
+ col = self.column_by_spec_getter(spec)
28
+ col.read_state_prefix(buf)
29
+ return col.read_data(n_items, buf)
30
+
31
+ def write_items(self, items, buf):
32
+ items = [x if isinstance(x, str) else json.dumps(x) for x in items]
33
+ self.string_column.write_items(items, buf)
34
+
35
+
36
+ def create_json_column(spec, column_by_spec_getter, column_options):
37
+ return JsonColumn(column_by_spec_getter, **column_options)
@@ -35,25 +35,32 @@ class LowCardinalityColumn(Column):
35
35
  serialization_type = has_additional_keys_bit | need_update_dictionary
36
36
 
37
37
  def __init__(self, nested_column, **kwargs):
38
+ self.init_kwargs = kwargs
38
39
  self.nested_column = nested_column
39
40
  super(LowCardinalityColumn, self).__init__(**kwargs)
40
41
 
41
42
  def read_state_prefix(self, buf):
42
- return read_binary_uint64(buf)
43
+ super(LowCardinalityColumn, self).read_state_prefix(buf)
44
+
45
+ read_binary_uint64(buf)
43
46
 
44
47
  def write_state_prefix(self, buf):
48
+ super(LowCardinalityColumn, self).write_state_prefix(buf)
49
+
45
50
  # KeysSerializationVersion. See ClickHouse docs.
46
51
  write_binary_int64(1, buf)
47
52
 
48
53
  def _write_data(self, items, buf):
49
54
  index, keys = [], []
50
55
  key_by_index_element = {}
56
+ nested_is_nullable = False
51
57
 
52
58
  if self.nested_column.nullable:
53
59
  # First element represents NULL if column is nullable.
54
60
  index.append(self.nested_column.null_value)
55
61
  # Prevent null map writing. Reset nested column nullable flag.
56
62
  self.nested_column.nullable = False
63
+ nested_is_nullable = True
57
64
 
58
65
  for x in items:
59
66
  if x is None:
@@ -87,14 +94,26 @@ class LowCardinalityColumn(Column):
87
94
  return
88
95
 
89
96
  int_type = int(log(len(index), 2) / 8)
90
- int_column = self.int_types[int_type]()
97
+ int_column = self.int_types[int_type](**self.init_kwargs)
91
98
 
92
99
  serialization_type = self.serialization_type | int_type
93
100
 
94
101
  write_binary_int64(serialization_type, buf)
95
102
  write_binary_int64(len(index), buf)
96
103
 
97
- self.nested_column.write_data(index, buf)
104
+ if nested_is_nullable:
105
+ # Given we reset nested column nullable flag above,
106
+ # we need to write null map manually. If to invoke
107
+ # write_data method, it will cause an exception,
108
+ # because `prepare_data` may not be able to handle
109
+ # null value correctly.
110
+ self.nested_column.write_items(
111
+ [self.nested_column.null_value], buf)
112
+ # Remove null map from index, because it is already written.
113
+ index_to_write = index[1:]
114
+ self.nested_column.write_data(index_to_write, buf)
115
+ else:
116
+ self.nested_column.write_data(index, buf)
98
117
  write_binary_int64(len(items), buf)
99
118
  int_column.write_items(keys, buf)
100
119
 
@@ -106,7 +125,7 @@ class LowCardinalityColumn(Column):
106
125
 
107
126
  # Lowest byte contains info about key type.
108
127
  key_type = serialization_type & 0xf
109
- keys_column = self.int_types[key_type]()
128
+ keys_column = self.int_types[key_type](**self.init_kwargs)
110
129
 
111
130
  nullable = self.nested_column.nullable
112
131
  # Prevent null map reading. Reset nested column nullable flag.
@@ -13,20 +13,27 @@ class MapColumn(Column):
13
13
  null_value = {}
14
14
 
15
15
  def __init__(self, key_column, value_column, **kwargs):
16
- self.offset_column = UInt64Column()
16
+ self.offset_column = UInt64Column(**kwargs)
17
17
  self.key_column = key_column
18
18
  self.value_column = value_column
19
19
  super(MapColumn, self).__init__(**kwargs)
20
20
 
21
21
  def read_state_prefix(self, buf):
22
+ super(MapColumn, self).read_state_prefix(buf)
23
+
22
24
  self.key_column.read_state_prefix(buf)
23
25
  self.value_column.read_state_prefix(buf)
24
26
 
25
27
  def write_state_prefix(self, buf):
28
+ super(MapColumn, self).write_state_prefix(buf)
29
+
26
30
  self.key_column.write_state_prefix(buf)
27
31
  self.value_column.write_state_prefix(buf)
28
32
 
29
33
  def read_items(self, n_items, buf):
34
+ if not n_items:
35
+ return [{}]
36
+
30
37
  offsets = list(self.offset_column.read_items(n_items, buf))
31
38
  last_offset = offsets[-1]
32
39
  keys = self.key_column.read_data(last_offset, buf)
@@ -57,7 +64,7 @@ class MapColumn(Column):
57
64
 
58
65
 
59
66
  def create_map_column(spec, column_by_spec_getter, column_options):
60
- # Match commas outside of parentheses so we don't match the comma in
67
+ # Match commas outside of parentheses, so we don't match the comma in
61
68
  # Decimal types.
62
69
  key, value = comma_re.split(spec[4:-1])
63
70
  key_column = column_by_spec_getter(key.strip())
@@ -1,21 +1,10 @@
1
1
 
2
2
  from .arraycolumn import create_array_column
3
- from .util import get_inner_spec, get_inner_columns, \
4
- get_inner_columns_with_types
3
+ from .util import get_inner_spec
5
4
 
6
5
 
7
6
  def create_nested_column(spec, column_by_spec_getter, column_options):
8
7
  return create_array_column(
9
- 'Array(Tuple({}))'.format(','.join(get_nested_columns(spec))),
8
+ 'Array(Tuple({}))'.format(get_inner_spec('Nested', spec)),
10
9
  column_by_spec_getter, column_options
11
10
  )
12
-
13
-
14
- def get_nested_columns(spec):
15
- inner_spec = get_inner_spec('Nested', spec)
16
- return get_inner_columns(inner_spec)
17
-
18
-
19
- def get_columns_with_types(spec):
20
- inner_spec = get_inner_spec('Nested', spec)
21
- return get_inner_columns_with_types(inner_spec)
@@ -21,19 +21,21 @@ class NumpyDateTimeColumnBase(NumpyColumn):
21
21
  def apply_timezones_after_read(self, dt):
22
22
  timezone = self.timezone if self.timezone else self.local_timezone
23
23
 
24
- ts = pd.to_datetime(dt, utc=True).tz_convert(timezone)
25
-
26
- if self.offset_naive:
24
+ if self.offset_naive and timezone.zone != 'UTC':
25
+ ts = pd.to_datetime(dt, utc=True).tz_convert(timezone)
27
26
  ts = ts.tz_localize(None)
27
+ return ts.to_numpy(self.datetime_dtype)
28
28
 
29
- return ts.to_numpy(self.datetime_dtype)
29
+ return dt
30
30
 
31
31
  def apply_timezones_before_write(self, items):
32
32
  if isinstance(items, pd.DatetimeIndex):
33
33
  ts = items
34
34
  else:
35
35
  timezone = self.timezone if self.timezone else self.local_timezone
36
- ts = pd.to_datetime(items).tz_localize(timezone)
36
+ ts = pd.to_datetime(items)
37
+ if not getattr(ts.dtype, 'tz', None):
38
+ ts = ts.tz_localize(timezone)
37
39
 
38
40
  ts = ts.tz_convert('UTC')
39
41
  return ts.tz_localize(None).to_numpy(self.datetime_dtype)
@@ -65,7 +67,7 @@ class NumpyDateTimeColumn(NumpyDateTimeColumnBase):
65
67
 
66
68
 
67
69
  class NumpyDateTime64Column(NumpyDateTimeColumnBase):
68
- dtype = np.dtype(np.uint64)
70
+ dtype = np.dtype(np.int64)
69
71
  datetime_dtype = 'datetime64[ns]'
70
72
 
71
73
  max_scale = 9
@@ -75,15 +77,15 @@ class NumpyDateTime64Column(NumpyDateTimeColumnBase):
75
77
  super(NumpyDateTime64Column, self).__init__(**kwargs)
76
78
 
77
79
  def read_items(self, n_items, buf):
78
- scale = 10 ** self.scale
79
- frac_scale = 10 ** (self.max_scale - self.scale)
80
-
80
+ # Clickhouse: t seconds is represented as t * 10^scale.
81
+ # datetime64[ns]: t seconds is represented as t * 10^9.
82
+ # Since 0 <= scale <= 9, multiply by the integer 10^(9 - scale).
81
83
  items = super(NumpyDateTime64Column, self).read_items(n_items, buf)
82
84
 
83
- seconds = (items // scale).astype('datetime64[s]')
84
- microseconds = ((items % scale) * frac_scale).astype('timedelta64[ns]')
85
+ tmp = np.copy(items)
86
+ tmp *= 10 ** (9 - self.scale)
87
+ dt = tmp.view(dtype='datetime64[ns]')
85
88
 
86
- dt = seconds + microseconds
87
89
  return self.apply_timezones_after_read(dt)
88
90
 
89
91
  def write_items(self, items, buf):
@@ -120,12 +122,12 @@ def create_numpy_datetime_column(spec, column_options):
120
122
 
121
123
  context = column_options['context']
122
124
 
123
- tz_name = timezone = None
125
+ tz_name = None
124
126
  offset_naive = True
125
127
 
126
128
  # As Numpy do not use local timezone for converting timestamp to
127
129
  # datetime we need always detect local timezone for manual converting.
128
- local_timezone = get_localzone_name_compat()
130
+ local_tz_name = get_localzone_name_compat()
129
131
 
130
132
  # Use column's timezone if it's specified.
131
133
  if spec and spec[-1] == ')':
@@ -133,11 +135,12 @@ def create_numpy_datetime_column(spec, column_options):
133
135
  offset_naive = False
134
136
  else:
135
137
  if not context.settings.get('use_client_time_zone', False):
136
- if local_timezone != context.server_info.timezone:
137
- tz_name = context.server_info.timezone
138
+ remote_timezone = context.server_info.get_timezone()
139
+ if local_tz_name != remote_timezone:
140
+ tz_name = remote_timezone
138
141
 
139
- if tz_name:
140
- timezone = get_timezone(tz_name)
142
+ timezone = get_timezone(tz_name) if tz_name else None
143
+ local_timezone = get_timezone(local_tz_name) if local_tz_name else None
141
144
 
142
145
  return cls(timezone=timezone, offset_naive=offset_naive,
143
146
  local_timezone=local_timezone, **column_options)
@@ -37,7 +37,7 @@ class NumpyLowCardinalityColumn(LowCardinalityColumn):
37
37
  c = pd.Categorical(items)
38
38
 
39
39
  int_type = int(log(len(c.codes), 2) / 8)
40
- int_column = self.int_types[int_type]()
40
+ int_column = self.int_types[int_type](**self.init_kwargs)
41
41
 
42
42
  serialization_type = self.serialization_type | int_type
43
43
 
@@ -66,7 +66,7 @@ class NumpyLowCardinalityColumn(LowCardinalityColumn):
66
66
 
67
67
  # Lowest byte contains info about key type.
68
68
  key_type = serialization_type & 0xf
69
- keys_column = self.int_types[key_type]()
69
+ keys_column = self.int_types[key_type](**self.init_kwargs)
70
70
 
71
71
  nullable = self.nested_column.nullable
72
72
  # Prevent null map reading. Reset nested column nullable flag.
@@ -15,6 +15,7 @@ from .intcolumn import (
15
15
  UInt8Column, UInt16Column, UInt32Column, UInt64Column
16
16
  )
17
17
  from .lowcardinalitycolumn import create_low_cardinality_column
18
+ from .jsoncolumn import create_json_column
18
19
  from .mapcolumn import create_map_column
19
20
  from .nothingcolumn import NothingColumn
20
21
  from .nullcolumn import NullColumn
@@ -122,6 +123,11 @@ def get_column_by_spec(spec, column_options, use_numpy=None):
122
123
  spec, create_column_with_options, column_options
123
124
  )
124
125
 
126
+ elif spec.startswith("Object('json')"):
127
+ return create_json_column(
128
+ spec, create_column_with_options, column_options
129
+ )
130
+
125
131
  else:
126
132
  for alias, primitive in aliases:
127
133
  if spec.startswith(alias):
@@ -137,8 +143,12 @@ def get_column_by_spec(spec, column_options, use_numpy=None):
137
143
  raise errors.UnknownTypeError('Unknown type {}'.format(spec))
138
144
 
139
145
 
140
- def read_column(context, column_spec, n_items, buf, use_numpy=None):
141
- column_options = {'context': context}
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
+ }
142
152
  col = get_column_by_spec(column_spec, column_options, use_numpy=use_numpy)
143
153
  col.read_state_prefix(buf)
144
154
  return col.read_data(n_items, buf)
@@ -1,13 +1,21 @@
1
1
 
2
2
  from .base import Column
3
- from .util import get_inner_spec, get_inner_columns
3
+ from .util import get_inner_spec, get_inner_columns_with_types
4
4
 
5
5
 
6
6
  class TupleColumn(Column):
7
7
  py_types = (list, tuple)
8
8
 
9
- def __init__(self, nested_columns, **kwargs):
9
+ def __init__(self, names, nested_columns, **kwargs):
10
+ self.names = names
10
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
+
11
19
  super(TupleColumn, self).__init__(**kwargs)
12
20
  self.null_value = tuple(x.null_value for x in nested_columns)
13
21
 
@@ -23,15 +31,33 @@ class TupleColumn(Column):
23
31
 
24
32
  def read_data(self, n_items, buf):
25
33
  rv = [x.read_data(n_items, buf) for x in self.nested_columns]
26
- return list(zip(*rv))
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
27
40
 
28
41
  def read_items(self, n_items, buf):
29
42
  return self.read_data(n_items, buf)
30
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
+
31
56
 
32
57
  def create_tuple_column(spec, column_by_spec_getter, column_options):
33
58
  inner_spec = get_inner_spec('Tuple', spec)
34
- columns = get_inner_columns(inner_spec)
59
+ columns_with_types = get_inner_columns_with_types(inner_spec)
60
+ names, types = zip(*columns_with_types)
35
61
 
36
- return TupleColumn([column_by_spec_getter(x) for x in columns],
62
+ return TupleColumn(names, [column_by_spec_getter(x) for x in types],
37
63
  **column_options)
@@ -37,12 +37,13 @@ def get_inner_columns(spec):
37
37
 
38
38
 
39
39
  def get_inner_columns_with_types(spec):
40
+ spec = spec.strip()
40
41
  brackets = 0
41
42
  prev_comma = 0
42
43
  prev_space = 0
43
44
 
44
45
  columns = []
45
- for i, x in enumerate(spec + ','):
46
+ for i, x in enumerate(spec.strip() + ','):
46
47
  if x == ',':
47
48
  if brackets == 0:
48
49
  columns.append((
@@ -54,7 +54,7 @@ class UUIDColumn(FormatColumn):
54
54
 
55
55
  try:
56
56
  if not isinstance(item, UUID):
57
- item = UUID(item)
57
+ item = UUID(int=item) if item is null_value else UUID(item)
58
58
 
59
59
  except ValueError:
60
60
  raise errors.CannotParseUuidError(