Skip to content

Commit da64362

Browse files
committed
Extract ConfigLoaders, and add Github config loader for raw user content
1 parent 593603b commit da64362

File tree

5 files changed

+89
-43
lines changed

5 files changed

+89
-43
lines changed

aws_doc_sdk_examples_tools/doc_gen.py

Lines changed: 68 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33

44
import yaml
55
import json
6+
import requests
67

8+
from abc import ABC, abstractmethod
79
from collections import defaultdict
810
from dataclasses import dataclass, field, fields, is_dataclass, asdict
911
from functools import reduce
@@ -47,6 +49,46 @@ class DocGenMergeWarning(MetadataError):
4749
pass
4850

4951

52+
class ConfigLoader(ABC):
53+
@abstractmethod
54+
def load(self, filename: str) -> Tuple[Path, Any]:
55+
pass
56+
57+
58+
class NoneLoader(ConfigLoader):
59+
def load(self, filename: str) -> Tuple[Path, Any]:
60+
return Path(filename), yaml.safe_load("")
61+
62+
63+
class FileLoader(ConfigLoader):
64+
def __init__(self, root: Optional[Path] = None):
65+
self.config = root or Path(__file__).parent / "config"
66+
67+
def load(self, filename: str) -> Tuple[Path, Any]:
68+
path = self.config / filename
69+
print(f"Opening {path}")
70+
with path.open(encoding="utf-8") as file:
71+
return path, yaml.safe_load(file)
72+
73+
74+
class GitHubLoader(ConfigLoader):
75+
def __init__(self, repo: Optional[str] = None, commit: Optional[str] = None):
76+
self.repo = repo or "awsdocs/aws-doc-sdk-examples-tools"
77+
self.commit = (
78+
commit or "refs/heads/main"
79+
) # or refs/tags/2025.07.0 or a specific SHA
80+
self.path = f"{self.repo}/{self.commit}/aws_doc_sdk_examples_tools/config"
81+
82+
def load(self, filename: str) -> Tuple[Path, Any]:
83+
path = f"{self.path}/{filename}"
84+
url = f"https://raw.githubusercontent.com/{path}"
85+
print(f"Requesting {url}")
86+
r = requests.get(url)
87+
if r.status_code == 200:
88+
return Path(path), yaml.safe_load(r.text)
89+
raise Exception(f"Failed to request {url} ({r.status_code} {r.text})")
90+
91+
5092
@dataclass
5193
class DocGen:
5294
root: Path
@@ -170,7 +212,9 @@ def empty(cls, validation: ValidationConfig = ValidationConfig()) -> "DocGen":
170212

171213
@classmethod
172214
def default(cls) -> "DocGen":
173-
return DocGen.empty().for_root(Path(__file__).parent, incremental=True)
215+
return DocGen.empty().for_root(
216+
Path(__file__).parent, GitHubLoader(), incremental=True
217+
)
174218

175219
def clone(self) -> "DocGen":
176220
return DocGen(
@@ -186,13 +230,9 @@ def clone(self) -> "DocGen":
186230
examples={},
187231
)
188232

189-
def for_root(
190-
self, root: Path, config: Optional[Path] = None, incremental=False
191-
) -> "DocGen":
233+
def for_root(self, root: Path, loader: ConfigLoader, incremental=False) -> "DocGen":
192234
self.root = root
193235

