Skip to content

Commit 49125b8

Browse files
committed
Backport minor fixes from 3.1
1 parent 7f75921 commit 49125b8

20 files changed

+77
-57
lines changed

.github/workflows/release-docs.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ jobs:
1111
runs-on: ubuntu-latest
1212

1313
steps:
14-
- uses: actions/checkout@v3
15-
- name: Set up Python 3.11
16-
uses: actions/setup-python@v3
14+
- uses: actions/checkout@v5
15+
- name: Set up Python 3.12
16+
uses: actions/setup-python@v6
1717
with:
18-
python-version: "3.11"
18+
python-version: "3.12"
1919
- name: Install dependencies
2020
run: |
2121
python -m pip install --upgrade pip
@@ -26,7 +26,7 @@ jobs:
2626
make html
2727
touch _build/html/.nojekyll
2828
- name: Deploy docs to GitHub pages
29-
uses: peaceiris/actions-gh-pages@v3
29+
uses: peaceiris/actions-gh-pages@v4
3030
with:
3131
github_token: ${{ secrets.GITHUB_TOKEN }}
3232
publish_branch: gh-pages

.github/workflows/test-package.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,24 @@ jobs:
1010
strategy:
1111
max-parallel: 6
1212
matrix:
13-
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', 'pypy-3.9']
13+
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.9', 'pypy-3.10', 'pypy-3.11']
1414

1515
steps:
16-
- uses: actions/checkout@v3
16+
- uses: actions/checkout@v5
1717
- name: Set up Python ${{ matrix.python-version }}
18-
uses: actions/setup-python@v3
18+
uses: actions/setup-python@v6
1919
with:
2020
python-version: ${{ matrix.python-version }}
2121
- name: Install dependencies
2222
run: |
2323
python -m pip install --upgrade pip
2424
pip install .[tests] --use-pep517
2525
- name: Lint with flake8
26-
if: matrix.python-version == '3.11'
26+
if: matrix.python-version == '3.12'
2727
run: |
2828
flake8 webware setup.py --count --exit-zero --statistics
2929
- name: Lint with pylint
30-
if: matrix.python-version == '3.11'
30+
if: matrix.python-version == '3.12'
3131
run: |
3232
pylint webware
3333
- name: Run all unit tests

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Sessions/
3030
Webware-for-Python-*
3131

3232
.idea/
33+
.vscode/
3334
.tox/
3435
.venv/
3536
.venv.*/

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
# -- Project information -----------------------------------------------------
2323

2424
project = 'Webware for Python 3'
25-
copyright = '1999-2023, Christoph Zwerschke et al'
25+
copyright = '1999-2025, Christoph Zwerschke et al'
2626
author = 'Christoph Zwerschke et al.'
2727

2828
# The short X.Y version

docs/install.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ When installing Webware for Python 3, the following "extras" can optionally be i
5353

5454
* "dev": extras for developing Webware applications
5555
* "examples": extras for running all Webware examples
56-
* "test": extras needed to test all functions of Webware
56+
* "tests": extras needed to test all functions of Webware
5757
* "docs": extras needed to build this documentation
5858

59-
On your development machine, we recommend installing the full "test" environment which also includes the other two environments. To do that, you need to specify the "Extras" name in square brackets when installing Webware for Python 3::
59+
On your development machine, we recommend installing the full "tests" environment which also includes the other two environments. To do that, you need to specify the "Extras" name in square brackets when installing Webware for Python 3::
6060

61-
pip install "Webware-for-Python[dev]>=3"
61+
pip install "Webware-for-Python[tests]>=3"
6262

6363

6464
Installation from Source

tox.ini

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,26 @@
22
envlist = py{36,37,38,39,310,311,312}, pypy3, flake8, pylint, docs, manifest
33

44
[testenv:flake8]
5-
basepython = python3.11
5+
basepython = python3.12
66
deps = flake8>=6,<7
77
commands =
88
flake8 webware setup.py
99

1010
[testenv:pylint]
11-
basepython = python3.11
11+
basepython = python3.12
1212
deps = pylint>=2.16,<3
1313
commands =
1414
pylint webware
1515

