Skip to content

Basic mypy typings #382

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jul 24, 2022
5 changes: 5 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,14 @@ jobs:
- name: Install python dependencies
run: |
poetry install -E "test coverage lint"

- name: Lint with flake8
run: |
poetry run flake8

- name: Lint with mypy
run: poetry run mypy .

- name: Test with pytest
continue-on-error: ${{ matrix.tmux-version == 'master' }}
run: |
Expand Down
6 changes: 6 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ $ pip install --user --upgrade --pre libtmux
- `retry()`: Add deprecation warning. This will be removed in 0.13.x ({issue}`368`, {issue}`372`)
- New function `retry_until()`: Polls a callback function for a set period of time until it returns `True` or times out. By default it will raise {exc}`libtmux.exc.WaitTimeout`, with `raises=False` it will return `False`. Thank you @categulario! ({issue}`368`, {issue}`372`)

### Internals

- {issue}`382` [mypy] support added:

- Basic mypy tests now pass

## libtmux 0.11.0 (2022-03-10)

### Compatibility
Expand Down
7 changes: 4 additions & 3 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import sys
from os.path import dirname, relpath
from pathlib import Path
from typing import Dict, List

import libtmux # NOQA
from libtmux import test # NOQA
Expand All @@ -16,7 +17,7 @@
sys.path.insert(0, str(cwd / "_ext"))

# package data
about = {}
about: Dict = {}
with open("../libtmux/__about__.py") as fp:
exec(fp.read(), about)

