diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1bebbf8..8e1f5bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,4 +20,5 @@ jobs: with: python-version: ${{ matrix.python-version }} - run: pip install -r requirements-travis.txt + - run: make install - run: make check diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..75c2a06 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,4 @@ +prune debian +prune .github +prune docs +global-exclude *.py[cod] __pycache__ *.so *.spec *.txt .gitignore diff --git a/Makefile b/Makefile index 2ef447a..4ca686f 100644 --- a/Makefile +++ b/Makefile @@ -1,100 +1,95 @@ PYTHON=$(shell which python 2>/dev/null || which python3 2>/dev/null) -DESTDIR=/ -BUILDIR=$(CURDIR)/debian/aexpect PROJECT=aexpect -VERSION="1.8.0" +VERSION=$(shell $(PYTHON) -m setuptools_scm) COMMIT=$(shell git log --pretty=format:'%H' -n 1) SHORT_COMMIT=$(shell git log --pretty=format:'%h' -n 1) COMMIT_DATE=$(shell git log --pretty='format:%cd' --date='format:%Y%m%d' -n 1) MOCK_CONFIG=default all: - @echo "make check - Runs tree static check, unittests and functional tests. Some tests are only executed when AEXPECT_TIME_SENSITIVE=yes is set." - @echo "make clean - Get rid of scratch and byte files" - @echo "make source - Create source package" - @echo "make install - Install on local system" - @echo "make build-deb-src - Generate a source debian package" - @echo "make build-deb-bin - Generate a binary debian package" - @echo "make build-deb-all - Generate both source and binary debian packages" - @echo "RPM related targets:" - @echo "make srpm: Generate a source RPM package (.srpm)" - @echo "make rpm: Generate binary RPMs" + @echo "make check - Run lint and tests" + @echo "make clean - Remove build artifacts" + @echo "make source - Create source package (commit snapshot)" + @echo "make source-release - Create source package (versioned tag)" + @echo "make install - Install from built wheel" + @echo "make develop - Editable install" + @echo "make pypi - Build wheel+sdist (ready for upload)" @echo - @echo "Release related targets:" - @echo "source-release: Create source package for the latest tagged release" - @echo "srpm-release: Generate a source RPM package (.srpm) for the latest tagged release" - @echo "rpm-release: Generate binary RPMs for the latest tagged release" + @echo "Debian targets: build-deb-src, build-deb-bin, build-deb-all" + @echo "RPM targets: srpm, rpm, srpm-release, rpm-release" +# --- Packaging --- source: clean - if test ! -d SOURCES; then mkdir SOURCES; fi - git archive --prefix="aexpect-$(COMMIT)/" -o "SOURCES/aexpect-$(SHORT_COMMIT).tar.gz" HEAD + mkdir -p SOURCES + git archive --prefix="$(PROJECT)-$(COMMIT)/" -o "SOURCES/$(PROJECT)-$(SHORT_COMMIT).tar.gz" HEAD source-release: clean - if test ! -d SOURCES; then mkdir SOURCES; fi - git archive --prefix="aexpect-$(VERSION)/" -o "SOURCES/aexpect-$(VERSION).tar.gz" $(VERSION) + mkdir -p SOURCES + git archive --prefix="$(PROJECT)-$(VERSION)/" -o "SOURCES/$(PROJECT)-$(VERSION).tar.gz" $(VERSION) install: - $(PYTHON) setup.py install --root $(DESTDIR) $(COMPILE) + rm -r dist 2>/dev/null || true + $(PYTHON) -m pip install --upgrade pip build wheel + $(PYTHON) -m build + $(PYTHON) -m pip install --no-deps --force-reinstall dist/*.whl +develop: + $(PYTHON) -m pip install --editable .[dev] + +pypi: clean + $(PYTHON) -m build + $(PYTHON) -m twine check dist/* + @echo + @echo + @echo "Use 'python3 -m twine upload dist/*'" + @echo "to upload this release" + +# --- Checks --- +check: clean + inspekt checkall --disable-lint R0917,R0205,R0801,W4901,W0703,W0511 --disable-style E203,E501,E265,W601,E402 --exclude .venv* + $(PYTHON) -m black --check -- $(shell git ls-files -- "*.py") + $(PYTHON) -m isort --check-only -- $(shell git ls-files -- "*.py") + $(PYTHON) -m pytest + +test: check + +# --- Distro packaging (unchanged except cosmetic) --- prepare-source: - # build the source package in the parent directory - # then rename it to project_version.orig.tar.gz dch -D "utopic" -M -v "$(VERSION)" "Automated (make builddeb) build." - $(PYTHON) setup.py sdist $(COMPILE) --dist-dir=../ + $(PYTHON) -m build --sdist --outdir ../ rename -f 's/$(PROJECT)-(.*)\.tar\.gz/$(PROJECT)_$$1\.orig\.tar\.gz/' ../* build-deb-src: prepare-source - # build the source package dpkg-buildpackage -S -elookkas@gmail.com -rfakeroot build-deb-bin: prepare-source - # build binary package dpkg-buildpackage -b -rfakeroot build-deb-all: prepare-source - # build both source and binary packages dpkg-buildpackage -i -I -rfakeroot srpm: source - if test ! -d BUILD/SRPM; then mkdir -p BUILD/SRPM; fi - mock -r $(MOCK_CONFIG) --resultdir BUILD/SRPM -D "rel_build 0" -D "commit $(COMMIT)" -D "commit_date $(COMMIT_DATE)" --buildsrpm --spec python-aexpect.spec --sources SOURCES + mkdir -p BUILD/SRPM + mock -r $(MOCK_CONFIG) --resultdir BUILD/SRPM -D "rel_build 0" -D "commit $(COMMIT)" -D "commit_date $(COMMIT_DATE)" --buildsrpm --spec python-$(PROJECT).spec --sources SOURCES rpm: srpm - if test ! -d BUILD/RPM; then mkdir -p BUILD/RPM; fi - mock -r $(MOCK_CONFIG) --resultdir BUILD/RPM -D "rel_build 0" -D "commit $(COMMIT)" -D "commit_date $(COMMIT_DATE)" --rebuild BUILD/SRPM/python-aexpect-$(VERSION)-*.src.rpm + mkdir -p BUILD/RPM + mock -r $(MOCK_CONFIG) --resultdir BUILD/RPM -D "rel_build 0" -D "commit $(COMMIT)" -D "commit_date $(COMMIT_DATE)" --rebuild BUILD/SRPM/python-$(PROJECT)-$(VERSION)-*.src.rpm srpm-release: source-release - if test ! -d BUILD/SRPM; then mkdir -p BUILD/SRPM; fi - mock -r $(MOCK_CONFIG) --resultdir BUILD/SRPM -D "rel_build 1" --buildsrpm --spec python-aexpect.spec --sources SOURCES + mkdir -p BUILD/SRPM + mock -r $(MOCK_CONFIG) --resultdir BUILD/SRPM -D "rel_build 1" --buildsrpm --spec python-$(PROJECT).spec --sources SOURCES rpm-release: srpm-release - if test ! -d BUILD/RPM; then mkdir -p BUILD/RPM; fi - mock -r $(MOCK_CONFIG) --resultdir BUILD/RPM -D "rel_build 1" --rebuild BUILD/SRPM/python-aexpect-$(VERSION)-*.src.rpm - -check: clean - inspekt checkall --disable-lint R0917,R0205,R0801,W4901,W0703,W0511 --disable-style E203,E501,E265,W601,E402 --exclude .venv* - $(PYTHON) -m black --line-length 79 --check -- $(shell git ls-files -- "*.py") - $(PYTHON) -m pip install -e . - $(PYTHON) -m pytest tests + mkdir -p BUILD/RPM + mock -r $(MOCK_CONFIG) --resultdir BUILD/RPM -D "rel_build 1" --rebuild BUILD/SRPM/python-$(PROJECT)-$(VERSION)-*.src.rpm clean: - $(PYTHON) setup.py clean $(MAKE) -f $(CURDIR)/debian/rules clean || true - rm -rf build/ MANIFEST BUILD BUILDROOT SPECS RPMS SRPMS SOURCES + rm -rf .mypy_cache *.egg-info MANIFEST BUILD BUILDROOT SPECS RPMS SRPMS SOURCES dist find . -name '*.pyc' -delete + find . -name '__pycache__' -delete -pypi: clean - if test ! -d PYPI_UPLOAD; then mkdir PYPI_UPLOAD; fi - $(PYTHON) setup.py bdist_wheel -d PYPI_UPLOAD - $(PYTHON) setup.py sdist -d PYPI_UPLOAD - @echo - @echo "Please use the files on PYPI_UPLOAD dir to upload a new version to PyPI" - @echo "The URL to do that may be a bit tricky to find, so here it is:" - @echo " https://pypi.python.org/pypi?%3Aaction=submit_form" - @echo - @echo "Alternatively, you can also run a command like: " - @echo " twine upload -u PYPI_UPLOAD/*.{tar.gz,whl}" - @echo - -.PHONY: source install clean +.PHONY: all source source-release install develop pypi check test clean \ + build-deb-src build-deb-bin build-deb-all srpm rpm srpm-release rpm-release prepare-source diff --git a/aexpect/__init__.py b/aexpect/__init__.py index 6501f94..3e32262 100644 --- a/aexpect/__init__.py +++ b/aexpect/__init__.py @@ -14,23 +14,24 @@ entry-points. """ -from .exceptions import ExpectError -from .exceptions import ExpectProcessTerminatedError -from .exceptions import ExpectTimeoutError -from .exceptions import ShellCmdError -from .exceptions import ShellError -from .exceptions import ShellProcessTerminatedError -from .exceptions import ShellStatusError -from .exceptions import ShellTimeoutError - -from .client import Spawn -from .client import Tail -from .client import Expect -from .client import ShellSession -from .client import kill_tail_threads -from .client import run_tail -from .client import run_bg -from .client import run_fg - -from . import remote -from . import rss_client +from . import remote, rss_client +from .client import ( + Expect, + ShellSession, + Spawn, + Tail, + kill_tail_threads, + run_bg, + run_fg, + run_tail, +) +from .exceptions import ( + ExpectError, + ExpectProcessTerminatedError, + ExpectTimeoutError, + ShellCmdError, + ShellError, + ShellProcessTerminatedError, + ShellStatusError, + ShellTimeoutError, +) diff --git a/aexpect/client.py b/aexpect/client.py index cb7ae38..a369046 100644 --- a/aexpect/client.py +++ b/aexpect/client.py @@ -17,38 +17,39 @@ # disable too-many-* as we need them pylint: disable=R0902,R0913,R0914,C0302 -import time -import signal +import locale +import logging import os import re -import threading -import shutil import select +import shutil +import signal import subprocess -import locale -import logging +import threading +import time -from aexpect.exceptions import ExpectError -from aexpect.exceptions import ExpectProcessTerminatedError -from aexpect.exceptions import ExpectTimeoutError -from aexpect.exceptions import ShellCmdError -from aexpect.exceptions import ShellError -from aexpect.exceptions import ShellProcessTerminatedError -from aexpect.exceptions import ShellStatusError -from aexpect.exceptions import ShellTimeoutError - -from aexpect.shared import BASE_DIR -from aexpect.shared import get_filenames -from aexpect.shared import get_reader_filename -from aexpect.shared import get_lock_fd -from aexpect.shared import is_file_locked -from aexpect.shared import unlock_fd -from aexpect.shared import wait_for_lock - -from aexpect.utils import astring -from aexpect.utils import data_factory -from aexpect.utils import process as utils_process +from aexpect.exceptions import ( + ExpectError, + ExpectProcessTerminatedError, + ExpectTimeoutError, + ShellCmdError, + ShellError, + ShellProcessTerminatedError, + ShellStatusError, + ShellTimeoutError, +) +from aexpect.shared import ( + BASE_DIR, + get_filenames, + get_lock_fd, + get_reader_filename, + is_file_locked, + unlock_fd, + wait_for_lock, +) +from aexpect.utils import astring, data_factory from aexpect.utils import path as utils_path +from aexpect.utils import process as utils_process from aexpect.utils import wait as utils_wait _THREAD_KILL_REQUESTED = threading.Event() diff --git a/aexpect/ops_windows.py b/aexpect/ops_windows.py index 3acf492..e8124a3 100644 --- a/aexpect/ops_windows.py +++ b/aexpect/ops_windows.py @@ -33,12 +33,12 @@ Network configuration and downloads. """ +import logging import re import uuid -import logging -from textwrap import dedent from base64 import b64encode from enum import Enum, auto +from textwrap import dedent # avocado imports from aexpect.exceptions import ShellError, ShellProcessTerminatedError diff --git a/aexpect/remote.py b/aexpect/remote.py index 276bcd2..b13a8fd 100644 --- a/aexpect/remote.py +++ b/aexpect/remote.py @@ -43,16 +43,15 @@ # ..todo:: we could reduce the disabled issues after more significant refactoring from __future__ import division + import logging -import time import re import shlex +import time -from aexpect.client import Expect -from aexpect.client import RemoteSession -from aexpect.exceptions import ExpectTimeoutError -from aexpect.exceptions import ExpectProcessTerminatedError from aexpect import rss_client +from aexpect.client import Expect, RemoteSession +from aexpect.exceptions import ExpectProcessTerminatedError, ExpectTimeoutError LOG = logging.getLogger(__name__) diff --git a/aexpect/remote_door.py b/aexpect/remote_door.py index 504d5cd..aeb1217 100644 --- a/aexpect/remote_door.py +++ b/aexpect/remote_door.py @@ -57,13 +57,13 @@ # disable too-many/few-* as we need them pylint: disable=R0903,R0912,R0913,R0914,R0915,R0917,C0302 # ..todo:: we could reduce the disabled issues after more significant refactoring +import importlib +import inspect +import logging import os import re -import logging -import inspect -import importlib -import threading import tempfile +import threading import time # NOTE: enable this before importing the Pyro backend in order to debug issues @@ -72,13 +72,10 @@ try: try: # noinspection PyPackageRequirements,PyUnresolvedReferences - from Pyro5.compatibility import Pyro4 - # noinspection PyPackageRequirements - from Pyro5 import server - # noinspection PyPackageRequirements - from Pyro5 import nameserver + from Pyro5 import nameserver, server + from Pyro5.compatibility import Pyro4 NS_MODULE = "Pyro5.nameserver" except ImportError: diff --git a/aexpect/rss_client.py b/aexpect/rss_client.py index f331306..c2137ee 100644 --- a/aexpect/rss_client.py +++ b/aexpect/rss_client.py @@ -25,13 +25,14 @@ # ..todo:: we could reduce the disabled issues after more significant refactoring from __future__ import division, print_function + +import argparse +import glob +import os import socket import struct -import time import sys -import os -import glob -import argparse +import time # Globals CHUNKSIZE = 65536 diff --git a/aexpect/scripts/__init__.py b/aexpect/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scripts/aexpect_helper b/aexpect/scripts/aexpect_helper.py similarity index 66% rename from scripts/aexpect_helper rename to aexpect/scripts/aexpect_helper.py index 4a41d49..6cbb609 100755 --- a/scripts/aexpect_helper +++ b/aexpect/scripts/aexpect_helper.py @@ -15,24 +15,26 @@ Helper script that runs and interacts with the process executed by aexpect """ -import os -import sys import logging +import os import pty -import tempfile import select +import sys +import tempfile -from aexpect.shared import BASE_DIR -from aexpect.shared import get_filenames -from aexpect.shared import get_reader_filename -from aexpect.shared import get_lock_fd -from aexpect.shared import unlock_fd -from aexpect.shared import wait_for_lock -from aexpect.shared import makestandard -from aexpect.shared import makeraw +from aexpect.shared import ( + BASE_DIR, + get_filenames, + get_lock_fd, + get_reader_filename, + makeraw, + makestandard, + unlock_fd, + wait_for_lock, +) -def main(): # too-many-* pylint:disable=R0914,R0912,R0915 +def main(): # too-many-* pylint:disable=R0914,R0912,R0915 """Wait for commands and then handle communication with the process""" a_id = sys.stdin.readline().strip() echo = sys.stdin.readline().strip() == "True" @@ -42,36 +44,43 @@ def main(): # too-many-* pylint:disable=R0914,R0912,R0915 base_dir = os.path.join(BASE_DIR, f"aexpect_{a_id}") # Define filenames to be used for communication - (shell_pid_filename, - status_filename, - output_filename, - inpipe_filename, - ctrlpipe_filename, - lock_server_running_filename, - lock_client_starting_filename, - log_filename) = get_filenames(base_dir) + ( + shell_pid_filename, + status_filename, + output_filename, + inpipe_filename, + ctrlpipe_filename, + lock_server_running_filename, + lock_client_starting_filename, + log_filename, + ) = get_filenames(base_dir) assert os.path.isdir(base_dir) - logging_format = '%(asctime)s %(levelname)-5.5s| %(message)s' - date_format = '%m/%d %H:%M:%S' - logging.basicConfig(filename=log_filename, level=logging.DEBUG, - format=logging_format, datefmt=date_format) + logging_format = "%(asctime)s %(levelname)-5.5s| %(message)s" + date_format = "%m/%d %H:%M:%S" + logging.basicConfig( + filename=log_filename, + level=logging.DEBUG, + format=logging_format, + datefmt=date_format, + ) server_log = logging.getLogger() - server_log.info('Server %s starting with parameters', str(a_id)) - server_log.info('echo: %s', str(echo)) - server_log.info('readers: %s', str(readers)) - server_log.info('command: %s', str(command)) + server_log.info("Server %s starting with parameters", str(a_id)) + server_log.info("echo: %s", str(echo)) + server_log.info("readers: %s", str(readers)) + server_log.info("command: %s", str(command)) # Populate the reader filenames list - reader_filenames = [get_reader_filename(base_dir, reader) - for reader in readers] + reader_filenames = [ + get_reader_filename(base_dir, reader) for reader in readers + ] # Set $TERM = dumb os.putenv("TERM", "dumb") - server_log.info('Forking child process for command') + server_log.info("Forking child process for command") (shell_pid, shell_fd) = pty.fork() if shell_pid == 0: # Child process: run the command in a subshell @@ -83,64 +92,70 @@ def main(): # too-many-* pylint:disable=R0914,R0912,R0915 # 2MB => 8196kb, 4MB => 16392, ... new_stack = (1 + len(command) // 2072576) * 8196 command = f"ulimit -s {new_stack}\nulimit -n 819200\n{command}" - with tempfile.NamedTemporaryFile(suffix='.sh', prefix='aexpect-', - dir=base_dir) as tmp_file: - tmp_file.write(command.encode('utf-8')) + with tempfile.NamedTemporaryFile( + suffix=".sh", prefix="aexpect-", dir=base_dir + ) as tmp_file: + tmp_file.write(command.encode("utf-8")) tmp_file.flush() - os.execv("/bin/bash", ["/bin/bash", "-c", - f"source {tmp_file.name}"]) + os.execv( + "/bin/bash", ["/bin/bash", "-c", f"source {tmp_file.name}"] + ) else: os.execv("/bin/bash", ["/bin/bash", "-c", command]) else: # Parent process - server_log.info('Acquiring server lock on %s', - lock_server_running_filename) + server_log.info( + "Acquiring server lock on %s", lock_server_running_filename + ) lock_server_running = get_lock_fd(lock_server_running_filename) # Set terminal echo on/off and disable pre- and post-processing makestandard(shell_fd, echo) - server_log.info('Opening output file %s', output_filename) + server_log.info("Opening output file %s", output_filename) with open(output_filename, "wb") as output_file: - server_log.info('Opening input pipe %s', inpipe_filename) + server_log.info("Opening input pipe %s", inpipe_filename) os.mkfifo(inpipe_filename) inpipe_fd = os.open(inpipe_filename, os.O_RDWR) - server_log.info('Opening control pipe %s', ctrlpipe_filename) + server_log.info("Opening control pipe %s", ctrlpipe_filename) os.mkfifo(ctrlpipe_filename) ctrlpipe_fd = os.open(ctrlpipe_filename, os.O_RDWR) # Open output pipes (readers) reader_fds = [] for filename in reader_filenames: - server_log.info('Opening output pipe %s', filename) + server_log.info("Opening output pipe %s", filename) os.mkfifo(filename) reader_fds.append(os.open(filename, os.O_RDWR)) - server_log.info('Reader fd list: %s', reader_fds) + server_log.info("Reader fd list: %s", reader_fds) # Write shell PID to file - server_log.info('Writing shell PID file %s', shell_pid_filename) + server_log.info("Writing shell PID file %s", shell_pid_filename) with open(shell_pid_filename, "w", encoding="utf-8") as file_obj: file_obj.write(str(shell_pid)) # Print something to stdout so the client can start working - print(f"Server {a_id} ready") # py3k pylint: disable=C0325 + print(f"Server {a_id} ready") # py3k pylint: disable=C0325 sys.stdout.flush() # Initialize buffers buffers = [b"" for reader in readers] # Read from child and write to files/pipes - server_log.info('Entering main read loop') + server_log.info("Entering main read loop") while True: check_termination = False # Make a list of reader pipes whose buffers are not empty - fds = [reader_fd for (i, reader_fd) in enumerate(reader_fds) - if buffers[i]] + fds = [ + reader_fd + for (i, reader_fd) in enumerate(reader_fds) + if buffers[i] + ] # Wait until there's something to do - r_fds, w_fds = select.select([shell_fd, inpipe_fd, - ctrlpipe_fd], - fds, [], 0.5)[:2] + r_fds, w_fds = select.select( + [shell_fd, inpipe_fd, ctrlpipe_fd], fds, [], 0.5 + )[:2] # If a reader pipe is ready for writing -- - for (i, reader_fd) in enumerate(reader_fds): + for i, reader_fd in enumerate(reader_fds): if reader_fd in w_fds: bytes_written = os.write(reader_fd, buffers[i]) buffers[i] = buffers[i][bytes_written:] @@ -177,8 +192,10 @@ def main(): # too-many-* pylint:disable=R0914,R0912,R0915 data = os.read(inpipe_fd, 1024) os.write(shell_fd, data) - server_log.info('Out of the main read loop. Writing status to %s', - status_filename) + server_log.info( + "Out of the main read loop. Writing status to %s", + status_filename, + ) with open(status_filename, "w", encoding="utf-8") as file_obj: file_obj.write(str(status)) @@ -187,13 +204,13 @@ def main(): # too-many-* pylint:disable=R0914,R0912,R0915 # Close all files and pipes os.close(inpipe_fd) - server_log.info('Closed input pipe') + server_log.info("Closed input pipe") for reader_fd in reader_fds: os.close(reader_fd) - server_log.info('Closed reader fd %s', reader_fd) + server_log.info("Closed reader fd %s", reader_fd) unlock_fd(lock_server_running) - server_log.info('Exiting normally') + server_log.info("Exiting normally") sys.exit(0) diff --git a/aexpect/shared.py b/aexpect/shared.py index 1a077a4..e422097 100644 --- a/aexpect/shared.py +++ b/aexpect/shared.py @@ -11,8 +11,8 @@ """Some shared functions""" -import os import fcntl +import os import termios import time diff --git a/aexpect/utils/process.py b/aexpect/utils/process.py index 5914778..642ec71 100644 --- a/aexpect/utils/process.py +++ b/aexpect/utils/process.py @@ -11,9 +11,9 @@ """Process handling helpers""" -import subprocess -import signal import os +import signal +import subprocess def getoutput(cmd): diff --git a/aexpect/utils/wait.py b/aexpect/utils/wait.py index 382c71d..19721d3 100644 --- a/aexpect/utils/wait.py +++ b/aexpect/utils/wait.py @@ -11,8 +11,8 @@ """Module that helps waiting for conditions""" -import time import logging +import time _LOG = logging.getLogger(__file__) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..68e396b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,58 @@ +[build-system] +requires = ["setuptools>=61.0", "setuptools-scm>=8"] +build-backend = "setuptools.build_meta" + +[project] +name = "aexpect" +description = "Python library used to control interactive programs" +readme = "README.rst" +dynamic = ["version"] +license = "GPL-2.0-or-later" +authors = [{name = "Aexpect developers", email = "avocado-devel@redhat.com"}] +maintainers = [{name = "Aexpect developers", email = "avocado-devel@redhat.com"}] +requires-python = ">=3.8" +classifiers = [ + "Development Status :: 6 - Mature", + "Natural Language :: English", + "Operating System :: POSIX", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", +] +dependencies = [] + +[project.urls] +Homepage = "https://github.com/avocado-framework/aexpect" +Repository = "https://github.com/avocado-framework/aexpect" +Issues = "https://github.com/avocado-framework/aexpect/issues" + +[project.optional-dependencies] +test = ["pytest>=6.0"] +lint = ["black", "pycodestyle", "isort", "inspektor"] +dev = ["aexpect[test,lint]", "setuptools-scm>=8", "build", "twine"] + +[project.scripts] +aexpect_helper = "aexpect.scripts.aexpect_helper:main" + +[tool.setuptools.packages.find] +include = ["aexpect*"] + +[tool.setuptools_scm] +version_scheme = "post-release" +local_scheme = "node-and-date" + +[tool.black] +line-length = 79 +target-version = ["py38", "py39", "py310", "py311", "py312", "py313"] + +[tool.pytest.ini_options] +addopts = "-ra" +testpaths = ["tests"] + +[tool.isort] +profile = "black" +line_length = 79 diff --git a/setup.py b/setup.py deleted file mode 100644 index 2925141..0000000 --- a/setup.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/env python -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# -# See LICENSE for more details. -# -# Copyright: Red Hat Inc. 2013-2015 -# Author: Lucas Meneghel Rodrigues - -"""Aexpect setup script""" - -from setuptools import setup - - -def get_long_description(): - """Returns the content of README.rst""" - with open("README.rst", "r", encoding="utf-8") as req: - req_contents = req.read() - return req_contents - - -if __name__ == "__main__": - setup( - name="aexpect", - version="1.8.0", - description="Aexpect", - author="Aexpect developers", - author_email="avocado-devel@redhat.com", - long_description=get_long_description(), - long_description_content_type="text/markdown", - url="http://avocado-framework.github.io/", - license="GPLv2+", - classifiers=[ - "Development Status :: 6 - Mature", - "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", - "Natural Language :: English", - "Operating System :: POSIX", - "Programming Language :: Python :: 3", - ], - packages=["aexpect", "aexpect.utils"], - scripts=["scripts/aexpect_helper"], - test_suite="tests", - ) diff --git a/tests/test_remote_door.py b/tests/test_remote_door.py index 981ba6a..d474fd7 100644 --- a/tests/test_remote_door.py +++ b/tests/test_remote_door.py @@ -14,12 +14,12 @@ # # selftests pylint: disable=C0111,C0111,W0613,R0913,E1101 -import os import glob +import html +import os import re import shutil import unittest.mock -import html from aexpect import client, remote, remote_door from aexpect.client import RemoteSession