Skip to content

Commit

Permalink
Downgrade to Python 3.8
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidSouther committed Feb 26, 2024
1 parent d9aa68d commit 4acf774
Show file tree
Hide file tree
Showing 15 changed files with 121 additions and 106 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v5
with:
python-version: "3.11"
python-version: "3.8"
cache: "pip"
- run: pip install -r requirements.txt
- run: python -m black --check **/*.py
Expand Down
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.11
3.8
20 changes: 10 additions & 10 deletions aws_doc_sdk_examples_tools/doc_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

import yaml

from typing import Self
from dataclasses import dataclass, field
from pathlib import Path
from typing import Dict, List, Optional, Set

# from os import glob

Expand All @@ -29,22 +29,22 @@
class DocGen:
root: Path
errors: MetadataErrors
sdks: dict[str, Sdk] = field(default_factory=dict)
services: dict[str, Service] = field(default_factory=dict)
snippets: dict[str, Snippet] = field(default_factory=dict)
snippet_files: set[str] = field(default_factory=set)
examples: list[Example] = field(default_factory=list)
cross_blocks: set[str] = field(default_factory=set)

def collect_snippets(self, snippets_root: Path | None):
sdks: Dict[str, Sdk] = field(default_factory=dict)
services: Dict[str, Service] = field(default_factory=dict)
snippets: Dict[str, Snippet] = field(default_factory=dict)
snippet_files: Set[str] = field(default_factory=set)
examples: List[Example] = field(default_factory=list)
cross_blocks: Set[str] = field(default_factory=set)

def collect_snippets(self, snippets_root: Optional[Path]):
if snippets_root is None:
snippets_root = self.root.parent.parent
snippets, errs = collect_snippets(snippets_root)
self.snippets = snippets
self.errors.extend(errs)

@classmethod
def from_root(cls, root: Path) -> Self:
def from_root(cls, root: Path) -> "DocGen":
errors = MetadataErrors()

metadata = root / ".doc_gen/metadata"
Expand Down
8 changes: 4 additions & 4 deletions aws_doc_sdk_examples_tools/file_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@

import os

from shutil import rmtree
from pathlib import Path
from collections.abc import Generator, Callable
from typing import Callable, Generator, List
from shutil import rmtree

from pathspec import GitIgnoreSpec


def match_path_to_specs(path: Path, specs: list[GitIgnoreSpec]) -> bool:
def match_path_to_specs(path: Path, specs: List[GitIgnoreSpec]) -> bool:
"""
Return True if we should skip this path, that is, it is matched by a .gitignore.
"""
Expand All @@ -21,7 +21,7 @@ def match_path_to_specs(path: Path, specs: list[GitIgnoreSpec]) -> bool:


def walk_with_gitignore(
root: Path, specs: list[GitIgnoreSpec] = []
root: Path, specs: List[GitIgnoreSpec] = []
) -> Generator[Path, None, None]:
"""
Starting from a root directory, walk the file system yielding a path for each file.
Expand Down
84 changes: 43 additions & 41 deletions aws_doc_sdk_examples_tools/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Optional, Self
from typing import Any, Dict, List, Optional, Set, Union
from os.path import splitext

from aws_doc_sdk_examples_tools import metadata_errors
Expand All @@ -24,8 +26,8 @@ class Url:

@classmethod
def from_yaml(
cls, yaml: None | dict[str, str | None]
) -> None | Self | MetadataParseError:
cls, yaml: None | Dict[str, Optional[str]]
) -> Optional[Union[Url, MetadataParseError]]:
if yaml is None:
return None
title = yaml.get("title", "")
Expand All @@ -41,12 +43,12 @@ def from_yaml(
class Excerpt:
description: Optional[str]
# Tags embedded in source files to extract as snippets.
snippet_tags: list[str]
snippet_tags: List[str]
# A path within the repo to extract the entire file as a snippet.
snippet_files: list[str] = field(default_factory=list)
snippet_files: List[str] = field(default_factory=list)

@classmethod
def from_yaml(cls, yaml: Any) -> Self:
def from_yaml(cls, yaml: Any) -> "Excerpt":
description = yaml.get("description")
snippet_files = [str(file) for file in yaml.get("snippet_files", [])]
snippet_tags = [str(tag) for tag in yaml.get("snippet_tags", [])]
Expand All @@ -59,21 +61,21 @@ class Version:
# Additional ZonBook XML to include in the tab for this sample.
block_content: Optional[str] = field(default=None)
# The specific code samples to include in the example.
excerpts: list[Excerpt] = field(default_factory=list)
excerpts: List[Excerpt] = field(default_factory=list)
# Link to the source code for this example. TODO rename.
github: Optional[str] = field(default=None)
add_services: dict[str, list[str]] = field(default_factory=dict)
add_services: Dict[str, List[str]] = field(default_factory=dict)
# Deprecated. Replace with guide_topic list.
sdkguide: Optional[str] = field(default=None)
# Link to additional topic places. TODO: Overwritten by aws-doc-sdk-example when merging.
more_info: list[Url] = field(default_factory=list)
more_info: List[Url] = field(default_factory=list)

@classmethod
def from_yaml(
cls,
yaml: dict[str, Any],
services: dict[str, Service],
cross_content_blocks: set[str],
yaml: Dict[str, Any],
services: Dict[str, Service],
cross_content_blocks: Set[str],
is_action: bool,
) -> tuple["Version", MetadataErrors]:
errors = MetadataErrors()
Expand Down Expand Up @@ -107,7 +109,7 @@ def from_yaml(
if len(excerpts) > 0 and block_content is not None:
errors.append(metadata_errors.BlockContentAndExcerptConflict())

more_info: list[Url] = []
more_info: List[Url] = []
for url in yaml.get("more_info", []):
url = Url.from_yaml(url)
if isinstance(url, Url):
Expand Down Expand Up @@ -139,28 +141,28 @@ def from_yaml(
@dataclass
class Language:
name: str
versions: list[Version]
versions: List[Version]

@classmethod
def from_yaml(
cls,
name: str,
yaml: Any,
sdks: dict[str, Sdk],
services: dict[str, Service],
blocks: set[str],
sdks: Dict[str, Sdk],
services: Dict[str, Service],
blocks: Set[str],
is_action: bool,
) -> tuple[Self, MetadataErrors]:
) -> tuple[Language, MetadataErrors]:
errors = MetadataErrors()
if name not in sdks:
errors.append(metadata_errors.UnknownLanguage(language=name))

yaml_versions: list[dict[str, Any]] | None = yaml.get("versions")
yaml_versions: List[Dict[str, Any]] | None = yaml.get("versions")
if yaml_versions is None or len(yaml_versions) == 0:
errors.append(metadata_errors.MissingField(field="versions"))
yaml_versions = []

versions: list[Version] = []
versions: List[Version] = []
for version in yaml_versions:
vers, version_errors = Version.from_yaml(
version, services, blocks, is_action
Expand All @@ -184,27 +186,27 @@ class Example:
# Used in the TOC. TODO: Defaults to slug-to-title of the ID if not provided.
title_abbrev: str
synopsis: str
languages: dict[str, Language]
languages: Dict[str, Language]
# String label categories. Categories inferred by cross-service with multiple services, and can be whatever else it wants. Controls where in the TOC it appears.
category: Optional[str] = field(default=None)
# Link to additional topic places.
guide_topic: Optional[Url] = field(default=None) # TODO: Url|list[Url]
guide_topic: Optional[Url] = field(default=None) # TODO: Url|List[Url]
# TODO how to add a language here and require it in services_schema.
# TODO document service_main and services. Not to be used by tributaries. Part of Cross Service.
# List of services used by the examples. Lines up with those in services.yaml.
service_main: Optional[str] = field(default=None)
services: dict[str, list[str]] = field(default_factory=dict)
synopsis_list: list[str] = field(default_factory=list)
services: Dict[str, List[str]] = field(default_factory=dict)
synopsis_list: List[str] = field(default_factory=list)
source_key: Optional[str] = field(default=None)

@classmethod
def from_yaml(
cls,
yaml: Any,
sdks: dict[str, Sdk],
services: dict[str, Service],
blocks: set[str],
) -> tuple[Self, MetadataErrors]:
sdks: Dict[str, Sdk],
services: Dict[str, Service],
blocks: Set[str],
) -> tuple[Example, MetadataErrors]:
errors = MetadataErrors()

title = get_with_valid_entities("title", yaml, errors)
Expand Down Expand Up @@ -233,7 +235,7 @@ def from_yaml(
is_action = category == "Api"

yaml_languages = yaml.get("languages")
languages: dict[str, Language] = {}
languages: Dict[str, Language] = {}
if yaml_languages is None:
errors.append(metadata_errors.MissingField(field="languages"))
else:
Expand Down Expand Up @@ -264,16 +266,16 @@ def from_yaml(


def parse_services(
yaml: Any, errors: MetadataErrors, known_services: dict[str, Service]
) -> dict[str, list[str]]:
yaml: Any, errors: MetadataErrors, known_services: Dict[str, Service]
) -> Dict[str, List[str]]:
if yaml is None:
return {}
services: dict[str, list[str]] = {}
services: Dict[str, List[str]] = {}
for name in yaml:
if name not in known_services:
errors.append(metadata_errors.UnknownService(service=name))
else:
service: dict[str, None] | None = yaml.get(name)
service: Dict[str, None] | None = yaml.get(name)
# While .get replaces missing with {}, `sqs: ` in yaml parses a literal `None`
if service is None:
service = {}
Expand All @@ -286,7 +288,7 @@ def parse_services(


def get_with_valid_entities(
name: str, d: dict[str, str], errors: MetadataErrors, opt: bool = False
name: str, d: Dict[str, str], errors: MetadataErrors, opt: bool = False
) -> str:
field = d.get(name)
if field is None:
Expand All @@ -305,7 +307,7 @@ def get_with_valid_entities(
return field


def idFormat(id: str, services: dict[str, Service]) -> bool:
def idFormat(id: str, services: Dict[str, Service]) -> bool:
[service, *rest] = id.split("_")
if len(rest) == 0:
return False
Expand All @@ -314,12 +316,12 @@ def idFormat(id: str, services: dict[str, Service]) -> bool:

def parse(
file: str,
yaml: dict[str, Any],
sdks: dict[str, Sdk],
services: dict[str, Service],
blocks: set[str],
) -> tuple[list[Example], MetadataErrors]:
examples: list[Example] = []
yaml: Dict[str, Any],
sdks: Dict[str, Sdk],
services: Dict[str, Service],
blocks: Set[str],
) -> tuple[List[Example], MetadataErrors]:
examples: List[Example] = []
errors = MetadataErrors()
for id in yaml:
if not idFormat(id, services):
Expand Down
10 changes: 6 additions & 4 deletions aws_doc_sdk_examples_tools/metadata_errors.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

from __future__ import annotations

import re
from dataclasses import dataclass
from typing import Optional, Iterator, Iterable, TypeVar, Self
from typing import Optional, Iterator, Iterable, List, TypeVar


@dataclass
Expand Down Expand Up @@ -54,11 +56,11 @@ def __init__(self, item: MetadataError):


class MetadataErrors:
"""MyPy isn't catching list[Foo].append(list[Foo])"""
"""MyPy isn't catching List[Foo].append(List[Foo])"""

def __init__(self, no_duplicates: bool = False):
self.no_duplicates = no_duplicates
self._errors: list[MetadataError] = []
self._errors: List[MetadataError] = []

def append(self, item: MetadataError):
if not isinstance(item, MetadataError):
Expand All @@ -74,7 +76,7 @@ def append(self, item: MetadataError):
def extend(self, errors: Iterable[MetadataError]):
self._errors.extend(errors)

def maybe_extend(self, maybe_errors: K | Self) -> K | None:
def maybe_extend(self, maybe_errors: K | MetadataErrors) -> K | None:
if isinstance(maybe_errors, MetadataErrors):
self.extend(maybe_errors._errors)
return None
Expand Down
7 changes: 4 additions & 3 deletions aws_doc_sdk_examples_tools/metadata_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import pytest
import yaml
from pathlib import Path
from typing import List, Set, Tuple

from aws_doc_sdk_examples_tools import metadata_errors
from aws_doc_sdk_examples_tools.metadata import (
Expand All @@ -25,8 +26,8 @@


def load(
path: Path, doc_gen: DocGen, blocks: set[str] = set()
) -> tuple[list[Example], metadata_errors.MetadataErrors]:
path: Path, doc_gen: DocGen, blocks: Set[str] = set()
) -> Tuple[List[Example], metadata_errors.MetadataErrors]:
root = Path(__file__).parent
filename = root / "test_resources" / path
with open(filename) as file:
Expand Down Expand Up @@ -407,7 +408,7 @@ def test_verify_load_successful():
],
)
def test_common_errors(
filename: str, expected_errors: list[metadata_errors.MetadataError]
filename: str, expected_errors: List[metadata_errors.MetadataError]
):
_, actual = load(Path(filename), DOC_GEN, set(["test/block", "cross_block.xml"]))
assert expected_errors == [*actual]
Expand Down
Loading

0 comments on commit 4acf774

Please sign in to comment.