bottleneckcrm/backend/pyproject.toml
2026-10-21 09:25:18 +05:30

177 lines
5.7 KiB
TOML

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "django-crm"
version = "1.18.2"
# The one-line summary PyPI shows under the project title and in search results,
# so it carries the terms people actually search for ("open source CRM",
# "self-hosted CRM", "Django CRM") and names the modules rather than the
# architecture. It leads with the product name because an unrelated project,
# DjangoCRM/django-crm, shares this one's name on GitHub and awesome lists.
# Published release metadata is immutable, so a change here only reaches PyPI
# on the next version bump.
description = "BottleCRM, CRM for AI and People. The open-source self-hosted CRM with a Django REST API: leads, deals, contacts, invoices and support tickets, multi-tenant by PostgreSQL row-level security."
readme = "README.md"
requires-python = ">=3.12"
license = { text = "MIT" }
authors = [
{ name = "RunCode Inc.", email = "hello@bottlecrm.io" },
]
keywords = [
"django",
"crm",
"drf",
"django-rest-framework",
"multi-tenant",
"saas",
"sales",
"leads",
"contacts",
"opportunity",
# Added for discovery: these are the phrases people search rather than the
# words the codebase happens to use. "self-hosted" and "open-source-crm"
# are how someone shopping for an alternative describes what they want.
"self-hosted",
"open-source-crm",
"sales-pipeline",
"invoicing",
"helpdesk",
"support-tickets",
"rest-api",
"postgresql",
"row-level-security",
"salesforce-alternative",
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
"Framework :: Django",
"Framework :: Django :: 6.1",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Office/Business",
"Topic :: Software Development :: Libraries :: Application Frameworks",
]
dependencies = [
"django>=6.1.2",
"celery>=5.6.3",
"python-dotenv>=1.2.4",
"django-cors-headers>=4.9.0",
"djangorestframework>=3.18.3",
"djangorestframework-simplejwt>=5.5.1",
"drf-spectacular>=0.30.0",
"django-ses>=4.8.2",
# psycopg 3, not psycopg2. The `pool` extra is required: Django refuses
# pool options under psycopg2 (ImproperlyConfigured, "Database pooling
# requires psycopg >= 3"), and DATABASES["default"]["OPTIONS"]["pool"] in
# crm/settings.py depends on it. No application code imports the driver
# directly, so the swap is confined to this line.
"psycopg[binary,pool]>=3.3.6",
"whitenoise>=6.12.0",
"sentry-sdk>=2.72.0",
"django-storages>=1.14.6",
"django-crum>=0.7.9",
"disposable-email-domains>=0.0.280",
"redis>=8.1.0",
"requests>=2.34.2",
"faker>=40.43.0",
"python-dateutil>=2.9.0.post0",
"google-auth>=2.62.0",
# X.509 handling for inbound SNS webhook signature verification
# (cases/inbound/sns.py). The API floor is 42, where the not_valid_*_utc
# accessors landed; this pin sits higher only because floors here track the
# versions in uv.lock.
"cryptography>=50.0.2",
# Routing-rule `regex` conditions (cases/routing.py). RE2 matches in time
# linear in the input, so an admin's pattern cannot backtrack for hours on
# a ticket's tags or sender domain the way `re` can.
"google-re2>=1.1.20251105",
# PDF generation (also needs system libs: cairo, pango, gdk-pixbuf, libffi, shared-mime-info)
"weasyprint>=70.0",
"cairocffi>=1.7.1",
# Production WSGI server
"gunicorn>=26.2.0",
"uvicorn[standard]>=0.54.0",
"openpyxl>=3.1.5",
"defusedxml>=0.7.1",
# The tz database's own alias list, read by common.org_time.canonical_timezone.
"tzdata>=2026.5",
]
[project.urls]
# Owner spelled `Django-CRM`, matching GitHub's own casing. The lowercase form
# these used to carry resolves fine, because GitHub URLs are case-insensitive,
# which is exactly what makes the habit dangerous: the same lowercase spelling
# in the PyPI trusted publisher silently matched nothing and cost three failed
# releases of 1.3.0. Keep every reference to the repo in GitHub's casing.
Homepage = "https://github.com/Django-CRM/Django-CRM"
Repository = "https://github.com/Django-CRM/Django-CRM"
Documentation = "https://django-crm.readthedocs.io/en/latest/"
Issues = "https://github.com/Django-CRM/Django-CRM/issues"
Changelog = "https://github.com/Django-CRM/Django-CRM/releases"
[dependency-groups]
dev = [
"pytest>=9.1.1",
"pytest-django>=4.14.0",
"pytest-cov>=7.1.0",
"ruff>=0.17.0",
]
docs = [
"mkdocs-material>=9.7.7",
]
[tool.hatch.build.targets.wheel]
# Must stay in sync with the first-party entries of INSTALLED_APPS in
# crm/settings.py, plus the crm project package itself. An app installed but
# not packaged here imports fine from a source checkout and raises
# ModuleNotFoundError on a pip install, which is how business_hours and macros
# went missing. common/tests/test_packaging.py fails if the two drift apart.
packages = [
"accounts",
"business_hours",
"cases",
"common",
"contacts",
"crm",
"invoices",
"leads",
"macros",
"opportunity",
"orders",
"tasks",
"webforms",
"webhooks",
]
[tool.hatch.build.targets.sdist]
include = [
"accounts/",
"business_hours/",
"cases/",
"common/",
"contacts/",
"crm/",
"invoices/",
"leads/",
"macros/",
"opportunity/",
"orders/",
"tasks/",
"webforms/",
"webhooks/",
"static/",
"manage.py",
".env.example",
"pytest.ini",
"ruff.toml",
"README.md",
]