Skip to content

Commit b7f56c9

Browse files
authored
Update packaging + CI, switch aioredis -> redis (#13)
* Update packaging + CI, switch aioredis -> redis * Update badges * Address review comments, remove redis support
1 parent ae23bd6 commit b7f56c9

File tree

12 files changed

+176
-307
lines changed

12 files changed

+176
-307
lines changed

.github/workflows/build_deploy.yml

Lines changed: 0 additions & 69 deletions
This file was deleted.

.github/workflows/ci.yml

Lines changed: 23 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,37 @@
11
name: CI
2-
on: [push, pull_request]
2+
3+
on:
4+
push:
5+
pull_request:
6+
37
jobs:
4-
black:
8+
lint:
59
runs-on: ubuntu-latest
610
steps:
711
- uses: actions/checkout@v4
812
- uses: actions/setup-python@v5
9-
with:
10-
python-version: "3.9"
11-
- run: pip install riot==0.19.0
12-
- run: riot -v run -s black -- --check .
13-
mypy:
14-
runs-on: ubuntu-latest
15-
steps:
16-
- uses: actions/checkout@v4
17-
- uses: actions/setup-python@v5
18-
with:
19-
python-version: "3.9"
20-
- run: pip install riot==0.19.0
21-
- run: riot -v run mypy
22-
flake8:
23-
runs-on: ubuntu-latest
24-
steps:
25-
- uses: actions/checkout@v4
26-
- uses: actions/setup-python@v5
27-
with:
28-
python-version: "3.9"
29-
- run: pip install riot==0.19.0
30-
- run: riot -v run flake8
13+
- run: pip install uv
14+
- run: uv venv
15+
- run: uv pip install --requirement pyproject.toml --all-extras
16+
- run: .venv/bin/ruff format --check .
17+
- run: .venv/bin/ruff check .
18+
- run: .venv/bin/mypy asyncio_connection_pool
19+
3120
test:
21+
runs-on: ubuntu-latest
3222
strategy:
3323
matrix:
34-
os: [ubuntu-latest, macos-latest]
3524
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
36-
runs-on: ${{ matrix.os }}
3725
steps:
3826
- uses: actions/checkout@v4
39-
- name: Setup Python
40-
uses: actions/setup-python@v5
27+
- uses: actions/setup-python@v5
4128
with:
4229
python-version: ${{ matrix.python-version }}
43-
- name: install riot
44-
run: pip install riot==0.19.0
45-
- name: run tests
46-
run: riot -v run --python=${{ matrix.python-version }} test -- --cov=asyncio_connection_pool --cov-branch --cov-config=.coveragerc
47-
- name: install coverage
48-
run: pip install coverage
49-
- name: upload coverage
50-
uses: coverallsapp/github-action@v2
51-
with:
52-
parallel: true
53-
flag-name: run ${{ join(matrix.*, ' - ') }}
54-
finish-coveralls:
55-
needs: test
56-
if: ${{ always() }}
57-
runs-on: ubuntu-latest
58-
steps:
59-
- name: Coveralls Finished
60-
uses: coverallsapp/github-action@v2
61-
with:
62-
parallel-finished: true
63-
allow-empty: true
30+
- run: pip install uv
31+
- run: uv venv
32+
- run: uv pip install --editable ".[dev,datadog,aioredis]"
33+
- run: .venv/bin/pytest --cov=asyncio_connection_pool --cov-branch --cov-config=.coveragerc
34+
- run: .venv/bin/codecov
35+
if: matrix.python-version == '3.11'
36+
env:
37+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

.github/workflows/release.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Release
2+
3+
on:
4+
release:
5+
types:
6+
- created
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
# IMPORTANT: this permission is mandatory for trusted publishing
13+
id-token: write
14+
steps:
15+
- uses: actions/checkout@v4
16+
- uses: actions/setup-python@v5
17+
with:
18+
python-version: "3.12"
19+
- run: pip install uv
20+
- run: uv venv
21+
- run: uv pip install --requirement pyproject.toml
22+
- run: uv pip install setuptools setuptools-scm wheel build
23+
- run: .venv/bin/python -m build --no-isolation
24+
- name: Publish package distributions to PyPI
25+
uses: pypa/gh-action-pypi-publish@release/v1

README.md

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
# asyncio-connection-pool
22

3-
[![GitHub Workflow Status (main)](https://img.shields.io/github/workflow/status/fellowinsights/asyncio-connection-pool/CI/main?style=flat)][main CI]
3+
[![GitHub Workflow Status (main)](https://img.shields.io/github/actions/workflow/status/fellowapp/asyncio-connection-pool/ci.yml?branch=main&style=flat)][main CI]
44
[![PyPI](https://img.shields.io/pypi/v/asyncio-connection-pool?style=flat)][package]
55
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/asyncio-connection-pool?style=flat)][package]
6+
[![codecov](https://codecov.io/gh/fellowapp/asyncio-connection-pool/graph/badge.svg?token=F3D4D9EG6M)](https://codecov.io/gh/fellowapp/asyncio-connection-pool)
7+
[![License](https://img.shields.io/pypi/l/prosemirror.svg?style=flat)](https://github.com/fellowapp/asyncio-connection-pool/blob/master/LICENSE.md)
68
[![Fellow Careers](https://img.shields.io/badge/fellow.app-hiring-576cf7.svg?style=flat)](https://fellow.app/careers/)
79

8-
[main CI]: https://github.com/fellowinsights/asyncio-connection-pool/actions?query=workflow%3ACI+branch%3Amain
10+
[main CI]: https://github.com/fellowapp/asyncio-connection-pool/actions?query=workflow%3ACI+branch%3Amain
911
[package]: https://pypi.org/project/asyncio-connection-pool/
1012

1113
This is a generic, high-throughput, optionally-burstable pool for asyncio.
@@ -21,10 +23,11 @@ Some cool features:
2123
- The contents of the pool can be anything; just implement a
2224
`ConnectionStrategy`.
2325

24-
[^1]: Theoretically, there is an implicit "lock" that is held while an asyncio
25-
task is executing. No other task can execute until the current task
26-
yields (since it's cooperative multitasking), so any operations during
27-
that time are atomic.
26+
[^1]:
27+
Theoretically, there is an implicit "lock" that is held while an asyncio
28+
task is executing. No other task can execute until the current task
29+
yields (since it's cooperative multitasking), so any operations during
30+
that time are atomic.
2831

2932
## Why?
3033

@@ -36,10 +39,8 @@ We also thought it would be nice if we didn't need to keep many connections
3639
open when they weren't needed, but still have the ability to make more when
3740
they are required.
3841

39-
4042
## API
4143

42-
4344
### `asyncio_connection_pool.ConnectionPool`
4445

4546
This is the implementation of the pool. It is generic over a type of
@@ -57,7 +58,6 @@ pool = ConnectionPool(strategy=my_strategy, max_size=15)
5758
The constructor can optionally be passed an integer as `burst_limit`. This
5859
allows the pool to open more connections than `max_size` temporarily.
5960

60-
6161
#### `@asynccontextmanager async def get_connection(self) -> AsyncIterator[Conn]`
6262

6363
This method is the only way to get a connection from the pool. It is expected
@@ -77,13 +77,11 @@ are available, the caller will yield to the event loop.
7777

7878
When the block is exited, the connection will be returned to the pool.
7979

80-
8180
### `asyncio_connection_pool.ConnectionStrategy`
8281

8382
This is an abstract class that defines the interface of the object passed as
8483
`strategy`. A subclass _must_ implement the following methods:
8584

86-
8785
#### `async def create_connection(self) -> Awaitable[Conn]`
8886

8987
This method is called to create a new connection to the resource. This happens
@@ -96,7 +94,6 @@ the pool, and in most cases will be stored in the pool to be re-used later.
9694
If this method raises an exception, it will bubble up to the frame where
9795
`ConnectionPool.get_connection()` was called.
9896

99-
10097
#### `def connection_is_closed(self, conn: Conn) -> bool`
10198

10299
This method is called to check if a connection is no longer able to be used.
@@ -111,7 +108,6 @@ exception is suppressed unless it is not a `BaseException`, like
111108
`asyncio.CancelledError`. It is the responsibility of the `ConnectionStrategy`
112109
implementation to avoid leaking a connection in this case.
113110

114-
115111
#### `async def close_connection(self, conn: Conn)`
116112

117113
This method is called to close a connection. This occurs when the pool has
@@ -122,8 +118,7 @@ If this method raises an exception, the connection is assumed to be closed and
122118
the exception bubbles to the caller of `ConnectionPool.get_connection().__aexit__`
123119
(usually an `async with` block).
124120

125-
126-
## Integrations with 3rd-party libraries
121+
## Integrations with 3rd-party libraries
127122

128123
This package includes support for [`ddtrace`][ddtrace]/[`datadog`][datadog] and
129124
for [`aioredis`][aioredis] (<2.0.0).
@@ -142,14 +137,12 @@ arguments of the base class, supports:
142137
- Optional `extra_tags` argument: Additional tags to provide to all metrics
143138
(strings in a `"key:value"` format)
144139

145-
146140
### `asyncio_connection_pool.contrib.aioredis.RedisConnectionStrategy`
147141

148142
This class implements the `ConnectionStrategy` abstract methods, using
149143
`aioredis.Redis` objects as connections. The constructor takes arbitrary
150144
arguments and forwards them to `aioredis.create_redis`.
151145

152-
153146
## How is this safe without locks?
154147

155148
I encourage you to read the [source](https://github.com/fellowinsights/asyncio-connection-pool/blob/master/asyncio_connection_pool/__init__.py)

asyncio_connection_pool/__init__.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from abc import ABC, abstractmethod
21
import asyncio
32
import inspect
3+
from abc import ABC, abstractmethod
44
from contextlib import asynccontextmanager
55
from typing import AsyncIterator, Awaitable, Generic, Optional, TypeVar
66

@@ -10,16 +10,13 @@
1010

1111
class ConnectionStrategy(ABC, Generic[Conn]):
1212
@abstractmethod
13-
async def make_connection(self) -> Conn:
14-
...
13+
async def make_connection(self) -> Conn: ...
1514

1615
@abstractmethod
17-
def connection_is_closed(self, conn: Conn) -> bool:
18-
...
16+
def connection_is_closed(self, conn: Conn) -> bool: ...
1917

2018
@abstractmethod
21-
async def close_connection(self, conn: Conn) -> None:
22-
...
19+
async def close_connection(self, conn: Conn) -> None: ...
2320

2421

2522
async def _close_connection_compat(
@@ -60,18 +57,19 @@ def __init__(
6057
*,
6158
strategy: ConnectionStrategy[Conn],
6259
max_size: int,
63-
burst_limit: Optional[int] = None
60+
burst_limit: Optional[int] = None,
6461
) -> None:
6562
self._loop = asyncio.get_event_loop()
6663
self.strategy = strategy
6764
self.max_size = max_size
6865
self.burst_limit = burst_limit
6966
if burst_limit is not None and burst_limit < max_size:
70-
raise ValueError("burst_limit must be greater than or equal to max_size")
67+
msg = "burst_limit must be greater than or equal to max_size"
68+
raise ValueError(msg)
7169
self.in_use = 0
7270
self.currently_allocating = 0
7371
self.currently_deallocating = 0
74-
self.available: "asyncio.Queue[Conn]" = asyncio.Queue(maxsize=self.max_size)
72+
self.available: asyncio.Queue[Conn] = asyncio.Queue(maxsize=self.max_size)
7573

7674
@property
7775
def _total(self) -> int:
@@ -110,7 +108,7 @@ def _get_conn(self) -> Awaitable[Conn]:
110108
# Incidentally, awaiting a done Future doesn't involve yielding to
111109
# the event loop; it's more like getting the next value from a
112110
# generator.
113-
fut: "asyncio.Future[Conn]" = self._loop.create_future()
111+
fut: asyncio.Future[Conn] = self._loop.create_future()
114112
fut.set_result(self.available.get_nowait())
115113
self.in_use += 1
116114
return fut

asyncio_connection_pool/contrib/aioredis.py

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)