def __init__(self, body, on_ack=noop, hostname=None, eventer=None, app=None, connection_errors=None, request_dict=None, delivery_info=None, task=None, on_reject=noop, **opts): self.app = app name = self.name = body['task'] self.id = body['id'] self.args = body.get('args', []) self.kwargs = body.get('kwargs', {}) try: self.kwargs.items except AttributeError: raise InvalidTaskError( 'Task keyword arguments is not a mapping') if NEEDS_KWDICT: self.kwargs = kwdict(self.kwargs) eta = body.get('eta') expires = body.get('expires') utc = self.utc = body.get('utc', False) self.on_ack = on_ack self.on_reject = on_reject self.hostname = hostname or socket.gethostname() self.eventer = eventer self.connection_errors = connection_errors or () self.task = task or self.app.tasks[name] self.acknowledged = self._already_revoked = False self.time_start = self.worker_pid = self._terminate_on_ack = None self._tzlocal = None # timezone means the message is timezone-aware, and the only timezone # supported at this point is UTC. if eta is not None: try: self.eta = maybe_iso8601(eta) except (AttributeError, ValueError, TypeError) as exc: raise InvalidTaskError( 'invalid eta value {0!r}: {1}'.format(eta, exc)) if utc: self.eta = maybe_make_aware(self.eta, self.tzlocal) else: self.eta = None if expires is not None: try: self.expires = maybe_iso8601(expires) except (AttributeError, ValueError, TypeError) as exc: raise InvalidTaskError( 'invalid expires value {0!r}: {1}'.format(expires, exc)) if utc: self.expires = maybe_make_aware(self.expires, self.tzlocal) else: self.expires = None delivery_info = {} if delivery_info is None else delivery_info self.delivery_info = { 'exchange': delivery_info.get('exchange'), 'routing_key': delivery_info.get('routing_key'), 'priority': delivery_info.get('priority'), 'redelivered': delivery_info.get('redelivered'), } self.request_dict = body
def __init__(self, body, on_ack=noop, hostname=None, eventer=None, app=None, connection_errors=None, request_dict=None, delivery_info=None, task=None, **opts): self.app = app or app_or_default(app) name = self.name = body['task'] self.id = body['id'] self.args = body.get('args', []) self.kwargs = body.get('kwargs', {}) try: self.kwargs.items except AttributeError: raise exceptions.InvalidTaskError( 'Task keyword arguments is not a mapping') if NEEDS_KWDICT: self.kwargs = kwdict(self.kwargs) eta = body.get('eta') expires = body.get('expires') utc = self.utc = body.get('utc', False) self.on_ack = on_ack self.hostname = hostname or socket.gethostname() self.eventer = eventer self.connection_errors = connection_errors or () self.task = task or self.app.tasks[name] self.acknowledged = self._already_revoked = False self.time_start = self.worker_pid = self._terminate_on_ack = None self._tzlocal = None # timezone means the message is timezone-aware, and the only timezone # supported at this point is UTC. if eta is not None: self.eta = maybe_iso8601(eta) if utc: self.eta = maybe_make_aware(self.eta, self.tzlocal) else: self.eta = None if expires is not None: self.expires = maybe_iso8601(expires) if utc: self.expires = maybe_make_aware(self.expires, self.tzlocal) else: self.expires = None delivery_info = {} if delivery_info is None else delivery_info self.delivery_info = { 'exchange': delivery_info.get('exchange'), 'routing_key': delivery_info.get('routing_key'), 'priority': delivery_info.get('priority'), } self.request_dict = body
def __init__(self, body, on_ack=noop, hostname=None, eventer=None, app=None, connection_errors=None, request_dict=None, delivery_info=None, task=None, **opts): self.app = app or app_or_default(app) name = self.name = body['task'] self.id = body['id'] self.args = body.get('args', []) self.kwargs = body.get('kwargs', {}) try: self.kwargs.items except AttributeError: raise exceptions.InvalidTaskError( 'Task keyword arguments is not a mapping') if NEEDS_KWDICT: self.kwargs = kwdict(self.kwargs) eta = body.get('eta') expires = body.get('expires') utc = self.utc = body.get('utc', False) self.on_ack = on_ack self.hostname = hostname or socket.gethostname() self.eventer = eventer self.connection_errors = connection_errors or () self.task = task or self.app.tasks[name] self.acknowledged = self._already_revoked = False self.time_start = self.worker_pid = self._terminate_on_ack = None self._tzlocal = None # timezone means the message is timezone-aware, and the only timezone # supported at this point is UTC. if eta is not None: self.eta = maybe_iso8601(eta) if utc: self.eta = maybe_make_aware(self.eta, self.tzlocal) else: self.eta = None if expires is not None: self.expires = maybe_iso8601(expires) if utc: self.expires = maybe_make_aware(self.expires, self.tzlocal) else: self.expires = None delivery_info = {} if delivery_info is None else delivery_info self.delivery_info = { 'exchange': delivery_info.get('exchange'), 'routing_key': delivery_info.get('routing_key'), 'priority': delivery_info.get('priority'), } # amqplib transport adds the channel here for some reason, so need # to remove it. self.delivery_info.pop('channel', None) self.request_dict = body
def test_roundtrip(self): now = self.app.now() # 3.x returns naive, but 4.x returns aware now = maybe_make_aware(now) roundtripped = from_timestamp(to_timestamp(now)) # we lose microseconds in the roundtrip, so we need to ignore them now = now.replace(microsecond=0) self.assertEqual(now, roundtripped)
def test_score(self): run_every = 61 * 60 entry = self.create_entry(run_every=run_every) entry = entry._next_instance() score = entry.score expected = entry.last_run_at + timedelta(seconds=run_every) expected = expected.replace( microsecond=0) # discard microseconds, lost in timestamp # 3.x returns naive, but 4.x returns aware expected = maybe_make_aware(expected) self.assertEqual(score, to_timestamp(expected)) self.assertEqual(expected, from_timestamp(score))
def test_next(self): initial = self.create_entry().save() now = self.app.now() # 3.x is naive but 4.x is aware now = maybe_make_aware(now) n = initial.next(last_run_at=now) self.assertIsNotNone(now.tzinfo) self.assertEqual(n.last_run_at, now) self.assertEqual(initial.total_run_count + 1, n.total_run_count) # updated meta was stored into redis loaded = RedBeatSchedulerEntry.from_key(initial.key, app=self.app) self.assertEqual(loaded.last_run_at, now) self.assertEqual(loaded.total_run_count, initial.total_run_count + 1) # new entry updated the schedule redis = self.app.redbeat_redis self.assertEqual( redis.zscore(self.app.redbeat_conf.schedule_key, n.key), n.score)
def __init__(self, body, on_ack=noop, hostname=None, eventer=None, app=None, connection_errors=None, request_dict=None, delivery_info=None, task=None, **opts): self.app = app or app_or_default(app) name = self.name = body['task'] self.id = body['id'] self.args = body.get('args', []) self.kwargs = body.get('kwargs', {}) try: self.kwargs.items except AttributeError: raise InvalidTaskError( 'Task keyword arguments is not a mapping') if NEEDS_KWDICT: self.kwargs = kwdict(self.kwargs) eta = body.get('eta') expires = body.get('expires') utc = self.utc = body.get('utc', False) self.on_ack = on_ack self.hostname = hostname or socket.gethostname() self.eventer = eventer self.connection_errors = connection_errors or () self.task = task or self.app.tasks[name] self.acknowledged = self._already_revoked = False self.time_start = self.worker_pid = self._terminate_on_ack = None self._tzlocal = None # timezone means the message is timezone-aware, and the only timezone # supported at this point is UTC. if eta is not None: try: self.eta = maybe_iso8601(eta) except (AttributeError, ValueError), exc: raise InvalidTaskError( 'invalid eta value %r: %s' % (eta, exc, )) if utc: self.eta = maybe_make_aware(self.eta, self.tzlocal)
def test_maybe_make_aware(self): aware = datetime.utcnow().replace(tzinfo=timezone.utc) self.assertTrue(maybe_make_aware(aware), timezone.utc) naive = datetime.utcnow() self.assertTrue(maybe_make_aware(naive))
self.eta = maybe_iso8601(eta) except (AttributeError, ValueError), exc: raise InvalidTaskError( 'invalid eta value %r: %s' % (eta, exc, )) if utc: self.eta = maybe_make_aware(self.eta, self.tzlocal) else: self.eta = None if expires is not None: try: self.expires = maybe_iso8601(expires) except (AttributeError, ValueError), exc: raise InvalidTaskError( 'invalid expires value %r: %s' % (expires, exc, )) if utc: self.expires = maybe_make_aware(self.expires, self.tzlocal) else: self.expires = None delivery_info = {} if delivery_info is None else delivery_info self.delivery_info = { 'exchange': delivery_info.get('exchange'), 'routing_key': delivery_info.get('routing_key'), 'priority': delivery_info.get('priority'), } # amqplib transport adds the channel here for some reason, so need # to remove it. self.delivery_info.pop('channel', None) self.request_dict = body
def as_task_v2(self, task_id, name, args=None, kwargs=None, countdown=None, eta=None, group_id=None, expires=None, retries=0, chord=None, callbacks=None, errbacks=None, reply_to=None, time_limit=None, soft_time_limit=None, create_sent_event=False, root_id=None, parent_id=None, shadow=None, chain=None, now=None, timezone=None, origin=None, argsrepr=None, kwargsrepr=None): args = args or () kwargs = kwargs or {} if not isinstance(args, (list, tuple)): raise TypeError('task args must be a list or tuple') if not isinstance(kwargs, Mapping): raise TypeError('task keyword arguments must be a mapping') if countdown: # convert countdown to ETA self._verify_seconds(countdown, 'countdown') now = now or self.app.now() timezone = timezone or self.app.timezone eta = maybe_make_aware( now + timedelta(seconds=countdown), tz=timezone, ) if isinstance(expires, numbers.Real): self._verify_seconds(expires, 'expires') now = now or self.app.now() timezone = timezone or self.app.timezone expires = maybe_make_aware( now + timedelta(seconds=expires), tz=timezone, ) eta = eta and eta.isoformat() expires = expires and expires.isoformat() if argsrepr is None: argsrepr = saferepr(args, self.argsrepr_maxsize) if kwargsrepr is None: kwargsrepr = saferepr(kwargs, self.kwargsrepr_maxsize) if JSON_NEEDS_UNICODE_KEYS: # pragma: no cover if callbacks: callbacks = [utf8dict(callback) for callback in callbacks] if errbacks: errbacks = [utf8dict(errback) for errback in errbacks] if chord: chord = utf8dict(chord) return task_message( headers={ 'lang': 'py', 'task': name, 'id': task_id, 'eta': eta, 'expires': expires, 'group': group_id, 'retries': retries, 'timelimit': [time_limit, soft_time_limit], 'root_id': root_id, 'parent_id': parent_id, 'argsrepr': argsrepr, 'kwargsrepr': kwargsrepr, 'origin': origin or anon_nodename() }, properties={ 'correlation_id': task_id, 'reply_to': reply_to or '', }, body=( args, kwargs, { 'callbacks': callbacks, 'errbacks': errbacks, 'chain': chain, 'chord': chord, }, ), sent_event={ 'uuid': task_id, 'root_id': root_id, 'parent_id': parent_id, 'name': name, 'args': argsrepr, 'kwargs': kwargsrepr, 'retries': retries, 'eta': eta, 'expires': expires, } if create_sent_event else None, )
def __init__(self, message, on_ack=noop, hostname=None, eventer=None, app=None, connection_errors=None, request_dict=None, task=None, on_reject=noop, body=None, headers=None, decoded=False, utc=True, maybe_make_aware=maybe_make_aware, maybe_iso8601=maybe_iso8601, **opts): if headers is None: headers = message.headers if body is None: body = message.body self.app = app self.message = message self.body = body self.utc = utc self._decoded = decoded if decoded: self.content_type = self.content_encoding = None else: self.content_type, self.content_encoding = ( message.content_type, message.content_encoding, ) self.id = headers['id'] type = self.type = self.name = headers['task'] self.root_id = headers.get('root_id') self.parent_id = headers.get('parent_id') if 'shadow' in headers: self.name = headers['shadow'] or self.name if 'timelimit' in headers: self.time_limits = headers['timelimit'] self.argsrepr = headers.get('argsrepr', '') self.kwargsrepr = headers.get('kwargsrepr', '') self.on_ack = on_ack self.on_reject = on_reject self.hostname = hostname or gethostname() self.eventer = eventer self.connection_errors = connection_errors or () self.task = task or self.app.tasks[type] # timezone means the message is timezone-aware, and the only timezone # supported at this point is UTC. eta = headers.get('eta') if eta is not None: try: eta = maybe_iso8601(eta) except (AttributeError, ValueError, TypeError) as exc: raise InvalidTaskError( 'invalid eta value {0!r}: {1}'.format(eta, exc)) self.eta = maybe_make_aware(eta, self.tzlocal) else: self.eta = None expires = headers.get('expires') if expires is not None: try: expires = maybe_iso8601(expires) except (AttributeError, ValueError, TypeError) as exc: raise InvalidTaskError( 'invalid expires value {0!r}: {1}'.format(expires, exc)) self.expires = maybe_make_aware(expires, self.tzlocal) else: self.expires = None delivery_info = message.delivery_info or {} properties = message.properties or {} headers.update({ 'reply_to': properties.get('reply_to'), 'correlation_id': properties.get('correlation_id'), 'delivery_info': { 'exchange': delivery_info.get('exchange'), 'routing_key': delivery_info.get('routing_key'), 'priority': properties.get('priority'), 'redelivered': delivery_info.get('redelivered'), } }) self.request_dict = headers
def __init__( self, body, on_ack=noop, hostname=None, eventer=None, app=None, connection_errors=None, request_dict=None, message=None, task=None, on_reject=noop, **opts ): self.app = app name = self.name = body["task"] self.id = body["id"] self.args = body.get("args", []) self.kwargs = body.get("kwargs", {}) try: self.kwargs.items except AttributeError: raise InvalidTaskError("Task keyword arguments is not a mapping") if NEEDS_KWDICT: self.kwargs = kwdict(self.kwargs) eta = body.get("eta") expires = body.get("expires") utc = self.utc = body.get("utc", False) self.on_ack = on_ack self.on_reject = on_reject self.hostname = hostname or socket.gethostname() self.eventer = eventer self.connection_errors = connection_errors or () self.task = task or self.app.tasks[name] self.acknowledged = self._already_revoked = False self.time_start = self.worker_pid = self._terminate_on_ack = None self._apply_result = None self._tzlocal = None # timezone means the message is timezone-aware, and the only timezone # supported at this point is UTC. if eta is not None: try: self.eta = maybe_iso8601(eta) except (AttributeError, ValueError, TypeError) as exc: raise InvalidTaskError("invalid eta value {0!r}: {1}".format(eta, exc)) if utc: self.eta = maybe_make_aware(self.eta, self.tzlocal) else: self.eta = None if expires is not None: try: self.expires = maybe_iso8601(expires) except (AttributeError, ValueError, TypeError) as exc: raise InvalidTaskError("invalid expires value {0!r}: {1}".format(expires, exc)) if utc: self.expires = maybe_make_aware(self.expires, self.tzlocal) else: self.expires = None if message: delivery_info = message.delivery_info or {} properties = message.properties or {} body.update( { "headers": message.headers, "reply_to": properties.get("reply_to"), "correlation_id": properties.get("correlation_id"), "delivery_info": { "exchange": delivery_info.get("exchange"), "routing_key": delivery_info.get("routing_key"), "priority": delivery_info.get("priority"), "redelivered": delivery_info.get("redelivered"), }, } ) else: body.update(DEFAULT_FIELDS) self.request_dict = body
def __init__( self, message, on_ack=noop, hostname=None, eventer=None, app=None, connection_errors=None, request_dict=None, task=None, on_reject=noop, body=None, headers=None, decoded=False, utc=True, maybe_make_aware=maybe_make_aware, maybe_iso8601=maybe_iso8601, **opts ): if headers is None: headers = message.headers if body is None: body = message.body self.app = app self.message = message self.body = body self.utc = utc self._decoded = decoded if decoded: self.content_type = self.content_encoding = None else: self.content_type, self.content_encoding = (message.content_type, message.content_encoding) self.id = headers["id"] type = self.type = self.name = headers["task"] self.root_id = headers.get("root_id") self.parent_id = headers.get("parent_id") if "shadow" in headers: self.name = headers["shadow"] or self.name if "timelimit" in headers: self.time_limits = headers["timelimit"] self.argsrepr = headers.get("argsrepr", "") self.kwargsrepr = headers.get("kwargsrepr", "") self.on_ack = on_ack self.on_reject = on_reject self.hostname = hostname or socket.gethostname() self.eventer = eventer self.connection_errors = connection_errors or () self.task = task or self.app.tasks[type] # timezone means the message is timezone-aware, and the only timezone # supported at this point is UTC. eta = headers.get("eta") if eta is not None: try: eta = maybe_iso8601(eta) except (AttributeError, ValueError, TypeError) as exc: raise InvalidTaskError("invalid eta value {0!r}: {1}".format(eta, exc)) self.eta = maybe_make_aware(eta, self.tzlocal) else: self.eta = None expires = headers.get("expires") if expires is not None: try: expires = maybe_iso8601(expires) except (AttributeError, ValueError, TypeError) as exc: raise InvalidTaskError("invalid expires value {0!r}: {1}".format(expires, exc)) self.expires = maybe_make_aware(expires, self.tzlocal) else: self.expires = None delivery_info = message.delivery_info or {} properties = message.properties or {} headers.update( { "reply_to": properties.get("reply_to"), "correlation_id": properties.get("correlation_id"), "delivery_info": { "exchange": delivery_info.get("exchange"), "routing_key": delivery_info.get("routing_key"), "priority": properties.get("priority"), "redelivered": delivery_info.get("redelivered"), }, } ) self.request_dict = headers
exc, )) if utc: self.eta = maybe_make_aware(self.eta, self.tzlocal) else: self.eta = None if expires is not None: try: self.expires = maybe_iso8601(expires) except (AttributeError, ValueError), exc: raise InvalidTaskError('invalid expires value %r: %s' % ( expires, exc, )) if utc: self.expires = maybe_make_aware(self.expires, self.tzlocal) else: self.expires = None delivery_info = {} if delivery_info is None else delivery_info self.delivery_info = { 'exchange': delivery_info.get('exchange'), 'routing_key': delivery_info.get('routing_key'), 'priority': delivery_info.get('priority'), } # amqplib transport adds the channel here for some reason, so need # to remove it. self.delivery_info.pop('channel', None) self.request_dict = body
def timestamp_from_dt(dt): """Convert a datetime to seconds since epoch.""" return calendar.timegm(maybe_make_aware(dt).utctimetuple()) if dt else 0
def __init__(self, body, on_ack=noop, hostname=None, eventer=None, app=None, connection_errors=None, request_dict=None, message=None, task=None, on_reject=noop, **opts): self.app = app name = self.name = body['task'] self.id = body['id'] self.args = body.get('args', []) self.kwargs = body.get('kwargs', {}) try: self.kwargs.items except AttributeError: raise InvalidTaskError('Task keyword arguments is not a mapping') if NEEDS_KWDICT: self.kwargs = kwdict(self.kwargs) eta = body.get('eta') expires = body.get('expires') utc = self.utc = body.get('utc', False) self.on_ack = on_ack self.on_reject = on_reject self.hostname = hostname or socket.gethostname() self.eventer = eventer self.connection_errors = connection_errors or () self.task = task or self.app.tasks[name] self.acknowledged = self._already_revoked = False self.time_start = self.worker_pid = self._terminate_on_ack = None self._apply_result = None self._tzlocal = None # timezone means the message is timezone-aware, and the only timezone # supported at this point is UTC. if eta is not None: try: self.eta = maybe_iso8601(eta) except (AttributeError, ValueError, TypeError) as exc: raise InvalidTaskError('invalid eta value {0!r}: {1}'.format( eta, exc)) if utc: self.eta = maybe_make_aware(self.eta, self.tzlocal) else: self.eta = None if expires is not None: try: self.expires = maybe_iso8601(expires) except (AttributeError, ValueError, TypeError) as exc: raise InvalidTaskError( 'invalid expires value {0!r}: {1}'.format(expires, exc)) if utc: self.expires = maybe_make_aware(self.expires, self.tzlocal) else: self.expires = None if message: delivery_info = message.delivery_info or {} properties = message.properties or {} body.update({ 'headers': message.headers, 'reply_to': properties.get('reply_to'), 'correlation_id': properties.get('correlation_id'), 'delivery_info': { 'exchange': delivery_info.get('exchange'), 'routing_key': delivery_info.get('routing_key'), 'priority': properties.get('priority', delivery_info.get('priority')), 'redelivered': delivery_info.get('redelivered'), } }) else: body.update(DEFAULT_FIELDS) self.request_dict = body
def as_task_v2( self, task_id, name, args=None, kwargs=None, countdown=None, eta=None, group_id=None, expires=None, retries=0, chord=None, callbacks=None, errbacks=None, reply_to=None, time_limit=None, soft_time_limit=None, create_sent_event=False, root_id=None, parent_id=None, shadow=None, chain=None, now=None, timezone=None, ): args = args or () kwargs = kwargs or {} if not isinstance(args, (list, tuple)): raise TypeError("task args must be a list or tuple") if not isinstance(kwargs, Mapping): raise TypeError("task keyword arguments must be a mapping") if countdown: # convert countdown to ETA now = now or self.app.now() timezone = timezone or self.app.timezone eta = maybe_make_aware(now + timedelta(seconds=countdown), tz=timezone) if isinstance(expires, numbers.Real): now = now or self.app.now() timezone = timezone or self.app.timezone expires = maybe_make_aware(now + timedelta(seconds=expires), tz=timezone) eta = eta and eta.isoformat() expires = expires and expires.isoformat() argsrepr = saferepr(args) kwargsrepr = saferepr(kwargs) if JSON_NEEDS_UNICODE_KEYS: # pragma: no cover if callbacks: callbacks = [utf8dict(callback) for callback in callbacks] if errbacks: errbacks = [utf8dict(errback) for errback in errbacks] if chord: chord = utf8dict(chord) return task_message( headers={ "lang": "py", "task": name, "id": task_id, "eta": eta, "expires": expires, "group": group_id, "retries": retries, "timelimit": [time_limit, soft_time_limit], "root_id": root_id, "parent_id": parent_id, "argsrepr": argsrepr, "kwargsrepr": kwargsrepr, }, properties={"correlation_id": task_id, "reply_to": reply_to or ""}, body=(args, kwargs, {"callbacks": callbacks, "errbacks": errbacks, "chain": chain, "chord": chord}), sent_event={ "uuid": task_id, "root_id": root_id, "parent_id": parent_id, "name": name, "args": argsrepr, "kwargs": kwargsrepr, "retries": retries, "eta": eta, "expires": expires, } if create_sent_event else None, )