Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[COST-4514] Upgrade to django 4.0 #4839

Merged
merged 8 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,14 @@ celery = ">=5.2.2"
ciso8601 = ">=2.1"
confluent-kafka = ">=2.1.0"
croniter = "*"
Django = "<4.0"
Django = "<4.1"
django-cors-headers = ">=3.1"
django-environ = ">=0.4"
django-extensions = ">=2.2"
django-filter = ">=2.2"
django-prometheus = ">=1.1"
django-redis = ">=4.10"
django-tenants = ">=3.4"
djangorestframework = ">=3.11,!=3.14.0"
djangorestframework = ">=3.14.0"
djangorestframework-csv = ">=2.1"
google-api-python-client = ">=1.12.4"
google-auth = ">=1.22.1"
Expand All @@ -50,6 +49,7 @@ psycopg2 = ">=2.9"
pyarrow = ">=0.17.1"
python-dateutil = ">=2.8"
querystring-parser = ">=1.2"
redis = ">=5.0.1"
requests = ">=2.20"
sentry-sdk = ">=0.13"
statsmodels = ">=0.12"
Expand Down
1,141 changes: 516 additions & 625 deletions Pipfile.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions koku/api/common/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# noqa
from uuid import UUID

from django.utils.translation import ugettext as _
from django.utils.translation import gettext

RH_IDENTITY_HEADER = "HTTP_X_RH_IDENTITY"

Expand All @@ -11,7 +11,7 @@

def error_obj(key, message):
"""Create an error object."""
return {key: [_(message)]}
return {key: [gettext(message)]}


def log_json(tracing_id="", *, msg, context=None, **kwargs):
Expand Down
6 changes: 3 additions & 3 deletions koku/api/dataexport/syncer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from dateutil.rrule import MONTHLY
from dateutil.rrule import rrule
from django.conf import settings
from django.utils.translation import gettext as _
from django.utils.translation import gettext

from api.provider.models import Provider

Expand Down Expand Up @@ -85,15 +85,15 @@ def _copy_object(self, s3_destination_bucket, source_object):
if source_object.storage_class == "GLACIER" and e.response["Error"]["Code"] == "InvalidObjectState":
request = {"Days": 2, "GlacierJobParameters": {"Tier": "Standard"}}
source_object.restore_object(RestoreRequest=request)
LOG.info(_("Glacier Storage restore for %s is in progress."), source_object.key)
LOG.info(gettext("Glacier Storage restore for %s is in progress."), source_object.key)
raise SyncedFileInColdStorageError(
f"Requested file {source_object.key} is currently in AWS Glacier Storage, "
f"an request has been made to restore the file."
)
# if object cannot be copied because restore is already in progress raise
# SyncedFileInColdStorageError and wait a while longer
elif e.response["Error"]["Code"] == "RestoreAlreadyInProgress":
LOG.info(_("Glacier Storage restore for %s is in progress."), source_object.key)
LOG.info(gettext("Glacier Storage restore for %s is in progress."), source_object.key)
raise SyncedFileInColdStorageError(
f"Requested file {source_object.key} has not yet been restored from AWS Glacier Storage."
)
Expand Down
16 changes: 7 additions & 9 deletions koku/api/dataexport/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,7 @@
class DataExportRequestValidator:
"""Validator that ensures date fields are appropriately defined for a new request."""

def set_context(self, serializer):
"""
Set extra data from the serializer so we can do extra lookup validation.

This hook is called by the serializer instance prior to the validation call being made.
"""
self.queryset = serializer.context["view"].get_queryset()
self.instance = getattr(serializer, "instance", None)
requires_context = True

def pending_instance_exists(self, start_date, end_date):
"""Check for a pending or processing instance that matches the requested dates."""
Expand All @@ -29,8 +22,13 @@ def pending_instance_exists(self, start_date, end_date):
)
return queryset.exists()

def __call__(self, attrs):
def __call__(self, attrs, serializer_field):
"""Enforce validation of all relevant fields."""

