diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..00ca355 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,26 @@ +name: main + +on: + push: + branches: [main, test-me-*] + tags: '*' + pull_request: + +jobs: + main-windows: + uses: asottile/workflows/.github/workflows/tox.yml@v1.5.0 + with: + env: '["py38"]' + os: windows-latest + wheel-tags: true + main-macos: + uses: asottile/workflows/.github/workflows/tox.yml@v1.5.0 + with: + env: '["py38"]' + os: macos-latest + wheel-tags: true + main-linux: + uses: asottile/workflows/.github/workflows/tox.yml@v1.5.0 + with: + env: '["py38"]' + os: ubuntu-latest diff --git a/.gitignore b/.gitignore index 03d9416..6ac9777 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,3 @@ /.tox /build /dist -/venv diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2aa8e94..124e792 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,29 +1,37 @@ -# See https://pre-commit.com for more information -# See https://pre-commit.com/hooks.html for more hooks repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.1.0 +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 hooks: - - id: trailing-whitespace - - id: end-of-file-fixer - - id: check-yaml - - id: check-added-large-files - - id: double-quote-string-fixer - - repo: https://github.com/PyCQA/flake8 - rev: 4.0.1 + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: debug-statements + - id: double-quote-string-fixer + - id: name-tests-test + - id: requirements-txt-fixer +- repo: https://github.com/asottile/setup-cfg-fmt + rev: v2.5.0 hooks: - - id: flake8 - - repo: https://github.com/asottile/reorder_python_imports - rev: v2.7.1 + - id: setup-cfg-fmt +- repo: https://github.com/asottile/reorder-python-imports + rev: v3.12.0 hooks: - - id: reorder-python-imports - args: [--py37-plus] - - repo: https://github.com/asottile/add-trailing-comma - rev: v2.2.1 + - id: reorder-python-imports + args: [--py38-plus, --add-import, 'from __future__ import annotations'] +- repo: https://github.com/asottile/add-trailing-comma + rev: v3.1.0 hooks: - - id: add-trailing-comma - args: [--py36-plus] - - repo: https://github.com/asottile/setup-cfg-fmt - rev: v1.20.0 + - id: add-trailing-comma +- repo: https://github.com/asottile/pyupgrade + rev: v3.15.1 hooks: - - id: setup-cfg-fmt + - id: pyupgrade + args: [--py38-plus] +- repo: https://github.com/hhatto/autopep8 + rev: v2.0.4 + hooks: + - id: autopep8 +- repo: https://github.com/PyCQA/flake8 + rev: 7.0.0 + hooks: + - id: flake8 diff --git a/README.md b/README.md index db07238..7c5f4a6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -[![Build Status](https://dev.azure.com/shellcheck-py/shellcheck-py/_apis/build/status/shellcheck-py.shellcheck-py?branchName=master)](https://dev.azure.com/shellcheck-py/shellcheck-py/_build/latest?definitionId=1&branchName=master) -[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/shellcheck-py/shellcheck-py/master.svg)](https://results.pre-commit.ci/latest/github/shellcheck-py/shellcheck-py/master) +[![build status](https://github.com/shellcheck-py/shellcheck-py/actions/workflows/main.yml/badge.svg)](https://github.com/shellcheck-py/shellcheck-py/actions/workflows/main.yml) +[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/shellcheck-py/shellcheck-py/main.svg)](https://results.pre-commit.ci/latest/github/shellcheck-py/shellcheck-py/main) # shellcheck-py @@ -27,7 +27,7 @@ Sample `.pre-commit-config.yaml`: ```yaml - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.8.0.4 + rev: v0.10.0.1 hooks: - id: shellcheck ``` diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index ec6f42c..0000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,32 +0,0 @@ -trigger: - branches: - include: [master, test-me-*] - tags: - include: ['*'] - -resources: - repositories: - - repository: asottile - type: github - endpoint: github - name: asottile/azure-pipeline-templates - ref: refs/tags/v2.4.0 - -jobs: -- template: job--python-tox.yml@asottile - parameters: - toxenvs: [py38] - os: windows - coverage: false - wheel_tags: true -- template: job--python-tox.yml@asottile - parameters: - toxenvs: [py38] - os: macos - coverage: false - wheel_tags: true -- template: job--python-tox.yml@asottile - parameters: - toxenvs: [py38] - os: linux - coverage: false diff --git a/setup.cfg b/setup.cfg index 9ad8f74..17cedcb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,6 @@ [metadata] name = shellcheck_py +version = 0.10.0.1 description = Python wrapper around invoking shellcheck (https://www.shellcheck.net/) long_description = file: README.md long_description_content_type = text/markdown @@ -7,17 +8,63 @@ url = https://github.com/ryanrhee/shellcheck-py author = Ryan Rhee author_email = pypi@rhee.io license = MIT -license_file = LICENSE +license_files = LICENSE classifiers = License :: OSI Approved :: MIT License Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.7 - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: Implementation :: PyPy [options] -python_requires = >=3.7 +python_requires = >=3.8 +setup_requires = + setuptools-download + +[setuptools_download] +download_scripts = + [shellcheck] + group = shellcheck-binary + marker = sys_platform == "linux" and platform_machine == "armv6hf" + marker = sys_platform == "linux" and platform_machine == "armv7l" + url = https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.linux.armv6hf.tar.xz + sha256 = 1c89cb51e1412b580d7ba8aac240251ffb0b829788f83d2daa4a82da42d275e4 + extract = tar + extract_path = shellcheck-v0.10.0/shellcheck + [shellcheck] + group = shellcheck-binary + marker = sys_platform == "linux" and platform_machine == "aarch64" + url = https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.linux.aarch64.tar.xz + sha256 = 324a7e89de8fa2aed0d0c28f3dab59cf84c6d74264022c00c22af665ed1a09bb + extract = tar + extract_path = shellcheck-v0.10.0/shellcheck + [shellcheck] + group = shellcheck-binary + marker = sys_platform == "linux" and platform_machine == "x86_64" + url = https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.linux.x86_64.tar.xz + sha256 = 6c881ab0698e4e6ea235245f22832860544f17ba386442fe7e9d629f8cbedf87 + extract = tar + extract_path = shellcheck-v0.10.0/shellcheck + [shellcheck] + group = shellcheck-binary + marker = sys_platform == "darwin" and platform_machine == "arm64" + url = https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.darwin.aarch64.tar.xz + sha256 = bbd2f14826328eee7679da7221f2bc3afb011f6a928b848c80c321f6046ddf81 + extract = tar + extract_path = shellcheck-v0.10.0/shellcheck + [shellcheck] + group = shellcheck-binary + marker = sys_platform == "darwin" and platform_machine == "x86_64" + url = https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.darwin.x86_64.tar.xz + sha256 = ef27684f23279d112d8ad84e0823642e43f838993bbb8c0963db9b58a90464c2 + extract = tar + extract_path = shellcheck-v0.10.0/shellcheck + [shellcheck.exe] + group = shellcheck-binary + marker = sys_platform == "win32" and platform_machine == "AMD64" + marker = sys_platform == "win32" and platform_machine == "ARM64" + marker = sys_platform == "cygwin" and platform_machine == "x86_64" + url = https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.zip + sha256 = eb6cd53a54ea97a56540e9d296ce7e2fa68715aa507ff23574646c1e12b2e143 + extract = zip + extract_path = shellcheck.exe diff --git a/setup.py b/setup.py index a5bad2d..851bbfd 100644 --- a/setup.py +++ b/setup.py @@ -1,163 +1,11 @@ -#!/usr/bin/env python3 -import hashlib -import http -import io -import os.path -import platform -import stat -import sys -import tarfile -import urllib.request -import zipfile -from distutils.command.build import build as orig_build -from distutils.core import Command -from typing import Tuple +from __future__ import annotations from setuptools import setup -from setuptools.command.install import install as orig_install - -SHELLCHECK_VERSION = '0.8.0' -POSTFIX_SHA256 = { - ('linux', 'armv6hf'): ( - 'linux.armv6hf.tar.xz', - '17857c8a0a8f4001aa9638732991cbb6e85c4a410500b11e2e0a98d9858afca8', - ), - ('linux', 'aarch64'): ( - 'linux.aarch64.tar.xz', - '9f47bbff5624babfa712eb9d64ece14c6c46327122d0c54983f627ae3a30a4ac', - ), - ('linux', 'x86_64'): ( - 'linux.x86_64.tar.xz', - 'ab6ee1b178f014d1b86d1e24da20d1139656c8b0ed34d2867fbb834dad02bf0a', - ), - ('darwin', 'x86_64'): ( - 'darwin.x86_64.tar.xz', - 'e065d4afb2620cc8c1d420a9b3e6243c84ff1a693c1ff0e38f279c8f31e86634', - ), - ('win32', 'AMD64'): ( - 'zip', - '2a616cbb5b15aec8238f22c0d62dede1b6d155798adc45ff4d0206395a8a5833', - ), -} -POSTFIX_SHA256[('cygwin', 'x86_64')] = POSTFIX_SHA256[('win32', 'AMD64')] -POSTFIX_SHA256[('darwin', 'arm64')] = POSTFIX_SHA256[('darwin', 'x86_64')] -POSTFIX_SHA256[('linux', 'armv7l')] = POSTFIX_SHA256[('linux', 'armv6hf')] -PY_VERSION = '4' - - -def get_download_url() -> Tuple[str, str]: - postfix, sha256 = POSTFIX_SHA256[(sys.platform, platform.machine())] - url = ( - f'https://github.com/koalaman/shellcheck/releases/download/' - f'v{SHELLCHECK_VERSION}/shellcheck-v{SHELLCHECK_VERSION}.{postfix}' - ) - return url, sha256 - - -def download(url: str, sha256: str) -> bytes: - with urllib.request.urlopen(url) as resp: - code = resp.getcode() - if code != http.HTTPStatus.OK: - raise ValueError(f'HTTP failure. Code: {code}') - data = resp.read() - - checksum = hashlib.sha256(data).hexdigest() - if checksum != sha256: - raise ValueError(f'sha256 mismatch, expected {sha256}, got {checksum}') - - return data - - -def extract(url: str, data: bytes) -> bytes: - with io.BytesIO(data) as bio: - if '.tar.' in url: - with tarfile.open(fileobj=bio) as tarf: - for info in tarf.getmembers(): - if info.isfile() and info.name.endswith('shellcheck'): - return tarf.extractfile(info).read() - elif url.endswith('.zip'): - with zipfile.ZipFile(bio) as zipf: - for info in zipf.infolist(): - if info.filename.endswith('.exe'): - return zipf.read(info.filename) - - raise AssertionError(f'unreachable {url}') - - -def save_executable(data: bytes, base_dir: str): - exe = 'shellcheck' if sys.platform != 'win32' else 'shellcheck.exe' - output_path = os.path.join(base_dir, exe) - os.makedirs(base_dir) - - with open(output_path, 'wb') as fp: - fp.write(data) - - # Mark as executable. - # https://stackoverflow.com/a/14105527 - mode = os.stat(output_path).st_mode - mode |= stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH - os.chmod(output_path, mode) - - -class build(orig_build): - sub_commands = orig_build.sub_commands + [('fetch_binaries', None)] - - -class install(orig_install): - sub_commands = orig_install.sub_commands + [('install_shellcheck', None)] - - -class fetch_binaries(Command): - build_temp = None - - def initialize_options(self): - pass - - def finalize_options(self): - self.set_undefined_options('build', ('build_temp', 'build_temp')) - - def run(self): - # save binary to self.build_temp - url, sha256 = get_download_url() - archive = download(url, sha256) - data = extract(url, archive) - save_executable(data, self.build_temp) - - -class install_shellcheck(Command): - description = 'install the shellcheck executable' - outfiles = () - build_dir = install_dir = None - - def initialize_options(self): - pass - - def finalize_options(self): - # this initializes attributes based on other commands' attributes - self.set_undefined_options('build', ('build_temp', 'build_dir')) - self.set_undefined_options( - 'install', ('install_scripts', 'install_dir'), - ) - - def run(self): - self.outfiles = self.copy_tree(self.build_dir, self.install_dir) - - def get_outputs(self): - return self.outfiles - - -command_overrides = { - 'install': install, - 'install_shellcheck': install_shellcheck, - 'build': build, - 'fetch_binaries': fetch_binaries, -} - try: from wheel.bdist_wheel import bdist_wheel as orig_bdist_wheel except ImportError: - pass + cmdclass = {} else: class bdist_wheel(orig_bdist_wheel): def finalize_options(self): @@ -170,6 +18,6 @@ def get_tag(self): # We don't contain any python source, nor any python extensions return 'py2.py3', 'none', plat - command_overrides['bdist_wheel'] = bdist_wheel + cmdclass = {'bdist_wheel': bdist_wheel} -setup(version=f'{SHELLCHECK_VERSION}.{PY_VERSION}', cmdclass=command_overrides) +setup(cmdclass=cmdclass) diff --git a/tox.ini b/tox.ini index e13b944..0403be0 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py38,pre-commit +envlist = py,pre-commit [testenv] commands =