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.
- clickhouse_driver/__init__.py +9 -9
- clickhouse_driver/block.py +227 -195
- clickhouse_driver/blockstreamprofileinfo.py +22 -22
- clickhouse_driver/bufferedreader.cp39-win_amd64.pyd +0 -0
- clickhouse_driver/bufferedwriter.cp39-win_amd64.pyd +0 -0
- clickhouse_driver/client.py +812 -666
- clickhouse_driver/clientinfo.py +119 -80
- clickhouse_driver/columns/arraycolumn.py +161 -150
- clickhouse_driver/columns/base.py +221 -147
- clickhouse_driver/columns/boolcolumn.py +7 -0
- clickhouse_driver/columns/datecolumn.py +108 -49
- clickhouse_driver/columns/datetimecolumn.py +203 -207
- clickhouse_driver/columns/decimalcolumn.py +116 -118
- clickhouse_driver/columns/enumcolumn.py +129 -119
- clickhouse_driver/columns/exceptions.py +12 -12
- clickhouse_driver/columns/floatcolumn.py +34 -34
- clickhouse_driver/columns/intcolumn.py +157 -157
- clickhouse_driver/columns/intervalcolumn.py +33 -33
- clickhouse_driver/columns/ipcolumn.py +118 -118
- clickhouse_driver/columns/jsoncolumn.py +37 -0
- clickhouse_driver/columns/largeint.cp39-win_amd64.pyd +0 -0
- clickhouse_driver/columns/lowcardinalitycolumn.py +142 -123
- clickhouse_driver/columns/mapcolumn.py +73 -58
- clickhouse_driver/columns/nestedcolumn.py +10 -0
- clickhouse_driver/columns/nothingcolumn.py +13 -13
- clickhouse_driver/columns/nullablecolumn.py +7 -7
- clickhouse_driver/columns/nullcolumn.py +15 -15
- clickhouse_driver/columns/numpy/base.py +47 -14
- clickhouse_driver/columns/numpy/boolcolumn.py +8 -0
- clickhouse_driver/columns/numpy/datecolumn.py +19 -12
- clickhouse_driver/columns/numpy/datetimecolumn.py +146 -145
- clickhouse_driver/columns/numpy/floatcolumn.py +24 -13
- clickhouse_driver/columns/numpy/intcolumn.py +43 -43
- clickhouse_driver/columns/numpy/lowcardinalitycolumn.py +96 -83
- clickhouse_driver/columns/numpy/service.py +58 -80
- clickhouse_driver/columns/numpy/stringcolumn.py +78 -76
- clickhouse_driver/columns/numpy/tuplecolumn.py +37 -0
- clickhouse_driver/columns/service.py +185 -131
- clickhouse_driver/columns/simpleaggregatefunctioncolumn.py +7 -7
- clickhouse_driver/columns/stringcolumn.py +73 -73
- clickhouse_driver/columns/tuplecolumn.py +63 -65
- clickhouse_driver/columns/util.py +61 -0
- clickhouse_driver/columns/uuidcolumn.py +64 -64
- clickhouse_driver/compression/__init__.py +32 -28
- clickhouse_driver/compression/base.py +87 -52
- clickhouse_driver/compression/lz4.py +21 -55
- clickhouse_driver/compression/lz4hc.py +9 -9
- clickhouse_driver/compression/zstd.py +20 -51
- clickhouse_driver/connection.py +825 -632
- clickhouse_driver/context.py +36 -36
- clickhouse_driver/dbapi/__init__.py +62 -62
- clickhouse_driver/dbapi/connection.py +99 -96
- clickhouse_driver/dbapi/cursor.py +370 -368
- clickhouse_driver/dbapi/errors.py +40 -40
- clickhouse_driver/dbapi/extras.py +73 -0
- clickhouse_driver/defines.py +58 -42
- clickhouse_driver/errors.py +453 -446
- clickhouse_driver/log.py +48 -44
- clickhouse_driver/numpy/block.py +8 -8
- clickhouse_driver/numpy/helpers.py +28 -25
- clickhouse_driver/numpy/result.py +123 -123
- clickhouse_driver/opentelemetry.py +43 -0
- clickhouse_driver/progress.py +44 -32
- clickhouse_driver/protocol.py +130 -105
- clickhouse_driver/queryprocessingstage.py +8 -8
- clickhouse_driver/reader.py +69 -69
- clickhouse_driver/readhelpers.py +26 -26
- clickhouse_driver/result.py +144 -144
- clickhouse_driver/settings/available.py +405 -405
- clickhouse_driver/settings/types.py +50 -50
- clickhouse_driver/settings/writer.py +34 -29
- clickhouse_driver/streams/compressed.py +88 -88
- clickhouse_driver/streams/native.py +108 -90
- clickhouse_driver/util/compat.py +39 -0
- clickhouse_driver/util/escape.py +94 -55
- clickhouse_driver/util/helpers.py +173 -57
- clickhouse_driver/varint.cp39-win_amd64.pyd +0 -0
- clickhouse_driver/writer.py +67 -67
- clickhouse_driver-0.2.10.dist-info/METADATA +215 -0
- clickhouse_driver-0.2.10.dist-info/RECORD +89 -0
- {clickhouse_driver-0.2.1.dist-info → clickhouse_driver-0.2.10.dist-info}/WHEEL +1 -1
- {clickhouse_driver-0.2.1.dist-info → clickhouse_driver-0.2.10.dist-info/licenses}/LICENSE +21 -21
- clickhouse_driver-0.2.1.dist-info/METADATA +0 -24
- clickhouse_driver-0.2.1.dist-info/RECORD +0 -80
- {clickhouse_driver-0.2.1.dist-info → clickhouse_driver-0.2.10.dist-info}/top_level.txt +0 -0
clickhouse_driver/protocol.py
CHANGED
|
@@ -1,105 +1,130 @@
|
|
|
1
|
-
|
|
2
|
-
class ClientPacketTypes(object):
|
|
3
|
-
"""
|
|
4
|
-
Packet types that client transmits
|
|
5
|
-
"""
|
|
6
|
-
# Name, version, revision, default DB
|
|
7
|
-
HELLO = 0
|
|
8
|
-
|
|
9
|
-
# Query id, query settings, stage up to which the query must be executed,
|
|
10
|
-
# whether the compression must be used, query text
|
|
11
|
-
# (without data for INSERTs).
|
|
12
|
-
QUERY = 1
|
|
13
|
-
|
|
14
|
-
# A block of data (compressed or not).
|
|
15
|
-
DATA = 2
|
|
16
|
-
|
|
17
|
-
# Cancel the query execution.
|
|
18
|
-
CANCEL = 3
|
|
19
|
-
|
|
20
|
-
# Check that connection to the server is alive.
|
|
21
|
-
PING = 4
|
|
22
|
-
|
|
23
|
-
# Check status of tables on the server.
|
|
24
|
-
TABLES_STATUS_REQUEST = 5
|
|
25
|
-
|
|
26
|
-
_types_str = [
|
|
27
|
-
'Hello', 'Query', 'Data', 'Cancel', 'Ping', 'TablesStatusRequest'
|
|
28
|
-
]
|
|
29
|
-
|
|
30
|
-
@classmethod
|
|
31
|
-
def to_str(cls, packet):
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
#
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
#
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
#
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
#
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
#
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
#
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
#
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
# A block with
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
# A
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
#
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
#
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
1
|
+
|
|
2
|
+
class ClientPacketTypes(object):
|
|
3
|
+
"""
|
|
4
|
+
Packet types that client transmits
|
|
5
|
+
"""
|
|
6
|
+
# Name, version, revision, default DB
|
|
7
|
+
HELLO = 0
|
|
8
|
+
|
|
9
|
+
# Query id, query settings, stage up to which the query must be executed,
|
|
10
|
+
# whether the compression must be used, query text
|
|
11
|
+
# (without data for INSERTs).
|
|
12
|
+
QUERY = 1
|
|
13
|
+
|
|
14
|
+
# A block of data (compressed or not).
|
|
15
|
+
DATA = 2
|
|
16
|
+
|
|
17
|
+
# Cancel the query execution.
|
|
18
|
+
CANCEL = 3
|
|
19
|
+
|
|
20
|
+
# Check that connection to the server is alive.
|
|
21
|
+
PING = 4
|
|
22
|
+
|
|
23
|
+
# Check status of tables on the server.
|
|
24
|
+
TABLES_STATUS_REQUEST = 5
|
|
25
|
+
|
|
26
|
+
_types_str = [
|
|
27
|
+
'Hello', 'Query', 'Data', 'Cancel', 'Ping', 'TablesStatusRequest'
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def to_str(cls, packet):
|
|
32
|
+
try:
|
|
33
|
+
return cls._types_str[packet]
|
|
34
|
+
except IndexError:
|
|
35
|
+
return 'Unknown packet'
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ServerPacketTypes(object):
|
|
39
|
+
"""
|
|
40
|
+
Packet types that server transmits.
|
|
41
|
+
"""
|
|
42
|
+
# Name, version, revision.
|
|
43
|
+
HELLO = 0
|
|
44
|
+
|
|
45
|
+
# A block of data (compressed or not).
|
|
46
|
+
DATA = 1
|
|
47
|
+
|
|
48
|
+
# The exception during query execution.
|
|
49
|
+
EXCEPTION = 2
|
|
50
|
+
|
|
51
|
+
# Query execution progress: rows read, bytes read.
|
|
52
|
+
PROGRESS = 3
|
|
53
|
+
|
|
54
|
+
# Ping response
|
|
55
|
+
PONG = 4
|
|
56
|
+
|
|
57
|
+
# All packets were transmitted
|
|
58
|
+
END_OF_STREAM = 5
|
|
59
|
+
|
|
60
|
+
# Packet with profiling info.
|
|
61
|
+
PROFILE_INFO = 6
|
|
62
|
+
|
|
63
|
+
# A block with totals (compressed or not).
|
|
64
|
+
TOTALS = 7
|
|
65
|
+
|
|
66
|
+
# A block with minimums and maximums (compressed or not).
|
|
67
|
+
EXTREMES = 8
|
|
68
|
+
|
|
69
|
+
# A response to TablesStatus request.
|
|
70
|
+
TABLES_STATUS_RESPONSE = 9
|
|
71
|
+
|
|
72
|
+
# System logs of the query execution
|
|
73
|
+
LOG = 10
|
|
74
|
+
|
|
75
|
+
# Columns' description for default values calculation
|
|
76
|
+
TABLE_COLUMNS = 11
|
|
77
|
+
|
|
78
|
+
# List of unique parts ids.
|
|
79
|
+
PART_UUIDS = 12
|
|
80
|
+
|
|
81
|
+
# String (UUID) describes a request for which next task is needed
|
|
82
|
+
READ_TASK_REQUEST = 13
|
|
83
|
+
|
|
84
|
+
# Packet with profile events from server.
|
|
85
|
+
PROFILE_EVENTS = 14
|
|
86
|
+
|
|
87
|
+
MERGE_TREE_ALL_RANGES_ANNOUNCEMENT = 15
|
|
88
|
+
|
|
89
|
+
# Request from a MergeTree replica to a coordinator
|
|
90
|
+
MERGE_TREE_READ_TASK_REQUEST = 16
|
|
91
|
+
|
|
92
|
+
# Receive server's (session-wide) default timezone
|
|
93
|
+
TIMEZONE_UPDATE = 17
|
|
94
|
+
|
|
95
|
+
_types_str = [
|
|
96
|
+
'Hello', 'Data', 'Exception', 'Progress', 'Pong', 'EndOfStream',
|
|
97
|
+
'ProfileInfo', 'Totals', 'Extremes', 'TablesStatusResponse', 'Log',
|
|
98
|
+
'TableColumns', 'PartUUIDs', 'ReadTaskRequest', 'ProfileEvents',
|
|
99
|
+
'MergeTreeAllRangesAnnouncement', 'MergeTreeReadTaskRequest',
|
|
100
|
+
'TimezoneUpdate'
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
@classmethod
|
|
104
|
+
def to_str(cls, packet):
|
|
105
|
+
try:
|
|
106
|
+
return cls._types_str[packet]
|
|
107
|
+
except IndexError:
|
|
108
|
+
return 'Unknown packet'
|
|
109
|
+
|
|
110
|
+
@classmethod
|
|
111
|
+
def strings_in_message(cls, packet):
|
|
112
|
+
if packet == cls.TABLE_COLUMNS:
|
|
113
|
+
return 2
|
|
114
|
+
return 0
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class Compression(object):
|
|
118
|
+
DISABLED = 0
|
|
119
|
+
ENABLED = 1
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class CompressionMethod(object):
|
|
123
|
+
LZ4 = 1
|
|
124
|
+
LZ4HC = 2
|
|
125
|
+
ZSTD = 3
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class CompressionMethodByte(object):
|
|
129
|
+
LZ4 = 0x82
|
|
130
|
+
ZSTD = 0x90
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
class QueryProcessingStage(object):
|
|
3
|
-
"""
|
|
4
|
-
Determines till which state SELECT query should be executed.
|
|
5
|
-
"""
|
|
6
|
-
FETCH_COLUMNS = 0
|
|
7
|
-
WITH_MERGEABLE_STATE = 1
|
|
8
|
-
COMPLETE = 2
|
|
1
|
+
|
|
2
|
+
class QueryProcessingStage(object):
|
|
3
|
+
"""
|
|
4
|
+
Determines till which state SELECT query should be executed.
|
|
5
|
+
"""
|
|
6
|
+
FETCH_COLUMNS = 0
|
|
7
|
+
WITH_MERGEABLE_STATE = 1
|
|
8
|
+
COMPLETE = 2
|
clickhouse_driver/reader.py
CHANGED
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
from struct import Struct
|
|
2
|
-
|
|
3
|
-
from .varint import read_varint
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def read_binary_str(buf):
|
|
7
|
-
length = read_varint(buf)
|
|
8
|
-
return read_binary_str_fixed_len(buf, length)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def read_binary_bytes(buf):
|
|
12
|
-
length = read_varint(buf)
|
|
13
|
-
return read_binary_bytes_fixed_len(buf, length)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def read_binary_str_fixed_len(buf, length):
|
|
17
|
-
return read_binary_bytes_fixed_len(buf, length).decode('utf-8')
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def read_binary_bytes_fixed_len(buf, length):
|
|
21
|
-
return buf.read(length)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def read_binary_int(buf, fmt):
|
|
25
|
-
"""
|
|
26
|
-
Reads int from buffer with provided format.
|
|
27
|
-
"""
|
|
28
|
-
# Little endian.
|
|
29
|
-
s = Struct('<' + fmt)
|
|
30
|
-
return s.unpack(buf.read(s.size))[0]
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def read_binary_int8(buf):
|
|
34
|
-
return read_binary_int(buf, 'b')
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def read_binary_int16(buf):
|
|
38
|
-
return read_binary_int(buf, 'h')
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def read_binary_int32(buf):
|
|
42
|
-
return read_binary_int(buf, 'i')
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def read_binary_int64(buf):
|
|
46
|
-
return read_binary_int(buf, 'q')
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def read_binary_uint8(buf):
|
|
50
|
-
return read_binary_int(buf, 'B')
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def read_binary_uint16(buf):
|
|
54
|
-
return read_binary_int(buf, 'H')
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def read_binary_uint32(buf):
|
|
58
|
-
return read_binary_int(buf, 'I')
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def read_binary_uint64(buf):
|
|
62
|
-
return read_binary_int(buf, 'Q')
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def read_binary_uint128(buf):
|
|
66
|
-
hi = read_binary_int(buf, 'Q')
|
|
67
|
-
lo = read_binary_int(buf, 'Q')
|
|
68
|
-
|
|
69
|
-
return (hi << 64) + lo
|
|
1
|
+
from struct import Struct
|
|
2
|
+
|
|
3
|
+
from .varint import read_varint
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def read_binary_str(buf):
|
|
7
|
+
length = read_varint(buf)
|
|
8
|
+
return read_binary_str_fixed_len(buf, length)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def read_binary_bytes(buf):
|
|
12
|
+
length = read_varint(buf)
|
|
13
|
+
return read_binary_bytes_fixed_len(buf, length)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def read_binary_str_fixed_len(buf, length):
|
|
17
|
+
return read_binary_bytes_fixed_len(buf, length).decode('utf-8')
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def read_binary_bytes_fixed_len(buf, length):
|
|
21
|
+
return buf.read(length)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def read_binary_int(buf, fmt):
|
|
25
|
+
"""
|
|
26
|
+
Reads int from buffer with provided format.
|
|
27
|
+
"""
|
|
28
|
+
# Little endian.
|
|
29
|
+
s = Struct('<' + fmt)
|
|
30
|
+
return s.unpack(buf.read(s.size))[0]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def read_binary_int8(buf):
|
|
34
|
+
return read_binary_int(buf, 'b')
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def read_binary_int16(buf):
|
|
38
|
+
return read_binary_int(buf, 'h')
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def read_binary_int32(buf):
|
|
42
|
+
return read_binary_int(buf, 'i')
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def read_binary_int64(buf):
|
|
46
|
+
return read_binary_int(buf, 'q')
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def read_binary_uint8(buf):
|
|
50
|
+
return read_binary_int(buf, 'B')
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def read_binary_uint16(buf):
|
|
54
|
+
return read_binary_int(buf, 'H')
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def read_binary_uint32(buf):
|
|
58
|
+
return read_binary_int(buf, 'I')
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def read_binary_uint64(buf):
|
|
62
|
+
return read_binary_int(buf, 'Q')
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def read_binary_uint128(buf):
|
|
66
|
+
hi = read_binary_int(buf, 'Q')
|
|
67
|
+
lo = read_binary_int(buf, 'Q')
|
|
68
|
+
|
|
69
|
+
return (hi << 64) + lo
|
clickhouse_driver/readhelpers.py
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
from .errors import ServerException
|
|
2
|
-
from .reader import read_binary_str, read_binary_uint8, read_binary_int32
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def read_exception(buf, additional_message=None):
|
|
6
|
-
code = read_binary_int32(buf)
|
|
7
|
-
name = read_binary_str(buf)
|
|
8
|
-
message = read_binary_str(buf)
|
|
9
|
-
stack_trace = read_binary_str(buf)
|
|
10
|
-
has_nested = bool(read_binary_uint8(buf))
|
|
11
|
-
|
|
12
|
-
new_message = ''
|
|
13
|
-
|
|
14
|
-
if additional_message:
|
|
15
|
-
new_message += additional_message + '. '
|
|
16
|
-
|
|
17
|
-
if name != 'DB::Exception':
|
|
18
|
-
new_message += name + ". "
|
|
19
|
-
|
|
20
|
-
new_message += message + ". Stack trace:\n\n" + stack_trace
|
|
21
|
-
|
|
22
|
-
nested = None
|
|
23
|
-
if has_nested:
|
|
24
|
-
nested = read_exception(buf)
|
|
25
|
-
|
|
26
|
-
return ServerException(new_message, code, nested=nested)
|
|
1
|
+
from .errors import ServerException
|
|
2
|
+
from .reader import read_binary_str, read_binary_uint8, read_binary_int32
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def read_exception(buf, additional_message=None):
|
|
6
|
+
code = read_binary_int32(buf)
|
|
7
|
+
name = read_binary_str(buf)
|
|
8
|
+
message = read_binary_str(buf)
|
|
9
|
+
stack_trace = read_binary_str(buf)
|
|
10
|
+
has_nested = bool(read_binary_uint8(buf))
|
|
11
|
+
|
|
12
|
+
new_message = ''
|
|
13
|
+
|
|
14
|
+
if additional_message:
|
|
15
|
+
new_message += additional_message + '. '
|
|
16
|
+
|
|
17
|
+
if name != 'DB::Exception':
|
|
18
|
+
new_message += name + ". "
|
|
19
|
+
|
|
20
|
+
new_message += message + ". Stack trace:\n\n" + stack_trace
|
|
21
|
+
|
|
22
|
+
nested = None
|
|
23
|
+
if has_nested:
|
|
24
|
+
nested = read_exception(buf)
|
|
25
|
+
|
|
26
|
+
return ServerException(new_message, code, nested=nested)
|