[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "saleor" version = "3.24.0-a.0" description = "A modular, high performance, headless e-commerce platform built with Python, GraphQL, Django, and React." authors = [{ name = "Saleor Commerce", email = "hello@saleor.io" }] requires-python = ">=3.12,<3.13" readme = "README.md" license = "BSD-3-Clause" dependencies = [ "asgiref>=3.11.1,<4", "authlib>=1.6.12,<2", "azure-common>=1.1.28,<2", "azure-storage-blob>=12.29.0,<13", "azure-storage-common>=2.1.0,<3", "babel>=2.18.0,<2.19", "boto3~=1.43", "botocore~=1.43", "cryptography>=50.0.2", "dj-database-url>=3.1.2,<4", "dj-email-url>=1,<2", "django[bcrypt]~=5.2.17", "django-cache-url>=3.4.6,<4", "django-celery-beat>=2.8.1,<3", "django-countries~=7.2", "django-filter~=26.1", "django-measurement~=3.0", "django-mptt>=0,<1", "django-phonenumber-field>=8.4.0,<9", "django-stubs-ext>=5.1.3,<6", "faker>=40.32.0,<41.0", "google-cloud-pubsub>=2.39.0,<3.0", "google-cloud-storage>=2.0.0,<3", "google-i18n-address>=3.1.0,<4", "graphene<3.0", "graphql-core>=2.3.2,<3", "graphql-relay>=2.0.1,<3", "lxml>=6.1.1,<7", "measurement>=3.2.2,<4", "micawber>=0.6.2,<0.7", "oauthlib~=3.1", "petl==1.7.20", "phonenumberslite>=9.0.36,<10", "pillow>=12.3.0,<13", "prices~=1.0", "promise~=2.3", "pybars3>=0.9.7,<0.10", "pyjwt>=2.15.0,<3", "python-dateutil>=2.8.2,<3", "python-json-logger>=0.1.11,<3.3.0", "pytimeparse>=1.1.8,<2", "redis>=5.0.1,<6", "requests>=2.33.0,<3", "requests-hardened>=1.3.0,<2.0.0", "Rx>=1.6.3,<2", "semantic-version>=2.10.0,<3", "sentry-sdk~=2.58", "stripe>=3.0.0,<4", "text-unidecode~=1.2", "urllib3>=2.8.0,<3", "uvicorn[standard]==0.52.1", "psycopg[binary]>=3.3.4,<4", "pydantic>=2.13.4,<3", "pydantic-core>=2.33.0,<3", "opentelemetry-api>=1.32.1,<2", "opentelemetry-sdk>=1.32.1,<2", "opentelemetry-semantic-conventions>=0.53b1,<0.54", "opentelemetry-distro[otlp]>=0.53b1,<0.54", "celery[redis, sqs]>=5.6.3,<6.0.0", "kombu[sqs]>=4.6.11,<6.0.0", "django-storages[google]~=1.11", "python-magic>=0.4.27,<0.5 ; sys_platform != 'win32'", "python-magic-bin>=0.4.14,<0.5 ; sys_platform == 'win32'", "nh3>=0.2.20", "idna>=3.18", "orjson>=3.11.9", ] [project.urls] Homepage = "https://saleor.io/" Repository = "https://github.com/saleor/saleor" Documentation = "https://docs.saleor.io/" [dependency-groups] dev = [ "coverage~=7.14", "deptry>=0.23.0,<0.24", "django-extensions~=4.1", # TODO: once on django-stubs >= 6.0.2, revert the PublishedQuerySet TypeVar # workaround in saleor/core/models.py back to bound="PublishableModel". # The fix landed in https://github.com/typeddjango/django-stubs/commit/461fb9ba8d26667cb43cfb55827acdc6d4ed42ed "django-stubs[compatible-mypy]>=5.1.3,<6", "fakeredis~=2.26", "freezegun>=1,<2", "mypy-extensions>=1.1.0,<2", "openpyxl>=3.1.5,<4", "pre-commit~=4.6", "pytest>=9.0.3,<10", "pytest-asyncio>=1.4.0,<2", "pytest-celery>=1.0.1,<2", "pytest-cov>=7.1.0,<8", "pytest-django==4.12.0", "pytest-django-queries>=1.2,<1.3", "pytest-memray>=1.9.0,<2", # Used via @pytest.mark.limit_memory "pytest-mock>=3.6.1,<4", "pytest-recording>=0.13.0,<0.14", "pytest-socket>=0.8.0,<1", "pytest-xdist>=3.0.2,<4", "pywatchman>=3.0.0,<4", "ruff>=0.12.2,<0.13", "types-certifi>=2021.10.8,<2022", "types-freezegun>=1.1.7,<2", "types-mock>=5.2.0.20260508,<6", "types-python-dateutil>=2.9.0.20260518,<3", "types-redis>=4.6.0,<5", "types-requests>=2.33.0.20260712,<3", "types-six>=1.17.0.20260518,<2", "vcrpy>=8.1.1,<9", "poethepoet>=0.45.0,<0.46", "ipdb>=0.13.13,<0.14", ] [tool.poe] envfile = ".env" [tool.uv] environments = [ "platform_python_implementation != 'PyPy'" ] package = false # Applies the 21 days cooldown (3 weeks) recommendation from Snyk # (https://snyk.io/articles/npm-security-best-practices-shai-hulud-attack/#2-2-snyk-cooldown-in-automatic-p-rs) exclude-newer = "3 weeks" [tool.uv.exclude-newer-package] # To customize on a per-package basis, for example you can do this: # setuptools = "2026-04-07T14:30:00Z" # Note: the timestamp should correspond to the package's upload time on PyPI. # It doesn't need to match exactly, it can be set slightly after the actual # publication time (add a few more seconds, but no more than a few minutes). # Setting the timestamp too far after the publication time increases the risk # of a race condition (e.g., a malicious version being uploaded within that # window). # Note: if you remove a package from this list and 'uv lock' does not update the # lockfile, run 'uv lock --refresh' to force a refresh. cryptography = "2026-09-30T15:31:00" # https://pypi.org/pypi/cryptography/50.0.2/json pyjwt = "2026-09-23T16:57:00Z" # https://pypi.org/pypi/pyjwt/2.15.0/json urllib3 = "2026-09-15T19:30:00Z" # https://pypi.org/pypi/urllib3/2.8.0/json [tool.pytest] addopts = [ "-n=auto", "--record-mode=none", "--ds=saleor.tests.settings", "--disable-socket", "--allow-hosts=127.0.0.1,::1,cache,host.docker.internal,host.containers.internal", "--allow-unix-socket", "--pdbcls=IPython.terminal.debugger:TerminalPdb", "--dist=loadgroup", ] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" testpaths = ["saleor"] filterwarnings = [ "ignore::DeprecationWarning", "ignore::PendingDeprecationWarning", ] markers = [ "integration", "e2e", "slow", ] [tool.poe.tasks] start.help = "Start development server with hot reload" start.cmd = "uvicorn saleor.asgi:application --reload" worker.help = "Start Celery worker" worker.cmd = "celery --app saleor.celeryconf:app worker -E" scheduler.help = "Start Celery Beat scheduler" scheduler.cmd = "celery --app saleor.celeryconf:app beat --scheduler saleor.schedulers.schedulers.DatabaseScheduler" build-schema.cmd = "python manage.py get_graphql_schema" build-schema.capture_stdout = "saleor/graphql/schema.graphql" build-schema.help = "Build GraphQL schema to saleor/graphql/schema.graphql file" migrate.cmd = "python manage.py migrate" migrate.help = "Run database migrations" make-migrations.cmd = "python manage.py makemigrations" make-migrations.help = "Create new migrations based on changes in models" release.shell = "npm run release" release.help = """ Release new Saleor verison Prerequisities: - Node installed on machine - Run npm install to install dependencies """ shell.cmd = "python manage.py shell" shell.help = "Start Django shell in interactive mode" populatedb.cmd = "python manage.py populatedb --createsuperuser" populatedb.help = """ Populates database with sample data and creates admin user with credentials: - email: admin@example.com - password: admin """ test.cmd="pytest --reuse-db" test.help = "Run tests with db reuse to speed up testing time" [tool.deptry] extend_exclude = ["conftest\\.py", ".*/conftest\\.py", ".*/tests/.*"] [tool.deptry.package_module_name_map] graphql-core = "graphql" pillow = "PIL" python-magic-bin = "magic" [tool.deptry.per_rule_ignores] DEP002 = ["azure-common", "azure-storage-blob", "azure-storage-common", "django-redis", "psycopg", "pyxb"] [tool.django-stubs] django_settings_module = "saleor.settings" [tool.mypy] allow_untyped_globals = true allow_redefinition = true check_untyped_defs = true ignore_missing_imports = true pretty = true show_column_numbers = true show_error_codes = true show_error_context = true show_traceback = true warn_redundant_casts = true warn_unused_ignores = true plugins = [ "mypy_django_plugin.main", "pydantic.mypy" ] exclude = [ "tests/" ] [[tool.mypy.overrides]] module = ["saleor.*.migrations.*"] ignore_errors = true [tool.pydantic-mypy] init_forbid_extra = true init_typed = true warn_required_dynamic_aliases = true [tool.ruff] target-version = "py312" [tool.ruff.lint] select = [ "ASYNC", "B", "C4", "D", "DTZ", "E", "F", "FURB", "G", "I", "ISC001", "ISC002", "LOG", "PGH", "PIE", "PT", "PYI", "RET", "T20", "UP", "W" ] ignore = [ "B009", # Do not call getattr with a constant value "B010", # Do not call setattr with a constant value "B023", # Function definition does not bind loop variable "D100", # Missing docstring in public module "D101", # Missing docstring in public class "D102", # Missing docstring in public method "D103", # Missing docstring in public function "D104", # Missing docstring in public package "D105", # Missing docstring in magic method "D106", # Missing docstring in public nested class "D107", # Missing docstring in __init__ "D202", # No blank lines allowed after function docstring "D203", # 1 blank line required before class docstring "D206", # Docstring should be indented with spaces, not tabs "D213", # Multi-line docstring summary should start at the second line "D407", # Missing dashed underline after section "E501", # Line too long "PT019", # Fixture without value is injected as parameter, use @pytest.mark.usefixtures instead "PYI041", # Use `float` instead of `int | float` "RET504", # Unnecessary assignment before return statement "UP046" # Parameter syntax for generic classes; not supported by mypy: https://github.com/python/mypy/issues/18507 ] [tool.ruff.lint.flake8-pytest-style] fixture-parentheses = false mark-parentheses = false [tool.ruff.lint.isort] known-first-party = ["saleor"]