Skip to content

Commit dbf6222

Browse files
committed
Adding Catalog files.
1 parent d89cb1b commit dbf6222

File tree

84 files changed

+120639
-3
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+120639
-3
lines changed

.github/workflows/catalog.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Validate Catalogs
2+
3+
# Controls when the action will run.
4+
on: # yamllint disable-line rule:truthy
5+
# Triggers the workflow on push or pull request events but only for the main branch
6+
push:
7+
branches: [main]
8+
pull_request:
9+
branches: [main]
10+
11+
# Allows you to run this workflow manually from the Actions tab
12+
workflow_dispatch:
13+
14+
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
15+
jobs:
16+
# This workflow contains a single job called "build"
17+
build:
18+
name: Validate Catalogs
19+
# The type of runner that the job will run on
20+
runs-on: ubuntu-latest
21+
22+
# Steps represent a sequence of tasks that will be executed as part of the job
23+
steps:
24+
- name: Checkout repo content
25+
uses: actions/checkout@v4 # checkout the repository content to github runner.
26+
- name: Setup Python
27+
uses: actions/setup-python@v3
28+
with:
29+
python-version: 3.11 # install the python needed
30+
- name: Install dependencies
31+
run: >-
32+
python3 -m pip install -r .tools/scanners/requirements.txt
33+
- name: Check WRITEMEs
34+
run: >-
35+
python3 .tools/scanners/catalog.py --check --diff

.github/workflows/writeme.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@ jobs:
3232
python3 -m pip install -r .tools/readmes/requirements.txt
3333
- name: Check WRITEMEs
3434
run: >-
35-
python3 .tools/readmes/writeme.py --check --diff
35+
python3 .tools/scanners/writeme.py --check --diff
File renamed without changes.
File renamed without changes.

.tools/scanners/__init__.py

Whitespace-only changes.

.tools/scanners/catalog.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env python3
2+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
import sys
6+
7+
from update import update
8+
9+
# For debugging, engineers can skip update with the --no-update flag. Yes, it's
10+
# a double negative, but it's quick and early in the startup because of the
11+
# reliance on the side-effect imports from `update` and needing them to happen
12+
# before importing runner, which means before importing the runner argparser.
13+
NO_UPDATE_FLAG = "--no-update"
14+
15+
16+
if __name__ == "__main__":
17+
if NO_UPDATE_FLAG not in sys.argv:
18+
update()
19+
else:
20+
sys.argv.remove(NO_UPDATE_FLAG)
21+
22+
# This import must remain in the main, after the update, as it depends on
23+
# importing the things that got changed during update.
24+
from catalog_runner import main
25+
26+
sys.exit(main())

