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.
Files changed (42) hide show
  1. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/CHANGELOG.md +24 -0
  2. sqlalchemy-dlock-0.4/MANIFEST.in +8 -0
  3. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/PKG-INFO +97 -69
  4. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/README.md +85 -38
  5. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/pyproject.toml +40 -19
  6. sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/__init__.py +7 -0
  7. sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/asyncio/baselock.py +46 -0
  8. sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/asyncio/functions.py +27 -0
  9. {sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/asyncio/impl → sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/asyncio/lock}/mysql.py +14 -36
  10. {sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/asyncio/impl → sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/asyncio/lock}/postgresql.py +8 -83
  11. sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/types.py → sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/baselock.py +7 -30
  12. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock/exceptions.py +3 -0
  13. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock/functions.py +15 -8
  14. {sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/impl → sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/lock}/mysql.py +21 -46
  15. {sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/impl → sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/lock}/postgresql.py +21 -91
  16. sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/statement/__init__.py +0 -0
  17. sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/statement/mysql.py +20 -0
  18. sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/statement/postgresql.py +75 -0
  19. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock/utils.py +7 -10
  20. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock/version.py +2 -2
  21. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock.egg-info/PKG-INFO +97 -69
  22. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock.egg-info/SOURCES.txt +11 -14
  23. sqlalchemy-dlock-0.4/src/sqlalchemy_dlock.egg-info/requires.txt +36 -0
  24. sqlalchemy-dlock-0.3/.coveragerc +0 -10
  25. sqlalchemy-dlock-0.3/.readthedocs.yaml +0 -19
  26. sqlalchemy-dlock-0.3/MANIFEST.in +0 -30
  27. sqlalchemy-dlock-0.3/codecov.yml +0 -5
  28. sqlalchemy-dlock-0.3/scripts/run-test.sh +0 -13
  29. sqlalchemy-dlock-0.3/scripts/wait-for-mysql.sh +0 -17
  30. sqlalchemy-dlock-0.3/scripts/wait-for-postgres.sh +0 -15
  31. sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/__init__.py +0 -6
  32. sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/asyncio/functions.py +0 -21
  33. sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/asyncio/types.py +0 -62
  34. sqlalchemy-dlock-0.3/src/sqlalchemy_dlock.egg-info/requires.txt +0 -3
  35. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/AUTHORS.md +0 -0
  36. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/LICENSE +0 -0
  37. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/setup.cfg +0 -0
  38. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock/asyncio/__init__.py +0 -0
  39. {sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/asyncio/impl → sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/asyncio/lock}/__init__.py +0 -0
  40. {sqlalchemy-dlock-0.3/src/sqlalchemy_dlock/impl → sqlalchemy-dlock-0.4/src/sqlalchemy_dlock/lock}/__init__.py +0 -0
  41. {sqlalchemy-dlock-0.3 → sqlalchemy-dlock-0.4}/src/sqlalchemy_dlock.egg-info/dependency_links.txt +0 -0
  42. {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
@@ -0,0 +1,8 @@
1
+ exclude .*
2
+ exclude *.docker-compose.yml
3
+ exclude codecov.yml
4
+
5
+ prune .*
6
+ prune docs
7
+ prune tests
8
+ prune scripts
@@ -1,39 +1,11 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sqlalchemy-dlock
3
- Version: 0.3
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 3-Clause License
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
- ## Usages
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@localhost/')
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.acquired
69
+ assert not lock.locked
83
70
 
84
71
  # lock
85
72
  lock.acquire()
86
- assert lock.acquired
73
+ assert lock.locked
87
74
 
88
75
  # un-lock
89
76
  lock.release()
90
- assert not lock.acquired
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@localhost/')
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.acquired
96
+ assert lock.locked
110
97
 
111
98
  # Auto un-locked
112
- assert not lock.acquired
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.acquired
103
+ # It's NOT locked here !!!
104
+ assert not lock2.locked
118
105
  # lock it now:
119
106
  lock2.acquire()
120
- assert lock2.acquired
107
+ assert lock2.locked
121
108
 
122
109
  # Auto un-locked
123
- assert not lock2.acquired
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@localhost/')
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.acquired
141
- assert not lock.acquired
127
+ assert lock.locked
128
+ assert not lock.locked
142
129
  ```
143
130
 
144
131
  - Asynchronous I/O Support
145
132
 
146
- > ℹ️ **info**:
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@localhost/')
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
- ## Tests
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 [SQLAlchemy][] engines are tested:
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
- - mysqlclient
175
- - PyMySQL
176
- - aiomysql ([asyncio][])
186
+ You can run unit-tests
177
187
 
178
- - Postgres:
188
+ - on local environment:
179
189
 
180
- - psycopg2
181
- - asyncpg ([asyncio][])
190
+ 1. Install the project with drivers and `asyncio` extra requires, a virtual environment ([venv][]) is strongly advised:
182
191
 
183
- You can run unit-tests:
192
+ ```bash
193
+ pip install -e .[mysqlclient psycopg2-binary aiomysql asyncpg]
194
+ ```
184
195
 
185
- - directly:
196
+ 1. start up mysql and postgresql
186
197
 
187
- 1. Install the project (A virtual environment ([venv][]) is strongly advised):
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
- pip install -e .
202
+ docker compose -f db.docker-compose.yml up
191
203
  ```
192
204
 
193
- 1. Start up your mysql and postgresql
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@localhost/test postgresql://postgres:test@localhost/
203
- TEST_ASYNC_URLS=mysql+aiomysql://test:test@localhost/test postgresql+asyncpg://postgres:test@localhost/
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
- - in docker-compose:
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 --abort-on-container-exit
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
- ## Usages
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@localhost/')
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.acquired
40
+ assert not lock.locked
35
41
 
36
42
  # lock
37
43
  lock.acquire()
38
- assert lock.acquired
44
+ assert lock.locked
39
45
 
40
46
  # un-lock
41
47
  lock.release()
42
- assert not lock.acquired
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@localhost/')
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.acquired
67
+ assert lock.locked
62
68
 
63
69
  # Auto un-locked
64
- assert not lock.acquired
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.acquired
74
+ # It's NOT locked here !!!
75
+ assert not lock2.locked
70
76
  # lock it now:
71
77
  lock2.acquire()
72
- assert lock2.acquired
78
+ assert lock2.locked
73
79
 
74
80
  # Auto un-locked
75
- assert not lock2.acquired
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@localhost/')
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.acquired
93
- assert not lock.acquired
98
+ assert lock.locked
99
+ assert not lock.locked
94
100
  ```
95
101
 
96
102
  - Asynchronous I/O Support
97
103
 
98
- > ℹ️ **info**:
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@localhost/')
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
- ## Tests
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 [SQLAlchemy][] engines are tested:
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
- - mysqlclient
127
- - PyMySQL
128
- - aiomysql ([asyncio][])
157
+ You can run unit-tests
129
158
 
130
- - Postgres:
159
+ - on local environment:
131
160
 
132
- - psycopg2
133
- - asyncpg ([asyncio][])
161
+ 1. Install the project with drivers and `asyncio` extra requires, a virtual environment ([venv][]) is strongly advised:
134
162
 
135
- You can run unit-tests:
163
+ ```bash
164
+ pip install -e .[mysqlclient psycopg2-binary aiomysql asyncpg]
165
+ ```
136
166
 
137
- - directly:
167
+ 1. start up mysql and postgresql
138
168
 
139
- 1. Install the project (A virtual environment ([venv][]) is strongly advised):
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
- pip install -e .
173
+ docker compose -f db.docker-compose.yml up
143
174
  ```
144
175
 
145
- 1. Start up your mysql and postgresql
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@localhost/test postgresql://postgres:test@localhost/
155
- TEST_ASYNC_URLS=mysql+aiomysql://test:test@localhost/test postgresql+asyncpg://postgres:test@localhost/
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
- - in docker-compose:
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 --abort-on-container-exit
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>=45", "wheel", "setuptools_scm>=6.2"]
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.black]
35
- line-length = 127
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
- [project.optional-dependencies]
45
- asyncio = ["SQLAlchemy[asyncio]"]
63
+ [tool.black]
64
+ line-length = 127
65
+ [tool.isort]
66
+ profile = "black"
@@ -0,0 +1,7 @@
1
+ """
2
+ Distributed lock based on Database and SQLAlchemy
3
+ """
4
+
5
+ from .exceptions import *
6
+ from .functions import *
7
+ from .version import version as __version__