newstack 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. newstack/__init__.py +4 -0
  2. newstack/__main__.py +8 -0
  3. newstack/cli.py +387 -0
  4. newstack/data/stacks/fastapi/stack.json +42 -0
  5. newstack/data/stacks/fastapi/template/.github/workflows/ci.yml +30 -0
  6. newstack/data/stacks/fastapi/template/.gitignore +11 -0
  7. newstack/data/stacks/fastapi/template/Dockerfile +13 -0
  8. newstack/data/stacks/fastapi/template/LICENSE +21 -0
  9. newstack/data/stacks/fastapi/template/README.md +30 -0
  10. newstack/data/stacks/fastapi/template/pyproject.toml +31 -0
  11. newstack/data/stacks/fastapi/template/src/{{package_name}}/__init__.py +4 -0
  12. newstack/data/stacks/fastapi/template/src/{{package_name}}/main.py +50 -0
  13. newstack/data/stacks/fastapi/template/tests/test_api.py +41 -0
  14. newstack/data/stacks/node-express-ts/stack.json +14 -0
  15. newstack/data/stacks/node-express-ts/template/.github/workflows/ci.yml +28 -0
  16. newstack/data/stacks/node-express-ts/template/.gitignore +6 -0
  17. newstack/data/stacks/node-express-ts/template/LICENSE +21 -0
  18. newstack/data/stacks/node-express-ts/template/README.md +24 -0
  19. newstack/data/stacks/node-express-ts/template/package.json +26 -0
  20. newstack/data/stacks/node-express-ts/template/src/app.ts +35 -0
  21. newstack/data/stacks/node-express-ts/template/src/server.ts +7 -0
  22. newstack/data/stacks/node-express-ts/template/tests/app.test.ts +32 -0
  23. newstack/data/stacks/node-express-ts/template/tsconfig.json +14 -0
  24. newstack/data/stacks/python-cli/stack.json +50 -0
  25. newstack/data/stacks/python-cli/template/.github/workflows/ci.yml +32 -0
  26. newstack/data/stacks/python-cli/template/.gitignore +11 -0
  27. newstack/data/stacks/python-cli/template/LICENSE +21 -0
  28. newstack/data/stacks/python-cli/template/README.md +35 -0
  29. newstack/data/stacks/python-cli/template/pyproject.toml +32 -0
  30. newstack/data/stacks/python-cli/template/src/{{package_name}}/__init__.py +4 -0
  31. newstack/data/stacks/python-cli/template/src/{{package_name}}/__main__.py +6 -0
  32. newstack/data/stacks/python-cli/template/src/{{package_name}}/cli.py +30 -0
  33. newstack/data/stacks/python-cli/template/tests/test_cli.py +20 -0
  34. newstack/data/stacks/python-lib/stack.json +42 -0
  35. newstack/data/stacks/python-lib/template/.github/workflows/ci.yml +32 -0
  36. newstack/data/stacks/python-lib/template/.gitignore +11 -0
  37. newstack/data/stacks/python-lib/template/LICENSE +21 -0
  38. newstack/data/stacks/python-lib/template/README.md +28 -0
  39. newstack/data/stacks/python-lib/template/pyproject.toml +34 -0
  40. newstack/data/stacks/python-lib/template/src/{{package_name}}/__init__.py +6 -0
  41. newstack/data/stacks/python-lib/template/src/{{package_name}}/core.py +23 -0
  42. newstack/data/stacks/python-lib/template/tests/test_core.py +31 -0
  43. newstack/data/stacks/react-vite-ts/stack.json +15 -0
  44. newstack/data/stacks/react-vite-ts/template/.github/workflows/ci.yml +29 -0
  45. newstack/data/stacks/react-vite-ts/template/.gitignore +7 -0
  46. newstack/data/stacks/react-vite-ts/template/LICENSE +21 -0
  47. newstack/data/stacks/react-vite-ts/template/README.md +25 -0
  48. newstack/data/stacks/react-vite-ts/template/index.html +12 -0
  49. newstack/data/stacks/react-vite-ts/template/package.json +28 -0
  50. newstack/data/stacks/react-vite-ts/template/src/App.test.tsx +20 -0
  51. newstack/data/stacks/react-vite-ts/template/src/App.tsx +15 -0
  52. newstack/data/stacks/react-vite-ts/template/src/main.tsx +16 -0
  53. newstack/data/stacks/react-vite-ts/template/src/styles.css +26 -0
  54. newstack/data/stacks/react-vite-ts/template/tsconfig.json +16 -0
  55. newstack/data/stacks/react-vite-ts/template/vite.config.ts +10 -0
  56. newstack/data/stacks/static-site/stack.json +14 -0
  57. newstack/data/stacks/static-site/template/.github/workflows/deploy-pages.yml +30 -0
  58. newstack/data/stacks/static-site/template/.gitignore +2 -0
  59. newstack/data/stacks/static-site/template/LICENSE +21 -0
  60. newstack/data/stacks/static-site/template/README.md +21 -0
  61. newstack/data/stacks/static-site/template/index.html +34 -0
  62. newstack/data/stacks/static-site/template/main.js +15 -0
  63. newstack/data/stacks/static-site/template/styles.css +74 -0
  64. newstack/data/stacks/static-site/template/tests/site.test.mjs +22 -0
  65. newstack/registry.py +137 -0
  66. newstack/render.py +163 -0
  67. newstack/verify.py +133 -0
  68. newstack-0.1.0.dist-info/METADATA +197 -0
  69. newstack-0.1.0.dist-info/RECORD +72 -0
  70. newstack-0.1.0.dist-info/WHEEL +4 -0
  71. newstack-0.1.0.dist-info/entry_points.txt +2 -0
  72. newstack-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "node-express-ts",
