Skip to content

Commit

Permalink
Merge branch 'saleor:main' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
iamleson98 authored Jan 16, 2025
2 parents 14dea7b + 4130011 commit 80761df
Show file tree
Hide file tree
Showing 373 changed files with 5,317 additions and 2,718 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ repos:
exclude_types: [svg]

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.4
rev: v0.9.1
hooks:
- id: ruff
- id: ruff-format
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ All notable, unreleased changes to this project will be documented in this file.
- `RequestPasswordReset`,
`RequestPasswordReset` will now require `channel` as input for staff users,
- `SetPassword` - #16243 by @kadewu
- Require `MANAGE_ORDERS` for updating order and order line metadata - #17223 by @IKarbowiak
- The `updateMetadata` for `Order` and `OrderLine` types requires the `MANAGE_ORDERS` permission

### GraphQL API

Expand Down Expand Up @@ -49,3 +51,5 @@ All notable, unreleased changes to this project will be documented in this file.
- Fix decreasing voucher code usage after changing `includeDraftOrderInVoucherUsage` to false - #17028 by @zedzior
- Fix undiscounted price taxation when prices are entered with taxes - #16992 by @zedzior
- Fix `products` sorting when using `sortBy: {field: COLLECTION}` - #17189 by @korycins
- Fix checkout funds releasing task - #17198 by @IKarbowiak
- Fixed 'healthcheck' middleware (`/health/` endpoint) not forwarding incoming traffic whenever the protocol wasn't HTTP (such as WebSocket or Lifespan) - #17248 by @NyanKiyoshi
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@
<a href="https://docs.saleor.io/">
<img src="https://img.shields.io/badge/docs-docs.saleor.io-brightgreen.svg" alt="Documentation" />
</a>
<a href="https://github.com/python/black">
<img src="https://img.shields.io/badge/code%20style-black-000000.svg" alt="Code style: black">
<a href="https://github.com/astral-sh/ruff">
<img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Linted by Ruff">
</a>
</div>

