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

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

Ir al canal en Telegram

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

Mostrar más
1 060
Suscriptores
-224 horas
-107 días
+9630 días
Archivo de publicaciones
🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 `HttpBasicSyncAuth` and `HttpBasicAsyncAuth` must strictly configure `auth_scheme` prefix (#1330) Currently HTTP-Basic auth is not strict about its auth_scheme prefix. This would be a breaking change, I allow it. Currently, we allow both header values: some-login:password and Basic some-login:password. Which is not really cool: django-modern-rest/dmr/security/http.py Lines 56 to 76 in a2d44b1 We must make this configurable, as all other auth classes do. This must require auth_scheme: str = 'Basic' prefix by default. Also, we must update the OpenAPI description as well: django-modern-rest/dmr/security/http.py Lines 82 to 89 in a2d44b1 (please, do not take this issue before the 1st of September) #feature #good_first_issue #help_wanted #security #opensource_september #django_modern_rest sent via relator

🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 Make sure that `SSE` validation for events work correctly, including custom types and `validate_events=False` (#1329) django-modern-rest/dmr/streaming/sse/metadata.py Lines 169 to 175 in a2d44b1 Currently we have two problems: 1. Even when validate_events=False, we still validate that id and event fields for SSEvent does not contain NULL char and does not contain multiline strings. Which is not really cool. Why? Beceause we slow things down in production, when users explicitly ask us not to. We need to move the validation somewhere else. I propose moving this login into the validator or renderer. But, it must respect the setting. Even if some field is not valid in production, it must not be validated if validate_events=False 2. Currently custom SSE event types are not validated the same way. It would be automatically solved, when 1. is fixed. We would just need more tests for this :) (please, do not take this issue before the 1st of September) #bug #good_first_issue #help_wanted #opensource_september #django_modern_rest sent via relator

🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 The JWT blocklist is silently bypassed by tokens without a `jti` (#1322) There are two problem with jti and blocklist app: 1. We ignore cases where jti is None in the payload. None can't be found here: self.blocklist_model().objects.filter(jti=token.jti).exists(), so this check always passes. Moreover, it does not make sence to use tokens without jti and blocklist app 2. We don't check that token is created with a valid jti when blocklist app is used. We must do that, so this won't potentially fail on tokens with jti=None: django-modern-rest/dmr/security/jwt/blocklist/auth.py Lines 59 to 70 in a2d44b1 So, the logout path raises IntegrityError (HTTP 500) rather than a clean error. We need to add ['jti'] to self.require_claims with JWTokenBlocklistSyncMixin and JWTokenBlocklistAsyncMixin. (please, do not take this issue before the 1st of September) #bug #good_first_issue #help_wanted #security #opensource_september #django_modern_rest sent via relator

🚀 New issue to wemake-services/django-modern-rest by @kondratevdev 📝 Strict boolean `Query` component cannot parse valid OpenAPI boolean values (#1325) What's wrong? Boolean query parameters cannot be parsed correctly when using Pydantic strict validation, even though DMR generates a valid OpenAPI schema for them. For example:
from pydantic import BaseModel, StrictBool

class ProjectsQuery(BaseModel):
    random: StrictBool = False
DMR generates the expected OpenAPI schema:
- name: random
  in: query
  schema:
    type: boolean
    default: false
However, a valid request: GET /projects?random=false is rejected with 400 Bad Request:
{
  "detail": [
    {
      "msg": "Input should be a valid boolean",
      "loc": ["parsed_query", "random"],
      "type": "value_error"
    }
  ]
}
Schemathesis detects this as a schema-compliant request being rejected: API rejected schema-compliant request
Valid data should have been accepted
Expected: 2xx, 401, 403, 404, 409, 5xx
[400] Bad Request Reproduce with: curl -X GET --insecure \ 'http://localhost/api/projects/projects/?random=false'
Why not use a regular bool? A regular Pydantic bool successfully parses query parameters:
class ProjectsQuery(BaseModel):
    random: bool = False
So these work as expected:
?random=true   -> True
?random=false  -> False
However, Pydantic's non-strict boolean parsing also accepts other representations:
?random=1      -> True
?random=0      -> False
This makes the actual API validation more permissive than the generated OpenAPI schema. How it should be? Maybe it should be possible to use strict boolean validation for query parameters while still accepting their valid HTTP/OpenAPI representation? Used versions 0.14.0 OS information Not important for this case (please, do not take this issue before the 1st of September) #bug #good_first_issue #help_wanted #openapi #opensource_september #django_modern_rest sent via relator

🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 `@sensitive_variables` decorator is missing on auth views (#1323) We already have @endpoint_decorator(sensitive_post_parameters()) on all API views that work with auth, but I forgot about sensitive_variables: https://docs.djangoproject.com/en/6.1/howto/error-reporting/#django.views.decorators.debug.sensitive_variables We need to add vars that must not leak into the logs / error reporting middlewares / etc. (please, do not take this issue before the 1st of September) #bug #good_first_issue #help_wanted #security #opensource_september #django_modern_rest sent via relator

🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 `RedirectTo` accepts protocol-relative URLs (#1326) django-modern-rest/dmr/response.py Lines 164 to 168 in a2d44b1 This might be a bug in Django as well.
>>> from urllib.parse import urlsplit
>>> urlsplit('//evil.example/x').scheme
''
So, the scheme check is skipped. Django has https://github.com/django/django/blob/73cc09f14f13fedddc14d6ba5b287cb33c24e4a4/django/utils/http.py#L274 for this case. And this is how it is used: https://github.com/django/django/blob/73cc09f14f13fedddc14d6ba5b287cb33c24e4a4/django/contrib/auth/views.py#L43-L59 We need to add docs about RedirectTo usage. So, developers will know that redirects to users' paths are not always safe. (please, do not take this issue before the 1st of September) #documentation #good_first_issue #help_wanted #security #opensource_september #django_modern_rest sent via relator

🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 Refactor `dmr/security/jwt/auth.py` and `dmr/security/jwt/cookie.py` (#1321) Currently we store JWT's auth as: • dmr/security/jwt/auth.py for headers • dmr/security/jwt/cookie.py for cookies But, Token auth uses: • dmr/security/token/auth/header.pydmr/security/token/auth/cookie.py Which is better. We need to refactor the JWT layout to be the same. (please, do not take this issue before the 1st of September) #good_first_issue #help_wanted #python #opensource_september #django_modern_rest sent via relator

🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 Refresh JWT tokens authenticate as access JWT tokens (#1320) Currently it is possible to auth with JWT access token and JWT refresh token when HeaderJWTSyncAuth / HeaderJWTAsyncAuth / CookieJWT*Auth are used. We need to change how decode_token method works. It must check:
if token.extras.get('type') != self.expected_token_type:
    raise NotAuthenticatedError
And define expected_token_type attribute on base JWT auth with 'access' as the default value. (please, do not take this issue before the 1st of September) #bug #good_first_issue #help_wanted #security #opensource_september #django_modern_rest sent via relator

🚀 New issue to wemake-services/django-modern-rest by @sobolevn 📝 Implement "Breaking changes" detector (#912) Since we have a pretty good OpenAPI scheme, it allows us to DO THINGS 😆 And one of the imporant things it allows us to do is to find breaking API changes. So, here's how I plan to implement this: 1. We would need #909 first 2. Next, we can write a set of test cases that would run on the old schema, but with the new code 3. This way it can detect that clients following the old schema - won't get the expected results back 4. These tests can surely be run with schemathesis 5. We would need to document this and document the setup 6. Maybe provide some tooling, except #909 And we should also list static schema diff tools and explain what is the difference. (Which is that some schema changes are really hard to find statically, because semantics is also important). CC @Stranger6667 #feature #good_first_issue #help_wanted #opensource_september #django_modern_rest sent via relator

🚀 New issue to faststream-community/zMQTT by @borisalekseev 📝 MQTT 5 publish() silently succeeds when PUBACK or PUBREC rejects the message (#65) Summary MQTTClient.publish() returns normally when an MQTT 5 broker rejects a QoS 1 or QoS 2 PUBLISH with a negative acknowledgement reason code. For example, Mosquitto returns 0x87 (Not authorized) for an ACL-denied publication:
Received PubAck(packet_id=1, reason_code=135, properties=None)
The message was not accepted by the broker, but await client.publish(...) completes without an exception. Current behavior For QoS 1, _handle_puback() resolves the publish future successfully without checking PubAck.reason_code. For QoS 2, _handle_pubrec() also ignores the reason code and sends PUBREL even when PUBREC contains 0x87. MQTT 5 only permits PUBREL after a PUBREC reason code below 0x80. The public MQTTClient.publish() method discards the acknowledgement returned by MQTTProtocol.publish(). Expected behavior • PUBACK/PUBREC reason codes below 0x80, including 0x00 and 0x10 (No matching subscribers), complete successfully. • A PUBACK or PUBREC reason code of 0x80 or greater raises a public MQTTPublishError. • The exception exposes at least reason_code; exposing the optional Reason String would also be useful. • A negative PUBREC completes and removes the QoS 2 flight, releases its packet identifier, and does not send PUBREL. • The MQTT connection remains usable after the rejected operation. • MQTT 3.1.1 behavior remains unchanged because PUBACK and PUBREC do not carry reason codes in that protocol version. MQTTPublishError would be consistent with the existing MQTTSubscribeError. Protocol referencesMQTT 5.0 section 2.4: reason codes 0x80 and greater indicate failure. • MQTT 5.0 section 3.4.2.1: PUBACK 0x87 means the PUBLISH is not authorized. • MQTT 5.0 section 3.5.2.1: PUBREC has the same publish-rejection reason codes. • MQTT 5.0 section 4.3.3: PUBREL is sent only after a PUBREC reason code below 0x80. • MQTT 5.0 section 4.4: a negative PUBACK/PUBREC acknowledges the packet for retry purposes, but does not make the publication successful. • MQTT 3.1.1 section 3.3.5: when a PUBLISH is not authorized, the server must either send a positive acknowledgement or close the connection because the protocol has no negative publish acknowledgement. Reproduction result Reproduced with Mosquitto 2.1.2 and a read-only ACL:
MQTT 5 QoS 1:
Received PubAck(packet_id=1, reason_code=135, properties=None)
publish() returned normally

MQTT 5 QoS 2:
Received PubRec(packet_id=1, reason_code=135, properties=None)
QoS 2 PUBREC received, sent PUBREL
publish() returned normally
Mosquitto logs Denied PUBLISH for both messages. Suggested tests • QoS 1 negative PUBACK raises and releases the packet identifier. • QoS 1 0x10 completes successfully. • QoS 2 negative PUBREC raises, releases the packet identifier, and sends no PUBREL. • Optional Reason String is preserved in the exception. • MQTT 3.1.1 ACK behavior is unchanged. #good_first_issue #faststream #zmqtt sent via relator

🚀 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