0
0
mirror of https://github.com/PostHog/posthog.git synced 2024-11-24 18:07:17 +01:00

chore: upgrade python to 3.11 🐍 (#22932)

🐍
This commit is contained in:
Sandy Spicer 2024-06-21 09:45:42 -07:00 committed by GitHub
parent 01a9f360ad
commit 23a789d9fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
42 changed files with 239 additions and 272 deletions

View File

@ -1,3 +1,7 @@
# hadolint global ignore=DL3004
# hadolint doesn't like changes to this file, but it is only used for local dev
# Defines the environment you're dropped into with codespaces
# I've take
# https://github.com/microsoft/vscode-dev-containers/blob/main/containers/python-3/.devcontainer/Dockerfile
@ -7,7 +11,7 @@
# experience as rich as possible. Perhaps later down the line it might be worth
# rolling our own
#
FROM mcr.microsoft.com/vscode/devcontainers/python:3.10-bullseye
FROM mcr.microsoft.com/vscode/devcontainers/python:3.11-bullseye
# Make sure all exit codes on pipes cause failures
SHELL ["/bin/bash", "-o", "pipefail", "-c"]

View File

@ -6,7 +6,7 @@ name: Run Django tests
inputs:
python-version:
required: true
description: Python version, e.g. 3.10.10
description: Python version, e.g. 3.11.9
clickhouse-server-image:
required: true
description: ClickHouse server image tag, e.g. clickhouse/clickhouse-server:latest

View File

@ -54,7 +54,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.10.10
python-version: 3.11.9
cache: 'pip'
cache-dependency-path: '**/requirements*.txt'
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}

View File

@ -28,7 +28,7 @@ jobs:
concurrency: 1
group: 1
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
python-version: '3.10.10'
python-version: '3.11.9'
clickhouse-server-image: 'clickhouse/clickhouse-server:23.12.5.81-alpine'
segment: 'FOSS'
person-on-events: false

View File

@ -108,7 +108,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.10.10
python-version: 3.11.9
cache: 'pip'
cache-dependency-path: '**/requirements*.txt'
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
@ -163,7 +163,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.10.10
python-version: 3.11.9
cache: 'pip'
cache-dependency-path: '**/requirements*.txt'
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
@ -177,22 +177,21 @@ jobs:
sudo apt-get install libxml2-dev libxmlsec1-dev libxmlsec1-openssl
# First running migrations from master, to simulate the real-world scenario
- name: Checkout master
uses: actions/checkout@v3
with:
ref: master
- name: Install python dependencies for master
run: |
uv pip install --system -r requirements.txt -r requirements-dev.txt
- name: Run migrations up to master
run: |
python manage.py migrate
# Commented out to move to Python 3.11. Uncomment after deploy.
# - name: Checkout master
# uses: actions/checkout@v3
# with:
# ref: master
#
# - name: Install python dependencies for master
# run: |
# uv pip install --system -r requirements.txt -r requirements-dev.txt
#
# - name: Run migrations up to master
# run: |
# python manage.py migrate
# Now we can consider this PR's migrations
- name: Checkout this PR
uses: actions/checkout@v3
@ -204,22 +203,24 @@ jobs:
run: |
python manage.py migrate
- name: Check migrations
run: |
python manage.py makemigrations --check --dry-run
git fetch origin master
# `git diff --name-only` returns a list of files that were changed - added OR deleted OR modified
# With `--name-status` we get the same, but including a column for status, respectively: A, D, M
# In this check we exclusively care about files that were
# added (A) in posthog/migrations/. We also want to ignore
# initial migrations (0001_*) as these are guaranteed to be
# run on initial setup where there is no data.
git diff --name-status origin/master..HEAD | grep "A\sposthog/migrations/" | awk '{print $2}' | grep -v migrations/0001_ | python manage.py test_migrations_are_safe
- name: Check CH migrations
run: |
# Same as above, except now for CH looking at files that were added in posthog/clickhouse/migrations/
git diff --name-status origin/master..HEAD | grep "A\sposthog/clickhouse/migrations/" | awk '{print $2}' | python manage.py test_ch_migrations_are_safe
# Commented out to move to Python 3.11. Uncomment after deploy.
#
# - name: Check migrations
# run: |
# python manage.py makemigrations --check --dry-run
# git fetch origin master
# # `git diff --name-only` returns a list of files that were changed - added OR deleted OR modified
# # With `--name-status` we get the same, but including a column for status, respectively: A, D, M
# # In this check we exclusively care about files that were
# # added (A) in posthog/migrations/. We also want to ignore
# # initial migrations (0001_*) as these are guaranteed to be
# # run on initial setup where there is no data.
# git diff --name-status origin/master..HEAD | grep "A\sposthog/migrations/" | awk '{print $2}' | grep -v migrations/0001_ | python manage.py test_migrations_are_safe
#
# - name: Check CH migrations
# run: |
# # Same as above, except now for CH looking at files that were added in posthog/clickhouse/migrations/
# git diff --name-status origin/master..HEAD | grep "A\sposthog/clickhouse/migrations/" | awk '{print $2}' | python manage.py test_ch_migrations_are_safe
django:
needs: changes
@ -231,7 +232,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.10.10']
python-version: ['3.11.9']
clickhouse-server-image: ['clickhouse/clickhouse-server:23.12.5.81-alpine']
segment: ['Core']
person-on-events: [false, true]
@ -242,7 +243,7 @@ jobs:
- segment: 'Temporal'
person-on-events: false
clickhouse-server-image: 'clickhouse/clickhouse-server:23.12.5.81-alpine'
python-version: '3.10.10'
python-version: '3.11.9'
concurrency: 1
group: 1
@ -330,7 +331,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.10.10
python-version: 3.11.9
cache: 'pip'
cache-dependency-path: '**/requirements*.txt'
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}

View File

@ -70,7 +70,7 @@ jobs:
if: needs.changes.outputs.hog == 'true'
uses: actions/setup-python@v5
with:
python-version: 3.10.10
python-version: 3.11.9
cache: 'pip'
cache-dependency-path: '**/requirements*.txt'
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}

View File

@ -115,7 +115,7 @@ jobs:
if: needs.changes.outputs.plugin-server == 'true'
uses: actions/setup-python@v5
with:
python-version: 3.10.10
python-version: 3.11.9
cache: 'pip'
cache-dependency-path: '**/requirements*.txt'
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}
@ -207,7 +207,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.10.10
python-version: 3.11.9
cache: 'pip'
cache-dependency-path: '**/requirements*.txt'
token: ${{ secrets.POSTHOG_BOT_GITHUB_TOKEN }}

View File

@ -14,6 +14,7 @@
<env name="REPLAY_EMBEDDINGS_ALLOWED_TEAM" value="1,2,3" />
</envs>
<option name="SDK_HOME" value="" />
<option name="SDK_NAME" value="Python 3.11 (posthog)" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/env/bin" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />

View File

