Skip to content

Commit

Permalink
build: use hatch for build and ruff for linting (#81)
Browse files Browse the repository at this point in the history
* build: use hatch and ruff

* fix: fix linting

* test: remove envs

* chore: cleanup

* chore: remove min-req

* chore: add setup

* chore: fix setuppy

* fix: fix docs build
  • Loading branch information
tlambert03 committed Nov 16, 2022
1 parent f9c9390 commit 0c9e6ac
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 94 deletions.
18 changes: 4 additions & 14 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace

- repo: https://github.com/PyCQA/autoflake
rev: v1.7.7
hooks:
- id: autoflake
args: ["--in-place", "--remove-all-unused-imports"]

- repo: https://github.com/PyCQA/isort
rev: 5.10.1
hooks:
Expand All @@ -41,15 +35,11 @@ repos:
hooks:
- id: black

- repo: https://github.com/PyCQA/flake8
rev: 5.0.4
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.118
hooks:
- id: flake8
additional_dependencies:
- flake8-pyprojecttoml @ git+https://github.com/tlambert03/flake8-pyprojecttoml.git@main
- flake8-bugbear
- flake8-docstrings
- flake8-typing-imports
- id: ruff
args: ["--fix"]

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.982
Expand Down
113 changes: 45 additions & 68 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# https://peps.python.org/pep-0517/
[build-system]
requires = ["setuptools>=45", "wheel", "setuptools-scm>=6.2"]
build-backend = "setuptools.build_meta"
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"

# https://peps.python.org/pep-0621/
[project]
Expand All @@ -13,15 +13,24 @@ license = { text = "BSD 3-Clause License" }
authors = [{ email = "talley.lambert@gmail.com" }, { name = "Talley Lambert" }]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Topic :: Desktop Environment",
"Topic :: Software Development",
"Topic :: Software Development :: User Interfaces",
]
dynamic = ["version"]
dependencies = ['psygnal', 'pydantic', 'in-n-out>=0.1.5', 'typing_extensions']
dependencies = [
"psygnal>=0.3.4",
"pydantic>=1.8",
"in-n-out>=0.1.5",
"typing_extensions",
]