Expand Down
685 changes: 464 additions & 221 deletions poetry.lock

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ package-mode = false
azure-common = "^1.1.28"
azure-storage-blob = "^12.23.1"
azure-storage-common = "^2.1.0"
babel = ">=2.8,<2.15"
babel = ">=2.8,<2.17"
boto3 = "^1.28"
botocore = "^1.35"
braintree = ">=4.2,<4.30"
braintree = ">=4.2,<4.32"
cryptography = "^43.0.1"
dj-database-url = "^2"
dj-email-url = "^1"
Expand All @@ -37,7 +37,7 @@ package-mode = false
django-filter = "^24.3"
django-measurement = "^3.0"
django-mptt = "^0"
django-phonenumber-field = ">=4,<8"
django-phonenumber-field = ">=4,<9"
django-prices = "^2.3"
django-stubs-ext = "^5.1.1"
draftjs-sanitizer = "^1.0.0"
Expand All @@ -59,16 +59,16 @@ package-mode = false
opentracing = "^2.3.0"
petl = "1.7.15"
phonenumberslite = "^8.13.52"
pillow = "^11.0.0"
pillow = "^11.1.0"
pillow-avif-plugin = "^1.3.1"
posuto = "^2024.7.0"
posuto = "^2025.1.0"
prices = "^1.0"
promise = "^2.3"
pybars3 = "^0.9.7"
pyjwt = "^2.10.1"
python-dateutil = "^2.8.2"
python-http-client = "^3.3.7"
python-json-logger = ">=0.1.11,<2.1.0"
python-json-logger = ">=0.1.11,<3.3.0"
pytimeparse = "^1.1.8"
razorpay = "^1.2"
redis = "^5.0.1"
Expand Down Expand Up @@ -114,7 +114,7 @@ package-mode = false
pytest = "^8.3.2"
pytest-asyncio = "^0.25.0"
pytest-celery = "^1.0.1"
pytest-cov = "^5.0.0"
pytest-cov = "^6.0.0"
pytest-django = "4.9.0"
pytest-django-queries = "~1.2"
pytest-memray = "^1.5.0"
Expand All @@ -123,7 +123,7 @@ package-mode = false
pytest-socket = "^0.7.0"
pytest-xdist = "^3.0.2"
pywatchman = "^2.0.0"
ruff = "^0.8.4"
ruff = "^0.9.1"
semgrep = ">=1.34.0"
types-certifi = "^2021.10.8"
types-freezegun = "^1.1.7"
Expand Down Expand Up @@ -177,7 +177,7 @@ exclude = [


[tool.ruff]
target-version = "py39"
target-version = "py312"

[tool.ruff.lint]
select = [
Expand Down
32 changes: 15 additions & 17 deletions saleor/account/events.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
from typing import Optional

from ..app.models import App
from ..order.models import Order, OrderLine
from . import CustomerEvents
from .models import CustomerEvent, User


def customer_account_created_event(*, user: User) -> Optional[CustomerEvent]:
def customer_account_created_event(*, user: User) -> CustomerEvent | None:
return CustomerEvent.objects.create(user=user, type=CustomerEvents.ACCOUNT_CREATED)


def customer_account_activated_event(
*, staff_user: Optional[User], app: Optional[App], account_id: int
) -> Optional[CustomerEvent]:
*, staff_user: User | None, app: App | None, account_id: int
) -> CustomerEvent | None:
return CustomerEvent.objects.create(
user=staff_user,
app=app,
Expand All @@ -22,8 +20,8 @@ def customer_account_activated_event(


def customer_account_deactivated_event(
*, staff_user: Optional[User], app: Optional[App], account_id: int
) -> Optional[CustomerEvent]:
*, staff_user: User | None, app: App | None, account_id: int
) -> CustomerEvent | None:
return CustomerEvent.objects.create(
user=staff_user,
app=app,
Expand All @@ -32,44 +30,44 @@ def customer_account_deactivated_event(
)


def customer_password_reset_link_sent_event(*, user_id: int) -> Optional[CustomerEvent]:
def customer_password_reset_link_sent_event(*, user_id: int) -> CustomerEvent | None:
return CustomerEvent.objects.create(
user_id=user_id, type=CustomerEvents.PASSWORD_RESET_LINK_SENT
)


def customer_password_reset_event(*, user: User) -> Optional[CustomerEvent]:
def customer_password_reset_event(*, user: User) -> CustomerEvent | None:
return CustomerEvent.objects.create(user=user, type=CustomerEvents.PASSWORD_RESET)


def customer_password_changed_event(*, user: User) -> Optional[CustomerEvent]:
def customer_password_changed_event(*, user: User) -> CustomerEvent | None:
return CustomerEvent.objects.create(user=user, type=CustomerEvents.PASSWORD_CHANGED)


def customer_email_change_request_event(
*, user_id: int, parameters: dict
) -> Optional[CustomerEvent]:
) -> CustomerEvent | None:
return CustomerEvent.objects.create(
user_id=user_id, type=CustomerEvents.EMAIL_CHANGE_REQUEST, parameters=parameters
)


def customer_email_changed_event(
*, user_id: int, parameters: dict
) -> Optional[CustomerEvent]:
) -> CustomerEvent | None:
return CustomerEvent.objects.create(
user_id=user_id, type=CustomerEvents.EMAIL_CHANGED, parameters=parameters
)


def customer_placed_order_event(*, user: User, order: Order) -> Optional[CustomerEvent]:
def customer_placed_order_event(*, user: User, order: Order) -> CustomerEvent | None:
return CustomerEvent.objects.create(
user=user, order=order, type=CustomerEvents.PLACED_ORDER
)


def customer_added_to_note_order_event(
*, user: Optional[User], order: Order, message: str
*, user: User | None, order: Order, message: str
) -> CustomerEvent:
return CustomerEvent.objects.create(
user=user,
Expand All @@ -91,7 +89,7 @@ def customer_downloaded_a_digital_link_event(


def customer_deleted_event(
*, staff_user: Optional[User], app: Optional[App], deleted_count: int = 1
*, staff_user: User | None, app: App | None, deleted_count: int = 1
) -> CustomerEvent:
return CustomerEvent.objects.create(
user=staff_user,
Expand All @@ -103,7 +101,7 @@ def customer_deleted_event(


def assigned_email_to_a_customer_event(
*, staff_user: Optional[User], app: Optional[App], new_email: str
*, staff_user: User | None, app: App | None, new_email: str
) -> CustomerEvent:
return CustomerEvent.objects.create(
user=staff_user,
Expand All @@ -115,7 +113,7 @@ def assigned_email_to_a_customer_event(


def assigned_name_to_a_customer_event(
*, staff_user: Optional[User], app: Optional[App], new_name: str
*, staff_user: User | None, app: App | None, new_name: str
) -> CustomerEvent:
return CustomerEvent.objects.create(
user=staff_user,
Expand Down
5 changes: 2 additions & 3 deletions saleor/account/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from collections.abc import Iterable
from functools import partial
from typing import Union
from uuid import uuid4

from django.conf import settings
Expand Down Expand Up @@ -301,7 +300,7 @@ def get_full_name(self):
def get_short_name(self):
return self.email

def has_perm(self, perm: Union[BasePermissionEnum, str], obj=None) -> bool:
def has_perm(self, perm: BasePermissionEnum | str, obj=None) -> bool:
# This method is overridden to accept perm as BasePermissionEnum
perm = perm.value if isinstance(perm, BasePermissionEnum) else perm

Expand All @@ -311,7 +310,7 @@ def has_perm(self, perm: Union[BasePermissionEnum, str], obj=None) -> bool:
return _user_has_perm(self, perm, obj)

def has_perms(
self, perm_list: Iterable[Union[BasePermissionEnum, str]], obj=None
self, perm_list: Iterable[BasePermissionEnum | str], obj=None
) -> bool:
# This method is overridden to accept perm as BasePermissionEnum
perm_list = [
Expand Down
3 changes: 1 addition & 2 deletions saleor/account/notifications.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from typing import Optional
from urllib.parse import urlencode

from django.contrib.auth.tokens import default_token_generator
Expand Down Expand Up @@ -39,7 +38,7 @@ def get_user_custom_payload(user: User):


def send_password_reset_notification(
redirect_url, user, manager, channel_slug: Optional[str], staff=False
redirect_url, user, manager, channel_slug: str | None, staff=False
):
"""Trigger sending a password reset notification for the given customer/staff."""

Expand Down
3 changes: 1 addition & 2 deletions saleor/account/throttling.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import datetime
import logging
from math import ceil
from typing import Optional

from django.core.cache import cache
from django.core.exceptions import ValidationError
Expand All @@ -19,7 +18,7 @@
logger = logging.getLogger(__name__)


def authenticate_with_throttling(request, email, password) -> Optional[models.User]:
def authenticate_with_throttling(request, email, password) -> models.User | None:
ip = get_client_ip(request)
if not ip:
logger.warning("Unknown request's IP address.")
Expand Down
6 changes: 3 additions & 3 deletions saleor/account/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from dataclasses import dataclass
from typing import TYPE_CHECKING, Optional
from typing import TYPE_CHECKING

from django.conf import settings
from django.db.models import Exists, OuterRef
Expand All @@ -19,8 +19,8 @@
@dataclass
class RequestorAwareContext:
allow_replica: bool
user: Optional[User] = None
app: Optional[App] = None
user: User | None = None
app: App | None = None

@property
def META(self):
Expand Down
9 changes: 4 additions & 5 deletions saleor/app/installation_utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import logging
import time
from io import BytesIO
from typing import Optional, Union

import requests
from celery.exceptions import MaxRetriesExceededError
Expand Down Expand Up @@ -134,7 +133,7 @@ def fetch_brand_data(manifest_data, timeout=settings.COMMON_REQUESTS_TIMEOUT):
return brand_data


def _set_brand_data(brand_obj: Optional[Union[App, AppInstallation]], logo: File):
def _set_brand_data(brand_obj: App | AppInstallation | None, logo: File):
if not brand_obj:
return
try:
Expand Down Expand Up @@ -183,8 +182,8 @@ def fetch_brand_data_task(
def fetch_brand_data_async(
manifest_data: dict,
*,
app_installation: Optional[AppInstallation] = None,
app: Optional[App] = None,
app_installation: AppInstallation | None = None,
app: App | None = None,
):
if brand_data := manifest_data.get("brand"):
app_id = app.pk if app else None
Expand Down Expand Up @@ -255,7 +254,7 @@ def install_app(app_installation: AppInstallation, activate: bool = False):

webhook_events = []
for db_webhook, manifest_webhook in zip(
webhooks, manifest_data.get("webhooks", [])
webhooks, manifest_data.get("webhooks", []), strict=False
):
for event_type in manifest_webhook["events"]:
webhook_events.append(
Expand Down
4 changes: 2 additions & 2 deletions saleor/app/management/commands/create_app.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import json
from typing import Any, Optional
from typing import Any

import graphene
from django.core.management import BaseCommand, CommandError
Expand Down Expand Up @@ -72,7 +72,7 @@ def send_app_data(self, target_url, data: dict[str, Any]):
raise CommandError(f"Request failed. Exception: {e}") from e
response.raise_for_status()

def handle(self, *args: Any, **options: Any) -> Optional[str]:
def handle(self, *args: Any, **options: Any) -> str | None:
name = options["name"]
is_active = options["activate"]
target_url = options["target_url"]
Expand Down
4 changes: 2 additions & 2 deletions saleor/app/management/commands/install_app.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import json
from typing import Any, Optional
from typing import Any

from django.core.exceptions import ValidationError
from django.core.management import BaseCommand, CommandError
Expand Down Expand Up @@ -33,7 +33,7 @@ def validate_manifest_url(self, manifest_url: str):
f"Incorrect format of manifest-url: {manifest_url}"
) from e

def handle(self, *args: Any, **options: Any) -> Optional[str]:
def handle(self, *args: Any, **options: Any) -> str | None:
activate = options["activate"]
manifest_url = options["manifest-url"]

Expand Down
Loading

0 comments on commit 80761df

Please sign in to comment.