194-
config = config or Path(__file__).parent / "config"
195-
196236
try:
197237
with open(root / ".doc_gen" / "validation.yaml", encoding="utf-8") as file:
198238
validation = yaml.safe_load(file)
@@ -203,46 +243,37 @@ def for_root(
203243
pass
204244

205245
try:
206-
sdk_path = config / "sdks.yaml"
207-
with sdk_path.open(encoding="utf-8") as file:
208-
meta = yaml.safe_load(file)
209-
sdks, errs = parse_sdks(sdk_path, meta)
210-
self.sdks = sdks
211-
self.errors.extend(errs)
246+
sdk_path, meta = loader.load("sdks.yaml")
247+
sdks, errs = parse_sdks(sdk_path, meta)
248+
self.sdks = sdks
249+
self.errors.extend(errs)
212250
except Exception:
213251
pass
214252

215253
try:
216-
services_path = config / "services.yaml"
217-
with services_path.open(encoding="utf-8") as file:
218-
meta = yaml.safe_load(file)
219-
services, service_errors = parse_services(services_path, meta)
220-
self.services = services
221-
for service in self.services.values():
222-
if service.expanded:
223-
self.entities[service.long] = service.expanded.long
224-
self.entities[service.short] = service.expanded.short
225-
self.errors.extend(service_errors)
254+
services_path, meta = loader.load("services.yaml")
255+
services, service_errors = parse_services(services_path, meta)
256+
257+
self.services = services
258+
for service in self.services.values():
259+
if service.expanded:
260+
self.entities[service.long] = service.expanded.long
261+
self.entities[service.short] = service.expanded.short
262+
self.errors.extend(service_errors)
226263
except Exception:
227264
pass
228265

229266
try:
230-
categories_path = config / "categories.yaml"
231-
with categories_path.open(encoding="utf-8") as file:
232-
meta = yaml.safe_load(file)
233-
standard_categories, categories, errs = parse_categories(
234-
categories_path, meta
235-
)
236-
self.standard_categories = standard_categories
237-
self.categories = categories
238-
self.errors.extend(errs)
267+
path, meta = loader.load("categories.yaml")
268+
standard_categories, categories, errs = parse_categories(path, meta)
269+
self.standard_categories = standard_categories
270+
self.categories = categories
271+
self.errors.extend(errs)
239272
except Exception:
240273
pass
241274

242275
try:
243-
entities_config_path = config / "entities.yaml"
244-
with entities_config_path.open(encoding="utf-8") as file:
245-
entities_config = yaml.safe_load(file)
276+
path, entities_config = loader.load("entities.yaml")
246277
for entity, expanded in entities_config["expanded_override"].items():
247278
self.entities[entity] = expanded
248279
except Exception:
@@ -294,12 +325,13 @@ def process_metadata(self, path: Path) -> "DocGen":
294325
def from_root(
295326
cls,
296327
root: Path,
297-
config: Optional[Path] = None,
328+
loader: Optional[ConfigLoader] = None,
298329
validation: ValidationConfig = ValidationConfig(),
299330
incremental: bool = False,
300331
) -> "DocGen":
332+
loader = loader or GitHubLoader()
301333
return DocGen.empty(validation=validation).for_root(
302-
root, config, incremental=incremental
334+
root, loader, incremental=incremental
303335
)
304336

305337
def validate(self):

aws_doc_sdk_examples_tools/doc_gen_test.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import json
1111

1212
from .categories import Category, TitleInfo
13-
from .doc_gen import DocGen, DocGenEncoder
13+
from .doc_gen import DocGen, DocGenEncoder, FileLoader
1414
from .metadata import Example
1515
from .metadata_errors import MetadataErrors, MetadataError
1616
from .sdks import Sdk, SdkVersion
@@ -65,7 +65,7 @@ def test_merge(a: DocGen, b: DocGen, d: DocGen):
6565
def test_incremental():
6666
errors = MetadataErrors()
6767
doc_gen = DocGen(Path(), errors).for_root(
68-
Path(__file__).parent / "test_resources", incremental=False
68+
Path(__file__).parent / "test_resources", loader=FileLoader(), incremental=False
6969
)
7070
assert len(doc_gen.examples) == 0
7171
doc_gen.process_metadata(doc_gen.root / "awsentity_metadata.yaml")
@@ -231,7 +231,7 @@ def test_doc_gen_encoder(sample_doc_gen: DocGen):
231231
def test_doc_gen_load_snippets():
232232
errors = MetadataErrors()
233233
doc_gen = DocGen(Path(), errors).for_root(
234-
Path(__file__).parent / "test_resources", incremental=False
234+
Path(__file__).parent / "test_resources", loader=FileLoader(), incremental=False
235235
)
236236
doc_gen.process_metadata(doc_gen.root / "valid_metadata.yaml")
237237
doc_gen.collect_snippets()

aws_doc_sdk_examples_tools/sdks.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ def parse(file: Path, yaml: Dict[str, Any]) -> tuple[Dict[str, Sdk], MetadataErr
182182
from pathlib import Path
183183

184184
path = Path(__file__).parent.parent.parent / ".doc_gen" / "metadata" / "sdks.yaml"
185+
185186
with open(path) as file:
186187
meta = yaml.safe_load(file)
187188
examples, errors = parse(path, meta)

aws_doc_sdk_examples_tools/stats.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22
from pathlib import Path
33
from pprint import pformat
44

5-
from .doc_gen import DocGen
5+
from .doc_gen import DocGen, FileLoader
66

77

88
def main(roots: List[str]):
99
base = DocGen.empty()
1010
for root in roots:
1111
docgen_root = Path(root)
12-
doc_gen = base.clone().for_root(docgen_root)
12+
doc_gen = base.clone().for_root(
13+
docgen_root, loader=FileLoader(Path(root) / ".doc_gen" / "config")
14+
)
1315
doc_gen.collect_snippets()
1416
print(f"Root {docgen_root.name}")
1517
stats = doc_gen.stats()

aws_doc_sdk_examples_tools/validate.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from pathlib import Path
77
from sys import exit
88

9-
from .doc_gen import DocGen
9+
from .doc_gen import DocGen, FileLoader
1010
from .project_validator import check_files, verify_sample_files, ValidationConfig
1111

1212

@@ -32,11 +32,22 @@ def main():
3232
"must have them.",
3333
required=False,
3434
)
35+
parser.add_argument(
36+
"--local_loader",
37+
action="store_true",
38+
default=False,
39+
help="Use LocalConfigLoader, instead of GithubConfigLoader",
40+
required=False,
41+
)
3542
args = parser.parse_args()
3643
root_path = Path(args.root).resolve()
3744

45+
loader = FileLoader() if args.local_loader else None
46+
3847
doc_gen = DocGen.from_root(
39-
root=root_path, validation=ValidationConfig(strict_titles=args.strict_titles)
48+
root=root_path,
49+
loader=loader,
50+
validation=ValidationConfig(strict_titles=args.strict_titles),
4051
)
4152
doc_gen.collect_snippets(snippets_root=root_path)
4253
doc_gen.validate()

0 commit comments

Comments
 (0)