示例#1
0
    def _get_type_dict(self) -> FakeAnnotation:
        if not self.dict_items:
            return Type.DictStrAny

        first_key = self.dict_items[0]["key"]
        if first_key in SYNTAX_TYPE_MAP:
            result = TypeSubscript(Type.Dict)
            result.add_child(SYNTAX_TYPE_MAP[first_key])
            result.add_child(
                TypeValue(self.service_name, self.prefix,
                          self.dict_items[0]["value"]).get_type())
            return result

        typed_dict_name = f"{self.prefix}TypeDef"
        shape_type_stub = get_shape_type_stub(self.service_name,
                                              typed_dict_name)
        if shape_type_stub:
            return shape_type_stub

        typed_dict = TypeTypedDict(typed_dict_name)
        for item in self.dict_items:
            key_name = self._parse_constant(item["key"])
            prefix = f"{self.prefix}{key_name}"
            typed_dict.add_attribute(
                key_name,
                TypeValue(self.service_name, prefix, item["value"]).get_type(),
                required=False,
            )
        return typed_dict
 def setup_method(self):
     self.result = TypeTypedDict(
         "MyDict",
         [
             TypedDictAttribute("required", Type.bool, True),
             TypedDictAttribute("optional", Type.str, False),
         ],
         "documentation",
     )
 def test_has_both(self) -> None:
     assert self.result.has_both()
     assert not TypeTypedDict(
         "MyDict", [TypedDictAttribute("required", Type.bool, True)],
     ).has_both()
     assert not TypeTypedDict(
         "MyDict", [TypedDictAttribute("optional", Type.str, False)],
     ).has_both()
     assert not TypeTypedDict("MyDict", []).has_both()
示例#4
0
 def _make_output_typed_dict(self, typed_dict: TypeTypedDict) -> None:
     for attribute in typed_dict.children:
         attribute.required = True
     child_names = {i.name for i in typed_dict.children}
     if "ResponseMetadata" not in child_names:
         typed_dict.add_attribute(
             "ResponseMetadata",
             self.response_metadata_typed_dict,
             True,
         )
示例#5
0
    def _parse_shape_structure(
        self,
        shape: StructureShape,
        output: bool = False,
        output_child: bool = False,
        is_streaming: bool = False,
    ) -> FakeAnnotation:
        if not shape.members.items():
            return Type.DictStrAny if output_child else Type.MappingStrAny

        required = shape.required_members
        typed_dict_name = self._get_typed_dict_name(shape)
        shape_type_stub = get_shape_type_stub(self.service_name,
                                              typed_dict_name)
        if shape_type_stub:
            return shape_type_stub
        typed_dict = TypeTypedDict(typed_dict_name)

        if typed_dict.name in self._typed_dict_map:
            old_typed_dict = self._typed_dict_map[typed_dict.name]
            child_names = {i.name for i in old_typed_dict.children}
            if output and "ResponseMetadata" in child_names:
                return self._typed_dict_map[typed_dict.name]
            if not output and "ResponseMetadata" not in child_names:
                return self._typed_dict_map[typed_dict.name]

            if output:
                typed_dict.name = self._get_typed_dict_name(
                    shape, postfix="ResponseMetadata")
                self.logger.debug(
                    f"Marking {typed_dict.name} as ResponseMetadataTypeDef")
            else:
                old_typed_dict.name = self._get_typed_dict_name(
                    shape, postfix="ResponseMetadata")
                self._typed_dict_map[old_typed_dict.name] = old_typed_dict
                self.logger.debug(
                    f"Marking {old_typed_dict.name} as ResponseMetadataTypeDef"
                )

        self._typed_dict_map[typed_dict.name] = typed_dict
        for attr_name, attr_shape in shape.members.items():
            typed_dict.add_attribute(
                attr_name,
                self.parse_shape(
                    attr_shape,
                    output_child=output or output_child,
                    is_streaming=is_streaming,
                ),
                attr_name in required,
            )
        if output:
            self._make_output_typed_dict(typed_dict)
        return typed_dict
 def test_is_same(self) -> None:
     assert self.result.is_same(
         TypeTypedDict(
             "OtherDict",
             [
                 TypedDictAttribute("required", Type.bool, True),
                 TypedDictAttribute("optional", Type.str, False),
             ],
         ))
     assert not self.result.is_same(
         TypeTypedDict(
             "OtherDict",
             [
                 TypedDictAttribute("required", Type.bool, True),
                 TypedDictAttribute("optional", Type.float, False),
             ],
         ))
