Files
chat/venv/lib/python3.12/site-packages/kafka/util.py
Andrew K. Choi 91c7e04474
All checks were successful
continuous-integration/drone/push Build is passing
API refactor
2025-10-07 16:25:52 +09:00

141 lines
4.5 KiB
Python

from __future__ import absolute_import, division
import binascii
import functools
import re
import time
import weakref
from kafka.errors import KafkaTimeoutError
from kafka.vendor import six
if six.PY3:
MAX_INT = 2 ** 31
TO_SIGNED = 2 ** 32
def crc32(data):
crc = binascii.crc32(data)
# py2 and py3 behave a little differently
# CRC is encoded as a signed int in kafka protocol
# so we'll convert the py3 unsigned result to signed
if crc >= MAX_INT:
crc -= TO_SIGNED
return crc
else:
from binascii import crc32 # noqa: F401
class Timer:
__slots__ = ('_start_at', '_expire_at', '_timeout_ms', '_error_message')
def __init__(self, timeout_ms, error_message=None, start_at=None):
self._timeout_ms = timeout_ms
self._start_at = start_at or time.time()
if timeout_ms is not None:
self._expire_at = self._start_at + timeout_ms / 1000
else:
self._expire_at = float('inf')
self._error_message = error_message
@property
def expired(self):
return time.time() >= self._expire_at
@property
def timeout_ms(self):
if self._timeout_ms is None:
return None
elif self._expire_at == float('inf'):
return float('inf')
remaining = self._expire_at - time.time()
if remaining < 0:
return 0
else:
return int(remaining * 1000)
@property
def elapsed_ms(self):
return int(1000 * (time.time() - self._start_at))
def maybe_raise(self):
if self.expired:
raise KafkaTimeoutError(self._error_message)
def __str__(self):
return "Timer(%s ms remaining)" % (self.timeout_ms)
# Taken from: https://github.com/apache/kafka/blob/39eb31feaeebfb184d98cc5d94da9148c2319d81/clients/src/main/java/org/apache/kafka/common/internals/Topic.java#L29
TOPIC_MAX_LENGTH = 249
TOPIC_LEGAL_CHARS = re.compile('^[a-zA-Z0-9._-]+$')
def ensure_valid_topic_name(topic):
""" Ensures that the topic name is valid according to the kafka source. """
# See Kafka Source:
# https://github.com/apache/kafka/blob/39eb31feaeebfb184d98cc5d94da9148c2319d81/clients/src/main/java/org/apache/kafka/common/internals/Topic.java
if topic is None:
raise TypeError('All topics must not be None')
if not isinstance(topic, six.string_types):
raise TypeError('All topics must be strings')
if len(topic) == 0:
raise ValueError('All topics must be non-empty strings')
if topic == '.' or topic == '..':
raise ValueError('Topic name cannot be "." or ".."')
if len(topic) > TOPIC_MAX_LENGTH:
raise ValueError('Topic name is illegal, it can\'t be longer than {0} characters, topic: "{1}"'.format(TOPIC_MAX_LENGTH, topic))
if not TOPIC_LEGAL_CHARS.match(topic):
raise ValueError('Topic name "{0}" is illegal, it contains a character other than ASCII alphanumerics, ".", "_" and "-"'.format(topic))
class WeakMethod(object):
"""
Callable that weakly references a method and the object it is bound to. It
is based on https://stackoverflow.com/a/24287465.
Arguments:
object_dot_method: A bound instance method (i.e. 'object.method').
"""
def __init__(self, object_dot_method):
try:
self.target = weakref.ref(object_dot_method.__self__)
except AttributeError:
self.target = weakref.ref(object_dot_method.im_self)
self._target_id = id(self.target())
try:
self.method = weakref.ref(object_dot_method.__func__)
except AttributeError:
self.method = weakref.ref(object_dot_method.im_func)
self._method_id = id(self.method())
def __call__(self, *args, **kwargs):
"""
Calls the method on target with args and kwargs.
"""
return self.method()(self.target(), *args, **kwargs)
def __hash__(self):
return hash(self.target) ^ hash(self.method)
def __eq__(self, other):
if not isinstance(other, WeakMethod):
return False
return self._target_id == other._target_id and self._method_id == other._method_id
class Dict(dict):
"""Utility class to support passing weakrefs to dicts
See: https://docs.python.org/2/library/weakref.html
"""
pass
def synchronized(func):
def wrapper(self, *args, **kwargs):
with self._lock:
return func(self, *args, **kwargs)
functools.update_wrapper(wrapper, func)
return wrapper