Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[flake8]
ignore = E203, E231, E266, E302, E501, W503
max-line-length = 88
7 changes: 2 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12"]
python-version: ["3.12", "3.13"]
os: [macOS-latest, ubuntu-latest, windows-latest]

steps:
Expand All @@ -25,10 +25,7 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- name: Install
run: |
python -m pip install --upgrade pip
make setup
pip install -U .
run: make install
- name: Test
run: make test
- name: Lint
Expand Down
27 changes: 18 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
PYTHON?=python
SOURCES=squatter setup.py
SOURCES=squatter

UV:=$(shell uv --version)
ifdef UV
VENV:=uv venv
PIP:=uv pip
else
VENV:=python -m venv
PIP:=python -m pip
endif

.PHONY: venv
venv:
$(PYTHON) -m venv .venv
source .venv/bin/activate && make setup
$(VENV) .venv
source .venv/bin/activate && make install
@echo 'run `source .venv/bin/activate` to use virtualenv'

# The rest of these are intended to be run within the venv, where python points
# to whatever was used to set up the venv.

.PHONY: setup
setup:
python -m pip install -Ur requirements-dev.txt
.PHONY: install
install:
$(PIP) install -Ue .[dev]

.PHONY: test
test:
Expand All @@ -27,10 +36,10 @@ format:
lint:
python -m ufmt check $(SOURCES)
python -m flake8 $(SOURCES)
mypy --strict squatter
python -m mypy squatter

