uk
Feedback
Находки в опенсорсе: Python

Находки в опенсорсе: Python

Відкрити в Telegram

Легкие задачки в опенсорсе из мира Python Чат: @opensource_findings_chat

Показати більше
959
Підписники
Немає даних24 години
-57 днів
-1230 день
Архів дописів
🚀 New issue to ag2ai/faststream by @Lancetnik 📝 Bug: `redis.asyncio.Redis` type hint is not injected and fails validation (#3065) Describe the bug Annotating a handler argument with redis.asyncio.Redis — the obvious type for the connection — does not inject it. Instead the argument is treated as a message field and fails validation. The working annotation is faststream.redis.annotations.Redis, which is a different symbol with the same name. The two names are identical, the import paths differ, and nothing in the failure points at the fix. How to reproduce
from redis.asyncio import Redis

@broker.subscriber(stream=StreamSub("stream", group="group", consumer="consumer"))
async def handler(msg: RedisStreamMessage, redis: Redis) -> None:
    ...
vs. the version that works:
from faststream.redis.annotations import Redis
Real usage A worker running faststream[redis] in production hit this and left a warning to their future selves in the handler docstring — SW-Maestro-17th-HBB/Kkori-AI, worker/src/main.py#L186-L191:
redis 는 FastStream 이 Context 로 넣어주는 커넥션이다. redis.asyncio.Redis 를 그대로 힌트로 쓰면 주입되지 않고 검증 오류가 난다. ("redis is the connection FastStream injects via Context. If you use redis.asyncio.Redis directly as the hint, it is not injected and you get a validation error.")
They also import it aliased — from faststream.redis.annotations import Redis as InjectedRedis — which suggests the name collision cost them enough to want it visible at the call site. Expected behavior Two things would each be enough on their own: 1. Documentation — the Redis pages show Redis in examples without making the import path explicit enough to survive a copy-paste. A short note that the annotation comes from faststream.redis.annotations, and that the same-named driver class will not work, closes it. 2. A better failure — when an argument is annotated with a broker client class that has a matching FastStream annotation, say so in the error instead of failing validation on a missing message field. Additional context Found by reading a real user's source, not reported by them — they worked around it and moved on, which is the reason this kind of papercut stays invisible. Companion finding: #3064. @IvanKirpichnikov — the docs half is cheap; the error-message half is your call. #bug #documentation #good_first_issue #redis #faststream #ag2ai sent via relator

🚀 New issue to ag2ai/faststream by @mahdialibi 📝 DOC - V 0.5 - Error in documentaion (#3047) in documentation : https://faststream.ag2.ai/0.5/getting-started/observability/logging/#setting-logging-configuration-from-file is stated :
If you use FastStream CLI, you have the option to use a file to configure your logging of the entire application directly from the command line.
faststream run serve:app --log-file config.json
But this is misleading , this feature is not available in v 0.5 #good_first_issue #faststream #ag2ai sent via relator

🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 Add `Parser.validate` method to perform import-time checks (#1304) While working on #1275, I realized that proposed OctetStreamParser is kinda unique, because it must not contain Body[...] near FileMetadata[...] defintions. Why? Because it only accepts a single stream of bytes, there can't be a body nearby. So, what should we do for similar cases? I propose adding validate method to the Parser class, empty by default. It would be similar to ComponentParser.validate method. And then call it in validation process. This test parser should check that it only works on endpoints with FileMetadata and no Body. #feature #good_first_issue #help_wanted #django_modern_rest sent via relator

🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 Fix how `Controller` generates `additionalOperations` (#1300) See https://spec.openapis.org/oas/v3.2.0.html#path-item-object django-modern-rest can use custom allowed_http_methods to add any desired additional HTTP methods. But, right now Controller does not respect to this option when generating schema: django-modern-rest/dmr/controller.py Lines 529 to 555 in 3e2874f But, this is not correct. We can only add methods that are defined on PathItem directly. All other items must go to additionalOperations dict. This needs to be fixed, tested, and schema must be generated and tested as well. #bug #good_first_issue #help_wanted #openapi #django_modern_rest sent via relator

🚀 New issue to ag2ai/faststream by @kumaranvpl 📝 Ability to configure topic params in confluent create_topics (#1827) Current state: every topic FastStream creates is created with num_partitions=1, replication_factor=1, hardcoded: faststream/faststream/confluent/helpers/admin.py Lines 52 to 55 in 2e36197 The only knob users have is the broker-wide allow_auto_create_topics flag — all topics of a broker are created, or none of them are. There is no way to configure a single topic, nor to opt a single topic out of creation. Request: introduce a Topic schema object accepted by subscriber() / publisher() alongside plain strings, carrying per-topic settings:
from faststream.confluent import KafkaBroker, Topic

broker = KafkaBroker()

@broker.subscriber(
    Topic("topic-name", num_partitions=3),
    Topic("topic-name2", num_partitions=1, replication_factor=2),
    Topic("externally-managed", declare=False),
    "topic-without-settings",
)
async def handler(msg: str) -> None: ...
Scope 1.  num_partitions / replication_factor per topic — the original ask, from https://github.com/airtai/faststream/discussions/1821. Today both are pinned to 1, which makes FastStream-created topics unusable in any real deployment. 2.  declare: bool = True — opt a single topic out of creation while auto-creation stays the default for everything else. This subsumes #2679: the global default is not changing, because a broker-wide switch is the wrong granularity — a service typically owns some of its topics and consumes others that are provisioned by a different team or by IaC. Proposed semantics of declare=False: skip the create_topics call for that topic and nothing else — do not probe the cluster for existence, do not fail if the topic is missing. This matches what allow_auto_create_topics=False does today (a warning, then let the consumer proceed) and matches NATS' JStream(declare=False). Note this deliberately differs from RabbitMQ's RabbitQueue(declare=False), which maps to AMQP passive=True and does raise when the queue is absent — Kafka has no cheap equivalent of a passive declare. Interaction with the broker-level flag: allow_auto_create_topics=False on the broker keeps winning over everything — it stays the "create nothing at all" switch. declare only narrows creation further when the broker-level flag is on. Consistency across brokers: declare is the established name for this in FastStream — RabbitQueue(declare=...), JStream(declare=...), KvWatch(declare=...), ObjWatch(declare=...). Topic should use the same name rather than inventing a Kafka-specific one. AioKafka is out of scope. FastStream never creates topics for faststream.kafka — there is no AdminClient.create_topics call on that path, and aiokafka (0.13.0) does not support an allow_auto_create_topics consumer option at all:
$ grep -rn "auto_create\|auto\.create" .venv/lib/python3.11/site-packages/aiokafka/
$ grep -rn "auto_create" faststream/kafka/
Both return nothing. Topic creation on that path is entirely the Kafka server's auto.create.topics.enable, which FastStream cannot influence. Topic may still be accepted there later for symmetry, but declare would be a no-op, so it should not block this issue. Implementation notescreate_subscriber() / create_publisher() signatures must accept str | Topic*topics: str is what currently trips mypy on the branch in progress. • Normalise strTopic(name) at registration time, as RabbitMQ does with strRabbitQueue. • AsyncConfluentConsumer.topics_to_create should filter on declare faststream/faststream/confluent/helpers/client.py  Lines 292 to 294 in 2e36197Topic needs __hash__ / __eq__ consistent with each other, since topics end up as dict keys (see #2796 for the RabbitMQ precedent). Related: #2679 (closed in favour of this), #1486, #1658, #2451. #enhancement #good_first_issue #confluent #kafka #faststream #ag2ai sent via relator

🚀 New issue to ag2ai/faststream by @Lancetnik 📝 feature: document RPC responses in AsyncAPI (#1586) #enhancement #good_first_issue #core #asyncapi #faststream #ag2ai sent via relator

🚀 New issue to wemake-services/django-modern-rest by @vyhuholl 📝 Reusable controllers to issue JWT tokens as cookies (#1290) FEATURE Thesis Follow-up to #1287. That PR added CookieJWTSyncAuth / CookieJWTAsyncAuth, which read a JWT from a cookie. Nothing in the framework writes one, so the issuing half is still left to every user. docs/pages/auth/jwt.rst currently carries a .. todo:: in place of an example, and this issue is that todo. What is needed 1. Obtain: authenticate and set the access and refresh cookies 2. Refresh: read the refresh token from its cookie and rotate both 3. Log out: clear both cookies, ideally blocklisting the access token (there is no logout controller today at all) The design obstacle This is the part that needs a decision, and it is why the todo is still a todo rather than a patch. Cookie values are only known at request time, but both ways of declaring cookies fix them at decoration time: • @modify(cookies=...) takes NewCookie instances, and ModifyEndpointPayload.actionable_cookies() returns exactly those objects. Static values only. • @validate takes ResponseSpec(cookies=...), which accepts only CookieSpec, that is a description and not a value. Runtime values then go through self.to_response(..., cookies={...: NewCookie(value=...)}). The second one works, and it is what a hand-written controller does today. But in a reusable controller the decorator runs once, on the base class. The cookie names and flags would be frozen there, and a subclass could only change them by redefining post completely, which removes the reason to have a reusable controller in the first place. Note that per-subclass data does already reach endpoint metadata: Controller.__init_subclass__ builds an Endpoint per concrete subclass, and ResponseSpecProvider.provide_response_specs receives controller_cls. So a hook is feasible. The open question is its shape, not whether it can exist. Open questions • Where do the cookie names and flags come from? ClassVars on the controller like the existing jwt_* settings, dmr settings, or a dedicated spec object? • Should the tokens still appear in the response body? Putting them in both places is convenient and undoes the point of httponly. • Does logout blocklist the access token, or stay transport-only? • How is Set-Cookie represented in the generated OpenAPI schema when the names are configurable? Requirements for whatever we buildhttponly=True and secure=True by default, and samesite no weaker than 'lax' • The refresh cookie scoped by path to the refresh endpoint, so it is not sent to the rest of the API • Cookie names matching the auth side, which defaults to DEFAULT_ACCESS_COOKIE (access_token) and DEFAULT_REFRESH_COOKIE (refresh_token) in dmr/security/jwt/cookie.py • Sync and async variants, like every other controller here • Working together with the CSRF check in CookieJWTSyncAuth • The .. todo:: in docs/pages/auth/jwt.rst replaced by a real example Reasoning The cookie flags are the entire security surface of this flow. An example is copied verbatim far more often than it is read, and a copy that drops httponly hands the token to any XSS on the page. So the docs deliberately ship no example until there is a controller that gets the defaults right. That is the same reasoning behind ObtainTokensSyncController for the body flow: users should not have to reassemble the security-critical parts. #feature #help_wanted #django_modern_rest sent via relator

🚀 New issue to ag2ai/faststream by @Lancetnik 📝 Feature: use aio_pika.Pool to connect RMQ (#975) For now, FastStream uses a regular RobustConnection and RobustChannel to connect RabbitMQ, but we should support aio-pika connection Pool feature in this case https://aio-pika.readthedocs.io/en/latest/quick-start.html#connection-pooling Probably, regular behavior should be the Pool with size 1 #enhancement #good_first_issue #rabbitmq #100 #faststream #ag2ai sent via relator

🚀 New issue to wemake-services/wemake-python-styleguide by @sobolevn 📝 Build a MCP extra (#3770) We need to add an MCP protocol support to wemake-python-styleguide. It should be installed with wemake-python-styleguide[mcp] and advertised in the readme. What should it do? Provide the same output as wps explain WPSXXX. But, tool call is much more expensive than an MCP call. CC @Khabib73 #feature #help_wanted #levelstarter #good_first_issue #wemake_python_styleguide #wps sent via relator

🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 Should we really keep `QueryTokenSyncAuth` and `QueryTokenAsyncAuth`? (#1288) They are really unsafe, because they can expose the token in logs. I don't think that we should offer explicitly unsafe auth methods even with the disclaimer. Let's remove everything related to QueryTokenSyncAuth and QueryTokenAsyncAuth from the next release. What do others think? Any objections? #feature #good_first_issue #help_wanted #django_modern_rest sent via relator

🚀 New issue to faststream-community/zMQTT by @borisalekseev 📝 Supress Artemis flaky test (#57) Race condition in Artemis produces flaks on message ordering tests (https://issues.apache.org/jira/browse/ARTEMIS-6191). We have to supress it while ordering is broken in Artemis. Flaky run: https://github.com/faststream-community/zMQTT/actions/runs/32063447688/job/95489785526 Left artemis issue link pytest.skip. #good_first_issue #faststream #zmqtt sent via relator

🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 Support conditional files models (#1275) We already have conditional Body models. Which we fully test and support. Docs: https://django-modern-rest.readthedocs.io/en/latest/pages/negotiation.html#using-different-schemes-for-different-content-types But, we don't test conditional FileMetadata[] components. See this TODO: django-modern-rest/dmr/components.py Lines 884 to 900 in e0c2546 Supporting it might require some additional work. #feature #good_first_issue #help_wanted #django_modern_rest sent via relator

🚀 New issue to ag2ai/faststream by @IvanKirpichnikov 📝 Bug: Uncorrect typehint for `partition_assignment_strategy` parameter in `faststream.kafka` (#3019) Now: partition_assignment_strategy: Sequence["AbstractPartitionAssignor"] Need: partition_assignment_strategy: Sequence["type[AbstractPartitionAssignor]"] #bug #good_first_issue #aiokafka #faststream #ag2ai sent via relator

🚀 New issue to faststream-community/zMQTT by @borisalekseev 📝 Add Last Will support to the public MQTTClient API (#45) Problem zmqtt already implements MQTT Last Will at the packet/codec level, but it cannot be configured through the public high-level client API. Currently: • Will and WillProperties are only available through private  zmqtt._internal modules; • MQTTClient and create_client() do not accept a will= argument; • MQTTClient._connect() builds every CONNECT packet without a Will. As a result, users and frameworks built on the public zmqtt.MQTTClient API, including FastStream, cannot configure an MQTT Last Will without depending on private implementation details. Proposed API
from zmqtt import MQTTClient, QoS, Will, WillProperties

will = Will(
    topic="devices/device-42/status",
    payload=b"offline",
    qos=QoS.AT_LEAST_ONCE,
    retain=True,
    properties=WillProperties(
        will_delay_interval=10,
        content_type="text/plain",
    ),
)

client = MQTTClient(
    "broker.example.com",
    version="5.0",
    will=will,
)
For MQTT 3.1.1, the same Will type should be usable without WillProperties. Scope • Export Will and WillProperties from the top-level zmqtt package. • Add will: Will | None = None to MQTTClient. • Add the same argument to create_client() and all of its typed overloads. • Store the configured Will and pass it to every Connect packet created by  the client. • Preserve the same Will configuration when the client reconnects after an  established connection is lost. • Reject MQTT 5.0 Will properties on MQTT 3.1.1 with a clear error consistent  with other version-specific options. • Keep the current behavior unchanged when will=None. Tests The tests should exercise the public client path rather than only the existing packet codec: • MQTT 3.1.1: construct MQTTClient(..., will=...), decode the emitted  CONNECT, and verify the Will topic, payload, QoS, and retain flag. • MQTT 5.0: verify the same fields together with WillProperties. • Simulate will receiving of second client when the first reconnected unexpectedly Tests should test public behaviour with real broker instead internals testing and avoid monkey patching. #enhancement #good_first_issue #faststream #zmqtt sent via relator

🚀 New issue to ag2ai/faststream by @kumaranvpl 📝 Ability to configure topic params in confluent create_topics (#1827) Current state: every topic FastStream creates is created with num_partitions=1, replication_factor=1, hardcoded: faststream/faststream/confluent/helpers/admin.py Lines 52 to 55 in 2e36197 The only knob users have is the broker-wide allow_auto_create_topics flag — all topics of a broker are created, or none of them are. There is no way to configure a single topic, nor to opt a single topic out of creation. Request: introduce a Topic schema object accepted by subscriber() / publisher() alongside plain strings, carrying per-topic settings:
from faststream.confluent import KafkaBroker, Topic

broker = KafkaBroker()

@broker.subscriber(
    Topic("topic-name", num_partitions=3),
    Topic("topic-name2", num_partitions=1, replication_factor=2),
    Topic("externally-managed", declare=False),
    "topic-without-settings",
)
async def handler(msg: str) -> None: ...
Scope 1.  num_partitions / replication_factor per topic — the original ask, from https://github.com/airtai/faststream/discussions/1821. Today both are pinned to 1, which makes FastStream-created topics unusable in any real deployment. 2.  declare: bool = True — opt a single topic out of creation while auto-creation stays the default for everything else. This subsumes #2679: the global default is not changing, because a broker-wide switch is the wrong granularity — a service typically owns some of its topics and consumes others that are provisioned by a different team or by IaC. Proposed semantics of declare=False: skip the create_topics call for that topic and nothing else — do not probe the cluster for existence, do not fail if the topic is missing. This matches what allow_auto_create_topics=False does today (a warning, then let the consumer proceed) and matches NATS' JStream(declare=False). Note this deliberately differs from RabbitMQ's RabbitQueue(declare=False), which maps to AMQP passive=True and does raise when the queue is absent — Kafka has no cheap equivalent of a passive declare. Interaction with the broker-level flag: allow_auto_create_topics=False on the broker keeps winning over everything — it stays the "create nothing at all" switch. declare only narrows creation further when the broker-level flag is on. Consistency across brokers: declare is the established name for this in FastStream — RabbitQueue(declare=...), JStream(declare=...), KvWatch(declare=...), ObjWatch(declare=...). Topic should use the same name rather than inventing a Kafka-specific one. AioKafka is out of scope. FastStream never creates topics for faststream.kafka — there is no AdminClient.create_topics call on that path, and aiokafka (0.13.0) does not support an allow_auto_create_topics consumer option at all:
$ grep -rn "auto_create\|auto\.create" .venv/lib/python3.11/site-packages/aiokafka/
$ grep -rn "auto_create" faststream/kafka/
Both return nothing. Topic creation on that path is entirely the Kafka server's auto.create.topics.enable, which FastStream cannot influence. Topic may still be accepted there later for symmetry, but declare would be a no-op, so it should not block this issue. Implementation notescreate_subscriber() / create_publisher() signatures must accept str | Topic*topics: str is what currently trips mypy on the branch in progress. • Normalise strTopic(name) at registration time, as RabbitMQ does with strRabbitQueue. • AsyncConfluentConsumer.topics_to_create should filter on declare faststream/faststream/confluent/helpers/client.py  Lines 292 to 294 in 2e36197Topic needs __hash__ / __eq__ consistent with each other, since topics end up as dict keys (see #2796 for the RabbitMQ precedent). Related: #2679 (closed in favour of this), #1486, #1658, #2451. #good_first_issue #confluent #kafka #faststream #ag2ai sent via relator

🚀 New issue to ag2ai/faststream by @Lancetnik 📝 Feature: `StreamSub(declare=False)` to opt out of Redis Stream creation (#3013) Is your feature request related to a problem? Please describe. FastStream creates the Redis Stream for you whenever a subscriber uses a consumer group — mkstream=True is hardcoded and there is no way to turn it off: faststream/faststream/redis/subscriber/usecases/stream_subscriber.py Lines 133 to 138 in 2e36197 That is a fine default, but it means a typo in a stream name silently provisions a new empty stream instead of failing, and a service that is only supposed to consume a stream provisioned elsewhere has no way to say so. Every other broker in FastStream already has this opt-out — RabbitQueue(declare=False), RabbitExchange(declare=False), JStream(declare=False), KvWatch(declare=False), ObjWatch(declare=False). Redis is the only one missing it. The same knob is being added to Kafka in #1827. Describe the solution you'd like A declare: bool = True argument on StreamSub, passed through as mkstream=not declare. Default behaviour does not change. Feature code example
from faststream import FastStream
from faststream.redis import RedisBroker, StreamSub

broker = RedisBroker()
app = FastStream(broker)


# unchanged default — stream is created if missing
@broker.subscriber(stream=StreamSub("orders", group="g", consumer="c"))
async def owned(msg: str) -> None: ...


# provisioned elsewhere — fail fast instead of creating an empty stream
@broker.subscriber(
    stream=StreamSub("external-events", group="g", consumer="c", declare=False)
)
async def consumed(msg: str) -> None: ...
Semantics Redis only offers the "check, do not create" form, so declare=False fails when the stream is absent — the same as RabbitMQ's declare=False (AMQP passive=True), and unlike NATS' variant which just skips creation. Verified against redis:alpine:
mkstream=False -> ResponseError: The XGROUP subcommand requires the key to exist.
                  Note that for CREATE you may want to use the MKSTREAM option to
                  create an empty stream automatically.
exists after mkstream=False: 0
mkstream=True  -> exists after: 1
The existing except ResponseError only swallows "already exists", so this error propagates as-is today — which is the wanted behaviour. Wrapping it in a FastStream error with a message pointing at declare=False would be a nice touch, not a requirement. Implementation notes 1. Add declare: bool = True to StreamSub.__init__ and to __slots__ faststream/faststream/redis/schemas/stream_sub.py  Lines 44 to 69 in 2e36197  — plus an Args: entry in the class docstring. 2. Pass mkstream=not stream.declare at the xgroup_create call linked above. 3. declare only has an effect on the consumer-group path — that xgroup_create runs only when group and consumer are both set. Without a group the subscriber uses XREAD, which never creates anything. StreamSub already emits RuntimeWarning for argument combinations that have no effect (no_ack with a group, polling_interval with last_id != ">"); declare=False without a group deserves the same treatment. 4. Tests go in tests/brokers/redis/ — one real-broker case asserting the stream is not created and the error surfaces, one asserting the default still creates it. Out of scope: publishing. XADD always creates the stream and Redis exposes no flag to prevent it, so there is no publisher-side equivalent. Additional context Prior art to copy the naming and docstring style from: RabbitQueue.declare and JStream.declare. #enhancement #good_first_issue #redis #faststream #ag2ai sent via relator

🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 Support `django-stubs@6.1` (#1263) We need to bump the package version and fix any potential problems found by mypy. #good_first_issue #help_wanted #dependencies #django_modern_rest sent via relator

🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 Add `Router.to_urlpatterns` method (#1262) The main idea is that we can refactor this:
>>> from django.urls import include, path
>>> from dmr.routing import Router

>>> router = Router(
...     'api/',
...     [
...         path('user/', UserController.as_view(), name='users'),
...     ],
... )
>>> urlpatterns = [
...     path(router.prefix, include((router.urls, 'my_app'), namespace='api')),
... ]
into this:
>>> from django.urls import include, path
>>> from dmr.routing import Router

>>> router = Router(
...     'api/',
...     [
...         path('user/', UserController.as_view(), name='users'),
...     ],
... )
>>> urlpatterns = [
...     path(*router.to_urlpatterns(namespace='api')),
... ]
It should return tuple of (prefix, urlpatterns) properly typed. It also should be a default way in the docs. You would also need to update routing.rst docs to show that these two operations are basically the same. See how we do it with Router.include in the same file. #feature #good_first_issue #help_wanted #django_modern_rest sent via relator

🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 Support `ty` for type-checking (#1257) Very interesting Things to do: • Install specific ty version • Enable its strict mode • Type-check dmr/ and typesafety/ directories • Fix all real problems found by it • Ignore all false-positives • Add a changelog entry • Update list of support type-checkers in README.md If it produces way to many errors for one specific problem: disable it in config instead. #feature #good_first_issue #help_wanted #django_modern_rest sent via relator