From efebd9644e1dbd52be826c9bdcb33e658f59aae6 Mon Sep 17 00:00:00 2001 From: Karl Engelhardt Date: Mon, 19 Dec 2022 14:41:02 +0100 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Add=20db=20index=20in?= =?UTF-8?q?=20FoiMessage.email=5Fmessage=5Fid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...imessage_foirequest__email_m_304d80_idx.py | 19 +++++++++++++++++++ froide/foirequest/models/message.py | 2 ++ 2 files changed, 21 insertions(+) create mode 100644 froide/foirequest/migrations/0061_foimessage_foirequest__email_m_304d80_idx.py diff --git a/froide/foirequest/migrations/0061_foimessage_foirequest__email_m_304d80_idx.py b/froide/foirequest/migrations/0061_foimessage_foirequest__email_m_304d80_idx.py new file mode 100644 index 000000000..f39837dcd --- /dev/null +++ b/froide/foirequest/migrations/0061_foimessage_foirequest__email_m_304d80_idx.py @@ -0,0 +1,19 @@ +# Generated by Django 4.0.8 on 2022-12-19 13:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("foirequest", "0060_foirequest_banner"), + ] + + operations = [ + migrations.AddIndex( + model_name="foimessage", + index=models.Index( + fields=["email_message_id"], name="foirequest__email_m_304d80_idx" + ), + ), + ] diff --git a/froide/foirequest/models/message.py b/froide/foirequest/models/message.py index f3f5e2b6d..cc4ccb9fe 100644 --- a/froide/foirequest/models/message.py +++ b/froide/foirequest/models/message.py @@ -168,6 +168,8 @@ class Meta: verbose_name = _("Freedom of Information Message") verbose_name_plural = _("Freedom of Information Messages") + indexes = [models.Index(fields=["email_message_id"])] + def __str__(self): return _("Message in '%(request)s' at %(time)s") % { "request": self.request, From 2540a014e07505ace0290c68570c49a6fcd8d616 Mon Sep 17 00:00:00 2001 From: Karl Engelhardt Date: Mon, 19 Dec 2022 16:19:20 +0100 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=92=BB=20Add=20o?= =?UTF-8?q?ffset=5Fpath=20option=20to=20parse=5Fmail=5Flog=20mgmt=20cmd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- froide/helper/management/commands/parse_mail_log.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/froide/helper/management/commands/parse_mail_log.py b/froide/helper/management/commands/parse_mail_log.py index d0818e717..6a70040a8 100644 --- a/froide/helper/management/commands/parse_mail_log.py +++ b/froide/helper/management/commands/parse_mail_log.py @@ -9,8 +9,9 @@ class Command(BaseCommand): help = "Processes mail logs for deliveries" def add_arguments(self, parser): - parser.add_argument("log_path", default=None) + parser.add_argument("log_path") + parser.add_argument("offset_path") def handle(self, *args, **options): translation.activate(settings.LANGUAGE_CODE) - check_delivery_from_log(options["log_path"]) + check_delivery_from_log(str(options["log_path"]), str(options["offset_path"])) From 00ab02106017c8257132021c36e966c103133c0b Mon Sep 17 00:00:00 2001 From: Karl Engelhardt Date: Mon, 19 Dec 2022 17:25:32 +0100 Subject: [PATCH 3/4] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Move=20test=5Fmail=5Fl?= =?UTF-8?q?og=5Fparsing=20to=20pytest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- froide/helper/tests/test_email_log_parsing.py | 345 ++++++++---------- 1 file changed, 162 insertions(+), 183 deletions(-) diff --git a/froide/helper/tests/test_email_log_parsing.py b/froide/helper/tests/test_email_log_parsing.py index dae2d791f..942e43526 100644 --- a/froide/helper/tests/test_email_log_parsing.py +++ b/froide/helper/tests/test_email_log_parsing.py @@ -2,7 +2,7 @@ import os.path import tempfile -from django.test import TestCase +import pytest from ..email_log_parsing import ( PostfixLogfileParser, @@ -18,204 +18,183 @@ def p(path): return os.path.join(TEST_DATA_ROOT, path) -class MaillogParseTest(TestCase): - DEMO_FIELDS = [ - " to=", - " relay=mx1.bund.de[77.87.224.131]:25", - " delay=0.54", - " delays=0.09/0.01/0.28/0.16", - " dsn=2.0.0", - " status=sent (250 2.0.0 Ok: queued as QUEUEUEUEUEU)", - ] - - MAIL_1_ID = "" - MAIL_1_LOG = [ - "Jan 1 01:02:04 mail postfix/smtpd[1234567]: 163CB3EE5E7F: client=localhost.localdomain[127.0.0.1], sasl_method=PLAIN, sasl_username=examplemail@example.com\n", - "Jan 1 01:02:04 mail postfix/cleanup[2345678]: 163CB3EE5E7F: message-id=\n", - "Jan 1 01:02:05 mail postfix/qmgr[2345678]: 163CB3EE5E7F: from=, size=12321, nrcpt=1 (queue active)\n", - "Jan 1 01:02:05 mail postfix/smtp[2345678]: 163CB3EE5E7F: to=, relay=example.com[123.456.789.123]:25, delay=0.67, delays=0.1/0.37/0.13/0.07, dsn=2.0.0, status=sent (250 Requested mail action okay, completed: id=aaaaa-bbbbb-ccccc-ddddd\n", - "Jan 1 01:02:05 mail postfix/qmgr[2345678]: 163CB3EE5E7F: removed\n", - ] - MAIL_2_ID = "" - MAIL_2_LOG = [ - "Jan 1 01:02:04 mail postfix/smtpd[2345678]: 065AB16D682C: client=localhost.localdomain[127.0.0.1], sasl_method=PLAIN, sasl_username=examplemail@example.com\n", - "Jan 1 01:02:04 mail postfix/cleanup[2345678]: 065AB16D682C: message-id=\n", - "Jan 1 01:02:04 mail postfix/qmgr[2345678]: 065AB16D682C: from=, size=5608, nrcpt=1 (queue active)\n", - "Jan 1 01:02:05 mail postfix/smtp[2345678]: 065AB16D682C: to=, relay=example.org[234.456.321.123]:25, delay=5.2, delays=0.09/0.02/0.14/4.9, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as ABCDEF)\n", - "Jan 1 01:02:05 mail postfix/qmgr[2345678]: 065AB16D682C: removed\n", - ] - MAIL_2_DATA = { - "message-id": "", - "from": "a.foo.sadasd1231as@example.com", - "to": "b.doe@example.org", +DEMO_FIELDS = [ + " to=", + " relay=mx1.bund.de[77.87.224.131]:25", + " delay=0.54", + " delays=0.09/0.01/0.28/0.16", + " dsn=2.0.0", + " status=sent (250 2.0.0 Ok: queued as QUEUEUEUEUEU)", +] + +MAIL_1_ID = "" +MAIL_1_LOG = [ + "Jan 1 01:02:04 mail postfix/smtpd[1234567]: 163CB3EE5E7F: client=localhost.localdomain[127.0.0.1], sasl_method=PLAIN, sasl_username=examplemail@example.com\n", + "Jan 1 01:02:04 mail postfix/cleanup[2345678]: 163CB3EE5E7F: message-id=\n", + "Jan 1 01:02:05 mail postfix/qmgr[2345678]: 163CB3EE5E7F: from=, size=12321, nrcpt=1 (queue active)\n", + "Jan 1 01:02:05 mail postfix/smtp[2345678]: 163CB3EE5E7F: to=, relay=example.com[123.456.789.123]:25, delay=0.67, delays=0.1/0.37/0.13/0.07, dsn=2.0.0, status=sent (250 Requested mail action okay, completed: id=aaaaa-bbbbb-ccccc-ddddd\n", + "Jan 1 01:02:05 mail postfix/qmgr[2345678]: 163CB3EE5E7F: removed\n", +] +MAIL_2_ID = "" +MAIL_2_LOG = [ + "Jan 1 01:02:04 mail postfix/smtpd[2345678]: 065AB16D682C: client=localhost.localdomain[127.0.0.1], sasl_method=PLAIN, sasl_username=examplemail@example.com\n", + "Jan 1 01:02:04 mail postfix/cleanup[2345678]: 065AB16D682C: message-id=\n", + "Jan 1 01:02:04 mail postfix/qmgr[2345678]: 065AB16D682C: from=, size=5608, nrcpt=1 (queue active)\n", + "Jan 1 01:02:05 mail postfix/smtp[2345678]: 065AB16D682C: to=, relay=example.org[234.456.321.123]:25, delay=5.2, delays=0.09/0.02/0.14/4.9, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as ABCDEF)\n", + "Jan 1 01:02:05 mail postfix/qmgr[2345678]: 065AB16D682C: removed\n", +] +MAIL_2_DATA = { + "message-id": "", + "from": "a.foo.sadasd1231as@example.com", + "to": "b.doe@example.org", + "status": "sent", + "removed": "", +} + + +def test_parse_field_minimal(): + assert PostfixLogfileParser._parse_fields(DEMO_FIELDS) == { + "to": "poststelle@zitis.bund.de", + "relay": "mx1.bund.de[77.87.224.131]:25", + "delay": "0.54", + "delays": "0.09/0.01/0.28/0.16", + "dsn": "2.0.0", "status": "sent", + } + + +def test_parse_fields_limit(): + assert PostfixLogfileParser._parse_fields(DEMO_FIELDS, ["to", "status"]) == { + "to": "poststelle@zitis.bund.de", + "status": "sent", + } + + assert PostfixLogfileParser._parse_fields(DEMO_FIELDS, {"to", "status"}) == { + "to": "poststelle@zitis.bund.de", + "status": "sent", + } + + +def test_parse_without_value(): + assert PostfixLogfileParser._parse_fields([" removed"]) == { "removed": "", } - def test_parse_field_minimal(self): - self.assertEqual( - PostfixLogfileParser._parse_fields(self.DEMO_FIELDS), - { - "to": "poststelle@zitis.bund.de", - "relay": "mx1.bund.de[77.87.224.131]:25", - "delay": "0.54", - "delays": "0.09/0.01/0.28/0.16", - "dsn": "2.0.0", - "status": "sent", - }, - ) - def test_parse_fields_limit(self): - self.assertEqual( - PostfixLogfileParser._parse_fields(self.DEMO_FIELDS, ["to", "status"]), - { - "to": "poststelle@zitis.bund.de", - "status": "sent", - }, - ) +def test_parse_empty_file(): + parser = PostfixLogfileParser(io.StringIO("")) + assert next(parser, None) is None - self.assertEqual( - PostfixLogfileParser._parse_fields(self.DEMO_FIELDS, {"to", "status"}), - { - "to": "poststelle@zitis.bund.de", - "status": "sent", - }, - ) - def test_parse_without_value(self): - self.assertEqual( - PostfixLogfileParser._parse_fields([" removed"]), - { - "removed": "", - }, +def test_parse_line(): + parser = PostfixLogfileParser(io.StringIO(""), relevant_fields={"field"}) + assert ( + parser._parse_line( + "Jan 1 01:02:03 mail postfix/something[1234566]: ABCDEF1234: field=value" ) + ) == PostfixLogLine("Jan 1 01:02:03", "ABCDEF1234", {"field": "value"}) - def test_parse_empty_file(self): - parser = PostfixLogfileParser(io.StringIO("")) - self.assertEqual(next(parser, None), None) - - def test_parse_line(self): - parser = PostfixLogfileParser(io.StringIO(""), relevant_fields={"field"}) - self.assertEqual( - parser._parse_line( - "Jan 1 01:02:03 mail postfix/something[1234566]: ABCDEF1234: field=value" - ), - PostfixLogLine("Jan 1 01:02:03", "ABCDEF1234", {"field": "value"}), + assert ( + parser._parse_line( + "Jan 1 01:02:03 mail postfix/something[1234566]: ABCDEF1234: field=value, field2" ) + ) == PostfixLogLine("Jan 1 01:02:03", "ABCDEF1234", {"field": "value"}) - self.assertEqual( - parser._parse_line( - "Jan 1 01:02:03 mail postfix/something[1234566]: ABCDEF1234: field=value, field2" - ), - PostfixLogLine("Jan 1 01:02:03", "ABCDEF1234", {"field": "value"}), - ) - def test_parse_file(self): - with open(p("maillog_001.txt")) as f: - parser = PostfixLogfileParser(f) - msg1 = next(parser) - self.assertEqual(msg1["data"]["message-id"], self.MAIL_1_ID) - self.assertEqual(len(msg1["log"]), 5) - - self.assertEqual(len(parser._msg_log), 1) - - msg2 = next(parser) - self.assertEqual( - msg2["data"], - self.MAIL_2_DATA, - ) - self.assertEqual( - msg2["log"], - self.MAIL_2_LOG, - ) - self.assertEqual(next(parser, None), None) - - self.assertEqual(len(parser._msg_log), 0) - - def test_parse_file_with_partial_log(self): - with open(p("maillog_002.txt")) as f: - parser = PostfixLogfileParser(f) - self.assertEqual(next(parser, None), None) - self.assertEqual(len(parser._msg_log), 1) - - def test_email_signal(self): - invocations = [] - - def callback(**kwargs): - invocations.append(kwargs) - - email_left_queue.connect(callback) - self.assertEqual(len(invocations), 0) - with tempfile.TemporaryDirectory() as dir: - check_delivery_from_log(p("maillog_001.txt"), str(dir + "/mail_log.offset")) - self.assertEqual(len(invocations), 2) - self.assertEqual(invocations[0]["message_id"], self.MAIL_1_ID) - self.assertEqual(invocations[1]["message_id"], self.MAIL_2_ID) - self.assertEqual( - invocations[0]["log"], - self.MAIL_1_LOG, - ) - self.assertEqual( - invocations[1]["log"], - self.MAIL_2_LOG, - ) +def test_parse_file(): + with open(p("maillog_001.txt")) as f: + parser = PostfixLogfileParser(f) + msg1 = next(parser) + assert msg1["data"]["message-id"] == MAIL_1_ID + assert len(msg1["log"]) == 5 - def test_pygtail_log_append(self): - invocations = [] - - def callback(**kwargs): - invocations.append(kwargs) - - email_left_queue.connect(callback) - self.assertEqual(len(invocations), 0) - - with tempfile.TemporaryDirectory() as tmpdir: - logfile_path = str(tmpdir + "/mail_log") - offset_file_path = str(tmpdir + "/mail_log.offset") - with open(logfile_path, "w") as logfile: - check_delivery_from_log(logfile_path, offset_file_path) - self.assertEqual(len(invocations), 0) - with open(p("maillog_003.txt")) as fixture: - logfile.write(fixture.read()) - logfile.flush() - check_delivery_from_log(logfile_path, offset_file_path) - self.assertEqual(len(invocations), 1) - - with open(p("maillog_004.txt")) as fixture: - logfile.write(fixture.read()) - logfile.flush() - check_delivery_from_log(logfile_path, offset_file_path) - self.assertEqual(len(invocations), 2) - - check_delivery_from_log(logfile_path, offset_file_path) - self.assertEqual(len(invocations), 2) - - self.assertEqual(invocations[0]["message_id"], self.MAIL_2_ID) - self.assertEqual(invocations[1]["message_id"], self.MAIL_1_ID) - self.assertEqual( - invocations[0]["log"], - self.MAIL_2_LOG, - ) + assert len(parser._msg_log) == 1 - self.assertEqual(invocations[1]["log"], self.MAIL_1_LOG) + msg2 = next(parser) + assert msg2["data"] == MAIL_2_DATA + assert msg2["log"] == MAIL_2_LOG + assert next(parser, None) is None - def test_multiple_partial(self): - invocations = [] + assert len(parser._msg_log) == 0 - def callback(**kwargs): - invocations.append(kwargs) - email_left_queue.connect(callback) - self.assertEqual(len(invocations), 0) - with tempfile.TemporaryDirectory() as dir: - check_delivery_from_log(p("maillog_005.txt"), str(dir + "/mail_log.offset")) - self.assertEqual(len(invocations), 1) +def test_parse_file_with_partial_log(): + with open(p("maillog_002.txt")) as f: + parser = PostfixLogfileParser(f) + assert next(parser, None) is None + assert len(parser._msg_log) == 1 - check_delivery_from_log(p("maillog_005.txt"), str(dir + "/mail_log.offset")) - self.assertEqual(len(invocations), 1) - self.assertEqual(invocations[0]["message_id"], self.MAIL_1_ID) - self.assertEqual( - invocations[0]["log"], - self.MAIL_1_LOG, - ) +@pytest.mark.django_db +def test_email_signal(): + invocations = [] + + def callback(**kwargs): + invocations.append(kwargs) + + email_left_queue.connect(callback) + assert len(invocations) == 0 + with tempfile.TemporaryDirectory() as dir: + check_delivery_from_log(p("maillog_001.txt"), str(dir + "/mail_log.offset")) + assert len(invocations) == 2 + assert invocations[0]["message_id"] == MAIL_1_ID + assert invocations[1]["message_id"] == MAIL_2_ID + assert invocations[0]["log"] == MAIL_1_LOG + assert invocations[1]["log"] == MAIL_2_LOG + + +@pytest.mark.django_db +def test_pygtail_log_append(): + invocations = [] + + def callback(**kwargs): + invocations.append(kwargs) + + email_left_queue.connect(callback) + assert len(invocations) == 0 + + with tempfile.TemporaryDirectory() as tmpdir: + logfile_path = str(tmpdir + "/mail_log") + offset_file_path = str(tmpdir + "/mail_log.offset") + with open(logfile_path, "w") as logfile: + check_delivery_from_log(logfile_path, offset_file_path) + assert len(invocations) == 0 + with open(p("maillog_003.txt")) as fixture: + logfile.write(fixture.read()) + logfile.flush() + check_delivery_from_log(logfile_path, offset_file_path) + assert len(invocations) == 1 + + with open(p("maillog_004.txt")) as fixture: + logfile.write(fixture.read()) + logfile.flush() + check_delivery_from_log(logfile_path, offset_file_path) + assert len(invocations) == 2 + + check_delivery_from_log(logfile_path, offset_file_path) + assert len(invocations) == 2 + + assert invocations[0]["message_id"] == MAIL_2_ID + assert invocations[1]["message_id"] == MAIL_1_ID + assert invocations[0]["log"] == MAIL_2_LOG + + assert invocations[1]["log"] == MAIL_1_LOG + + +def test_multiple_partial(): + invocations = [] + + def callback(**kwargs): + invocations.append(kwargs) + + email_left_queue.connect(callback) + assert len(invocations) == 0 + with tempfile.TemporaryDirectory() as dir: + check_delivery_from_log(p("maillog_005.txt"), str(dir + "/mail_log.offset")) + assert len(invocations) == 1 + + check_delivery_from_log(p("maillog_005.txt"), str(dir + "/mail_log.offset")) + assert len(invocations) == 1 + + assert invocations[0]["message_id"] == MAIL_1_ID + assert invocations[0]["log"] == MAIL_1_LOG From 102b0b5ea2e5ce41f2a6add1a5777f87656b4338 Mon Sep 17 00:00:00 2001 From: Karl Engelhardt Date: Mon, 19 Dec 2022 17:28:18 +0100 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=90=9B=20Use=20pre-line=20file=20offs?= =?UTF-8?q?et?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- froide/helper/email_log_parsing.py | 4 ++-- requirements-test.txt | 14 ++++++++++---- requirements.in | 2 +- requirements.txt | 14 ++++++++++---- setup.py | 2 +- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/froide/helper/email_log_parsing.py b/froide/helper/email_log_parsing.py index e51324c17..2d43eae5b 100644 --- a/froide/helper/email_log_parsing.py +++ b/froide/helper/email_log_parsing.py @@ -166,11 +166,11 @@ def iteration_done(self): if not self._msg_log: self.logfile_reader.update_offset_file() else: - first_logoffset = sorted(x["offset"] for x in self._msg_log.values())[0] + first_logoffset = min(x["offset"] for x in self._msg_log.values()) self.logfile_reader.write_offset_to_file(first_logoffset) def __next__(self): - for line, offset in self.logfile_reader.with_offsets(): + for line, offset in self.logfile_reader.with_offsets(offset_position="pre"): parsed_line = self._parse_line(line) if parsed_line is None: continue diff --git a/requirements-test.txt b/requirements-test.txt index 3d104c44f..94b4d2050 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,11 +1,13 @@ # -# This file is autogenerated by pip-compile with python 3.10 +# This file is autogenerated by pip-compile with python 3.9 # To update, run: # # pip-compile requirements-test.in # -e git+https://github.com/okfde/django-filingcabinet.git@main#egg=django-filingcabinet # via -r requirements.in +-e git+https://github.com/okfde/pygtail.git@3be17b00f55781caba62d589bcf8aceb0805a58c#egg=pygtail + # via -r requirements.in aiohttp==3.8.3 # via geoip2 aiosignal==1.3.1 @@ -174,7 +176,7 @@ djangorestframework-jsonp==1.0.2 # via -r requirements.in dnspython==2.2.1 # via pyisemail -easy-thumbnails==2.8.3 +easy-thumbnails==2.8.4 # via -r requirements.in elasticsearch==7.17.8 # via @@ -228,6 +230,8 @@ idna==3.4 # via # requests # yarl +importlib-metadata==5.2.0 + # via markdown inflection==0.5.1 # via pytest-factoryboy iniconfig==1.1.1 @@ -330,8 +334,6 @@ pyflakes==3.0.1 # via # -r requirements-test.in # flake8 -pygtail==0.14.0 - # via -r requirements.in pyisemail==2.0.1 # via -r requirements.in pyotp==2.8.0 @@ -444,11 +446,13 @@ types-urllib3==1.26.25.4 # via types-requests typing-extensions==4.4.0 # via + # black # django-stubs # django-stubs-ext # libcst # mypy # pyee + # pypdf2 # pytest-factoryboy # typing-inspect typing-inspect==0.8.0 @@ -491,6 +495,8 @@ wrapt==1.14.1 # via deprecated yarl==1.8.2 # via aiohttp +zipp==3.11.0 + # via importlib-metadata zopfli==0.2.2 # via fonttools diff --git a/requirements.in b/requirements.in index 854568983..a87dd3d09 100644 --- a/requirements.in +++ b/requirements.in @@ -34,7 +34,6 @@ phonenumbers Pillow>=9.0.0 psycopg2-binary pyisemail -pygtail>=0.14.0 pypdf2>=2 python-magic python-mimeparse @@ -46,3 +45,4 @@ WeasyPrint websockets -e git+https://github.com/okfde/django-filingcabinet.git@main#egg=django-filingcabinet +-e git+https://github.com/okfde/pygtail.git@3be17b00f55781caba62d589bcf8aceb0805a58c#egg=pygtail diff --git a/requirements.txt b/requirements.txt index 6cdc7c9a2..a85fb5e81 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,13 @@ # -# This file is autogenerated by pip-compile with python 3.10 +# This file is autogenerated by pip-compile with python 3.9 # To update, run: # # pip-compile requirements.in # -e git+https://github.com/okfde/django-filingcabinet.git@main#egg=django-filingcabinet # via -r requirements.in +-e git+https://github.com/okfde/pygtail.git@3be17b00f55781caba62d589bcf8aceb0805a58c#egg=pygtail + # via -r requirements.in aiohttp==3.8.3 # via geoip2 aiosignal==1.3.1 @@ -153,7 +155,7 @@ djangorestframework-jsonp==1.0.2 # via -r requirements.in dnspython==2.2.1 # via pyisemail -easy-thumbnails==2.8.3 +easy-thumbnails==2.8.4 # via -r requirements.in elasticsearch==7.17.8 # via @@ -185,6 +187,8 @@ idna==3.4 # via # requests # yarl +importlib-metadata==5.2.0 + # via markdown itypes==1.2.0 # via coreapi jinja2==3.1.2 @@ -238,8 +242,6 @@ pycryptodome==3.16.0 # via django-filingcabinet pydyf==0.5.0 # via weasyprint -pygtail==0.14.0 - # via -r requirements.in pyisemail==2.0.1 # via -r requirements.in pyotp==2.8.0 @@ -301,6 +303,8 @@ tinycss2==1.2.1 # via # cssselect2 # weasyprint +typing-extensions==4.4.0 + # via pypdf2 tzdata==2022.7 # via django-celery-beat unicodecsv==0.14.1 @@ -337,5 +341,7 @@ wrapt==1.14.1 # via deprecated yarl==1.8.2 # via aiohttp +zipp==3.11.0 + # via importlib-metadata zopfli==0.2.2 # via fonttools diff --git a/setup.py b/setup.py index fdc028eaa..3fc6c4b66 100644 --- a/setup.py +++ b/setup.py @@ -55,7 +55,7 @@ def find_version(*file_paths): "dj-database-url", "django-filter", "phonenumbers", - "pygtail>=0.14.0", + "pygtail @ git+https://github.com/okfde/pygtail.git@3be17b00f55781caba62d589bcf8aceb0805a58c#egg=pygtail", "django-filingcabinet", "icalendar", "easy-thumbnails",