diff --git a/.cspell.json b/.cspell.json index 1bc0030c84..68858f1215 100644 --- a/.cspell.json +++ b/.cspell.json @@ -131,6 +131,7 @@ "filename", "filepath", "filesystem", + "filterset", "fineuploader", "firefox", "Firefox", diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 46336586a5..61fb3a04fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -109,7 +109,7 @@ jobs: - name: Install deps run: | pip install --upgrade pip - pip install tox==3.14.3 + pip install tox==4.20.0 sudo apt update sudo apt install gdal-bin - name: Setup config diff --git a/docs/source/conf.py b/docs/source/conf.py index b87c79b935..56c6ef0ae6 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -56,9 +56,7 @@ # Location of word list. # convert the spelling list to a text file and save -with open("../../.cspell.txt", "w", encoding=locale.getpreferredencoding(False)) as cspell_txt, open( - "../../.cspell.json", encoding=locale.getpreferredencoding(False) -) as cspell_json: +with open("../../.cspell.txt", "w", encoding="utf-8") as cspell_txt, open("../../.cspell.json", encoding="utf-8") as cspell_json: cspell_txt.write("\n".join(json.load(cspell_json)["words"])) spelling_word_list_filename = "../../.cspell.txt" @@ -83,14 +81,12 @@ # built documents. # # Grab the version from the package.json file -with open( - os.path.join(os.path.dirname(os.path.realpath(__file__)), "../../package.json"), encoding=locale.getpreferredencoding(False) -) as f: - data = json.load(f) +with open("../../package.json", encoding=locale.getpreferredencoding(False)) as package_json: + package = json.load(package_json) -version = data["version"] +version = package["version"] # The full version, including alpha/beta/rc tags. -release = data["version"] +release = package["version"] # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/source/migrations.rst b/docs/source/migrations.rst index 32f35b7f85..cc95efce1f 100644 --- a/docs/source/migrations.rst +++ b/docs/source/migrations.rst @@ -54,7 +54,7 @@ Version 2.22.0 -------------- - Run ``./manage.py migrate``. - There is a Redis dependency update in this release that requires users and deployments to modify their settings' ``CACHES`` config. - #. Update your dependencies with pip install -r requirements/base.txt + #. Update your dependencies with ``pip install -r requirements/base.txt`` #. Update the CACHES BACKEND property to ``django_redis.cache.RedisCache`` #. Update the CACHES LOCATION property to match the redis-py native URL notation for connection strings, including the redis protocol and database number. e.g. ``redis://localhost:6379/1`` diff --git a/mypy.ini b/mypy.ini index 43c4e0e15f..0f27946b3e 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,9 +1,10 @@ [mypy] ignore_missing_imports = True exclude = (?x)( - ^docs\/source\/conf.py$ | - ^seed\/tests\/test_search\.py$ | - ^src\/.*$ + ^docs\/source\/conf\.py$ + | ^seed\/tests\/test_search\.py$ + | ^src\/.*$ + | ^venv\/.*$ ) [mypy-seed.*.migrations.*] diff --git a/requirements/aws.txt b/requirements/aws.txt index 2fec7bddbf..c28395f25f 100644 --- a/requirements/aws.txt +++ b/requirements/aws.txt @@ -1,6 +1,4 @@ -r base.txt -boto3==1.34.42 -django-redis==5.2.0 -django-sslify==0.2.7 -django-ses==3.5.0 -uWSGI==2.0.22; sys_platform != "win32" +boto3==1.35.21 +django-ses==4.1.1 +uWSGI==2.0.26; sys_platform != "win32" diff --git a/requirements/base.txt b/requirements/base.txt index 0bfdca1064..b1acb9f7cb 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,60 +1,57 @@ # Django -django==3.2.25 +django==3.2.25 # TODO update # Used by django-filter. See here: https://github.com/carltongibson/django-filter/blob/fe90e3a5fdeaff0983d1325a3e9dcf3458ef078f/docs/guide/rest_framework.txt#L210 -django-crispy-forms==1.8.1 +django-crispy-forms==1.8.1 # Update to major version 2 # Persistence stores psycopg2-binary==2.9.9 - -# background process management -celery==5.2.2 -django-celery-beat==2.2.1 -django-redis==5.2.0 # Version is tied to compatibility with boto3 -hiredis==2.3.2 +# Background process management +celery==5.4.0 +django-celery-beat==2.7.0 +django-redis==5.4.0 +hiredis==3.0.0 brotli==1.1.0 -django-compressor==4.4 +django-compressor==4.4 # Update after Django 4.2 django-extensions==3.2.3 -django-model-utils==4.3.1 +django-model-utils==5.0.0 # Time zones support -pytz==2024.1 +pytz==2024.2 python-dateutil==2.9.0.post0 # Metric/imperial units support -django-pint==0.6 +django-pint==0.7.3 # API -djangorestframework==3.12.2 -# Django-post-office dependency needs to be installed via github b/c -# with pypi version Celery fails to auto discover post_office tasks -django-post_office @ git+https://github.com/ui/django-post_office@v3.6.0 -drf-yasg==1.20.0 # TODO bump this to 1.21.7 to add `get_paginated_response_schema` bug fix (once pytz is bumped) -django-filter==2.4.0 -drf-nested-routers==0.91 +djangorestframework==3.15.1 # Update after Django 4.2 +django-post_office==3.8.0 # Update after Django 4.2 +drf-yasg==1.21.7 +django-filter==22.1 # Update after Django 4.2 and drf-spectacular +drf-nested-routers==0.94.0 # Update after Django 4.2 # Server monitoring -sentry-sdk==2.11.0 +sentry-sdk==2.14.0 # Various packages -jellyfish==0.8.2 -Markdown==3.1.1 +jellyfish==1.1.0 +Markdown==3.7 polling==0.3.2 -pyyaml==6.0.1 +pyyaml==6.0.2 street-address==0.4.0 -xlrd==1.2.0 -xlsxwriter==1.2.7 -xmltodict==0.12.0 -requests==2.32.0 -probablepeople==0.5.4 -xmlschema==1.1.1 -lark==0.11.3 +xlrd==1.2.0 # Try updating this major version 2 +xlsxwriter==1.2.7 # Try updating this major version 3 +xmltodict==0.13.0 +requests==2.32.3 +probablepeople==0.5.5 +xmlschema==1.1.1 # Try updating this major version 3 +lark==0.11.3 # Try updating this major version 1 pandas==2.2.2 # Parsing and managing geojson data (this is only used in managed tasks at the moment) -geojson==2.5.0 +geojson==3.1.0 # BuildingSync Asset Extractor # this also includes the lxml dependency required by SEED @@ -64,17 +61,12 @@ buildingsync-asset-extractor==v0.2.0 seed-salesforce==0.1.0 # geospatial and pnnl/buildingid-py -shapely==2.0.1 +shapely==2.0.6 usaddress==0.5.10 pnnl-buildingid @ git+https://github.com/SEED-platform/buildingid@bdb0a6e -future==0.18.3 - -django-treebeard==4.6.1 +django-treebeard==4.7.1 -django-two-factor-auth[phonenumbers]==1.16.0 -qrcode[pil]==6.1 +django-two-factor-auth[phonenumbers]==1.16.0 # Update after Django 4.2 +qrcode[pil]==7.4.2 pyotp==2.9.0 - -# This dependency can be removed once a version newer than 8.5.0 has been released that fixes Django autoreload -importlib_metadata==8.4.0 diff --git a/requirements/local.txt b/requirements/local.txt index 0553bfebd6..94d08c6c6f 100644 --- a/requirements/local.txt +++ b/requirements/local.txt @@ -1,5 +1,3 @@ # Local development dependencies go here -r test.txt -django-debug-toolbar==2.2.1 -# github3 for generating the change log -github3.py==3.2.0 +django-debug-toolbar==4.3.0 # Update after Django 4.2 diff --git a/requirements/test.txt b/requirements/test.txt index ab909c697e..dcf2644501 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -2,36 +2,31 @@ -r base.txt # general -coverage==4.5.4 -coveralls==1.9.2 -tox==3.14.3 -psutil==5.6.7 +coverage==7.6.1 +coveralls==4.0.1 +tox==4.20.0 # Keep this in sync with ci.yml +psutil==6.0.0 # python testing -Faker==0.9.3 -mock==2.0.0 -vcrpy==4.2.1 -pytest==7.4.4 -pytest-django==4.7.0 -# Lock urllib3 to v1 until vcrpy supports it -urllib3<2 +Faker==29.0.0 +mock==5.1.0 +vcrpy==6.0.1 +pytest==8.3.3 +pytest-django==4.9.0 +urllib3==1.26.20 # TODO update after vcrpy supports v2 # static code analysis -pycodestyle==2.11.1 -pre-commit==3.7.0 -ruff==0.3.4 +pre-commit==3.8.0 +ruff==0.6.5 # documentation and spelling -Sphinx==7.2.6 +Sphinx==7.4.7 # TODO update after python 3.9 sphinxcontrib-spelling==8.0.0 sphinx_rtd_theme==2.0.0 docutils==0.20.1 # property-based testing -hypothesis==6.94.0 - -# For running the server -uWSGI==2.0.23; sys_platform != "win32" +hypothesis==6.112.1 # static type checking -mypy==1.9.0 +mypy==1.11.2 diff --git a/seed/context_processors.py b/seed/context_processors.py index 0600592f0b..6de12c5d78 100644 --- a/seed/context_processors.py +++ b/seed/context_processors.py @@ -1,7 +1,7 @@ from django.core.cache import cache -def global_vars(request): +def global_vars(_request): method_2fa = cache.get("method_2fa") user_email = cache.get("user_email") return {"method_2fa": method_2fa, "user_email": user_email} diff --git a/seed/filtersets.py b/seed/filtersets.py index f9faa9b0c9..99267f1b47 100644 --- a/seed/filtersets.py +++ b/seed/filtersets.py @@ -7,27 +7,16 @@ FilterSet classes to provide advanced filtering API endpoints. """ -from datetime import datetime - -import pytz -from dateutil.relativedelta import relativedelta from django.db.models import Q -from django.utils.timezone import make_aware -from django_filters import BaseInFilter, CharFilter, DateFilter, NumberFilter +from django_filters import CharFilter, DateFilter, NumberFilter from django_filters.rest_framework import FilterSet -from seed.models import Cycle, GreenAssessment, GreenAssessmentProperty, PropertyState, PropertyView -from seed.models import StatusLabel as Label +from seed.models import GreenAssessment, GreenAssessmentProperty, PropertyView # Oops! we override a builtin in some of the models property_decorator = property -# Public Classes and Functions -class NumberInFilter(BaseInFilter, NumberFilter): - pass - - class GreenAssessmentFilterSet(FilterSet): name = CharFilter(field_name="name", lookup_expr="exact") award_body = CharFilter(field_name="award_body", lookup_expr="exact") @@ -50,50 +39,6 @@ class Meta: fields = ("year", "assessment", "rating", "view") -class LabelFilterSet(FilterSet): - """Provide filtering for Label by property id, taxlot id, name or color.""" - - property = NumberInFilter(field_name="property__pk", lookup_expr="in") - taxlot = NumberInFilter(field_name="taxlot__pk", lookup_expr="in") - - class Meta: - model = Label - fields = ["name", "color", "property", "taxlot"] - - -class CycleFilterSet(FilterSet): - """Provide filtering for Cycle by name, start date, end date or - calendar year.""" - - start_lte = DateFilter(field_name="start", lookup_expr="lte") - end_gte = DateFilter(field_name="end", lookup_expr="gte") - year = CharFilter(method="year_filter") - - class Meta: - model = Cycle - fields = ["name", "start_lte", "end_gte", "year"] - - def year_filter(self, queryset, name, value): - """ - Provide close enough filtering for Cycle spanning the single calendar - year supplied to the filter. - """ - max_time_diff = 26 - name = f"{value} Calendar Year" - cycles = queryset.filter(name__icontains=name) - if not cycles: - start = make_aware(datetime(int(value), 1, 1), pytz.UTC) - end = start + relativedelta(years=1) - relativedelta(seconds=1) - - # to eliminate the question of timezone saved in vs timezone - # queried from, start and end dates are nudge1d in by the max - # possible time difference between 2 servers - start = start + relativedelta(hours=max_time_diff) - end = end - relativedelta(hours=max_time_diff) - cycles = queryset.filter(start__lte=start, end__gte=end) - return cycles - - class PropertyViewFilterSet(FilterSet): """Provide advanced filtering for PropertyView @@ -127,37 +72,3 @@ def identifier_filter(self, queryset, name, value): home_energy_score_id = Q(state__home_energy_score_id=value) query = jurisdiction_property_id | custom_id_1 | pm_property_id | home_energy_score_id | ubid return queryset.filter(query) - - -class PropertyStateFilterSet(FilterSet): - """Provide advanced filtering for PropertyState - - Filter options for propertystate by energy_score (gte), city, - pm_parent_property_id, and property_identifier. - - The property_identifier filter provides a single query parameter key for - filtering against any of the property ID type fields. - (jurisdiction_property_id, custom_id_1, pm_property_id or - home_energy_score_id) - """ - - energy_score = NumberFilter(field_name="energy_score", lookup_expr="gte") - property_identifier = CharFilter(method="identifier_filter") - - class Meta: - model = PropertyState - fields = ["energy_score", "city", "pm_parent_property_id", "property_identifier"] - - def identifier_filter(self, queryset, name, value): - """ - Filter queryset for case-insensitive value matching - jurisdiction_property_id OR custom_id_1 OR pm_property_id - OR home_energy_score_id. - """ - jurisdiction_property_id = Q(jurisdiction_property_id__iexact=value) - custom_id_1 = Q(custom_id_1__iexact=value) - pm_property_id = Q(pm_property_id=value) - ubid = Q(ubid__iexact=value) - home_energy_score_id = Q(home_energy_score_id=value) - query = jurisdiction_property_id | custom_id_1 | pm_property_id | home_energy_score_id | ubid - return queryset.filter(query) diff --git a/seed/migrations/0001_initial.py b/seed/migrations/0001_initial.py index 05a54eca40..717d36e6fe 100644 --- a/seed/migrations/0001_initial.py +++ b/seed/migrations/0001_initial.py @@ -363,7 +363,7 @@ class Migration(migrations.Migration): default=django.utils.timezone.now, verbose_name="modified", editable=False, blank=True ), ), - ("compliant", models.NullBooleanField()), + ("compliant", models.BooleanField(null=True)), ("approved_date", models.DateField(null=True, verbose_name="approved_date", blank=True)), ( "approver", diff --git a/seed/migrations/0038_auto_20161008_2244.py b/seed/migrations/0038_auto_20161008_2244.py index eb2cf09ca6..666835ec69 100644 --- a/seed/migrations/0038_auto_20161008_2244.py +++ b/seed/migrations/0038_auto_20161008_2244.py @@ -19,7 +19,7 @@ class Migration(migrations.Migration): ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), ("created", django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, verbose_name="created")), ("modified", django_extensions.db.fields.ModificationDateTimeField(auto_now=True, verbose_name="modified")), - ("compliant", models.NullBooleanField()), + ("compliant", models.BooleanField(null=True)), ("approved_date", models.DateField(blank=True, null=True, verbose_name="approved_date")), ( "approver", @@ -52,7 +52,7 @@ class Migration(migrations.Migration): ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), ("created", django_extensions.db.fields.CreationDateTimeField(auto_now_add=True, verbose_name="created")), ("modified", django_extensions.db.fields.ModificationDateTimeField(auto_now=True, verbose_name="modified")), - ("compliant", models.NullBooleanField()), + ("compliant", models.BooleanField(null=True)), ("approved_date", models.DateField(blank=True, null=True, verbose_name="approved_date")), ( "approver", diff --git a/seed/migrations/0068_green_assessments.py b/seed/migrations/0068_green_assessments.py index 35de54e350..7ccf622f3f 100644 --- a/seed/migrations/0068_green_assessments.py +++ b/seed/migrations/0068_green_assessments.py @@ -54,7 +54,7 @@ class Migration(migrations.Migration): ("version", models.CharField(blank=True, max_length=50, null=True)), ("date", models.DateField(blank=True, null=True)), ("target_date", models.DateField(blank=True, null=True)), - ("eligibility", models.NullBooleanField()), + ("eligibility", models.BooleanField(null=True)), ("_expiration_date", models.DateField(blank=True, null=True)), ("extra_data", models.JSONField(blank=True, default=dict)), ("assessment", models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to="seed.GreenAssessment")), diff --git a/seed/search.py b/seed/search.py index 24f237a6d7..a1ee9ebb80 100644 --- a/seed/search.py +++ b/seed/search.py @@ -156,7 +156,7 @@ def build_shared_buildings_orgs(orgs): # this is a parent org, so get all of the child orgs other_orgs.extend(org.child_orgs.all()) other_orgs.append(org) - # remove dups + # remove dupes other_orgs = list(set(other_orgs)) return other_orgs @@ -274,7 +274,7 @@ def inventory_search_filter_sort(inventory_type, params, user, cycle_id=None): cycle_id=cycle_id, ) - if inventory != []: + if inventory: # full text search across a couple common fields inventory = search_inventory(inventory_type, params["q"], queryset=inventory) diff --git a/seed/tests/test_analysis_pipelines.py b/seed/tests/test_analysis_pipelines.py index 5414e1c05f..3d87da2afd 100644 --- a/seed/tests/test_analysis_pipelines.py +++ b/seed/tests/test_analysis_pipelines.py @@ -1076,7 +1076,7 @@ def test_get_location(self): location, status = _get_location(self.property_view) self.assertEqual(status, "success") self.assertTrue(location is not None) - self.assertEqual(location, "730 Garcia Street, Boring, Oregon, 97080") + self.assertEqual(location, "1070 Hunt Street, Boring, Oregon, 97015") def test_get_data_for_census_tract_fetch(self): pvids = [self.property_view.id] @@ -1091,7 +1091,7 @@ def test_get_data_for_census_tract_fetch(self): "geocoding_confidence": None, "tract": None, "valid_coords": False, - "location": "730 Garcia Street, Boring, Oregon, 97080", + "location": "1070 Hunt Street, Boring, Oregon, 97015", } }, ) diff --git a/seed/tests/test_audit_template_configs.py b/seed/tests/test_audit_template_configs.py index e0e3eaa850..3e3437af15 100644 --- a/seed/tests/test_audit_template_configs.py +++ b/seed/tests/test_audit_template_configs.py @@ -57,7 +57,7 @@ def test_audit_template_config_create(self): assert data["update_at_hour"] == 23 assert data["update_at_minute"] == 59 - # testing one to one relationship + # testing one-to-one relationship response = self.client.post(url, params, content_type="application/json") assert response.status_code == 400 assert response.json()["errors"] == {"organization": ["This field must be unique."]} diff --git a/seed/views/v3/green_assessment_properties.py b/seed/views/v3/green_assessment_properties.py index f6cd4983de..6a2d247716 100644 --- a/seed/views/v3/green_assessment_properties.py +++ b/seed/views/v3/green_assessment_properties.py @@ -92,7 +92,7 @@ class GreenAssessmentPropertyViewSet(SEEDOrgModelViewSet): serializer_class = GreenAssessmentPropertySerializer model = GreenAssessmentProperty orgfilter = "assessment__organization_id" - filter_class = GAPropertyFilterSet + filterset_class = GAPropertyFilterSet @action(detail=True, methods=["get"]) @has_perm_class("requires_root_member_access") diff --git a/seed/views/v3/green_assessment_urls.py b/seed/views/v3/green_assessment_urls.py index da43fa73e4..90cae8e96e 100644 --- a/seed/views/v3/green_assessment_urls.py +++ b/seed/views/v3/green_assessment_urls.py @@ -135,4 +135,4 @@ class GreenAssessmentURLViewSet(SEEDOrgModelViewSet): serializer_class = GreenAssessmentURLSerializer model = GreenAssessmentURL orgfilter = "property_assessment__assessment__organization_id" - filter_fields = ("property_assessment__id",) + filterset_fields = ("property_assessment__id",) diff --git a/seed/views/v3/green_assessments.py b/seed/views/v3/green_assessments.py index 1a11e8bb47..a5d899fcf1 100644 --- a/seed/views/v3/green_assessments.py +++ b/seed/views/v3/green_assessments.py @@ -181,4 +181,4 @@ class GreenAssessmentViewSet(SEEDOrgCreateUpdateModelViewSet): serializer_class = GreenAssessmentSerializer model = GreenAssessment - filter_class = GreenAssessmentFilterSet + filterset_class = GreenAssessmentFilterSet diff --git a/seed/views/v3/property_views.py b/seed/views/v3/property_views.py index 0175526f4f..b0b4f7b16f 100644 --- a/seed/views/v3/property_views.py +++ b/seed/views/v3/property_views.py @@ -89,7 +89,7 @@ def get_queryset(self): serializer_class = BriefPropertyViewSerializer pagination_class = None model = PropertyView - filter_class = PropertyViewFilterSet + filterset_class = PropertyViewFilterSet orgfilter = "property__organization_id" data_name = "property_views" queryset = PropertyView.objects.all() diff --git a/tox.ini b/tox.ini index 08c7063831..9b66bc257f 100644 --- a/tox.ini +++ b/tox.ini @@ -1,106 +1,74 @@ [tox] -envlist= - python, - precommit, - docs, - functional, - apitest, - lint, - lint-fix -skipsdist=True +env_list = + python + precommit + docs + functional + apitest + lint +no_package = True + +[testenv] +deps = -r requirements/test.txt [testenv:python] -deps= - -r{toxinidir}/requirements/test.txt -commands= - ./manage.py flush --noinput +commands = + python manage.py flush_db coverage run manage.py test coveralls -passenv= +pass_env = + DISPLAY DJANGO_LOG_LEVEL DJANGO_SETTINGS_MODULE - DISPLAY - SEED_PM_UN SEED_PM_PW - TRAVIS - TRAVIS_JOB_ID - TRAVIS_BRANCH + SEED_PM_UN TESTING_MAPQUEST_API_KEY -whitelist_externals= - cp +allowlist_externals = python [testenv:precommit] -basepython=python -deps= - -r{toxinidir}/requirements/test.txt -commands= - pre-commit run --all-files {posargs} +commands = pre-commit run --all-files {posargs} [testenv:docs] -changedir=docs -deps= - -r{toxinidir}/requirements/test.txt -commands= +change_dir = docs +commands = # After we fix doc build links/issues, then add the -W flag - ; make spelling SPHINXOPTS='-W --keep-going' - make spelling - sphinx-build -b html -d {envtmpdir}/doctrees {toxinidir}/docs/source {envtmpdir}/html -whitelist_externals= - make - cp + # make spelling SPHINXOPTS='-W --keep-going' + sphinx-build -M spelling source build + sphinx-build -b html -d {envtmpdir}/doctrees source {envtmpdir}/html [testenv:mypy] -basepython=python -deps= - mypy == 1.0.0 -commands=mypy --install-types --non-interactive --show-error-codes {toxinidir} +deps = mypy +commands = mypy --install-types --non-interactive --show-error-codes . [testenv:functional] -commands= - ./manage.py flush --noinput +deps = +commands = npm install npm test -deps= - -r{toxinidir}/requirements/test.txt -passenv= - DJANGO_SETTINGS_MODULE - DISPLAY - COVERALLS_REPO_TOKEN - TRAVIS - SAUCE_USERNAME - SAUCE_ACCESS_KEY - TRAVIS_JOB_NUMBER - TRAVIS_BUILD_NUMBER - MAPQUEST_API_KEY -whitelist_externals= - cp - npm +pass_env = DISPLAY +allowlist_externals = npm [testenv:apitest] -setenv= - CELERY_ALWAYS_EAGER = false - ; when running the API tests make sure to not use always eager -commands= - {toxinidir}/bin/apitest_start_server.sh - python {toxinidir}/seed/tests/api/test_seed_host_api.py --noinput --nofile -deps= - -r{toxinidir}/requirements/test.txt -passenv= - DJANGO_SETTINGS_MODULE -whitelist_externals= - cp +# when running the API tests make sure to not use always eager +setenv = CELERY_ALWAYS_EAGER=false +commands = + sh ./bin/apitest_start_server.sh + python seed/tests/api/test_seed_host_api.py --noinput --nofile +pass_env = DJANGO_SETTINGS_MODULE +allowlist_externals = python + sh [testenv:lint] -commands= - npm install --ignore-scripts +deps = +commands = + npm install npm run lint -whitelist_externals= - npm +allowlist_externals = npm [testenv:lint-fix] -commands= - npm install --ignore-scripts +deps = +commands = + npm install npm run lint:fix -whitelist_externals= - npm +allowlist_externals = npm