Skip to content

Commit

Permalink
Update pre-commit and ruff config (#235)
Browse files Browse the repository at this point in the history
* Update pre-commit and ruff config

* Fix top level imports
  • Loading branch information
blink1073 committed Dec 5, 2023
1 parent c93886c commit e2c1b08
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 60 deletions.
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ repos:
- id: trailing-whitespace

- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.27.1
rev: 0.27.2
hooks:
- id: check-github-workflows

Expand Down Expand Up @@ -49,7 +49,7 @@ repos:
args: ["-L", "incase"]

- repo: https://github.com/pre-commit/mirrors-mypy
rev: "v1.6.1"
rev: "v1.7.1"
hooks:
- id: mypy
files: "^terminado"
Expand All @@ -65,7 +65,7 @@ repos:
- id: rst-inline-touching-normal

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.5
rev: v0.1.7
hooks:
- id: ruff
types_or: [python, jupyter]
Expand All @@ -74,7 +74,7 @@ repos:
types_or: [python, jupyter]

- repo: https://github.com/scientific-python/cookie
rev: "2023.10.27"
rev: "2023.11.17"
hooks:
- id: sp-repo-review
additional_dependencies: ["repo-review[cli]"]
9 changes: 5 additions & 4 deletions demos/common_demo_stuff.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import os.path
import webbrowser
from pathlib import Path

import tornado.ioloop

import terminado

STATIC_DIR = os.path.join(os.path.dirname(terminado.__file__), "_static")
TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), "templates")
HERE = Path(terminado.__file__).parent
STATIC_DIR = HERE / "_static"
TEMPLATE_DIR = HERE / "templates"


def run_and_show_browser(url, term_manager):
Expand All @@ -15,7 +16,7 @@ def run_and_show_browser(url, term_manager):
try:
loop.start()
except KeyboardInterrupt:
print(" Shutting down on SIGINT")
print(" Shutting down on SIGINT") # noqa: T201
finally:
term_manager.shutdown()
loop.close()
18 changes: 10 additions & 8 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
# All configuration values have a default; values that are commented out
# serve to show the default.

import os.path as osp
import shutil
import sys
from pathlib import Path

HERE = osp.dirname(__file__)
sys.path.insert(0, osp.join(HERE, ".."))
HERE = Path(__file__).parent.resolve()
sys.path.insert(0, HERE.parent)

# 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
Expand All @@ -42,16 +42,18 @@

# General information about the project.
project = "Terminado"
copyright = "2014, Thomas Kluyver" # noqa
copyright = "2014, Thomas Kluyver"

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# Get information from _version.py and use it to generate version and release
_version_py = osp.join(HERE, "../terminado/_version.py")
_version_py = HERE / "../terminado/_version.py"
version_ns: dict = {}
exec(compile(open(_version_py).read(), _version_py, "exec"), version_ns) # noqa

with _version_py.open() as fid:
exec(compile(fid.read(), _version_py, "exec"), version_ns) # noqa: S102
# The short X.Y version.
version = "{}.{}".format(*tuple(version_ns["__version__"].split(".")[:2]))
# The full version, including alpha/beta/rc tags.
Expand Down Expand Up @@ -259,5 +261,5 @@


def setup(app):
dest = osp.join(HERE, "changelog.md")
shutil.copy(osp.join(HERE, "..", "CHANGELOG.md"), dest)
dest = HERE / "changelog.md"
shutil.copy(HERE / ".." / "CHANGELOG.md", dest)
46 changes: 26 additions & 20 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -101,32 +101,38 @@ source = ["terminado"]
files = "terminado"
python_version = "3.8"
strict = true
show_error_codes = true
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
warn_unreachable = true

[tool.ruff]
line-length = 100