示例#7
0
    def _parse_shape_structure(self, shape: StructureShape) -> FakeAnnotation:
        if not shape.members.items():
            return Type.DictStrAny

        required = shape.required_members
        typed_dict_name = f"{shape.name}TypeDef"
        if typed_dict_name in self._typed_dict_map:
            return self._typed_dict_map[typed_dict_name]
        typed_dict = TypeTypedDict(typed_dict_name)
        self._typed_dict_map[typed_dict_name] = typed_dict
        for attr_name, attr_shape in shape.members.items():
            typed_dict.add_attribute(
                attr_name,
                self._parse_shape(attr_shape),
                attr_name in required,
            )
        return typed_dict
示例#8
0
    def get_request_type_annotation(self, name: str) -> TypeTypedDict | None:
        """
        Get TypedDict based on function arguments.
        """
        result = TypeTypedDict(name)
        for argument in self.arguments:
            if argument.is_kwflag():
                continue

            if not argument.type_annotation:
                continue
            result.add_attribute(
                argument.name,
                argument.type_annotation,
                required=argument.required,
            )

        if not result.children:
            return None
        return result
    def _parse_shape_structure(self, shape: StructureShape) -> FakeAnnotation:
        if not shape.members.items():
            return Type.DictStrAny

        required = shape.required_members
        typed_dict_name = f"{shape.name}TypeDef"
        shape_type_stub = get_shape_type_stub(self.service_name,
                                              typed_dict_name)
        if shape_type_stub:
            return shape_type_stub

        if typed_dict_name in self._typed_dict_map:
            return self._typed_dict_map[typed_dict_name]
        typed_dict = TypeTypedDict(typed_dict_name)
        self._typed_dict_map[typed_dict_name] = typed_dict
        for attr_name, attr_shape in shape.members.items():
            typed_dict.add_attribute(
                attr_name,
                self._parse_shape(attr_shape),
                attr_name in required,
            )
        if shape.name.endswith("Output"):
            typed_dict.add_attribute(
                "ResponseMetadata",
                self.response_metadata_typed_dict,
                False,
            )
        return typed_dict
示例#10
0
    def _fix_keys_typed_dict(
        self, typed_dict: TypeTypedDict, argument_line: TypeDocLine,
    ) -> None:
        for line in argument_line.indented:
            if not line.name:
                continue

            attribute = typed_dict.get_attribute(line.name)
            attribute.required = line.required
            if attribute.type_annotation is Type.Any:
                attribute.type_annotation = get_type_from_docstring(line.type_name)
            if not line.indented:
                continue

            self._fix_keys(attribute.type_annotation, line)
 def service_package(self) -> ServicePackage:
     service_name = ServiceName("service", "Service")
     return ServicePackage(
         Boto3StubsPackageData,
         service_name=service_name,
         client=Client("Client", service_name, "base"),
         service_resource=ServiceResource("ServiceResource", service_name,
                                          "base"),
         waiters=[Waiter("waiter", "waiter", service_name)],
         paginators=[
             Paginator("Paginator", "Paginator", "paginate", service_name)
         ],
         typed_dicts=[TypeTypedDict("MyTypedDict", [])],
         literals=[TypeLiteral("MyLiteral", ["value"])],
         helper_functions=["helper_function"],
     )
示例#12
0
    def __init__(self, session: Session, service_name: ServiceName):
        loader = session._loader
        botocore_session: BotocoreSession = session._session
        service_data = botocore_session.get_service_data(
            service_name.boto3_name)
        self.service_name = service_name
        self.service_model = ServiceModel(service_data,
                                          service_name.boto3_name)
        self._typed_dict_map: dict[str, TypeTypedDict] = {}
        self._waiters_shape: Mapping[str, Any] | None = None
        try:
            self._waiters_shape = loader.load_service_model(
                service_name.boto3_name, "waiters-2")
        except UnknownServiceError:
            pass
        self._paginators_shape: Mapping[str, Any] | None = None
        try:
            self._paginators_shape = loader.load_service_model(
                service_name.boto3_name, "paginators-1")
        except UnknownServiceError:
            pass
        self._resources_shape: Mapping[str, Any] | None = None
        try:
            self._resources_shape = loader.load_service_model(
                service_name.boto3_name, "resources-1")
        except UnknownServiceError:
            pass

        self.logger = get_logger()
        self.response_metadata_typed_dict = TypeTypedDict(
            "ResponseMetadataTypeDef",
            [
                TypedDictAttribute("RequestId", Type.str, True),
                TypedDictAttribute("HostId", Type.str, True),
                TypedDictAttribute("HTTPStatusCode", Type.int, True),
                TypedDictAttribute("HTTPHeaders", Type.DictStrStr, True),
                TypedDictAttribute("RetryAttempts", Type.int, True),
            ],
        )
        self.proxy_operation_model = OperationModel({}, self.service_model)
