From fbddbc6c6a80a1a16007d31505f6b19826d84e4f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 28 Aug 2022 12:59:52 -0500 Subject: [PATCH 0001/1073] chore: Format --- tests/test_pane.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/test_pane.py b/tests/test_pane.py index c8697c5d6..ef33cca48 100644 --- a/tests/test_pane.py +++ b/tests/test_pane.py @@ -69,18 +69,16 @@ def test_capture_pane(session: Session) -> None: session.new_window( attach=True, window_name="capture_pane", - window_shell='env -i PS1="$ " /usr/bin/env bash --norc --noprofile' + window_shell='env -i PS1="$ " /usr/bin/env bash --norc --noprofile', ) pane = session.attached_window.attached_pane assert pane is not None pane_contents = "\n".join(pane.capture_pane()) - assert pane_contents == '$' + assert pane_contents == "$" pane.send_keys( - r'printf "\n%s\n" "Hello World !"', - literal=True, - suppress_history=False + r'printf "\n%s\n" "Hello World !"', literal=True, suppress_history=False ) pane_contents = "\n".join(pane.capture_pane()) assert pane_contents == r'$ printf "\n%s\n" "Hello World !"{}'.format( - '\n\nHello World !\n$' + "\n\nHello World !\n$" ) From 0b7a11ec2692be97d90e9567f036466d081ee77e Mon Sep 17 00:00:00 2001 From: rockandska Date: Sun, 28 Aug 2022 20:52:56 +0200 Subject: [PATCH 0002/1073] fix(tmux_cmd): use shutil.which and only PATH to discover tmux --- libtmux/common.py | 85 ++------------------------------------------ libtmux/conftest.py | 4 +-- tests/test_common.py | 17 ++++----- 3 files changed, 11 insertions(+), 95 deletions(-) diff --git a/libtmux/common.py b/libtmux/common.py index 3c4337caa..12a4caeee 100644 --- a/libtmux/common.py +++ b/libtmux/common.py @@ -8,6 +8,7 @@ import logging import os import re +import shutil import subprocess import sys import typing as t @@ -203,14 +204,6 @@ class tmux_cmd: """ :term:`tmux(1)` command via :py:mod:`subprocess`. - Parameters - ---------- - tmux_search_paths : list, optional - Default PATHs to search tmux for, defaults to ``default_paths`` used - in :func:`which`. - append_env_path : bool - Append environment PATHs to tmux search paths. True by default. - Examples -------- @@ -239,14 +232,7 @@ class tmux_cmd: """ def __init__(self, *args: t.Any, **kwargs: t.Any) -> None: - tmux_bin = which( - "tmux", - default_paths=kwargs.get( - "tmux_search_paths", - ["/bin", "/sbin", "/usr/bin", "/usr/sbin", "/usr/local/bin"], - ), - append_env_path=kwargs.get("append_env_path", True), - ) + tmux_bin = shutil.which("tmux") if not tmux_bin: raise (exc.TmuxCommandNotFound) @@ -461,73 +447,6 @@ def get_by_id(self, id: str) -> Optional[O]: return None -def which( - exe: str, - default_paths: t.List[str] = [ - "/bin", - "/sbin", - "/usr/bin", - "/usr/sbin", - "/usr/local/bin", - ], - append_env_path: bool = True, -) -> t.Optional[str]: - """ - Return path of bin. Python clone of /usr/bin/which. - - Parameters - ---------- - exe : str - Application to search PATHs for. - default_paths : list - Paths to check inside of - append_env_path : bool, optional - Append list of directories to check in from PATH environment variable. - Default True. Setting False only for testing / diagnosing. - - Returns - ------- - str - path of application, if found in paths. - - Notes - ----- - from salt.util - https://www.github.com/saltstack/salt - license apache - """ - - def _is_executable_file_or_link(exe: str) -> bool: - # check for os.X_OK doesn't suffice because directory may executable - return os.access(exe, os.X_OK) and (os.path.isfile(exe) or os.path.islink(exe)) - - if _is_executable_file_or_link(exe): - # executable in cwd or fullpath - return exe - - # Enhance POSIX path for the reliability at some environments, when - # $PATH is changing. This also keeps order, where 'first came, first - # win' for cases to find optional alternatives - if append_env_path: - search_path = ( - os.environ.get("PATH") and os.environ["PATH"].split(os.pathsep) or list() - ) - else: - search_path = [] - - for default_path in default_paths: - if default_path not in search_path: - search_path.append(default_path) - for path in search_path: - full_path = os.path.join(path, exe) - if _is_executable_file_or_link(full_path): - return full_path - logger.info( - "'{}' could not be found in the following search path: " - "'{}'".format(exe, search_path) - ) - - return None - - def get_version() -> LooseVersion: """ Return tmux version. diff --git a/libtmux/conftest.py b/libtmux/conftest.py index 324fd2c6a..8f82f69c6 100644 --- a/libtmux/conftest.py +++ b/libtmux/conftest.py @@ -1,6 +1,7 @@ import logging import os import typing as t +import shutil import pytest @@ -9,7 +10,6 @@ from _pytest.monkeypatch import MonkeyPatch from libtmux import exc -from libtmux.common import which from libtmux.server import Server from libtmux.test import TEST_SESSION_PREFIX, get_test_session_name, namer @@ -109,7 +109,7 @@ def add_doctest_fixtures( request: SubRequest, doctest_namespace: t.Dict[str, t.Any], ) -> None: - if isinstance(request._pyfuncitem, DoctestItem) and which("tmux"): + if isinstance(request._pyfuncitem, DoctestItem) and shutil.which("tmux"): doctest_namespace["server"] = request.getfixturevalue("server") session: "Session" = request.getfixturevalue("session") doctest_namespace["session"] = session diff --git a/tests/test_common.py b/tests/test_common.py index f3d4920ea..34e3335b7 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -2,6 +2,7 @@ import re import sys +import os import typing as t from distutils.version import LooseVersion from typing import Optional @@ -23,8 +24,7 @@ has_minimum_version, has_version, session_check_name, - tmux_cmd, - which, + tmux_cmd ) from libtmux.exc import BadSessionName, LibTmuxException, TmuxCommandNotFound from libtmux.session import Session @@ -174,16 +174,13 @@ def test_has_lte_version() -> None: assert not has_lte_version("1.7b") -def test_which_no_bin_found() -> None: - assert which("top") - assert which("top", default_paths=[]) - assert not which("top", default_paths=[], append_env_path=False) - assert not which("top", default_paths=["/"], append_env_path=False) - - def test_tmux_cmd_raises_on_not_found() -> None: + previous_path = os.environ["PATH"] + os.environ["PATH"] = "" with pytest.raises(TmuxCommandNotFound): - tmux_cmd("-V", tmux_search_paths=[], append_env_path=False) + tmux_cmd("-V") + + os.environ["PATH"] = previous_path tmux_cmd("-V") From 9b0f340f5506708aa45a0faec47555dbf5a46191 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 28 Aug 2022 14:27:17 -0500 Subject: [PATCH 0003/1073] test(test_tmux_cmd_raises_on_not_found): Use monkeypatch --- tests/test_common.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tests/test_common.py b/tests/test_common.py index 34e3335b7..14c5c39a5 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -2,7 +2,6 @@ import re import sys -import os import typing as t from distutils.version import LooseVersion from typing import Optional @@ -24,7 +23,7 @@ has_minimum_version, has_version, session_check_name, - tmux_cmd + tmux_cmd, ) from libtmux.exc import BadSessionName, LibTmuxException, TmuxCommandNotFound from libtmux.session import Session @@ -174,16 +173,11 @@ def test_has_lte_version() -> None: assert not has_lte_version("1.7b") -def test_tmux_cmd_raises_on_not_found() -> None: - previous_path = os.environ["PATH"] - os.environ["PATH"] = "" +def test_tmux_cmd_raises_on_not_found(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setenv("PATH", "") with pytest.raises(TmuxCommandNotFound): tmux_cmd("-V") - os.environ["PATH"] = previous_path - - tmux_cmd("-V") - def test_tmux_cmd_unicode(session: Session) -> None: session.cmd("new-window", "-t", 3, "-n", "юникод", "-F", "Ελληνικά") From c9da2e41b4f56a8f484d81b914d103bf02673147 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 28 Aug 2022 14:32:44 -0500 Subject: [PATCH 0004/1073] docs(CHANGES): Note deprecation of which() --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index b8f51b2c2..8cb7b271c 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,8 @@ $ pip install --user --upgrade --pre libtmux ### Breaking changes +- Remove `common.which()` in favor of {func}`shutil.which`, Credit: + @rocksandska, via #407 - Fixes #402: {func}`common.tmux_cmd` will only strip _trailing_ empty lines. Before this change, all empty lines were filtered out. This will lead to a more accurate behavior when using {meth}`Pane.capture_pane`. Credit: @rockandska, via #405. From 7643b43e555390fd51255193d6e28ac00c952db9 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 28 Aug 2022 15:23:28 -0500 Subject: [PATCH 0005/1073] doc(get_version): Note which() update --- libtmux/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libtmux/common.py b/libtmux/common.py index 12a4caeee..b3db8344b 100644 --- a/libtmux/common.py +++ b/libtmux/common.py @@ -460,7 +460,7 @@ def get_version() -> LooseVersion: Returns ------- :class:`distutils.version.LooseVersion` - tmux version according to :func:`libtmux.common.which`'s tmux + tmux version according to :func:`shtuil.which`'s tmux """ proc = tmux_cmd("-V") if proc.stderr: From 4bfc08ab7a8370847e434b6001ef78094c3ccdcd Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 28 Aug 2022 16:18:32 -0500 Subject: [PATCH 0006/1073] Tag v0.15.0a1, deprecate which() in favor of shtuil.which() --- libtmux/__about__.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libtmux/__about__.py b/libtmux/__about__.py index bc4e896bd..8661fc83d 100644 --- a/libtmux/__about__.py +++ b/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.0a0" +__version__ = "0.15.0a1" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" diff --git a/pyproject.toml b/pyproject.toml index ad6445334..1b8485d31 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.0a0" +version = "0.15.0a1" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] From b74e8bf41251156ce80d2acb2541a4ca93914979 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 3 Sep 2022 09:06:25 -0500 Subject: [PATCH 0007/1073] build(deps): Update black, pytest, pathspec --- poetry.lock | 74 ++++++++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 43 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2a09163fc..19bc66665 100644 --- a/poetry.lock +++ b/poetry.lock @@ -20,14 +20,6 @@ typed-ast = {version = ">=1.4.0,<2.0", markers = "implementation_name == \"cpyth typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} wrapt = ">=1.11,<2" -[[package]] -name = "atomicwrites" -version = "1.4.1" -description = "Atomic file writes." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - [[package]] name = "attrs" version = "22.1.0" @@ -70,7 +62,7 @@ lxml = ["lxml"] [[package]] name = "black" -version = "22.6.0" +version = "22.8.0" description = "The uncompromising code formatter." category = "dev" optional = false @@ -406,11 +398,11 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" [[package]] name = "pathspec" -version = "0.9.0" +version = "0.10.1" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.7" [[package]] name = "platformdirs" @@ -487,14 +479,13 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pytest" -version = "7.1.2" +version = "7.1.3" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.7" [package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} @@ -962,9 +953,6 @@ astroid = [ {file = "astroid-2.11.7-py3-none-any.whl", hash = "sha256:86b0a340a512c65abf4368b80252754cda17c02cdbbd3f587dddf98112233e7b"}, {file = "astroid-2.11.7.tar.gz", hash = "sha256:bb24615c77f4837c707669d16907331374ae8a964650a66999da3f5ca68dc946"}, ] -atomicwrites = [ - {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"}, -] attrs = [ {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, @@ -978,29 +966,29 @@ beautifulsoup4 = [ {file = "beautifulsoup4-4.11.1.tar.gz", hash = "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"}, ] black = [ - {file = "black-22.6.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f586c26118bc6e714ec58c09df0157fe2d9ee195c764f630eb0d8e7ccce72e69"}, - {file = "black-22.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b270a168d69edb8b7ed32c193ef10fd27844e5c60852039599f9184460ce0807"}, - {file = "black-22.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6797f58943fceb1c461fb572edbe828d811e719c24e03375fd25170ada53825e"}, - {file = "black-22.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c85928b9d5f83b23cee7d0efcb310172412fbf7cb9d9ce963bd67fd141781def"}, - {file = "black-22.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:f6fe02afde060bbeef044af7996f335fbe90b039ccf3f5eb8f16df8b20f77666"}, - {file = "black-22.6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cfaf3895a9634e882bf9d2363fed5af8888802d670f58b279b0bece00e9a872d"}, - {file = "black-22.6.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94783f636bca89f11eb5d50437e8e17fbc6a929a628d82304c80fa9cd945f256"}, - {file = "black-22.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2ea29072e954a4d55a2ff58971b83365eba5d3d357352a07a7a4df0d95f51c78"}, - {file = "black-22.6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e439798f819d49ba1c0bd9664427a05aab79bfba777a6db94fd4e56fae0cb849"}, - {file = "black-22.6.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:187d96c5e713f441a5829e77120c269b6514418f4513a390b0499b0987f2ff1c"}, - {file = "black-22.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:074458dc2f6e0d3dab7928d4417bb6957bb834434516f21514138437accdbe90"}, - {file = "black-22.6.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a218d7e5856f91d20f04e931b6f16d15356db1c846ee55f01bac297a705ca24f"}, - {file = "black-22.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:568ac3c465b1c8b34b61cd7a4e349e93f91abf0f9371eda1cf87194663ab684e"}, - {file = "black-22.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6c1734ab264b8f7929cef8ae5f900b85d579e6cbfde09d7387da8f04771b51c6"}, - {file = "black-22.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9a3ac16efe9ec7d7381ddebcc022119794872abce99475345c5a61aa18c45ad"}, - {file = "black-22.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:b9fd45787ba8aa3f5e0a0a98920c1012c884622c6c920dbe98dbd05bc7c70fbf"}, - {file = "black-22.6.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7ba9be198ecca5031cd78745780d65a3f75a34b2ff9be5837045dce55db83d1c"}, - {file = "black-22.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3db5b6409b96d9bd543323b23ef32a1a2b06416d525d27e0f67e74f1446c8f2"}, - {file = "black-22.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:560558527e52ce8afba936fcce93a7411ab40c7d5fe8c2463e279e843c0328ee"}, - {file = "black-22.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b154e6bbde1e79ea3260c4b40c0b7b3109ffcdf7bc4ebf8859169a6af72cd70b"}, - {file = "black-22.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:4af5bc0e1f96be5ae9bd7aaec219c901a94d6caa2484c21983d043371c733fc4"}, - {file = "black-22.6.0-py3-none-any.whl", hash = "sha256:ac609cf8ef5e7115ddd07d85d988d074ed00e10fbc3445aee393e70164a2219c"}, - {file = "black-22.6.0.tar.gz", hash = "sha256:6c6d39e28aed379aec40da1c65434c77d75e65bb59a1e1c283de545fb4e7c6c9"}, + {file = "black-22.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ce957f1d6b78a8a231b18e0dd2d94a33d2ba738cd88a7fe64f53f659eea49fdd"}, + {file = "black-22.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5107ea36b2b61917956d018bd25129baf9ad1125e39324a9b18248d362156a27"}, + {file = "black-22.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8166b7bfe5dcb56d325385bd1d1e0f635f24aae14b3ae437102dedc0c186747"}, + {file = "black-22.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd82842bb272297503cbec1a2600b6bfb338dae017186f8f215c8958f8acf869"}, + {file = "black-22.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d839150f61d09e7217f52917259831fe2b689f5c8e5e32611736351b89bb2a90"}, + {file = "black-22.8.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a05da0430bd5ced89176db098567973be52ce175a55677436a271102d7eaa3fe"}, + {file = "black-22.8.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a098a69a02596e1f2a58a2a1c8d5a05d5a74461af552b371e82f9fa4ada8342"}, + {file = "black-22.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5594efbdc35426e35a7defa1ea1a1cb97c7dbd34c0e49af7fb593a36bd45edab"}, + {file = "black-22.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a983526af1bea1e4cf6768e649990f28ee4f4137266921c2c3cee8116ae42ec3"}, + {file = "black-22.8.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b2c25f8dea5e8444bdc6788a2f543e1fb01494e144480bc17f806178378005e"}, + {file = "black-22.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:78dd85caaab7c3153054756b9fe8c611efa63d9e7aecfa33e533060cb14b6d16"}, + {file = "black-22.8.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:cea1b2542d4e2c02c332e83150e41e3ca80dc0fb8de20df3c5e98e242156222c"}, + {file = "black-22.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5b879eb439094751185d1cfdca43023bc6786bd3c60372462b6f051efa6281a5"}, + {file = "black-22.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0a12e4e1353819af41df998b02c6742643cfef58282915f781d0e4dd7a200411"}, + {file = "black-22.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3a73f66b6d5ba7288cd5d6dad9b4c9b43f4e8a4b789a94bf5abfb878c663eb3"}, + {file = "black-22.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:e981e20ec152dfb3e77418fb616077937378b322d7b26aa1ff87717fb18b4875"}, + {file = "black-22.8.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8ce13ffed7e66dda0da3e0b2eb1bdfc83f5812f66e09aca2b0978593ed636b6c"}, + {file = "black-22.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:32a4b17f644fc288c6ee2bafdf5e3b045f4eff84693ac069d87b1a347d861497"}, + {file = "black-22.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ad827325a3a634bae88ae7747db1a395d5ee02cf05d9aa7a9bd77dfb10e940c"}, + {file = "black-22.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53198e28a1fb865e9fe97f88220da2e44df6da82b18833b588b1883b16bb5d41"}, + {file = "black-22.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:bc4d4123830a2d190e9cc42a2e43570f82ace35c3aeb26a512a2102bce5af7ec"}, + {file = "black-22.8.0-py3-none-any.whl", hash = "sha256:d2c21d439b2baf7aa80d6dd4e3659259be64c6f49dfd0f32091063db0e006db4"}, + {file = "black-22.8.0.tar.gz", hash = "sha256:792f7eb540ba9a17e8656538701d3eb1afcb134e3b45b71f20b25c77a8db7e6e"}, ] certifi = [ {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"}, @@ -1249,8 +1237,8 @@ packaging = [ {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, ] pathspec = [ - {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, - {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, + {file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"}, + {file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"}, ] platformdirs = [ {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, @@ -1281,8 +1269,8 @@ pyparsing = [ {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, ] pytest = [ - {file = "pytest-7.1.2-py3-none-any.whl", hash = "sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c"}, - {file = "pytest-7.1.2.tar.gz", hash = "sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"}, + {file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"}, + {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, ] pytest-cov = [ {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, From 8161c6879284f6ec97e901dc37a3f7466c9b8ad0 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 3 Sep 2022 09:06:36 -0500 Subject: [PATCH 0008/1073] chore(conftest): Sort import --- libtmux/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libtmux/conftest.py b/libtmux/conftest.py index 8f82f69c6..280d58253 100644 --- a/libtmux/conftest.py +++ b/libtmux/conftest.py @@ -1,7 +1,7 @@ import logging import os -import typing as t import shutil +import typing as t import pytest From 6de8dc874795e5e204d9003e8232237c3e030f1f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 3 Sep 2022 22:38:25 -0500 Subject: [PATCH 0009/1073] build(deps): Add flake8-bugbear See also: https://github.com/PyCQA/flake8-bugbear --- poetry.lock | 21 ++++++++++++++++++++- pyproject.toml | 3 ++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 19bc66665..63a48eca6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -170,6 +170,21 @@ mccabe = ">=0.6.0,<0.7.0" pycodestyle = ">=2.7.0,<2.8.0" pyflakes = ">=2.3.0,<2.4.0" +[[package]] +name = "flake8-bugbear" +version = "22.8.23" +description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +attrs = ">=19.2.0" +flake8 = ">=3.0.0" + +[package.extras] +dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit"] + [[package]] name = "furo" version = "2022.6.21" @@ -942,7 +957,7 @@ test = [] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "efda75071ab0c8bf180900071d009becabfc0ef718bde0171d664495ae2a37fb" +content-hash = "4dd682d8c18a0ccbd336ee7d54331a7cc485ca8b8afc4fdd6c5288fca16d5bbd" [metadata.files] alabaster = [ @@ -1071,6 +1086,10 @@ flake8 = [ {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, ] +flake8-bugbear = [ + {file = "flake8-bugbear-22.8.23.tar.gz", hash = "sha256:de0717d11124a082118dd08387b34fd86b2721642ec2d8e92be66cfa5ea7c445"}, + {file = "flake8_bugbear-22.8.23-py3-none-any.whl", hash = "sha256:1b0ebe0873d1cd55bf9f1588bfcb930db339018ef44a3981a26532daa9fd14a8"}, +] furo = [ {file = "furo-2022.6.21-py3-none-any.whl", hash = "sha256:061b68e323345e27fcba024cf33a1e77f3dfd8d9987410be822749a706e2add6"}, {file = "furo-2022.6.21.tar.gz", hash = "sha256:9aa983b7488a4601d13113884bfb7254502c8729942e073a0acb87a5512af223"}, diff --git a/pyproject.toml b/pyproject.toml index 1b8485d31..1560926c6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -78,6 +78,7 @@ isort = "*" ### Lint ### flake8 = "*" +flake8-bugbear = "^22.8.23" mypy = "*" [tool.poetry.extras] @@ -98,7 +99,7 @@ docs = [ test = ["pytest", "pytest-rerunfailures", "pytest-mock", "pytest-watcher"] coverage = ["codecov", "coverage", "pytest-cov"] format = ["black", "isort"] -lint = ["flake8", "mypy"] +lint = ["flake8", "flake8-bugbear", "mypy"] [tool.mypy] strict = true From 4413bebdaae98ef063c9daf92cdddb96139c81b1 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 4 Sep 2022 07:47:47 -0500 Subject: [PATCH 0010/1073] docs(CHANGES): Note addition of flake8-bugbear --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index 8cb7b271c..749319aec 100644 --- a/CHANGES +++ b/CHANGES @@ -20,6 +20,10 @@ $ pip install --user --upgrade --pre libtmux all empty lines were filtered out. This will lead to a more accurate behavior when using {meth}`Pane.capture_pane`. Credit: @rockandska, via #405. +### Development + +- Add [flake8-bugbear](https://github.com/PyCQA/flake8-bugbear) (#408) + ### Documentation - Move to sphinx-autoissues, #406 From f34682dfbf09755ba48972d6e834b1b1f15c2fc4 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 5 Sep 2022 08:40:40 -0500 Subject: [PATCH 0011/1073] build(deps): Add flake8-comprehensions See also: https://github.com/adamchainz/flake8-comprehensions --- poetry.lock | 18 +++++++++++++++++- pyproject.toml | 3 ++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 63a48eca6..239a117e6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -185,6 +185,18 @@ flake8 = ">=3.0.0" [package.extras] dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit"] +[[package]] +name = "flake8-comprehensions" +version = "3.10.0" +description = "A flake8 plugin to help you write better list/set/dict comprehensions." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +flake8 = ">=3.0,<3.2.0 || >3.2.0" +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} + [[package]] name = "furo" version = "2022.6.21" @@ -957,7 +969,7 @@ test = [] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "4dd682d8c18a0ccbd336ee7d54331a7cc485ca8b8afc4fdd6c5288fca16d5bbd" +content-hash = "01a21031768112b50fddb746eb5dd982b5aa456b8e5f88b6803640e17fb6ce4a" [metadata.files] alabaster = [ @@ -1090,6 +1102,10 @@ flake8-bugbear = [ {file = "flake8-bugbear-22.8.23.tar.gz", hash = "sha256:de0717d11124a082118dd08387b34fd86b2721642ec2d8e92be66cfa5ea7c445"}, {file = "flake8_bugbear-22.8.23-py3-none-any.whl", hash = "sha256:1b0ebe0873d1cd55bf9f1588bfcb930db339018ef44a3981a26532daa9fd14a8"}, ] +flake8-comprehensions = [ + {file = "flake8-comprehensions-3.10.0.tar.gz", hash = "sha256:181158f7e7aa26a63a0a38e6017cef28c6adee71278ce56ce11f6ec9c4905058"}, + {file = "flake8_comprehensions-3.10.0-py3-none-any.whl", hash = "sha256:dad454fd3d525039121e98fa1dd90c46bc138708196a4ebbc949ad3c859adedb"}, +] furo = [ {file = "furo-2022.6.21-py3-none-any.whl", hash = "sha256:061b68e323345e27fcba024cf33a1e77f3dfd8d9987410be822749a706e2add6"}, {file = "furo-2022.6.21.tar.gz", hash = "sha256:9aa983b7488a4601d13113884bfb7254502c8729942e073a0acb87a5512af223"}, diff --git a/pyproject.toml b/pyproject.toml index 1560926c6..a4d41744f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -79,6 +79,7 @@ isort = "*" ### Lint ### flake8 = "*" flake8-bugbear = "^22.8.23" +flake8-comprehensions = "*" mypy = "*" [tool.poetry.extras] @@ -99,7 +100,7 @@ docs = [ test = ["pytest", "pytest-rerunfailures", "pytest-mock", "pytest-watcher"] coverage = ["codecov", "coverage", "pytest-cov"] format = ["black", "isort"] -lint = ["flake8", "flake8-bugbear", "mypy"] +lint = ["flake8", "flake8-bugbear", "flake8-comprehensions", "mypy"] [tool.mypy] strict = true From f712acaaad0fa68752ceccb6721d4f6a29b95ed7 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 5 Sep 2022 09:38:11 -0500 Subject: [PATCH 0012/1073] docs(CHANGES): Note flake8-comprehensions --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 749319aec..f8623b128 100644 --- a/CHANGES +++ b/CHANGES @@ -23,6 +23,7 @@ $ pip install --user --upgrade --pre libtmux ### Development - Add [flake8-bugbear](https://github.com/PyCQA/flake8-bugbear) (#408) +- Add [flake8-comprehensions](https://github.com/adamchainz/flake8-comprehensions) (#409) ### Documentation From f7151c850ff7d7e933e2d942045d1af8b78c4d42 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 04:56:15 -0500 Subject: [PATCH 0013/1073] build(deps): Update certifi package --- poetry.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index 239a117e6..7caf59241 100644 --- a/poetry.lock +++ b/poetry.lock @@ -85,7 +85,7 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2022.6.15" +version = "2022.6.15.1" description = "Python package for providing Mozilla's CA Bundle." category = "dev" optional = false @@ -969,7 +969,7 @@ test = [] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "01a21031768112b50fddb746eb5dd982b5aa456b8e5f88b6803640e17fb6ce4a" +content-hash = "e00cb19fda6c088e0fa3a6427e8e59c11815f022273656df5f89e2a5216a3d89" [metadata.files] alabaster = [ @@ -1018,8 +1018,8 @@ black = [ {file = "black-22.8.0.tar.gz", hash = "sha256:792f7eb540ba9a17e8656538701d3eb1afcb134e3b45b71f20b25c77a8db7e6e"}, ] certifi = [ - {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"}, - {file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"}, + {file = "certifi-2022.6.15.1-py3-none-any.whl", hash = "sha256:43dadad18a7f168740e66944e4fa82c6611848ff9056ad910f8f7a3e46ab89e0"}, + {file = "certifi-2022.6.15.1.tar.gz", hash = "sha256:cffdcd380919da6137f76633531a5817e3a9f268575c128249fb637e4f9e73fb"}, ] charset-normalizer = [ {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, From 0f213bcfc7f7fc39481eeb7aaf9285af31cd2ebb Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 04:04:58 -0500 Subject: [PATCH 0014/1073] docs: Update doctests --- README.md | 45 +++++++++++---------- docs/quickstart.md | 43 ++++++++++++++------ docs/reference/properties.md | 77 +++++++++++++++--------------------- docs/topics/traversal.md | 31 ++++++++------- 4 files changed, 104 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index b30c501dc..9c751f3dd 100644 --- a/README.md +++ b/README.md @@ -53,9 +53,9 @@ Connect to a live tmux session: ```python >>> import libtmux ->>> server = libtmux.Server() ->>> server - +>>> s = libtmux.Server() +>>> s + ``` Tip: You can also use [tmuxp]'s [`tmuxp shell`] to drop straight into your @@ -70,32 +70,30 @@ List sessions: ```python >>> server.list_sessions() -[Session($3 foo), Session($1 libtmux)] +[Session($... libtmux_...), Session($... ...)] ``` Find session: ```python ->>> server.get_by_id('$3') -Session($3 foo) +>>> server.get_by_id('$0') +Session($... ...) ``` Find session by dict lookup: ```python +>>> server.sessions[0].rename_session('foo') +Session($... foo) >>> server.find_where({ "session_name": "foo" }) -Session($3 foo) -``` - -Assign session to `session`: - -```python ->>> session = server.find_where({ "session_name": "foo" }) +Session($... foo) ``` Control your session: ```python +# Assign session to `session`: +>>> session = server.find_where({ "session_name": "foo" }) >>> session.new_window(attach=False, window_name="ha in the bg") Window(@8 2:ha in the bg, Session($3 foo)) >>> session.kill_window("ha in") @@ -104,13 +102,14 @@ Window(@8 2:ha in the bg, Session($3 foo)) Create new window in the background (don't switch to it): ```python ->>> w = session.new_window(attach=False, window_name="ha in the bg") -Window(@11 3:ha in the bg, Session($3 foo)) +>>> session.new_window(attach=False, window_name="ha in the bg") +Window(@... ...:ha in the bg, Session($... libtmux_...)) ``` Close window: ```python +>>> w = session.attached_window >>> w.kill_window() ``` @@ -119,14 +118,14 @@ Grab remaining tmux window: ```python >>> window = session.attached_window >>> window.split_window(attach=False) -Pane(%23 Window(@10 1:bar, Session($3 foo))) +Pane(%... Window(@... ...:..., Session($... libtmux_...))) ``` Rename window: ```python >>> window.rename_window('libtmuxower') -Window(@10 1:libtmuxower, Session($3 foo)) +Window(@... ...:libtmuxower, Session($... ...)) ``` Split window (create a new pane): @@ -135,8 +134,13 @@ Split window (create a new pane): >>> pane = window.split_window() >>> pane = window.split_window(attach=False) >>> pane.select_pane() +Pane(%... Window(@... ...:..., Session($... libtmux_...))) >>> window = session.new_window(attach=False, window_name="test") +>>> window +Window(@... ...:test, Session($...)) >>> pane = window.split_window(attach=False) +>>> pane +Pane(%... Window(@... ...:..., Session($... libtmux_...))) ``` Type inside the pane (send key strokes): @@ -152,7 +156,8 @@ Grab the output of pane: ```python >>> pane.clear() # clear the pane ->>> pane.send_keys('cowsay hello') +>>> pane.send_keys("cowsay 'hello'", enter=True) +>>> import time; time.sleep(1) >>> print('\n'.join(pane.cmd('capture-pane', '-p').stdout)) ``` @@ -170,9 +175,9 @@ Traverse and navigate: ```python >>> pane.window -Window(@10 1:libtmuxower, Session($3 foo)) +Window(@... ...:..., Session($... ...)) >>> pane.window.session -Session($3 foo) +Session($... ...) ``` # Python support diff --git a/docs/quickstart.md b/docs/quickstart.md index bc28cdb51..f2cef0b99 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -108,7 +108,7 @@ First, we can grab a {class}`Server`. >>> import libtmux >>> server = libtmux.Server() >>> server - + ``` :::{tip} @@ -139,7 +139,7 @@ We can list sessions with {meth}`Server.list_sessions`: ```python >>> server.list_sessions() -[Session($3 foo), Session($1 libtmux)] +[Session($... ...), Session($... ...)] ``` This returns a list of {class}`Session` objects you can grab. We can @@ -147,6 +147,7 @@ find our current session with: ```python >>> server.list_sessions()[0] +Session($... ...) ``` However, this isn't guaranteed, libtmux works against current tmux information, the @@ -157,11 +158,11 @@ so {meth}`Server.get_by_id` and {meth}`Server.find_where` exists as a lookup. tmux sessions use the `$[0-9]` convention as a way to identify sessions. -`$3` is whatever the ID `list_sessions()` returned above. +`$1` is whatever the ID `list_sessions()` returned above. ```python ->>> server.get_by_id('$3') -Session($3 foo) +>>> server.get_by_id('$1') +Session($... ...) ``` You may `session = server.get_by_id('$')` to use the session object. @@ -169,8 +170,12 @@ You may `session = server.get_by_id('$')` to use the session object. ## Get session by name / other properties ```python +# Just for setting up the example: +>>> server.sessions[0].rename_session('foo') +Session($... foo) + >>> server.find_where({ "session_name": "foo" }) -Session($3 foo) +Session($... foo) ``` With `find_where`, pass in a dict and return the first object found. In @@ -181,7 +186,13 @@ through Windows and Panes, respectively. So you may now use: ```python +# Prepping the example: +>>> server.sessions[0].rename_session('foo') +Session($... foo) + >>> session = server.find_where({ "session_name": "foo" }) +>>> session +Session($... foo) ``` to give us a `session` object to play with. @@ -195,7 +206,7 @@ Let's make a {meth}`Session.new_window`, in the background: ```python >>> session.new_window(attach=False, window_name="ha in the bg") -Window(@8 2:ha in the bg, Session($3 foo)) +Window(@... ...:ha in the bg, Session($... ...)) ``` So a few things: @@ -214,7 +225,7 @@ Let's delete that window ({meth}`Session.kill_window`). Method 1: Use passthrough to tmux's `target` system. ```python ->>> session.kill_window("ha in") +>>> session.kill_window(window.id) ``` The window in the bg dissappeared. This was the equivalent of @@ -234,14 +245,17 @@ should have history, so navigate up with the arrow key. ```python >>> session.new_window(attach=False, window_name="ha in the bg") -Window(@11 3:ha in the bg, Session($3 foo)) +Window(@... ...:ha in the bg, Session($... ...)) ``` Try to kill the window by the matching id `@[0-9999]`. ```python +# Setup >>> session.new_window(attach=False, window_name="ha in the bg") -Window(@12 3:ha in the bg, Session($3 foo)) +Window(@... ...:ha in the bg, Session($... ...)) + +>>> session.kill_window('ha in the bg') ``` In addition, you could also `.kill_window` direction from the {class}`Window` @@ -249,6 +263,8 @@ object: ```python >>> window = session.new_window(attach=False, window_name="check this out") +>>> window +Window(@... ...:check this out, Session($... ...)) ``` And kill: @@ -266,7 +282,7 @@ Now that we know how to create windows, let's use one. Let's use {meth}`Session. to grab our current window. ```python ->>> window = session.attached_window() +>>> window = session.attached_window ``` `window` now has access to all of the objects inside of {class}`Window`. @@ -275,7 +291,7 @@ Let's create a pane, {meth}`Window.split_window`: ```python >>> window.split_window(attach=False) -Pane(%23 Window(@10 1:bar, Session($3 foo))) +Pane(%... Window(@... ...:..., Session($... ...))) ``` Powered up. Let's have a break down: @@ -288,7 +304,7 @@ Also, since you are aware of this power, let's commemorate the experience: ```python >>> window.rename_window('libtmuxower') -Window(@10 1:libtmuxower, Session($3 foo)) +Window(@... ...:..., Session($... ...)) ``` You should have noticed {meth}`Window.rename_window` renamed the window. @@ -313,6 +329,7 @@ can also use the `.select_*` available on the object, in this case the pane has ```python >>> pane.select_pane() +Pane(%... Window(@... ...:..., Session($... ...))) ``` ```{eval-rst} diff --git a/docs/reference/properties.md b/docs/reference/properties.md index e89e227b4..a2061fa12 100644 --- a/docs/reference/properties.md +++ b/docs/reference/properties.md @@ -24,15 +24,16 @@ $ python Import libtmux: ```python -import libtmux +>>> import libtmux ``` Attach default tmux {class}`~libtmux.Server` to `t`: ```python +>>> import libtmux >>> t = libtmux.Server() >>> t - + ``` ## Session @@ -40,36 +41,26 @@ Attach default tmux {class}`~libtmux.Server` to `t`: Get the {class}`~libtmux.Session` object: ```python ->>> session = t.sessions[0] +>>> session = server.sessions[0] >>> session -Session($0 libtmux) +Session($... libtmux_...) ``` Quick access to basic attributes: ```python >>> session.name -'libtmux' +'libtmux_...' >>> session.id -'$0' - ->>> session.width -'213' - ->>> session.height -'114' +'$...' ``` To see all attributes for a session: ```python ->>> session._info.keys() -['session_height', 'session_windows', 'session_width', 'session_id', 'session_created', 'session_attached', 'session_grouped', 'session_name'] - ->>> session._info -{'session_height': '114', 'session_windows': '3', 'session_width': '213', 'session_id': '$0', 'session_created': '1464905357', 'session_attached': '1', 'session_grouped': '0', 'session_name': 'libtmux'} - +>>> sorted(list(session._info.keys())) +['session_attached', 'session_created', ...] ``` Some may conflict with python API, to access them, you can use `.get()`, to get the count @@ -77,7 +68,7 @@ of sessions in a window: ```python >>> session.get('session_windows') -'3' +'...' ``` ## Windows @@ -88,40 +79,37 @@ The same concepts apply for {class}`~libtmux.Window`: >>> window = session.attached_window >>> window -Window(@2 2:docs, Session($0 libtmux)) +Window(@... ...:..., Session($... ...)) ``` Basics: ```python >>> window.name -'docs' +'...' >>> window.id -'@2' +'@...' >>> window.height -'114' +'...' >>> window.width -'213' +'...' ``` Everything available: ```python ->>> window._info -{'window_panes': '4', 'window_active': '1', 'window_height': '114', 'window_activity_flag': '0', 'window_width': '213', 'session_id': '$0', 'window_id': '@2', 'window_layout': 'dad5,213x114,0,0[213x60,0,0,4,213x53,0,61{70x53,0,61,5,70x53,71,61,6,71x53,142,61,7}]', 'window_silence_flag': '0', 'window_index': '2', 'window_bell_flag': '0', 'session_name': 'libtmux', 'window_flags': '*', 'window_name': 'docs'} - ->>> window.keys() -['window_panes', 'window_active', 'window_height', 'window_activity_flag', 'window_width', 'session_id', 'window_id', 'window_layout', 'window_silence_flag', 'window_index', 'window_bell_flag', 'session_name', 'window_flags', 'window_name'] +>>> sorted(list(window.keys())) +['session_id', 'session_name', 'window_active', ..., 'window_width'] ``` Use `get()` for details not accessible via properties: ```python ->>> pane.get('window_panes') -'4' +>>> window.get('window_panes') +'1' ``` ## Panes @@ -132,40 +120,39 @@ Get the {class}`~libtmux.Pane`: >>> pane = window.attached_pane >>> pane -Pane(%5 Window(@2 2:docs, Session($0 libtmux))) +Pane(%... Window(@... ...:..., Session($... libtmux_...))) ``` Basics: ```python >>> pane.current_command -'python' +'...' + +>>> type(pane.current_command) + >>> pane.height -'53' +'...' >>> pane.width -'70' +'...' >>> pane.index -'1' +'0' ``` Everything: -```python ->>> pane._info -{'alternate_saved_x': '0', 'alternate_saved_y': '0', 'cursor_y': '47', 'cursor_x': '0', 'pane_in_mode': '0', 'insert_flag': '0', 'keypad_flag': '0', 'cursor_flag': '1', 'pane_current_command': 'python', 'window_index': '2', 'history_size': '216', 'scroll_region_lower': '52', 'keypad_cursor_flag': '0', 'history_bytes': '38778', 'pane_active': '1', 'pane_dead': '0', 'pane_synchronized': '0', 'window_id': '@2', 'pane_index': '1', 'pane_width': '70', 'mouse_any_flag': '0', 'mouse_button_flag': '0', 'window_name': 'docs', 'pane_current_path': '/Users/me/work/python/libtmux/doc', 'pane_tty': '/dev/ttys007', 'pane_title': 'Python REPL (ptpython)', 'session_id': '$0', 'alternate_on': '0', 'mouse_standard_flag': '0', 'wrap_flag': '1', 'history_limit': '2000', 'pane_pid': '37172', 'pane_height': '53', 'session_name': 'libtmux', 'scroll_region_upper': '0', 'pane_id': '%5'} - ->>> pane._info.keys() -['alternate_saved_x', 'alternate_saved_y', 'cursor_y', 'cursor_x', 'pane_in_mode', 'insert_flag', 'keypad_flag', 'cursor_flag', 'pane_current_command', 'window_index', 'history_size', 'scroll_region_lower', 'keypad_cursor_flag', 'history_bytes', 'pane_active', 'pane_dead', 'pane_synchronized', 'window_id', 'pane_index', 'pane_width', 'mouse_any_flag', 'mouse_button_flag', 'window_name', 'pane_current_path', 'pane_tty', 'pane_title', 'session_id', 'alternate_on', 'mouse_standard_flag', 'wrap_flag', 'history_limit', 'pane_pid', 'pane_height', 'session_name', 'scroll_region_upper', 'pane_id'] -``` +````python +>>> sorted(list(pane._info.keys())) +['alternate_on', 'alternate_saved_x', ..., 'wrap_flag'] Use `get()` for details keys: ```python >>> pane.get('pane_width') -'70' -``` +'...' +```` [formats]: http://man.openbsd.org/OpenBSD-5.9/man1/tmux.1#FORMATS diff --git a/docs/topics/traversal.md b/docs/topics/traversal.md index 3d8864f2c..a03b515c0 100644 --- a/docs/topics/traversal.md +++ b/docs/topics/traversal.md @@ -31,53 +31,55 @@ import libtmux Attach default tmux {class}`~libtmux.Server` to `t`: ```python +>>> import libtmux >>> t = libtmux.Server(); >>> t - + ``` Get first session {class}`~libtmux.Session` to `session`: ```python ->>> session = t.sessions[0] +>>> session = server.sessions[0] >>> session -Session($0 libtmux) +Session($... ...) ``` Get a list of sessions: ```python ->>> t.sessions -[Session($0 libtmux), Session($1 tmuxp)] +>>> server.sessions +[Session($... ...), Session($... ...)] ``` Iterate through sessions in a server: ```python ->>> for sess in t.sessions: +>>> for sess in server.sessions: ... print(sess) - -Session($0 libtmux) -Session($1 tmuxp) +Session($... ...) +Session($... ...) ``` Grab a {class}`~libtmux.Window` from a session: ```python >>> session.windows[0] -Window(@1 1:libtmux, Session($0 libtmux)) +Window(@... ...:..., Session($... ...)) ``` Grab the currently focused window from session: ```python >>> session.attached_window ->>> Window(@2 2:docs, Session($0 libtmux))grab the currently focused {class}`Pane` from session: +Window(@... ...:..., Session($... ...)) ``` +Grab the currently focused {class}`Pane` from session: + ```python >>> session.attached_pane -Pane(%5 Window(@2 2:docs, Session($0 libtmux))) +Pane(%... Window(@... ...:..., Session($... ...))) ``` Assign the attached {class}`~libtmux.Pane` to `p`: @@ -89,11 +91,12 @@ Assign the attached {class}`~libtmux.Pane` to `p`: Access the window/server of a pane: ```python +>>> p = session.attached_pane >>> p.window -Window(@2 2:docs, Session($0 libtmux)) +Window(@... ...:..., Session($... ...)) >>> p.server - + ``` [target]: http://man.openbsd.org/OpenBSD-5.9/man1/tmux.1#COMMANDS From 6e5a6cb509d967544b29f5d32e9d26ec66ae94f0 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 05:42:26 -0500 Subject: [PATCH 0015/1073] docs(CHANGES): Note doc updates --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index f8623b128..8f07354fa 100644 --- a/CHANGES +++ b/CHANGES @@ -28,6 +28,7 @@ $ pip install --user --upgrade --pre libtmux ### Documentation - Move to sphinx-autoissues, #406 +- Examples updated for correctness, #412 (cherry-picked from #410) ## libtmux 0.14.2 (2022-08-17) From c2cb01d205beda6a9e90e7817e8f51f15ddb0be8 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 05:16:57 -0500 Subject: [PATCH 0016/1073] ci(coverage): Update coverage configuration This is based on pytest's See also: https://github.com/pytest-dev/pytest/blob/7.1.x/.coveragerc --- .coveragerc | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/.coveragerc b/.coveragerc index 9ed88302e..7c74c56a0 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,15 +1,20 @@ [run] +parallel = 1 +branch = 1 + omit = - test/* - */_vendor/* - */_* - pkg/* - */log.py + docs/conf.py + */_compat.py [report] +skip_covered = True +show_missing = True exclude_lines = - pragma: no cover - def __repr__ - raise NotImplementedError - if __name__ == .__main__.: - def parse_args + \#\s*pragma: no cover + ^\s*raise NotImplementedError\b + ^\s*return NotImplemented\b + ^\s*assert False(,|$) + ^\s*assert_never\( + + ^\s*if TYPE_CHECKING: + ^\s*@overload( |$) From 6a12794b4659acc99480d4eab979c200dc46e9e6 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 9 Sep 2022 06:58:49 -0500 Subject: [PATCH 0017/1073] build(deps): pytest_plugin.py infrastructure --- libtmux/{conftest.py => pytest_plugin.py} | 0 pyproject.toml | 3 +++ tests/conftest.py | 1 - 3 files changed, 3 insertions(+), 1 deletion(-) rename libtmux/{conftest.py => pytest_plugin.py} (100%) diff --git a/libtmux/conftest.py b/libtmux/pytest_plugin.py similarity index 100% rename from libtmux/conftest.py rename to libtmux/pytest_plugin.py diff --git a/pyproject.toml b/pyproject.toml index a4d41744f..069a9bab9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,6 +102,9 @@ coverage = ["codecov", "coverage", "pytest-cov"] format = ["black", "isort"] lint = ["flake8", "flake8-bugbear", "flake8-comprehensions", "mypy"] +[tool.poetry.plugins.pytest11] +libtmux = "libtmux.pytest_plugin" + [tool.mypy] strict = true diff --git a/tests/conftest.py b/tests/conftest.py index 535e57934..e69de29bb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1 +0,0 @@ -from libtmux.conftest import * # noqa F40 From 247962f8e3a96846a26fc17315d22416461ad255 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 9 Sep 2022 07:01:43 -0500 Subject: [PATCH 0018/1073] tests: Change prefix to libtmux_ --- libtmux/pytest_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libtmux/pytest_plugin.py b/libtmux/pytest_plugin.py index 280d58253..9e045f13e 100644 --- a/libtmux/pytest_plugin.py +++ b/libtmux/pytest_plugin.py @@ -51,7 +51,7 @@ def clear_env(monkeypatch: MonkeyPatch) -> None: def server(request: SubRequest, monkeypatch: MonkeyPatch) -> Server: t = Server() - t.socket_name = "tmuxp_test%s" % next(namer) + t.socket_name = "libtmux_test%s" % next(namer) def fin() -> None: t.kill_server() From 07302485e11c4ff869f7d42625556096adcfc676 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 05:32:36 -0500 Subject: [PATCH 0019/1073] ci(pytest): Fix coverage due to pytest plugin change Moving from conftest.py to pytest_plugin.py (which comes via a setuptools entry point) requires a workaround to prevent loss of coverage from real libtmux tests relying on our pytest plugin. See also: - https://pytest-cov.readthedocs.io/en/latest/plugins.html - https://github.com/pytest-dev/pytest/issues/935#issuecomment-245107960 --- .github/workflows/tests.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e5443194d..64b3ba367 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -68,7 +68,11 @@ jobs: export PATH=$HOME/tmux-builds/tmux-${{ matrix.tmux-version }}/bin:$PATH ls $HOME/tmux-builds/tmux-${{ matrix.tmux-version }}/bin tmux -V - poetry run py.test --cov=./ --cov-report=xml + poetry run py.test --cov=./ --cov-append --cov-report=xml + env: + COV_CORE_SOURCE: . + COV_CORE_CONFIG: .coveragerc + COV_CORE_DATAFILE: .coverage.eager - uses: codecov/codecov-action@v2 with: token: ${{ secrets.CODECOV_TOKEN }} From 2aa5408c5eb9ecfa8e59de930d53eb073c997d4b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 06:33:35 -0500 Subject: [PATCH 0020/1073] pytest plugin: Add default tmux configuration --- libtmux/pytest_plugin.py | 50 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/libtmux/pytest_plugin.py b/libtmux/pytest_plugin.py index 9e045f13e..49373c1bb 100644 --- a/libtmux/pytest_plugin.py +++ b/libtmux/pytest_plugin.py @@ -1,5 +1,7 @@ +import getpass import logging import os +import pathlib import shutil import typing as t @@ -17,6 +19,47 @@ from libtmux.session import Session logger = logging.getLogger(__name__) +USING_ZSH = "zsh" in os.getenv("SHELL", "") + + +@pytest.fixture(autouse=True, scope="session") +def home_path(tmp_path_factory: pytest.TempPathFactory) -> pathlib.Path: + return tmp_path_factory.mktemp("home") + + +@pytest.fixture(autouse=True, scope="session") +def user_path(home_path: pathlib.Path) -> pathlib.Path: + p = home_path / getpass.getuser() + p.mkdir() + return p + + +@pytest.mark.skipif(USING_ZSH, reason="Using ZSH") +@pytest.fixture(autouse=USING_ZSH, scope="session") +def zshrc(user_path: pathlib.Path) -> pathlib.Path: + """This quiets ZSH default message. + + Needs a startup file .zshenv, .zprofile, .zshrc, .zlogin. + """ + p = user_path / ".zshrc" + p.touch() + return p + + +@pytest.fixture(scope="function") +def config_file(user_path: pathlib.Path) -> pathlib.Path: + """Set default tmux configuration (base indexes for windows, panes) + + We need this for tests to work across tmux versions in our CI matrix. + """ + c = user_path / ".tmux.conf" + c.write_text( + """ +set -g base-index 1 + """, + encoding="utf-8", + ) + return c @pytest.fixture(autouse=True) @@ -48,9 +91,10 @@ def clear_env(monkeypatch: MonkeyPatch) -> None: @pytest.fixture(scope="function") -def server(request: SubRequest, monkeypatch: MonkeyPatch) -> Server: - - t = Server() +def server( + request: SubRequest, monkeypatch: MonkeyPatch, config_file: pathlib.Path +) -> Server: + t = Server(config_file=str(config_file.absolute())) t.socket_name = "libtmux_test%s" % next(namer) def fin() -> None: From ffa8483a88d4fd9617697b3b7978e5666f34fc63 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 06:20:25 -0500 Subject: [PATCH 0021/1073] docs: Base indexes This makes the docs look more realistic, but we need to make it work across tmux versions and python versions put into the CI matrix. --- README.md | 26 +++++++++++++------------- docs/quickstart.md | 28 ++++++++++++++-------------- docs/reference/properties.md | 10 +++++----- docs/topics/traversal.md | 16 ++++++++-------- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 9c751f3dd..b3ec76ad6 100644 --- a/README.md +++ b/README.md @@ -70,23 +70,23 @@ List sessions: ```python >>> server.list_sessions() -[Session($... libtmux_...), Session($... ...)] +[Session($1 ...), Session($0 ...)] ``` Find session: ```python ->>> server.get_by_id('$0') -Session($... ...) +>>> server.get_by_id('$1') +Session($1 ...) ``` Find session by dict lookup: ```python >>> server.sessions[0].rename_session('foo') -Session($... foo) +Session($1 foo) >>> server.find_where({ "session_name": "foo" }) -Session($... foo) +Session($1 foo) ``` Control your session: @@ -103,7 +103,7 @@ Create new window in the background (don't switch to it): ```python >>> session.new_window(attach=False, window_name="ha in the bg") -Window(@... ...:ha in the bg, Session($... libtmux_...)) +Window(@2 2:ha in the bg, Session($1 ...)) ``` Close window: @@ -118,14 +118,14 @@ Grab remaining tmux window: ```python >>> window = session.attached_window >>> window.split_window(attach=False) -Pane(%... Window(@... ...:..., Session($... libtmux_...))) +Pane(%2 Window(@1 1:... Session($1 ...))) ``` Rename window: ```python >>> window.rename_window('libtmuxower') -Window(@... ...:libtmuxower, Session($... ...)) +Window(@1 1:libtmuxower, Session($1 ...)) ``` Split window (create a new pane): @@ -134,13 +134,13 @@ Split window (create a new pane): >>> pane = window.split_window() >>> pane = window.split_window(attach=False) >>> pane.select_pane() -Pane(%... Window(@... ...:..., Session($... libtmux_...))) +Pane(%3 Window(@1 1:..., Session($1 ...))) >>> window = session.new_window(attach=False, window_name="test") >>> window -Window(@... ...:test, Session($...)) +Window(@2 2:test, Session($1 ...)) >>> pane = window.split_window(attach=False) >>> pane -Pane(%... Window(@... ...:..., Session($... libtmux_...))) +Pane(%5 Window(@2 2:test, Session($1 ...))) ``` Type inside the pane (send key strokes): @@ -175,9 +175,9 @@ Traverse and navigate: ```python >>> pane.window -Window(@... ...:..., Session($... ...)) +Window(@1 1:..., Session($1 ...)) >>> pane.window.session -Session($... ...) +Session($1 ...) ``` # Python support diff --git a/docs/quickstart.md b/docs/quickstart.md index f2cef0b99..8d8b19350 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -139,7 +139,7 @@ We can list sessions with {meth}`Server.list_sessions`: ```python >>> server.list_sessions() -[Session($... ...), Session($... ...)] +[Session($1 ...), Session($0 ...)] ``` This returns a list of {class}`Session` objects you can grab. We can @@ -147,7 +147,7 @@ find our current session with: ```python >>> server.list_sessions()[0] -Session($... ...) +Session($1 ...) ``` However, this isn't guaranteed, libtmux works against current tmux information, the @@ -162,7 +162,7 @@ tmux sessions use the `$[0-9]` convention as a way to identify sessions. ```python >>> server.get_by_id('$1') -Session($... ...) +Session($1 ...) ``` You may `session = server.get_by_id('$')` to use the session object. @@ -172,10 +172,10 @@ You may `session = server.get_by_id('$')` to use the session object. ```python # Just for setting up the example: >>> server.sessions[0].rename_session('foo') -Session($... foo) +Session($1 foo) >>> server.find_where({ "session_name": "foo" }) -Session($... foo) +Session($1 foo) ``` With `find_where`, pass in a dict and return the first object found. In @@ -188,11 +188,11 @@ So you may now use: ```python # Prepping the example: >>> server.sessions[0].rename_session('foo') -Session($... foo) +Session($1 foo) >>> session = server.find_where({ "session_name": "foo" }) >>> session -Session($... foo) +Session($1 foo) ``` to give us a `session` object to play with. @@ -206,7 +206,7 @@ Let's make a {meth}`Session.new_window`, in the background: ```python >>> session.new_window(attach=False, window_name="ha in the bg") -Window(@... ...:ha in the bg, Session($... ...)) +Window(@2 ...:ha in the bg, Session($1 ...)) ``` So a few things: @@ -245,7 +245,7 @@ should have history, so navigate up with the arrow key. ```python >>> session.new_window(attach=False, window_name="ha in the bg") -Window(@... ...:ha in the bg, Session($... ...)) +Window(@2 ...:ha in the bg, Session($1 ...)) ``` Try to kill the window by the matching id `@[0-9999]`. @@ -253,7 +253,7 @@ Try to kill the window by the matching id `@[0-9999]`. ```python # Setup >>> session.new_window(attach=False, window_name="ha in the bg") -Window(@... ...:ha in the bg, Session($... ...)) +Window(@1 ...:ha in the bg, Session($1 ...)) >>> session.kill_window('ha in the bg') ``` @@ -264,7 +264,7 @@ object: ```python >>> window = session.new_window(attach=False, window_name="check this out") >>> window -Window(@... ...:check this out, Session($... ...)) +Window(@2 2:check this out, Session($1 ...)) ``` And kill: @@ -291,7 +291,7 @@ Let's create a pane, {meth}`Window.split_window`: ```python >>> window.split_window(attach=False) -Pane(%... Window(@... ...:..., Session($... ...))) +Pane(%2 Window(@1 ...:..., Session($1 ...))) ``` Powered up. Let's have a break down: @@ -304,7 +304,7 @@ Also, since you are aware of this power, let's commemorate the experience: ```python >>> window.rename_window('libtmuxower') -Window(@... ...:..., Session($... ...)) +Window(@1 ...:..., Session($1 ...)) ``` You should have noticed {meth}`Window.rename_window` renamed the window. @@ -329,7 +329,7 @@ can also use the `.select_*` available on the object, in this case the pane has ```python >>> pane.select_pane() -Pane(%... Window(@... ...:..., Session($... ...))) +Pane(%1 Window(@1 ...:..., Session($1 ...))) ``` ```{eval-rst} diff --git a/docs/reference/properties.md b/docs/reference/properties.md index a2061fa12..085361f3f 100644 --- a/docs/reference/properties.md +++ b/docs/reference/properties.md @@ -43,7 +43,7 @@ Get the {class}`~libtmux.Session` object: ```python >>> session = server.sessions[0] >>> session -Session($... libtmux_...) +Session($1 libtmux_...) ``` Quick access to basic attributes: @@ -53,7 +53,7 @@ Quick access to basic attributes: 'libtmux_...' >>> session.id -'$...' +'$1' ``` To see all attributes for a session: @@ -79,7 +79,7 @@ The same concepts apply for {class}`~libtmux.Window`: >>> window = session.attached_window >>> window -Window(@... ...:..., Session($... ...)) +Window(@1 ...:..., Session($1 ...)) ``` Basics: @@ -89,7 +89,7 @@ Basics: '...' >>> window.id -'@...' +'@1' >>> window.height '...' @@ -120,7 +120,7 @@ Get the {class}`~libtmux.Pane`: >>> pane = window.attached_pane >>> pane -Pane(%... Window(@... ...:..., Session($... libtmux_...))) +Pane(%1 Window(@1 ...:..., Session($1 libtmux_...))) ``` Basics: diff --git a/docs/topics/traversal.md b/docs/topics/traversal.md index a03b515c0..02b537306 100644 --- a/docs/topics/traversal.md +++ b/docs/topics/traversal.md @@ -42,14 +42,14 @@ Get first session {class}`~libtmux.Session` to `session`: ```python >>> session = server.sessions[0] >>> session -Session($... ...) +Session($1 ...) ``` Get a list of sessions: ```python >>> server.sessions -[Session($... ...), Session($... ...)] +[Session($1 ...), Session($0 ...)] ``` Iterate through sessions in a server: @@ -57,29 +57,29 @@ Iterate through sessions in a server: ```python >>> for sess in server.sessions: ... print(sess) -Session($... ...) -Session($... ...) +Session($1 ...) +Session($0 ...) ``` Grab a {class}`~libtmux.Window` from a session: ```python >>> session.windows[0] -Window(@... ...:..., Session($... ...)) +Window(@1 ...:..., Session($1 ...)) ``` Grab the currently focused window from session: ```python >>> session.attached_window -Window(@... ...:..., Session($... ...)) +Window(@1 ...:..., Session($1 ...)) ``` Grab the currently focused {class}`Pane` from session: ```python >>> session.attached_pane -Pane(%... Window(@... ...:..., Session($... ...))) +Pane(%1 Window(@1 ...:..., Session($1 ...))) ``` Assign the attached {class}`~libtmux.Pane` to `p`: @@ -93,7 +93,7 @@ Access the window/server of a pane: ```python >>> p = session.attached_pane >>> p.window -Window(@... ...:..., Session($... ...)) +Window(@1 ...:..., Session($1 ...)) >>> p.server From 057bdec4e621fdea311f77803100b6ec39cf092c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 06:52:05 -0500 Subject: [PATCH 0022/1073] docs(libtmux modules): Base index output improvements --- libtmux/pane.py | 4 ++-- libtmux/server.py | 6 +++--- libtmux/window.py | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libtmux/pane.py b/libtmux/pane.py index 0ac259f99..469a0d9b3 100644 --- a/libtmux/pane.py +++ b/libtmux/pane.py @@ -39,13 +39,13 @@ class Pane(TmuxMappingObject): Examples -------- >>> pane - Pane(%1 Window(@1 ...:..., Session($1 ...))) + Pane(%1 Window(@1 1:..., Session($1 ...))) >>> pane in window.panes True >>> pane.window - Window(@1 ...:..., Session($1 ...)) + Window(@1 1:..., Session($1 ...)) >>> pane.session Session($1 ...) diff --git a/libtmux/server.py b/libtmux/server.py index e0e7c35c7..a049f3b9e 100644 --- a/libtmux/server.py +++ b/libtmux/server.py @@ -56,13 +56,13 @@ class Server(TmuxRelationalObject["Session", "SessionDict"], EnvironmentMixin): [Session($1 ...)] >>> server.sessions[0].windows - [Window(@1 ...:..., Session($1 ...)] + [Window(@1 1:..., Session($1 ...)] >>> server.sessions[0].attached_window - Window(@1 ...:..., Session($1 ...) + Window(@1 1:..., Session($1 ...) >>> server.sessions[0].attached_pane - Pane(%1 Window(@1 ...:..., Session($1 ...))) + Pane(%1 Window(@1 1:..., Session($1 ...))) References ---------- diff --git a/libtmux/window.py b/libtmux/window.py index d38b8298c..434dca17c 100644 --- a/libtmux/window.py +++ b/libtmux/window.py @@ -44,7 +44,7 @@ class Window(TmuxMappingObject, TmuxRelationalObject["Pane", "PaneDict"]): >>> window = session.new_window('My project') >>> window - Window(@... ...:My project, Session($... ...)) + Window(@2 2:My project, Session($... ...)) Windows have panes: @@ -329,10 +329,10 @@ def rename_window(self, new_name: str) -> "Window": >>> window = session.attached_window >>> window.rename_window('My project') - Window(@1 ...:My project, Session($1 ...)) + Window(@1 1:My project, Session($1 ...)) >>> window.rename_window('New name') - Window(@1 ...:New name, Session($1 ...)) + Window(@1 1:New name, Session($1 ...)) """ import shlex From 71176d8a1aec7c27764d8ed49b306763ca9ec62e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 07:28:49 -0500 Subject: [PATCH 0023/1073] docs(prettier): Line wrapping --- .prettierrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.prettierrc b/.prettierrc index de753c537..2d553cc6c 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,3 +1,4 @@ { - "printWidth": 100 + "printWidth": 100, + "proseWrap": 'always' } From 14cde4dd84bc87f8c75a0ca6770293c3763766bc Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 07:28:37 -0500 Subject: [PATCH 0024/1073] docs(conf): Add pytest to intersphinx_mapping --- docs/conf.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 1bbb683df..94c7f7fd6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -160,7 +160,10 @@ ) ] -intersphinx_mapping = {"http://docs.python.org/": None} +intersphinx_mapping = { + "": ("https://docs.python.org/", None), + "pytest": ("https://docs.pytest.org/en/stable/", None), +} def linkcode_resolve( From 17837f72d9f4558c03120d2baa0aafbf53e324b3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 07:39:09 -0500 Subject: [PATCH 0025/1073] refactor!(pytest_plugin): Remove all autouse from default usage This prevents plugins from being invoked simply by having libtmux installed. We don't want that - it would interrupt systems. Explicit is better than implicit. Move autouse for libtmux itself to the appropriate places. --- docs/conftest.py | 1 + libtmux/conftest.py | 44 +++++++++++++++++++++++++++ libtmux/pytest_plugin.py | 65 +++++++++++++++++++++------------------- tests/conftest.py | 1 + 4 files changed, 80 insertions(+), 31 deletions(-) create mode 100644 docs/conftest.py create mode 100644 libtmux/conftest.py diff --git a/docs/conftest.py b/docs/conftest.py new file mode 100644 index 000000000..62571f546 --- /dev/null +++ b/docs/conftest.py @@ -0,0 +1 @@ +from libtmux.conftest import * # NOQA: F4 diff --git a/libtmux/conftest.py b/libtmux/conftest.py new file mode 100644 index 000000000..c99992127 --- /dev/null +++ b/libtmux/conftest.py @@ -0,0 +1,44 @@ +import pathlib +import shutil +import typing as t + +import pytest + +from _pytest.doctest import DoctestItem + +from libtmux.pytest_plugin import USING_ZSH + +if t.TYPE_CHECKING: + from libtmux.session import Session + + +@pytest.fixture(autouse=True) +def add_doctest_fixtures( + request: pytest.FixtureRequest, + doctest_namespace: t.Dict[str, t.Any], +) -> None: + if isinstance(request._pyfuncitem, DoctestItem) and shutil.which("tmux"): + request.getfixturevalue("set_home") + doctest_namespace["server"] = request.getfixturevalue("server") + session: "Session" = request.getfixturevalue("session") + doctest_namespace["session"] = session + doctest_namespace["window"] = session.attached_window + doctest_namespace["pane"] = session.attached_pane + + +@pytest.fixture(autouse=True, scope="function") +def set_home( + monkeypatch: pytest.MonkeyPatch, + user_path: pathlib.Path, +) -> None: + monkeypatch.setenv("HOME", str(user_path)) + + +@pytest.fixture(autouse=True, scope="session") +@pytest.mark.usefixtures("clear_env") +def setup( + request: pytest.FixtureRequest, + config_file: pathlib.Path, +) -> None: + if USING_ZSH: + request.getfixturevalue("zshrc") diff --git a/libtmux/pytest_plugin.py b/libtmux/pytest_plugin.py index 49373c1bb..863e9e44f 100644 --- a/libtmux/pytest_plugin.py +++ b/libtmux/pytest_plugin.py @@ -2,15 +2,10 @@ import logging import os import pathlib -import shutil import typing as t import pytest -from _pytest.doctest import DoctestItem -from _pytest.fixtures import SubRequest -from _pytest.monkeypatch import MonkeyPatch - from libtmux import exc from libtmux.server import Server from libtmux.test import TEST_SESSION_PREFIX, get_test_session_name, namer @@ -22,20 +17,33 @@ USING_ZSH = "zsh" in os.getenv("SHELL", "") -@pytest.fixture(autouse=True, scope="session") +@pytest.fixture(scope="session") def home_path(tmp_path_factory: pytest.TempPathFactory) -> pathlib.Path: + """Temporary `/home/` path.""" return tmp_path_factory.mktemp("home") -@pytest.fixture(autouse=True, scope="session") -def user_path(home_path: pathlib.Path) -> pathlib.Path: - p = home_path / getpass.getuser() +@pytest.fixture(scope="session") +def home_user_name() -> str: + """Default username to set for :func:`user_path` fixture.""" + return getpass.getuser() + + +@pytest.fixture(scope="session") +def user_path(home_path: pathlib.Path, home_user_name: str) -> pathlib.Path: + """Default temporary user directory. + + Used by: :func:`config_file`, :func:`zshrc` + + Note: You will need to set the home directory, see :ref:`set_home`. + """ + p = home_path / home_user_name p.mkdir() return p @pytest.mark.skipif(USING_ZSH, reason="Using ZSH") -@pytest.fixture(autouse=USING_ZSH, scope="session") +@pytest.fixture(scope="session") def zshrc(user_path: pathlib.Path) -> pathlib.Path: """This quiets ZSH default message. @@ -46,11 +54,15 @@ def zshrc(user_path: pathlib.Path) -> pathlib.Path: return p -@pytest.fixture(scope="function") +@pytest.fixture(scope="session") def config_file(user_path: pathlib.Path) -> pathlib.Path: - """Set default tmux configuration (base indexes for windows, panes) + """Default `.tmux.conf` configuration. + + - ``base-index -g 1`` + + These guarantee pane and windows targets can be reliably referenced and asserted. - We need this for tests to work across tmux versions in our CI matrix. + Note: You will need to set the home directory, see :ref:`set_home`. """ c = user_path / ".tmux.conf" c.write_text( @@ -62,8 +74,8 @@ def config_file(user_path: pathlib.Path) -> pathlib.Path: return c -@pytest.fixture(autouse=True) -def clear_env(monkeypatch: MonkeyPatch) -> None: +@pytest.fixture +def clear_env(monkeypatch: pytest.MonkeyPatch) -> None: """Clear out any unnecessary environment variables that could interrupt tests. tmux show-environment tests were being interrupted due to a lot of crazy env vars. @@ -92,9 +104,12 @@ def clear_env(monkeypatch: MonkeyPatch) -> None: @pytest.fixture(scope="function") def server( - request: SubRequest, monkeypatch: MonkeyPatch, config_file: pathlib.Path + request: pytest.FixtureRequest, + monkeypatch: pytest.MonkeyPatch, + config_file: pathlib.Path, ) -> Server: - t = Server(config_file=str(config_file.absolute())) + """Returns a new, temporary :class:`libtmux.Server`""" + t = Server() t.socket_name = "libtmux_test%s" % next(namer) def fin() -> None: @@ -106,7 +121,8 @@ def fin() -> None: @pytest.fixture(scope="function") -def session(request: SubRequest, server: Server) -> "Session": +def session(request: pytest.FixtureRequest, server: Server) -> "Session": + """Returns a new, temporary :class:`libtmux.Session`""" session_name = "tmuxp" if not server.has_session(session_name): @@ -146,16 +162,3 @@ def session(request: SubRequest, server: Server) -> "Session": assert TEST_SESSION_NAME != "tmuxp" return session - - -@pytest.fixture(autouse=True) -def add_doctest_fixtures( - request: SubRequest, - doctest_namespace: t.Dict[str, t.Any], -) -> None: - if isinstance(request._pyfuncitem, DoctestItem) and shutil.which("tmux"): - doctest_namespace["server"] = request.getfixturevalue("server") - session: "Session" = request.getfixturevalue("session") - doctest_namespace["session"] = session - doctest_namespace["window"] = session.attached_window - doctest_namespace["pane"] = session.attached_pane diff --git a/tests/conftest.py b/tests/conftest.py index e69de29bb..62571f546 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -0,0 +1 @@ +from libtmux.conftest import * # NOQA: F4 From 87b13bfde265cddb853c07db84c832a1c72dd4f1 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 07:29:01 -0500 Subject: [PATCH 0026/1073] docs(pytest-plugin): Add pytest plugin page --- docs/developing.md | 8 ++++ docs/index.md | 1 + docs/pytest-plugin.md | 98 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 docs/pytest-plugin.md diff --git a/docs/developing.md b/docs/developing.md index 244b55b44..2ace7f008 100644 --- a/docs/developing.md +++ b/docs/developing.md @@ -23,6 +23,14 @@ Makefile commands prefixed with `watch_` will watch files and rerun. Helpers: `make test` Rerun tests on file change: `make watch_test` (requires [entr(1)]) +### Pytest plugin + +:::{seealso} + +See {ref}`pytest_plugin`. + +::: + ## Documentation Default preview server: http://localhost:8023 diff --git a/docs/index.md b/docs/index.md index bf7af19ca..ed92e5ade 100644 --- a/docs/index.md +++ b/docs/index.md @@ -28,6 +28,7 @@ api :hidden: developing +pytest-plugin internals/index history glossary diff --git a/docs/pytest-plugin.md b/docs/pytest-plugin.md new file mode 100644 index 000000000..8f546f2e3 --- /dev/null +++ b/docs/pytest-plugin.md @@ -0,0 +1,98 @@ +(pytest_plugin)= + +# `pytest` plugin + +Testing tmux with libtmux + +```{seealso} Using libtmux? + +Do you want more flexbility? Correctness? Power? Defaults changed? [Connect with us] on the tracker, we want to know +your case, we won't stabilize APIs until we're sure everything is by the book. + +[connect with us]: https://github.com/tmux-python/libtmux/discussions + +``` + +```{module} libtmux.pytest_plugin + +``` + +## Usage + +Install `libtmux` via the python package manager of your choosing, e.g. + +```console +$ pip install libtmux +``` + +The pytest plugin will automatically be detected via pytest, and the fixtures will be added. + +## Fixtures + +`pytest-tmux` works through providing {ref}`pytest fixtures ` - so read up on +those! + +The plugin's fixtures guarantee a fresh, headless `tmux(1)` server, session, window, or pane is +passed into your test. + +(recommended-fixtures)= + +## Recommended fixtures + +These are fixtures are automatically used when the plugin is enabled and `pytest` is ran. + +- Creating temporary, test directories for: + - `/home/` ({func}`home_path`) + - `/home/${user}` ({func}`user_path`) +- Default `.tmux.conf` configuration with these settings ({func}`config_file`): + + - `base-index -g 1` + + These are set to ensure panes and windows can be reliably referenced and asserted. + +## Setting a tmux configuration + +If you would like :func:`session` fixture to automatically use a configuration, you have a few +options: + +- Pass a `config_file` into :class:`libtmux.server.Server` +- Set the `HOME` directory to a local or temporary pytest path with a configurat configuration file + +You could also read the code and override :func:`server`'s fixture in your own doctest. doctest. + +(set_home)= + +### Setting a temporary home directory + +```python +import pathlib +import pytest + +@pytest.fixture(autouse=True, scope="function") +def set_home( + monkeypatch: pytest.MonkeyPatch, + user_path: pathlib.Path, +): + monkeypatch.setenv("HOME", str(user_path)) +``` + +## See examples + +View libtmux's own [tests/](https://github.com/tmux-python/libtmux/tree/master/tests) as well as +tmuxp's [tests/](https://github.com/tmux-python/tmuxp/tree/master/tests). + +libtmux's tests `autouse` the {ref}`recommended-fixtures` above to ensure stable, assertions and +object lookups in the test grid. + +## API reference + +```{eval-rst} +.. autoapimodule:: libtmux.pytest_plugin + :members: + :inherited-members: + :private-members: + :show-inheritance: + :member-order: bysource + :exclude-members: Server, TEST_SESSION_PREFIX, get_test_session_name, + namer, logger +``` From 9f1403f4fa46bee3d4d5a604f795f6204e3bdb54 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 08:42:39 -0500 Subject: [PATCH 0027/1073] docs(CHANGES): Note pytest plugin addition --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index 8f07354fa..f6c41ba9b 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,10 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ +### New features + +- Added a [pytest plugin](https://libtmux.git-pull.com/pytest-plugin.html), #411. + ### Breaking changes - Remove `common.which()` in favor of {func}`shutil.which`, Credit: From d152b8b671bf1e5b406abd9122166dce99dcedf6 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 08:44:12 -0500 Subject: [PATCH 0028/1073] ci(prettier): Revert line wrapping for now This reverts commit 71176d8a1aec7c27764d8ed49b306763ca9ec62e. --- .prettierrc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.prettierrc b/.prettierrc index 2d553cc6c..de753c537 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,3 @@ { - "printWidth": 100, - "proseWrap": 'always' + "printWidth": 100 } From 39f53b8e20c3f252f19ff2061d58b8dd09c9d922 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 08:47:12 -0500 Subject: [PATCH 0029/1073] Tag v0.15.0a2 --- libtmux/__about__.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libtmux/__about__.py b/libtmux/__about__.py index 8661fc83d..460f8ff6e 100644 --- a/libtmux/__about__.py +++ b/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.0a1" +__version__ = "0.15.0a2" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" diff --git a/pyproject.toml b/pyproject.toml index 069a9bab9..296ac6623 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.0a1" +version = "0.15.0a2" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] From 7841acecffbe6368c85acaa648f084571ad430c0 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 6 Sep 2022 21:08:14 -0500 Subject: [PATCH 0030/1073] build(deps): Remove sphinx-autoapi This makes locking much easier --- poetry.lock | 177 +------------------------------------------------ pyproject.toml | 1 - 2 files changed, 1 insertion(+), 177 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7caf59241..f8a4c815c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -6,20 +6,6 @@ category = "dev" optional = false python-versions = "*" -[[package]] -name = "astroid" -version = "2.11.7" -description = "An abstract syntax tree for Python with inference support." -category = "dev" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -lazy-object-proxy = ">=1.4.0" -typed-ast = {version = ">=1.4.0,<2.0", markers = "implementation_name == \"cpython\" and python_version < \"3.8\""} -typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} -wrapt = ">=1.11,<2" - [[package]] name = "attrs" version = "22.1.0" @@ -280,14 +266,6 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] -[[package]] -name = "lazy-object-proxy" -version = "1.7.1" -description = "A fast and thorough lazy object proxy." -category = "dev" -optional = false -python-versions = ">=3.6" - [[package]] name = "livereload" version = "2.6.3" @@ -666,26 +644,6 @@ docs = ["sphinxcontrib-websupport"] lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "isort", "mypy (>=0.971)", "sphinx-lint", "types-requests", "types-typed-ast"] test = ["cython", "html5lib", "pytest (>=4.6)", "typed-ast"] -[[package]] -name = "sphinx-autoapi" -version = "1.9.0" -description = "Sphinx API documentation generator" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -astroid = ">=2.7" -Jinja2 = "*" -PyYAML = "*" -sphinx = ">=3.0" -unidecode = "*" - -[package.extras] -docs = ["sphinx", "sphinx-rtd-theme"] -dotnet = ["sphinxcontrib-dotnetdomain"] -go = ["sphinxcontrib-golangdomain"] - [[package]] name = "sphinx-autobuild" version = "2021.3.14" @@ -907,14 +865,6 @@ category = "dev" optional = false python-versions = ">=3.7" -[[package]] -name = "unidecode" -version = "1.3.4" -description = "ASCII transliterations of Unicode text" -category = "dev" -optional = false -python-versions = ">=3.5" - [[package]] name = "urllib3" version = "1.26.12" @@ -939,14 +889,6 @@ python-versions = ">=3.6" [package.extras] watchmedo = ["PyYAML (>=3.10)"] -[[package]] -name = "wrapt" -version = "1.14.1" -description = "Module for decorators, wrappers and monkey patching." -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - [[package]] name = "zipp" version = "3.8.1" @@ -969,17 +911,13 @@ test = [] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "e00cb19fda6c088e0fa3a6427e8e59c11815f022273656df5f89e2a5216a3d89" +content-hash = "8e3aec114870c502cb2514d712abbff9aa92897df2d53aec0e98c2642e5b3926" [metadata.files] alabaster = [ {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, ] -astroid = [ - {file = "astroid-2.11.7-py3-none-any.whl", hash = "sha256:86b0a340a512c65abf4368b80252754cda17c02cdbbd3f587dddf98112233e7b"}, - {file = "astroid-2.11.7.tar.gz", hash = "sha256:bb24615c77f4837c707669d16907331374ae8a964650a66999da3f5ca68dc946"}, -] attrs = [ {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, @@ -1134,45 +1072,6 @@ jinja2 = [ {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, ] -lazy-object-proxy = [ - {file = "lazy-object-proxy-1.7.1.tar.gz", hash = "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-win32.whl", hash = "sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:46ff647e76f106bb444b4533bb4153c7370cdf52efc62ccfc1a28bdb3cc95442"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12f3bb77efe1367b2515f8cb4790a11cffae889148ad33adad07b9b55e0ab22c"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c19814163728941bb871240d45c4c30d33b8a2e85972c44d4e63dd7107faba44"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:e40f2013d96d30217a51eeb1db28c9ac41e9d0ee915ef9d00da639c5b63f01a1"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2052837718516a94940867e16b1bb10edb069ab475c3ad84fd1e1a6dd2c0fcfc"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win32.whl", hash = "sha256:6a24357267aa976abab660b1d47a34aaf07259a0c3859a34e536f1ee6e76b5bb"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:6aff3fe5de0831867092e017cf67e2750c6a1c7d88d84d2481bd84a2e019ec35"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6a6e94c7b02641d1311228a102607ecd576f70734dc3d5e22610111aeacba8a0"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ce15276a1a14549d7e81c243b887293904ad2d94ad767f42df91e75fd7b5b6"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e368b7f7eac182a59ff1f81d5f3802161932a41dc1b1cc45c1f757dc876b5d2c"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6ecbb350991d6434e1388bee761ece3260e5228952b1f0c46ffc800eb313ff42"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:553b0f0d8dbf21890dd66edd771f9b1b5f51bd912fa5f26de4449bfc5af5e029"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win32.whl", hash = "sha256:c7a683c37a8a24f6428c28c561c80d5f4fd316ddcf0c7cab999b15ab3f5c5c69"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:df2631f9d67259dc9620d831384ed7732a198eb434eadf69aea95ad18c587a28"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07fa44286cda977bd4803b656ffc1c9b7e3bc7dff7d34263446aec8f8c96f88a"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dca6244e4121c74cc20542c2ca39e5c4a5027c81d112bfb893cf0790f96f57e"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ba172fc5b03978764d1df5144b4ba4ab13290d7bab7a50f12d8117f8630c38"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:043651b6cb706eee4f91854da4a089816a6606c1428fd391573ef8cb642ae4f7"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b9e89b87c707dd769c4ea91f7a31538888aad05c116a59820f28d59b3ebfe25a"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-win32.whl", hash = "sha256:9d166602b525bf54ac994cf833c385bfcc341b364e3ee71e3bf5a1336e677b55"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:8f3953eb575b45480db6568306893f0bd9d8dfeeebd46812aa09ca9579595148"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dd7ed7429dbb6c494aa9bc4e09d94b778a3579be699f9d67da7e6804c422d3de"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70ed0c2b380eb6248abdef3cd425fc52f0abd92d2b07ce26359fcbc399f636ad"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7096a5e0c1115ec82641afbdd70451a144558ea5cf564a896294e346eb611be1"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f769457a639403073968d118bc70110e7dce294688009f5c24ab78800ae56dc8"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:39b0e26725c5023757fc1ab2a89ef9d7ab23b84f9251e28f9cc114d5b59c1b09"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-win32.whl", hash = "sha256:2130db8ed69a48a3440103d4a520b89d8a9405f1b06e2cc81640509e8bf6548f"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61"}, - {file = "lazy_object_proxy-1.7.1-pp37.pp38-none-any.whl", hash = "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84"}, -] livereload = [ {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, ] @@ -1382,10 +1281,6 @@ sphinx = [ {file = "Sphinx-5.1.1-py3-none-any.whl", hash = "sha256:309a8da80cb6da9f4713438e5b55861877d5d7976b69d87e336733637ea12693"}, {file = "Sphinx-5.1.1.tar.gz", hash = "sha256:ba3224a4e206e1fbdecf98a4fae4992ef9b24b85ebf7b584bb340156eaf08d89"}, ] -sphinx-autoapi = [ - {file = "sphinx-autoapi-1.9.0.tar.gz", hash = "sha256:c897ea337df16ad0cde307cbdfe2bece207788dde1587fa4fc8b857d1fc5dcba"}, - {file = "sphinx_autoapi-1.9.0-py2.py3-none-any.whl", hash = "sha256:d217953273b359b699d8cb81a5a72985a3e6e15cfe3f703d9a3c201ffc30849b"}, -] sphinx-autobuild = [ {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, {file = "sphinx_autobuild-2021.3.14-py3-none-any.whl", hash = "sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac"}, @@ -1493,10 +1388,6 @@ typing-extensions = [ {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, ] -unidecode = [ - {file = "Unidecode-1.3.4-py3-none-any.whl", hash = "sha256:afa04efcdd818a93237574791be9b2817d7077c25a068b00f8cff7baa4e59257"}, - {file = "Unidecode-1.3.4.tar.gz", hash = "sha256:8e4352fb93d5a735c788110d2e7ac8e8031eb06ccbfe8d324ab71735015f9342"}, -] urllib3 = [ {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, @@ -1528,72 +1419,6 @@ watchdog = [ {file = "watchdog-2.1.9-py3-none-win_ia64.whl", hash = "sha256:ad576a565260d8f99d97f2e64b0f97a48228317095908568a9d5c786c829d428"}, {file = "watchdog-2.1.9.tar.gz", hash = "sha256:43ce20ebb36a51f21fa376f76d1d4692452b2527ccd601950d69ed36b9e21609"}, ] -wrapt = [ - {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"}, - {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"}, - {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, - {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, - {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"}, - {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"}, - {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"}, - {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"}, - {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"}, - {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"}, - {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"}, - {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"}, - {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"}, - {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"}, - {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"}, - {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"}, - {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"}, - {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"}, - {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"}, - {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"}, - {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"}, - {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, -] zipp = [ {file = "zipp-3.8.1-py3-none-any.whl", hash = "sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009"}, {file = "zipp-3.8.1.tar.gz", hash = "sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2"}, diff --git a/pyproject.toml b/pyproject.toml index 296ac6623..170c1c6b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,7 +56,6 @@ sphinx-inline-tabs = { version = "*", python = "^3.7" } sphinxext-opengraph = "*" sphinx-copybutton = "*" sphinxext-rediraffe = "*" -sphinx-autoapi = "*" sphinx-autoissues = "*" myst_parser = "*" docutils = "~0.18.0" From 35fd5135591c11f19967b92e6a5f8fdb7fdf0f0b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 6 Sep 2022 21:08:57 -0500 Subject: [PATCH 0031/1073] build(deps): Add gp-libs Handles: - doctests in markdown - linkifying issues in changelog - rendering table of contents for sphinx.ext.autodoc directives And we can remove sphinx-autoapi --- poetry.lock | 18 +++++++++++++++++- pyproject.toml | 2 ++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index f8a4c815c..8d6c6e7f8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -197,6 +197,18 @@ pygments = "*" sphinx = ">=4.0,<6.0" sphinx-basic-ng = "*" +[[package]] +name = "gp-libs" +version = "0.0.1a9" +description = "Internal utilities for projects following git-pull python package spec" +category = "dev" +optional = false +python-versions = ">=3.7,<4.0" + +[package.dependencies] +docutils = ">=0.18.0,<0.19.0" +myst_parser = "*" + [[package]] name = "idna" version = "3.3" @@ -911,7 +923,7 @@ test = [] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "8e3aec114870c502cb2514d712abbff9aa92897df2d53aec0e98c2642e5b3926" +content-hash = "e1c5f5d6708250ba7f638da8b534906b3bbd7d15138b1e26027df218f8807a9f" [metadata.files] alabaster = [ @@ -1048,6 +1060,10 @@ furo = [ {file = "furo-2022.6.21-py3-none-any.whl", hash = "sha256:061b68e323345e27fcba024cf33a1e77f3dfd8d9987410be822749a706e2add6"}, {file = "furo-2022.6.21.tar.gz", hash = "sha256:9aa983b7488a4601d13113884bfb7254502c8729942e073a0acb87a5512af223"}, ] +gp-libs = [ + {file = "gp-libs-0.0.1a9.tar.gz", hash = "sha256:835608ba29220c4d77e7e3f5a9ae27368ac1eb4b43f0cd1e6cdec9c27e9a9e3a"}, + {file = "gp_libs-0.0.1a9-py3-none-any.whl", hash = "sha256:2c055bd65f0880325a800775a2ee4c23dacc9eb8a56408fdb665a66da7d38ed3"}, +] idna = [ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, diff --git a/pyproject.toml b/pyproject.toml index 170c1c6b7..03239b19c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,7 @@ python = "^3.7" ### Docs ### sphinx = "*" furo = "*" +gp-libs = "*" sphinx-autobuild = "*" sphinx-autodoc-typehints = "*" sphinx-click = "*" @@ -95,6 +96,7 @@ docs = [ "sphinxext-rediraffe", "myst_parser", "furo", + "gp-libs" ] test = ["pytest", "pytest-rerunfailures", "pytest-mock", "pytest-watcher"] coverage = ["codecov", "coverage", "pytest-cov"] From 72db710f6418b83daf97ca4a73b0be134e541239 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 6 Sep 2022 21:15:55 -0500 Subject: [PATCH 0032/1073] docs: Move to gp-lib modules Remove sphinx-autoapi, which has broken imports. The only purpose this module had was showing table of contents. The tradeoff was a lot of difficult to track, subtle bugs. Also move to linkify_issues. A much simpler and more concise issue linker. --- docs/conf.py | 15 ++++----------- docs/internals/test.md | 2 +- docs/pytest-plugin.md | 4 +--- docs/reference/common.md | 2 +- docs/reference/exceptions.md | 2 +- docs/reference/panes.md | 2 +- docs/reference/servers.md | 2 +- docs/reference/sessions.md | 2 +- docs/reference/windows.md | 2 +- 9 files changed, 12 insertions(+), 21 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 94c7f7fd6..3a8abd835 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -22,19 +22,19 @@ extensions = [ "sphinx.ext.autodoc", - "autoapi.extension", "sphinx.ext.intersphinx", "sphinx_autodoc_typehints", "sphinx.ext.todo", "sphinx.ext.linkcode", "sphinx.ext.napoleon", - "sphinx_autoissues", "sphinx_click.ext", # sphinx-click "sphinx_inline_tabs", "sphinx_copybutton", "sphinxext.opengraph", "sphinxext.rediraffe", "myst_parser", + "linkify_issues", + "sphinx_toctree_autodoc_fix", ] myst_enable_extensions = [ @@ -94,21 +94,14 @@ ] } -# sphinx-autoissues -issuetracker = "github" -issuetracker_project = about["__github__"].replace("https://github.com/", "") +# linkify_issues +issue_url_tpl = f'{about["__github__"]}/issues/{{issue_id}}' # sphinx.ext.autodoc autoclass_content = "both" autodoc_member_order = "bysource" autosummary_generate = True -# sphinx-autoapi -autoapi_type = "python" -autoapi_dirs = [project_root / "libtmux"] -autoapi_generate_api_docs = False # when fales, use directives -suppress_warnings = ["autoapi.python_import_resolution", "autoapi.not_readable"] - # sphinx-copybutton copybutton_prompt_text = ( r">>> |\.\.\. |> |\$ |\# | In \[\d*\]: | {2,5}\.\.\.: | {5,8}: " diff --git a/docs/internals/test.md b/docs/internals/test.md index f2984c095..8fbff818b 100644 --- a/docs/internals/test.md +++ b/docs/internals/test.md @@ -1,6 +1,6 @@ # Test helpers ```{eval-rst} -.. autoapimodule:: libtmux.test +.. automodule:: libtmux.test :members: ``` diff --git a/docs/pytest-plugin.md b/docs/pytest-plugin.md index 8f546f2e3..652eb532f 100644 --- a/docs/pytest-plugin.md +++ b/docs/pytest-plugin.md @@ -87,12 +87,10 @@ object lookups in the test grid. ## API reference ```{eval-rst} -.. autoapimodule:: libtmux.pytest_plugin +.. automodule:: libtmux.pytest_plugin :members: :inherited-members: :private-members: :show-inheritance: :member-order: bysource - :exclude-members: Server, TEST_SESSION_PREFIX, get_test_session_name, - namer, logger ``` diff --git a/docs/reference/common.md b/docs/reference/common.md index 47d0ce67c..8d15a0520 100644 --- a/docs/reference/common.md +++ b/docs/reference/common.md @@ -1,6 +1,6 @@ # Utilities ```{eval-rst} -.. autoapimodule:: libtmux.common +.. automodule:: libtmux.common :members: ``` diff --git a/docs/reference/exceptions.md b/docs/reference/exceptions.md index 74182e745..85ce1d2ec 100644 --- a/docs/reference/exceptions.md +++ b/docs/reference/exceptions.md @@ -1,6 +1,6 @@ # Exceptions ```{eval-rst} -.. autoapimodule:: libtmux.exc +.. automodule:: libtmux.exc :members: ``` diff --git a/docs/reference/panes.md b/docs/reference/panes.md index eca3b5ef5..383b4286f 100644 --- a/docs/reference/panes.md +++ b/docs/reference/panes.md @@ -10,7 +10,7 @@ [pty(4)]: https://www.freebsd.org/cgi/man.cgi?query=pty&sektion=4 ```{eval-rst} -.. autoapiclass:: libtmux.Pane +.. autoclass:: libtmux.Pane :members: :inherited-members: :private-members: diff --git a/docs/reference/servers.md b/docs/reference/servers.md index 2f754cd80..b87687842 100644 --- a/docs/reference/servers.md +++ b/docs/reference/servers.md @@ -10,7 +10,7 @@ tmux initializes a server on automatically on first running (e.g. executing `tmux`) ```{eval-rst} -.. autoapiclass:: libtmux.Server +.. autoclass:: libtmux.Server :members: :inherited-members: :private-members: diff --git a/docs/reference/sessions.md b/docs/reference/sessions.md index 08fce42c2..008d64df9 100644 --- a/docs/reference/sessions.md +++ b/docs/reference/sessions.md @@ -7,7 +7,7 @@ - Identified by `$`, e.g. `$313` ```{eval-rst} -.. autoapiclass:: libtmux.Session +.. autoclass:: libtmux.Session :members: :inherited-members: :private-members: diff --git a/docs/reference/windows.md b/docs/reference/windows.md index 7fe3514cb..728554b0d 100644 --- a/docs/reference/windows.md +++ b/docs/reference/windows.md @@ -11,7 +11,7 @@ ``` ```{eval-rst} -.. autoapiclass:: Window +.. autoclass:: Window :members: :inherited-members: :private-members: From fbc5e820784bdd397ce4f4a3eddc77ad77cafb36 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 6 Sep 2022 21:19:52 -0500 Subject: [PATCH 0033/1073] build(Makefile): Detect markdown files with make watch_test This makes it easier to QA doctest files via make watch_test --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c9609c7bc..fd60024a4 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ PY_FILES= find . -type f -not -path '*/\.*' | grep -i '.*[.]py$$' 2> /dev/null +DOC_FILES= find . -type f -not -path '*/\.*' | grep -i '.*[.]rst\$\|.*[.]md\$\|.*[.]css\$\|.*[.]py\$\|mkdocs\.yml\|CHANGES\|TODO\|.*conf\.py' 2> /dev/null +ALL_FILES= find . -type f -not -path '*/\.*' | grep -i '.*[.]py\$\|.*[.]rst\$\|.*[.]md\$\|.*[.]css\$\|.*[.]py\$\|mkdocs\.yml\|CHANGES\|TODO\|.*conf\.py' 2> /dev/null entr_warn: @@ -22,7 +24,7 @@ start: $(MAKE) test; poetry run ptw . watch_test: - if command -v entr > /dev/null; then ${PY_FILES} | entr -c $(MAKE) test; else $(MAKE) test entr_warn; fi + if command -v entr > /dev/null; then ${ALL_FILES} | entr -c $(MAKE) test; else $(MAKE) test entr_warn; fi build_docs: $(MAKE) -C docs html From fd7e81d86a01dc80bc95b33b3d36378f5dcd7c58 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 9 Sep 2022 07:07:01 -0500 Subject: [PATCH 0034/1073] docs(test): Update for gp-libs pytest module --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 309f2e3e0..7fd0a0140 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,7 +19,7 @@ line_length = 88 [tool:pytest] filterwarnings = ignore:.* Use packaging.version.*:DeprecationWarning:: -addopts = --tb=short --no-header --showlocals --doctest-modules --reruns 2 +addopts = --tb=short --no-header --showlocals --doctest-docutils-modules --reruns 2 -p no:doctest doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE testpaths = libtmux From a9f27f9cd230a674e2572bf1f39b3f14c056a597 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 09:32:35 -0500 Subject: [PATCH 0035/1073] ci(tests): Add cowsay for tests --- .github/workflows/tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 64b3ba367..5242ca6ca 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -68,6 +68,7 @@ jobs: export PATH=$HOME/tmux-builds/tmux-${{ matrix.tmux-version }}/bin:$PATH ls $HOME/tmux-builds/tmux-${{ matrix.tmux-version }}/bin tmux -V + sudo apt install cowsay poetry run py.test --cov=./ --cov-append --cov-report=xml env: COV_CORE_SOURCE: . From 55d93b0a0b9fef0f33f5b30f5cff4652017ab38c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 09:08:04 -0500 Subject: [PATCH 0036/1073] docs(README): Skip cowsay test --- README.md | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index b3ec76ad6..7f8c57583 100644 --- a/README.md +++ b/README.md @@ -157,19 +157,18 @@ Grab the output of pane: ```python >>> pane.clear() # clear the pane >>> pane.send_keys("cowsay 'hello'", enter=True) ->>> import time; time.sleep(1) ->>> print('\n'.join(pane.cmd('capture-pane', '-p').stdout)) -``` - - sh-3.2$ cowsay 'hello' - _______ - < hello > - ------- - \ ^__^ - \ (oo)\_______ - (__)\ )\/\ - ||----w | - || || +>>> print('\n'.join(pane.cmd('capture-pane', '-p').stdout)) # doctest: +SKIP +$ cowsay 'hello' + _______ +< hello > + ------- + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || +... +``` Traverse and navigate: From 207018d1f4077eaa21f60d1cc06662bc7901c53e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 10:09:31 -0500 Subject: [PATCH 0037/1073] docs(CHANGES): Note docs / tests --- CHANGES | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES b/CHANGES index f6c41ba9b..e07a90c6c 100644 --- a/CHANGES +++ b/CHANGES @@ -29,10 +29,18 @@ $ pip install --user --upgrade --pre libtmux - Add [flake8-bugbear](https://github.com/PyCQA/flake8-bugbear) (#408) - Add [flake8-comprehensions](https://github.com/adamchainz/flake8-comprehensions) (#409) +### Tests + +- Test doctests in documentation via + [pytest-doctest-docutils](https://gp-libs.git-pull.com/doctest/pytest.html) (#410) + ### Documentation - Move to sphinx-autoissues, #406 - Examples updated for correctness, #412 (cherry-picked from #410) +- Render changelog in [linkify_issues](https://gp-libs.git-pull.com/linkify_issues/) (#410) +- Fix Table of contents rendering with sphinx autodoc with + [sphinx_toctree_autodoc_fix](https://gp-libs.git-pull.com/sphinx_toctree_autodoc_fix/) (#410) ## libtmux 0.14.2 (2022-08-17) From cd4e81c3b50573cddef7f0cb3820cf92e1d80e25 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 10:13:09 -0500 Subject: [PATCH 0038/1073] Tag v0.15.0a3 --- libtmux/__about__.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libtmux/__about__.py b/libtmux/__about__.py index 460f8ff6e..f8b33971c 100644 --- a/libtmux/__about__.py +++ b/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.0a2" +__version__ = "0.15.0a3" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" diff --git a/pyproject.toml b/pyproject.toml index 03239b19c..b3331f6bc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.0a2" +version = "0.15.0a3" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] From ddead903a44a9c8b37b8f31a6bfc0039044aadaf Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 10:48:37 -0500 Subject: [PATCH 0039/1073] docs(pytest-plugin): Fix refs --- docs/pytest-plugin.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/pytest-plugin.md b/docs/pytest-plugin.md index 652eb532f..4c2ab3dad 100644 --- a/docs/pytest-plugin.md +++ b/docs/pytest-plugin.md @@ -52,13 +52,13 @@ These are fixtures are automatically used when the plugin is enabled and `pytest ## Setting a tmux configuration -If you would like :func:`session` fixture to automatically use a configuration, you have a few +If you would like {func}`session fixture ` to automatically use a configuration, you have a few options: -- Pass a `config_file` into :class:`libtmux.server.Server` +- Pass a `config_file` into {class}`~libtmux.Server` - Set the `HOME` directory to a local or temporary pytest path with a configurat configuration file -You could also read the code and override :func:`server`'s fixture in your own doctest. doctest. +You could also read the code and override {func}`server fixtures `'s in your own doctest. doctest. (set_home)= From 5cd0bfcf9b2de8c46a376100465dedbed0ccad2e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 10:54:20 -0500 Subject: [PATCH 0040/1073] docs: Remove unneeded docstring --- libtmux/common.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libtmux/common.py b/libtmux/common.py index b3db8344b..d914d536d 100644 --- a/libtmux/common.py +++ b/libtmux/common.py @@ -430,13 +430,6 @@ def get_by_id(self, id: str) -> Optional[O]: Returns ------- object - - Notes - ----- - Based on `.get()`_ from `backbone.js`_. - - .. _backbone.js: http://backbonejs.org/ - .. _.get(): http://backbonejs.org/#Collection-get """ for child in self.children: if child[self.child_id_attribute] == id: From 97f470887ac42458a59f3322a903cff93ee9edde Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 11:02:40 -0500 Subject: [PATCH 0041/1073] refactor!: Move libtmux to src/ --- {libtmux => src/libtmux}/__about__.py | 0 {libtmux => src/libtmux}/__init__.py | 0 {libtmux => src/libtmux}/_compat.py | 0 {libtmux => src/libtmux}/common.py | 0 {libtmux => src/libtmux}/conftest.py | 0 {libtmux => src/libtmux}/exc.py | 0 {libtmux => src/libtmux}/formats.py | 0 {libtmux => src/libtmux}/pane.py | 0 {libtmux => src/libtmux}/py.typed | 0 {libtmux => src/libtmux}/pytest_plugin.py | 0 {libtmux => src/libtmux}/server.py | 0 {libtmux => src/libtmux}/session.py | 0 {libtmux => src/libtmux}/test.py | 0 {libtmux => src/libtmux}/window.py | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename {libtmux => src/libtmux}/__about__.py (100%) rename {libtmux => src/libtmux}/__init__.py (100%) rename {libtmux => src/libtmux}/_compat.py (100%) rename {libtmux => src/libtmux}/common.py (100%) rename {libtmux => src/libtmux}/conftest.py (100%) rename {libtmux => src/libtmux}/exc.py (100%) rename {libtmux => src/libtmux}/formats.py (100%) rename {libtmux => src/libtmux}/pane.py (100%) rename {libtmux => src/libtmux}/py.typed (100%) rename {libtmux => src/libtmux}/pytest_plugin.py (100%) rename {libtmux => src/libtmux}/server.py (100%) rename {libtmux => src/libtmux}/session.py (100%) rename {libtmux => src/libtmux}/test.py (100%) rename {libtmux => src/libtmux}/window.py (100%) diff --git a/libtmux/__about__.py b/src/libtmux/__about__.py similarity index 100% rename from libtmux/__about__.py rename to src/libtmux/__about__.py diff --git a/libtmux/__init__.py b/src/libtmux/__init__.py similarity index 100% rename from libtmux/__init__.py rename to src/libtmux/__init__.py diff --git a/libtmux/_compat.py b/src/libtmux/_compat.py similarity index 100% rename from libtmux/_compat.py rename to src/libtmux/_compat.py diff --git a/libtmux/common.py b/src/libtmux/common.py similarity index 100% rename from libtmux/common.py rename to src/libtmux/common.py diff --git a/libtmux/conftest.py b/src/libtmux/conftest.py similarity index 100% rename from libtmux/conftest.py rename to src/libtmux/conftest.py diff --git a/libtmux/exc.py b/src/libtmux/exc.py similarity index 100% rename from libtmux/exc.py rename to src/libtmux/exc.py diff --git a/libtmux/formats.py b/src/libtmux/formats.py similarity index 100% rename from libtmux/formats.py rename to src/libtmux/formats.py diff --git a/libtmux/pane.py b/src/libtmux/pane.py similarity index 100% rename from libtmux/pane.py rename to src/libtmux/pane.py diff --git a/libtmux/py.typed b/src/libtmux/py.typed similarity index 100% rename from libtmux/py.typed rename to src/libtmux/py.typed diff --git a/libtmux/pytest_plugin.py b/src/libtmux/pytest_plugin.py similarity index 100% rename from libtmux/pytest_plugin.py rename to src/libtmux/pytest_plugin.py diff --git a/libtmux/server.py b/src/libtmux/server.py similarity index 100% rename from libtmux/server.py rename to src/libtmux/server.py diff --git a/libtmux/session.py b/src/libtmux/session.py similarity index 100% rename from libtmux/session.py rename to src/libtmux/session.py diff --git a/libtmux/test.py b/src/libtmux/test.py similarity index 100% rename from libtmux/test.py rename to src/libtmux/test.py diff --git a/libtmux/window.py b/src/libtmux/window.py similarity index 100% rename from libtmux/window.py rename to src/libtmux/window.py From 1957f34c98310b0a89deb8276bddc03663f4c2c3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 11:03:17 -0500 Subject: [PATCH 0042/1073] build(pyproject): Move libtmux to src/ --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b3331f6bc..0952659c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ keywords = ["tmux", "session manager", "terminal", "ncurses"] homepage = "http://github.com/tmux-python/libtmux/" readme = "README.md" packages = [ - { include = "libtmux" }, + { include = "*", from = "src" }, ] include = [ { path = "CHANGES", format = "sdist" }, From 0e8a506776b515703140bf690d71f1efad2383e3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 11:05:03 -0500 Subject: [PATCH 0043/1073] docs(conf): Update for src/ move --- docs/conf.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 3a8abd835..f5d81447b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,13 +11,14 @@ # Get the project root dir, which is the parent dir of this cwd = Path(__file__).parent project_root = cwd.parent +project_src = project_root / "src" -sys.path.insert(0, str(project_root)) +sys.path.insert(0, str(project_src)) sys.path.insert(0, str(cwd / "_ext")) # package data about: Dict[str, str] = {} -with open(project_root / "libtmux" / "__about__.py") as fp: +with open(project_src / "libtmux" / "__about__.py") as fp: exec(fp.read(), about) extensions = [ From d8e72521b6d19d95200e66ec06123263775d597b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 11:10:19 -0500 Subject: [PATCH 0044/1073] ci(pytest): Update testpaths for src/ --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 7fd0a0140..921540d5a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -22,6 +22,6 @@ filterwarnings = addopts = --tb=short --no-header --showlocals --doctest-docutils-modules --reruns 2 -p no:doctest doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE testpaths = - libtmux + src/libtmux tests docs From 03a7a9e883c0dddb80217a23291141a5b9c37dc4 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 11:10:43 -0500 Subject: [PATCH 0045/1073] docs(flake8): Use src directory --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 921540d5a..2547e7343 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [flake8] -exclude = .*/,*.egg,libtmux/_compat.py,libtmux/__*__.py +exclude = .*/,*.egg,src/libtmux/_compat.py,src/libtmux/__*__.py select = E,W,F,N max-line-length = 88 # Stuff we ignore thanks to black: https://github.com/ambv/black/issues/429 From 778ceebb33f137373d8096413eefac2eb3df03de Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 11:17:03 -0500 Subject: [PATCH 0046/1073] docs(CHANGES): Note move to src/ --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index e07a90c6c..892d74050 100644 --- a/CHANGES +++ b/CHANGES @@ -23,6 +23,7 @@ $ pip install --user --upgrade --pre libtmux - Fixes #402: {func}`common.tmux_cmd` will only strip _trailing_ empty lines. Before this change, all empty lines were filtered out. This will lead to a more accurate behavior when using {meth}`Pane.capture_pane`. Credit: @rockandska, via #405. +- Source files for `libtmux` modules moved to `src/`, via #414. ### Development From 0955b4c00dc5bf861646f136af0395fcd39324f8 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 11:18:00 -0500 Subject: [PATCH 0047/1073] Tag v0.15.0a4 (move to src/ layout) --- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0952659c3..ee444b87d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.0a3" +version = "0.15.0a4" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index f8b33971c..f9dba0e1a 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.0a3" +__version__ = "0.15.0a4" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From 87a523cb29ea5533d8ab6679f5e75183d25990e7 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 16:55:15 -0500 Subject: [PATCH 0048/1073] Tag v0.15.0 --- CHANGES | 4 +++- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 892d74050..b69c933c8 100644 --- a/CHANGES +++ b/CHANGES @@ -8,10 +8,12 @@ To install the unreleased libtmux version, see [developmental releases](https:// $ pip install --user --upgrade --pre libtmux ``` -## libtmux 0.15.x (unreleased) +## libtmux 0.16.x (unreleased) - _Insert changes/features/fixes for next release here_ +## libtmux 0.15.0 (2022-09-10) + ### New features - Added a [pytest plugin](https://libtmux.git-pull.com/pytest-plugin.html), #411. diff --git a/pyproject.toml b/pyproject.toml index ee444b87d..4a683401a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.0a4" +version = "0.15.0" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index f9dba0e1a..e8018a1a7 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.0a4" +__version__ = "0.15.0" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From 780939dc885e05623800a0697428dd05b219265d Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 21:04:26 -0500 Subject: [PATCH 0049/1073] docs(README): Fix doctest --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7f8c57583..e71025bbd 100644 --- a/README.md +++ b/README.md @@ -92,10 +92,10 @@ Session($1 foo) Control your session: ```python -# Assign session to `session`: ->>> session = server.find_where({ "session_name": "foo" }) +>>> session.rename_session('foo') +Session($1 foo) >>> session.new_window(attach=False, window_name="ha in the bg") -Window(@8 2:ha in the bg, Session($3 foo)) +Window(@2 2:ha in the bg, Session($1 foo)) >>> session.kill_window("ha in") ``` From 0a189b7e31cf2466cad58d17e595690fb58053c9 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Sep 2022 21:21:54 -0500 Subject: [PATCH 0050/1073] Tag v0.15.0post0 --- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4a683401a..e2a6dfc75 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.0" +version = "0.15.0post0" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index e8018a1a7..2debfe131 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.0" +__version__ = "0.15.0post0" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From 9fa6caa8f1746a6ddea5a80d0114ebfb245ba216 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 11 Sep 2022 06:48:08 -0500 Subject: [PATCH 0051/1073] docs(conf): Remove autosummary_generate --- docs/conf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index f5d81447b..fce70e2c0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -101,7 +101,6 @@ # sphinx.ext.autodoc autoclass_content = "both" autodoc_member_order = "bysource" -autosummary_generate = True # sphinx-copybutton copybutton_prompt_text = ( From 82ef481dd62e34bda9ff392841edea3a85021d03 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 11 Sep 2022 07:27:26 -0500 Subject: [PATCH 0052/1073] build(deps): Remove old issues package --- CHANGES | 1 - poetry.lock | 14 +------------- pyproject.toml | 2 -- 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/CHANGES b/CHANGES index b69c933c8..781d688ab 100644 --- a/CHANGES +++ b/CHANGES @@ -39,7 +39,6 @@ $ pip install --user --upgrade --pre libtmux ### Documentation -- Move to sphinx-autoissues, #406 - Examples updated for correctness, #412 (cherry-picked from #410) - Render changelog in [linkify_issues](https://gp-libs.git-pull.com/linkify_issues/) (#410) - Fix Table of contents rendering with sphinx autodoc with diff --git a/poetry.lock b/poetry.lock index 8d6c6e7f8..8adb44e5d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -687,14 +687,6 @@ Sphinx = ">=5.1.1" testing = ["covdefaults (>=2.2)", "coverage (>=6.4.2)", "diff-cover (>=6.5.1)", "nptyping (>=2.2)", "pytest (>=7.1.2)", "pytest-cov (>=3)", "sphobjinv (>=2.2.2)", "typing-extensions (>=4.3)"] type_comments = ["typed-ast (>=1.5.4)"] -[[package]] -name = "sphinx-autoissues" -version = "0.0.1" -description = "Sphinx integration with different issuetrackers" -category = "dev" -optional = false -python-versions = ">=3.7,<4.0" - [[package]] name = "sphinx-basic-ng" version = "0.0.1a12" @@ -923,7 +915,7 @@ test = [] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "e1c5f5d6708250ba7f638da8b534906b3bbd7d15138b1e26027df218f8807a9f" +content-hash = "e02be5b316b8c1d108beb01470d942c1fbdb5795130b10c62e41b2bef2c85904" [metadata.files] alabaster = [ @@ -1305,10 +1297,6 @@ sphinx-autodoc-typehints = [ {file = "sphinx_autodoc_typehints-1.19.2-py3-none-any.whl", hash = "sha256:3d761de928d5a86901331133d6d4a2552afa2e798ebcfc0886791792aeb4dd9a"}, {file = "sphinx_autodoc_typehints-1.19.2.tar.gz", hash = "sha256:872fb2d7b3d794826c28e36edf6739e93549491447dcabeb07c58855e9f914de"}, ] -sphinx-autoissues = [ - {file = "sphinx-autoissues-0.0.1.tar.gz", hash = "sha256:a308fd914d700ff2aa2b4584c29975a030ede7171898130ec816eca7ec2c8ce8"}, - {file = "sphinx_autoissues-0.0.1-py3-none-any.whl", hash = "sha256:07503b774c3a64b97d2614fa409410316fbfeb87ba4553dbe3a7d2131b7453a0"}, -] sphinx-basic-ng = [ {file = "sphinx_basic_ng-0.0.1a12-py3-none-any.whl", hash = "sha256:e8b6efd2c5ece014156de76065eda01ddfca0fee465aa020b1e3c12f84570bbe"}, {file = "sphinx_basic_ng-0.0.1a12.tar.gz", hash = "sha256:cffffb14914ddd26c94b1330df1d72dab5a42e220aaeb5953076a40b9c50e801"}, diff --git a/pyproject.toml b/pyproject.toml index e2a6dfc75..12c59e78e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,7 +57,6 @@ sphinx-inline-tabs = { version = "*", python = "^3.7" } sphinxext-opengraph = "*" sphinx-copybutton = "*" sphinxext-rediraffe = "*" -sphinx-autoissues = "*" myst_parser = "*" docutils = "~0.18.0" @@ -89,7 +88,6 @@ docs = [ "sphinx-autoapi", "sphinx-autodoc-typehints", "sphinx-autobuild", - "sphinx-autoissues", "sphinx-copybutton", "sphinxext-opengraph", "sphinx-inline-tabs", From 4dab4efce589fc75b6b44f13637090ca5b32e065 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 11 Sep 2022 07:28:41 -0500 Subject: [PATCH 0053/1073] build(pyproject): Remove unused package specifier and re-lock --- poetry.lock | 2 +- pyproject.toml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 8adb44e5d..900127dc3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -915,7 +915,7 @@ test = [] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "e02be5b316b8c1d108beb01470d942c1fbdb5795130b10c62e41b2bef2c85904" +content-hash = "8d3b35942a6fa00bd31c365d691c1dfc82966a6b841478dbb894f88499bc9116" [metadata.files] alabaster = [ diff --git a/pyproject.toml b/pyproject.toml index 12c59e78e..9642fd236 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -85,7 +85,6 @@ mypy = "*" docs = [ "docutils", "sphinx", - "sphinx-autoapi", "sphinx-autodoc-typehints", "sphinx-autobuild", "sphinx-copybutton", From ce537369051eb85f8c31d761e789ce02593244b6 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 11 Sep 2022 07:29:17 -0500 Subject: [PATCH 0054/1073] docs(index): Remove unused toc entry --- docs/index.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index ed92e5ade..6df2dd637 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,7 +19,6 @@ quickstart about topics/index reference/index -api ``` From 6cbb6e0881243fad2c63155390ac045024a08cdd Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 11 Sep 2022 07:31:28 -0500 Subject: [PATCH 0055/1073] docs(quickstart): Cleanup --- docs/quickstart.md | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/docs/quickstart.md b/docs/quickstart.md index 8d8b19350..749c4cb95 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -15,8 +15,6 @@ from inside a live tmux session. - [tmux] - [pip] - for this handbook's examples -[pip]: https://pip.pypa.io/en/stable/installing/ - [tmux]: https://tmux.github.io/ (installation)= @@ -76,27 +74,19 @@ Session name `-s`: `foo` ::: -```{eval-rst} -.. todo:: Do a version of this with `sliderepl`_ - -``` - ```console - $ python - ``` For commandline completion, you can also use [ptpython]. ```console - $ pip install --user ptpython -$ ptpython - ``` -[ptpython]: https://github.com/prompt-toolkit/ptpython +```console +$ ptpython +``` ```{module} libtmux @@ -170,7 +160,6 @@ You may `session = server.get_by_id('$')` to use the session object. ## Get session by name / other properties ```python -# Just for setting up the example: >>> server.sessions[0].rename_session('foo') Session($1 foo) @@ -186,7 +175,6 @@ through Windows and Panes, respectively. So you may now use: ```python -# Prepping the example: >>> server.sessions[0].rename_session('foo') Session($1 foo) @@ -251,9 +239,8 @@ Window(@2 ...:ha in the bg, Session($1 ...)) Try to kill the window by the matching id `@[0-9999]`. ```python -# Setup >>> session.new_window(attach=False, window_name="ha in the bg") -Window(@1 ...:ha in the bg, Session($1 ...)) +Window(@2 ...:ha in the bg, Session($1 ...)) >>> session.kill_window('ha in the bg') ``` @@ -387,11 +374,10 @@ sessions in the background. :) :::{seealso} If you want to dig deeper, check out {ref}`API`, the code for -and our [test suite] (see {ref}`developing`.) +and our [test suite] (see {ref}`development`.) ::: -[sliderepl]: http://discorporate.us/projects/sliderepl/ [workspacebuilder.py]: https://github.com/tmux-python/libtmux/blob/master/libtmux/workspacebuilder.py [test suite]: https://github.com/tmux-python/libtmux/tree/master/tests -[ptpython]: https://github.com/jonathanslenders/ptpython +[ptpython]: https://github.com/prompt-toolkit/ptpython From af15b08f4283e91e758a47f4a1a21143c1f5cd16 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 11 Sep 2022 10:54:25 -0500 Subject: [PATCH 0056/1073] Tag v0.15.1 (packaging cleanup) --- CHANGES | 10 ++++++++++ poetry.lock | 6 +++--- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 781d688ab..36896108a 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,16 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ +## libtmux 0.15.1 (2022-09-11) + +### Packaging + +- pyproject.toml: Drop old issues package, remove anther package from grouping + +### Documentation + +- Cleanup quickstart page + ## libtmux 0.15.0 (2022-09-10) ### New features diff --git a/poetry.lock b/poetry.lock index 900127dc3..908539818 100644 --- a/poetry.lock +++ b/poetry.lock @@ -199,7 +199,7 @@ sphinx-basic-ng = "*" [[package]] name = "gp-libs" -version = "0.0.1a9" +version = "0.0.1a10" description = "Internal utilities for projects following git-pull python package spec" category = "dev" optional = false @@ -1053,8 +1053,8 @@ furo = [ {file = "furo-2022.6.21.tar.gz", hash = "sha256:9aa983b7488a4601d13113884bfb7254502c8729942e073a0acb87a5512af223"}, ] gp-libs = [ - {file = "gp-libs-0.0.1a9.tar.gz", hash = "sha256:835608ba29220c4d77e7e3f5a9ae27368ac1eb4b43f0cd1e6cdec9c27e9a9e3a"}, - {file = "gp_libs-0.0.1a9-py3-none-any.whl", hash = "sha256:2c055bd65f0880325a800775a2ee4c23dacc9eb8a56408fdb665a66da7d38ed3"}, + {file = "gp-libs-0.0.1a10.tar.gz", hash = "sha256:54fbe07f42628b114f0b1472bb03ce75be2928090ec26d8d6f675f3bd9f58c2e"}, + {file = "gp_libs-0.0.1a10-py3-none-any.whl", hash = "sha256:701b190ffd468ca4d776b196707344748dd550aea03db9aaa1ffdecdd0c32506"}, ] idna = [ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, diff --git a/pyproject.toml b/pyproject.toml index 9642fd236..7301776c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.0post0" +version = "0.15.1" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index 2debfe131..a0e0340bb 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.0post0" +__version__ = "0.15.1" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From 3766d8141438e8b5bbbd6577b091abe8487a251e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 11 Sep 2022 11:29:05 -0500 Subject: [PATCH 0057/1073] docs(conf): Fix source links for src/ layout Follow up to #414 change --- docs/conf.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index fce70e2c0..0c8b08fe1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -217,16 +217,18 @@ def linkcode_resolve( fn = relpath(fn, start=dirname(libtmux.__file__)) if "dev" in about["__version__"]: - return "{}/blob/master/{}/{}{}".format( + return "{}/blob/master/{}/{}/{}{}".format( about["__github__"], + "src", about["__package_name__"], fn, linespec, ) else: - return "{}/blob/v{}/{}/{}{}".format( + return "{}/blob/v{}/{}/{}/{}{}".format( about["__github__"], about["__version__"], + "src", about["__package_name__"], fn, linespec, From 141cdb0a44597c2c4b7d3ae982c8ba919b49e388 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 11 Sep 2022 16:42:51 -0500 Subject: [PATCH 0058/1073] build(metadata): Add pytest framework classifier --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 7301776c0..994d6125b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,7 @@ classifiers = [ "Operating System :: POSIX", "Operating System :: MacOS :: MacOS X", "Environment :: Web Environment", + "Framework :: Pytest", "Intended Audience :: Developers", "Programming Language :: Python", "Programming Language :: Python :: 3.7", From 49b9d6cc50fd397158b3035868fa045cc695a0b1 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 11 Sep 2022 16:44:23 -0500 Subject: [PATCH 0059/1073] docs(CHANGES): Note pyproject.toml update --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index 36896108a..0b0c65c3a 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,10 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ +### Packaging + +- pyproject.toml: Note pytest framework in trove classifiers + ## libtmux 0.15.1 (2022-09-11) ### Packaging From 65d2e8ce8b08fa6c33456f28f16376bf7ddaf50c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 11 Sep 2022 21:50:31 -0500 Subject: [PATCH 0060/1073] tests(conftest): Add pytester plugin For testing pytest plugin --- tests/conftest.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index 62571f546..ec9aaf09f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1 +1,3 @@ from libtmux.conftest import * # NOQA: F4 + +pytest_plugins = ["pytester"] From 69e737711c3857d136c3c70cab080e34faf88465 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 11 Sep 2022 21:55:23 -0500 Subject: [PATCH 0061/1073] tests(pytest_plugin): Initial tests for plugin --- tests/test_pytest_plugin.py | 69 +++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 tests/test_pytest_plugin.py diff --git a/tests/test_pytest_plugin.py b/tests/test_pytest_plugin.py new file mode 100644 index 000000000..b165806e3 --- /dev/null +++ b/tests/test_pytest_plugin.py @@ -0,0 +1,69 @@ +import textwrap + +import pytest + +import _pytest.pytester + + +def test_plugin( + pytester: _pytest.pytester.Pytester, + monkeypatch: pytest.MonkeyPatch, +) -> None: + # Initialize variables + pytester.plugins = ["pytest_plugin"] + pytester.makefile( + ".ini", + pytest=textwrap.dedent( + """ +[pytest] +addopts=-vv + """.strip() + ), + ) + pytester.makeconftest( + textwrap.dedent( + r""" +import pathlib +import pytest + +@pytest.fixture(autouse=True) +def setup( + request: pytest.FixtureRequest, +) -> None: + pass + """ + ) + ) + tests_path = pytester.path / "tests" + files = { + "example.py": textwrap.dedent( + """ +import pathlib + +def test_repo_git_remote_checkout( + session, +) -> None: + assert session.name is not None + + assert session._session_id == "$1" + + new_window = session.new_window(attach=False, window_name="my window name") + assert new_window.name == "my window name" + """ + ) + } + first_test_key = list(files.keys())[0] + first_test_filename = str(tests_path / first_test_key) + + # Setup: Files + tests_path.mkdir() + for file_name, text in files.items(): + test_file = tests_path / file_name + test_file.write_text( + text, + encoding="utf-8", + ) + + # Test + result = pytester.runpytest(str(first_test_filename)) + result.assert_outcomes(passed=1) From 124cb524e32c60f8ec5218f39dcc5b822ab96bb9 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 11 Sep 2022 21:59:07 -0500 Subject: [PATCH 0062/1073] docs(CHANGES): Note testing of pytest plugin --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index 0b0c65c3a..2eacc56b6 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,10 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ +### Tests + +- pytest plugin: Initial tests (for testing the plugin itself, #423) + ### Packaging - pyproject.toml: Note pytest framework in trove classifiers From b41d0bd9736c20ab2201c0af8468c149309989a7 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 14 Sep 2022 07:06:04 -0500 Subject: [PATCH 0063/1073] build(deps): Update certifi, flake-bugbear, idna --- poetry.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/poetry.lock b/poetry.lock index 908539818..7e1869382 100644 --- a/poetry.lock +++ b/poetry.lock @@ -71,7 +71,7 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2022.6.15.1" +version = "2022.6.15.2" description = "Python package for providing Mozilla's CA Bundle." category = "dev" optional = false @@ -158,7 +158,7 @@ pyflakes = ">=2.3.0,<2.4.0" [[package]] name = "flake8-bugbear" -version = "22.8.23" +version = "22.9.11" description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." category = "dev" optional = false @@ -211,7 +211,7 @@ myst_parser = "*" [[package]] name = "idna" -version = "3.3" +version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" category = "dev" optional = false @@ -960,8 +960,8 @@ black = [ {file = "black-22.8.0.tar.gz", hash = "sha256:792f7eb540ba9a17e8656538701d3eb1afcb134e3b45b71f20b25c77a8db7e6e"}, ] certifi = [ - {file = "certifi-2022.6.15.1-py3-none-any.whl", hash = "sha256:43dadad18a7f168740e66944e4fa82c6611848ff9056ad910f8f7a3e46ab89e0"}, - {file = "certifi-2022.6.15.1.tar.gz", hash = "sha256:cffdcd380919da6137f76633531a5817e3a9f268575c128249fb637e4f9e73fb"}, + {file = "certifi-2022.6.15.2-py3-none-any.whl", hash = "sha256:0aa1a42fbd57645fabeb6290a7687c21755b0344ecaeaa05f4e9f6207ae2e9a8"}, + {file = "certifi-2022.6.15.2.tar.gz", hash = "sha256:aa08c101214127b9b0472ca6338315113c9487d45376fd3e669201b477c71003"}, ] charset-normalizer = [ {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, @@ -1041,8 +1041,8 @@ flake8 = [ {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, ] flake8-bugbear = [ - {file = "flake8-bugbear-22.8.23.tar.gz", hash = "sha256:de0717d11124a082118dd08387b34fd86b2721642ec2d8e92be66cfa5ea7c445"}, - {file = "flake8_bugbear-22.8.23-py3-none-any.whl", hash = "sha256:1b0ebe0873d1cd55bf9f1588bfcb930db339018ef44a3981a26532daa9fd14a8"}, + {file = "flake8-bugbear-22.9.11.tar.gz", hash = "sha256:39236c0e97160d1ab05d9f87422173d16e925a6220b3635bfc4aee766bf8194a"}, + {file = "flake8_bugbear-22.9.11-py3-none-any.whl", hash = "sha256:e74350a4cfc670e184f3433c223b1e7378f1cf8345ded6c8f12ac1a50c5df22b"}, ] flake8-comprehensions = [ {file = "flake8-comprehensions-3.10.0.tar.gz", hash = "sha256:181158f7e7aa26a63a0a38e6017cef28c6adee71278ce56ce11f6ec9c4905058"}, @@ -1057,8 +1057,8 @@ gp-libs = [ {file = "gp_libs-0.0.1a10-py3-none-any.whl", hash = "sha256:701b190ffd468ca4d776b196707344748dd550aea03db9aaa1ffdecdd0c32506"}, ] idna = [ - {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, - {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] imagesize = [ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, From f01e0d600077c350983cc4094025dfa5b25c84b3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 15 Sep 2022 21:00:14 -0500 Subject: [PATCH 0064/1073] build(deps): Bump certifi and furo --- poetry.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7e1869382..918464ae8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -71,7 +71,7 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2022.6.15.2" +version = "2022.9.14" description = "Python package for providing Mozilla's CA Bundle." category = "dev" optional = false @@ -185,7 +185,7 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [[package]] name = "furo" -version = "2022.6.21" +version = "2022.9.15" description = "A clean customisable Sphinx documentation theme." category = "dev" optional = false @@ -193,7 +193,7 @@ python-versions = ">=3.7" [package.dependencies] beautifulsoup4 = "*" -pygments = "*" +pygments = ">=2.7" sphinx = ">=4.0,<6.0" sphinx-basic-ng = "*" @@ -960,8 +960,8 @@ black = [ {file = "black-22.8.0.tar.gz", hash = "sha256:792f7eb540ba9a17e8656538701d3eb1afcb134e3b45b71f20b25c77a8db7e6e"}, ] certifi = [ - {file = "certifi-2022.6.15.2-py3-none-any.whl", hash = "sha256:0aa1a42fbd57645fabeb6290a7687c21755b0344ecaeaa05f4e9f6207ae2e9a8"}, - {file = "certifi-2022.6.15.2.tar.gz", hash = "sha256:aa08c101214127b9b0472ca6338315113c9487d45376fd3e669201b477c71003"}, + {file = "certifi-2022.9.14-py3-none-any.whl", hash = "sha256:e232343de1ab72c2aa521b625c80f699e356830fd0e2c620b465b304b17b0516"}, + {file = "certifi-2022.9.14.tar.gz", hash = "sha256:36973885b9542e6bd01dea287b2b4b3b21236307c56324fcc3f1160f2d655ed5"}, ] charset-normalizer = [ {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, @@ -1049,8 +1049,8 @@ flake8-comprehensions = [ {file = "flake8_comprehensions-3.10.0-py3-none-any.whl", hash = "sha256:dad454fd3d525039121e98fa1dd90c46bc138708196a4ebbc949ad3c859adedb"}, ] furo = [ - {file = "furo-2022.6.21-py3-none-any.whl", hash = "sha256:061b68e323345e27fcba024cf33a1e77f3dfd8d9987410be822749a706e2add6"}, - {file = "furo-2022.6.21.tar.gz", hash = "sha256:9aa983b7488a4601d13113884bfb7254502c8729942e073a0acb87a5512af223"}, + {file = "furo-2022.9.15-py3-none-any.whl", hash = "sha256:9129dead1f75e9fb4fa407612f1d5a0d0320767e6156c925aafe36f362f9b11a"}, + {file = "furo-2022.9.15.tar.gz", hash = "sha256:4a7ef1c8a3b615171592da4d2ad8a53cc4aacfbe111958890f5f9ff7279066ab"}, ] gp-libs = [ {file = "gp-libs-0.0.1a10.tar.gz", hash = "sha256:54fbe07f42628b114f0b1472bb03ce75be2928090ec26d8d6f675f3bd9f58c2e"}, From ea31e1f882b76ad4f85d916af6096c96d024a245 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 16 Sep 2022 18:53:18 -0500 Subject: [PATCH 0065/1073] chore: Remove unused import --- src/libtmux/common.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libtmux/common.py b/src/libtmux/common.py index d914d536d..b4465425e 100644 --- a/src/libtmux/common.py +++ b/src/libtmux/common.py @@ -6,7 +6,6 @@ """ import logging -import os import re import shutil import subprocess From 356e5e6e0880f92e2e43207c5cf92498eea0a996 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 17 Sep 2022 05:39:04 -0500 Subject: [PATCH 0066/1073] build(ci): Python 3.7.13 --- .python-version | 2 +- .tool-versions | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.python-version b/.python-version index ad0e6c1a4..9020162ba 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.10.6 3.9.13 3.8.13 3.7.12 +3.10.6 3.9.13 3.8.13 3.7.13 diff --git a/.tool-versions b/.tool-versions index f9d413269..fbc6993bc 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ poetry 1.1.15 -python 3.10.6 3.9.13 3.8.13 3.7.12 +python 3.10.6 3.9.13 3.8.13 3.7.13 From f1e1ad1b2e2d12826b1f72005d61b1d6765bc6b1 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 17 Sep 2022 09:52:51 -0500 Subject: [PATCH 0067/1073] ci(tests): Remove cowsay, unused --- .github/workflows/tests.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5242ca6ca..64b3ba367 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -68,7 +68,6 @@ jobs: export PATH=$HOME/tmux-builds/tmux-${{ matrix.tmux-version }}/bin:$PATH ls $HOME/tmux-builds/tmux-${{ matrix.tmux-version }}/bin tmux -V - sudo apt install cowsay poetry run py.test --cov=./ --cov-append --cov-report=xml env: COV_CORE_SOURCE: . From 1d42c81d6b0c3ac0f7ed7f4f402f969098044f73 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 17 Sep 2022 09:50:53 -0500 Subject: [PATCH 0068/1073] ci(tests): Split out pypi release to avoid docker pull --- .github/workflows/tests.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 64b3ba367..938f07528 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -77,6 +77,27 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} + release: + runs-on: ubuntu-latest + needs: build + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + + strategy: + matrix: + python-version: ["3.10"] + + steps: + - uses: actions/checkout@v3 + + - name: Install poetry + run: pipx install "poetry==1.1.15" + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache: 'poetry' + - name: Build package if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') run: poetry build From 96f025864430a8d949960be7c7d8ee012b795fa4 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 17 Sep 2022 10:13:28 -0500 Subject: [PATCH 0069/1073] docs(CHANGES): Note CI Speedup / tweak --- CHANGES | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGES b/CHANGES index 2eacc56b6..7ca1d4973 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,10 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ +## libtmux 0.15.x (unreleased) + +**Maintenance release, no features or fixes** + ### Tests - pytest plugin: Initial tests (for testing the plugin itself, #423) @@ -20,6 +24,14 @@ $ pip install --user --upgrade --pre libtmux - pyproject.toml: Note pytest framework in trove classifiers +### Infrastructure + +- CI speedups (#428) + + - Avoid fetching unused apt package + - Split out release to separate job so the PyPI Upload docker image isn't pulled on normal + runs + ## libtmux 0.15.1 (2022-09-11) ### Packaging From c58f645a8508497d01a564dd6af7da126adecfd3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 17 Sep 2022 10:15:06 -0500 Subject: [PATCH 0070/1073] Tag v0.15.2a0 (test CI release tweak from #428) --- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 994d6125b..585aa5f62 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.1" +version = "0.15.2a0" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index a0e0340bb..2be93454b 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.1" +__version__ = "0.15.2a0" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From 0fa500a8c342d95167ce6a77f0dd5409c679b5c9 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 17 Sep 2022 10:26:10 -0500 Subject: [PATCH 0071/1073] ci(codeql): Clean up comments, bump versions --- .github/workflows/codeql-analysis.yml | 47 +++------------------------ 1 file changed, 5 insertions(+), 42 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 02c7e1688..5da69bd96 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,21 +1,9 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# name: "CodeQL" on: push: branches: [ master ] pull_request: - # The branches below must be a subset of the branches above branches: [ master ] schedule: - cron: '16 5 * * 2' @@ -29,42 +17,17 @@ jobs: contents: read security-events: write - strategy: - fail-fast: false - matrix: - language: [ 'python' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://git.io/codeql-language-support - steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main + languages: "python" - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release + uses: github/codeql-action/autobuild@v2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 From 31b94282efc9d8845c9a395619475beb7f804721 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 17 Sep 2022 11:07:08 -0500 Subject: [PATCH 0072/1073] Tag v0.15.2 --- CHANGES | 2 +- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 7ca1d4973..b29eb230f 100644 --- a/CHANGES +++ b/CHANGES @@ -12,7 +12,7 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ -## libtmux 0.15.x (unreleased) +## libtmux 0.15.2 (2022-09-17) **Maintenance release, no features or fixes** diff --git a/pyproject.toml b/pyproject.toml index 585aa5f62..9c1cd0e91 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.2a0" +version = "0.15.2" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index 2be93454b..c5f8d9461 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.2a0" +__version__ = "0.15.2" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From 47b721a124a31ec4e432aa4bbb37a4800eb93e60 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 18 Sep 2022 16:26:40 -0500 Subject: [PATCH 0073/1073] docs(pytest_plugin): Move up in menu --- docs/index.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index 6df2dd637..a908e3e37 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,7 +19,7 @@ quickstart about topics/index reference/index - +pytest-plugin ``` ```{toctree} @@ -27,7 +27,6 @@ reference/index :hidden: developing -pytest-plugin internals/index history glossary From d209c30a39bb98b30d3878baa2acd540112b4806 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 18 Sep 2022 16:33:47 -0500 Subject: [PATCH 0074/1073] docs(pytest-plugin): Doc updates --- docs/pytest-plugin.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/pytest-plugin.md b/docs/pytest-plugin.md index 4c2ab3dad..36b727d34 100644 --- a/docs/pytest-plugin.md +++ b/docs/pytest-plugin.md @@ -1,10 +1,11 @@ (pytest_plugin)= -# `pytest` plugin +# tmux `pytest` plugin -Testing tmux with libtmux +libtmux provides pytest fixtures for tmux. The plugin automatically manages setup and teardown of an +independent tmux server. -```{seealso} Using libtmux? +```{seealso} Using the pytest plugin? Do you want more flexbility? Correctness? Power? Defaults changed? [Connect with us] on the tracker, we want to know your case, we won't stabilize APIs until we're sure everything is by the book. @@ -25,7 +26,7 @@ Install `libtmux` via the python package manager of your choosing, e.g. $ pip install libtmux ``` -The pytest plugin will automatically be detected via pytest, and the fixtures will be added. +The pytest plugin will be automatically detected via pytest, and the fixtures will be added. ## Fixtures From 131878c050479f5379450f0a85a4b2271050b32a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 18 Sep 2022 17:58:17 -0500 Subject: [PATCH 0075/1073] ci: Bump python to 3.10.7 --- .python-version | 2 +- .tool-versions | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.python-version b/.python-version index 9020162ba..946e73f19 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.10.6 3.9.13 3.8.13 3.7.13 +3.10.7 3.9.13 3.8.13 3.7.13 diff --git a/.tool-versions b/.tool-versions index fbc6993bc..caa1c7f5e 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ poetry 1.1.15 -python 3.10.6 3.9.13 3.8.13 3.7.13 +python 3.10.7 3.9.13 3.8.13 3.7.13 From 9d5f10c8f53c4f73586cee4e9633a947eeb86993 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 18 Sep 2022 18:03:17 -0500 Subject: [PATCH 0076/1073] ci: Bump poetry to 1.2.x (#436) See also: - https://python-poetry.org/blog/announcing-poetry-1.2.0/ - https://github.com/python-poetry/poetry/releases/tag/1.2.1 --- .github/workflows/docs.yml | 2 +- .github/workflows/tests.yml | 4 +-- .tool-versions | 2 +- poetry.lock | 59 ++++++++++++++++++++++++------------- 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 3e1abf99d..726b5d600 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -36,7 +36,7 @@ jobs: - name: Install poetry if: env.PUBLISH == 'true' - run: pipx install "poetry==1.1.15" + run: pipx install "poetry==1.2.1" - name: Set up Python ${{ matrix.python-version }} if: env.PUBLISH == 'true' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 938f07528..20f65b186 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v3 - name: Install poetry - run: pipx install "poetry==1.1.15" + run: pipx install "poetry==1.2.1" - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 @@ -90,7 +90,7 @@ jobs: - uses: actions/checkout@v3 - name: Install poetry - run: pipx install "poetry==1.1.15" + run: pipx install "poetry==1.2.1" - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 diff --git a/.tool-versions b/.tool-versions index caa1c7f5e..4c9b42d1c 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -poetry 1.1.15 +poetry 1.2.1 python 3.10.7 3.9.13 3.8.13 3.7.13 diff --git a/poetry.lock b/poetry.lock index 918464ae8..d2c0c8073 100644 --- a/poetry.lock +++ b/poetry.lock @@ -21,7 +21,7 @@ tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900 tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] [[package]] -name = "babel" +name = "Babel" version = "2.10.3" description = "Internationalization utilities" category = "dev" @@ -199,7 +199,7 @@ sphinx-basic-ng = "*" [[package]] name = "gp-libs" -version = "0.0.1a10" +version = "0.0.1a11" description = "Internal utilities for projects following git-pull python package spec" category = "dev" optional = false @@ -265,7 +265,7 @@ plugins = ["setuptools"] requirements_deprecated_finder = ["pip-api", "pipreqs"] [[package]] -name = "jinja2" +name = "Jinja2" version = "3.1.2" description = "A very fast and expressive template engine." category = "dev" @@ -309,11 +309,11 @@ compare = ["commonmark (>=0.9.1,<0.10.0)", "markdown (>=3.3.6,<3.4.0)", "mistlet linkify = ["linkify-it-py (>=1.0,<2.0)"] plugins = ["mdit-py-plugins"] profiling = ["gprof2dot"] -rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-book-theme", "sphinx-copybutton", "sphinx-design"] +rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] -name = "markupsafe" +name = "MarkupSafe" version = "2.1.1" description = "Safely add untrusted strings to HTML/XML markup." category = "dev" @@ -400,7 +400,7 @@ typing-extensions = "*" code_style = ["pre-commit (>=2.12,<3.0)"] linkify = ["linkify-it-py (>=1.0,<2.0)"] rtd = ["ipython", "sphinx-book-theme", "sphinx-design", "sphinxcontrib.mermaid (>=0.7.1,<0.8.0)", "sphinxext-opengraph (>=0.6.3,<0.7.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] -testing = ["beautifulsoup4", "coverage", "pytest (>=6,<7)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx-pytest"] +testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=6,<7)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx-pytest"] [[package]] name = "packaging" @@ -473,7 +473,7 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] -name = "pygments" +name = "Pygments" version = "2.13.0" description = "Pygments is a syntax highlighting package written in Python." category = "dev" @@ -554,6 +554,7 @@ python-versions = ">= 3.6" [package.dependencies] pytest = ">=5.3" +setuptools = ">=40.0" [[package]] name = "pytest-watcher" @@ -575,7 +576,7 @@ optional = false python-versions = "*" [[package]] -name = "pyyaml" +name = "PyYAML" version = "6.0" description = "YAML parser and emitter for Python" category = "dev" @@ -600,6 +601,19 @@ urllib3 = ">=1.21.1,<1.27" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "setuptools" +version = "65.3.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mock", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + [[package]] name = "six" version = "1.16.0" @@ -625,7 +639,7 @@ optional = false python-versions = ">=3.6" [[package]] -name = "sphinx" +name = "Sphinx" version = "5.1.1" description = "Python documentation generator" category = "dev" @@ -731,7 +745,7 @@ rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme"] [[package]] name = "sphinx-inline-tabs" -version = "2021.4.11b8" +version = "2021.3.28b7" description = "Add inline tabbed content to your Sphinx documentation." category = "dev" optional = false @@ -926,7 +940,7 @@ attrs = [ {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, ] -babel = [ +Babel = [ {file = "Babel-2.10.3-py3-none-any.whl", hash = "sha256:ff56f4892c1c4bf0d814575ea23471c230d544203c7748e8c68f0089478d48eb"}, {file = "Babel-2.10.3.tar.gz", hash = "sha256:7614553711ee97490f732126dc077f8d0ae084ebc6a96e23db1482afabdb2c51"}, ] @@ -973,7 +987,6 @@ click = [ ] codecov = [ {file = "codecov-2.1.12-py2.py3-none-any.whl", hash = "sha256:585dc217dc3d8185198ceb402f85d5cb5dbfa0c5f350a5abcdf9e347776a5b47"}, - {file = "codecov-2.1.12-py3.8.egg", hash = "sha256:782a8e5352f22593cbc5427a35320b99490eb24d9dcfa2155fd99d2b75cfb635"}, {file = "codecov-2.1.12.tar.gz", hash = "sha256:a0da46bb5025426da895af90938def8ee12d37fcbcbbbc15b6dc64cf7ebc51c1"}, ] colorama = [ @@ -1053,8 +1066,8 @@ furo = [ {file = "furo-2022.9.15.tar.gz", hash = "sha256:4a7ef1c8a3b615171592da4d2ad8a53cc4aacfbe111958890f5f9ff7279066ab"}, ] gp-libs = [ - {file = "gp-libs-0.0.1a10.tar.gz", hash = "sha256:54fbe07f42628b114f0b1472bb03ce75be2928090ec26d8d6f675f3bd9f58c2e"}, - {file = "gp_libs-0.0.1a10-py3-none-any.whl", hash = "sha256:701b190ffd468ca4d776b196707344748dd550aea03db9aaa1ffdecdd0c32506"}, + {file = "gp-libs-0.0.1a11.tar.gz", hash = "sha256:2fa1d886aae88f17614c052652509ce6347adc5f39e1b35223ef0ee2b56069e5"}, + {file = "gp_libs-0.0.1a11-py3-none-any.whl", hash = "sha256:75248e0409e8af142cd2ccdbf3382300d26eb73f0155b0de721368c3543e5c35"}, ] idna = [ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, @@ -1076,7 +1089,7 @@ isort = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] -jinja2 = [ +Jinja2 = [ {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, ] @@ -1087,7 +1100,7 @@ markdown-it-py = [ {file = "markdown-it-py-2.1.0.tar.gz", hash = "sha256:cf7e59fed14b5ae17c0006eff14a2d9a00ed5f3a846148153899a0224e2c07da"}, {file = "markdown_it_py-2.1.0-py3-none-any.whl", hash = "sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27"}, ] -markupsafe = [ +MarkupSafe = [ {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, @@ -1202,7 +1215,7 @@ pyflakes = [ {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, ] -pygments = [ +Pygments = [ {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, ] @@ -1234,7 +1247,7 @@ pytz = [ {file = "pytz-2022.2.1-py2.py3-none-any.whl", hash = "sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197"}, {file = "pytz-2022.2.1.tar.gz", hash = "sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5"}, ] -pyyaml = [ +PyYAML = [ {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, @@ -1273,6 +1286,10 @@ requests = [ {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, ] +setuptools = [ + {file = "setuptools-65.3.0-py3-none-any.whl", hash = "sha256:2e24e0bec025f035a2e72cdd1961119f557d78ad331bb00ff82efb2ab8da8e82"}, + {file = "setuptools-65.3.0.tar.gz", hash = "sha256:7732871f4f7fa58fb6bdcaeadb0161b2bd046c85905dbaa066bdcbcc81953b57"}, +] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, @@ -1285,7 +1302,7 @@ soupsieve = [ {file = "soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759"}, {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"}, ] -sphinx = [ +Sphinx = [ {file = "Sphinx-5.1.1-py3-none-any.whl", hash = "sha256:309a8da80cb6da9f4713438e5b55861877d5d7976b69d87e336733637ea12693"}, {file = "Sphinx-5.1.1.tar.gz", hash = "sha256:ba3224a4e206e1fbdecf98a4fae4992ef9b24b85ebf7b584bb340156eaf08d89"}, ] @@ -1310,8 +1327,8 @@ sphinx-copybutton = [ {file = "sphinx_copybutton-0.5.0-py3-none-any.whl", hash = "sha256:9684dec7434bd73f0eea58dda93f9bb879d24bff2d8b187b1f2ec08dfe7b5f48"}, ] sphinx-inline-tabs = [ - {file = "sphinx_inline_tabs-2021.4.11b8-py3-none-any.whl", hash = "sha256:efd6e7ad576a6bc1c616cbaa9b0e6f6fe2b28a776947069ed8d6037667799808"}, - {file = "sphinx_inline_tabs-2021.4.11b8.tar.gz", hash = "sha256:3c4d7759cbbb7752b7e7acd96ed0ea2c58fcc4ae38891a718544b931a5a4818f"}, + {file = "sphinx_inline_tabs-2021.3.28b7-py3-none-any.whl", hash = "sha256:951982fee76fd21ba880182efe6d500872122a2d41a6e4e0ce0b529123500874"}, + {file = "sphinx_inline_tabs-2021.3.28b7.tar.gz", hash = "sha256:e21b7439a4af86fc738a1b74fead87af59640b6e782efe83ef6c3936fc3924ab"}, ] sphinxcontrib-applehelp = [ {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, From bfcbfa6c2569fb7de9375a0eb4d3049afb3006a0 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 18 Sep 2022 18:24:29 -0500 Subject: [PATCH 0077/1073] ci(poetry): Prefer active python See also: - https://python-poetry.org/blog/announcing-poetry-1.2.0/#virtualenvsprefer-active-python - https://python-poetry.org/docs/configuration/#virtualenvsprefer-active-python-experimental --- poetry.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/poetry.toml b/poetry.toml index ab1033bd3..5fcef8cd4 100644 --- a/poetry.toml +++ b/poetry.toml @@ -1,2 +1,3 @@ [virtualenvs] in-project = true +prefer-active-python = true From f183aac117f2d37b0d3115f4b4eac8dc3a0c5740 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 18 Sep 2022 21:59:13 -0500 Subject: [PATCH 0078/1073] tests: Add doctests --- src/libtmux/test.py | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/libtmux/test.py b/src/libtmux/test.py index 19e9a8b29..ae65716bd 100644 --- a/src/libtmux/test.py +++ b/src/libtmux/test.py @@ -27,6 +27,16 @@ class RandomStrSequence: def __init__( self, characters: str = "abcdefghijklmnopqrstuvwxyz0123456789_" ) -> None: + """Create a random letter / number generator. 8 chars in length. + + >>> rng = RandomStrSequence() + >>> next(rng) + '...' + >>> len(next(rng)) + 8 + >>> type(next(rng)) + + """ self.characters: str = characters def __iter__(self) -> "RandomStrSequence": @@ -68,7 +78,6 @@ def retry_until( Examples -------- - >>> def fn(): ... p = session.attached_window.attached_pane ... p.server._update_panes() @@ -110,6 +119,15 @@ def get_test_session_name(server: "Server", prefix: str = TEST_SESSION_PREFIX) - ------- str Random session name guaranteed to not collide with current ones. + + Examples + -------- + >>> get_test_session_name(server=server) + 'libtmux_...' + + Never the same twice: + >>> get_test_session_name(server=server) != get_test_session_name(server=server) + True """ while True: session_name = prefix + next(namer) @@ -138,6 +156,15 @@ def get_test_window_name( ------- str Random window name guaranteed to not collide with current ones. + + Examples + -------- + >>> get_test_window_name(session=session) + 'libtmux_...' + + Never the same twice: + >>> get_test_window_name(session=session) != get_test_window_name(session=session) + True """ assert prefix is not None while True: @@ -178,10 +205,9 @@ def temp_session( Examples -------- - >>> with temp_session(server) as session: ... session.new_window(window_name='my window') - Window(@... ...:..., Session($... ...)) + Window(@3 2:my window, Session($... ...)) """ if "session_name" in kwargs: @@ -230,17 +256,15 @@ def temp_window( Examples -------- - >>> with temp_window(session) as window: ... window - Window(@... ...:..., Session($... ...)) + Window(@2 2:... Session($1 libtmux_...)) >>> with temp_window(session) as window: ... window.split_window() - Pane(%... Window(@... ...:..., Session($... ...))) + Pane(%4 Window(@3 2:libtmux_..., Session($1 libtmux_...))) """ - if "window_name" not in kwargs: window_name = get_test_window_name(session) else: @@ -262,7 +286,6 @@ def temp_window( class EnvironmentVarGuard: - """Mock environmental variables safetly. Helps rotect the environment variable properly. Can be used as context @@ -270,13 +293,11 @@ class EnvironmentVarGuard: Notes ----- - Vendorized to fix issue with Anaconda Python 2 not including test module, see #121 [1]_ References ---------- - .. [1] Just installed, "ImportError: cannot import name test_support". GitHub issue for tmuxp. https://github.com/tmux-python/tmuxp/issues/121. Created October 12th, 2015. Accessed April 7th, 2018. From fc75c0d2350b343d433da20d0ce2db2c0637ae4a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 18 Sep 2022 22:07:15 -0500 Subject: [PATCH 0079/1073] docs: pytest-plugin/ --- docs/index.md | 2 +- docs/{pytest-plugin.md => pytest-plugin/index.md} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename docs/{pytest-plugin.md => pytest-plugin/index.md} (100%) diff --git a/docs/index.md b/docs/index.md index a908e3e37..67c779bcf 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,7 +19,7 @@ quickstart about topics/index reference/index -pytest-plugin +pytest-plugin/index ``` ```{toctree} diff --git a/docs/pytest-plugin.md b/docs/pytest-plugin/index.md similarity index 100% rename from docs/pytest-plugin.md rename to docs/pytest-plugin/index.md From 3e7d5b04c323d19da69020dc8be00d5ec4ddd6c6 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 18 Sep 2022 22:07:56 -0500 Subject: [PATCH 0080/1073] docs(redirects): Update to pytest-plugin --- docs/redirects.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/redirects.txt b/docs/redirects.txt index c237369f5..9188d36fa 100644 --- a/docs/redirects.txt +++ b/docs/redirects.txt @@ -5,3 +5,4 @@ "traversal.md" "topics/traversal.md" "sessions.md" "reference/sessions.md" "api.md" "internals/index.md" +"pytest-plugin.md" "pytest-plugin/index.md" From 3df720945ae979e508eeae32599803922edd6bad Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 18 Sep 2022 22:09:02 -0500 Subject: [PATCH 0081/1073] docs(tests): Move into pytest --- docs/internals/index.md | 5 ----- docs/pytest-plugin/index.md | 5 +++++ docs/{internals => pytest-plugin}/test.md | 0 3 files changed, 5 insertions(+), 5 deletions(-) rename docs/{internals => pytest-plugin}/test.md (100%) diff --git a/docs/internals/index.md b/docs/internals/index.md index 531cfbbfd..348a1df32 100644 --- a/docs/internals/index.md +++ b/docs/internals/index.md @@ -8,11 +8,6 @@ These APIs are internal and not covered by versioning policy. ::: -```{toctree} - -test -``` - ## Environmental variables (LIBTMUX_TMUX_FORMAT_SEPARATOR)= diff --git a/docs/pytest-plugin/index.md b/docs/pytest-plugin/index.md index 36b727d34..9fa2670af 100644 --- a/docs/pytest-plugin/index.md +++ b/docs/pytest-plugin/index.md @@ -5,6 +5,11 @@ libtmux provides pytest fixtures for tmux. The plugin automatically manages setup and teardown of an independent tmux server. +```{toctree} + +test +``` + ```{seealso} Using the pytest plugin? Do you want more flexbility? Correctness? Power? Defaults changed? [Connect with us] on the tracker, we want to know diff --git a/docs/internals/test.md b/docs/pytest-plugin/test.md similarity index 100% rename from docs/internals/test.md rename to docs/pytest-plugin/test.md From 1f1aebacbc7ab571f62499242d7674565e746934 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 18 Sep 2022 22:13:37 -0500 Subject: [PATCH 0082/1073] docs: Organize pytest-plugin --- docs/pytest-plugin/index.md | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/docs/pytest-plugin/index.md b/docs/pytest-plugin/index.md index 9fa2670af..bceb87f08 100644 --- a/docs/pytest-plugin/index.md +++ b/docs/pytest-plugin/index.md @@ -5,11 +5,6 @@ libtmux provides pytest fixtures for tmux. The plugin automatically manages setup and teardown of an independent tmux server. -```{toctree} - -test -``` - ```{seealso} Using the pytest plugin? Do you want more flexbility? Correctness? Power? Defaults changed? [Connect with us] on the tracker, we want to know @@ -33,7 +28,15 @@ $ pip install libtmux The pytest plugin will be automatically detected via pytest, and the fixtures will be added. -## Fixtures +### Real world usage + +View libtmux's own [tests/](https://github.com/tmux-python/libtmux/tree/master/tests) as well as +tmuxp's [tests/](https://github.com/tmux-python/tmuxp/tree/master/tests). + +libtmux's tests `autouse` the {ref}`recommended-fixtures` above to ensure stable, assertions and +object lookups in the test grid. + +## pytest-tmux `pytest-tmux` works through providing {ref}`pytest fixtures ` - so read up on those! @@ -82,15 +85,7 @@ def set_home( monkeypatch.setenv("HOME", str(user_path)) ``` -## See examples - -View libtmux's own [tests/](https://github.com/tmux-python/libtmux/tree/master/tests) as well as -tmuxp's [tests/](https://github.com/tmux-python/tmuxp/tree/master/tests). - -libtmux's tests `autouse` the {ref}`recommended-fixtures` above to ensure stable, assertions and -object lookups in the test grid. - -## API reference +## Fixtures ```{eval-rst} .. automodule:: libtmux.pytest_plugin @@ -100,3 +95,11 @@ object lookups in the test grid. :show-inheritance: :member-order: bysource ``` + +## Test utilities + +```{toctree} +:maxdepth: 1 + +test +``` From 91bf7b3132c8032c6c935c0fc9e12f62b9c0aa49 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 18 Sep 2022 22:25:36 -0500 Subject: [PATCH 0083/1073] docs: Point directly to traversal --- docs/index.md | 2 +- docs/topics/index.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 67c779bcf..2a2d82ebe 100644 --- a/docs/index.md +++ b/docs/index.md @@ -17,7 +17,7 @@ hide-toc: true quickstart about -topics/index +topics/traversal reference/index pytest-plugin/index ``` diff --git a/docs/topics/index.md b/docs/topics/index.md index 027df370d..7fe9893b8 100644 --- a/docs/topics/index.md +++ b/docs/topics/index.md @@ -1,3 +1,7 @@ +--- +orphan: true +--- + # Topic Guides ```{toctree} From fdea6b7288ee95cb78f20ef923c47a505e74ab1f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 18 Sep 2022 22:27:31 -0500 Subject: [PATCH 0084/1073] docs: Reference -> API Reference --- docs/reference/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/index.md b/docs/reference/index.md index 355dbfc89..2a6c9ff63 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -2,7 +2,7 @@ (reference)= -# Reference +# API Reference ```{toctree} From 569dac752b573e9d3dd78a68197658ab4d33eb18 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 18 Sep 2022 22:28:00 -0500 Subject: [PATCH 0085/1073] docs: Temporarily rename traversal to usage --- docs/topics/traversal.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/topics/traversal.md b/docs/topics/traversal.md index 02b537306..7b20bfb04 100644 --- a/docs/topics/traversal.md +++ b/docs/topics/traversal.md @@ -1,6 +1,6 @@ (traversal)= -# Traversal +# Usage libtmux convenient access to move around the hierachy of sessions, windows and panes in tmux. From 0d4acff15977d144e2d45fbefce7a5e1615f5a26 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 19 Sep 2022 21:53:59 -0500 Subject: [PATCH 0086/1073] test(conftest): Add pytester --- src/libtmux/conftest.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libtmux/conftest.py b/src/libtmux/conftest.py index c99992127..0039f306d 100644 --- a/src/libtmux/conftest.py +++ b/src/libtmux/conftest.py @@ -11,11 +11,14 @@ if t.TYPE_CHECKING: from libtmux.session import Session +pytest_plugins = ["pytester"] + @pytest.fixture(autouse=True) def add_doctest_fixtures( request: pytest.FixtureRequest, doctest_namespace: t.Dict[str, t.Any], + pytester: pytest.Pytester, ) -> None: if isinstance(request._pyfuncitem, DoctestItem) and shutil.which("tmux"): request.getfixturevalue("set_home") @@ -24,6 +27,7 @@ def add_doctest_fixtures( doctest_namespace["session"] = session doctest_namespace["window"] = session.attached_window doctest_namespace["pane"] = session.attached_pane + doctest_namespace["pytester"] = pytester @pytest.fixture(autouse=True, scope="function") From 44950dadcf0f0274d51ddcbefe8340c15be217d4 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 19 Sep 2022 21:52:27 -0500 Subject: [PATCH 0087/1073] tests(pytest_plugin): Add session, server doctest example --- src/libtmux/pytest_plugin.py | 42 ++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/libtmux/pytest_plugin.py b/src/libtmux/pytest_plugin.py index 863e9e44f..860187309 100644 --- a/src/libtmux/pytest_plugin.py +++ b/src/libtmux/pytest_plugin.py @@ -108,7 +108,24 @@ def server( monkeypatch: pytest.MonkeyPatch, config_file: pathlib.Path, ) -> Server: - """Returns a new, temporary :class:`libtmux.Server`""" + """Returns a new, temporary :class:`libtmux.Server` + + >>> from libtmux.server import Server + + >>> def test_example(server: "Server"): + ... session = server.new_session('my session') + ... assert len(server.sessions) == 1 + ... assert [session.name.startswith('my') for session in server.sessions] + + .. :: + + >>> import inspect + >>> test_mod = pytester.makepyfile(whatever=inspect.getsource(test_example)) + >>> result = pytester.inline_run(str(test_mod), '--disable-warnings') + ===... + + >>> result.assertoutcome(passed=1) + """ t = Server() t.socket_name = "libtmux_test%s" % next(namer) @@ -122,7 +139,28 @@ def fin() -> None: @pytest.fixture(scope="function") def session(request: pytest.FixtureRequest, server: Server) -> "Session": - """Returns a new, temporary :class:`libtmux.Session`""" + """Returns a new, temporary :class:`libtmux.Session` + + >>> from libtmux.session import Session + + >>> def test_example(session: "Session"): + ... assert isinstance(session.name, str) + ... assert session.name.startswith('libtmux_') + ... window = session.new_window(window_name='new one') + ... assert window.name == 'new one' + + .. :: + + The nifty little thing above hides our pytester assertions from docs. + + >>> import inspect + + >>> test_mod = pytester.makepyfile(whatever=inspect.getsource(test_example)) + >>> result = pytester.inline_run(str(test_mod), '--disable-warnings') + ===... + + >>> result.assertoutcome(passed=1) + """ session_name = "tmuxp" if not server.has_session(session_name): From 10d1f9b293b4bf9f353446cb3e9f7b312f786fd9 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 19 Sep 2022 22:10:28 -0500 Subject: [PATCH 0088/1073] test: Root level conftest ________________________ ERROR collecting test session _________________________ Defining 'pytest_plugins' in a non-top-level conftest is no longer supported: It affects the entire test suite instead of just below the conftest as expected. /home/runner/work/libtmux/libtmux/src/libtmux/conftest.py Please move it to a top level conftest file at the rootdir: /home/runner/work/libtmux/libtmux For more information, visit: https://docs.pytest.org/en/stable/deprecations.html#pytest-plugins-in-non-top-level-conftest-files --- conftest.py | 1 + src/libtmux/conftest.py | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 conftest.py diff --git a/conftest.py b/conftest.py new file mode 100644 index 000000000..c6481d5f7 --- /dev/null +++ b/conftest.py @@ -0,0 +1 @@ +pytest_plugins = ["pytester"] diff --git a/src/libtmux/conftest.py b/src/libtmux/conftest.py index 0039f306d..6a1c1775a 100644 --- a/src/libtmux/conftest.py +++ b/src/libtmux/conftest.py @@ -11,8 +11,6 @@ if t.TYPE_CHECKING: from libtmux.session import Session -pytest_plugins = ["pytester"] - @pytest.fixture(autouse=True) def add_doctest_fixtures( From 882c83734eaa164160ebc28541bdc99ea8ea721f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 19 Sep 2022 22:25:28 -0500 Subject: [PATCH 0089/1073] build: Add docs/__init__.py to satiate mypy conftest.py: error: Duplicate module named "conftest" (also at "docs/conftest.py") --- docs/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/__init__.py diff --git a/docs/__init__.py b/docs/__init__.py new file mode 100644 index 000000000..e69de29bb From 908459daa698745b049c573bc608bee174ea62d6 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 19 Sep 2022 22:26:24 -0500 Subject: [PATCH 0090/1073] tests(conftest): Add request to doctest I still have to run locals().keys() to scope request into the doctest context, no idea why. --- src/libtmux/conftest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libtmux/conftest.py b/src/libtmux/conftest.py index 6a1c1775a..fe18ef4f8 100644 --- a/src/libtmux/conftest.py +++ b/src/libtmux/conftest.py @@ -26,6 +26,7 @@ def add_doctest_fixtures( doctest_namespace["window"] = session.attached_window doctest_namespace["pane"] = session.attached_pane doctest_namespace["pytester"] = pytester + doctest_namespace["request"] = request @pytest.fixture(autouse=True, scope="function") From 1619b121cf3cc50e1ee70666da6900b0a75287a3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 19 Sep 2022 22:27:01 -0500 Subject: [PATCH 0091/1073] test(pytest_plugin): I have no idea *why* this works The request context isn't detected inside the doctest unless I run locals(). The request context is needed to join the example code's import so the type annotation shows. --- src/libtmux/pytest_plugin.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/libtmux/pytest_plugin.py b/src/libtmux/pytest_plugin.py index 860187309..1f9a4e140 100644 --- a/src/libtmux/pytest_plugin.py +++ b/src/libtmux/pytest_plugin.py @@ -112,19 +112,28 @@ def server( >>> from libtmux.server import Server - >>> def test_example(server: "Server"): + >>> def test_example(server: Server): + ... assert isinstance(server, Server) ... session = server.new_session('my session') ... assert len(server.sessions) == 1 ... assert [session.name.startswith('my') for session in server.sessions] .. :: - >>> import inspect - >>> test_mod = pytester.makepyfile(whatever=inspect.getsource(test_example)) - >>> result = pytester.inline_run(str(test_mod), '--disable-warnings') + >>> locals().keys() + dict_keys(...) + + >>> source = ''.join([ + ... example.source for example in request._pyfuncitem.dtest.examples + ... ][:3]) + + >>> pytester.makepyfile(**{'whatever.py': source}) + PosixPath(...) + + >>> result = pytester.runpytest('whatever.py', '--disable-warnings') ===... - >>> result.assertoutcome(passed=1) + >>> result.assert_outcomes(passed=1) """ t = Server() t.socket_name = "libtmux_test%s" % next(namer) From 399f3a5dcfb6464f87ce832cc78092bdfdc8d6c6 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 19 Sep 2022 22:28:54 -0500 Subject: [PATCH 0092/1073] docs(pytest_plugin): Fortify typings a bit more w/ -> None --- src/libtmux/pytest_plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libtmux/pytest_plugin.py b/src/libtmux/pytest_plugin.py index 1f9a4e140..5281e33a7 100644 --- a/src/libtmux/pytest_plugin.py +++ b/src/libtmux/pytest_plugin.py @@ -112,7 +112,7 @@ def server( >>> from libtmux.server import Server - >>> def test_example(server: Server): + >>> def test_example(server: Server) -> None: ... assert isinstance(server, Server) ... session = server.new_session('my session') ... assert len(server.sessions) == 1 @@ -152,7 +152,7 @@ def session(request: pytest.FixtureRequest, server: Server) -> "Session": >>> from libtmux.session import Session - >>> def test_example(session: "Session"): + >>> def test_example(session: "Session") -> None: ... assert isinstance(session.name, str) ... assert session.name.startswith('libtmux_') ... window = session.new_window(window_name='new one') From adbcd0c0595483c5f6b3f3d2221986d66eeba611 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 19 Sep 2022 22:34:43 -0500 Subject: [PATCH 0093/1073] tests(pytest_plugin): Pull pytester independently in tests --- src/libtmux/conftest.py | 2 -- src/libtmux/pytest_plugin.py | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libtmux/conftest.py b/src/libtmux/conftest.py index fe18ef4f8..cd01c8ad4 100644 --- a/src/libtmux/conftest.py +++ b/src/libtmux/conftest.py @@ -16,7 +16,6 @@ def add_doctest_fixtures( request: pytest.FixtureRequest, doctest_namespace: t.Dict[str, t.Any], - pytester: pytest.Pytester, ) -> None: if isinstance(request._pyfuncitem, DoctestItem) and shutil.which("tmux"): request.getfixturevalue("set_home") @@ -25,7 +24,6 @@ def add_doctest_fixtures( doctest_namespace["session"] = session doctest_namespace["window"] = session.attached_window doctest_namespace["pane"] = session.attached_pane - doctest_namespace["pytester"] = pytester doctest_namespace["request"] = request diff --git a/src/libtmux/pytest_plugin.py b/src/libtmux/pytest_plugin.py index 5281e33a7..dade47b4c 100644 --- a/src/libtmux/pytest_plugin.py +++ b/src/libtmux/pytest_plugin.py @@ -127,6 +127,8 @@ def server( ... example.source for example in request._pyfuncitem.dtest.examples ... ][:3]) + >>> pytester = request.getfixturevalue('pytester') + >>> pytester.makepyfile(**{'whatever.py': source}) PosixPath(...) @@ -164,6 +166,8 @@ def session(request: pytest.FixtureRequest, server: Server) -> "Session": >>> import inspect + >>> pytester = request.getfixturevalue('pytester') + >>> test_mod = pytester.makepyfile(whatever=inspect.getsource(test_example)) >>> result = pytester.inline_run(str(test_mod), '--disable-warnings') ===... From 9e8526b46cc3cca94aad8eef552fca8963b25187 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 19 Sep 2022 22:45:16 -0500 Subject: [PATCH 0094/1073] docs(pytest_plugin): Cleanup --- src/libtmux/pytest_plugin.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/libtmux/pytest_plugin.py b/src/libtmux/pytest_plugin.py index dade47b4c..186f41092 100644 --- a/src/libtmux/pytest_plugin.py +++ b/src/libtmux/pytest_plugin.py @@ -119,14 +119,10 @@ def server( ... assert [session.name.startswith('my') for session in server.sessions] .. :: - >>> locals().keys() dict_keys(...) - >>> source = ''.join([ - ... example.source for example in request._pyfuncitem.dtest.examples - ... ][:3]) - + >>> source = ''.join([e.source for e in request._pyfuncitem.dtest.examples][:3]) >>> pytester = request.getfixturevalue('pytester') >>> pytester.makepyfile(**{'whatever.py': source}) @@ -161,18 +157,19 @@ def session(request: pytest.FixtureRequest, server: Server) -> "Session": ... assert window.name == 'new one' .. :: + >>> locals().keys() + dict_keys(...) - The nifty little thing above hides our pytester assertions from docs. - - >>> import inspect - + >>> source = ''.join([e.source for e in request._pyfuncitem.dtest.examples][:3]) >>> pytester = request.getfixturevalue('pytester') - >>> test_mod = pytester.makepyfile(whatever=inspect.getsource(test_example)) - >>> result = pytester.inline_run(str(test_mod), '--disable-warnings') + >>> pytester.makepyfile(**{'whatever.py': source}) + PosixPath(...) + + >>> result = pytester.runpytest('whatever.py', '--disable-warnings') ===... - >>> result.assertoutcome(passed=1) + >>> result.assert_outcomes(passed=1) """ session_name = "tmuxp" From 66285445b58a0997d5a0fc5a47f972161b63d542 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 19 Sep 2022 22:47:32 -0500 Subject: [PATCH 0095/1073] docs(CHANGES): Note pytest plugin example --- CHANGES | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES b/CHANGES index b29eb230f..de94a41ee 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,12 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ +## libtmux 0.15.3 (unreleased) + +### Tests / docs + +- Examples for pytest plugin (#439) + ## libtmux 0.15.2 (2022-09-17) **Maintenance release, no features or fixes** From bc0077f9ee32148eaa48549fd71c243b4dc80535 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 20 Sep 2022 00:55:48 -0500 Subject: [PATCH 0096/1073] tests: Consolidate conftest.py to root --- conftest.py | 46 +++++++++++++++++++++++++++++++++++++++++ docs/conftest.py | 1 - src/libtmux/conftest.py | 45 ---------------------------------------- tests/conftest.py | 3 --- 4 files changed, 46 insertions(+), 49 deletions(-) delete mode 100644 docs/conftest.py delete mode 100644 src/libtmux/conftest.py delete mode 100644 tests/conftest.py diff --git a/conftest.py b/conftest.py index c6481d5f7..a728f2f20 100644 --- a/conftest.py +++ b/conftest.py @@ -1 +1,47 @@ +import pathlib +import shutil +import typing as t + +import pytest + +from _pytest.doctest import DoctestItem + +from libtmux.pytest_plugin import USING_ZSH + +if t.TYPE_CHECKING: + from libtmux.session import Session + pytest_plugins = ["pytester"] + + +@pytest.fixture(autouse=True) +def add_doctest_fixtures( + request: pytest.FixtureRequest, + doctest_namespace: t.Dict[str, t.Any], +) -> None: + if isinstance(request._pyfuncitem, DoctestItem) and shutil.which("tmux"): + request.getfixturevalue("set_home") + doctest_namespace["server"] = request.getfixturevalue("server") + session: "Session" = request.getfixturevalue("session") + doctest_namespace["session"] = session + doctest_namespace["window"] = session.attached_window + doctest_namespace["pane"] = session.attached_pane + doctest_namespace["request"] = request + + +@pytest.fixture(autouse=True, scope="function") +def set_home( + monkeypatch: pytest.MonkeyPatch, + user_path: pathlib.Path, +) -> None: + monkeypatch.setenv("HOME", str(user_path)) + + +@pytest.fixture(autouse=True, scope="session") +@pytest.mark.usefixtures("clear_env") +def setup( + request: pytest.FixtureRequest, + config_file: pathlib.Path, +) -> None: + if USING_ZSH: + request.getfixturevalue("zshrc") diff --git a/docs/conftest.py b/docs/conftest.py deleted file mode 100644 index 62571f546..000000000 --- a/docs/conftest.py +++ /dev/null @@ -1 +0,0 @@ -from libtmux.conftest import * # NOQA: F4 diff --git a/src/libtmux/conftest.py b/src/libtmux/conftest.py deleted file mode 100644 index cd01c8ad4..000000000 --- a/src/libtmux/conftest.py +++ /dev/null @@ -1,45 +0,0 @@ -import pathlib -import shutil -import typing as t - -import pytest - -from _pytest.doctest import DoctestItem - -from libtmux.pytest_plugin import USING_ZSH - -if t.TYPE_CHECKING: - from libtmux.session import Session - - -@pytest.fixture(autouse=True) -def add_doctest_fixtures( - request: pytest.FixtureRequest, - doctest_namespace: t.Dict[str, t.Any], -) -> None: - if isinstance(request._pyfuncitem, DoctestItem) and shutil.which("tmux"): - request.getfixturevalue("set_home") - doctest_namespace["server"] = request.getfixturevalue("server") - session: "Session" = request.getfixturevalue("session") - doctest_namespace["session"] = session - doctest_namespace["window"] = session.attached_window - doctest_namespace["pane"] = session.attached_pane - doctest_namespace["request"] = request - - -@pytest.fixture(autouse=True, scope="function") -def set_home( - monkeypatch: pytest.MonkeyPatch, - user_path: pathlib.Path, -) -> None: - monkeypatch.setenv("HOME", str(user_path)) - - -@pytest.fixture(autouse=True, scope="session") -@pytest.mark.usefixtures("clear_env") -def setup( - request: pytest.FixtureRequest, - config_file: pathlib.Path, -) -> None: - if USING_ZSH: - request.getfixturevalue("zshrc") diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index ec9aaf09f..000000000 --- a/tests/conftest.py +++ /dev/null @@ -1,3 +0,0 @@ -from libtmux.conftest import * # NOQA: F4 - -pytest_plugins = ["pytester"] From 5e0fa62274893359ab54a14bcdf7e289c8d55630 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 20 Sep 2022 01:00:24 -0500 Subject: [PATCH 0097/1073] docs(CHANGES): Note root-level conftest.py --- CHANGES | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES b/CHANGES index de94a41ee..295754665 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,13 @@ $ pip install --user --upgrade --pre libtmux ### Tests / docs - Examples for pytest plugin (#439) +- Move conftest.py to root level (#440) + + - https://docs.pytest.org/en/stable/deprecations.html#pytest-plugins-in-non-top-level-conftest-files + - Less conftest.py files + - We can now run py.test for `README.md` without needing to proxy through + `docs/index.md` + ## libtmux 0.15.2 (2022-09-17) From 9828540dd9f8074e8d088c5efe707a7db95304cc Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 20 Sep 2022 01:01:39 -0500 Subject: [PATCH 0098/1073] Tag v0.15.3 (root-level conftest, pytest plugin doctests) --- CHANGES | 3 +-- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 295754665..2244b41ac 100644 --- a/CHANGES +++ b/CHANGES @@ -12,7 +12,7 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ -## libtmux 0.15.3 (unreleased) +## libtmux 0.15.3 (2022-09-20) ### Tests / docs @@ -24,7 +24,6 @@ $ pip install --user --upgrade --pre libtmux - We can now run py.test for `README.md` without needing to proxy through `docs/index.md` - ## libtmux 0.15.2 (2022-09-17) **Maintenance release, no features or fixes** diff --git a/pyproject.toml b/pyproject.toml index 9c1cd0e91..a8a6d5a4b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.2" +version = "0.15.3" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index c5f8d9461..49b48f63c 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.2" +__version__ = "0.15.3" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From bfde0017cd33fd5d498f3d27a6da2b0fc6f0cf8c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 21 Sep 2022 18:26:12 -0500 Subject: [PATCH 0099/1073] fix(pytest_plugin): Pytester import Fixes (#441) --- tests/test_pytest_plugin.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_pytest_plugin.py b/tests/test_pytest_plugin.py index b165806e3..3d9cb5503 100644 --- a/tests/test_pytest_plugin.py +++ b/tests/test_pytest_plugin.py @@ -2,11 +2,9 @@ import pytest -import _pytest.pytester - def test_plugin( - pytester: _pytest.pytester.Pytester, + pytester: pytest.Pytester, monkeypatch: pytest.MonkeyPatch, ) -> None: # Initialize variables From 69101f2c221cbf817f215ebbd7ff6b1bbbc77a5f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 21 Sep 2022 18:30:10 -0500 Subject: [PATCH 0100/1073] fix(test_common): Avoid reliance on internal pytest API for typing --- tests/test_common.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/test_common.py b/tests/test_common.py index 14c5c39a5..d09d21e84 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -8,8 +8,6 @@ import pytest -from _pytest.monkeypatch import MonkeyPatch - import libtmux from libtmux.common import ( TMUX_MAX_VERSION, @@ -31,7 +29,7 @@ version_regex = re.compile(r"([0-9]\.[0-9])|(master)") -def test_allows_master_version(monkeypatch: MonkeyPatch) -> None: +def test_allows_master_version(monkeypatch: pytest.MonkeyPatch) -> None: class Hi: stdout = ["tmux master"] stderr = None @@ -49,7 +47,7 @@ def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi: ), "Is the latest supported version with -master appended" -def test_allows_next_version(monkeypatch: MonkeyPatch) -> None: +def test_allows_next_version(monkeypatch: pytest.MonkeyPatch) -> None: TMUX_NEXT_VERSION = str(float(TMUX_MAX_VERSION) + 0.1) class Hi: @@ -67,7 +65,7 @@ def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi: assert TMUX_NEXT_VERSION == get_version() -def test_get_version_openbsd(monkeypatch: MonkeyPatch) -> None: +def test_get_version_openbsd(monkeypatch: pytest.MonkeyPatch) -> None: class Hi: stderr = ["tmux: unknown option -- V"] @@ -84,7 +82,7 @@ def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi: ), "Is the latest supported version with -openbsd appended" -def test_get_version_too_low(monkeypatch: MonkeyPatch) -> None: +def test_get_version_too_low(monkeypatch: pytest.MonkeyPatch) -> None: class Hi: stderr = ["tmux: unknown option -- V"] @@ -97,7 +95,7 @@ def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi: exc_info.match("is running tmux 1.3 or earlier") -def test_ignores_letter_versions(monkeypatch: MonkeyPatch) -> None: +def test_ignores_letter_versions(monkeypatch: pytest.MonkeyPatch) -> None: """Ignore letters such as 1.8b. See ticket https://github.com/tmux-python/tmuxp/issues/55. @@ -120,7 +118,7 @@ def test_ignores_letter_versions(monkeypatch: MonkeyPatch) -> None: assert type(has_version("1.9a")) is bool -def test_error_version_less_1_7(monkeypatch: MonkeyPatch) -> None: +def test_error_version_less_1_7(monkeypatch: pytest.MonkeyPatch) -> None: def mock_get_version() -> LooseVersion: return LooseVersion("1.7") From 472a3a3d236d6e769b27e734d8c417a42482b19f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 21 Sep 2022 18:54:28 -0500 Subject: [PATCH 0101/1073] build(pyproject): Include conftest.py with source output --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index a8a6d5a4b..dd5570a91 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,7 @@ include = [ { path = ".tmuxp.yaml", format = "sdist" }, { path = "tests", format = "sdist" }, { path = "docs", format = "sdist" }, + { path = "conftest.py", format = "sdist" }, ] [tool.poetry.urls] From 62c2f399534d1ec3ee7e013ebfd1d3e98cc4772c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 21 Sep 2022 18:54:59 -0500 Subject: [PATCH 0102/1073] build(pyproject): Include .tmuxp-before-script.sh with sdist --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index dd5570a91..89895a4c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,7 @@ packages = [ include = [ { path = "CHANGES", format = "sdist" }, { path = ".tmuxp.yaml", format = "sdist" }, + { path = ".tmuxp-before-script.sh", format = "sdist" }, { path = "tests", format = "sdist" }, { path = "docs", format = "sdist" }, { path = "conftest.py", format = "sdist" }, From bc34e8fdb01b18d2749fe886aca62afb7d1baee7 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 21 Sep 2022 18:45:54 -0500 Subject: [PATCH 0103/1073] docs(CHANGES): Update changes for import fixes --- CHANGES | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES b/CHANGES index 2244b41ac..924f5f4f8 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,13 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ +## libtmux 0.15.4 (unreleased) + +### Bug fixes + +- Use stable `pytest` API imports where possible to fix issues in downstream + packaging on Arch (#441, via #442) + ## libtmux 0.15.3 (2022-09-20) ### Tests / docs From f4d5bfcfeeda1f6822eed59e234b1a22faacd3a0 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 21 Sep 2022 18:57:40 -0500 Subject: [PATCH 0104/1073] docs(CHANGES): Note source files additions --- CHANGES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index 924f5f4f8..97431e254 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,11 @@ $ pip install --user --upgrade --pre libtmux - Use stable `pytest` API imports where possible to fix issues in downstream packaging on Arch (#441, via #442) +### Packaging + +- Add `.tmuxp-before-script.sh` (used by `.tmuxp.yaml`) and `conftest.py` to + source distributoins (#441, via #442) + ## libtmux 0.15.3 (2022-09-20) ### Tests / docs From 9c349ccc0deb87d3e8df56aa790b0c3f6868dc1e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Wed, 21 Sep 2022 19:00:59 -0500 Subject: [PATCH 0105/1073] Tag v0.15.4 (packaging and import fixes for pytest, via #442) --- CHANGES | 2 +- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 97431e254..7b24a3b20 100644 --- a/CHANGES +++ b/CHANGES @@ -12,7 +12,7 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ -## libtmux 0.15.4 (unreleased) +## libtmux 0.15.4 (2022-09-21) ### Bug fixes diff --git a/pyproject.toml b/pyproject.toml index 89895a4c0..8286cebdd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.3" +version = "0.15.4" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index 49b48f63c..ec531be09 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.3" +__version__ = "0.15.4" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From bc566a847ce06bb73e84f92cfb832d39792b2d5f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 23 Sep 2022 19:41:39 -0500 Subject: [PATCH 0106/1073] build(dep): Update flake8-bugbear --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index d2c0c8073..785823568 100644 --- a/poetry.lock +++ b/poetry.lock @@ -158,7 +158,7 @@ pyflakes = ">=2.3.0,<2.4.0" [[package]] name = "flake8-bugbear" -version = "22.9.11" +version = "22.9.23" description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." category = "dev" optional = false @@ -1054,8 +1054,8 @@ flake8 = [ {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, ] flake8-bugbear = [ - {file = "flake8-bugbear-22.9.11.tar.gz", hash = "sha256:39236c0e97160d1ab05d9f87422173d16e925a6220b3635bfc4aee766bf8194a"}, - {file = "flake8_bugbear-22.9.11-py3-none-any.whl", hash = "sha256:e74350a4cfc670e184f3433c223b1e7378f1cf8345ded6c8f12ac1a50c5df22b"}, + {file = "flake8-bugbear-22.9.23.tar.gz", hash = "sha256:17b9623325e6e0dcdcc80ed9e4aa811287fcc81d7e03313b8736ea5733759937"}, + {file = "flake8_bugbear-22.9.23-py3-none-any.whl", hash = "sha256:cd2779b2b7ada212d7a322814a1e5651f1868ab0d3f24cc9da66169ab8fda474"}, ] flake8-comprehensions = [ {file = "flake8-comprehensions-3.10.0.tar.gz", hash = "sha256:181158f7e7aa26a63a0a38e6017cef28c6adee71278ce56ce11f6ec9c4905058"}, From 48404afe9d9c948cfa5db0c01af0b9f9559474b0 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 23 Sep 2022 19:43:10 -0500 Subject: [PATCH 0107/1073] ci(tmuxp): Remove .tmuxp-before-script.sh --- .tmuxp-before-script.sh | 3 --- .tmuxp.yaml | 1 - pyproject.toml | 1 - 3 files changed, 5 deletions(-) delete mode 100755 .tmuxp-before-script.sh diff --git a/.tmuxp-before-script.sh b/.tmuxp-before-script.sh deleted file mode 100755 index 0721faabd..000000000 --- a/.tmuxp-before-script.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -poetry shell --no-ansi --no-interaction &2> /dev/null -poetry install --no-ansi --no-interaction &2> /dev/null diff --git a/.tmuxp.yaml b/.tmuxp.yaml index c1a39a8a1..6cbc4a146 100644 --- a/.tmuxp.yaml +++ b/.tmuxp.yaml @@ -1,6 +1,5 @@ session_name: libtmux start_directory: ./ # load session relative to config location (project root). -before_script: ./.tmuxp-before-script.sh shell_command_before: - '[ -f .venv/bin/activate ] && source .venv/bin/activate && reset' windows: diff --git a/pyproject.toml b/pyproject.toml index 8286cebdd..585f3faa9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,6 @@ packages = [ include = [ { path = "CHANGES", format = "sdist" }, { path = ".tmuxp.yaml", format = "sdist" }, - { path = ".tmuxp-before-script.sh", format = "sdist" }, { path = "tests", format = "sdist" }, { path = "docs", format = "sdist" }, { path = "conftest.py", format = "sdist" }, From ba563d225698728e3e245e0babf1179edc3506ff Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 23 Sep 2022 19:46:30 -0500 Subject: [PATCH 0108/1073] docs(CHANGES): Note removal of tmuxp-before-script.sh --- CHANGES | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES b/CHANGES index 7b24a3b20..b515a4053 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,12 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ +## libtmux 0.15.5 (unreleased) + +### Packaging + +- Remove `.tmuxp-before-script.sh` from `.tmuxp.yaml` + ## libtmux 0.15.4 (2022-09-21) ### Bug fixes From dd899cae02649dc9e362e3e6ca47162c530cb1f5 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 23 Sep 2022 19:53:53 -0500 Subject: [PATCH 0109/1073] Tag v0.15.5 (Remove .tmuxp-before-script.sh) --- CHANGES | 2 +- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index b515a4053..289eb0848 100644 --- a/CHANGES +++ b/CHANGES @@ -12,7 +12,7 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ -## libtmux 0.15.5 (unreleased) +## libtmux 0.15.5 (2022-09-23) ### Packaging diff --git a/pyproject.toml b/pyproject.toml index 585f3faa9..b1025ccd0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.4" +version = "0.15.5" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index ec531be09..4893a3340 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.4" +__version__ = "0.15.5" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From 13d37f5ba2cc0752c6b1ccd3d2e933ad79fdd31f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 23 Sep 2022 20:00:39 -0500 Subject: [PATCH 0110/1073] build: Remove MANIFEST.in This is deprecated by poetry's pyproject.toml include field --- MANIFEST.in | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index a40f8cae6..000000000 --- a/MANIFEST.in +++ /dev/null @@ -1,3 +0,0 @@ -include README.md LICENSE CHANGES pyproject.toml .tmuxp.yaml -include requirements/*.txt -recursive-include docs *.md From 291630e745d04e872c2a6b2581ee504cff276419 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 23 Sep 2022 20:03:47 -0500 Subject: [PATCH 0111/1073] docs(CHANGES): Note removal of MANIFEST.in --- CHANGES | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGES b/CHANGES index 289eb0848..4b1e40c76 100644 --- a/CHANGES +++ b/CHANGES @@ -12,8 +12,20 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ +## libtmux 0.15.6 (unreleased) + +_Maintenance only, no bug fixes or features_ + +### Packaging + +- Remove `MANIFEST.in` + + This is handled by poetry's `include` in pyproject.toml. + ## libtmux 0.15.5 (2022-09-23) +_Maintenance only, no bug fixes or features_ + ### Packaging - Remove `.tmuxp-before-script.sh` from `.tmuxp.yaml` From 79580eb7f886a14472d1264ab4f57371e480ca6c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 23 Sep 2022 20:05:05 -0500 Subject: [PATCH 0112/1073] Tag v0.15.6 (remove MANIFEST.in) --- CHANGES | 2 +- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 4b1e40c76..d1fee4b1a 100644 --- a/CHANGES +++ b/CHANGES @@ -12,7 +12,7 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ -## libtmux 0.15.6 (unreleased) +## libtmux 0.15.6 (2022-09-23) _Maintenance only, no bug fixes or features_ diff --git a/pyproject.toml b/pyproject.toml index b1025ccd0..ce01f274c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.5" +version = "0.15.6" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index 4893a3340..b106c9eef 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.5" +__version__ = "0.15.6" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From 72b7b60493511236ef7f0df9c3712c06010bd6ce Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 23 Sep 2022 20:42:26 -0500 Subject: [PATCH 0113/1073] build: Remove .coveragerc, use pyproject.toml --- .coveragerc | 20 -------------------- pyproject.toml | 24 +++++++++++++++++++++++- 2 files changed, 23 insertions(+), 21 deletions(-) delete mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 7c74c56a0..000000000 --- a/.coveragerc +++ /dev/null @@ -1,20 +0,0 @@ -[run] -parallel = 1 -branch = 1 - -omit = - docs/conf.py - */_compat.py - -[report] -skip_covered = True -show_missing = True -exclude_lines = - \#\s*pragma: no cover - ^\s*raise NotImplementedError\b - ^\s*return NotImplemented\b - ^\s*assert False(,|$) - ^\s*assert_never\( - - ^\s*if TYPE_CHECKING: - ^\s*@overload( |$) diff --git a/pyproject.toml b/pyproject.toml index ce01f274c..f00507273 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -95,7 +95,7 @@ docs = [ "sphinxext-rediraffe", "myst_parser", "furo", - "gp-libs" + "gp-libs", ] test = ["pytest", "pytest-rerunfailures", "pytest-mock", "pytest-watcher"] coverage = ["codecov", "coverage", "pytest-cov"] @@ -108,6 +108,28 @@ libtmux = "libtmux.pytest_plugin" [tool.mypy] strict = true +[tool.coverage.run] +branch = true +parallel = true +omit = [ + "*/_compat.py", + "docs/conf.py", +] + +[tool.coverage.report] +show_missing = true +skip_covered = true +exclude_lines = [ + "pragma: no cover", + "def __repr__", + "raise NotImplementedError", + "return NotImplemented", + "def parse_args", + "if TYPE_CHECKING:", + "if t.TYPE_CHECKING:", + "@overload( |$)", +] + [build-system] requires = ["poetry_core>=1.0.0", "setuptools>50"] build-backend = "poetry.core.masonry.api" From e3f7c8e5c7920bfb29b8d7f224f127b169298350 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 23 Sep 2022 20:46:37 -0500 Subject: [PATCH 0114/1073] docs(CHANGES): Note move of coveragerc to pyproject --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index d1fee4b1a..2a1d7889b 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,8 @@ _Maintenance only, no bug fixes or features_ This is handled by poetry's `include` in pyproject.toml. +- Move `.coveragerc` -> `pyproject.toml` (#443) + ## libtmux 0.15.5 (2022-09-23) _Maintenance only, no bug fixes or features_ From 77f898d70e56445eae29044cd6fd4b5443f1c5ec Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 23 Sep 2022 21:07:48 -0500 Subject: [PATCH 0115/1073] Tag v0.15.7 (deprecate .coveragerc for pyproject.toml) --- CHANGES | 6 ++++-- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 2a1d7889b..f69037089 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,10 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ +## libtmux 0.15.7 (2022-09-23) + +- Move `.coveragerc` -> `pyproject.toml` (#443) + ## libtmux 0.15.6 (2022-09-23) _Maintenance only, no bug fixes or features_ @@ -22,8 +26,6 @@ _Maintenance only, no bug fixes or features_ This is handled by poetry's `include` in pyproject.toml. -- Move `.coveragerc` -> `pyproject.toml` (#443) - ## libtmux 0.15.5 (2022-09-23) _Maintenance only, no bug fixes or features_ diff --git a/pyproject.toml b/pyproject.toml index f00507273..0d25f43b0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.6" +version = "0.15.7" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index b106c9eef..b2f1dc9ad 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.6" +__version__ = "0.15.7" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From 0b8188889245f9e7fe113f29719f5d70eeedc587 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 24 Sep 2022 08:44:44 -0500 Subject: [PATCH 0116/1073] docs(conftest.py): Document root-level rationale --- conftest.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/conftest.py b/conftest.py index a728f2f20..d45b5ee5b 100644 --- a/conftest.py +++ b/conftest.py @@ -1,3 +1,12 @@ +"""Conftest.py (root-level) + +We keep this in root pytest fixtures in pytest's doctest plugin to be available, as well +as avoiding conftest.py from being included in the wheel, in addition to pytest_plugin +for pytester only being available via the root directory. + +See "pytest_plugins in non-top-level conftest files" in +https://docs.pytest.org/en/stable/deprecations.html +""" import pathlib import shutil import typing as t From 4eb3c46e3133634fb84aeb75a17ae498de488829 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 24 Sep 2022 13:08:59 -0500 Subject: [PATCH 0117/1073] build(deps): Update certifi --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 785823568..6686b8e0b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -71,7 +71,7 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2022.9.14" +version = "2022.9.24" description = "Python package for providing Mozilla's CA Bundle." category = "dev" optional = false @@ -974,8 +974,8 @@ black = [ {file = "black-22.8.0.tar.gz", hash = "sha256:792f7eb540ba9a17e8656538701d3eb1afcb134e3b45b71f20b25c77a8db7e6e"}, ] certifi = [ - {file = "certifi-2022.9.14-py3-none-any.whl", hash = "sha256:e232343de1ab72c2aa521b625c80f699e356830fd0e2c620b465b304b17b0516"}, - {file = "certifi-2022.9.14.tar.gz", hash = "sha256:36973885b9542e6bd01dea287b2b4b3b21236307c56324fcc3f1160f2d655ed5"}, + {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"}, + {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"}, ] charset-normalizer = [ {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, From 3c5289c0d2b01e5ca2aee9bd939db87c5ecf9fb4 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 24 Sep 2022 13:22:53 -0500 Subject: [PATCH 0118/1073] build(deps): Bump sphinx 5.2, use autodoc ToC improvement --- docs/conf.py | 2 +- poetry.lock | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 0c8b08fe1..38dfd6d14 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -35,7 +35,6 @@ "sphinxext.rediraffe", "myst_parser", "linkify_issues", - "sphinx_toctree_autodoc_fix", ] myst_enable_extensions = [ @@ -101,6 +100,7 @@ # sphinx.ext.autodoc autoclass_content = "both" autodoc_member_order = "bysource" +toc_object_entries_show_parents = "hide" # sphinx-copybutton copybutton_prompt_text = ( diff --git a/poetry.lock b/poetry.lock index 6686b8e0b..948252291 100644 --- a/poetry.lock +++ b/poetry.lock @@ -640,7 +640,7 @@ python-versions = ">=3.6" [[package]] name = "Sphinx" -version = "5.1.1" +version = "5.2.0" description = "Python documentation generator" category = "dev" optional = false @@ -648,16 +648,16 @@ python-versions = ">=3.6" [package.dependencies] alabaster = ">=0.7,<0.8" -babel = ">=1.3" -colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} +babel = ">=2.9" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} docutils = ">=0.14,<0.20" -imagesize = "*" -importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} -Jinja2 = ">=2.3" -packaging = "*" -Pygments = ">=2.0" +imagesize = ">=1.3" +importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""} +Jinja2 = ">=3.0" +packaging = ">=21.0" +Pygments = ">=2.12" requests = ">=2.5.0" -snowballstemmer = ">=1.1" +snowballstemmer = ">=2.0" sphinxcontrib-applehelp = "*" sphinxcontrib-devhelp = "*" sphinxcontrib-htmlhelp = ">=2.0.0" @@ -667,8 +667,8 @@ sphinxcontrib-serializinghtml = ">=1.1.5" [package.extras] docs = ["sphinxcontrib-websupport"] -lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "isort", "mypy (>=0.971)", "sphinx-lint", "types-requests", "types-typed-ast"] -test = ["cython", "html5lib", "pytest (>=4.6)", "typed-ast"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.971)", "sphinx-lint", "types-requests", "types-typed-ast"] +test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"] [[package]] name = "sphinx-autobuild" @@ -1303,8 +1303,8 @@ soupsieve = [ {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"}, ] Sphinx = [ - {file = "Sphinx-5.1.1-py3-none-any.whl", hash = "sha256:309a8da80cb6da9f4713438e5b55861877d5d7976b69d87e336733637ea12693"}, - {file = "Sphinx-5.1.1.tar.gz", hash = "sha256:ba3224a4e206e1fbdecf98a4fae4992ef9b24b85ebf7b584bb340156eaf08d89"}, + {file = "Sphinx-5.2.0.tar.gz", hash = "sha256:1790c2098937dcfa7871c9d102c24eccd4a8b883b67c5c1e26892fb52d102542"}, + {file = "sphinx-5.2.0-py3-none-any.whl", hash = "sha256:422812bdf2dacab55c47ee4dd4746bb82e739fe4c97ce16dd68bcc208e348e73"}, ] sphinx-autobuild = [ {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, From 65408ccbe70d7bae29e9c36f534982c6ca32da1b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 25 Sep 2022 22:09:43 -0500 Subject: [PATCH 0119/1073] build(deps): Bump sphinx to 5.2.1, setuptools, gp-libs --- poetry.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/poetry.lock b/poetry.lock index 948252291..cd0d807f9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -199,7 +199,7 @@ sphinx-basic-ng = "*" [[package]] name = "gp-libs" -version = "0.0.1a11" +version = "0.0.1a12" description = "Internal utilities for projects following git-pull python package spec" category = "dev" optional = false @@ -603,7 +603,7 @@ use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "setuptools" -version = "65.3.0" +version = "65.4.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" category = "dev" optional = false @@ -640,7 +640,7 @@ python-versions = ">=3.6" [[package]] name = "Sphinx" -version = "5.2.0" +version = "5.2.1" description = "Python documentation generator" category = "dev" optional = false @@ -1066,8 +1066,8 @@ furo = [ {file = "furo-2022.9.15.tar.gz", hash = "sha256:4a7ef1c8a3b615171592da4d2ad8a53cc4aacfbe111958890f5f9ff7279066ab"}, ] gp-libs = [ - {file = "gp-libs-0.0.1a11.tar.gz", hash = "sha256:2fa1d886aae88f17614c052652509ce6347adc5f39e1b35223ef0ee2b56069e5"}, - {file = "gp_libs-0.0.1a11-py3-none-any.whl", hash = "sha256:75248e0409e8af142cd2ccdbf3382300d26eb73f0155b0de721368c3543e5c35"}, + {file = "gp-libs-0.0.1a12.tar.gz", hash = "sha256:3a9a3018fa524a0008dd2a88197b2ab503a769bfa780337bf00f5753e1b95552"}, + {file = "gp_libs-0.0.1a12-py3-none-any.whl", hash = "sha256:7115eb6f65de812352fd08da1316a31458d3ceedede3fb9f7f4d2236aae0ca27"}, ] idna = [ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, @@ -1287,8 +1287,8 @@ requests = [ {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, ] setuptools = [ - {file = "setuptools-65.3.0-py3-none-any.whl", hash = "sha256:2e24e0bec025f035a2e72cdd1961119f557d78ad331bb00ff82efb2ab8da8e82"}, - {file = "setuptools-65.3.0.tar.gz", hash = "sha256:7732871f4f7fa58fb6bdcaeadb0161b2bd046c85905dbaa066bdcbcc81953b57"}, + {file = "setuptools-65.4.0-py3-none-any.whl", hash = "sha256:c2d2709550f15aab6c9110196ea312f468f41cd546bceb24127a1be6fdcaeeb1"}, + {file = "setuptools-65.4.0.tar.gz", hash = "sha256:a8f6e213b4b0661f590ccf40de95d28a177cd747d098624ad3f69c40287297e9"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, @@ -1303,8 +1303,8 @@ soupsieve = [ {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"}, ] Sphinx = [ - {file = "Sphinx-5.2.0.tar.gz", hash = "sha256:1790c2098937dcfa7871c9d102c24eccd4a8b883b67c5c1e26892fb52d102542"}, - {file = "sphinx-5.2.0-py3-none-any.whl", hash = "sha256:422812bdf2dacab55c47ee4dd4746bb82e739fe4c97ce16dd68bcc208e348e73"}, + {file = "Sphinx-5.2.1.tar.gz", hash = "sha256:c009bb2e9ac5db487bcf53f015504005a330ff7c631bb6ab2604e0d65bae8b54"}, + {file = "sphinx-5.2.1-py3-none-any.whl", hash = "sha256:3dcf00fcf82cf91118db9b7177edea4fc01998976f893928d0ab0c58c54be2ca"}, ] sphinx-autobuild = [ {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, From d0a73608fbcdb55033658f5cb126fa4d5414fb30 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 27 Sep 2022 22:27:15 -0500 Subject: [PATCH 0120/1073] build(deps): Bump mypy, myst, sphinx, sphinx-autodoc-typehints --- poetry.lock | 98 +++++++++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 48 deletions(-) diff --git a/poetry.lock b/poetry.lock index cd0d807f9..cc6663f72 100644 --- a/poetry.lock +++ b/poetry.lock @@ -330,19 +330,19 @@ python-versions = "*" [[package]] name = "mdit-py-plugins" -version = "0.3.0" +version = "0.3.1" description = "Collection of plugins for markdown-it-py" category = "dev" optional = false -python-versions = "~=3.6" +python-versions = ">=3.7" [package.dependencies] markdown-it-py = ">=1.0.0,<3.0.0" [package.extras] -code_style = ["pre-commit (==2.6)"] -rtd = ["myst-parser (>=0.14.0,<0.15.0)", "sphinx-book-theme (>=0.1.0,<0.2.0)"] -testing = ["coverage", "pytest (>=3.6,<4)", "pytest-cov", "pytest-regressions"] +code_style = ["pre-commit"] +rtd = ["attrs", "myst-parser (>=0.16.1,<0.17.0)", "sphinx-book-theme (>=0.1.0,<0.2.0)"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] name = "mdurl" @@ -354,11 +354,11 @@ python-versions = ">=3.7" [[package]] name = "mypy" -version = "0.971" +version = "0.981" description = "Optional static typing for Python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] mypy-extensions = ">=0.4.3" @@ -381,17 +381,17 @@ python-versions = "*" [[package]] name = "myst-parser" -version = "0.18.0" +version = "0.18.1" description = "An extended commonmark compliant parser, with bridges to docutils & sphinx." category = "dev" optional = false python-versions = ">=3.7" [package.dependencies] -docutils = ">=0.15,<0.19" +docutils = ">=0.15,<0.20" jinja2 = "*" markdown-it-py = ">=1.0.0,<3.0.0" -mdit-py-plugins = ">=0.3.0,<0.4.0" +mdit-py-plugins = ">=0.3.1,<0.4.0" pyyaml = "*" sphinx = ">=4,<6" typing-extensions = "*" @@ -400,7 +400,7 @@ typing-extensions = "*" code_style = ["pre-commit (>=2.12,<3.0)"] linkify = ["linkify-it-py (>=1.0,<2.0)"] rtd = ["ipython", "sphinx-book-theme", "sphinx-design", "sphinxcontrib.mermaid (>=0.7.1,<0.8.0)", "sphinxext-opengraph (>=0.6.3,<0.7.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] -testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=6,<7)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx-pytest"] +testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=6,<7)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx (<5.2)", "sphinx-pytest"] [[package]] name = "packaging" @@ -640,7 +640,7 @@ python-versions = ">=3.6" [[package]] name = "Sphinx" -version = "5.2.1" +version = "5.2.2" description = "Python documentation generator" category = "dev" optional = false @@ -667,7 +667,7 @@ sphinxcontrib-serializinghtml = ">=1.1.5" [package.extras] docs = ["sphinxcontrib-websupport"] -lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.971)", "sphinx-lint", "types-requests", "types-typed-ast"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.981)", "sphinx-lint", "types-requests", "types-typed-ast"] test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"] [[package]] @@ -688,18 +688,19 @@ test = ["pytest", "pytest-cov"] [[package]] name = "sphinx-autodoc-typehints" -version = "1.19.2" +version = "1.19.4" description = "Type hints (PEP 484) support for the Sphinx autodoc extension" category = "dev" optional = false python-versions = ">=3.7" [package.dependencies] -Sphinx = ">=5.1.1" +sphinx = ">=5.2.1" [package.extras] -testing = ["covdefaults (>=2.2)", "coverage (>=6.4.2)", "diff-cover (>=6.5.1)", "nptyping (>=2.2)", "pytest (>=7.1.2)", "pytest-cov (>=3)", "sphobjinv (>=2.2.2)", "typing-extensions (>=4.3)"] -type_comments = ["typed-ast (>=1.5.4)"] +docs = ["furo (>=2022.9.15)", "sphinx (>=5.2.1)", "sphinx-autodoc-typehints (>=1.19.3)"] +testing = ["covdefaults (>=2.2)", "coverage (>=6.4.4)", "diff-cover (>=7.0.1)", "nptyping (>=2.3.1)", "pytest (>=7.1.3)", "pytest-cov (>=3)", "sphobjinv (>=2.2.2)", "typing-extensions (>=4.3)"] +type-comment = ["typed-ast (>=1.5.4)"] [[package]] name = "sphinx-basic-ng" @@ -1147,45 +1148,46 @@ mccabe = [ {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] mdit-py-plugins = [ - {file = "mdit-py-plugins-0.3.0.tar.gz", hash = "sha256:ecc24f51eeec6ab7eecc2f9724e8272c2fb191c2e93cf98109120c2cace69750"}, - {file = "mdit_py_plugins-0.3.0-py3-none-any.whl", hash = "sha256:b1279701cee2dbf50e188d3da5f51fee8d78d038cdf99be57c6b9d1aa93b4073"}, + {file = "mdit-py-plugins-0.3.1.tar.gz", hash = "sha256:3fc13298497d6e04fe96efdd41281bfe7622152f9caa1815ea99b5c893de9441"}, + {file = "mdit_py_plugins-0.3.1-py3-none-any.whl", hash = "sha256:606a7f29cf56dbdfaf914acb21709b8f8ee29d857e8f29dcc33d8cb84c57bfa1"}, ] mdurl = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] mypy = [ - {file = "mypy-0.971-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2899a3cbd394da157194f913a931edfd4be5f274a88041c9dc2d9cdcb1c315c"}, - {file = "mypy-0.971-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98e02d56ebe93981c41211c05adb630d1d26c14195d04d95e49cd97dbc046dc5"}, - {file = "mypy-0.971-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:19830b7dba7d5356d3e26e2427a2ec91c994cd92d983142cbd025ebe81d69cf3"}, - {file = "mypy-0.971-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:02ef476f6dcb86e6f502ae39a16b93285fef97e7f1ff22932b657d1ef1f28655"}, - {file = "mypy-0.971-cp310-cp310-win_amd64.whl", hash = "sha256:25c5750ba5609a0c7550b73a33deb314ecfb559c350bb050b655505e8aed4103"}, - {file = "mypy-0.971-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d3348e7eb2eea2472db611486846742d5d52d1290576de99d59edeb7cd4a42ca"}, - {file = "mypy-0.971-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3fa7a477b9900be9b7dd4bab30a12759e5abe9586574ceb944bc29cddf8f0417"}, - {file = "mypy-0.971-cp36-cp36m-win_amd64.whl", hash = "sha256:2ad53cf9c3adc43cf3bea0a7d01a2f2e86db9fe7596dfecb4496a5dda63cbb09"}, - {file = "mypy-0.971-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:855048b6feb6dfe09d3353466004490b1872887150c5bb5caad7838b57328cc8"}, - {file = "mypy-0.971-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:23488a14a83bca6e54402c2e6435467a4138785df93ec85aeff64c6170077fb0"}, - {file = "mypy-0.971-cp37-cp37m-win_amd64.whl", hash = "sha256:4b21e5b1a70dfb972490035128f305c39bc4bc253f34e96a4adf9127cf943eb2"}, - {file = "mypy-0.971-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9796a2ba7b4b538649caa5cecd398d873f4022ed2333ffde58eaf604c4d2cb27"}, - {file = "mypy-0.971-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a361d92635ad4ada1b1b2d3630fc2f53f2127d51cf2def9db83cba32e47c856"}, - {file = "mypy-0.971-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b793b899f7cf563b1e7044a5c97361196b938e92f0a4343a5d27966a53d2ec71"}, - {file = "mypy-0.971-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d1ea5d12c8e2d266b5fb8c7a5d2e9c0219fedfeb493b7ed60cd350322384ac27"}, - {file = "mypy-0.971-cp38-cp38-win_amd64.whl", hash = "sha256:23c7ff43fff4b0df93a186581885c8512bc50fc4d4910e0f838e35d6bb6b5e58"}, - {file = "mypy-0.971-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1f7656b69974a6933e987ee8ffb951d836272d6c0f81d727f1d0e2696074d9e6"}, - {file = "mypy-0.971-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d2022bfadb7a5c2ef410d6a7c9763188afdb7f3533f22a0a32be10d571ee4bbe"}, - {file = "mypy-0.971-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef943c72a786b0f8d90fd76e9b39ce81fb7171172daf84bf43eaf937e9f220a9"}, - {file = "mypy-0.971-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d744f72eb39f69312bc6c2abf8ff6656973120e2eb3f3ec4f758ed47e414a4bf"}, - {file = "mypy-0.971-cp39-cp39-win_amd64.whl", hash = "sha256:77a514ea15d3007d33a9e2157b0ba9c267496acf12a7f2b9b9f8446337aac5b0"}, - {file = "mypy-0.971-py3-none-any.whl", hash = "sha256:0d054ef16b071149917085f51f89555a576e2618d5d9dd70bd6eea6410af3ac9"}, - {file = "mypy-0.971.tar.gz", hash = "sha256:40b0f21484238269ae6a57200c807d80debc6459d444c0489a102d7c6a75fa56"}, + {file = "mypy-0.981-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4bc460e43b7785f78862dab78674e62ec3cd523485baecfdf81a555ed29ecfa0"}, + {file = "mypy-0.981-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:756fad8b263b3ba39e4e204ee53042671b660c36c9017412b43af210ddee7b08"}, + {file = "mypy-0.981-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a16a0145d6d7d00fbede2da3a3096dcc9ecea091adfa8da48fa6a7b75d35562d"}, + {file = "mypy-0.981-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce65f70b14a21fdac84c294cde75e6dbdabbcff22975335e20827b3b94bdbf49"}, + {file = "mypy-0.981-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e35d764784b42c3e256848fb8ed1d4292c9fc0098413adb28d84974c095b279"}, + {file = "mypy-0.981-cp310-cp310-win_amd64.whl", hash = "sha256:e53773073c864d5f5cec7f3fc72fbbcef65410cde8cc18d4f7242dea60dac52e"}, + {file = "mypy-0.981-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6ee196b1d10b8b215e835f438e06965d7a480f6fe016eddbc285f13955cca659"}, + {file = "mypy-0.981-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ad21d4c9d3673726cf986ea1d0c9fb66905258709550ddf7944c8f885f208be"}, + {file = "mypy-0.981-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d1debb09043e1f5ee845fa1e96d180e89115b30e47c5d3ce53bc967bab53f62d"}, + {file = "mypy-0.981-cp37-cp37m-win_amd64.whl", hash = "sha256:9f362470a3480165c4c6151786b5379351b790d56952005be18bdbdd4c7ce0ae"}, + {file = "mypy-0.981-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c9e0efb95ed6ca1654951bd5ec2f3fa91b295d78bf6527e026529d4aaa1e0c30"}, + {file = "mypy-0.981-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e178eaffc3c5cd211a87965c8c0df6da91ed7d258b5fc72b8e047c3771317ddb"}, + {file = "mypy-0.981-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:06e1eac8d99bd404ed8dd34ca29673c4346e76dd8e612ea507763dccd7e13c7a"}, + {file = "mypy-0.981-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa38f82f53e1e7beb45557ff167c177802ba7b387ad017eab1663d567017c8ee"}, + {file = "mypy-0.981-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:64e1f6af81c003f85f0dfed52db632817dabb51b65c0318ffbf5ff51995bbb08"}, + {file = "mypy-0.981-cp38-cp38-win_amd64.whl", hash = "sha256:e1acf62a8c4f7c092462c738aa2c2489e275ed386320c10b2e9bff31f6f7e8d6"}, + {file = "mypy-0.981-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b6ede64e52257931315826fdbfc6ea878d89a965580d1a65638ef77cb551f56d"}, + {file = "mypy-0.981-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eb3978b191b9fa0488524bb4ffedf2c573340e8c2b4206fc191d44c7093abfb7"}, + {file = "mypy-0.981-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f8fcf7b4b3cc0c74fb33ae54a4cd00bb854d65645c48beccf65fa10b17882c"}, + {file = "mypy-0.981-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f64d2ce043a209a297df322eb4054dfbaa9de9e8738291706eaafda81ab2b362"}, + {file = "mypy-0.981-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2ee3dbc53d4df7e6e3b1c68ac6a971d3a4fb2852bf10a05fda228721dd44fae1"}, + {file = "mypy-0.981-cp39-cp39-win_amd64.whl", hash = "sha256:8e8e49aa9cc23aa4c926dc200ce32959d3501c4905147a66ce032f05cb5ecb92"}, + {file = "mypy-0.981-py3-none-any.whl", hash = "sha256:794f385653e2b749387a42afb1e14c2135e18daeb027e0d97162e4b7031210f8"}, + {file = "mypy-0.981.tar.gz", hash = "sha256:ad77c13037d3402fbeffda07d51e3f228ba078d1c7096a73759c9419ea031bf4"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] myst-parser = [ - {file = "myst-parser-0.18.0.tar.gz", hash = "sha256:739a4d96773a8e55a2cacd3941ce46a446ee23dcd6b37e06f73f551ad7821d86"}, - {file = "myst_parser-0.18.0-py3-none-any.whl", hash = "sha256:4965e51918837c13bf1c6f6fe2c6bddddf193148360fbdaefe743a4981358f6a"}, + {file = "myst-parser-0.18.1.tar.gz", hash = "sha256:79317f4bb2c13053dd6e64f9da1ba1da6cd9c40c8a430c447a7b146a594c246d"}, + {file = "myst_parser-0.18.1-py3-none-any.whl", hash = "sha256:61b275b85d9f58aa327f370913ae1bec26ebad372cc99f3ab85c8ec3ee8d9fb8"}, ] packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, @@ -1303,16 +1305,16 @@ soupsieve = [ {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"}, ] Sphinx = [ - {file = "Sphinx-5.2.1.tar.gz", hash = "sha256:c009bb2e9ac5db487bcf53f015504005a330ff7c631bb6ab2604e0d65bae8b54"}, - {file = "sphinx-5.2.1-py3-none-any.whl", hash = "sha256:3dcf00fcf82cf91118db9b7177edea4fc01998976f893928d0ab0c58c54be2ca"}, + {file = "Sphinx-5.2.2.tar.gz", hash = "sha256:7225c104dc06169eb73b061582c4bc84a9594042acae6c1582564de274b7df2f"}, + {file = "sphinx-5.2.2-py3-none-any.whl", hash = "sha256:9150a8ed2e98d70e778624373f183c5498bf429dd605cf7b63e80e2a166c35a5"}, ] sphinx-autobuild = [ {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, {file = "sphinx_autobuild-2021.3.14-py3-none-any.whl", hash = "sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac"}, ] sphinx-autodoc-typehints = [ - {file = "sphinx_autodoc_typehints-1.19.2-py3-none-any.whl", hash = "sha256:3d761de928d5a86901331133d6d4a2552afa2e798ebcfc0886791792aeb4dd9a"}, - {file = "sphinx_autodoc_typehints-1.19.2.tar.gz", hash = "sha256:872fb2d7b3d794826c28e36edf6739e93549491447dcabeb07c58855e9f914de"}, + {file = "sphinx_autodoc_typehints-1.19.4-py3-none-any.whl", hash = "sha256:e190d8ee8204c3de05a64f41cf10e592e987e4063c8ec0de7e4b11f6e036b2e2"}, + {file = "sphinx_autodoc_typehints-1.19.4.tar.gz", hash = "sha256:ffd8e710f6757471b5c831c7ece88f52a9ff15f27836f4ef1c8695a64f8dcca8"}, ] sphinx-basic-ng = [ {file = "sphinx_basic_ng-0.0.1a12-py3-none-any.whl", hash = "sha256:e8b6efd2c5ece014156de76065eda01ddfca0fee465aa020b1e3c12f84570bbe"}, From 771b7b6f0f6ca5fe1fda7ffee6a497d16563e263 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 27 Sep 2022 22:37:03 -0500 Subject: [PATCH 0121/1073] build(deps): Loosen constraints --- poetry.lock | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index cc6663f72..7520fc6ab 100644 --- a/poetry.lock +++ b/poetry.lock @@ -930,7 +930,7 @@ test = [] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "8d3b35942a6fa00bd31c365d691c1dfc82966a6b841478dbb894f88499bc9116" +content-hash = "36af79cc783bed3c54ef5e8c829e839e4a0386625d34acfd0a7dfeaa511dd98f" [metadata.files] alabaster = [ diff --git a/pyproject.toml b/pyproject.toml index 0d25f43b0..25c86deef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,7 +60,7 @@ sphinxext-opengraph = "*" sphinx-copybutton = "*" sphinxext-rediraffe = "*" myst_parser = "*" -docutils = "~0.18.0" +docutils = "*" ### Testing ### pytest = "*" From 0c7e75a9e5d2606d08a0e58dbffbc68e0b54fd6e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 27 Sep 2022 22:49:16 -0500 Subject: [PATCH 0122/1073] build(deps): Update gp-libs --- poetry.lock | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7520fc6ab..8b269cd10 100644 --- a/poetry.lock +++ b/poetry.lock @@ -930,7 +930,7 @@ test = [] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "36af79cc783bed3c54ef5e8c829e839e4a0386625d34acfd0a7dfeaa511dd98f" +content-hash = "cda172f196f0ccd20595a7ee7cce28a8553268204869f9fe4b9e28c933837b09" [metadata.files] alabaster = [ diff --git a/pyproject.toml b/pyproject.toml index 25c86deef..e44b726b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,7 +51,7 @@ python = "^3.7" ### Docs ### sphinx = "*" furo = "*" -gp-libs = "*" +gp-libs = "~0.0.1a12" sphinx-autobuild = "*" sphinx-autodoc-typehints = "*" sphinx-click = "*" From b23be236c28a628a25db568266083422d08c2c52 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 29 Sep 2022 18:53:28 -0500 Subject: [PATCH 0123/1073] build(deps): Update furo, sphinx-basic-ng --- poetry.lock | 128 ++++++++++++++++++++++++++-------------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/poetry.lock b/poetry.lock index 8b269cd10..d2e2ef923 100644 --- a/poetry.lock +++ b/poetry.lock @@ -122,7 +122,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "coverage" -version = "6.4.4" +version = "6.5.0" description = "Code coverage measurement for Python" category = "dev" optional = false @@ -185,7 +185,7 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [[package]] name = "furo" -version = "2022.9.15" +version = "2022.9.29" description = "A clean customisable Sphinx documentation theme." category = "dev" optional = false @@ -517,7 +517,7 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2. [[package]] name = "pytest-cov" -version = "3.0.0" +version = "4.0.0" description = "Pytest plugin for measuring coverage." category = "dev" optional = false @@ -532,7 +532,7 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale [[package]] name = "pytest-mock" -version = "3.8.2" +version = "3.9.0" description = "Thin-wrapper around the mock package for easier use with pytest" category = "dev" optional = false @@ -704,14 +704,14 @@ type-comment = ["typed-ast (>=1.5.4)"] [[package]] name = "sphinx-basic-ng" -version = "0.0.1a12" +version = "1.0.0b1" description = "A modern skeleton for Sphinx themes." category = "dev" optional = false python-versions = ">=3.7" [package.dependencies] -sphinx = ">=4.0,<6.0" +sphinx = ">=4.0" [package.extras] docs = ["furo", "ipython", "myst-parser", "sphinx-copybutton", "sphinx-inline-tabs"] @@ -995,56 +995,56 @@ colorama = [ {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, ] coverage = [ - {file = "coverage-6.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e7b4da9bafad21ea45a714d3ea6f3e1679099e420c8741c74905b92ee9bfa7cc"}, - {file = "coverage-6.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fde17bc42e0716c94bf19d92e4c9f5a00c5feb401f5bc01101fdf2a8b7cacf60"}, - {file = "coverage-6.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdbb0d89923c80dbd435b9cf8bba0ff55585a3cdb28cbec65f376c041472c60d"}, - {file = "coverage-6.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:67f9346aeebea54e845d29b487eb38ec95f2ecf3558a3cffb26ee3f0dcc3e760"}, - {file = "coverage-6.4.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42c499c14efd858b98c4e03595bf914089b98400d30789511577aa44607a1b74"}, - {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c35cca192ba700979d20ac43024a82b9b32a60da2f983bec6c0f5b84aead635c"}, - {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9cc4f107009bca5a81caef2fca843dbec4215c05e917a59dec0c8db5cff1d2aa"}, - {file = "coverage-6.4.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f444627b3664b80d078c05fe6a850dd711beeb90d26731f11d492dcbadb6973"}, - {file = "coverage-6.4.4-cp310-cp310-win32.whl", hash = "sha256:66e6df3ac4659a435677d8cd40e8eb1ac7219345d27c41145991ee9bf4b806a0"}, - {file = "coverage-6.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:35ef1f8d8a7a275aa7410d2f2c60fa6443f4a64fae9be671ec0696a68525b875"}, - {file = "coverage-6.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c1328d0c2f194ffda30a45f11058c02410e679456276bfa0bbe0b0ee87225fac"}, - {file = "coverage-6.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61b993f3998ee384935ee423c3d40894e93277f12482f6e777642a0141f55782"}, - {file = "coverage-6.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d5dd4b8e9cd0deb60e6fcc7b0647cbc1da6c33b9e786f9c79721fd303994832f"}, - {file = "coverage-6.4.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7026f5afe0d1a933685d8f2169d7c2d2e624f6255fb584ca99ccca8c0e966fd7"}, - {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9c7b9b498eb0c0d48b4c2abc0e10c2d78912203f972e0e63e3c9dc21f15abdaa"}, - {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ee2b2fb6eb4ace35805f434e0f6409444e1466a47f620d1d5763a22600f0f892"}, - {file = "coverage-6.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ab066f5ab67059d1f1000b5e1aa8bbd75b6ed1fc0014559aea41a9eb66fc2ce0"}, - {file = "coverage-6.4.4-cp311-cp311-win32.whl", hash = "sha256:9d6e1f3185cbfd3d91ac77ea065d85d5215d3dfa45b191d14ddfcd952fa53796"}, - {file = "coverage-6.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:e3d3c4cc38b2882f9a15bafd30aec079582b819bec1b8afdbde8f7797008108a"}, - {file = "coverage-6.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a095aa0a996ea08b10580908e88fbaf81ecf798e923bbe64fb98d1807db3d68a"}, - {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef6f44409ab02e202b31a05dd6666797f9de2aa2b4b3534e9d450e42dea5e817"}, - {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b7101938584d67e6f45f0015b60e24a95bf8dea19836b1709a80342e01b472f"}, - {file = "coverage-6.4.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14a32ec68d721c3d714d9b105c7acf8e0f8a4f4734c811eda75ff3718570b5e3"}, - {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6a864733b22d3081749450466ac80698fe39c91cb6849b2ef8752fd7482011f3"}, - {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:08002f9251f51afdcc5e3adf5d5d66bb490ae893d9e21359b085f0e03390a820"}, - {file = "coverage-6.4.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a3b2752de32c455f2521a51bd3ffb53c5b3ae92736afde67ce83477f5c1dd928"}, - {file = "coverage-6.4.4-cp37-cp37m-win32.whl", hash = "sha256:f855b39e4f75abd0dfbcf74a82e84ae3fc260d523fcb3532786bcbbcb158322c"}, - {file = "coverage-6.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ee6ae6bbcac0786807295e9687169fba80cb0617852b2fa118a99667e8e6815d"}, - {file = "coverage-6.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:564cd0f5b5470094df06fab676c6d77547abfdcb09b6c29c8a97c41ad03b103c"}, - {file = "coverage-6.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cbbb0e4cd8ddcd5ef47641cfac97d8473ab6b132dd9a46bacb18872828031685"}, - {file = "coverage-6.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6113e4df2fa73b80f77663445be6d567913fb3b82a86ceb64e44ae0e4b695de1"}, - {file = "coverage-6.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d032bfc562a52318ae05047a6eb801ff31ccee172dc0d2504614e911d8fa83e"}, - {file = "coverage-6.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e431e305a1f3126477abe9a184624a85308da8edf8486a863601d58419d26ffa"}, - {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cf2afe83a53f77aec067033199797832617890e15bed42f4a1a93ea24794ae3e"}, - {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:783bc7c4ee524039ca13b6d9b4186a67f8e63d91342c713e88c1865a38d0892a"}, - {file = "coverage-6.4.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ff934ced84054b9018665ca3967fc48e1ac99e811f6cc99ea65978e1d384454b"}, - {file = "coverage-6.4.4-cp38-cp38-win32.whl", hash = "sha256:e1fabd473566fce2cf18ea41171d92814e4ef1495e04471786cbc943b89a3781"}, - {file = "coverage-6.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:4179502f210ebed3ccfe2f78bf8e2d59e50b297b598b100d6c6e3341053066a2"}, - {file = "coverage-6.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:98c0b9e9b572893cdb0a00e66cf961a238f8d870d4e1dc8e679eb8bdc2eb1b86"}, - {file = "coverage-6.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc600f6ec19b273da1d85817eda339fb46ce9eef3e89f220055d8696e0a06908"}, - {file = "coverage-6.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a98d6bf6d4ca5c07a600c7b4e0c5350cd483c85c736c522b786be90ea5bac4f"}, - {file = "coverage-6.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01778769097dbd705a24e221f42be885c544bb91251747a8a3efdec6eb4788f2"}, - {file = "coverage-6.4.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfa0b97eb904255e2ab24166071b27408f1f69c8fbda58e9c0972804851e0558"}, - {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fcbe3d9a53e013f8ab88734d7e517eb2cd06b7e689bedf22c0eb68db5e4a0a19"}, - {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:15e38d853ee224e92ccc9a851457fb1e1f12d7a5df5ae44544ce7863691c7a0d"}, - {file = "coverage-6.4.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6913dddee2deff8ab2512639c5168c3e80b3ebb0f818fed22048ee46f735351a"}, - {file = "coverage-6.4.4-cp39-cp39-win32.whl", hash = "sha256:354df19fefd03b9a13132fa6643527ef7905712109d9c1c1903f2133d3a4e145"}, - {file = "coverage-6.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:1238b08f3576201ebf41f7c20bf59baa0d05da941b123c6656e42cdb668e9827"}, - {file = "coverage-6.4.4-pp36.pp37.pp38-none-any.whl", hash = "sha256:f67cf9f406cf0d2f08a3515ce2db5b82625a7257f88aad87904674def6ddaec1"}, - {file = "coverage-6.4.4.tar.gz", hash = "sha256:e16c45b726acb780e1e6f88b286d3c10b3914ab03438f32117c4aa52d7f30d58"}, + {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"}, + {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"}, + {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"}, + {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"}, + {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"}, + {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"}, + {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"}, + {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"}, + {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"}, + {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"}, + {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"}, + {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"}, + {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"}, + {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"}, + {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"}, + {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"}, + {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"}, + {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"}, + {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"}, + {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"}, ] docutils = [ {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, @@ -1063,8 +1063,8 @@ flake8-comprehensions = [ {file = "flake8_comprehensions-3.10.0-py3-none-any.whl", hash = "sha256:dad454fd3d525039121e98fa1dd90c46bc138708196a4ebbc949ad3c859adedb"}, ] furo = [ - {file = "furo-2022.9.15-py3-none-any.whl", hash = "sha256:9129dead1f75e9fb4fa407612f1d5a0d0320767e6156c925aafe36f362f9b11a"}, - {file = "furo-2022.9.15.tar.gz", hash = "sha256:4a7ef1c8a3b615171592da4d2ad8a53cc4aacfbe111958890f5f9ff7279066ab"}, + {file = "furo-2022.9.29-py3-none-any.whl", hash = "sha256:559ee17999c0f52728481dcf6b1b0cf8c9743e68c5e3a18cb45a7992747869a9"}, + {file = "furo-2022.9.29.tar.gz", hash = "sha256:d4238145629c623609c2deb5384f8d036e2a1ee2a101d64b67b4348112470dbd"}, ] gp-libs = [ {file = "gp-libs-0.0.1a12.tar.gz", hash = "sha256:3a9a3018fa524a0008dd2a88197b2ab503a769bfa780337bf00f5753e1b95552"}, @@ -1230,12 +1230,12 @@ pytest = [ {file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"}, ] pytest-cov = [ - {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, - {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, + {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"}, + {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"}, ] pytest-mock = [ - {file = "pytest-mock-3.8.2.tar.gz", hash = "sha256:77f03f4554392558700295e05aed0b1096a20d4a60a4f3ddcde58b0c31c8fca2"}, - {file = "pytest_mock-3.8.2-py3-none-any.whl", hash = "sha256:8a9e226d6c0ef09fcf20c94eb3405c388af438a90f3e39687f84166da82d5948"}, + {file = "pytest-mock-3.9.0.tar.gz", hash = "sha256:c899a0dcc8a5f22930acd020b500abd5f956911f326864a3b979e4866e14da82"}, + {file = "pytest_mock-3.9.0-py3-none-any.whl", hash = "sha256:1a1b9264224d026932d6685a0f9cef3b61d91563c3e74af9fe5afb2767e13812"}, ] pytest-rerunfailures = [ {file = "pytest-rerunfailures-10.2.tar.gz", hash = "sha256:9e1e1bad51e07642c5bbab809fc1d4ec8eebcb7de86f90f1a26e6ef9de446697"}, @@ -1317,8 +1317,8 @@ sphinx-autodoc-typehints = [ {file = "sphinx_autodoc_typehints-1.19.4.tar.gz", hash = "sha256:ffd8e710f6757471b5c831c7ece88f52a9ff15f27836f4ef1c8695a64f8dcca8"}, ] sphinx-basic-ng = [ - {file = "sphinx_basic_ng-0.0.1a12-py3-none-any.whl", hash = "sha256:e8b6efd2c5ece014156de76065eda01ddfca0fee465aa020b1e3c12f84570bbe"}, - {file = "sphinx_basic_ng-0.0.1a12.tar.gz", hash = "sha256:cffffb14914ddd26c94b1330df1d72dab5a42e220aaeb5953076a40b9c50e801"}, + {file = "sphinx_basic_ng-1.0.0b1-py3-none-any.whl", hash = "sha256:ade597a3029c7865b24ad0eda88318766bcc2f9f4cef60df7e28126fde94db2a"}, + {file = "sphinx_basic_ng-1.0.0b1.tar.gz", hash = "sha256:89374bd3ccd9452a301786781e28c8718e99960f2d4f411845ea75fc7bb5a9b0"}, ] sphinx-click = [ {file = "sphinx-click-4.3.0.tar.gz", hash = "sha256:bd4db5d3c1bec345f07af07b8e28a76cfc5006d997984e38ae246bbf8b9a3b38"}, From 3f27604c436cc95ead306c79b3462a1b8bd37a4d Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 29 Sep 2022 18:54:46 -0500 Subject: [PATCH 0124/1073] docs(conf): Add edit links --- docs/conf.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index 38dfd6d14..56fc7d7eb 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -82,6 +82,9 @@ "class": "", }, ], + "source_repository": f"{about['__github__']}/", + "source_branch": "master", + "source_directory": "docs/", } html_sidebars = { "**": [ From 0c6bec538777ab2ad205c8e683810dd1d79ba0cb Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 29 Sep 2022 18:55:10 -0500 Subject: [PATCH 0125/1073] docs(conf): Add announcement --- docs/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/conf.py b/docs/conf.py index 56fc7d7eb..383fe7ce1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -85,6 +85,7 @@ "source_repository": f"{about['__github__']}/", "source_branch": "master", "source_directory": "docs/", + "announcement": "Friendly reminder: 📌 Pin the package, libtmux is pre-1.0 and APIs will be changing throughout 2022-2023.", } html_sidebars = { "**": [ From d73c340f37e4788bffafd1bef9c8c5e1818e972d Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 30 Sep 2022 06:48:09 -0500 Subject: [PATCH 0126/1073] build(deps): Bump setuptools --- poetry.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index d2e2ef923..0ef38cf2e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -603,14 +603,14 @@ use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "setuptools" -version = "65.4.0" +version = "65.4.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mock", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] @@ -1289,8 +1289,8 @@ requests = [ {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, ] setuptools = [ - {file = "setuptools-65.4.0-py3-none-any.whl", hash = "sha256:c2d2709550f15aab6c9110196ea312f468f41cd546bceb24127a1be6fdcaeeb1"}, - {file = "setuptools-65.4.0.tar.gz", hash = "sha256:a8f6e213b4b0661f590ccf40de95d28a177cd747d098624ad3f69c40287297e9"}, + {file = "setuptools-65.4.1-py3-none-any.whl", hash = "sha256:1b6bdc6161661409c5f21508763dc63ab20a9ac2f8ba20029aaaa7fdb9118012"}, + {file = "setuptools-65.4.1.tar.gz", hash = "sha256:3050e338e5871e70c72983072fe34f6032ae1cdeeeb67338199c2f74e083a80e"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, From 31b5cc4cdb295a110c6df6a26a4d2e153d319e1a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 30 Sep 2022 18:40:11 -0500 Subject: [PATCH 0127/1073] build(deps): Bump sphinx --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 0ef38cf2e..5b094692c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -640,7 +640,7 @@ python-versions = ">=3.6" [[package]] name = "Sphinx" -version = "5.2.2" +version = "5.2.3" description = "Python documentation generator" category = "dev" optional = false @@ -1305,8 +1305,8 @@ soupsieve = [ {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"}, ] Sphinx = [ - {file = "Sphinx-5.2.2.tar.gz", hash = "sha256:7225c104dc06169eb73b061582c4bc84a9594042acae6c1582564de274b7df2f"}, - {file = "sphinx-5.2.2-py3-none-any.whl", hash = "sha256:9150a8ed2e98d70e778624373f183c5498bf429dd605cf7b63e80e2a166c35a5"}, + {file = "Sphinx-5.2.3.tar.gz", hash = "sha256:5b10cb1022dac8c035f75767799c39217a05fc0fe2d6fe5597560d38e44f0363"}, + {file = "sphinx-5.2.3-py3-none-any.whl", hash = "sha256:7abf6fabd7b58d0727b7317d5e2650ef68765bbe0ccb63c8795fa8683477eaa2"}, ] sphinx-autobuild = [ {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, From d2cabea6d06750bf4c8986288761a653ea2e7872 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 1 Oct 2022 05:21:06 -0500 Subject: [PATCH 0128/1073] build(deps): Loosen dev dependencies --- poetry.lock | 2 +- pyproject.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 5b094692c..6a6b48fdb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -930,7 +930,7 @@ test = [] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "cda172f196f0ccd20595a7ee7cce28a8553268204869f9fe4b9e28c933837b09" +content-hash = "92b0a96ae2ee9b02bf74a4d65c483d09e569f56f127a71ce66ce223a5a85ae97" [metadata.files] alabaster = [ diff --git a/pyproject.toml b/pyproject.toml index e44b726b3..64c88ec94 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,7 +66,7 @@ docutils = "*" pytest = "*" pytest-rerunfailures = "*" pytest-mock = "*" -pytest-watcher = "^0.2.3" +pytest-watcher = "*" ### Coverage ### codecov = "*" @@ -79,7 +79,7 @@ isort = "*" ### Lint ### flake8 = "*" -flake8-bugbear = "^22.8.23" +flake8-bugbear = "*" flake8-comprehensions = "*" mypy = "*" From 662c70611017448661a663e44b3b0ded2a163db5 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 1 Oct 2022 13:49:09 -0500 Subject: [PATCH 0129/1073] build(deps): Bump gp-libs, docutils --- poetry.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/poetry.lock b/poetry.lock index 6a6b48fdb..15618c687 100644 --- a/poetry.lock +++ b/poetry.lock @@ -136,11 +136,11 @@ toml = ["tomli"] [[package]] name = "docutils" -version = "0.18.1" +version = "0.19" description = "Docutils -- Python Documentation Utilities" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" [[package]] name = "flake8" @@ -199,14 +199,14 @@ sphinx-basic-ng = "*" [[package]] name = "gp-libs" -version = "0.0.1a12" +version = "0.0.1a14" description = "Internal utilities for projects following git-pull python package spec" category = "dev" optional = false python-versions = ">=3.7,<4.0" [package.dependencies] -docutils = ">=0.18.0,<0.19.0" +docutils = "*" myst_parser = "*" [[package]] @@ -227,7 +227,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "importlib-metadata" -version = "4.12.0" +version = "4.13.0" description = "Read metadata from Python packages" category = "dev" optional = false @@ -238,9 +238,9 @@ typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} zipp = ">=0.5" [package.extras] -docs = ["jaraco.packaging (>=9)", "rst.linker (>=1.9)", "sphinx"] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] +testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] [[package]] name = "iniconfig" @@ -1047,8 +1047,8 @@ coverage = [ {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"}, ] docutils = [ - {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, - {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, + {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"}, + {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"}, ] flake8 = [ {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, @@ -1067,8 +1067,8 @@ furo = [ {file = "furo-2022.9.29.tar.gz", hash = "sha256:d4238145629c623609c2deb5384f8d036e2a1ee2a101d64b67b4348112470dbd"}, ] gp-libs = [ - {file = "gp-libs-0.0.1a12.tar.gz", hash = "sha256:3a9a3018fa524a0008dd2a88197b2ab503a769bfa780337bf00f5753e1b95552"}, - {file = "gp_libs-0.0.1a12-py3-none-any.whl", hash = "sha256:7115eb6f65de812352fd08da1316a31458d3ceedede3fb9f7f4d2236aae0ca27"}, + {file = "gp-libs-0.0.1a14.tar.gz", hash = "sha256:3a2a4b4eba60b111bff6da85d40103c6c55eee9f1ab33446ef06a974599d01bf"}, + {file = "gp_libs-0.0.1a14-py3-none-any.whl", hash = "sha256:6525e9ac7a467cd7da47ccf4d82da430a3cde7a8936850d1539662b0306123f8"}, ] idna = [ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, @@ -1079,8 +1079,8 @@ imagesize = [ {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, ] importlib-metadata = [ - {file = "importlib_metadata-4.12.0-py3-none-any.whl", hash = "sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23"}, - {file = "importlib_metadata-4.12.0.tar.gz", hash = "sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670"}, + {file = "importlib_metadata-4.13.0-py3-none-any.whl", hash = "sha256:8a8a81bcf996e74fee46f0d16bd3eaa382a7eb20fd82445c3ad11f4090334116"}, + {file = "importlib_metadata-4.13.0.tar.gz", hash = "sha256:dd0173e8f150d6815e098fd354f6414b0f079af4644ddfe90c71e2fc6174346d"}, ] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, From bb744b0a08e27401b0c4e58786f74ca074fa8807 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 1 Oct 2022 13:53:02 -0500 Subject: [PATCH 0130/1073] test(setup.cfg): Mute myst-parser deprecation warning for now --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index 2547e7343..07e521520 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,6 +19,7 @@ line_length = 88 [tool:pytest] filterwarnings = ignore:.* Use packaging.version.*:DeprecationWarning:: + ignore:The frontend.Option(Parser)? class.*:DeprecationWarning:: addopts = --tb=short --no-header --showlocals --doctest-docutils-modules --reruns 2 -p no:doctest doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE testpaths = From 87294c5a4906994f2c5c9fc1cc2ed13905f7fece Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 1 Oct 2022 14:28:44 -0500 Subject: [PATCH 0131/1073] build(deps): Bump gp-libs to 0.0.1a16 (fix warnings) --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 15618c687..38f9dc214 100644 --- a/poetry.lock +++ b/poetry.lock @@ -199,7 +199,7 @@ sphinx-basic-ng = "*" [[package]] name = "gp-libs" -version = "0.0.1a14" +version = "0.0.1a16" description = "Internal utilities for projects following git-pull python package spec" category = "dev" optional = false @@ -930,7 +930,7 @@ test = [] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "92b0a96ae2ee9b02bf74a4d65c483d09e569f56f127a71ce66ce223a5a85ae97" +content-hash = "c208d98cc99abc44680c0fa2a2f3a261f3d03925f26db6cd5a799b99c31561c1" [metadata.files] alabaster = [ @@ -1067,8 +1067,8 @@ furo = [ {file = "furo-2022.9.29.tar.gz", hash = "sha256:d4238145629c623609c2deb5384f8d036e2a1ee2a101d64b67b4348112470dbd"}, ] gp-libs = [ - {file = "gp-libs-0.0.1a14.tar.gz", hash = "sha256:3a2a4b4eba60b111bff6da85d40103c6c55eee9f1ab33446ef06a974599d01bf"}, - {file = "gp_libs-0.0.1a14-py3-none-any.whl", hash = "sha256:6525e9ac7a467cd7da47ccf4d82da430a3cde7a8936850d1539662b0306123f8"}, + {file = "gp-libs-0.0.1a16.tar.gz", hash = "sha256:37e4bb88e09b451bb5bb39dd450b0aa878eb70a8859b7426ea327db7306464b1"}, + {file = "gp_libs-0.0.1a16-py3-none-any.whl", hash = "sha256:07f532df6921b6ac5f512636f7927ffff9ba55011b2e4b301ae8d854cb0c8f91"}, ] idna = [ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, diff --git a/pyproject.toml b/pyproject.toml index 64c88ec94..eb641a564 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,7 +51,7 @@ python = "^3.7" ### Docs ### sphinx = "*" furo = "*" -gp-libs = "~0.0.1a12" +gp-libs = "~0.0.1a16" sphinx-autobuild = "*" sphinx-autodoc-typehints = "*" sphinx-click = "*" From d5f556fde865bc552657a657c57ab045f795841b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 2 Oct 2022 12:44:55 -0500 Subject: [PATCH 0132/1073] build(deps): Bump pytz --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 38f9dc214..8f236b8cc 100644 --- a/poetry.lock +++ b/poetry.lock @@ -569,7 +569,7 @@ watchdog = ">=2.0.0" [[package]] name = "pytz" -version = "2022.2.1" +version = "2022.4" description = "World timezone definitions, modern and historical" category = "dev" optional = false @@ -1246,8 +1246,8 @@ pytest-watcher = [ {file = "pytest_watcher-0.2.3-py3-none-any.whl", hash = "sha256:af935963399509a5b0e855740ba7227852f1a7fccfbb1cbb79fa19a445af02d2"}, ] pytz = [ - {file = "pytz-2022.2.1-py2.py3-none-any.whl", hash = "sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197"}, - {file = "pytz-2022.2.1.tar.gz", hash = "sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5"}, + {file = "pytz-2022.4-py2.py3-none-any.whl", hash = "sha256:2c0784747071402c6e99f0bafdb7da0fa22645f06554c7ae06bf6358897e9c91"}, + {file = "pytz-2022.4.tar.gz", hash = "sha256:48ce799d83b6f8aab2020e369b627446696619e79645419610b9facd909b3174"}, ] PyYAML = [ {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, From f148a86b2b0b733d42dcea55021c9874431c5eb4 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 2 Oct 2022 12:45:26 -0500 Subject: [PATCH 0133/1073] build(deps): Pin importlib_metadata < 5 until our dependencies are figured out --- poetry.lock | 2 +- pyproject.toml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 8f236b8cc..dd79acc7c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -930,7 +930,7 @@ test = [] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "c208d98cc99abc44680c0fa2a2f3a261f3d03925f26db6cd5a799b99c31561c1" +content-hash = "10e095669da8a8cb3b57cfff4af333ab29f4fb12f670912b817d323215057215" [metadata.files] alabaster = [ diff --git a/pyproject.toml b/pyproject.toml index eb641a564..09f7d368c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,6 +83,9 @@ flake8-bugbear = "*" flake8-comprehensions = "*" mypy = "*" +### Quirks ### +importlib-metadata = "<5" # https://github.com/PyCQA/flake8/issues/1701 + [tool.poetry.extras] docs = [ "docutils", From 130dc36849daffad83b15e4c3a8f3c4b65d85d48 Mon Sep 17 00:00:00 2001 From: Chung Tran Date: Sun, 25 Sep 2022 21:22:34 -0400 Subject: [PATCH 0134/1073] Allow empty window name. --- src/libtmux/session.py | 3 +++ tests/test_window.py | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/src/libtmux/session.py b/src/libtmux/session.py index f996286de..b5e7a12ba 100644 --- a/src/libtmux/session.py +++ b/src/libtmux/session.py @@ -253,6 +253,9 @@ def new_window( if window_name: window_args += ("-n%s" % window_name,) + if window_name == '': + window_args += ('-n', '') + window_args += ( # empty string for window_index will use the first one available "-t%s:%s" diff --git a/tests/test_window.py b/tests/test_window.py index 401716ee5..daf674314 100644 --- a/tests/test_window.py +++ b/tests/test_window.py @@ -290,3 +290,11 @@ def test_select_layout_accepts_no_arg(server: Server, session: Session) -> None: window = session.new_window(window_name="test_window") window.select_layout() + + +def test_empty_window_name(session: Session) -> None: + session.set_option("automatic-rename", "off") + window = session.new_window(window_name="''", attach=True) + + assert window == session.attached_window + assert window.get("window_name") == "''" From 50164f54fd678c90fd8c82cf1cc01c0ece8fb6a4 Mon Sep 17 00:00:00 2001 From: Chung Tran Date: Mon, 26 Sep 2022 22:09:43 -0400 Subject: [PATCH 0135/1073] Refactoring. --- src/libtmux/session.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/libtmux/session.py b/src/libtmux/session.py index b5e7a12ba..f74c6e2a3 100644 --- a/src/libtmux/session.py +++ b/src/libtmux/session.py @@ -250,11 +250,8 @@ def new_window( window_args += ( '-F"%s"' % formats.FORMAT_SEPARATOR.join(tmux_formats), ) # output - if window_name: - window_args += ("-n%s" % window_name,) - - if window_name == '': - window_args += ('-n', '') + if window_name is not None and isinstance(window_name, str): + window_args += ("-n", window_name) window_args += ( # empty string for window_index will use the first one available From c825acfcd2315db9fa0eb531671b0dc10ae27c8c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 2 Oct 2022 13:06:28 -0500 Subject: [PATCH 0136/1073] test(empty_window): Assert empty window name passed --- tests/test_window.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/test_window.py b/tests/test_window.py index daf674314..4c10c9c2a 100644 --- a/tests/test_window.py +++ b/tests/test_window.py @@ -5,7 +5,7 @@ import pytest from libtmux import exc -from libtmux.common import has_gte_version +from libtmux.common import has_gte_version, has_lt_version from libtmux.pane import Pane from libtmux.server import Server from libtmux.session import Session @@ -292,9 +292,21 @@ def test_select_layout_accepts_no_arg(server: Server, session: Session) -> None: window.select_layout() +@pytest.mark.skipif( + has_lt_version("3.2"), reason="needs filter introduced in tmux >= 3.2" +) def test_empty_window_name(session: Session) -> None: session.set_option("automatic-rename", "off") window = session.new_window(window_name="''", attach=True) assert window == session.attached_window assert window.get("window_name") == "''" + + cmd = session.cmd( + "list-windows", + "-F", + "#{window_name}", + "-f", + "#{==:#{session_name}," + session.name + "}", + ) + assert "''" in cmd.stdout From 7fdb3f3e45d0c25e0b87f58b727e3d36e8ef86b4 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 2 Oct 2022 13:15:24 -0500 Subject: [PATCH 0137/1073] docs(CHANGES): Note improvement to handling of empty window --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index f69037089..74f0a433b 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,10 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ +### Bug fixes + +- `Session.new_window()`: Improve support for `window_name: ''` downstream in tmuxp (#444, credit: @trankchung) + ## libtmux 0.15.7 (2022-09-23) - Move `.coveragerc` -> `pyproject.toml` (#443) From f3d44d1176be5d66e7cbe49613c8a3f82c3b6497 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 2 Oct 2022 13:24:55 -0500 Subject: [PATCH 0138/1073] Tag v0.15.8 (improvement for window_name: '' in tmuxp, #444) In re: https://github.com/tmux-python/tmuxp/issues/822 --- CHANGES | 4 +++- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 74f0a433b..2ea49d03d 100644 --- a/CHANGES +++ b/CHANGES @@ -12,7 +12,9 @@ $ pip install --user --upgrade --pre libtmux - _Insert changes/features/fixes for next release here_ -### Bug fixes +## libtmux 0.15.8 (2022-10-02) + +### Bug fix - `Session.new_window()`: Improve support for `window_name: ''` downstream in tmuxp (#444, credit: @trankchung) diff --git a/pyproject.toml b/pyproject.toml index 09f7d368c..cf7a53f03 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.7" +version = "0.15.8" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index b2f1dc9ad..5afa80917 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.7" +__version__ = "0.15.8" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From 0b24c31b50aab8adf4aa517f63a3a0f8ddd92527 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 3 Oct 2022 20:58:56 -0500 Subject: [PATCH 0139/1073] build(deps): Fix flake8 / importlib-metadaata pin, bump mypy --- poetry.lock | 97 ++++++++++++++++++++++++++++++++++++-------------- pyproject.toml | 5 ++- 2 files changed, 75 insertions(+), 27 deletions(-) diff --git a/poetry.lock b/poetry.lock index dd79acc7c..fba78f7cd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -156,6 +156,19 @@ mccabe = ">=0.6.0,<0.7.0" pycodestyle = ">=2.7.0,<2.8.0" pyflakes = ">=2.3.0,<2.4.0" +[[package]] +name = "flake8" +version = "5.0.4" +description = "the modular source code checker: pep8 pyflakes and co" +category = "dev" +optional = false +python-versions = ">=3.6.1" + +[package.dependencies] +mccabe = ">=0.7.0,<0.8.0" +pycodestyle = ">=2.9.0,<2.10.0" +pyflakes = ">=2.5.0,<2.6.0" + [[package]] name = "flake8-bugbear" version = "22.9.23" @@ -328,6 +341,14 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +category = "dev" +optional = false +python-versions = ">=3.6" + [[package]] name = "mdit-py-plugins" version = "0.3.1" @@ -354,7 +375,7 @@ python-versions = ">=3.7" [[package]] name = "mypy" -version = "0.981" +version = "0.982" description = "Optional static typing for Python" category = "dev" optional = false @@ -464,6 +485,14 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +[[package]] +name = "pycodestyle" +version = "2.9.1" +description = "Python style guide checker" +category = "dev" +optional = false +python-versions = ">=3.6" + [[package]] name = "pyflakes" version = "2.3.1" @@ -472,6 +501,14 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +[[package]] +name = "pyflakes" +version = "2.5.0" +description = "passive checker of Python programs" +category = "dev" +optional = false +python-versions = ">=3.6" + [[package]] name = "Pygments" version = "2.13.0" @@ -930,7 +967,7 @@ test = [] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "10e095669da8a8cb3b57cfff4af333ab29f4fb12f670912b817d323215057215" +content-hash = "f1282974a06e37d4b7ce7de0b71b94890c23870cb9f32a0fae12dcff122c8103" [metadata.files] alabaster = [ @@ -1053,6 +1090,8 @@ docutils = [ flake8 = [ {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, + {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"}, + {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"}, ] flake8-bugbear = [ {file = "flake8-bugbear-22.9.23.tar.gz", hash = "sha256:17b9623325e6e0dcdcc80ed9e4aa811287fcc81d7e03313b8736ea5733759937"}, @@ -1146,6 +1185,8 @@ MarkupSafe = [ mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] mdit-py-plugins = [ {file = "mdit-py-plugins-0.3.1.tar.gz", hash = "sha256:3fc13298497d6e04fe96efdd41281bfe7622152f9caa1815ea99b5c893de9441"}, @@ -1156,30 +1197,30 @@ mdurl = [ {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] mypy = [ - {file = "mypy-0.981-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4bc460e43b7785f78862dab78674e62ec3cd523485baecfdf81a555ed29ecfa0"}, - {file = "mypy-0.981-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:756fad8b263b3ba39e4e204ee53042671b660c36c9017412b43af210ddee7b08"}, - {file = "mypy-0.981-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a16a0145d6d7d00fbede2da3a3096dcc9ecea091adfa8da48fa6a7b75d35562d"}, - {file = "mypy-0.981-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce65f70b14a21fdac84c294cde75e6dbdabbcff22975335e20827b3b94bdbf49"}, - {file = "mypy-0.981-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e35d764784b42c3e256848fb8ed1d4292c9fc0098413adb28d84974c095b279"}, - {file = "mypy-0.981-cp310-cp310-win_amd64.whl", hash = "sha256:e53773073c864d5f5cec7f3fc72fbbcef65410cde8cc18d4f7242dea60dac52e"}, - {file = "mypy-0.981-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6ee196b1d10b8b215e835f438e06965d7a480f6fe016eddbc285f13955cca659"}, - {file = "mypy-0.981-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ad21d4c9d3673726cf986ea1d0c9fb66905258709550ddf7944c8f885f208be"}, - {file = "mypy-0.981-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d1debb09043e1f5ee845fa1e96d180e89115b30e47c5d3ce53bc967bab53f62d"}, - {file = "mypy-0.981-cp37-cp37m-win_amd64.whl", hash = "sha256:9f362470a3480165c4c6151786b5379351b790d56952005be18bdbdd4c7ce0ae"}, - {file = "mypy-0.981-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c9e0efb95ed6ca1654951bd5ec2f3fa91b295d78bf6527e026529d4aaa1e0c30"}, - {file = "mypy-0.981-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e178eaffc3c5cd211a87965c8c0df6da91ed7d258b5fc72b8e047c3771317ddb"}, - {file = "mypy-0.981-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:06e1eac8d99bd404ed8dd34ca29673c4346e76dd8e612ea507763dccd7e13c7a"}, - {file = "mypy-0.981-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa38f82f53e1e7beb45557ff167c177802ba7b387ad017eab1663d567017c8ee"}, - {file = "mypy-0.981-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:64e1f6af81c003f85f0dfed52db632817dabb51b65c0318ffbf5ff51995bbb08"}, - {file = "mypy-0.981-cp38-cp38-win_amd64.whl", hash = "sha256:e1acf62a8c4f7c092462c738aa2c2489e275ed386320c10b2e9bff31f6f7e8d6"}, - {file = "mypy-0.981-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b6ede64e52257931315826fdbfc6ea878d89a965580d1a65638ef77cb551f56d"}, - {file = "mypy-0.981-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eb3978b191b9fa0488524bb4ffedf2c573340e8c2b4206fc191d44c7093abfb7"}, - {file = "mypy-0.981-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f8fcf7b4b3cc0c74fb33ae54a4cd00bb854d65645c48beccf65fa10b17882c"}, - {file = "mypy-0.981-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f64d2ce043a209a297df322eb4054dfbaa9de9e8738291706eaafda81ab2b362"}, - {file = "mypy-0.981-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2ee3dbc53d4df7e6e3b1c68ac6a971d3a4fb2852bf10a05fda228721dd44fae1"}, - {file = "mypy-0.981-cp39-cp39-win_amd64.whl", hash = "sha256:8e8e49aa9cc23aa4c926dc200ce32959d3501c4905147a66ce032f05cb5ecb92"}, - {file = "mypy-0.981-py3-none-any.whl", hash = "sha256:794f385653e2b749387a42afb1e14c2135e18daeb027e0d97162e4b7031210f8"}, - {file = "mypy-0.981.tar.gz", hash = "sha256:ad77c13037d3402fbeffda07d51e3f228ba078d1c7096a73759c9419ea031bf4"}, + {file = "mypy-0.982-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5085e6f442003fa915aeb0a46d4da58128da69325d8213b4b35cc7054090aed5"}, + {file = "mypy-0.982-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:41fd1cf9bc0e1c19b9af13a6580ccb66c381a5ee2cf63ee5ebab747a4badeba3"}, + {file = "mypy-0.982-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f793e3dd95e166b66d50e7b63e69e58e88643d80a3dcc3bcd81368e0478b089c"}, + {file = "mypy-0.982-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86ebe67adf4d021b28c3f547da6aa2cce660b57f0432617af2cca932d4d378a6"}, + {file = "mypy-0.982-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:175f292f649a3af7082fe36620369ffc4661a71005aa9f8297ea473df5772046"}, + {file = "mypy-0.982-cp310-cp310-win_amd64.whl", hash = "sha256:8ee8c2472e96beb1045e9081de8e92f295b89ac10c4109afdf3a23ad6e644f3e"}, + {file = "mypy-0.982-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58f27ebafe726a8e5ccb58d896451dd9a662a511a3188ff6a8a6a919142ecc20"}, + {file = "mypy-0.982-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6af646bd46f10d53834a8e8983e130e47d8ab2d4b7a97363e35b24e1d588947"}, + {file = "mypy-0.982-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7aeaa763c7ab86d5b66ff27f68493d672e44c8099af636d433a7f3fa5596d40"}, + {file = "mypy-0.982-cp37-cp37m-win_amd64.whl", hash = "sha256:724d36be56444f569c20a629d1d4ee0cb0ad666078d59bb84f8f887952511ca1"}, + {file = "mypy-0.982-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14d53cdd4cf93765aa747a7399f0961a365bcddf7855d9cef6306fa41de01c24"}, + {file = "mypy-0.982-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:26ae64555d480ad4b32a267d10cab7aec92ff44de35a7cd95b2b7cb8e64ebe3e"}, + {file = "mypy-0.982-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6389af3e204975d6658de4fb8ac16f58c14e1bacc6142fee86d1b5b26aa52bda"}, + {file = "mypy-0.982-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b35ce03a289480d6544aac85fa3674f493f323d80ea7226410ed065cd46f206"}, + {file = "mypy-0.982-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c6e564f035d25c99fd2b863e13049744d96bd1947e3d3d2f16f5828864506763"}, + {file = "mypy-0.982-cp38-cp38-win_amd64.whl", hash = "sha256:cebca7fd333f90b61b3ef7f217ff75ce2e287482206ef4a8b18f32b49927b1a2"}, + {file = "mypy-0.982-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a705a93670c8b74769496280d2fe6cd59961506c64f329bb179970ff1d24f9f8"}, + {file = "mypy-0.982-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75838c649290d83a2b83a88288c1eb60fe7a05b36d46cbea9d22efc790002146"}, + {file = "mypy-0.982-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:91781eff1f3f2607519c8b0e8518aad8498af1419e8442d5d0afb108059881fc"}, + {file = "mypy-0.982-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaa97b9ddd1dd9901a22a879491dbb951b5dec75c3b90032e2baa7336777363b"}, + {file = "mypy-0.982-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a692a8e7d07abe5f4b2dd32d731812a0175626a90a223d4b58f10f458747dd8a"}, + {file = "mypy-0.982-cp39-cp39-win_amd64.whl", hash = "sha256:eb7a068e503be3543c4bd329c994103874fa543c1727ba5288393c21d912d795"}, + {file = "mypy-0.982-py3-none-any.whl", hash = "sha256:1021c241e8b6e1ca5a47e4d52601274ac078a89845cfde66c6d5f769819ffa1d"}, + {file = "mypy-0.982.tar.gz", hash = "sha256:85f7a343542dc8b1ed0a888cdd34dca56462654ef23aa673907305b260b3d746"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, @@ -1212,10 +1253,14 @@ py = [ pycodestyle = [ {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, + {file = "pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b"}, + {file = "pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785"}, ] pyflakes = [ {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, + {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"}, + {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"}, ] Pygments = [ {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, diff --git a/pyproject.toml b/pyproject.toml index cf7a53f03..c1702383b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -78,7 +78,10 @@ black = "*" isort = "*" ### Lint ### -flake8 = "*" +flake8 = [ + { version = "*", python = "^3.7" }, + { version = ">=5", python = "^3.8" }, +] flake8-bugbear = "*" flake8-comprehensions = "*" mypy = "*" From b33b66dea23f2ba08569c2d3597c3f2b1662b5a5 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 6 Oct 2022 19:09:35 -0500 Subject: [PATCH 0140/1073] docs: Add MIGRATION --- MIGRATION | 28 ++++++++++++++++++++++++++++ docs/index.md | 1 + docs/migration.md | 9 +++++++++ 3 files changed, 38 insertions(+) create mode 100644 MIGRATION create mode 100644 docs/migration.md diff --git a/MIGRATION b/MIGRATION new file mode 100644 index 000000000..c0be5bdc4 --- /dev/null +++ b/MIGRATION @@ -0,0 +1,28 @@ +# Migration notes + +Migration and deprecation notes for libtmux are here, see {ref}`changelog` as +well. + +```{admonition} Welcome on board! 👋 +1. 📌 For safety, **always** pin the package +2. 📖 Check the migration notes _(You are here)_ +3. 📣 If you feel something got deprecated and it interrupted you - past, present, or future - voice your opinion on the [tracker]. + + We want to make libtmux fun, reliable, and useful for users. + + API changes can be painful. + + If we can do something to draw the sting, we'll do it. We're taking a balanced approach. That's why these notes are here! + + (Please pin the package. 🙏) + + [tracker]: https://github.com/tmux-python/libtmux/discussions +``` + +## Next release + +_Add migration notes here_ + + diff --git a/docs/index.md b/docs/index.md index 2a2d82ebe..a43882111 100644 --- a/docs/index.md +++ b/docs/index.md @@ -29,6 +29,7 @@ pytest-plugin/index developing internals/index history +migration glossary GitHub ``` diff --git a/docs/migration.md b/docs/migration.md new file mode 100644 index 000000000..7bd3f4664 --- /dev/null +++ b/docs/migration.md @@ -0,0 +1,9 @@ +(migration)= + +```{currentmodule} libtmux + +``` + +```{include} ../MIGRATION + +``` From 7d8839b1aeee41369ffe473a0b12127282a591c9 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Thu, 6 Oct 2022 19:17:01 -0500 Subject: [PATCH 0141/1073] docs(conf): Update link to migration --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 383fe7ce1..eb2e11caa 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -85,7 +85,7 @@ "source_repository": f"{about['__github__']}/", "source_branch": "master", "source_directory": "docs/", - "announcement": "Friendly reminder: 📌 Pin the package, libtmux is pre-1.0 and APIs will be changing throughout 2022-2023.", + "announcement": "Friendly reminder: 📌 Pin the package, libtmux is pre-1.0 and APIs will be changing throughout 2022-2023.", } html_sidebars = { "**": [ From a1c8fdbbdea52af4a36190d1634be2cad63e93e0 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 7 Oct 2022 22:01:56 -0500 Subject: [PATCH 0142/1073] build(deps): Bump typing-extensions, black, pytest-mock --- poetry.lock | 60 ++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/poetry.lock b/poetry.lock index fba78f7cd..067235047 100644 --- a/poetry.lock +++ b/poetry.lock @@ -48,11 +48,11 @@ lxml = ["lxml"] [[package]] name = "black" -version = "22.8.0" +version = "22.10.0" description = "The uncompromising code formatter." category = "dev" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.7" [package.dependencies] click = ">=8.0.0" @@ -569,7 +569,7 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale [[package]] name = "pytest-mock" -version = "3.9.0" +version = "3.10.0" description = "Thin-wrapper around the mock package for easier use with pytest" category = "dev" optional = false @@ -915,7 +915,7 @@ python-versions = ">=3.6" [[package]] name = "typing-extensions" -version = "4.3.0" +version = "4.4.0" description = "Backported and Experimental Type Hints for Python 3.7+" category = "dev" optional = false @@ -987,29 +987,27 @@ beautifulsoup4 = [ {file = "beautifulsoup4-4.11.1.tar.gz", hash = "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"}, ] black = [ - {file = "black-22.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ce957f1d6b78a8a231b18e0dd2d94a33d2ba738cd88a7fe64f53f659eea49fdd"}, - {file = "black-22.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5107ea36b2b61917956d018bd25129baf9ad1125e39324a9b18248d362156a27"}, - {file = "black-22.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8166b7bfe5dcb56d325385bd1d1e0f635f24aae14b3ae437102dedc0c186747"}, - {file = "black-22.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd82842bb272297503cbec1a2600b6bfb338dae017186f8f215c8958f8acf869"}, - {file = "black-22.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d839150f61d09e7217f52917259831fe2b689f5c8e5e32611736351b89bb2a90"}, - {file = "black-22.8.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a05da0430bd5ced89176db098567973be52ce175a55677436a271102d7eaa3fe"}, - {file = "black-22.8.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a098a69a02596e1f2a58a2a1c8d5a05d5a74461af552b371e82f9fa4ada8342"}, - {file = "black-22.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5594efbdc35426e35a7defa1ea1a1cb97c7dbd34c0e49af7fb593a36bd45edab"}, - {file = "black-22.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a983526af1bea1e4cf6768e649990f28ee4f4137266921c2c3cee8116ae42ec3"}, - {file = "black-22.8.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b2c25f8dea5e8444bdc6788a2f543e1fb01494e144480bc17f806178378005e"}, - {file = "black-22.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:78dd85caaab7c3153054756b9fe8c611efa63d9e7aecfa33e533060cb14b6d16"}, - {file = "black-22.8.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:cea1b2542d4e2c02c332e83150e41e3ca80dc0fb8de20df3c5e98e242156222c"}, - {file = "black-22.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5b879eb439094751185d1cfdca43023bc6786bd3c60372462b6f051efa6281a5"}, - {file = "black-22.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0a12e4e1353819af41df998b02c6742643cfef58282915f781d0e4dd7a200411"}, - {file = "black-22.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3a73f66b6d5ba7288cd5d6dad9b4c9b43f4e8a4b789a94bf5abfb878c663eb3"}, - {file = "black-22.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:e981e20ec152dfb3e77418fb616077937378b322d7b26aa1ff87717fb18b4875"}, - {file = "black-22.8.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8ce13ffed7e66dda0da3e0b2eb1bdfc83f5812f66e09aca2b0978593ed636b6c"}, - {file = "black-22.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:32a4b17f644fc288c6ee2bafdf5e3b045f4eff84693ac069d87b1a347d861497"}, - {file = "black-22.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ad827325a3a634bae88ae7747db1a395d5ee02cf05d9aa7a9bd77dfb10e940c"}, - {file = "black-22.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53198e28a1fb865e9fe97f88220da2e44df6da82b18833b588b1883b16bb5d41"}, - {file = "black-22.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:bc4d4123830a2d190e9cc42a2e43570f82ace35c3aeb26a512a2102bce5af7ec"}, - {file = "black-22.8.0-py3-none-any.whl", hash = "sha256:d2c21d439b2baf7aa80d6dd4e3659259be64c6f49dfd0f32091063db0e006db4"}, - {file = "black-22.8.0.tar.gz", hash = "sha256:792f7eb540ba9a17e8656538701d3eb1afcb134e3b45b71f20b25c77a8db7e6e"}, + {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, + {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, + {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, + {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, + {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, + {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, + {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, + {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, + {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, + {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, + {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, + {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, + {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"}, + {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"}, + {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"}, + {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"}, + {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"}, + {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"}, + {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"}, + {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"}, + {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, ] certifi = [ {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"}, @@ -1279,8 +1277,8 @@ pytest-cov = [ {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"}, ] pytest-mock = [ - {file = "pytest-mock-3.9.0.tar.gz", hash = "sha256:c899a0dcc8a5f22930acd020b500abd5f956911f326864a3b979e4866e14da82"}, - {file = "pytest_mock-3.9.0-py3-none-any.whl", hash = "sha256:1a1b9264224d026932d6685a0f9cef3b61d91563c3e74af9fe5afb2767e13812"}, + {file = "pytest-mock-3.10.0.tar.gz", hash = "sha256:fbbdb085ef7c252a326fd8cdcac0aa3b1333d8811f131bdcc701002e1be7ed4f"}, + {file = "pytest_mock-3.10.0-py3-none-any.whl", hash = "sha256:f4c973eeae0282963eb293eb173ce91b091a79c1334455acfac9ddee8a1c784b"}, ] pytest-rerunfailures = [ {file = "pytest-rerunfailures-10.2.tar.gz", hash = "sha256:9e1e1bad51e07642c5bbab809fc1d4ec8eebcb7de86f90f1a26e6ef9de446697"}, @@ -1453,8 +1451,8 @@ typed-ast = [ {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, ] typing-extensions = [ - {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, - {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, + {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, + {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, ] urllib3 = [ {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, From 68d3768de61b426c65e504db6ef03d3f3ec31886 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 8 Oct 2022 10:13:55 -0500 Subject: [PATCH 0143/1073] docs(history): Fix missing changelog ref --- docs/history.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/history.md b/docs/history.md index ae0d96a9b..9a3a29110 100644 --- a/docs/history.md +++ b/docs/history.md @@ -1,3 +1,5 @@ +(changes)= +(changelog)= (history)= ```{currentmodule} libtmux From 780cf52df29ff0c7c1bb8945adced78f723d2f60 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 9 Oct 2022 23:50:01 -0500 Subject: [PATCH 0144/1073] docs(CHANGES,MIGRATION): Note the latest --- CHANGES | 4 +++- MIGRATION | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 2ea49d03d..fc1fb7198 100644 --- a/CHANGES +++ b/CHANGES @@ -10,7 +10,9 @@ $ pip install --user --upgrade --pre libtmux ## libtmux 0.16.x (unreleased) -- _Insert changes/features/fixes for next release here_ +- _Notes on upcoming releases will be added here_ + + ## libtmux 0.15.8 (2022-10-02) diff --git a/MIGRATION b/MIGRATION index c0be5bdc4..9d0d28b5f 100644 --- a/MIGRATION +++ b/MIGRATION @@ -21,7 +21,9 @@ well. ## Next release -_Add migration notes here_ +_Migration instructions for the upcoming release will be added here_ + + +### Bug fix + +- `tmux_cmd()`: Fix raise of TmuxCommandNotFound (#450) + ## libtmux 0.15.8 (2022-10-02) ### Bug fix From d42de6c5e3b9560a03df50dde671064d7aa412d0 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 30 Oct 2022 12:34:52 -0500 Subject: [PATCH 0157/1073] ci: Add python 3.11 to package classifiers, version pins --- .github/workflows/docs.yml | 2 +- .github/workflows/tests.yml | 4 ++-- .python-version | 2 +- .tool-versions | 2 +- pyproject.toml | 1 + 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 726b5d600..2baa81b93 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.10"] + python-version: ["3.11"] steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 20f65b186..42ad9c404 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.7", "3.10"] + python-version: ["3.7", "3.11"] tmux-version: ["2.6", "2.7", "2.8", "3.0a", "3.1b", "3.2a", "3.3a", "master"] steps: - uses: actions/checkout@v3 @@ -84,7 +84,7 @@ jobs: strategy: matrix: - python-version: ["3.10"] + python-version: ["3.11"] steps: - uses: actions/checkout@v3 diff --git a/.python-version b/.python-version index 946e73f19..b6ec5ca97 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.10.7 3.9.13 3.8.13 3.7.13 +3.11.0 3.10.7 3.9.13 3.8.13 3.7.13 diff --git a/.tool-versions b/.tool-versions index 4c9b42d1c..a0c5b80d4 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ poetry 1.2.1 -python 3.10.7 3.9.13 3.8.13 3.7.13 +python 3.11.0 3.10.7 3.9.13 3.8.13 3.7.13 diff --git a/pyproject.toml b/pyproject.toml index 1e7d1281d..9538ddd90 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ classifiers = [ "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Utilities", From a3c88f8ddeedb2f17ba01328e0ffe8caf0cb8051 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 30 Oct 2022 12:36:37 -0500 Subject: [PATCH 0158/1073] docs(CHANGES): Note python 3.11 updates --- CHANGES | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGES b/CHANGES index 3916bf5dc..794dc9635 100644 --- a/CHANGES +++ b/CHANGES @@ -18,6 +18,18 @@ $ pip install --user --upgrade --pre libtmux - `tmux_cmd()`: Fix raise of TmuxCommandNotFound (#450) +### CI + +- Use python 3.11 (#451) + +### Packaging + +- Add python 3.11 to trove classifiers (#451) + +### Development + +- Add python 3.11 to asdf and pyenv configurations (#451) + ## libtmux 0.15.8 (2022-10-02) ### Bug fix From 07fa5a6061dc1c5626d4276ab175e4b13948fb38 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 30 Oct 2022 15:10:37 -0500 Subject: [PATCH 0159/1073] Tag v0.15.9 --- CHANGES | 2 ++ pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 794dc9635..5392ccb0e 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,8 @@ $ pip install --user --upgrade --pre libtmux +## libtmux 0.15.9 (2022-10-30) + ### Bug fix - `tmux_cmd()`: Fix raise of TmuxCommandNotFound (#450) diff --git a/pyproject.toml b/pyproject.toml index 9538ddd90..9b843f7a8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.8" +version = "0.15.9" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index 5afa80917..fde9ce0d6 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.8" +__version__ = "0.15.9" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From 3c7132219b052976dcce594f0d38ad178ca36fb5 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 5 Nov 2022 06:57:26 -0500 Subject: [PATCH 0160/1073] build(deps): Bump setuptools, sphinxext-opengraph,autodoc-typehints, babel --- poetry.lock | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1266990db..b11ba78be 100644 --- a/poetry.lock +++ b/poetry.lock @@ -22,7 +22,7 @@ tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy [[package]] name = "Babel" -version = "2.10.3" +version = "2.11.0" description = "Internationalization utilities" category = "dev" optional = false @@ -144,7 +144,7 @@ python-versions = ">=3.7" [[package]] name = "exceptiongroup" -version = "1.0.0" +version = "1.0.1" description = "Backport of PEP 654 (exception groups)" category = "dev" optional = false @@ -609,7 +609,7 @@ watchdog = ">=2.0.0" [[package]] name = "pytz" -version = "2022.5" +version = "2022.6" description = "World timezone definitions, modern and historical" category = "dev" optional = false @@ -643,7 +643,7 @@ use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "setuptools" -version = "65.5.0" +version = "65.5.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" category = "dev" optional = false @@ -651,7 +651,7 @@ python-versions = ">=3.7" [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mock", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] @@ -728,18 +728,18 @@ test = ["pytest", "pytest-cov"] [[package]] name = "sphinx-autodoc-typehints" -version = "1.19.4" +version = "1.19.5" description = "Type hints (PEP 484) support for the Sphinx autodoc extension" category = "dev" optional = false python-versions = ">=3.7" [package.dependencies] -sphinx = ">=5.2.1" +sphinx = ">=5.3" [package.extras] -docs = ["furo (>=2022.9.15)", "sphinx (>=5.2.1)", "sphinx-autodoc-typehints (>=1.19.3)"] -testing = ["covdefaults (>=2.2)", "coverage (>=6.4.4)", "diff-cover (>=7.0.1)", "nptyping (>=2.3.1)", "pytest (>=7.1.3)", "pytest-cov (>=3)", "sphobjinv (>=2.2.2)", "typing-extensions (>=4.3)"] +docs = ["furo (>=2022.9.29)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"] +testing = ["covdefaults (>=2.2)", "coverage (>=6.5)", "diff-cover (>=7.0.1)", "nptyping (>=2.3.1)", "pytest (>=7.2)", "pytest-cov (>=4)", "sphobjinv (>=2.2.2)", "typing-extensions (>=4.4)"] type-comment = ["typed-ast (>=1.5.4)"] [[package]] @@ -872,14 +872,14 @@ test = ["pytest"] [[package]] name = "sphinxext-opengraph" -version = "0.6.3" +version = "0.7.2" description = "Sphinx Extension to enable OGP support" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] -sphinx = ">=2.0" +sphinx = ">=4.0" [[package]] name = "sphinxext-rediraffe" @@ -982,8 +982,8 @@ attrs = [ {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, ] Babel = [ - {file = "Babel-2.10.3-py3-none-any.whl", hash = "sha256:ff56f4892c1c4bf0d814575ea23471c230d544203c7748e8c68f0089478d48eb"}, - {file = "Babel-2.10.3.tar.gz", hash = "sha256:7614553711ee97490f732126dc077f8d0ae084ebc6a96e23db1482afabdb2c51"}, + {file = "Babel-2.11.0-py3-none-any.whl", hash = "sha256:1ad3eca1c885218f6dce2ab67291178944f810a10a9b5f3cb8382a5a232b64fe"}, + {file = "Babel-2.11.0.tar.gz", hash = "sha256:5ef4b3226b0180dedded4229651c8b0e1a3a6a2837d45a073272f313e4cf97f6"}, ] beautifulsoup4 = [ {file = "beautifulsoup4-4.11.1-py3-none-any.whl", hash = "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30"}, @@ -1089,8 +1089,8 @@ docutils = [ {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"}, ] exceptiongroup = [ - {file = "exceptiongroup-1.0.0-py3-none-any.whl", hash = "sha256:2ac84b496be68464a2da60da518af3785fff8b7ec0d090a581604bc870bdee41"}, - {file = "exceptiongroup-1.0.0.tar.gz", hash = "sha256:affbabf13fb6e98988c38d9c5650e701569fe3c1de3233cfb61c5f33774690ad"}, + {file = "exceptiongroup-1.0.1-py3-none-any.whl", hash = "sha256:4d6c0aa6dd825810941c792f53d7b8d71da26f5e5f84f20f9508e8f2d33b140a"}, + {file = "exceptiongroup-1.0.1.tar.gz", hash = "sha256:73866f7f842ede6cb1daa42c4af078e2035e5f7607f0e2c762cc51bb31bbe7b2"}, ] flake8 = [ {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, @@ -1292,8 +1292,8 @@ pytest-watcher = [ {file = "pytest_watcher-0.2.5-py3-none-any.whl", hash = "sha256:7a15b3c7c6babefdee51da2d62851f109e2d2d65c64f72da04f97f0a9569ab74"}, ] pytz = [ - {file = "pytz-2022.5-py2.py3-none-any.whl", hash = "sha256:335ab46900b1465e714b4fda4963d87363264eb662aab5e65da039c25f1f5b22"}, - {file = "pytz-2022.5.tar.gz", hash = "sha256:c4d88f472f54d615e9cd582a5004d1e5f624854a6a27a6211591c251f22a6914"}, + {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"}, + {file = "pytz-2022.6.tar.gz", hash = "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2"}, ] PyYAML = [ {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, @@ -1335,8 +1335,8 @@ requests = [ {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, ] setuptools = [ - {file = "setuptools-65.5.0-py3-none-any.whl", hash = "sha256:f62ea9da9ed6289bfe868cd6845968a2c854d1427f8548d52cae02a42b4f0356"}, - {file = "setuptools-65.5.0.tar.gz", hash = "sha256:512e5536220e38146176efb833d4a62aa726b7bbff82cfbc8ba9eaa3996e0b17"}, + {file = "setuptools-65.5.1-py3-none-any.whl", hash = "sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31"}, + {file = "setuptools-65.5.1.tar.gz", hash = "sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, @@ -1359,8 +1359,8 @@ sphinx-autobuild = [ {file = "sphinx_autobuild-2021.3.14-py3-none-any.whl", hash = "sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac"}, ] sphinx-autodoc-typehints = [ - {file = "sphinx_autodoc_typehints-1.19.4-py3-none-any.whl", hash = "sha256:e190d8ee8204c3de05a64f41cf10e592e987e4063c8ec0de7e4b11f6e036b2e2"}, - {file = "sphinx_autodoc_typehints-1.19.4.tar.gz", hash = "sha256:ffd8e710f6757471b5c831c7ece88f52a9ff15f27836f4ef1c8695a64f8dcca8"}, + {file = "sphinx_autodoc_typehints-1.19.5-py3-none-any.whl", hash = "sha256:ea55b3cc3f485e3a53668bcdd08de78121ab759f9724392fdb5bf3483d786328"}, + {file = "sphinx_autodoc_typehints-1.19.5.tar.gz", hash = "sha256:38a227378e2bc15c84e29af8cb1d7581182da1107111fd1c88b19b5eb7076205"}, ] sphinx-basic-ng = [ {file = "sphinx_basic_ng-1.0.0b1-py3-none-any.whl", hash = "sha256:ade597a3029c7865b24ad0eda88318766bcc2f9f4cef60df7e28126fde94db2a"}, @@ -1403,8 +1403,8 @@ sphinxcontrib-serializinghtml = [ {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, ] sphinxext-opengraph = [ - {file = "sphinxext-opengraph-0.6.3.tar.gz", hash = "sha256:cd89e13cc7a44739f81b64ee57c1c20ef0c05dda5d1d8201d31ec2f34e4c29db"}, - {file = "sphinxext_opengraph-0.6.3-py3-none-any.whl", hash = "sha256:bf76017c105856b07edea6caf4942b6ae9bb168585dccfd6dbdb6e4161f6b03a"}, + {file = "sphinxext-opengraph-0.7.2.tar.gz", hash = "sha256:85230ee14d50c97d9db457d4dc4c9f9ea08bc78e7dd6850d615e05705e5c2977"}, + {file = "sphinxext_opengraph-0.7.2-py3-none-any.whl", hash = "sha256:7a33e13a1e1d6afa66744c24d1f5aabdde77ba70018403f9137a2d8dbe958c24"}, ] sphinxext-rediraffe = [ {file = "sphinxext-rediraffe-0.2.7.tar.gz", hash = "sha256:651dcbfae5ffda9ffd534dfb8025f36120e5efb6ea1a33f5420023862b9f725d"}, From 57830266e40679895c0998565a241c3ad8aeab9e Mon Sep 17 00:00:00 2001 From: Bjoern Hiller Date: Tue, 1 Nov 2022 17:03:15 +0100 Subject: [PATCH 0161/1073] fix(test_capture_pane): use of double `env` This makes the test fail (at least for me) as it still won't start bash but my login-shell (which is not bash). --- tests/test_pane.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test_pane.py b/tests/test_pane.py index ef33cca48..58def41f5 100644 --- a/tests/test_pane.py +++ b/tests/test_pane.py @@ -1,5 +1,6 @@ """Tests for libtmux Pane object.""" import logging +import shutil from libtmux.session import Session @@ -66,10 +67,13 @@ def test_set_width(session: Session) -> None: def test_capture_pane(session: Session) -> None: + env = shutil.which("env") + assert env is not None, "Cannot find usable `env` in PATH." + session.new_window( attach=True, window_name="capture_pane", - window_shell='env -i PS1="$ " /usr/bin/env bash --norc --noprofile', + window_shell=f"{env} PS1='$ ' bash --norc --noprofile", ) pane = session.attached_window.attached_pane assert pane is not None From b74e428d594cd83e010024926879f64d7101948e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 5 Nov 2022 08:51:31 -0500 Subject: [PATCH 0162/1073] docs(CHANGES): Note test_capture_pane improvement --- CHANGES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index 5392ccb0e..9aa68ecb6 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,11 @@ $ pip install --user --upgrade --pre libtmux +### Tests + +- Compatibility improvement for `test_capture_pane` and `env` (#452), credit: + @zappolowski! + ## libtmux 0.15.9 (2022-10-30) ### Bug fix From abc4f5be7648f3a55d92676b649c92a084bc1b0a Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 5 Nov 2022 09:42:20 -0500 Subject: [PATCH 0163/1073] ci(poetry): Remove in-project: true flag poetry env list poetry env remove --- poetry.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/poetry.toml b/poetry.toml index 5fcef8cd4..d11b90b04 100644 --- a/poetry.toml +++ b/poetry.toml @@ -1,3 +1,2 @@ [virtualenvs] -in-project = true prefer-active-python = true From 5869e01d47e1e624fb954c0f7ba59d8341598fb3 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 5 Nov 2022 09:44:35 -0500 Subject: [PATCH 0164/1073] ci(poetry): Bump poetry 1.2.1 -> 1.2.2 See also: https://github.com/python-poetry/poetry/releases/tag/1.2.2 --- .github/workflows/docs.yml | 2 +- .github/workflows/tests.yml | 4 ++-- .tool-versions | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 2baa81b93..3b88c2a6f 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -36,7 +36,7 @@ jobs: - name: Install poetry if: env.PUBLISH == 'true' - run: pipx install "poetry==1.2.1" + run: pipx install "poetry==1.2.2" - name: Set up Python ${{ matrix.python-version }} if: env.PUBLISH == 'true' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 42ad9c404..75aef723d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v3 - name: Install poetry - run: pipx install "poetry==1.2.1" + run: pipx install "poetry==1.2.2" - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 @@ -90,7 +90,7 @@ jobs: - uses: actions/checkout@v3 - name: Install poetry - run: pipx install "poetry==1.2.1" + run: pipx install "poetry==1.2.2" - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 diff --git a/.tool-versions b/.tool-versions index a0c5b80d4..1adbdc0d9 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -poetry 1.2.1 +poetry 1.2.2 python 3.11.0 3.10.7 3.9.13 3.8.13 3.7.13 From c548e5e4bbaeb872bbf1ff3a2508a4b9ba2f775e Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 5 Nov 2022 11:12:09 -0500 Subject: [PATCH 0165/1073] test(test_capture_pane): Remove bashism --- tests/test_pane.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_pane.py b/tests/test_pane.py index 58def41f5..c9c658f6e 100644 --- a/tests/test_pane.py +++ b/tests/test_pane.py @@ -73,7 +73,7 @@ def test_capture_pane(session: Session) -> None: session.new_window( attach=True, window_name="capture_pane", - window_shell=f"{env} PS1='$ ' bash --norc --noprofile", + window_shell=f"{env} PS1='$ ' sh", ) pane = session.attached_window.attached_pane assert pane is not None From b778e039888f3a917197e33a18995a27cd4c0f37 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 5 Nov 2022 11:13:29 -0500 Subject: [PATCH 0166/1073] docs(common): bash -> console --- src/libtmux/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libtmux/common.py b/src/libtmux/common.py index 5376f8ef3..430053963 100644 --- a/src/libtmux/common.py +++ b/src/libtmux/common.py @@ -219,7 +219,7 @@ class tmux_cmd: Equivalent to: - .. code-block:: bash + .. code-block:: console $ tmux new-session -s my session From bdd71228ea008ee3ccb4b1d94b74dc3595f57fa7 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 5 Nov 2022 13:28:49 -0500 Subject: [PATCH 0167/1073] docs(CHANGES): Note removal of bashism --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index 9aa68ecb6..536d0b194 100644 --- a/CHANGES +++ b/CHANGES @@ -16,8 +16,12 @@ $ pip install --user --upgrade --pre libtmux ### Tests +_There will be more tests over the coming weeks and months to shore up +flakiness across shells and environments._ + - Compatibility improvement for `test_capture_pane` and `env` (#452), credit: @zappolowski! +- Remove more BASHisms from tests (#455) ## libtmux 0.15.9 (2022-10-30) From c425c376759459c99edc7df9894fd123ad71415f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 5 Nov 2022 13:41:44 -0500 Subject: [PATCH 0168/1073] Tag v0.15.10 (test environment improvements) --- CHANGES | 6 +++-- poetry.lock | 49 +++++++++++++++++++++++----------------- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 4 files changed, 34 insertions(+), 25 deletions(-) diff --git a/CHANGES b/CHANGES index 536d0b194..86d5af26f 100644 --- a/CHANGES +++ b/CHANGES @@ -14,11 +14,13 @@ $ pip install --user --upgrade --pre libtmux -### Tests +## libtmux 0.15.10 (2022-11-05) -_There will be more tests over the coming weeks and months to shore up +_There will be more improvements over the coming weeks and months to shore up flakiness across shells and environments._ +### Tests + - Compatibility improvement for `test_capture_pane` and `env` (#452), credit: @zappolowski! - Remove more BASHisms from tests (#455) diff --git a/poetry.lock b/poetry.lock index b11ba78be..0764f87f3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -18,10 +18,10 @@ python-versions = ">=3.5" dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] -tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] +tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] [[package]] -name = "Babel" +name = "babel" version = "2.11.0" description = "Internationalization utilities" category = "dev" @@ -86,7 +86,7 @@ optional = false python-versions = ">=3.6.0" [package.extras] -unicode_backport = ["unicodedata2"] +unicode-backport = ["unicodedata2"] [[package]] name = "click" @@ -284,12 +284,12 @@ python-versions = ">=3.6.1,<4.0" [package.extras] colors = ["colorama (>=0.4.3,<0.5.0)"] -pipfile_deprecated_finder = ["pipreqs", "requirementslib"] +pipfile-deprecated-finder = ["pipreqs", "requirementslib"] plugins = ["setuptools"] -requirements_deprecated_finder = ["pip-api", "pipreqs"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] [[package]] -name = "Jinja2" +name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." category = "dev" @@ -328,7 +328,7 @@ typing_extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} [package.extras] benchmarking = ["psutil", "pytest", "pytest-benchmark (>=3.2,<4.0)"] -code_style = ["pre-commit (==2.6)"] +code-style = ["pre-commit (==2.6)"] compare = ["commonmark (>=0.9.1,<0.10.0)", "markdown (>=3.3.6,<3.4.0)", "mistletoe (>=0.8.1,<0.9.0)", "mistune (>=2.0.2,<2.1.0)", "panflute (>=2.1.3,<2.2.0)"] linkify = ["linkify-it-py (>=1.0,<2.0)"] plugins = ["mdit-py-plugins"] @@ -337,7 +337,7 @@ rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx- testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] -name = "MarkupSafe" +name = "markupsafe" version = "2.1.1" description = "Safely add untrusted strings to HTML/XML markup." category = "dev" @@ -372,7 +372,7 @@ python-versions = ">=3.7" markdown-it-py = ">=1.0.0,<3.0.0" [package.extras] -code_style = ["pre-commit"] +code-style = ["pre-commit"] rtd = ["attrs", "myst-parser (>=0.16.1,<0.17.0)", "sphinx-book-theme (>=0.1.0,<0.2.0)"] testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] @@ -429,7 +429,7 @@ sphinx = ">=4,<6" typing-extensions = "*" [package.extras] -code_style = ["pre-commit (>=2.12,<3.0)"] +code-style = ["pre-commit (>=2.12,<3.0)"] linkify = ["linkify-it-py (>=1.0,<2.0)"] rtd = ["ipython", "sphinx-book-theme", "sphinx-design", "sphinxcontrib.mermaid (>=0.7.1,<0.8.0)", "sphinxext-opengraph (>=0.6.3,<0.7.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=6,<7)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx (<5.2)", "sphinx-pytest"] @@ -513,7 +513,7 @@ optional = false python-versions = ">=3.6" [[package]] -name = "Pygments" +name = "pygments" version = "2.13.0" description = "Pygments is a syntax highlighting package written in Python." category = "dev" @@ -616,7 +616,7 @@ optional = false python-versions = "*" [[package]] -name = "PyYAML" +name = "pyyaml" version = "6.0" description = "YAML parser and emitter for Python" category = "dev" @@ -639,7 +639,7 @@ urllib3 = ">=1.21.1,<1.27" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "setuptools" @@ -679,7 +679,7 @@ optional = false python-versions = ">=3.6" [[package]] -name = "Sphinx" +name = "sphinx" version = "5.3.0" description = "Python documentation generator" category = "dev" @@ -781,7 +781,7 @@ python-versions = ">=3.6" sphinx = ">=1.8" [package.extras] -code_style = ["pre-commit (==2.12.1)"] +code-style = ["pre-commit (==2.12.1)"] rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme"] [[package]] @@ -981,7 +981,7 @@ attrs = [ {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, ] -Babel = [ +babel = [ {file = "Babel-2.11.0-py3-none-any.whl", hash = "sha256:1ad3eca1c885218f6dce2ab67291178944f810a10a9b5f3cb8382a5a232b64fe"}, {file = "Babel-2.11.0.tar.gz", hash = "sha256:5ef4b3226b0180dedded4229651c8b0e1a3a6a2837d45a073272f313e4cf97f6"}, ] @@ -1134,7 +1134,7 @@ isort = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, ] -Jinja2 = [ +jinja2 = [ {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, ] @@ -1145,7 +1145,7 @@ markdown-it-py = [ {file = "markdown-it-py-2.1.0.tar.gz", hash = "sha256:cf7e59fed14b5ae17c0006eff14a2d9a00ed5f3a846148153899a0224e2c07da"}, {file = "markdown_it_py-2.1.0-py3-none-any.whl", hash = "sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27"}, ] -MarkupSafe = [ +markupsafe = [ {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, @@ -1263,7 +1263,7 @@ pyflakes = [ {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"}, {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"}, ] -Pygments = [ +pygments = [ {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, ] @@ -1295,7 +1295,7 @@ pytz = [ {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"}, {file = "pytz-2022.6.tar.gz", hash = "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2"}, ] -PyYAML = [ +pyyaml = [ {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, @@ -1303,6 +1303,13 @@ PyYAML = [ {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, + {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, + {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, @@ -1350,7 +1357,7 @@ soupsieve = [ {file = "soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759"}, {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"}, ] -Sphinx = [ +sphinx = [ {file = "Sphinx-5.3.0.tar.gz", hash = "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5"}, {file = "sphinx-5.3.0-py3-none-any.whl", hash = "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d"}, ] diff --git a/pyproject.toml b/pyproject.toml index 9b843f7a8..5b6b57f77 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.9" +version = "0.15.10" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index fde9ce0d6..336efd170 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.9" +__version__ = "0.15.10" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From 9878f60de4c1d54ac2f3b0dc2511c0bfdc8e061c Mon Sep 17 00:00:00 2001 From: Bjoern Hiller Date: Tue, 1 Nov 2022 17:32:05 +0100 Subject: [PATCH 0169/1073] feat(Session.new_window): set up environment This allows to set up a custom environment when creating a new window. --- src/libtmux/session.py | 11 ++++++++ tests/test_session.py | 57 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/libtmux/session.py b/src/libtmux/session.py index f74c6e2a3..19b1bfd91 100644 --- a/src/libtmux/session.py +++ b/src/libtmux/session.py @@ -19,6 +19,7 @@ TmuxRelationalObject, WindowDict, handle_option_error, + has_gte_version, has_version, session_check_name, ) @@ -202,6 +203,7 @@ def new_window( attach: bool = True, window_index: str = "", window_shell: t.Optional[str] = None, + environment: t.Optional[t.Dict[str, str]] = None, ) -> Window: """ Return :class:`Window` from ``$ tmux new-window``. @@ -259,6 +261,15 @@ def new_window( % (self.id, window_index), ) + if environment: + if has_gte_version("3.0"): + for k, v in environment.items(): + window_args += (f"-e{k}={v}",) + else: + logger.warning( + "Cannot set up environment as tmux 3.0 or newer is required." + ) + if window_shell: window_args += (window_shell,) diff --git a/tests/test_session.py b/tests/test_session.py index c23d17c61..b3db613cb 100644 --- a/tests/test_session.py +++ b/tests/test_session.py @@ -1,11 +1,12 @@ """Test for libtmux Session object.""" import logging +import shutil import typing as t import pytest from libtmux import exc -from libtmux.common import has_gte_version +from libtmux.common import has_gte_version, has_lt_version from libtmux.pane import Pane from libtmux.server import Server from libtmux.session import Session @@ -257,3 +258,57 @@ def test_cmd_inserts_sesion_id(session: Session) -> None: assert "-t" in cmd.cmd assert current_session_id in cmd.cmd assert cmd.cmd[-1] == last_arg + + +@pytest.mark.skipif( + has_lt_version("3.0"), + reason="needs -e flag for new-window which was introduced in 3.0", +) +@pytest.mark.parametrize( + "environment", + [ + {"ENV_VAR": "window"}, + {"ENV_VAR_1": "window_1", "ENV_VAR_2": "window_2"}, + ], +) +def test_new_window_with_environment( + session: Session, + environment: t.Dict[str, str], +) -> None: + env = shutil.which("env") + assert env is not None, "Cannot find usable `env` in PATH." + + window = session.new_window( + attach=True, + window_name="window_with_environment", + window_shell=f"{env} PS1='$ ' sh", + environment=environment, + ) + pane = window.attached_pane + assert pane is not None + for k, v in environment.items(): + pane.send_keys(f"echo ${k}") + assert pane.capture_pane()[-2] == v + + +@pytest.mark.skipif( + has_gte_version("3.0"), + reason="3.0 has the -e flag on new-window", +) +def test_new_window_with_environment_logs_warning_for_old_tmux( + session: Session, + caplog: pytest.LogCaptureFixture, +) -> None: + env = shutil.which("env") + assert env is not None, "Cannot find usable `env` in PATH." + + session.new_window( + attach=True, + window_name="window_with_environment", + window_shell=f"{env} PS1='$ ' sh", + environment={"ENV_VAR": "window"}, + ) + + assert any( + "Cannot set up environment" in record.msg for record in caplog.records + ), "Warning missing" From 4244049b4afbb5d7a5383f2ec010a967c9aab104 Mon Sep 17 00:00:00 2001 From: Bjoern Hiller Date: Tue, 1 Nov 2022 17:37:21 +0100 Subject: [PATCH 0170/1073] feat(Window.split_window): set up environment This allows to set up a custom environment when creating a new pane. --- src/libtmux/window.py | 12 +++++++++- tests/test_window.py | 55 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/libtmux/window.py b/src/libtmux/window.py index 434dca17c..a6f03733d 100644 --- a/src/libtmux/window.py +++ b/src/libtmux/window.py @@ -9,7 +9,7 @@ import shlex import typing as t -from libtmux.common import tmux_cmd +from libtmux.common import has_gte_version, tmux_cmd from libtmux.pane import Pane from . import exc, formats @@ -442,6 +442,7 @@ def split_window( vertical: bool = True, shell: t.Optional[str] = None, percent: t.Optional[int] = None, + environment: t.Optional[t.Dict[str, str]] = None, ) -> Pane: """ Split window and return the created :class:`Pane`. @@ -520,6 +521,15 @@ def split_window( if not attach: tmux_args += ("-d",) + if environment: + if has_gte_version("3.0"): + for k, v in environment.items(): + tmux_args += (f"-e{k}={v}",) + else: + logger.warning( + "Cannot set up environment as tmux 3.0 or newer is required." + ) + if shell: tmux_args += (shell,) diff --git a/tests/test_window.py b/tests/test_window.py index 4c10c9c2a..02fb40552 100644 --- a/tests/test_window.py +++ b/tests/test_window.py @@ -1,5 +1,7 @@ """Test for libtmux Window object.""" import logging +import shutil +import time import typing as t import pytest @@ -310,3 +312,56 @@ def test_empty_window_name(session: Session) -> None: "#{==:#{session_name}," + session.name + "}", ) assert "''" in cmd.stdout + + +@pytest.mark.skipif( + has_lt_version("3.0"), + reason="needs -e flag for split-window which was introduced in 3.0", +) +@pytest.mark.parametrize( + "environment", + [ + {"ENV_VAR": "pane"}, + {"ENV_VAR_1": "pane_1", "ENV_VAR_2": "pane_2"}, + ], +) +def test_split_window_with_environment( + session: Session, + environment: t.Dict[str, str], +) -> None: + env = shutil.which("env") + assert env is not None, "Cannot find usable `env` in Path." + + window = session.new_window(window_name="split_window_with_environment") + pane = window.split_window( + shell=f"{env} PS1='$ ' sh", + environment=environment, + ) + assert pane is not None + # wait a bit for the prompt to be ready as the test gets flaky otherwise + time.sleep(0.05) + for k, v in environment.items(): + pane.send_keys(f"echo ${k}") + assert pane.capture_pane()[-2] == v + + +@pytest.mark.skipif( + has_gte_version("3.0"), + reason="3.0 has the -e flag on split-window", +) +def test_split_window_with_environment_logs_warning_for_old_tmux( + session: Session, + caplog: pytest.LogCaptureFixture, +) -> None: + env = shutil.which("env") + assert env is not None, "Cannot find usable `env` in Path." + + window = session.new_window(window_name="split_window_with_environment") + window.split_window( + shell=f"{env} PS1='$ ' sh", + environment={"ENV_VAR": "pane"}, + ) + + assert any( + "Cannot set up environment" in record.msg for record in caplog.records + ), "Warning missing" From 496b583f8032243fdd552df8bc47d33c8995f3c2 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 6 Nov 2022 14:17:30 -0600 Subject: [PATCH 0171/1073] docs(window,session): Document environment variable --- src/libtmux/session.py | 3 +++ src/libtmux/window.py | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/libtmux/session.py b/src/libtmux/session.py index 19b1bfd91..37cd8c122 100644 --- a/src/libtmux/session.py +++ b/src/libtmux/session.py @@ -229,6 +229,9 @@ def new_window( When this command exits the window will close. This feature is useful for long-running processes where the closing of the window upon completion is desired. + environment: dict, optional + Environmental variables for new window. tmux 3.0+ only. Passthrough to + ``-e``. Returns ------- diff --git a/src/libtmux/window.py b/src/libtmux/window.py index a6f03733d..0075b0187 100644 --- a/src/libtmux/window.py +++ b/src/libtmux/window.py @@ -469,6 +469,8 @@ def split_window( window upon completion is desired. percent: int, optional percentage to occupy with respect to current window + environment: dict, optional + Environmental variables for new pane. tmux 3.0+ only. Passthrough to ``-e``. Returns ------- From fca7c0d533f007995793da4b6c8961f6aaca6f8f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 6 Nov 2022 14:17:46 -0600 Subject: [PATCH 0172/1073] docs(CHANGES): Note environment variable update --- CHANGES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index 86d5af26f..df5f059fb 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,11 @@ $ pip install --user --upgrade --pre libtmux +### Features + +- `Window.split_window()` and `Session.new_window()` now support an optional + dictionary of environmental variables, via (#453), credit @zappolowski. + ## libtmux 0.15.10 (2022-11-05) _There will be more improvements over the coming weeks and months to shore up From 99266bce6f5cfa29da18323c6629a3b3fdf31910 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 6 Nov 2022 14:30:02 -0600 Subject: [PATCH 0173/1073] Tag v0.16.0a0 --- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5b6b57f77..48f0dcec0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.15.10" +version = "0.16.0a0" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index 336efd170..af64115fd 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.15.10" +__version__ = "0.16.a0" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From f3f4cd277913d41fd46f308997ea1883cb89b317 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 6 Nov 2022 18:12:44 -0600 Subject: [PATCH 0174/1073] build(deps): Bump platformdirs --- poetry.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 0764f87f3..1117cce6d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -455,15 +455,15 @@ python-versions = ">=3.7" [[package]] name = "platformdirs" -version = "2.5.2" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +version = "2.5.3" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] +docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"] +test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] name = "pluggy" @@ -1244,8 +1244,8 @@ pathspec = [ {file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"}, ] platformdirs = [ - {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, - {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, + {file = "platformdirs-2.5.3-py3-none-any.whl", hash = "sha256:0cb405749187a194f444c25c82ef7225232f11564721eabffc6ec70df83b11cb"}, + {file = "platformdirs-2.5.3.tar.gz", hash = "sha256:6e52c21afff35cb659c6e52d8b4d61b9bd544557180440538f255d9382c8cbe0"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, From 7705dc2224731d8c795273f2cf077270e1b961fa Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 11 Nov 2022 21:45:24 -0600 Subject: [PATCH 0175/1073] build(deps): Update mypy --- poetry.lock | 57 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1117cce6d..4c26f1102 100644 --- a/poetry.lock +++ b/poetry.lock @@ -386,7 +386,7 @@ python-versions = ">=3.7" [[package]] name = "mypy" -version = "0.982" +version = "0.990" description = "Optional static typing for Python" category = "dev" optional = false @@ -400,6 +400,7 @@ typing-extensions = ">=3.10" [package.extras] dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] python2 = ["typed-ast (>=1.4.0,<2)"] reports = ["lxml"] @@ -1202,30 +1203,36 @@ mdurl = [ {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] mypy = [ - {file = "mypy-0.982-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5085e6f442003fa915aeb0a46d4da58128da69325d8213b4b35cc7054090aed5"}, - {file = "mypy-0.982-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:41fd1cf9bc0e1c19b9af13a6580ccb66c381a5ee2cf63ee5ebab747a4badeba3"}, - {file = "mypy-0.982-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f793e3dd95e166b66d50e7b63e69e58e88643d80a3dcc3bcd81368e0478b089c"}, - {file = "mypy-0.982-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86ebe67adf4d021b28c3f547da6aa2cce660b57f0432617af2cca932d4d378a6"}, - {file = "mypy-0.982-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:175f292f649a3af7082fe36620369ffc4661a71005aa9f8297ea473df5772046"}, - {file = "mypy-0.982-cp310-cp310-win_amd64.whl", hash = "sha256:8ee8c2472e96beb1045e9081de8e92f295b89ac10c4109afdf3a23ad6e644f3e"}, - {file = "mypy-0.982-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58f27ebafe726a8e5ccb58d896451dd9a662a511a3188ff6a8a6a919142ecc20"}, - {file = "mypy-0.982-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6af646bd46f10d53834a8e8983e130e47d8ab2d4b7a97363e35b24e1d588947"}, - {file = "mypy-0.982-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7aeaa763c7ab86d5b66ff27f68493d672e44c8099af636d433a7f3fa5596d40"}, - {file = "mypy-0.982-cp37-cp37m-win_amd64.whl", hash = "sha256:724d36be56444f569c20a629d1d4ee0cb0ad666078d59bb84f8f887952511ca1"}, - {file = "mypy-0.982-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14d53cdd4cf93765aa747a7399f0961a365bcddf7855d9cef6306fa41de01c24"}, - {file = "mypy-0.982-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:26ae64555d480ad4b32a267d10cab7aec92ff44de35a7cd95b2b7cb8e64ebe3e"}, - {file = "mypy-0.982-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6389af3e204975d6658de4fb8ac16f58c14e1bacc6142fee86d1b5b26aa52bda"}, - {file = "mypy-0.982-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b35ce03a289480d6544aac85fa3674f493f323d80ea7226410ed065cd46f206"}, - {file = "mypy-0.982-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c6e564f035d25c99fd2b863e13049744d96bd1947e3d3d2f16f5828864506763"}, - {file = "mypy-0.982-cp38-cp38-win_amd64.whl", hash = "sha256:cebca7fd333f90b61b3ef7f217ff75ce2e287482206ef4a8b18f32b49927b1a2"}, - {file = "mypy-0.982-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a705a93670c8b74769496280d2fe6cd59961506c64f329bb179970ff1d24f9f8"}, - {file = "mypy-0.982-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75838c649290d83a2b83a88288c1eb60fe7a05b36d46cbea9d22efc790002146"}, - {file = "mypy-0.982-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:91781eff1f3f2607519c8b0e8518aad8498af1419e8442d5d0afb108059881fc"}, - {file = "mypy-0.982-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaa97b9ddd1dd9901a22a879491dbb951b5dec75c3b90032e2baa7336777363b"}, - {file = "mypy-0.982-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a692a8e7d07abe5f4b2dd32d731812a0175626a90a223d4b58f10f458747dd8a"}, - {file = "mypy-0.982-cp39-cp39-win_amd64.whl", hash = "sha256:eb7a068e503be3543c4bd329c994103874fa543c1727ba5288393c21d912d795"}, - {file = "mypy-0.982-py3-none-any.whl", hash = "sha256:1021c241e8b6e1ca5a47e4d52601274ac078a89845cfde66c6d5f769819ffa1d"}, - {file = "mypy-0.982.tar.gz", hash = "sha256:85f7a343542dc8b1ed0a888cdd34dca56462654ef23aa673907305b260b3d746"}, + {file = "mypy-0.990-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aaf1be63e0207d7d17be942dcf9a6b641745581fe6c64df9a38deb562a7dbafa"}, + {file = "mypy-0.990-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d555aa7f44cecb7ea3c0ac69d58b1a5afb92caa017285a8e9c4efbf0518b61b4"}, + {file = "mypy-0.990-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f694d6d09a460b117dccb6857dda269188e3437c880d7b60fa0014fa872d1e9"}, + {file = "mypy-0.990-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:269f0dfb6463b8780333310ff4b5134425157ef0d2b1d614015adaf6d6a7eabd"}, + {file = "mypy-0.990-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8798c8ed83aa809f053abff08664bdca056038f5a02af3660de00b7290b64c47"}, + {file = "mypy-0.990-cp310-cp310-win_amd64.whl", hash = "sha256:47a9955214615108c3480a500cfda8513a0b1cd3c09a1ed42764ca0dd7b931dd"}, + {file = "mypy-0.990-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4a8a6c10f4c63fbf6ad6c03eba22c9331b3946a4cec97f008e9ffb4d3b31e8e2"}, + {file = "mypy-0.990-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cd2dd3730ba894ec2a2082cc703fbf3e95a08479f7be84912e3131fc68809d46"}, + {file = "mypy-0.990-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7da0005e47975287a92b43276e460ac1831af3d23032c34e67d003388a0ce8d0"}, + {file = "mypy-0.990-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:262c543ef24deb10470a3c1c254bb986714e2b6b1a67d66daf836a548a9f316c"}, + {file = "mypy-0.990-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3ff201a0c6d3ea029d73b1648943387d75aa052491365b101f6edd5570d018ea"}, + {file = "mypy-0.990-cp311-cp311-win_amd64.whl", hash = "sha256:1767830da2d1afa4e62b684647af0ff79b401f004d7fa08bc5b0ce2d45bcd5ec"}, + {file = "mypy-0.990-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6826d9c4d85bbf6d68cb279b561de6a4d8d778ca8e9ab2d00ee768ab501a9852"}, + {file = "mypy-0.990-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46897755f944176fbc504178422a5a2875bbf3f7436727374724842c0987b5af"}, + {file = "mypy-0.990-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0680389c34284287fe00e82fc8bccdea9aff318f7e7d55b90d967a13a9606013"}, + {file = "mypy-0.990-cp37-cp37m-win_amd64.whl", hash = "sha256:b08541a06eed35b543ae1a6b301590eb61826a1eb099417676ddc5a42aa151c5"}, + {file = "mypy-0.990-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:be88d665e76b452c26fb2bdc3d54555c01226fba062b004ede780b190a50f9db"}, + {file = "mypy-0.990-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b8f4a8213b1fd4b751e26b59ae0e0c12896568d7e805861035c7a15ed6dc9eb"}, + {file = "mypy-0.990-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b6f85c2ad378e3224e017904a051b26660087b3b76490d533b7344f1546d3ff"}, + {file = "mypy-0.990-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ee5f99817ee70254e7eb5cf97c1b11dda29c6893d846c8b07bce449184e9466"}, + {file = "mypy-0.990-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49082382f571c3186ce9ea0bd627cb1345d4da8d44a8377870f4442401f0a706"}, + {file = "mypy-0.990-cp38-cp38-win_amd64.whl", hash = "sha256:aba38e3dd66bdbafbbfe9c6e79637841928ea4c79b32e334099463c17b0d90ef"}, + {file = "mypy-0.990-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9d851c09b981a65d9d283a8ccb5b1d0b698e580493416a10942ef1a04b19fd37"}, + {file = "mypy-0.990-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d847dd23540e2912d9667602271e5ebf25e5788e7da46da5ffd98e7872616e8e"}, + {file = "mypy-0.990-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cc6019808580565040cd2a561b593d7c3c646badd7e580e07d875eb1bf35c695"}, + {file = "mypy-0.990-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a3150d409609a775c8cb65dbe305c4edd7fe576c22ea79d77d1454acd9aeda8"}, + {file = "mypy-0.990-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3227f14fe943524f5794679156488f18bf8d34bfecd4623cf76bc55958d229c5"}, + {file = "mypy-0.990-cp39-cp39-win_amd64.whl", hash = "sha256:c76c769c46a1e6062a84837badcb2a7b0cdb153d68601a61f60739c37d41cc74"}, + {file = "mypy-0.990-py3-none-any.whl", hash = "sha256:8f1940325a8ed460ba03d19ab83742260fa9534804c317224e5d4e5aa588e2d6"}, + {file = "mypy-0.990.tar.gz", hash = "sha256:72382cb609142dba3f04140d016c94b4092bc7b4d98ca718740dc989e5271b8d"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, From bca0504301273d1482538b4a543912c1df0e0958 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 13 Nov 2022 07:10:40 -0600 Subject: [PATCH 0176/1073] build(deps): Bump pathspec, platformdirs --- poetry.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index 4c26f1102..01848acb8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -448,7 +448,7 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" [[package]] name = "pathspec" -version = "0.10.1" +version = "0.10.2" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false @@ -456,7 +456,7 @@ python-versions = ">=3.7" [[package]] name = "platformdirs" -version = "2.5.3" +version = "2.5.4" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false @@ -1247,12 +1247,12 @@ packaging = [ {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, ] pathspec = [ - {file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"}, - {file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"}, + {file = "pathspec-0.10.2-py3-none-any.whl", hash = "sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5"}, + {file = "pathspec-0.10.2.tar.gz", hash = "sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0"}, ] platformdirs = [ - {file = "platformdirs-2.5.3-py3-none-any.whl", hash = "sha256:0cb405749187a194f444c25c82ef7225232f11564721eabffc6ec70df83b11cb"}, - {file = "platformdirs-2.5.3.tar.gz", hash = "sha256:6e52c21afff35cb659c6e52d8b4d61b9bd544557180440538f255d9382c8cbe0"}, + {file = "platformdirs-2.5.4-py3-none-any.whl", hash = "sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10"}, + {file = "platformdirs-2.5.4.tar.gz", hash = "sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, From 91e989118e1740099579132e3ce38bbb90cbf10c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 19 Nov 2022 07:18:02 -0600 Subject: [PATCH 0177/1073] build(deps): Bump mypy, setuptools, sphinx-copybutton --- poetry.lock | 84 ++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/poetry.lock b/poetry.lock index 01848acb8..20b726332 100644 --- a/poetry.lock +++ b/poetry.lock @@ -144,7 +144,7 @@ python-versions = ">=3.7" [[package]] name = "exceptiongroup" -version = "1.0.1" +version = "1.0.4" description = "Backport of PEP 654 (exception groups)" category = "dev" optional = false @@ -386,7 +386,7 @@ python-versions = ">=3.7" [[package]] name = "mypy" -version = "0.990" +version = "0.991" description = "Optional static typing for Python" category = "dev" optional = false @@ -644,7 +644,7 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "setuptools" -version = "65.5.1" +version = "65.6.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" category = "dev" optional = false @@ -772,18 +772,18 @@ sphinx = ">=2.0" [[package]] name = "sphinx-copybutton" -version = "0.5.0" +version = "0.5.1" description = "Add a copy button to each of your code cells." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] sphinx = ">=1.8" [package.extras] code-style = ["pre-commit (==2.12.1)"] -rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme"] +rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"] [[package]] name = "sphinx-inline-tabs" @@ -1090,8 +1090,8 @@ docutils = [ {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"}, ] exceptiongroup = [ - {file = "exceptiongroup-1.0.1-py3-none-any.whl", hash = "sha256:4d6c0aa6dd825810941c792f53d7b8d71da26f5e5f84f20f9508e8f2d33b140a"}, - {file = "exceptiongroup-1.0.1.tar.gz", hash = "sha256:73866f7f842ede6cb1daa42c4af078e2035e5f7607f0e2c762cc51bb31bbe7b2"}, + {file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"}, + {file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"}, ] flake8 = [ {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, @@ -1203,36 +1203,36 @@ mdurl = [ {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] mypy = [ - {file = "mypy-0.990-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aaf1be63e0207d7d17be942dcf9a6b641745581fe6c64df9a38deb562a7dbafa"}, - {file = "mypy-0.990-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d555aa7f44cecb7ea3c0ac69d58b1a5afb92caa017285a8e9c4efbf0518b61b4"}, - {file = "mypy-0.990-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f694d6d09a460b117dccb6857dda269188e3437c880d7b60fa0014fa872d1e9"}, - {file = "mypy-0.990-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:269f0dfb6463b8780333310ff4b5134425157ef0d2b1d614015adaf6d6a7eabd"}, - {file = "mypy-0.990-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8798c8ed83aa809f053abff08664bdca056038f5a02af3660de00b7290b64c47"}, - {file = "mypy-0.990-cp310-cp310-win_amd64.whl", hash = "sha256:47a9955214615108c3480a500cfda8513a0b1cd3c09a1ed42764ca0dd7b931dd"}, - {file = "mypy-0.990-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4a8a6c10f4c63fbf6ad6c03eba22c9331b3946a4cec97f008e9ffb4d3b31e8e2"}, - {file = "mypy-0.990-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cd2dd3730ba894ec2a2082cc703fbf3e95a08479f7be84912e3131fc68809d46"}, - {file = "mypy-0.990-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7da0005e47975287a92b43276e460ac1831af3d23032c34e67d003388a0ce8d0"}, - {file = "mypy-0.990-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:262c543ef24deb10470a3c1c254bb986714e2b6b1a67d66daf836a548a9f316c"}, - {file = "mypy-0.990-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3ff201a0c6d3ea029d73b1648943387d75aa052491365b101f6edd5570d018ea"}, - {file = "mypy-0.990-cp311-cp311-win_amd64.whl", hash = "sha256:1767830da2d1afa4e62b684647af0ff79b401f004d7fa08bc5b0ce2d45bcd5ec"}, - {file = "mypy-0.990-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6826d9c4d85bbf6d68cb279b561de6a4d8d778ca8e9ab2d00ee768ab501a9852"}, - {file = "mypy-0.990-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46897755f944176fbc504178422a5a2875bbf3f7436727374724842c0987b5af"}, - {file = "mypy-0.990-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0680389c34284287fe00e82fc8bccdea9aff318f7e7d55b90d967a13a9606013"}, - {file = "mypy-0.990-cp37-cp37m-win_amd64.whl", hash = "sha256:b08541a06eed35b543ae1a6b301590eb61826a1eb099417676ddc5a42aa151c5"}, - {file = "mypy-0.990-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:be88d665e76b452c26fb2bdc3d54555c01226fba062b004ede780b190a50f9db"}, - {file = "mypy-0.990-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b8f4a8213b1fd4b751e26b59ae0e0c12896568d7e805861035c7a15ed6dc9eb"}, - {file = "mypy-0.990-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b6f85c2ad378e3224e017904a051b26660087b3b76490d533b7344f1546d3ff"}, - {file = "mypy-0.990-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ee5f99817ee70254e7eb5cf97c1b11dda29c6893d846c8b07bce449184e9466"}, - {file = "mypy-0.990-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49082382f571c3186ce9ea0bd627cb1345d4da8d44a8377870f4442401f0a706"}, - {file = "mypy-0.990-cp38-cp38-win_amd64.whl", hash = "sha256:aba38e3dd66bdbafbbfe9c6e79637841928ea4c79b32e334099463c17b0d90ef"}, - {file = "mypy-0.990-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9d851c09b981a65d9d283a8ccb5b1d0b698e580493416a10942ef1a04b19fd37"}, - {file = "mypy-0.990-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d847dd23540e2912d9667602271e5ebf25e5788e7da46da5ffd98e7872616e8e"}, - {file = "mypy-0.990-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cc6019808580565040cd2a561b593d7c3c646badd7e580e07d875eb1bf35c695"}, - {file = "mypy-0.990-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a3150d409609a775c8cb65dbe305c4edd7fe576c22ea79d77d1454acd9aeda8"}, - {file = "mypy-0.990-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3227f14fe943524f5794679156488f18bf8d34bfecd4623cf76bc55958d229c5"}, - {file = "mypy-0.990-cp39-cp39-win_amd64.whl", hash = "sha256:c76c769c46a1e6062a84837badcb2a7b0cdb153d68601a61f60739c37d41cc74"}, - {file = "mypy-0.990-py3-none-any.whl", hash = "sha256:8f1940325a8ed460ba03d19ab83742260fa9534804c317224e5d4e5aa588e2d6"}, - {file = "mypy-0.990.tar.gz", hash = "sha256:72382cb609142dba3f04140d016c94b4092bc7b4d98ca718740dc989e5271b8d"}, + {file = "mypy-0.991-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7d17e0a9707d0772f4a7b878f04b4fd11f6f5bcb9b3813975a9b13c9332153ab"}, + {file = "mypy-0.991-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0714258640194d75677e86c786e80ccf294972cc76885d3ebbb560f11db0003d"}, + {file = "mypy-0.991-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0c8f3be99e8a8bd403caa8c03be619544bc2c77a7093685dcf308c6b109426c6"}, + {file = "mypy-0.991-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc9ec663ed6c8f15f4ae9d3c04c989b744436c16d26580eaa760ae9dd5d662eb"}, + {file = "mypy-0.991-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4307270436fd7694b41f913eb09210faff27ea4979ecbcd849e57d2da2f65305"}, + {file = "mypy-0.991-cp310-cp310-win_amd64.whl", hash = "sha256:901c2c269c616e6cb0998b33d4adbb4a6af0ac4ce5cd078afd7bc95830e62c1c"}, + {file = "mypy-0.991-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d13674f3fb73805ba0c45eb6c0c3053d218aa1f7abead6e446d474529aafc372"}, + {file = "mypy-0.991-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1c8cd4fb70e8584ca1ed5805cbc7c017a3d1a29fb450621089ffed3e99d1857f"}, + {file = "mypy-0.991-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:209ee89fbb0deed518605edddd234af80506aec932ad28d73c08f1400ef80a33"}, + {file = "mypy-0.991-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37bd02ebf9d10e05b00d71302d2c2e6ca333e6c2a8584a98c00e038db8121f05"}, + {file = "mypy-0.991-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:26efb2fcc6b67e4d5a55561f39176821d2adf88f2745ddc72751b7890f3194ad"}, + {file = "mypy-0.991-cp311-cp311-win_amd64.whl", hash = "sha256:3a700330b567114b673cf8ee7388e949f843b356a73b5ab22dd7cff4742a5297"}, + {file = "mypy-0.991-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1f7d1a520373e2272b10796c3ff721ea1a0712288cafaa95931e66aa15798813"}, + {file = "mypy-0.991-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:641411733b127c3e0dab94c45af15fea99e4468f99ac88b39efb1ad677da5711"}, + {file = "mypy-0.991-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3d80e36b7d7a9259b740be6d8d906221789b0d836201af4234093cae89ced0cd"}, + {file = "mypy-0.991-cp37-cp37m-win_amd64.whl", hash = "sha256:e62ebaad93be3ad1a828a11e90f0e76f15449371ffeecca4a0a0b9adc99abcef"}, + {file = "mypy-0.991-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b86ce2c1866a748c0f6faca5232059f881cda6dda2a893b9a8373353cfe3715a"}, + {file = "mypy-0.991-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac6e503823143464538efda0e8e356d871557ef60ccd38f8824a4257acc18d93"}, + {file = "mypy-0.991-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0cca5adf694af539aeaa6ac633a7afe9bbd760df9d31be55ab780b77ab5ae8bf"}, + {file = "mypy-0.991-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12c56bf73cdab116df96e4ff39610b92a348cc99a1307e1da3c3768bbb5b135"}, + {file = "mypy-0.991-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:652b651d42f155033a1967739788c436491b577b6a44e4c39fb340d0ee7f0d70"}, + {file = "mypy-0.991-cp38-cp38-win_amd64.whl", hash = "sha256:4175593dc25d9da12f7de8de873a33f9b2b8bdb4e827a7cae952e5b1a342e243"}, + {file = "mypy-0.991-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:98e781cd35c0acf33eb0295e8b9c55cdbef64fcb35f6d3aa2186f289bed6e80d"}, + {file = "mypy-0.991-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6d7464bac72a85cb3491c7e92b5b62f3dcccb8af26826257760a552a5e244aa5"}, + {file = "mypy-0.991-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c9166b3f81a10cdf9b49f2d594b21b31adadb3d5e9db9b834866c3258b695be3"}, + {file = "mypy-0.991-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8472f736a5bfb159a5e36740847808f6f5b659960115ff29c7cecec1741c648"}, + {file = "mypy-0.991-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e80e758243b97b618cdf22004beb09e8a2de1af481382e4d84bc52152d1c476"}, + {file = "mypy-0.991-cp39-cp39-win_amd64.whl", hash = "sha256:74e259b5c19f70d35fcc1ad3d56499065c601dfe94ff67ae48b85596b9ec1461"}, + {file = "mypy-0.991-py3-none-any.whl", hash = "sha256:de32edc9b0a7e67c2775e574cb061a537660e51210fbf6006b0b36ea695ae9bb"}, + {file = "mypy-0.991.tar.gz", hash = "sha256:3c0165ba8f354a6d9881809ef29f1a9318a236a6d81c690094c5df32107bde06"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, @@ -1349,8 +1349,8 @@ requests = [ {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, ] setuptools = [ - {file = "setuptools-65.5.1-py3-none-any.whl", hash = "sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31"}, - {file = "setuptools-65.5.1.tar.gz", hash = "sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"}, + {file = "setuptools-65.6.0-py3-none-any.whl", hash = "sha256:6211d2f5eddad8757bd0484923ca7c0a6302ebc4ab32ea5e94357176e0ca0840"}, + {file = "setuptools-65.6.0.tar.gz", hash = "sha256:d1eebf881c6114e51df1664bc2c9133d022f78d12d5f4f665b9191f084e2862d"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, @@ -1385,8 +1385,8 @@ sphinx-click = [ {file = "sphinx_click-4.3.0-py3-none-any.whl", hash = "sha256:23e85a3cb0b728a421ea773699f6acadefae171d1a764a51dd8ec5981503ccbe"}, ] sphinx-copybutton = [ - {file = "sphinx-copybutton-0.5.0.tar.gz", hash = "sha256:a0c059daadd03c27ba750da534a92a63e7a36a7736dcf684f26ee346199787f6"}, - {file = "sphinx_copybutton-0.5.0-py3-none-any.whl", hash = "sha256:9684dec7434bd73f0eea58dda93f9bb879d24bff2d8b187b1f2ec08dfe7b5f48"}, + {file = "sphinx-copybutton-0.5.1.tar.gz", hash = "sha256:366251e28a6f6041514bfb5439425210418d6c750e98d3a695b73e56866a677a"}, + {file = "sphinx_copybutton-0.5.1-py3-none-any.whl", hash = "sha256:0842851b5955087a7ec7fc870b622cb168618ad408dee42692e9a5c97d071da8"}, ] sphinx-inline-tabs = [ {file = "sphinx_inline_tabs-2021.3.28b7-py3-none-any.whl", hash = "sha256:951982fee76fd21ba880182efe6d500872122a2d41a6e4e0ce0b529123500874"}, From 8c11f88f1d0bcf22f7e15f0cb15ae4fce6e5ac54 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 22 Nov 2022 15:30:17 -0600 Subject: [PATCH 0178/1073] build(deps): Bump sphinxext-opengraph, setuptools --- poetry.lock | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/poetry.lock b/poetry.lock index 20b726332..80149283f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -587,15 +587,16 @@ dev = ["pre-commit", "pytest-asyncio", "tox"] [[package]] name = "pytest-rerunfailures" -version = "10.2" +version = "10.3" description = "pytest plugin to re-run tests to eliminate flaky failures" category = "dev" optional = false -python-versions = ">= 3.6" +python-versions = ">=3.6" [package.dependencies] +importlib-metadata = {version = ">=1", markers = "python_version < \"3.8\""} +packaging = ">=17.1" pytest = ">=5.3" -setuptools = ">=40.0" [[package]] name = "pytest-watcher" @@ -642,19 +643,6 @@ urllib3 = ">=1.21.1,<1.27" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] -[[package]] -name = "setuptools" -version = "65.6.0" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - [[package]] name = "six" version = "1.16.0" @@ -873,7 +861,7 @@ test = ["pytest"] [[package]] name = "sphinxext-opengraph" -version = "0.7.2" +version = "0.7.3" description = "Sphinx Extension to enable OGP support" category = "dev" optional = false @@ -1291,8 +1279,8 @@ pytest-mock = [ {file = "pytest_mock-3.10.0-py3-none-any.whl", hash = "sha256:f4c973eeae0282963eb293eb173ce91b091a79c1334455acfac9ddee8a1c784b"}, ] pytest-rerunfailures = [ - {file = "pytest-rerunfailures-10.2.tar.gz", hash = "sha256:9e1e1bad51e07642c5bbab809fc1d4ec8eebcb7de86f90f1a26e6ef9de446697"}, - {file = "pytest_rerunfailures-10.2-py3-none-any.whl", hash = "sha256:d31d8e828dfd39363ad99cd390187bf506c7a433a89f15c3126c7d16ab723fe2"}, + {file = "pytest-rerunfailures-10.3.tar.gz", hash = "sha256:d8244d799f89a6edb5e57301ddaeb3b6f10d6691638d51e80b371311592e28c6"}, + {file = "pytest_rerunfailures-10.3-py3-none-any.whl", hash = "sha256:6be6f96510bf94b54198bf15bc5568fe2cdff88e83875912e22d29810acf65ff"}, ] pytest-watcher = [ {file = "pytest-watcher-0.2.5.tar.gz", hash = "sha256:0a220d18b778fbae4d876f8d7d2eb86e63d7d8257cd6b05f42c13aa6625c0b6f"}, @@ -1348,10 +1336,6 @@ requests = [ {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, ] -setuptools = [ - {file = "setuptools-65.6.0-py3-none-any.whl", hash = "sha256:6211d2f5eddad8757bd0484923ca7c0a6302ebc4ab32ea5e94357176e0ca0840"}, - {file = "setuptools-65.6.0.tar.gz", hash = "sha256:d1eebf881c6114e51df1664bc2c9133d022f78d12d5f4f665b9191f084e2862d"}, -] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, @@ -1417,8 +1401,8 @@ sphinxcontrib-serializinghtml = [ {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, ] sphinxext-opengraph = [ - {file = "sphinxext-opengraph-0.7.2.tar.gz", hash = "sha256:85230ee14d50c97d9db457d4dc4c9f9ea08bc78e7dd6850d615e05705e5c2977"}, - {file = "sphinxext_opengraph-0.7.2-py3-none-any.whl", hash = "sha256:7a33e13a1e1d6afa66744c24d1f5aabdde77ba70018403f9137a2d8dbe958c24"}, + {file = "sphinxext-opengraph-0.7.3.tar.gz", hash = "sha256:837e5612709b4df7f1715f0832bf7d46cc0a61ebd7bb5aeab28edd6377beaf23"}, + {file = "sphinxext_opengraph-0.7.3-py3-none-any.whl", hash = "sha256:edbfb21f1d31f572fc87a6ccc347cac502a3b8bb04c312bc2fa4888542f8505d"}, ] sphinxext-rediraffe = [ {file = "sphinxext-rediraffe-0.2.7.tar.gz", hash = "sha256:651dcbfae5ffda9ffd534dfb8025f36120e5efb6ea1a33f5420023862b9f725d"}, From a1c728b47ffd2a9c18e484668bdd6cb96471536f Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 26 Nov 2022 12:12:32 -0600 Subject: [PATCH 0179/1073] build(deps): Bump setuptools, urllib3 --- poetry.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/poetry.lock b/poetry.lock index 80149283f..279d5e218 100644 --- a/poetry.lock +++ b/poetry.lock @@ -915,11 +915,11 @@ python-versions = ">=3.7" [[package]] name = "urllib3" -version = "1.26.12" +version = "1.26.13" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] @@ -939,7 +939,7 @@ watchmedo = ["PyYAML (>=3.10)"] [[package]] name = "zipp" -version = "3.10.0" +version = "3.11.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "dev" optional = false @@ -1456,8 +1456,8 @@ typing-extensions = [ {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, ] urllib3 = [ - {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, - {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, + {file = "urllib3-1.26.13-py2.py3-none-any.whl", hash = "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc"}, + {file = "urllib3-1.26.13.tar.gz", hash = "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8"}, ] watchdog = [ {file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a735a990a1095f75ca4f36ea2ef2752c99e6ee997c46b0de507ba40a09bf7330"}, @@ -1487,6 +1487,6 @@ watchdog = [ {file = "watchdog-2.1.9.tar.gz", hash = "sha256:43ce20ebb36a51f21fa376f76d1d4692452b2527ccd601950d69ed36b9e21609"}, ] zipp = [ - {file = "zipp-3.10.0-py3-none-any.whl", hash = "sha256:4fcb6f278987a6605757302a6e40e896257570d11c51628968ccb2a47e80c6c1"}, - {file = "zipp-3.10.0.tar.gz", hash = "sha256:7a7262fd930bd3e36c50b9a64897aec3fafff3dfdeec9623ae22b40e93f99bb8"}, + {file = "zipp-3.11.0-py3-none-any.whl", hash = "sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa"}, + {file = "zipp-3.11.0.tar.gz", hash = "sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766"}, ] From 30ca8bd6b0a984e52822049af0251bc027a6ee2b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Fri, 2 Dec 2022 11:02:12 -0600 Subject: [PATCH 0180/1073] chore(Makefile): Fix link to entr --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fd60024a4..b5b6cd08e 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ entr_warn: @echo " ! File watching functionality non-operational ! " @echo " " @echo "Install entr(1) to automatically run tasks on file change." - @echo "See http://entrproject.org/ " + @echo "See https://eradman.com/entrproject/ " @echo "----------------------------------------------------------" isort: From d46a0cc0d98266367bcd330b709208c591bb2504 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 5 Dec 2022 18:34:09 -0600 Subject: [PATCH 0181/1073] build(deps): Bump urllib3, mdit-py-plugins, watchdog, zipp --- poetry.lock | 61 ++++++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/poetry.lock b/poetry.lock index 279d5e218..f5e0c71ec 100644 --- a/poetry.lock +++ b/poetry.lock @@ -362,7 +362,7 @@ python-versions = ">=3.6" [[package]] name = "mdit-py-plugins" -version = "0.3.1" +version = "0.3.2" description = "Collection of plugins for markdown-it-py" category = "dev" optional = false @@ -928,7 +928,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "watchdog" -version = "2.1.9" +version = "2.2.0" description = "Filesystem events monitoring" category = "dev" optional = false @@ -1183,8 +1183,8 @@ mccabe = [ {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] mdit-py-plugins = [ - {file = "mdit-py-plugins-0.3.1.tar.gz", hash = "sha256:3fc13298497d6e04fe96efdd41281bfe7622152f9caa1815ea99b5c893de9441"}, - {file = "mdit_py_plugins-0.3.1-py3-none-any.whl", hash = "sha256:606a7f29cf56dbdfaf914acb21709b8f8ee29d857e8f29dcc33d8cb84c57bfa1"}, + {file = "mdit-py-plugins-0.3.2.tar.gz", hash = "sha256:c37ca25a4a5244b41cc3b34b9d7762a96ee0416dd43efaa837304d592a84995f"}, + {file = "mdit_py_plugins-0.3.2-py3-none-any.whl", hash = "sha256:01e1c0f5432792d79ef627cd1745ce7c240d88d84b4e9dc6e87529a0f3ebba3e"}, ] mdurl = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, @@ -1460,31 +1460,34 @@ urllib3 = [ {file = "urllib3-1.26.13.tar.gz", hash = "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8"}, ] watchdog = [ - {file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a735a990a1095f75ca4f36ea2ef2752c99e6ee997c46b0de507ba40a09bf7330"}, - {file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b17d302850c8d412784d9246cfe8d7e3af6bcd45f958abb2d08a6f8bedf695d"}, - {file = "watchdog-2.1.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ee3e38a6cc050a8830089f79cbec8a3878ec2fe5160cdb2dc8ccb6def8552658"}, - {file = "watchdog-2.1.9-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64a27aed691408a6abd83394b38503e8176f69031ca25d64131d8d640a307591"}, - {file = "watchdog-2.1.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:195fc70c6e41237362ba720e9aaf394f8178bfc7fa68207f112d108edef1af33"}, - {file = "watchdog-2.1.9-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bfc4d351e6348d6ec51df007432e6fe80adb53fd41183716017026af03427846"}, - {file = "watchdog-2.1.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8250546a98388cbc00c3ee3cc5cf96799b5a595270dfcfa855491a64b86ef8c3"}, - {file = "watchdog-2.1.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:117ffc6ec261639a0209a3252546b12800670d4bf5f84fbd355957a0595fe654"}, - {file = "watchdog-2.1.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:97f9752208f5154e9e7b76acc8c4f5a58801b338de2af14e7e181ee3b28a5d39"}, - {file = "watchdog-2.1.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:247dcf1df956daa24828bfea5a138d0e7a7c98b1a47cf1fa5b0c3c16241fcbb7"}, - {file = "watchdog-2.1.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:226b3c6c468ce72051a4c15a4cc2ef317c32590d82ba0b330403cafd98a62cfd"}, - {file = "watchdog-2.1.9-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d9820fe47c20c13e3c9dd544d3706a2a26c02b2b43c993b62fcd8011bcc0adb3"}, - {file = "watchdog-2.1.9-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:70af927aa1613ded6a68089a9262a009fbdf819f46d09c1a908d4b36e1ba2b2d"}, - {file = "watchdog-2.1.9-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ed80a1628cee19f5cfc6bb74e173f1b4189eb532e705e2a13e3250312a62e0c9"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_aarch64.whl", hash = "sha256:9f05a5f7c12452f6a27203f76779ae3f46fa30f1dd833037ea8cbc2887c60213"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_armv7l.whl", hash = "sha256:255bb5758f7e89b1a13c05a5bceccec2219f8995a3a4c4d6968fe1de6a3b2892"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_i686.whl", hash = "sha256:d3dda00aca282b26194bdd0adec21e4c21e916956d972369359ba63ade616153"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_ppc64.whl", hash = "sha256:186f6c55abc5e03872ae14c2f294a153ec7292f807af99f57611acc8caa75306"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:083171652584e1b8829581f965b9b7723ca5f9a2cd7e20271edf264cfd7c1412"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_s390x.whl", hash = "sha256:b530ae007a5f5d50b7fbba96634c7ee21abec70dc3e7f0233339c81943848dc1"}, - {file = "watchdog-2.1.9-py3-none-manylinux2014_x86_64.whl", hash = "sha256:4f4e1c4aa54fb86316a62a87b3378c025e228178d55481d30d857c6c438897d6"}, - {file = "watchdog-2.1.9-py3-none-win32.whl", hash = "sha256:5952135968519e2447a01875a6f5fc8c03190b24d14ee52b0f4b1682259520b1"}, - {file = "watchdog-2.1.9-py3-none-win_amd64.whl", hash = "sha256:7a833211f49143c3d336729b0020ffd1274078e94b0ae42e22f596999f50279c"}, - {file = "watchdog-2.1.9-py3-none-win_ia64.whl", hash = "sha256:ad576a565260d8f99d97f2e64b0f97a48228317095908568a9d5c786c829d428"}, - {file = "watchdog-2.1.9.tar.gz", hash = "sha256:43ce20ebb36a51f21fa376f76d1d4692452b2527ccd601950d69ed36b9e21609"}, + {file = "watchdog-2.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ed91c3ccfc23398e7aa9715abf679d5c163394b8cad994f34f156d57a7c163dc"}, + {file = "watchdog-2.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:76a2743402b794629a955d96ea2e240bd0e903aa26e02e93cd2d57b33900962b"}, + {file = "watchdog-2.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:920a4bda7daa47545c3201a3292e99300ba81ca26b7569575bd086c865889090"}, + {file = "watchdog-2.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ceaa9268d81205876bedb1069f9feab3eccddd4b90d9a45d06a0df592a04cae9"}, + {file = "watchdog-2.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1893d425ef4fb4f129ee8ef72226836619c2950dd0559bba022b0818c63a7b60"}, + {file = "watchdog-2.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9e99c1713e4436d2563f5828c8910e5ff25abd6ce999e75f15c15d81d41980b6"}, + {file = "watchdog-2.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a5bd9e8656d07cae89ac464ee4bcb6f1b9cecbedc3bf1334683bed3d5afd39ba"}, + {file = "watchdog-2.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a048865c828389cb06c0bebf8a883cec3ae58ad3e366bcc38c61d8455a3138f"}, + {file = "watchdog-2.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e722755d995035dd32177a9c633d158f2ec604f2a358b545bba5bed53ab25bca"}, + {file = "watchdog-2.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:af4b5c7ba60206759a1d99811b5938ca666ea9562a1052b410637bb96ff97512"}, + {file = "watchdog-2.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:619d63fa5be69f89ff3a93e165e602c08ed8da402ca42b99cd59a8ec115673e1"}, + {file = "watchdog-2.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1f2b0665c57358ce9786f06f5475bc083fea9d81ecc0efa4733fd0c320940a37"}, + {file = "watchdog-2.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:441024df19253bb108d3a8a5de7a186003d68564084576fecf7333a441271ef7"}, + {file = "watchdog-2.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1a410dd4d0adcc86b4c71d1317ba2ea2c92babaf5b83321e4bde2514525544d5"}, + {file = "watchdog-2.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:28704c71afdb79c3f215c90231e41c52b056ea880b6be6cee035c6149d658ed1"}, + {file = "watchdog-2.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2ac0bd7c206bb6df78ef9e8ad27cc1346f2b41b1fef610395607319cdab89bc1"}, + {file = "watchdog-2.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:27e49268735b3c27310883012ab3bd86ea0a96dcab90fe3feb682472e30c90f3"}, + {file = "watchdog-2.2.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:2af1a29fd14fc0a87fb6ed762d3e1ae5694dcde22372eebba50e9e5be47af03c"}, + {file = "watchdog-2.2.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:c7bd98813d34bfa9b464cf8122e7d4bec0a5a427399094d2c17dd5f70d59bc61"}, + {file = "watchdog-2.2.0-py3-none-manylinux2014_i686.whl", hash = "sha256:56fb3f40fc3deecf6e518303c7533f5e2a722e377b12507f6de891583f1b48aa"}, + {file = "watchdog-2.2.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:74535e955359d79d126885e642d3683616e6d9ab3aae0e7dcccd043bd5a3ff4f"}, + {file = "watchdog-2.2.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:cf05e6ff677b9655c6e9511d02e9cc55e730c4e430b7a54af9c28912294605a4"}, + {file = "watchdog-2.2.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:d6ae890798a3560688b441ef086bb66e87af6b400a92749a18b856a134fc0318"}, + {file = "watchdog-2.2.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:e5aed2a700a18c194c39c266900d41f3db0c1ebe6b8a0834b9995c835d2ca66e"}, + {file = "watchdog-2.2.0-py3-none-win32.whl", hash = "sha256:d0fb5f2b513556c2abb578c1066f5f467d729f2eb689bc2db0739daf81c6bb7e"}, + {file = "watchdog-2.2.0-py3-none-win_amd64.whl", hash = "sha256:1f8eca9d294a4f194ce9df0d97d19b5598f310950d3ac3dd6e8d25ae456d4c8a"}, + {file = "watchdog-2.2.0-py3-none-win_ia64.whl", hash = "sha256:ad0150536469fa4b693531e497ffe220d5b6cd76ad2eda474a5e641ee204bbb6"}, + {file = "watchdog-2.2.0.tar.gz", hash = "sha256:83cf8bc60d9c613b66a4c018051873d6273d9e45d040eed06d6a96241bd8ec01"}, ] zipp = [ {file = "zipp-3.11.0-py3-none-any.whl", hash = "sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa"}, From 5f66a685da893f8b68cd2cd0c73569a64a122eec Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Dec 2022 08:26:45 -0600 Subject: [PATCH 0182/1073] build(deps): Bump dev deps --- poetry.lock | 105 +++++++++++++++++++--------------------------------- 1 file changed, 39 insertions(+), 66 deletions(-) diff --git a/poetry.lock b/poetry.lock index f5e0c71ec..32ad02b97 100644 --- a/poetry.lock +++ b/poetry.lock @@ -48,7 +48,7 @@ lxml = ["lxml"] [[package]] name = "black" -version = "22.10.0" +version = "22.12.0" description = "The uncompromising code formatter." category = "dev" optional = false @@ -71,7 +71,7 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2022.9.24" +version = "2022.12.7" description = "Python package for providing Mozilla's CA Bundle." category = "dev" optional = false @@ -182,7 +182,7 @@ pyflakes = ">=2.5.0,<2.6.0" [[package]] name = "flake8-bugbear" -version = "22.10.27" +version = "22.12.6" description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." category = "dev" optional = false @@ -209,7 +209,7 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} [[package]] name = "furo" -version = "2022.9.29" +version = "2022.12.7" description = "A clean customisable Sphinx documentation theme." category = "dev" optional = false @@ -218,7 +218,7 @@ python-versions = ">=3.7" [package.dependencies] beautifulsoup4 = "*" pygments = ">=2.7" -sphinx = ">=4.0,<6.0" +sphinx = ">=5.0,<7.0" sphinx-basic-ng = "*" [[package]] @@ -362,7 +362,7 @@ python-versions = ">=3.6" [[package]] name = "mdit-py-plugins" -version = "0.3.2" +version = "0.3.3" description = "Collection of plugins for markdown-it-py" category = "dev" optional = false @@ -437,18 +437,15 @@ testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=6,<7)", "pytest-cov", [[package]] name = "packaging" -version = "21.3" +version = "22.0" description = "Core utilities for Python packages" category = "dev" optional = false -python-versions = ">=3.6" - -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" +python-versions = ">=3.7" [[package]] name = "pathspec" -version = "0.10.2" +version = "0.10.3" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false @@ -456,7 +453,7 @@ python-versions = ">=3.7" [[package]] name = "platformdirs" -version = "2.5.4" +version = "2.6.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false @@ -524,17 +521,6 @@ python-versions = ">=3.6" [package.extras] plugins = ["importlib-metadata"] -[[package]] -name = "pyparsing" -version = "3.0.9" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "dev" -optional = false -python-versions = ">=3.6.8" - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - [[package]] name = "pytest" version = "7.2.0" @@ -747,7 +733,7 @@ docs = ["furo", "ipython", "myst-parser", "sphinx-copybutton", "sphinx-inline-ta [[package]] name = "sphinx-click" -version = "4.3.0" +version = "4.4.0" description = "Sphinx extension that automatically documents click applications" category = "dev" optional = false @@ -979,31 +965,22 @@ beautifulsoup4 = [ {file = "beautifulsoup4-4.11.1.tar.gz", hash = "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"}, ] black = [ - {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, - {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, - {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, - {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, - {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, - {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, - {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, - {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, - {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, - {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, - {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, - {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, - {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"}, - {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"}, - {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"}, - {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"}, - {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"}, - {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"}, - {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"}, - {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"}, - {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, + {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, + {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, + {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, + {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, + {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, + {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, + {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, + {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, + {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, + {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, + {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, + {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, ] certifi = [ - {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"}, - {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"}, + {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, + {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, ] charset-normalizer = [ {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, @@ -1088,16 +1065,16 @@ flake8 = [ {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"}, ] flake8-bugbear = [ - {file = "flake8-bugbear-22.10.27.tar.gz", hash = "sha256:a6708608965c9e0de5fff13904fed82e0ba21ac929fe4896459226a797e11cd5"}, - {file = "flake8_bugbear-22.10.27-py3-none-any.whl", hash = "sha256:6ad0ab754507319060695e2f2be80e6d8977cfcea082293089a9226276bd825d"}, + {file = "flake8-bugbear-22.12.6.tar.gz", hash = "sha256:4cdb2c06e229971104443ae293e75e64c6107798229202fbe4f4091427a30ac0"}, + {file = "flake8_bugbear-22.12.6-py3-none-any.whl", hash = "sha256:b69a510634f8a9c298dfda2b18a8036455e6b19ecac4fe582e4d7a0abfa50a30"}, ] flake8-comprehensions = [ {file = "flake8-comprehensions-3.10.1.tar.gz", hash = "sha256:412052ac4a947f36b891143430fef4859705af11b2572fbb689f90d372cf26ab"}, {file = "flake8_comprehensions-3.10.1-py3-none-any.whl", hash = "sha256:d763de3c74bc18a79c039a7ec732e0a1985b0c79309ceb51e56401ad0a2cd44e"}, ] furo = [ - {file = "furo-2022.9.29-py3-none-any.whl", hash = "sha256:559ee17999c0f52728481dcf6b1b0cf8c9743e68c5e3a18cb45a7992747869a9"}, - {file = "furo-2022.9.29.tar.gz", hash = "sha256:d4238145629c623609c2deb5384f8d036e2a1ee2a101d64b67b4348112470dbd"}, + {file = "furo-2022.12.7-py3-none-any.whl", hash = "sha256:7cb76c12a25ef65db85ab0743df907573d03027a33631f17d267e598ebb191f7"}, + {file = "furo-2022.12.7.tar.gz", hash = "sha256:d8008f8efbe7587a97ba533c8b2df1f9c21ee9b3e5cad0d27f61193d38b1a986"}, ] gp-libs = [ {file = "gp-libs-0.0.1a17.tar.gz", hash = "sha256:3eaa0bc8587c8d473fbd191fd03dbf08bbdc007db3ae1402102307ca58e50190"}, @@ -1183,8 +1160,8 @@ mccabe = [ {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] mdit-py-plugins = [ - {file = "mdit-py-plugins-0.3.2.tar.gz", hash = "sha256:c37ca25a4a5244b41cc3b34b9d7762a96ee0416dd43efaa837304d592a84995f"}, - {file = "mdit_py_plugins-0.3.2-py3-none-any.whl", hash = "sha256:01e1c0f5432792d79ef627cd1745ce7c240d88d84b4e9dc6e87529a0f3ebba3e"}, + {file = "mdit-py-plugins-0.3.3.tar.gz", hash = "sha256:5cfd7e7ac582a594e23ba6546a2f406e94e42eb33ae596d0734781261c251260"}, + {file = "mdit_py_plugins-0.3.3-py3-none-any.whl", hash = "sha256:36d08a29def19ec43acdcd8ba471d3ebab132e7879d442760d963f19913e04b9"}, ] mdurl = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, @@ -1231,16 +1208,16 @@ myst-parser = [ {file = "myst_parser-0.18.1-py3-none-any.whl", hash = "sha256:61b275b85d9f58aa327f370913ae1bec26ebad372cc99f3ab85c8ec3ee8d9fb8"}, ] packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, + {file = "packaging-22.0-py3-none-any.whl", hash = "sha256:957e2148ba0e1a3b282772e791ef1d8083648bc131c8ab0c1feba110ce1146c3"}, + {file = "packaging-22.0.tar.gz", hash = "sha256:2198ec20bd4c017b8f9717e00f0c8714076fc2fd93816750ab48e2c41de2cfd3"}, ] pathspec = [ - {file = "pathspec-0.10.2-py3-none-any.whl", hash = "sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5"}, - {file = "pathspec-0.10.2.tar.gz", hash = "sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0"}, + {file = "pathspec-0.10.3-py3-none-any.whl", hash = "sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6"}, + {file = "pathspec-0.10.3.tar.gz", hash = "sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6"}, ] platformdirs = [ - {file = "platformdirs-2.5.4-py3-none-any.whl", hash = "sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10"}, - {file = "platformdirs-2.5.4.tar.gz", hash = "sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7"}, + {file = "platformdirs-2.6.0-py3-none-any.whl", hash = "sha256:1a89a12377800c81983db6be069ec068eee989748799b946cce2a6e80dcc54ca"}, + {file = "platformdirs-2.6.0.tar.gz", hash = "sha256:b46ffafa316e6b83b47489d240ce17173f123a9b9c83282141c3daf26ad9ac2e"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, @@ -1262,10 +1239,6 @@ pygments = [ {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, ] -pyparsing = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, -] pytest = [ {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, @@ -1365,8 +1338,8 @@ sphinx-basic-ng = [ {file = "sphinx_basic_ng-1.0.0b1.tar.gz", hash = "sha256:89374bd3ccd9452a301786781e28c8718e99960f2d4f411845ea75fc7bb5a9b0"}, ] sphinx-click = [ - {file = "sphinx-click-4.3.0.tar.gz", hash = "sha256:bd4db5d3c1bec345f07af07b8e28a76cfc5006d997984e38ae246bbf8b9a3b38"}, - {file = "sphinx_click-4.3.0-py3-none-any.whl", hash = "sha256:23e85a3cb0b728a421ea773699f6acadefae171d1a764a51dd8ec5981503ccbe"}, + {file = "sphinx-click-4.4.0.tar.gz", hash = "sha256:cc67692bd28f482c7f01531c61b64e9d2f069bfcf3d24cbbb51d4a84a749fa48"}, + {file = "sphinx_click-4.4.0-py3-none-any.whl", hash = "sha256:2821c10a68fc9ee6ce7c92fad26540d8d8c8f45e6d7258f0e4fb7529ae8fab49"}, ] sphinx-copybutton = [ {file = "sphinx-copybutton-0.5.1.tar.gz", hash = "sha256:366251e28a6f6041514bfb5439425210418d6c750e98d3a695b73e56866a677a"}, From afb218e39196ec53622252effb29f56da51f0a0b Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Dec 2022 13:38:29 -0600 Subject: [PATCH 0183/1073] ci: Add libevent-2.1-7 --- .github/workflows/tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 75aef723d..48ab2d841 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -65,6 +65,7 @@ jobs: - name: Test with pytest continue-on-error: ${{ matrix.tmux-version == 'master' }} run: | + sudo apt install libevent-2.1-7 export PATH=$HOME/tmux-builds/tmux-${{ matrix.tmux-version }}/bin:$PATH ls $HOME/tmux-builds/tmux-${{ matrix.tmux-version }}/bin tmux -V From 896056ee53475c92719ae995344acac7881809d7 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Tue, 11 Jan 2022 07:01:18 -0600 Subject: [PATCH 0184/1073] Custom Version implementation --- src/libtmux/_compat.py | 104 +++++++++++++++++++++++++++++++++++++++++ tests/test_version.py | 43 +++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 tests/test_version.py diff --git a/src/libtmux/_compat.py b/src/libtmux/_compat.py index d7b6bb274..e96b69f0a 100644 --- a/src/libtmux/_compat.py +++ b/src/libtmux/_compat.py @@ -1,4 +1,5 @@ # flake8: NOQA +import functools import sys import types import typing as t @@ -31,3 +32,106 @@ def str_from_console(s: t.Union[str, bytes]) -> str: return str(s) except UnicodeDecodeError: return str(s, encoding="utf_8") if isinstance(s, bytes) else s + + +import re +from typing import Iterator, List, Tuple + +from packaging.version import Version + +### +### Legacy support for LooseVersion / LegacyVersion, e.g. 2.4-openbsd +### https://github.com/pypa/packaging/blob/21.3/packaging/version.py#L106-L115 +### License: BSD, Accessed: Jan 14th, 2022 +### + +LegacyCmpKey = Tuple[int, Tuple[str, ...]] + +_legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE) +_legacy_version_replacement_map = { + "pre": "c", + "preview": "c", + "-": "final-", + "rc": "c", + "dev": "@", +} + + +def _parse_version_parts(s: str) -> Iterator[str]: + for part in _legacy_version_component_re.split(s): + part = _legacy_version_replacement_map.get(part, part) + + if not part or part == ".": + continue + + if part[:1] in "0123456789": + # pad for numeric comparison + yield part.zfill(8) + else: + yield "*" + part + + # ensure that alpha/beta/candidate are before final + yield "*final" + + +def _legacy_cmpkey(version: str) -> LegacyCmpKey: + # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch + # greater than or equal to 0. This will effectively put the LegacyVersion, + # which uses the defacto standard originally implemented by setuptools, + # as before all PEP 440 versions. + epoch = -1 + + # This scheme is taken from pkg_resources.parse_version setuptools prior to + # it's adoption of the packaging library. + parts: List[str] = [] + for part in _parse_version_parts(version.lower()): + if part.startswith("*"): + # remove "-" before a prerelease tag + if part < "*final": + while parts and parts[-1] == "*final-": + parts.pop() + + # remove trailing zeros from each series of numeric parts + while parts and parts[-1] == "00000000": + parts.pop() + + parts.append(part) + + return epoch, tuple(parts) + + +@functools.total_ordering +class LegacyVersion: + _key: LegacyCmpKey + + def __hash__(self) -> int: + return hash(self._key) + + def __init__(self, version: object) -> None: + self._version = str(version) + self._key = _legacy_cmpkey(self._version) + + def __str__(self) -> str: + return self._version + + def __lt__(self, other: object) -> bool: + if isinstance(other, str): + other = LegacyVersion(other) + if not isinstance(other, LegacyVersion): + return NotImplemented + + return self._key < other._key + + def __eq__(self, other: object) -> bool: + if isinstance(other, str): + other = LegacyVersion(other) + if not isinstance(other, LegacyVersion): + return NotImplemented + + return self._key == other._key + + def __repr__(self) -> str: + return "".format(repr(str(self))) + + +LooseVersion = LegacyVersion diff --git a/tests/test_version.py b/tests/test_version.py new file mode 100644 index 000000000..8250d019e --- /dev/null +++ b/tests/test_version.py @@ -0,0 +1,43 @@ +import operator +from contextlib import nullcontext as does_not_raise + +import pytest + +from libtmux._compat import LooseVersion + + +@pytest.mark.parametrize( + "version", + [ + "1", + "1.0", + "1.0.0", + "1.0.0b", + "1.0.0b1", + "1.0.0b-openbsd", + "1.0.0-next", + "1.0.0-next.1", + ], +) +def test_version(version): + assert LooseVersion(version) + + +@pytest.mark.parametrize( + "version,op,versionb,raises", + [ + ["1", operator.eq, "1", False], + ["1", operator.eq, "1.0", False], + ["1", operator.eq, "1.0.0", False], + ["1", operator.gt, "1.0.0a", False], + ["1", operator.gt, "1.0.0b", False], + ["1", operator.lt, "1.0.0p1", False], + ["1", operator.lt, "1.0.0-openbsd", False], + ["1", operator.lt, "1", AssertionError], + ["1", operator.lt, "1", AssertionError], + ], +) +def test_version_compare(version, op, versionb, raises): + raises_ctx = pytest.raises(raises) if raises else does_not_raise() + with raises_ctx: + assert op(LooseVersion(version), LooseVersion(versionb)) From ac1f16a7f9f548c58e428035678c9c7ace6f02be Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Dec 2022 08:48:37 -0600 Subject: [PATCH 0185/1073] test(common): Use LooseVersion from compat --- tests/test_common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_common.py b/tests/test_common.py index d09d21e84..da9bcdeea 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -3,12 +3,12 @@ import re import sys import typing as t -from distutils.version import LooseVersion from typing import Optional import pytest import libtmux +from libtmux._compat import LooseVersion from libtmux.common import ( TMUX_MAX_VERSION, TMUX_MIN_VERSION, From 7864b10f6981bcaaae8cc285adf08ccf633acd3c Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Dec 2022 10:56:25 -0600 Subject: [PATCH 0186/1073] chore(test_version): Updates for mypy --- tests/test_version.py | 55 ++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/tests/test_version.py b/tests/test_version.py index 8250d019e..dc4af269d 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -1,10 +1,20 @@ import operator +import typing as t from contextlib import nullcontext as does_not_raise import pytest from libtmux._compat import LooseVersion +if t.TYPE_CHECKING: + from _pytest.python_api import RaisesContext + from typing_extensions import TypeAlias + + VersionCompareOp: TypeAlias = t.Callable[ + [t.Any, t.Any], + bool, + ] + @pytest.mark.parametrize( "version", @@ -19,25 +29,42 @@ "1.0.0-next.1", ], ) -def test_version(version): +def test_version(version: str) -> None: assert LooseVersion(version) +class VersionCompareFixture(t.NamedTuple): + a: object + op: "VersionCompareOp" + b: object + raises: t.Union[t.Type[Exception], bool] + + @pytest.mark.parametrize( - "version,op,versionb,raises", + VersionCompareFixture._fields, [ - ["1", operator.eq, "1", False], - ["1", operator.eq, "1.0", False], - ["1", operator.eq, "1.0.0", False], - ["1", operator.gt, "1.0.0a", False], - ["1", operator.gt, "1.0.0b", False], - ["1", operator.lt, "1.0.0p1", False], - ["1", operator.lt, "1.0.0-openbsd", False], - ["1", operator.lt, "1", AssertionError], - ["1", operator.lt, "1", AssertionError], + VersionCompareFixture(a="1", op=operator.eq, b="1", raises=False), + VersionCompareFixture(a="1", op=operator.eq, b="1.0", raises=False), + VersionCompareFixture(a="1", op=operator.eq, b="1.0.0", raises=False), + VersionCompareFixture(a="1", op=operator.gt, b="1.0.0a", raises=False), + VersionCompareFixture(a="1", op=operator.gt, b="1.0.0b", raises=False), + VersionCompareFixture(a="1", op=operator.lt, b="1.0.0p1", raises=False), + VersionCompareFixture(a="1", op=operator.lt, b="1.0.0-openbsd", raises=False), + VersionCompareFixture(a="1", op=operator.lt, b="1", raises=AssertionError), + VersionCompareFixture(a="1", op=operator.lt, b="1", raises=AssertionError), + VersionCompareFixture(a="1.0.0c", op=operator.gt, b="1.0.0b", raises=False), ], ) -def test_version_compare(version, op, versionb, raises): - raises_ctx = pytest.raises(raises) if raises else does_not_raise() +def test_version_compare( + a: str, + op: "VersionCompareOp", + b: str, + raises: t.Union[t.Type[Exception], bool], +) -> None: + raises_ctx: "RaisesContext[Exception]" = ( + pytest.raises(t.cast(t.Type[Exception], raises)) + if raises + else t.cast("RaisesContext[Exception]", does_not_raise()) + ) with raises_ctx: - assert op(LooseVersion(version), LooseVersion(versionb)) + assert op(LooseVersion(a), LooseVersion(b)) From 887086e0ee7515057e13b6e649fc5448469d58c1 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Dec 2022 13:26:51 -0600 Subject: [PATCH 0187/1073] chore(common): Use compat LooseVersion --- src/libtmux/common.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libtmux/common.py b/src/libtmux/common.py index 430053963..eda8ea5aa 100644 --- a/src/libtmux/common.py +++ b/src/libtmux/common.py @@ -11,11 +11,10 @@ import subprocess import sys import typing as t -from distutils.version import LooseVersion from typing import Dict, Generic, KeysView, List, Optional, TypeVar, Union, overload from . import exc -from ._compat import console_to_str, str_from_console +from ._compat import LooseVersion, console_to_str, str_from_console if t.TYPE_CHECKING: from typing_extensions import Literal From 094e624538c63b7af919e6aa75815c1abf006866 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Dec 2022 14:00:53 -0600 Subject: [PATCH 0188/1073] ci: Remove pytest filterwarnings --- setup.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 0620db0c5..882dc98ee 100644 --- a/setup.cfg +++ b/setup.cfg @@ -18,7 +18,6 @@ line_length = 88 [tool:pytest] filterwarnings = - ignore:.* Use packaging.version.*:DeprecationWarning:: ignore:The frontend.Option(Parser)? class.*:DeprecationWarning:: addopts = --tb=short --no-header --showlocals --doctest-docutils-modules --reruns 2 -p no:doctest doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE From 68443d6ac54f274a24ab19d190afba4674441d21 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Dec 2022 14:19:06 -0600 Subject: [PATCH 0189/1073] docs(CHANGES): Note update --- CHANGES | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/CHANGES b/CHANGES index df5f059fb..e83a9565f 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,27 @@ $ pip install --user --upgrade --pre libtmux +### Breaking changes + +- Fix `distutils` warning, vendorize `LegacyVersion` (#351) + + Removal of reliancy on `distutils.version.LooseVersion`, which does not + support `tmux(1)` versions like `3.1a`. + + Fixes warning: + + > DeprecationWarning: distutils Version classes are deprecated. Use + > packaging.version instead. + + The temporary workaround, before 0.16.0 (assuming _setup.cfg_): + + ```ini + [tool:pytest] + filterwarnings = + ignore:.* Use packaging.version.*:DeprecationWarning:: + ignore:The frontend.Option(Parser)? class.*:DeprecationWarning:: + ``` + ### Features - `Window.split_window()` and `Session.new_window()` now support an optional From f37eab41b6b13f355c77d77a6c07bbfaf70478f9 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Dec 2022 14:52:16 -0600 Subject: [PATCH 0190/1073] release: Tag v0.16.0a1 --- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 48f0dcec0..71d8307b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.16.0a0" +version = "0.16.0a1" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index af64115fd..d0224dc1c 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.16.a0" +__version__ = "0.16.0a1" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From 4399af397dafc4f988b782d6fc9590c1839cb712 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sat, 10 Dec 2022 15:20:24 -0600 Subject: [PATCH 0191/1073] release: Tag v0.16.0 --- CHANGES | 4 +++- pyproject.toml | 2 +- src/libtmux/__about__.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index e83a9565f..ba94c552d 100644 --- a/CHANGES +++ b/CHANGES @@ -8,12 +8,14 @@ To install the unreleased libtmux version, see [developmental releases](https:// $ pip install --user --upgrade --pre libtmux ``` -## libtmux 0.16.x (unreleased) +## libtmux 0.17.x (unreleased) - _Notes on upcoming releases will be added here_ +## libtmux 0.16.0 (2022-12-10) + ### Breaking changes - Fix `distutils` warning, vendorize `LegacyVersion` (#351) diff --git a/pyproject.toml b/pyproject.toml index 71d8307b5..7ab525496 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "libtmux" -version = "0.16.0a1" +version = "0.16.0" description = "Typed scripting library / ORM / API wrapper for tmux" license = "MIT" authors = ["Tony Narlock "] diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py index d0224dc1c..3d05a1c85 100644 --- a/src/libtmux/__about__.py +++ b/src/libtmux/__about__.py @@ -1,6 +1,6 @@ __title__ = "libtmux" __package_name__ = "libtmux" -__version__ = "0.16.0a1" +__version__ = "0.16.0" __description__ = "Typed scripting library / ORM / API wrapper for tmux" __email__ = "tony@git-pull.com" __author__ = "Tony Narlock" From 3a9dff8e7ec7fea52ee11a3963f5b7a76d694500 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 11 Dec 2022 10:11:15 -0600 Subject: [PATCH 0192/1073] build(deps): Remove unused sphinx-click dev dependency --- CHANGES | 4 ++++ docs/conf.py | 1 - poetry.lock | 19 +------------------ pyproject.toml | 1 - 4 files changed, 5 insertions(+), 20 deletions(-) diff --git a/CHANGES b/CHANGES index ba94c552d..31e01a96d 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,10 @@ $ pip install --user --upgrade --pre libtmux +### Internal + +- Remove unused `sphinx-click` development dependency + ## libtmux 0.16.0 (2022-12-10) ### Breaking changes diff --git a/docs/conf.py b/docs/conf.py index eb2e11caa..11b4d7e04 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -28,7 +28,6 @@ "sphinx.ext.todo", "sphinx.ext.linkcode", "sphinx.ext.napoleon", - "sphinx_click.ext", # sphinx-click "sphinx_inline_tabs", "sphinx_copybutton", "sphinxext.opengraph", diff --git a/poetry.lock b/poetry.lock index 32ad02b97..7b05c41a0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -731,19 +731,6 @@ sphinx = ">=4.0" [package.extras] docs = ["furo", "ipython", "myst-parser", "sphinx-copybutton", "sphinx-inline-tabs"] -[[package]] -name = "sphinx-click" -version = "4.4.0" -description = "Sphinx extension that automatically documents click applications" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -click = ">=7.0" -docutils = "*" -sphinx = ">=2.0" - [[package]] name = "sphinx-copybutton" version = "0.5.1" @@ -945,7 +932,7 @@ test = [] [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "6a05ee2efdef9d79f3c1f8283f8c6ada1be53819a998d129fb15e69477019cca" +content-hash = "d25dba0a8150565015a5e747f3d73d87cbf45d73170cfc44252a3cc048ae91cb" [metadata.files] alabaster = [ @@ -1337,10 +1324,6 @@ sphinx-basic-ng = [ {file = "sphinx_basic_ng-1.0.0b1-py3-none-any.whl", hash = "sha256:ade597a3029c7865b24ad0eda88318766bcc2f9f4cef60df7e28126fde94db2a"}, {file = "sphinx_basic_ng-1.0.0b1.tar.gz", hash = "sha256:89374bd3ccd9452a301786781e28c8718e99960f2d4f411845ea75fc7bb5a9b0"}, ] -sphinx-click = [ - {file = "sphinx-click-4.4.0.tar.gz", hash = "sha256:cc67692bd28f482c7f01531c61b64e9d2f069bfcf3d24cbbb51d4a84a749fa48"}, - {file = "sphinx_click-4.4.0-py3-none-any.whl", hash = "sha256:2821c10a68fc9ee6ce7c92fad26540d8d8c8f45e6d7258f0e4fb7529ae8fab49"}, -] sphinx-copybutton = [ {file = "sphinx-copybutton-0.5.1.tar.gz", hash = "sha256:366251e28a6f6041514bfb5439425210418d6c750e98d3a695b73e56866a677a"}, {file = "sphinx_copybutton-0.5.1-py3-none-any.whl", hash = "sha256:0842851b5955087a7ec7fc870b622cb168618ad408dee42692e9a5c97d071da8"}, diff --git a/pyproject.toml b/pyproject.toml index 7ab525496..cf57835fa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,6 @@ furo = "*" gp-libs = "~0.0.1a17" sphinx-autobuild = "*" sphinx-autodoc-typehints = "*" -sphinx-click = "*" sphinx-inline-tabs = { version = "*", python = "^3.7" } sphinxext-opengraph = "*" sphinx-copybutton = "*" From 5be6a1fb7b5b85ee9b85722df56ae367ab425b80 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Mon, 12 Dec 2022 07:45:02 -0600 Subject: [PATCH 0193/1073] build: Vendorize packaging.version @ 22.0 See also: - https://github.com/pypa/packaging/blob/22.0/packaging/version.py - https://github.com/pypa/packaging/blob/22.0/packaging/_structures.py --- src/libtmux/_vendor/__init__.py | 0 src/libtmux/_vendor/_structures.py | 62 ++++ src/libtmux/_vendor/version.py | 564 +++++++++++++++++++++++++++++ 3 files changed, 626 insertions(+) create mode 100644 src/libtmux/_vendor/__init__.py create mode 100644 src/libtmux/_vendor/_structures.py create mode 100644 src/libtmux/_vendor/version.py diff --git a/src/libtmux/_vendor/__init__.py b/src/libtmux/_vendor/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/libtmux/_vendor/_structures.py b/src/libtmux/_vendor/_structures.py new file mode 100644 index 000000000..25c1775d8 --- /dev/null +++ b/src/libtmux/_vendor/_structures.py @@ -0,0 +1,62 @@ +# via https://github.com/pypa/packaging/blob/22.0/packaging/_structures.py +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +class InfinityType: + def __repr__(self) -> str: + return "Infinity" + + def __hash__(self) -> int: + return hash(repr(self)) + + def __lt__(self, other: object) -> bool: + return False + + def __le__(self, other: object) -> bool: + return False + + def __eq__(self, other: object) -> bool: + return isinstance(other, self.__class__) + + def __gt__(self, other: object) -> bool: + return True + + def __ge__(self, other: object) -> bool: + return True + + def __neg__(self: object) -> "NegativeInfinityType": + return NegativeInfinity + + +Infinity = InfinityType() + + +class NegativeInfinityType: + def __repr__(self) -> str: + return "-Infinity" + + def __hash__(self) -> int: + return hash(repr(self)) + + def __lt__(self, other: object) -> bool: + return True + + def __le__(self, other: object) -> bool: + return True + + def __eq__(self, other: object) -> bool: + return isinstance(other, self.__class__) + + def __gt__(self, other: object) -> bool: + return False + + def __ge__(self, other: object) -> bool: + return False + + def __neg__(self: object) -> InfinityType: + return Infinity + + +NegativeInfinity = NegativeInfinityType() diff --git a/src/libtmux/_vendor/version.py b/src/libtmux/_vendor/version.py new file mode 100644 index 000000000..a2e5d31b9 --- /dev/null +++ b/src/libtmux/_vendor/version.py @@ -0,0 +1,564 @@ +# via https://github.com/pypa/packaging/blob/22.0/packaging/version.py +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +""" +.. testsetup:: + + from packaging.version import parse, Version +""" + +import collections +import itertools +import re +from typing import Callable, Optional, SupportsInt, Tuple, Union + +from ._structures import Infinity, InfinityType, NegativeInfinity, NegativeInfinityType + +__all__ = ["VERSION_PATTERN", "parse", "Version", "InvalidVersion"] + +InfiniteTypes = Union[InfinityType, NegativeInfinityType] +PrePostDevType = Union[InfiniteTypes, Tuple[str, int]] +SubLocalType = Union[InfiniteTypes, int, str] +LocalType = Union[ + NegativeInfinityType, + Tuple[ + Union[ + SubLocalType, + Tuple[SubLocalType, str], + Tuple[NegativeInfinityType, SubLocalType], + ], + ..., + ], +] +CmpKey = Tuple[ + int, Tuple[int, ...], PrePostDevType, PrePostDevType, PrePostDevType, LocalType +] +VersionComparisonMethod = Callable[[CmpKey, CmpKey], bool] + +_Version = collections.namedtuple( + "_Version", ["epoch", "release", "dev", "pre", "post", "local"] +) + + +def parse(version: str) -> "Version": + """Parse the given version string. + + >>> parse('1.0.dev1') + + + :param version: The version string to parse. + :raises InvalidVersion: When the version string is not a valid version. + """ + return Version(version) + + +class InvalidVersion(ValueError): + """Raised when a version string is not a valid version. + + >>> Version("invalid") + Traceback (most recent call last): + ... + libtmux._vendor.version.InvalidVersion: Invalid version: 'invalid' + """ + + +class _BaseVersion: + _key: CmpKey + + def __hash__(self) -> int: + return hash(self._key) + + # Please keep the duplicated `isinstance` check + # in the six comparisons hereunder + # unless you find a way to avoid adding overhead function calls. + def __lt__(self, other: "_BaseVersion") -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key < other._key + + def __le__(self, other: "_BaseVersion") -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key <= other._key + + def __eq__(self, other: object) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key == other._key + + def __ge__(self, other: "_BaseVersion") -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key >= other._key + + def __gt__(self, other: "_BaseVersion") -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key > other._key + + def __ne__(self, other: object) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key != other._key + + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse +_VERSION_PATTERN = r""" + v? + (?: + (?:(?P[0-9]+)!)? # epoch + (?P[0-9]+(?:\.[0-9]+)*) # release segment + (?P
                                          # pre-release
+            [-_\.]?
+            (?P(a|b|c|rc|alpha|beta|pre|preview))
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+        (?P                                         # post release
+            (?:-(?P[0-9]+))
+            |
+            (?:
+                [-_\.]?
+                (?Ppost|rev|r)
+                [-_\.]?
+                (?P[0-9]+)?
+            )
+        )?
+        (?P                                          # dev release
+            [-_\.]?
+            (?Pdev)
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+    )
+    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
+"""
+
+VERSION_PATTERN = _VERSION_PATTERN
+"""
+A string containing the regular expression used to match a valid version.
+
+The pattern is not anchored at either end, and is intended for embedding in larger
+expressions (for example, matching a version number as part of a file name). The
+regular expression should be compiled with the ``re.VERBOSE`` and ``re.IGNORECASE``
+flags set.
+
+:meta hide-value:
+"""
+
+
+class Version(_BaseVersion):
+    """This class abstracts handling of a project's versions.
+
+    A :class:`Version` instance is comparison aware and can be compared and
+    sorted using the standard Python interfaces.
+
+    >>> v1 = Version("1.0a5")
+    >>> v2 = Version("1.0")
+    >>> v1
+    
+    >>> v2
+    
+    >>> v1 < v2
+    True
+    >>> v1 == v2
+    False
+    >>> v1 > v2
+    False
+    >>> v1 >= v2
+    False
+    >>> v1 <= v2
+    True
+    """
+
+    _regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
+
+    def __init__(self, version: str) -> None:
+        """Initialize a Version object.
+
+        :param version:
+            The string representation of a version which will be parsed and normalized
+            before use.
+        :raises InvalidVersion:
+            If the ``version`` does not conform to PEP 440 in any way then this
+            exception will be raised.
+        """
+
+        # Validate the version and parse it into pieces
+        match = self._regex.search(version)
+        if not match:
+            raise InvalidVersion(f"Invalid version: '{version}'")
+
+        # Store the parsed out pieces of the version
+        self._version = _Version(
+            epoch=int(match.group("epoch")) if match.group("epoch") else 0,
+            release=tuple(int(i) for i in match.group("release").split(".")),
+            pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
+            post=_parse_letter_version(
+                match.group("post_l"), match.group("post_n1") or match.group("post_n2")
+            ),
+            dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
+            local=_parse_local_version(match.group("local")),
+        )
+
+        # Generate a key which will be used for sorting
+        self._key = _cmpkey(
+            self._version.epoch,
+            self._version.release,
+            self._version.pre,
+            self._version.post,
+            self._version.dev,
+            self._version.local,
+        )
+
+    def __repr__(self) -> str:
+        """A representation of the Version that shows all internal state.
+
+        >>> Version('1.0.0')
+        
+        """
+        return f""
+
+    def __str__(self) -> str:
+        """A string representation of the version that can be rounded-tripped.
+
+        >>> str(Version("1.0a5"))
+        '1.0a5'
+        """
+        parts = []
+
+        # Epoch
+        if self.epoch != 0:
+            parts.append(f"{self.epoch}!")
+
+        # Release segment
+        parts.append(".".join(str(x) for x in self.release))
+
+        # Pre-release
+        if self.pre is not None:
+            parts.append("".join(str(x) for x in self.pre))
+
+        # Post-release
+        if self.post is not None:
+            parts.append(f".post{self.post}")
+
+        # Development release
+        if self.dev is not None:
+            parts.append(f".dev{self.dev}")
+
+        # Local version segment
+        if self.local is not None:
+            parts.append(f"+{self.local}")
+
+        return "".join(parts)
+
+    @property
+    def epoch(self) -> int:
+        """The epoch of the version.
+
+        >>> Version("2.0.0").epoch
+        0
+        >>> Version("1!2.0.0").epoch
+        1
+        """
+        _epoch: int = self._version.epoch
+        return _epoch
+
+    @property
+    def release(self) -> Tuple[int, ...]:
+        """The components of the "release" segment of the version.
+
+        >>> Version("1.2.3").release
+        (1, 2, 3)
+        >>> Version("2.0.0").release
+        (2, 0, 0)
+        >>> Version("1!2.0.0.post0").release
+        (2, 0, 0)
+
+        Includes trailing zeroes but not the epoch or any pre-release / development /
+        post-release suffixes.
+        """
+        _release: Tuple[int, ...] = self._version.release
+        return _release
+
+    @property
+    def pre(self) -> Optional[Tuple[str, int]]:
+        """The pre-release segment of the version.
+
+        >>> print(Version("1.2.3").pre)
+        None
+        >>> Version("1.2.3a1").pre
+        ('a', 1)
+        >>> Version("1.2.3b1").pre
+        ('b', 1)
+        >>> Version("1.2.3rc1").pre
+        ('rc', 1)
+        """
+        _pre: Optional[Tuple[str, int]] = self._version.pre
+        return _pre
+
+    @property
+    def post(self) -> Optional[int]:
+        """The post-release number of the version.
+
+        >>> print(Version("1.2.3").post)
+        None
+        >>> Version("1.2.3.post1").post
+        1
+        """
+        return self._version.post[1] if self._version.post else None
+
+    @property
+    def dev(self) -> Optional[int]:
+        """The development number of the version.
+
+        >>> print(Version("1.2.3").dev)
+        None
+        >>> Version("1.2.3.dev1").dev
+        1
+        """
+        return self._version.dev[1] if self._version.dev else None
+
+    @property
+    def local(self) -> Optional[str]:
+        """The local version segment of the version.
+
+        >>> print(Version("1.2.3").local)
+        None
+        >>> Version("1.2.3+abc").local
+        'abc'
+        """
+        if self._version.local:
+            return ".".join(str(x) for x in self._version.local)
+        else:
+            return None
+
+    @property
+    def public(self) -> str:
+        """The public portion of the version.
+
+        >>> Version("1.2.3").public
+        '1.2.3'
+        >>> Version("1.2.3+abc").public
+        '1.2.3'
+        >>> Version("1.2.3+abc.dev1").public
+        '1.2.3'
+        """
+        return str(self).split("+", 1)[0]
+
+    @property
+    def base_version(self) -> str:
+        """The "base version" of the version.
+
+        >>> Version("1.2.3").base_version
+        '1.2.3'
+        >>> Version("1.2.3+abc").base_version
+        '1.2.3'
+        >>> Version("1!1.2.3+abc.dev1").base_version
+        '1!1.2.3'
+
+        The "base version" is the public version of the project without any pre or post
+        release markers.
+        """
+        parts = []
+
+        # Epoch
+        if self.epoch != 0:
+            parts.append(f"{self.epoch}!")
+
+        # Release segment
+        parts.append(".".join(str(x) for x in self.release))
+
+        return "".join(parts)
+
+    @property
+    def is_prerelease(self) -> bool:
+        """Whether this version is a pre-release.
+
+        >>> Version("1.2.3").is_prerelease
+        False
+        >>> Version("1.2.3a1").is_prerelease
+        True
+        >>> Version("1.2.3b1").is_prerelease
+        True
+        >>> Version("1.2.3rc1").is_prerelease
+        True
+        >>> Version("1.2.3dev1").is_prerelease
+        True
+        """
+        return self.dev is not None or self.pre is not None
+
+    @property
+    def is_postrelease(self) -> bool:
+        """Whether this version is a post-release.
+
+        >>> Version("1.2.3").is_postrelease
+        False
+        >>> Version("1.2.3.post1").is_postrelease
+        True
+        """
+        return self.post is not None
+
+    @property
+    def is_devrelease(self) -> bool:
+        """Whether this version is a development release.
+
+        >>> Version("1.2.3").is_devrelease
+        False
+        >>> Version("1.2.3.dev1").is_devrelease
+        True
+        """
+        return self.dev is not None
+
+    @property
+    def major(self) -> int:
+        """The first item of :attr:`release` or ``0`` if unavailable.
+
+        >>> Version("1.2.3").major
+        1
+        """
+        return self.release[0] if len(self.release) >= 1 else 0
+
+    @property
+    def minor(self) -> int:
+        """The second item of :attr:`release` or ``0`` if unavailable.
+
+        >>> Version("1.2.3").minor
+        2
+        >>> Version("1").minor
+        0
+        """
+        return self.release[1] if len(self.release) >= 2 else 0
+
+    @property
+    def micro(self) -> int:
+        """The third item of :attr:`release` or ``0`` if unavailable.
+
+        >>> Version("1.2.3").micro
+        3
+        >>> Version("1").micro
+        0
+        """
+        return self.release[2] if len(self.release) >= 3 else 0
+
+
+def _parse_letter_version(
+    letter: str, number: Union[str, bytes, SupportsInt]
+) -> Optional[Tuple[str, int]]:
+
+    if letter:
+        # We consider there to be an implicit 0 in a pre-release if there is
+        # not a numeral associated with it.
+        if number is None:
+            number = 0
+
+        # We normalize any letters to their lower case form
+        letter = letter.lower()
+
+        # We consider some words to be alternate spellings of other words and
+        # in those cases we want to normalize the spellings to our preferred
+        # spelling.
+        if letter == "alpha":
+            letter = "a"
+        elif letter == "beta":
+            letter = "b"
+        elif letter in ["c", "pre", "preview"]:
+            letter = "rc"
+        elif letter in ["rev", "r"]:
+            letter = "post"
+
+        return letter, int(number)
+    if not letter and number:
+        # We assume if we are given a number, but we are not given a letter
+        # then this is using the implicit post release syntax (e.g. 1.0-1)
+        letter = "post"
+
+        return letter, int(number)
+
+    return None
+
+
+_local_version_separators = re.compile(r"[\._-]")
+
+
+def _parse_local_version(local: str) -> Optional[LocalType]:
+    """
+    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
+    """
+    if local is not None:
+        return tuple(
+            part.lower() if not part.isdigit() else int(part)
+            for part in _local_version_separators.split(local)
+        )
+    return None
+
+
+def _cmpkey(
+    epoch: int,
+    release: Tuple[int, ...],
+    pre: Optional[Tuple[str, int]],
+    post: Optional[Tuple[str, int]],
+    dev: Optional[Tuple[str, int]],
+    local: Optional[Tuple[SubLocalType]],
+) -> CmpKey:
+
+    # When we compare a release version, we want to compare it with all of the
+    # trailing zeros removed. So we'll use a reverse the list, drop all the now
+    # leading zeros until we come to something non zero, then take the rest
+    # re-reverse it back into the correct order and make it a tuple and use
+    # that for our sorting key.
+    _release = tuple(
+        reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
+    )
+
+    # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
+    # We'll do this by abusing the pre segment, but we _only_ want to do this
+    # if there is not a pre or a post segment. If we have one of those then
+    # the normal sorting rules will handle this case correctly.
+    if pre is None and post is None and dev is not None:
+        _pre: PrePostDevType = NegativeInfinity
+    # Versions without a pre-release (except as noted above) should sort after
+    # those with one.
+    elif pre is None:
+        _pre = Infinity
+    else:
+        _pre = pre
+
+    # Versions without a post segment should sort before those with one.
+    if post is None:
+        _post: PrePostDevType = NegativeInfinity
+
+    else:
+        _post = post
+
+    # Versions without a development segment should sort after those with one.
+    if dev is None:
+        _dev: PrePostDevType = Infinity
+
+    else:
+        _dev = dev
+
+    if local is None:
+        # Versions without a local segment should sort before those with one.
+        _local: LocalType = NegativeInfinity
+    else:
+        # Versions with a local segment need that segment parsed to implement
+        # the sorting rules in PEP440.
+        # - Alpha numeric segments sort before numeric segments
+        # - Alpha numeric segments sort lexicographically
+        # - Numeric segments sort numerically
+        # - Shorter versions sort before longer versions when the prefixes
+        #   match exactly
+        _local = tuple(
+            (i, "") if isinstance(i, int) else (NegativeInfinity, i) for i in local
+        )
+
+    return epoch, _release, _pre, _post, _dev, _local

From 3c229523476ff4478579f882be5b707b4f4922eb Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Mon, 12 Dec 2022 07:46:08 -0600
Subject: [PATCH 0194/1073] fix(version): Fix compat

---
 src/libtmux/_compat.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libtmux/_compat.py b/src/libtmux/_compat.py
index e96b69f0a..517b57c86 100644
--- a/src/libtmux/_compat.py
+++ b/src/libtmux/_compat.py
@@ -37,7 +37,7 @@ def str_from_console(s: t.Union[str, bytes]) -> str:
 import re
 from typing import Iterator, List, Tuple
 
-from packaging.version import Version
+from libtmux._vendor.version import Version
 
 ###
 ### Legacy support for LooseVersion / LegacyVersion, e.g. 2.4-openbsd

From 55f85f4d9ad58b696b8a706a5fdabc73bfe09d2b Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Mon, 12 Dec 2022 07:49:45 -0600
Subject: [PATCH 0195/1073] docs(CHANGES): Note update for Version

---
 CHANGES | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/CHANGES b/CHANGES
index 31e01a96d..e7d822880 100644
--- a/CHANGES
+++ b/CHANGES
@@ -18,6 +18,14 @@ $ pip install --user --upgrade --pre libtmux
 
 - Remove unused `sphinx-click` development dependency
 
+## libtmux 0.16.1 (2022-12-12)
+
+### Fixes
+
+- Remove reliance on `packaging.version.Version` (#461)
+
+  This is too critical of a package to pin a dependency as it may interfere with other packages the user relies on. In addition, libtmux doesn't need strict compatibility with `packaging`.
+
 ## libtmux 0.16.0 (2022-12-10)
 
 ### Breaking changes

From 7985c6ab77a00b401f8b5c3925efde0db1128736 Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Mon, 12 Dec 2022 07:52:27 -0600
Subject: [PATCH 0196/1073] Tag 0.16.1 (fixes packaging.version.Version
 dependency via #461)

---
 pyproject.toml           | 2 +-
 src/libtmux/__about__.py | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/pyproject.toml b/pyproject.toml
index cf57835fa..6d2950c4f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "libtmux"
-version = "0.16.0"
+version = "0.16.1"
 description = "Typed scripting library / ORM / API wrapper for tmux"
 license = "MIT"
 authors = ["Tony Narlock "]
diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py
index 3d05a1c85..b962f8a23 100644
--- a/src/libtmux/__about__.py
+++ b/src/libtmux/__about__.py
@@ -1,6 +1,6 @@
 __title__ = "libtmux"
 __package_name__ = "libtmux"
-__version__ = "0.16.0"
+__version__ = "0.16.1"
 __description__ = "Typed scripting library / ORM / API wrapper for tmux"
 __email__ = "tony@git-pull.com"
 __author__ = "Tony Narlock"

From 684082c8dc5c7a52c6ee9eb79b60e76d08cfb4fa Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Fri, 16 Dec 2022 17:45:30 -0600
Subject: [PATCH 0197/1073] build(deps): Bump isort and pytest-watcher

---
 poetry.lock | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/poetry.lock b/poetry.lock
index 7b05c41a0..14bc64742 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -276,11 +276,11 @@ python-versions = "*"
 
 [[package]]
 name = "isort"
-version = "5.10.1"
+version = "5.11.2"
 description = "A Python utility / library to sort Python imports."
 category = "dev"
 optional = false
-python-versions = ">=3.6.1,<4.0"
+python-versions = ">=3.7.0"
 
 [package.extras]
 colors = ["colorama (>=0.4.3,<0.5.0)"]
@@ -586,11 +586,11 @@ pytest = ">=5.3"
 
 [[package]]
 name = "pytest-watcher"
-version = "0.2.5"
+version = "0.2.6"
 description = "Continiously runs pytest on changes in *.py files"
 category = "dev"
 optional = false
-python-versions = ">=3.6.2,<4.0.0"
+python-versions = ">=3.7.0,<4.0.0"
 
 [package.dependencies]
 watchdog = ">=2.0.0"
@@ -1084,8 +1084,8 @@ iniconfig = [
     {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
 ]
 isort = [
-    {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"},
-    {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"},
+    {file = "isort-5.11.2-py3-none-any.whl", hash = "sha256:e486966fba83f25b8045f8dd7455b0a0d1e4de481e1d7ce4669902d9fb85e622"},
+    {file = "isort-5.11.2.tar.gz", hash = "sha256:dd8bbc5c0990f2a095d754e50360915f73b4c26fc82733eb5bfc6b48396af4d2"},
 ]
 jinja2 = [
     {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
@@ -1243,8 +1243,8 @@ pytest-rerunfailures = [
     {file = "pytest_rerunfailures-10.3-py3-none-any.whl", hash = "sha256:6be6f96510bf94b54198bf15bc5568fe2cdff88e83875912e22d29810acf65ff"},
 ]
 pytest-watcher = [
-    {file = "pytest-watcher-0.2.5.tar.gz", hash = "sha256:0a220d18b778fbae4d876f8d7d2eb86e63d7d8257cd6b05f42c13aa6625c0b6f"},
-    {file = "pytest_watcher-0.2.5-py3-none-any.whl", hash = "sha256:7a15b3c7c6babefdee51da2d62851f109e2d2d65c64f72da04f97f0a9569ab74"},
+    {file = "pytest-watcher-0.2.6.tar.gz", hash = "sha256:351dfb3477366030ff275bfbfc9f29bee35cd07f16a3355b38bf92766886bae4"},
+    {file = "pytest_watcher-0.2.6-py3-none-any.whl", hash = "sha256:0a507159d051c9461790363e0f9b2827c1d82ad2ae8966319598695e485b1dd5"},
 ]
 pytz = [
     {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"},

From cc88acb6288c0aa4c9686f850d7709cf3b2b5c2d Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Sat, 17 Dec 2022 09:31:13 -0600
Subject: [PATCH 0198/1073] build(deps): Bump isort

---
 poetry.lock | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/poetry.lock b/poetry.lock
index 14bc64742..ea36f810c 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -276,7 +276,7 @@ python-versions = "*"
 
 [[package]]
 name = "isort"
-version = "5.11.2"
+version = "5.11.3"
 description = "A Python utility / library to sort Python imports."
 category = "dev"
 optional = false
@@ -1084,8 +1084,8 @@ iniconfig = [
     {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
 ]
 isort = [
-    {file = "isort-5.11.2-py3-none-any.whl", hash = "sha256:e486966fba83f25b8045f8dd7455b0a0d1e4de481e1d7ce4669902d9fb85e622"},
-    {file = "isort-5.11.2.tar.gz", hash = "sha256:dd8bbc5c0990f2a095d754e50360915f73b4c26fc82733eb5bfc6b48396af4d2"},
+    {file = "isort-5.11.3-py3-none-any.whl", hash = "sha256:83155ffa936239d986b0f190347a3f2285f42a9b9e1725c89d865b27dd0627e5"},
+    {file = "isort-5.11.3.tar.gz", hash = "sha256:a8ca25fbfad0f7d5d8447a4314837298d9f6b23aed8618584c894574f626b64b"},
 ]
 jinja2 = [
     {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},

From 268752ad65243cc0cf0683d99b8527285fc8e78c Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Sat, 17 Dec 2022 18:11:58 -0600
Subject: [PATCH 0199/1073] Logging statements: Use f-strings

---
 src/libtmux/common.py        | 6 +++++-
 src/libtmux/pytest_plugin.py | 2 +-
 src/libtmux/server.py        | 4 ++--
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/libtmux/common.py b/src/libtmux/common.py
index eda8ea5aa..88029b30c 100644
--- a/src/libtmux/common.py
+++ b/src/libtmux/common.py
@@ -267,7 +267,11 @@ def __init__(self, *args: t.Any, **kwargs: t.Any) -> None:
         else:
             self.stdout = stdout_split
 
-        logger.debug("self.stdout for {}: \n{}".format(" ".join(cmd), self.stdout))
+        logger.debug(
+            "self.stdout for {cmd}: {stdout}".format(
+                cmd=" ".join(cmd), stdout=self.stdout
+            )
+        )
 
 
 # class TmuxMappingObject(t.Mapping[str, t.Union[str,int,bool]]):
diff --git a/src/libtmux/pytest_plugin.py b/src/libtmux/pytest_plugin.py
index 186f41092..ce62da913 100644
--- a/src/libtmux/pytest_plugin.py
+++ b/src/libtmux/pytest_plugin.py
@@ -204,7 +204,7 @@ def session(request: pytest.FixtureRequest, server: Server) -> "Session":
         pass
 
     for old_test_session in old_test_sessions:
-        logger.debug("Old test test session %s found. Killing it." % old_test_session)
+        logger.debug(f"Old test test session {old_test_session} found. Killing it.")
         server.kill_session(old_test_session)
     assert TEST_SESSION_NAME == session.get("session_name")
     assert TEST_SESSION_NAME != "tmuxp"
diff --git a/src/libtmux/server.py b/src/libtmux/server.py
index a049f3b9e..7f5d0affa 100644
--- a/src/libtmux/server.py
+++ b/src/libtmux/server.py
@@ -364,7 +364,7 @@ def attached_sessions(self) -> t.Optional[t.List[Session]]:
             attached = session.get("session_attached")
             # for now session_active is a unicode
             if attached != "0":
-                logger.debug("session %s attached", session.get("name"))
+                logger.debug(f"session {session.get('name')} attached")
                 attached_sessions.append(session)
             else:
                 continue
@@ -564,7 +564,7 @@ def new_session(
                         "Session named %s exists" % session_name
                     )
 
-        logger.debug("creating session %s" % session_name)
+        logger.debug(f"creating session {session_name}")
 
         sformats = formats.SESSION_FORMATS
         tmux_formats = ["#{%s}" % f for f in sformats]

From 039d291d4258bc790386fb14bca72657229b014f Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Thu, 13 Oct 2022 18:17:02 -0500
Subject: [PATCH 0200/1073] refactor(Server): (attached_)sessions return list
 if server off

---
 src/libtmux/server.py | 70 +++++++++++++++++++++++++++++++++++--------
 tests/test_server.py  | 33 ++++++++++++++++++++
 2 files changed, 90 insertions(+), 13 deletions(-)

diff --git a/src/libtmux/server.py b/src/libtmux/server.py
index 7f5d0affa..cfc0bda44 100644
--- a/src/libtmux/server.py
+++ b/src/libtmux/server.py
@@ -6,6 +6,8 @@
 """
 import logging
 import os
+import shutil
+import subprocess
 import typing as t
 
 from libtmux.common import tmux_cmd
@@ -115,6 +117,42 @@ def __init__(
         if colors:
             self.colors = colors
 
+    def is_alive(self) -> bool:
+        """If server alive or not.
+
+        >>> tmux = Server(socket_name="no_exist")
+        >>> assert not tmux.is_alive()
+        """
+        try:
+            res = self.cmd("list-sessions")
+            return res.returncode == 0
+        except Exception:
+            return False
+
+    def raise_if_dead(self) -> None:
+        """Raise if server not connected.
+
+        >>> tmux = Server(socket_name="no_exist")
+        >>> try:
+        ...     tmux.raise_if_dead()
+        ... except Exception as e:
+        ...     print(type(e))
+        
+        """
+        tmux_bin = shutil.which("tmux")
+        if tmux_bin is None:
+            raise exc.TmuxCommandNotFound()
+
+        cmd_args: t.List[str] = ["list-sessions"]
+        if self.socket_name:
+            cmd_args.insert(0, f"-L{self.socket_name}")
+        if self.socket_path:
+            cmd_args.insert(0, f"-S{self.socket_path}")
+        if self.config_file:
+            cmd_args.insert(0, f"-f{self.config_file}")
+
+        subprocess.check_call([tmux_bin] + cmd_args)
+
     def cmd(self, *args: t.Any, **kwargs: t.Any) -> tmux_cmd:
         """
         Execute tmux command and return output.
@@ -207,7 +245,10 @@ def list_sessions(self) -> t.List[Session]:
     @property
     def sessions(self) -> t.List[Session]:
         """Property / alias to return :meth:`~.list_sessions`."""
-        return self.list_sessions()
+        try:
+            return self.list_sessions()
+        except Exception:
+            return []
 
     #: Alias :attr:`sessions` for :class:`~libtmux.common.TmuxRelationalObject`
     children = sessions  # type: ignore
@@ -348,7 +389,7 @@ def _update_panes(self) -> "Server":
         return self
 
     @property
-    def attached_sessions(self) -> t.Optional[t.List[Session]]:
+    def attached_sessions(self) -> t.List[Session]:
         """
         Return active :class:`Session` objects.
 
@@ -357,19 +398,22 @@ def attached_sessions(self) -> t.Optional[t.List[Session]]:
         list of :class:`Session`
         """
 
-        sessions = self._sessions
-        attached_sessions = list()
+        try:
+            sessions = self._sessions
+            attached_sessions = list()
 
-        for session in sessions:
-            attached = session.get("session_attached")
-            # for now session_active is a unicode
-            if attached != "0":
-                logger.debug(f"session {session.get('name')} attached")
-                attached_sessions.append(session)
-            else:
-                continue
+            for session in sessions:
+                attached = session.get("session_attached")
+                # for now session_active is a unicode
+                if attached != "0":
+                    logger.debug(f"session {session.get('name')} attached")
+                    attached_sessions.append(session)
+                else:
+                    continue
 
-        return [Session(server=self, **s) for s in attached_sessions] or None
+            return [Session(server=self, **s) for s in attached_sessions] or []
+        except Exception:
+            return []
 
     def has_session(self, target_session: str, exact: bool = True) -> bool:
         """
diff --git a/tests/test_server.py b/tests/test_server.py
index 782150086..d7830fd0b 100644
--- a/tests/test_server.py
+++ b/tests/test_server.py
@@ -1,6 +1,8 @@
 """Test for libtmux Server object."""
 import logging
 
+import pytest
+
 from libtmux.common import has_gte_version
 from libtmux.server import Server
 from libtmux.session import Session
@@ -123,3 +125,34 @@ def test_new_session_shell(server: Server) -> None:
         assert pane_start_command.replace('"', "") == cmd
     else:
         assert pane_start_command == cmd
+
+
+def test_no_server_sessions() -> None:
+    server = Server(socket_name="test_attached_session_no_server")
+    assert server.sessions == []
+
+
+def test_no_server_attached_sessions() -> None:
+    server = Server(socket_name="test_no_server_attached_sessions")
+    assert server.attached_sessions == []
+
+
+def test_no_server_is_alive() -> None:
+    dead_server = Server(socket_name="test_no_server_is_alive")
+    assert not dead_server.is_alive()
+
+
+def test_with_server_is_alive(server: Server) -> None:
+    server.new_session()
+    assert server.is_alive()
+
+
+def test_no_server_raise_if_dead() -> None:
+    dead_server = Server(socket_name="test_attached_session_no_server")
+    with pytest.raises(Exception):
+        dead_server.raise_if_dead()
+
+
+def test_with_server_raise_if_dead(server: Server) -> None:
+    server.new_session()
+    server.raise_if_dead()

From c0d8ae6d3112c7edd6990800d97b455e66531ca6 Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Sat, 17 Dec 2022 18:36:04 -0600
Subject: [PATCH 0201/1073] docs(CHANGES): Note the server being connected /
 disconnected

---
 CHANGES | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/CHANGES b/CHANGES
index e7d822880..64b36ec79 100644
--- a/CHANGES
+++ b/CHANGES
@@ -14,6 +14,13 @@ $ pip install --user --upgrade --pre libtmux
 
 
 
+### New features
+
+#### Detect if server active (#448)
+
+- `Server.is_alive()`
+- `Server.raise_if_dead()`
+
 ### Internal
 
 - Remove unused `sphinx-click` development dependency

From 59d8e38be06c64632b5eac2b81954d9780a70b63 Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Sun, 18 Dec 2022 08:25:23 -0600
Subject: [PATCH 0202/1073] build(deps): Bump pytz

---
 poetry.lock | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/poetry.lock b/poetry.lock
index ea36f810c..b5d57a0e9 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -597,7 +597,7 @@ watchdog = ">=2.0.0"
 
 [[package]]
 name = "pytz"
-version = "2022.6"
+version = "2022.7"
 description = "World timezone definitions, modern and historical"
 category = "dev"
 optional = false
@@ -1247,8 +1247,8 @@ pytest-watcher = [
     {file = "pytest_watcher-0.2.6-py3-none-any.whl", hash = "sha256:0a507159d051c9461790363e0f9b2827c1d82ad2ae8966319598695e485b1dd5"},
 ]
 pytz = [
-    {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"},
-    {file = "pytz-2022.6.tar.gz", hash = "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2"},
+    {file = "pytz-2022.7-py2.py3-none-any.whl", hash = "sha256:93007def75ae22f7cd991c84e02d434876818661f8df9ad5df9e950ff4e52cfd"},
+    {file = "pytz-2022.7.tar.gz", hash = "sha256:7ccfae7b4b2c067464a6733c6261673fdb8fd1be905460396b97a073e9fa683a"},
 ]
 pyyaml = [
     {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},

From 49d6a946332cc173a170c1758b511779f1850dcb Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Mon, 19 Dec 2022 05:20:50 -0600
Subject: [PATCH 0203/1073] build(deps): Bump coverage

---
 poetry.lock | 103 ++++++++++++++++++++++++++--------------------------
 1 file changed, 52 insertions(+), 51 deletions(-)

diff --git a/poetry.lock b/poetry.lock
index b5d57a0e9..ace0b3004 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -122,7 +122,7 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7
 
 [[package]]
 name = "coverage"
-version = "6.5.0"
+version = "7.0.0"
 description = "Code coverage measurement for Python"
 category = "dev"
 optional = false
@@ -986,56 +986,57 @@ colorama = [
     {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
 ]
 coverage = [
-    {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"},
-    {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"},
-    {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"},
-    {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"},
-    {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"},
-    {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"},
-    {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"},
-    {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"},
-    {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"},
-    {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"},
-    {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"},
-    {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"},
-    {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"},
-    {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"},
-    {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"},
-    {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"},
-    {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"},
-    {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"},
-    {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"},
-    {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"},
-    {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"},
-    {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"},
-    {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"},
-    {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"},
-    {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"},
-    {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"},
-    {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"},
-    {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"},
-    {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"},
-    {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"},
-    {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"},
-    {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"},
-    {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"},
-    {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"},
-    {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"},
-    {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"},
-    {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"},
-    {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"},
-    {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"},
-    {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"},
-    {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"},
-    {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"},
-    {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"},
-    {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"},
-    {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"},
-    {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"},
-    {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"},
-    {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"},
-    {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"},
-    {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"},
+    {file = "coverage-7.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f2569682d6ea9628da8d6ba38579a48b1e53081226ec7a6c82b5024b3ce5009f"},
+    {file = "coverage-7.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ec256a592b497f26054195f7d7148892aca8c4cdcc064a7cc66ef7a0455b811"},
+    {file = "coverage-7.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5885a4ceb6dde34271bb0adafa4a248a7f589c89821e9da3110c39f92f41e21b"},
+    {file = "coverage-7.0.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d43d406a4d73aa7f855fa44fa77ff47e739b565b2af3844600cdc016d01e46b9"},
+    {file = "coverage-7.0.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18df11efa615b79b9ecc13035a712957ff6283f7b244e57684e1c092869f541"},
+    {file = "coverage-7.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f6a4bf5bdee93f6817797beba7086292c2ebde6df0d5822e0c33f8b05415c339"},
+    {file = "coverage-7.0.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:33efe89cd0efef016db19d8d05aa46631f76793de90a61b6717acb202b36fe60"},
+    {file = "coverage-7.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:96b5b1f1079e48f56bfccf103bcf44d48b9eb5163f1ea523fad580f15d3fe5e0"},
+    {file = "coverage-7.0.0-cp310-cp310-win32.whl", hash = "sha256:fb85b7a7a4b204bd59d6d0b0c8d87d9ffa820da225e691dfaffc3137dc05b5f6"},
+    {file = "coverage-7.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:793dcd9d42035746fc7637df4336f7581df19d33c5c5253cf988c99d8e93a8ba"},
+    {file = "coverage-7.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d564142a03d3bc8913499a458e931b52ddfe952f69b6cd4b24d810fd2959044a"},
+    {file = "coverage-7.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0a8b0e86bede874bf5da566b02194fbb12dd14ce3585cabd58452007f272ba81"},
+    {file = "coverage-7.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e645c73cbfc4577d93747d3f793115acf6f907a7eb9208fa807fdcf2da1964a4"},
+    {file = "coverage-7.0.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de06e7585abe88c6d38c1b73ce4c3cb4c1a79fbb0da0d0f8e8689ef5729ec60d"},
+    {file = "coverage-7.0.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a30b646fbdd5bc52f506e149fa4fbdef82432baf6b81774e61ec4e3b43b9cbde"},
+    {file = "coverage-7.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:db8141856dc9be0917413df7200f53accf1d84c8b156868e6af058a1ea8e903a"},
+    {file = "coverage-7.0.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:59e71912c7fc78d08a567ee65656123878f49ca1b5672e660ea70bf8dfbebf8f"},
+    {file = "coverage-7.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b8f7cd942dda3795fc9eadf303cc53a422ac057e3b70c2ad6d4276ec6a83a541"},
+    {file = "coverage-7.0.0-cp311-cp311-win32.whl", hash = "sha256:bf437a04b9790d3c9cd5b48e9ce9aa84229040e3ae7d6c670a55118906113c5a"},
+    {file = "coverage-7.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:a7e1bb36b4e57a2d304322021b35d4e4a25fa0d501ba56e8e51efaebf4480556"},
+    {file = "coverage-7.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:215f40ef86f1958a1151fa7fad2b4f2f99534c4e10a34a1e065eba3f19ef8868"},
+    {file = "coverage-7.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae088eb1cbdad8206931b1bf3f11dee644e038a9300be84d3e705e29356e5b1d"},
+    {file = "coverage-7.0.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9071e197faa24837b967bc9aa0b9ef961f805a75f1ee3ea1f3367f55cd46c3c"},
+    {file = "coverage-7.0.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f1e6d9c70d45a960d3f3d781ea62b167fdf2e0e1f6bb282b96feea653adb923"},
+    {file = "coverage-7.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9fadd15f9fcfd7b16d9cccce9f5e6ec6f9b8df860633ad9aa62c2b14c259560f"},
+    {file = "coverage-7.0.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:10b6246cae61896ab4c7568e498e492cbb73a2dfa4c3af79141c43cf806f929a"},
+    {file = "coverage-7.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a8785791c2120af114ea7a06137f7778632e568a5aa2bbfc3b46c573b702af74"},
+    {file = "coverage-7.0.0-cp37-cp37m-win32.whl", hash = "sha256:30220518dd89c4878908d73f5f3d1269f86e9e045354436534587a18c7b9da85"},
+    {file = "coverage-7.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:bc904aa96105d73357de03de76336b1e3db28e2b12067d36625fd9646ab043fd"},
+    {file = "coverage-7.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2331b7bd84a1be79bd17ca8e103ce38db8cbf7cb354dc56e651ba489cf849212"},
+    {file = "coverage-7.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e907db8bdd0ad1253a33c20fdc5f0f6209d271114a9c6f1fcdf96617343f7ca0"},
+    {file = "coverage-7.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0deee68e0dae1d6e3fe6943c76d7e66fbeb6519bd08e4e5366bcc28a8a9aca"},
+    {file = "coverage-7.0.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fff0f08bc5ffd0d78db821971472b4adc2ee876b86f743e46d634fb8e3c22f"},
+    {file = "coverage-7.0.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a290b7921c1c05787b953e5854d394e887df40696f21381cc33c4e2179bf50ac"},
+    {file = "coverage-7.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:100546219af59d2ad82d4575de03a303eb27b75ea36ffbd1677371924d50bcbc"},
+    {file = "coverage-7.0.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c1ba6e63b831112b9484ff5905370d89e43d4316bac76d403031f60d61597466"},
+    {file = "coverage-7.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c685fc17d6f4f1a3833e9dac27d0b931f7ccb52be6c30d269374203c7d0204a2"},
+    {file = "coverage-7.0.0-cp38-cp38-win32.whl", hash = "sha256:8938f3a10f45019b502020ba9567b97b6ecc8c76b664b421705c5406d4f92fe8"},
+    {file = "coverage-7.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:c4b63888bef2928d0eca12cbce0760cfb696acb4fe226eb55178b6a2a039328a"},
+    {file = "coverage-7.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cda63459eb20652b22e038729a8f5063862c189a3963cb042a764b753172f75e"},
+    {file = "coverage-7.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e06abac1a4aec1ff989131e43ca917fc7bd296f34bf0cfe86cbf74343b21566d"},
+    {file = "coverage-7.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32b94ad926e933976627f040f96dd1d9b0ac91f8d27e868c30a28253b9b6ac2d"},
+    {file = "coverage-7.0.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6b4af31fb49a2ae8de1cd505fa66c403bfcc5066e845ac19d8904dcfc9d40da"},
+    {file = "coverage-7.0.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36b62f0220459e528ad5806cc7dede71aa716e067d2cb10cb4a09686b8791fba"},
+    {file = "coverage-7.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:43ec1935c6d6caab4f3bc126d20bd709c0002a175d62208ebe745be37a826a41"},
+    {file = "coverage-7.0.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8593c9baf1f0f273afa22f5b45508b76adc7b8e94e17e7d98fbe1e3cd5812af2"},
+    {file = "coverage-7.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fee283cd36c3f14422d9c1b51da24ddbb5e1eed89ad2480f6a9f115df38b5df8"},
+    {file = "coverage-7.0.0-cp39-cp39-win32.whl", hash = "sha256:97c0b001ff15b8e8882995fc07ac0a08c8baf8b13c1145f3f12e0587bbb0e335"},
+    {file = "coverage-7.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:8dbf83a4611c591b5de65069b6fd4dd3889200ed270cd2f7f5ac765d3842889f"},
+    {file = "coverage-7.0.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:bcaf18e46668057051a312c714a4548b81f7e8fb3454116ad97be7562d2a99e4"},
+    {file = "coverage-7.0.0.tar.gz", hash = "sha256:9a175da2a7320e18fc3ee1d147639a2b3a8f037e508c96aa2da160294eb50e17"},
 ]
 docutils = [
     {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"},

From e40fd333905b3d8fe996d7cf49a4c21e837b8efd Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Mon, 19 Dec 2022 21:36:35 -0600
Subject: [PATCH 0204/1073] build(deps): Bump sphinxext-opengraph

---
 poetry.lock | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/poetry.lock b/poetry.lock
index ace0b3004..481f9f4c1 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -834,7 +834,7 @@ test = ["pytest"]
 
 [[package]]
 name = "sphinxext-opengraph"
-version = "0.7.3"
+version = "0.7.4"
 description = "Sphinx Extension to enable OGP support"
 category = "dev"
 optional = false
@@ -1358,8 +1358,8 @@ sphinxcontrib-serializinghtml = [
     {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"},
 ]
 sphinxext-opengraph = [
-    {file = "sphinxext-opengraph-0.7.3.tar.gz", hash = "sha256:837e5612709b4df7f1715f0832bf7d46cc0a61ebd7bb5aeab28edd6377beaf23"},
-    {file = "sphinxext_opengraph-0.7.3-py3-none-any.whl", hash = "sha256:edbfb21f1d31f572fc87a6ccc347cac502a3b8bb04c312bc2fa4888542f8505d"},
+    {file = "sphinxext-opengraph-0.7.4.tar.gz", hash = "sha256:b7db74764f5bc28a32f03ed6bf97a131a5f29dc9aeff8745282a83f6096602e4"},
+    {file = "sphinxext_opengraph-0.7.4-py3-none-any.whl", hash = "sha256:40e0bda1cb851019e773398cfb313e3788b424f3991028ee5c1027b84a08e378"},
 ]
 sphinxext-rediraffe = [
     {file = "sphinxext-rediraffe-0.2.7.tar.gz", hash = "sha256:651dcbfae5ffda9ffd534dfb8025f36120e5efb6ea1a33f5420023862b9f725d"},

From 45878239a8bf51074ee780d14aaf8d73f607d63c Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Thu, 22 Dec 2022 21:03:35 -0600
Subject: [PATCH 0205/1073] build(deps): Bump attrs, isort

---
 poetry.lock | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/poetry.lock b/poetry.lock
index 481f9f4c1..eacb16536 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -8,17 +8,18 @@ python-versions = "*"
 
 [[package]]
 name = "attrs"
-version = "22.1.0"
+version = "22.2.0"
 description = "Classes Without Boilerplate"
 category = "dev"
 optional = false
-python-versions = ">=3.5"
+python-versions = ">=3.6"
 
 [package.extras]
-dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"]
-docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
-tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"]
-tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
+cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"]
+dev = ["attrs[docs,tests]"]
+docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"]
+tests = ["attrs[tests-no-zope]", "zope.interface"]
+tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"]
 
 [[package]]
 name = "babel"
@@ -276,7 +277,7 @@ python-versions = "*"
 
 [[package]]
 name = "isort"
-version = "5.11.3"
+version = "5.11.4"
 description = "A Python utility / library to sort Python imports."
 category = "dev"
 optional = false
@@ -940,8 +941,8 @@ alabaster = [
     {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"},
 ]
 attrs = [
-    {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"},
-    {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"},
+    {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"},
+    {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"},
 ]
 babel = [
     {file = "Babel-2.11.0-py3-none-any.whl", hash = "sha256:1ad3eca1c885218f6dce2ab67291178944f810a10a9b5f3cb8382a5a232b64fe"},
@@ -1085,8 +1086,8 @@ iniconfig = [
     {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
 ]
 isort = [
-    {file = "isort-5.11.3-py3-none-any.whl", hash = "sha256:83155ffa936239d986b0f190347a3f2285f42a9b9e1725c89d865b27dd0627e5"},
-    {file = "isort-5.11.3.tar.gz", hash = "sha256:a8ca25fbfad0f7d5d8447a4314837298d9f6b23aed8618584c894574f626b64b"},
+    {file = "isort-5.11.4-py3-none-any.whl", hash = "sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b"},
+    {file = "isort-5.11.4.tar.gz", hash = "sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6"},
 ]
 jinja2 = [
     {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},

From 90c5afe983309f94a987a33b7486f22a533cabd5 Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Fri, 23 Dec 2022 18:41:55 -0600
Subject: [PATCH 0206/1073] all: Update packages

---
 poetry.lock | 110 ++++++++++++++++++++++++++--------------------------
 1 file changed, 55 insertions(+), 55 deletions(-)

diff --git a/poetry.lock b/poetry.lock
index eacb16536..5e53b3fc6 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -123,7 +123,7 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7
 
 [[package]]
 name = "coverage"
-version = "7.0.0"
+version = "7.0.1"
 description = "Code coverage measurement for Python"
 category = "dev"
 optional = false
@@ -145,7 +145,7 @@ python-versions = ">=3.7"
 
 [[package]]
 name = "exceptiongroup"
-version = "1.0.4"
+version = "1.1.0"
 description = "Backport of PEP 654 (exception groups)"
 category = "dev"
 optional = false
@@ -987,65 +987,65 @@ colorama = [
     {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
 ]
 coverage = [
-    {file = "coverage-7.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f2569682d6ea9628da8d6ba38579a48b1e53081226ec7a6c82b5024b3ce5009f"},
-    {file = "coverage-7.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ec256a592b497f26054195f7d7148892aca8c4cdcc064a7cc66ef7a0455b811"},
-    {file = "coverage-7.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5885a4ceb6dde34271bb0adafa4a248a7f589c89821e9da3110c39f92f41e21b"},
-    {file = "coverage-7.0.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d43d406a4d73aa7f855fa44fa77ff47e739b565b2af3844600cdc016d01e46b9"},
-    {file = "coverage-7.0.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18df11efa615b79b9ecc13035a712957ff6283f7b244e57684e1c092869f541"},
-    {file = "coverage-7.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f6a4bf5bdee93f6817797beba7086292c2ebde6df0d5822e0c33f8b05415c339"},
-    {file = "coverage-7.0.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:33efe89cd0efef016db19d8d05aa46631f76793de90a61b6717acb202b36fe60"},
-    {file = "coverage-7.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:96b5b1f1079e48f56bfccf103bcf44d48b9eb5163f1ea523fad580f15d3fe5e0"},
-    {file = "coverage-7.0.0-cp310-cp310-win32.whl", hash = "sha256:fb85b7a7a4b204bd59d6d0b0c8d87d9ffa820da225e691dfaffc3137dc05b5f6"},
-    {file = "coverage-7.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:793dcd9d42035746fc7637df4336f7581df19d33c5c5253cf988c99d8e93a8ba"},
-    {file = "coverage-7.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d564142a03d3bc8913499a458e931b52ddfe952f69b6cd4b24d810fd2959044a"},
-    {file = "coverage-7.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0a8b0e86bede874bf5da566b02194fbb12dd14ce3585cabd58452007f272ba81"},
-    {file = "coverage-7.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e645c73cbfc4577d93747d3f793115acf6f907a7eb9208fa807fdcf2da1964a4"},
-    {file = "coverage-7.0.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de06e7585abe88c6d38c1b73ce4c3cb4c1a79fbb0da0d0f8e8689ef5729ec60d"},
-    {file = "coverage-7.0.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a30b646fbdd5bc52f506e149fa4fbdef82432baf6b81774e61ec4e3b43b9cbde"},
-    {file = "coverage-7.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:db8141856dc9be0917413df7200f53accf1d84c8b156868e6af058a1ea8e903a"},
-    {file = "coverage-7.0.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:59e71912c7fc78d08a567ee65656123878f49ca1b5672e660ea70bf8dfbebf8f"},
-    {file = "coverage-7.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b8f7cd942dda3795fc9eadf303cc53a422ac057e3b70c2ad6d4276ec6a83a541"},
-    {file = "coverage-7.0.0-cp311-cp311-win32.whl", hash = "sha256:bf437a04b9790d3c9cd5b48e9ce9aa84229040e3ae7d6c670a55118906113c5a"},
-    {file = "coverage-7.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:a7e1bb36b4e57a2d304322021b35d4e4a25fa0d501ba56e8e51efaebf4480556"},
-    {file = "coverage-7.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:215f40ef86f1958a1151fa7fad2b4f2f99534c4e10a34a1e065eba3f19ef8868"},
-    {file = "coverage-7.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae088eb1cbdad8206931b1bf3f11dee644e038a9300be84d3e705e29356e5b1d"},
-    {file = "coverage-7.0.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9071e197faa24837b967bc9aa0b9ef961f805a75f1ee3ea1f3367f55cd46c3c"},
-    {file = "coverage-7.0.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f1e6d9c70d45a960d3f3d781ea62b167fdf2e0e1f6bb282b96feea653adb923"},
-    {file = "coverage-7.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9fadd15f9fcfd7b16d9cccce9f5e6ec6f9b8df860633ad9aa62c2b14c259560f"},
-    {file = "coverage-7.0.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:10b6246cae61896ab4c7568e498e492cbb73a2dfa4c3af79141c43cf806f929a"},
-    {file = "coverage-7.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a8785791c2120af114ea7a06137f7778632e568a5aa2bbfc3b46c573b702af74"},
-    {file = "coverage-7.0.0-cp37-cp37m-win32.whl", hash = "sha256:30220518dd89c4878908d73f5f3d1269f86e9e045354436534587a18c7b9da85"},
-    {file = "coverage-7.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:bc904aa96105d73357de03de76336b1e3db28e2b12067d36625fd9646ab043fd"},
-    {file = "coverage-7.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2331b7bd84a1be79bd17ca8e103ce38db8cbf7cb354dc56e651ba489cf849212"},
-    {file = "coverage-7.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e907db8bdd0ad1253a33c20fdc5f0f6209d271114a9c6f1fcdf96617343f7ca0"},
-    {file = "coverage-7.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0deee68e0dae1d6e3fe6943c76d7e66fbeb6519bd08e4e5366bcc28a8a9aca"},
-    {file = "coverage-7.0.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fff0f08bc5ffd0d78db821971472b4adc2ee876b86f743e46d634fb8e3c22f"},
-    {file = "coverage-7.0.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a290b7921c1c05787b953e5854d394e887df40696f21381cc33c4e2179bf50ac"},
-    {file = "coverage-7.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:100546219af59d2ad82d4575de03a303eb27b75ea36ffbd1677371924d50bcbc"},
-    {file = "coverage-7.0.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c1ba6e63b831112b9484ff5905370d89e43d4316bac76d403031f60d61597466"},
-    {file = "coverage-7.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c685fc17d6f4f1a3833e9dac27d0b931f7ccb52be6c30d269374203c7d0204a2"},
-    {file = "coverage-7.0.0-cp38-cp38-win32.whl", hash = "sha256:8938f3a10f45019b502020ba9567b97b6ecc8c76b664b421705c5406d4f92fe8"},
-    {file = "coverage-7.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:c4b63888bef2928d0eca12cbce0760cfb696acb4fe226eb55178b6a2a039328a"},
-    {file = "coverage-7.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cda63459eb20652b22e038729a8f5063862c189a3963cb042a764b753172f75e"},
-    {file = "coverage-7.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e06abac1a4aec1ff989131e43ca917fc7bd296f34bf0cfe86cbf74343b21566d"},
-    {file = "coverage-7.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32b94ad926e933976627f040f96dd1d9b0ac91f8d27e868c30a28253b9b6ac2d"},
-    {file = "coverage-7.0.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6b4af31fb49a2ae8de1cd505fa66c403bfcc5066e845ac19d8904dcfc9d40da"},
-    {file = "coverage-7.0.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36b62f0220459e528ad5806cc7dede71aa716e067d2cb10cb4a09686b8791fba"},
-    {file = "coverage-7.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:43ec1935c6d6caab4f3bc126d20bd709c0002a175d62208ebe745be37a826a41"},
-    {file = "coverage-7.0.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8593c9baf1f0f273afa22f5b45508b76adc7b8e94e17e7d98fbe1e3cd5812af2"},
-    {file = "coverage-7.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fee283cd36c3f14422d9c1b51da24ddbb5e1eed89ad2480f6a9f115df38b5df8"},
-    {file = "coverage-7.0.0-cp39-cp39-win32.whl", hash = "sha256:97c0b001ff15b8e8882995fc07ac0a08c8baf8b13c1145f3f12e0587bbb0e335"},
-    {file = "coverage-7.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:8dbf83a4611c591b5de65069b6fd4dd3889200ed270cd2f7f5ac765d3842889f"},
-    {file = "coverage-7.0.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:bcaf18e46668057051a312c714a4548b81f7e8fb3454116ad97be7562d2a99e4"},
-    {file = "coverage-7.0.0.tar.gz", hash = "sha256:9a175da2a7320e18fc3ee1d147639a2b3a8f037e508c96aa2da160294eb50e17"},
+    {file = "coverage-7.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b3695c4f4750bca943b3e1f74ad4be8d29e4aeab927d50772c41359107bd5d5c"},
+    {file = "coverage-7.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fa6a5a224b7f4cfb226f4fc55a57e8537fcc096f42219128c2c74c0e7d0953e1"},
+    {file = "coverage-7.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74f70cd92669394eaf8d7756d1b195c8032cf7bbbdfce3bc489d4e15b3b8cf73"},
+    {file = "coverage-7.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b66bb21a23680dee0be66557dc6b02a3152ddb55edf9f6723fa4a93368f7158d"},
+    {file = "coverage-7.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d87717959d4d0ee9db08a0f1d80d21eb585aafe30f9b0a54ecf779a69cb015f6"},
+    {file = "coverage-7.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:854f22fa361d1ff914c7efa347398374cc7d567bdafa48ac3aa22334650dfba2"},
+    {file = "coverage-7.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:1e414dc32ee5c3f36544ea466b6f52f28a7af788653744b8570d0bf12ff34bc0"},
+    {file = "coverage-7.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6c5ad996c6fa4d8ed669cfa1e8551348729d008a2caf81489ab9ea67cfbc7498"},
+    {file = "coverage-7.0.1-cp310-cp310-win32.whl", hash = "sha256:691571f31ace1837838b7e421d3a09a8c00b4aac32efacb4fc9bd0a5c647d25a"},
+    {file = "coverage-7.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:89caf4425fe88889e2973a8e9a3f6f5f9bbe5dd411d7d521e86428c08a873a4a"},
+    {file = "coverage-7.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:63d56165a7c76265468d7e0c5548215a5ba515fc2cba5232d17df97bffa10f6c"},
+    {file = "coverage-7.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4f943a3b2bc520102dd3e0bb465e1286e12c9a54f58accd71b9e65324d9c7c01"},
+    {file = "coverage-7.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:830525361249dc4cd013652b0efad645a385707a5ae49350c894b67d23fbb07c"},
+    {file = "coverage-7.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd1b9c5adc066db699ccf7fa839189a649afcdd9e02cb5dc9d24e67e7922737d"},
+    {file = "coverage-7.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e00c14720b8b3b6c23b487e70bd406abafc976ddc50490f645166f111c419c39"},
+    {file = "coverage-7.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6d55d840e1b8c0002fce66443e124e8581f30f9ead2e54fbf6709fb593181f2c"},
+    {file = "coverage-7.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:66b18c3cf8bbab0cce0d7b9e4262dc830e93588986865a8c78ab2ae324b3ed56"},
+    {file = "coverage-7.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:12a5aa77783d49e05439fbe6e6b427484f8a0f9f456b46a51d8aac022cfd024d"},
+    {file = "coverage-7.0.1-cp311-cp311-win32.whl", hash = "sha256:b77015d1cb8fe941be1222a5a8b4e3fbca88180cfa7e2d4a4e58aeabadef0ab7"},
+    {file = "coverage-7.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb992c47cb1e5bd6a01e97182400bcc2ba2077080a17fcd7be23aaa6e572e390"},
+    {file = "coverage-7.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e78e9dcbf4f3853d3ae18a8f9272111242531535ec9e1009fa8ec4a2b74557dc"},
+    {file = "coverage-7.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e60bef2e2416f15fdc05772bf87db06c6a6f9870d1db08fdd019fbec98ae24a9"},
+    {file = "coverage-7.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9823e4789ab70f3ec88724bba1a203f2856331986cd893dedbe3e23a6cfc1e4e"},
+    {file = "coverage-7.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9158f8fb06747ac17bd237930c4372336edc85b6e13bdc778e60f9d685c3ca37"},
+    {file = "coverage-7.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:486ee81fa694b4b796fc5617e376326a088f7b9729c74d9defa211813f3861e4"},
+    {file = "coverage-7.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1285648428a6101b5f41a18991c84f1c3959cee359e51b8375c5882fc364a13f"},
+    {file = "coverage-7.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2c44fcfb3781b41409d0f060a4ed748537557de9362a8a9282182fafb7a76ab4"},
+    {file = "coverage-7.0.1-cp37-cp37m-win32.whl", hash = "sha256:d6814854c02cbcd9c873c0f3286a02e3ac1250625cca822ca6bc1018c5b19f1c"},
+    {file = "coverage-7.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f66460f17c9319ea4f91c165d46840314f0a7c004720b20be58594d162a441d8"},
+    {file = "coverage-7.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b373c9345c584bb4b5f5b8840df7f4ab48c4cbb7934b58d52c57020d911b856"},
+    {file = "coverage-7.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d3022c3007d3267a880b5adcf18c2a9bf1fc64469b394a804886b401959b8742"},
+    {file = "coverage-7.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92651580bd46519067e36493acb394ea0607b55b45bd81dd4e26379ed1871f55"},
+    {file = "coverage-7.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cfc595d2af13856505631be072835c59f1acf30028d1c860b435c5fc9c15b69"},
+    {file = "coverage-7.0.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b4b3a4d9915b2be879aff6299c0a6129f3d08a775d5a061f503cf79571f73e4"},
+    {file = "coverage-7.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b6f22bb64cc39bcb883e5910f99a27b200fdc14cdd79df8696fa96b0005c9444"},
+    {file = "coverage-7.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72d1507f152abacea81f65fee38e4ef3ac3c02ff8bc16f21d935fd3a8a4ad910"},
+    {file = "coverage-7.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0a79137fc99815fff6a852c233628e735ec15903cfd16da0f229d9c4d45926ab"},
+    {file = "coverage-7.0.1-cp38-cp38-win32.whl", hash = "sha256:b3763e7fcade2ff6c8e62340af9277f54336920489ceb6a8cd6cc96da52fcc62"},
+    {file = "coverage-7.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:09f6b5a8415b6b3e136d5fec62b552972187265cb705097bf030eb9d4ffb9b60"},
+    {file = "coverage-7.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:978258fec36c154b5e250d356c59af7d4c3ba02bef4b99cda90b6029441d797d"},
+    {file = "coverage-7.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:19ec666533f0f70a0993f88b8273057b96c07b9d26457b41863ccd021a043b9a"},
+    {file = "coverage-7.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfded268092a84605f1cc19e5c737f9ce630a8900a3589e9289622db161967e9"},
+    {file = "coverage-7.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07bcfb1d8ac94af886b54e18a88b393f6a73d5959bb31e46644a02453c36e475"},
+    {file = "coverage-7.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:397b4a923cc7566bbc7ae2dfd0ba5a039b61d19c740f1373791f2ebd11caea59"},
+    {file = "coverage-7.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aec2d1515d9d39ff270059fd3afbb3b44e6ec5758af73caf18991807138c7118"},
+    {file = "coverage-7.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c20cfebcc149a4c212f6491a5f9ff56f41829cd4f607b5be71bb2d530ef243b1"},
+    {file = "coverage-7.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fd556ff16a57a070ce4f31c635953cc44e25244f91a0378c6e9bdfd40fdb249f"},
+    {file = "coverage-7.0.1-cp39-cp39-win32.whl", hash = "sha256:b9ea158775c7c2d3e54530a92da79496fb3fb577c876eec761c23e028f1e216c"},
+    {file = "coverage-7.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:d1991f1dd95eba69d2cd7708ff6c2bbd2426160ffc73c2b81f617a053ebcb1a8"},
+    {file = "coverage-7.0.1-pp37.pp38.pp39-none-any.whl", hash = "sha256:3dd4ee135e08037f458425b8842d24a95a0961831a33f89685ff86b77d378f89"},
+    {file = "coverage-7.0.1.tar.gz", hash = "sha256:a4a574a19eeb67575a5328a5760bbbb737faa685616586a9f9da4281f940109c"},
 ]
 docutils = [
     {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"},
     {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"},
 ]
 exceptiongroup = [
-    {file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"},
-    {file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"},
+    {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"},
+    {file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"},
 ]
 flake8 = [
     {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"},

From 715317dd902012e8924b8d429d9ad20ecc4fbb8b Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Mon, 26 Dec 2022 16:45:27 -0600
Subject: [PATCH 0207/1073] ci(mypy): Declare files to run 'mypy' with no args

---
 pyproject.toml | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/pyproject.toml b/pyproject.toml
index 6d2950c4f..2cc5fa214 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -113,6 +113,10 @@ libtmux = "libtmux.pytest_plugin"
 
 [tool.mypy]
 strict = true
+files = [
+  "src",
+  "tests"
+]
 
 [tool.coverage.run]
 branch = true

From ad8fb1e4ba58cc57e06024d1cde31f3e1c7eb04b Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Mon, 26 Dec 2022 20:10:52 -0600
Subject: [PATCH 0208/1073] Tag v0.17.0a0 (only prerelease before dataclasses)

---
 pyproject.toml           | 2 +-
 src/libtmux/__about__.py | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/pyproject.toml b/pyproject.toml
index 2cc5fa214..ccbd1f6a2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "libtmux"
-version = "0.16.1"
+version = "0.17.0a0"
 description = "Typed scripting library / ORM / API wrapper for tmux"
 license = "MIT"
 authors = ["Tony Narlock "]
diff --git a/src/libtmux/__about__.py b/src/libtmux/__about__.py
index b962f8a23..58d166205 100644
--- a/src/libtmux/__about__.py
+++ b/src/libtmux/__about__.py
@@ -1,6 +1,6 @@
 __title__ = "libtmux"
 __package_name__ = "libtmux"
-__version__ = "0.16.1"
+__version__ = "0.17.0a0"
 __description__ = "Typed scripting library / ORM / API wrapper for tmux"
 __email__ = "tony@git-pull.com"
 __author__ = "Tony Narlock"

From 24d7401822cbfa9441c1a33468331f8f144ab20c Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Fri, 16 Sep 2022 17:26:05 -0500
Subject: [PATCH 0209/1073] feat! Port libvcs utilities

---
 src/libtmux/_internal/__init__.py    |   0
 src/libtmux/_internal/dataclasses.py |  84 ++++
 src/libtmux/_internal/query_list.py  | 349 ++++++++++++++++
 src/libtmux/_internal/subprocess.py  | 587 +++++++++++++++++++++++++++
 src/libtmux/_internal/types.py       |  22 +
 5 files changed, 1042 insertions(+)
 create mode 100644 src/libtmux/_internal/__init__.py
 create mode 100644 src/libtmux/_internal/dataclasses.py
 create mode 100644 src/libtmux/_internal/query_list.py
 create mode 100644 src/libtmux/_internal/subprocess.py
 create mode 100644 src/libtmux/_internal/types.py

diff --git a/src/libtmux/_internal/__init__.py b/src/libtmux/_internal/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/libtmux/_internal/dataclasses.py b/src/libtmux/_internal/dataclasses.py
new file mode 100644
index 000000000..5cabfb19d
--- /dev/null
+++ b/src/libtmux/_internal/dataclasses.py
@@ -0,0 +1,84 @@
+""":mod:`dataclasses` utilities.
+
+Note
+----
+This is an internal API not covered by versioning policy.
+"""
+import dataclasses
+from operator import attrgetter
+
+
+class SkipDefaultFieldsReprMixin:
+    r"""Skip default fields in :func:`~dataclasses.dataclass`
+    :func:`object representation `.
+
+    Notes
+    -----
+
+    Credit: Pietro Oldrati, 2022-05-08, Unilicense
+
+    https://stackoverflow.com/a/72161437/1396928
+
+    Examples
+    --------
+
+    >>> @dataclasses.dataclass()
+    ... class Item:
+    ...     name: str
+    ...     unit_price: float = 1.00
+    ...     quantity_on_hand: int = 0
+    ...
+
+    >>> @dataclasses.dataclass(repr=False)
+    ... class ItemWithMixin(SkipDefaultFieldsReprMixin):
+    ...     name: str
+    ...     unit_price: float = 1.00
+    ...     quantity_on_hand: int = 0
+    ...
+
+    >>> Item('Test')
+    Item(name='Test', unit_price=1.0, quantity_on_hand=0)
+
+    >>> ItemWithMixin('Test')
+    ItemWithMixin(name=Test)
+
+    >>> Item('Test', quantity_on_hand=2)
+    Item(name='Test', unit_price=1.0, quantity_on_hand=2)
+
+    >>> ItemWithMixin('Test', quantity_on_hand=2)
+    ItemWithMixin(name=Test, quantity_on_hand=2)
+
+    If you want to copy/paste the :meth:`~.__repr__()`
+    directly, you can omit the ``repr=False``:
+
+    >>> @dataclasses.dataclass
+    ... class ItemWithMixin(SkipDefaultFieldsReprMixin):
+    ...     name: str
+    ...     unit_price: float = 1.00
+    ...     quantity_on_hand: int = 0
+    ...     __repr__ = SkipDefaultFieldsReprMixin.__repr__
+    ...
+
+    >>> ItemWithMixin('Test')
+    ItemWithMixin(name=Test)
+
+    >>> ItemWithMixin('Test', unit_price=2.00)
+    ItemWithMixin(name=Test, unit_price=2.0)
+
+    >>> item = ItemWithMixin('Test')
+    >>> item.unit_price = 2.05
+
+    >>> item
+    ItemWithMixin(name=Test, unit_price=2.05)
+    """
+
+    def __repr__(self) -> str:
+        """Omit default fields in object representation."""
+        nodef_f_vals = (
+            (f.name, attrgetter(f.name)(self))
+            for f in dataclasses.fields(self)
+            if attrgetter(f.name)(self) != f.default
+        )
+
+        nodef_f_repr = ", ".join(f"{name}={value}" for name, value in nodef_f_vals)
+        return f"{self.__class__.__name__}({nodef_f_repr})"
diff --git a/src/libtmux/_internal/query_list.py b/src/libtmux/_internal/query_list.py
new file mode 100644
index 000000000..70af21f0b
--- /dev/null
+++ b/src/libtmux/_internal/query_list.py
@@ -0,0 +1,349 @@
+"""Utilities for filtering or searching :class:`list` of objects / list data.
+
+Note
+----
+This is an internal API not covered by versioning policy.
+"""
+import re
+import traceback
+from collections.abc import Mapping, Sequence
+from re import Pattern
+from typing import TYPE_CHECKING, Any, Callable, List, Optional, TypeVar, Union
+
+if TYPE_CHECKING:
+    from typing_extensions import Protocol
+
+    class LookupProtocol(Protocol):
+        """Protocol for :class:`QueryList` filtering operators."""
+
+        def __call__(
+            self,
+            data: Union[str, List[str], "Mapping[str, str]"],
+            rhs: Union[str, List[str], "Mapping[str, str]", "Pattern[str]"],
+        ) -> bool:
+            """Callback for :class:`QueryList` filtering operators."""
+            ...
+
+
+T = TypeVar("T", Any, Any)
+
+
+def keygetter(
+    obj: "Mapping[str, Any]",
+    path: str,
+) -> Union[None, Any, str, List[str], "Mapping[str, str]"]:
+    """obj, "foods__breakfast", obj['foods']['breakfast']
+
+    >>> keygetter({ "foods": { "breakfast": "cereal" } }, "foods__breakfast")
+    'cereal'
+    >>> keygetter({ "foods": { "breakfast": "cereal" } }, "foods")
+    {'breakfast': 'cereal'}
+
+    """
+    try:
+        sub_fields = path.split("__")
+        dct = obj
+        for sub_field in sub_fields:
+            if isinstance(dct, dict):
+                dct = dct[sub_field]
+            elif hasattr(dct, sub_field):
+                dct = getattr(dct, sub_field)
+
+        return dct
+    except Exception as e:
+        traceback.print_stack()
+        print(f"Above error was {e}")
+    return None
+
+
+def parse_lookup(obj: "Mapping[str, Any]", path: str, lookup: str) -> Optional[Any]:
+    """Check if field lookup key, e.g. "my__path__contains" has comparator, return val.
+
+    If comparator not used or value not found, return None.
+
+    mykey__endswith("mykey") -> "mykey" else None
+
+    >>> parse_lookup({ "food": "red apple" }, "food__istartswith", "__istartswith")
+    'red apple'
+    """
+    try:
+        if isinstance(path, str) and isinstance(lookup, str) and path.endswith(lookup):
+            field_name = path.rsplit(lookup)[0]
+            if field_name is not None:
+                return keygetter(obj, field_name)
+    except Exception:
+        traceback.print_stack()
+    return None
+
+
+def lookup_exact(
+    data: Union[str, List[str], "Mapping[str, str]"],
+    rhs: Union[str, List[str], "Mapping[str, str]", "Pattern[str]"],
+) -> bool:
+    return rhs == data
+
+
+def lookup_iexact(
+    data: Union[str, List[str], "Mapping[str, str]"],
+    rhs: Union[str, List[str], "Mapping[str, str]", "Pattern[str]"],
+) -> bool:
+    if not isinstance(rhs, str) or not isinstance(data, str):
+        return False
+
+    return rhs.lower() == data.lower()
+
+
+def lookup_contains(
+    data: Union[str, List[str], "Mapping[str, str]"],
+    rhs: Union[str, List[str], "Mapping[str, str]", "Pattern[str]"],
+) -> bool:
+    if not isinstance(rhs, str) or not isinstance(data, (str, Mapping, list)):
+        return False
+
+    return rhs in data
+
+
+def lookup_icontains(
+    data: Union[str, List[str], "Mapping[str, str]"],
+    rhs: Union[str, List[str], "Mapping[str, str]", "Pattern[str]"],
+) -> bool:
+    if not isinstance(rhs, str) or not isinstance(data, (str, Mapping, list)):
+        return False
+
+    if isinstance(data, str):
+        return rhs.lower() in data.lower()
+    if isinstance(data, Mapping):
+        return rhs.lower() in [k.lower() for k in data.keys()]
+
+    return False
+
+
+def lookup_startswith(
+    data: Union[str, List[str], "Mapping[str, str]"],
+    rhs: Union[str, List[str], "Mapping[str, str]", "Pattern[str]"],
+) -> bool:
+    if not isinstance(rhs, str) or not isinstance(data, str):
+        return False
+
+    return data.startswith(rhs)
+
+
+def lookup_istartswith(
+    data: Union[str, List[str], "Mapping[str, str]"],
+    rhs: Union[str, List[str], "Mapping[str, str]", "Pattern[str]"],
+) -> bool:
+    if not isinstance(rhs, str) or not isinstance(data, str):
+        return False
+
+    return data.lower().startswith(rhs.lower())
+
+
+def lookup_endswith(
+    data: Union[str, List[str], "Mapping[str, str]"],
+    rhs: Union[str, List[str], "Mapping[str, str]", "Pattern[str]"],
+) -> bool:
+    if not isinstance(rhs, str) or not isinstance(data, str):
+        return False
+
+    return data.endswith(rhs)
+
+
+def lookup_iendswith(
+    data: Union[str, List[str], "Mapping[str, str]"],
+    rhs: Union[str, List[str], "Mapping[str, str]", "Pattern[str]"],
+) -> bool:
+    if not isinstance(rhs, str) or not isinstance(data, str):
+        return False
+    return data.lower().endswith(rhs.lower())
+
+
+def lookup_in(
+    data: Union[str, List[str], "Mapping[str, str]"],
+    rhs: Union[str, List[str], "Mapping[str, str]", "Pattern[str]"],
+) -> bool:
+    if isinstance(rhs, list):
+        return data in rhs
+
+    try:
+        if isinstance(rhs, str) and isinstance(data, Mapping):
+            return rhs in data
+        if isinstance(rhs, str) and isinstance(data, (str, list)):
+            return rhs in data
+        if isinstance(rhs, str) and isinstance(data, Mapping):
+            return rhs in data
+        # TODO: Add a deep Mappingionary matcher
+        # if isinstance(rhs, Mapping) and isinstance(data, Mapping):
+        #     return rhs.items() not in data.items()
+    except Exception:
+        return False
+    return False
+
+
+def lookup_nin(
+    data: Union[str, List[str], "Mapping[str, str]"],
+    rhs: Union[str, List[str], "Mapping[str, str]", "Pattern[str]"],
+) -> bool:
+    if isinstance(rhs, list):
+        return data not in rhs
+
+    try:
+        if isinstance(rhs, str) and isinstance(data, Mapping):
+            return rhs not in data
+        if isinstance(rhs, str) and isinstance(data, (str, list)):
+            return rhs not in data
+        if isinstance(rhs, str) and isinstance(data, Mapping):
+            return rhs not in data
+        # TODO: Add a deep Mappingionary matcher
+        # if isinstance(rhs, Mapping) and isinstance(data, Mapping):
+        #     return rhs.items() not in data.items()
+    except Exception:
+        return False
+    return False
+
+
+def lookup_regex(
+    data: Union[str, List[str], "Mapping[str, str]"],
+    rhs: Union[str, List[str], "Mapping[str, str]", "Pattern[str]"],
+) -> bool:
+    if isinstance(data, (str, bytes, re.Pattern)) and isinstance(rhs, (str, bytes)):
+        return bool(re.search(rhs, data))
+    return False
+
+
+def lookup_iregex(
+    data: Union[str, List[str], "Mapping[str, str]"],
+    rhs: Union[str, List[str], "Mapping[str, str]", "Pattern[str]"],
+) -> bool:
+    if isinstance(data, (str, bytes, re.Pattern)) and isinstance(rhs, (str, bytes)):
+        return bool(re.search(rhs, data, re.IGNORECASE))
+    return False
+
+
+LOOKUP_NAME_MAP: 'Mapping[str, "LookupProtocol"]' = {
+    "eq": lookup_exact,
+    "exact": lookup_exact,
+    "iexact": lookup_iexact,
+    "contains": lookup_contains,
+    "icontains": lookup_icontains,
+    "startswith": lookup_startswith,
+    "istartswith": lookup_istartswith,
+    "endswith": lookup_endswith,
+    "iendswith": lookup_iendswith,
+    "in": lookup_in,
+    "nin": lookup_nin,
+    "regex": lookup_regex,
+    "iregex": lookup_iregex,
+}
+
+
+class QueryList(List[T]):
+    """Filter list of object/dictionaries. For small, local datasets.
+
+    *Experimental, unstable*.
+
+    >>> query = QueryList(
+    ...     [
+    ...         {
+    ...             "place": "Largo",
+    ...             "city": "Tampa",
+    ...             "state": "Florida",
+    ...             "foods": {"fruit": ["banana", "orange"], "breakfast": "cereal"},
+    ...         },
+    ...         {
+    ...             "place": "Chicago suburbs",
+    ...             "city": "Elmhurst",
+    ...             "state": "Illinois",
+    ...             "foods": {"fruit": ["apple", "cantelope"], "breakfast": "waffles"},
+    ...         },
+    ...     ]
+    ... )
+    >>> query.filter(place="Chicago suburbs")[0]['city']
+    'Elmhurst'
+    >>> query.filter(place__icontains="chicago")[0]['city']
+    'Elmhurst'
+    >>> query.filter(foods__breakfast="waffles")[0]['city']
+    'Elmhurst'
+    >>> query.filter(foods__fruit__in="cantelope")[0]['city']
+    'Elmhurst'
+    >>> query.filter(foods__fruit__in="orange")[0]['city']
+    'Tampa'
+    """
+
+    data: "Sequence[T]"
+    pk_key: Optional[str]
+
+    def items(self) -> List[T]:
+        data: "Sequence[T]"
+
+        if self.pk_key is None:
+            raise Exception("items() require a pk_key exists")
+        return [(getattr(item, self.pk_key), item) for item in self]
+
+    def __eq__(
+        self,
+        other: object,
+        # other: Union[
+        #     "QueryList[T]",
+        #     List[Mapping[str, str]],
+        #     List[Mapping[str, int]],
+        #     List[Mapping[str, Union[str, Mapping[str, Union[List[str], str]]]]],
+        # ],
+    ) -> bool:
+        data = other
+
+        if not isinstance(self, list) or not isinstance(data, list):
+            return False
+
+        if len(self) == len(data):
+            for (a, b) in zip(self, data):
+                if isinstance(a, Mapping):
+                    a_keys = a.keys()
+                    if a.keys == b.keys():
+                        for key in a_keys:
+                            if abs(a[key] - b[key]) > 1:
+                                return False
+                else:
+                    if a != b:
+                        return False
+
+            return True
+        return False
+
+    def filter(
+        self, matcher: Optional[Union[Callable[[T], bool], T]] = None, **kwargs: Any
+    ) -> "QueryList[T]":
+        def filter_lookup(obj: Any) -> bool:
+            for path, v in kwargs.items():
+                try:
+                    lhs, op = path.rsplit("__", 1)
+
+                    if op not in LOOKUP_NAME_MAP:
+                        raise ValueError(f"{op} not in LOOKUP_NAME_MAP")
+                except ValueError:
+                    lhs = path
+                    op = "exact"
+
+                assert op in LOOKUP_NAME_MAP
+                path = lhs
+                data = keygetter(obj, path)
+
+                if data is None or not LOOKUP_NAME_MAP[op](data, v):
+                    return False
+
+            return True
+
+        if callable(matcher):
+            _filter = matcher
+        elif matcher is not None:
+
+            def val_match(obj: Union[str, List[Any]]) -> bool:
+                if isinstance(matcher, list):
+                    return obj in matcher
+                else:
+                    return obj == matcher
+
+            _filter = val_match
+        else:
+            _filter = filter_lookup
+
+        return self.__class__(k for k in self if _filter(k))
diff --git a/src/libtmux/_internal/subprocess.py b/src/libtmux/_internal/subprocess.py
new file mode 100644
index 000000000..1059a478f
--- /dev/null
+++ b/src/libtmux/_internal/subprocess.py
@@ -0,0 +1,587 @@
+"""Invokable :mod:`subprocess` wrapper.
+
+Defer running a subprocess, such as by handing to an executor.
+
+Note
+----
+This is an internal API not covered by versioning policy.
+
+Examples
+--------
+
+- :class:`~SubprocessCommand`: Wraps :class:`subprocess.Popen` and
+  :func:`subprocess.run` in a :func:`~dataclasses.dataclass`.
+
+  Before:
+
+  >>> import subprocess
+  >>> subprocess.run(
+  ...    ['echo', 'hi'],
+  ...    capture_output=True, universal_newlines=True
+  ... ).stdout
+  'hi\\n'
+
+  With this:
+
+  >>> cmd = SubprocessCommand(['echo', 'hi'])
+  >>> cmd.args
+  ['echo', 'hi']
+  >>> cmd.run(capture_output=True, universal_newlines=True).stdout
+  'hi\\n'
+
+  Tweak params before invocation:
+
+  >>> cmd = SubprocessCommand(['echo', 'hi'])
+  >>> cmd.args[1] = 'hello'
+  >>> cmd.args
+  ['echo', 'hello']
+  >>> cmd.run(capture_output=True, universal_newlines=True).stdout
+  'hello\\n'
+"""
+import dataclasses
+import subprocess
+import sys
+from collections.abc import Mapping, Sequence
+from typing import (
+    IO,
+    TYPE_CHECKING,
+    Any,
+    Callable,
+    List,
+    Optional,
+    TypeVar,
+    Union,
+    overload,
+)
+
+from typing_extensions import Literal, TypeAlias
+
+from .dataclasses import SkipDefaultFieldsReprMixin
+from .types import StrOrBytesPath
+
+F = TypeVar("F", bound=Callable[..., Any])
+
+
+if sys.platform == "win32":
+    _ENV: TypeAlias = "Mapping[str, str]"
+else:
+    _ENV: TypeAlias = Union[
+        "Mapping[bytes, StrOrBytesPath]", "Mapping[str, StrOrBytesPath]"
+    ]
+_FILE: TypeAlias = Union[None, int, IO[Any]]
+_TXT: TypeAlias = Union[bytes, str]
+
+if TYPE_CHECKING:
+    #: Command
+    _CMD: TypeAlias = Union[StrOrBytesPath, "Sequence[StrOrBytesPath]"]
+
+
+@dataclasses.dataclass(repr=False)
+class SubprocessCommand(SkipDefaultFieldsReprMixin):
+    """Wraps a :mod:`subprocess` request. Inspect, mutate, control before invocation.
+
+    Attributes
+    ----------
+    args : _CMD
+        A string, or a sequence of program arguments.
+
+    bufsize : int
+        supplied as the buffering argument to the open() function when creating the
+        stdin/stdout/stderr pipe file objects
+
+    executable : Optional[StrOrBytesPath]
+        A replacement program to execute.
+
+    stdin : _FILE
+        standard output for executed program
+
+    stdout :
+        standard output for executed program
+
+    stderr :
+        standard output for executed program
+
+    close_fds : Controls closing or inheriting of file descriptors.
+
+    shell : If true, the command will be executed through the shell.
+
+    cwd : Sets the current directory before the child is executed.
+
+    env : Defines the environment variables for the new process.
+
+    text :
+        If ``True``, decode stdin, stdout and stderr using the given encoding (if set)
+        or the system default otherwise.
+
+    universal_newlines :
+        Alias of text, provided for backwards compatibility.
+
+    startupinfo :
+        Windows only
+
+    creationflags :
+        Windows only
+
+    preexec_fn :
+        (POSIX only) An object to be called in the child process just before the child
+        is executed.
+
+    restore_signals :
+        POSIX only
+
+    start_new_session :
+        POSIX only
+
+    group :
+        POSIX only
+
+    extra_groups :
+        POSIX only
+
+    user :
+        POSIX only
+
+    umask :
+        POSIX only
+
+    pass_fds :
+        POSIX only
+
+    encoding :
+        Text mode encoding to use for file objects stdin, stdout and stderr.
+
+    errors :
+        Text mode error handling to use for file objects stdin, stdout and stderr.
+
+    Examples
+    --------
+    >>> cmd = SubprocessCommand("ls")
+    >>> cmd.args
+    'ls'
+
+    With ``shell=True``:
+
+    >>> cmd = SubprocessCommand("ls -l", shell=True)
+    >>> cmd.shell
+    True
+    >>> cmd.args
+    'ls -l'
+    >>> cmd.check_call()
+    0
+    """
+
+    args: "_CMD"
+    bufsize: int = -1
+    executable: Optional[StrOrBytesPath] = None
+    stdin: _FILE = None
+    stdout: _FILE = None
+    stderr: _FILE = None
+    preexec_fn: Optional[Callable[[], Any]] = None
+    close_fds: bool = True
+    shell: bool = False
+    cwd: Optional[StrOrBytesPath] = None
+    env: Optional[_ENV] = None
+
+    # Windows
+    creationflags: int = 0
+    startupinfo: Optional[Any] = None
+
+    # POSIX-only
+    restore_signals: bool = True
+    start_new_session: bool = False
+    pass_fds: Any = ()
+    if sys.version_info >= (3, 9):
+        umask: int = -1
+    if sys.version_info >= (3, 10):
+        pipesize: int = -1
+
+    if sys.version_info >= (3, 9):
+        user: Optional[str] = None
+        group: Optional[str] = None
+        extra_groups: Optional[List[str]] = None
+
+    # Alias of text, for backwards compatibility
+    universal_newlines: Optional[bool] = None
+    text: Optional[Literal[True]] = None
+
+    # Text mode encoding and error handling to use for file objects
+    # stdin, stdout, stderr
+    encoding: Optional[str] = None
+    errors: Optional[str] = None
+
+    # user, group, extra_groups, umask were added in 3.9
+    @overload
+    def Popen(
+        self,
+        args: Optional["_CMD"] = ...,
+        universal_newlines: bool = ...,
+        *,
+        text: Optional[bool] = ...,
+        encoding: str,
+        errors: Optional[str] = ...,
+    ) -> "subprocess.Popen[str]":
+        ...
+
+    @overload
+    def Popen(
+        self,
+        args: Optional["_CMD"] = ...,
+        universal_newlines: bool = ...,
+        *,
+        text: Optional[bool] = ...,
+        encoding: Optional[str] = ...,
+        errors: str,
+    ) -> "subprocess.Popen[str]":
+        ...
+
+    @overload
+    def Popen(
+        self,
+        args: Optional["_CMD"] = ...,
+        *,
+        universal_newlines: Literal[True],
+        # where the *real* keyword only args start
+        text: Optional[bool] = ...,
+        encoding: Optional[str] = ...,
+        errors: Optional[str] = ...,
+    ) -> "subprocess.Popen[str]":
+        ...
+
+    @overload
+    def Popen(
+        self,
+        args: Optional["_CMD"] = ...,
+        universal_newlines: bool = ...,
+        *,
+        text: Literal[True],
+        encoding: Optional[str] = ...,
+        errors: Optional[str] = ...,
+    ) -> "subprocess.Popen[str]":
+        ...
+
+    @overload
+    def Popen(
+        self,
+        args: Optional["_CMD"] = ...,
+        universal_newlines: Literal[False] = ...,
+        *,
+        text: Literal[None, False] = ...,
+        encoding: None = ...,
+        errors: None = ...,
+    ) -> "subprocess.Popen[bytes]":
+        ...
+
+    def Popen(
+        self,
+        args: Optional["_CMD"] = None,
+        universal_newlines: Optional[bool] = None,
+        *,
+        text: Optional[bool] = None,
+        encoding: Optional[str] = None,
+        errors: Optional[str] = None,
+        **kwargs: Any,
+    ) -> "subprocess.Popen[Any]":
+        """Run commands :class:`subprocess.Popen`, optionally overrides via kwargs.
+
+        Parameters
+        ----------
+        **kwargs : dict, optional
+            Overrides existing attributes for :class:`subprocess.Popen`
+
+        Examples
+        --------
+        >>> cmd = SubprocessCommand(args=['echo', 'hello'])
+        >>> proc = cmd.Popen(stdout=subprocess.PIPE)
+        >>> proc.communicate() # doctest: +SKIP
+        """
+        return subprocess.Popen(
+            **dataclasses.replace(
+                self,
+                args=args or self.args,
+                encoding=encoding,
+                errors=errors,
+                text=text,
+                universal_newlines=universal_newlines,
+                **kwargs,
+            ).__dict__,
+        )
+
+    def check_call(self, **kwargs: Any) -> int:
+        """Run command :func:`subprocess.check_call`, optionally overrides via kwargs.
+
+        Parameters
+        ----------
+        **kwargs : dict, optional
+            Overrides existing attributes for :func:`subprocess.check_call`
+
+        Examples
+        --------
+        >>> cmd = SubprocessCommand(args=['echo', 'hello'])
+        >>> cmd.check_call(stdout=subprocess.PIPE)
+        0
+        """
+        return subprocess.check_call(**dataclasses.replace(self, **kwargs).__dict__)
+
+    @overload
+    def check_output(
+        self,
+        universal_newlines: bool = ...,
+        *,
+        input: Optional[Union[str, bytes]] = ...,
+        encoding: Optional[str] = ...,
+        errors: Optional[str] = ...,
+        text: Literal[True],
+        **kwargs: Any,
+    ) -> str:
+        ...
+
+    @overload
+    def check_output(
+        self,
+        universal_newlines: Optional[bool] = ...,
+        *,
+        input: Optional[Union[str, bytes]] = ...,
+        encoding: str,
+        errors: Optional[str] = ...,
+        text: Optional[bool] = ...,
+        **kwargs: Any,
+    ) -> str:
+        ...
+
+    @overload
+    def check_output(
+        self,
+        universal_newlines: bool = ...,
+        *,
+        input: Optional[Union[str, bytes]] = ...,
+        encoding: Optional[str] = ...,
+        errors: str,
+        text: Optional[bool] = ...,
+        **kwargs: Any,
+    ) -> str:
+        ...
+
+    @overload
+    def check_output(
+        self,
+        universal_newlines: Literal[True] = ...,
+        *,
+        input: Optional[Union[str, bytes]] = ...,
+        encoding: Optional[str] = ...,
+        errors: Optional[str] = ...,
+        text: Optional[bool] = ...,
+        **kwargs: Any,
+    ) -> str:
+        ...
+
+    @overload
+    def check_output(
+        self,
+        universal_newlines: Literal[False],
+        *,
+        input: Optional[Union[str, bytes]] = ...,
+        encoding: None = ...,
+        errors: None = ...,
+        text: Literal[None, False] = ...,
+        **kwargs: Any,
+    ) -> bytes:
+        ...
+
+    def check_output(
+        self,
+        universal_newlines: Optional[bool] = None,
+        *,
+        input: Optional[Union[str, bytes]] = None,
+        encoding: Optional[str] = None,
+        errors: Optional[str] = None,
+        text: Optional[bool] = None,
+        **kwargs: Any,
+    ) -> Union[bytes, str]:
+        r"""Run command :func:`subprocess.check_output`, optionally override via kwargs.
+
+        Parameters
+        ----------
+        input : Union[bytes, str], optional
+            pass string to subprocess's stdin. Bytes by default, str in text mode.
+
+            Text mode is triggered by setting any of text, encoding, errors or
+            universal_newlines.
+        **kwargs : dict, optional
+            Overrides existing attributes for :func:`subprocess.check_output`
+
+        Examples
+        --------
+        >>> cmd = SubprocessCommand(args=['echo', 'hello'])
+        >>> proc = cmd.check_output(shell=True)
+
+        Examples from :mod:`subprocess`:
+
+        >>> import subprocess
+        >>> cmd = SubprocessCommand(
+        ...     ["/bin/sh", "-c", "ls -l non_existent_file ; exit 0"])
+        >>> cmd.check_output(stderr=subprocess.STDOUT)
+        b"ls: ...non_existent_file...: No such file or directory\n"
+
+        >>> cmd = SubprocessCommand(["sed", "-e", "s/foo/bar/"])
+        >>> cmd.check_output(input=b"when in the course of fooman events\n")
+        b'when in the course of barman events\n'
+        """
+        params = dataclasses.replace(self, **kwargs).__dict__
+        params.pop("stdout")
+        output = subprocess.check_output(input=input, **params)
+        if isinstance(output, (bytes, str)):
+            return output
+        raise Exception(f"output is not str or bytes: {output}")
+
+    @overload
+    def run(
+        self,
+        universal_newlines: bool = ...,
+        *,
+        capture_output: bool = ...,
+        check: bool = ...,
+        encoding: Optional[str] = ...,
+        errors: Optional[str] = ...,
+        input: Optional[str] = ...,
+        text: Literal[True],
+    ) -> "subprocess.CompletedProcess[str]":
+        ...
+
+    @overload
+    def run(
+        self,
+        universal_newlines: bool = ...,
+        *,
+        capture_output: bool = ...,
+        check: bool = ...,
+        encoding: str,
+        errors: Optional[str] = ...,
+        input: Optional[str] = ...,
+        text: Optional[bool] = ...,
+    ) -> "subprocess.CompletedProcess[str]":
+        ...
+
+    @overload
+    def run(
+        self,
+        universal_newlines: bool = ...,
+        *,
+        capture_output: bool = ...,
+        check: bool = ...,
+        encoding: Optional[str] = ...,
+        errors: str,
+        input: Optional[str] = ...,
+        text: Optional[bool] = ...,
+    ) -> "subprocess.CompletedProcess[str]":
+        ...
+
+    @overload
+    def run(
+        self,
+        *,
+        universal_newlines: Literal[True],
+        # where the *real* keyword only args start
+        capture_output: bool = ...,
+        check: bool = ...,
+        encoding: Optional[str] = ...,
+        errors: Optional[str] = ...,
+        input: Optional[str] = ...,
+        text: Optional[bool] = ...,
+    ) -> "subprocess.CompletedProcess[str]":
+        ...
+
+    @overload
+    def run(
+        self,
+        universal_newlines: Literal[False] = ...,
+        *,
+        capture_output: bool = ...,
+        check: bool = ...,
+        encoding: None = ...,
+        errors: None = ...,
+        input: Optional[bytes] = ...,
+        text: Literal[None, False] = ...,
+    ) -> "subprocess.CompletedProcess[bytes]":
+        ...
+
+    def run(
+        self,
+        universal_newlines: Optional[bool] = None,
+        *,
+        capture_output: bool = False,
+        check: bool = False,
+        encoding: Optional[str] = None,
+        errors: Optional[str] = None,
+        input: Optional[Union[str, bytes]] = None,
+        text: Optional[bool] = None,
+        timeout: Optional[float] = None,
+        **kwargs: Any,
+    ) -> "subprocess.CompletedProcess[Any]":
+        r"""Run command in :func:`subprocess.run`, optionally overrides via kwargs.
+
+        Parameters
+        ----------
+        input : Union[bytes, str], optional
+            pass string to subprocess's stdin. Bytes by default, str in text mode.
+
+            Text mode is triggered by setting any of text, encoding, errors or
+            universal_newlines.
+
+        check : bool
+            If True and the exit code was non-zero, it raises a
+            :exc:`subprocess.CalledProcessError`. The CalledProcessError object will
+            have the return code in the returncode attribute, and output & stderr
+            attributes if those streams were captured.
+
+        timeout : int
+            If given, and the process takes too long, a :exc:`subprocess.TimeoutExpired`
+
+        **kwargs : dict, optional
+            Overrides existing attributes for :func:`subprocess.run`
+
+        Examples
+        --------
+        >>> import subprocess
+        >>> cmd = SubprocessCommand(
+        ...     ["/bin/sh", "-c", "ls -l non_existent_file ; exit 0"])
+        >>> cmd.run()
+        CompletedProcess(args=['/bin/sh', '-c', 'ls -l non_existent_file ; exit 0'],
+                         returncode=0)
+
+        >>> import subprocess
+        >>> cmd = SubprocessCommand(
+        ...     ["/bin/sh", "-c", "ls -l non_existent_file ; exit 0"])
+        >>> cmd.run(check=True)
+        CompletedProcess(args=['/bin/sh', '-c', 'ls -l non_existent_file ; exit 0'],
+                         returncode=0)
+
+        >>> cmd = SubprocessCommand(["sed", "-e", "s/foo/bar/"])
+        >>> completed = cmd.run(input=b"when in the course of fooman events\n")
+        >>> completed
+        CompletedProcess(args=['sed', '-e', 's/foo/bar/'], returncode=0)
+        >>> completed.stderr
+
+        >>> cmd = SubprocessCommand(["sed", "-e", "s/foo/bar/"])
+        >>> completed = cmd.run(input=b"when in the course of fooman events\n",
+        ...                     capture_output=True)
+        >>> completed
+        CompletedProcess(args=['sed', '-e', 's/foo/bar/'], returncode=0,
+                        stdout=b'when in the course of barman events\n', stderr=b'')
+        >>> completed.stdout
+        b'when in the course of barman events\n'
+        >>> completed.stderr
+        b''
+        """
+        return subprocess.run(
+            **dataclasses.replace(
+                self,
+                universal_newlines=universal_newlines,
+                errors=errors,
+                text=text,
+                **kwargs,
+            ).__dict__,
+            check=check,
+            capture_output=capture_output,
+            input=input,
+            timeout=timeout,
+        )
diff --git a/src/libtmux/_internal/types.py b/src/libtmux/_internal/types.py
new file mode 100644
index 000000000..b092268a7
--- /dev/null
+++ b/src/libtmux/_internal/types.py
@@ -0,0 +1,22 @@
+"""Internal :term:`type annotations `
+
+Notes
+-----
+
+:class:`StrPath` and :class:`StrOrBytesPath` is based on `typeshed's`_.
+
+.. _typeshed's: https://github.com/python/typeshed/blob/5df8de7/stdlib/_typeshed/__init__.pyi#L115-L118
+"""  # NOQA E501
+from os import PathLike
+from typing import TYPE_CHECKING, Union
+
+if TYPE_CHECKING:
+    from typing_extensions import TypeAlias
+
+StrPath: "TypeAlias" = Union[str, "PathLike[str]"]  # stable
+""":class:`os.PathLike` or :class:`str`"""
+
+StrOrBytesPath: "TypeAlias" = Union[
+    str, bytes, "PathLike[str]", "PathLike[bytes]"
+]  # stable
+""":class:`os.PathLike`, :class:`str` or :term:`bytes-like object`"""

From c62c82ef415872c37372a103dcecf923730f70ea Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Mon, 26 Dec 2022 16:11:19 -0600
Subject: [PATCH 0210/1073] chore: Remove subprocess (unused, keeping for
 types)

---
 src/libtmux/_internal/subprocess.py | 587 ----------------------------
 1 file changed, 587 deletions(-)
 delete mode 100644 src/libtmux/_internal/subprocess.py

diff --git a/src/libtmux/_internal/subprocess.py b/src/libtmux/_internal/subprocess.py
deleted file mode 100644
index 1059a478f..000000000
--- a/src/libtmux/_internal/subprocess.py
+++ /dev/null
@@ -1,587 +0,0 @@
-"""Invokable :mod:`subprocess` wrapper.
-
-Defer running a subprocess, such as by handing to an executor.
-
-Note
-----
-This is an internal API not covered by versioning policy.
-
-Examples
---------
-
-- :class:`~SubprocessCommand`: Wraps :class:`subprocess.Popen` and
-  :func:`subprocess.run` in a :func:`~dataclasses.dataclass`.
-
-  Before:
-
-  >>> import subprocess
-  >>> subprocess.run(
-  ...    ['echo', 'hi'],
-  ...    capture_output=True, universal_newlines=True
-  ... ).stdout
-  'hi\\n'
-
-  With this:
-
-  >>> cmd = SubprocessCommand(['echo', 'hi'])
-  >>> cmd.args
-  ['echo', 'hi']
-  >>> cmd.run(capture_output=True, universal_newlines=True).stdout
-  'hi\\n'
-
-  Tweak params before invocation:
-
-  >>> cmd = SubprocessCommand(['echo', 'hi'])
-  >>> cmd.args[1] = 'hello'
-  >>> cmd.args
-  ['echo', 'hello']
-  >>> cmd.run(capture_output=True, universal_newlines=True).stdout
-  'hello\\n'
-"""
-import dataclasses
-import subprocess
-import sys
-from collections.abc import Mapping, Sequence
-from typing import (
-    IO,
-    TYPE_CHECKING,
-    Any,
-    Callable,
-    List,
-    Optional,
-    TypeVar,
-    Union,
-    overload,
-)
-
-from typing_extensions import Literal, TypeAlias
-
-from .dataclasses import SkipDefaultFieldsReprMixin
-from .types import StrOrBytesPath
-
-F = TypeVar("F", bound=Callable[..., Any])
-
-
-if sys.platform == "win32":
-    _ENV: TypeAlias = "Mapping[str, str]"
-else:
-    _ENV: TypeAlias = Union[
-        "Mapping[bytes, StrOrBytesPath]", "Mapping[str, StrOrBytesPath]"
-    ]
-_FILE: TypeAlias = Union[None, int, IO[Any]]
-_TXT: TypeAlias = Union[bytes, str]
-
-if TYPE_CHECKING:
-    #: Command
-    _CMD: TypeAlias = Union[StrOrBytesPath, "Sequence[StrOrBytesPath]"]
-
-
-@dataclasses.dataclass(repr=False)
-class SubprocessCommand(SkipDefaultFieldsReprMixin):
-    """Wraps a :mod:`subprocess` request. Inspect, mutate, control before invocation.
-
-    Attributes
-    ----------
-    args : _CMD
-        A string, or a sequence of program arguments.
-
-    bufsize : int
-        supplied as the buffering argument to the open() function when creating the
-        stdin/stdout/stderr pipe file objects
-
-    executable : Optional[StrOrBytesPath]
-        A replacement program to execute.
-
-    stdin : _FILE
-        standard output for executed program
-
-    stdout :
-        standard output for executed program
-
-    stderr :
-        standard output for executed program
-
-    close_fds : Controls closing or inheriting of file descriptors.
-
-    shell : If true, the command will be executed through the shell.
-
-    cwd : Sets the current directory before the child is executed.
-
-    env : Defines the environment variables for the new process.
-
-    text :
-        If ``True``, decode stdin, stdout and stderr using the given encoding (if set)
-        or the system default otherwise.
-
-    universal_newlines :
-        Alias of text, provided for backwards compatibility.
-
-    startupinfo :
-        Windows only
-
-    creationflags :
-        Windows only
-
-    preexec_fn :
-        (POSIX only) An object to be called in the child process just before the child
-        is executed.
-
-    restore_signals :
-        POSIX only
-
-    start_new_session :
-        POSIX only
-
-    group :
-        POSIX only
-
-    extra_groups :
-        POSIX only
-
-    user :
-        POSIX only
-
-    umask :
-        POSIX only
-
-    pass_fds :
-        POSIX only
-
-    encoding :
-        Text mode encoding to use for file objects stdin, stdout and stderr.
-
-    errors :
-        Text mode error handling to use for file objects stdin, stdout and stderr.
-
-    Examples
-    --------
-    >>> cmd = SubprocessCommand("ls")
-    >>> cmd.args
-    'ls'
-
-    With ``shell=True``:
-
-    >>> cmd = SubprocessCommand("ls -l", shell=True)
-    >>> cmd.shell
-    True
-    >>> cmd.args
-    'ls -l'
-    >>> cmd.check_call()
-    0
-    """
-
-    args: "_CMD"
-    bufsize: int = -1
-    executable: Optional[StrOrBytesPath] = None
-    stdin: _FILE = None
-    stdout: _FILE = None
-    stderr: _FILE = None
-    preexec_fn: Optional[Callable[[], Any]] = None
-    close_fds: bool = True
-    shell: bool = False
-    cwd: Optional[StrOrBytesPath] = None
-    env: Optional[_ENV] = None
-
-    # Windows
-    creationflags: int = 0
-    startupinfo: Optional[Any] = None
-
-    # POSIX-only
-    restore_signals: bool = True
-    start_new_session: bool = False
-    pass_fds: Any = ()
-    if sys.version_info >= (3, 9):
-        umask: int = -1
-    if sys.version_info >= (3, 10):
-        pipesize: int = -1
-
-    if sys.version_info >= (3, 9):
-        user: Optional[str] = None
-        group: Optional[str] = None
-        extra_groups: Optional[List[str]] = None
-
-    # Alias of text, for backwards compatibility
-    universal_newlines: Optional[bool] = None
-    text: Optional[Literal[True]] = None
-
-    # Text mode encoding and error handling to use for file objects
-    # stdin, stdout, stderr
-    encoding: Optional[str] = None
-    errors: Optional[str] = None
-
-    # user, group, extra_groups, umask were added in 3.9
-    @overload
-    def Popen(
-        self,
-        args: Optional["_CMD"] = ...,
-        universal_newlines: bool = ...,
-        *,
-        text: Optional[bool] = ...,
-        encoding: str,
-        errors: Optional[str] = ...,
-    ) -> "subprocess.Popen[str]":
-        ...
-
-    @overload
-    def Popen(
-        self,
-        args: Optional["_CMD"] = ...,
-        universal_newlines: bool = ...,
-        *,
-        text: Optional[bool] = ...,
-        encoding: Optional[str] = ...,
-        errors: str,
-    ) -> "subprocess.Popen[str]":
-        ...
-
-    @overload
-    def Popen(
-        self,
-        args: Optional["_CMD"] = ...,
-        *,
-        universal_newlines: Literal[True],
-        # where the *real* keyword only args start
-        text: Optional[bool] = ...,
-        encoding: Optional[str] = ...,
-        errors: Optional[str] = ...,
-    ) -> "subprocess.Popen[str]":
-        ...
-
-    @overload
-    def Popen(
-        self,
-        args: Optional["_CMD"] = ...,
-        universal_newlines: bool = ...,
-        *,
-        text: Literal[True],
-        encoding: Optional[str] = ...,
-        errors: Optional[str] = ...,
-    ) -> "subprocess.Popen[str]":
-        ...
-
-    @overload
-    def Popen(
-        self,
-        args: Optional["_CMD"] = ...,
-        universal_newlines: Literal[False] = ...,
-        *,
-        text: Literal[None, False] = ...,
-        encoding: None = ...,
-        errors: None = ...,
-    ) -> "subprocess.Popen[bytes]":
-        ...
-
-    def Popen(
-        self,
-        args: Optional["_CMD"] = None,
-        universal_newlines: Optional[bool] = None,
-        *,
-        text: Optional[bool] = None,
-        encoding: Optional[str] = None,
-        errors: Optional[str] = None,
-        **kwargs: Any,
-    ) -> "subprocess.Popen[Any]":
-        """Run commands :class:`subprocess.Popen`, optionally overrides via kwargs.
-
-        Parameters
-        ----------
-        **kwargs : dict, optional
-            Overrides existing attributes for :class:`subprocess.Popen`
-
-        Examples
-        --------
-        >>> cmd = SubprocessCommand(args=['echo', 'hello'])
-        >>> proc = cmd.Popen(stdout=subprocess.PIPE)
-        >>> proc.communicate() # doctest: +SKIP
-        """
-        return subprocess.Popen(
-            **dataclasses.replace(
-                self,
-                args=args or self.args,
-                encoding=encoding,
-                errors=errors,
-                text=text,
-                universal_newlines=universal_newlines,
-                **kwargs,
-            ).__dict__,
-        )
-
-    def check_call(self, **kwargs: Any) -> int:
-        """Run command :func:`subprocess.check_call`, optionally overrides via kwargs.
-
-        Parameters
-        ----------
-        **kwargs : dict, optional
-            Overrides existing attributes for :func:`subprocess.check_call`
-
-        Examples
-        --------
-        >>> cmd = SubprocessCommand(args=['echo', 'hello'])
-        >>> cmd.check_call(stdout=subprocess.PIPE)
-        0
-        """
-        return subprocess.check_call(**dataclasses.replace(self, **kwargs).__dict__)
-
-    @overload
-    def check_output(
-        self,
-        universal_newlines: bool = ...,
-        *,
-        input: Optional[Union[str, bytes]] = ...,
-        encoding: Optional[str] = ...,
-        errors: Optional[str] = ...,
-        text: Literal[True],
-        **kwargs: Any,
-    ) -> str:
-        ...
-
-    @overload
-    def check_output(
-        self,
-        universal_newlines: Optional[bool] = ...,
-        *,
-        input: Optional[Union[str, bytes]] = ...,
-        encoding: str,
-        errors: Optional[str] = ...,
-        text: Optional[bool] = ...,
-        **kwargs: Any,
-    ) -> str:
-        ...
-
-    @overload
-    def check_output(
-        self,
-        universal_newlines: bool = ...,
-        *,
-        input: Optional[Union[str, bytes]] = ...,
-        encoding: Optional[str] = ...,
-        errors: str,
-        text: Optional[bool] = ...,
-        **kwargs: Any,
-    ) -> str:
-        ...
-
-    @overload
-    def check_output(
-        self,
-        universal_newlines: Literal[True] = ...,
-        *,
-        input: Optional[Union[str, bytes]] = ...,
-        encoding: Optional[str] = ...,
-        errors: Optional[str] = ...,
-        text: Optional[bool] = ...,
-        **kwargs: Any,
-    ) -> str:
-        ...
-
-    @overload
-    def check_output(
-        self,
-        universal_newlines: Literal[False],
-        *,
-        input: Optional[Union[str, bytes]] = ...,
-        encoding: None = ...,
-        errors: None = ...,
-        text: Literal[None, False] = ...,
-        **kwargs: Any,
-    ) -> bytes:
-        ...
-
-    def check_output(
-        self,
-        universal_newlines: Optional[bool] = None,
-        *,
-        input: Optional[Union[str, bytes]] = None,
-        encoding: Optional[str] = None,
-        errors: Optional[str] = None,
-        text: Optional[bool] = None,
-        **kwargs: Any,
-    ) -> Union[bytes, str]:
-        r"""Run command :func:`subprocess.check_output`, optionally override via kwargs.
-
-        Parameters
-        ----------
-        input : Union[bytes, str], optional
-            pass string to subprocess's stdin. Bytes by default, str in text mode.
-
-            Text mode is triggered by setting any of text, encoding, errors or
-            universal_newlines.
-        **kwargs : dict, optional
-            Overrides existing attributes for :func:`subprocess.check_output`
-
-        Examples
-        --------
-        >>> cmd = SubprocessCommand(args=['echo', 'hello'])
-        >>> proc = cmd.check_output(shell=True)
-
-        Examples from :mod:`subprocess`:
-
-        >>> import subprocess
-        >>> cmd = SubprocessCommand(
-        ...     ["/bin/sh", "-c", "ls -l non_existent_file ; exit 0"])
-        >>> cmd.check_output(stderr=subprocess.STDOUT)
-        b"ls: ...non_existent_file...: No such file or directory\n"
-
-        >>> cmd = SubprocessCommand(["sed", "-e", "s/foo/bar/"])
-        >>> cmd.check_output(input=b"when in the course of fooman events\n")
-        b'when in the course of barman events\n'
-        """
-        params = dataclasses.replace(self, **kwargs).__dict__
-        params.pop("stdout")
-        output = subprocess.check_output(input=input, **params)
-        if isinstance(output, (bytes, str)):
-            return output
-        raise Exception(f"output is not str or bytes: {output}")
-
-    @overload
-    def run(
-        self,
-        universal_newlines: bool = ...,
-        *,
-        capture_output: bool = ...,
-        check: bool = ...,
-        encoding: Optional[str] = ...,
-        errors: Optional[str] = ...,
-        input: Optional[str] = ...,
-        text: Literal[True],
-    ) -> "subprocess.CompletedProcess[str]":
-        ...
-
-    @overload
-    def run(
-        self,
-        universal_newlines: bool = ...,
-        *,
-        capture_output: bool = ...,
-        check: bool = ...,
-        encoding: str,
-        errors: Optional[str] = ...,
-        input: Optional[str] = ...,
-        text: Optional[bool] = ...,
-    ) -> "subprocess.CompletedProcess[str]":
-        ...
-
-    @overload
-    def run(
-        self,
-        universal_newlines: bool = ...,
-        *,
-        capture_output: bool = ...,
-        check: bool = ...,
-        encoding: Optional[str] = ...,
-        errors: str,
-        input: Optional[str] = ...,
-        text: Optional[bool] = ...,
-    ) -> "subprocess.CompletedProcess[str]":
-        ...
-
-    @overload
-    def run(
-        self,
-        *,
-        universal_newlines: Literal[True],
-        # where the *real* keyword only args start
-        capture_output: bool = ...,
-        check: bool = ...,
-        encoding: Optional[str] = ...,
-        errors: Optional[str] = ...,
-        input: Optional[str] = ...,
-        text: Optional[bool] = ...,
-    ) -> "subprocess.CompletedProcess[str]":
-        ...
-
-    @overload
-    def run(
-        self,
-        universal_newlines: Literal[False] = ...,
-        *,
-        capture_output: bool = ...,
-        check: bool = ...,
-        encoding: None = ...,
-        errors: None = ...,
-        input: Optional[bytes] = ...,
-        text: Literal[None, False] = ...,
-    ) -> "subprocess.CompletedProcess[bytes]":
-        ...
-
-    def run(
-        self,
-        universal_newlines: Optional[bool] = None,
-        *,
-        capture_output: bool = False,
-        check: bool = False,
-        encoding: Optional[str] = None,
-        errors: Optional[str] = None,
-        input: Optional[Union[str, bytes]] = None,
-        text: Optional[bool] = None,
-        timeout: Optional[float] = None,
-        **kwargs: Any,
-    ) -> "subprocess.CompletedProcess[Any]":
-        r"""Run command in :func:`subprocess.run`, optionally overrides via kwargs.
-
-        Parameters
-        ----------
-        input : Union[bytes, str], optional
-            pass string to subprocess's stdin. Bytes by default, str in text mode.
-
-            Text mode is triggered by setting any of text, encoding, errors or
-            universal_newlines.
-
-        check : bool
-            If True and the exit code was non-zero, it raises a
-            :exc:`subprocess.CalledProcessError`. The CalledProcessError object will
-            have the return code in the returncode attribute, and output & stderr
-            attributes if those streams were captured.
-
-        timeout : int
-            If given, and the process takes too long, a :exc:`subprocess.TimeoutExpired`
-
-        **kwargs : dict, optional
-            Overrides existing attributes for :func:`subprocess.run`
-
-        Examples
-        --------
-        >>> import subprocess
-        >>> cmd = SubprocessCommand(
-        ...     ["/bin/sh", "-c", "ls -l non_existent_file ; exit 0"])
-        >>> cmd.run()
-        CompletedProcess(args=['/bin/sh', '-c', 'ls -l non_existent_file ; exit 0'],
-                         returncode=0)
-
-        >>> import subprocess
-        >>> cmd = SubprocessCommand(
-        ...     ["/bin/sh", "-c", "ls -l non_existent_file ; exit 0"])
-        >>> cmd.run(check=True)
-        CompletedProcess(args=['/bin/sh', '-c', 'ls -l non_existent_file ; exit 0'],
-                         returncode=0)
-
-        >>> cmd = SubprocessCommand(["sed", "-e", "s/foo/bar/"])
-        >>> completed = cmd.run(input=b"when in the course of fooman events\n")
-        >>> completed
-        CompletedProcess(args=['sed', '-e', 's/foo/bar/'], returncode=0)
-        >>> completed.stderr
-
-        >>> cmd = SubprocessCommand(["sed", "-e", "s/foo/bar/"])
-        >>> completed = cmd.run(input=b"when in the course of fooman events\n",
-        ...                     capture_output=True)
-        >>> completed
-        CompletedProcess(args=['sed', '-e', 's/foo/bar/'], returncode=0,
-                        stdout=b'when in the course of barman events\n', stderr=b'')
-        >>> completed.stdout
-        b'when in the course of barman events\n'
-        >>> completed.stderr
-        b''
-        """
-        return subprocess.run(
-            **dataclasses.replace(
-                self,
-                universal_newlines=universal_newlines,
-                errors=errors,
-                text=text,
-                **kwargs,
-            ).__dict__,
-            check=check,
-            capture_output=capture_output,
-            input=input,
-            timeout=timeout,
-        )

From 91b59ddb60580c1f28c98d9b706b3f111d9aab8e Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Mon, 26 Dec 2022 16:16:11 -0600
Subject: [PATCH 0211/1073] chore(internals): Remove types module for now, keep
 for adjustments

These were retrofitting to support Python 3.7, so keep in git history
in case we ever bring it back.
---
 src/libtmux/_internal/types.py | 22 ----------------------
 1 file changed, 22 deletions(-)
 delete mode 100644 src/libtmux/_internal/types.py

diff --git a/src/libtmux/_internal/types.py b/src/libtmux/_internal/types.py
deleted file mode 100644
index b092268a7..000000000
--- a/src/libtmux/_internal/types.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"""Internal :term:`type annotations `
-
-Notes
------
-
-:class:`StrPath` and :class:`StrOrBytesPath` is based on `typeshed's`_.
-
-.. _typeshed's: https://github.com/python/typeshed/blob/5df8de7/stdlib/_typeshed/__init__.pyi#L115-L118
-"""  # NOQA E501
-from os import PathLike
-from typing import TYPE_CHECKING, Union
-
-if TYPE_CHECKING:
-    from typing_extensions import TypeAlias
-
-StrPath: "TypeAlias" = Union[str, "PathLike[str]"]  # stable
-""":class:`os.PathLike` or :class:`str`"""
-
-StrOrBytesPath: "TypeAlias" = Union[
-    str, bytes, "PathLike[str]", "PathLike[bytes]"
-]  # stable
-""":class:`os.PathLike`, :class:`str` or :term:`bytes-like object`"""

From 4cc7849c8e688f7f291f1bc6f11d81e4fed327ad Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Mon, 26 Dec 2022 13:02:56 -0600
Subject: [PATCH 0212/1073] feat(QueryList): Add .get()

---
 src/libtmux/_internal/query_list.py | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/src/libtmux/_internal/query_list.py b/src/libtmux/_internal/query_list.py
index 70af21f0b..05354cd57 100644
--- a/src/libtmux/_internal/query_list.py
+++ b/src/libtmux/_internal/query_list.py
@@ -27,6 +27,8 @@ def __call__(
 
 T = TypeVar("T", Any, Any)
 
+no_arg = object()
+
 
 def keygetter(
     obj: "Mapping[str, Any]",
@@ -347,3 +349,18 @@ def val_match(obj: Union[str, List[Any]]) -> bool:
             _filter = filter_lookup
 
         return self.__class__(k for k in self if _filter(k))
+
+    def get(
+        self,
+        matcher: Optional[Union[Callable[[T], bool], T]] = None,
+        default: Optional[Any] = no_arg,
+        **kwargs: Any,
+    ) -> Optional[T]:
+        objs = self.filter(matcher=matcher, **kwargs)
+        if len(objs) > 1:
+            raise Exception("Multiple objects returned")
+        elif len(objs) == 0:
+            if default == no_arg:
+                raise Exception("No objects found")
+            return default
+        return objs[0]

From f536105df6c6066f9f20fda2381453ca85bece8b Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Sat, 17 Dec 2022 21:22:17 -0600
Subject: [PATCH 0213/1073] Add tests for legacy API

---
 tests/legacy_api/__init__.py        |   0
 tests/legacy_api/test_common.py     | 212 ++++++++++++++++
 tests/legacy_api/test_pane.py       |  88 +++++++
 tests/legacy_api/test_server.py     | 158 ++++++++++++
 tests/legacy_api/test_session.py    | 314 ++++++++++++++++++++++++
 tests/legacy_api/test_test.py       |  88 +++++++
 tests/legacy_api/test_tmuxobject.py | 191 +++++++++++++++
 tests/legacy_api/test_version.py    |  70 ++++++
 tests/legacy_api/test_window.py     | 367 ++++++++++++++++++++++++++++
 9 files changed, 1488 insertions(+)
 create mode 100644 tests/legacy_api/__init__.py
 create mode 100644 tests/legacy_api/test_common.py
 create mode 100644 tests/legacy_api/test_pane.py
 create mode 100644 tests/legacy_api/test_server.py
 create mode 100644 tests/legacy_api/test_session.py
 create mode 100644 tests/legacy_api/test_test.py
 create mode 100644 tests/legacy_api/test_tmuxobject.py
 create mode 100644 tests/legacy_api/test_version.py
 create mode 100644 tests/legacy_api/test_window.py

diff --git a/tests/legacy_api/__init__.py b/tests/legacy_api/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/legacy_api/test_common.py b/tests/legacy_api/test_common.py
new file mode 100644
index 000000000..da9bcdeea
--- /dev/null
+++ b/tests/legacy_api/test_common.py
@@ -0,0 +1,212 @@
+"""Tests for utility functions in libtmux."""
+
+import re
+import sys
+import typing as t
+from typing import Optional
+
+import pytest
+
+import libtmux
+from libtmux._compat import LooseVersion
+from libtmux.common import (
+    TMUX_MAX_VERSION,
+    TMUX_MIN_VERSION,
+    get_libtmux_version,
+    get_version,
+    has_gt_version,
+    has_gte_version,
+    has_lt_version,
+    has_lte_version,
+    has_minimum_version,
+    has_version,
+    session_check_name,
+    tmux_cmd,
+)
+from libtmux.exc import BadSessionName, LibTmuxException, TmuxCommandNotFound
+from libtmux.session import Session
+
+version_regex = re.compile(r"([0-9]\.[0-9])|(master)")
+
+
+def test_allows_master_version(monkeypatch: pytest.MonkeyPatch) -> None:
+    class Hi:
+        stdout = ["tmux master"]
+        stderr = None
+
+    def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi:
+        return Hi()
+
+    monkeypatch.setattr(libtmux.common, "tmux_cmd", mock_tmux_cmd)
+
+    assert has_minimum_version()
+    assert has_gte_version(TMUX_MIN_VERSION)
+    assert has_gt_version(TMUX_MAX_VERSION), "Greater than the max-supported version"
+    assert (
+        "%s-master" % TMUX_MAX_VERSION == get_version()
+    ), "Is the latest supported version with -master appended"
+
+
+def test_allows_next_version(monkeypatch: pytest.MonkeyPatch) -> None:
+    TMUX_NEXT_VERSION = str(float(TMUX_MAX_VERSION) + 0.1)
+
+    class Hi:
+        stdout = [f"tmux next-{TMUX_NEXT_VERSION}"]
+        stderr = None
+
+    def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi:
+        return Hi()
+
+    monkeypatch.setattr(libtmux.common, "tmux_cmd", mock_tmux_cmd)
+
+    assert has_minimum_version()
+    assert has_gte_version(TMUX_MIN_VERSION)
+    assert has_gt_version(TMUX_MAX_VERSION), "Greater than the max-supported version"
+    assert TMUX_NEXT_VERSION == get_version()
+
+
+def test_get_version_openbsd(monkeypatch: pytest.MonkeyPatch) -> None:
+    class Hi:
+        stderr = ["tmux: unknown option -- V"]
+
+    def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi:
+        return Hi()
+
+    monkeypatch.setattr(libtmux.common, "tmux_cmd", mock_tmux_cmd)
+    monkeypatch.setattr(sys, "platform", "openbsd 5.2")
+    assert has_minimum_version()
+    assert has_gte_version(TMUX_MIN_VERSION)
+    assert has_gt_version(TMUX_MAX_VERSION), "Greater than the max-supported version"
+    assert (
+        "%s-openbsd" % TMUX_MAX_VERSION == get_version()
+    ), "Is the latest supported version with -openbsd appended"
+
+
+def test_get_version_too_low(monkeypatch: pytest.MonkeyPatch) -> None:
+    class Hi:
+        stderr = ["tmux: unknown option -- V"]
+
+    def mock_tmux_cmd(*args: t.Any, **kwargs: t.Any) -> Hi:
+        return Hi()
+
+    monkeypatch.setattr(libtmux.common, "tmux_cmd", mock_tmux_cmd)
+    with pytest.raises(LibTmuxException) as exc_info:
+        get_version()
+    exc_info.match("is running tmux 1.3 or earlier")
+
+
+def test_ignores_letter_versions(monkeypatch: pytest.MonkeyPatch) -> None:
+    """Ignore letters such as 1.8b.
+
+    See ticket https://github.com/tmux-python/tmuxp/issues/55.
+
+    In version 0.1.7 this is adjusted to use LooseVersion, in order to
+    allow letters.
+
+    """
+    monkeypatch.setattr(libtmux.common, "TMUX_MIN_VERSION", "1.9a")
+    result = has_minimum_version()
+    assert result
+
+    monkeypatch.setattr(libtmux.common, "TMUX_MIN_VERSION", "1.8a")
+    result = has_minimum_version()
+    assert result
+
+    # Should not throw
+    assert type(has_version("1.8")) is bool
+    assert type(has_version("1.8a")) is bool
+    assert type(has_version("1.9a")) is bool
+
+
+def test_error_version_less_1_7(monkeypatch: pytest.MonkeyPatch) -> None:
+    def mock_get_version() -> LooseVersion:
+        return LooseVersion("1.7")
+
+    monkeypatch.setattr(libtmux.common, "get_version", mock_get_version)
+    with pytest.raises(LibTmuxException) as excinfo:
+        has_minimum_version()
+        excinfo.match(r"libtmux only supports")
+
+    with pytest.raises(LibTmuxException) as excinfo:
+        has_minimum_version()
+
+        excinfo.match(r"libtmux only supports")
+
+
+def test_has_version() -> None:
+    assert has_version(str(get_version()))
+
+
+def test_has_gt_version() -> None:
+    assert has_gt_version("1.6")
+    assert has_gt_version("1.6b")
+
+    assert not has_gt_version("4.0")
+    assert not has_gt_version("4.0b")
+
+
+def test_has_gte_version() -> None:
+    assert has_gte_version("1.6")
+    assert has_gte_version("1.6b")
+    assert has_gte_version(str(get_version()))
+
+    assert not has_gte_version("4.0")
+    assert not has_gte_version("4.0b")
+
+
+def test_has_lt_version() -> None:
+    assert has_lt_version("4.0a")
+    assert has_lt_version("4.0")
+
+    assert not has_lt_version("1.7")
+    assert not has_lt_version(str(get_version()))
+
+
+def test_has_lte_version() -> None:
+    assert has_lte_version("4.0a")
+    assert has_lte_version("4.0")
+    assert has_lte_version(str(get_version()))
+
+    assert not has_lte_version("1.7")
+    assert not has_lte_version("1.7b")
+
+
+def test_tmux_cmd_raises_on_not_found(monkeypatch: pytest.MonkeyPatch) -> None:
+    monkeypatch.setenv("PATH", "")
+    with pytest.raises(TmuxCommandNotFound):
+        tmux_cmd("-V")
+
+
+def test_tmux_cmd_unicode(session: Session) -> None:
+    session.cmd("new-window", "-t", 3, "-n", "юникод", "-F", "Ελληνικά")
+
+
+@pytest.mark.parametrize(
+    "session_name,raises,exc_msg_regex",
+    [
+        ("", True, "may not be empty"),
+        (None, True, "may not be empty"),
+        ("my great session.", True, "may not contain periods"),
+        ("name: great session", True, "may not contain colons"),
+        ("new great session", False, None),
+        ("ajf8a3fa83fads,,,a", False, None),
+    ],
+)
+def test_session_check_name(
+    session_name: Optional[str], raises: bool, exc_msg_regex: Optional[str]
+) -> None:
+    if raises:
+        with pytest.raises(BadSessionName) as exc_info:
+            session_check_name(session_name)
+        if exc_msg_regex is not None:
+            assert exc_info.match(exc_msg_regex)
+    else:
+        session_check_name(session_name)
+
+
+def test_get_libtmux_version() -> None:
+    from libtmux.__about__ import __version__
+
+    version = get_libtmux_version()
+    assert isinstance(version, LooseVersion)
+    assert LooseVersion(__version__) == version
diff --git a/tests/legacy_api/test_pane.py b/tests/legacy_api/test_pane.py
new file mode 100644
index 000000000..c9c658f6e
--- /dev/null
+++ b/tests/legacy_api/test_pane.py
@@ -0,0 +1,88 @@
+"""Tests for libtmux Pane object."""
+import logging
+import shutil
+
+from libtmux.session import Session
+
+logger = logging.getLogger(__name__)
+
+
+def test_resize_pane(session: Session) -> None:
+    """Test Pane.resize_pane()."""
+
+    window = session.attached_window
+    window.rename_window("test_resize_pane")
+
+    pane1 = window.attached_pane
+    assert pane1 is not None
+    pane1_height = pane1["pane_height"]
+    window.split_window()
+
+    pane1.resize_pane(height=4)
+    assert pane1["pane_height"] != pane1_height
+    assert int(pane1["pane_height"]) == 4
+
+    pane1.resize_pane(height=3)
+    assert int(pane1["pane_height"]) == 3
+
+
+def test_send_keys(session: Session) -> None:
+    pane = session.attached_window.attached_pane
+    assert pane is not None
+    pane.send_keys("c-c", literal=True)
+
+    pane_contents = "\n".join(pane.cmd("capture-pane", "-p").stdout)
+    assert "c-c" in pane_contents
+
+    pane.send_keys("c-a", literal=False)
+    assert "c-a" not in pane_contents, "should not print to pane"
+
+
+def test_set_height(session: Session) -> None:
+    window = session.new_window(window_name="test_set_height")
+    window.split_window()
+    pane1 = window.attached_pane
+    assert pane1 is not None
+    pane1_height = pane1["pane_height"]
+
+    pane1.set_height(4)
+    assert pane1["pane_height"] != pane1_height
+    assert int(pane1["pane_height"]) == 4
+
+
+def test_set_width(session: Session) -> None:
+    window = session.new_window(window_name="test_set_width")
+    window.split_window()
+
+    window.select_layout("main-vertical")
+    pane1 = window.attached_pane
+    assert pane1 is not None
+    pane1_width = pane1["pane_width"]
+
+    pane1.set_width(10)
+    assert pane1["pane_width"] != pane1_width
+    assert int(pane1["pane_width"]) == 10
+
+    pane1.reset()
+
+
+def test_capture_pane(session: Session) -> None:
+    env = shutil.which("env")
+    assert env is not None, "Cannot find usable `env` in PATH."
+
+    session.new_window(
+        attach=True,
+        window_name="capture_pane",
+        window_shell=f"{env} PS1='$ ' sh",
+    )
+    pane = session.attached_window.attached_pane
+    assert pane is not None
+    pane_contents = "\n".join(pane.capture_pane())
+    assert pane_contents == "$"
+    pane.send_keys(
+        r'printf "\n%s\n" "Hello World !"', literal=True, suppress_history=False
+    )
+    pane_contents = "\n".join(pane.capture_pane())
+    assert pane_contents == r'$ printf "\n%s\n" "Hello World !"{}'.format(
+        "\n\nHello World !\n$"
+    )
diff --git a/tests/legacy_api/test_server.py b/tests/legacy_api/test_server.py
new file mode 100644
index 000000000..d7830fd0b
--- /dev/null
+++ b/tests/legacy_api/test_server.py
@@ -0,0 +1,158 @@
+"""Test for libtmux Server object."""
+import logging
+
+import pytest
+
+from libtmux.common import has_gte_version
+from libtmux.server import Server
+from libtmux.session import Session
+
+logger = logging.getLogger(__name__)
+
+
+def test_has_session(server: Server, session: Session) -> None:
+    session_name = session.get("session_name")
+    assert session_name is not None
+    assert server.has_session(session_name)
+    assert not server.has_session("asdf2314324321")
+
+
+def test_socket_name(server: Server) -> None:
+    """``-L`` socket_name.
+
+    ``-L`` socket_name  file name of socket. which will be stored in
+            env TMUX_TMPDIR or /tmp if unset.)
+
+    """
+    myserver = Server(socket_name="test")
+
+    assert myserver.socket_name == "test"
+
+
+def test_socket_path(server: Server) -> None:
+    """``-S`` socket_path  (alternative path for server socket)."""
+    myserver = Server(socket_path="test")
+
+    assert myserver.socket_path == "test"
+
+
+def test_config(server: Server) -> None:
+    """``-f`` file for tmux(1) configuration."""
+    myserver = Server(config_file="test")
+    assert myserver.config_file == "test"
+
+
+def test_256_colors(server: Server) -> None:
+    myserver = Server(colors=256)
+    assert myserver.colors == 256
+
+    proc = myserver.cmd("list-sessions")
+
+    assert "-2" in proc.cmd
+    assert "-8" not in proc.cmd
+
+
+def test_88_colors(server: Server) -> None:
+    myserver = Server(colors=88)
+    assert myserver.colors == 88
+
+    proc = myserver.cmd("list-sessions")
+
+    assert "-8" in proc.cmd
+    assert "-2" not in proc.cmd
+
+
+def test_show_environment(server: Server) -> None:
+    """Server.show_environment() returns dict."""
+    _vars = server.show_environment()
+    assert isinstance(_vars, dict)
+
+
+def test_getenv(server: Server, session: Session) -> None:
+    """Set environment then Server.show_environment(key)."""
+    server.set_environment("FOO", "BAR")
+    assert "BAR" == server.getenv("FOO")
+
+    server.set_environment("FOO", "DAR")
+    assert "DAR" == server.getenv("FOO")
+
+    assert "DAR" == server.show_environment()["FOO"]
+
+
+def test_show_environment_not_set(server: Server) -> None:
+    """Unset environment variable returns None."""
+    assert server.getenv("BAR") is None
+
+
+def test_new_session(server: Server) -> None:
+    """Server.new_session creates and returns valid session"""
+    mysession = server.new_session("test_new_session")
+    assert mysession.get("session_name") == "test_new_session"
+    assert server.has_session("test_new_session")
+
+
+def test_new_session_no_name(server: Server) -> None:
+    """Server.new_session works with no name"""
+    first_session = server.new_session()
+    first_session_name = first_session.get("session_name")
+    assert first_session_name is not None
+    assert server.has_session(first_session_name)
+
+    expected_session_name = str(int(first_session_name) + 1)
+
+    # When a new session is created, it should enumerate
+    second_session = server.new_session()
+    second_session_name = second_session.get("session_name")
+    assert expected_session_name == second_session_name
+    assert second_session_name is not None
+    assert server.has_session(second_session_name)
+
+
+def test_new_session_shell(server: Server) -> None:
+    """Server.new_session creates and returns valid session running with
+    specified command"""
+    cmd = "sleep 1m"
+    mysession = server.new_session("test_new_session", window_command=cmd)
+    window = mysession.list_windows()[0]
+    pane = window.list_panes()[0]
+    assert mysession.get("session_name") == "test_new_session"
+    assert server.has_session("test_new_session")
+
+    pane_start_command = pane.get("pane_start_command")
+    assert pane_start_command is not None
+
+    if has_gte_version("3.2"):
+        assert pane_start_command.replace('"', "") == cmd
+    else:
+        assert pane_start_command == cmd
+
+
+def test_no_server_sessions() -> None:
+    server = Server(socket_name="test_attached_session_no_server")
+    assert server.sessions == []
+
+
+def test_no_server_attached_sessions() -> None:
+    server = Server(socket_name="test_no_server_attached_sessions")
+    assert server.attached_sessions == []
+
+
+def test_no_server_is_alive() -> None:
+    dead_server = Server(socket_name="test_no_server_is_alive")
+    assert not dead_server.is_alive()
+
+
+def test_with_server_is_alive(server: Server) -> None:
+    server.new_session()
+    assert server.is_alive()
+
+
+def test_no_server_raise_if_dead() -> None:
+    dead_server = Server(socket_name="test_attached_session_no_server")
+    with pytest.raises(Exception):
+        dead_server.raise_if_dead()
+
+
+def test_with_server_raise_if_dead(server: Server) -> None:
+    server.new_session()
+    server.raise_if_dead()
diff --git a/tests/legacy_api/test_session.py b/tests/legacy_api/test_session.py
new file mode 100644
index 000000000..b3db613cb
--- /dev/null
+++ b/tests/legacy_api/test_session.py
@@ -0,0 +1,314 @@
+"""Test for libtmux Session object."""
+import logging
+import shutil
+import typing as t
+
+import pytest
+
+from libtmux import exc
+from libtmux.common import has_gte_version, has_lt_version
+from libtmux.pane import Pane
+from libtmux.server import Server
+from libtmux.session import Session
+from libtmux.test import TEST_SESSION_PREFIX, namer
+from libtmux.window import Window
+
+logger = logging.getLogger(__name__)
+
+
+def test_has_session(server: Server, session: Session) -> None:
+    """Server.has_session returns True if has session_name exists."""
+    TEST_SESSION_NAME = session.get("session_name")
+    assert TEST_SESSION_NAME is not None
+    assert server.has_session(TEST_SESSION_NAME)
+    if has_gte_version("2.1"):
+        assert not server.has_session(TEST_SESSION_NAME[:-2])
+        assert server.has_session(TEST_SESSION_NAME[:-2], exact=False)
+    assert not server.has_session("asdf2314324321")
+
+
+def test_select_window(session: Session) -> None:
+    """Session.select_window moves window."""
+    # get the current window_base_index, since different user tmux config
+    # may start at 0 or 1, or whatever they want.
+    window_idx = session.attached_window.get("window_index")
+    assert window_idx is not None
+    window_base_index = int(window_idx)
+
+    session.new_window(window_name="test_window")
+    window_count = len(session._windows)
+
+    assert window_count >= 2  # 2 or more windows
+
+    assert len(session._windows) == window_count
+
+    # tmux selects a window, moves to it, shows it as attached_window
+    selected_window1 = session.select_window(window_base_index)
+    assert isinstance(selected_window1, Window)
+    attached_window1 = session.attached_window
+
+    assert selected_window1 == attached_window1
+    assert selected_window1.__dict__ == attached_window1.__dict__
+
+    # again: tmux selects a window, moves to it, shows it as
+    # attached_window
+    selected_window2 = session.select_window(window_base_index + 1)
+    assert isinstance(selected_window2, Window)
+    attached_window2 = session.attached_window
+
+    assert selected_window2 == attached_window2
+    assert selected_window2.__dict__ == attached_window2.__dict__
+
+    # assure these windows were really different
+    assert selected_window1 != selected_window2
+    assert selected_window1.__dict__ != selected_window2.__dict__
+
+
+def test_select_window_returns_Window(session: Session) -> None:
+    """Session.select_window returns Window object."""
+
+    window_count = len(session._windows)
+    assert len(session._windows) == window_count
+
+    window_idx = session.attached_window.get("window_index")
+    assert window_idx is not None
+    window_base_index = int(window_idx)
+    window = session.select_window(window_base_index)
+    assert isinstance(window, Window)
+
+
+def test_attached_window(session: Session) -> None:
+    """Session.attached_window returns Window."""
+    assert isinstance(session.attached_window, Window)
+
+
+def test_attached_pane(session: Session) -> None:
+    """Session.attached_pane returns Pane."""
+    assert isinstance(session.attached_pane, Pane)
+
+
+def test_session_rename(session: Session) -> None:
+    """Session.rename_session renames session."""
+    session_name = session.get("session_name")
+    assert session_name is not None
+    TEST_SESSION_NAME = session_name
+
+    test_name = "testingdis_sessname"
+    session.rename_session(test_name)
+    session_name = session.get("session_name")
+    assert session_name is not None
+    assert session_name == test_name
+    session.rename_session(TEST_SESSION_NAME)
+    session_name = session.get("session_name")
+    assert session_name is not None
+    assert session_name == TEST_SESSION_NAME
+
+
+def test_new_session(server: Server) -> None:
+    """Server.new_session creates new session."""
+    new_session_name = TEST_SESSION_PREFIX + next(namer)
+    new_session = server.new_session(session_name=new_session_name, detach=True)
+
+    assert isinstance(new_session, Session)
+    assert new_session.get("session_name") == new_session_name
+
+
+def test_show_options(session: Session) -> None:
+    """Session.show_options() returns dict."""
+
+    options = session.show_options()
+    assert isinstance(options, dict)
+
+
+def test_set_show_options_single(session: Session) -> None:
+    """Set option then Session.show_options(key)."""
+
+    session.set_option("history-limit", 20)
+    assert session.show_option("history-limit") == 20
+
+    session.set_option("history-limit", 40)
+    assert session.show_option("history-limit") == 40
+
+    assert session.show_options()["history-limit"] == 40
+
+
+def test_set_show_option(session: Session) -> None:
+    """Set option then Session.show_option(key)."""
+    session.set_option("history-limit", 20)
+    assert session.show_option("history-limit") == 20
+
+    session.set_option("history-limit", 40)
+
+    assert session.show_option("history-limit") == 40
+
+
+def test_empty_session_option_returns_None(session: Session) -> None:
+    assert session.show_option("default-shell") is None
+
+
+def test_show_option_unknown(session: Session) -> None:
+    """Session.show_option raises UnknownOption for invalid option."""
+    cmd_exception: t.Type[exc.OptionError] = exc.UnknownOption
+    if has_gte_version("3.0"):
+        cmd_exception = exc.InvalidOption
+    with pytest.raises(cmd_exception):
+        session.show_option("moooz")
+
+
+def test_show_option_ambiguous(session: Session) -> None:
+    """Session.show_option raises AmbiguousOption for ambiguous option."""
+    with pytest.raises(exc.AmbiguousOption):
+        session.show_option("default-")
+
+
+def test_set_option_ambigous(session: Session) -> None:
+    """Session.set_option raises AmbiguousOption for invalid option."""
+    with pytest.raises(exc.AmbiguousOption):
+        session.set_option("default-", 43)
+
+
+def test_set_option_invalid(session: Session) -> None:
+    """Session.set_option raises UnknownOption for invalid option."""
+    if has_gte_version("2.4"):
+        with pytest.raises(exc.InvalidOption):
+            session.set_option("afewewfew", 43)
+    else:
+        with pytest.raises(exc.UnknownOption):
+            session.set_option("afewewfew", 43)
+
+
+def test_show_environment(session: Session) -> None:
+    """Session.show_environment() returns dict."""
+
+    _vars = session.show_environment()
+    assert isinstance(_vars, dict)
+
+
+def test_set_show_environment_single(session: Session) -> None:
+    """Set environment then Session.show_environment(key)."""
+
+    session.set_environment("FOO", "BAR")
+    assert session.getenv("FOO") == "BAR"
+
+    session.set_environment("FOO", "DAR")
+    assert session.getenv("FOO") == "DAR"
+
+    assert session.show_environment()["FOO"] == "DAR"
+
+
+def test_show_environment_not_set(session: Session) -> None:
+    """Not set environment variable returns None."""
+    assert session.getenv("BAR") is None
+
+
+def test_remove_environment(session: Session) -> None:
+    """Remove environment variable."""
+    assert session.getenv("BAM") is None
+    session.set_environment("BAM", "OK")
+    assert session.getenv("BAM") == "OK"
+    session.remove_environment("BAM")
+    assert session.getenv("BAM") is None
+
+
+def test_unset_environment(session: Session) -> None:
+    """Unset environment variable."""
+    assert session.getenv("BAM") is None
+    session.set_environment("BAM", "OK")
+    assert session.getenv("BAM") == "OK"
+    session.unset_environment("BAM")
+    assert session.getenv("BAM") is None
+
+
+@pytest.mark.parametrize(
+    "session_name,raises",
+    [("hey.period", True), ("hey:its a colon", True), ("hey moo", False)],
+)
+def test_periods_raise_badsessionname(
+    server: Server, session: Session, session_name: str, raises: bool
+) -> None:
+    new_name = session_name + "moo"  # used for rename / switch
+    if raises:
+        with pytest.raises(exc.BadSessionName):
+            session.rename_session(new_name)
+
+        with pytest.raises(exc.BadSessionName):
+            server.new_session(session_name)
+
+        with pytest.raises(exc.BadSessionName):
+            server.has_session(session_name)
+
+        with pytest.raises(exc.BadSessionName):
+            server.switch_client(new_name)
+
+        with pytest.raises(exc.BadSessionName):
+            server.attach_session(new_name)
+
+    else:
+        server.new_session(session_name)
+        server.has_session(session_name)
+        session.rename_session(new_name)
+        with pytest.raises(exc.LibTmuxException):
+            server.switch_client(new_name)
+
+
+def test_cmd_inserts_sesion_id(session: Session) -> None:
+    current_session_id = session.id
+    last_arg = "last-arg"
+    cmd = session.cmd("not-a-command", last_arg)
+    assert "-t" in cmd.cmd
+    assert current_session_id in cmd.cmd
+    assert cmd.cmd[-1] == last_arg
+
+
+@pytest.mark.skipif(
+    has_lt_version("3.0"),
+    reason="needs -e flag for new-window which was introduced in 3.0",
+)
+@pytest.mark.parametrize(
+    "environment",
+    [
+        {"ENV_VAR": "window"},
+        {"ENV_VAR_1": "window_1", "ENV_VAR_2": "window_2"},
+    ],
+)
+def test_new_window_with_environment(
+    session: Session,
+    environment: t.Dict[str, str],
+) -> None:
+    env = shutil.which("env")
+    assert env is not None, "Cannot find usable `env` in PATH."
+
+    window = session.new_window(
+        attach=True,
+        window_name="window_with_environment",
+        window_shell=f"{env} PS1='$ ' sh",
+        environment=environment,
+    )
+    pane = window.attached_pane
+    assert pane is not None
+    for k, v in environment.items():
+        pane.send_keys(f"echo ${k}")
+        assert pane.capture_pane()[-2] == v
+
+
+@pytest.mark.skipif(
+    has_gte_version("3.0"),
+    reason="3.0 has the -e flag on new-window",
+)
+def test_new_window_with_environment_logs_warning_for_old_tmux(
+    session: Session,
+    caplog: pytest.LogCaptureFixture,
+) -> None:
+    env = shutil.which("env")
+    assert env is not None, "Cannot find usable `env` in PATH."
+
+    session.new_window(
+        attach=True,
+        window_name="window_with_environment",
+        window_shell=f"{env} PS1='$ ' sh",
+        environment={"ENV_VAR": "window"},
+    )
+
+    assert any(
+        "Cannot set up environment" in record.msg for record in caplog.records
+    ), "Warning missing"
diff --git a/tests/legacy_api/test_test.py b/tests/legacy_api/test_test.py
new file mode 100644
index 000000000..741a340bd
--- /dev/null
+++ b/tests/legacy_api/test_test.py
@@ -0,0 +1,88 @@
+from time import time
+
+import pytest
+
+from libtmux.exc import WaitTimeout
+from libtmux.test import retry_until
+
+
+def test_retry_three_times() -> None:
+    ini = time()
+    value = 0
+
+    def call_me_three_times() -> bool:
+        nonlocal value
+
+        if value == 2:
+            return True
+
+        value += 1
+
+        return False
+
+    retry_until(call_me_three_times, 1)
+
+    end = time()
+
+    assert abs((end - ini) - 0.1) < 0.01
+
+
+def test_function_times_out() -> None:
+    ini = time()
+
+    def never_true() -> bool:
+        return False
+
+    with pytest.raises(WaitTimeout):
+        retry_until(never_true, 1)
+
+    end = time()
+
+    assert abs((end - ini) - 1.0) < 0.01
+
+
+def test_function_times_out_no_rise() -> None:
+    ini = time()
+
+    def never_true() -> bool:
+        return False
+
+    retry_until(never_true, 1, raises=False)
+
+    end = time()
+
+    assert abs((end - ini) - 1.0) < 0.01
+
+
+def test_function_times_out_no_raise_assert() -> None:
+    ini = time()
+
+    def never_true() -> bool:
+        return False
+
+    assert not retry_until(never_true, 1, raises=False)
+
+    end = time()
+
+    assert abs((end - ini) - 1.0) < 0.01
+
+
+def test_retry_three_times_no_raise_assert() -> None:
+    ini = time()
+    value = 0
+
+    def call_me_three_times() -> bool:
+        nonlocal value
+
+        if value == 2:
+            return True
+
+        value += 1
+
+        return False
+
+    assert retry_until(call_me_three_times, 1, raises=False)
+
+    end = time()
+
+    assert abs((end - ini) - 0.1) < 0.01
diff --git a/tests/legacy_api/test_tmuxobject.py b/tests/legacy_api/test_tmuxobject.py
new file mode 100644
index 000000000..992c73d3f
--- /dev/null
+++ b/tests/legacy_api/test_tmuxobject.py
@@ -0,0 +1,191 @@
+"""Tests for libtmux TmuxRelationalObject and TmuxMappingObject."""
+import logging
+
+from libtmux.pane import Pane
+from libtmux.server import Server
+from libtmux.session import Session
+from libtmux.test import TEST_SESSION_PREFIX, namer
+from libtmux.window import Window
+
+logger = logging.getLogger(__name__)
+
+
+"""Test the :class:`TmuxRelationalObject` base class object."""
+
+
+def test_find_where(server: Server, session: Session) -> None:
+    """Test that find_where() retrieves single matching object."""
+    # server.find_where
+    for session in server.sessions:
+        session_id = session.get("session_id")
+        assert session_id is not None
+
+        assert server.find_where({"session_id": session_id}) == session
+        assert isinstance(server.find_where({"session_id": session_id}), Session)
+
+        # session.find_where
+        for window in session.windows:
+            window_id = window.get("window_id")
+            assert window_id is not None
+
+            assert session.find_where({"window_id": window_id}) == window
+            assert isinstance(session.find_where({"window_id": window_id}), Window)
+
+            # window.find_where
+            for pane in window.panes:
+                pane_id = pane.get("pane_id")
+                assert pane_id is not None
+
+                assert window.find_where({"pane_id": pane_id}) == pane
+                assert isinstance(window.find_where({"pane_id": pane_id}), Pane)
+
+
+def test_find_where_None(server: Server, session: Session) -> None:
+    """.find_where returns None if no results found."""
+
+    while True:
+        nonexistant_session = TEST_SESSION_PREFIX + next(namer)
+
+        if not server.has_session(nonexistant_session):
+            break
+
+    assert server.find_where({"session_name": nonexistant_session}) is None
+
+
+def test_find_where_multiple_infos(server: Server, session: Session) -> None:
+    """.find_where returns objects with multiple attributes."""
+
+    for session in server.sessions:
+        session_id = session.get("session_id")
+        assert session_id is not None
+        session_name = session.get("session_name")
+        assert session_name is not None
+
+        find_where = server.find_where(
+            {"session_id": session_id, "session_name": session_name}
+        )
+
+        assert find_where == session
+        assert isinstance(find_where, Session)
+
+        # session.find_where
+        for window in session.windows:
+            window_id = window.get("window_id")
+            assert window_id is not None
+            window_index = window.get("window_index")
+            assert window_index is not None
+
+            find_where = session.find_where(
+                {"window_id": window_id, "window_index": window_index}
+            )
+
+            assert find_where == window
+            assert isinstance(find_where, Window)
+
+            # window.find_where
+            for pane in window.panes:
+                pane_id = pane.get("pane_id")
+                assert pane_id is not None
+                pane_tty = pane.get("pane_tty")
+                assert pane_tty is not None
+
+                find_where = window.find_where(
+                    {"pane_id": pane_id, "pane_tty": pane_tty}
+                )
+
+                assert find_where == pane
+                assert isinstance(find_where, Pane)
+
+
+def test_where(server: Server, session: Session) -> None:
+    """Test self.where() returns matching objects."""
+
+    window = session.attached_window
+    window.split_window()  # create second pane
+
+    for session in server.sessions:
+        session_id = session.get("session_id")
+        assert session_id is not None
+        session_name = session.get("session_name")
+        assert session_name is not None
+
+        server_sessions = server.where(
+            {"session_id": session_id, "session_name": session_name}
+        )
+
+        assert len(server_sessions) == 1
+        assert isinstance(server_sessions, list)
+        assert server_sessions[0] == session
+        assert isinstance(server_sessions[0], Session)
+
+        # session.where
+        for window in session.windows:
+            window_id = window.get("window_id")
+            assert window_id is not None
+
+            window_index = window.get("window_index")
+            assert window_index is not None
+
+            session_windows = session.where(
+                {"window_id": window_id, "window_index": window_index}
+            )
+
+            assert len(session_windows) == 1
+            assert isinstance(session_windows, list)
+            assert session_windows[0] == window
+            assert isinstance(session_windows[0], Window)
+
+            # window.where
+            for pane in window.panes:
+                pane_id = pane.get("pane_id")
+                assert pane_id is not None
+
+                pane_tty = pane.get("pane_tty")
+                assert pane_tty is not None
+
+                window_panes = window.where({"pane_id": pane_id, "pane_tty": pane_tty})
+
+                assert len(window_panes) == 1
+                assert isinstance(window_panes, list)
+                assert window_panes[0] == pane
+                assert isinstance(window_panes[0], Pane)
+
+
+def test_get_by_id(server: Server, session: Session) -> None:
+    """Test self.get_by_id() retrieves child object."""
+
+    window = session.attached_window
+
+    window.split_window()  # create second pane
+
+    for session in server.sessions:
+        session_id = session.get("session_id")
+        assert session_id is not None
+        get_session_by_id = server.get_by_id(session_id)
+
+        assert get_session_by_id == session
+        assert isinstance(get_session_by_id, Session)
+        assert server.get_by_id("$" + next(namer)) is None
+
+        # session.get_by_id
+        for window in session.windows:
+            window_id = window.get("window_id")
+            assert window_id is not None
+
+            get_window_by_id = session.get_by_id(window_id)
+
+            assert get_window_by_id == window
+            assert isinstance(get_window_by_id, Window)
+
+            assert session.get_by_id("@" + next(namer)) is None
+
+            # window.get_by_id
+            for pane in window.panes:
+                pane_id = pane.get("pane_id")
+                assert pane_id is not None
+
+                get_pane_by_id = window.get_by_id(pane_id)
+
+                assert get_pane_by_id == pane
+                assert isinstance(get_pane_by_id, Pane)
+                assert window.get_by_id("%" + next(namer)) is None
diff --git a/tests/legacy_api/test_version.py b/tests/legacy_api/test_version.py
new file mode 100644
index 000000000..dc4af269d
--- /dev/null
+++ b/tests/legacy_api/test_version.py
@@ -0,0 +1,70 @@
+import operator
+import typing as t
+from contextlib import nullcontext as does_not_raise
+
+import pytest
+
+from libtmux._compat import LooseVersion
+
+if t.TYPE_CHECKING:
+    from _pytest.python_api import RaisesContext
+    from typing_extensions import TypeAlias
+
+    VersionCompareOp: TypeAlias = t.Callable[
+        [t.Any, t.Any],
+        bool,
+    ]
+
+
+@pytest.mark.parametrize(
+    "version",
+    [
+        "1",
+        "1.0",
+        "1.0.0",
+        "1.0.0b",
+        "1.0.0b1",
+        "1.0.0b-openbsd",
+        "1.0.0-next",
+        "1.0.0-next.1",
+    ],
+)
+def test_version(version: str) -> None:
+    assert LooseVersion(version)
+
+
+class VersionCompareFixture(t.NamedTuple):
+    a: object
+    op: "VersionCompareOp"
+    b: object
+    raises: t.Union[t.Type[Exception], bool]
+
+
+@pytest.mark.parametrize(
+    VersionCompareFixture._fields,
+    [
+        VersionCompareFixture(a="1", op=operator.eq, b="1", raises=False),
+        VersionCompareFixture(a="1", op=operator.eq, b="1.0", raises=False),
+        VersionCompareFixture(a="1", op=operator.eq, b="1.0.0", raises=False),
+        VersionCompareFixture(a="1", op=operator.gt, b="1.0.0a", raises=False),
+        VersionCompareFixture(a="1", op=operator.gt, b="1.0.0b", raises=False),
+        VersionCompareFixture(a="1", op=operator.lt, b="1.0.0p1", raises=False),
+        VersionCompareFixture(a="1", op=operator.lt, b="1.0.0-openbsd", raises=False),
+        VersionCompareFixture(a="1", op=operator.lt, b="1", raises=AssertionError),
+        VersionCompareFixture(a="1", op=operator.lt, b="1", raises=AssertionError),
+        VersionCompareFixture(a="1.0.0c", op=operator.gt, b="1.0.0b", raises=False),
+    ],
+)
+def test_version_compare(
+    a: str,
+    op: "VersionCompareOp",
+    b: str,
+    raises: t.Union[t.Type[Exception], bool],
+) -> None:
+    raises_ctx: "RaisesContext[Exception]" = (
+        pytest.raises(t.cast(t.Type[Exception], raises))
+        if raises
+        else t.cast("RaisesContext[Exception]", does_not_raise())
+    )
+    with raises_ctx:
+        assert op(LooseVersion(a), LooseVersion(b))
diff --git a/tests/legacy_api/test_window.py b/tests/legacy_api/test_window.py
new file mode 100644
index 000000000..02fb40552
--- /dev/null
+++ b/tests/legacy_api/test_window.py
@@ -0,0 +1,367 @@
+"""Test for libtmux Window object."""
+import logging
+import shutil
+import time
+import typing as t
+
+import pytest
+
+from libtmux import exc
+from libtmux.common import has_gte_version, has_lt_version
+from libtmux.pane import Pane
+from libtmux.server import Server
+from libtmux.session import Session
+from libtmux.window import Window
+
+logger = logging.getLogger(__name__)
+
+
+def test_select_window(session: Session) -> None:
+    window_count = len(session._windows)
+    # to do, get option for   base-index from tmux
+    # for now however, let's get the index from the first window.
+    assert window_count == 1
+
+    window_base_index = int(session.attached_window.index)
+
+    window = session.new_window(window_name="testing 3")
+
+    # self.assertEqual(2,
+    # int(session.attached_window.index))
+    assert int(window_base_index) + 1 == int(window.index)
+
+    session.select_window(str(window_base_index))
+    assert window_base_index == int(session.attached_window.index)
+
+    session.select_window("testing 3")
+    assert int(window_base_index) + 1 == int(session.attached_window.index)
+
+    assert len(session._windows) == 2
+
+
+def test_zfresh_window_data(session: Session) -> None:
+    attached_window = session.attached_window
+    assert attached_window is not None
+    pane_base_idx = attached_window.show_window_option("pane-base-index", g=True)
+    assert pane_base_idx is not None
+    pane_base_index = int(pane_base_idx)
+
+    assert len(session.windows) == 1
+
+    assert len(session.attached_window.panes) == 1
+    current_windows = len(session._windows)
+    assert session.get("session_id") != "@0"
+    assert current_windows == 1
+
+    assert len(session.attached_window.panes) == 1
+    assert isinstance(session.server, Server)
+    # len(session.attached_window.panes))
+
+    assert len(session.windows), 1
+    assert len(session.attached_window.panes) == 1
+    for w in session.windows:
+        assert isinstance(w, Window)
+    window = session.attached_window
+    assert isinstance(window, Window)
+    assert len(session.attached_window.panes) == 1
+    window.split_window()
+
+    attached_window = session.attached_window
+    assert attached_window is not None
+    attached_window.select_pane(pane_base_index)
+
+    attached_pane = session.attached_pane
+    assert attached_pane is not None
+    attached_pane.send_keys("cd /srv/www/flaskr")
+
+    attached_window.select_pane(pane_base_index + 1)
+    attached_pane = session.attached_pane
+    assert attached_pane is not None
+    attached_pane.send_keys("source .venv/bin/activate")
+    session.new_window(window_name="second")
+    current_windows += 1
+    assert current_windows == len(session._windows)
+    session.new_window(window_name="hey")
+    current_windows += 1
+    assert current_windows == len(session._windows)
+
+    session.select_window("1")
+    session.kill_window(target_window="hey")
+    current_windows -= 1
+    assert current_windows == len(session._windows)
+
+
+def test_newest_pane_data(session: Session) -> None:
+    window = session.new_window(window_name="test", attach=True)
+    assert isinstance(window, Window)
+    assert len(window.panes) == 1
+    window.split_window(attach=True)
+
+    assert len(window.panes) == 2
+    # note: the below used to accept -h, removing because split_window now
+    # has attach as its only argument now
+    window.split_window(attach=True)
+    assert len(window.panes) == 3
+
+
+def test_attached_pane(session: Session) -> None:
+    """Window.attached_window returns active Pane."""
+
+    window = session.attached_window  # current window
+    assert isinstance(window.attached_pane, Pane)
+
+
+def test_split_window(session: Session) -> None:
+    """Window.split_window() splits window, returns new Pane, vertical."""
+    window_name = "test split window"
+    window = session.new_window(window_name=window_name, attach=True)
+    pane = window.split_window()
+    assert len(window.panes) == 2
+    assert isinstance(pane, Pane)
+    assert float(window.panes[0].height) <= ((float(window.width) + 1) / 2)
+
+
+def test_split_window_shell(session: Session) -> None:
+    """Window.split_window() splits window, returns new Pane, vertical."""
+    window_name = "test split window"
+    cmd = "sleep 1m"
+    window = session.new_window(window_name=window_name, attach=True)
+    pane = window.split_window(shell=cmd)
+    assert len(window.panes) == 2
+    assert isinstance(pane, Pane)
+    assert float(window.panes[0].height) <= ((float(window.width) + 1) / 2)
+    if has_gte_version("3.2"):
+        assert pane.get("pane_start_command", "").replace('"', "") == cmd
+    else:
+        assert pane.get("pane_start_command") == cmd
+
+
+def test_split_window_horizontal(session: Session) -> None:
+    """Window.split_window() splits window, returns new Pane, horizontal."""
+    window_name = "test split window"
+    window = session.new_window(window_name=window_name, attach=True)
+    pane = window.split_window(vertical=False)
+    assert len(window.panes) == 2
+    assert isinstance(pane, Pane)
+    assert float(window.panes[0].width) <= ((float(window.width) + 1) / 2)
+
+
+@pytest.mark.parametrize(
+    "window_name_before,window_name_after",
+    [("test", "ha ha ha fjewlkjflwef"), ("test", "hello \\ wazzup 0")],
+)
+def test_window_rename(
+    session: Session, window_name_before: str, window_name_after: str
+) -> None:
+    """Window.rename_window()."""
+    window_name_before = "test"
+    window_name_after = "ha ha ha fjewlkjflwef"
+
+    session.set_option("automatic-rename", "off")
+    window = session.new_window(window_name=window_name_before, attach=True)
+
+    assert window == session.attached_window
+    assert window.get("window_name") == window_name_before
+
+    window.rename_window(window_name_after)
+
+    window = session.attached_window
+
+    assert window.get("window_name") == window_name_after
+
+    window = session.attached_window
+
+    assert window.get("window_name") == window_name_after
+
+
+def test_kill_window(session: Session) -> None:
+    session.new_window()
+    # create a second window to not kick out the client.
+    # there is another way to do this via options too.
+
+    w = session.attached_window
+
+    w.get("window_id")
+
+    w.kill_window()
+    with pytest.raises(IndexError):
+        w.get("window_id")
+
+
+def test_show_window_options(session: Session) -> None:
+    """Window.show_window_options() returns dict."""
+    window = session.new_window(window_name="test_window")
+
+    options = window.show_window_options()
+    assert isinstance(options, dict)
+
+
+def test_set_show_window_options(session: Session) -> None:
+    """Set option then Window.show_window_options(key)."""
+    window = session.new_window(window_name="test_window")
+
+    window.set_window_option("main-pane-height", 20)
+    assert window.show_window_option("main-pane-height") == 20
+
+    window.set_window_option("main-pane-height", 40)
+    assert window.show_window_option("main-pane-height") == 40
+    assert window.show_window_options()["main-pane-height"] == 40
+
+    if has_gte_version("2.3"):
+        window.set_window_option("pane-border-format", " #P ")
+        assert window.show_window_option("pane-border-format") == " #P "
+
+
+def test_empty_window_option_returns_None(session: Session) -> None:
+    window = session.new_window(window_name="test_window")
+    assert window.show_window_option("alternate-screen") is None
+
+
+def test_show_window_option(session: Session) -> None:
+    """Set option then Window.show_window_option(key)."""
+    window = session.new_window(window_name="test_window")
+
+    window.set_window_option("main-pane-height", 20)
+    assert window.show_window_option("main-pane-height") == 20
+
+    window.set_window_option("main-pane-height", 40)
+    assert window.show_window_option("main-pane-height") == 40
+    assert window.show_window_option("main-pane-height") == 40
+
+
+def test_show_window_option_unknown(session: Session) -> None:
+    """Window.show_window_option raises UnknownOption for bad option key."""
+    window = session.new_window(window_name="test_window")
+
+    cmd_exception: t.Type[exc.OptionError] = exc.UnknownOption
+    if has_gte_version("3.0"):
+        cmd_exception = exc.InvalidOption
+    with pytest.raises(cmd_exception):
+        window.show_window_option("moooz")
+
+
+def test_show_window_option_ambiguous(session: Session) -> None:
+    """show_window_option raises AmbiguousOption for ambiguous option."""
+    window = session.new_window(window_name="test_window")
+
+    with pytest.raises(exc.AmbiguousOption):
+        window.show_window_option("clock-mode")
+
+
+def test_set_window_option_ambiguous(session: Session) -> None:
+    """set_window_option raises AmbiguousOption for ambiguous option."""
+    window = session.new_window(window_name="test_window")
+
+    with pytest.raises(exc.AmbiguousOption):
+        window.set_window_option("clock-mode", 12)
+
+
+def test_set_window_option_invalid(session: Session) -> None:
+    """Window.set_window_option raises ValueError for invalid option key."""
+
+    window = session.new_window(window_name="test_window")
+
+    if has_gte_version("2.4"):
+        with pytest.raises(exc.InvalidOption):
+            window.set_window_option("afewewfew", 43)
+    else:
+        with pytest.raises(exc.UnknownOption):
+            window.set_window_option("afewewfew", 43)
+
+
+def test_move_window(session: Session) -> None:
+    """Window.move_window results in changed index"""
+
+    window = session.new_window(window_name="test_window")
+    new_index = str(int(window.index) + 1)
+    window.move_window(new_index)
+    assert window.index == new_index
+
+
+def test_move_window_to_other_session(server: Server, session: Session) -> None:
+    window = session.new_window(window_name="test_window")
+    new_session = server.new_session("test_move_window")
+    window.move_window(session=new_session.get("session_id"))
+    window_id = window.get("window_id")
+    assert window_id is not None
+    assert new_session.get_by_id(window_id) == window
+
+
+def test_select_layout_accepts_no_arg(server: Server, session: Session) -> None:
+    """tmux allows select-layout with no arguments, so let's allow it here."""
+
+    window = session.new_window(window_name="test_window")
+    window.select_layout()
+
+
+@pytest.mark.skipif(
+    has_lt_version("3.2"), reason="needs filter introduced in tmux >= 3.2"
+)
+def test_empty_window_name(session: Session) -> None:
+    session.set_option("automatic-rename", "off")
+    window = session.new_window(window_name="''", attach=True)
+
+    assert window == session.attached_window
+    assert window.get("window_name") == "''"
+
+    cmd = session.cmd(
+        "list-windows",
+        "-F",
+        "#{window_name}",
+        "-f",
+        "#{==:#{session_name}," + session.name + "}",
+    )
+    assert "''" in cmd.stdout
+
+
+@pytest.mark.skipif(
+    has_lt_version("3.0"),
+    reason="needs -e flag for split-window which was introduced in 3.0",
+)
+@pytest.mark.parametrize(
+    "environment",
+    [
+        {"ENV_VAR": "pane"},
+        {"ENV_VAR_1": "pane_1", "ENV_VAR_2": "pane_2"},
+    ],
+)
+def test_split_window_with_environment(
+    session: Session,
+    environment: t.Dict[str, str],
+) -> None:
+    env = shutil.which("env")
+    assert env is not None, "Cannot find usable `env` in Path."
+
+    window = session.new_window(window_name="split_window_with_environment")
+    pane = window.split_window(
+        shell=f"{env} PS1='$ ' sh",
+        environment=environment,
+    )
+    assert pane is not None
+    # wait a bit for the prompt to be ready as the test gets flaky otherwise
+    time.sleep(0.05)
+    for k, v in environment.items():
+        pane.send_keys(f"echo ${k}")
+        assert pane.capture_pane()[-2] == v
+
+
+@pytest.mark.skipif(
+    has_gte_version("3.0"),
+    reason="3.0 has the -e flag on split-window",
+)
+def test_split_window_with_environment_logs_warning_for_old_tmux(
+    session: Session,
+    caplog: pytest.LogCaptureFixture,
+) -> None:
+    env = shutil.which("env")
+    assert env is not None, "Cannot find usable `env` in Path."
+
+    window = session.new_window(window_name="split_window_with_environment")
+    window.split_window(
+        shell=f"{env} PS1='$ ' sh",
+        environment={"ENV_VAR": "pane"},
+    )
+
+    assert any(
+        "Cannot set up environment" in record.msg for record in caplog.records
+    ), "Warning missing"

From 9231e3f98031c528a4b4c092017097fa5790b8dc Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Sun, 18 Dec 2022 07:38:02 -0600
Subject: [PATCH 0214/1073] tests(legacy API[window]): Update for newest
 behavior

---
 tests/legacy_api/test_window.py | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/tests/legacy_api/test_window.py b/tests/legacy_api/test_window.py
index 02fb40552..e6a26a6c1 100644
--- a/tests/legacy_api/test_window.py
+++ b/tests/legacy_api/test_window.py
@@ -181,11 +181,12 @@ def test_kill_window(session: Session) -> None:
 
     w = session.attached_window
 
-    w.get("window_id")
+    assert isinstance(w.get("window_id"), str)
+    assert len(session.windows.filter(window_id=w.get("window_id"))) == 1
 
     w.kill_window()
-    with pytest.raises(IndexError):
-        w.get("window_id")
+
+    assert len(session.windows.filter(window_id=w.get("window_id"))) == 0
 
 
 def test_show_window_options(session: Session) -> None:

From 20f7c5c27cc3fe87c37c93302d390ac9b38bc9d5 Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Sun, 18 Dec 2022 07:45:23 -0600
Subject: [PATCH 0215/1073] chore(legacy test): Typings

---
 tests/legacy_api/test_tmuxobject.py | 12 ++++++------
 tests/legacy_api/test_window.py     | 11 +++++++++++
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/tests/legacy_api/test_tmuxobject.py b/tests/legacy_api/test_tmuxobject.py
index 992c73d3f..73d7a95ed 100644
--- a/tests/legacy_api/test_tmuxobject.py
+++ b/tests/legacy_api/test_tmuxobject.py
@@ -75,12 +75,12 @@ def test_find_where_multiple_infos(server: Server, session: Session) -> None:
             window_index = window.get("window_index")
             assert window_index is not None
 
-            find_where = session.find_where(
+            find_where_window = session.find_where(
                 {"window_id": window_id, "window_index": window_index}
             )
 
-            assert find_where == window
-            assert isinstance(find_where, Window)
+            assert find_where_window == window
+            assert isinstance(find_where_window, Window)
 
             # window.find_where
             for pane in window.panes:
@@ -89,12 +89,12 @@ def test_find_where_multiple_infos(server: Server, session: Session) -> None:
                 pane_tty = pane.get("pane_tty")
                 assert pane_tty is not None
 
-                find_where = window.find_where(
+                find_where_pane = window.find_where(
                     {"pane_id": pane_id, "pane_tty": pane_tty}
                 )
 
-                assert find_where == pane
-                assert isinstance(find_where, Pane)
+                assert find_where_pane == pane
+                assert isinstance(find_where_pane, Pane)
 
 
 def test_where(server: Server, session: Session) -> None:
diff --git a/tests/legacy_api/test_window.py b/tests/legacy_api/test_window.py
index e6a26a6c1..b58150f51 100644
--- a/tests/legacy_api/test_window.py
+++ b/tests/legacy_api/test_window.py
@@ -22,12 +22,15 @@ def test_select_window(session: Session) -> None:
     # for now however, let's get the index from the first window.
     assert window_count == 1
 
+    assert session.attached_window is not None
+    assert session.attached_window.index is not None
     window_base_index = int(session.attached_window.index)
 
     window = session.new_window(window_name="testing 3")
 
     # self.assertEqual(2,
     # int(session.attached_window.index))
+    assert window.index is not None
     assert int(window_base_index) + 1 == int(window.index)
 
     session.select_window(str(window_base_index))
@@ -118,6 +121,8 @@ def test_split_window(session: Session) -> None:
     pane = window.split_window()
     assert len(window.panes) == 2
     assert isinstance(pane, Pane)
+    assert window.width is not None
+    assert window.panes[0].height is not None
     assert float(window.panes[0].height) <= ((float(window.width) + 1) / 2)
 
 
@@ -129,6 +134,8 @@ def test_split_window_shell(session: Session) -> None:
     pane = window.split_window(shell=cmd)
     assert len(window.panes) == 2
     assert isinstance(pane, Pane)
+    assert window.width is not None
+    assert window.panes[0].height is not None
     assert float(window.panes[0].height) <= ((float(window.width) + 1) / 2)
     if has_gte_version("3.2"):
         assert pane.get("pane_start_command", "").replace('"', "") == cmd
@@ -143,6 +150,8 @@ def test_split_window_horizontal(session: Session) -> None:
     pane = window.split_window(vertical=False)
     assert len(window.panes) == 2
     assert isinstance(pane, Pane)
+    assert window.width is not None
+    assert window.panes[0].width is not None
     assert float(window.panes[0].width) <= ((float(window.width) + 1) / 2)
 
 
@@ -274,6 +283,7 @@ def test_move_window(session: Session) -> None:
     """Window.move_window results in changed index"""
 
     window = session.new_window(window_name="test_window")
+    assert window.index is not None
     new_index = str(int(window.index) + 1)
     window.move_window(new_index)
     assert window.index == new_index
@@ -304,6 +314,7 @@ def test_empty_window_name(session: Session) -> None:
 
     assert window == session.attached_window
     assert window.get("window_name") == "''"
+    assert session.name is not None
 
     cmd = session.cmd(
         "list-windows",

From ec073f80e5dfc03d470f75fa79e6faaa8bb710b1 Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Fri, 16 Sep 2022 17:21:24 -0500
Subject: [PATCH 0216/1073] Formats: Update to remove pane_title (removed in
 later tmux versions)

---
 src/libtmux/formats.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libtmux/formats.py b/src/libtmux/formats.py
index ce3745318..545e28d56 100644
--- a/src/libtmux/formats.py
+++ b/src/libtmux/formats.py
@@ -64,7 +64,7 @@
     "pane_index",
     "pane_width",
     "pane_height",
-    "pane_title",
+    # "pane_title",  # removed in 3.1+
     "pane_id",
     "pane_active",
     "pane_dead",

From 373973b2c59d9193677d6db478106c3a74662c2c Mon Sep 17 00:00:00 2001
From: Tony Narlock 
Date: Mon, 12 Sep 2022 19:59:17 -0500
Subject: [PATCH 0217/1073] feat: Basic dataclass

---
 CHANGES                             |  31 ++
 MIGRATION                           |  33 ++
 README.md                           |   8 +-
 docs/about.md                       |   4 +-
 docs/internals/dataclasses.md       |   8 +
 docs/internals/index.md             |  11 +-
 docs/internals/query_list.md        |   6 +
 docs/quickstart.md                  |  28 +-
 docs/reference/properties.md        |  55 +--
 src/libtmux/_internal/query_list.py |  22 +-
 src/libtmux/common.py               | 168 -------
 src/libtmux/formats.py              |   2 +-
 src/libtmux/neo.py                  | 244 ++++++++++
 src/libtmux/pane.py                 | 302 +++++++-----
 src/libtmux/pytest_plugin.py        |   8 +-
 src/libtmux/server.py               | 416 ++++++++---------
 src/libtmux/session.py              | 688 ++++++++++++++++------------
 src/libtmux/test.py                 |   8 +-
 src/libtmux/window.py               | 596 ++++++++++++++----------
 tests/test_dataclasses.py           | 180 ++++++++
 tests/test_pane.py                  |  24 +-
 tests/test_pytest_plugin.py         |   6 +-
 tests/test_server.py                |  16 +-
 tests/test_session.py               |  24 +-
 tests/test_tmuxobject.py            | 103 +++--
 tests/test_window.py                |  81 ++--
 26 files changed, 1849 insertions(+), 1223 deletions(-)
 create mode 100644 docs/internals/dataclasses.md
 create mode 100644 docs/internals/query_list.md
 create mode 100644 src/libtmux/neo.py
 create mode 100644 tests/test_dataclasses.py

diff --git a/CHANGES b/CHANGES
index 64b36ec79..a21ae251a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -14,6 +14,37 @@ $ pip install --user --upgrade --pre libtmux
 
 
 
+### Breaking changes
+
+- Finding objects / relations
+
+  - 0.16 and below: `session._windows()`, `session.list_windows()`, etc.
+
+    0.17 and after: {attr}`session.windows `
+
+  - 0.16 and below: `session.find_where({'window_name': my_window})`
+
+    0.17 and after: {meth}`session.windows.get(window_name=my_window, default=None) `
+
+    - If not found and not `default`, raises {exc}`~libtmux._internal.query_list.ObjectDoesNotExist`
+    - If multiple objects found, raises {exc}`~libtmux._internal.query_list.MultipleObjectsReturned`
+
+  - 0.16 and below: `session.where({'window_name': my_window})`
+
+    0.17 and after: {meth}`session.windows.filter(window_name=my_window) `
+
+- Accessing attributes
+
+  - 0.16 and below: `window['id']`
+
+    0.17 and after: `window.id`
+  - 0.16 and below: `window.get('id')`
+
+    0.17 and after: `window.id`
+  - 0.16 and below: `window.get('id', None)`
+
+    0.17 and after: `getattr(window, 'id', None)`
+
 ### New features
 
 #### Detect if server active (#448)
diff --git a/MIGRATION b/MIGRATION
index 9d0d28b5f..987892cba 100644
--- a/MIGRATION
+++ b/MIGRATION
@@ -19,6 +19,39 @@ well.
    [tracker]: https://github.com/tmux-python/libtmux/discussions
 ```
 
+## 0.17.x: Simplified attributes
+
+### Finding objects / relations
+
+- 0.16 and below: `session._windows()`, `session.list_windows()`, etc.
+
+  0.17 and after: {attr}`session.windows `
+
+- 0.16 and below: `session.find_where({'window_name': my_window})`
+
+  0.17 and after: {meth}`session.windows.get(window_name=my_window, default=None) `
+
+  - If not found and not `default`, raises {exc}`~libtmux._internal.query_list.ObjectDoesNotExist`
+  - If multiple objects found, raises {exc}`~libtmux._internal.query_list.MultipleObjectsReturned`
+
+
+
+- 0.16 and below: `session.where({'window_name': my_window})`
+
+  0.17 and after: {meth}`session.windows.filter(window_name=my_window) `
+
+### Accessing attributes
+
+- 0.16 and below: `window['id']`
+
+  0.17 and after: `window.id`
+- 0.16 and below: `window.get('id')`
+
+  0.17 and after: `window.id`
+- 0.16 and below: `window.get('id', None)`
+
+  0.17 and after: `getattr(window, 'id', None)`
+
 ## Next release
 
 _Migration instructions for the upcoming release will be added here_
diff --git a/README.md b/README.md
index e71025bbd..dabad67fa 100644
--- a/README.md
+++ b/README.md
@@ -69,14 +69,14 @@ current tmux server / session / window pane.
 List sessions:
 
 ```python
->>> server.list_sessions()
+>>> server.sessions
 [Session($1 ...), Session($0 ...)]
 ```
 
 Find session:
 
 ```python
->>> server.get_by_id('$1')
+>>> server.sessions.filter(session_id='$1')[0]
 Session($1 ...)
 ```
 
@@ -85,7 +85,7 @@ Find session by dict lookup:
 ```python
 >>> server.sessions[0].rename_session('foo')
 Session($1 foo)
->>> server.find_where({ "session_name": "foo" })
+>>> server.sessions.filter(session_name="foo")[0]
 Session($1 foo)
 ```
 
@@ -150,12 +150,14 @@ Type inside the pane (send key strokes):
 
 >>> pane.send_keys('echo hey', enter=False)
 >>> pane.enter()
+Pane(%1 ...)
 ```
 
 Grab the output of pane:
 
 ```python
 >>> pane.clear()  # clear the pane
+Pane(%1 ...)
 >>> pane.send_keys("cowsay 'hello'", enter=True)
 >>> print('\n'.join(pane.cmd('capture-pane', '-p').stdout))  # doctest: +SKIP
 $ cowsay 'hello'
diff --git a/docs/about.md b/docs/about.md
index d2aad5aaf..37197e55d 100644
--- a/docs/about.md
+++ b/docs/about.md
@@ -85,8 +85,8 @@ How is libtmux able to keep references to panes, windows and sessions?
 > Window index refers to the # of the window in the session.
 >
 > To assert pane, window and session data, libtmux will use
-> {meth}`Server.list_sessions()`, {meth}`Session.list_windows()`,
-> {meth}`Window.list_panes()` to update objects.
+> {meth}`Server.sessions()`, {meth}`Session.windows()`,
+> {meth}`Window.panes()` to update objects.
 
 ## Naming conventions
 
diff --git a/docs/internals/dataclasses.md b/docs/internals/dataclasses.md
new file mode 100644
index 000000000..96249dc28
--- /dev/null
+++ b/docs/internals/dataclasses.md
@@ -0,0 +1,8 @@
+# Dataclass helpers - `libtmux._internal.dataclasses`
+
+```{eval-rst}
+.. automodule:: libtmux._internal.dataclasses
+   :members:
+   :special-members:
+
+```
diff --git a/docs/internals/index.md b/docs/internals/index.md
index 348a1df32..cc23abcc4 100644
--- a/docs/internals/index.md
+++ b/docs/internals/index.md
@@ -3,9 +3,9 @@
 # Internals
 
 :::{warning}
+Be careful with these! Internal APIs are **not** covered by version policies. They can break or be removed between minor versions!
 
-These APIs are internal and not covered by versioning policy.
-
+If you need an internal API stabilized please [file an issue](https://github.com/tmux-python/libtmux/issues).
 :::
 
 ## Environmental variables
@@ -23,3 +23,10 @@ to split `tmux(1)`'s formatting information.
 
 If you find any compatibility problems with the default, or better yet find a string copacetic
 many environments and tmux releases, note it at .
+
+## Changes
+
+```{toctree}
+dataclasses
+query_list
+``
diff --git a/docs/internals/query_list.md b/docs/internals/query_list.md
new file mode 100644
index 000000000..29f1f9c33
--- /dev/null
+++ b/docs/internals/query_list.md
@@ -0,0 +1,6 @@
+# List querying - `libtmux._internal.query_list`
+
+```{eval-rst}
+.. automodule:: libtmux._internal.query_list
+   :members:
+```
diff --git a/docs/quickstart.md b/docs/quickstart.md
index 749c4cb95..ed6386a89 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -125,10 +125,10 @@ Windows and Panes.
 If you have multiple tmux sessions open, you can see that all of the
 methods in {class}`Server` are available.
 
-We can list sessions with {meth}`Server.list_sessions`:
+We can list sessions with {meth}`Server.sessions`:
 
 ```python
->>> server.list_sessions()
+>>> server.sessions
 [Session($1 ...), Session($0 ...)]
 ```
 
@@ -136,22 +136,22 @@ This returns a list of {class}`Session` objects you can grab. We can
 find our current session with:
 
 ```python
->>> server.list_sessions()[0]
+>>> server.sessions[0]
 Session($1 ...)
 ```
 
 However, this isn't guaranteed, libtmux works against current tmux information, the
 session's name could be changed, or another tmux session may be created,
-so {meth}`Server.get_by_id` and {meth}`Server.find_where` exists as a lookup.
+so {meth}`Server.sessions` and {meth}`Server.windows` exists as a lookup.
 
 ## Get session by ID
 
 tmux sessions use the `$[0-9]` convention as a way to identify sessions.
 
-`$1` is whatever the ID `list_sessions()` returned above.
+`$1` is whatever the ID `sessions()` returned above.
 
 ```python
->>> server.get_by_id('$1')
+>>> server.sessions.filter(session_id='$1')[0]
 Session($1 ...)
 ```
 
@@ -163,13 +163,16 @@ You may `session = server.get_by_id('$')` to use the session object.
 >>> server.sessions[0].rename_session('foo')
 Session($1 foo)
 
->>> server.find_where({ "session_name": "foo" })
+>>> server.sessions.filter(session_name="foo")[0]
+Session($1 foo)
+
+>>> server.sessions.get(session_name="foo")
 Session($1 foo)
 ```
 
-With `find_where`, pass in a dict and return the first object found. In
+With `filter`, pass in attributes and return a list of matches. In
 this case, a {class}`Server` holds a collection of child {class}`Session`.
-{class}`Session` and {class}`Window` both utilize `find_where` to sift
+{class}`Session` and {class}`Window` both utilize `filter` to sift
 through Windows and Panes, respectively.
 
 So you may now use:
@@ -178,7 +181,7 @@ So you may now use:
 >>> server.sessions[0].rename_session('foo')
 Session($1 foo)
 
->>> session = server.find_where({ "session_name": "foo" })
+>>> session = server.sessions.get(session_name="foo")
 >>> session
 Session($1 foo)
 ```
@@ -213,7 +216,7 @@ Let's delete that window ({meth}`Session.kill_window`).
 Method 1: Use passthrough to tmux's `target` system.
 
 ```python
->>> session.kill_window(window.id)
+>>> session.kill_window(window.window_id)
 ```
 
 The window in the bg dissappeared. This was the equivalent of
@@ -260,7 +263,7 @@ And kill:
 >>> window.kill_window()
 ```
 
-Use {meth}`Session.list_windows()` and {meth}`Session.find_where()` to list and sort
+Use {meth}`Session.windows` and {meth}`Session.windows.filter()` to list and sort
 through active {class}`Window`'s.
 
 ## Manipulating windows
@@ -346,6 +349,7 @@ using {meth}`Pane.enter()`:
 
 ```python
 >>> pane.enter()
+Pane(%1 ...)
 ```
 
 ### Avoid cluttering shell history
diff --git a/docs/reference/properties.md b/docs/reference/properties.md
index 085361f3f..2f5e63906 100644
--- a/docs/reference/properties.md
+++ b/docs/reference/properties.md
@@ -49,25 +49,24 @@ Session($1 libtmux_...)
 Quick access to basic attributes:
 
 ```python
->>> session.name
+>>> session.session_name
 'libtmux_...'
 
->>> session.id
+>>> session.session_id
 '$1'
 ```
 
 To see all attributes for a session:
 
 ```python
->>> sorted(list(session._info.keys()))
+from libtmux.neo import Obj
+
+>>> sorted(list(Obj.__dataclass_fields__.keys()))
 ['session_attached', 'session_created', ...]
 ```
 
-Some may conflict with python API, to access them, you can use `.get()`, to get the count
-of sessions in a window:
-
 ```python
->>> session.get('session_windows')
+>>> session.session_windows
 '...'
 ```
 
@@ -85,30 +84,23 @@ Window(@1 ...:..., Session($1 ...))
 Basics:
 
 ```python
->>> window.name
+>>> window.window_name
 '...'
 
->>> window.id
+>>> window.window_id
 '@1'
 
->>> window.height
+>>> window.window_height
 '...'
 
->>> window.width
+>>> window.window_width
 '...'
 ```
 
-Everything available:
-
-```python
->>> sorted(list(window.keys()))
-['session_id', 'session_name', 'window_active', ..., 'window_width']
-```
-
-Use `get()` for details not accessible via properties:
+Use attribute access for details not accessible via properties:
 
 ```python
->>> window.get('window_panes')
+>>> window.window_panes
 '1'
 ```
 
@@ -126,33 +118,20 @@ Pane(%1 Window(@1 ...:..., Session($1 libtmux_...)))
 Basics:
 
 ```python
->>> pane.current_command
+>>> pane.pane_current_command
 '...'
 
->>> type(pane.current_command)
+>>> type(pane.pane_current_command)
 
 
->>> pane.height
+>>> pane.pane_height
 '...'
 
->>> pane.width
+>>> pane.pane_width
 '...'
 
->>> pane.index
+>>> pane.pane_index
 '0'
 ```
 
-Everything:
-
-````python
->>> sorted(list(pane._info.keys()))
-['alternate_on', 'alternate_saved_x', ..., 'wrap_flag']
-
-Use `get()` for details keys:
-
-```python
->>> pane.get('pane_width')
-'...'
-````
-
 [formats]: http://man.openbsd.org/OpenBSD-5.9/man1/tmux.1#FORMATS
diff --git a/src/libtmux/_internal/query_list.py b/src/libtmux/_internal/query_list.py
index 05354cd57..f4ea936ce 100644
--- a/src/libtmux/_internal/query_list.py
+++ b/src/libtmux/_internal/query_list.py
@@ -30,6 +30,14 @@ def __call__(
 no_arg = object()
 
 
+class MultipleObjectsReturned(Exception):
+    """The requested object does not exist"""
+
+
+class ObjectDoesNotExist(Exception):
+    """The query returned multiple objects when only one was expected."""
+
+
 def keygetter(
     obj: "Mapping[str, Any]",
     path: str,
@@ -269,6 +277,8 @@ class QueryList(List[T]):
     'Elmhurst'
     >>> query.filter(foods__fruit__in="orange")[0]['city']
     'Tampa'
+    >>> query.get(foods__fruit__in="orange")['city']
+    'Tampa'
     """
 
     data: "Sequence[T]"
@@ -314,6 +324,8 @@ def __eq__(
     def filter(
         self, matcher: Optional[Union[Callable[[T], bool], T]] = None, **kwargs: Any
     ) -> "QueryList[T]":
+        """Filter list of objects."""
+
         def filter_lookup(obj: Any) -> bool:
             for path, v in kwargs.items():
                 try:
@@ -356,11 +368,17 @@ def get(
         default: Optional[Any] = no_arg,
         **kwargs: Any,
     ) -> Optional[T]:
+        """Retrieve one object
+
+        Raises exception if multiple objects found.
+
+        Raises exception if no object found, unless ``default``
+        """
         objs = self.filter(matcher=matcher, **kwargs)
         if len(objs) > 1:
-            raise Exception("Multiple objects returned")
+            raise MultipleObjectsReturned()
         elif len(objs) == 0:
             if default == no_arg:
-                raise Exception("No objects found")
+                raise ObjectDoesNotExist()
             return default
         return objs[0]
diff --git a/src/libtmux/common.py b/src/libtmux/common.py
index 88029b30c..281abc7ec 100644
--- a/src/libtmux/common.py
+++ b/src/libtmux/common.py
@@ -274,174 +274,6 @@ def __init__(self, *args: t.Any, **kwargs: t.Any) -> None:
         )
 
 
-# class TmuxMappingObject(t.Mapping[str, t.Union[str,int,bool]]):
-class TmuxMappingObject(t.Mapping[t.Any, t.Any]):
-    r"""Base: :py:class:`MutableMapping`.
-
-    Convenience container. Base class for :class:`Pane`, :class:`Window`,
-    :class:`Session` and :class:`Server`.
-
-    Instance attributes for useful information :term:`tmux(1)` uses for
-    Session, Window, Pane, stored :attr:`self._info`. For example, a
-    :class:`Window` will have a ``window_id`` and ``window_name``.
-
-    ================ ================================== ==============
-    Object           formatter_prefix                   value
-    ================ ================================== ==============
-    :class:`Server`  n/a                                n/a
-    :class:`Session` :attr:`Session.formatter_prefix`   session\_
-    :class:`Window`  :attr:`Window.formatter_prefix`    window\_
-    :class:`Pane`    :attr:`Pane.formatter_prefix`      pane\_
-    ================ ================================== ==============
-    """
-    _info: t.Dict[t.Any, t.Any]
-    formatter_prefix: str
-
-    def __getitem__(self, key: str) -> str:
-        item = self._info[key]
-        assert item is not None
-        assert isinstance(item, str)
-        return item
-
-    def __setitem__(self, key: str, value: str) -> None:
-        self._info[key] = value
-        self.dirty = True
-
-    def __delitem__(self, key: str) -> None:
-        del self._info[key]
-        self.dirty = True
-
-    def keys(self) -> KeysView[str]:
-        """Return list of keys."""
-        return self._info.keys()
-
-    def __iter__(self) -> t.Iterator[str]:
-        return self._info.__iter__()
-
-    def __len__(self) -> int:
-        return len(self._info.keys())
-
-    def __getattr__(self, key: str) -> str:
-        try:
-            val = self._info[self.formatter_prefix + key]
-            assert val is not None
-            assert isinstance(val, str)
-            return val
-        except KeyError:
-            raise AttributeError(f"{self.__class__} has no property {key}")
-
-
-O = TypeVar("O", "Pane", "Window", "Session")
-D = TypeVar("D", "PaneDict", "WindowDict", "SessionDict")
-
-
-class TmuxRelationalObject(Generic[O, D]):
-    """Base Class for managing tmux object child entities.  .. # NOQA
-
-    Manages collection of child objects  (a :class:`Server` has a collection of
-    :class:`Session` objects, a :class:`Session` has collection of
-    :class:`Window`)
-
-    Children of :class:`TmuxRelationalObject` are going to have a
-    ``self.children``, ``self.child_id_attribute``.
-
-    ================ ========================= =================================
-    Object           .children                 method
-    ================ ========================= =================================
-    :class:`Server`  :attr:`Server._sessions`  :meth:`Server.list_sessions`
-    :class:`Session` :attr:`Session._windows`  :meth:`Session.list_windows`
-    :class:`Window`  :attr:`Window._panes`     :meth:`Window.list_panes`
-    :class:`Pane`    n/a                       n/a
-    ================ ========================= =================================
-
-    ================ ================================== ==============
-    Object           child_id_attribute                 value
-    ================ ================================== ==============
-    :class:`Server`  :attr:`Server.child_id_attribute`  session_id
-    :class:`Session` :attr:`Session.child_id_attribute` window_id
-    :class:`Window`  :attr:`Window.child_id_attribute`  pane_id
-    :class:`Pane`    n/a                                n/a
-    ================ ================================== ==============
-    """
-
-    children: t.List[O]
-    child_id_attribute: str
-
-    def find_where(self, attrs: D) -> Optional[Union["Pane", "Window", "Session"]]:
-        """Return object on first match.
-
-        .. versionchanged:: 0.4
-            Renamed from ``.findWhere`` to ``.find_where``.
-
-        """
-        try:
-            return self.where(attrs)[0]
-        except IndexError:
-            return None
-
-    @overload
-    def where(self, attrs: D, first: "Literal[True]") -> O:
-        ...
-
-    @overload
-    def where(self, attrs: D, first: "Literal[False]") -> t.List[O]:
-        ...
-
-    @overload
-    def where(self, attrs: D) -> t.List[O]:
-        ...
-
-    def where(self, attrs: D, first: bool = False) -> t.Union[List[O], O]:
-        """
-        Return objects matching child objects properties.
-
-        Parameters
-        ----------
-        attrs : dict
-            tmux properties to match values of
-
-        Returns
-        -------
-        list of objects, or one object if ``first=True``
-        """
-
-        # from https://github.com/serkanyersen/underscore.py
-        def by(val: O) -> bool:
-            for key in attrs.keys():
-                try:
-                    if attrs[key] != val[key]:
-                        return False
-                except KeyError:
-                    return False
-            return True
-
-        target_children: t.List[O] = [s for s in self.children if by(s)]
-
-        if first:
-            return target_children[0]
-        return target_children
-
-    def get_by_id(self, id: str) -> Optional[O]:
-        """
-        Return object based on ``child_id_attribute``.
-
-        Parameters
-        ----------
-        val : str
-
-        Returns
-        -------
-        object
-        """
-        for child in self.children:
-            if child[self.child_id_attribute] == id:
-                return child
-            else:
-                continue
-
-        return None
-
-
 def get_version() -> LooseVersion:
     """
     Return tmux version.
diff --git a/src/libtmux/formats.py b/src/libtmux/formats.py
index 545e28d56..b74bd989f 100644
--- a/src/libtmux/formats.py
+++ b/src/libtmux/formats.py
@@ -19,7 +19,7 @@
     "session_created",
     "session_created_string",
     "session_attached",
-    "session_grouped",
+    # "session_grouped",  Apparently unused, mistake found while adding dataclasses
     "session_group",
 ]
 
diff --git a/src/libtmux/neo.py b/src/libtmux/neo.py
new file mode 100644
index 000000000..be1621214
--- /dev/null
+++ b/src/libtmux/neo.py
@@ -0,0 +1,244 @@
+import dataclasses
+import logging
+import typing as t
+
+from libtmux import exc
+from libtmux.common import tmux_cmd
+from libtmux.formats import FORMAT_SEPARATOR
+
+if t.TYPE_CHECKING:
+    from typing_extensions import Literal
+
+    ListCmd = Literal["list-sessions", "list-windows", "list-panes"]
+    ListExtraArgs = t.Optional[t.Iterable[str]]
+
+    from libtmux.server import Server
+
+logger = logging.getLogger(__name__)
+
+
+OutputRaw = t.Dict[str, t.Any]
+OutputsRaw = t.List[OutputRaw]
+
+
+"""
+Quirks:
+
+QUIRK_TMUX_3_1_X_0001:
+
+- tmux 3.1 and 3.1a:
+- server crash with list-panes w/ buffer_created, client_activity, client_created
+"""
+
+
+@dataclasses.dataclass()
+class Obj:
+    server: "Server"
+
+    active_window_index: t.Union[str, None] = None
+    alternate_saved_x: t.Union[str, None] = None
+    alternate_saved_y: t.Union[str, None] = None
+    # See QUIRK_TMUX_3_1_X_0001
+    # buffer_created: t.Union[str, None] = None
+    buffer_name: t.Union[str, None] = None
+    buffer_sample: t.Union[str, None] = None
+    buffer_size: t.Union[str, None] = None
+    # See QUIRK_TMUX_3_1_X_0001
+    # client_activity: t.Union[str, None] = None
+    client_cell_height: t.Union[str, None] = None
+    client_cell_width: t.Union[str, None] = None
+    # See QUIRK_TMUX_3_1_X_0001
+    # client_created: t.Union[str, None] = None
+    client_discarded: t.Union[str, None] = None
+    client_flags: t.Union[str, None] = None
+    client_height: t.Union[str, None] = None
+    client_key_table: t.Union[str, None] = None
+    client_name: t.Union[str, None] = None
+    client_pid: t.Union[str, None] = None
+    client_termname: t.Union[str, None] = None
+    client_tty: t.Union[str, None] = None
+    client_uid: t.Union[str, None] = None
+    client_user: t.Union[str, None] = None
+    client_width: t.Union[str, None] = None
+    client_written: t.Union[str, None] = None
+    command_list_alias: t.Union[str, None] = None
+    command_list_name: t.Union[str, None] = None
+    command_list_usage: t.Union[str, None] = None
+    config_files: t.Union[str, None] = None
+    copy_cursor_line: t.Union[str, None] = None
+    copy_cursor_word: t.Union[str, None] = None
+    copy_cursor_x: t.Union[str, None] = None
+    copy_cursor_y: t.Union[str, None] = None
+    current_file: t.Union[str, None] = None
+    cursor_character: t.Union[str, None] = None
+    cursor_flag: t.Union[str, None] = None
+    cursor_x: t.Union[str, None] = None
+    cursor_y: t.Union[str, None] = None
+    history_bytes: t.Union[str, None] = None
+    history_limit: t.Union[str, None] = None
+    history_size: t.Union[str, None] = None
+    insert_flag: t.Union[str, None] = None
+    keypad_cursor_flag: t.Union[str, None] = None
+    keypad_flag: t.Union[str, None] = None
+    last_window_index: t.Union[str, None] = None
+    line: t.Union[str, None] = None
+    mouse_all_flag: t.Union[str, None] = None
+    mouse_any_flag: t.Union[str, None] = None
+    mouse_button_flag: t.Union[str, None] = None
+    mouse_sgr_flag: t.Union[str, None] = None
+    mouse_standard_flag: t.Union[str, None] = None
+    next_session_id: t.Union[str, None] = None
+    origin_flag: t.Union[str, None] = None
+    pane_active: t.Union[str, None] = None  # Not detected by script
+    pane_bg: t.Union[str, None] = None
+    pane_bottom: t.Union[str, None] = None
+    pane_current_command: t.Union[str, None] = None
+    pane_current_path: t.Union[str, None] = None
+    pane_dead_signal: t.Union[str, None] = None
+    pane_dead_status: t.Union[str, None] = None
+    pane_dead_time: t.Union[str, None] = None
+    pane_fg: t.Union[str, None] = None
+    pane_height: t.Union[str, None] = None
+    pane_id: t.Union[str, None] = None
+    pane_index: t.Union[str, None] = None
+    pane_left: t.Union[str, None] = None
+    pane_pid: t.Union[str, None] = None
+    pane_right: t.Union[str, None] = None
+    pane_search_string: t.Union[str, None] = None
+    pane_start_command: t.Union[str, None] = None
+    pane_start_path: t.Union[str, None] = None
+    pane_tabs: t.Union[str, None] = None
+    pane_top: t.Union[str, None] = None
+    pane_tty: t.Union[str, None] = None
+    pane_width: t.Union[str, None] = None
+
+    pid: t.Union[str, None] = None
+    scroll_position: t.Union[str, None] = None
+    scroll_region_lower: t.Union[str, None] = None
+    scroll_region_upper: t.Union[str, None] = None
+    search_match: t.Union[str, None] = None
+    selection_end_x: t.Union[str, None] = None
+    selection_end_y: t.Union[str, None] = None
+    selection_start_x: t.Union[str, None] = None
+    selection_start_y: t.Union[str, None] = None
+    session_activity: t.Union[str, None] = None
+    session_alerts: t.Union[str, None] = None
+    session_attached: t.Union[str, None] = None
+    session_attached_list: t.Union[str, None] = None
+    session_created: t.Union[str, None] = None
+    session_group: t.Union[str, None] = None
+    session_group_attached: t.Union[str, None] = None
+    session_group_list: t.Union[str, None] = None
+    session_group_size: t.Union[str, None] = None
+    session_id: t.Union[str, None] = None
+    session_last_attached: t.Union[str, None] = None
+    session_name: t.Union[str, None] = None
+    session_path: t.Union[str, None] = None
+    session_stack: t.Union[str, None] = None
+    session_windows: t.Union[str, None] = None
+    socket_path: t.Union[str, None] = None
+    start_time: t.Union[str, None] = None
+    uid: t.Union[str, None] = None
+    user: t.Union[str, None] = None
+    version: t.Union[str, None] = None
+    window_active: t.Union[str, None] = None  # Not detected by script
+    window_active_clients: t.Union[str, None] = None
+    window_active_sessions: t.Union[str, None] = None
+    window_activity: t.Union[str, None] = None
+    window_cell_height: t.Union[str, None] = None
+    window_cell_width: t.Union[str, None] = None
+    window_height: t.Union[str, None] = None
+    window_id: t.Union[str, None] = None
+    window_index: t.Union[str, None] = None
+    window_layout: t.Union[str, None] = None
+    window_linked: t.Union[str, None] = None
+    window_linked_sessions: t.Union[str, None] = None
+    window_linked_sessions_list: t.Union[str, None] = None
+    window_marked_flag: t.Union[str, None] = None
+    window_name: t.Union[str, None] = None
+    window_offset_x: t.Union[str, None] = None
+    window_offset_y: t.Union[str, None] = None
+    window_panes: t.Union[str, None] = None
+    window_raw_flags: t.Union[str, None] = None
+    window_stack_index: t.Union[str, None] = None
+    window_width: t.Union[str, None] = None
+    wrap_flag: t.Union[str, None] = None
+
+    def _refresh(
+        self,
+        obj_key: str,
+        obj_id: str,
+        list_cmd: "ListCmd" = "list-panes",
+    ) -> None:
+        assert isinstance(obj_id, str)
+        obj = fetch_obj(
+            obj_key=obj_key, obj_id=obj_id, list_cmd=list_cmd, server=self.server
+        )
+        assert obj is not None
+        if obj is not None:
+            for k, v in obj.items():
+                setattr(self, k, v)
+
+
+def fetch_objs(
+    server: "Server", list_cmd: "ListCmd", list_extra_args: "ListExtraArgs" = None
+) -> OutputsRaw:
+    formats = list(Obj.__dataclass_fields__.keys())
+
+    cmd_args: t.List[t.Union[str, int]] = list()
+
+    if server.socket_name:
+        cmd_args.insert(0, f"-L{server.socket_name}")
+    if server.socket_path:
+        cmd_args.insert(0, f"-S{server.socket_path}")
+    tmux_formats = [f"#{{{f}}}{FORMAT_SEPARATOR}" for f in formats]
+
+    tmux_cmds = [
+        *cmd_args,
+        list_cmd,
+    ]
+
+    if list_extra_args is not None and isinstance(list_extra_args, t.Iterable):
+        tmux_cmds.extend(list(list_extra_args))
+
+    tmux_cmds.append("-F%s" % "".join(tmux_formats))
+
+    proc = tmux_cmd(*tmux_cmds)  # output
+
+    if proc.stderr:
+        raise exc.LibTmuxException(proc.stderr)
+
+    obj_output = proc.stdout
+
+    obj_formatters = [
+        dict(zip(formats, formatter.split(FORMAT_SEPARATOR)))
+        for formatter in obj_output
+    ]
+
+    # Filter empty values
+    obj_formatters_filtered = [
+        {k: v for k, v in formatter.items() if v} for formatter in obj_formatters
+    ]
+
+    return obj_formatters_filtered
+
+
+def fetch_obj(
+    server: "Server",
+    obj_key: str,
+    obj_id: str,
+    list_cmd: "ListCmd" = "list-panes",
+    list_extra_args: "ListExtraArgs" = None,
+) -> OutputRaw:
+    obj_formatters_filtered = fetch_objs(
+        server=server, list_cmd=list_cmd, list_extra_args=list_extra_args
+    )
+
+    obj = None
+    for _obj in obj_formatters_filtered:
+        if _obj.get(obj_key) == obj_id:
+            obj = _obj
+
+    assert obj is not None
+
+    return obj
diff --git a/src/libtmux/pane.py b/src/libtmux/pane.py
index 469a0d9b3..bdc161b0d 100644
--- a/src/libtmux/pane.py
+++ b/src/libtmux/pane.py
@@ -5,14 +5,17 @@
 ~~~~~~~~~~~~
 
 """
+import dataclasses
 import logging
 import typing as t
+import warnings
 from typing import overload
 
 from libtmux.common import tmux_cmd
+from libtmux.neo import Obj, fetch_obj
 
-from . import exc
-from .common import PaneDict, TmuxMappingObject, TmuxRelationalObject
+from . import exc, formats
+from .common import PaneDict
 
 if t.TYPE_CHECKING:
     from typing_extensions import Literal
@@ -25,7 +28,8 @@
 logger = logging.getLogger(__name__)
 
 
-class Pane(TmuxMappingObject):
+@dataclasses.dataclass()
+class Pane(Obj):
     """
     A :term:`tmux(1)` :term:`Pane` [pane_manual]_.
 
@@ -68,47 +72,41 @@ class Pane(TmuxMappingObject):
        Accessed April 1st, 2018.
     """
 
-    formatter_prefix = "pane_"
-    """Namespace used for :class:`~libtmux.common.TmuxMappingObject`"""
-    window: "Window"
-    """:class:`libtmux.Window` pane is linked to"""
-    session: "Session"
-    """:class:`libtmux.Session` pane is linked to"""
     server: "Server"
-    """:class:`libtmux.Server` pane is linked to"""
 
-    def __init__(
-        self,
-        window: "Window",
-        pane_id: t.Union[str, int],
-        **kwargs: t.Any,
-    ) -> None:
-        self.window = window
-        self.session = self.window.session
-        self.server = self.session.server
-
-        self._pane_id = pane_id
+    def refresh(self) -> None:
+        assert isinstance(self.pane_id, str)
+        return super()._refresh(obj_key="pane_id", obj_id=self.pane_id)
+
+    @classmethod
+    def from_pane_id(cls, server: "Server", pane_id: str) -> "Pane":
+        pane = fetch_obj(
+            obj_key="pane_id",
+            obj_id=pane_id,
+            server=server,
+            list_cmd="list-panes",
+            list_extra_args=("-a",),
+        )
+        return cls(server=server, **pane)
 
-        self.server._update_panes()
+    #
+    # Relations
+    #
 
     @property
-    def _info(self) -> PaneDict:  # type: ignore  # mypy#1362
-        attrs = {"pane_id": self._pane_id}
-
-        # from https://github.com/serkanyersen/underscore.py
-        def by(val: PaneDict) -> bool:
-            for key in attrs.keys():
-                try:
-                    if attrs[key] != val[key]:
-                        return False
-                except KeyError:
-                    return False
-            return True
+    def window(self) -> "Window":
+        assert isinstance(self.window_id, str)
+        from libtmux.window import Window
 
-        target_panes = [s for s in self.server._panes if by(s)]
+        return Window.from_window_id(server=self.server, window_id=self.window_id)
 
-        return target_panes[0]
+    @property
+    def session(self) -> "Session":
+        return self.window.session
 
+    #
+    # Command (pane-scoped)
+    #
     def cmd(self, cmd: str, *args: t.Any, **kwargs: t.Any) -> tmux_cmd:
         """Return :meth:`Server.cmd` defaulting to ``target_pane`` as target.
 
@@ -116,16 +114,56 @@ def cmd(self, cmd: str, *args: t.Any, **kwargs: t.Any) -> tmux_cmd:
 
         Specifying ``('-t', 'custom-target')`` or ``('-tcustom_target')`` in
         ``args`` will override using the object's ``pane_id`` as target.
-
-        Returns
-        -------
-        :class:`Server.cmd`
         """
         if not any(arg.startswith("-t") for arg in args):
-            args = ("-t", self.get("pane_id")) + args
+            args = ("-t", self.pane_id) + args
 
         return self.server.cmd(cmd, *args, **kwargs)
 
+    #
+    # Commands (tmux-like)
+    #
+    def resize_pane(self, *args: t.Any, **kwargs: t.Any) -> "Pane":
+        """
+        ``$ tmux resize-pane`` of pane and return ``self``.
+
+        Parameters
+        ----------
+        target_pane : str
+            ``target_pane``, or ``-U``,``-D``, ``-L``, ``-R``.
+
+        Other Parameters
+        ----------------
+        height : int
+            ``resize-pane -y`` dimensions
+        width : int
+            ``resize-pane -x`` dimensions
+
+        Raises
+        ------
+        exc.LibTmuxException
+        """
+        if "height" in kwargs:
+            proc = self.cmd("resize-pane", "-y%s" % int(kwargs["height"]))
+        elif "width" in kwargs:
+            proc = self.cmd("resize-pane", "-x%s" % int(kwargs["width"]))
+        else:
+            proc = self.cmd("resize-pane", args[0])
+
+        if proc.stderr:
+            raise exc.LibTmuxException(proc.stderr)
+
+        self.refresh()
+        return self
+
+    def capture_pane(self) -> t.Union[str, t.List[str]]:
+        """
+        Capture text from pane.
+
+        ``$ tmux capture-pane`` to pane.
+        """
+        return self.cmd("capture-pane", "-p").stdout
+
     def send_keys(
         self,
         cmd: str,
@@ -204,11 +242,6 @@ def display_message(
         get_text : bool, optional
             Returns only text without displaying a message in
             target-client status line.
-
-        Returns
-        -------
-        :class:`list`
-        :class:`None`
         """
         if get_text:
             return self.cmd("display-message", "-p", cmd).stdout
@@ -216,14 +249,25 @@ def display_message(
         self.cmd("display-message", cmd)
         return None
 
-    def clear(self) -> None:
-        """Clear pane."""
-        self.send_keys("reset")
-
-    def reset(self) -> None:
-        """Reset and clear pane history."""
+    #
+    # Commands ("climber"-helpers)
+    #
+    # These are commands that climb to the parent scope's methods with
+    # additional scoped window info.
+    #
+    def select_pane(self) -> "Pane":
+        """
+        Select pane. Return ``self``.
 
-        self.cmd("send-keys", r"-R \; clear-history")
+        To select a window object asynchrously. If a ``pane`` object exists
+        and is no longer longer the current window, ``w.select_pane()``
+        will make ``p`` the current pane.
+        """
+        assert isinstance(self.pane_id, str)
+        pane = self.window.select_pane(self.pane_id)
+        if pane is None:
+            raise exc.LibTmuxException(f"Pane not found: {self}")
+        return pane
 
     def split_window(
         self,
@@ -231,7 +275,7 @@ def split_window(
         vertical: bool = True,
         start_directory: t.Optional[str] = None,
         percent: t.Optional[int] = None,
-    ) -> "Pane":
+    ) -> "Pane":  # New Pane, not self
         """
         Split window at pane and return newly created :class:`Pane`.
 
@@ -245,20 +289,19 @@ def split_window(
             specifies the working directory in which the new pane is created.
         percent: int, optional
             percentage to occupy with respect to current pane
-
-        Returns
-        -------
-        :class:`Pane`
         """
         return self.window.split_window(
-            target=self.get("pane_id"),
+            target=self.pane_id,
             start_directory=start_directory,
             attach=attach,
             vertical=vertical,
             percent=percent,
         )
 
-    def set_width(self, width: int) -> None:
+    #
+    # Commands (helpers)
+    #
+    def set_width(self, width: int) -> "Pane":
         """
         Set width of pane.
 
@@ -268,8 +311,9 @@ def set_width(self, width: int) -> None:
             pane width, in cells
         """
         self.resize_pane(width=width)
+        return self
 
-    def set_height(self, height: int) -> None:
+    def set_height(self, height: int) -> "Pane":
         """
         Set height of pane.
 
@@ -279,82 +323,102 @@ def set_height(self, height: int) -> None:
             height of pain, in cells
         """
         self.resize_pane(height=height)
+        return self
 
-    def resize_pane(self, *args: t.Any, **kwargs: t.Any) -> "Pane":
+    def enter(self) -> "Pane":
         """
-        ``$ tmux resize-pane`` of pane and return ``self``.
+        Send carriage return to pane.
 
-        Parameters
-        ----------
-        target_pane : str
-            ``target_pane``, or ``-U``,``-D``, ``-L``, ``-R``.
+        ``$ tmux send-keys`` send Enter to the pane.
+        """
+        self.cmd("send-keys", "Enter")
+        return self
 
-        Other Parameters
-        ----------------
-        height : int
-            ``resize-pane -y`` dimensions
-        width : int
-            ``resize-pane -x`` dimensions
+    def clear(self) -> "Pane":
+        """Clear pane."""
+        self.send_keys("reset")
+        return self
 
-        Returns
-        -------
-        :class:`Pane`
+    def reset(self) -> "Pane":
+        """Reset and clear pane history."""
 
-        Raises
-        ------
-        exc.LibTmuxException
-        """
-        if "height" in kwargs:
-            proc = self.cmd("resize-pane", "-y%s" % int(kwargs["height"]))
-        elif "width" in kwargs:
-            proc = self.cmd("resize-pane", "-x%s" % int(kwargs["width"]))
-        else:
-            proc = self.cmd("resize-pane", args[0])
+        self.cmd("send-keys", r"-R \; clear-history")
+        return self
 
-        if proc.stderr:
-            raise exc.LibTmuxException(proc.stderr)
+    #
+    # Dunder
+    #
+    def __eq__(self, other: object) -> bool:
+        assert isinstance(other, Pane)
+        return self.pane_id == other.pane_id
 
-        self.server._update_panes()
-        return self
+    def __repr__(self) -> str:
+        return "{}({} {})".format(self.__class__.__name__, self.pane_id, self.window)
 
-    def enter(self) -> None:
-        """
-        Send carriage return to pane.
+    #
+    # Aliases
+    #
+    @property
+    def id(self) -> t.Optional[str]:
+        """Alias of :attr:`Pane.pane_id`
 
-        ``$ tmux send-keys`` send Enter to the pane.
-        """
-        self.cmd("send-keys", "Enter")
+        >>> pane.id
+        '%1'
 
-    def capture_pane(self) -> t.Union[str, t.List[str]]:
+        >>> pane.id == pane.pane_id
+        True
         """
-        Capture text from pane.
+        return self.pane_id
 
-        ``$ tmux capture-pane`` to pane.
+    @property
+    def index(self) -> t.Optional[str]:
+        """Alias of :attr:`Pane.pane_index`
 
-        Returns
-        -------
-        :class:`list`
+        >>> pane.index
+        '0'
+
+        >>> pane.index == pane.pane_index
+        True
         """
-        return self.cmd("capture-pane", "-p").stdout
+        return self.pane_index
 
-    def select_pane(self) -> "Pane":
+    @property
+    def height(self) -> t.Optional[str]:
+        """Alias of :attr:`Pane.pane_height`
+
+        >>> pane.height.isdigit()
+        True
+
+        >>> pane.height == pane.pane_height
+        True
         """
-        Select pane. Return ``self``.
+        return self.pane_height
 
-        To select a window object asynchrously. If a ``pane`` object exists
-        and is no longer longer the current window, ``w.select_pane()``
-        will make ``p`` the current pane.
+    @property
+    def width(self) -> t.Optional[str]:
+        """Alias of :attr:`Pane.pane_width`
+
+        >>> pane.width.isdigit()
+        True
 
-        Returns
-        -------
-        :class:`pane`
+        >>> pane.width == pane.pane_width
+        True
         """
-        pane = self.window.select_pane(self._pane_id)
-        if pane is None:
-            raise exc.LibTmuxException(f"Pane not found: {self}")
-        return pane
+        return self.pane_width
 
-    def __repr__(self) -> str:
-        return "{}({} {})".format(
-            self.__class__.__name__, self.get("pane_id"), self.window
-        )
+    #
+    # Legacy
+    #
+    def get(self, key: str, default: t.Optional[t.Any] = None) -> t.Any:
+        """
+        .. deprecated:: 0.16
+        """
+        warnings.warn("Pane.get() is deprecated")
+        return getattr(self, key, default)
+
+    def __getitem__(self, key: str) -> t.Any:
+        """
+        .. deprecated:: 0.16
+        """
+        warnings.warn(f"Item lookups, e.g. pane['{key}'] is deprecated")
+        return getattr(self, key)
diff --git a/src/libtmux/pytest_plugin.py b/src/libtmux/pytest_plugin.py
index ce62da913..8a8124c1d 100644
--- a/src/libtmux/pytest_plugin.py
+++ b/src/libtmux/pytest_plugin.py
@@ -178,8 +178,8 @@ def session(request: pytest.FixtureRequest, server: Server) -> "Session":
 
     # find current sessions prefixed with tmuxp
     old_test_sessions = []
-    for s in server._sessions:
-        old_name = s.get("session_name")
+    for s in server.sessions:
+        old_name = s.session_name
         if old_name is not None and old_name.startswith(TEST_SESSION_PREFIX):
             old_test_sessions.append(old_name)
 
@@ -194,7 +194,7 @@ def session(request: pytest.FixtureRequest, server: Server) -> "Session":
     Make sure that tmuxp can :ref:`test_builder_visually` and switches to
     the newly created session for that testcase.
     """
-    session_id = session.get("session_id")
+    session_id = session.session_id
     assert session_id is not None
 
     try:
@@ -206,7 +206,7 @@ def session(request: pytest.FixtureRequest, server: Server) -> "Session":
     for old_test_session in old_test_sessions:
         logger.debug(f"Old test test session {old_test_session} found. Killing it.")
         server.kill_session(old_test_session)
-    assert TEST_SESSION_NAME == session.get("session_name")
+    assert TEST_SESSION_NAME == session.session_name
     assert TEST_SESSION_NAME != "tmuxp"
 
     return session
diff --git a/src/libtmux/server.py b/src/libtmux/server.py
index cfc0bda44..af3ed718a 100644
--- a/src/libtmux/server.py
+++ b/src/libtmux/server.py
@@ -9,16 +9,20 @@
 import shutil
 import subprocess
 import typing as t
+import warnings
 
+from libtmux._internal.query_list import QueryList
 from libtmux.common import tmux_cmd
+from libtmux.neo import fetch_objs
+from libtmux.pane import Pane
 from libtmux.session import Session
+from libtmux.window import Window
 
 from . import exc, formats
 from .common import (
     EnvironmentMixin,
     PaneDict,
     SessionDict,
-    TmuxRelationalObject,
     WindowDict,
     has_gte_version,
     session_check_name,
@@ -27,14 +31,13 @@
 logger = logging.getLogger(__name__)
 
 
-class Server(TmuxRelationalObject["Session", "SessionDict"], EnvironmentMixin):
-
+class Server(EnvironmentMixin):
     """
     The :term:`tmux(1)` :term:`Server` [server_manual]_.
 
-    - :attr:`Server._sessions` [:class:`Session`, ...]
+    - :attr:`Server.sessions` [:class:`Session`, ...]
 
-      - :attr:`Session._windows` [:class:`Window`, ...]
+      - :attr:`Session.windows` [:class:`Window`, ...]
 
         - :attr:`Window._panes` [:class:`Pane`, ...]
 
@@ -153,10 +156,18 @@ def raise_if_dead(self) -> None:
 
         subprocess.check_call([tmux_bin] + cmd_args)
 
+    #
+    # Command
+    #
     def cmd(self, *args: t.Any, **kwargs: t.Any) -> tmux_cmd:
         """
         Execute tmux command and return output.
 
+        Examples
+        --------
+        >>> server.cmd('display-message', 'hi')
+        
+
         Returns
         -------
         :class:`common.tmux_cmd`
@@ -185,233 +196,35 @@ def cmd(self, *args: t.Any, **kwargs: t.Any) -> tmux_cmd:
 
         return tmux_cmd(*cmd_args, **kwargs)
 
-    def _list_sessions(self) -> t.List[SessionDict]:
-        """
-        Return list of sessions in :py:obj:`dict` form.
-
-        Retrieved from ``$ tmux(1) list-sessions`` stdout.
-
-        The :py:obj:`list` is derived from ``stdout`` in
-        :class:`common.tmux_cmd` which wraps :py:class:`subprocess.Popen`.
-
-        Returns
-        -------
-        list of dict
-        """
-
-        sformats = formats.SESSION_FORMATS
-        tmux_formats = ["#{%s}" % f for f in sformats]
-
-        tmux_args = ("-F%s" % formats.FORMAT_SEPARATOR.join(tmux_formats),)  # output
-
-        list_sessions_cmd = self.cmd("list-sessions", *tmux_args)
-
-        if list_sessions_cmd.stderr:
-            raise exc.LibTmuxException(list_sessions_cmd.stderr)
-
-        sformats = formats.SESSION_FORMATS
-        tmux_formats = ["#{%s}" % format for format in sformats]
-        sessions_output = list_sessions_cmd.stdout
-
-        # combine format keys with values returned from ``tmux list-sessions``
-        sessions_formatters = [
-            dict(zip(sformats, session.split(formats.FORMAT_SEPARATOR)))
-            for session in sessions_output
-        ]
-
-        # clear up empty dict
-        sessions_formatters_filtered = [
-            {k: v for k, v in session.items() if v} for session in sessions_formatters
-        ]
-
-        return sessions_formatters_filtered
-
-    @property
-    def _sessions(self) -> t.List[SessionDict]:
-        """Property / alias to return :meth:`~._list_sessions`."""
-
-        return self._list_sessions()
-
-    def list_sessions(self) -> t.List[Session]:
-        """
-        Return list of :class:`Session` from the ``tmux(1)`` session.
-
-        Returns
-        -------
-        list of :class:`Session`
-        """
-        return [Session(server=self, **s) for s in self._sessions]
-
-    @property
-    def sessions(self) -> t.List[Session]:
-        """Property / alias to return :meth:`~.list_sessions`."""
-        try:
-            return self.list_sessions()
-        except Exception:
-            return []
-
-    #: Alias :attr:`sessions` for :class:`~libtmux.common.TmuxRelationalObject`
-    children = sessions  # type: ignore
-
-    def _list_windows(self) -> t.List[WindowDict]:
-        """
-        Return list of windows in :py:obj:`dict` form.
-
-        Retrieved from ``$ tmux(1) list-windows`` stdout.
-
-        The :py:obj:`list` is derived from ``stdout`` in
-        :class:`common.tmux_cmd` which wraps :py:class:`subprocess.Popen`.
-
-        Returns
-        -------
-        list of dict
-        """
-
-        wformats = ["session_name", "session_id"] + formats.WINDOW_FORMATS
-        tmux_formats = ["#{%s}" % format for format in wformats]
-
-        proc = self.cmd(
-            "list-windows",  # ``tmux list-windows``
-            "-a",
-            "-F%s" % formats.FORMAT_SEPARATOR.join(tmux_formats),  # output
-        )
-
-        if proc.stderr:
-            raise exc.LibTmuxException(proc.stderr)
-
-        window_output = proc.stdout
-
-        wformats = ["session_name", "session_id"] + formats.WINDOW_FORMATS
-
-        # combine format keys with values returned from ``tmux list-windows``
-        window_formatters = [
-            dict(zip(wformats, window.split(formats.FORMAT_SEPARATOR)))
-            for window in window_output
-        ]
-
-        # clear up empty dict
-        window_formatters_filtered = [
-            {k: v for k, v in window.items() if v} for window in window_formatters
-        ]
-
-        # tmux < 1.8 doesn't have window_id, use window_name
-        for w in window_formatters_filtered:
-            if "window_id" not in w:
-                w["window_id"] = w["window_name"]
-
-        if self._windows:
-            self._windows[:] = []
-
-        self._windows.extend(window_formatters_filtered)
-
-        return self._windows
-
-    def _update_windows(self) -> "Server":
-        """
-        Update internal window data and return ``self`` for chainability.
-
-        Returns
-        -------
-        :class:`Server`
-        """
-        self._list_windows()
-        return self
-
-    def _list_panes(self) -> t.List[PaneDict]:
-        """
-        Return list of panes in :py:obj:`dict` form.
-
-        Retrieved from ``$ tmux(1) list-panes`` stdout.
-
-        The :py:obj:`list` is derived from ``stdout`` in
-        :class:`util.tmux_cmd` which wraps :py:class:`subprocess.Popen`.
-
-        Returns
-        -------
-        list
-        """
-
-        pformats = [
-            "session_name",
-            "session_id",
-            "window_index",
-            "window_id",
-            "window_name",
-        ] + formats.PANE_FORMATS
-        tmux_formats = [("#{%%s}%s" % formats.FORMAT_SEPARATOR) % f for f in pformats]
-
-        proc = self.cmd("list-panes", "-a", "-F%s" % "".join(tmux_formats))  # output
-
-        if proc.stderr:
-            raise exc.LibTmuxException(proc.stderr)
-
-        pane_output = proc.stdout
-
-        pformats = [
-            "session_name",
-            "session_id",
-            "window_index",
-            "window_id",
-            "window_name",
-        ] + formats.PANE_FORMATS
-
-        # combine format keys with values returned from ``tmux list-panes``
-        pane_formatters = [
-            dict(zip(pformats, formatter.split(formats.FORMAT_SEPARATOR)))
-            for formatter in pane_output
-        ]
-
-        # Filter empty values
-        pane_formatters_filtered = [
-            {
-                k: v for k, v in formatter.items() if v or k == "pane_current_path"
-            }  # preserve pane_current_path, in case it entered a new process
-            # where we may not get a cwd from.
-            for formatter in pane_formatters
-        ]
-
-        if self._panes:
-            self._panes[:] = []
-
-        self._panes.extend(pane_formatters_filtered)
-
-        return self._panes
-
-    def _update_panes(self) -> "Server":
-        """
-        Update internal pane data and return ``self`` for chainability.
-
-        Returns
-        -------
-        :class:`Server`
-        """
-        self._list_panes()
-        return self
-
     @property
     def attached_sessions(self) -> t.List[Session]:
         """
         Return active :class:`Session` objects.
 
+        Examples
+        --------
+        >>> server.attached_sessions
+        []
+
         Returns
         -------
         list of :class:`Session`
         """
-
         try:
-            sessions = self._sessions
+            sessions = self.sessions
             attached_sessions = list()
 
             for session in sessions:
-                attached = session.get("session_attached")
+                attached = session.session_attached
                 # for now session_active is a unicode
                 if attached != "0":
-                    logger.debug(f"session {session.get('name')} attached")
+                    logger.debug(f"session {session.name} attached")
                     attached_sessions.append(session)
                 else:
                     continue
 
-            return [Session(server=self, **s) for s in attached_sessions] or []
+            return attached_sessions
+            # return [Session(**s) for s in attached_sessions] or None
         except Exception:
             return []
 
@@ -610,9 +423,6 @@ def new_session(
 
         logger.debug(f"creating session {session_name}")
 
-        sformats = formats.SESSION_FORMATS
-        tmux_formats = ["#{%s}" % f for f in sformats]
-
         env = os.environ.get("TMUX")
 
         if env:
@@ -620,7 +430,7 @@ def new_session(
 
         tmux_args: t.Tuple[t.Union[str, int], ...] = (
             "-P",
-            "-F%s" % formats.FORMAT_SEPARATOR.join(tmux_formats),  # output
+            "-F#{session_id}",  # output
         )
 
         if session_name is not None:
@@ -653,14 +463,172 @@ def new_session(
         if env:
             os.environ["TMUX"] = env
 
-        # Combine format keys with values returned from ``tmux list-windows``
-        session_params = dict(
-            zip(sformats, session_stdout.split(formats.FORMAT_SEPARATOR))
+        session_formatters = dict(
+            zip(["session_id"], session_stdout.split(formats.FORMAT_SEPARATOR))
+        )
+
+        return Session.from_session_id(
+            server=self, session_id=session_formatters["session_id"]
         )
 
-        # Filter empty values
-        session_params = {k: v for k, v in session_params.items() if v}
+    #
+    # Relations
+    #
+    @property
+    def sessions(self) -> QueryList[Session]:  # type:ignore
+        """Sessions belonging server.
+
+        Can be accessed via
+        :meth:`.sessions.get() ` and
+        :meth:`.sessions.filter() `
+        """
+        sessions: t.List["Session"] = []
+
+        try:
+            for obj in fetch_objs(
+                list_cmd="list-sessions",
+                server=self,
+            ):
+                sessions.append(Session(server=self, **obj))
+        except Exception:
+            pass
 
-        session = Session(server=self, **session_params)
+        return QueryList(sessions)
 
-        return session
+    @property
+    def windows(self) -> QueryList[Window]:  # type:ignore
+        """Windows belonging server.
+
+        Can be accessed via
+        :meth:`.sessions.get() ` and
+        :meth:`.sessions.filter() `
+        """
+        windows: t.List["Window"] = []
+        for obj in fetch_objs(
+            list_cmd="list-windows",
+            list_extra_args=("-a",),
+            server=self,
+        ):
+            windows.append(Window(server=self, **obj))
+
+        return QueryList(windows)
+
+    @property
+    def panes(self) -> QueryList[Pane]:  # type:ignore
+        """Panes belonging server.
+
+        Can be accessed via
+        :meth:`.sessions.get() ` and
+        :meth:`.sessions.filter() `
+        """
+        panes: t.List["Pane"] = []
+        for obj in fetch_objs(
+            list_cmd="list-panes",
+            list_extra_args=["-s"],
+            server=self,
+        ):
+            panes.append(Pane(server=self, **obj))
+
+        return QueryList(panes)
+
+    def _list_panes(self) -> t.List[PaneDict]:
+        """
+        Return list of panes in :py:obj:`dict` form.
+
+        Retrieved from ``$ tmux(1) list-panes`` stdout.
+
+        The :py:obj:`list` is derived from ``stdout`` in
+        :class:`util.tmux_cmd` which wraps :py:class:`subprocess.Popen`.
+        """
+        return [p.__dict__ for p in self.panes]
+
+    def _update_panes(self) -> "Server":
+        """
+        Update internal pane data and return ``self`` for chainability.
+
+        Returns
+        -------
+        :class:`Server`
+        """
+        self._list_panes()
+        return self
+
+    #
+    # Legacy: Redundant stuff we want to remove
+    #
+    def get_by_id(self, id: str) -> t.Optional[Session]:
+        """
+        .. deprecated:: 0.16
+        """
+        warnings.warn("Server.get_by_id() is deprecated")
+        return self.sessions.get(session_id=id, default=None)
+
+    def where(self, kwargs: t.Dict[str, t.Any]) -> t.List[Session]:
+        """
+        .. deprecated:: 0.16
+        """
+        warnings.warn("Server.find_where() is deprecated")
+        try:
+            return self.sessions.filter(**kwargs)
+        except IndexError:
+            return []
+
+    def find_where(self, kwargs: t.Dict[str, t.Any]) -> t.Optional[Session]:
+        """
+        .. deprecated:: 0.16
+        """
+        warnings.warn("Server.find_where() is deprecated")
+        return self.sessions.get(default=None, **kwargs)
+
+    def _list_windows(self) -> t.List[WindowDict]:
+        """Return list of windows in :py:obj:`dict` form.
+
+        Retrieved from ``$ tmux(1) list-windows`` stdout.
+
+        The :py:obj:`list` is derived from ``stdout`` in
+        :class:`common.tmux_cmd` which wraps :py:class:`subprocess.Popen`.
+
+        .. deprecated:: 0.16
+        """
+        warnings.warn("Server._list_windows() is deprecated")
+        return [w.__dict__ for w in self.windows]
+
+    def _update_windows(self) -> "Server":
+        """Update internal window data and return ``self`` for chainability.
+
+        .. deprecated:: 0.16
+        """
+        warnings.warn("Server._update_windows() is deprecated")
+        self._list_windows()
+        return self
+
+    @property
+    def _sessions(self) -> t.List[SessionDict]:
+        """Property / alias to return :meth:`~._list_sessions`.
+
+        .. deprecated:: 0.16
+        """
+        warnings.warn("Server._sessions is deprecated")
+        return self._list_sessions()
+
+    def _list_sessions(self) -> t.List["SessionDict"]:
+        """
+        .. deprecated:: 0.16
+        """
+        warnings.warn("Server._list_sessions() is deprecated")
+        return [s.__dict__ for s in self.sessions]
+
+    def list_sessions(self) -> t.List[Session]:
+        """Return list of :class:`Session` from the ``tmux(1)`` session.
+
+        .. deprecated:: 0.16
+
+        Returns
+        -------
+        list of :class:`Session`
+        """
+        warnings.warn("Server.list_sessions is deprecated")
+        return self.sessions
+
+    #: Alias :attr:`sessions` for :class:`~libtmux.common.TmuxRelationalObject`
+    children = sessions
diff --git a/src/libtmux/session.py b/src/libtmux/session.py
index 37cd8c122..b1ffabf0f 100644
--- a/src/libtmux/session.py
+++ b/src/libtmux/session.py
@@ -4,19 +4,22 @@
 ~~~~~~~~~~~~~~~
 
 """
+import dataclasses
 import logging
 import os
 import typing as t
+import warnings
 
+from libtmux._internal.query_list import QueryList
 from libtmux.common import tmux_cmd
+from libtmux.formats import FORMAT_SEPARATOR
+from libtmux.neo import Obj, fetch_obj, fetch_objs
+from libtmux.pane import Pane
 from libtmux.window import Window
 
-from . import exc, formats
+from . import exc
 from .common import (
     EnvironmentMixin,
-    SessionDict,
-    TmuxMappingObject,
-    TmuxRelationalObject,
     WindowDict,
     handle_option_error,
     has_gte_version,
@@ -25,16 +28,48 @@
 )
 
 if t.TYPE_CHECKING:
-    from .pane import Pane
     from .server import Server
 
 
 logger = logging.getLogger(__name__)
 
 
-class Session(
-    TmuxMappingObject, TmuxRelationalObject["Window", "WindowDict"], EnvironmentMixin
-):
+# Dataclasses define the schema in a typed annotation way.
+#
+# Users load through YAML, JSON, TOML, or any sort of data entry, these are parsed
+# into dataclasses. Bi-directionals.
+#
+# This means the "intermediary language" is actually a first class, typed, declarative
+# python syntax. It's so first class, it's used in tests, exposed as an experimental API
+# with full intention for users to bootstrap sessions fast.
+#
+# Pitfalls: Lock / pin your versions. APIs may change. It's a Public API - but
+# considered experimental in the sense we .
+#
+# The good news is, since it's typed, you will be able to refactor quickly. In fact,
+# it's easier to factor these than a config where there's no safety.
+#
+# Session.build_workspace(
+#     windows=[
+#         Window(
+#             panes=[
+#                 panes=[]
+#             ]
+#
+#         )
+#     ],
+#     settings=WorkspaceBuilderSettings(
+#         backend='libtmux.ext.workspace_builder.backends.default'
+#     )
+# )
+# WorkspaceBuilder:
+#     backend = 'libtmux.ext.workspace_builder.backends.default'
+#
+
+
+@dataclasses.dataclass()
+class Session(Obj, EnvironmentMixin):
+
     """
     A :term:`tmux(1)` :term:`Session` [session_manual]_.
 
@@ -71,40 +106,62 @@ class Session(
        https://man.openbsd.org/tmux.1#DESCRIPTION. Accessed April 1st, 2018.
     """
 
-    child_id_attribute = "window_id"
-    """Unique child ID key for :class:`~libtmux.common.TmuxRelationalObject`"""
-    formatter_prefix = "session_"
-    """Namespace used for :class:`~libtmux.common.TmuxMappingObject`"""
     server: "Server"
-    """:class:`libtmux.server.Server` session is linked to"""
 
-    def __init__(self, server: "Server", session_id: str, **kwargs: t.Any) -> None:
-        EnvironmentMixin.__init__(self)
-        self.server = server
+    def refresh(self) -> None:
+        assert isinstance(self.session_id, str)
+        return super()._refresh(
+            obj_key="session_id", obj_id=self.session_id, list_cmd="list-sessions"
+        )
 
-        self._session_id = session_id
-        self.server._update_windows()
+    @classmethod
+    def from_session_id(cls, server: "Server", session_id: str) -> "Session":
+        session = fetch_obj(
+            obj_key="session_id",
+            obj_id=session_id,
+            list_cmd="list-sessions",
+            server=server,
+        )
+        return cls(server=server, **session)
 
+    #
+    # Relations
+    #
     @property
-    def _info(self) -> t.Optional[SessionDict]:  # type: ignore  # mypy#1362
-        attrs = {"session_id": str(self._session_id)}
-
-        def by(val: SessionDict) -> bool:
-            for key in attrs.keys():
-                try:
-                    if attrs[key] != val[key]:
-                        return False
-                except KeyError:
-                    return False
-            return True
-
-        target_sessions = [s for s in self.server._sessions if by(s)]
-        try:
-            return target_sessions[0]
-        except IndexError as e:
-            logger.error(e)
-        return None
+    def windows(self) -> QueryList["Window"]:  # type:ignore
+        """Windows belonging session.
+
+        Can be accessed via
+        :meth:`.windows.get() ` and
+        :meth:`.windows.filter() `
+        """
+        windows: t.List["Window"] = []
+        for obj in fetch_objs(
+            list_cmd="list-windows",
+            list_extra_args=["-t", str(self.session_id)],
+            server=self.server,
+        ):
+            if obj.get("session_id") == self.session_id:
+                windows.append(Window(server=self.server, **obj))
+
+        return QueryList(windows)
 
+    @property
+    def panes(self) -> QueryList["Pane"]:  # type:ignore
+        panes: t.List["Pane"] = []
+        for obj in fetch_objs(
+            list_cmd="list-panes",
+            list_extra_args=["-s", "-t", str(self.session_id)],
+            server=self.server,
+        ):
+            if obj.get("session_id") == self.session_id:
+                panes.append(Pane(server=self.server, **obj))
+
+        return QueryList(panes)
+
+    #
+    # Command
+    #
     def cmd(self, *args: t.Any, **kwargs: t.Any) -> tmux_cmd:
         """
         Return :meth:`server.cmd`.
@@ -124,43 +181,258 @@ def cmd(self, *args: t.Any, **kwargs: t.Any) -> tmux_cmd:
             # insert -t immediately after 1st arg, as per tmux format
             new_args: t.Tuple[str, ...] = tuple()
             new_args += (args[0],)
+            assert isinstance(self.session_id, str)
             new_args += (
                 "-t",
-                self.id,
+                self.session_id,
             )
             new_args += tuple(args[1:])
             args = new_args
         return self.server.cmd(*args, **kwargs)
 
-    def attach_session(self) -> None:
+    #
+    # Commands (tmux-like)
+    #
+    def set_option(
+        self, option: str, value: t.Union[str, int], _global: bool = False
+    ) -> "Session":
+        """
+        Set option ``$ tmux set-option