Skip to content

Commit

Permalink
feat: upgrade all dependencies, PostgreSQL 10->13, use ruff
Browse files Browse the repository at this point in the history
Done:
 - Upgrade all dependencies
 - Upgrade postgresql from v10 to v13 (v13 is used in production)
 - Use ruff instead of black/isort/flake8, remove noqa's, reformat
 - Use pyproject.toml instead of setup.cfg

Background for @map_enums_to_values_in_kwargs decorator:

Graphene 3 changed from using enum values to enums, for example:
```python
class TestEnum(graphene.Enum):
  FIRST = 'first'
  SECOND = 'second'
```
would've been serialized previously using the enum values, i.e.
'first' and 'second'. But with Graphene 3 they are serialized as
'TestEnum.FIRST' and 'TestEnum.SECOND'. This broke functionality as
parts of the codebase were expecting the enum values as per Graphene 2.

Forced backwards compatibility by forcefully mapping enums to their
values.

Related https://github.com/graphql-python/graphene issues & PRs:
 - "Improve enum compatibility" PR:
   - graphql-python/graphene#1153
 - "graphene3: enum doesn't resolve to value" issue:
   - graphql-python/graphene#1277
 - "I would like my enum input values to be the enum instance instead
   of the enum values" issue:
   - graphql-python/graphene#1151

See https://github.com/graphql-python/graphene/wiki/v3-release-notes
for Graphene v3's breaking changes,

refs PT-1730
  • Loading branch information
karisal-anders committed Oct 11, 2024
1 parent b736d8a commit bcbf88b
Show file tree
Hide file tree
Showing 80 changed files with 4,205 additions and 2,989 deletions.
30 changes: 16 additions & 14 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
# Pre-commit hook documentation:
# - https://pre-commit.com/
# - https://pre-commit.com/hooks.html
#
# Ruff pre-commit hook documentation:
# - https://github.com/astral-sh/ruff-pre-commit
default_language_version:
python: python3.11
repos:
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version
rev: v0.6.9
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
- repo: https://github.com/PyCQA/flake8
rev: 6.0.0
hooks:
- id: flake8
exclude: migrations|snapshots
# Run the linter
- id: ruff
args: [ --fix ]
# Run the formatter
- id: ruff-format
19 changes: 14 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ The project is now running at http://localhost:8081

Prerequisites:

- PostgreSQL 10
- PostgreSQL 13
- Python 3.11

Steps:
Expand Down Expand Up @@ -253,11 +253,20 @@ To view the API documentation, in DEBUG mode visit http://localhost:8081/graphql

## Code format

This project uses [`black`](https://github.com/ambv/black) for Python code formatting.
We follow the basic config, without any modifications. Basic `black` commands:
This project uses [ruff](https://github.com/astral-sh/ruff) for Python code linting and formatting.
Ruff is configured through [pyproject.toml](./pyproject.toml).
Basic `ruff` commands:

- To let `black` do its magic: `black .`
- To see which files `black` would change: `black --check .`
- Check linting: `ruff check` or `ruff check --fix` to auto-fix
- Check & auto-fix linting: `ruff check --fix`
- Format: `ruff format`

Basically:
- Ruff linter (i.e. `ruff check --fix`) does what `flake8` and `isort` did before.
- Ruff formatter (i.e. `ruff format`) does what `black` did before.

Integrations for `ruff` are available for many editors:
- https://docs.astral.sh/ruff/integrations/

Or you can use [`pre-commit`](https://pre-commit.com/) to quickly format your code before committing.

Expand Down
23 changes: 23 additions & 0 deletions common/mixins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class SaveAfterPostGenerationMixin:
"""
Mixin for saving Django model instances after post-generation hooks.
To use this derive the factory class that uses @factory.post_generation
decorator from factory.django.DjangoModelFactory as well as this, e.g.
class TestFactory(SaveAfterPostGenerationMixin, factory.django.DjangoModelFactory)
NOTE: Needs to be before factory.django.DjangoModelFactory in the class
definition to work, because of how Python resolves method resolution order (MRO).
Rationale:
- Because factory 3.3.0 has deprecated saving the instance after
post-generation hooks, and will remove the functionality in the
next major release.
"""

@classmethod
def _after_postgeneration(cls, instance, create, results=None):
"""Save again the instance if creating and at least one hook ran."""
if create and results:
# Some post-generation hooks ran, and may have modified us.
instance.save()
32 changes: 5 additions & 27 deletions common/models.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import django
import uuid
from copy import deepcopy

from django.conf import settings
from django.db import models, transaction
from django.utils.translation import gettext_lazy as _
from parler.managers import TranslatableQuerySet as ParlerTranslatableQuerySet
from parler.models import TranslatableModel as ParlerTranslatableModel

from common.utils import map_enums_to_values_in_kwargs
from palvelutarjotin.exceptions import MissingDefaultTranslationError


Expand All @@ -28,38 +30,13 @@ class Meta:

class TranslatableQuerySet(ParlerTranslatableQuerySet):
@transaction.atomic
@map_enums_to_values_in_kwargs
def create_translatable_object(self, **kwargs):
translations = kwargs.pop("translations")
obj = self.create(**kwargs)
obj.create_or_update_translations(translations)
return obj

def _extract_model_params(self, defaults, **kwargs):
# FIXME: Remove this method when it's possible to update to django-parler 2.0,
# (which is not compatible with django-ilmoitin atm). This function is cherry
# picked from django-parler 2.0 to fix a bug when calling
# queryset.get_or_create(**params)
translated_defaults = {}
if defaults:
for field in self.model._parler_meta.get_all_fields():
try:
translated_defaults[field] = defaults.pop(field)
except KeyError:
pass

if django.VERSION < (2, 2):
lookup, params = super(
ParlerTranslatableQuerySet, self
)._extract_model_params(defaults, **kwargs)
params.update(translated_defaults)
return lookup, params
else:
params = super(ParlerTranslatableQuerySet, self)._extract_model_params(
defaults, **kwargs
)
params.update(translated_defaults)
return params


class TranslatableModel(ParlerTranslatableModel):
objects = TranslatableQuerySet.as_manager()
Expand All @@ -77,6 +54,7 @@ def create_or_update_translations(self, translations):
raise MissingDefaultTranslationError("Default translation is missing")
self.clear_translations()
for translation in translations:
translation = deepcopy(translation)
language_code = translation.pop("language_code")
if language_code not in settings.PARLER_SUPPORTED_LANGUAGE_CODES:
continue
Expand Down
1 change: 1 addition & 0 deletions common/notification_service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import logging

import requests

logger = logging.getLogger(__name__)
Expand Down
5 changes: 3 additions & 2 deletions common/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from unittest.mock import patch
from uuid import UUID

import factory.random
import pytest
import responses
from django.contrib.auth.models import AnonymousUser
from django.test import RequestFactory
from freezegun import freeze_time
from graphene.test import Client
from unittest.mock import patch
from uuid import UUID

import occurrences.signals
from common.tests.json_fixtures import * # noqa
Expand Down
Loading

0 comments on commit bcbf88b

Please sign in to comment.