示例#13
0
    def __init__(self, session: Session, service_name: ServiceName):
        loader = session._loader  # pylint: disable=protected-access
        botocore_session: BotocoreSession = session._session  # pylint: disable=protected-access
        service_data = botocore_session.get_service_data(
            service_name.boto3_name)
        self.service_name = service_name
        self.service_model = ServiceModel(service_data,
                                          service_name.boto3_name)
        self._typed_dict_map: Dict[str, TypeTypedDict] = {}
        self._waiters_shape: Optional[Shape] = None
        try:
            self._waiters_shape = loader.load_service_model(
                service_name.boto3_name, "waiters-2")
        except UnknownServiceError:
            pass
        self._paginators_shape: Optional[Shape] = None
        try:
            self._paginators_shape = loader.load_service_model(
                service_name.boto3_name, "paginators-1")
        except UnknownServiceError:
            pass
        self._resources_shape: Optional[Shape] = None
        try:
            self._resources_shape = loader.load_service_model(
                service_name.boto3_name, "resources-1")
        except UnknownServiceError:
            pass

        self.logger = get_logger()
        self.response_metadata_typed_dict = TypeTypedDict(
            "ResponseMetadata",
            [
                TypedDictAttribute("RequestId", Type.str, True),
                TypedDictAttribute("HostId", Type.str, True),
                TypedDictAttribute("HTTPStatusCode", Type.int, True),
                TypedDictAttribute("HTTPHeaders", Type.DictStrAny, True),
                TypedDictAttribute("RetryAttempts", Type.int, True),
            ],
        )
示例#14
0
"""
Collection of TypedDicts added by boto3
"""
from mypy_boto3_builder.type_annotations.type import Type
from mypy_boto3_builder.type_annotations.type_typed_dict import (
    TypeTypedDict,
    TypedDictAttribute,
)

s3_copy_source_type = TypeTypedDict(
    "CopySourceTypeDef",
    [
        TypedDictAttribute("Bucket", Type.str, True),
        TypedDictAttribute("Key", Type.str, True),
        TypedDictAttribute("VersionId", Type.str, False),
    ],
)

ec2_tag_type = TypeTypedDict(
    "TagTypeDef",
    [
        TypedDictAttribute("Key", Type.str, True),
        TypedDictAttribute("Value", Type.str, False),
    ],
)

