diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index e7d592e5..00000000 --- a/.coveragerc +++ /dev/null @@ -1,2 +0,0 @@ -[run] -omit = */tests* diff --git a/.github/workflows/constraints.txt b/.github/workflows/constraints.txt new file mode 100644 index 00000000..6198f842 --- /dev/null +++ b/.github/workflows/constraints.txt @@ -0,0 +1,5 @@ +pip==21.3.1 +nox==2021.10.1 +nox-poetry==0.9.0 +poetry==1.1.12 +virtualenv==20.10.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6d393257..2068064a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,30 +1,73 @@ -# This workflow will upload a Python Package using Twine when a release is created -# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries +--- name: Release on: - release: - types: [created] + push: + branches: + - main + - master jobs: - deploy: - + release: + name: Release runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.x' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install setuptools wheel twine - - name: Build and publish - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} - run: | - python setup.py sdist bdist_wheel - twine upload dist/* + - name: Check out the repository + uses: actions/checkout@v2.4.0 + with: + fetch-depth: 2 + + - name: Set up Python + uses: actions/setup-python@v2.3.1 + with: + python-version: "3.10" + + - name: Upgrade pip + run: | + pip install --constraint=.github/workflows/constraints.txt pip + pip --version + + - name: Install Poetry + run: | + pip install --constraint=.github/workflows/constraints.txt poetry + poetry --version + + - name: Check if there is a parent commit + id: check-parent-commit + run: | + echo "::set-output name=sha::$(git rev-parse --verify --quiet HEAD^)" + + - name: Detect and tag new version + id: check-version + if: steps.check-parent-commit.outputs.sha + uses: salsify/action-detect-and-tag-new-version@v2.0.1 + with: + version-command: | + bash -o pipefail -c "poetry version | awk '{ print \$2 }'" + + - name: Bump version for developmental release + if: "! steps.check-version.outputs.tag" + run: | + poetry version patch && + version=$(poetry version | awk '{ print $2 }') && + poetry version $version.dev.$(date +%s) + + - name: Build package + run: | + poetry build --ansi + + + - name: Publish package on PyPI + if: steps.check-version.outputs.tag + uses: pypa/gh-action-pypi-publish@v1.4.2 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} + + - name: Publish the release notes + uses: release-drafter/release-drafter@v5.15.0 + with: + publish: ${{ steps.check-version.outputs.tag != '' }} + tag: ${{ steps.check-version.outputs.tag }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d0368aa4..7abac910 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,38 +1,137 @@ -# This workflow will install Python dependencies, run tests and lint with a variety of Python versions -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions +--- name: Tests on: - push: - branches: [ master ] - pull_request: - branches: [ master ] + - push + - pull_request jobs: - build: - + tests: + name: ${{ matrix.session }} ${{ matrix.python }} / ${{ matrix.os }} + runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - platform: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.7", "3.8", "3.9", "3.10"] - runs-on: ${{ matrix.platform }} + include: + - { python: "3.10", os: "ubuntu-latest", session: "pre-commit" } + - { python: "3.10", os: "ubuntu-latest", session: "tests" } + - { python: "3.9", os: "ubuntu-latest", session: "tests" } + - { python: "3.8", os: "ubuntu-latest", session: "tests" } + - { python: "3.7", os: "ubuntu-latest", session: "tests" } + - { python: "3.10", os: "windows-latest", session: "tests" } + - { python: "3.10", os: "macos-latest", session: "tests" } + + env: + NOXSESSION: ${{ matrix.session }} + FORCE_COLOR: "1" + PRE_COMMIT_COLOR: "always" steps: - - uses: actions/checkout@v2.4.0 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2.3.1 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - python -m pip install -r requirements-dev.txt - - name: Lint with flake8 - run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - name: Test with pytest - run: | - pytest + - name: Check out the repository + uses: actions/checkout@v2.4.0 + + - name: Set up Python ${{ matrix.python }} + uses: actions/setup-python@v2.3.1 + with: + python-version: ${{ matrix.python }} + + - name: Upgrade pip + run: | + pip install --constraint=.github/workflows/constraints.txt pip + pip --version + + - name: Upgrade pip in virtual environments + shell: python + run: | + import os + import pip + with open(os.environ["GITHUB_ENV"], mode="a") as io: + print(f"VIRTUALENV_PIP={pip.__version__}", file=io) + + - name: Install Poetry + run: | + pipx install --pip-args=--constraint=.github/workflows/constraints.txt poetry + poetry --version + + - name: Install Nox + run: | + pipx install --pip-args=--constraint=.github/workflows/constraints.txt nox + pipx inject --pip-args=--constraint=.github/workflows/constraints.txt nox nox-poetry + nox --version + + - name: Compute pre-commit cache key + if: matrix.session == 'pre-commit' + id: pre-commit-cache + shell: python + run: | + import hashlib + import sys + python = "py{}.{}".format(*sys.version_info[:2]) + payload = sys.version.encode() + sys.executable.encode() + digest = hashlib.sha256(payload).hexdigest() + result = "${{ runner.os }}-{}-{}-pre-commit".format(python, digest[:8]) + print("::set-output name=result::{}".format(result)) + + - name: Restore pre-commit cache + uses: actions/cache@v2.1.7 + if: matrix.session == 'pre-commit' + with: + path: ~/.cache/pre-commit + key: ${{ steps.pre-commit-cache.outputs.result }}-${{ hashFiles('.pre-commit-config.yaml') }} + restore-keys: | + ${{ steps.pre-commit-cache.outputs.result }}- + + - name: Run Nox + run: | + nox --force-color --python=${{ matrix.python }} + + - name: Upload coverage data + if: always() && matrix.session == 'tests' + uses: "actions/upload-artifact@v2.3.1" + with: + name: coverage-data + path: ".coverage.*" + + coverage: + runs-on: ubuntu-latest + needs: tests + steps: + - name: Check out the repository + uses: actions/checkout@v2.4.0 + + - name: Set up Python + uses: actions/setup-python@v2.3.1 + with: + python-version: "3.10" + + - name: Upgrade pip + run: | + pip install --constraint=.github/workflows/constraints.txt pip + pip --version + + - name: Install Poetry + run: | + pipx install --pip-args=--constraint=.github/workflows/constraints.txt poetry + poetry --version + + - name: Install Nox + run: | + pipx install --pip-args=--constraint=.github/workflows/constraints.txt nox + pipx inject --pip-args=--constraint=.github/workflows/constraints.txt nox nox-poetry + nox --version + + - name: Download coverage data + uses: actions/download-artifact@v2.1.0 + with: + name: coverage-data + + - name: Combine coverage data and display human readable report + run: | + nox --force-color --session=coverage + + - name: Create coverage report + run: | + nox --force-color --session=coverage -- xml + + - name: Upload coverage report + uses: codecov/codecov-action@v2.1.0 diff --git a/.gitignore b/.gitignore index 380478e7..ff634564 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,11 @@ *~ -\#* -\.\#* *.pyc *.egg-info/ venv/ -.coverage* -coverage.xml -dist/ -build/ -runtests.py +/.coverage +/.coverage.* +/.nox/ +/dist/ .cache *.swp -.ropeproject/ +__pycache__/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f32216e4..b5db20fc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,6 +16,11 @@ repos: rev: 6de8252c035844f1e679f509b5f37340b44d5c39 hooks: - id: flake8 + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.1.0 + hooks: + - id: check-yaml + - id: trailing-whitespace - repo: https://github.com/asottile/pyupgrade rev: v2.29.1 hooks: diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 67a5dc89..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1,9 +0,0 @@ -include changes.rst -include LICENSE -include Makefile -include README.rst -include requirements.txt -include setup.cfg - -recursive-include inquirer/ * -recursive-include tests/ * diff --git a/README.rst b/README.rst index cde106da..8e604be7 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ ==================== ================================================================================= -Tests |Tests| |coveralls| +Tests |Tests| |Codecov| -------------------- --------------------------------------------------------------------------------- Downloads |pip dm| |pip dw| |pip dd| -------------------- --------------------------------------------------------------------------------- @@ -28,7 +28,7 @@ Installation ============ .. code:: console - + pip install inquirer @@ -46,7 +46,7 @@ Text .. code:: python import re - + import inquirer questions = [ inquirer.Text('name', message="What's your name"), @@ -156,9 +156,9 @@ Licensed under `the MIT license`_. .. |Tests| image:: https://github.com/magmax/python-inquirer/workflows/Tests/badge.svg :target: https://github.com/magmax/python-inquirer/actions?workflow=Tests :alt: Tests -.. |coveralls| image:: https://coveralls.io/repos/magmax/python-inquirer/badge.png - :target: `Coveralls`_ - :alt: Coveralls results_ +.. |Codecov| image:: https://codecov.io/gh/magmax/python-inquirer/branch/master/graph/badge.svg + :target: https://app.codecov.io/gh/magmax/python-inquirer + :alt: Codecov .. |pip version| image:: https://img.shields.io/pypi/v/inquirer.svg :target: https://pypi.python.org/pypi/inquirer :alt: Latest PyPI version @@ -201,7 +201,6 @@ Licensed under `the MIT license`_. :alt: Example of Checkbox Question .. _Inquirer.js: https://github.com/SBoudrias/Inquirer.js -.. _Coveralls: https://coveralls.io/r/magmax/python-inquirer .. _examples/: https://github.com/magmax/python-inquirer/tree/master/examples .. _`download the python-inquirer code from GitHub`: https://github.com/magmax/python-inquirer .. _`download the wheel from Pypi`: https://pypi.python.org/pypi/inquirer diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..4f6dd27d --- /dev/null +++ b/codecov.yml @@ -0,0 +1,10 @@ + +comment: false +coverage: + status: + project: + default: + target: "90" + patch: + default: + target: "90" diff --git a/noxfile.py b/noxfile.py new file mode 100644 index 00000000..17195045 --- /dev/null +++ b/noxfile.py @@ -0,0 +1,217 @@ +"""Nox sessions.""" +import os +import shlex +import shutil +import sys +from pathlib import Path +from textwrap import dedent + +import nox + + +try: + from nox_poetry import Session + from nox_poetry import session +except ImportError: + message = f"""\ + Nox failed to import the 'nox-poetry' package. + + Please install it using the following command: + + {sys.executable} -m pip install nox-poetry""" + raise SystemExit(dedent(message)) from None + + +package = "inquirer" +python_versions = ["3.10", "3.9", "3.8", "3.7"] +nox.needs_version = ">= 2021.6.6" +nox.options.sessions = ( + "pre-commit", + "tests", +) + + +def activate_virtualenv_in_precommit_hooks(session: Session) -> None: + """Activate virtualenv in hooks installed by pre-commit. + + This function patches git hooks installed by pre-commit to activate the + session's virtual environment. This allows pre-commit to locate hooks in + that environment when invoked from git. + + Args: + session: The Session object. + """ + assert session.bin is not None # noqa: S101 + + # Only patch hooks containing a reference to this session's bindir. Support + # quoting rules for Python and bash, but strip the outermost quotes so we + # can detect paths within the bindir, like /python. + bindirs = [ + bindir[1:-1] if bindir[0] in "'\"" else bindir for bindir in (repr(session.bin), shlex.quote(session.bin)) + ] + + virtualenv = session.env.get("VIRTUAL_ENV") + if virtualenv is None: + return + + headers = { + # pre-commit < 2.16.0 + "python": f"""\ + import os + os.environ["VIRTUAL_ENV"] = {virtualenv!r} + os.environ["PATH"] = os.pathsep.join(( + {session.bin!r}, + os.environ.get("PATH", ""), + )) + """, + # pre-commit >= 2.16.0 + "bash": f"""\ + VIRTUAL_ENV={shlex.quote(virtualenv)} + PATH={shlex.quote(session.bin)}"{os.pathsep}$PATH" + """, + } + + hookdir = Path(".git") / "hooks" + if not hookdir.is_dir(): + return + + for hook in hookdir.iterdir(): + if hook.name.endswith(".sample") or not hook.is_file(): + continue + + if not hook.read_bytes().startswith(b"#!"): + continue + + text = hook.read_text() + + if not any(Path("A") == Path("a") and bindir.lower() in text.lower() or bindir in text for bindir in bindirs): + continue + + lines = text.splitlines() + + for executable, header in headers.items(): + if executable in lines[0].lower(): + lines.insert(1, dedent(header)) + hook.write_text("\n".join(lines)) + break + + +@session(name="pre-commit", python=python_versions[0]) +def precommit(session: Session) -> None: + """Lint using pre-commit.""" + args = session.posargs or ["run", "--all-files", "--show-diff-on-failure"] + session.install( + "black", + "darglint", + "flake8", + "flake8-bandit", + "flake8-bugbear", + "flake8-docstrings", + "flake8-rst-docstrings", + "isort", + "pep8-naming", + "pre-commit", + "pre-commit-hooks", + "pyupgrade", + ) + session.run("pre-commit", *args) + if args and args[0] == "install": + activate_virtualenv_in_precommit_hooks(session) + + +@session(python=python_versions[0]) +def safety(session: Session) -> None: + """Scan dependencies for insecure packages.""" + requirements = session.poetry.export_requirements() + session.install("safety") + session.run("safety", "check", "--full-report", f"--file={requirements}") + + +@session(python=python_versions) +def mypy(session: Session) -> None: + """Type-check using mypy.""" + args = session.posargs or ["src", "tests", "docs/conf.py"] + session.install(".") + session.install("mypy", "pytest") + session.run("mypy", *args) + if not session.posargs: + session.run("mypy", f"--python-executable={sys.executable}", "noxfile.py") + + +@session(python=python_versions) +def tests(session: Session) -> None: + """Run the test suite.""" + session.install(".") + session.install("coverage[toml]", "pexpect", "pytest", "pygments") + try: + session.run("coverage", "run", "--parallel", "-m", "pytest", *session.posargs) + finally: + if session.interactive: + session.notify("coverage", posargs=[]) + + +@session(python=python_versions[0]) +def coverage(session: Session) -> None: + """Produce the coverage report.""" + args = session.posargs or ["report"] + + session.install("coverage[toml]") + + if not session.posargs and any(Path().glob(".coverage.*")): + session.run("coverage", "combine") + + session.run("coverage", *args) + + +@session(python=python_versions) +def typeguard(session: Session) -> None: + """Runtime type checking using Typeguard.""" + session.install(".") + session.install("pytest", "typeguard", "pygments") + session.run("pytest", f"--typeguard-packages={package}", *session.posargs) + + +@session(python=python_versions) +def xdoctest(session: Session) -> None: + """Run examples with xdoctest.""" + if session.posargs: + args = [package, *session.posargs] + else: + args = [f"--modname={package}", "--command=all"] + if "FORCE_COLOR" in os.environ: + args.append("--colored=1") + + session.install(".") + session.install("xdoctest[colors]") + session.run("python", "-m", "xdoctest", *args) + + +@session(name="docs-build", python=python_versions[0]) +def docs_build(session: Session) -> None: + """Build the documentation.""" + args = session.posargs or ["docs", "docs/_build"] + if not session.posargs and "FORCE_COLOR" in os.environ: + args.insert(0, "--color") + + session.install(".") + session.install("sphinx", "sphinx-click", "furo") + + build_dir = Path("docs", "_build") + if build_dir.exists(): + shutil.rmtree(build_dir) + + session.run("sphinx-build", *args) + + +@session(python=python_versions[0]) +def docs(session: Session) -> None: + """Build and serve the documentation with live reloading on file changes.""" + args = session.posargs or ["--open-browser", "docs", "docs/_build"] + session.install(".") + session.install("sphinx", "sphinx-autobuild", "sphinx-click", "furo") + + build_dir = Path("docs", "_build") + if build_dir.exists(): + shutil.rmtree(build_dir) + + session.run("sphinx-autobuild", *args) diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 00000000..a8af2463 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,128 @@ +[[package]] +name = "ansicon" +version = "1.89.0" +description = "Python wrapper for loading Jason Hood's ANSICON" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "blessed" +version = "1.19.0" +description = "Easy, practical library for making terminal apps, by providing an elegant, well-documented interface to Colors, Keyboard input, and screen Positioning capabilities." +category = "main" +optional = false +python-versions = ">=2.7" + +[package.dependencies] +jinxed = {version = ">=1.1.0", markers = "platform_system == \"Windows\""} +six = ">=1.9.0" +wcwidth = ">=0.1.4" + +[[package]] +name = "jinxed" +version = "1.1.0" +description = "Jinxed Terminal Library" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +ansicon = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "pexpect" +version = "4.8.0" +description = "Pexpect allows easy control of interactive console applications." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +ptyprocess = ">=0.5" + +[[package]] +name = "ptyprocess" +version = "0.7.0" +description = "Run a subprocess in a pseudo terminal" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "python-editor" +version = "1.0.4" +description = "Programmatically open an editor, capture the result." +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "readchar" +version = "3.0.4" +description = "Utilities to read single characters and key-strokes" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "wcwidth" +version = "0.2.5" +description = "Measures the displayed width of unicode strings in a terminal" +category = "main" +optional = false +python-versions = "*" + +[metadata] +lock-version = "1.1" +python-versions = ">=3.7" +content-hash = "2b644ac763c76fcccda8b7a64b51abad9c3f3858c00d5a8d7579763e71c5ac51" + +[metadata.files] +ansicon = [ + {file = "ansicon-1.89.0-py2.py3-none-any.whl", hash = "sha256:f1def52d17f65c2c9682cf8370c03f541f410c1752d6a14029f97318e4b9dfec"}, + {file = "ansicon-1.89.0.tar.gz", hash = "sha256:e4d039def5768a47e4afec8e89e83ec3ae5a26bf00ad851f914d1240b444d2b1"}, +] +blessed = [ + {file = "blessed-1.19.0-py2.py3-none-any.whl", hash = "sha256:1f2d462631b2b6d2d4c3c65b54ef79ad87a6ca2dd55255df2f8d739fcc8a1ddb"}, + {file = "blessed-1.19.0.tar.gz", hash = "sha256:4db0f94e5761aea330b528e84a250027ffe996b5a94bf03e502600c9a5ad7a61"}, +] +jinxed = [ + {file = "jinxed-1.1.0-py2.py3-none-any.whl", hash = "sha256:6a61ccf963c16aa885304f27e6e5693783676897cea0c7f223270c8b8e78baf8"}, + {file = "jinxed-1.1.0.tar.gz", hash = "sha256:d8f1731f134e9e6b04d95095845ae6c10eb15cb223a5f0cabdea87d4a279c305"}, +] +pexpect = [ + {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, + {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, +] +ptyprocess = [ + {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, + {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, +] +python-editor = [ + {file = "python-editor-1.0.4.tar.gz", hash = "sha256:51fda6bcc5ddbbb7063b2af7509e43bd84bfc32a4ff71349ec7847713882327b"}, + {file = "python_editor-1.0.4-py2-none-any.whl", hash = "sha256:5f98b069316ea1c2ed3f67e7f5df6c0d8f10b689964a4a811ff64f0106819ec8"}, + {file = "python_editor-1.0.4-py2.7.egg", hash = "sha256:ea87e17f6ec459e780e4221f295411462e0d0810858e055fc514684350a2f522"}, + {file = "python_editor-1.0.4-py3-none-any.whl", hash = "sha256:1bf6e860a8ad52a14c3ee1252d5dc25b2030618ed80c022598f00176adc8367d"}, + {file = "python_editor-1.0.4-py3.5.egg", hash = "sha256:c3da2053dbab6b29c94e43c486ff67206eafbe7eb52dbec7390b5e2fb05aac77"}, +] +readchar = [ + {file = "readchar-3.0.4-py3-none-any.whl", hash = "sha256:ebe7b51edae808101ea54b63468e8bea87e0c246301a0100f7777219eb2eb844"}, + {file = "readchar-3.0.4.tar.gz", hash = "sha256:3ce642ade5b61efee273b3c4bf55c77a84398178842627c74fcb796e1666ab13"}, +] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] +wcwidth = [ + {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, + {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, +] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..94116e49 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,44 @@ +[tool.poetry] +name = "inquirer" +version = "3.0.0" +description = "Collection of common interactive command line user interfaces, based on Inquirer.js" +authors = ["Miguel Ángel García "] +license = "MIT" +readme = "README.rst" +homepage = "https://github.com/magmax/python-inquirer" +repository = "https://github.com/magmax/python-inquirer" +documentation = "https://github.com/magmax/python-inquirer" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Topic :: Software Development :: User Interfaces", + "Topic :: Software Development :: Libraries :: Application Frameworks", +] + +[tool.poetry.dependencies] +python = ">=3.7" +blessed = ">=1.19.0" +readchar = ">=2.0.1" +python-editor = ">=1.0.4" + +[tool.poetry.dev-dependencies] +pexpect = ">=4.8.0" + +[tool.coverage.paths] +source = ["src", "*/site-packages"] +tests = ["tests", "*/tests"] + +[tool.coverage.run] +branch = true +source = ["inquirer", "tests"] + +[tool.coverage.report] +show_missing = true +fail_under = 90 + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index c9fd125d..00000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,12 +0,0 @@ --r requirements.txt - -flake8==3.8.4 -pexpect==4.8.0 - -pytest==6.2.5 -pytest-cov==2.12.1 -mock==4.0.3 - -python-coveralls==2.9.3 - -wheel >= 0.36.2 diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 36941581..00000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -blessed==1.19.0 -readchar==2.0.1 -python-editor==1.0.4 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index f25c4c05..00000000 --- a/setup.cfg +++ /dev/null @@ -1,5 +0,0 @@ -[tool:pytest] -norecursedirs = .git venv build dist - -[bdist_wheel] -universal=1 diff --git a/setup.py b/setup.py deleted file mode 100644 index b92e90fb..00000000 --- a/setup.py +++ /dev/null @@ -1,80 +0,0 @@ -import sys -import os -from setuptools import setup, find_packages -from setuptools.command.test import test as TestCommand - -version = "3.0.0" -github_ref = os.getenv("GITHUB_REF") -if github_ref and github_ref.startswith("refs/tags"): - version = github_ref[10:] - - -def read_description(): - try: - with open("README.rst", encoding="utf8") as fd: - return fd.read() - except TypeError: - with open("README.rst") as fd: - return fd.read() - - -def read_requirements(): - try: - with open("requirements.txt", encoding="utf8") as fd: - return fd.read() - except TypeError: - with open("requirements.txt") as fd: - return fd.read() - - -class PyTest(TestCommand): - user_options = [ - ("pytest-args=", "a", "Arguments to pass to py.test"), - ] - - def initialize_options(self): - TestCommand.initialize_options(self) - self.pytest_args = [] - - def finalize_options(self): - TestCommand.finalize_options(self) - self.test_args = [] - self.test_suite = True - - def run_tests(self): - # import here, cause outside the eggs aren't loaded - import pytest - - errno = pytest.main(self.pytest_args or ["--cov-report=term-missing"]) - sys.exit(errno) - - -setup( - name="inquirer", - version=version, - description=("Collection of common interactive command line user interfaces," " based on Inquirer.js"), - long_description=read_description(), - cmdclass={"test": PyTest}, - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Environment :: Console", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent", - "Topic :: Software Development :: User Interfaces", - "Topic :: Software Development :: " "Libraries :: Application Frameworks", - ], - keywords="color terminal", - author="Miguel Ángel García", - author_email="miguelangel.garcia@gmail.com", - url="https://github.com/magmax/python-inquirer", - license="MIT", - packages=find_packages(exclude=["tests"]), - include_package_data=True, - zip_safe=False, - install_requires=read_requirements().splitlines(), -) diff --git a/inquirer/__init__.py b/src/inquirer/__init__.py similarity index 73% rename from inquirer/__init__.py rename to src/inquirer/__init__.py index 31552435..ccc14e01 100644 --- a/inquirer/__init__.py +++ b/src/inquirer/__init__.py @@ -1,5 +1,5 @@ -from .prompt import prompt -from .questions import ( +from inquirer.prompt import prompt +from inquirer.questions import ( Text, Editor, Password, @@ -11,7 +11,7 @@ load_from_json, load_from_list, ) -from .shortcuts import text, editor, password, confirm, list_input, checkbox +from inquirer.shortcuts import text, editor, password, confirm, list_input, checkbox __all__ = [ "prompt", diff --git a/inquirer/errors.py b/src/inquirer/errors.py similarity index 100% rename from inquirer/errors.py rename to src/inquirer/errors.py diff --git a/inquirer/events.py b/src/inquirer/events.py similarity index 100% rename from inquirer/events.py rename to src/inquirer/events.py diff --git a/inquirer/prompt.py b/src/inquirer/prompt.py similarity index 100% rename from inquirer/prompt.py rename to src/inquirer/prompt.py diff --git a/inquirer/questions.py b/src/inquirer/questions.py similarity index 100% rename from inquirer/questions.py rename to src/inquirer/questions.py diff --git a/inquirer/render/__init__.py b/src/inquirer/render/__init__.py similarity index 100% rename from inquirer/render/__init__.py rename to src/inquirer/render/__init__.py diff --git a/inquirer/render/console/__init__.py b/src/inquirer/render/console/__init__.py similarity index 100% rename from inquirer/render/console/__init__.py rename to src/inquirer/render/console/__init__.py diff --git a/inquirer/render/console/_checkbox.py b/src/inquirer/render/console/_checkbox.py similarity index 100% rename from inquirer/render/console/_checkbox.py rename to src/inquirer/render/console/_checkbox.py diff --git a/inquirer/render/console/_confirm.py b/src/inquirer/render/console/_confirm.py similarity index 100% rename from inquirer/render/console/_confirm.py rename to src/inquirer/render/console/_confirm.py diff --git a/inquirer/render/console/_editor.py b/src/inquirer/render/console/_editor.py similarity index 100% rename from inquirer/render/console/_editor.py rename to src/inquirer/render/console/_editor.py diff --git a/inquirer/render/console/_list.py b/src/inquirer/render/console/_list.py similarity index 100% rename from inquirer/render/console/_list.py rename to src/inquirer/render/console/_list.py diff --git a/inquirer/render/console/_password.py b/src/inquirer/render/console/_password.py similarity index 100% rename from inquirer/render/console/_password.py rename to src/inquirer/render/console/_password.py diff --git a/inquirer/render/console/_path.py b/src/inquirer/render/console/_path.py similarity index 100% rename from inquirer/render/console/_path.py rename to src/inquirer/render/console/_path.py diff --git a/inquirer/render/console/_text.py b/src/inquirer/render/console/_text.py similarity index 100% rename from inquirer/render/console/_text.py rename to src/inquirer/render/console/_text.py diff --git a/inquirer/render/console/base.py b/src/inquirer/render/console/base.py similarity index 100% rename from inquirer/render/console/base.py rename to src/inquirer/render/console/base.py diff --git a/inquirer/shortcuts.py b/src/inquirer/shortcuts.py similarity index 100% rename from inquirer/shortcuts.py rename to src/inquirer/shortcuts.py diff --git a/inquirer/themes.py b/src/inquirer/themes.py similarity index 100% rename from inquirer/themes.py rename to src/inquirer/themes.py diff --git a/tests/unit/test_question.py b/tests/unit/test_question.py index 9a2a2dbc..476d2af2 100644 --- a/tests/unit/test_question.py +++ b/tests/unit/test_question.py @@ -260,14 +260,13 @@ def do_test(path, result=True): do_test(None, False) - if os.environ.get("TRAVIS_PYTHON_VERSION") != "pypy3": - # Path component must not be longer then 255 bytes - do_test("a" * 256, False) - do_test(os.path.abspath("/asdf/" + "a" * 256), False) - do_test("{}/{}".format("a" * 255, "b" * 255), True) - - # Path component must not contains null bytes - do_test("some/path/with/{}byte".format(b"\x00".decode("utf-8")), False) + # Path component must not be longer then 255 bytes + do_test("a" * 256, False) + do_test(os.path.abspath("/asdf/" + "a" * 256), False) + do_test("{}/{}".format("a" * 255, "b" * 255), True) + + # Path component must not contains null bytes + do_test("some/path/with/{}byte".format(b"\x00".decode("utf-8")), False) def test_path_type_validation_no_existence_check(self): def do_test(path_type, path, result=True):