|
16 | 16 | import json |
17 | 17 | import re |
18 | 18 | import sys |
19 | | -from pathlib import Path |
| 19 | +from pathlib import Path, PurePath |
20 | 20 | from typing import Any |
21 | 21 |
|
22 | 22 | ROOT_DIR = Path(__file__).resolve().parents[2] |
23 | 23 | DEFAULT_SPEC_PATH = ROOT_DIR / 'docs' / 'api-reference' / 'app-client-openapi.json' |
24 | 24 | DEFAULT_OUTPUT = ROOT_DIR / 'desktop' / 'macos' / 'Desktop' / 'Sources' / 'Generated' / 'OmiApi.generated.swift' |
25 | 25 |
|
| 26 | + |
| 27 | +def source_label_for_path(path: PurePath, root_dir: PurePath = ROOT_DIR) -> str: |
| 28 | + try: |
| 29 | + return path.relative_to(root_dir).as_posix() |
| 30 | + except ValueError: |
| 31 | + return path.as_posix() |
| 32 | + |
| 33 | + |
26 | 34 | # Schemas to generate. Keep this the high-traffic desktop read surface; expand |
27 | 35 | # as the desktop Codable migration progresses. Each entry pulls in transitive |
28 | 36 | # $ref dependencies automatically. |
@@ -198,7 +206,7 @@ def _render_enum(name: str, schema: dict[str, Any]) -> str: |
198 | 206 | lines.append(' case _unknown = "__unknown__"') |
199 | 207 | lines.append(' public init(from decoder: Decoder) throws {') |
200 | 208 | lines.append(' let c = try decoder.singleValueContainer()') |
201 | | - lines.append(f' let raw = try c.decode(String.self)') |
| 209 | + lines.append(' let raw = try c.decode(String.self)') |
202 | 210 | lines.append(f' self = {name}(rawValue: raw) ?? ._unknown') |
203 | 211 | lines.append(' }') |
204 | 212 | lines.append('}') |
@@ -486,7 +494,7 @@ def _render_patch_struct(name: str, schema: dict[str, Any]) -> str: |
486 | 494 | lines.append(' var c = encoder.container(keyedBy: CodingKeys.self)') |
487 | 495 | for swift_name, _, _ in fields: |
488 | 496 | lines.append(f' switch {swift_name} {{') |
489 | | - lines.append(f' case .omitted: break') |
| 497 | + lines.append(' case .omitted: break') |
490 | 498 | lines.append(f' case .value(let value): try c.encode(value, forKey: .{swift_name})') |
491 | 499 | lines.append(f' case .null: try c.encodeNil(forKey: .{swift_name})') |
492 | 500 | lines.append(' }') |
@@ -907,20 +915,20 @@ def parse_args() -> argparse.Namespace: |
907 | 915 |
|
908 | 916 | def main() -> int: |
909 | 917 | args = parse_args() |
910 | | - spec = json.loads(args.spec.read_text()) |
911 | | - generated = generate(spec, str(args.spec.relative_to(ROOT_DIR)) if args.spec.is_absolute() else str(args.spec)) |
| 918 | + spec = json.loads(args.spec.read_text(encoding='utf-8')) |
| 919 | + generated = generate(spec, source_label_for_path(args.spec)) |
912 | 920 |
|
913 | 921 | if args.check: |
914 | | - existing = args.output.read_text() if args.output.exists() else '' |
| 922 | + existing = args.output.read_text(encoding='utf-8') if args.output.exists() else '' |
915 | 923 | if existing != generated: |
916 | | - rel = args.output.relative_to(ROOT_DIR) if args.output.is_absolute() else args.output |
| 924 | + rel = source_label_for_path(args.output) |
917 | 925 | print(f'{rel} is out of date. Run: python {Path(__file__).name}', file=sys.stderr) |
918 | 926 | return 1 |
919 | 927 | return 0 |
920 | 928 |
|
921 | 929 | args.output.parent.mkdir(parents=True, exist_ok=True) |
922 | | - args.output.write_text(generated) |
923 | | - print(f'wrote {args.output}') |
| 930 | + args.output.write_text(generated, encoding='utf-8', newline='\n') |
| 931 | + print(f'wrote {source_label_for_path(args.output)}') |
924 | 932 | return 0 |
925 | 933 |
|
926 | 934 |
|
|
0 commit comments