Expand Down Expand Up @@ -68,8 +69,8 @@
html_css_files = ["css/custom.css"]
html_extra_path = ["manifest.json"]
html_theme = "furo"
html_theme_path = []
html_theme_options = {
html_theme_path: List = []
html_theme_options: Dict = {
"light_logo": "img/libtmux.svg",
"dark_logo": "img/libtmux.svg",
"footer_icons": [
Expand Down
154 changes: 128 additions & 26 deletions docs/developing.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@

[poetry] is a required package to develop.

`git clone https://github.com/tmux-python/libtmux.git`
```console
$ git clone https://github.com/tmux-python/libtmux.git
```

`cd libtmux`
```console
$ cd libtmux
```

`poetry install -E "docs test coverage lint format"`
```console
$ poetry install -E "docs test coverage lint format"
```

Makefile commands prefixed with `watch_` will watch files and rerun.

Expand All @@ -21,23 +27,122 @@ Rerun tests on file change: `make watch_test` (requires [entr(1)])

Default preview server: http://localhost:8023

[sphinx-autobuild] will automatically build the docs, watch for file changes and launch a server.

From home directory: `make start_docs` From inside `docs/`: `make start`

[sphinx-autobuild]: https://github.com/executablebooks/sphinx-autobuild

### Manual documentation (the hard way)

`cd docs/` and `make html` to build. `make serve` to start http server.

Helpers:
`make build_docs`, `make serve_docs`
Helpers: `make build_docs`, `make serve_docs`

Rebuild docs on file change: `make watch_docs` (requires [entr(1)])

Rebuild docs and run server via one terminal: `make dev_docs` (requires above, and a
`make(1)` with `-J` support, e.g. GNU Make)
Rebuild docs and run server via one terminal: `make dev_docs` (requires above, and a `make(1)` with
`-J` support, e.g. GNU Make)

## Formatting

The project uses [black] and [isort] (one after the other). Configurations are in `pyproject.toml`
and `setup.cfg`:

- `make black isort`: Run `black` first, then `isort` to handle import nuances

## Linting

[flake8] and [mypy] run via CI in our GitHub Actions. See the configuration in `pyproject.toml` and
`setup.cfg`.

### flake8

[flake8] provides fast, reliable, barebones styling and linting.

````{tab} Command

poetry:

```console
$ poetry run flake8
```

If you setup manually:

```console
$ flake8
```

````

````{tab} make

```console
$ make flake8
```

````

````{tab} Watch

```console
$ make watch_flake8
```

requires [`entr(1)`].

## Formatting / Linting
````

The project uses [black] and [isort] (one after the other) and runs [flake8] via
CI. See the configuration in `pyproject.toml` and `setup.cfg`:
````{tab} Configuration

`make black isort`: Run `black` first, then `isort` to handle import nuances
`make flake8`, to watch (requires `entr(1)`): `make watch_flake8`
See `[flake8]` in setup.cfg.

```{literalinclude} ../setup.cfg
:language: ini
:start-at: "[flake8]"
:end-before: "[isort]"

```

````

### mypy

[mypy] is used for static type checking.

````{tab} Command

poetry:

```console
$ poetry run mypy .
```

If you setup manually:

```console
$ mypy .
```

````

````{tab} make

```console
$ make mypy
```

````

````{tab} Watch

```console
$ make watch_mypy
```

requires [`entr(1)`].
````

## Releasing

Expand Down Expand Up @@ -68,23 +173,18 @@ the top::

`libtmux/__init__.py` and `__about__.py` - Set version

`git commit -m 'Tag v0.9.1'`

`git tag v0.9.1`

`pip install wheel twine`

`python setup.py sdist bdist_wheel`

`twine upload dist/*`

### Twine
```console
$ git commit -m 'Tag v0.9.1'
```

`twine upload dist/*`
```console
$ git tag v0.9.1
```

You will be asked for PyPI login information.
After `git push` and `git push --tags`, CI will automatically build and deploy
to PyPI.

### Releasing with Poetry (hypothetical)
### Releasing with Poetry (manual)

This isn't used yet since package maintainers may want setup.py in the source.
See https://github.com/tmux-python/tmuxp/issues/625.
Expand All @@ -104,6 +204,8 @@ Update `__version__` in `__about__.py` and `pyproject.toml`::
[twine]: https://twine.readthedocs.io/
[poetry]: https://python-poetry.org/
[entr(1)]: http://eradman.com/entrproject/
[`entr(1)`]: http://eradman.com/entrproject/
[black]: https://github.com/psf/black
[isort]: https://pypi.org/project/isort/
[flake8]: https://flake8.pycqa.org/
[mypy]: http://mypy-lang.org/
2 changes: 1 addition & 1 deletion libtmux/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ def str_from_console(s: t.Union[str, bytes]) -> str:
try:
return str(s)
except UnicodeDecodeError:
return str(s, encoding="utf_8")
return str(s, encoding="utf_8") if isinstance(s, bytes) else s
2 changes: 1 addition & 1 deletion libtmux/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ def new_session(
if env:
del os.environ["TMUX"]

tmux_args = (
tmux_args: t.Tuple = (
"-s%s" % session_name,
"-P",
"-F%s" % formats.FORMAT_SEPARATOR.join(tmux_formats), # output
Expand Down
2 changes: 1 addition & 1 deletion libtmux/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def new_window(
wformats = ["session_name", "session_id"] + formats.WINDOW_FORMATS
tmux_formats = ["#{%s}" % f for f in wformats]

window_args = tuple()
window_args: t.Tuple = tuple()

if not attach:
window_args += ("-d",)
Expand Down
20 changes: 16 additions & 4 deletions libtmux/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import contextlib
import logging
import os
import tempfile
import random
import time
import warnings
from typing import Callable, Optional
Expand All @@ -15,13 +15,25 @@
RETRY_TIMEOUT_SECONDS = int(os.getenv("RETRY_TIMEOUT_SECONDS", 8))
RETRY_INTERVAL_SECONDS = float(os.getenv("RETRY_INTERVAL_SECONDS", 0.05))

namer = tempfile._RandomNameSequence()

class RandomStrSequence:
def __init__(self, characters: str = "abcdefghijklmnopqrstuvwxyz0123456789_"):
self.characters: str = characters

def __iter__(self):
return self

def __next__(self):
return "".join(random.sample(self.characters, k=8))


namer = RandomStrSequence()
current_dir = os.path.abspath(os.path.dirname(__file__))
example_dir = os.path.abspath(os.path.join(current_dir, "..", "examples"))
fixtures_dir = os.path.realpath(os.path.join(current_dir, "fixtures"))


def retry(seconds: Optional[float] = RETRY_TIMEOUT_SECONDS) -> bool:
def retry(seconds: float = RETRY_TIMEOUT_SECONDS) -> bool:
"""
Retry a block of code until a time limit or ``break``.

Expand Down Expand Up @@ -60,7 +72,7 @@ def retry_until(
fun: Callable,
seconds: float = RETRY_TIMEOUT_SECONDS,
*,
interval: Optional[float] = RETRY_INTERVAL_SECONDS,
interval: float = RETRY_INTERVAL_SECONDS,
raises: Optional[bool] = True,
) -> bool:
"""
Expand Down
6 changes: 3 additions & 3 deletions libtmux/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ def __repr__(self):
)

@property
def _info(self, *args):

def _info(self):
attrs = {"window_id": self._window_id}

# from https://github.com/serkanyersen/underscore.py
Expand Down Expand Up @@ -445,7 +444,7 @@ def split_window(

# '-t%s' % self.attached_pane.get('pane_id'),
# 2013-10-18 LOOK AT THIS, rm'd it..
tmux_args = tuple()
tmux_args: t.Tuple = tuple()

if target:
tmux_args += ("-t%s" % target,)
Expand Down Expand Up @@ -504,6 +503,7 @@ def attached_pane(self) -> t.Optional[Pane]:
# for now pane_active is a unicode
if "pane_active" in pane and pane.get("pane_active") == "1":
return Pane(window=self, **pane)
return None

def _list_panes(self) -> t.List[PaneDict]:
panes = self.server._update_panes()._panes
Expand Down