# Set extra data from the serializer to do extra lookup validation.
self.queryset = serializer_field.context["view"].get_queryset()
self.instance = getattr(serializer_field, "instance", None)

start_date = attrs["start_date"]
end_date = attrs["end_date"]
if end_date < start_date:
Expand Down
4 changes: 2 additions & 2 deletions koku/api/deprecated_settings/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
"""View for Settings."""
from django.utils.decorators import method_decorator
from django.utils.translation import ugettext as _
from django.utils.translation import gettext
from django.views.decorators.cache import never_cache
from rest_framework.response import Response
from rest_framework.serializers import ValidationError
Expand Down Expand Up @@ -39,7 +39,7 @@ def post(self, request):
"""Handle all changed settings."""
if not isinstance(request.data, dict):
msg = "Invalid input format."
raise ValidationError({"details": _(msg)})
raise ValidationError({"details": gettext(msg)})
for settings_clazz in SETTINGS_GENERATORS.values():
instance = settings_clazz(request)
instance.handle_settings(request.data)
Expand Down
4 changes: 3 additions & 1 deletion koku/api/iam/test/iam_test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,12 +255,14 @@ def wrapper(*args, **kwargs):
"entitlements": {"cost_management": {"is_entitled": "True"}},
}

get_response = Mock()

