Skip to content

Commit 4195b06

Browse files
feat: add py.typed during ap init
1 parent 267c171 commit 4195b06

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

src/afterpython/cli/commands/init.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,24 @@ def init_website():
4646
subprocess.run(["ap", "update", "website"])
4747

4848

49+
def init_py_typed():
50+
from afterpython.tools.pyproject import find_package_directory
51+
52+
try:
53+
package_dir = find_package_directory()
54+
except FileNotFoundError:
55+
click.echo(
56+
"Could not find package directory (__init__.py not found), skipping py-typed initialization"
57+
)
58+
return
59+
py_typed_path = package_dir / "py.typed"
60+
if py_typed_path.exists():
61+
click.echo(f"py.typed file already exists at {py_typed_path}")
62+
return
63+
py_typed_path.touch()
64+
click.echo(f"Created {py_typed_path}")
65+
66+
4967
@click.command()
5068
@click.option(
5169
"--yes",
@@ -85,6 +103,9 @@ def init(ctx, yes):
85103

86104
init_website()
87105

106+
# TODO: add type checking related stuff here
107+
init_py_typed()
108+
88109
create_workflow("deploy")
89110
create_workflow("ci")
90111

src/afterpython/tools/pyproject.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from tomlkit.toml_document import TOMLDocument
77

88
import asyncio
9+
from pathlib import Path
910

1011
from pyproject_metadata import StandardMetadata
1112

@@ -27,6 +28,41 @@ def read_metadata() -> StandardMetadata:
2728
return StandardMetadata.from_pyproject(read_pyproject())
2829

2930

31+
def find_package_directory() -> Path:
32+
"""Find the user's package directory.
33+
34+
Supports both common Python project layouts:
35+
- src layout: user_project/src/package_name/__init__.py
36+
- flat layout: user_project/package_name/__init__.py
37+
38+
Returns:
39+
Path to the package directory containing __init__.py
40+
41+
Raises:
42+
FileNotFoundError: If package directory cannot be found in either layout
43+
"""
44+
metadata = read_metadata()
45+
package_name = metadata.name
46+
project_root = ap.paths.user_path
47+
48+
# Try src layout first (recommended layout)
49+
src_layout_dir = project_root / "src" / package_name
50+
if (src_layout_dir / "__init__.py").exists():
51+
return src_layout_dir
52+
53+
# Try flat layout
54+
flat_layout_dir = project_root / package_name
55+
if (flat_layout_dir / "__init__.py").exists():
56+
return flat_layout_dir
57+
58+
# Package not found in either location
59+
raise FileNotFoundError(
60+
f"Could not find package '{package_name}' in either src layout "
61+
f"({src_layout_dir}) or flat layout ({flat_layout_dir}). "
62+
f"Expected to find __init__.py in one of these locations."
63+
)
64+
65+
3066
def init_pyproject():
3167
"""Initialize pyproject.toml with sensible defaults
3268
- add [build-system] section with uv build backend (same as `uv init --package`)

0 commit comments

Comments
 (0)