valkey-glide 2.0.0rc7__cp310-cp310-macosx_11_0_arm64.whl → 2.1.0rc1__cp310-cp310-macosx_11_0_arm64.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.

Potentially problematic release.


This version of valkey-glide might be problematic. Click here for more details.

Files changed (45) hide show
  1. glide/__init__.py +103 -107
  2. glide/async_commands/cluster_commands.py +83 -101
  3. glide/async_commands/core.py +554 -424
  4. glide/async_commands/{server_modules/ft.py → ft.py} +8 -7
  5. glide/async_commands/{server_modules/glide_json.py → glide_json.py} +15 -92
  6. glide/async_commands/standalone_commands.py +18 -17
  7. glide/glide.cpython-310-darwin.so +0 -0
  8. glide/glide.pyi +26 -1
  9. glide/glide_client.py +70 -45
  10. glide/logger.py +33 -21
  11. glide/opentelemetry.py +185 -0
  12. glide_shared/__init__.py +326 -0
  13. {glide/async_commands → glide_shared/commands}/batch.py +411 -18
  14. glide_shared/commands/batch_options.py +261 -0
  15. glide_shared/commands/core_options.py +407 -0
  16. {glide/async_commands → glide_shared/commands}/server_modules/ft_options/ft_aggregate_options.py +3 -3
  17. {glide/async_commands → glide_shared/commands}/server_modules/ft_options/ft_create_options.py +4 -2
  18. {glide/async_commands → glide_shared/commands}/server_modules/ft_options/ft_profile_options.py +4 -4
  19. {glide/async_commands → glide_shared/commands}/server_modules/ft_options/ft_search_options.py +4 -2
  20. {glide/async_commands → glide_shared/commands}/server_modules/json_batch.py +4 -4
  21. glide_shared/commands/server_modules/json_options.py +93 -0
  22. {glide/async_commands → glide_shared/commands}/sorted_set.py +2 -2
  23. {glide/async_commands → glide_shared/commands}/stream.py +1 -1
  24. {glide → glide_shared}/config.py +120 -32
  25. {glide → glide_shared}/constants.py +3 -3
  26. {glide → glide_shared}/exceptions.py +27 -1
  27. glide_shared/protobuf/command_request_pb2.py +54 -0
  28. glide_shared/protobuf/connection_request_pb2.py +52 -0
  29. {glide → glide_shared}/protobuf/response_pb2.py +6 -6
  30. {glide → glide_shared}/routes.py +29 -15
  31. valkey_glide-2.1.0rc1.dist-info/METADATA +210 -0
  32. valkey_glide-2.1.0rc1.dist-info/RECORD +39 -0
  33. glide/protobuf/command_request_pb2.py +0 -54
  34. glide/protobuf/command_request_pb2.pyi +0 -1187
  35. glide/protobuf/connection_request_pb2.py +0 -54
  36. glide/protobuf/connection_request_pb2.pyi +0 -320
  37. glide/protobuf/response_pb2.pyi +0 -100
  38. valkey_glide-2.0.0rc7.dist-info/METADATA +0 -144
  39. valkey_glide-2.0.0rc7.dist-info/RECORD +0 -37
  40. /glide/py.typed → /glide_shared/commands/__init__.py +0 -0
  41. {glide/async_commands → glide_shared/commands}/bitmap.py +0 -0
  42. {glide/async_commands → glide_shared/commands}/command_args.py +0 -0
  43. {glide/async_commands → glide_shared/commands}/server_modules/ft_options/ft_constants.py +0 -0
  44. {glide → glide_shared}/protobuf_codec.py +0 -0
  45. {valkey_glide-2.0.0rc7.dist-info → valkey_glide-2.1.0rc1.dist-info}/WHEEL +0 -0
@@ -5,24 +5,24 @@ module for `vector search` commands.
5
5
 
6
6
  from typing import List, Mapping, Optional, cast
7
7
 