1616
[testenv:docs]
17-
basepython = python3.11
17+
basepython = python3.12
1818
extras =
1919
docs
2020
commands =
2121
sphinx-build -b html -nEW docs docs/_build/html
2222

2323
[testenv:manifest]
24-
basepython = python3.11
24+
basepython = python3.12
2525
deps = check-manifest>=0.49
2626
commands =
2727
check-manifest -v

webware/Application.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"""
1515

1616
import atexit
17+
import importlib
1718
import os
1819
import signal
1920
import sys
@@ -295,27 +296,27 @@ def initSessions(self):
295296
moduleName = setting('SessionModule')
296297
className = moduleName.rpartition('.')[2]
297298
try:
298-
exec(f'from {moduleName} import {className}')
299-
cls = locals()[className]
299+
module = importlib.import_module(moduleName)
300+
cls = getattr(module, className)
300301
if not isinstance(cls, type):
301-
raise ImportError
302+
raise ImportError(f'{cls!r} is not a type')
302303
self._sessionClass = cls
303-
except ImportError:
304+
except (ImportError, AttributeError) as err:
304305
print(f"ERROR: Could not import Session class '{className}'"
305-
f" from module '{moduleName}'")
306+
f" from module '{moduleName}':\n{err}")
306307
self._sessionClass = None
307308
moduleName = setting('SessionStore')
308309
if moduleName in (
309310
'Dynamic', 'File', 'Memcached', 'Memory', 'Redis', 'Shelve'):
310311
moduleName = f'Session{moduleName}Store'
311312
className = moduleName.rpartition('.')[2]
312313
try:
313-
exec(f'from {moduleName} import {className}')
314-
cls = locals()[className]
314+
module = importlib.import_module(moduleName)
315+
cls = getattr(module, className)
315316
if not isinstance(cls, type):
316-
raise ImportError
317+
raise ImportError(f'{cls!r} is not a type')
317318
self._sessions = cls(self)
318-
except ImportError as err:
319+
except (ImportError, AttributeError) as err:
319320
print(f"ERROR: Could not import SessionStore class '{className}'"
320321
f" from module '{moduleName}':\n{err}")
321322
self._sessions = None

webware/Examples/PushServlet.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def pushHTML(self, count):
5757
if count:
5858
wr('<h3>This page has been replaced'
5959
f' <strong style="color:#339">{count:d}</strong>'
60-
f" time{'' if count ==1 else 's'}.</h3>")
60+
f" time{'' if count == 1 else 's'}.</h3>")
6161
if count == 3:
6262
wr('<p>Stopped pushing contents.</p>')
6363
else:

webware/MiscUtils/DBPool.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,20 @@ def _unthreadsafeReturnConnection(self, con):
152152
"""
153153
self._unthreadsafeAddConnection(con)
154154

155+
def close(self):
156+
"""Close all connections in the pool."""
157+
try:
158+
queue = self._queue
159+
except AttributeError:
160+
connections = self._connections
161+
while connections:
162+
con = connections.pop()
163+
con.close()
164+
else:
165+
while not queue.empty():
166+
con = queue.get_nowait()
167+
con.close()
168+
155169
# The following functions are used with DB-API 2 modules
156170
# that are threadsafe at the connection level, like psycopg.
157171
# Note: In this case, connections are shared between threads.

webware/MiscUtils/DataTable.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -791,8 +791,7 @@ def __repr__(self):
791791
return repr(self._values)
792792

793793
def __iter__(self):
794-
for value in self._values:
795-
yield value
794+
yield from self._values
796795

797796
def get(self, key, default=None):
798797
index = self._nameToIndexMap.get(key)
@@ -801,7 +800,7 @@ def get(self, key, default=None):
801800
return self._values[index]
802801

803802
def has_key(self, key):
804-
warn("has_key is deprecated, please us 'in' instead.",
803+
warn("has_key is deprecated, use 'in' instead.",
805804
DeprecationWarning, stacklevel=2)
806805
return key in self
807806

0 commit comments

Comments
 (0)