[tool.ruff.lint]
select = [
"A", "B", "C", "DTZ", "E", "EM", "F", "FBT", "I", "ICN", "ISC", "N",
"PLC", "PLE", "PLR", "PLW", "RUF", "S", "SIM", "T", "TID", "UP",
"W", "YTT",
extend-select = [
"B", # flake8-bugbear
"I", # isort
"C4", # flake8-comprehensions
"EM", # flake8-errmsg
"ICN", # flake8-import-conventions
"G", # flake8-logging-format
"PGH", # pygrep-hooks
"PIE", # flake8-pie
"PL", # pylint
"PTH", # flake8-use-pathlib
"PT", # flake8-pytest-style
"RET", # flake8-return
"RUF", # Ruff-specific
"SIM", # flake8-simplify
"T20", # flake8-print
"UP", # pyupgrade
"YTT", # flake8-2020
"EXE", # flake8-executable
"PYI", # flake8-pyi
"S", # flake8-bandit
]
ignore = [
# FBT001 Boolean positional arg in function definition
"FBT001", "FBT002", "FBT003",
# E501 Line too long (158 > 100 characters)
"E501",
# SIM105 Use `contextlib.suppress(...)`
"SIM105",
# T201 `print` found
"T201",
# N802 Function name `CreateWellKnownSid` should be lowercase
"N802", "N803",
# Rules that conflict with the formatter.
"ISC001", "W191",
"PLR", # Design related pylint codes
"S101", # Use of `assert` detected
]
unfixable = [
# Don't touch print statements
Expand All @@ -143,8 +149,8 @@ unfixable = [
# T201 `print` found
# B007 Loop control variable `i` not used within the loop body.
# N802 Function name `assertIn` should be lowercase
# S101 Use of `assert` detected
"tests/*" = ["B011", "F841", "C408", "E402", "T201", "B007", "N802", "S101"]
# PT009 Use a regular `assert` instead of unittest-style
"tests/*" = ["B011", "F841", "C408", "E402", "T201", "B007", "N802", "PT009"]

[tool.interrogate]
ignore-init-module=true
Expand All @@ -157,4 +163,4 @@ fail-under=100
exclude = ["demos", "doc", "tests"]

[tool.repo-review]
ignore = ["PY007", "GH102", "PC110"]
ignore = [ "GH102"]
14 changes: 8 additions & 6 deletions terminado/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
# Copyright (c) 2014, Ramalingam Saravanan <sarava@sarava.net>
# Distributed under the terms of the Simplified BSD License.

from ._version import __version__ # noqa
from .management import NamedTermManager # noqa
from .management import SingleTermManager # noqa
from .management import TermManagerBase # noqa
from .management import UniqueTermManager # noqa
from .websocket import TermSocket # noqa
from ._version import __version__ # noqa: F401
from .management import (
NamedTermManager, # noqa: F401
SingleTermManager, # noqa: F401
TermManagerBase, # noqa: F401
UniqueTermManager, # noqa: F401
)
from .websocket import TermSocket # noqa: F401
21 changes: 10 additions & 11 deletions terminado/management.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def resize_to_smallest(self) -> None:
if cols is not None and cols < mincols:
mincols = cols

if minrows == 10001 or mincols == 10001: # noqa
if minrows == 10001 or mincols == 10001:
return

rows, cols = self.ptyproc.getwinsize()
Expand All @@ -93,6 +93,7 @@ def killpg(self, sig: int = signal.SIGTERM) -> Any:
return self.ptyproc.kill(sig)
pgid = os.getpgid(self.ptyproc.pid)
os.killpg(pgid, sig)
return None

async def terminate(self, force: bool = False) -> bool:
"""This forces a child process to terminate. It starts nicely with
Expand Down Expand Up @@ -149,16 +150,15 @@ def _poll(fd: int, timeout: float = 0.1) -> list[tuple[int, int]]:
fd, select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR
) # read-only
return poller.poll(timeout * 1000) # milliseconds
else:
# poll() not supported on Windows
r, _, _ = select.select([fd], [], [], timeout)
return r
# poll() not supported on Windows
r, _, _ = select.select([fd], [], [], timeout)
return r


class TermManagerBase:
"""Base class for a terminal manager."""

def __init__( # noqa
def __init__(
self,
shell_command: str,
server_url: str = "",
Expand Down Expand Up @@ -254,7 +254,7 @@ def pty_read(self, fd: int, events: Any = None) -> None:
"""Called by the event loop when there is pty data ready to read."""
# prevent blocking on fd
if not _poll(fd, timeout=0.1): # 100ms
self.log.debug(f"Spurious pty_read() on fd {fd}")
self.log.debug("Spurious pty_read() on fd %s", fd)
return
ptywclients = self.ptys_by_fd[fd]
try:
Expand Down Expand Up @@ -282,7 +282,6 @@ def get_terminal(self, url_component: Any = None) -> PtyWithClients:

def client_disconnected(self, websocket: Any) -> None:
"""Override this to e.g. kill terminals on client disconnection."""
pass

async def shutdown(self) -> None:
"""Shutdown the manager."""
Expand Down Expand Up @@ -321,7 +320,7 @@ async def kill_all(self) -> None:
self.terminal = None


class MaxTerminalsReached(Exception): # noqa
class MaxTerminalsReached(Exception):
"""An error raised when we exceed the max number of terminals."""

def __init__(self, max_terminals: int) -> None:
Expand Down Expand Up @@ -374,7 +373,7 @@ def __init__(self, max_terminals: Any = None, **kwargs: Any) -> None:

def get_terminal(self, term_name: str) -> PtyWithClients: # type:ignore[override]
"""Get or create a terminal by name."""
assert term_name is not None # noqa
assert term_name is not None

if term_name in self.terminals:
return self.terminals[term_name]
Expand Down Expand Up @@ -424,7 +423,7 @@ def on_eof(self, ptywclients: PtyWithClients) -> None:
super().on_eof(ptywclients)
name = ptywclients.term_name
self.log.info("Terminal %s closed", name)
assert name is not None # noqa: S101
assert name is not None
self.terminals.pop(name, None)

async def kill_all(self) -> None:
Expand Down
6 changes: 3 additions & 3 deletions terminado/uimodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# Distributed under the terms of the Simplified BSD License.
from __future__ import annotations

import os.path
from pathlib import Path

import tornado.web

Expand All @@ -31,6 +31,6 @@ def javascript_files(self) -> list[str]:

def embedded_javascript(self) -> str:
"""Get the embedded JS content as a string."""
file = os.path.join(os.path.dirname(__file__), "uimod_embed.js")
with open(file) as f:
file = Path(__file__).parent / "uimod_embed.js"
with file.open() as f:
return f.read()
6 changes: 3 additions & 3 deletions terminado/websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ def initialize(self, term_manager: TermManagerBase) -> None:
def origin_check(self, origin: str | None = None) -> bool:
"""Deprecated: backward-compat for terminado <= 0.5."""
origin = origin or self.request.headers.get("Origin", "")
assert origin is not None # noqa: S101
assert origin is not None
return self.check_origin(origin)

def open(self, url_component: Any = None) -> None: # type:ignore[override] # noqa
def open(self, url_component: Any = None) -> None: # type:ignore[override]
"""Websocket connection opened.
Call our terminal manager to get a terminal, and connect to it as a
Expand Down Expand Up @@ -98,7 +98,7 @@ def on_message(self, message: str) -> None: # type:ignore[misc]
# logging.info("TermSocket.on_message: %s - (%s) %s", self.term_name, type(message), len(message) if isinstance(message, bytes) else message[:250])
command = json.loads(message)
msg_type = command[0]
assert self.terminal is not None # noqa
assert self.terminal is not None
if msg_type == "stdin":
yield self.stdin_to_ptyproc(command[1])
if self._enable_output_logging:
Expand Down
8 changes: 7 additions & 1 deletion tests/basic_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ async def test_namespace(self):
assert killed
assert not terminal.ptyproc.isalive()
assert terminal.ptyproc.closed
[tm.close() for tm in tms]

@tornado.testing.gen_test
@pytest.mark.skipif("linux" not in platform, reason="It only works on Linux")
Expand All @@ -260,6 +261,8 @@ async def test_max_terminals(self):
tm = await self.get_term_client(urls[MAX_TERMS])
msg = await tm.read_msg()
self.assertEqual(msg, None) # Connection closed
tm.close()
[tm.close() for tm in tms]


class SingleTermTests(TermTestCase):
Expand All @@ -273,6 +276,7 @@ async def test_single_process(self):
killed = await self.single_tm.terminal.terminate(True)
assert killed
assert self.single_tm.terminal.ptyproc.closed
[tm.close() for tm in tms]


class UniqueTermTests(TermTestCase):
Expand All @@ -281,6 +285,7 @@ async def test_unique_processes(self):
tms = await self.get_term_clients(["/unique", "/unique"])
pids = await self.get_pids(tms)
self.assertNotEqual(pids[0], pids[1])
[tm.close() for tm in tms]

@tornado.testing.gen_test
@pytest.mark.skipif("linux" not in platform, reason="It only works on Linux")
Expand All @@ -303,6 +308,7 @@ async def test_max_terminals(self):
tm = await self.get_term_client("/unique")
msg = await tm.read_msg()
self.assertEqual(msg[0], "setup")
tm.close()

@tornado.testing.gen_test
@pytest.mark.timeout(timeout=ASYNC_TEST_TIMEOUT, method="thread")
Expand All @@ -324,7 +330,7 @@ async def test_large_io_doesnt_hang(self):
bytes_discarded, other = await tm.discard_stdout()
# Echo won't actually output anything on Windows.
if "win" not in platform:
assert bytes_discarded > 10000 # noqa
assert bytes_discarded > 10000
assert other == []
tm.close()

Expand Down

0 comments on commit e2c1b08

Please sign in to comment.