8
- from glide.async_commands.server_modules.ft_options.ft_aggregate_options import (
8
+ from glide_shared.commands.server_modules.ft_options.ft_aggregate_options import (
9
9
  FtAggregateOptions,
10
10
  )
11
- from glide.async_commands.server_modules.ft_options.ft_constants import (
11
+ from glide_shared.commands.server_modules.ft_options.ft_constants import (
12
12
  CommandNames,
13
13
  FtCreateKeywords,
14
14
  )
15
- from glide.async_commands.server_modules.ft_options.ft_create_options import (
15
+ from glide_shared.commands.server_modules.ft_options.ft_create_options import (
16
16
  Field,
17
17
  FtCreateOptions,
18
18
  )
19
- from glide.async_commands.server_modules.ft_options.ft_profile_options import (
19
+ from glide_shared.commands.server_modules.ft_options.ft_profile_options import (
20
20
  FtProfileOptions,
21
21
  )
22
- from glide.async_commands.server_modules.ft_options.ft_search_options import (
22
+ from glide_shared.commands.server_modules.ft_options.ft_search_options import (
23
23
  FtSearchOptions,
24
24
  )
25
- from glide.constants import (
25
+ from glide_shared.constants import (
26
26
  TOK,
27
27
  FtAggregateResponse,
28
28
  FtInfoResponse,
@@ -30,7 +30,8 @@ from glide.constants import (
30
30
  FtSearchResponse,
31
31
  TEncodable,
32
32
  )
33
- from glide.glide_client import TGlideClient
33
+
34
+ from ..glide_client import TGlideClient
34
35
 
35
36
 
36
37
  async def create(
@@ -7,7 +7,7 @@ Examples:
7
7
  >>> import json
8
8
  >>> value = {'a': 1.0, 'b': 2}
9
9
  >>> json_str = json.dumps(value) # Convert Python dictionary to JSON string using json.dumps()
10
- >>> await json.set(client, "doc", "$", json_str)
10
+ >>> await glide_json.set(client, "doc", "$", json_str)
11
11
  'OK' # Indicates successful setting of the value at path '$' in the key stored at `doc`.
12
12
  >>> json_get = await glide_json.get(client, "doc", "$") # Returns the value at path '$' in the JSON document stored at
13
13
  # `doc` as JSON string.
@@ -19,97 +19,20 @@ Examples:
19
19
  """
20
20
  from typing import List, Optional, Union, cast
21
21
 
22
- from glide.async_commands.core import ConditionalChange
23
- from glide.constants import TOK, TEncodable, TJsonResponse, TJsonUniversalResponse
24
- from glide.glide_client import TGlideClient
25
-
26
-
27
- class JsonGetOptions:
28
- """
29
- Represents options for formatting JSON data, to be used in the [JSON.GET](https://valkey.io/commands/json.get/) command.
30
-
31
- Args:
32
- indent (Optional[str]): Sets an indentation string for nested levels. Defaults to None.
33
- newline (Optional[str]): Sets a string that's printed at the end of each line. Defaults to None.
34
- space (Optional[str]): Sets a string that's put between a key and a value. Defaults to None.
35
- """
36
-
37
- def __init__(
38
- self,
39
- indent: Optional[str] = None,
40
- newline: Optional[str] = None,
41
- space: Optional[str] = None,
42
- ):
43
- self.indent = indent
44
- self.new_line = newline
45
- self.space = space
46
-
47
- def get_options(self) -> List[str]:
48
- args = []
49
- if self.indent:
50
- args.extend(["INDENT", self.indent])
51
- if self.new_line:
52
- args.extend(["NEWLINE", self.new_line])
53
- if self.space:
54
- args.extend(["SPACE", self.space])
55
- return args
56
-
57
-
58
- class JsonArrIndexOptions:
59
- """
60
- Options for the `JSON.ARRINDEX` command.
61
-
62
- Args:
63
- start (int): The inclusive start index from which the search begins. Defaults to None.
64
- end (Optional[int]): The exclusive end index where the search stops. Defaults to None.
65
-
66
- Note:
67
- - If `start` is greater than `end`, the command returns `-1` to indicate that the value was not found.
68
- - Indices that exceed the array bounds are automatically adjusted to the nearest valid position.
69
- """
70
-
71
- def __init__(self, start: int, end: Optional[int] = None):
72
- self.start = start
73
- self.end = end
74
-
75
- def to_args(self) -> List[str]:
76
- """
77
- Get the options as a list of arguments for the JSON.ARRINDEX command.
78
-
79
- Returns:
80
- List[str]: A list containing the start and end indices if specified.
81
- """
82
- args = [str(self.start)]
83
- if self.end is not None:
84
- args.append(str(self.end))
85
- return args
86
-
87
-
88
- class JsonArrPopOptions:
89
- """
90
- Options for the JSON.ARRPOP command.
91
-
92
- Args:
93
- path (TEncodable): The path within the JSON document.
94
- index (Optional[int]): The index of the element to pop. If not specified, will pop the last element.
95
- Out of boundary indexes are rounded to their respective array boundaries. Defaults to None.
96
- """
97
-
98
- def __init__(self, path: TEncodable, index: Optional[int] = None):
99
- self.path = path
100
- self.index = index
101
-
102
- def to_args(self) -> List[TEncodable]:
103
- """
104
- Get the options as a list of arguments for the `JSON.ARRPOP` command.
105
-
106
- Returns:
107
- List[TEncodable]: A list containing the path and, if specified, the index.
108
- """
109
- args = [self.path]
110
- if self.index is not None:
111
- args.append(str(self.index))
112
- return args
22
+ from glide_shared.commands.core_options import ConditionalChange
23
+ from glide_shared.commands.server_modules.json_options import (
24
+ JsonArrIndexOptions,
25
+ JsonArrPopOptions,
26
+ JsonGetOptions,
27
+ )
28
+ from glide_shared.constants import (
29
+ TOK,
30
+ TEncodable,
31
+ TJsonResponse,
32
+ TJsonUniversalResponse,
33
+ )
34
+
35
+ from ..glide_client import TGlideClient
113
36
 
114
37
 
115
38
  async def set(
@@ -4,24 +4,25 @@ from __future__ import annotations
4
4
 
5
5
  from typing import Dict, List, Mapping, Optional, Union, cast
6
6
 
7
- from glide.async_commands.batch import Batch
8
- from glide.async_commands.command_args import ObjectType
9
- from glide.async_commands.core import (
10
- CoreCommands,
7
+ from glide.glide import Script
8
+ from glide_shared.commands.batch import Batch
9
+ from glide_shared.commands.batch_options import BatchOptions
10
+ from glide_shared.commands.command_args import ObjectType
11
+ from glide_shared.commands.core_options import (
11
12
  FlushMode,
12
13
  FunctionRestorePolicy,
13
14
  InfoSection,
14
15
  )
15
- from glide.constants import (
16
+ from glide_shared.constants import (
16
17
  TOK,
17
18
  TEncodable,
18
19
  TFunctionListResponse,
19
20
  TFunctionStatsFullResponse,
20
21
  TResult,
21
22
  )
22
- from glide.protobuf.command_request_pb2 import RequestType
23
+ from glide_shared.protobuf.command_request_pb2 import RequestType
23
24
 
24
- from ..glide import Script
25
+ from .core import CoreCommands
25
26
 
26
27
 
27
28
  class StandaloneCommands(CoreCommands):
@@ -76,7 +77,7 @@ class StandaloneCommands(CoreCommands):
76
77
  self,
77
78
  batch: Batch,
78
79
  raise_on_error: bool,
79
- timeout: Optional[int] = None,
80
+ options: Optional[BatchOptions] = None,
80
81
  ) -> Optional[List[TResult]]:
81
82
  """
82
83
  Executes a batch by processing the queued commands.
@@ -96,10 +97,7 @@ class StandaloneCommands(CoreCommands):
96
97
  When set to ``False``, errors will be included as part of the batch response array, allowing
97
98
  the caller to process both successful and failed commands together. In this case, error details
98
99
  will be provided as instances of ``RequestError``.
99
- timeout (Optional[int]): The duration in milliseconds that the client should wait for the batch request
100
- to complete. This duration encompasses sending the request, awaiting a response from the server, and any
101
- required reconnections or retries. If the specified timeout is exceeded for the request,
102
- a timeout error will be raised. If not explicitly set, the client's default request timeout will be used.
100
+ options (Optional[BatchOptions]): A ``BatchOptions`` object containing execution options.
103
101
 
104
102
  Returns:
105
103
  Optional[List[TResult]]: An array of results, where each entry corresponds to a command's execution result.
@@ -125,33 +123,38 @@ class StandaloneCommands(CoreCommands):
125
123
  # Expected Output: Pipeline Batch Result: [OK, OK, b'value1', b'value2']
126
124
 
127
125
  Example (Atomic Batch - Transaction with options):
126
+ >>> from glide import BatchOptions
128
127
  >>> transaction = Batch(is_atomic=True)
129
128
  >>> transaction.set("key", "1")
130
129
  >>> transaction.incr("key")
131
130
  >>> transaction.custom_command(["get", "key"])
131
+ >>> options = BatchOptions(timeout=1000) # Set a timeout of 1000 milliseconds
132
132
  >>> result = await client.exec(
133
133
  ... transaction,
134
134
  ... raise_on_error=False, # Do not raise an error on failure
135
- ... timeout=1000 # Set a timeout of 1000 milliseconds
135
+ ... options=options
136
136
  ... )
137
137
  >>> print(f"Transaction Result: {result}")
138
138
  # Expected Output: Transaction Result: [OK, 2, b'2']
139
139
 
140
140
  Example (Non-Atomic Batch - Pipeline with options):
141
+ >>> from glide import BatchOptions
141
142
  >>> pipeline = Batch(is_atomic=False)
142
143
  >>> pipeline.custom_command(["set", "key1", "value1"])
143
144
  >>> pipeline.custom_command(["set", "key2", "value2"])
144
145
  >>> pipeline.custom_command(["get", "key1"])
145
146
  >>> pipeline.custom_command(["get", "key2"])
147
+ >>> options = BatchOptions(timeout=1000) # Set a timeout of 1000 milliseconds
146
148
  >>> result = await client.exec(
147
149
  ... pipeline,
148
150
  ... raise_on_error=False, # Do not raise an error on failure
149
- ... timeout=1000 # Set a timeout of 1000 milliseconds
151
+ ... options=options
150
152
  ... )
151
153
  >>> print(f"Pipeline Result: {result}")
152
154
  # Expected Output: Pipeline Result: [OK, OK, b'value1', b'value2']
153
155
  """
154
156
  commands = batch.commands[:]
157
+ timeout = options.timeout if options else None
155
158
  return await self._execute_batch(
156
159
  commands,
157
160
  is_atomic=batch.is_atomic,
@@ -868,8 +871,6 @@ class StandaloneCommands(CoreCommands):
868
871
  TOK: A simple "OK" response.
869
872
 
870
873
  Examples:
871
- >>> await client.watch("sampleKey")
872
- 'OK'
873
874
  >>> await client.unwatch()
874
875
  'OK'
875
876
  """
@@ -1033,7 +1034,7 @@ class StandaloneCommands(CoreCommands):
1033
1034
 
1034
1035
  Examples:
1035
1036
  >>> lua_script = Script("return { KEYS[1], ARGV[1] }")
1036
- >>> await client.invoke_script(lua_script, keys=["foo"], args=["bar"] );
1037
+ >>> await client.invoke_script(lua_script, keys=["foo"], args=["bar"])
1037
1038
  [b"foo", b"bar"]
1038
1039
  """
1039
1040
  return await self._execute_script(script.get_hash(), keys, args)
Binary file
glide/glide.pyi CHANGED
@@ -2,7 +2,7 @@ from collections.abc import Callable
2
2
  from enum import Enum
3
3
  from typing import List, Optional, Union
4
4
 
5
- from glide.constants import TResult
5
+ from glide_shared.constants import TResult
6
6
 
7
7
  DEFAULT_TIMEOUT_IN_MILLISECONDS: int = ...
8
8
  MAX_REQUEST_ARGS_LEN: int = ...
@@ -27,6 +27,28 @@ class ClusterScanCursor:
27
27
  def get_cursor(self) -> str: ...
28
28
  def is_finished(self) -> bool: ...
29
29
 
30
+ class OpenTelemetryConfig:
31
+ def __init__(
32
+ self,
33
+ traces: Optional[OpenTelemetryTracesConfig] = None,
34
+ metrics: Optional[OpenTelemetryMetricsConfig] = None,
35
+ flush_interval_ms: Optional[int] = None,
36
+ ) -> None: ...
37
+ def get_traces(self) -> Optional[OpenTelemetryTracesConfig]: ...
38
+ def set_traces(self, traces: OpenTelemetryTracesConfig) -> None: ...
39
+ def get_metrics(self) -> Optional[OpenTelemetryMetricsConfig]: ...
40
+
41
+ class OpenTelemetryTracesConfig:
42
+ def __init__(
43
+ self, endpoint: str, sample_percentage: Optional[int] = None
44
+ ) -> None: ...
45
+ def get_endpoint(self) -> str: ...
46
+ def get_sample_percentage(self) -> Optional[int]: ...
47
+
48
+ class OpenTelemetryMetricsConfig:
49
+ def __init__(self, endpoint: str) -> None: ...
50
+ def get_endpoint(self) -> str: ...
51
+
30
52
  def start_socket_listener_external(init_callback: Callable) -> None: ...
31
53
  def value_from_pointer(pointer: int) -> TResult: ...
32
54
  def create_leaked_value(message: str) -> int: ...
@@ -34,3 +56,6 @@ def create_leaked_bytes_vec(args_vec: List[bytes]) -> int: ...
34
56
  def get_statistics() -> dict: ...
35
57
  def py_init(level: Optional[Level], file_name: Optional[str]) -> Level: ...
36
58
  def py_log(log_level: Level, log_identifier: str, message: str) -> None: ...
59
+ def create_otel_span(name: str) -> int: ...
60
+ def drop_otel_span(span_ptr: int) -> None: ...
61
+ def init_opentelemetry(config: OpenTelemetryConfig) -> None: ...
glide/glide_client.py CHANGED
@@ -11,7 +11,6 @@ from typing import (
11
11
  Optional,
12
12
  Set,
13
13
  Tuple,
14
- Type,
15
14
  Union,
16
15
  cast,
17
16
  )
@@ -19,38 +18,49 @@ from typing import (
19
18
  import anyio
20
19
  import sniffio
21
20
  from anyio import to_thread
22
-
23
- from glide.async_commands.cluster_commands import ClusterCommands
24
- from glide.async_commands.command_args import ObjectType
25
- from glide.async_commands.core import CoreCommands
26
- from glide.async_commands.standalone_commands import StandaloneCommands
27
- from glide.config import BaseClientConfiguration, ServerCredentials
28
- from glide.constants import DEFAULT_READ_BYTES_SIZE, OK, TEncodable, TRequest, TResult
29
- from glide.exceptions import (
30
- ClosingError,
31
- ConfigurationError,
32
- ConnectionError,
33
- ExecAbortError,
34
- RequestError,
35
- TimeoutError,
36
- )
37
- from glide.logger import Level as LogLevel
38
- from glide.logger import Logger as ClientLogger
39
- from glide.protobuf.command_request_pb2 import Command, CommandRequest, RequestType
40
- from glide.protobuf.connection_request_pb2 import ConnectionRequest
41
- from glide.protobuf.response_pb2 import RequestErrorType, Response
42
- from glide.protobuf_codec import PartialMessageException, ProtobufCodec
43
- from glide.routes import Route, set_protobuf_route
44
-
45
- from .glide import (
21
+ from glide.glide import (
46
22
  DEFAULT_TIMEOUT_IN_MILLISECONDS,
47
23
  MAX_REQUEST_ARGS_LEN,
48
24
  ClusterScanCursor,
49
25
  create_leaked_bytes_vec,
26
+ create_otel_span,
27
+ drop_otel_span,
50
28
  get_statistics,
51
29
  start_socket_listener_external,
52
30
  value_from_pointer,
53
31
  )
32
+ from glide_shared.commands.command_args import ObjectType
33
+ from glide_shared.commands.core_options import PubSubMsg
34
+ from glide_shared.config import BaseClientConfiguration, ServerCredentials
35
+ from glide_shared.constants import (
36
+ DEFAULT_READ_BYTES_SIZE,
37
+ OK,
38
+ TEncodable,
39
+ TRequest,
40
+ TResult,
41
+ )
42
+ from glide_shared.exceptions import (
43
+ ClosingError,
44
+ ConfigurationError,
45
+ ConnectionError,
46
+ get_request_error_class,
47
+ )
48
+ from glide_shared.protobuf.command_request_pb2 import (
49
+ Command,
50
+ CommandRequest,
51
+ RequestType,
52
+ )
53
+ from glide_shared.protobuf.connection_request_pb2 import ConnectionRequest
54
+ from glide_shared.protobuf.response_pb2 import Response
55
+ from glide_shared.protobuf_codec import PartialMessageException, ProtobufCodec
56
+ from glide_shared.routes import Route, set_protobuf_route
57
+
58
+ from .async_commands.cluster_commands import ClusterCommands
59
+ from .async_commands.core import CoreCommands
60
+ from .async_commands.standalone_commands import StandaloneCommands
61
+ from .logger import Level as LogLevel
62
+ from .logger import Logger as ClientLogger
63
+ from .opentelemetry import OpenTelemetry
54
64
 
55
65
  if sys.version_info >= (3, 11):
56
66
  from typing import Self
@@ -66,20 +76,6 @@ if TYPE_CHECKING:
66
76
  TFuture = Union[asyncio.Future[Any], "_CompatFuture"]
67
77
 
68
78
 
69
- def get_request_error_class(
70
- error_type: Optional[RequestErrorType.ValueType],
71
- ) -> Type[RequestError]:
72
- if error_type == RequestErrorType.Disconnect:
73
- return ConnectionError
74
- if error_type == RequestErrorType.ExecAbort:
75
- return ExecAbortError
76
- if error_type == RequestErrorType.Timeout:
77
- return TimeoutError
78
- if error_type == RequestErrorType.Unspecified:
79
- return RequestError
80
- return RequestError
81
-
82
-
83
79
  class _CompatFuture:
84
80
  """anyio shim for asyncio.Future-like functionality"""
85
81
 
@@ -410,6 +406,13 @@ class BaseClient(CoreCommands):
410
406
  raise ClosingError(
411
407
  "Unable to execute requests; the client is closed. Please create a new client."
412
408
  )
409
+
410
+ # Create span if OpenTelemetry is configured and sampling indicates we should trace
411
+ span = None
412
+ if OpenTelemetry.should_sample():
413
+ command_name = RequestType.Name(request_type)
414
+ span = create_otel_span(command_name)
415
+
413
416
  request = CommandRequest()
414
417
  request.callback_idx = self._get_callback_index()
415
418
  request.single_command.request_type = request_type
@@ -424,6 +427,11 @@ class BaseClient(CoreCommands):
424
427
  request.single_command.args_vec_pointer = create_leaked_bytes_vec(
425
428
  encoded_args
426
429
  )
430
+
431
+ # Add span pointer to request if span was created
432
+ if span:
433
+ request.root_span_ptr = span
434
+
427
435
  set_protobuf_route(request, route)
428
436
  return await self._write_request_await_response(request)
429
437
 
@@ -441,6 +449,14 @@ class BaseClient(CoreCommands):
441
449
  raise ClosingError(
442
450
  "Unable to execute requests; the client is closed. Please create a new client."
443
451
  )
452
+
453
+ # Create span if OpenTelemetry is configured and sampling indicates we should trace
454
+ span = None
455
+
456
+ if OpenTelemetry.should_sample():
457
+ # Use "Batch" as span name for batches
458
+ span = create_otel_span("Batch")
459
+
444
460
  request = CommandRequest()
445
461
  request.callback_idx = self._get_callback_index()
446
462
  batch_commands = []
@@ -462,6 +478,11 @@ class BaseClient(CoreCommands):
462
478
  request.batch.timeout = timeout
463
479
  request.batch.retry_server_error = retry_server_error
464
480
  request.batch.retry_connection_error = retry_connection_error
481
+
482
+ # Add span pointer to request if span was created
483
+ if span:
484
+ request.root_span_ptr = span
485
+
465
486
  set_protobuf_route(request, route)
466
487
  return await self._write_request_await_response(request)
467
488
 
@@ -496,7 +517,7 @@ class BaseClient(CoreCommands):
496
517
  set_protobuf_route(request, route)
497
518
  return await self._write_request_await_response(request)
498
519
 
499
- async def get_pubsub_message(self) -> CoreCommands.PubSubMsg:
520
+ async def get_pubsub_message(self) -> PubSubMsg:
500
521
  if self._is_closed:
501
522
  raise ClosingError(
502
523
  "Unable to execute requests; the client is closed. Please create a new client."
@@ -523,7 +544,7 @@ class BaseClient(CoreCommands):
523
544
  await response_future
524
545
  return response_future.result()
525
546
 
526
- def try_get_pubsub_message(self) -> Optional[CoreCommands.PubSubMsg]:
547
+ def try_get_pubsub_message(self) -> Optional[PubSubMsg]:
527
548
  if self._is_closed:
528
549
  raise ClosingError(
529
550
  "Unable to execute requests; the client is closed. Please create a new client."
@@ -540,7 +561,7 @@ class BaseClient(CoreCommands):
540
561
  )
541
562
 
542
563
  # locking might not be required
543
- msg: Optional[CoreCommands.PubSubMsg] = None
564
+ msg: Optional[PubSubMsg] = None
544
565
  try:
545
566
  self._pubsub_lock.acquire()
546
567
  self._complete_pubsub_futures_safe()
@@ -558,7 +579,7 @@ class BaseClient(CoreCommands):
558
579
 
559
580
  def _notification_to_pubsub_message_safe(
560
581
  self, response: Response
561
- ) -> Optional[CoreCommands.PubSubMsg]:
582
+ ) -> Optional[PubSubMsg]:
562
583
  pubsub_message = None
563
584
  push_notification = cast(
564
585
  Dict[str, Any], value_from_pointer(response.resp_pointer)
@@ -577,11 +598,11 @@ class BaseClient(CoreCommands):
577
598
  ):
578
599
  values: List = push_notification["values"]
579
600
  if message_kind == "PMessage":
580
- pubsub_message = BaseClient.PubSubMsg(
601
+ pubsub_message = PubSubMsg(
581
602
  message=values[2], channel=values[1], pattern=values[0]
582
603
  )
583
604
  else:
584
- pubsub_message = BaseClient.PubSubMsg(
605
+ pubsub_message = PubSubMsg(
585
606
  message=values[1], channel=values[0], pattern=None
586
607
  )
587
608
  elif (
@@ -656,6 +677,10 @@ class BaseClient(CoreCommands):
656
677
  else:
657
678
  res_future.set_result(None)
658
679
 
680
+ # Clean up span if it was created
681
+ if response.HasField("root_span_ptr"):
682
+ drop_otel_span(response.root_span_ptr)
683
+
659
684
  async def _process_push(self, response: Response) -> None:
660
685
  if response.HasField("closing_error") or not response.HasField("resp_pointer"):
661
686
  err_msg = (
glide/logger.py CHANGED
@@ -2,11 +2,12 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import traceback
5
6
  from enum import Enum
6
7
  from typing import Optional
7
8
 
8
- from .glide import Level as internalLevel
9
- from .glide import py_init, py_log
9
+ from glide.glide import Level as internalLevel
10
+ from glide.glide import py_init, py_log
10
11
 
11
12
 
12
13
  class Level(Enum):
@@ -20,13 +21,12 @@ class Level(Enum):
20
21
 
21
22
  class Logger:
22
23
  """
23
- A singleton class that allows logging which is consistent with logs from the internal rust core.
24
+ A singleton class that allows logging which is consistent with logs from the internal GLIDE core.
24
25
  The logger can be set up in 2 ways -
25
26
  1. By calling Logger.init, which configures the logger only if it wasn't previously configured.
26
27
  2. By calling Logger.set_logger_config, which replaces the existing configuration, and means that new logs will not be
27
28
  saved with the logs that were sent before the call.
28
- If set_logger_config wasn't called, the first log attempt will initialize a new logger with default configuration decided
29
- by the Rust core.
29
+ If none of these functions are called, the first log attempt will initialize a new logger with default configuration.
30
30
  """
31
31
 
32
32
  _instance = None
@@ -38,48 +38,60 @@ class Logger:
38
38
 
39
39
  @classmethod
40
40
  def init(cls, level: Optional[Level] = None, file_name: Optional[str] = None):
41
- """_summary_
41
+ """
42
42
  Initialize a logger if it wasn't initialized before - this method is meant to be used when there is no intention to
43
- replace an existing logger.
44
- The logger will filter all logs with a level lower than the given level,
45
- If given a fileName argument, will write the logs to files postfixed with fileName. If fileName isn't provided,
43
+ replace an existing logger. Otherwise, use `set_logger_config` for overriding the existing logger configs.
44
+ The logger will filter all logs with a level lower than the given level.
45
+ If given a file_name argument, will write the logs to files postfixed with file_name. If file_name isn't provided,
46
46
  the logs will be written to the console.
47
+
47
48
  Args:
48
49
  level (Optional[Level]): Set the logger level to one of [ERROR, WARN, INFO, DEBUG, TRACE, OFF].
49
- If log level isn't provided, the logger will be configured with default configuration decided by the Rust core.
50
- file_name (Optional[str]): If provided the target of the logs will be the file mentioned.
51
- Otherwise, logs will be printed to the console.
52
- To turn off logging completely, set the level to Level.OFF.
50
+ If log level isn't provided, the logger will be configured with default configuration.
51
+ To turn off logging completely, set the level to Level.OFF.
52
+ file_name (Optional[str]): If provided the target of the logs will be the file mentioned.
53
+ Otherwise, logs will be printed to the console.
53
54
  """
54
55
  if cls._instance is None:
55
56
  cls._instance = cls(level, file_name)
56
57
 
57
58
  @classmethod
58
- def log(cls, log_level: Level, log_identifier: str, message: str):
59
- """Logs the provided message if the provided log level is lower then the logger level.
59
+ def log(
60
+ cls,
61
+ log_level: Level,
62
+ log_identifier: str,
63
+ message: str,
64
+ err: Optional[Exception] = None,
65
+ ):
66
+ """
67
+ Logs the provided message if the provided log level is lower then the logger level.
60
68
 
61
69
  Args:
62
- log_level (Level): The log level of the provided message
70
+ log_level (Level): The log level of the provided message.
63
71
  log_identifier (str): The log identifier should give the log a context.
64
72
  message (str): The message to log.
73
+ err (Optional[Exception]): The exception or error to log.
65
74
  """
66
75
  if not cls._instance:
67
76
  cls._instance = cls(None)
68
77
  if not log_level.value.is_lower(Logger.logger_level):
69
78
  return
79
+ if err:
80
+ message = f"{message}: {traceback.format_exception(err)}"
70
81
  py_log(log_level.value, log_identifier, message)
71
82
 
72
83
  @classmethod
73
84
  def set_logger_config(
74
85
  cls, level: Optional[Level] = None, file_name: Optional[str] = None
75
86
  ):
76
- """Creates a new logger instance and configure it with the provided log level and file name.
87
+ """
88
+ Creates a new logger instance and configure it with the provided log level and file name.
77
89
 
78
90
  Args:
79
91
  level (Optional[Level]): Set the logger level to one of [ERROR, WARN, INFO, DEBUG, TRACE, OFF].
80
- If log level isn't provided, the logger will be configured with default configuration decided by the Rust core.
81
- file_name (Optional[str]): If provided the target of the logs will be the file mentioned.
82
- Otherwise, logs will be printed to the console.
83
- To turn off logging completely, set the level to OFF.
92
+ If log level isn't provided, the logger will be configured with default configuration.
93
+ To turn off logging completely, set the level to OFF.
94
+ file_name (Optional[str]): If provided the target of the logs will be the file mentioned.
95
+ Otherwise, logs will be printed to the console.
84
96
  """
85
97
  Logger._instance = Logger(level, file_name)