@ -14,6 +14,7 @@
<env name="REPLAY_EMBEDDINGS_ALLOWED_TEAM" value="1,2,3" />
</envs>
<option name="SDK_HOME" value="$PROJECT_DIR$/env/bin/python" />
<option name="SDK_NAME" value="Python 3.11 (posthog)" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/env/bin" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />

View File

@ -5,17 +5,18 @@
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
<env name="CLICKHOUSE_SECURE" value="False" />
<env name="DATABASE_URL" value="postgres://posthog:posthog@localhost:5432/posthog" />
<env name="DEBUG" value="1" />
<env name="KAFKA_HOSTS" value="localhost" />
<env name="PYTHONUNBUFFERED" value="1" />
<env name="SKIP_SERVICE_VERSION_REQUIREMENTS" value="1" />
<env name="REPLAY_EMBEDDINGS_ALLOWED_TEAM" value="1,2,3" />
</envs>
<option name="SDK_HOME" value="$PROJECT_DIR$/env/bin/python" />
<option name="SDK_NAME" value="Python 3.11 (posthog)" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/env/bin" />
<option name="IS_MODULE_SDK" value="false" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />

View File

@ -1,9 +1,11 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="PostHog" type="Python.DjangoServer" factoryName="Django server">
<module name="posthog" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
<env name="BILLING_SERVICE_URL" value="https://billing.dev.posthog.dev" />
<env name="CAPTURE_TIME_TO_SEE_DATA" value="0" />
<env name="CLICKHOUSE_SECURE" value="False" />
@ -14,14 +16,13 @@
<env name="KEA_VERBOSE_LOGGING" value="false" />
<env name="PRINT_SQL" value="1" />
<env name="PYDEVD_USE_CYTHON" value="NO" />
<env name="PYTHONUNBUFFERED" value="1" />
<env name="SESSION_RECORDING_KAFKA_COMPRESSION" value="gzip" />
<env name="SESSION_RECORDING_KAFKA_HOSTS" value="localhost" />
<env name="SESSION_RECORDING_KAFKA_MAX_REQUEST_SIZE_BYTES" value="20971520" />
<env name="SKIP_SERVICE_VERSION_REQUIREMENTS" value="1" />
</envs>
<option name="SDK_HOME" value="$PROJECT_DIR$/env/bin/python" />
<option name="SDK_NAME" value="Python 3.10 (posthog)" />
<option name="SDK_NAME" value="Python 3.11 (posthog)" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />

View File

@ -4,7 +4,7 @@ set -e
# Generate schema.py from schema.json
datamodel-codegen \
--class-name='SchemaRoot' --collapse-root-models --target-python-version 3.10 --disable-timestamp \
--class-name='SchemaRoot' --collapse-root-models --target-python-version 3.11 --disable-timestamp \
--use-one-literal-as-default --use-default --use-default-kwarg --use-subclass-enum \
--input frontend/src/queries/schema.json --input-file-type jsonschema \
--output posthog/schema.py --output-model-type pydantic_v2.BaseModel \
@ -29,3 +29,9 @@ if [[ "$OSTYPE" == "darwin"* ]]; then
else
sed -i -e 's/Optional\[PropertyOperator\] = \("[A-Za-z_]*"\)/Optional[PropertyOperator] = PropertyOperator(\1)/g' posthog/schema.py
fi
# Replace class Foo(str, Enum) with class Foo(StrEnum) for proper handling in format strings in python 3.11
# Remove this when https://github.com/koxudaxi/datamodel-code-generator/issues/1313 is resolved
sed -i -e 's/str, Enum/StrEnum/g' posthog/schema.py
sed -i 's/from enum import Enum/from enum import Enum, StrEnum/g' posthog/schema.py

View File

@ -184,7 +184,7 @@ if ! command -v docker &> /dev/null; then
# Setup Docker
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo -E apt-key add -
sudo add-apt-repository -y "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
sudo add-apt-repository -y "deb [arch=amd64] https://download.docker.com/linux/ubuntu jammy stable"
sudo apt update
sudo apt-cache policy docker-ce
sudo apt install -y docker-ce

View File

