From 2615d90f95267171c6278a5d06146afadcf0cba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Sch=C3=A4ckermann?= Date: Mon, 6 Jun 2022 14:58:36 +0200 Subject: [PATCH 01/13] Creating git workflow to replace .travis.yml --- .../workflows/check-code-and-run-tests.yml | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/check-code-and-run-tests.yml diff --git a/.github/workflows/check-code-and-run-tests.yml b/.github/workflows/check-code-and-run-tests.yml new file mode 100644 index 00000000..13c14d69 --- /dev/null +++ b/.github/workflows/check-code-and-run-tests.yml @@ -0,0 +1,30 @@ +name: Check code and run tests + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["2.7", "3.6", "3.8", "3.9", "3.10"] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install --upgrade flake8>=3.7.9 pyparsing==2.4.4 pytest==4.6.6 + - name: Analysing the code with flake8 + run: | + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=88 --statistics + - name: Running tests + run: | + py.test --version + pip install ".[testing]" + pytest tests/ --ignore=tests/system/data/ --showlocals --verbose --show-capture=all --log-level=debug From 11a25af145d51a493e97a6582b70bc89b0aa822d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Sch=C3=A4ckermann?= Date: Mon, 6 Jun 2022 15:23:48 +0200 Subject: [PATCH 02/13] Only test for Python 2.7, 3.6 and 3.8 for now --- .github/workflows/check-code-and-run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-code-and-run-tests.yml b/.github/workflows/check-code-and-run-tests.yml index 13c14d69..75f7fbed 100644 --- a/.github/workflows/check-code-and-run-tests.yml +++ b/.github/workflows/check-code-and-run-tests.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["2.7", "3.6", "3.8", "3.9", "3.10"] + python-version: ["2.7", "3.6", "3.8"] steps: - name: Checkout uses: actions/checkout@v3 From ad86d45d9cfb4101c042ced162a671700d139c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Sch=C3=A4ckermann?= Date: Tue, 7 Jun 2022 15:33:41 +0200 Subject: [PATCH 03/13] Fixing dependency versions for GITHUB CI/CD action --- .github/workflows/check-code-and-run-tests.yml | 2 +- setup.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check-code-and-run-tests.yml b/.github/workflows/check-code-and-run-tests.yml index 75f7fbed..dc40fd0e 100644 --- a/.github/workflows/check-code-and-run-tests.yml +++ b/.github/workflows/check-code-and-run-tests.yml @@ -18,7 +18,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install --upgrade flake8>=3.7.9 pyparsing==2.4.4 pytest==4.6.6 + pip install --upgrade flake8>=3.7.9 pyparsing==2.0.2 pytest==4.6.11 - name: Analysing the code with flake8 run: | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics diff --git a/setup.py b/setup.py index fe042802..edec361a 100644 --- a/setup.py +++ b/setup.py @@ -45,9 +45,9 @@ TEST_REQUIREMENTS = [ - "pyparsing==2.0.1", - "pytest>=3.6.0", - "flake8>=3.5.0", + "pyparsing==2.0.2", + "pytest==4.6.11", + "flake8>=3.7.9", "pycrypto==2.6", "requests==2.9.1", ] From 9aff137bca0afc36be67ee7a16cb25e28348a569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Sch=C3=A4ckermann?= Date: Tue, 21 Jun 2022 20:40:03 +0200 Subject: [PATCH 04/13] Attempt to fix tests --- .../workflows/check-code-and-run-tests.yml | 5 +-- setup.py | 45 ++++++++++++------- tests/pip/test_pip.py | 4 +- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/.github/workflows/check-code-and-run-tests.yml b/.github/workflows/check-code-and-run-tests.yml index dc40fd0e..07477c82 100644 --- a/.github/workflows/check-code-and-run-tests.yml +++ b/.github/workflows/check-code-and-run-tests.yml @@ -17,8 +17,8 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - python -m pip install --upgrade pip - pip install --upgrade flake8>=3.7.9 pyparsing==2.0.2 pytest==4.6.11 + python -m pip install --upgrade pip wheel setuptools + pip install ".[testing]" - name: Analysing the code with flake8 run: | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics @@ -26,5 +26,4 @@ jobs: - name: Running tests run: | py.test --version - pip install ".[testing]" pytest tests/ --ignore=tests/system/data/ --showlocals --verbose --show-capture=all --log-level=debug diff --git a/setup.py b/setup.py index edec361a..c607d2a7 100644 --- a/setup.py +++ b/setup.py @@ -40,17 +40,35 @@ # =================== SETUP =================== -from distutils.core import setup -from setuptools import find_packages +from setuptools import setup,find_packages - -TEST_REQUIREMENTS = [ - "pyparsing==2.0.2", - "pytest==4.6.11", - "flake8>=3.7.9", - "pycrypto==2.6", - "requests==2.9.1", -] +if sys.version_info.major==2: + INSTALL_REQUIREMENTS = [ + "rsa==4.5", + "six", # required by StaSh + "pyperclip", # required by libdist for copy/paste on PC + "requests==2.9.1", + "pycrypto==2.6", + "pyte", + ] + TEST_REQUIREMENTS = [ + "pyparsing==2.0.2", + "pytest==4.6.11", + "flake8>=3.7.9", + ] +else: + INSTALL_REQUIREMENTS=[ + "six", # required by StaSh + "pyperclip", # required by libdist for copy/paste on PC + "requests", + "pycrypto", + "pyte", + ], + TEST_REQUIREMENTS = [ + "pyparsing", + "pytest", + "flake8>=3.7.9", + ] PARENT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -125,12 +143,7 @@ def get_stash_version(corepath): }, scripts=[os.path.join(STASH_DIR, "launch_stash.py")], zip_safe=False, - install_requires=[ - "six", # required by StaSh - "pyperclip", # required by libdist for copy/paste on PC - "requests", - "pyte", - ], + install_requires=INSTALL_REQUIREMENTS, extras_require={ "testing": TEST_REQUIREMENTS, }, diff --git a/tests/pip/test_pip.py b/tests/pip/test_pip.py index bc4d63f6..c4475ef6 100644 --- a/tests/pip/test_pip.py +++ b/tests/pip/test_pip.py @@ -136,7 +136,7 @@ def test_install_pypi_nobinary(self): @requires_network def test_install_pypi_onlybinary(self): """test 'pip install --only-binary :all: '.""" - output = self.run_command("pip --verbose install --only-binary :all: rsa", exitcode=0) + output = self.run_command("pip --verbose install --only-binary :all: rsa==4.5", exitcode=0) self.assertIn("Downloading package", output) self.assert_did_run_setup(output, allow_source=False) self.assertIn("Package installed: rsa", output) @@ -153,7 +153,7 @@ def test_install_command(self): self.run_command("pyrsa-keygen --help", exitcode=127) # 2. install - output = self.run_command("pip --verbose install rsa", exitcode=0) + output = self.run_command("pip --verbose install rsa==4.5", exitcode=0) self.assertIn("Downloading package", output) self.assert_did_run_setup(output) self.assertIn("Package installed: rsa", output) From b722d714915ca3d3c6411cdb2ae0e54c2dac95f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Sch=C3=A4ckermann?= Date: Wed, 22 Jun 2022 08:47:08 +0200 Subject: [PATCH 05/13] Fixing pyte version and missing PYTHONPATH for install test --- .github/workflows/check-code-and-run-tests.yml | 2 ++ setup.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check-code-and-run-tests.yml b/.github/workflows/check-code-and-run-tests.yml index 07477c82..32efe5b5 100644 --- a/.github/workflows/check-code-and-run-tests.yml +++ b/.github/workflows/check-code-and-run-tests.yml @@ -26,4 +26,6 @@ jobs: - name: Running tests run: | py.test --version + # make install test work... + export PYTHONPATH=$(python -m site --user-site) pytest tests/ --ignore=tests/system/data/ --showlocals --verbose --show-capture=all --log-level=debug diff --git a/setup.py b/setup.py index c607d2a7..75cfb149 100644 --- a/setup.py +++ b/setup.py @@ -49,7 +49,7 @@ "pyperclip", # required by libdist for copy/paste on PC "requests==2.9.1", "pycrypto==2.6", - "pyte", + "pyte==0.8.1", ] TEST_REQUIREMENTS = [ "pyparsing==2.0.2", From cb9616605c30c230ec323a668b961d52c904b9cc Mon Sep 17 00:00:00 2001 From: mkb79 Date: Wed, 18 Jan 2023 14:28:24 +0100 Subject: [PATCH 06/13] Patch stash to run with Pythonista 3.4 beta `launch_stash.py` will work. But an ignore exception `No method found for selector "setAutomaticallyAdjustsContentInsetForKeyboard:"` is raised. pip seams to fail to download files. --- system/shcommon.py | 11 ++++++++--- system/shui/pythonista_ui.py | 8 ++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/system/shcommon.py b/system/shcommon.py index 1ef2232b..f25d49be 100644 --- a/system/shcommon.py +++ b/system/shcommon.py @@ -17,9 +17,14 @@ if IN_PYTHONISTA: import plistlib - _properties = plistlib.readPlist(os.path.join(os.path.dirname(sys.executable), 'Info.plist')) - PYTHONISTA_VERSION = _properties['CFBundleShortVersionString'] - PYTHONISTA_VERSION_LONG = _properties['CFBundleVersion'] + info_plist_path = os.path.join(os.path.dirname(sys.executable), 'Info.plist') + if hasattr(plistlib, 'readPlist'): + _properties = plistlib.readPlist(info_plist_path) + elif hasattr(plistlib, 'load'): + with open(info_plist_path, 'rb') as info_plist: + _properties = plistlib.load(info_plist) + else: + raise Exception('`plistlib` does not support reading a plist file.') if PYTHONISTA_VERSION < '3.0': python_capi = ctypes.pythonapi diff --git a/system/shui/pythonista_ui.py b/system/shui/pythonista_ui.py index 05e5c64e..920fef24 100644 --- a/system/shui/pythonista_ui.py +++ b/system/shui/pythonista_ui.py @@ -385,14 +385,14 @@ def _vk_tapped(self, sender): # noinspection PyAttributeOutsideInit,PyUnusedLocal,PyPep8Naming class ShTerminal(ShBaseTerminal): """ - This is a wrapper class of the actual TextView that subclass the SUITextView. + This is a wrapper class of the actual TextView that subclass the UITextView. The wrapper is used to encapsulate the objc calls so that it behaves more like a regular ui.TextView. """ def __init__(self, stash, parent, superview, width, height): - # Create the actual TextView by subclass SUITextView + # Create the actual TextView by subclass UITextView UIKeyCommand = ObjCClass('UIKeyCommand') def kcDispatcher_(_self, _cmd, _sender): @@ -490,7 +490,7 @@ def keyCommands(_self, _cmd): ('UIKeyInputRightArrow', 0): parent.arrowRightAction, } - _ShTerminal = create_objc_class('_ShTerminal', ObjCClass('SUITextView'), [keyCommands, kcDispatcher_]) + _ShTerminal = create_objc_class('_ShTerminal', ObjCClass('UITextView'), [keyCommands, kcDispatcher_]) self.is_editing = False @@ -894,7 +894,7 @@ def render(self, no_wait=False): self.render_thread.cancel() self._render() else: # delayed rendering - if self.render_thread is None or not self.render_thread.isAlive(): + if self.render_thread is None or not self.render_thread.is_alive(): self.render_thread = sh_delay(self._render, self.RENDER_INTERVAL) # Do nothing if there is already a delayed rendering thread waiting From 73ed7f31e36d050969dbb3c16f2f504042034f4a Mon Sep 17 00:00:00 2001 From: mkb79 Date: Wed, 18 Jan 2023 15:24:45 +0100 Subject: [PATCH 07/13] Patch ssl issue in `wget` and Pythonista 3.4 --- bin/wget.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/wget.py b/bin/wget.py index d4e59d07..eb98d3c3 100644 --- a/bin/wget.py +++ b/bin/wget.py @@ -5,9 +5,12 @@ import sys import argparse +import ssl from six.moves.urllib.request import urlopen +import certifi + try: import console except ImportError: @@ -51,7 +54,8 @@ def main(args): try: print('Opening: %s\n' % url) - u = urlopen(url) + context = ssl.create_default_context(cafile=certifi.where()) + u = urlopen(url, context=context) meta = u.info() try: From b3b17e5ae6920bdfc459ba041b68c38b8c92ee75 Mon Sep 17 00:00:00 2001 From: mkb79 Date: Wed, 18 Jan 2023 15:44:45 +0100 Subject: [PATCH 08/13] re-add `PYTHONISTA_VERSION` and `PYTHONISTA_VERSION_LONG` --- system/shcommon.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/system/shcommon.py b/system/shcommon.py index f25d49be..d51aa7d6 100644 --- a/system/shcommon.py +++ b/system/shcommon.py @@ -26,6 +26,9 @@ else: raise Exception('`plistlib` does not support reading a plist file.') + PYTHONISTA_VERSION = _properties['CFBundleShortVersionString'] + PYTHONISTA_VERSION_LONG = _properties['CFBundleVersion'] + if PYTHONISTA_VERSION < '3.0': python_capi = ctypes.pythonapi else: From e16036761a315047e3db1a99c306c0b269652d5e Mon Sep 17 00:00:00 2001 From: mkb79 Date: Thu, 19 Jan 2023 09:35:26 +0100 Subject: [PATCH 09/13] Fix: `Thread.isAlive()` was removed in Python 3.9 Using `Thread.is_alive` in Python 3.9+ and fallback to `Thread.isAlive` to keep backward compatibility. --- system/shthreads.py | 11 +++++++++-- system/shui/pythonista_ui.py | 10 +++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/system/shthreads.py b/system/shthreads.py index ef047f7e..6219ee4e 100644 --- a/system/shthreads.py +++ b/system/shthreads.py @@ -261,9 +261,16 @@ def status(self): # False | not None | stopped # True | None | impossible # True | not None | running - if self.isAlive(): + + # `Thread.isAlive()` was removed in Python 3.9 + if hasattr(self, 'is_alive'): + is_alive = self.is_alive() + else: + is_alive = self.isAlive() + + if is_alive: return self.STARTED - elif (not self.is_alive()) and (self.ident is not None): + elif (not is_alive) and (self.ident is not None): return self.STOPPED else: return self.CREATED diff --git a/system/shui/pythonista_ui.py b/system/shui/pythonista_ui.py index 920fef24..a677ba09 100644 --- a/system/shui/pythonista_ui.py +++ b/system/shui/pythonista_ui.py @@ -894,7 +894,15 @@ def render(self, no_wait=False): self.render_thread.cancel() self._render() else: # delayed rendering - if self.render_thread is None or not self.render_thread.is_alive(): + # `Thread.isAlive()` was removed in Python 3.9 + is_render_thread_alive = False + if self.render_thread is not None: + if hasattr(self.render_thread, 'is_alive'): + is_render_thread_alive = self.render_thread.is_alive() + else: + is_render_thread_alive = self.render_thread.isAlive() + + if self.render_thread is None or not is_render_thread_alive: self.render_thread = sh_delay(self._render, self.RENDER_INTERVAL) # Do nothing if there is already a delayed rendering thread waiting From ff0b99a5b753e2ac04bffdc68663cb84b1624f69 Mon Sep 17 00:00:00 2001 From: mkb79 Date: Thu, 19 Jan 2023 09:39:07 +0100 Subject: [PATCH 10/13] Fix `SUITextView` issue Using `SUITextView` by default and switch to `SUITextView_PY3` if available. Thanks goes to @jsbain for finding out the solution. --- system/shui/pythonista_ui.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/system/shui/pythonista_ui.py b/system/shui/pythonista_ui.py index a677ba09..fa5ec773 100644 --- a/system/shui/pythonista_ui.py +++ b/system/shui/pythonista_ui.py @@ -490,7 +490,10 @@ def keyCommands(_self, _cmd): ('UIKeyInputRightArrow', 0): parent.arrowRightAction, } - _ShTerminal = create_objc_class('_ShTerminal', ObjCClass('UITextView'), [keyCommands, kcDispatcher_]) + try: + _ShTerminal = create_objc_class('_ShTerminal', ObjCClass('SUITextView'), [keyCommands, kcDispatcher_]) + except ValueError: + _ShTerminal = create_objc_class('_ShTerminal', ObjCClass('SUITextView_PY3'), [keyCommands, kcDispatcher_]) self.is_editing = False @@ -895,7 +898,7 @@ def render(self, no_wait=False): self._render() else: # delayed rendering # `Thread.isAlive()` was removed in Python 3.9 - is_render_thread_alive = False + is_render_thread_alive = None if self.render_thread is not None: if hasattr(self.render_thread, 'is_alive'): is_render_thread_alive = self.render_thread.is_alive() From b002219d03545aba0a4130ed85380c0fc19c6ff1 Mon Sep 17 00:00:00 2001 From: mkb79 Date: Thu, 19 Jan 2023 09:44:04 +0100 Subject: [PATCH 11/13] correct docstrings and comments for SUITextView --- system/shui/pythonista_ui.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/shui/pythonista_ui.py b/system/shui/pythonista_ui.py index fa5ec773..2bb27e3f 100644 --- a/system/shui/pythonista_ui.py +++ b/system/shui/pythonista_ui.py @@ -385,14 +385,14 @@ def _vk_tapped(self, sender): # noinspection PyAttributeOutsideInit,PyUnusedLocal,PyPep8Naming class ShTerminal(ShBaseTerminal): """ - This is a wrapper class of the actual TextView that subclass the UITextView. + This is a wrapper class of the actual TextView that subclass the SUITextView/SUITextView_PY3. The wrapper is used to encapsulate the objc calls so that it behaves more like a regular ui.TextView. """ def __init__(self, stash, parent, superview, width, height): - # Create the actual TextView by subclass UITextView + # Create the actual TextView by subclass SUITextView/SUITextView_PY3 UIKeyCommand = ObjCClass('UIKeyCommand') def kcDispatcher_(_self, _cmd, _sender): @@ -886,7 +886,7 @@ def _build_attributed_string(self, chars): def render(self, no_wait=False): """ - Render the screen buffer to the UITextView. Normally the rendering process + Render the screen buffer to the SUITextView/SUITextView_PY3. Normally the rendering process is delayed to throttle the total attempts of rendering. :param bool no_wait: Immediately render the screen without delay. """ From 8d9e5a3b41e627cc1a1188f13cc5b49ab5b8155c Mon Sep 17 00:00:00 2001 From: bennr01 Date: Wed, 15 Mar 2023 08:36:48 +0100 Subject: [PATCH 12/13] Fix wrong merge conflic resolution (NameError) Thanks @cclauss Co-authored-by: Christian Clauss --- system/shthreads.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/shthreads.py b/system/shthreads.py index cb4ca34b..3686494a 100644 --- a/system/shthreads.py +++ b/system/shthreads.py @@ -263,7 +263,7 @@ def status(self): # True | not None | running if self.is_alive(): return self.STARTED - elif (not is_alive) and (self.ident is not None): + elif (not self.is_alive()) and (self.ident is not None): return self.STOPPED else: return self.CREATED From 9c5fac1efebff247a49b890f2eaa2da83be648e8 Mon Sep 17 00:00:00 2001 From: bennr01 Date: Wed, 15 Mar 2023 09:04:54 +0100 Subject: [PATCH 13/13] Add py 3.10 to test matrix See discussion in #463 Co-authored-by: Christian Clauss --- .github/workflows/check-code-and-run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-code-and-run-tests.yml b/.github/workflows/check-code-and-run-tests.yml index b086b10f..9cb3d77d 100644 --- a/.github/workflows/check-code-and-run-tests.yml +++ b/.github/workflows/check-code-and-run-tests.yml @@ -24,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["2.7", "3.6"] # TODO: Add for Pythonista v3.4 -- , "3.10" + python-version: ["2.7", "3.6", "3.10"] steps: - name: Checkout uses: actions/checkout@v3