.PHONY: release
release:
rm -rf dist
python setup.py sdist bdist_wheel
twine upload dist/*
hatch build
hatch publish
53 changes: 53 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"

[project]
name = "squatter"
readme = "README.md"
authors = [
{name="Amethyst Reese", email="amethyst@n7.gg"},
{name="Tim Hatch"},
]
license = "MIT"
license-files = ["LICENSE"]
dynamic = ["version", "description"]
requires-python = ">=3.12"
dependencies = [
"click >= 8",
"hatch >= 1.14",
]

[project.optional-dependencies]
dev = [
"black==25.1.0",
"coverage==7.8.0",
"flake8==7.2.0",
"mypy==1.15.0",
"tox==4.26.0",
"ufmt==2.8.0",
"usort==1.0.8",
"volatile==2.1.0",
]

[project.scripts]
squatter = "squatter.__main__:cli"

[project.urls]
Home = "https://github.com/python-packaging/squatter"

[tool.hatch.version]
source = "vcs"

[tool.mypy]
ignore_missing_imports = true
strict = true

[tool.tox]
env_list = ["3.12", "3.13"]

[tool.tox.env_run_base]
commands = [["make", "test"]]
extras = ["dev"]
# set_env = { COVERAGE_FILE="{env:env_dir}/.coverage" }
allowlist_externals = ["make"]
10 changes: 0 additions & 10 deletions requirements-dev.txt

This file was deleted.

55 changes: 0 additions & 55 deletions setup.cfg

This file was deleted.

3 changes: 0 additions & 3 deletions setup.py

This file was deleted.

41 changes: 23 additions & 18 deletions squatter/templates.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import glob
import sys
from pathlib import Path
from subprocess import check_call, check_output
from typing import Optional

SETUP_PY_TMPL = """\
from setuptools import setup
PYPROJECT_TEMPLATE = """\
["build-system"]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = {package_name!r}
description = "coming soon"
version = "0.0.0a1"
authors = [
{{name={author!r}, email={author_email!r} }},
]
"""

setup(
name={package_name!r},
description="coming soon",
version="0.0.0a1",
author={author!r},
author_email={author_email!r},
)
INIT_TEMPLATE = """\
'''coming soon'''
"""


Expand All @@ -36,15 +40,16 @@ def generate(
["git", "config", "user.email"], encoding="utf-8"
).strip()

data = SETUP_PY_TMPL.format(**locals())
(Path(self.staging_directory) / "setup.py").write_text(data)
data = PYPROJECT_TEMPLATE.format(**locals())
(Path(self.staging_directory) / "pyproject.toml").write_text(data)

pkg_dir = Path(self.staging_directory) / package_name.replace("-", "_")
pkg_dir.mkdir(parents=True, exist_ok=True)
(pkg_dir / "__init__.py").write_text(INIT_TEMPLATE)

def sdist(self) -> None:
check_call([sys.executable, "setup.py", "sdist"], cwd=self.staging_directory)
check_call(["hatch", "build"], cwd=self.staging_directory)

def upload(self) -> None:
self.sdist()
check_call(
["twine", "upload"] + glob.glob(f"{self.staging_directory}/dist/*.tar.gz"),
cwd=self.staging_directory,
)
check_call(["hatch", "upload"], cwd=self.staging_directory)
53 changes: 36 additions & 17 deletions squatter/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import tarfile
import unittest
from pathlib import Path
from subprocess import check_call
Expand All @@ -18,17 +19,26 @@ def test_env_smoke(self) -> None:
env.generate("foo", "Author Name", "email@example.com")
env.sdist()

tarballs = list(Path(d).rglob("*.tar.gz"))
self.assertEqual(
[Path(d) / "dist" / "foo-0.0.0a1.tar.gz"],
list(Path(d).rglob("*.tar.gz")),
tarballs,
)

egg_info = list(Path(d).rglob("PKG-INFO"))
self.assertEqual(1, len(egg_info))
egg_info_text = egg_info[0].read_text()
self.assertIn("\nName: foo\n", egg_info_text)
self.assertIn("\nAuthor: Author Name\n", egg_info_text)
self.assertIn("\nAuthor-email: email@example.com\n", egg_info_text)
with tarfile.open(tarballs[0]) as tar:
members = [
member
for member in tar.getmembers()
if member.name.endswith("PKG-INFO")
]
pkg_info = tar.extractfile(members[0])
assert pkg_info is not None
egg_info_text = pkg_info.read()

self.assertIn(b"\nName: foo\n", egg_info_text)
self.assertIn(
b"\nAuthor-email: Author Name <email@example.com>\n", egg_info_text
)

@patch("squatter.templates.check_output")
def test_env_git_prompts(self, check_output_mock: Any) -> None:
Expand All @@ -43,17 +53,26 @@ def test_env_git_prompts(self, check_output_mock: Any) -> None:
env.generate("foo")
env.sdist()

tarballs = list(Path(d).rglob("*.tar.gz"))
self.assertEqual(
[Path(d) / "dist" / "foo-0.0.0a1.tar.gz"],
list(Path(d).rglob("*.tar.gz")),
tarballs,
)

egg_info = list(Path(d).rglob("PKG-INFO"))
self.assertEqual(1, len(egg_info))
egg_info_text = egg_info[0].read_text()
self.assertIn("\nName: foo\n", egg_info_text)
self.assertIn("\nAuthor: Bob\n", egg_info_text)
self.assertIn("\nAuthor-email: email@example.com\n", egg_info_text)
with tarfile.open(tarballs[0]) as tar:
members = [
member
for member in tar.getmembers()
if member.name.endswith("PKG-INFO")
]
pkg_info = tar.extractfile(members[0])
assert pkg_info is not None
egg_info_text = pkg_info.read()

self.assertIn(b"\nName: foo\n", egg_info_text)
self.assertIn(
b"\nAuthor-email: Bob <email@example.com>\n", egg_info_text
)

@patch("squatter.templates.check_output")
@patch("squatter.templates.check_call")
Expand All @@ -68,11 +87,11 @@ def test_cli_functional(self, check_call_mock: Any, check_output_mock: Any) -> N

def patched_check_call(cmd: List[str], **kwargs: Any) -> Any:
nonlocal uploads
if cmd[0] != "twine":
if cmd[0] != "hatch":
return check_call(cmd, **kwargs)
else:
assert cmd[-1].endswith(".tar.gz")
uploads += 1
if "upload" in cmd:
uploads += 1

check_call_mock.side_effect = patched_check_call

Expand Down