Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions conformance/test/_util.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import asyncio
import sys

Expand Down
11 changes: 8 additions & 3 deletions conformance/test/client.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from __future__ import annotations

import argparse
import asyncio
import ssl
import sys
import time
import traceback
from collections.abc import AsyncIterator, Iterator
from tempfile import NamedTemporaryFile
from typing import Literal, TypeVar
from typing import TYPE_CHECKING, Literal, TypeVar

import httpx
from _util import create_standard_streams
Expand All @@ -29,14 +30,18 @@
UnaryRequest,
UnimplementedRequest,
)
from google.protobuf.any_pb2 import Any
from google.protobuf.message import Message

from connectrpc.client import ResponseMetadata
from connectrpc.code import Code
from connectrpc.errors import ConnectError
from connectrpc.request import Headers

if TYPE_CHECKING:
from collections.abc import AsyncIterator, Iterator

from google.protobuf.any_pb2 import Any


def _convert_code(error: Code) -> ConformanceCode:
match error:
Expand Down
18 changes: 14 additions & 4 deletions conformance/test/gen/connectrpc/conformance/v1/service_connect.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
# Generated by https://github.com/connectrpc/connect-python. DO NOT EDIT!
# source: connectrpc/conformance/v1/service.proto
from __future__ import annotations

from collections.abc import AsyncGenerator, AsyncIterator, Iterable, Iterator, Mapping
from typing import Protocol
from typing import TYPE_CHECKING, Protocol