3
+ "title": "Express + TypeScript API",
4
+ "language": "node",
5
+ "blurb": "HTTP API: Express 5, typed handlers, supertest tests, CI",
6
+ "requires": ["node", "npm", "git"],
7
+ "default_description": "An Express API.",
8
+ "next_steps": ["cd {path}", "npm install", "npm run dev"],
9
+ "verify": [
10
+ {"name": "install", "cmd": "npm install --no-audit --no-fund --silent", "tools": ["npm"], "timeout": 900},
11
+ {"name": "typecheck", "cmd": "npm run typecheck", "tools": ["npm"], "timeout": 300},
12
+ {"name": "test", "cmd": "npm test", "tools": ["npm"], "timeout": 300}
13
+ ]
14
+ }
@@ -0,0 +1,28 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ test:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ node-version: ["22", "24"]
18
+ steps:
19
+ - uses: actions/checkout@v7
20
+ - uses: actions/setup-node@v7
21
+ with:
22
+ node-version: ${{ matrix.node-version }}
23
+ cache: npm
24
+ # no lockfile is shipped yet: run `npm install` once locally and commit
25
+ # package-lock.json, then switch this to `npm ci` for reproducible installs
26
+ - run: npm install --no-audit --no-fund
27
+ - run: npm run typecheck
28
+ - run: npm test
@@ -0,0 +1,6 @@
1
+ node_modules/
2
+ dist/
3
+ coverage/
4
+ *.local
5
+ .env
6
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) {{ year }} {{ author }}
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,24 @@
1
+ # {{ title }}
2
+
3
+ {{ description }}
4
+
5
+ Express 5 on TypeScript: `GET /health`, `GET /items`, `POST /items`.
6
+
7
+ ## Develop
8
+
9
+ ```bash
10
+ npm install
11
+ npm run dev # http://localhost:3000
12
+ ```
13
+
14
+ ## Check
15
+
16
+ ```bash
17
+ npm run typecheck
18
+ npm test
19
+ ```
20
+
21
+ After the first `npm install`, commit `package-lock.json` and switch CI's install step
22
+ to `npm ci` for reproducible installs.
23
+
24
+ Generated with [newstack](https://github.com/DawnofGenX/newstack).
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "{{ npm_name }}",
3
+ "private": true,
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "description": "{{ description }}",
7
+ "main": "src/server.ts",
8
+ "scripts": {
9
+ "dev": "tsx watch src/server.ts",
10
+ "start": "tsx src/server.ts",
11
+ "test": "vitest run",
12
+ "typecheck": "tsc --noEmit"
13
+ },
14
+ "dependencies": {
15
+ "express": "^5.3.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/express": "^5.0.6",
19
+ "@types/node": "^26.6.6",
20
+ "@types/supertest": "^7.2.1",
21
+ "supertest": "^7.3.1",
22
+ "tsx": "^4.23.15",
23
+ "typescript": "^7.0.2",
24
+ "vitest": "^5.0.5"
25
+ }
26
+ }
@@ -0,0 +1,35 @@
1
+ import express, { type Request, type Response } from "express";
2
+
3
+ export interface Item {
4
+ id: number;
5
+ name: string;
6
+ }
7
+
8
+ export function createApp() {
9
+ const app = express();
10
+ app.use(express.json());
11
+
12
+ const items: Item[] = [];
13
+ let nextId = 1;
14
+
15
+ app.get("/health", (_req: Request, res: Response) => {
16
+ res.json({ status: "ok" });
17
+ });
18
+
19
+ app.get("/items", (_req: Request, res: Response) => {
20
+ res.json(items);
21
+ });
22
+
23
+ app.post("/items", (req: Request, res: Response) => {
24
+ const name = typeof req.body?.name === "string" ? req.body.name.trim() : "";
25
+ if (!name) {
26
+ res.status(400).json({ error: "name is required" });
27
+ return;
28
+ }
29
+ const item: Item = { id: nextId++, name };
30
+ items.push(item);
31
+ res.status(201).json(item);
32
+ });
33
+
34
+ return app;
35
+ }
@@ -0,0 +1,7 @@
1
+ import { createApp } from "./app";
2
+
3
+ const port = Number(process.env.PORT ?? 3000);
4
+
5
+ createApp().listen(port, () => {
6
+ console.log(`listening on http://localhost:${port}`);
7
+ });
@@ -0,0 +1,32 @@
1
+ import request from "supertest";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ import { createApp } from "../src/app";
5
+
6
+ describe("api", () => {
7
+ it("answers the health check", async () => {
8
+ const response = await request(createApp()).get("/health");
9
+ expect(response.status).toBe(200);
10
+ expect(response.body).toEqual({ status: "ok" });
11
+ });
12
+
13
+ it("starts with no items", async () => {
14
+ const response = await request(createApp()).get("/items");
15
+ expect(response.body).toEqual([]);
16
+ });
17
+
18
+ it("creates an item and lists it", async () => {
19
+ const app = createApp();
20
+ const created = await request(app).post("/items").send({ name: "pen" });
21
+ expect(created.status).toBe(201);
22
+ expect(created.body).toEqual({ id: 1, name: "pen" });
23
+
24
+ const listed = await request(app).get("/items");
25
+ expect(listed.body).toHaveLength(1);
26
+ });
27
+
28
+ it("rejects an item without a name", async () => {
29
+ const response = await request(createApp()).post("/items").send({});
30
+ expect(response.status).toBe(400);
31
+ });
32
+ });
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "skipLibCheck": true,
10
+ "esModuleInterop": true,
11
+ "types": ["node"]
12
+ },
13
+ "include": ["src", "tests"]
14
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "python-cli",
3
+ "title": "Python CLI",
4
+ "language": "python",
5
+ "blurb": "Console command on argparse: zero runtime deps, tested entry point",
6
+ "requires": [
7
+ "uv",
8
+ "git"
9
+ ],
10
+ "default_description": "A command line tool.",
11
+ "next_steps": [
12
+ "cd {path}",
13
+ "uv sync",
14
+ "uv run {npm_name} greet --name you"
15
+ ],
16
+ "verify": [
17
+ {
18
+ "name": "install",
19
+ "cmd": "uv venv -q .venv && uv pip install -q --python .venv/bin/python -e . pytest ruff",
20
+ "tools": [
21
+ "uv"
22
+ ],
23
+ "timeout": 900
24
+ },
25
+ {
26
+ "name": "ruff",
27
+ "cmd": ".venv/bin/ruff check .",
28
+ "tools": [
29
+ "uv"
30
+ ],
31
+ "timeout": 300
32
+ },
33
+ {
34
+ "name": "pytest",
35
+ "cmd": ".venv/bin/python -m pytest -q",
36
+ "tools": [
37
+ "uv"
38
+ ],
39
+ "timeout": 300
40
+ },
41
+ {
42
+ "name": "run",
43
+ "cmd": ".venv/bin/{{ npm_name }} greet --name newstack",
44
+ "tools": [
45
+ "uv"
46
+ ],
47
+ "timeout": 120
48
+ }
49
+ ]
50
+ }
@@ -0,0 +1,32 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ test:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
18
+ steps:
19
+ - uses: actions/checkout@v7
20
+ - name: Set up uv
21
+ uses: astral-sh/setup-uv@v10.3.3
22
+ with:
23
+ python-version: ${{ matrix.python-version }}
24
+ enable-cache: true
25
+ - name: Install
26
+ run: uv sync --group dev
27
+ - name: Lint
28
+ run: uv run ruff check .
29
+ - name: Test
30
+ run: uv run pytest
31
+ - name: Smoke test the CLI
32
+ run: uv run {{ npm_name }} greet --name CI
@@ -0,0 +1,11 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .venv/
5
+ build/
6
+ dist/
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+ .coverage
10
+ htmlcov/
11
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) {{ year }} {{ author }}
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,35 @@
1
+ # {{ title }}
2
+
3
+ {{ description }}
4
+
5
+ A single-command CLI built on the standard library — no runtime dependencies.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ uv sync
11
+ uv run {{ npm_name }} --help
12
+ ```
13
+
14
+ Or install it on your PATH:
15
+
16
+ ```bash
17
+ uv tool install .
18
+ {{ npm_name }} greet --name world
19
+ ```
20
+
21
+ ## Commands
22
+
23
+ ```text
24
+ {{ npm_name }} greet --name <name> print a greeting
25
+ {{ npm_name }} --version print the version
26
+ ```
27
+
28
+ ## Develop
29
+
30
+ ```bash
31
+ uv run pytest
32
+ uv run ruff check .
33
+ ```
34
+
35
+ Generated with [newstack](https://github.com/DawnofGenX/newstack).
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "{{ npm_name }}"
7
+ version = "0.1.0"
8
+ description = "{{ description }}"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "{{ author }}", email = "{{ email }}" }]
14
+ dependencies = []
15
+ classifiers = ["Environment :: Console", "Programming Language :: Python :: 3"]
16
+
17
+ [project.scripts]
18
+ {{ npm_name }} = "{{ package_name }}.cli:main"
19
+
20
+ [dependency-groups]
21
+ dev = ["pytest>=8.0", "ruff>=0.6"]
22
+
23
+ [tool.hatch.build.targets.wheel]
24
+ packages = ["src/{{ package_name }}"]
25
+
26
+ [tool.ruff]
27
+ line-length = 100
28
+ target-version = "py310"
29
+
30
+ [tool.pytest.ini_options]
31
+ testpaths = ["tests"]
32
+ addopts = "-q"
@@ -0,0 +1,4 @@
1
+ """{{ title }} — {{ description }}"""
2
+
3
+ __version__ = "0.1.0"
4
+ __all__ = ["__version__"]
@@ -0,0 +1,6 @@
1
+ import sys
2
+
3
+ from .cli import main
4
+
5
+ if __name__ == "__main__":
6
+ sys.exit(main())
@@ -0,0 +1,30 @@
1
+ """Command line entry point for {{ title }}."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import sys
7
+ from collections.abc import Sequence
8
+
9
+ from . import __version__
10
+
11
+
12
+ def build_parser() -> argparse.ArgumentParser:
13
+ parser = argparse.ArgumentParser(prog="{{ npm_name }}", description="{{ description }}")
14
+ parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
15
+ sub = parser.add_subparsers(dest="command", required=True)
16
+
17
+ greet = sub.add_parser("greet", help="print a greeting")
18
+ greet.add_argument("--name", default="world", help="who to greet")
19
+ return parser
20
+
21
+
22
+ def main(argv: Sequence[str] | None = None) -> int:
23
+ args = build_parser().parse_args(argv)
24
+ if args.command == "greet":
25
+ print(f"Hello, {args.name}!")
26
+ return 0
27
+
28
+
29
+ if __name__ == "__main__":
30
+ sys.exit(main())
@@ -0,0 +1,20 @@
1
+ from {{ package_name }}.cli import main
2
+
3
+
4
+ def test_greet_uses_default_name(capsys) -> None:
5
+ assert main(["greet"]) == 0
6
+ assert capsys.readouterr().out.strip() == "Hello, world!"
7
+
8
+
9
+ def test_greet_uses_given_name(capsys) -> None:
10
+ assert main(["greet", "--name", "Ada"]) == 0
11
+ assert "Ada" in capsys.readouterr().out
12
+
13
+
14
+ def test_version_prints_and_exits(capsys) -> None:
15
+ import pytest
16
+
17
+ with pytest.raises(SystemExit) as excinfo:
18
+ main(["--version"])
19
+ assert excinfo.value.code == 0
20
+ assert "0.1.0" in capsys.readouterr().out
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "python-lib",
3
+ "title": "Python library",
4
+ "language": "python",
5
+ "blurb": "Installable package: src layout, pytest, ruff, 4-version CI matrix",
6
+ "requires": [
7
+ "uv",
8
+ "git"
9
+ ],
10
+ "default_description": "A Python library.",
11
+ "next_steps": [
12
+ "cd {path}",
13
+ "uv sync",
14
+ "uv run pytest"
15
+ ],
16
+ "verify": [
17
+ {
18
+ "name": "install",
19
+ "cmd": "uv venv -q .venv && uv pip install -q --python .venv/bin/python -e . pytest ruff",
20
+ "tools": [
21
+ "uv"
22
+ ],
23
+ "timeout": 900
24
+ },
25
+ {
26
+ "name": "ruff",
27
+ "cmd": ".venv/bin/ruff check .",
28
+ "tools": [
29
+ "uv"
30
+ ],
31
+ "timeout": 300
32
+ },
33
+ {
34
+ "name": "pytest",
35
+ "cmd": ".venv/bin/python -m pytest -q",
36
+ "tools": [
37
+ "uv"
38
+ ],
39
+ "timeout": 300
40
+ }
41
+ ]
42
+ }
@@ -0,0 +1,32 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ test:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
18
+ steps:
19
+ - uses: actions/checkout@v7
20
+ - name: Set up uv
21
+ uses: astral-sh/setup-uv@v10.3.3
22
+ with:
23
+ python-version: ${{ matrix.python-version }}
24
+ enable-cache: true
25
+ - name: Install
26
+ run: uv sync --group dev
27
+ - name: Lint
28
+ run: uv run ruff check .
29
+ - name: Test
30
+ run: uv run pytest
31
+ - name: Build
32
+ run: uv build
@@ -0,0 +1,11 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .venv/
5
+ build/
6
+ dist/
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+ .coverage
10
+ htmlcov/
11
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) {{ year }} {{ author }}
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,28 @@
1
+ # {{ title }}
2
+
3
+ {{ description }}
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ uv sync
9
+ ```
10
+
11
+ ## Use
12
+
13
+ ```python
14
+ from {{ package_name }} import truncate, word_count
15
+
16
+ word_count("hello world") # 2
17
+ truncate("hello world", 8) # "hello w…"
18
+ ```
19
+
20
+ ## Develop
21
+
22
+ ```bash
23
+ uv run pytest # tests
24
+ uv run ruff check . # lint
25
+ uv build # sdist + wheel
26
+ ```
27
+
28
+ Generated with [newstack](https://github.com/DawnofGenX/newstack).
@@ -0,0 +1,34 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "{{ npm_name }}"
7
+ version = "0.1.0"
8
+ description = "{{ description }}"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "{{ author }}", email = "{{ email }}" }]
14
+ classifiers = [
15
+ "Programming Language :: Python :: 3",
16
+ "Programming Language :: Python :: 3.10",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Programming Language :: Python :: 3.13",
20
+ ]
21
+
22
+ [dependency-groups]
23
+ dev = ["pytest>=8.0", "ruff>=0.6"]
24
+
25
+ [tool.hatch.build.targets.wheel]
26
+ packages = ["src/{{ package_name }}"]
27
+
28
+ [tool.ruff]
29
+ line-length = 100
30
+ target-version = "py310"
31
+
32
+ [tool.pytest.ini_options]
33
+ testpaths = ["tests"]
34
+ addopts = "-q"
@@ -0,0 +1,6 @@
1
+ """{{ title }} — {{ description }}"""
2
+
3
+ from .core import truncate, word_count
4
+
5
+ __version__ = "0.1.0"
6
+ __all__ = ["__version__", "truncate", "word_count"]