Compare commits

...
8 Commits
Author SHA1 Message Date
Stan Triepels 06ad6154e3 Release 1.4.4 (#37) 2022-11-13 01:06:19 +01:00
Stan Triepels 542e04db54 Feat: Add biweekly and bimonthly and fix translations (#36) 2022-11-13 01:00:11 +01:00
Stan Triepels 17205549eb Fix baseconv/base62 deprecation warning for Django 5.x (#34) 2022-11-09 00:41:12 +01:00
Stan Triepels 1764c5c8ae Release 1.4.3 (#32)
Update changelog and bump version number
2022-11-07 17:47:05 +01:00
Mikhail Krassavin f0cb10bc37 Add Python 3.11 support and tests, remove Python 3.7 (#31) 2022-11-07 17:29:29 +01:00
Stan Triepels 167c348509 Update changelog and readme (#29)
Added changes from the previous versions and diff between Q and Q2
2022-11-05 23:06:34 +01:00
Stan Triepels 6f19b3d270 Fix: func reference in admin (#28) 2022-11-05 02:45:44 +01:00
Stan Triepels f62bd7b6b4 Fix install docs: update q to q2 (#25) 2022-10-27 02:08:08 +02:00
23 changed files with 995 additions and 641 deletions
+5 -2
View File
@@ -22,8 +22,11 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install -U pip setuptools poetry apt-get update
python -m pip install poetry apt-get -y install gettext
python -m pip install pip setuptools django poetry
# compile messages to get .mo files
django-admin compilemessages
- name: Build and publish package - name: Build and publish package
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
run: poetry --build --username=__token__ --password=${{ secrets.PYPI_TOKEN }} publish run: poetry --build --username=__token__ --password=${{ secrets.PYPI_TOKEN }} publish
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
python-version: [ "3.8", "3.9", "3.10" ] python-version: [ "3.8", "3.9", "3.10", "3.11" ]
django: [ "3.2", "4.1" ] django: [ "3.2", "4.1" ]
services: services:
+48 -2
View File
@@ -1,8 +1,54 @@
# Changelog # Changelog
## [Unreleased](https://github.com/koed00/django-q/tree/HEAD) ## [Unreleased](https://github.com/GDay/django-q2/tree/HEAD)
[Full Changelog](https://github.com/koed00/django-q/compare/v1.3.9...HEAD) ## [v1.4.4](https://github.com/GDay/django-q2/tree/v1.4.4) (2022-11-13)
**Merged pull requests:**
- Fix: Deprecation warning for Django 5.x https://github.com/GDay/django-q2/pull/34
- Feat: Add biweekly and bimonthly https://github.com/GDay/django-q2/pull/36
- Fix: Fix all translation strings and remove compiled https://github.com/GDay/django-q2/pull/36
## [v1.4.3](https://github.com/GDay/django-q2/tree/v1.4.3) (2022-11-07)
**Merged pull requests:**
- Fix: func reference in admin https://github.com/GDay/django-q2/pull/28
- Add python 3.11 support and remove 3.7 (as it was never supported by this package anyway)
## [v1.4.2](https://github.com/GDay/django-q2/tree/v1.4.2) (2022-10-22)
**Merged pull requests:**
- Make redis dependency optional and update boto3 #22
## [v1.4.1](https://github.com/GDay/django-q2/tree/v1.4.1) (2022-10-21)
**Merged pull requests:**
- Fix typo configure.rst https://github.com/GDay/django-q2/pull/1
- Update dependencies https://github.com/GDay/django-q2/pull/2
- Show function name in log when running task https://github.com/GDay/django-q2/pull/3
- Codecov -> Coveralls https://github.com/GDay/django-q2/pull/4
- Fix: readthedocs config file https://github.com/GDay/django-q2/pull/5
- Docs updates https://github.com/GDay/django-q2/pull/6
- Feat: Release plan to pypi https://github.com/GDay/django-q2/pull/7
- Feat: Turkish translations https://github.com/GDay/django-q2/pull/8
- Fix: Connection issues with CONN_MAX_AGE > 0 https://github.com/GDay/django-q2/pull/9
- Replace use of eval() by ast.parse() + ast.literal_eval() https://github.com/GDay/django-q2/pull/10
- Admin improvements https://github.com/GDay/django-q2/pull/11
- Save limit per group/func/name https://github.com/GDay/django-q2/pull/12
- Use logger.hasHandlers() to setup fallback logging https://github.com/GDay/django-q2/pull/13
- allow atomic on external db https://github.com/GDay/django-q2/pull/14
- Fix install command and remove old warnings https://github.com/GDay/django-q2/pull/16
- Remove arrow dependency https://github.com/GDay/django-q2/pull/17
- Remove funding file, add docker/compose for development project and fix https://github.com/GDay/django-q2/pull/18
- Fix unclear error when function is not called correctly https://github.com/GDay/django-q2/pull/19
- Remove blessed dependency https://github.com/GDay/django-q2/pull/20
- Release new version and docs fixes https://github.com/GDay/django-q2/pull/21
## v1.4.0
**Closed issues:** **Closed issues:**
+13 -1
View File
@@ -22,13 +22,25 @@ Features
- Redis, IronMQ, SQS, MongoDB or ORM - Redis, IronMQ, SQS, MongoDB or ORM
- Rollbar and Sentry support - Rollbar and Sentry support
Changes compared to the original Django-Q:
- Dropped support for Disque (hasn't been updated in a long time)
- Dropped Redis, Arrow and Blessed dependencies
- Updated all current dependencies
- Added tests for Django 4.x
- Added Turkish language
- Improved admin area
- Fixed a lot of issues
See the `changelog <https://github.com/GDay/django-q2/blob/master/CHANGELOG.md>`__ for all changes.
Requirements Requirements
~~~~~~~~~~~~ ~~~~~~~~~~~~
- `Django <https://www.djangoproject.com>`__ > = 3.2 - `Django <https://www.djangoproject.com>`__ > = 3.2
- `Django-picklefield <https://github.com/gintas/django-picklefield>`__ - `Django-picklefield <https://github.com/gintas/django-picklefield>`__
Tested with: Python 3.7, 3.8, 3.9, 3.10 Django 3.2.X and 4.1.X Tested with: Python 3.8, 3.9, 3.10, 3.11 Django 3.2.X and 4.1.X
Brokers Brokers
~~~~~~~ ~~~~~~~
+38 -47
View File
@@ -1,6 +1,5 @@
# Standard # Standard
import ast import ast
import inspect
import pydoc import pydoc
import signal import signal
import socket import socket
@@ -44,7 +43,7 @@ from django_q.signals import post_execute, pre_execute
from django_q.signing import BadSignature, SignedPackage from django_q.signing import BadSignature, SignedPackage
from django_q.status import Stat, Status from django_q.status import Stat, Status
from .utils import add_months, add_years from .utils import add_months, add_years, get_func_repr
class Cluster: class Cluster:
@@ -75,7 +74,7 @@ class Cluster:
), ),
) )
self.sentinel.start() self.sentinel.start()
logger.info(_(f"Q Cluster {self.name} starting.")) logger.info(_("Q Cluster %(name)s starting.") % {'name': self.name})
while not self.start_event.is_set(): while not self.start_event.is_set():
sleep(0.1) sleep(0.1)
return self.pid return self.pid
@@ -83,10 +82,10 @@ class Cluster:
def stop(self) -> bool: def stop(self) -> bool:
if not self.sentinel.is_alive(): if not self.sentinel.is_alive():
return False return False
logger.info(_(f"Q Cluster {self.name} stopping.")) logger.info(_("Q Cluster %(name)s stopping.") % {'name': self.name})
self.stop_event.set() self.stop_event.set()
self.sentinel.join() self.sentinel.join()
logger.info(_(f"Q Cluster {self.name} has stopped.")) logger.info(_("Q Cluster %(name)s has stopped.") % {'name': self.name})
self.start_event = None self.start_event = None
self.stop_event = None self.stop_event = None
return True return True
@@ -94,8 +93,8 @@ class Cluster:
def sig_handler(self, signum, frame): def sig_handler(self, signum, frame):
logger.debug( logger.debug(
_( _(
f'{current_process().name} got signal {Conf.SIGNAL_NAMES.get(signum, "UNKNOWN")}' '%(name)s got signal %(signal)s'
) ) % {'name': current_process().name, 'signal': Conf.SIGNAL_NAMES.get(signum, "UNKNOWN")}
) )
self.stop() self.stop()
@@ -217,21 +216,21 @@ class Sentinel:
db.connections.close_all() db.connections.close_all()
if process == self.monitor: if process == self.monitor:
self.monitor = self.spawn_monitor() self.monitor = self.spawn_monitor()
logger.error(_(f"reincarnated monitor {process.name} after sudden death")) logger.error(_("reincarnated monitor %(name)s after sudden death") % {'name': process.name})
elif process == self.pusher: elif process == self.pusher:
self.pusher = self.spawn_pusher() self.pusher = self.spawn_pusher()
logger.error(_(f"reincarnated pusher {process.name} after sudden death")) logger.error(_("reincarnated pusher %(name)s after sudden death") % {'name': process.name})
else: else:
self.pool.remove(process) self.pool.remove(process)
self.spawn_worker() self.spawn_worker()
if process.timer.value == 0: if process.timer.value == 0:
# only need to terminate on timeout, otherwise we risk destabilizing the queues # only need to terminate on timeout, otherwise we risk destabilizing the queues
process.terminate() process.terminate()
logger.warning(_(f"reincarnated worker {process.name} after timeout")) logger.warning(_("reincarnated worker %(name)s after timeout") % {'name': process.name})
elif int(process.timer.value) == -2: elif int(process.timer.value) == -2:
logger.info(_(f"recycled worker {process.name}")) logger.info(_("recycled worker %(name)s") % {'name': process.name})
else: else:
logger.error(_(f"reincarnated worker {process.name} after death")) logger.error(_("reincarnated worker %(name)s after death") % {'name': process.name})
self.reincarnations += 1 self.reincarnations += 1
@@ -254,12 +253,12 @@ class Sentinel:
def guard(self): def guard(self):
logger.info( logger.info(
_( _(
f"{current_process().name} guarding cluster {humanize(self.cluster_id.hex)}" "%(name)s guarding cluster %(cluster_name)s"
) ) % {'name': current_process().name, 'cluster_name': humanize(self.cluster_id.hex)}
) )
self.start_event.set() self.start_event.set()
Stat(self).save() Stat(self).save()
logger.info(_(f"Q Cluster {humanize(self.cluster_id.hex)} running.")) logger.info(_("Q Cluster %(cluster_name)s running.") % {'cluster_name': humanize(self.cluster_id.hex)})
counter = 0 counter = 0
cycle = Conf.GUARD_CYCLE # guard loop sleep in seconds cycle = Conf.GUARD_CYCLE # guard loop sleep in seconds
# Guard loop. Runs at least once # Guard loop. Runs at least once
@@ -293,7 +292,7 @@ class Sentinel:
def stop(self): def stop(self):
Stat(self).save() Stat(self).save()
name = current_process().name name = current_process().name
logger.info(_(f"{name} stopping cluster processes")) logger.info(_("%(name)s stopping cluster processes") % {'name': name})
# Stopping pusher # Stopping pusher
self.event_out.set() self.event_out.set()
# Wait for it to stop # Wait for it to stop
@@ -318,7 +317,7 @@ class Sentinel:
self.result_queue.close() self.result_queue.close()
# Wait for the result queue to empty # Wait for the result queue to empty
self.result_queue.join_thread() self.result_queue.join_thread()
logger.info(_(f"{name} waiting for the monitor.")) logger.info(_("%(name)s waiting for the monitor.") % {'name': name})
# Wait for everything to close or time out # Wait for everything to close or time out
count = 0 count = 0
if not self.timeout: if not self.timeout:
@@ -340,7 +339,7 @@ def pusher(task_queue: Queue, event: Event, broker: Broker = None):
""" """
if not broker: if not broker:
broker = get_broker() broker = get_broker()
logger.info(_(f"{current_process().name} pushing tasks at {current_process().pid}")) logger.info(_("%(process_name)s pushing tasks at %(id)s") % {'process_name': current_process().name, 'id': current_process().pid})
while True: while True:
try: try:
task_set = broker.dequeue() task_set = broker.dequeue()
@@ -361,10 +360,10 @@ def pusher(task_queue: Queue, event: Event, broker: Broker = None):
continue continue
task["ack_id"] = ack_id task["ack_id"] = ack_id
task_queue.put(task) task_queue.put(task)
logger.debug(_(f"queueing from {broker.list_key}")) logger.debug(_("queueing from %(list_key)s") % {'list_key': broker.list_key})
if event.is_set(): if event.is_set():
break break
logger.info(_(f"{current_process().name} stopped pushing tasks")) logger.info(_("%(name)s stopped pushing tasks") % {'name': current_process().name})
def monitor(result_queue: Queue, broker: Broker = None): def monitor(result_queue: Queue, broker: Broker = None):
@@ -376,7 +375,7 @@ def monitor(result_queue: Queue, broker: Broker = None):
if not broker: if not broker:
broker = get_broker() broker = get_broker()
name = current_process().name name = current_process().name
logger.info(_(f"{name} monitoring at {current_process().pid}")) logger.info(_("%(name)s monitoring at %(id)s") % {'name': name, 'id': current_process().pid})
for task in iter(result_queue.get, "STOP"): for task in iter(result_queue.get, "STOP"):
# save the result # save the result
if task.get("cached", False): if task.get("cached", False):
@@ -393,11 +392,11 @@ def monitor(result_queue: Queue, broker: Broker = None):
info_name = get_func_repr(task['func']) info_name = get_func_repr(task['func'])
if task["success"]: if task["success"]:
# log success # log success
logger.info(_(f"Processed '{info_name}' ({task['name']})")) logger.info(_("Processed '%(info_name)s' (%(task_name)s)") % {'info_name': info_name, 'task_name': task['name']})
else: else:
# log failure # log failure
logger.error(_(f"Failed '{info_name}' ({task['name']}) - {task['result']}")) logger.error(_("Failed '%(info_name)s' (%(task_name)s) - %(task_result)s") % {'info_name': info_name, 'task_name': task['name'], 'task_result': task['result']})
logger.info(_(f"{name} stopped monitoring results")) logger.info(_("%(name)s stopped monitoring results") % {'name': name})
def worker( def worker(
@@ -411,7 +410,7 @@ def worker(
:type timer: multiprocessing.Value :type timer: multiprocessing.Value
""" """
proc_name = current_process().name proc_name = current_process().name
logger.info(_(f"{proc_name} ready for work at {current_process().pid}")) logger.info(_("%(proc_name)s ready for work at %(id)s") % {'proc_name': proc_name, 'id': current_process().pid})
task_count = 0 task_count = 0
if timeout is None: if timeout is None:
timeout = -1 timeout = -1
@@ -423,7 +422,7 @@ def worker(
# Get the function from the task # Get the function from the task
func = task["func"] func = task["func"]
func_name = get_func_repr(func) func_name = get_func_repr(func)
logger.info(_(f"{proc_name} processing '{func_name}' ({task['name']})")) logger.info(_("%(proc_name)s processing '%(func_name)s' (%(task_name)s)") % {'proc_name': proc_name, 'func_name': func_name, 'task_name': task['name']})
f = task["func"] f = task["func"]
# if it's not an instance try to get it from the string # if it's not an instance try to get it from the string
if not callable(task["func"]): if not callable(task["func"]):
@@ -438,7 +437,7 @@ def worker(
res = f(*task["args"], **task["kwargs"]) res = f(*task["args"], **task["kwargs"])
result = (res, True) result = (res, True)
except Exception: except Exception:
result = (f"Could not process '{func_name}'. Check the location of the function and the args/kwargs.", False) result = (_("Could not process '%(func_name)s'. Check the location of the function and the args/kwargs.") % {'func_name': func_name}, False)
if error_reporter: if error_reporter:
error_reporter.report() error_reporter.report()
if task.get("sync", False): if task.get("sync", False):
@@ -454,19 +453,7 @@ def worker(
if task_count == Conf.RECYCLE or rss_check(): if task_count == Conf.RECYCLE or rss_check():
timer.value = -2 # Recycled timer.value = -2 # Recycled
break break
logger.info(_(f"{proc_name} stopped doing work")) logger.info(_("%(proc_name)s stopped doing work") % {'proc_name': proc_name})
def get_func_repr(func):
# convert func to string
if inspect.isfunction(func):
return f"{func.__module__}.{func.__name__}"
elif inspect.ismethod(func) and hasattr(func.__self__, '__name__'):
return (
f"{func.__self__.__module__}."
f"{func.__self__.__name__}.{func.__name__}"
)
else:
return str(func)
def save_task(task, broker: Broker): def save_task(task, broker: Broker):
""" """
@@ -645,8 +632,12 @@ def scheduler(broker: Broker = None):
next_run = next_run + timedelta(days=1) next_run = next_run + timedelta(days=1)
elif s.schedule_type == s.WEEKLY: elif s.schedule_type == s.WEEKLY:
next_run = next_run + timedelta(weeks=1) next_run = next_run + timedelta(weeks=1)
elif s.schedule_type == s.BIWEEKLY:
next_run = next_run + timedelta(weeks=2)
elif s.schedule_type == s.MONTHLY: elif s.schedule_type == s.MONTHLY:
next_run = add_months(next_run, 1) next_run = add_months(next_run, 1)
elif s.schedule_type == s.BIMONTHLY:
next_run = add_months(next_run, 2)
elif s.schedule_type == s.QUARTERLY: elif s.schedule_type == s.QUARTERLY:
next_run = add_months(next_run, 3) next_run = add_months(next_run, 3)
elif s.schedule_type == s.YEARLY: elif s.schedule_type == s.YEARLY:
@@ -678,14 +669,14 @@ def scheduler(broker: Broker = None):
if not s.task: if not s.task:
logger.error( logger.error(
_( _(
f"{current_process().name} failed to create a task from schedule [{s.name or s.id}]" "%(process_name)s failed to create a task from schedule [%(schedule)s]"
) ) % {'process_name': current_process().name, 'schedule': s.name or s.id}
) )
else: else:
logger.info( logger.info(
_( _(
f"{current_process().name} created a task from schedule [{s.name or s.id}]" "%(process_name)s created a task from schedule [%(schedule)s]"
) ) % {'process_name': current_process().name, 'schedule': s.name or s.id}
) )
# default behavior is to delete a ONCE schedule # default behavior is to delete a ONCE schedule
if s.schedule_type == s.ONCE: if s.schedule_type == s.ONCE:
@@ -724,12 +715,12 @@ def set_cpu_affinity(n: int, process_ids: list, actual: bool = not Conf.TESTING)
""" """
# check if we have the psutil module # check if we have the psutil module
if not psutil: if not psutil:
logger.warning("Skipping cpu affinity because psutil was not found.") logger.warning(_("Skipping cpu affinity because psutil was not found."))
return return
# check if the platform supports cpu_affinity # check if the platform supports cpu_affinity
if actual and not hasattr(psutil.Process(process_ids[0]), "cpu_affinity"): if actual and not hasattr(psutil.Process(process_ids[0]), "cpu_affinity"):
logger.warning( logger.warning(
"Faking cpu affinity because it is not supported on this platform" _("Faking cpu affinity because it is not supported on this platform")
) )
actual = False actual = False
# get the available processors # get the available processors
@@ -750,7 +741,7 @@ def set_cpu_affinity(n: int, process_ids: list, actual: bool = not Conf.TESTING)
p = psutil.Process(pid) p = psutil.Process(pid)
if actual: if actual:
p.cpu_affinity(affinity) p.cpu_affinity(affinity)
logger.info(_(f"{pid} will use cpu {affinity}")) logger.info(_("%(pid)s will use cpu %(affinity)s") % {'pid': pid, 'affinity': affinity})
def rss_check(): def rss_check():
+1 -1
View File
@@ -82,7 +82,7 @@ class Conf:
# Verify SAVE_LIMIT_PER is valid # Verify SAVE_LIMIT_PER is valid
if SAVE_LIMIT_PER not in ["group", "name", "func", None]: if SAVE_LIMIT_PER not in ["group", "name", "func", None]:
warn(f"SAVE_LIMIT_PER ({SAVE_LIMIT_PER}) is not a valid option. Options are: 'group', 'name', 'func' and None. Default is None.") warn(_("SAVE_LIMIT_PER (%(option)s) is not a valid option. Options are: 'group', 'name', 'func' and None. Default is None.") % {'option': SAVE_LIMIT_PER})
# Guard loop sleep in seconds. Should be between 0 and 60 seconds. # Guard loop sleep in seconds. Should be between 0 and 60 seconds.
GUARD_CYCLE = conf.get("guard_cycle", 0.5) GUARD_CYCLE = conf.get("guard_cycle", 0.5)
+6 -2
View File
@@ -6,7 +6,11 @@ from django.core.signing import BadSignature, JSONSerializer, SignatureExpired
from django.core.signing import Signer as Sgnr from django.core.signing import Signer as Sgnr
from django.core.signing import TimestampSigner as TsS from django.core.signing import TimestampSigner as TsS
from django.core.signing import b64_decode, dumps from django.core.signing import b64_decode, dumps
from django.utils import baseconv try:
from django.core.signing import base62
except ImportError:
# For django < 4.0
from django.utils.baseconv import base62
from django.utils.crypto import constant_time_compare from django.utils.crypto import constant_time_compare
from django.utils.encoding import force_bytes, force_str from django.utils.encoding import force_bytes, force_str
@@ -69,7 +73,7 @@ class TimestampSigner(Signer, TsS):
""" """
result = super(TimestampSigner, self).unsign(value) result = super(TimestampSigner, self).unsign(value)
value, timestamp = result.rsplit(self.sep, 1) value, timestamp = result.rsplit(self.sep, 1)
timestamp = baseconv.base62.decode(timestamp) timestamp = base62.decode(timestamp)
if max_age is not None: if max_age is not None:
if isinstance(max_age, datetime.timedelta): if isinstance(max_age, datetime.timedelta):
max_age = max_age.total_seconds() max_age = max_age.total_seconds()
Binary file not shown.
+276 -236
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-15 15:53+0100\n" "POT-Creation-Date: 2022-11-12 01:47+0000\n"
"PO-Revision-Date: 2018-08-05 18:28+0200\n" "PO-Revision-Date: 2018-08-05 18:28+0200\n"
"Last-Translator: Jonas Winkler\n" "Last-Translator: Jonas Winkler\n"
"Language-Team: \n" "Language-Team: \n"
@@ -17,431 +17,471 @@ msgstr ""
"X-Generator: Poedit 2.1.1\n" "X-Generator: Poedit 2.1.1\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: admin.py:40 #: django_q/admin.py:43
msgid "Resubmit selected tasks to queue" msgid "Resubmit selected tasks to queue"
msgstr "Ausgewählte Aufgaben erneut ausführen" msgstr "Ausgewählte Aufgaben erneut ausführen"
#: brokers/disque.py:59 #: django_q/admin.py:98 django_q/models.py:228
msgid "No Disque nodes configured" #, fuzzy
msgstr "Keine Disque-Knoten konfiguriert" #| msgid "Success"
msgid "success"
msgstr "erfolg"
#: brokers/disque.py:76 #: django_q/admin.py:109 django_q/models.py:230
msgid "Could not connect to any Disque nodes" msgid "last_run"
msgstr "Konnte zu keinem Disque-Knoten verbinden" msgstr ""
#: cluster.py:76 #: django_q/cluster.py:77
#, fuzzy, python-brace-format #, python-format
#| msgid "Q Cluster-{} starting." msgid "Q Cluster %(name)s starting."
msgid "Q Cluster {self.name} starting." msgstr "Q-Cluster %(name)s wird gestartet."
msgstr "Q-Cluster {self.name} wird gestartet."
#: cluster.py:84 #: django_q/cluster.py:85
#, fuzzy, python-brace-format #, fuzzy, python-format
#| msgid "Q Cluster-{} stopping." #| msgid "Q Cluster-{} stopping."
msgid "Q Cluster {self.name} stopping." msgid "Q Cluster %(name)s stopping."
msgstr "Q-Cluster {self.name} wird gestoppt." msgstr "Q-Cluster {name} wird gestoppt."
#: cluster.py:87 #: django_q/cluster.py:88
#, fuzzy, python-brace-format #, python-format
#| msgid "Q Cluster-{} has stopped." msgid "Q Cluster %(name)s has stopped."
msgid "Q Cluster {self.name} has stopped." msgstr "Q-Cluster %(name)s wurde gestoppt."
msgstr "Q-Cluster {self.name} wurde gestoppt."
#: cluster.py:95 #: django_q/cluster.py:96
#, python-format
msgid "%(name)s got signal %(signal)s"
msgstr "%(name)s erhielt das Signal %(signal)s"
#: django_q/cluster.py:219
#, python-format
msgid "reincarnated monitor %(name)s after sudden death"
msgstr "Monitor %(name)s wurde nach unerwartetem Absturz neu gestartet"
#: django_q/cluster.py:222
#, python-format
msgid "reincarnated pusher %(name)s after sudden death"
msgstr "Pusher %(name)s wurde nach unerwartetem Absturz neu gestartet"
#: django_q/cluster.py:229
#, python-format
msgid "reincarnated worker %(name)s after timeout"
msgstr "Worker %(name)s wurde nach Zeitüberschreitung neu gestartet"
#: django_q/cluster.py:231
#, python-format
msgid "recycled worker %(name)s"
msgstr "Worker %(name)s wurde wiederverwendet"
#: django_q/cluster.py:233
#, python-format
msgid "reincarnated worker %(name)s after death"
msgstr "Worker %(name)s wurde nach unerwartetem Absturz neu gestartet"
#: django_q/cluster.py:256
#, python-format
msgid "%(name)s guarding cluster %(cluster_name)s"
msgstr "%(name)s beschützt das Cluster %(cluster_name)s"
#: django_q/cluster.py:261
#, python-format
msgid "Q Cluster %(cluster_name)s running."
msgstr "Q-Cluster %(cluster_name)s läuft."
#: django_q/cluster.py:295
#, python-format
msgid "%(name)s stopping cluster processes"
msgstr "%(name)s hält Cluster-Prozesse an"
#: django_q/cluster.py:320
#, python-format
msgid "%(name)s waiting for the monitor."
msgstr "%(name)s wartet auf den Monitor."
#: django_q/cluster.py:342
#, python-format
msgid "%(process_name)s pushing tasks at %(id)s"
msgstr "%(process_name)s veröffentlicht Aufagaben auf %(id)s"
#: django_q/cluster.py:363
#, python-format
msgid "queueing from %(list_key)s"
msgstr "Einreihen von %(list_key)s"
#: django_q/cluster.py:366
#, python-format
msgid "%(name)s stopped pushing tasks"
msgstr "%(name)s veröffentlicht keine Aufgaben mehr"
#: django_q/cluster.py:378
#, python-format
msgid "%(name)s monitoring at %(id)s"
msgstr "%(name)s beobachtet auf %(id)s"
#: django_q/cluster.py:395
#, python-format
msgid "Processed '%(info_name)s' (%(task_name)s)"
msgstr "[%(task_name)s] - '%(info_name)s' wurde verarbeitet"
#: django_q/cluster.py:398
#, python-format
msgid "Failed '%(info_name)s' (%(task_name)s) - %(task_result)s"
msgstr "'%(info_name)s' (%(task_name)s) ist fehlgeschlagen - %(task_result)s"
#: django_q/cluster.py:399
#, python-format
msgid "%(name)s stopped monitoring results"
msgstr "%(name)s überwacht keine Ergebnisse mehr"
#: django_q/cluster.py:413
#, python-format
msgid "%(proc_name)s ready for work at %(id)s"
msgstr "%(proc_name)s ist bereit für Arbeit auf %(id)s"
#: django_q/cluster.py:425
#, python-format
msgid "%(proc_name)s processing '%(func_name)s' (%(task_name)s)"
msgstr "%(proc_name)s verarbeitet '%(func_name)s' (%(task_name)s)"
#: django_q/cluster.py:440
#, python-format
msgid "" msgid ""
"{current_process().name} got signal {Conf.SIGNAL_NAMES.get(signum, \"UNKNOWN" "Could not process '%(func_name)s'. Check the location of the function and "
"\")}" "the args/kwargs."
msgstr "" msgstr ""
"{current_process().name} erhielt das Signal {Conf.SIGNAL_NAMES.get(signum, " "Konnte '%(func_name)s' nicht verarbeiten. Überprüfen Sie den Ort der "
"\"UNKNOWN\")}" "Funktion und die args/kwargs."
#: cluster.py:216 #: django_q/cluster.py:456
#, fuzzy, python-brace-format #, python-format
#| msgid "reincarnated monitor {} after sudden death" msgid "%(proc_name)s stopped doing work"
msgid "reincarnated monitor {process.name} after sudden death" msgstr "%(proc_name)s hat die Arbeit beendet"
msgstr "Monitor {process.name} wurde nach unerwartetem Absturz neu gestartet"
#: cluster.py:219 #: django_q/cluster.py:649 django_q/models.py:144
#, fuzzy, python-brace-format
#| msgid "reincarnated pusher {} after sudden death"
msgid "reincarnated pusher {process.name} after sudden death"
msgstr "Pusher {process.name} wurde nach unerwartetem Absturz neu gestartet"
#: cluster.py:226
#, fuzzy, python-brace-format
#| msgid "reincarnated worker {} after timeout"
msgid "reincarnated worker {process.name} after timeout"
msgstr "Worker {process.name} wurde nach Zeitüberschreitung neu gestartet"
#: cluster.py:228
#, fuzzy, python-brace-format
#| msgid "recycled worker {}"
msgid "recycled worker {process.name}"
msgstr "Worker {process.name} wurde wiederverwendet"
#: cluster.py:230
#, fuzzy, python-brace-format
#| msgid "reincarnated worker {} after death"
msgid "reincarnated worker {process.name} after death"
msgstr "Worker {process.name} wurde nach unerwartetem Absturz neu gestartet"
#: cluster.py:251
msgid ""
"{current_process().name} guarding cluster {humanize(self.cluster_id.hex)}"
msgstr ""
"{current_process().name} beschützt das Cluster {humanize(self.cluster_id."
"hex)}"
#: cluster.py:256
msgid "Q Cluster {humanize(self.cluster_id.hex)} running."
msgstr "Q-Cluster {humanize(self.cluster_id.hex)} ist bereit."
#: cluster.py:290
#, fuzzy, python-brace-format
#| msgid "{} stopping cluster processes"
msgid "{name} stopping cluster processes"
msgstr "{name} hält Cluster-Prozesse an"
#: cluster.py:315
#, fuzzy, python-brace-format
#| msgid "{} waiting for the monitor."
msgid "{name} waiting for the monitor."
msgstr "{name} wartet auf den Monitor."
#: cluster.py:337
msgid "{current_process().name} pushing tasks at {current_process().pid}"
msgstr ""
"{current_process().name} veröffentlicht Aufagaben auf {current_process().pid}"
#: cluster.py:358
#, fuzzy, python-brace-format
#| msgid "queueing from {}"
msgid "queueing from {broker.list_key}"
msgstr "Einreihen von {broker.list_key}"
#: cluster.py:361
#, fuzzy
#| msgid "{} stopped pushing tasks"
msgid "{current_process().name} stopped pushing tasks"
msgstr "{current_process().name} veröffentlicht keine Aufgaben mehr"
#: cluster.py:373
#, fuzzy
#| msgid "{} monitoring at {}"
msgid "{name} monitoring at {current_process().pid}"
msgstr "{name} beobachtet auf {current_process().pid}"
#: cluster.py:387
#, fuzzy
#| msgid "Processed [{}]"
msgid "Processed [{task['name']}]"
msgstr "[{task['name']}] wurde verarbeitet"
#: cluster.py:390
msgid "Failed [{task['name']}] - {task['result']}"
msgstr "[{task['name']}] ist fehlgeschlagen - {task['result']}"
#: cluster.py:391
#, fuzzy, python-brace-format
#| msgid "{} stopped monitoring results"
msgid "{name} stopped monitoring results"
msgstr "{name} überwacht keine Ergebnisse mehr"
#: cluster.py:405
#, fuzzy
#| msgid "{} ready for work at {}"
msgid "{name} ready for work at {current_process().pid}"
msgstr "{name} ist bereit für Arbeit auf {current_process().pid}"
#: cluster.py:415
#, fuzzy
#| msgid "{} processing [{}]"
msgid "{name} processing [{task[\"name\"]}]"
msgstr "{name} verarbeitet [{task[\"name\"]}]"
#: cluster.py:455
#, fuzzy, python-brace-format
#| msgid "{} stopped doing work"
msgid "{name} stopped doing work"
msgstr "{name} hat die Arbeit beendet"
#: cluster.py:619 models.py:143
msgid "Please install croniter to enable cron expressions" msgid "Please install croniter to enable cron expressions"
msgstr "Bitte installieren Sie croniter, um Cron-Ausdrücke zu aktivieren" msgstr "Bitte installieren Sie croniter, um Cron-Ausdrücke zu aktivieren"
#: cluster.py:644 #: django_q/cluster.py:672
#, fuzzy #, python-format
#| msgid "{} failed to create a task from schedule [{}]" msgid "%(process_name)s failed to create a task from schedule [%(schedule)s]"
msgid ""
"{current_process().name} failed to create a task from schedule [{s.name or s."
"id}]"
msgstr "" msgstr ""
"{current_process().name} konnte keine Aufgabe von Zeitplan [{s.name or s." "%(process_name)s konnte keine Aufgabe von Zeitplan [%(schedule)s] erstellen"
"id}] erstellen"
#: cluster.py:650 #: django_q/cluster.py:678
#, fuzzy #, python-format
#| msgid "{} created a task from schedule [{}]" msgid "%(process_name)s created a task from schedule [%(schedule)s]"
msgid ""
"{current_process().name} created a task from schedule [{s.name or s.id}]"
msgstr "" msgstr ""
"{current_process().name} hat eine Aufgabe des Zeitplans [{s.name or s.id}] " "%(process_name)s hat eine Aufgabe des Zeitplans [%(schedule)s] erstellt"
"erstellt"
#: cluster.py:716 #: django_q/cluster.py:718
#, fuzzy, python-brace-format msgid "Skipping cpu affinity because psutil was not found."
#| msgid "{} will use cpu {}" msgstr "Cpu-Affinität wird übersprungen, da psutil nicht gefunden wurde."
msgid "{pid} will use cpu {affinity}"
msgstr "{pid} wird CPU {affinity} benutzen" #: django_q/cluster.py:723
msgid "Faking cpu affinity because it is not supported on this platform"
msgstr ""
"Vortäuschen von CPU-Affinität, da diese auf dieser Plattform nicht "
"unterstützt wird"
#: django_q/cluster.py:744
#, python-format
msgid "%(pid)s will use cpu %(affinity)s"
msgstr "%(pid)s wird CPU %(affinity)s benutzen"
#: django_q/conf.py:85
#, python-format
msgid ""
"SAVE_LIMIT_PER (%(option)s) is not a valid option. Options are: 'group', "
"'name', 'func' and None. Default is None."
msgstr ""
"SAVE_LIMIT_PER (%(option)s) ist keine gültige Option. Optionen sind: "
"'group', 'name', 'func' und None. Standard ist None."
#. Translators: Cluster status descriptions #. Translators: Cluster status descriptions
#: conf.py:184 #: django_q/conf.py:194
msgid "Starting" msgid "Starting"
msgstr "Wird gestartet" msgstr "Wird gestartet"
#: conf.py:185 #: django_q/conf.py:195
msgid "Working" msgid "Working"
msgstr "Arbeitet" msgstr "Arbeitet"
#: conf.py:186 #: django_q/conf.py:196
msgid "Idle" msgid "Idle"
msgstr "Leerlauf" msgstr "Leerlauf"
#: conf.py:187 #: django_q/conf.py:197
msgid "Stopped" msgid "Stopped"
msgstr "Gestoppt" msgstr "Gestoppt"
#: conf.py:188 #: django_q/conf.py:198
msgid "Stopping" msgid "Stopping"
msgstr "Wird gestoppt" msgstr "Wird gestoppt"
#. Translators: help text for qcluster management command #. Translators: help text for qcluster management command
#: management/commands/qcluster.py:9 #: django_q/management/commands/qcluster.py:9
msgid "Starts a Django Q Cluster." msgid "Starts a Django Q Cluster."
msgstr "Startet ein Django-Q-Cluster." msgstr "Startet ein Django-Q-Cluster."
#. Translators: help text for qinfo management command #. Translators: help text for qinfo management command
#: management/commands/qinfo.py:11 #: django_q/management/commands/qinfo.py:11
msgid "General information over all clusters." msgid "General information over all clusters."
msgstr "Allgemeine Informationen über alle Cluster" msgstr "Allgemeine Informationen über alle Cluster"
#. Translators: help text for qmemory management command
#: django_q/management/commands/qmemory.py:9
msgid "Monitors Q Cluster memory usage"
msgstr "Überwacht die Speichernutzung von Q Cluster"
#. Translators: help text for qmonitor management command #. Translators: help text for qmonitor management command
#: management/commands/qmonitor.py:9 #: django_q/management/commands/qmonitor.py:9
msgid "Monitors Q Cluster activity" msgid "Monitors Q Cluster activity"
msgstr "Q-Cluster aktiv überwachen" msgstr "Q-Cluster aktiv überwachen"
#: models.py:118 #: django_q/models.py:119
msgid "Successful task" msgid "Successful task"
msgstr "Erfolgreiche Aufgabe" msgstr "Erfolgreiche Aufgabe"
#: models.py:119 #: django_q/models.py:120
msgid "Successful tasks" msgid "Successful tasks"
msgstr "Erfolgreiche Aufgaben" msgstr "Erfolgreiche Aufgaben"
#: models.py:134 #: django_q/models.py:135
msgid "Failed task" msgid "Failed task"
msgstr "Fehlgeschlagene Aufgabe" msgstr "Fehlgeschlagene Aufgabe"
#: models.py:135 #: django_q/models.py:136
msgid "Failed tasks" msgid "Failed tasks"
msgstr "Fehlgeschlagene Aufgaben" msgstr "Fehlgeschlagene Aufgaben"
#: models.py:159 #: django_q/models.py:160
msgid "e.g. 1, 2, 'John'" msgid "e.g. 1, 2, 'John'"
msgstr "zum Beispiel 1, 2, 'John'" msgstr "zum Beispiel 1, 2, 'John'"
#: models.py:161 #: django_q/models.py:162
msgid "e.g. x=1, y=2, name='John'" msgid "e.g. x=1, y=2, name='John'"
msgstr "zum Beispiel x=1, y=2, name='John'" msgstr "zum Beispiel x=1, y=2, name='John'"
#: models.py:173 #: django_q/models.py:176
msgid "Once" msgid "Once"
msgstr "Einmal" msgstr "Einmal"
#: models.py:174 #: django_q/models.py:177
msgid "Minutes" msgid "Minutes"
msgstr "Minuten" msgstr "Minuten"
#: models.py:175 #: django_q/models.py:178
msgid "Hourly" msgid "Hourly"
msgstr "Stündlich" msgstr "Stündlich"
#: models.py:176 #: django_q/models.py:179
msgid "Daily" msgid "Daily"
msgstr "Täglich" msgstr "Täglich"
#: models.py:177 #: django_q/models.py:180
msgid "Weekly" msgid "Weekly"
msgstr "Wöchentlich" msgstr "Wöchentlich"
#: models.py:178 #: django_q/models.py:181
msgid "Biweekly"
msgstr "Zweiwöchentlich"
#: django_q/models.py:182
msgid "Monthly" msgid "Monthly"
msgstr "Monatlich" msgstr "Monatlich"
#: models.py:179 #: django_q/models.py:183
msgid "Bimonthly"
msgstr "Zweimonatlich"
#: django_q/models.py:184
msgid "Quarterly" msgid "Quarterly"
msgstr "Vierteljährlich" msgstr "Vierteljährlich"
#: models.py:180 #: django_q/models.py:185
msgid "Yearly" msgid "Yearly"
msgstr "Jährlich" msgstr "Jährlich"
#: models.py:181 #: django_q/models.py:186
msgid "Cron" msgid "Cron"
msgstr "Cron" msgstr "Cron"
#: models.py:184 #: django_q/models.py:189
msgid "Schedule Type" msgid "Schedule Type"
msgstr "Zeitplan-Typ" msgstr "Zeitplan-Typ"
#: models.py:187 #: django_q/models.py:192
msgid "Number of minutes for the Minutes type" msgid "Number of minutes for the Minutes type"
msgstr "Anzahl Minuten für den Typ 'Minuten'" msgstr "Anzahl Minuten für den Typ 'Minuten'"
#: models.py:190 #: django_q/models.py:195
msgid "Repeats" msgid "Repeats"
msgstr "Wiederhohlungen" msgstr "Wiederhohlungen"
#: models.py:190 #: django_q/models.py:195
msgid "n = n times, -1 = forever" msgid "n = n times, -1 = forever"
msgstr "n = n mal, -1 = für immer" msgstr "n = n mal, -1 = für immer"
#: models.py:193 #: django_q/models.py:198
msgid "Next Run" msgid "Next Run"
msgstr "Nächste Ausführung" msgstr "Nächste Ausführung"
#: models.py:200 #: django_q/models.py:205
msgid "Cron expression" msgid "Cron expression"
msgstr "Cron-Ausdruck" msgstr "Cron-Ausdruck"
#: models.py:226 #: django_q/models.py:235
msgid "Scheduled task" msgid "Scheduled task"
msgstr "Geplante Aufgabe" msgstr "Geplante Aufgabe"
#: models.py:227 #: django_q/models.py:236
msgid "Scheduled tasks" msgid "Scheduled tasks"
msgstr "Geplante Aufgaben" msgstr "Geplante Aufgaben"
#: models.py:250 #: django_q/models.py:262
msgid "Queued task" msgid "Queued task"
msgstr "Eingereihte Aufgabe" msgstr "Eingereihte Aufgabe"
#: models.py:251 #: django_q/models.py:263
msgid "Queued tasks" msgid "Queued tasks"
msgstr "Eingereihte Aufgaben" msgstr "Eingereihte Aufgaben"
#: monitor.py:35 #: django_q/monitor.py:62 django_q/monitor.py:339
msgid "Host" msgid "Host"
msgstr "Host" msgstr "Host"
#: monitor.py:39 #: django_q/monitor.py:66 django_q/monitor.py:343 django_q/monitor.py:450
msgid "Id" msgid "Id"
msgstr "Id" msgstr "Id"
#: monitor.py:43 #: django_q/monitor.py:70
msgid "State" msgid "State"
msgstr "Status" msgstr "Status"
#: monitor.py:47 #: django_q/monitor.py:74
msgid "Pool" msgid "Pool"
msgstr "Pool" msgstr "Pool"
#: monitor.py:51 #: django_q/monitor.py:78
msgid "TQ" msgid "TQ"
msgstr "TQ" msgstr "TQ"
#: monitor.py:55 #: django_q/monitor.py:82
msgid "RQ" msgid "RQ"
msgstr "RQ" msgstr "RQ"
#: monitor.py:59 #: django_q/monitor.py:86
msgid "RC" msgid "RC"
msgstr "RC" msgstr "RC"
#: monitor.py:63 #: django_q/monitor.py:90
msgid "Up" msgid "Up"
msgstr "Up" msgstr "Up"
#: monitor.py:143 monitor.py:247 #: django_q/monitor.py:170 django_q/monitor.py:279
msgid "Queued" msgid "Queued"
msgstr "Eingereiht" msgstr "Eingereiht"
#: monitor.py:151 #: django_q/monitor.py:178
msgid "Success" msgid "Success"
msgstr "Erfolg" msgstr "Erfolg"
#: monitor.py:161 monitor.py:255 #: django_q/monitor.py:188 django_q/monitor.py:287
msgid "Failures" msgid "Failures"
msgstr "Fehlschläge" msgstr "Fehlschläge"
#: monitor.py:172 #: django_q/monitor.py:199 django_q/monitor.py:485
msgid "[Press q to quit]" msgid "[Press q to quit]"
msgstr "[Drücken Sie q zum Beenden]" msgstr "[Drücken Sie q zum Beenden]"
#: monitor.py:191 #: django_q/monitor.py:223
msgid "day" msgid "day"
msgstr "Tag" msgstr "Tag"
#: monitor.py:212 #: django_q/monitor.py:244
msgid "second" msgid "second"
msgstr "Sekunde" msgstr "Sekunde"
#: monitor.py:215 #: django_q/monitor.py:247
msgid "minute" msgid "minute"
msgstr "Minute" msgstr "Minute"
#: monitor.py:218 #: django_q/monitor.py:250
msgid "hour" msgid "hour"
msgstr "Stunde" msgstr "Stunde"
#: monitor.py:228 #: django_q/monitor.py:260
msgid "" #, python-format
"-- {Conf.PREFIX.capitalize()} { \".\".join(str(v) for v in VERSION)} on " msgid "-- %(prefix)s %(version)s on %(info)s --"
"{broker.info()} --" msgstr "-- %(prefix)s %(version)s auf %(info)s --"
msgstr ""
"-- {Conf.PREFIX.capitalize()} { \".\".join(str(v) for v in VERSION)} auf "
"{broker.info()} --"
#: monitor.py:234 #: django_q/monitor.py:266
msgid "Clusters" msgid "Clusters"
msgstr "Cluster" msgstr "Cluster"
#: monitor.py:238 #: django_q/monitor.py:270
msgid "Workers" msgid "Workers"
msgstr "Arbeiter" msgstr "Arbeiter"
#: monitor.py:242 #: django_q/monitor.py:274
msgid "Restarts" msgid "Restarts"
msgstr "Neustarts" msgstr "Neustarts"
#: monitor.py:251 #: django_q/monitor.py:283
msgid "Successes" msgid "Successes"
msgstr "Erfolge" msgstr "Erfolge"
#: monitor.py:260 #: django_q/monitor.py:292
msgid "Schedules" msgid "Schedules"
msgstr "Zeitpläne" msgstr "Zeitpläne"
#: monitor.py:264 #: django_q/monitor.py:296
#, fuzzy, python-brace-format #, python-format
#| msgid "Tasks/{}" msgid "Tasks/%(per)s"
msgid "Tasks/{per}" msgstr "Aufgaben/%(per)s"
msgstr "Aufgaben/{per}"
#: monitor.py:268 #: django_q/monitor.py:300
msgid "Avg time" msgid "Avg time"
msgstr "Durchschnittl. Zeit" msgstr "Durchschnittl. Zeit"
#: signals.py:22 #: django_q/monitor.py:348
#, fuzzy, python-brace-format msgid "Available (%)"
#| msgid "malformed return hook '{}' for [{}]" msgstr "Verfügbar (%)"
msgid "malformed return hook '{instance.hook}' for [{instance.name}]"
msgstr "Ungültiger Return-Hook '{instance.hook}' für [{instance.name}]"
#: signals.py:30 #: django_q/monitor.py:354
#, fuzzy msgid "Available (MB)"
#| msgid "return hook {} failed on [{}] because {}" msgstr "Verfügbar (MB)"
msgid ""
"return hook {instance.hook} failed on [{instance.name}] because {str(e)}" #: django_q/monitor.py:359
msgstr "" msgid "Total (MB)"
"Return-Hook {instance.hook} für [{instance.name}] ist gescheitert: {str(e)}" msgstr "Insgesamt (MB)"
#: django_q/monitor.py:364
msgid "Sentinel (MB)"
msgstr "Sentinel (MB)"
#: django_q/monitor.py:370
msgid "Monitor (MB)"
msgstr "Monitor (MB)"
#: django_q/monitor.py:376
msgid "Workers (MB)"
msgstr "Arbeiter (MB)"
#: django_q/monitor.py:478
#, python-format
msgid "Available lowest (): %(memory_percent)s ((at)s)"
msgstr "Niedrigste verfügbar (): %(memory_percent)s ((at)s)"
#: django_q/monitor.py:496
msgid "No clusters appear to be running."
msgstr "Es scheinen keine Cluster zu laufen."
#: django_q/signals.py:22
#, python-format
msgid "malformed return hook '%(hook)s' for [%(name)s]"
msgstr "Ungültiger Return-Hook '%(hook)s' für [%(name)s]"
#: django_q/signals.py:30
#, python-format
msgid "return hook %(hook)s failed on [%(name)s] because %(error)s"
msgstr "Return-Hook %(hook)s für [%(name)s] ist gescheitert: %(error)s"
Binary file not shown.
+287 -147
View File
@@ -6,349 +6,489 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-08-05 15:48+0200\n" "POT-Creation-Date: 2022-11-12 01:47+0000\n"
"PO-Revision-Date: 2018-08-05 18:28+0200\n" "PO-Revision-Date: 2018-08-05 18:28+0200\n"
"Last-Translator: Thierry BOULOGNE <contact@tng-concepts.com>\n"
"Language-Team: \n" "Language-Team: \n"
"Language: fr-FR\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.1.1\n" "X-Generator: Poedit 2.1.1\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Last-Translator: Thierry BOULOGNE <contact@tng-concepts.com>\n"
"Language: fr-FR\n"
#: admin.py:48 #: django_q/admin.py:43
msgid "Resubmit selected tasks to queue" msgid "Resubmit selected tasks to queue"
msgstr "Resoumettre les tâches sélectionnées à la file d'attente" msgstr "Resoumettre les tâches sélectionnées à la file d'attente"
#: cluster.py:54 #: django_q/admin.py:98 django_q/models.py:228
msgid "Q Cluster-{} starting." #, fuzzy
msgstr "Démarrage de Q Cluster-{}." #| msgid "Success"
msgid "success"
msgstr "succès"
#: cluster.py:62 #: django_q/admin.py:109 django_q/models.py:230
msgid "Q Cluster-{} stopping." msgid "last_run"
msgstr "Arrêt de Q Cluster-{}." msgstr ""
#: cluster.py:65 #: django_q/cluster.py:77
msgid "Q Cluster-{} has stopped." #, python-format
msgstr "Q Cluster-{} a été arrêté." msgid "Q Cluster %(name)s starting."
msgstr "Démarrage de Q Cluster-%(name)s."
#: cluster.py:71 #: django_q/cluster.py:85
msgid "{} got signal {}" #, python-format
msgstr "{} à reçu le signal {}" msgid "Q Cluster %(name)s stopping."
msgstr "Arrêt de Q Cluster-%(name)s."
#: cluster.py:169 #: django_q/cluster.py:88
msgid "reincarnated monitor {} after sudden death" #, python-format
msgstr "moniteur réintégré {} après un arrêt intempestif" msgid "Q Cluster %(name)s has stopped."
msgstr "Q Cluster-%(name)s a été arrêté."
#: cluster.py:172 #: django_q/cluster.py:96
msgid "reincarnated pusher {} after sudden death" #, python-format
msgstr "pousseur réintégré {} après un arrêt intempestif" msgid "%(name)s got signal %(signal)s"
msgstr "%(name)s à reçu le signal %(signal)s"
#: cluster.py:179 #: django_q/cluster.py:219
msgid "reincarnated worker {} after timeout" #, python-format
msgstr "processus réintégré {} après un arrêt une attente trop longue" msgid "reincarnated monitor %(name)s after sudden death"
msgstr "moniteur réintégré %(name)s après un arrêt intempestif"
#: cluster.py:181 #: django_q/cluster.py:222
msgid "recycled worker {}" #, python-format
msgstr "processus recyclé" msgid "reincarnated pusher %(name)s after sudden death"
msgstr "pousseur réintégré %(name)s après un arrêt intempestif"
#: cluster.py:183 #: django_q/cluster.py:229
msgid "reincarnated worker {} after death" #, python-format
msgstr "processus réintégré {} après arrêt" msgid "reincarnated worker %(name)s after timeout"
msgstr "processus réintégré %(name)s après un arrêt une attente trop longue"
#: cluster.py:202 #: django_q/cluster.py:231
msgid "{} guarding cluster at {}" #, python-format
msgstr "{} surveillance du cluster à {}" msgid "recycled worker %(name)s"
msgstr "processus recyclé %(name)s"
#: cluster.py:205 #: django_q/cluster.py:233
msgid "Q Cluster-{} running." #, python-format
msgstr "Q Cluster-{} en cours d'exécution." msgid "reincarnated worker %(name)s after death"
msgstr "processus réintégré %(name)s après arrêt"
#: cluster.py:239 #: django_q/cluster.py:256
msgid "{} stopping cluster processes" #, python-format
msgstr "{} arrêt des processus de cluster" msgid "%(name)s guarding cluster %(cluster_name)s"
msgstr "%(name)s surveillance du cluster à %(cluster_name)s"
#: cluster.py:264 #: django_q/cluster.py:261
msgid "{} waiting for the monitor." #, python-format
msgstr "{} en attente du moniteur." msgid "Q Cluster %(cluster_name)s running."
msgstr "Démarrage de Q Cluster-%(cluster_name)s."
#: cluster.py:285 #: django_q/cluster.py:295
msgid "{} pushing tasks at {}" #, python-format
msgstr "{} tâche envoyé à {}" msgid "%(name)s stopping cluster processes"
msgstr "%(name)s arrêt des processus de cluster"
#: cluster.py:306 #: django_q/cluster.py:320
msgid "queueing from {}" #, python-format
msgstr "mise en file d'attente de {}" msgid "%(name)s waiting for the monitor."
msgstr "%(name)s en attente du moniteur."
#: cluster.py:309 #: django_q/cluster.py:342
msgid "{} stopped pushing tasks" #, python-format
msgstr "{} a cessé de pousser les tâches" msgid "%(process_name)s pushing tasks at %(id)s"
msgstr "%(process_name)s tâche envoyé à %(id)s"
#: cluster.py:320 #: django_q/cluster.py:363
msgid "{} monitoring at {}" #, python-format
msgstr "{} Surveillance de {}" msgid "queueing from %(list_key)s"
msgstr "mise en file d'attente de %(list_key)s"
#: cluster.py:334 #: django_q/cluster.py:366
msgid "Processed [{}]" #, python-format
msgstr "Traitement de [{}]" msgid "%(name)s stopped pushing tasks"
msgstr "%(name)s a cessé de pousser les tâches"
#: cluster.py:337 #: django_q/cluster.py:378
msgid "Failed [{}] - {}" #, python-format
msgstr "Echec [{}] - {}" msgid "%(name)s monitoring at %(id)s"
msgstr "%(name)s Surveillance de %(id)s"
#: cluster.py:338 #: django_q/cluster.py:395
msgid "{} stopped monitoring results" #, python-format
msgstr "{} arrêt des résultats de surveillance" msgid "Processed '%(info_name)s' (%(task_name)s)"
msgstr "traité '%(info_name)s' (%(task_name)s)"
#: cluster.py:349 #: django_q/cluster.py:398
msgid "{} ready for work at {}" #, python-format
msgstr "{} prêt pour le travail à {}" msgid "Failed '%(info_name)s' (%(task_name)s) - %(task_result)s"
msgstr "Manqué '%(info_name)s' (%(task_name)s) - %(task_result)s"
#: cluster.py:357 #: django_q/cluster.py:399
msgid "{} processing [{}]" #, python-format
msgstr "{} en cours de traitement [{}]" msgid "%(name)s stopped monitoring results"
msgstr "%(name)s arrêt des résultats de surveillance"
#: cluster.py:398 #: django_q/cluster.py:413
msgid "{} stopped doing work" #, python-format
msgstr "{} arrêté de travailler" msgid "%(proc_name)s ready for work at %(id)s"
msgstr "%(proc_name)s prêt pour le travail à %(id)s"
#: cluster.py:543 #: django_q/cluster.py:425
msgid "{} failed to create a task from schedule [{}]" #, python-format
msgstr "{} Echec de la création d'une tâche à partir de Schedule [{}]" msgid "%(proc_name)s processing '%(func_name)s' (%(task_name)s)"
msgstr "%(proc_name)s en traitement '%(func_name)s' (%(task_name)s)"
#: cluster.py:547 #: django_q/cluster.py:440
msgid "{} created a task from schedule [{}]" #, python-format
msgstr "{} a créé une tâche à partir de Schedule [{}]" msgid ""
"Could not process '%(func_name)s'. Check the location of the function and "
"the args/kwargs."
msgstr ""
"Impossible de traiter '%(func_name)s'. Vérifiez l'emplacement de la fonction "
"et les args/kwargs."
#: cluster.py:595 #: django_q/cluster.py:456
msgid "{} will use cpu {}" #, python-format
msgstr "{} utilisera le CPU {}" msgid "%(proc_name)s stopped doing work"
msgstr "%(proc_name)s arrêté de travailler"
#: conf.py:169 #: django_q/cluster.py:649 django_q/models.py:144
msgid "Please install croniter to enable cron expressions"
msgstr "Veuillez installer croniter pour activer les expressions croniques."
#: django_q/cluster.py:672
#, python-format
msgid "%(process_name)s failed to create a task from schedule [%(schedule)s]"
msgstr ""
"%(process_name)s Echec de la création d'une tâche à partir de Schedule "
"[%(schedule)s]"
#: django_q/cluster.py:678
#, python-format
msgid "%(process_name)s created a task from schedule [%(schedule)s]"
msgstr "%(process_name)s a créé une tâche à partir de Schedule [%(schedule)s]"
#: django_q/cluster.py:718
msgid "Skipping cpu affinity because psutil was not found."
msgstr "Sauter l'affinité du processeur parce que psutil n'a pas été trouvé."
#: django_q/cluster.py:723
msgid "Faking cpu affinity because it is not supported on this platform"
msgstr ""
"Simulation de l'affinité du processeur parce qu'elle n'est pas supportée sur "
"cette plateforme."
#: django_q/cluster.py:744
#, python-format
msgid "%(pid)s will use cpu %(affinity)s"
msgstr "%(pid)s utilisera le CPU %(affinity)s"
#: django_q/conf.py:85
#, python-format
msgid ""
"SAVE_LIMIT_PER (%(option)s) is not a valid option. Options are: 'group', "
"'name', 'func' and None. Default is None."
msgstr ""
"SAVE_LIMIT_PER (%(option)s) n'est pas une option valide. Les options sont : "
"'group', 'name', 'func' et None. La valeur par défaut est None."
#. Translators: Cluster status descriptions
#: django_q/conf.py:194
msgid "Starting" msgid "Starting"
msgstr "Démarrage" msgstr "Démarrage"
#: conf.py:170 #: django_q/conf.py:195
msgid "Working" msgid "Working"
msgstr "Actif" msgstr "Actif"
#: conf.py:171 #: django_q/conf.py:196
msgid "Idle" msgid "Idle"
msgstr "En attente" msgstr "En attente"
#: conf.py:172 #: django_q/conf.py:197
msgid "Stopped" msgid "Stopped"
msgstr "Arrêté" msgstr "Arrêté"
#: conf.py:173 #: django_q/conf.py:198
msgid "Stopping" msgid "Stopping"
msgstr "En cours d’arrêt" msgstr "En cours d’arrêt"
#: management/commands/qcluster.py:9 #. Translators: help text for qcluster management command
#: django_q/management/commands/qcluster.py:9
msgid "Starts a Django Q Cluster." msgid "Starts a Django Q Cluster."
msgstr "Démarre un cluster Django Q." msgstr "Démarre un cluster Django Q."
#: management/commands/qinfo.py:11 #. Translators: help text for qinfo management command
#: django_q/management/commands/qinfo.py:11
msgid "General information over all clusters." msgid "General information over all clusters."
msgstr "Informations générales sur tous les clusters." msgstr "Informations générales sur tous les clusters."
#: management/commands/qmonitor.py:9 #. Translators: help text for qmemory management command
#: django_q/management/commands/qmemory.py:9
#, fuzzy
#| msgid "Monitors Q Cluster activity"
msgid "Monitors Q Cluster memory usage"
msgstr "Surveille l'utilisation de la mémoire du cluster Q"
#. Translators: help text for qmonitor management command
#: django_q/management/commands/qmonitor.py:9
msgid "Monitors Q Cluster activity" msgid "Monitors Q Cluster activity"
msgstr "Activité du cluster Moniteur Q" msgstr "Activité du cluster Moniteur Q"
#: models.py:104 #: django_q/models.py:119
msgid "Successful task" msgid "Successful task"
msgstr "Tâche réussie" msgstr "Tâche réussie"
#: models.py:105 #: django_q/models.py:120
msgid "Successful tasks" msgid "Successful tasks"
msgstr "Tâches réussies" msgstr "Tâches réussies"
#: models.py:121 #: django_q/models.py:135
msgid "Failed task" msgid "Failed task"
msgstr "Tâche échoué" msgstr "Tâche échoué"
#: models.py:122 #: django_q/models.py:136
msgid "Failed tasks" msgid "Failed tasks"
msgstr "Tâches échouées" msgstr "Tâches échouées"
#: models.py:131 #: django_q/models.py:160
msgid "e.g. 1, 2, 'John'" msgid "e.g. 1, 2, 'John'"
msgstr "ex. 1, 2, ‘Jean’" msgstr "ex. 1, 2, ‘Jean’"
#: models.py:132 #: django_q/models.py:162
msgid "e.g. x=1, y=2, name='John'" msgid "e.g. x=1, y=2, name='John'"
msgstr "p. ex. x = 1, y = 2, Nom = ‘Jean’" msgstr "p. ex. x = 1, y = 2, Nom = ‘Jean’"
#: models.py:142 #: django_q/models.py:176
msgid "Once" msgid "Once"
msgstr "Une fois" msgstr "Une fois"
#: models.py:143 #: django_q/models.py:177
msgid "Minutes" msgid "Minutes"
msgstr "Minutes" msgstr "Minutes"
#: models.py:144 #: django_q/models.py:178
msgid "Hourly" msgid "Hourly"
msgstr "Toutes les heures" msgstr "Toutes les heures"
#: models.py:145 #: django_q/models.py:179
msgid "Daily" msgid "Daily"
msgstr "Quotidien" msgstr "Quotidien"
#: models.py:146 #: django_q/models.py:180
msgid "Weekly" msgid "Weekly"
msgstr "Hebdomadaire" msgstr "Hebdomadaire"
#: models.py:147 #: django_q/models.py:181
#, fuzzy
#| msgid "Weekly"
msgid "Biweekly"
msgstr "Bihebdomadaire"
#: django_q/models.py:182
msgid "Monthly" msgid "Monthly"
msgstr "Mensuel" msgstr "Mensuel"
#: models.py:148 #: django_q/models.py:183
#, fuzzy
#| msgid "Monthly"
msgid "Bimonthly"
msgstr "Bimestriel"
#: django_q/models.py:184
msgid "Quarterly" msgid "Quarterly"
msgstr "Tous les quart-d’heure" msgstr "Tous les quart-d’heure"
#: models.py:149 #: django_q/models.py:185
msgid "Yearly" msgid "Yearly"
msgstr "Annuel" msgstr "Annuel"
#: models.py:151 #: django_q/models.py:186
msgid "Cron"
msgstr "Cron"
#: django_q/models.py:189
msgid "Schedule Type" msgid "Schedule Type"
msgstr "Type de plannification" msgstr "Type de plannification"
#: models.py:153 #: django_q/models.py:192
msgid "Number of minutes for the Minutes type" msgid "Number of minutes for the Minutes type"
msgstr "Nombre de minutes pour le type de minutes" msgstr "Nombre de minutes pour le type de minutes"
#: models.py:154 #: django_q/models.py:195
msgid "Repeats" msgid "Repeats"
msgstr "Répéter" msgstr "Répéter"
#: models.py:154 #: django_q/models.py:195
msgid "n = n times, -1 = forever" msgid "n = n times, -1 = forever"
msgstr "n = n fois,-1 = Toujours" msgstr "n = n fois,-1 = Toujours"
#: models.py:155 #: django_q/models.py:198
msgid "Next Run" msgid "Next Run"
msgstr "Prochaine exécution" msgstr "Prochaine exécution"
#: models.py:180 #: django_q/models.py:205
msgid "Cron expression"
msgstr "Expression du Cron"
#: django_q/models.py:235
msgid "Scheduled task" msgid "Scheduled task"
msgstr "Tâche planifiée" msgstr "Tâche planifiée"
#: models.py:181 #: django_q/models.py:236
msgid "Scheduled tasks" msgid "Scheduled tasks"
msgstr "Tâches planifiées" msgstr "Tâches planifiées"
#: models.py:204 #: django_q/models.py:262
msgid "Queued task" msgid "Queued task"
msgstr "Tâche en file d'attente" msgstr "Tâche en file d'attente"
#: models.py:205 #: django_q/models.py:263
msgid "Queued tasks" msgid "Queued tasks"
msgstr "Tâches en file d'attente" msgstr "Tâches en file d'attente"
#: monitor.py:33 #: django_q/monitor.py:62 django_q/monitor.py:339
msgid "Host" msgid "Host"
msgstr "Hôte" msgstr "Hôte"
#: monitor.py:34 #: django_q/monitor.py:66 django_q/monitor.py:343 django_q/monitor.py:450
msgid "Id" msgid "Id"
msgstr "Id" msgstr "Id"
#: monitor.py:35 #: django_q/monitor.py:70
msgid "State" msgid "State"
msgstr "Statut" msgstr "Statut"
#: monitor.py:36 #: django_q/monitor.py:74
msgid "Pool" msgid "Pool"
msgstr "Piscine" msgstr "Piscine"
#: monitor.py:37 #: django_q/monitor.py:78
msgid "TQ" msgid "TQ"
msgstr "TQ" msgstr "TQ"
#: monitor.py:38 #: django_q/monitor.py:82
msgid "RQ" msgid "RQ"
msgstr "RQ" msgstr "RQ"
#: monitor.py:39 #: django_q/monitor.py:86
msgid "RC" msgid "RC"
msgstr "RC" msgstr "RC"
#: monitor.py:40 #: django_q/monitor.py:90
msgid "Up" msgid "Up"
msgstr "Haut" msgstr "Haut"
#: monitor.py:90 monitor.py:165 #: django_q/monitor.py:170 django_q/monitor.py:279
msgid "Queued" msgid "Queued"
msgstr "En file d'attente" msgstr "En file d'attente"
#: monitor.py:92 #: django_q/monitor.py:178
msgid "Success" msgid "Success"
msgstr "Succès" msgstr "Succès"
#: monitor.py:95 monitor.py:173 #: django_q/monitor.py:188 django_q/monitor.py:287
msgid "Failures" msgid "Failures"
msgstr "Défaillances" msgstr "Défaillances"
#: monitor.py:101 #: django_q/monitor.py:199 django_q/monitor.py:485
msgid "[Press q to quit]" msgid "[Press q to quit]"
msgstr "[appuyez sur q pour quitter]" msgstr "[appuyez sur q pour quitter]"
#: monitor.py:120 #: django_q/monitor.py:223
msgid "day" msgid "day"
msgstr "jour" msgstr "jour"
#: monitor.py:137 #: django_q/monitor.py:244
msgid "second" msgid "second"
msgstr "seconde" msgstr "seconde"
#: monitor.py:140 #: django_q/monitor.py:247
msgid "minute" msgid "minute"
msgstr "minute" msgstr "minute"
#: monitor.py:143 #: django_q/monitor.py:250
msgid "hour" msgid "hour"
msgstr "heure" msgstr "heure"
#: monitor.py:151 #: django_q/monitor.py:260
msgid "-- {} {} on {} --" #, python-format
msgstr "--{} {} sur {}--" msgid "-- %(prefix)s %(version)s on %(info)s --"
msgstr "--%(prefix)s %(version)s sur %(info)s --"
#: monitor.py:153 #: django_q/monitor.py:266
msgid "Clusters" msgid "Clusters"
msgstr "Grappes" msgstr "Grappes"
#: monitor.py:157 #: django_q/monitor.py:270
msgid "Workers" msgid "Workers"
msgstr "Processus" msgstr "Processus"
#: monitor.py:161 #: django_q/monitor.py:274
msgid "Restarts" msgid "Restarts"
msgstr "Redémarrages" msgstr "Redémarrages"
#: monitor.py:169 #: django_q/monitor.py:283
msgid "Successes" msgid "Successes"
msgstr "Succès" msgstr "Succès"
#: monitor.py:177 #: django_q/monitor.py:292
msgid "Schedules" msgid "Schedules"
msgstr "Planifications" msgstr "Planifications"
#: monitor.py:181 #: django_q/monitor.py:296
msgid "Tasks/{}" #, python-format
msgstr "Tâches/{}" msgid "Tasks/%(per)s"
msgstr "Tâches/%(per)s"
#: monitor.py:185 #: django_q/monitor.py:300
msgid "Avg time" msgid "Avg time"
msgstr "Temps Moyen" msgstr "Temps Moyen"
#: signals.py:21 #: django_q/monitor.py:348
msgid "malformed return hook '{}' for [{}]" msgid "Available (%)"
msgstr "hook de retour mal formé' {} 'pour [{}]" msgstr ""
#: signals.py:26 #: django_q/monitor.py:354
msgid "return hook {} failed on [{}] because {}" msgid "Available (MB)"
msgstr "le crochet de retour {} a échoué sur [{}] parce que {}" msgstr "Disponible sur (MB)"
#: django_q/monitor.py:359
msgid "Total (MB)"
msgstr "Total (MB)"
#: django_q/monitor.py:364
msgid "Sentinel (MB)"
msgstr "Sentinel (MB)"
#: django_q/monitor.py:370
msgid "Monitor (MB)"
msgstr "Monitor (MB)"
#: django_q/monitor.py:376
#, fuzzy
#| msgid "Workers"
msgid "Workers (MB)"
msgstr "Processus (MB)"
#: django_q/monitor.py:478
#, python-format
msgid "Available lowest (): %(memory_percent)s ((at)s)"
msgstr "Disponible le plus bas () : %(memory_percent)s ((at)s)"
#: django_q/monitor.py:496
msgid "No clusters appear to be running."
msgstr "Aucun cluster ne semble être en cours d'exécution."
#: django_q/signals.py:22
#, python-format
msgid "malformed return hook '%(hook)s' for [%(name)s]"
msgstr "hook de retour mal formé' %(hook)s 'pour [%(name)s]"
#: django_q/signals.py:30
#, python-format
msgid "return hook %(hook)s failed on [%(name)s] because %(error)s"
msgstr "le crochet de retour %(hook)s a échoué sur [%(name)s] parce que %(error)s"
+225 -176
View File
@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-06-18 23:55+0300\n" "POT-Creation-Date: 2022-11-12 01:47+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Ethem Güner <ethemguener@gmail.com>\n" "Last-Translator: Ethem Güner <ethemguener@gmail.com>\n"
"Language-Team: \n" "Language-Team: \n"
@@ -17,166 +17,199 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: django_q/admin.py:40
#: django_q/admin.py:43
msgid "Resubmit selected tasks to queue" msgid "Resubmit selected tasks to queue"
msgstr "Seçili işleri kuyruğa tekrar gönder" msgstr "Seçili işleri kuyruğa tekrar gönder"
#: django_q/brokers/disque.py:60 #: django_q/admin.py:98 django_q/models.py:228
msgid "No Disque nodes configured" #, fuzzy
msgstr "Disque nodları konfigüre edilmemiş" #| msgid "Success"
msgid "success"
msgstr "başarılı olanlar"
#: django_q/brokers/disque.py:77 #: django_q/admin.py:109 django_q/models.py:230
msgid "Could not connect to any Disque nodes" msgid "last_run"
msgstr "Herhangi bir Disque noduna bağlanılamadı"
#: django_q/cluster.py:79
#, python-brace-format
msgid "Q Cluster {self.name} starting."
msgstr "Q Cluster {self.name} başlatılıyor."
#: django_q/cluster.py:87
#, python-brace-format
msgid "Q Cluster {self.name} stopping."
msgstr "Q Cluster {self.name} durduruluyor."
#: django_q/cluster.py:90
#, python-brace-format
msgid "Q Cluster {self.name} has stopped."
msgstr "Q Cluster {self.name} durduruldu."
#: django_q/cluster.py:98
msgid ""
"{current_process().name} got signal {Conf.SIGNAL_NAMES.get(signum, \"UNKNOWN"
"\")}"
msgstr "" msgstr ""
"{current_process().name} şu sinyali aldı {Conf.SIGNAL_NAMES.get(signum, \"UNKNOWN"
"\")}"
#: django_q/cluster.py:220 #: django_q/cluster.py:77
#, python-brace-format #, python-format
msgid "reincarnated monitor {process.name} after sudden death" msgid "Q Cluster %(name)s starting."
msgstr "Monitor {process.name} ani ölüm sonrası tekrar dirildi" msgstr "Q Cluster %(name)s başlatılıyor."
#: django_q/cluster.py:223 #: django_q/cluster.py:85
#, python-brace-format #, python-format
msgid "reincarnated pusher {process.name} after sudden death" msgid "Q Cluster %(name)s stopping."
msgstr "Pusher {process.name} ani ölüm sonrası tekrar dirildi" msgstr "Q Cluster %(name)s durduruluyor."
#: django_q/cluster.py:230 #: django_q/cluster.py:88
#, python-brace-format #, python-format
msgid "reincarnated worker {process.name} after timeout" msgid "Q Cluster %(name)s has stopped."
msgstr "Worker {process.name} zaman aşımı sonrası tekrar dirildi" msgstr "Q Cluster %(name)s durduruldu."
#: django_q/cluster.py:232 #: django_q/cluster.py:96
#, python-brace-format #, python-format
msgid "recycled worker {process.name}" msgid "%(name)s got signal %(signal)s"
msgstr "Worker {process.name} geri döndürüldü" msgstr "%(name)s, %(signal)s pid'inde izleniyor/monitoring yapılıyor."
#: django_q/cluster.py:234 #: django_q/cluster.py:219
#, python-brace-format #, python-format
msgid "reincarnated worker {process.name} after death" msgid "reincarnated monitor %(name)s after sudden death"
msgstr "Worker {process.name} ani ölüm sonrası tekrar dirildi" msgstr "Monitor %(name)s ani ölüm sonrası tekrar dirildi"
#: django_q/cluster.py:222
#, python-format
msgid "reincarnated pusher %(name)s after sudden death"
msgstr "Pusher %(name)s ani ölüm sonrası tekrar dirildi"
#: django_q/cluster.py:229
#, python-format
msgid "reincarnated worker %(name)s after timeout"
msgstr "Worker %(name)s zaman aşımı sonrası tekrar dirildi"
#: django_q/cluster.py:231
#, python-format
msgid "recycled worker %(name)s"
msgstr "Worker %(name)s geri döndürüldü"
#: django_q/cluster.py:233
#, python-format
msgid "reincarnated worker %(name)s after death"
msgstr "Worker %(name)s ani ölüm sonrası tekrar dirildi"
#: django_q/cluster.py:256 #: django_q/cluster.py:256
msgid "" #, python-format
"{current_process().name} guarding cluster {humanize(self.cluster_id.hex)}" msgid "%(name)s guarding cluster %(cluster_name)s"
msgstr "{current_process().name}, {humanize(self.cluster_id.hex)} cluster'ını koruyor" msgstr "%(name)s, %(cluster_name)s cluster'ını koruyor"
#: django_q/cluster.py:261 #: django_q/cluster.py:261
msgid "Q Cluster {humanize(self.cluster_id.hex)} running." #, python-format
msgstr "Q Cluster {humanize(self.cluster_id.hex)} çalışıyor." msgid "Q Cluster %(cluster_name)s running."
msgstr "Q Cluster %(cluster_name)s başlatılıyor."
#: django_q/cluster.py:295 #: django_q/cluster.py:295
#, python-brace-format #, python-format
msgid "{name} stopping cluster processes" msgid "%(name)s stopping cluster processes"
msgstr "Cluster {name} işlemleri durduruluyor." msgstr "Cluster %(name)s işlemleri durduruluyor."
#: django_q/cluster.py:320 #: django_q/cluster.py:320
#, python-brace-format #, python-format
msgid "{name} waiting for the monitor." msgid "%(name)s waiting for the monitor."
msgstr "{name} monitor için bekliyor." msgstr "%(name)s monitor için bekliyor."
#: django_q/cluster.py:342 #: django_q/cluster.py:342
msgid "{current_process().name} pushing tasks at {current_process().pid}" #, python-format
msgstr "{current_process().name, işleri {current_process().pid} pid'ine gönderiyor." msgid "%(process_name)s pushing tasks at %(id)s"
msgstr "%(process_name)s, işleri %(id)s pid'ine gönderiyor."
#: django_q/cluster.py:363 #: django_q/cluster.py:363
#, python-brace-format #, python-format
msgid "queueing from {broker.list_key}" msgid "queueing from %(list_key)s"
msgstr "" msgstr ""
#: django_q/cluster.py:366 #: django_q/cluster.py:366
msgid "{current_process().name} stopped pushing tasks" #, python-format
msgstr "{current_process().name} işleri göndermeyi durdurdu" msgid "%(name)s stopped pushing tasks"
msgstr "%(name)s işleri göndermeyi durdurdu"
#: django_q/cluster.py:378 #: django_q/cluster.py:378
msgid "{name} monitoring at {current_process().pid}" #, python-format
msgstr "{name}, {current_process().pid} pid'inde izleniyor/monitoring yapılıyor." msgid "%(name)s monitoring at %(id)s"
msgstr "%(name)s, %(id)s pid'inde izleniyor/monitoring yapılıyor."
#: django_q/cluster.py:394 #: django_q/cluster.py:395
msgid "Processed [{task['name']}]" #, python-format
msgstr "[{task['name']}] işlendi." msgid "Processed '%(info_name)s' (%(task_name)s)"
msgstr "[%(task_name)s] - '%(info_name)s işlendi."
#: django_q/cluster.py:397
msgid "Failed [{task['name']}] - {task['result']}"
msgstr "[{task['name']}] - {task['result']} başarısız oldu"
#: django_q/cluster.py:398 #: django_q/cluster.py:398
#, python-brace-format #, python-format
msgid "{name} stopped monitoring results" msgid "Failed '%(info_name)s' (%(task_name)s) - %(task_result)s"
msgstr "{name} sonuçları göstermeyi bıraktı" msgstr "[%(task_name)s] - '%(info_name)s' - %(task_result)s başarısız oldu"
#: django_q/cluster.py:412 #: django_q/cluster.py:399
msgid "{name} ready for work at {current_process().pid}" #, python-format
msgstr "{name}, {current_process().pid} pid'inde çalışmaya hazır" msgid "%(name)s stopped monitoring results"
msgstr "%(name)s sonuçları göstermeyi bıraktı"
#: django_q/cluster.py:422 #: django_q/cluster.py:413
msgid "{name} processing [{task[\"name\"]}]" #, python-format
msgstr "{name}, [{task[\"name\"]}] işlerini işiyor" msgid "%(proc_name)s ready for work at %(id)s"
msgstr "%(proc_name)s, %(id)s pid'inde çalışmaya hazır"
#: django_q/cluster.py:453 #: django_q/cluster.py:425
#, python-brace-format #, python-format
msgid "{name} stopped doing work" msgid "%(proc_name)s processing '%(func_name)s' (%(task_name)s)"
msgstr "{name} çalışmayı bıraktı" msgstr "%(proc_name)s, '%(func_name)s' [%(task_name)s] işlerini işiyor"
#: django_q/cluster.py:635 django_q/models.py:143 #: django_q/cluster.py:440
#, python-format
msgid ""
"Could not process '%(func_name)s'. Check the location of the function and "
"the args/kwargs."
msgstr ""
"%(func_name)s' işlenemedi. İşlevin konumunu ve args/kwargs öğelerini kontrol "
"edin."
#: django_q/cluster.py:456
#, python-format
msgid "%(proc_name)s stopped doing work"
msgstr "%(proc_name)s çalışmayı bıraktı"
#: django_q/cluster.py:649 django_q/models.py:144
msgid "Please install croniter to enable cron expressions" msgid "Please install croniter to enable cron expressions"
msgstr "Cron expressions'ları açmak için croniter yükleyin" msgstr "Cron expressions'ları açmak için croniter yükleyin"
#: django_q/cluster.py:665 #: django_q/cluster.py:672
msgid "" #, python-format
"{current_process().name} failed to create a task from schedule [{s.name or s." msgid "%(process_name)s failed to create a task from schedule [%(schedule)s]"
"id}]" msgstr "%(process_name)s programdan bir görev oluşturamadı [%(schedule)s]"
msgstr ""
#: django_q/cluster.py:671 #: django_q/cluster.py:678
msgid "" #, python-format
"{current_process().name} created a task from schedule [{s.name or s.id}]" msgid "%(process_name)s created a task from schedule [%(schedule)s]"
msgstr "" msgstr "%(process_name)s programdan bir görev oluşturamadı [%(schedule)s]"
#: django_q/cluster.py:737 #: django_q/cluster.py:718
#, python-brace-format msgid "Skipping cpu affinity because psutil was not found."
msgid "{pid} will use cpu {affinity}" msgstr "Psutil bulunamadığı için cpu benzeşimi atlanıyor."
#: django_q/cluster.py:723
msgid "Faking cpu affinity because it is not supported on this platform"
msgstr "Bu platformda desteklenmediği için sahte cpu benzeşimi"
#: django_q/cluster.py:744
#, python-format
msgid "%(pid)s will use cpu %(affinity)s"
msgstr "%(pid)s cpu %(affinity)s kullanacaktır"
#: django_q/conf.py:85
#, python-format
msgid ""
"SAVE_LIMIT_PER (%(option)s) is not a valid option. Options are: 'group', "
"'name', 'func' and None. Default is None."
msgstr "" msgstr ""
"SAVE_LIMIT_PER (%(option)s) geçerli bir seçenek değil. Seçenekler şunlardır: "
"'group', 'name', 'func' ve None. Varsayılan değer None'dır."
#. Translators: Cluster status descriptions #. Translators: Cluster status descriptions
#: django_q/conf.py:196 #: django_q/conf.py:194
msgid "Starting" msgid "Starting"
msgstr "Başlıyor" msgstr "Başlıyor"
#: django_q/conf.py:197 #: django_q/conf.py:195
msgid "Working" msgid "Working"
msgstr "Çalışıyor" msgstr "Çalışıyor"
#: django_q/conf.py:198 #: django_q/conf.py:196
msgid "Idle" msgid "Idle"
msgstr "Boşta" msgstr "Boşta"
#: django_q/conf.py:199 #: django_q/conf.py:197
msgid "Stopped" msgid "Stopped"
msgstr "Durdu" msgstr "Durdu"
#: django_q/conf.py:200 #: django_q/conf.py:198
msgid "Stopping" msgid "Stopping"
msgstr "Durduruluyor" msgstr "Durduruluyor"
@@ -200,239 +233,255 @@ msgstr "Q Cluster'ın bellek kullanımını izler"
msgid "Monitors Q Cluster activity" msgid "Monitors Q Cluster activity"
msgstr "Q Cluster'ın aktivitelerini izler" msgstr "Q Cluster'ın aktivitelerini izler"
#: django_q/models.py:118 #: django_q/models.py:119
msgid "Successful task" msgid "Successful task"
msgstr "Başarılı iş" msgstr "Başarılı iş"
#: django_q/models.py:119 #: django_q/models.py:120
msgid "Successful tasks" msgid "Successful tasks"
msgstr "Başarılı işler" msgstr "Başarılı işler"
#: django_q/models.py:134 #: django_q/models.py:135
msgid "Failed task" msgid "Failed task"
msgstr "Başarısız iş" msgstr "Başarısız iş"
#: django_q/models.py:135 #: django_q/models.py:136
msgid "Failed tasks" msgid "Failed tasks"
msgstr "Başarısız işler" msgstr "Başarısız işler"
#: django_q/models.py:159 #: django_q/models.py:160
msgid "e.g. 1, 2, 'John'" msgid "e.g. 1, 2, 'John'"
msgstr "Örneğin: 1, 2, 'Melih'" msgstr "Örneğin: 1, 2, 'Melih'"
#: django_q/models.py:161 #: django_q/models.py:162
msgid "e.g. x=1, y=2, name='John'" msgid "e.g. x=1, y=2, name='John'"
msgstr "Örneğin: x=1, y=2, name='Melih'" msgstr "Örneğin: x=1, y=2, name='Melih'"
#: django_q/models.py:173 #: django_q/models.py:176
msgid "Once" msgid "Once"
msgstr "Bir kere" msgstr "Bir kere"
#: django_q/models.py:174 #: django_q/models.py:177
msgid "Minutes" msgid "Minutes"
msgstr "Dakika" msgstr "Dakika"
#: django_q/models.py:175 #: django_q/models.py:178
msgid "Hourly" msgid "Hourly"
msgstr "Saatlik" msgstr "Saatlik"
#: django_q/models.py:176 #: django_q/models.py:179
msgid "Daily" msgid "Daily"
msgstr "Günlük" msgstr "Günlük"
#: django_q/models.py:177 #: django_q/models.py:180
msgid "Weekly" msgid "Weekly"
msgstr "Haftalık" msgstr "Haftalık"
#: django_q/models.py:178 #: django_q/models.py:181
#, fuzzy
#| msgid "Weekly"
msgid "Biweekly"
msgstr "İki haftada bir"
#: django_q/models.py:182
msgid "Monthly" msgid "Monthly"
msgstr "Aylık" msgstr "Aylık"
#: django_q/models.py:179 #: django_q/models.py:183
#, fuzzy
#| msgid "Monthly"
msgid "Bimonthly"
msgstr "İki ayda bir"
#: django_q/models.py:184
msgid "Quarterly" msgid "Quarterly"
msgstr "Bir Çeyrek (3 Ay)" msgstr "Bir Çeyrek (3 Ay)"
#: django_q/models.py:180 #: django_q/models.py:185
msgid "Yearly" msgid "Yearly"
msgstr "Yıllık" msgstr "Yıllık"
#: django_q/models.py:181 #: django_q/models.py:186
msgid "Cron" msgid "Cron"
msgstr "" msgstr ""
#: django_q/models.py:184 #: django_q/models.py:189
msgid "Schedule Type" msgid "Schedule Type"
msgstr "Zamanlama Tipi" msgstr "Zamanlama Tipi"
#: django_q/models.py:187 #: django_q/models.py:192
msgid "Number of minutes for the Minutes type" msgid "Number of minutes for the Minutes type"
msgstr "Dakika tipine göre dakika sayısı" msgstr "Dakika tipine göre dakika sayısı"
#: django_q/models.py:190 #: django_q/models.py:195
msgid "Repeats" msgid "Repeats"
msgstr "Tekrar eder" msgstr "Tekrar eder"
#: django_q/models.py:190 #: django_q/models.py:195
msgid "n = n times, -1 = forever" msgid "n = n times, -1 = forever"
msgstr "n = n kere, -1 = sonsuza kadar" msgstr "n = n kere, -1 = sonsuza kadar"
#: django_q/models.py:193 #: django_q/models.py:198
msgid "Next Run" msgid "Next Run"
msgstr "Bir dahaki çalışma tarihi" msgstr "Bir dahaki çalışma tarihi"
#: django_q/models.py:200 #: django_q/models.py:205
msgid "Cron expression" msgid "Cron expression"
msgstr "" msgstr ""
#: django_q/models.py:227 #: django_q/models.py:235
msgid "Scheduled task" msgid "Scheduled task"
msgstr "Zamanlanmış iş" msgstr "Zamanlanmış iş"
#: django_q/models.py:228 #: django_q/models.py:236
msgid "Scheduled tasks" msgid "Scheduled tasks"
msgstr "Zamanlanmış işler" msgstr "Zamanlanmış işler"
#: django_q/models.py:251 #: django_q/models.py:262
msgid "Queued task" msgid "Queued task"
msgstr "Sıraya alınmış iş" msgstr "Sıraya alınmış iş"
#: django_q/models.py:252 #: django_q/models.py:263
msgid "Queued tasks" msgid "Queued tasks"
msgstr "Sıraya alınmış işler" msgstr "Sıraya alınmış işler"
#: django_q/monitor.py:54 django_q/monitor.py:322 #: django_q/monitor.py:62 django_q/monitor.py:339
msgid "Host" msgid "Host"
msgstr "" msgstr ""
#: django_q/monitor.py:58 django_q/monitor.py:326 django_q/monitor.py:433 #: django_q/monitor.py:66 django_q/monitor.py:343 django_q/monitor.py:450
msgid "Id" msgid "Id"
msgstr "" msgstr ""
#: django_q/monitor.py:62 #: django_q/monitor.py:70
msgid "State" msgid "State"
msgstr "Durum" msgstr "Durum"
#: django_q/monitor.py:66 #: django_q/monitor.py:74
msgid "Pool" msgid "Pool"
msgstr "Havuz" msgstr "Havuz"
#: django_q/monitor.py:70 #: django_q/monitor.py:78
msgid "TQ" msgid "TQ"
msgstr "" msgstr ""
#: django_q/monitor.py:74 #: django_q/monitor.py:82
msgid "RQ" msgid "RQ"
msgstr "" msgstr ""
#: django_q/monitor.py:78 #: django_q/monitor.py:86
msgid "RC" msgid "RC"
msgstr "" msgstr ""
#: django_q/monitor.py:82 #: django_q/monitor.py:90
msgid "Up" msgid "Up"
msgstr "" msgstr ""
#: django_q/monitor.py:162 django_q/monitor.py:266 #: django_q/monitor.py:170 django_q/monitor.py:279
msgid "Queued" msgid "Queued"
msgstr "Sıraya alınmış" msgstr "Sıraya alınmış"
#: django_q/monitor.py:170 #: django_q/monitor.py:178
msgid "Success" msgid "Success"
msgstr "Başarılı olanlar" msgstr "Başarılı olanlar"
#: django_q/monitor.py:180 django_q/monitor.py:274 #: django_q/monitor.py:188 django_q/monitor.py:287
msgid "Failures" msgid "Failures"
msgstr "Başarısız olanlar" msgstr "Başarısız olanlar"
#: django_q/monitor.py:191 #: django_q/monitor.py:199 django_q/monitor.py:485
msgid "[Press q to quit]" msgid "[Press q to quit]"
msgstr "[Çıkmak için q'ya basın]" msgstr "[Çıkmak için q'ya basın]"
#: django_q/monitor.py:210 #: django_q/monitor.py:223
msgid "day" msgid "day"
msgstr "gün" msgstr "gün"
#: django_q/monitor.py:231 #: django_q/monitor.py:244
msgid "second" msgid "second"
msgstr "saniye" msgstr "saniye"
#: django_q/monitor.py:234 #: django_q/monitor.py:247
msgid "minute" msgid "minute"
msgstr "dakika" msgstr "dakika"
#: django_q/monitor.py:237 #: django_q/monitor.py:250
msgid "hour" msgid "hour"
msgstr "saat" msgstr "saat"
#: django_q/monitor.py:247 #: django_q/monitor.py:260
msgid "" #, python-format
"-- {Conf.PREFIX.capitalize()} { \".\".join(str(v) for v in VERSION)} on " msgid "-- %(prefix)s %(version)s on %(info)s --"
"{broker.info()} --" msgstr "-- %(prefix)s %(version)s üzerinde %(info)s --"
msgstr ""
#: django_q/monitor.py:253 #: django_q/monitor.py:266
msgid "Clusters" msgid "Clusters"
msgstr "" msgstr ""
#: django_q/monitor.py:257 #: django_q/monitor.py:270
msgid "Workers" msgid "Workers"
msgstr "" msgstr ""
#: django_q/monitor.py:261 #: django_q/monitor.py:274
msgid "Restarts" msgid "Restarts"
msgstr "Yeniden çalıştırmalar" msgstr "Yeniden çalıştırmalar"
#: django_q/monitor.py:270 #: django_q/monitor.py:283
msgid "Successes" msgid "Successes"
msgstr "Başarılı olanlar" msgstr "Başarılı olanlar"
#: django_q/monitor.py:279 #: django_q/monitor.py:292
msgid "Schedules" msgid "Schedules"
msgstr "Zamanlanmışlar" msgstr "Zamanlanmışlar"
#: django_q/monitor.py:283 #: django_q/monitor.py:296
#, python-brace-format #, python-format
msgid "Tasks/{per}" msgid "Tasks/%(per)s"
msgstr "İş/{per}" msgstr "İş/%(per)s"
#: django_q/monitor.py:287 #: django_q/monitor.py:300
msgid "Avg time" msgid "Avg time"
msgstr "Ortalama süre" msgstr "Ortalama süre"
#: django_q/monitor.py:331 #: django_q/monitor.py:348
msgid "Available (%)" msgid "Available (%)"
msgstr "Müsait (%) " msgstr "Müsait (%) "
#: django_q/monitor.py:337 #: django_q/monitor.py:354
msgid "Available (MB)" msgid "Available (MB)"
msgstr "Müsait (MB)" msgstr "Müsait (MB)"
#: django_q/monitor.py:342 #: django_q/monitor.py:359
msgid "Total (MB)" msgid "Total (MB)"
msgstr "Toplam (MB)" msgstr "Toplam (MB)"
#: django_q/monitor.py:347 #: django_q/monitor.py:364
msgid "Sentinel (MB)" msgid "Sentinel (MB)"
msgstr "" msgstr ""
#: django_q/monitor.py:353 #: django_q/monitor.py:370
msgid "Monitor (MB)" msgid "Monitor (MB)"
msgstr "İzleme (MB)" msgstr "İzleme (MB)"
#: django_q/monitor.py:359 #: django_q/monitor.py:376
msgid "Workers (MB)" msgid "Workers (MB)"
msgstr "" msgstr ""
#: django_q/monitor.py:461 #: django_q/monitor.py:478
msgid "Available lowest (%): {} ({})" #, python-format
msgstr "Mevcut en düşük (%): {} ({})" msgid "Available lowest (): %(memory_percent)s ((at)s)"
msgstr "Mevcut en düşük (): %(memory_percent)s ((at)s)"
#: django_q/monitor.py:496
msgid "No clusters appear to be running."
msgstr "Hiçbir küme çalışıyor görünmüyor."
#: django_q/signals.py:22 #: django_q/signals.py:22
#, python-brace-format #, python-format
msgid "malformed return hook '{instance.hook}' for [{instance.name}]" msgid "malformed return hook '%(hook)s' for [%(name)s]"
msgstr "" msgstr ""
#: django_q/signals.py:30 #: django_q/signals.py:30
msgid "" #, python-format
"return hook {instance.hook} failed on [{instance.name}] because {str(e)}" msgid "return hook %(hook)s failed on [%(name)s] because %(error)s"
msgstr "" msgstr ""
@@ -0,0 +1,18 @@
# Generated by Django 4.1.2 on 2022-11-10 01:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('django_q', '0014_schedule_cluster'),
]
operations = [
migrations.AlterField(
model_name='schedule',
name='schedule_type',
field=models.CharField(choices=[('O', 'Once'), ('I', 'Minutes'), ('H', 'Hourly'), ('D', 'Daily'), ('W', 'Weekly'), ('BW', 'Biweekly'), ('M', 'Monthly'), ('BM', 'Bimonthly'), ('Q', 'Quarterly'), ('Y', 'Yearly'), ('C', 'Cron')], default='O', max_length=2, verbose_name='Schedule Type'),
),
]
+7 -2
View File
@@ -15,6 +15,7 @@ from picklefield.fields import dbsafe_decode
# Local # Local
from django_q.conf import croniter from django_q.conf import croniter
from django_q.signing import SignedPackage from django_q.signing import SignedPackage
from .utils import get_func_repr
class Task(models.Model): class Task(models.Model):
@@ -165,7 +166,9 @@ class Schedule(models.Model):
HOURLY = "H" HOURLY = "H"
DAILY = "D" DAILY = "D"
WEEKLY = "W" WEEKLY = "W"
BIWEEKLY = "BW"
MONTHLY = "M" MONTHLY = "M"
BIMONTHLY = "BM"
QUARTERLY = "Q" QUARTERLY = "Q"
YEARLY = "Y" YEARLY = "Y"
CRON = "C" CRON = "C"
@@ -175,13 +178,15 @@ class Schedule(models.Model):
(HOURLY, _("Hourly")), (HOURLY, _("Hourly")),
(DAILY, _("Daily")), (DAILY, _("Daily")),
(WEEKLY, _("Weekly")), (WEEKLY, _("Weekly")),
(BIWEEKLY, _("Biweekly")),
(MONTHLY, _("Monthly")), (MONTHLY, _("Monthly")),
(BIMONTHLY, _("Bimonthly")),
(QUARTERLY, _("Quarterly")), (QUARTERLY, _("Quarterly")),
(YEARLY, _("Yearly")), (YEARLY, _("Yearly")),
(CRON, _("Cron")), (CRON, _("Cron")),
) )
schedule_type = models.CharField( schedule_type = models.CharField(
max_length=1, choices=TYPE, default=TYPE[0][0], verbose_name=_("Schedule Type") max_length=2, choices=TYPE, default=TYPE[0][0], verbose_name=_("Schedule Type")
) )
minutes = models.PositiveSmallIntegerField( minutes = models.PositiveSmallIntegerField(
null=True, blank=True, help_text=_("Number of minutes for the Minutes type") null=True, blank=True, help_text=_("Number of minutes for the Minutes type")
@@ -241,7 +246,7 @@ class OrmQ(models.Model):
return SignedPackage.loads(self.payload) return SignedPackage.loads(self.payload)
def func(self): def func(self):
return self.task()["func"] return get_func_repr(self.task()["func"])
def task_id(self): def task_id(self):
return self.task()["id"] return self.task()["id"]
+8 -11
View File
@@ -257,8 +257,8 @@ def info(broker=None):
term.black_on_green( term.black_on_green(
term.center( term.center(
_( _(
f'-- {Conf.PREFIX.capitalize()} { ".".join(str(v) for v in VERSION)} on {broker.info()} --' '-- %(prefix)s %(version)s on %(info)s --'
) ) % {'prefix': Conf.PREFIX.capitalize(), 'version': ".".join(str(v) for v in VERSION), 'info': broker.info()}
) )
) )
) )
@@ -293,7 +293,7 @@ def info(broker=None):
+ term.move_x(1 * col_width) + term.move_x(1 * col_width)
+ term.white(str(models.Schedule.objects.count())) + term.white(str(models.Schedule.objects.count()))
+ term.move_x(2 * col_width) + term.move_x(2 * col_width)
+ term.cyan(_(f"Tasks/{per}")) + term.cyan(_("Tasks/%(per)s") % {'per': per})
+ term.move_x(3 * col_width) + term.move_x(3 * col_width)
+ term.white(f"{tasks_per:.2f}") + term.white(f"{tasks_per:.2f}")
+ term.move_x(4 * col_width) + term.move_x(4 * col_width)
@@ -475,17 +475,14 @@ def memory(run_once=False, workers=False, broker=None):
row += 1 row += 1
print( print(
term.move(row, 0) term.move(row, 0)
+ _("Available lowest (%): {} ({})").format( + _("Available lowest (): %(memory_percent)s ((at)s)") % { 'memory_percent': str(MEMORY_AVAILABLE_LOWEST_PERCENTAGE), 'at': MEMORY_AVAILABLE_LOWEST_PERCENTAGE_AT.strftime(
str(MEMORY_AVAILABLE_LOWEST_PERCENTAGE), "%Y-%m-%d %H:%M:%S+00:00"
MEMORY_AVAILABLE_LOWEST_PERCENTAGE_AT.strftime( )}
"%Y-%m-%d %H:%M:%S+00:00"
),
)
) )
# for testing # for testing
if run_once: if run_once:
return Stat.get_all(broker=broker) return Stat.get_all(broker=broker)
print(term.move(row + 2, 0) + term.center("[Press q to quit]")) print(term.move(row + 2, 0) + term.center(_("[Press q to quit]")))
val = term.inkey(timeout=1) val = term.inkey(timeout=1)
@@ -496,5 +493,5 @@ def get_ids():
for s in stat: for s in stat:
print(s.cluster_id) print(s.cluster_id)
else: else:
print("No clusters appear to be running.") print(_("No clusters appear to be running."))
return True return True
+3 -3
View File
@@ -19,7 +19,7 @@ def call_hook(sender, instance, **kwargs):
f = getattr(m, func) f = getattr(m, func)
except (ValueError, ImportError, AttributeError): except (ValueError, ImportError, AttributeError):
logger.error( logger.error(
_(f"malformed return hook '{instance.hook}' for [{instance.name}]") _("malformed return hook '%(hook)s' for [%(name)s]") % {'hook': instance.hook, 'name': instance.name}
) )
return return
try: try:
@@ -27,8 +27,8 @@ def call_hook(sender, instance, **kwargs):
except Exception as e: except Exception as e:
logger.error( logger.error(
_( _(
f"return hook {instance.hook} failed on [{instance.name}] because {str(e)}" "return hook %(hook)s failed on [%(name)s] because %(error)s"
) ) % {'hook': instance.hook, 'name': instance.name, 'error': str(e)}
) )
+24
View File
@@ -21,6 +21,7 @@ from django_q.tests.testing_utilities.multiple_database_routers import (
TestingMultipleAppsDatabaseRouter, TestingMultipleAppsDatabaseRouter,
TestingReplicaDatabaseRouter, TestingReplicaDatabaseRouter,
) )
from django_q.utils import add_months, add_years
@pytest.fixture @pytest.fixture
@@ -228,6 +229,29 @@ def test_scheduler(broker, monkeypatch):
# Done # Done
broker.delete_queue() broker.delete_queue()
# test bimonthly
schedule = create_schedule(
"django_q.tests.tasks.word_multiply",
2,
word="catch_up",
schedule_type=Schedule.BIMONTHLY
)
scheduler(broker=broker)
schedule = Schedule.objects.get(pk=schedule.pk)
assert schedule.next_run.date() == add_months(timezone.now(), 2).date()
# test biweekly
schedule = create_schedule(
"django_q.tests.tasks.word_multiply",
2,
word="catch_up",
schedule_type=Schedule.BIWEEKLY
)
scheduler(broker=broker)
schedule = Schedule.objects.get(pk=schedule.pk)
assert schedule.next_run.date() == (timezone.now() + timedelta(weeks=2)).date()
broker.delete_queue()
monkeypatch.setattr(Conf, "PREFIX", "some_cluster_name") monkeypatch.setattr(Conf, "PREFIX", "some_cluster_name")
# create a schedule on another cluster # create a schedule on another cluster
schedule = create_schedule( schedule = create_schedule(
+14 -2
View File
@@ -1,6 +1,5 @@
import datetime import inspect
from datetime import date from datetime import date
from django.utils.timezone import make_aware
import calendar import calendar
# credits: https://stackoverflow.com/a/4131114 # credits: https://stackoverflow.com/a/4131114
@@ -28,3 +27,16 @@ def add_years(d, years):
new_date = d + (date(d.year + years, 3, 1) - date(d.year, 3, 1)) new_date = d + (date(d.year + years, 3, 1) - date(d.year, 3, 1))
return d.replace(year=new_date.year, month=new_date.month, day=new_date.day) return d.replace(year=new_date.year, month=new_date.month, day=new_date.day)
def get_func_repr(func):
# convert func to string
if inspect.isfunction(func):
return f"{func.__module__}.{func.__name__}"
elif inspect.ismethod(func) and hasattr(func.__self__, '__name__'):
return (
f"{func.__self__.__module__}."
f"{func.__self__.__name__}.{func.__name__}"
)
else:
return str(func)
+1 -1
View File
@@ -73,7 +73,7 @@ author = 'Ilan Steemers, Stan Triepels'
# The short X.Y version. # The short X.Y version.
version = '1.4' version = '1.4'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '1.4.2' release = '1.4.4'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.
+1 -1
View File
@@ -27,7 +27,7 @@ Features
- Rollbar and Sentry support - Rollbar and Sentry support
Django Q2 is tested with: Python 3.7, 3.8, 3.9 and 3.10, Django 2.2.x and 3.2.x Django Q2 is tested with: Python 3.8, 3.9 and 3.10, 3.11, Django 3.2.x and 4.1.x
Currently available in English, German and French. Currently available in English, German and French.
+3 -3
View File
@@ -4,7 +4,7 @@ Installation
- Install the latest version with pip:: - Install the latest version with pip::
$ pip install django-q $ pip install django-q2
- Add :mod:`django_q` to ``INSTALLED_APPS`` in your projects :file:`settings.py`:: - Add :mod:`django_q` to ``INSTALLED_APPS`` in your projects :file:`settings.py`::
@@ -27,7 +27,7 @@ Installation
Requirements Requirements
------------ ------------
Django Q2 is tested for Python 3.7, 3.8, 3.9 and 3.10 Django Q2 is tested for Python 3.8, 3.9, 3.10 and 3.11
- `Django <https://www.djangoproject.com>`__ - `Django <https://www.djangoproject.com>`__
@@ -125,7 +125,7 @@ Other known issues are:
Python Python
~~~~~~ ~~~~~~
Current tests are performed with 3.7, 3.8, 3.9 and 3.10 Current tests are performed with 3.8, 3.9, 3.10 and 3.11
If you do encounter any regressions with earlier versions, please submit an issue on `github <https://github.com/GDay/django-q2>`__ If you do encounter any regressions with earlier versions, please submit an issue on `github <https://github.com/GDay/django-q2>`__
Open-source packages Open-source packages
+14 -1
View File
@@ -165,7 +165,7 @@ Reference
.. py:attribute:: TYPE .. py:attribute:: TYPE
:attr:`ONCE`, :attr:`MINUTES`, :attr:`HOURLY`, :attr:`DAILY`, :attr:`WEEKLY`, :attr:`MONTHLY`, :attr:`QUARTERLY`, :attr:`YEARLY`, :attr:`CRON` :attr:`ONCE`, :attr:`MINUTES`, :attr:`HOURLY`, :attr:`DAILY`, :attr:`WEEKLY`, :attr:`BIWEEKLY`, :attr:`MONTHLY`, :attr:`BIMONTHLY`, :attr:`QUARTERLY`, :attr:`YEARLY`, :attr:`CRON`
.. py:attribute:: minutes .. py:attribute:: minutes
@@ -224,10 +224,23 @@ Reference
`'W'` the task will run every week on they day and time of the first run. `'W'` the task will run every week on they day and time of the first run.
.. py:attribute:: BIWEEKLY
`'BW'` the task will run once every two weeks on they day and time of the first run.
.. py:attribute:: MONTHLY .. py:attribute:: MONTHLY
`'M'` the tasks runs every month on they day and time of the last run. `'M'` the tasks runs every month on they day and time of the last run.
.. note::
Months are tricky. If you schedule something on the 31st of the month and the next month has only 30 days or less, the task will run on the last day of the next month.
It will however continue to run on that day, e.g. the 28th, in subsequent months.
.. py:attribute:: BIMONTHLY
`'BM'` the tasks runs once every two months on they day and time of the last run.
.. note:: .. note::
Months are tricky. If you schedule something on the 31st of the month and the next month has only 30 days or less, the task will run on the last day of the next month. Months are tricky. If you schedule something on the 31st of the month and the next month has only 30 days or less, the task will run on the last day of the next month.
+2 -2
View File
@@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "django-q2" name = "django-q2"
version = "1.4.2" version = "1.4.4"
packages = [ packages = [
{ include = "django_q" }, { include = "django_q" },
] ]
@@ -26,10 +26,10 @@ classifiers = [
'Operating System :: MacOS', 'Operating System :: MacOS',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Topic :: Internet :: WWW/HTTP', 'Topic :: Internet :: WWW/HTTP',
'Topic :: System :: Distributed Computing', 'Topic :: System :: Distributed Computing',
'Topic :: Software Development :: Libraries :: Python Modules', 'Topic :: Software Development :: Libraries :: Python Modules',