@ -20,7 +20,7 @@
"first_name": "",
"last_name": "",
"email": "",
"is_email_verified": false
"is_email_verified": null
}
},
"children": [

View File

@ -1,5 +1,5 @@
[mypy]
python_version = 3.10
python_version = 3.11
plugins =
mypy_django_plugin.main,
mypy_drf_plugin.main,

View File

@ -11,11 +11,13 @@ from posthog.api.forbid_destroy_model import ForbidDestroyModel
from posthog.api.routing import TeamAndOrgViewSetMixin
from posthog.api.shared import UserBasicSerializer
from posthog.api.utils import ClassicBehaviorBooleanFieldSerializer
from posthog.models.comment import Comment
class CommentSerializer(serializers.ModelSerializer):
created_by = UserBasicSerializer(read_only=True)
deleted = ClassicBehaviorBooleanFieldSerializer()
class Meta:
model = Comment

View File

@ -23,6 +23,7 @@ from posthog.api.routing import TeamAndOrgViewSetMixin
from posthog.api.shared import UserBasicSerializer
from posthog.api.tagged_item import TaggedItemSerializerMixin, TaggedItemViewSetMixin
from posthog.api.dashboards.dashboard import Dashboard
from posthog.api.utils import ClassicBehaviorBooleanFieldSerializer
from posthog.auth import PersonalAPIKeyAuthentication, TemporaryTokenAuthentication
from posthog.constants import FlagRequestType
from posthog.event_usage import report_user_action
@ -89,6 +90,9 @@ class FeatureFlagSerializer(TaggedItemSerializerMixin, serializers.HyperlinkedMo
is_simple_flag = serializers.SerializerMethodField()
rollout_percentage = serializers.SerializerMethodField()
ensure_experience_continuity = ClassicBehaviorBooleanFieldSerializer()
has_enriched_analytics = ClassicBehaviorBooleanFieldSerializer()
experiment_set: serializers.PrimaryKeyRelatedField = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
surveys: serializers.SerializerMethodField = serializers.SerializerMethodField()
features: serializers.SerializerMethodField = serializers.SerializerMethodField()

View File

@ -22,6 +22,7 @@ from rest_framework.response import Response
from posthog.api.routing import TeamAndOrgViewSetMixin
from posthog.api.shared import FiltersSerializer
from posthog.api.utils import ClassicBehaviorBooleanFieldSerializer
from posthog.models import Plugin, PluginAttachment, PluginConfig, User
from posthog.models.activity_logging.activity_log import (
ActivityPage,
@ -586,6 +587,8 @@ class PluginConfigSerializer(serializers.ModelSerializer):
delivery_rate_24h = serializers.SerializerMethodField()
error = serializers.SerializerMethodField()
deleted = ClassicBehaviorBooleanFieldSerializer()
class Meta:
model = PluginConfig
fields = [

View File

@ -36,6 +36,32 @@ else:
class DefaultRouterPlusPlus(ExtendedDefaultRouter):
"""DefaultRouter with optional trailing slash and drf-extensions nesting."""
# This is an override because of changes in djangorestframework 3.15, which is required for python 3.11
# changes taken from and explained here: https://github.com/nautobot/nautobot/pull/5546/files#diff-81850a2ccad5814aab4f477d447f85cc0a82e9c10fd88fd72327cda51a750471R30
def _register(self, prefix, viewset, basename=None):
"""
Override DRF's BaseRouter.register() to bypass an unnecessary restriction added in version 3.15.0.
(Reference: https://github.com/encode/django-rest-framework/pull/8438)
"""
if basename is None:
basename = self.get_default_basename(viewset)
# DRF:
# if self.is_already_registered(basename):
# msg = (f'Router with basename "{basename}" is already registered. '
# f'Please provide a unique basename for viewset "{viewset}"')
# raise ImproperlyConfigured(msg)
#
# We bypass this because we have at least one use case (/api/extras/jobs/) where we are *intentionally*
# registering two viewsets with the same basename, but have carefully defined them so as not to conflict.
# resuming standard DRF code...
self.registry.append((prefix, viewset, basename))
# invalidate the urls cache
if hasattr(self, "_urls"):
del self._urls
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.trailing_slash = r"/?"

View File

@ -77,7 +77,7 @@
"/home/runner/work/posthog/posthog/posthog/api/property_definition.py: Error [PropertyDefinitionViewSet]: exception raised while getting serializer. Hint: Is get_serializer_class() returning None or is get_queryset() not working without a request? Ignoring the view for now. (Exception: 'AnonymousUser' object has no attribute 'organization')",
'/home/runner/work/posthog/posthog/posthog/api/property_definition.py: Warning [PropertyDefinitionViewSet]: could not derive type of path parameter "project_id" because model "posthog.models.property_definition.PropertyDefinition" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".',
'/home/runner/work/posthog/posthog/posthog/api/query.py: Warning [QueryViewSet]: could not derive type of path parameter "project_id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. <int:project_id>) or annotating the parameter type with @extend_schema. Defaulting to "string".',
'/opt/hostedtoolcache/Python/3.10.10/x64/lib/python3.10/site-packages/pydantic/_internal/_model_construction.py: Warning [QueryViewSet > ModelMetaclass]: Encountered 2 components with identical names "Person" and different classes <class \'str\'> and <class \'posthog.api.person.PersonSerializer\'>. This will very likely result in an incorrect schema. Try renaming one.',
'/opt/hostedtoolcache/Python/3.11.9/x64/lib/python3.11/site-packages/pydantic/_internal/_model_construction.py: Warning [QueryViewSet > ModelMetaclass]: Encountered 2 components with identical names "Person" and different classes <class \'str\'> and <class \'posthog.api.person.PersonSerializer\'>. This will very likely result in an incorrect schema. Try renaming one.',
'/home/runner/work/posthog/posthog/posthog/api/query.py: Warning [QueryViewSet]: could not derive type of path parameter "id" because it is untyped and obtaining queryset from the viewset failed. Consider adding a type to the path (e.g. <int:id>) or annotating the parameter type with @extend_schema. Defaulting to "string".',
'/home/runner/work/posthog/posthog/posthog/api/query.py: Error [QueryViewSet]: unable to guess serializer. This is graceful fallback handling for APIViews. Consider using GenericAPIView as view base class, if view is under your control. Either way you may want to add a serializer_class (or method). Ignoring view for now.',
'/home/runner/work/posthog/posthog/ee/session_recordings/session_recording_playlist.py: Warning [SessionRecordingPlaylistViewSet]: could not derive type of path parameter "project_id" because model "posthog.session_recordings.models.session_recording_playlist.SessionRecordingPlaylist" contained no such field. Consider annotating parameter with @extend_schema. Defaulting to "string".',

View File

@ -35,7 +35,11 @@ from posthog.api.decide import hostname_in_allowed_url_list
from posthog.api.email_verification import EmailVerifier
from posthog.api.organization import OrganizationSerializer
from posthog.api.shared import OrganizationBasicSerializer, TeamBasicSerializer
from posthog.api.utils import PublicIPOnlyHttpAdapter, raise_if_user_provided_url_unsafe
from posthog.api.utils import (
PublicIPOnlyHttpAdapter,
raise_if_user_provided_url_unsafe,
ClassicBehaviorBooleanFieldSerializer,
)
from posthog.auth import (
PersonalAPIKeyAuthentication,
SessionAuthentication,
@ -84,6 +88,7 @@ class UserSerializer(serializers.ModelSerializer):
current_password = serializers.CharField(write_only=True, required=False)
notification_settings = serializers.DictField(required=False)
scene_personalisation = ScenePersonalisationBasicSerializer(many=True, read_only=True)
anonymize_data = ClassicBehaviorBooleanFieldSerializer()
class Meta:
model = User

View File

@ -6,6 +6,8 @@ from enum import Enum, auto
from ipaddress import ip_address
from requests.adapters import HTTPAdapter
from typing import Literal, Optional, Union
from rest_framework.fields import Field
from urllib3 import HTTPSConnectionPool, HTTPConnectionPool, PoolManager
from uuid import UUID
@ -13,7 +15,7 @@ import structlog
from django.core.exceptions import RequestDataTooBig
from django.db.models import QuerySet
from prometheus_client import Counter
from rest_framework import request, status
from rest_framework import request, status, serializers
from rest_framework.exceptions import ValidationError
from statshog.defaults.django import statsd
@ -34,6 +36,14 @@ class PaginationMode(Enum):
previous = auto()
# This overrides a change in DRF 3.15 that alters our behavior. If the user passes an empty argument,
# the new version keeps it as null vs coalescing it to the default.
# Don't add this to new classes
class ClassicBehaviorBooleanFieldSerializer(serializers.BooleanField):
def __init__(self, **kwargs):
Field.__init__(self, allow_null=True, required=False, **kwargs)
def get_target_entity(filter: Union[Filter, StickinessFilter]) -> Entity:
# Except for "events", we require an entity id and type to be provided
if not filter.target_entity_id and filter.target_entity_type != "events":

View File

@ -254,7 +254,7 @@ class BatchExport(UUIDModel):
raise ValueError(f"Invalid interval: '{self.interval}'")
class BatchExportLogEntryLevel(str, enum.Enum):
class BatchExportLogEntryLevel(enum.StrEnum):
"""Enumeration of batch export log levels."""
DEBUG = "DEBUG"

View File

@ -1,11 +1,11 @@
import uuid
from enum import Enum
from enum import StrEnum
from typing import Optional
from django.conf import settings
class ReplicationScheme(str, Enum):
class ReplicationScheme(StrEnum):
NOT_SHARDED = "NOT_SHARDED"
SHARDED = "SHARDED"
REPLICATED = "REPLICATED"

View File

@ -1,4 +1,4 @@
from enum import Enum
from enum import StrEnum
from typing import Literal
from semantic_version import Version
@ -9,7 +9,7 @@ INTERNAL_BOT_EMAIL_SUFFIX = "@posthogbot.user"
# N.B. Keep this in sync with frontend enum (types.ts)
# AND ensure it is added to the Billing Service
class AvailableFeature(str, Enum):
class AvailableFeature(StrEnum):
ZAPIER = "zapier"
ORGANIZATIONS_PROJECTS = "organizations_projects"
PROJECT_BASED_PERMISSIONING = "project_based_permissioning"
@ -215,19 +215,19 @@ SAMPLING_FACTOR = "sampling_factor"
BREAKDOWN_TYPES = Literal["event", "person", "cohort", "group", "session", "hogql"]
class FunnelOrderType(str, Enum):
class FunnelOrderType(StrEnum):
STRICT = "strict"
UNORDERED = "unordered"
ORDERED = "ordered"
class FunnelVizType(str, Enum):
class FunnelVizType(StrEnum):
TRENDS = "trends"
TIME_TO_CONVERT = "time_to_convert"
STEPS = "steps"
class FunnelCorrelationType(str, Enum):
class FunnelCorrelationType(StrEnum):
EVENTS = "events"
PROPERTIES = "properties"
EVENT_WITH_PROPERTIES = "event_with_properties"
@ -240,7 +240,7 @@ DISTINCT_ID_FILTER = "distinct_id"
PERSON_UUID_FILTER = "person_uuid"
class AnalyticsDBMS(str, Enum):
class AnalyticsDBMS(StrEnum):
POSTGRES = "postgres"
CLICKHOUSE = "clickhouse"
@ -251,13 +251,13 @@ WEEKLY_ACTIVE = "weekly_active"
MONTHLY_ACTIVE = "monthly_active"
class RetentionQueryType(str, Enum):
class RetentionQueryType(StrEnum):
RETURNING = "returning"
TARGET = "target"
TARGET_FIRST_TIME = "target_first_time"
class ExperimentSignificanceCode(str, Enum):
class ExperimentSignificanceCode(StrEnum):
SIGNIFICANT = "significant"
NOT_ENOUGH_EXPOSURE = "not_enough_exposure"
LOW_WIN_PROBABILITY = "low_win_probability"
@ -265,7 +265,7 @@ class ExperimentSignificanceCode(str, Enum):
HIGH_P_VALUE = "high_p_value"
class ExperimentNoResultsErrorKeys(str, Enum):
class ExperimentNoResultsErrorKeys(StrEnum):
NO_EVENTS = "no-events"
NO_FLAG_INFO = "no-flag-info"
NO_CONTROL_VARIANT = "no-control-variant"
@ -273,12 +273,12 @@ class ExperimentNoResultsErrorKeys(str, Enum):
NO_RESULTS = "no-results"
class PropertyOperatorType(str, Enum):
class PropertyOperatorType(StrEnum):
AND = "AND"
OR = "OR"
class BreakdownAttributionType(str, Enum):
class BreakdownAttributionType(StrEnum):
FIRST_TOUCH = "first_touch"
# FIRST_TOUCH attribution means the breakdown value is the first property value found within all funnel steps
LAST_TOUCH = "last_touch"
@ -294,7 +294,7 @@ MAX_SLUG_LENGTH = 48
GROUP_TYPES_LIMIT = 5
class EventDefinitionType(str, Enum):
class EventDefinitionType(StrEnum):
# Mimics EventDefinitionType in frontend/src/types.ts
ALL = "all"
ACTION_EVENT = "action_event"
@ -303,7 +303,7 @@ class EventDefinitionType(str, Enum):
EVENT_CUSTOM = "event_custom"
class FlagRequestType(str, Enum):
class FlagRequestType(StrEnum):
DECIDE = "decide"
LOCAL_EVALUATION = "local-evaluation"

View File

@ -1,4 +1,4 @@
from enum import Enum
from enum import StrEnum
from functools import wraps
from typing import Any, TypeVar, Union, cast
from collections.abc import Callable
@ -17,7 +17,7 @@ from posthog.utils import refresh_requested_by_client
from .utils import generate_cache_key, get_safe_cache
class CacheType(str, Enum):
class CacheType(StrEnum):
TRENDS = "Trends"
FUNNEL = "Funnel"
RETENTION = "Retention"

View File

@ -1,12 +1,11 @@
from enum import Enum
from enum import StrEnum
import mimesis
import mimesis.random
WeightedPool = tuple[list[str], list[int]]
class Industry(str, Enum):
class Industry(StrEnum):
TECHNOLOGY = "technology"
FINANCE = "finance"
MEDIA = "media"

View File

@ -1,7 +1,7 @@
import datetime as dt
import math
from dataclasses import dataclass, field
from enum import Enum, auto
from enum import auto, StrEnum
from typing import (
TYPE_CHECKING,
Any,
@ -66,7 +66,7 @@ class HedgeboxSessionIntent(SimSessionIntent):
DOWNGRADE_PLAN = auto()
class HedgeboxPlan(str, Enum):
class HedgeboxPlan(StrEnum):
PERSONAL_FREE = "personal/free"
PERSONAL_PRO = "personal/pro"
BUSINESS_STANDARD = "business/standard"

View File

@ -1,4 +1,4 @@
from enum import Enum
from enum import StrEnum
from typing import Any, Literal, Optional, Union
from dataclasses import dataclass, field
@ -394,7 +394,7 @@ class UUIDType(ConstantType):
@dataclass(kw_only=True)
class ArrayType(ConstantType):
data_type: ConstantDataType = field(default="array", init=False)
item_type: ConstantType = UnknownType()
item_type: ConstantType = field(default_factory=UnknownType)
def print_type(self) -> str:
return "Array"
@ -554,7 +554,7 @@ class Alias(Expr):
hidden: bool = False
class ArithmeticOperationOp(str, Enum):
class ArithmeticOperationOp(StrEnum):
Add = "+"
Sub = "-"
Mult = "*"
@ -581,7 +581,7 @@ class Or(Expr):
type: Optional[ConstantType] = None
class CompareOperationOp(str, Enum):
class CompareOperationOp(StrEnum):
Eq = "=="
NotEq = "!="
Gt = ">"

View File

@ -1,5 +1,5 @@
from datetime import date, datetime
from enum import Enum
from enum import StrEnum
from typing import Optional, Literal, TypeAlias
from uuid import UUID
from pydantic import ConfigDict, BaseModel
@ -47,7 +47,7 @@ BREAKDOWN_VALUES_LIMIT = 25
BREAKDOWN_VALUES_LIMIT_FOR_COUNTRIES = 300
class LimitContext(str, Enum):
class LimitContext(StrEnum):
QUERY = "query"
QUERY_ASYNC = "query_async"
EXPORT = "export"

View File

@ -1,5 +1,5 @@
import copy
from enum import Enum
from enum import StrEnum
import json
from typing import Any, Literal
from posthog.hogql_queries.legacy_compatibility.clean_properties import clean_entity_properties, clean_global_properties
@ -34,7 +34,7 @@ from posthog.types import InsightQueryNode
from posthog.utils import str_to_bool
class MathAvailability(str, Enum):
class MathAvailability(StrEnum):
Unavailable = ("Unavailable",)
All = ("All",)
ActorsOnly = "ActorsOnly"

View File

@ -1,5 +1,5 @@
import json
from enum import Enum
from enum import StrEnum
from typing import Any, Optional
from collections.abc import Callable
@ -83,7 +83,7 @@ class KafkaConsumerForTests:
return
class _KafkaSecurityProtocol(str, Enum):
class _KafkaSecurityProtocol(StrEnum):
PLAINTEXT = "PLAINTEXT"
SSL = "SSL"
SASL_PLAINTEXT = "SASL_PLAINTEXT"

View File

@ -3,7 +3,7 @@ import re
import subprocess
from collections import OrderedDict
from dataclasses import dataclass
from enum import Enum
from enum import StrEnum
from typing import Optional
from django.core.management.base import BaseCommand
@ -12,7 +12,7 @@ from django.core.management.base import BaseCommand
OUTPUT_FILE = "posthog/models/channel_type/channel_definitions.json"
class EntryKind(str, Enum):
class EntryKind(StrEnum):
source = "source"
medium = "medium"

View File

@ -1,6 +1,6 @@
import hashlib
from dataclasses import dataclass
from enum import Enum
from enum import StrEnum
import time
import structlog
from typing import Literal, Optional, Union, cast
@ -67,7 +67,7 @@ ENTITY_EXISTS_PREFIX = "flag_entity_exists_"
PERSON_KEY = "person"
class FeatureFlagMatchReason(str, Enum):
class FeatureFlagMatchReason(StrEnum):
SUPER_CONDITION_VALUE = "super_condition_value"
CONDITION_MATCH = "condition_match"
NO_CONDITION_MATCH = "no_condition_match"

View File

@ -1,7 +1,7 @@
import datetime
import os
from dataclasses import dataclass
from enum import Enum
from enum import StrEnum
from typing import Any, Optional, cast
from uuid import UUID
@ -288,13 +288,13 @@ class PluginStorage(models.Model):
value: models.TextField = models.TextField(blank=True, null=True)
class PluginLogEntrySource(str, Enum):
class PluginLogEntrySource(StrEnum):
SYSTEM = "SYSTEM"
PLUGIN = "PLUGIN"
CONSOLE = "CONSOLE"
class PluginLogEntryType(str, Enum):
class PluginLogEntryType(StrEnum):
DEBUG = "DEBUG"
LOG = "LOG"
INFO = "INFO"

View File

@ -1,5 +1,5 @@
import json
from enum import Enum
from enum import StrEnum
from typing import (
Any,
Literal,
@ -14,7 +14,7 @@ from posthog.models.filters.utils import GroupTypeIndex, validate_group_type_ind
from posthog.utils import str_to_bool
class BehavioralPropertyType(str, Enum):
class BehavioralPropertyType(StrEnum):
PERFORMED_EVENT = "performed_event"
PERFORMED_EVENT_MULTIPLE = "performed_event_multiple"
PERFORMED_EVENT_FIRST_TIME = "performed_event_first_time"

View File

@ -2,7 +2,7 @@
from __future__ import annotations
from enum import Enum
from enum import Enum, StrEnum
from typing import Any, Literal, Optional, Union
from pydantic import AwareDatetime, BaseModel, ConfigDict, Field, RootModel
@ -20,7 +20,7 @@ class MathGroupTypeIndex(float, Enum):
NUMBER_4 = 4
class AggregationAxisFormat(str, Enum):
class AggregationAxisFormat(StrEnum):
NUMERIC = "numeric"
DURATION = "duration"
DURATION_MS = "duration_ms"
@ -28,7 +28,7 @@ class AggregationAxisFormat(str, Enum):
PERCENTAGE_SCALED = "percentage_scaled"
class Kind(str, Enum):
class Kind(StrEnum):
METHOD = "Method"
FUNCTION = "Function"
CONSTRUCTOR = "Constructor"
@ -87,7 +87,7 @@ class AutocompleteCompletionItem(BaseModel):
)
class BaseMathType(str, Enum):
class BaseMathType(StrEnum):
TOTAL = "total"
DAU = "dau"
WEEKLY_ACTIVE = "weekly_active"
@ -95,14 +95,14 @@ class BaseMathType(str, Enum):
UNIQUE_SESSION = "unique_session"
class BreakdownAttributionType(str, Enum):
class BreakdownAttributionType(StrEnum):
FIRST_TOUCH = "first_touch"
LAST_TOUCH = "last_touch"
ALL_EVENTS = "all_events"
STEP = "step"
class BreakdownType(str, Enum):
class BreakdownType(StrEnum):
COHORT = "cohort"
PERSON = "person"
EVENT = "event"
@ -164,7 +164,7 @@ class ChartAxis(BaseModel):
column: str
class ChartDisplayType(str, Enum):
class ChartDisplayType(StrEnum):
ACTIONS_LINE_GRAPH = "ActionsLineGraph"
ACTIONS_BAR = "ActionsBar"
ACTIONS_AREA_GRAPH = "ActionsAreaGraph"
@ -205,7 +205,7 @@ class CompareFilter(BaseModel):
compare_to: Optional[str] = None
class CountPerActorMathType(str, Enum):
class CountPerActorMathType(StrEnum):
AVG_COUNT_PER_ACTOR = "avg_count_per_actor"
MIN_COUNT_PER_ACTOR = "min_count_per_actor"
MAX_COUNT_PER_ACTOR = "max_count_per_actor"
@ -255,14 +255,14 @@ class DatabaseSchemaSource(BaseModel):
status: str
class Type(str, Enum):
class Type(StrEnum):
POSTHOG = "posthog"
DATA_WAREHOUSE = "data_warehouse"
VIEW = "view"
BATCH_EXPORT = "batch_export"
class DatabaseSerializedFieldType(str, Enum):
class DatabaseSerializedFieldType(StrEnum):
INTEGER = "integer"
FLOAT = "float"
STRING = "string"
@ -301,13 +301,13 @@ class Day(RootModel[int]):
root: int
class DurationType(str, Enum):
class DurationType(StrEnum):
DURATION = "duration"
ACTIVE_SECONDS = "active_seconds"
INACTIVE_SECONDS = "inactive_seconds"
class Key(str, Enum):
class Key(StrEnum):
TAG_NAME = "tag_name"
TEXT = "text"
HREF = "href"
@ -336,14 +336,14 @@ class EmptyPropertyFilter(BaseModel):
)
class EntityType(str, Enum):
class EntityType(StrEnum):
ACTIONS = "actions"
EVENTS = "events"
DATA_WAREHOUSE = "data_warehouse"
NEW_ENTITY = "new_entity"
class ErrorTrackingOrder(str, Enum):
class ErrorTrackingOrder(StrEnum):
LAST_SEEN = "last_seen"
FIRST_SEEN = "first_seen"
UNIQUE_OCCURRENCES = "unique_occurrences"
@ -360,7 +360,7 @@ class EventDefinition(BaseModel):
properties: dict[str, Any]
class CorrelationType(str, Enum):
class CorrelationType(StrEnum):
SUCCESS = "success"
FAILURE = "failure"
@ -418,12 +418,12 @@ class EventsQueryPersonColumn(BaseModel):
uuid: str
class FilterLogicalOperator(str, Enum):
class FilterLogicalOperator(StrEnum):
AND_ = "AND"
OR_ = "OR"
class FunnelConversionWindowTimeUnit(str, Enum):
class FunnelConversionWindowTimeUnit(StrEnum):
SECOND = "second"
MINUTE = "minute"
HOUR = "hour"
@ -440,7 +440,7 @@ class FunnelCorrelationResult(BaseModel):
skewed: bool
class FunnelCorrelationResultsType(str, Enum):
class FunnelCorrelationResultsType(StrEnum):
EVENTS = "events"
PROPERTIES = "properties"
EVENT_WITH_PROPERTIES = "event_with_properties"
@ -468,18 +468,18 @@ class FunnelExclusionSteps(BaseModel):
funnelToStep: int
class FunnelLayout(str, Enum):
class FunnelLayout(StrEnum):
HORIZONTAL = "horizontal"
VERTICAL = "vertical"
class FunnelPathType(str, Enum):
class FunnelPathType(StrEnum):
FUNNEL_PATH_BEFORE_STEP = "funnel_path_before_step"
FUNNEL_PATH_BETWEEN_STEPS = "funnel_path_between_steps"
FUNNEL_PATH_AFTER_STEP = "funnel_path_after_step"
class FunnelStepReference(str, Enum):
class FunnelStepReference(StrEnum):
TOTAL = "total"
PREVIOUS = "previous"
@ -492,7 +492,7 @@ class FunnelTimeToConvertResults(BaseModel):
bins: list[list[int]]
class FunnelVizType(str, Enum):
class FunnelVizType(StrEnum):
STEPS = "steps"
TIME_TO_CONVERT = "time_to_convert"
TRENDS = "trends"
@ -516,37 +516,37 @@ class HogQLNotice(BaseModel):
start: Optional[int] = None
class BounceRatePageViewMode(str, Enum):
class BounceRatePageViewMode(StrEnum):
COUNT_PAGEVIEWS = "count_pageviews"
UNIQ_URLS = "uniq_urls"
class InCohortVia(str, Enum):
class InCohortVia(StrEnum):
AUTO = "auto"
LEFTJOIN = "leftjoin"
SUBQUERY = "subquery"
LEFTJOIN_CONJOINED = "leftjoin_conjoined"
class MaterializationMode(str, Enum):
class MaterializationMode(StrEnum):
AUTO = "auto"
LEGACY_NULL_AS_STRING = "legacy_null_as_string"
LEGACY_NULL_AS_NULL = "legacy_null_as_null"
DISABLED = "disabled"
class PersonsArgMaxVersion(str, Enum):
class PersonsArgMaxVersion(StrEnum):
AUTO = "auto"
V1 = "v1"
V2 = "v2"
class PersonsJoinMode(str, Enum):
class PersonsJoinMode(StrEnum):
INNER = "inner"
LEFT = "left"
class PersonsOnEventsMode(str, Enum):
class PersonsOnEventsMode(StrEnum):
DISABLED = "disabled"
PERSON_ID_NO_OVERRIDE_PROPERTIES_ON_EVENTS = "person_id_no_override_properties_on_events"
PERSON_ID_OVERRIDE_PROPERTIES_ON_EVENTS = "person_id_override_properties_on_events"
@ -579,7 +579,7 @@ class HogQueryResponse(BaseModel):
stdout: Optional[str] = None
class Compare(str, Enum):
class Compare(StrEnum):
CURRENT = "current"
PREVIOUS = "previous"
@ -619,7 +619,7 @@ class InsightDateRange(BaseModel):
)
class InsightFilterProperty(str, Enum):
class InsightFilterProperty(StrEnum):
TRENDS_FILTER = "trendsFilter"
FUNNELS_FILTER = "funnelsFilter"
RETENTION_FILTER = "retentionFilter"
@ -628,7 +628,7 @@ class InsightFilterProperty(str, Enum):
LIFECYCLE_FILTER = "lifecycleFilter"
class InsightNodeKind(str, Enum):
class InsightNodeKind(StrEnum):
TRENDS_QUERY = "TrendsQuery"
FUNNELS_QUERY = "FunnelsQuery"
RETENTION_QUERY = "RetentionQuery"
@ -637,7 +637,7 @@ class InsightNodeKind(str, Enum):
LIFECYCLE_QUERY = "LifecycleQuery"
class InsightType(str, Enum):
class InsightType(StrEnum):
TRENDS = "TRENDS"
STICKINESS = "STICKINESS"
LIFECYCLE = "LIFECYCLE"
@ -649,7 +649,7 @@ class InsightType(str, Enum):
HOG = "HOG"
class IntervalType(str, Enum):
class IntervalType(StrEnum):
MINUTE = "minute"
HOUR = "hour"
DAY = "day"
@ -657,14 +657,14 @@ class IntervalType(str, Enum):
MONTH = "month"
class LifecycleToggle(str, Enum):
class LifecycleToggle(StrEnum):
NEW = "new"
RESURRECTING = "resurrecting"
RETURNING = "returning"
DORMANT = "dormant"
class NodeKind(str, Enum):
class NodeKind(StrEnum):
EVENTS_NODE = "EventsNode"
ACTIONS_NODE = "ActionsNode"
DATA_WAREHOUSE_NODE = "DataWarehouseNode"
@ -709,7 +709,7 @@ class PathCleaningFilter(BaseModel):
regex: Optional[str] = None
class PathType(str, Enum):
class PathType(StrEnum):
FIELD_PAGEVIEW = "$pageview"
FIELD_SCREEN = "$screen"
CUSTOM_EVENT = "custom_event"
@ -758,7 +758,7 @@ class PathsFilterLegacy(BaseModel):
step_limit: Optional[int] = None
class PropertyFilterType(str, Enum):
class PropertyFilterType(StrEnum):
META = "meta"
EVENT = "event"
PERSON = "person"
@ -773,7 +773,7 @@ class PropertyFilterType(str, Enum):
DATA_WAREHOUSE_PERSON_PROPERTY = "data_warehouse_person_property"
class PropertyMathType(str, Enum):
class PropertyMathType(StrEnum):
AVG = "avg"
SUM = "sum"
MIN = "min"
@ -784,7 +784,7 @@ class PropertyMathType(str, Enum):
P99 = "p99"
class PropertyOperator(str, Enum):
class PropertyOperator(StrEnum):
EXACT = "exact"
IS_NOT = "is_not"
ICONTAINS = "icontains"
@ -899,7 +899,7 @@ class RecordingPropertyFilter(BaseModel):
value: Optional[Union[str, float, list[Union[str, float]]]] = None
class Kind1(str, Enum):
class Kind1(StrEnum):
ACTIONS_NODE = "ActionsNode"
EVENTS_NODE = "EventsNode"
@ -917,19 +917,19 @@ class RetentionEntity(BaseModel):
uuid: Optional[str] = None
class RetentionReference(str, Enum):
class RetentionReference(StrEnum):
TOTAL = "total"
PREVIOUS = "previous"
class RetentionPeriod(str, Enum):
class RetentionPeriod(StrEnum):
HOUR = "Hour"
DAY = "Day"
WEEK = "Week"
MONTH = "Month"
class RetentionType(str, Enum):
class RetentionType(StrEnum):
RETENTION_RECURRING = "retention_recurring"
RETENTION_FIRST_TIME = "retention_first_time"
@ -960,7 +960,7 @@ class SessionPropertyFilter(BaseModel):
value: Optional[Union[str, float, list[Union[str, float]]]] = None
class StepOrderValue(str, Enum):
class StepOrderValue(StrEnum):
STRICT = "strict"
UNORDERED = "unordered"
ORDERED = "ordered"
@ -1175,7 +1175,7 @@ class VizSpecificOptions(BaseModel):
RETENTION: Optional[RETENTION] = None
class Kind2(str, Enum):
class Kind2(StrEnum):
UNIT = "unit"
DURATION_S = "duration_s"
PERCENTAGE = "percentage"
@ -1222,7 +1222,7 @@ class WebOverviewQueryResponse(BaseModel):
)
class WebStatsBreakdown(str, Enum):
class WebStatsBreakdown(StrEnum):
PAGE = "Page"
INITIAL_PAGE = "InitialPage"
EXIT_PAGE = "ExitPage"

View File

@ -83,7 +83,7 @@ RUN corepack enable && \
#
# ---------------------------------------------------------
#
FROM python:3.10.10-slim-bullseye AS posthog-build
FROM python:3.11.9-slim-bookworm AS posthog-build
WORKDIR /code
SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]
@ -139,104 +139,7 @@ RUN apt-get update && \
#
# ---------------------------------------------------------
#
# Build a version of the unit docker image for python3.10
# We can remove this step once we are on python3.11
FROM unit:python3.11 as unit
FROM python:3.10-bullseye as unit-131-python-310
# copied from https://github.com/nginx/unit/blob/master/pkg/docker/Dockerfile.python3.11
LABEL org.opencontainers.image.title="Unit (python3.10)"
LABEL org.opencontainers.image.description="Official build of Unit for Docker."
LABEL org.opencontainers.image.url="https://unit.nginx.org"
LABEL org.opencontainers.image.source="https://github.com/nginx/unit"
LABEL org.opencontainers.image.documentation="https://unit.nginx.org/installation/#docker-images"
LABEL org.opencontainers.image.vendor="NGINX Docker Maintainers <docker-maint@nginx.com>"
LABEL org.opencontainers.image.version="1.31.1"
RUN set -ex \
&& savedAptMark="$(apt-mark showmanual)" \
&& apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y ca-certificates mercurial build-essential libssl-dev libpcre2-dev curl pkg-config \
&& mkdir -p /usr/lib/unit/modules /usr/lib/unit/debug-modules \
&& mkdir -p /usr/src/unit \
&& cd /usr/src/unit \
&& hg clone -u 1.31.1-1 https://hg.nginx.org/unit \
&& cd unit \
&& NCPU="$(getconf _NPROCESSORS_ONLN)" \
&& DEB_HOST_MULTIARCH="$(dpkg-architecture -q DEB_HOST_MULTIARCH)" \
&& CC_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_CFLAGS_MAINT_APPEND="-Wp,-D_FORTIFY_SOURCE=2 -fPIC" dpkg-buildflags --get CFLAGS)" \
&& LD_OPT="$(DEB_BUILD_MAINT_OPTIONS="hardening=+all,-pie" DEB_LDFLAGS_MAINT_APPEND="-Wl,--as-needed -pie" dpkg-buildflags --get LDFLAGS)" \
&& CONFIGURE_ARGS_MODULES="--prefix=/usr \
--statedir=/var/lib/unit \
--control=unix:/var/run/control.unit.sock \
--runstatedir=/var/run \
--pid=/var/run/unit.pid \
--logdir=/var/log \
--log=/var/log/unit.log \
--tmpdir=/var/tmp \
--user=unit \
--group=unit \
--openssl \
--libdir=/usr/lib/$DEB_HOST_MULTIARCH" \
&& CONFIGURE_ARGS="$CONFIGURE_ARGS_MODULES \
--njs" \
&& make -j $NCPU -C pkg/contrib .njs \
&& export PKG_CONFIG_PATH=$(pwd)/pkg/contrib/njs/build \
&& ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --ld-opt="$LD_OPT" --modulesdir=/usr/lib/unit/debug-modules --debug \
&& make -j $NCPU unitd \
&& install -pm755 build/sbin/unitd /usr/sbin/unitd-debug \
&& make clean \
&& ./configure $CONFIGURE_ARGS --cc-opt="$CC_OPT" --ld-opt="$LD_OPT" --modulesdir=/usr/lib/unit/modules \
&& make -j $NCPU unitd \
&& install -pm755 build/sbin/unitd /usr/sbin/unitd \
&& make clean \
&& /bin/true \
&& ./configure $CONFIGURE_ARGS_MODULES --cc-opt="$CC_OPT" --modulesdir=/usr/lib/unit/debug-modules --debug \
&& ./configure python --config=/usr/local/bin/python3-config \
&& make -j $NCPU python3-install \
&& make clean \
&& ./configure $CONFIGURE_ARGS_MODULES --cc-opt="$CC_OPT" --modulesdir=/usr/lib/unit/modules \
&& ./configure python --config=/usr/local/bin/python3-config \
&& make -j $NCPU python3-install \
&& cd \
&& rm -rf /usr/src/unit \
&& for f in /usr/sbin/unitd /usr/lib/unit/modules/*.unit.so; do \
ldd $f | awk '/=>/{print $(NF-1)}' | while read n; do dpkg-query -S $n; done | sed 's/^\([^:]\+\):.*$/\1/' | sort | uniq >> /requirements.apt; \
done \
&& apt-mark showmanual | xargs apt-mark auto > /dev/null \
&& { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; } \
&& /bin/true \
&& mkdir -p /var/lib/unit/ \
&& mkdir -p /docker-entrypoint.d/ \
&& groupadd --gid 998 unit \
&& useradd \
--uid 998 \
--gid unit \
--no-create-home \
--home /nonexistent \
--comment "unit user" \
--shell /bin/false \
unit \
&& apt-get update \
&& apt-get --no-install-recommends --no-install-suggests -y install curl $(cat /requirements.apt) \
&& apt-get purge -y --auto-remove build-essential \
&& rm -rf /var/lib/apt/lists/* \
&& rm -f /requirements.apt \
&& ln -sf /dev/stdout /var/log/unit.log
COPY --from=unit /usr/local/bin/docker-entrypoint.sh /usr/local/bin/
COPY --from=unit /usr/share/unit/welcome/welcome.* /usr/share/unit/welcome/
STOPSIGNAL SIGTERM
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
EXPOSE 80
CMD ["unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock"]
#
# ---------------------------------------------------------
#
FROM unit-131-python-310
FROM unit:python3.11
WORKDIR /code
SHELL ["/bin/bash", "-e", "-o", "pipefail", "-c"]
ENV PYTHONUNBUFFERED 1
@ -265,7 +168,7 @@ RUN apt-get install -y --no-install-recommends \
# Install and use a non-root user.
RUN groupadd -g 1000 posthog && \
useradd -u 999 -r -g posthog posthog && \
useradd -r -g posthog posthog && \
chown posthog:posthog /code
USER posthog

View File

@ -1,9 +1,5 @@
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# pip-compile --output-file=requirements-dev.txt requirements-dev.in
#
# This file was autogenerated by uv via the following command:
# uv pip compile requirements-dev.in -o requirements-dev.txt
aiohttp==3.9.3
# via
# -c requirements.txt
@ -42,7 +38,7 @@ black==23.9.1
# -r requirements-dev.in
# datamodel-code-generator
# inline-snapshot
boto3-stubs[s3]==1.34.84
boto3-stubs==1.34.84
# via -r requirements-dev.in
botocore-stubs==1.34.84
# via boto3-stubs
@ -50,7 +46,7 @@ certifi==2019.11.28
# via
# -c requirements.txt
# requests
cffi==1.14.5
cffi==1.16.0
# via
# -c requirements.txt
# cryptography
@ -67,9 +63,9 @@ click==8.1.7
# inline-snapshot
colorama==0.4.4
# via pytest-watch
coverage[toml]==5.5
coverage==5.5
# via pytest-cov
cryptography==37.0.2
cryptography==39.0.2
# via
# -c requirements.txt
# types-paramiko
@ -106,13 +102,13 @@ executing==2.0.1
# via inline-snapshot
faker==17.5.0
# via -r requirements-dev.in
fakeredis[lua]==2.11.0
fakeredis==2.11.0
# via -r requirements-dev.in
flaky==3.7.0
# via -r requirements-dev.in
freezegun==1.2.2
# via -r requirements-dev.in
frozenlist==1.3.0
frozenlist==1.4.1
# via
# -c requirements.txt
# aiohttp
@ -207,7 +203,7 @@ pycparser==2.20
# via
# -c requirements.txt
# cffi
pydantic[email]==2.5.3
pydantic==2.5.3
# via
# -c requirements.txt
# datamodel-code-generator
@ -377,7 +373,7 @@ urllib3==1.26.18
# responses
watchdog==2.1.8
# via pytest-watch
yarl==1.7.2
yarl==1.9.4
# via
# -c requirements.txt
# aiohttp

View File

@ -14,7 +14,7 @@ celery==5.3.4
celery-redbeat==2.1.1
clickhouse-driver==0.2.7
clickhouse-pool==0.5.3
cryptography==37.0.2
cryptography==39.0.2
dj-database-url==0.5.0
Django~=4.2.11
django-axes==5.9.0
@ -29,7 +29,7 @@ django-redis==5.2.0
django-statsd==2.5.2
django-structlog==2.1.3
django-revproxy==0.12.0
djangorestframework==3.14.0
djangorestframework==3.15.1
djangorestframework-csv==2.1.1
djangorestframework-dataclasses==1.2.0
django-fernet-encrypted-fields==0.1.3
@ -96,3 +96,5 @@ nh3==0.2.14
hogql-parser==1.0.21
zxcvbn==4.4.28
zstd==1.5.5.1
xmlsec==1.3.14
lxml==5.2.2

View File

@ -84,7 +84,7 @@ certifi==2019.11.28
# sentry-sdk
# snowflake-connector-python
# urllib3
cffi==1.14.5
cffi==1.16.0
# via
# cryptography
# pynacl
@ -113,7 +113,7 @@ clickhouse-driver==0.2.7
# sentry-sdk
clickhouse-pool==0.5.3
# via -r requirements.in
cryptography==37.0.2
cryptography==39.0.2
# via
# -r requirements.in
# django-fernet-encrypted-fields
@ -195,7 +195,7 @@ django-structlog==2.1.3
# via -r requirements.in
django-two-factor-auth==1.14.0
# via -r requirements.in
djangorestframework==3.14.0
djangorestframework==3.15.1
# via
# -r requirements.in
# djangorestframework-csv
@ -223,7 +223,7 @@ exceptiongroup==1.2.1
# via anyio
filelock==3.12.0
# via snowflake-connector-python
frozenlist==1.3.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal
@ -321,8 +321,9 @@ kombu==5.3.2
# via
# -r requirements.in
# celery
lxml==4.9.4
lxml==5.2.2
# via
# -r requirements.in
# python3-saml
# toronado
# xmlsec
@ -443,7 +444,7 @@ pyjwt==2.4.0
# social-auth-core
pynacl==1.5.0
# via paramiko
pyopenssl==22.0.0
pyopenssl==23.0.0
# via
# snowflake-connector-python
# urllib3
@ -474,7 +475,6 @@ pytz==2023.3
# via
# -r requirements.in
# clickhouse-driver
# djangorestframework
# dlt
# infi-clickhouse-orm
# pandas
@ -623,7 +623,7 @@ toronado==0.1.0
# via -r requirements.in
tqdm==4.64.1
# via openai
trio==0.20.0
trio==0.21.0
# via
# selenium
# trio-websocket
@ -685,9 +685,11 @@ wrapt==1.15.0
# via aiobotocore
wsproto==1.1.0
# via trio-websocket
xmlsec==1.3.13
# via python3-saml
yarl==1.7.2
xmlsec==1.3.14
# via
# -r requirements.in
# python3-saml
yarl==1.9.4
# via aiohttp
zstd==1.5.5.1
# via -r requirements.in

View File

@ -39,7 +39,7 @@
},
"applications": {
"posthog": {
"type": "python 3.10",
"type": "python 3.11",
"processes": $NGINX_UNIT_APP_PROCESSES,
"working_directory": "/code",
"path": ".",
@ -51,7 +51,7 @@
}
},
"metrics": {
"type": "python 3.10",
"type": "python 3.11",
"processes": 1,
"working_directory": "/code/bin",
"path": ".",