Skip to content

Commit

Permalink
Merge pull request #467 from City-of-Helsinki/HP-2082-python-graphene…
Browse files Browse the repository at this point in the history
…-django-update

HP-2082 | Update Graphene, Django and Python
  • Loading branch information
charn authored Feb 6, 2024
2 parents 61fabad + 077b6de commit 878e322
Show file tree
Hide file tree
Showing 45 changed files with 919 additions and 796 deletions.
26 changes: 12 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,18 @@ on:
branches: [develop, master]
pull_request:


env:
SECRET_KEY: topsecret123
FIELD_ENCRYPTION_KEYS: f164ec6bd6fbc4aef5647abc15199da0f9badcc1d2127bde2087ae0d794a9a0b


jobs:
test:
name: Tests
runs-on: ubuntu-latest

services:
postgres:
image: postgis/postgis:9.6-2.5
image: postgis/postgis:13-3.2
ports:
- 5432:5432
options: >-
Expand All @@ -33,15 +31,15 @@ jobs:

steps:
- name: Check out repository
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Set up Python 3.7
uses: actions/setup-python@v2
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: '3.7'
python-version: '3.11'

- name: Cache pip packages
uses: actions/cache@v2
uses: actions/cache@v4
env:
cache-name: cache-pip-modules
with:
Expand Down Expand Up @@ -74,15 +72,15 @@ jobs:

steps:
- name: Check out repository
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Set up Python 3.7
uses: actions/setup-python@v2
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: '3.7'
python-version: '3.11'

- name: Cache pip packages
uses: actions/cache@v2
uses: actions/cache@v4
env:
cache-name: cache-pip-modules
with:
Expand All @@ -99,7 +97,7 @@ jobs:
run: flake8

- name: Import sorting
run: isort -c
run: isort . --check --diff

- name: Formatting
run: black --check .
4 changes: 2 additions & 2 deletions .github/workflows/review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
runs-on: ubuntu-latest
name: Build
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Build
uses: andersinno/kolga-build-action@v2

Expand All @@ -35,7 +35,7 @@ jobs:
needs: build
name: Review
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: andersinno/kolga-setup-action@v2

- name: Review-Services
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
runs-on: ubuntu-latest
name: Build
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Build
uses: andersinno/kolga-build-action@v2

Expand All @@ -36,7 +36,7 @@ jobs:
needs: build
name: Staging
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: andersinno/kolga-setup-action@v2

- name: Deploy
Expand Down
18 changes: 13 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
default_language_version:
python: python3
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-toml
- id: check-added-large-files
- repo: https://github.com/psf/black
rev: 19.10b0
rev: 24.1.1
hooks:
- id: black
exclude: "snapshots"
- repo: https://gitlab.com/pycqa/flake8
rev: 3.7.9
- repo: https://github.com/pycqa/flake8
rev: 7.0.0
hooks:
- id: flake8
exclude: "migrations|snapshots"
additional_dependencies: ["pep8-naming"]
- repo: https://github.com/timothycrosley/isort
rev: 4.3.21
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
exclude: "migrations|snapshots"
41 changes: 24 additions & 17 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,53 +1,61 @@
# ==============================
FROM helsinkitest/python:3.7-slim as appbase
FROM python:3.11-slim-bookworm as appbase
# ==============================

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

WORKDIR /app
RUN mkdir /entrypoint

COPY tools /tools
ENV PATH="/tools:${PATH}"

RUN groupadd -g 1000 appuser \
&& useradd -u 1000 -g appuser -ms /bin/bash appuser \
&& chown -R appuser:appuser /app

COPY --chown=appuser:appuser requirements*.txt /app/

RUN apt-install.sh \
git \
curl \
build-essential \
libpq-dev \
gdal-bin \
netcat-openbsd \
pkg-config \
python3-gdal \
postgresql-client \
&& pip install -U pip \
&& pip install --upgrade pip setuptools wheel \
&& pip install --no-cache-dir --no-deps -r /app/requirements.txt \
&& pip install --no-cache-dir -r /app/requirements-prod.txt \
&& apt-cleanup.sh build-essential pkg-config
&& apt-cleanup.sh build-essential

COPY --chown=appuser:appuser docker-entrypoint.sh /entrypoint/docker-entrypoint.sh
ENTRYPOINT ["/entrypoint/docker-entrypoint.sh"]

# ==============================
FROM appbase as staticbuilder
# ==============================

ENV VAR_ROOT /app
COPY --chown=appuser:appuser . /app
RUN python manage.py collectstatic --noinput

# ==============================
FROM appbase as development
# ==============================

COPY --chown=appuser:appuser requirements-dev.txt /app/requirements-dev.txt
RUN pip install --no-cache-dir -r /app/requirements-dev.txt
RUN apt-install.sh build-essential \
&& pip install --no-cache-dir -r /app/requirements-dev.txt \
&& apt-cleanup.sh build-essential

ENV DEV_SERVER=1

COPY --chown=appuser:appuser . /app/

USER appuser

EXPOSE 8080/tcp

# ==============================
FROM appbase as staticbuilder
# ==============================

ENV VAR_ROOT /app
COPY --chown=appuser:appuser . /app
RUN python manage.py collectstatic --noinput

# ==============================
FROM appbase as production
# ==============================
Expand All @@ -56,5 +64,4 @@ COPY --from=staticbuilder --chown=appuser:appuser /app/static /app/static
COPY --chown=appuser:appuser . /app/

USER appuser

EXPOSE 8080/tcp
3 changes: 1 addition & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: '3.7'
services:
postgres:
image: helsinkitest/postgis:9.6-2.5-alpine
image: postgis/postgis:13-3.2-alpine
restart: on-failure
environment:
POSTGRES_USER: open_city_profile
Expand Down Expand Up @@ -36,7 +36,6 @@ volumes:
driver: local
django-media-volume:


networks:
default:
name: helsinki
4 changes: 2 additions & 2 deletions open_city_profile/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from django.core.exceptions import PermissionDenied
from django.utils.translation import gettext_lazy as _
from graphql.execution.base import ResolveInfo
from graphql.type import GraphQLResolveInfo

from open_city_profile.exceptions import ServiceNotIdentifiedError

Expand All @@ -13,7 +13,7 @@ def decorator(decorator_function):
def wrapper(function):
@wraps(function)
def context_tester(*args, **kwargs):
info = next(arg for arg in args if isinstance(arg, ResolveInfo))
info = next(arg for arg in args if isinstance(arg, GraphQLResolveInfo))
context = info.context

for test_func in test_funcs:
Expand Down
36 changes: 18 additions & 18 deletions open_city_profile/graphene.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@
from graphene_django import DjangoObjectType
from graphene_django.forms.converter import convert_form_field
from graphene_django.types import ALL_FIELDS
from graphql_sync_dataloaders import SyncDataLoader
from parler.models import TranslatableModel

from profiles.loaders import (
AddressesByProfileIdLoader,
EmailsByProfileIdLoader,
PhonesByProfileIdLoader,
PrimaryAddressForProfileLoader,
PrimaryEmailForProfileLoader,
PrimaryPhoneForProfileLoader,
addresses_by_profile_id_loader,
emails_by_profile_id_loader,
phones_by_profile_id_loader,
primary_address_for_profile_loader,
primary_email_for_profile_loader,
primary_phone_for_profile_loader,
)


Expand Down Expand Up @@ -52,12 +53,12 @@ class UUIDMultipleChoiceFilter(MultipleChoiceFilter):


_LOADERS = {
"addresses_by_profile_id_loader": AddressesByProfileIdLoader,
"emails_by_profile_id_loader": EmailsByProfileIdLoader,
"phones_by_profile_id_loader": PhonesByProfileIdLoader,
"primary_address_for_profile_loader": PrimaryAddressForProfileLoader,
"primary_email_for_profile_loader": PrimaryEmailForProfileLoader,
"primary_phone_for_profile_loader": PrimaryPhoneForProfileLoader,
"addresses_by_profile_id_loader": addresses_by_profile_id_loader,
"emails_by_profile_id_loader": emails_by_profile_id_loader,
"phones_by_profile_id_loader": phones_by_profile_id_loader,
"primary_address_for_profile_loader": primary_address_for_profile_loader,
"primary_email_for_profile_loader": primary_email_for_profile_loader,
"primary_phone_for_profile_loader": primary_phone_for_profile_loader,
}


Expand All @@ -69,17 +70,16 @@ def resolve(self, next, root, info, **kwargs):
context = info.context

if not self.cached_loaders:
for loader_name, loader_class in _LOADERS.items():
setattr(context, loader_name, loader_class())

for loader_name, loader_function in _LOADERS.items():
setattr(context, loader_name, SyncDataLoader(loader_function))
self.cached_loaders = True

return next(root, info, **kwargs)


def _parler_field_resolver(attname, instance, info, language=None):
if language:
return instance.safe_translation_getter(attname, language_code=language)
return instance.safe_translation_getter(attname, language_code=language.value)

return getattr(instance, attname)

Expand Down Expand Up @@ -151,7 +151,7 @@ def __init_subclass_with_meta__(
interfaces=(),
convert_choices_to_enum=True,
_meta=None,
**options
**options,
):
assert issubclass(model, TranslatableModel), (
'You need to pass a valid Django Parler Model in {}.Meta, received "{}".'
Expand All @@ -176,5 +176,5 @@ def __init_subclass_with_meta__(
interfaces=interfaces,
convert_choices_to_enum=convert_choices_to_enum,
_meta=_meta,
**options
**options,
)
19 changes: 14 additions & 5 deletions open_city_profile/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
from graphene.test import Client as GrapheneClient
from graphene_django.settings import graphene_settings
from graphene_django.views import instantiate_middleware
from graphql import build_client_schema, introspection_query
from graphql import build_client_schema, get_introspection_query
from graphql_sync_dataloaders import DeferredExecutionContext
from helusers.authz import UserAuthorization

from open_city_profile.schema import schema
Expand All @@ -33,7 +34,7 @@ def execute(
auth_token_payload=None,
service=_not_provided,
context=None,
**kwargs
**kwargs,
):
"""
Custom execute method which adds all of the middlewares defined in the
Expand Down Expand Up @@ -70,7 +71,7 @@ def execute(
*args,
context=context,
middleware=list(instantiate_middleware(graphene_settings.MIDDLEWARE)),
**kwargs
**kwargs,
)


Expand Down Expand Up @@ -127,6 +128,11 @@ def keycloak_setup(settings):
settings.KEYCLOAK_CLIENT_SECRET = "test-keycloak-client-secret"


@pytest.fixture
def execution_context_class():
return DeferredExecutionContext


@pytest.fixture
def user():
return UserFactory()
Expand Down Expand Up @@ -178,8 +184,11 @@ def superuser_gql_client():


@pytest.fixture
def gql_schema(anon_user_gql_client):
introspection = anon_user_gql_client.execute(introspection_query)
def gql_schema(anon_user_gql_client, execution_context_class):
introspection = anon_user_gql_client.execute(
get_introspection_query(descriptions=False),
execution_context_class=execution_context_class,
)
return build_client_schema(introspection["data"])


Expand Down
Loading

0 comments on commit 878e322

Please sign in to comment.