Skip to content

Commit 29e6950

Browse files
authored
Merge pull request #65 from mxstack/feature/ty-domain
Feature: support for ty typechecker (new domain under qa)
2 parents 987b77b + 7526d35 commit 29e6950

File tree

12 files changed

+148
-175
lines changed

12 files changed

+148
-175
lines changed

.github/workflows/release.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
uses: "./.github/workflows/lint.yml"
1818
variants:
1919
uses: "./.github/workflows/variants.yml"
20-
typecheck:
21-
uses: "./.github/workflows/typecheck.yml"
2220

2321
# Always build & lint package.
2422
build-package:
@@ -27,7 +25,6 @@
2725
- lint
2826
- tests
2927
- variants
30-
- typecheck
3128
runs-on: ubuntu-latest
3229
permissions:
3330
attestations: write

.github/workflows/typecheck.yml

Lines changed: 0 additions & 28 deletions
This file was deleted.

CHANGES.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## 2.2.0
4+
5+
- Feature: Add `qa.ty` domain for Astral's ty type checker.
6+
ty is an extremely fast Python type checker (10-100x faster than mypy).
7+
Registers with both CHECK_TARGETS and TYPECHECK_TARGETS for fast feedback.
8+
[jensens]
9+
310
## 2.1.0
411

512
- Enhancement: Use tables in the generated sphinx code for topic/domains.

Makefile

Lines changed: 53 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@
88
#: core.mxfiles
99
#: core.packages
1010
#: docs.sphinx
11-
#: qa.coverage
12-
#: qa.isort
13-
#: qa.mypy
1411
#: qa.ruff
1512
#: qa.test
13+
#: qa.ty
1614
#
1715
# SETTINGS (ALL CHANGES MADE BELOW SETTINGS WILL BE LOST)
1816
##############################################################################
@@ -111,12 +109,6 @@ MXMAKE?=-e .
111109
# Default: src
112110
RUFF_SRC?=src
113111

114-
## qa.isort
115-
116-
# Source folder to scan for Python files to run isort on.
117-
# Default: src
118-
ISORT_SRC?=src
119-
120112
## docs.sphinx
121113

122114
# Documentation source folder.
@@ -148,6 +140,17 @@ PROJECT_CONFIG?=mx.ini
148140
# Default: false
149141
PACKAGES_ALLOW_PRERELEASES?=false
150142

143+
## qa.ty
144+
145+
# Source folder for type checking.
146+
# Default: src
147+
TY_SRC?=src
148+
149+
# Target Python version for type checking (e.g., 3.12).
150+
# Leave empty to use default detection.
151+
# No default value.
152+
TY_PYTHON_VERSION?=
153+
151154
## qa.test
152155

153156
# The command which gets executed. Defaults to the location the
@@ -164,23 +167,6 @@ TEST_REQUIREMENTS?=pytest
164167
# No default value.
165168
TEST_DEPENDENCY_TARGETS?=
166169

167-
## qa.coverage
168-
169-
# The command which gets executed. Defaults to the location the
170-
# :ref:`run-coverage` template gets rendered to if configured.
171-
# Default: .mxmake/files/run-coverage.sh
172-
COVERAGE_COMMAND?=.mxmake/files/run-coverage.sh
173-
174-
## qa.mypy
175-
176-
# Source folder for code analysis.
177-
# Default: src
178-
MYPY_SRC?=src
179-
180-
# Mypy Python requirements to be installed (via pip).
181-
# Default: types-setuptools
182-
MYPY_REQUIREMENTS?=types-setuptools types-docutils types-PyYAML
183-
184170
## core.help
185171

186172
# Request to show all targets, descriptions and arguments for a given domain.
@@ -383,45 +369,6 @@ FORMAT_TARGETS+=ruff-format
383369
DIRTY_TARGETS+=ruff-dirty
384370
CLEAN_TARGETS+=ruff-clean
385371

