diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..9b847b2 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,24 @@ +*.sqlite3 +*.swp +*.mo +*~ +.ve +.ve2 +*.pyc +__pycache__ +.pytest_cache/ +media +.coverage +htmlcov +docs/_build +.cache/* +.pytest_cache/ +.hypothesis/* +geckodriver.log +ghostdriver.log +cove/lib/org-ids.json +cove/lib/org-ids.json.lock +chromedriver/ +src/ +node_modules/ +untracked/ diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 0000000..9a9be6f --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,16 @@ +# syntax=docker/dockerfile:1 +# Using python base image: https://hub.docker.com/_/python/ +FROM python:3.12 +WORKDIR /code + +# Copy in dependencies & requirements definition +COPY setup.py setup.py +COPY tools/ tools/ +COPY lib360dataquality/ lib360dataquality/ +COPY requirements_cove_dev.txt requirements_cove_dev.txt + +# Install requirements +RUN pip install -r requirements_cove_dev.txt + +# Copy in rest of the project +COPY . . diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..974e406 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,42 @@ +services: + web: + build: + context: . + dockerfile: Dockerfile.dev + command: ["/bin/bash", "-c", "pip install -r requirements_cove_dev.txt; cd /code/cove; python manage.py migrate; python manage.py runserver 0.0.0.0:8000"] + ports: + - "8000:8000" + environment: + DB_NAME: "/data/db.sqlite3" + MEDIA_ROOT: "/data/media/" + RQ_REDIS_HOST: redis + volumes: + - "dqt_data:/data" + - "./:/cove/:ro" + + worker: + build: + context: . + dockerfile: Dockerfile.dev + command: ["/bin/bash", "-c", "pip install -r requirements_cove_dev.txt; cd /code/cove; python manage.py rqworker default --with-scheduler"] + environment: + DB_NAME: "/data/db.sqlite3" + MEDIA_ROOT: "/data/media/" + RQ_REDIS_HOST: redis + volumes: + - "dqt_data:/data" + - "./:/cove/:ro" + + redis: + # ValKey is an open source redis drop-in replacement + # See: https://hub.docker.com/r/valkey/valkey/ + # https://valkey.io/topics/valkey.conf/ + image: "valkey/valkey:8" + ports: + - "6379:6379" + environment: + # disable persistence in dev + VALKEY_EXTRA_FLAGS: "--save ''" + +volumes: + dqt_data: {} diff --git a/cove/cove_360/views.py b/cove/cove_360/views.py index a97e0b9..a5f73ad 100644 --- a/cove/cove_360/views.py +++ b/cove/cove_360/views.py @@ -5,6 +5,7 @@ import logging import re import os +import django_rq from decimal import Decimal from cove.views import explore_data_context, cove_web_input_error @@ -43,7 +44,9 @@ def results_ready(request, pk): def data_loading(request, pk, template='cove_360/data_loading.html'): # Backward compatibility if we receive a post request to the loading page if request.method == 'POST': - return explore_360(request, pk) + explore_result = explore_360(request, pk) + if explore_result: + return explore_result # Data already loaded so redirect to results page try: @@ -54,9 +57,8 @@ def data_loading(request, pk, template='cove_360/data_loading.html'): return render(request, template, {"pk": pk}) - @cove_web_input_error -def explore_360(request, pk, template='cove_360/explore.html'): +def explore_360(request, pk, template='cove_360/explore.html') -> HttpResponse | None: cached_context = cache.get(pk) @@ -91,7 +93,6 @@ def explore_360(request, pk, template='cove_360/explore.html'): data_status, dsc = SuppliedDataStatus.objects.get_or_create( supplied_data=db_data, ) - context["data_status"] = data_status if db_data.source_url: context["source_url_domain"] = extract_domain(db_data.source_url) @@ -105,6 +106,19 @@ def explore_360(request, pk, template='cove_360/explore.html'): context["submission_tool"] = True context["publisher"] = publisher + explore_360_process.delay(pk, context, db_data, flatten=request.POST.get("flatten")) + + return data_loading(request, pk) + + +@django_rq.job("default", timeout=1800) +def explore_360_process(pk, context, db_data, flatten): + + data_status, dsc = SuppliedDataStatus.objects.get_or_create( + supplied_data=db_data, + ) + context["data_status"] = data_status + lib_cove_config = LibCoveConfig() lib_cove_config.config.update(settings.COVE_CONFIG) @@ -140,7 +154,7 @@ def explore_360(request, pk, template='cove_360/explore.html'): extension_metadatas = schema_360.resolve_extension(json_data) context.update(convert_json(upload_dir, upload_url, file_name, schema_url=schema_360.schema_file, - request=request, flatten=request.POST.get('flatten'), + flatten=flatten, lib_cove_config=lib_cove_config)) else: @@ -242,7 +256,7 @@ def explore_360(request, pk, template='cove_360/explore.html'): # Helpful when debugging DQT # import pprint # pprint.pprint(context, stream=open("/tmp/dqt.py", "w"), indent=2) - return render(request, template, context) + #return render(request, template, context) def create_passed_tests_context_data(failed_tests, available_tests): diff --git a/cove/cove_project/settings.py b/cove/cove_project/settings.py index bf5d982..e011bed 100644 --- a/cove/cove_project/settings.py +++ b/cove/cove_project/settings.py @@ -8,6 +8,13 @@ env = environ.Env( # set default values and casting DB_NAME=(str, os.path.join(BASE_DIR, 'db.sqlite3')), SENTRY_DSN=(str, ''), + MEDIA_ROOT=(str, os.path.join(BASE_DIR, 'media')), + + RQ_REDIS_HOST=(str, 'localhost'), + RQ_REDIS_PORT=(str, '6379'), + RQ_REDIS_DB=(str, '0'), + RQ_REDIS_USERNAME=(str, ''), + RQ_REDIS_PASSWORD=(str, ''), ) # We use the setting to choose whether to show the section about Sentry in the @@ -32,7 +39,7 @@ # We can't take MEDIA_ROOT and MEDIA_URL from cove settings, # ... otherwise the files appear under the BASE_DIR that is the Cove library install. # That could get messy. We want them to appear in our directory. -MEDIA_ROOT = os.path.join(BASE_DIR, 'media') +MEDIA_ROOT = env("MEDIA_ROOT") MEDIA_URL = '/media/' SECRET_KEY = settings.SECRET_KEY @@ -99,6 +106,7 @@ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'django_rq', ) WSGI_APPLICATION = 'cove_project.wsgi.application' @@ -136,3 +144,16 @@ # If enabled the grants data can be used in a template to create a browsable # table of grants. GRANTS_TABLE = False + +# Django RQ Queues +RQ_QUEUES = { + 'default': { + 'HOST': env("RQ_REDIS_HOST"), + 'PORT': env("RQ_REDIS_PORT"), + 'DB': env("RQ_REDIS_DB"), + 'USERNAME': env("RQ_REDIS_USERNAME"), + 'PASSWORD': env("RQ_REDIS_PASSWORD"), + 'DEFAULT_TIMEOUT': 360, + 'DEFAULT_RESULT_TTL': 800, + }, +} \ No newline at end of file diff --git a/cove/cove_project/urls.py b/cove/cove_project/urls.py index bf6ff0b..df56acd 100644 --- a/cove/cove_project/urls.py +++ b/cove/cove_project/urls.py @@ -1,6 +1,6 @@ from django.conf.urls.static import static from django.conf import settings -from django.urls import path +from django.urls import path, include from django.views.generic import TemplateView from cove.urls import urlpatterns, handler500 # noqa: F401 @@ -18,6 +18,11 @@ path("additional_checks", cove_360.views.additional_checks, name='additional_checks'), path("submit", TemplateView.as_view(template_name="cove_360/publishing.html", extra_context={"submission_tool": True}), name="publishing"), path("terms-conditions", TemplateView.as_view(template_name="cove_360/terms.html"), name="terms-conditions"), + ] urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + +urlpatterns += [ + path('django-rq/', include('django_rq.urls')) +] \ No newline at end of file diff --git a/requirements_cove.in b/requirements_cove.in index 673a204..3332a57 100644 --- a/requirements_cove.in +++ b/requirements_cove.in @@ -1,5 +1,6 @@ -e file:./ Django<5 +django-rq flattentool>=0.17.0 libcove>=0.30.0 libcoveweb==0.31.1 diff --git a/requirements_cove.txt b/requirements_cove.txt index e4a33d3..7f3858e 100644 --- a/requirements_cove.txt +++ b/requirements_cove.txt @@ -2,10 +2,10 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile ./requirements_cove.in +# pip-compile requirements_cove.in # -e file:./ - # via -r ./requirements_cove.in + # via -r requirements_cove.in asgiref==3.8.1 # via django attrs==25.3.0 @@ -13,11 +13,11 @@ attrs==25.3.0 backports-datetime-fromisoformat==2.0.3 # via flattentool bleach==6.2.0 - # via -r ./requirements_cove.in + # via -r requirements_cove.in btrees==6.1 # via zodb cached-property==2.0.1 - # via -r ./requirements_cove.in + # via -r requirements_cove.in certifi==2025.1.31 # via # requests @@ -26,31 +26,36 @@ cffi==1.17.1 # via persistent charset-normalizer==3.4.1 # via requests +click==8.1.8 + # via rq commonmark==0.9.1 - # via -r ./requirements_cove.in + # via -r requirements_cove.in dealer==2.1.0 - # via -r ./requirements_cove.in + # via -r requirements_cove.in defusedxml==0.7.1 # via odfpy django==4.2.20 # via - # -r ./requirements_cove.in + # -r requirements_cove.in # django-bootstrap3 # django-debug-toolbar + # django-rq # libcoveweb django-bootstrap3==25.1 # via - # -r ./requirements_cove.in + # -r requirements_cove.in # libcoveweb django-debug-toolbar==5.1.0 - # via -r ./requirements_cove.in + # via -r requirements_cove.in django-environ==0.12.0 - # via -r ./requirements_cove.in + # via -r requirements_cove.in +django-rq==3.0.0 + # via -r requirements_cove.in et-xmlfile==2.0.0 # via openpyxl flattentool==0.27.0 # via - # -r ./requirements_cove.in + # -r requirements_cove.in # libcove # libcoveweb idna==3.10 @@ -61,7 +66,7 @@ ijson==3.3.0 # lib360dataquality json-merge-patch==0.3.0 # via - # -r ./requirements_cove.in + # -r requirements_cove.in # lib360dataquality jsonref==1.1.0 # via @@ -69,16 +74,16 @@ jsonref==1.1.0 # libcove jsonschema==3.2.0 # via - # -r ./requirements_cove.in + # -r requirements_cove.in # lib360dataquality # libcove libcove==0.31.0 # via - # -r ./requirements_cove.in + # -r requirements_cove.in # lib360dataquality # libcoveweb libcoveweb==0.31.1 - # via -r ./requirements_cove.in + # via -r requirements_cove.in lxml==5.3.1 # via flattentool markupsafe==3.0.2 @@ -87,7 +92,7 @@ odfpy==1.4.1 # via flattentool openpyxl==3.1.5 # via - # -r ./requirements_cove.in + # -r requirements_cove.in # flattentool persistent==6.1.1 # via @@ -99,29 +104,35 @@ pyrsistent==0.20.0 # via jsonschema python-dateutil==2.9.0.post0 # via - # -r ./requirements_cove.in + # -r requirements_cove.in # lib360dataquality pytz==2025.2 # via flattentool rangedict==0.1.7 # via - # -r ./requirements_cove.in + # -r requirements_cove.in # lib360dataquality +redis==5.2.1 + # via + # django-rq + # rq requests==2.32.3 # via - # -r ./requirements_cove.in + # -r requirements_cove.in # libcove # libcoveweb rfc3339-validator==0.1.4 # via libcove rfc3987==1.3.8 # via - # -r ./requirements_cove.in + # -r requirements_cove.in # libcove +rq==2.3.1 + # via django-rq schema==0.7.7 # via flattentool sentry-sdk==2.24.1 - # via -r ./requirements_cove.in + # via -r requirements_cove.in six==1.17.0 # via # jsonschema @@ -132,7 +143,7 @@ sqlparse==0.5.3 # django # django-debug-toolbar strict-rfc3339==0.7 - # via -r ./requirements_cove.in + # via -r requirements_cove.in transaction==5.0 # via zodb urllib3==2.3.0 @@ -144,10 +155,10 @@ webencodings==0.5.1 werkzeug==3.1.3 # via libcoveweb whitenoise==6.9.0 - # via -r ./requirements_cove.in + # via -r requirements_cove.in xmltodict==0.14.2 # via - # -r ./requirements_cove.in + # -r requirements_cove.in # flattentool zc-lockfile==3.0.post1 # via zodb diff --git a/requirements_cove_dev.txt b/requirements_cove_dev.txt index 845c91d..db3a47a 100644 --- a/requirements_cove_dev.txt +++ b/requirements_cove_dev.txt @@ -2,10 +2,10 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile ./requirements_cove_dev.in +# pip-compile requirements_cove_dev.in # -e file:./ - # via -r ./requirements_cove.in + # via -r /home/rikki/Projects/dataquality/requirements_cove.in alabaster==1.0.0 # via sphinx asgiref==3.8.1 @@ -21,13 +21,13 @@ babel==2.17.0 backports-datetime-fromisoformat==2.0.3 # via flattentool black==25.1.0 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in bleach==6.2.0 - # via -r ./requirements_cove.in + # via -r /home/rikki/Projects/dataquality/requirements_cove.in btrees==6.1 # via zodb cached-property==2.0.1 - # via -r ./requirements_cove.in + # via -r /home/rikki/Projects/dataquality/requirements_cove.in certifi==2025.1.31 # via # requests @@ -40,44 +40,49 @@ cffi==1.17.1 charset-normalizer==3.4.1 # via requests chromedriver-autoinstaller==0.6.4 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in click==8.1.8 - # via black + # via + # black + # rq commonmark==0.9.1 # via - # -r ./requirements_cove.in + # -r /home/rikki/Projects/dataquality/requirements_cove.in # recommonmark coverage[toml]==7.7.1 # via # coveralls # pytest-cov coveralls==4.0.1 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in cryptography==44.0.2 # via # pyopenssl # urllib3 dealer==2.1.0 - # via -r ./requirements_cove.in + # via -r /home/rikki/Projects/dataquality/requirements_cove.in defusedxml==0.7.1 # via odfpy django==4.2.20 # via - # -r ./requirements_cove.in + # -r /home/rikki/Projects/dataquality/requirements_cove.in # django-bootstrap3 # django-debug-toolbar + # django-rq # django-selenium-login # libcoveweb django-bootstrap3==25.1 # via - # -r ./requirements_cove.in + # -r /home/rikki/Projects/dataquality/requirements_cove.in # libcoveweb django-debug-toolbar==5.1.0 - # via -r ./requirements_cove.in + # via -r /home/rikki/Projects/dataquality/requirements_cove.in django-environ==0.12.0 - # via -r ./requirements_cove.in + # via -r /home/rikki/Projects/dataquality/requirements_cove.in +django-rq==3.0.0 + # via -r /home/rikki/Projects/dataquality/requirements_cove.in django-selenium-login==2.0.0 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in docopt==0.6.2 # via coveralls docutils==0.21.2 @@ -90,16 +95,16 @@ et-xmlfile==2.0.0 execnet==2.1.1 # via pytest-xdist flake8==7.1.2 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in flattentool==0.27.0 # via - # -r ./requirements_cove.in + # -r /home/rikki/Projects/dataquality/requirements_cove.in # libcove # libcoveweb h11==0.14.0 # via wsproto hypothesis==6.13.0 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in idna==3.10 # via # requests @@ -117,7 +122,7 @@ jinja2==3.1.6 # via sphinx json-merge-patch==0.3.0 # via - # -r ./requirements_cove.in + # -r /home/rikki/Projects/dataquality/requirements_cove.in # lib360dataquality jsonref==1.1.0 # via @@ -125,18 +130,18 @@ jsonref==1.1.0 # libcove jsonschema==3.2.0 # via - # -r ./requirements_cove.in + # -r /home/rikki/Projects/dataquality/requirements_cove.in # lib360dataquality # libcove libcove==0.31.0 # via - # -r ./requirements_cove.in + # -r /home/rikki/Projects/dataquality/requirements_cove.in # lib360dataquality # libcoveweb libcoveweb==0.31.1 - # via -r ./requirements_cove.in + # via -r /home/rikki/Projects/dataquality/requirements_cove.in libsass==0.23.0 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in lxml==5.3.1 # via flattentool markupsafe==3.0.2 @@ -151,7 +156,7 @@ odfpy==1.4.1 # via flattentool openpyxl==3.1.5 # via - # -r ./requirements_cove.in + # -r /home/rikki/Projects/dataquality/requirements_cove.in # flattentool outcome==1.3.0.post0 # via @@ -189,33 +194,37 @@ pysocks==1.7.1 # via urllib3 pytest==8.3.5 # via - # -r ./requirements_cove_dev.in + # -r requirements_cove_dev.in # pytest-cov # pytest-django # pytest-xdist pytest-cov==6.0.0 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in pytest-django==4.10.0 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in pytest-localserver==0.9.0.post0 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in pytest-xdist==3.6.1 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in python-dateutil==2.9.0.post0 # via - # -r ./requirements_cove.in + # -r /home/rikki/Projects/dataquality/requirements_cove.in # lib360dataquality pytz==2025.2 # via flattentool rangedict==0.1.7 # via - # -r ./requirements_cove.in + # -r /home/rikki/Projects/dataquality/requirements_cove.in # lib360dataquality recommonmark==0.7.1 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in +redis==5.2.1 + # via + # django-rq + # rq requests==2.32.3 # via - # -r ./requirements_cove.in + # -r /home/rikki/Projects/dataquality/requirements_cove.in # coveralls # libcove # libcoveweb @@ -224,16 +233,18 @@ rfc3339-validator==0.1.4 # via libcove rfc3987==1.3.8 # via - # -r ./requirements_cove.in + # -r /home/rikki/Projects/dataquality/requirements_cove.in # libcove roman-numerals-py==3.1.0 # via sphinx +rq==2.3.1 + # via django-rq schema==0.7.7 # via flattentool selenium==4.2.0 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in sentry-sdk==2.24.1 - # via -r ./requirements_cove.in + # via -r /home/rikki/Projects/dataquality/requirements_cove.in six==1.17.0 # via # jsonschema @@ -250,12 +261,12 @@ sortedcontainers==2.4.0 # trio sphinx==8.2.3 # via - # -r ./requirements_cove_dev.in + # -r requirements_cove_dev.in # recommonmark # sphinx-rtd-theme # sphinxcontrib-jquery sphinx-rtd-theme==3.0.2 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in sphinxcontrib-applehelp==2.0.0 # via sphinx sphinxcontrib-devhelp==2.0.0 @@ -275,11 +286,11 @@ sqlparse==0.5.3 # django # django-debug-toolbar strict-rfc3339==0.7 - # via -r ./requirements_cove.in + # via -r /home/rikki/Projects/dataquality/requirements_cove.in transaction==5.0 # via zodb transifex-client==0.12.5 - # via -r ./requirements_cove_dev.in + # via -r requirements_cove_dev.in trio==0.29.0 # via # selenium @@ -303,12 +314,12 @@ werkzeug==3.1.3 # libcoveweb # pytest-localserver whitenoise==6.9.0 - # via -r ./requirements_cove.in + # via -r /home/rikki/Projects/dataquality/requirements_cove.in wsproto==1.2.0 # via trio-websocket xmltodict==0.14.2 # via - # -r ./requirements_cove.in + # -r /home/rikki/Projects/dataquality/requirements_cove.in # flattentool zc-lockfile==3.0.post1 # via zodb diff --git a/requirements_cove_dokku.txt b/requirements_cove_dokku.txt index 6b53ba4..b13a6c5 100644 --- a/requirements_cove_dokku.txt +++ b/requirements_cove_dokku.txt @@ -5,229 +5,229 @@ # pip-compile requirements_cove_dokku.in # -e file:./ - # via -r requirements_cove.txt + # via -r /home/rikki/Projects/dataquality/requirements_cove.txt asgiref==3.8.1 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # django attrs==25.3.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # jsonschema backports-datetime-fromisoformat==2.0.3 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # flattentool bleach==6.2.0 - # via -r requirements_cove.txt + # via -r /home/rikki/Projects/dataquality/requirements_cove.txt btrees==6.1 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # zodb cached-property==2.0.1 - # via -r requirements_cove.txt + # via -r /home/rikki/Projects/dataquality/requirements_cove.txt certifi==2025.1.31 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # requests # sentry-sdk cffi==1.17.1 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # persistent charset-normalizer==3.4.1 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # requests commonmark==0.9.1 - # via -r requirements_cove.txt + # via -r /home/rikki/Projects/dataquality/requirements_cove.txt dealer==2.1.0 - # via -r requirements_cove.txt + # via -r /home/rikki/Projects/dataquality/requirements_cove.txt defusedxml==0.7.1 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # odfpy django==4.2.20 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # django-bootstrap3 # django-debug-toolbar # libcoveweb django-bootstrap3==25.1 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # libcoveweb django-debug-toolbar==5.1.0 - # via -r requirements_cove.txt + # via -r /home/rikki/Projects/dataquality/requirements_cove.txt django-environ==0.12.0 - # via -r requirements_cove.txt + # via -r /home/rikki/Projects/dataquality/requirements_cove.txt et-xmlfile==2.0.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # openpyxl flattentool==0.27.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # libcove # libcoveweb gunicorn==23.0.0 # via -r requirements_cove_dokku.in idna==3.10 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # requests ijson==3.3.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # flattentool # lib360dataquality json-merge-patch==0.3.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # lib360dataquality jsonref==1.1.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # flattentool # libcove jsonschema==3.2.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # lib360dataquality # libcove libcove==0.31.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # lib360dataquality # libcoveweb libcoveweb==0.31.1 - # via -r requirements_cove.txt + # via -r /home/rikki/Projects/dataquality/requirements_cove.txt lxml==5.3.1 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # flattentool markupsafe==3.0.2 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # werkzeug odfpy==1.4.1 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # flattentool openpyxl==3.1.5 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # flattentool packaging==24.2 # via gunicorn persistent==6.1.1 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # btrees # zodb pycparser==2.22 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # cffi pyrsistent==0.20.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # jsonschema python-dateutil==2.9.0.post0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # lib360dataquality pytz==2025.2 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # flattentool rangedict==0.1.7 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # lib360dataquality requests==2.32.3 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # libcove # libcoveweb rfc3339-validator==0.1.4 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # libcove rfc3987==1.3.8 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # libcove schema==0.7.7 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # flattentool sentry-sdk==2.24.1 - # via -r requirements_cove.txt + # via -r /home/rikki/Projects/dataquality/requirements_cove.txt six==1.17.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # jsonschema # python-dateutil # rfc3339-validator sqlparse==0.5.3 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # django # django-debug-toolbar strict-rfc3339==0.7 - # via -r requirements_cove.txt + # via -r /home/rikki/Projects/dataquality/requirements_cove.txt transaction==5.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # zodb urllib3==2.3.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # requests # sentry-sdk webencodings==0.5.1 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # bleach werkzeug==3.1.3 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # libcoveweb whitenoise==6.9.0 - # via -r requirements_cove.txt + # via -r /home/rikki/Projects/dataquality/requirements_cove.txt xmltodict==0.14.2 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # flattentool zc-lockfile==3.0.post1 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # zodb zc-zlibstorage==1.2.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # flattentool zconfig==4.2 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # zodb zodb==6.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # flattentool # zc-zlibstorage zodbpickle==4.2 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # zodb zope-deferredimport==5.0 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # persistent zope-interface==7.2 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # btrees # persistent # transaction @@ -236,7 +236,7 @@ zope-interface==7.2 # zope-proxy zope-proxy==6.1 # via - # -r requirements_cove.txt + # -r /home/rikki/Projects/dataquality/requirements_cove.txt # zope-deferredimport # The following packages are considered to be unsafe in a requirements file: