sqlalchemy-dlock 0.3__tar.gz → 0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/CHANGELOG.md +24 -0
- sqlalchemy-dlock-0.4/MANIFEST.in +8 -0
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/PKG-INFO +97 -69
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/README.md +85 -38
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/pyproject.toml +40 -19
- sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/__init__.py +7 -0
- sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/asyncio/baselock.py +46 -0
- sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/asyncio/functions.py +27 -0
- {sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/asyncio/impl → sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/asyncio/lock}/mysql.py +14 -36
- {sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/asyncio/impl → sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/asyncio/lock}/postgresql.py +8 -83
- sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/types.py → sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/baselock.py +7 -30
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock/exceptions.py +3 -0
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock/functions.py +15 -8
- {sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/impl → sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/lock}/mysql.py +21 -46
- {sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/impl → sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/lock}/postgresql.py +21 -91
- sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/statement/__init__.py +0 -0
- sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/statement/mysql.py +20 -0
- sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/statement/postgresql.py +75 -0
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock/utils.py +7 -10
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock/version.py +2 -2
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock.egg-info/PKG-INFO +97 -69
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock.egg-info/SOURCES.txt +11 -14
- sqlalchemy-dlock-0.4/src/sqlalchemy_dlock.egg-info/requires.txt +36 -0
- sqlalchemy-dlock-0.3/.coveragerc +0 -10
- sqlalchemy-dlock-0.3/.readthedocs.yaml +0 -19
- sqlalchemy-dlock-0.3/MANIFEST.in +0 -30
- sqlalchemy-dlock-0.3/codecov.yml +0 -5
- sqlalchemy-dlock-0.3/scripts/run-test.sh +0 -13
- sqlalchemy-dlock-0.3/scripts/wait-for-mysql.sh +0 -17
- sqlalchemy-dlock-0.3/scripts/wait-for-postgres.sh +0 -15
- sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/__init__.py +0 -6
- sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/asyncio/functions.py +0 -21
- sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/asyncio/types.py +0 -62
- sqlalchemy-dlock-0.3/src/sqlalchemy_dlock.egg-info/requires.txt +0 -3
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/AUTHORS.md +0 -0
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/LICENSE +0 -0
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/setup.cfg +0 -0
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock/asyncio/__init__.py +0 -0
- {sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/asyncio/impl → sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/asyncio/lock}/__init__.py +0 -0
- {sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/impl → sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/lock}/__init__.py +0 -0
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock.egg-info/dependency_links.txt +0 -0
- {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock.egg-info/top_level.txt +0 -0
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## v0.4
|
|
4
|
+
|
|
5
|
+
Date: 2023-06-17
|
|
6
|
+
|
|
7
|
+
- Remove:
|
|
8
|
+
- remove `acquired` property, it's alias of `locked`
|
|
9
|
+
- remove setter of `locked` property
|
|
10
|
+
|
|
11
|
+
- Optimize:
|
|
12
|
+
- re-arrange package's structure
|
|
13
|
+
- Many optimizations
|
|
14
|
+
|
|
15
|
+
- CI/Test:
|
|
16
|
+
- Github action: Python 3.8~3.11 x SQLAlchemy 1.x/2.x matrix testing
|
|
17
|
+
- Local compose: Python 3.7~3.11 x SQLAlchemy 1.x/2.x matrix testing
|
|
18
|
+
|
|
19
|
+
- Doc: Update to Sphinx 7.x, and Furo theme
|
|
20
|
+
|
|
21
|
+
## v0.3.1
|
|
22
|
+
|
|
23
|
+
Date: 2023-06-13
|
|
24
|
+
|
|
25
|
+
- A hotfix for project's dependencies setup error.
|
|
26
|
+
|
|
3
27
|
## v0.3
|
|
4
28
|
|
|
5
29
|
Date: 2023-06-13
|
|
@@ -1,39 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sqlalchemy-dlock
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4
|
|
4
4
|
Summary: A distributed lock implementation based on SQLAlchemy
|
|
5
5
|
Author-email: liu xue yan <liu_xue_yan@foxmail.com>
|
|
6
|
-
License: BSD
|
|
7
|
-
|
|
8
|
-
Copyright (c) 2020, liu xue yan
|
|
9
|
-
All rights reserved.
|
|
10
|
-
|
|
11
|
-
Redistribution and use in source and binary forms, with or without
|
|
12
|
-
modification, are permitted provided that the following conditions are met:
|
|
13
|
-
|
|
14
|
-
1. Redistributions of source code must retain the above copyright notice, this
|
|
15
|
-
list of conditions and the following disclaimer.
|
|
16
|
-
|
|
17
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
18
|
-
this list of conditions and the following disclaimer in the documentation
|
|
19
|
-
and/or other materials provided with the distribution.
|
|
20
|
-
|
|
21
|
-
3. Neither the name of the copyright holder nor the names of its
|
|
22
|
-
contributors may be used to endorse or promote products derived from
|
|
23
|
-
this software without specific prior written permission.
|
|
24
|
-
|
|
25
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
26
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
27
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
28
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
29
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
30
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
31
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
32
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
33
|
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
34
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
35
|
-
|
|
6
|
+
License: BSD-3-Clause
|
|
36
7
|
Project-URL: homepage, https://github.com/tanbro/sqlalchemy-dlock
|
|
8
|
+
Project-URL: documentation, https://sqlalchemy-dlock.readthedocs.io/
|
|
37
9
|
Project-URL: repository, https://github.com/tanbro/sqlalchemy-dlock.git
|
|
38
10
|
Keywords: SQLAlchemy,lock,distributed,distributed lock,SQL,database,DBMS
|
|
39
11
|
Classifier: License :: OSI Approved :: BSD License
|
|
@@ -43,6 +15,15 @@ Classifier: Programming Language :: Python
|
|
|
43
15
|
Requires-Python: >=3.7
|
|
44
16
|
Description-Content-Type: text/markdown
|
|
45
17
|
Provides-Extra: asyncio
|
|
18
|
+
Provides-Extra: mysqlclient
|
|
19
|
+
Provides-Extra: pymysql
|
|
20
|
+
Provides-Extra: aiomysql
|
|
21
|
+
Provides-Extra: psycopg2
|
|
22
|
+
Provides-Extra: psycopg2-binary
|
|
23
|
+
Provides-Extra: psycopg3
|
|
24
|
+
Provides-Extra: psycopg3-binary
|
|
25
|
+
Provides-Extra: psycopg3-c
|
|
26
|
+
Provides-Extra: asyncpg3
|
|
46
27
|
License-File: LICENSE
|
|
47
28
|
License-File: AUTHORS.md
|
|
48
29
|
|
|
@@ -62,7 +43,13 @@ It currently supports below locks:
|
|
|
62
43
|
MySQL | [named lock](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html)
|
|
63
44
|
PostgreSQL | [advisory lock](https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS)
|
|
64
45
|
|
|
65
|
-
##
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install sqlalchemy-dlock
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Usage
|
|
66
53
|
|
|
67
54
|
- Work with [SQLAlchemy][] `Connection`:
|
|
68
55
|
|
|
@@ -72,22 +59,22 @@ PostgreSQL | [advisory lock](https://www.postgresql.org/docs/current/explicit-lo
|
|
|
72
59
|
|
|
73
60
|
key = 'user/001'
|
|
74
61
|
|
|
75
|
-
engine = create_engine('postgresql://scott:tiger@
|
|
62
|
+
engine = create_engine('postgresql://scott:tiger@127.0.0.1/')
|
|
76
63
|
conn = engine.connect()
|
|
77
64
|
|
|
78
65
|
# Create the D-Lock on the connection
|
|
79
66
|
lock = create_sadlock(conn, key)
|
|
80
67
|
|
|
81
68
|
# it's not lock when constructed
|
|
82
|
-
assert not lock.
|
|
69
|
+
assert not lock.locked
|
|
83
70
|
|
|
84
71
|
# lock
|
|
85
72
|
lock.acquire()
|
|
86
|
-
assert lock.
|
|
73
|
+
assert lock.locked
|
|
87
74
|
|
|
88
75
|
# un-lock
|
|
89
76
|
lock.release()
|
|
90
|
-
assert not lock.
|
|
77
|
+
assert not lock.locked
|
|
91
78
|
```
|
|
92
79
|
|
|
93
80
|
- `with` statement
|
|
@@ -100,27 +87,27 @@ PostgreSQL | [advisory lock](https://www.postgresql.org/docs/current/explicit-lo
|
|
|
100
87
|
|
|
101
88
|
key = 'user/001'
|
|
102
89
|
|
|
103
|
-
engine = create_engine('postgresql://scott:tiger@
|
|
90
|
+
engine = create_engine('postgresql://scott:tiger@127.0.0.1/')
|
|
104
91
|
with engine.connect() as conn:
|
|
105
92
|
|
|
106
93
|
# Create the D-Lock on the connection
|
|
107
94
|
with create_sadlock(conn, key) as lock:
|
|
108
95
|
# It's locked
|
|
109
|
-
assert lock.
|
|
96
|
+
assert lock.locked
|
|
110
97
|
|
|
111
98
|
# Auto un-locked
|
|
112
|
-
assert not lock.
|
|
99
|
+
assert not lock.locked
|
|
113
100
|
|
|
114
101
|
# If do not want to be locked in `with`, a `closing` wrapper may help
|
|
115
102
|
with closing(create_sadlock(conn, key)) as lock2:
|
|
116
|
-
# It's NOT locked here
|
|
117
|
-
assert not lock2.
|
|
103
|
+
# It's NOT locked here !!!
|
|
104
|
+
assert not lock2.locked
|
|
118
105
|
# lock it now:
|
|
119
106
|
lock2.acquire()
|
|
120
|
-
assert lock2.
|
|
107
|
+
assert lock2.locked
|
|
121
108
|
|
|
122
109
|
# Auto un-locked
|
|
123
|
-
assert not lock2.
|
|
110
|
+
assert not lock2.locked
|
|
124
111
|
```
|
|
125
112
|
|
|
126
113
|
- Work with [SQLAlchemy][] `ORM` session:
|
|
@@ -132,18 +119,18 @@ PostgreSQL | [advisory lock](https://www.postgresql.org/docs/current/explicit-lo
|
|
|
132
119
|
|
|
133
120
|
key = 'user/001'
|
|
134
121
|
|
|
135
|
-
engine = create_engine('postgresql://scott:tiger@
|
|
122
|
+
engine = create_engine('postgresql://scott:tiger@127.0.0.1/')
|
|
136
123
|
Session = sessionmaker(bind=engine)
|
|
137
124
|
|
|
138
125
|
with Session() as session:
|
|
139
126
|
with create_sadlock(session, key) as lock:
|
|
140
|
-
assert lock.
|
|
141
|
-
assert not lock.
|
|
127
|
+
assert lock.locked
|
|
128
|
+
assert not lock.locked
|
|
142
129
|
```
|
|
143
130
|
|
|
144
131
|
- Asynchronous I/O Support
|
|
145
132
|
|
|
146
|
-
>
|
|
133
|
+
> **Note**:
|
|
147
134
|
>
|
|
148
135
|
> - [SQLAlchemy][] `1.x`: <https://docs.sqlalchemy.org/14/orm/extensions/asyncio.html>
|
|
149
136
|
> - [SQLAlchemy][] `2.x`: <https://docs.sqlalchemy.org/20/orm/extensions/asyncio.html>
|
|
@@ -154,7 +141,7 @@ PostgreSQL | [advisory lock](https://www.postgresql.org/docs/current/explicit-lo
|
|
|
154
141
|
|
|
155
142
|
key = 'user/001'
|
|
156
143
|
|
|
157
|
-
engine = create_async_engine('postgresql+asyncpg://scott:tiger@
|
|
144
|
+
engine = create_async_engine('postgresql+asyncpg://scott:tiger@127.0.0.1/')
|
|
158
145
|
|
|
159
146
|
async with engine.begin() as conn:
|
|
160
147
|
async with create_async_sadlock(conn, key) as lock:
|
|
@@ -165,42 +152,65 @@ PostgreSQL | [advisory lock](https://www.postgresql.org/docs/current/explicit-lo
|
|
|
165
152
|
assert not lock.locked
|
|
166
153
|
```
|
|
167
154
|
|
|
168
|
-
|
|
155
|
+
> **Note**:
|
|
156
|
+
>
|
|
157
|
+
> [aiomysql][], [asyncpg][] and [psycopg][] are tested asynchronous drivers
|
|
158
|
+
>
|
|
159
|
+
> We can install asynchronous DB libraries like one of blows:
|
|
160
|
+
>
|
|
161
|
+
> - ```bash
|
|
162
|
+
> pip install sqlalchemy-dlock[asyncpg]
|
|
163
|
+
> ```
|
|
164
|
+
>
|
|
165
|
+
> - ```bash
|
|
166
|
+
> pip install sqlalchemy-dlock[asyncio] aiomysql
|
|
167
|
+
> ```
|
|
168
|
+
>
|
|
169
|
+
> - ```bash
|
|
170
|
+
> pip install SQLALchemy[asyncio] sqlalchemy-dlock psycopg
|
|
171
|
+
> ```
|
|
172
|
+
|
|
173
|
+
## Test
|
|
169
174
|
|
|
170
|
-
Following
|
|
175
|
+
Following drivers are tested:
|
|
171
176
|
|
|
172
177
|
- MySQL:
|
|
178
|
+
- [mysqlclient][] (synchronous)
|
|
179
|
+
- [pymysql][] (synchronous)
|
|
180
|
+
- [aiomysql][] (asynchronous)
|
|
181
|
+
- Postgres:
|
|
182
|
+
- [psycopg2][] (asynchronous)
|
|
183
|
+
- [asyncpg][] (asynchronous)
|
|
184
|
+
- [psycopg][] (synchronous and asynchronous)
|
|
173
185
|
|
|
174
|
-
|
|
175
|
-
- PyMySQL
|
|
176
|
-
- aiomysql ([asyncio][])
|
|
186
|
+
You can run unit-tests
|
|
177
187
|
|
|
178
|
-
-
|
|
188
|
+
- on local environment:
|
|
179
189
|
|
|
180
|
-
|
|
181
|
-
- asyncpg ([asyncio][])
|
|
190
|
+
1. Install the project with drivers and `asyncio` extra requires, a virtual environment ([venv][]) is strongly advised:
|
|
182
191
|
|
|
183
|
-
|
|
192
|
+
```bash
|
|
193
|
+
pip install -e .[mysqlclient psycopg2-binary aiomysql asyncpg]
|
|
194
|
+
```
|
|
184
195
|
|
|
185
|
-
|
|
196
|
+
1. start up mysql and postgresql
|
|
186
197
|
|
|
187
|
-
|
|
198
|
+
There is a docker [compose][] file `db.docker-compose.yml` in the project dir,
|
|
199
|
+
which can be used to run mysql and postgresql develop environment conveniently:
|
|
188
200
|
|
|
189
201
|
```bash
|
|
190
|
-
|
|
202
|
+
docker compose -f db.docker-compose.yml up
|
|
191
203
|
```
|
|
192
204
|
|
|
193
|
-
1.
|
|
194
|
-
|
|
195
|
-
1. Set environment variables `TEST_URLS` and `TEST_ASYNC_URLS` for sync and async database connection url.
|
|
205
|
+
1. set environment variables `TEST_URLS` and `TEST_ASYNC_URLS` for sync and async database connection url.
|
|
196
206
|
Multiple connections separated by space.
|
|
197
207
|
The test cases load environment variables in `tests/.env`.
|
|
198
208
|
|
|
199
209
|
eg (and also the defaults):
|
|
200
210
|
|
|
201
211
|
```ini
|
|
202
|
-
TEST_URLS=mysql://test:test@
|
|
203
|
-
TEST_ASYNC_URLS=mysql+aiomysql://test:test@
|
|
212
|
+
TEST_URLS=mysql://test:test@127.0.0.1/test postgresql://postgres:test@127.0.0.1/
|
|
213
|
+
TEST_ASYNC_URLS=mysql+aiomysql://test:test@127.0.0.1/test postgresql+asyncpg://postgres:test@127.0.0.1/
|
|
204
214
|
```
|
|
205
215
|
|
|
206
216
|
1. run unit-test
|
|
@@ -209,7 +219,7 @@ You can run unit-tests:
|
|
|
209
219
|
python -m unittest
|
|
210
220
|
```
|
|
211
221
|
|
|
212
|
-
-
|
|
222
|
+
- or on docker-compose:
|
|
213
223
|
|
|
214
224
|
1. build the project
|
|
215
225
|
|
|
@@ -219,12 +229,30 @@ You can run unit-tests:
|
|
|
219
229
|
|
|
220
230
|
1. run unit-test
|
|
221
231
|
|
|
232
|
+
Name of services for Python and [SQLAlchemy][] version matrix in the [compose][] file has such format:
|
|
233
|
+
|
|
234
|
+
python{{X.Y}}-sqlalchemy{{X}}
|
|
235
|
+
|
|
236
|
+
For example, if want to take a test for Python `3.9` and [SQLAlchemy][] `2.x`, we shall up to run unit-tests as below:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
cd tests
|
|
240
|
+
docker compose up python3.9-sqlalchemy2
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
For Python `3.8` and [SQLAlchemy][] `1.x`:
|
|
244
|
+
|
|
222
245
|
```bash
|
|
223
246
|
cd tests
|
|
224
|
-
docker compose up
|
|
225
|
-
docker compose rm -fsv
|
|
247
|
+
docker compose up python3.8-sqlalchemy1
|
|
226
248
|
```
|
|
227
249
|
|
|
228
250
|
[SQLAlchemy]: https://www.sqlalchemy.org/ "The Python SQL Toolkit and Object Relational Mapper"
|
|
229
|
-
[asyncio]: https://docs.python.org/library/asyncio.html "asyncio is a library to write concurrent code using the async/await syntax."
|
|
230
251
|
[venv]: https://docs.python.org/library/venv.html "The venv module supports creating lightweight “virtual environments”, each with their own independent set of Python packages installed in their site directories. "
|
|
252
|
+
[mysqlclient]: https://pypi.org/project/mysqlclient/ "Python interface to MySQL"
|
|
253
|
+
[psycopg2]: https://pypi.org/project/psycopg2/ "PostgreSQL database adapter for Python"
|
|
254
|
+
[psycopg]: https://pypi.org/project/psycopg/ "Psycopg 3 is a modern implementation of a PostgreSQL adapter for Python."
|
|
255
|
+
[aiomysql]: https://pypi.org/project/aiomysql/ "aiomysql is a “driver” for accessing a MySQL database from the asyncio (PEP-3156/tulip) framework."
|
|
256
|
+
[asyncpg]: https://pypi.org/project/asyncpg/ "asyncpg is a database interface library designed specifically for PostgreSQL and Python/asyncio. "
|
|
257
|
+
[pymysql]: https://pypi.org/project/pymysql/ "Pure Python MySQL Driver"
|
|
258
|
+
[compose]: https://docs.docker.com/compose/ "Compose is a tool for defining and running multi-container Docker applications."
|
|
@@ -14,7 +14,13 @@ It currently supports below locks:
|
|
|
14
14
|
MySQL | [named lock](https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html)
|
|
15
15
|
PostgreSQL | [advisory lock](https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS)
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install sqlalchemy-dlock
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
18
24
|
|
|
19
25
|
- Work with [SQLAlchemy][] `Connection`:
|
|
20
26
|
|
|
@@ -24,22 +30,22 @@ PostgreSQL | [advisory lock](https://www.postgresql.org/docs/current/explicit-lo
|
|
|
24
30
|
|
|
25
31
|
key = 'user/001'
|
|
26
32
|
|
|
27
|
-
engine = create_engine('postgresql://scott:tiger@
|
|
33
|
+
engine = create_engine('postgresql://scott:tiger@127.0.0.1/')
|
|
28
34
|
conn = engine.connect()
|
|
29
35
|
|
|
30
36
|
# Create the D-Lock on the connection
|
|
31
37
|
lock = create_sadlock(conn, key)
|
|
32
38
|
|
|
33
39
|
# it's not lock when constructed
|
|
34
|
-
assert not lock.
|
|
40
|
+
assert not lock.locked
|
|
35
41
|
|
|
36
42
|
# lock
|
|
37
43
|
lock.acquire()
|
|
38
|
-
assert lock.
|
|
44
|
+
assert lock.locked
|
|
39
45
|
|
|
40
46
|
# un-lock
|
|
41
47
|
lock.release()
|
|
42
|
-
assert not lock.
|
|
48
|
+
assert not lock.locked
|
|
43
49
|
```
|
|
44
50
|
|
|
45
51
|
- `with` statement
|
|
@@ -52,27 +58,27 @@ PostgreSQL | [advisory lock](https://www.postgresql.org/docs/current/explicit-lo
|
|
|
52
58
|
|
|
53
59
|
key = 'user/001'
|
|
54
60
|
|
|
55
|
-
engine = create_engine('postgresql://scott:tiger@
|
|
61
|
+
engine = create_engine('postgresql://scott:tiger@127.0.0.1/')
|
|
56
62
|
with engine.connect() as conn:
|
|
57
63
|
|
|
58
64
|
# Create the D-Lock on the connection
|
|
59
65
|
with create_sadlock(conn, key) as lock:
|
|
60
66
|
# It's locked
|
|
61
|
-
assert lock.
|
|
67
|
+
assert lock.locked
|
|
62
68
|
|
|
63
69
|
# Auto un-locked
|
|
64
|
-
assert not lock.
|
|
70
|
+
assert not lock.locked
|
|
65
71
|
|
|
66
72
|
# If do not want to be locked in `with`, a `closing` wrapper may help
|
|
67
73
|
with closing(create_sadlock(conn, key)) as lock2:
|
|
68
|
-
# It's NOT locked here
|
|
69
|
-
assert not lock2.
|
|
74
|
+
# It's NOT locked here !!!
|
|
75
|
+
assert not lock2.locked
|
|
70
76
|
# lock it now:
|
|
71
77
|
lock2.acquire()
|
|
72
|
-
assert lock2.
|
|
78
|
+
assert lock2.locked
|
|
73
79
|
|
|
74
80
|
# Auto un-locked
|
|
75
|
-
assert not lock2.
|
|
81
|
+
assert not lock2.locked
|
|
76
82
|
```
|
|
77
83
|
|
|
78
84
|
- Work with [SQLAlchemy][] `ORM` session:
|
|
@@ -84,18 +90,18 @@ PostgreSQL | [advisory lock](https://www.postgresql.org/docs/current/explicit-lo
|
|
|
84
90
|
|
|
85
91
|
key = 'user/001'
|
|
86
92
|
|
|
87
|
-
engine = create_engine('postgresql://scott:tiger@
|
|
93
|
+
engine = create_engine('postgresql://scott:tiger@127.0.0.1/')
|
|
88
94
|
Session = sessionmaker(bind=engine)
|
|
89
95
|
|
|
90
96
|
with Session() as session:
|
|
91
97
|
with create_sadlock(session, key) as lock:
|
|
92
|
-
assert lock.
|
|
93
|
-
assert not lock.
|
|
98
|
+
assert lock.locked
|
|
99
|
+
assert not lock.locked
|
|
94
100
|
```
|
|
95
101
|
|
|
96
102
|
- Asynchronous I/O Support
|
|
97
103
|
|
|
98
|
-
>
|
|
104
|
+
> **Note**:
|
|
99
105
|
>
|
|
100
106
|
> - [SQLAlchemy][] `1.x`: <https://docs.sqlalchemy.org/14/orm/extensions/asyncio.html>
|
|
101
107
|
> - [SQLAlchemy][] `2.x`: <https://docs.sqlalchemy.org/20/orm/extensions/asyncio.html>
|
|
@@ -106,7 +112,7 @@ PostgreSQL | [advisory lock](https://www.postgresql.org/docs/current/explicit-lo
|
|
|
106
112
|
|
|
107
113
|
key = 'user/001'
|
|
108
114
|
|
|
109
|
-
engine = create_async_engine('postgresql+asyncpg://scott:tiger@
|
|
115
|
+
engine = create_async_engine('postgresql+asyncpg://scott:tiger@127.0.0.1/')
|
|
110
116
|
|
|
111
117
|
async with engine.begin() as conn:
|
|
112
118
|
async with create_async_sadlock(conn, key) as lock:
|
|
@@ -117,42 +123,65 @@ PostgreSQL | [advisory lock](https://www.postgresql.org/docs/current/explicit-lo
|
|
|
117
123
|
assert not lock.locked
|
|
118
124
|
```
|
|
119
125
|
|
|
120
|
-
|
|
126
|
+
> **Note**:
|
|
127
|
+
>
|
|
128
|
+
> [aiomysql][], [asyncpg][] and [psycopg][] are tested asynchronous drivers
|
|
129
|
+
>
|
|
130
|
+
> We can install asynchronous DB libraries like one of blows:
|
|
131
|
+
>
|
|
132
|
+
> - ```bash
|
|
133
|
+
> pip install sqlalchemy-dlock[asyncpg]
|
|
134
|
+
> ```
|
|
135
|
+
>
|
|
136
|
+
> - ```bash
|
|
137
|
+
> pip install sqlalchemy-dlock[asyncio] aiomysql
|
|
138
|
+
> ```
|
|
139
|
+
>
|
|
140
|
+
> - ```bash
|
|
141
|
+
> pip install SQLALchemy[asyncio] sqlalchemy-dlock psycopg
|
|
142
|
+
> ```
|
|
143
|
+
|
|
144
|
+
## Test
|
|
121
145
|
|
|
122
|
-
Following
|
|
146
|
+
Following drivers are tested:
|
|
123
147
|
|
|
124
148
|
- MySQL:
|
|
149
|
+
- [mysqlclient][] (synchronous)
|
|
150
|
+
- [pymysql][] (synchronous)
|
|
151
|
+
- [aiomysql][] (asynchronous)
|
|
152
|
+
- Postgres:
|
|
153
|
+
- [psycopg2][] (asynchronous)
|
|
154
|
+
- [asyncpg][] (asynchronous)
|
|
155
|
+
- [psycopg][] (synchronous and asynchronous)
|
|
125
156
|
|
|
126
|
-
|
|
127
|
-
- PyMySQL
|
|
128
|
-
- aiomysql ([asyncio][])
|
|
157
|
+
You can run unit-tests
|
|
129
158
|
|
|
130
|
-
-
|
|
159
|
+
- on local environment:
|
|
131
160
|
|
|
132
|
-
|
|
133
|
-
- asyncpg ([asyncio][])
|
|
161
|
+
1. Install the project with drivers and `asyncio` extra requires, a virtual environment ([venv][]) is strongly advised:
|
|
134
162
|
|
|
135
|
-
|
|
163
|
+
```bash
|
|
164
|
+
pip install -e .[mysqlclient psycopg2-binary aiomysql asyncpg]
|
|
165
|
+
```
|
|
136
166
|
|
|
137
|
-
|
|
167
|
+
1. start up mysql and postgresql
|
|
138
168
|
|
|
139
|
-
|
|
169
|
+
There is a docker [compose][] file `db.docker-compose.yml` in the project dir,
|
|
170
|
+
which can be used to run mysql and postgresql develop environment conveniently:
|
|
140
171
|
|
|
141
172
|
```bash
|
|
142
|
-
|
|
173
|
+
docker compose -f db.docker-compose.yml up
|
|
143
174
|
```
|
|
144
175
|
|
|
145
|
-
1.
|
|
146
|
-
|
|
147
|
-
1. Set environment variables `TEST_URLS` and `TEST_ASYNC_URLS` for sync and async database connection url.
|
|
176
|
+
1. set environment variables `TEST_URLS` and `TEST_ASYNC_URLS` for sync and async database connection url.
|
|
148
177
|
Multiple connections separated by space.
|
|
149
178
|
The test cases load environment variables in `tests/.env`.
|
|
150
179
|
|
|
151
180
|
eg (and also the defaults):
|
|
152
181
|
|
|
153
182
|
```ini
|
|
154
|
-
TEST_URLS=mysql://test:test@
|
|
155
|
-
TEST_ASYNC_URLS=mysql+aiomysql://test:test@
|
|
183
|
+
TEST_URLS=mysql://test:test@127.0.0.1/test postgresql://postgres:test@127.0.0.1/
|
|
184
|
+
TEST_ASYNC_URLS=mysql+aiomysql://test:test@127.0.0.1/test postgresql+asyncpg://postgres:test@127.0.0.1/
|
|
156
185
|
```
|
|
157
186
|
|
|
158
187
|
1. run unit-test
|
|
@@ -161,7 +190,7 @@ You can run unit-tests:
|
|
|
161
190
|
python -m unittest
|
|
162
191
|
```
|
|
163
192
|
|
|
164
|
-
-
|
|
193
|
+
- or on docker-compose:
|
|
165
194
|
|
|
166
195
|
1. build the project
|
|
167
196
|
|
|
@@ -171,12 +200,30 @@ You can run unit-tests:
|
|
|
171
200
|
|
|
172
201
|
1. run unit-test
|
|
173
202
|
|
|
203
|
+
Name of services for Python and [SQLAlchemy][] version matrix in the [compose][] file has such format:
|
|
204
|
+
|
|
205
|
+
python{{X.Y}}-sqlalchemy{{X}}
|
|
206
|
+
|
|
207
|
+
For example, if want to take a test for Python `3.9` and [SQLAlchemy][] `2.x`, we shall up to run unit-tests as below:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
cd tests
|
|
211
|
+
docker compose up python3.9-sqlalchemy2
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
For Python `3.8` and [SQLAlchemy][] `1.x`:
|
|
215
|
+
|
|
174
216
|
```bash
|
|
175
217
|
cd tests
|
|
176
|
-
docker compose up
|
|
177
|
-
docker compose rm -fsv
|
|
218
|
+
docker compose up python3.8-sqlalchemy1
|
|
178
219
|
```
|
|
179
220
|
|
|
180
221
|
[SQLAlchemy]: https://www.sqlalchemy.org/ "The Python SQL Toolkit and Object Relational Mapper"
|
|
181
|
-
[asyncio]: https://docs.python.org/library/asyncio.html "asyncio is a library to write concurrent code using the async/await syntax."
|
|
182
222
|
[venv]: https://docs.python.org/library/venv.html "The venv module supports creating lightweight “virtual environments”, each with their own independent set of Python packages installed in their site directories. "
|
|
223
|
+
[mysqlclient]: https://pypi.org/project/mysqlclient/ "Python interface to MySQL"
|
|
224
|
+
[psycopg2]: https://pypi.org/project/psycopg2/ "PostgreSQL database adapter for Python"
|
|
225
|
+
[psycopg]: https://pypi.org/project/psycopg/ "Psycopg 3 is a modern implementation of a PostgreSQL adapter for Python."
|
|
226
|
+
[aiomysql]: https://pypi.org/project/aiomysql/ "aiomysql is a “driver” for accessing a MySQL database from the asyncio (PEP-3156/tulip) framework."
|
|
227
|
+
[asyncpg]: https://pypi.org/project/asyncpg/ "asyncpg is a database interface library designed specifically for PostgreSQL and Python/asyncio. "
|
|
228
|
+
[pymysql]: https://pypi.org/project/pymysql/ "Pure Python MySQL Driver"
|
|
229
|
+
[compose]: https://docs.docker.com/compose/ "Compose is a tool for defining and running multi-container Docker applications."
|
|
@@ -1,45 +1,66 @@
|
|
|
1
1
|
[build-system]
|
|
2
2
|
build-backend = "setuptools.build_meta"
|
|
3
|
-
requires = ["setuptools>=
|
|
3
|
+
requires = ["setuptools>=61", "setuptools_scm>=6.2"]
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
|
+
name = "sqlalchemy-dlock"
|
|
7
|
+
readme = {file = 'README.md', content-type = 'text/markdown'}
|
|
6
8
|
authors = [
|
|
7
9
|
{name = "liu xue yan", email = "liu_xue_yan@foxmail.com"},
|
|
8
10
|
]
|
|
11
|
+
description = "A distributed lock implementation based on SQLAlchemy"
|
|
12
|
+
keywords = ["SQLAlchemy", "lock", "distributed", "distributed lock", "SQL", "database", "DBMS"]
|
|
13
|
+
license = {text = "BSD-3-Clause"}
|
|
9
14
|
classifiers = [
|
|
10
15
|
"License :: OSI Approved :: BSD License",
|
|
11
16
|
"Topic :: Database :: Front-Ends",
|
|
12
17
|
"Intended Audience :: Developers",
|
|
13
18
|
"Programming Language :: Python",
|
|
14
19
|
]
|
|
15
|
-
description = "A distributed lock implementation based on SQLAlchemy"
|
|
16
|
-
keywords = ["SQLAlchemy", "lock", "distributed", "distributed lock", "SQL", "database", "DBMS"]
|
|
17
|
-
license = {file = 'LICENSE'}
|
|
18
|
-
name = "sqlalchemy-dlock"
|
|
19
|
-
readme = {file = 'README.md', content-type = 'text/markdown'}
|
|
20
|
-
requires-python = ">=3.7"
|
|
21
|
-
|
|
22
20
|
dynamic = ["version"]
|
|
23
21
|
|
|
22
|
+
# requires python version
|
|
23
|
+
requires-python = ">=3.7"
|
|
24
|
+
# requires
|
|
25
|
+
dependencies = [
|
|
26
|
+
"SQLAlchemy>=1.4.3,<3.0",
|
|
27
|
+
]
|
|
28
|
+
# extra requires
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
# SQLAlchemy with asyncio, no engines
|
|
31
|
+
asyncio = ["SQLAlchemy[asyncio]"]
|
|
32
|
+
# MySQL
|
|
33
|
+
mysqlclient = ["mysqlclient"]
|
|
34
|
+
pymysql = ["pymysql"]
|
|
35
|
+
# MySQL asyncio
|
|
36
|
+
aiomysql = ["SQLAlchemy[asyncio]", "aiomysql"]
|
|
37
|
+
# Postgres
|
|
38
|
+
# psycopg2: sync
|
|
39
|
+
psycopg2 = ["psycopg2>=2.8"] # psycopg2 compiling needed when install
|
|
40
|
+
psycopg2-binary = ["psycopg2-binary>=2.8"] # psycopg2 with pre-compiled C library
|
|
41
|
+
# psycopg3: both sync and asyncio
|
|
42
|
+
psycopg3 = ["SQLAlchemy>=2.0", "psycopg"] # psycopg3 dynamik link to libpq
|
|
43
|
+
psycopg3-binary = ["SQLAlchemy>=2.0", "psycopg[binary]"] # psycopg3 with pre-compiled C library
|
|
44
|
+
psycopg3-c = ["SQLAlchemy>=2.0", "psycopg[c]"] # psycopg3 compiling needed when install
|
|
45
|
+
# Postgres asyncio
|
|
46
|
+
asyncpg3 = ["SQLAlchemy[asyncio]", "asyncpg"]
|
|
47
|
+
|
|
48
|
+
# Project links
|
|
24
49
|
[project.urls]
|
|
25
50
|
homepage = "https://github.com/tanbro/sqlalchemy-dlock"
|
|
51
|
+
documentation = "https://sqlalchemy-dlock.readthedocs.io/"
|
|
26
52
|
repository = "https://github.com/tanbro/sqlalchemy-dlock.git"
|
|
27
53
|
|
|
28
|
-
[tool.setuptools_scm]
|
|
29
|
-
write_to = "src/sqlalchemy_dlock/version.py"
|
|
30
|
-
|
|
31
54
|
[tool.setuptools.packages.find]
|
|
32
55
|
where = ["src"]
|
|
33
56
|
|
|
34
|
-
[tool.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
dependencies = [
|
|
38
|
-
"SQLAlchemy>=1.4,<3.0",
|
|
39
|
-
]
|
|
57
|
+
[tool.setuptools_scm]
|
|
58
|
+
write_to = "src/sqlalchemy_dlock/version.py"
|
|
40
59
|
|
|
41
60
|
[options.packages.find]
|
|
42
61
|
where = "src"
|
|
43
62
|
|
|
44
|
-
[
|
|
45
|
-
|
|
63
|
+
[tool.black]
|
|
64
|
+
line-length = 127
|
|
65
|
+
[tool.isort]
|
|
66
|
+
profile = "black"
|