386-
##############################################################################
387-
# isort
388-
##############################################################################
389-
390-
# Adjust ISORT_SRC to respect PROJECT_PATH_PYTHON if still at default
391-
ifeq ($(ISORT_SRC),src)
392-
ISORT_SRC:=$(PYTHON_PROJECT_PREFIX)src
393-
endif
394-
395-
ISORT_TARGET:=$(SENTINEL_FOLDER)/isort.sentinel
396-
$(ISORT_TARGET): $(MXENV_TARGET)
397-
@echo "Install isort"
398-
@$(PYTHON_PACKAGE_COMMAND) install isort
399-
@touch $(ISORT_TARGET)
400-
401-
.PHONY: isort-check
402-
isort-check: $(ISORT_TARGET)
403-
@echo "Run isort check"
404-
@isort --check $(ISORT_SRC)
405-
406-
.PHONY: isort-format
407-
isort-format: $(ISORT_TARGET)
408-
@echo "Run isort format"
409-
@isort $(ISORT_SRC)
410-
411-
.PHONY: isort-dirty
412-
isort-dirty:
413-
@rm -f $(ISORT_TARGET)
414-
415-
.PHONY: isort-clean
416-
isort-clean: isort-dirty
417-
@test -e $(MXENV_PYTHON) && $(MXENV_PYTHON) -m pip uninstall -y isort || :
418-
419-
INSTALL_TARGETS+=$(ISORT_TARGET)
420-
CHECK_TARGETS+=isort-check
421-
FORMAT_TARGETS+=isort-format
422-
DIRTY_TARGETS+=isort-dirty
423-
CLEAN_TARGETS+=isort-clean
424-
425372
##############################################################################
426373
# sphinx
427374
##############################################################################
@@ -567,6 +514,47 @@ INSTALL_TARGETS+=packages
567514
DIRTY_TARGETS+=packages-dirty
568515
CLEAN_TARGETS+=packages-clean
569516

517+
##############################################################################
518+
# ty
519+
##############################################################################
520+
521+
# Adjust TY_SRC to respect PROJECT_PATH_PYTHON if still at default
522+
ifeq ($(TY_SRC),src)
523+
TY_SRC:=$(PYTHON_PROJECT_PREFIX)src
524+
endif
525+
526+
# Build ty flags
527+
TY_FLAGS:=
528+
ifneq ($(TY_PYTHON_VERSION),)
529+
TY_FLAGS+=--python-version $(TY_PYTHON_VERSION)
530+
endif
531+
532+
TY_TARGET:=$(SENTINEL_FOLDER)/ty.sentinel
533+
$(TY_TARGET): $(MXENV_TARGET)
534+
@echo "Install ty"
535+
@$(PYTHON_PACKAGE_COMMAND) install ty
536+
@touch $(TY_TARGET)
537+
538+
.PHONY: ty
539+
ty: $(PACKAGES_TARGET) $(TY_TARGET)
540+
@echo "Run ty"
541+
@ty check $(TY_FLAGS) $(TY_SRC)
542+
543+
.PHONY: ty-dirty
544+
ty-dirty:
545+
@rm -f $(TY_TARGET)
546+
547+
.PHONY: ty-clean
548+
ty-clean: ty-dirty
549+
@test -e $(MXENV_PYTHON) && $(MXENV_PYTHON) -m pip uninstall -y ty || :
550+
@rm -rf .ty
551+
552+
INSTALL_TARGETS+=$(TY_TARGET)
553+
CHECK_TARGETS+=ty
554+
TYPECHECK_TARGETS+=ty
555+
CLEAN_TARGETS+=ty-clean
556+
DIRTY_TARGETS+=ty-dirty
557+
570558
##############################################################################
571559
# test
572560
##############################################################################
@@ -596,69 +584,6 @@ INSTALL_TARGETS+=$(TEST_TARGET)
596584
CLEAN_TARGETS+=test-clean
597585
DIRTY_TARGETS+=test-dirty
598586