# extras
# https://peps.python.org/pep-0621/#dependencies-optional-dependencies
Expand All @@ -31,12 +40,6 @@ test-qt = ["pytest-qt", "fonticon-fontawesome6"]
qt = ["qtpy", "superqt"]
dev = [
"black",
"cruft",
"flake8-bugbear",
"flake8-docstrings",
"flake8-pyprojecttoml",
"flake8-typing-imports",
"flake8",
"ipython",
"isort",
"mypy",
Expand All @@ -57,65 +60,51 @@ docs = [
"mkdocs-macros-plugin==0.7.0",
"typing_extensions>=4.0",
]

[project.urls]
homepage = "https://github.com/pyapp-kit/app-model"
repository = "https://github.com/pyapp-kit/app-model"

# same as console_scripts entry point
# [project.scripts]
# spam-cli = "spam:main_cli"

# Entry points
# https://peps.python.org/pep-0621/#entry-points
# [project.entry-points."spam.magical"]
# tomatoes = "spam:main_tomatoes"

# https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html
[tool.setuptools]
zip-safe = false
include-package-data = true
packages = { find = { where = ["src"], exclude = [] } }
[tool.hatch.version]
source = "vcs"

[tool.setuptools.package-data]
"*" = ["py.typed"]
[tool.hatch.envs.test]
features = ["test"]
[tool.hatch.envs.test.scripts]
run = "pytest -v --color=yes --cov-config=pyproject.toml -W i --cov=app_model --cov-report=xml --cov-report=term-missing"

# https://github.com/pypa/setuptools_scm/#pyprojecttoml-usage
[tool.setuptools_scm]

# https://pycqa.github.io/isort/docs/configuration/options.html
[tool.isort]
profile = "black"
src_paths = ["src/app_model", "tests"]

# https://flake8.pycqa.org/en/latest/user/options.html
# https://gitlab.com/durko/flake8-pyprojecttoml
[tool.flake8]
exclude = "docs,.eggs,examples,_version.py"
max-line-length = 88
ignore = "E203"
min-python-version = "3.8.0"
docstring-convention = "all" # use numpy convention, while allowing D417
extend-ignore = """
E203 # whitespace before ':'
D107,D203,D212,D213,D402,D413,D415,D416 # numpy
D100 # missing docstring in public module
D105 # missing docstring in magic method
D401 # imperative mood
W503 # line break before binary operator
B010
"""
per-file-ignores = [
"tests/*,demo/*,docs/*: D",
"src/app_model/_registries.py,src/app_model/context/_expressions.py: D10",
]

# https://github.com/charliermarsh/ruff
[tool.ruff]
target-version = "py38"
line-length = 88
extend-select = ["D", "M001"]
extend-ignore = [
"D100",
"D107",
"D203",
"D212",
"D213",
"D402",
"D413",
"D415",
"D416",
]

# http://www.pydocstyle.org/en/stable/usage.html
[tool.pydocstyle]
match_dir = "src/app_model"
convention = "numpy"
add_select = "D402,D415,D417"
ignore = "D100,D213,D401,D413,D107"
[tool.ruff.per-file-ignores]
"tests/*.py" = ["D", "E501"]
"demo/*" = ["D"]
"docs/*" = ["D"]
"src/app_model/_registries.py" = ["D10"]
"src/app_model/context/_expressions.py" = ["D10"]
"src/app_model/types/_keys/*" = ["E501"]
"setup.py" = ["F821"]

# https://docs.pytest.org/en/6.2.x/customize.html
[tool.pytest.ini_options]
Expand Down Expand Up @@ -149,19 +138,14 @@ exclude_lines = [
"if TYPE_CHECKING:",
"@overload",
"except ImportError",
"pass",
]
skip_covered = true
show_missing = true

# https://github.com/cruft/cruft
[tool.cruft]
skip = ["tests"]

# https://github.com/mgedmin/check-manifest#configuration
[tool.check-manifest]
ignore = [
".cruft.json",
".flake8",
".github_changelog_generator",
".pre-commit-config.yaml",
"tests/**/*",
Expand All @@ -171,12 +155,5 @@ ignore = [
".readthedocs.yaml",
"mkdocs.yml",
"CHANGELOG.md",
".ruff_cache/**/*",
]

# https://python-semantic-release.readthedocs.io/en/latest/configuration.html
[tool.semantic_release]
version_source = "tag_only"
branch = "main"
changelog_sections = "feature,fix,breaking,documentation,performance,chore,:boom:,:sparkles:,:children_crossing:,:lipstick:,:iphone:,:egg:,:chart_with_upwards_trend:,:ambulance:,:lock:,:bug:,:zap:,:goal_net:,:alien:,:wheelchair:,:speech_balloon:,:mag:,:apple:,:penguin:,:checkered_flag:,:robot:,:green_apple:,Other"
# commit_parser=semantic_release.history.angular_parser
build_command = "pip install build && python -m build"
29 changes: 29 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import sys

sys.stderr.write(
"""
===============================
Unsupported installation method
===============================
app-model does not support installation with `python setup.py install`.
Please use `python -m pip install .` instead.
"""
)
sys.exit(1)


# The below code will never execute, however GitHub is particularly
# picky about where it finds Python packaging metadata.
# See: https://github.com/github/feedback/discussions/6456
#
# To be removed once GitHub catches up.

setup(
name="app-model",
install_requires=[
"psygnal>=0.3.4",
"pydantic>=1.8",
"in-n-out>=0.1.5",
"typing_extensions",
],
)
8 changes: 4 additions & 4 deletions src/app_model/backends/qt/_qmenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@
# fmt: off
class _AcceptsMenus(Protocol):
_app: Application
def clear(self) -> None: ... # noqa: E704
def addMenu(self, menu: QMenu) -> None: ... # noqa: E704
def addAction(self, menu: QAction) -> None: ... # noqa: E704
def addSeparator(self) -> None: ... # noqa: E704
def clear(self) -> None: ...
def addMenu(self, menu: QMenu) -> None: ...
def addAction(self, menu: QAction) -> None: ...
def addSeparator(self) -> None: ...

# fmt: on

Expand Down
4 changes: 2 additions & 2 deletions src/app_model/expressions/_expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,9 +468,9 @@ class ExprTranformer(ast.NodeTransformer):

# fmt: off
@overload
def visit(self, node: ast.expr) -> Expr: ... # noqa
def visit(self, node: ast.expr) -> Expr: ...
@overload
def visit(self, node: PassedType) -> PassedType: ... # noqa
def visit(self, node: PassedType) -> PassedType: ...
# fmt: on

def visit(self, node: ast.AST) -> Optional[ast.AST]:
Expand Down
6 changes: 5 additions & 1 deletion src/app_model/registries/_commands_reg.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def __getitem__(self, id: str) -> _RegisteredCommand:
raise KeyError(f"Command {id!r} not registered")
return self._commands[id]

def execute_command(
def execute_command( # noqa: D417
self,
id: str,
*args: Any,
Expand All @@ -165,13 +165,17 @@ def execute_command(
----------
id : CommandId
ID of the command to execute
*args: Any
Positional arguments to pass to the command
execute_asychronously : bool
Whether to execute the command asynchronously in a thread,
by default `False`. Note that *regardless* of this setting,
the return value will implement the `Future` API (so it's necessary)
to call `result()` on the returned object. Eventually, this will
default to True, but we need to solve `ensure_main_thread` Qt threading
issues first
**kwargs: Any
Keyword arguments to pass to the command
Returns
-------
Expand Down
14 changes: 10 additions & 4 deletions src/app_model/types/_keys/_key_codes.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ class ScanCode(IntEnum):
implementations to support special keyboards (such as multimedia or
legacy keyboards).
"""

UNIDENTIFIED = 0 # This value code should be used when no other value given in this specification is appropriate.

# ----------------------- Writing System Keys -----------------------
Expand Down Expand Up @@ -651,8 +652,10 @@ def __or__(


class KeyCombo(int):
"""KeyCombo is an integer combination of one or more
[`KeyMod`][app_model.types.KeyMod] and [`KeyCode`][app_model.types.KeyCode]."""
"""KeyCombo is an integer combination of one or more.
[`KeyMod`][app_model.types.KeyMod] and [`KeyCode`][app_model.types.KeyCode].
"""

def __new__(
cls: Type["KeyCombo"], modifiers: KeyMod, key: KeyCode = KeyCode.UNKNOWN
Expand All @@ -670,8 +673,11 @@ def __repr__(self) -> str:


class KeyChord(int):
"""KeyChord is an integer combination of two [`KeyCombo`][app_model.types.KeyCombo],
[`KeyCode`][app_model.types.KeyCode], or [int][]."""
"""KeyChord is an integer combination of two key combos.
It could be two [`KeyCombo`][app_model.types.KeyCombo]
[`KeyCode`][app_model.types.KeyCode], or [int][].
"""

def __new__(cls: Type["KeyChord"], first_part: int, second_part: int) -> "KeyChord":
# shift the second part 16 bits to the left
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def redo(self) -> Mock:
fixtures directory must be added to sys path during the test (as we do below)
"""
try:
from fake_module import GLOBAL_MOCK # noqa
from fake_module import GLOBAL_MOCK

return GLOBAL_MOCK
except ImportError as e:
Expand Down

0 comments on commit 0c9e6ac

Please sign in to comment.