diff --git a/.github/workflows/check-release.yml b/.github/workflows/check-release.yml deleted file mode 100644 index 643ffda..0000000 --- a/.github/workflows/check-release.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Check Release -on: - push: - branches: ["main"] - pull_request: - branches: ["*"] - -permissions: - contents: write - -jobs: - check_release: - runs-on: ubuntu-latest - strategy: - matrix: - group: [check_release, link_check] - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Install Python - uses: actions/setup-python@v2 - with: - python-version: 3.9 - architecture: "x64" - - name: Install node - uses: actions/setup-node@v2 - with: - node-version: "14.x" - - name: Get pip cache dir - id: pip-cache - run: | - echo "::set-output name=dir::$(pip cache dir)" - - name: Cache pip - uses: actions/cache@v1 - with: - path: ${{ steps.pip-cache.outputs.dir }} - key: ${{ runner.os }}-pip-${{ hashFiles('setup.cfg') }} - restore-keys: | - ${{ runner.os }}-pip- - ${{ runner.os }}-pip- - - name: Cache checked links - if: ${{ matrix.group == 'link_check' }} - uses: actions/cache@v2 - with: - path: ~/.cache/pytest-link-check - key: ${{ runner.os }}-linkcheck-${{ hashFiles('**/*.md', '**/*.rst') }}-md-links - restore-keys: | - ${{ runner.os }}-linkcheck- - - name: Upgrade packaging dependencies - run: | - pip install --upgrade pip setuptools wheel --user - - name: Install Dependencies - run: | - pip install -e . - - name: Check Release - if: ${{ matrix.group == 'check_release' }} - uses: jupyter-server/jupyter_releaser/.github/actions/check-release@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - - name: Check Links - if: ${{ matrix.group == 'link_check' }} - uses: jupyter-server/jupyter_releaser/.github/actions/check-links@v1 diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 73af585..35804d2 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -9,13 +9,18 @@ on: pull_request: branches: [ main ] +defaults: + run: + shell: bash -eux {0} + jobs: build: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.7', '3.8', '3.9', '3.10'] + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] + fail-fast: false steps: - uses: actions/checkout@v2 @@ -26,12 +31,50 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip check-manifest - pip install pytest pytest-cov - pip install . + pip install pytest-cov + pip install ".[test]" python -m ipykernel.kernelspec --user - name: Test with pytest run: | - pytest --cov jupyter_console - - name: Check Manifest - run: | - check-manifest + pytest --cov jupyter_console || pytest jupyter_console --lf + + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - name: Linting + run: | + pip install check-manifest mypy + check-manifest + mypy jupyter_console + + check_release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + - uses: jupyter-server/jupyter_releaser/.github/actions/check-release@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + check_links: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + - uses: jupyterlab/maintainer-tools/.github/actions/check-links@v1 + + test_minimum_verisons: + name: Test Minimum Versions + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v3 + - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 + with: + dependency_type: minimum + - name: Run the unit tests + run: | + pip install ".[test]" + pytest || pytest --lf diff --git a/docs/conf.py b/docs/conf.py index a61206f..fd908b2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -17,6 +17,7 @@ import os import shlex import shutil +from typing import Dict # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -74,7 +75,7 @@ # built documents. # -version_ns = {} +version_ns: Dict = {} version_py = os.path.join('..', 'jupyter_console', '_version.py') with open(version_py) as f: exec(compile(f.read(), version_py, 'exec'), version_ns) @@ -229,7 +230,7 @@ # -- Options for LaTeX output --------------------------------------------- -latex_elements = { +#latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', @@ -241,7 +242,7 @@ # Latex figure (float) alignment #'figure_align': 'htbp', -} +#} # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, diff --git a/jupyter_console/app.py b/jupyter_console/app.py index fb2518e..b68b4d7 100644 --- a/jupyter_console/app.py +++ b/jupyter_console/app.py @@ -63,7 +63,7 @@ #----------------------------------------------------------------------------- -class ZMQTerminalIPythonApp(JupyterApp, JupyterConsoleApp): +class ZMQTerminalIPythonApp(JupyterApp, JupyterConsoleApp): # type:ignore[misc] name = "jupyter-console" version = __version__ """Start a terminal frontend to the IPython zmq kernel.""" @@ -85,9 +85,9 @@ class ZMQTerminalIPythonApp(JupyterApp, JupyterConsoleApp): """ examples = _examples - classes = [ZMQTerminalInteractiveShell] + JupyterConsoleApp.classes - flags = Dict(flags) - aliases = Dict(aliases) + classes = [ZMQTerminalInteractiveShell] + JupyterConsoleApp.classes # type:ignore[operator] + flags = Dict(flags) # type:ignore[assignment] + aliases = Dict(aliases) # type:ignore[assignment] frontend_aliases = Any(frontend_aliases) frontend_flags = Any(frontend_flags) diff --git a/jupyter_console/ptshell.py b/jupyter_console/ptshell.py index 1dae25b..ef7ba4e 100644 --- a/jupyter_console/ptshell.py +++ b/jupyter_console/ptshell.py @@ -13,6 +13,7 @@ import sys from tempfile import TemporaryDirectory import time +import typing as t from warnings import warn from typing import Dict as DictType, Any as AnyType @@ -30,6 +31,7 @@ Instance, Any, ) +import inspect from traitlets.config import SingletonConfigurable from .completer import ZMQCompleter @@ -76,7 +78,29 @@ from pygments.util import ClassNotFound from pygments.token import Token -from jupyter_client.utils import run_sync +from jupyter_core.utils import run_sync as _run_sync + + +T = t.TypeVar("T") + + +def run_sync(coro: t.Callable[..., t.Union[T, t.Awaitable[T]]]) -> t.Callable[..., T]: + """Wraps coroutine in a function that blocks until it has executed. + + Parameters + ---------- + coro : coroutine-function + The coroutine-function to be executed. + + Returns + ------- + result : + Whatever the coroutine-function returns. + """ + if not inspect.iscoroutinefunction(coro): + return t.cast(t.Callable[..., T], coro) + return _run_sync(coro) + def ask_yes_no(prompt, default=None, interrupt=None): @@ -316,7 +340,7 @@ class ZMQTerminalInteractiveShell(SingletonConfigurable): ), default_value="multicolumn", ).tag(config=True) - + prompt_includes_vi_mode = Bool(True, help="Display the current vi mode (when using vi editing mode)." ).tag(config=True) @@ -374,7 +398,7 @@ def vi_mode(self): and self.prompt_includes_vi_mode): return '['+str(self.pt_cli.app.vi_state.input_mode)[3:6]+'] ' return '' - + def get_prompt_tokens(self, ec=None): if ec is None: ec = self.execution_count diff --git a/jupyter_console/tests/test_console.py b/jupyter_console/tests/test_console.py index fb8cc0d..f1fcf84 100644 --- a/jupyter_console/tests/test_console.py +++ b/jupyter_console/tests/test_console.py @@ -14,8 +14,10 @@ from traitlets.tests.utils import check_help_all_output -@pytest.mark.xfail -@pytest.mark.skipif(sys.platform == "win32", reason="skip on windows") +should_skip = sys.platform == "win32" or sys.version_info < (3,8) or sys.version_info[:2] == (3, 10) + + +@pytest.mark.skipif(should_skip, reason="not supported") def test_console_starts(): """test that `jupyter console` starts a terminal""" p, pexpect, t = start_console() @@ -28,7 +30,8 @@ def test_help_output(): """jupyter console --help-all works""" check_help_all_output('jupyter_console') -@pytest.mark.xfail + +@pytest.mark.skipif(should_skip, reason="not supported") def test_display_text(): "Ensure display protocol plain/text key is supported" # equivalent of: @@ -68,8 +71,8 @@ def start_console(): except IOError: pytest.skip("Couldn't find command %s" % cmd) - # timeout after one minute - t = 60 + # timeout after two minutes + t = 120 p.expect(r"In \[\d+\]", timeout=t) return p, pexpect, t diff --git a/mypy.ini b/mypy.ini index cb3c188..7c1be49 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,4 +1,4 @@ [mypy] -python_version = 3.7 +python_version = 3.8 ignore_missing_imports = True follow_imports = silent diff --git a/setup.py b/setup.py index c449c8a..ccad24c 100644 --- a/setup.py +++ b/setup.py @@ -45,16 +45,21 @@ 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', ], install_requires=[ 'jupyter_client>=7.0.0', + 'jupyter_core>=4.12,!=5.0.*', 'ipython', - 'ipykernel', # bless IPython kernel for now - 'prompt_toolkit>=2.0.0,<3.1.0,!=3.0.0,!=3.0.1', + 'ipykernel>=6.14', # bless IPython kernel for now + 'prompt_toolkit>=3.0.30', 'pygments', + 'pyzmq>=17', + 'traitlets>=5.4' ], extras_require={ - 'test:sys_platform != "win32"': ['pexpect'], + 'test': ['pexpect', 'pytest'], }, python_requires='>=3.7', entry_points={