599-
##############################################################################
600-
# coverage
601-
##############################################################################
602-
603-
COVERAGE_TARGET:=$(SENTINEL_FOLDER)/coverage.sentinel
604-
$(COVERAGE_TARGET): $(TEST_TARGET)
605-
@echo "Install Coverage"
606-
@$(PYTHON_PACKAGE_COMMAND) install -U coverage
607-
@touch $(COVERAGE_TARGET)
608-
609-
.PHONY: coverage
610-
coverage: $(FILES_TARGET) $(SOURCES_TARGET) $(PACKAGES_TARGET) $(COVERAGE_TARGET)
611-
@test -z "$(COVERAGE_COMMAND)" && echo "No coverage command defined" && exit 1 || :
612-
@echo "Run coverage using $(COVERAGE_COMMAND)"
613-
@/usr/bin/env bash -c "$(COVERAGE_COMMAND)"
614-
615-
.PHONY: coverage-dirty
616-
coverage-dirty:
617-
@rm -f $(COVERAGE_TARGET)
618-
619-
.PHONY: coverage-clean
620-
coverage-clean: coverage-dirty
621-
@test -e $(MXENV_PYTHON) && $(MXENV_PYTHON) -m pip uninstall -y coverage || :
622-
@rm -rf .coverage htmlcov
623-
624-
INSTALL_TARGETS+=$(COVERAGE_TARGET)
625-
DIRTY_TARGETS+=coverage-dirty
626-
CLEAN_TARGETS+=coverage-clean
627-
628-
##############################################################################
629-
# mypy
630-
##############################################################################
631-
632-
# Adjust MYPY_SRC to respect PROJECT_PATH_PYTHON if still at default
633-
ifeq ($(MYPY_SRC),src)
634-
MYPY_SRC:=$(PYTHON_PROJECT_PREFIX)src
635-
endif
636-
637-
MYPY_TARGET:=$(SENTINEL_FOLDER)/mypy.sentinel
638-
$(MYPY_TARGET): $(MXENV_TARGET)
639-
@echo "Install mypy"
640-
@$(PYTHON_PACKAGE_COMMAND) install mypy $(MYPY_REQUIREMENTS)
641-
@touch $(MYPY_TARGET)
642-
643-
.PHONY: mypy
644-
mypy: $(PACKAGES_TARGET) $(MYPY_TARGET)
645-
@echo "Run mypy"
646-
@mypy $(MYPY_SRC)
647-
648-
.PHONY: mypy-dirty
649-
mypy-dirty:
650-
@rm -f $(MYPY_TARGET)
651-
652-
.PHONY: mypy-clean
653-
mypy-clean: mypy-dirty
654-
@test -e $(MXENV_PYTHON) && $(MXENV_PYTHON) -m pip uninstall -y mypy || :
655-
@rm -rf .mypy_cache
656-
657-
INSTALL_TARGETS+=$(MYPY_TARGET)
658-
TYPECHECK_TARGETS+=mypy
659-
CLEAN_TARGETS+=mypy-clean
660-
DIRTY_TARGETS+=mypy-dirty
661-
662587
##############################################################################
663588
# help
664589
##############################################################################

src/mxmake/main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ def list_command(args: argparse.Namespace):
6767
sys.stdout.write(f"Requested domain not found: {args.domain}\n")
6868
sys.exit(1)
6969

70+
assert domain is not None # type narrowing for ty
71+
7072
sys.stdout.write(f"Domain {topic.name}.{domain.name}:\n")
7173
depends = ", ".join(domain.depends) if domain.depends else "No dependencies"
7274
sys.stdout.write(f" Depends: {depends}\n")

src/mxmake/templates.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,23 @@ def __init__(
5858
# XXX: if environment is None, default to ``get_template_environment``?
5959
self.environment = environment
6060

61-
@abc.abstractproperty
61+
@property
62+
@abc.abstractmethod
6263
def target_folder(self) -> Path:
6364
"""Target folder for rendered template."""
6465

65-
@abc.abstractproperty
66+
@property
67+
@abc.abstractmethod
6668
def target_name(self) -> str:
6769
"""Target file name for rendered template."""
6870

69-
@abc.abstractproperty
71+
@property
72+
@abc.abstractmethod
7073
def template_name(self) -> str:
7174
"""Template name to use."""
7275

73-
@abc.abstractproperty
76+
@property
77+
@abc.abstractmethod
7478
def template_variables(self) -> dict[str, typing.Any]:
7579
"""Variables for template rendering."""
7680

src/mxmake/testing/__init__.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,6 @@ def __init__(
7373

7474

7575
class RenderTestCase(unittest.TestCase):
76-
class Example:
77-
def __init__(self, want):
78-
self.want = want + "\n"
79-
8076
class Failure(Exception):
8177
pass
8278

@@ -96,6 +92,8 @@ def checkOutput(self, want, got, optionflags=None):
9692
if not success:
9793
raise RenderTestCase.Failure(
9894
self._checker.output_difference(
99-
RenderTestCase.Example(want), got, optionflags
95+
doctest.Example(source="", want=want + "\n"),
96+
got,
97+
optionflags,
10098
)
10199
)

src/mxmake/tests/test_templates.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class Template(templates.Template):
5252
def test_Template(self, tempdir: Path):
5353
# cannot instantiate abstract template
5454
with self.assertRaises(TypeError):
55-
templates.Template() # type: ignore
55+
templates.Template()
5656

5757
# create test template
5858
class Template(templates.Template):

0 commit comments

Comments
 (0)