with override_settings(DEVELOPMENT=True):
with override_settings(DEVELOPMENT_IDENTITY=identity):
with override_settings(FORCE_HEADER_OVERRIDE=True):
with override_settings(MIDDLEWARE=middleware):
request_context = IamTestCase._create_request_context(self.customer, user)
middleware = DevelopmentIdentityHeaderMiddleware()
middleware = DevelopmentIdentityHeaderMiddleware(get_response)
middleware.process_request(request_context["request"])
result = function(*args, **kwargs)
return result
Expand Down
4 changes: 2 additions & 2 deletions koku/api/metrics/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""Views for CostModelMetricsMap."""
import copy

from django.utils.encoding import force_text
from django.utils.encoding import force_str
from django.views.decorators.vary import vary_on_headers
from rest_framework import permissions
from rest_framework import status
Expand Down Expand Up @@ -55,4 +55,4 @@ class CostModelMetricMapJSONException(APIException):
def __init__(self, message):
"""Initialize with status code 500."""
self.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
self.detail = {"detail": force_text(message)}
self.detail = {"detail": force_str(message)}
6 changes: 3 additions & 3 deletions koku/api/query_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from django.conf import settings
from django.core.exceptions import PermissionDenied
from django.db.models import Q
from django.utils.translation import ugettext as _
from django.utils.translation import gettext
from django_tenants.utils import tenant_context
from querystring_parser import parser
from rest_framework.serializers import ValidationError
Expand Down Expand Up @@ -188,7 +188,7 @@ def _get_providers(self, provider):
for p in provider_list:
if self.provider_resource_list.get(p) is None:
msg = f'Invalid provider "{p}".'
raise ValidationError({"details": _(msg)})
raise ValidationError({"details": gettext(msg)})
access.extend(self.provider_resource_list[p])
return access

Expand Down Expand Up @@ -619,4 +619,4 @@ def get_tenant(user):
pass
if tenant:
return tenant
raise ValidationError({"details": _("Invalid user definition")})
raise ValidationError({"details": gettext("Invalid user definition")})
12 changes: 7 additions & 5 deletions koku/api/report/aws/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# SPDX-License-Identifier: Apache-2.0
#
"""AWS Report Serializers."""
from django.utils.translation import ugettext as _
from django.utils.translation import gettext
from rest_framework import serializers

from api.report.constants import AWS_COST_TYPE_CHOICES
Expand Down Expand Up @@ -122,7 +122,7 @@ def validate(self, data):
data["cost_type"] = get_cost_type(self.context.get("request"))
error = {}
if "delta" in data.get("order_by", {}) and "delta" not in data:
error["order_by"] = _("Cannot order by delta without a delta param")
error["order_by"] = gettext("Cannot order by delta without a delta param")
raise serializers.ValidationError(error)
return data

Expand Down Expand Up @@ -162,7 +162,7 @@ def validate_group_by(self, value):
# group_by[org_unit_id]=x&group_by[or:org_unit_id]=OU_001 is invalid
# If we ever want to change this we need to decide what would be appropriate to see
# here.
error = {"or_unit_id": _("Multiple org_unit_id must be represented with the or: prefix.")}
error = {"or_unit_id": gettext("Multiple org_unit_id must be represented with the or: prefix.")}
raise serializers.ValidationError(error)
key_used = key_used[0]
request = self.context.get("request")
Expand All @@ -172,13 +172,15 @@ def validate_group_by(self, value):
# or if we are grouping by org_unit_id with the * since that is essentially grouping by
# accounts. If we ever want to change this we need to decide what would be appropriate to see
# here. Such as all org units or top level org units
error = {"org_unit_id": _("Unsupported parameter or invalid value")}
error = {"org_unit_id": gettext("Unsupported parameter or invalid value")}
raise serializers.ValidationError(error)
if "or:" not in key_used:
if isinstance(group_by_params.get(key_used), list):
if len(group_by_params.get(key_used)) > 1:
# group_by[org_unit_id]=x&group_by[org_unit_id]=OU_001 is invalid
# because no child nodes would ever intersect due to the tree structure.
error = {"or_unit_id": _("Multiple org_unit_id must be represented with the or: prefix.")}
error = {
"or_unit_id": gettext("Multiple org_unit_id must be represented with the or: prefix.")
}
raise serializers.ValidationError(error)
return value
4 changes: 2 additions & 2 deletions koku/api/report/oci/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# SPDX-License-Identifier: Apache-2.0
#
"""OCI Report Serializers."""
from django.utils.translation import ugettext as _
from django.utils.translation import gettext
from rest_framework import serializers

from api.report.serializers import ExcludeSerializer as BaseExcludeSerializer
Expand Down Expand Up @@ -95,6 +95,6 @@
data["cost_type"] = get_cost_type(self.context.get("request"))
error = {}
if "delta" in data.get("order_by", {}) and "delta" not in data:
error["order_by"] = _("Cannot order by delta without a delta param")
error["order_by"] = gettext("Cannot order by delta without a delta param")

Check warning on line 98 in koku/api/report/oci/serializers.py

View check run for this annotation

Codecov / codecov/patch

koku/api/report/oci/serializers.py#L98

Added line #L98 was not covered by tests
raise serializers.ValidationError(error)
return data
14 changes: 7 additions & 7 deletions koku/api/report/ocp/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# SPDX-License-Identifier: Apache-2.0
#
"""OCP Report Serializers."""
from django.utils.translation import ugettext as _
from django.utils.translation import gettext
from rest_framework import serializers

from api.models import Provider
Expand All @@ -20,7 +20,7 @@
def order_by_field_requires_group_by(data, order_name, group_by_key):
error = {}
if order_name in data.get("order_by", {}) and group_by_key not in data.get("group_by", {}):
error["order_by"] = _(f"Cannot order by field {order_name} without grouping by {group_by_key}.")
error["order_by"] = gettext(f"Cannot order by field {order_name} without grouping by {group_by_key}.")
raise serializers.ValidationError(error)


Expand Down Expand Up @@ -161,15 +161,15 @@ def validate(self, data):
super().validate(data)
error = {}
if "delta" in data.get("order_by", {}) and "delta" not in data:
error["order_by"] = _("Cannot order by delta without a delta param")
error["order_by"] = gettext("Cannot order by delta without a delta param")
raise serializers.ValidationError(error)
order_by_field_requires_group_by(data, DISTRIBUTED_COST_INTERNAL["distributed_cost"], "project")
order_by_field_requires_group_by(data, "storage_class", "persistentvolumeclaim")
order_by_field_requires_group_by(data, "persistentvolumeclaim", "persistentvolumeclaim")
if data.get("delta") == DISTRIBUTED_COST_INTERNAL["distributed_cost"] and "project" not in data.get(
"group_by", {}
):
error["delta"] = _("Cannot use distributed_cost delta without grouping by project.")
error["delta"] = gettext("Cannot use distributed_cost delta without grouping by project.")
raise serializers.ValidationError(error)
return data

Expand Down Expand Up @@ -202,15 +202,15 @@ def validate_delta(self, value):
if "__" in value:
values = value.split("__")
if len(values) != 2:
error[value] = _("Only two fields may be compared")
error[value] = gettext("Only two fields may be compared")
raise serializers.ValidationError(error)
for val in values:
if val not in self.delta_fields:
error[value] = _("Unsupported parameter")
error[value] = gettext("Unsupported parameter")
raise serializers.ValidationError(error)
else:
if value not in self.delta_choices:
error[value] = _("Unsupported parameter")
error[value] = gettext("Unsupported parameter")
raise serializers.ValidationError(error)
return value

Expand Down
12 changes: 6 additions & 6 deletions koku/api/report/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import copy
from collections.abc import Mapping

from django.utils.translation import ugettext as _
from django.utils.translation import gettext
from rest_framework import serializers
from rest_framework.fields import DateField

Expand Down Expand Up @@ -43,7 +43,7 @@ def handle_invalid_fields(this, data):
if unknown_keys:
error = {}
for unknown_key in unknown_keys:
error[unknown_key] = _("Unsupported parameter or invalid value")
error[unknown_key] = gettext("Unsupported parameter or invalid value")
raise serializers.ValidationError(error)
return data

Expand Down Expand Up @@ -82,7 +82,7 @@ def validate_field(this, field, serializer_cls, value, **kwargs):
subclasses = serializer_cls.__subclasses__()
if subclasses and not serializer.is_valid():
message = "Unsupported parameter or invalid value"
error = serializers.ValidationError({field: _(message)})
error = serializers.ValidationError({field: gettext(message)})
for subcls in subclasses:
for parent in subcls.__bases__:
# when using multiple inheritance, the data is valid as long as one
Expand Down Expand Up @@ -502,7 +502,7 @@ def validate_order_by(self, value): # noqa: C901
continue # fields that do not require a group-by

if "or:" in key:
error[key] = _(f'The order_by key "{key}" can not contain the or parameter.')
error[key] = gettext(f'The order_by key "{key}" can not contain the or parameter.')
raise serializers.ValidationError(error)

if "group_by" in self.initial_data:
Expand Down Expand Up @@ -537,12 +537,12 @@ def validate_order_by(self, value): # noqa: C901
and value.get("date") <= dh.today.date()
):
continue
error[key] = _(
error[key] = gettext(
f"Order-by date must be from {materialized_view_month_start(dh).date()} to {dh.today.date()}"
)
raise serializers.ValidationError(error)

error[key] = _(f'Order-by "{key}" requires matching Group-by.')
error[key] = gettext(f'Order-by "{key}" requires matching Group-by.')
raise serializers.ValidationError(error)
validate_field(self, "order_by", self.ORDER_BY_SERIALIZER, value)
return value
Expand Down
4 changes: 2 additions & 2 deletions koku/api/settings/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from dataclasses import field

from django.utils.decorators import method_decorator
from django.utils.encoding import force_text
from django.utils.encoding import force_str
from django.views.decorators.cache import never_cache
from rest_framework import permissions
from rest_framework import status
Expand Down Expand Up @@ -39,7 +39,7 @@ class SettingsInvalidFilterException(APIException):
def __init__(self, message):
"""Initialize with status code 404."""
self.status_code = status.HTTP_404_NOT_FOUND
self.detail = {"detail": force_text(message)}
self.detail = {"detail": force_str(message)}


@dataclass
Expand Down
Loading
Loading