waiter_config_type = TypeTypedDict(
    "WaiterConfigTypeDef",
    [
        TypedDictAttribute("Delay", Type.int, False),
        TypedDictAttribute("MaxAttempts", Type.int, False),
class TestTypeTypedDict:
    result: TypeTypedDict

    def setup_method(self):
        self.result = TypeTypedDict(
            "MyDict",
            [
                TypedDictAttribute("required", Type.bool, True),
                TypedDictAttribute("optional", Type.str, False),
            ],
            "documentation",
        )

    def test_init(self) -> None:
        assert self.result.name == "MyDict"
        assert len(self.result.children) == 2
        assert self.result.docstring == "documentation"
        assert self.result.requires_safe_render

    def test_get_attribute(self) -> None:
        assert self.result.get_attribute("required") == self.result.children[0]

        with pytest.raises(ValueError):
            self.result.get_attribute("non_existing")

    def test_render(self) -> None:
        assert self.result.render() == "MyDict"
        assert self.result.render("OtherDict") == "MyDict"
        assert self.result.render("MyDict") == '"MyDict"'
        self.result.stringify = True
        assert self.result.render() == '"MyDict"'
        self.result.replace_with_dict.add(self.result.name)
        assert self.result.render("MyDict") == "Dict[str, Any]"

    def test_get_import_record(self) -> None:
        assert self.result.get_import_record().render(
        ) == "from .type_defs import MyDict"

    def test_get_types(self) -> None:
        assert self.result.get_types() == {self.result}

    def test_add_attribute(self) -> None:
        self.result.add_attribute("third", Type.int, False)
        assert len(self.result.children) == 3

    def test_is_dict(self) -> None:
        assert self.result.is_dict()

    def test_is_typed_dict(self) -> None:
        assert self.result.is_typed_dict()

    def test_render_class(self) -> None:
        assert self.result.render_class(
        ) == "class MyDict:\n    required: bool\n    optional: str"

    def test_has_optional(self) -> None:
        assert self.result.has_optional()
        assert not TypeTypedDict(
            "MyDict",
            [TypedDictAttribute("required", Type.bool, True)],
        ).has_optional()
        assert TypeTypedDict(
            "MyDict",
            [TypedDictAttribute("optional", Type.str, False)],
        ).has_optional()
        assert not TypeTypedDict("MyDict", []).has_optional()

    def test_has_required(self) -> None:
        assert self.result.has_required()
        assert TypeTypedDict(
            "MyDict",
            [TypedDictAttribute("required", Type.bool, True)],
        ).has_required()
        assert not TypeTypedDict(
            "MyDict",
            [TypedDictAttribute("optional", Type.str, False)],
        ).has_required()
        assert not TypeTypedDict("MyDict", []).has_required()

    def test_has_both(self) -> None:
        assert self.result.has_both()
        assert not TypeTypedDict(
            "MyDict",
            [TypedDictAttribute("required", Type.bool, True)],
        ).has_both()
        assert not TypeTypedDict(
            "MyDict",
            [TypedDictAttribute("optional", Type.str, False)],
        ).has_both()
        assert not TypeTypedDict("MyDict", []).has_both()

    def test_get_required(self) -> None:
        assert len(self.result.get_required()) == 1
        assert self.result.get_required()[0].name == "required"

    def test_get_optional(self) -> None:
        assert len(self.result.get_optional()) == 1
        assert self.result.get_optional()[0].name == "optional"

    def test_copy(self) -> None:
        assert self.result.copy().name == self.result.name

    def test_is_same(self) -> None:
        assert self.result.is_same(
            TypeTypedDict(
                "OtherDict",
                [
                    TypedDictAttribute("required", Type.bool, True),
                    TypedDictAttribute("optional", Type.str, False),
                ],
            ))
        assert not self.result.is_same(
            TypeTypedDict(
                "OtherDict",
                [
                    TypedDictAttribute("required", Type.bool, True),
                    TypedDictAttribute("optional", Type.float, False),
                ],
            ))

    def test_get_children_types(self) -> None:
        assert self.result.get_children_types() == {Type.str, Type.bool}

    def test_get_children_typed_dicts(self) -> None:
        assert len(self.result.get_children_typed_dicts()) == 0

    def test_get_children_literals(self) -> None:
        assert len(self.result.get_children_literals()) == 0
        assert len(self.result.get_children_literals([self.result])) == 0

    def test_replace_self_references(self) -> None:
        self.result.replace_self_references()
        TypeSubscript(Type.Set, [Type.Decimal]),
        TypeSubscript(Type.Set, [Type.str]),
        TypeSubscript(Type.Set, [Type.bytes]),
        TypeSubscript(Type.Set, [Type.bytearray]),
        Type.ListAny,
        Type.DictStrAny,
        Type.none,
    ],
)

# FIXME: a hack to avoid cicular TypedDict in lambda package
InvocationResponseTypeDef: TypeTypedDict = TypeTypedDict(
    "InvocationResponseTypeDef",
    [
        TypedDictAttribute("StatusCode", Type.int, False),
        TypedDictAttribute("FunctionError", Type.str, False),
        TypedDictAttribute("LogResult", Type.str, False),
        TypedDictAttribute("Payload", Type.IOBytes, False),
        TypedDictAttribute("ExecutedVersion", Type.str, False),
    ],
)

SHAPE_TYPE_MAP: Dict[ServiceName, Dict[str, FakeAnnotation]] = {
    ServiceNameCatalog.lambda_: {
        "InvocationResponseTypeDef": InvocationResponseTypeDef,
    },
    ServiceNameCatalog.dynamodb: {
        "AttributeValueTypeDef":
        DynamoDBValue,
        "ClientBatchGetItemRequestItemsKeysTypeDef":
        DynamoDBValue,
        "ClientBatchGetItemResponseResponsesTypeDef":