from connectrpc.client import ConnectClient, ConnectClientSync
from connectrpc.code import Code
from connectrpc.errors import ConnectError
from connectrpc.interceptor import Interceptor, InterceptorSync
from connectrpc.method import IdempotencyLevel, MethodInfo
from connectrpc.request import Headers, RequestContext
from connectrpc.server import (
ConnectASGIApplication,
ConnectWSGIApplication,
Expand All @@ -19,6 +17,18 @@

from . import service_pb2 as connectrpc_dot_conformance_dot_v1_dot_service__pb2

if TYPE_CHECKING:
from collections.abc import (
AsyncGenerator,
AsyncIterator,
Iterable,
Iterator,
Mapping,
)

from connectrpc.interceptor import Interceptor, InterceptorSync
from connectrpc.request import Headers, RequestContext


class ConformanceService(Protocol):
async def unary(
Expand Down
10 changes: 7 additions & 3 deletions conformance/test/server.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import argparse
import asyncio
import os
Expand All @@ -7,7 +9,6 @@
import ssl
import sys
import time
from collections.abc import AsyncIterator, Iterator
from contextlib import ExitStack, closing
from tempfile import NamedTemporaryFile
from typing import TYPE_CHECKING, Literal, TypeVar, get_args
Expand Down Expand Up @@ -43,14 +44,17 @@

from connectrpc.code import Code
from connectrpc.errors import ConnectError
from connectrpc.request import RequestContext

if TYPE_CHECKING:
from collections.abc import AsyncIterator, Iterator

from google.protobuf.message import Message

from connectrpc.request import RequestContext


# TODO: Use google.protobuf.any.pack on upgrade to protobuf==6.
def pack(msg: "Message") -> Any:
def pack(msg: Message) -> Any:
any_msg = Any()
any_msg.Pack(msg)
return any_msg
Expand Down
2 changes: 2 additions & 0 deletions conformance/test/test_client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import subprocess
import sys
from pathlib import Path
Expand Down
2 changes: 2 additions & 0 deletions conformance/test/test_server.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import os
import subprocess
import sys
Expand Down
7 changes: 6 additions & 1 deletion example/example/_eliza.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from __future__ import annotations

import random
import re
from collections.abc import Sequence
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from collections.abc import Sequence

# Ported from https://github.com/connectrpc/examples-go
# Originally from https://github.com/mattshiel/eliza-go
Expand Down
2 changes: 2 additions & 0 deletions example/example/eliza_client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import asyncio

from example.eliza_connect import ElizaServiceClient
Expand Down
2 changes: 2 additions & 0 deletions example/example/eliza_client_sync.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from example.eliza_connect import ElizaServiceClientSync
from example.eliza_pb2 import IntroduceRequest, SayRequest

Expand Down
18 changes: 14 additions & 4 deletions example/example/eliza_connect.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
# Generated by https://github.com/connectrpc/connect-python. DO NOT EDIT!
# source: example/eliza.proto
from __future__ import annotations

from collections.abc import AsyncGenerator, AsyncIterator, Iterable, Iterator, Mapping
from typing import Protocol
from typing import TYPE_CHECKING, Protocol

from connectrpc.client import ConnectClient, ConnectClientSync
from connectrpc.code import Code
from connectrpc.errors import ConnectError
from connectrpc.interceptor import Interceptor, InterceptorSync
from connectrpc.method import IdempotencyLevel, MethodInfo
from connectrpc.request import Headers, RequestContext
from connectrpc.server import (
ConnectASGIApplication,
ConnectWSGIApplication,
Expand All @@ -19,6 +17,18 @@

import example.eliza_pb2 as example_dot_eliza__pb2

if TYPE_CHECKING:
from collections.abc import (
AsyncGenerator,
AsyncIterator,
Iterable,
Iterator,
Mapping,
)

from connectrpc.interceptor import Interceptor, InterceptorSync
from connectrpc.request import Headers, RequestContext


class ElizaService(Protocol):
async def say(
Expand Down
7 changes: 5 additions & 2 deletions example/example/eliza_service.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from __future__ import annotations

import asyncio
from collections.abc import AsyncIterator
from typing import TYPE_CHECKING, cast

from connectrpc.request import RequestContext
from starlette.applications import Starlette
from starlette.responses import PlainTextResponse
from starlette.routing import Mount, Route
Expand All @@ -19,6 +19,9 @@
)

if TYPE_CHECKING:
from collections.abc import AsyncIterator

from connectrpc.request import RequestContext
from starlette.types import ASGIApp


Expand Down
10 changes: 8 additions & 2 deletions example/example/eliza_service_sync.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from __future__ import annotations

import time
from collections.abc import Iterator
from typing import TYPE_CHECKING

from connectrpc.request import RequestContext
from flask import Flask
from werkzeug.middleware.dispatcher import DispatcherMiddleware

Expand All @@ -17,6 +18,11 @@
from . import _eliza
from .eliza_connect import ElizaServiceSync, ElizaServiceWSGIApplication

if TYPE_CHECKING:
from collections.abc import Iterator

from connectrpc.request import RequestContext


class DemoElizaServiceSync(ElizaServiceSync):
stream_delay_secs: float
Expand Down
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ BUF_VERSION := "v1.57.0"

# Format Python files
format:
uv run ruff check --fix .
uv run ruff check --fix --unsafe-fixes --exit-zero .
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot to comment on this. I have been using unsafe-fixes for a long time and find it great, zero times has it done a wrong fix. That's probably because I work with well behaved code without weird side effects, but I think it applies here too. In the off chance it does do something wrong, manually fixing it would be relatively easy.

uv run ruff format .

# Lint Python files
Expand Down
2 changes: 2 additions & 0 deletions noextras/test/test_compression_default.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import pytest
from example.eliza_connect import (
ElizaService,
Expand Down
2 changes: 2 additions & 0 deletions protoc-gen-connect-python/scripts/generate_wheels.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import json
import shutil
import subprocess
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ extend-ignore = [
"PLR",
]

typing-extensions = false

[tool.ruff.lint.per-file-ignores]
"conformance/test/**" = ["ANN", "INP", "SLF", "SIM115", "S101", "D"]
"example/**" = [
Expand All @@ -206,6 +208,7 @@ extend-ignore = [
]

[tool.ruff.lint.isort]
required-imports = ["from __future__ import annotations"]
split-on-trailing-comma = false

[tool.ruff]
Expand Down
2 changes: 2 additions & 0 deletions src/connectrpc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

__all__ = ["__version__"]


Expand Down
8 changes: 6 additions & 2 deletions src/connectrpc/_asyncio_timeout.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
# SPDX-License-Identifier: PSF-2.0

# Backport of asyncio.timeout for Python 3.10
from __future__ import annotations

import enum
import sys
from asyncio import events, exceptions, tasks
from types import TracebackType
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from types import TracebackType

_HAX_EXCEPTION_GROUP = sys.version_info >= (3, 11)

Expand Down Expand Up @@ -80,7 +84,7 @@ def __repr__(self) -> str:
info_str = " ".join(info)
return f"<Timeout [{self._state.value}]{info_str}>"

async def __aenter__(self) -> "Timeout":
async def __aenter__(self) -> Timeout:
if self._state is not _State.CREATED:
msg = "Timeout has already been entered"
raise RuntimeError(msg)
Expand Down
13 changes: 8 additions & 5 deletions src/connectrpc/_client_async.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from __future__ import annotations

import asyncio
import functools
from asyncio import CancelledError, sleep, wait_for
from collections.abc import AsyncIterator, Iterable, Mapping
from types import TracebackType
from typing import TYPE_CHECKING, Any, Protocol, TypeVar

import httpx
Expand All @@ -11,7 +11,6 @@
from . import _client_shared
from ._asyncio_timeout import timeout as asyncio_timeout
from ._codec import Codec, get_proto_binary_codec, get_proto_json_codec
from ._compression import Compression
from ._envelope import EnvelopeReader, EnvelopeWriter
from ._interceptor_async import (
BidiStreamInterceptor,
Expand All @@ -24,8 +23,6 @@
from ._protocol import CONNECT_STREAMING_HEADER_COMPRESSION, ConnectWireError
from .code import Code
from .errors import ConnectError
from .method import MethodInfo
from .request import Headers, RequestContext

try:
from asyncio import (
Expand All @@ -36,6 +33,12 @@

if TYPE_CHECKING:
import sys
from collections.abc import AsyncIterator, Iterable, Mapping
from types import TracebackType

from ._compression import Compression
from .method import MethodInfo
from .request import Headers, RequestContext

if sys.version_info >= (3, 11):
from typing import Self
Expand Down
21 changes: 13 additions & 8 deletions src/connectrpc/_client_shared.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
from __future__ import annotations

import base64
import contextlib
from collections.abc import Iterable, Mapping, Sequence
from contextvars import ContextVar, Token
from http import HTTPStatus
from types import TracebackType
from typing import TypeVar

from httpx import Headers as HttpxHeaders
from typing import TYPE_CHECKING, TypeVar

from . import _compression
from ._codec import CODEC_NAME_JSON, CODEC_NAME_JSON_CHARSET_UTF8, Codec
Expand All @@ -25,9 +23,16 @@
from ._version import __version__
from .code import Code
from .errors import ConnectError
from .method import MethodInfo
from .request import Headers, RequestContext

if TYPE_CHECKING:
from collections.abc import Iterable, Mapping, Sequence
from types import TracebackType

from httpx import Headers as HttpxHeaders

from .method import MethodInfo

_DEFAULT_CONNECT_USER_AGENT = f"connectrpc/{__version__}"

REQ = TypeVar("REQ")
Expand Down Expand Up @@ -247,9 +252,9 @@ class ResponseMetadata:

_headers: Headers | None = None
_trailers: Headers | None = None
_token: Token["ResponseMetadata"] | None = None
_token: Token[ResponseMetadata] | None = None

def __enter__(self) -> "ResponseMetadata":
def __enter__(self) -> ResponseMetadata:
self._token = _current_response.set(self)
return self

Expand Down
Loading
Loading