.tools/scanners/catalog_runner.py

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
import argparse
5+
import config
6+
import logging
7+
import os
8+
import json
9+
from collections import defaultdict
10+
from difflib import unified_diff
11+
from pathlib import Path
12+
from typing import Optional
13+
14+
from render import Renderer, MissingMetadataError, RenderStatus
15+
from scanner import Scanner
16+
17+
from aws_doc_sdk_examples_tools.doc_gen import DocGen, DocGenEncoder
18+
19+
logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO").upper(), force=True)
20+
21+
22+
def prepare_scanner(doc_gen: DocGen) -> Optional[Scanner]:
23+
for path in (doc_gen.root / ".doc_gen/metadata").glob("*_metadata.yaml"):
24+
doc_gen.process_metadata(path)
25+
doc_gen.collect_snippets()
26+
doc_gen.validate()
27+
if doc_gen.errors:
28+
error_strings = [str(error) for error in doc_gen.errors]
29+
failed_list = "\n".join(f"DocGen Error: {e}" for e in error_strings)
30+
print(f"Metadata errors encountered:\n\t{failed_list}")
31+
return None
32+
33+
scanner = Scanner(doc_gen)
34+
35+
# Preload cross-content examples
36+
scanner.load_crosses()
37+
38+
return scanner
39+
40+
41+
def main():
42+
# Load all examples immediately for cross references. Trades correctness for speed.
43+
doc_gen = DocGen.from_root(Path(__file__).parent.parent.parent, incremental=True)
44+
# To get the complete list, fill the missing fields.
45+
doc_gen.fill_missing_fields()
46+
47+
languages = ['Python:3'] # Currently enabled only for Python version 3.
48+
parser = argparse.ArgumentParser()
49+
parser.add_argument(
50+
"--languages",
51+
choices=[*languages] + ["all"],
52+
nargs="+",
53+
help="The languages of the SDK. Choose from: %(choices)s.",
54+
default=["all"],
55+
)
56+
57+
parser.add_argument(
58+
"--services",
59+
choices=[*doc_gen.services.keys()] + ["all"],
60+
nargs="+",
61+
help="The targeted service. Choose from: %(choices)s.",
62+
default=["all"],
63+
)
64+
65+
parser.add_argument(
66+
"--verbose",
67+
action="store_true",
68+
help="When set, output verbose debugging info.",
69+
)
70+
parser.add_argument(
71+
"--dry-run",
72+
action="store_true",
73+
dest="dry_run",
74+
help="In dry run, compare current vs generated and exit with failure if they do not match.",
75+
default=False, # Change this to default false when we're ready to use this generally.
76+
)
77+
parser.add_argument("--no-dry-run", dest="dry_run", action="store_false")
78+
parser.add_argument("--check", dest="dry_run", action="store_true")
79+
parser.add_argument("--diff", action="store_true", default=False)
80+
args = parser.parse_args()
81+
82+
if "all" in args.languages:
83+
args.languages = [*languages]
84+
85+
if "all" in args.services:
86+
args.services = [*doc_gen.services.keys()]
87+
88+
if args.verbose:
89+
logging.basicConfig(level=logging.DEBUG)
90+
91+
logging.debug(f"Args configuration: {args}")
92+
93+
if args.dry_run:
94+
print("Dry run, no changes will be made.")
95+
96+
skipped = []
97+
failed = []
98+
written = []
99+
unchanged = []
100+
101+
102+
scanner = prepare_scanner(doc_gen)
103+
if scanner is None:
104+
return -1
105+
106+
renderer = Renderer(scanner)
107+
108+
for service in args.services:
109+
for language_and_version in args.languages:
110+
(language, version) = language_and_version.split(":")
111+
id = f"{language}:{version}:{service}"
112+
try:
113+
renderer.set_example(service, language, int(version), False)
114+
service_folder_path = renderer.lang_config["service_folder"]
115+
logging.debug("Cataloging %s", id)
116+
catalog_status = write_catalog_json(doc_gen, service, language, service_folder_path, args.dry_run)
117+
logging.debug("Status %s", catalog_status)
118+
119+
if catalog_status == RenderStatus.UPDATED:
120+
if args.dry_run:
121+
diff = None
122+
failed.append((id, diff))
123+
else:
124+
written.append(id)
125+
elif catalog_status == RenderStatus.UNCHANGED:
126+
unchanged.append(id)
127+
pass
128+
except FileNotFoundError as fnfe:
129+
logging.debug(fnfe, exc_info=True)
130+
skipped.append(id)
131+
except MissingMetadataError as mme:
132+
logging.debug(mme, exc_info=True)
133+
failed.append(id)
134+
except Exception as e:
135+
logging.error(e, exc_info=True)
136+
failed.append(id)
137+
138+
skip_list = "\n".join(f"Skipped {f}" for f in sorted(skipped))
139+
logging.debug(skip_list or "(None Skipped)")
140+
if unchanged:
141+
unchanged_list = "\n".join(f"Unchanged {f}" for f in sorted(unchanged))
142+
print(unchanged_list)
143+
if not args.dry_run:
144+
done_list = "\n".join(f"Wrote {f}" for f in sorted(written))
145+
print(done_list or "(None Written)")
146+
if failed:
147+
if args.diff:
148+
failed_list = "\n".join(
149+
f"Diff: {f[1]}" for f in sorted(failed, key=lambda f: f[0])
150+
)
151+
else:
152+
failed_list = "\n".join(f"Incorrect: {f[0]}" for f in sorted(failed))
153+
print(failed_list)
154+
print("Rerun catalog.py to update the example catalog list.")
155+
print("Catalog Run completed.")
156+
return len(failed)
157+
158+
159+
def write_catalog_json(doc_gen, service_name, language_name, folder_path, is_dry_run):
160+
filepath = (
161+
Path(__file__).parent.parent.parent
162+
/ folder_path
163+
/ 'examples_catalog.json'
164+
)
165+
166+
language_examples = []
167+
for example in doc_gen.examples.values():
168+
for lang_name, language in example.languages.items():
169+
for svc_name in example.services:
170+
if svc_name == service_name and lang_name == language_name:
171+
language_examples.append(example)
172+
173+
new_catalog = json.dumps(
174+
{"examples": language_examples},
175+
cls=DocGenEncoder, indent="\t"
176+
)
177+
178+
# If the file already exists, read it to compare contents.
179+
try:
180+
with open(filepath, "r", encoding="utf-8") as example_meta:
181+
old_catalog = example_meta.read()
182+
except FileNotFoundError:
183+
old_catalog = ""
184+
185+
if old_catalog == new_catalog:
186+
return RenderStatus.UNCHANGED
187+
else:
188+
if not is_dry_run:
189+
print(f"Writing serialized versions of DocGen to {filepath}")
190+
with open(filepath, "w", encoding="utf-8") as example_meta:
191+
example_meta.write(new_catalog)
192+
return RenderStatus.UPDATED
193+
194+
195+
def write_language_json(doc_gen, language_name):
196+
# Test creating a file
197+
filepath = f"example_json/{language_name}_examples_list.json"
198+
filepath = filepath.lower()
199+
print("Writing serialized versions of DocGen to %s", filepath)
200+
201+
language_examples = []
202+
for example in doc_gen.examples.values():
203+
for lang_name, language in example.languages.items():
204+
if lang_name == language_name:
205+
language_examples.append(example)
206+
207+
with open(filepath, "w") as example_meta:
208+
example_meta.write(
209+
json.dumps(
210+
{"examples": language_examples},
211+
cls=DocGenEncoder, indent="\t"
212+
)
213+
)
File renamed without changes.
File renamed without changes.
File renamed without changes.

.tools/readmes/runner.py renamed to .tools/scanners/runner.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ def main():
115115
for service in args.services:
116116
for language_and_version in args.languages:
117117
(language, version) = language_and_version.split(":")
118-
# write_service_json(doc_gen, service, language)
118+
write_service_json(doc_gen, service, language)
119119
id = f"{language}:{version}:{service}"
120120
try:
121121
renderer.set_example(service, language, int(version), args.safe)
@@ -192,7 +192,7 @@ def write_service_json(doc_gen, service_name, language_name):
192192
filepath = f"example_json/{language_name}_{service_name}_examples_list.json"
193193
filepath = filepath.lower()
194194
print("Writing serialized versions of DocGen to %s", filepath)
195-
195+
doc_gen.fill_missing_fields()
196196
language_examples = []
197197
for example in doc_gen.examples.values():
198198
for lang_name, language in example.languages.items():
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)