From 9b49eb9b8d5aa1456fd0955dfa1ff3eaf3872a67 Mon Sep 17 00:00:00 2001 From: Christoph Zwerschke Date: Sat, 20 May 2023 13:55:32 +0200 Subject: [PATCH 1/4] Better support for local testing of TestFuncs --- webware/MiscUtils/Tests/TestFuncs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webware/MiscUtils/Tests/TestFuncs.py b/webware/MiscUtils/Tests/TestFuncs.py index d49a21c..3431d6c 100644 --- a/webware/MiscUtils/Tests/TestFuncs.py +++ b/webware/MiscUtils/Tests/TestFuncs.py @@ -93,7 +93,7 @@ def testLocalIP(self): def assertLocal(ip): self.assertTrue( - ip == thisIp or ip.startswith(('127.', '192.168.')) + ip == thisIp or ip.startswith(('127.', '169.254', '192.168.')) or '172.16.' <= ip <= '172.31.') assertLocal(localIP(remote=None, useCache=None)) From 72c94e8708326382ef2fc04c1b27e96efa08a15e Mon Sep 17 00:00:00 2001 From: Christoph Zwerschke Date: Sat, 20 May 2023 13:56:35 +0200 Subject: [PATCH 2/4] Support posting binary data with query string (#16) --- webware/WebUtils/FieldStorage.py | 12 ++++++ .../Tests/TestFieldStorageModified.py | 40 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/webware/WebUtils/FieldStorage.py b/webware/WebUtils/FieldStorage.py index 2c6e010..42a5a95 100644 --- a/webware/WebUtils/FieldStorage.py +++ b/webware/WebUtils/FieldStorage.py @@ -413,6 +413,18 @@ def read_single(self): else: self.read_lines() self.file.seek(0) + # contrary to the standard library, we also parse the query string + if self.qs_on_post: + kwargs = { + 'keep_blank_values': self.keep_blank_values, + 'strict_parsing': self.strict_parsing, + 'encoding': self.encoding, 'errors': self.errors} + if self.max_num_fields is not None: # Python >= 3.8 + kwargs['max_num_fields'] = self.max_num_fields + if self.separator != '&': # Python >= 3.9.2 + kwargs['separator'] = self.separator + query = parse_qsl(self.qs_on_post, **kwargs) + self.list = [MiniFieldStorage(key, value) for key, value in query] bufsize = 8 * 1024 diff --git a/webware/WebUtils/Tests/TestFieldStorageModified.py b/webware/WebUtils/Tests/TestFieldStorageModified.py index 6041f72..39d238a 100644 --- a/webware/WebUtils/Tests/TestFieldStorageModified.py +++ b/webware/WebUtils/Tests/TestFieldStorageModified.py @@ -257,6 +257,46 @@ def testPostRequestWithNonUtf8TextData(self): self.assertEqual(fs.bytes_read, length) self.assertEqual(fs.file.read(), content) + def testPostRequestWithTextDataAndQueryParams(self): + text = 'The \u2603 by Raymond Briggs' + content = text.encode('utf-8') + length = len(content) + fs = FieldStorage(fp=BytesIO(content), environ={ + 'CONTENT_LENGTH': length, 'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'text/plain', + 'QUERY_STRING': 'a=1&b=2&b=2'}) + self.assertEqual(fs.headers, { + 'content-type': 'text/plain', + 'content-length': length}) + self.assertEqual(fs.type, 'text/plain') + self.assertEqual(fs.length, length) + self.assertEqual(fs.bytes_read, length) + self.assertEqual(fs.file.read(), text) + self.assertEqual(fs.getfirst('a'), '1') + self.assertEqual(fs.getfirst('b'), '2') + self.assertEqual(fs.getlist('a'), ['1']) + self.assertEqual(fs.getlist('b'), ['2', '2']) + + def testPostRequestWithBinaryDataAndQueryParams(self): + content = b'\xfe\xff\xc0' + length = len(content) + fs = FieldStorage(fp=BytesIO(content), environ={ + 'REQUEST_METHOD': 'POST', + 'CONTENT_LENGTH': length, + 'CONTENT_TYPE': 'application/octet-stream', + 'QUERY_STRING': 'a=1&b=2&b=2'}) + self.assertEqual(fs.headers, { + 'content-type': 'application/octet-stream', + 'content-length': length}) + self.assertEqual(fs.type, 'application/octet-stream') + self.assertEqual(fs.length, length) + self.assertEqual(fs.bytes_read, length) + self.assertEqual(fs.file.read(), content) + self.assertEqual(fs.getfirst('a'), '1') + self.assertEqual(fs.getfirst('b'), '2') + self.assertEqual(fs.getlist('a'), ['1']) + self.assertEqual(fs.getlist('b'), ['2', '2']) + def testPostRequestWithSmallPayloadWithContentLength(self): length = 1000 # much smaller than buffer size payload = 'x' * length From c43a8536ea4aebabd08dbbcc0f4d8dec372d912e Mon Sep 17 00:00:00 2001 From: Christoph Zwerschke Date: Sat, 27 May 2023 19:12:40 +0200 Subject: [PATCH 3/4] Support Python 3.12 --- .github/workflows/release-docs.yml | 4 ++-- .github/workflows/test-package.yml | 4 ++-- setup.py | 2 ++ tox.ini | 10 +++++----- webware/MiscUtils/Funcs.py | 5 +---- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release-docs.yml b/.github/workflows/release-docs.yml index 2e3af92..e977f20 100644 --- a/.github/workflows/release-docs.yml +++ b/.github/workflows/release-docs.yml @@ -12,10 +12,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up Python 3.10 + - name: Set up Python 3.11 uses: actions/setup-python@v3 with: - python-version: "3.10" + python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml index 060b18d..773aaa4 100644 --- a/.github/workflows/test-package.yml +++ b/.github/workflows/test-package.yml @@ -23,11 +23,11 @@ jobs: python -m pip install --upgrade pip pip install .[tests] --use-pep517 - name: Lint with flake8 - if: matrix.python-version == '3.10' + if: matrix.python-version == '3.11' run: | flake8 webware setup.py --count --exit-zero --statistics - name: Lint with pylint - if: matrix.python-version == '3.10' + if: matrix.python-version == '3.11' run: | pylint webware - name: Run all unit tests diff --git a/setup.py b/setup.py index 285d0a4..6109a0d 100644 --- a/setup.py +++ b/setup.py @@ -60,10 +60,12 @@ 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Operating System :: OS Independent', ], + install_requires=["setuptools"], extras_require={ 'dev': requireDev, 'docs': requireDocs, diff --git a/tox.ini b/tox.ini index ad40ef7..9eec447 100644 --- a/tox.ini +++ b/tox.ini @@ -1,27 +1,27 @@ [tox] -envlist = py{36,37,38,39,310,311}, pypy3, flake8, pylint, docs, manifest +envlist = py{36,37,38,39,310,311,312}, pypy3, flake8, pylint, docs, manifest [testenv:flake8] -basepython = python3.10 +basepython = python3.11 deps = flake8>=6,<7 commands = flake8 webware setup.py [testenv:pylint] -basepython = python3.10 +basepython = python3.11 deps = pylint>=2.16,<3 commands = pylint webware [testenv:docs] -basepython = python3.10 +basepython = python3.11 extras = docs commands = sphinx-build -b html -nEW docs docs/_build/html [testenv:manifest] -basepython = python3.10 +basepython = python3.11 deps = check-manifest>=0.49 commands = check-manifest -v diff --git a/webware/MiscUtils/Funcs.py b/webware/MiscUtils/Funcs.py index 55b26d0..d053ab2 100644 --- a/webware/MiscUtils/Funcs.py +++ b/webware/MiscUtils/Funcs.py @@ -278,10 +278,7 @@ def timestamp(t=None): def localTimeDelta(t=None): """Return timedelta of local zone from GMT.""" - if t is None: - t = time.time() - dt = datetime.datetime - return dt.fromtimestamp(t) - dt.utcfromtimestamp(t) + return datetime.timedelta(seconds=time.localtime(t).tm_gmtoff) def uniqueId(forObject=None): From 7f75921926f58182cd3f28d5f974d13807df4ef6 Mon Sep 17 00:00:00 2001 From: Christoph Zwerschke Date: Sat, 27 May 2023 19:25:19 +0200 Subject: [PATCH 4/4] Bump version number for patch release --- docs/conf.py | 2 +- webware/Properties.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index def94ca..7c7bb4e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -28,7 +28,7 @@ # The short X.Y version version = '3.0' # The full version, including alpha/beta/rc tags -release = '3.0.9' +release = '3.0.10' # -- General configuration --------------------------------------------------- diff --git a/webware/Properties.py b/webware/Properties.py index 1d3d05c..976f03b 100644 --- a/webware/Properties.py +++ b/webware/Properties.py @@ -1,6 +1,6 @@ name = 'Webware for Python' -version = (3, 0, 9) +version = (3, 0, 10) status = 'stable'