yaafcli 2026.2.5.15101__py3-none-any.whl → 2026.2.6.22353__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.
yaaf/cli.py CHANGED
@@ -23,7 +23,7 @@ def main() -> None:
23
23
  serve_parser.add_argument("--consumers-dir", default="consumers")
24
24
  serve_parser.set_defaults(command="serve")
25
25
 
26
- gen_parser = subparsers.add_parser("gen-services", help="Generate consumers/services.py")
26
+ gen_parser = subparsers.add_parser("gen-services", help="Generate consumers/api/__init__.py")
27
27
  gen_parser.add_argument("--consumers-dir", default="consumers")
28
28
  gen_parser.add_argument("--output", default=None)
29
29
  gen_parser.set_defaults(command="gen-services")
yaaf/gen_services.py CHANGED
@@ -1,4 +1,4 @@
1
- """Generate a consumers/services.py typing module from filesystem routes."""
1
+ """Generate a consumers/api/__init__.py typing module from filesystem routes."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -14,7 +14,9 @@ def _is_identifier(segment: str) -> bool:
14
14
 
15
15
 
16
16
  def _camel_case(parts: Iterable[str]) -> str:
17
- return "".join(part[:1].upper() + part[1:] for part in parts if part)
17
+ return "".join(
18
+ sub[:1].upper() + sub[1:] for part in parts if part for sub in part.split("_") if sub
19
+ )
18
20
 
19
21
 
20
22
  def _strip_dynamic(segment: str) -> str:
@@ -32,9 +34,11 @@ def _service_alias(route_parts: list[str]) -> str:
32
34
 
33
35
  def generate_services(consumers_dir: str = "consumers", output_path: str | None = None) -> Path:
34
36
  base = Path(consumers_dir)
35
- out_path = Path(output_path) if output_path else base / "services.py"
37
+ out_path = Path(output_path) if output_path else base / "api" / "__init__.py"
36
38
 
37
39
  if not base.exists():
40
+ if not out_path.parent.exists():
41
+ out_path.parent.mkdir(parents=True, exist_ok=True)
38
42
  out_path.write_text(HEADER + "\n__all__ = []\n")
39
43
  return out_path
40
44
 
@@ -76,5 +80,7 @@ def generate_services(consumers_dir: str = "consumers", output_path: str | None
76
80
  if dynamic_aliases:
77
81
  lines.append("\n# Dynamic routes use Protocol stubs (invalid import paths).\n")
78
82
 
83
+ if not out_path.parent.exists():
84
+ out_path.parent.mkdir(parents=True, exist_ok=True)
79
85
  out_path.write_text("".join(lines))
80
86
  return out_path
yaaf/loader.py CHANGED
@@ -72,7 +72,7 @@ def discover_routes(consumers_dir: str) -> tuple[list[RouteTarget], ServiceRegis
72
72
  service_aliases: dict[Path, list[str]] = {}
73
73
 
74
74
  for root, _dirs, files in os.walk(base):
75
- if "_server.py" not in files or "_service.py" not in files:
75
+ if "_server.py" not in files:
76
76
  continue
77
77
 
78
78
  root_path = Path(root)
@@ -90,7 +90,8 @@ def discover_routes(consumers_dir: str) -> tuple[list[RouteTarget], ServiceRegis
90
90
  aliases.append(route_parts[-1])
91
91
  service_aliases[root_path] = [alias for alias in aliases if alias]
92
92
 
93
- service_modules[root_path] = _load_module(root_path / "_service.py", "service")
93
+ if "_service.py" in files:
94
+ service_modules[root_path] = _load_module(root_path / "_service.py", "service")
94
95
  server_modules[root_path] = _load_module(root_path / "_server.py", "server")
95
96
 
96
97
  registry = ServiceRegistry(by_type={}, by_alias={})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yaafcli
3
- Version: 2026.2.5.15101
3
+ Version: 2026.2.6.22353
4
4
  Summary: Minimal ASGI app scaffold
5
5
  License: MIT License
6
6
 
@@ -105,7 +105,7 @@ In `_server.py`, export functions named after HTTP methods (lowercase): `get`, `
105
105
  Example `_server.py`:
106
106
 
107
107
  ```python
108
- from consumers.services import HelloService
108
+ from consumers.api import HelloService
109
109
  from yaaf import Request
110
110
  from yaaf.types import Params
111
111
 
@@ -117,7 +117,7 @@ async def get(request: Request, service: HelloService, params: Params):
117
117
  In `_service.py`, expose a module-level `service` instance (or a callable like `Service` or `get_service`). Services are registered and can be injected into other services or handlers:
118
118
 
119
119
  ```python
120
- from consumers.services import UsersService
120
+ from consumers.api import UsersService
121
121
 
122
122
 
123
123
  class Service:
@@ -157,7 +157,7 @@ service = Service()
157
157
 
158
158
  `consumers/api/hello/_service.py`
159
159
  ```python
160
- from yaaf.services import UsersService
160
+ from consumers.api import UsersService
161
161
 
162
162
 
163
163
  class Service:
@@ -173,7 +173,7 @@ service = Service
173
173
 
174
174
  `consumers/api/hello/_server.py`
175
175
  ```python
176
- from consumers.services import HelloService
176
+ from consumers.api import HelloService
177
177
  from yaaf import Request
178
178
 
179
179
 
@@ -197,7 +197,7 @@ python scripts/bump_version.py
197
197
 
198
198
  ## Service Type Generation
199
199
 
200
- Every `yaaf` command regenerates `consumers/services.py` for type-checking. You can also run it explicitly:
200
+ Every `yaaf` command regenerates `consumers/api/__init__.py` for type-checking. You can also run it explicitly:
201
201
 
202
202
  ```bash
203
203
  yaaf gen-services
@@ -1,16 +1,16 @@
1
1
  yaaf/__init__.py,sha256=mH1F6chTA4kRIaYK-yA1E7pBMOyReKi3rbrMiqKTxUY,602
2
2
  yaaf/__main__.py,sha256=MSmt_5Xg84uHqzTN38JwgseJK8rsJn_11A8WD99VtEo,61
3
3
  yaaf/app.py,sha256=7YrPl2_OZ-8NUy1RvUEBAbSntcqlP_in-2TLrKmGooE,3339
4
- yaaf/cli.py,sha256=X8YmeozhWjNtbEiyg_wTK75f_d-5LPKYkQmkU6v8dm0,1672
4
+ yaaf/cli.py,sha256=I8KlridkkikWwOO2BPwbqXoATP_RXZ0aHtCE26wMnao,1676
5
5
  yaaf/di.py,sha256=yoyTuL0Vc4MmGj_71M04JpLAzqBRREniZk1f2opEuEE,3039
6
- yaaf/gen_services.py,sha256=Gov7IlSLMG5Oo8RoRGHCbxHSsb_qecoh7IBZPWZKEe8,2869
7
- yaaf/loader.py,sha256=OzN2J5xl_sWGyNEaPz2LcuSEGfRPWHAGAs7QoK2JUdY,7215
6
+ yaaf/gen_services.py,sha256=f7OHHhvoPtcD_09p08Lf6i_N0KkM7wlrUsDOaoCHckg,3127
7
+ yaaf/loader.py,sha256=q8BV5kAeYCtX5sBRy7KYy9CfPShlJyfrv2TfjT18Zu0,7224
8
8
  yaaf/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  yaaf/responses.py,sha256=iXZ0vDYfGO-BEUBBsobCR4JfWLRx8zhwYD9taQ8Sat4,2616
10
10
  yaaf/types.py,sha256=BAD3Wkjqi4NKxNz2bT1xggPx0jU5Sz_hOvsHXmGszig,1262
11
- yaafcli-2026.2.5.15101.dist-info/licenses/LICENSE,sha256=ESYyLizI0WWtxMeS7rGVcX3ivMezm-HOd5WdeOh-9oU,1056
12
- yaafcli-2026.2.5.15101.dist-info/METADATA,sha256=ZRaPfbW4yBgyaCqm1NjLSELdwWsq461qz26BHwcGWAA,6247
13
- yaafcli-2026.2.5.15101.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
14
- yaafcli-2026.2.5.15101.dist-info/entry_points.txt,sha256=dh9ijq3gnFIr46RFjPjGR48PHQMUxwHopj3b9JipCRQ,39
15
- yaafcli-2026.2.5.15101.dist-info/top_level.txt,sha256=6WqEmcTdZROTeK4-7HzkB5h9JMBgs51otonH6vnjcAc,5
16
- yaafcli-2026.2.5.15101.dist-info/RECORD,,
11
+ yaafcli-2026.2.6.22353.dist-info/licenses/LICENSE,sha256=ESYyLizI0WWtxMeS7rGVcX3ivMezm-HOd5WdeOh-9oU,1056
12
+ yaafcli-2026.2.6.22353.dist-info/METADATA,sha256=ef4rWld98zs5mlfFT3ygcEygxIwlIhsRh4hTmRufAcg,6236
13
+ yaafcli-2026.2.6.22353.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
14
+ yaafcli-2026.2.6.22353.dist-info/entry_points.txt,sha256=dh9ijq3gnFIr46RFjPjGR48PHQMUxwHopj3b9JipCRQ,39
15
+ yaafcli-2026.2.6.22353.dist-info/top_level.txt,sha256=6WqEmcTdZROTeK4-7HzkB5h9JMBgs51otonH6vnjcAc,5
16
+ yaafcli-2026.2.6.22353.dist-info/RECORD,,