Skip to content

Commit

Permalink
Merge branch 'main' into fix-connector-startup-error
Browse files Browse the repository at this point in the history
  • Loading branch information
erikh360 committed Feb 14, 2024
2 parents bf27b6d + 68f6231 commit 63c9154
Show file tree
Hide file tree
Showing 22 changed files with 915 additions and 902 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- 5672:5672
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
- Fix connector startup error (#53, #54)

### Changed
- Drop support for Python 3.9 and 3.10 (#55)
- Update dependencies and add support for Python 3.12 (#56, #57)
- Switch to timezone-aware objects for message timestamps (#58)

## [0.1.0] - 2023-04-05

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Currently under development.
## Development
This project uses [poetry](https://python-poetry.org/docs/#installation) for packaging and dependancy management, so install that first.

Ensure you're also running at least python 3.7, `python --version`.
Ensure you're also running at least python 3.11, `python --version`.

Then you can install the dependencies
```bash
Expand Down
1,483 changes: 763 additions & 720 deletions poetry.lock

Large diffs are not rendered by default.

64 changes: 32 additions & 32 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "vumi2"
version = "0.1.1.dev0"
version = "0.1.2.dev0"
description = "Vumi, but with Python3 and Trio async"
authors = ["Praekelt.org <[email protected]>"]
license = "BSD 3-Clause"
Expand All @@ -14,37 +14,38 @@ include = [
]

[tool.poetry.dependencies]
python = "^3.9"
trio = "^0.22.0"
async-amqp = "^0.5.0"
attrs = "^23.1.0"
cattrs = "^22.2.0"
PyYAML = "^6.0"
sentry-sdk = "^1.9.3"
quart-trio = "^0.10.0"
hypercorn = "^0.14.3"
python = "^3.11"
trio = "^0.24.0"
async-amqp = "^0.5.5"
attrs = "^23.2.0"
cattrs = "^23.2.3"
PyYAML = "^6.0.1"
sentry-sdk = "^1.40.4"
quart-trio = "^0.11.1"
hypercorn = "^0.16.0"
"smpp.pdu3" = "^0.6"
httpx = "^0.24.0"
httpx = "^0.26.0"

[tool.poetry.group.dev.dependencies]
black = "^23.3.0"
mypy = "^1.2.0"
pytest = "^7.3.1"
black = "^24.2.0"
mypy = "^1.8.0"
pytest = "^8.0.0"
pytest-trio = "^0.8.0"
pytest-cov = "^4.0.0"
ruff = "^0.0.261"
Sphinx = "^6.1.3"
pytest-cov = "^4.1.0"
ruff = "^0.2.1"
Sphinx = "^7.2.6"
sphinxcontrib-httpdomain = "^1.8.1"
trio-typing = "^0.8.0"
trio-typing = "^0.10.0"
types-pyyaml = "^6.0.12.12"

[tool.poetry.group.lsp]
optional = true

[tool.poetry.group.lsp.dependencies]
python-lsp-server = "^1.7.2"
python-lsp-ruff = "^1.4.0"
python-lsp-black = "^1.2.1"
pylsp-mypy = "^0.6.6"
python-lsp-server = "^1.10.0"
python-lsp-ruff = "^2.1.0"
python-lsp-black = "^2.0.0"
pylsp-mypy = "^0.6.8"

[tool.poetry.scripts]
vumi2 = "vumi2.cli:main"
Expand All @@ -63,17 +64,14 @@ check_untyped_defs = true
[tool.pytest.ini_options]
trio_mode = true
addopts = "--cov=src --cov-report=term-missing"
filterwarnings = [
# We can't do anything about these warnings until upstream updates.
"ignore::trio.TrioDeprecationWarning:quart_trio.app",
"ignore::trio.TrioDeprecationWarning:anyio._backends._trio",
"ignore::trio.TrioDeprecationWarning:hypercorn.trio",
]

[tool.coverage.report]
exclude_also = ["@overload"]

[tool.ruff]
target-version = "py311"

[tool.ruff.lint]
select = [
"E", "F", "W", # pycodestyle + pyflakes == flake8 - mccabe
"I", # isort
Expand All @@ -86,12 +84,14 @@ select = [
"SIM", # flake8-simplify
"PTH", # flake8-use-pathlib
]
target-version = "py39"
ignore = [
"SIM117", # Nested `with` is often more readable.
]

[tool.ruff.isort]
[tool.ruff.lint.isort]
known-first-party = ["vumi2"]

[tool.ruff.per-file-ignores]
[tool.ruff.lint.per-file-ignores]
"tests/**" = [
"S101", # It's okay to use `assert` in tests.
"S101", # It's okay to use `assert` in tests.
]
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import json
from http import HTTPStatus
from logging import getLogger
from typing import Optional, Union

from attrs import define, field
from httpx import AsyncClient
Expand Down Expand Up @@ -54,12 +53,12 @@ class JunebugMessageApiConfig(BaseConfig):
# The URL to POST inbound messages to.
mo_message_url: str
# Authorization token to use for inbound message HTTP requests.
mo_message_url_auth_token: Optional[str] = None
mo_message_url_auth_token: str | None = None

# The URL to POST events with no associated message info to.
default_event_url: Optional[str] = None
default_event_url: str | None = None
# Authorization token to use for events with no associates message info.
default_event_auth_token: Optional[str] = None
default_event_auth_token: str | None = None

# Base URL path for outbound message HTTP requests. This has "/messages"
# appended to it. For compatibility with existing Junebug API clients, set
Expand All @@ -71,7 +70,7 @@ class JunebugMessageApiConfig(BaseConfig):
transport_type: TransportType = TransportType.SMS

# If None, all outbound messages must be replies or have a from address.
default_from_addr: Optional[str] = None
default_from_addr: str | None = None

# If True, outbound messages with both `to` and `reply_to` set will be sent
# as non-reply messages if the `reply_to` message can't be found.
Expand Down Expand Up @@ -188,7 +187,7 @@ async def handle_event(self, event: Event) -> None:
if cs.cancelled_caught:
logger.error(LOG_EV_HTTP_TIMEOUT, {"timeout": timeout, "event": ev})

async def http_send_message(self) -> tuple[Union[str, dict], int, dict[str, str]]:
async def http_send_message(self) -> tuple[str | dict, int, dict[str, str]]:
_message_id = generate_message_id()
try:
# TODO: Log requests that timed out?
Expand Down
29 changes: 11 additions & 18 deletions src/vumi2/applications/junebug_message_api/junebug_state_cache.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from abc import ABC, abstractmethod
from typing import Optional

import cattrs
from attrs import define
Expand All @@ -11,7 +10,7 @@
@define(frozen=True)
class EventHttpInfo:
url: str
auth_token: Optional[str]
auth_token: str | None


class JunebugStateCache(ABC): # pragma: no cover
Expand All @@ -20,29 +19,23 @@ async def store_event_http_info(
self,
message_id: str,
url: str,
auth_token: Optional[str],
) -> None:
...
auth_token: str | None,
) -> None: ...

@abstractmethod
async def fetch_event_http_info(self, message_id: str) -> Optional[EventHttpInfo]:
...
async def fetch_event_http_info(self, message_id: str) -> EventHttpInfo | None: ...

@abstractmethod
async def delete_event_http_info(self, message_id: str) -> None:
...
async def delete_event_http_info(self, message_id: str) -> None: ...

@abstractmethod
async def store_inbound(self, msg: Message) -> None:
...
async def store_inbound(self, msg: Message) -> None: ...

@abstractmethod
async def fetch_inbound(self, message_id: str) -> Optional[Message]:
...
async def fetch_inbound(self, message_id: str) -> Message | None: ...

@abstractmethod
async def delete_inbound(self, message_id: str) -> None:
...
async def delete_inbound(self, message_id: str) -> None: ...


@define
Expand All @@ -62,15 +55,15 @@ async def store_event_http_info(
self,
message_id: str,
url: str,
auth_token: Optional[str],
auth_token: str | None,
) -> None:
"""
Stores the mapping between one or many smpp message IDs and the vumi message ID
"""
if self.config.store_event_info:
self._event_http_info[message_id] = EventHttpInfo(url, auth_token)

async def fetch_event_http_info(self, message_id: str) -> Optional[EventHttpInfo]:
async def fetch_event_http_info(self, message_id: str) -> EventHttpInfo | None:
return self._event_http_info[message_id]

async def delete_event_http_info(self, message_id: str) -> None:
Expand All @@ -82,7 +75,7 @@ async def store_inbound(self, msg: Message) -> None:
"""
self._inbound[msg.message_id] = msg.serialise()

async def fetch_inbound(self, message_id: str) -> Optional[Message]:
async def fetch_inbound(self, message_id: str) -> Message | None:
msg = self._inbound[message_id]
return Message.deserialise(msg) if msg else None

Expand Down
16 changes: 8 additions & 8 deletions src/vumi2/applications/junebug_message_api/messages.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Optional
from typing import Any

import cattrs
from attrs import define, field
Expand Down Expand Up @@ -128,12 +128,12 @@ class JunebugOutboundMessage:
"""

content: str
to: Optional[str] = None
from_addr: Optional[str] = None
group: Optional[str] = None
reply_to: Optional[str] = None
event_url: Optional[str] = None
event_auth_token: Optional[str] = None
to: str | None = None
from_addr: str | None = None
group: str | None = None
reply_to: str | None = None
event_url: str | None = None
event_auth_token: str | None = None
priority: int = 1
channel_data: dict[str, Any] = field(factory=dict)

Expand All @@ -143,7 +143,7 @@ def __attrs_post_init__(self):

@classmethod
def deserialise(
cls, data: dict[str, Any], default_from: Optional[str] = None
cls, data: dict[str, Any], default_from: str | None = None
) -> "JunebugOutboundMessage":
if data.get("from") is None:
data["from"] = default_from
Expand Down
4 changes: 2 additions & 2 deletions src/vumi2/async_helpers.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from collections.abc import Awaitable
from inspect import isawaitable
from typing import TypeVar, Union, cast
from typing import TypeVar, cast

_RETURN = TypeVar("_RETURN")


async def maybe_awaitable(value: Union[_RETURN, Awaitable[_RETURN]]) -> _RETURN:
async def maybe_awaitable(value: _RETURN | Awaitable[_RETURN]) -> _RETURN:
if isawaitable(value):
# cast because isawaitable doesn't properly narrow the type
return await cast(Awaitable[_RETURN], value)
Expand Down
13 changes: 5 additions & 8 deletions src/vumi2/config.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import os
from argparse import Namespace
from collections.abc import Iterable
from collections.abc import Callable, Iterable
from pathlib import Path
from typing import (
Any,
Callable,
Generic,
Optional,
Protocol,
TypeVar,
Union,
get_type_hints,
)

Expand All @@ -27,7 +24,7 @@ class Configurable(Protocol, Generic[CT]):
config: CT


def get_config_class(cls: Union[Configurable[CT], type[Configurable[CT]]]) -> type[CT]:
def get_config_class(cls: Configurable[CT] | type[Configurable[CT]]) -> type[CT]:
return get_type_hints(cls)["config"]


Expand All @@ -37,7 +34,7 @@ def structure(config: dict, cls: type[CT]) -> CT:

def structure_config(
config: dict,
obj: Union[Configurable[CT], type[Configurable[CT]]],
obj: Configurable[CT] | type[Configurable[CT]],
) -> CT:
return structure(config, get_config_class(obj))

Expand All @@ -56,8 +53,8 @@ class BaseConfig:
amqp: AmqpConfig = Factory(AmqpConfig)
amqp_url: str = ""
worker_concurrency: int = 20
sentry_dsn: Optional[str] = None
http_bind: Optional[str] = None
sentry_dsn: str | None = None
http_bind: str | None = None
log_level: str = "INFO"


Expand Down
Loading

0 comments on commit 63c9154

Please sign in to comment.