def test_address_name_builtin_keyword():
    addr_builtin = metadata.Address(
        name="Any",
        module="any",
        package=("google", "protobuf"),
        api_naming=naming.NewNaming(proto_package="foo.bar.baz.v1"),
    )
    assert addr_builtin.module_alias == "gp_any"

    addr_kword = metadata.Address(
        name="Class",
        module="class",
        package=("google", "protobuf"),
        api_naming=naming.NewNaming(proto_package="foo.bar.baz.v1"),
    )
    assert addr_kword.module_alias == "gp_class"
def test_generator_duplicate_samples(fs):
    config_fpath = "samples.yaml"
    fs.create_file(
        config_fpath,
        contents=dedent("""
            # Note: the samples are duplicates.
            type: com.google.api.codegen.samplegen.v1p2.SampleConfigProto
            schema_version: 1.2.0
            samples:
            - id: squid_sample
              region_tag: humboldt_tag
              rpc: get_squid
            - id: squid_sample
              region_tag: humboldt_tag
              rpc: get_squid
            """),
    )

    generator = make_generator("samples=samples.yaml")
    generator._env.loader = jinja2.DictLoader({"sample.py.j2": ""})
    api_schema = make_api(
        naming=naming.NewNaming(name="Mollusc", version="v6"))

    with pytest.raises(types.DuplicateSample):
        generator.get_response(api_schema=api_schema, opts=Options.build(""))
예제 #3
0
def test_address_str_different_proto_package():
    addr = metadata.Address(
        package=('google', 'iam', 'v1'),
        module='options',
        name='GetPolicyOptions',
        api_naming=naming.NewNaming(proto_package='foo.bar.baz.v1'))
    assert str(addr) == 'options_pb2.GetPolicyOptions'
예제 #4
0
def test_address_str_different_proto_package_with_collision():
    addr = metadata.Address(
        package=('google', 'rpc'),
        module='status',
        name='Status',
        api_naming=naming.NewNaming(proto_package='foo.bar.baz.v1')
    ).with_context(collisions=frozenset({'status'}))
    # the module alias should be ignored for _pb2 types
    assert str(addr) == 'status_pb2.Status'
예제 #5
0
def test_message_pb2_sphinx_ident():
    meta = metadata.Metadata(
        address=metadata.Address(name='Timestamp',
                                 package=('google', 'protobuf'),
                                 module='timestamp',
                                 api_naming=naming.NewNaming(
                                     proto_package="foo.bar")))
    message = make_message("Timestamp",
                           package='google.protobuf',
                           module='timestamp',
                           meta=meta)
    assert message.ident.sphinx == 'google.protobuf.timestamp_pb2.Timestamp'
def test_generate_autogen_samples(mock_generate_sample, mock_generate_specs):
    opts = Options.build("autogen-snippets")
    g = generator.Generator(opts)
    # Need to have the sample template visible to the generator.
    g._env.loader = jinja2.DictLoader({"sample.py.j2": ""})

    api_schema = make_api(
        naming=naming.NewNaming(name="Mollusc", version="v6"))

    actual_response = g.get_response(api_schema, opts=opts)

    # Just check that generate_sample_specs was called
    # Correctness of the spec is tested in samplegen unit tests
    mock_generate_specs.assert_called_once_with(api_schema, opts=opts)
def test_samplegen_id_disambiguation(mock_gmtime, mock_generate_sample, fs):
    # These time values are nothing special,
    # they just need to be deterministic.
    returner = mock.MagicMock()
    returner.tm_year = 2112
    returner.tm_mon = 6
    returner.tm_mday = 1
    returner.tm_hour = 13
    returner.tm_min = 13
    returner.tm_sec = 13
    mock_gmtime.return_value = returner

    # Note: The first two samples will have the same nominal ID, the first by
    #       explicit naming and the second by falling back to the region_tag.
    #       The third has no id of any kind, so the generator is required to make a
    #       unique ID for it.
    fs.create_file(
        "samples.yaml",
        contents=dedent("""
            ---
            type: com.google.api.codegen.samplegen.v1p2.SampleConfigProto
            schema_version: 1.2.0
            samples:
            - id: squid_sample
              region_tag: humboldt_tag
              rpc: get_squid_streaming
            # Note that this region tag collides with the id of the previous sample.
            - region_tag: squid_sample
              rpc: get_squid_streaming
            # No id or region tag.
            - rpc: get_squid_streaming
            """),
    )
    g = generator.Generator(Options.build("samples=samples.yaml"))
    # Need to have the sample template visible to the generator.
    g._env.loader = jinja2.DictLoader({"sample.py.j2": ""})

    api_schema = make_api(
        naming=naming.NewNaming(name="Mollusc", version="v6"))
    actual_response = g.get_response(api_schema, opts=Options.build(""))
    expected_response = CodeGeneratorResponse(file=[
        CodeGeneratorResponse.File(
            name="samples/generated_samples/squid_sample_91a465c6.py",
            content="\n",
        ),
        CodeGeneratorResponse.File(
            name="samples/generated_samples/squid_sample_55051b38.py",
            content="\n",
        ),
        CodeGeneratorResponse.File(
            name="samples/generated_samples/157884ee.py",
            content="\n",
        ),
        # TODO(busunkim): Re-enable manifest generation once metadata
        # format has been formalized.
        # https://docs.google.com/document/d/1ghBam8vMj3xdoe4xfXhzVcOAIwrkbTpkMLgKc9RPD9k/edit#heading=h.sakzausv6hue
        # CodeGeneratorResponse.File(
        #     name="samples/generated_samples/mollusc.v6.python.21120601.131313.manifest.yaml",
        #     content=dedent(
        #         """\
        #     ---
        #     type: manifest/samples
        #     schema_version: 3
        #     python: &python
        #       environment: python
        #       bin: python3
        #       base_path: samples
        #       invocation: '{bin} {path} @args'
        #     samples:
        #     - <<: *python
        #       sample: squid_sample_91a465c6
        #       path: '{base_path}/squid_sample_91a465c6.py'
        #       region_tag: humboldt_tag
        #     - <<: *python
        #       sample: squid_sample_55051b38
        #       path: '{base_path}/squid_sample_55051b38.py'
        #       region_tag: squid_sample
        #     - <<: *python
        #       sample: 157884ee
        #       path: '{base_path}/157884ee.py'
        #     """
        #     ),
        # ),
    ])
    expected_response.supported_features |= (
        CodeGeneratorResponse.Feature.FEATURE_PROTO3_OPTIONAL)

    assert actual_response == expected_response
def test_samplegen_config_to_output_files(
    mock_gmtime,
    mock_generate_sample,
    fs,
):
    # These time values are nothing special,
    # they just need to be deterministic.
    returner = mock.MagicMock()
    returner.tm_year = 2112
    returner.tm_mon = 6
    returner.tm_mday = 1
    returner.tm_hour = 13
    returner.tm_min = 13
    returner.tm_sec = 13
    mock_gmtime.return_value = returner

    fs.create_file(
        "samples.yaml",
        contents=dedent("""
            ---
            type: com.google.api.codegen.samplegen.v1p2.SampleConfigProto
            schema_version: 1.2.0
            samples:
            - id: squid_sample
              region_tag: humboldt_tag
              rpc: get_squid_streaming
            - region_tag: clam_sample
              rpc: get_clam
            """),
    )

    g = generator.Generator(Options.build("samples=samples.yaml", ))
    # Need to have the sample template visible to the generator.
    g._env.loader = jinja2.DictLoader({"sample.py.j2": ""})

    api_schema = make_api(
        naming=naming.NewNaming(name="Mollusc", version="v6"))
    actual_response = g.get_response(api_schema, opts=Options.build(""))
    expected_response = CodeGeneratorResponse(file=[
        CodeGeneratorResponse.File(
            name="samples/generated_samples/squid_sample.py",
            content="\n",
        ),
        CodeGeneratorResponse.File(
            name="samples/generated_samples/clam_sample.py",
            content="\n",
        ),
        # TODO(busunkim): Re-enable manifest generation once metadata
        # format has been formalized.
        # https://docs.google.com/document/d/1ghBam8vMj3xdoe4xfXhzVcOAIwrkbTpkMLgKc9RPD9k/edit#heading=h.sakzausv6hue
        # CodeGeneratorResponse.File(
        #     name="samples/generated_samples/mollusc.v6.python.21120601.131313.manifest.yaml",
        #     content=dedent(
        #         """\
        #     ---
        #     type: manifest/samples
        #     schema_version: 3
        #     python: &python
        #       environment: python
        #       bin: python3
        #       base_path: samples
        #       invocation: '{bin} {path} @args'
        #     samples:
        #     - <<: *python
        #       sample: squid_sample
        #       path: '{base_path}/squid_sample.py'
        #       region_tag: humboldt_tag
        #     - <<: *python
        #       sample: clam_sample
        #       path: '{base_path}/clam_sample.py'
        #       region_tag: clam_sample
        #     """
        #     ),
        # ),
    ])
    expected_response.supported_features |= (
        CodeGeneratorResponse.Feature.FEATURE_PROTO3_OPTIONAL)

    assert actual_response == expected_response
예제 #9
0
def test_generate_sample_basic():
    # Note: the sample integration tests are needfully large
    # and difficult to eyeball parse. They are intended to be integration tests
    # that catch errors in behavior that is emergent from combining smaller features
    # or in features that are sufficiently small and trivial that it doesn't make sense
    # to have standalone tests.

    input_type = DummyMessage(
        type="REQUEST TYPE",
        fields={
            "classify_target":
            DummyField(message=DummyMessage(
                type="CLASSIFY TYPE",
                fields={
                    "video":
                    DummyField(message=DummyMessage(type="VIDEO TYPE"), ),
                    "location_annotation":
                    DummyField(message=DummyMessage(type="LOCATION TYPE"), )
                },
            ))
        },
        ident=DummyIdent(name="molluscs.v1.ClassifyRequest"))

    api_naming = naming.NewNaming(name="MolluscClient",
                                  namespace=("molluscs", "v1"))
    service = wrappers.Service(
        service_pb=namedtuple('service_pb', ['name'])('MolluscService'),
        methods={
            "Classify":
            DummyMethod(input=input_type,
                        output=message_factory("$resp.taxonomy"),
                        flattened_fields={
                            "classify_target":
                            DummyField(name="classify_target")
                        })
        },
        visible_resources={},
    )

    schema = DummyApiSchema(
        services={"animalia.mollusca.v1.Mollusc": service},
        naming=api_naming,
    )

    sample = {
        "service":
        "animalia.mollusca.v1.Mollusc",
        "rpc":
        "Classify",
        "id":
        "mollusc_classify_sync",
        "description":
        "Determine the full taxonomy of input mollusc",
        "request": [{
            "field": "classify_target.video",
            "value": "path/to/mollusc/video.mkv",
            "input_parameter": "video",
            "value_is_file": True
        }, {
            "field": "classify_target.location_annotation",
            "value": "New Zealand",
            "input_parameter": "location"
        }],
        "response": [{
            "print": ['Mollusc is a "%s"', "$resp.taxonomy"]
        }]
    }

    sample_str = samplegen.generate_sample(
        sample, schema, env.get_template('examples/sample.py.j2'))

    assert sample_str == golden_snippet("sample_basic.py")
예제 #10
0
def test_address_subpackage_empty():
    addr = metadata.Address(
        package=('foo', 'bar', 'baz', 'v1'),
        api_naming=naming.NewNaming(proto_package='foo.bar.baz.v1'),
    )
    assert addr.subpackage == ()
예제 #11
0
def test_address_subpackage_no_version():
    addr = metadata.Address(
        package=('foo', 'bar', 'baz', 'spam', 'eggs'),
        api_naming=naming.NewNaming(proto_package='foo.bar.baz'),
    )
    assert addr.subpackage == ('spam', 'eggs')
def test_generate_sample_basic():
    # Note: the sample integration tests are needfully large
    # and difficult to eyeball parse. They are intended to be integration tests
    # that catch errors in behavior that is emergent from combining smaller features
    # or in features that are sufficiently small and trivial that it doesn't make sense
    # to have standalone tests.

    classify_target_field = DummyField(
        name="classify_target",
        type=DummyMessageTypePB(name="ClassifyTarget"),
        message=DummyMessage(
            type="CLASSIFY TYPE",
            fields={
                "video": DummyField(
                    type=DummyMessageTypePB(name="Video"),
                    message=DummyMessage(type="VIDEO TYPE"),
                ),
                "location_annotation": DummyField(
                    type=DummyMessageTypePB(name="Location"),
                    message=DummyMessage(type="LOCATION TYPE"),
                )
            },
        ),
        ident=DummyIdent(sphinx="molluscs_v1.ClassifyTarget")
    )

    input_type = DummyMessage(
        type="REQUEST TYPE",
        fields={
            "classify_target": classify_target_field
        },
        ident=DummyIdent(name="molluscs.v1.ClassifyRequest",
                         sphinx="molluscs_v1.classify_request")
    )

    output_type = DummyMessage(
        type="RESPONSE TYPE",
        fields={
            "classification": DummyField(
                type=DummyMessageTypePB(name="Classification"),
            )
        },
        ident=DummyIdent(sphinx="molluscs_v1.classification")
    )

    api_naming = naming.NewNaming(
        name="MolluscClient", namespace=("molluscs", "v1"))
    service = wrappers.Service(
        service_pb=namedtuple('service_pb', ['name'])('MolluscService'),
        methods={
            "Classify": DummyMethod(
                name="Classify",
                input=input_type,
                output=message_factory("$resp.taxonomy"),
                client_output=output_type,
                flattened_fields={
                    "classify_target": classify_target_field
                }
            )
        },
        visible_resources={},
    )

    schema = DummyApiSchema(
        services={"animalia.mollusca.v1.Mollusc": service},
        naming=api_naming,
    )

    sample = {"service": "animalia.mollusca.v1.Mollusc",
              "region_tag": "molluscs_generated_molluscs_v1_Mollusc_Classify_sync",
              "rpc": "Classify",
              "id": "mollusc_classify_sync",
              "description": "Determine the full taxonomy of input mollusc",
              "request": [
                  {"field": "classify_target.video",
                   "value": "path/to/mollusc/video.mkv",
                   "input_parameter": "video",
                   "value_is_file": True},
                  {"field": "classify_target.location_annotation",
                   "value": "New Zealand",
                   "input_parameter": "location"}
              ],
              "response": [{"print": ['Mollusc is a "%s"', "$resp.taxonomy"]}]}

    sample_str, metadata = samplegen.generate_sample(
        sample,
        schema,
        env.get_template('examples/sample.py.j2')
    )

    assert sample_str == golden_snippet("sample_basic.py")

    assert json_format.MessageToDict(metadata) == {
        'regionTag': 'molluscs_generated_molluscs_v1_Mollusc_Classify_sync',
        'description': 'Sample for Classify',
        'language': 'PYTHON',
        'clientMethod': {
            'shortName': 'classify',
            'fullName': 'molluscs.v1.molluscclient.MolluscServiceClient.classify',
            'parameters': [
                {'type': 'molluscs_v1.classify_request', 'name': 'request'},
                {'type': 'molluscs_v1.ClassifyTarget', 'name': 'classify_target'},
                {'type': 'google.api_core.retry.Retry', 'name': 'retry'},
                {'type': 'float', 'name': 'timeout'},
                {'type': 'Sequence[Tuple[str, str]', 'name': 'metadata'}
            ],
            'resultType': 'molluscs_v1.classification',
            'client': {
                'shortName': 'MolluscServiceClient',
                'fullName': 'molluscs.v1.molluscclient.MolluscServiceClient'
            },
            'method': {
                'shortName': 'Classify',
                'fullName': '.MolluscService.Classify',
                'service': {'shortName': 'MolluscService', 'fullName': '.MolluscService'}}
            },
        'canonical': True,
        'origin': 'API_DEFINITION'
    }
def test_generate_sample_void_method():
    classify_target_field = DummyField(
        name="classify_target",
        type=DummyMessageTypePB(name="ClassifyTarget"),
        message=DummyMessage(
            type="CLASSIFY TYPE",
            fields={
                "video": DummyField(
                    type=DummyMessageTypePB(name="Video"),
                    message=DummyMessage(type="VIDEO TYPE"),
                ),
                "location_annotation": DummyField(
                    type=DummyMessageTypePB(name="Location"),
                    message=DummyMessage(type="LOCATION TYPE"),
                )
            },
        ),
        ident=DummyIdent(sphinx="molluscs_v1.ClassifyTarget")
    )

    input_type = DummyMessage(
        type="REQUEST TYPE",
        fields={
            "classify_target": classify_target_field
        },
        ident=DummyIdent(name="molluscs.v1.ClassifyRequest",
                         sphinx="molluscs_v1.classify_request")
    )

    api_naming = naming.NewNaming(
        name="MolluscClient", namespace=("molluscs", "v1"))
    service = wrappers.Service(
        service_pb=namedtuple('service_pb', ['name'])('MolluscService'),
        methods={
            "Classify": DummyMethod(
                name="Classify",
                client_output=DummyIdent(name="classify", sphinx="classify"),
                void=True,
                input=input_type,
                output=message_factory("$resp.taxonomy"),
                flattened_fields={
                    "classify_target": classify_target_field,
                }
            )
        },
        visible_resources={},
    )

    schema = DummyApiSchema(
        services={"animalia.mollusca.v1.Mollusc": service},
        naming=api_naming,
    )

    sample = {"service": "animalia.mollusca.v1.Mollusc",
              "region_tag": "molluscs_generated_molluscs_v1_Mollusc_Classify_sync",
              "rpc": "Classify",
              "id": "mollusc_classify_sync",
              "description": "Determine the full taxonomy of input mollusc",
              "request": [
                  {"field": "classify_target.video",
                   "value": "path/to/mollusc/video.mkv",
                   "input_parameter": "video",
                   "value_is_file": True},
                  {"field": "classify_target.location_annotation",
                   "value": "New Zealand",
                   "input_parameter": "location"}
              ]}

    sample_str, metadata = samplegen.generate_sample(
        sample,
        schema,
        env.get_template('examples/sample.py.j2')
    )

    assert sample_str == golden_snippet("sample_basic_void_method.py")

    assert json_format.MessageToDict(metadata) == {
        'regionTag': 'molluscs_generated_molluscs_v1_Mollusc_Classify_sync',
        'description': 'Sample for Classify',
        'language': 'PYTHON',
        'clientMethod': {
            'shortName': 'classify',
            'fullName': 'molluscs.v1.molluscclient.MolluscServiceClient.classify',
            'parameters': [
                {'type': 'molluscs_v1.classify_request', 'name': 'request'},
                {'type': 'molluscs_v1.ClassifyTarget', 'name': 'classify_target'},
                {'type': 'google.api_core.retry.Retry', 'name': 'retry'},
                {'type': 'float', 'name': 'timeout'},
                {'type': 'Sequence[Tuple[str, str]', 'name': 'metadata'}
            ],
            'client': {
                'shortName': 'MolluscServiceClient',
                'fullName': 'molluscs.v1.molluscclient.MolluscServiceClient'
            },
            'method': {
                'shortName': 'Classify',
                'fullName': '.MolluscService.Classify',
                'service': {'shortName': 'MolluscService', 'fullName': '.MolluscService'}
            }
        },
        'canonical': True,
        'origin': 'API_DEFINITION'
    }
def test_dont_generate_in_code_samples(mock_gmtime, mock_generate_sample, fs):
    # These time values are nothing special,
    # they just need to be deterministic.
    returner = mock.MagicMock()
    returner.tm_year = 2112
    returner.tm_mon = 6
    returner.tm_mday = 1
    returner.tm_hour = 13
    returner.tm_min = 13
    returner.tm_sec = 13
    mock_gmtime.return_value = returner

    config_fpath = "samples.yaml"
    fs.create_file(
        config_fpath,
        contents=dedent("""
            type: com.google.api.codegen.samplegen.v1p2.SampleConfigProto
            schema_version: 1.2.0
            samples:
            - id: squid_sample
              rpc: IdentifyMollusc
              service: Mollusc.v1.Mollusc
              sample_type:
              - standalone
              - incode/SQUID
            - id: clam_sample
              rpc: IdentifyMollusc
              service: Mollusc.v1.Mollusc
              sample_type:
              - incode/CLAM
            - id: whelk_sample
              rpc: IdentifyMollusc
              service: Mollusc.v1.Mollusc
              sample_type:
              - standalone
            - id: octopus_sample
              rpc: IdentifyMollusc
              service: Mollusc.v1.Mollusc
            """),
    )

    generator = make_generator(f"samples={config_fpath}")
    generator._env.loader = jinja2.DictLoader({"sample.py.j2": ""})
    api_schema = make_api(
        make_proto(
            descriptor_pb2.FileDescriptorProto(
                name="mollusc.proto",
                package="Mollusc.v1",
                service=[
                    descriptor_pb2.ServiceDescriptorProto(name="Mollusc")
                ],
            ), ),
        naming=naming.NewNaming(name="Mollusc", version="v6"),
    )

    # Note that we do NOT expect a clam sample.
    # There are four tests going on:
    # 1) Just an explicit standalone sample type.
    # 2) Multiple sample types, one of which is standalone.
    # 3) Explicit sample types but NO standalone sample type.
    # 4) Implicit standalone sample type.
    expected = CodeGeneratorResponse(file=[
        CodeGeneratorResponse.File(
            name="samples/generated_samples/squid_sample.py",
            content="\n",
        ),
        CodeGeneratorResponse.File(
            name="samples/generated_samples/whelk_sample.py",
            content="\n",
        ),
        CodeGeneratorResponse.File(
            name="samples/generated_samples/octopus_sample.py",
            content="\n",
        ),
        # TODO(busunkim): Re-enable manifest generation once metadata
        # format has been formalized.
        # https://docs.google.com/document/d/1ghBam8vMj3xdoe4xfXhzVcOAIwrkbTpkMLgKc9RPD9k/edit#heading=h.sakzausv6hue
        # CodeGeneratorResponse.File(
        #     name="samples/generated_samples/mollusc.v6.python.21120601.131313.manifest.yaml",
        #     content=dedent(
        #         """                ---
        #     type: manifest/samples
        #     schema_version: 3
        #     python: &python
        #       environment: python
        #       bin: python3
        #       base_path: samples
        #       invocation: \'{bin} {path} @args\'
        #     samples:
        #     - <<: *python
        #       sample: squid_sample
        #       path: \'{base_path}/squid_sample.py\'
        #     - <<: *python
        #       sample: whelk_sample
        #       path: \'{base_path}/whelk_sample.py\'
        #     - <<: *python
        #       sample: octopus_sample
        #       path: \'{base_path}/octopus_sample.py\'
        #     """
        #     ),
        # ),
    ])
    expected.supported_features |= CodeGeneratorResponse.Feature.FEATURE_PROTO3_OPTIONAL

    actual = generator.get_response(api_schema=api_schema,
                                    opts=Options.build(""))
    assert actual == expected
예제 #15
0
def test_samplegen_config_to_output_files(
    mock_gmtime,
    mock_generate_sample,
    fs,
):
    # These time values are nothing special,
    # they just need to be deterministic.
    returner = mock.MagicMock()
    returner.tm_year = 2112
    returner.tm_mon = 6
    returner.tm_mday = 1
    returner.tm_hour = 13
    returner.tm_min = 13
    returner.tm_sec = 13
    mock_gmtime.return_value = returner

    fs.create_file(
        "samples.yaml",
        contents=dedent("""
            ---
            type: com.google.api.codegen.samplegen.v1p2.SampleConfigProto
            schema_version: 1.2.0
            samples:
            - id: squid_sample
              region_tag: humboldt_tag
              rpc: get_squid_streaming
            - region_tag: clam_sample
              rpc: get_clam
            """),
    )

    g = generator.Generator(Options.build("samples=samples.yaml", ))
    # Need to have the sample template visible to the generator.
    g._env.loader = jinja2.DictLoader({"sample.py.j2": ""})

    api_schema = make_api(
        naming=naming.NewNaming(name="Mollusc", version="v6"))
    actual_response = g.get_response(api_schema, opts=Options.build(""))
    expected_response = CodeGeneratorResponse(file=[
        CodeGeneratorResponse.File(
            name="samples/squid_sample.py",
            content="\n",
        ),
        CodeGeneratorResponse.File(
            name="samples/clam_sample.py",
            content="\n",
        ),
        CodeGeneratorResponse.File(
            name="samples/mollusc.v6.python.21120601.131313.manifest.yaml",
            content=dedent("""\
                ---
                type: manifest/samples
                schema_version: 3
                python: &python
                  environment: python
                  bin: python3
                  base_path: samples
                  invocation: '{bin} {path} @args'
                samples:
                - <<: *python
                  sample: squid_sample
                  path: '{base_path}/squid_sample.py'
                  region_tag: humboldt_tag
                - <<: *python
                  sample: clam_sample
                  path: '{base_path}/clam_sample.py'
                  region_tag: clam_sample
                """),
        ),
    ])
    expected_response.supported_features |= (
        CodeGeneratorResponse.Feature.FEATURE_PROTO3_OPTIONAL)

    assert actual_response == expected_response
def make_naming(**kwargs) -> naming.Naming:
    kwargs.setdefault("name", "Hatstand")
    kwargs.setdefault("namespace", ("Google", "Cloud"))
    kwargs.setdefault("version", "v1")
    kwargs.setdefault("product_name", "Hatstand")
    return naming.NewNaming(**kwargs)
예제 #17
0
def test_samplegen_id_disambiguation(mock_gmtime, mock_generate_sample, fs):
    # These time values are nothing special,
    # they just need to be deterministic.
    returner = mock.MagicMock()
    returner.tm_year = 2112
    returner.tm_mon = 6
    returner.tm_mday = 1
    returner.tm_hour = 13
    returner.tm_min = 13
    returner.tm_sec = 13
    mock_gmtime.return_value = returner

    # Note: The first two samples will have the same nominal ID, the first by
    #       explicit naming and the second by falling back to the region_tag.
    #       The third has no id of any kind, so the generator is required to make a
    #       unique ID for it.
    fs.create_file(
        "samples.yaml",
        contents=dedent("""
            ---
            type: com.google.api.codegen.samplegen.v1p2.SampleConfigProto
            schema_version: 1.2.0
            samples:
            - id: squid_sample
              region_tag: humboldt_tag
              rpc: get_squid_streaming
            # Note that this region tag collides with the id of the previous sample.
            - region_tag: squid_sample
              rpc: get_squid_streaming
            # No id or region tag.
            - rpc: get_squid_streaming
            """),
    )
    g = generator.Generator(Options.build("samples=samples.yaml"))
    # Need to have the sample template visible to the generator.
    g._env.loader = jinja2.DictLoader({"sample.py.j2": ""})

    api_schema = make_api(
        naming=naming.NewNaming(name="Mollusc", version="v6"))
    actual_response = g.get_response(api_schema, opts=Options.build(""))
    expected_response = CodeGeneratorResponse(file=[
        CodeGeneratorResponse.File(
            name="samples/squid_sample_91a465c6.py",
            content="\n",
        ),
        CodeGeneratorResponse.File(
            name="samples/squid_sample_55051b38.py",
            content="\n",
        ),
        CodeGeneratorResponse.File(
            name="samples/157884ee.py",
            content="\n",
        ),
        CodeGeneratorResponse.File(
            name="samples/mollusc.v6.python.21120601.131313.manifest.yaml",
            content=dedent("""\
                ---
                type: manifest/samples
                schema_version: 3
                python: &python
                  environment: python
                  bin: python3
                  base_path: samples
                  invocation: '{bin} {path} @args'
                samples:
                - <<: *python
                  sample: squid_sample_91a465c6
                  path: '{base_path}/squid_sample_91a465c6.py'
                  region_tag: humboldt_tag
                - <<: *python
                  sample: squid_sample_55051b38
                  path: '{base_path}/squid_sample_55051b38.py'
                  region_tag: squid_sample
                - <<: *python
                  sample: 157884ee
                  path: '{base_path}/157884ee.py'
                """),
        ),
    ])
    expected_response.supported_features |= (
        CodeGeneratorResponse.Feature.FEATURE_PROTO3_OPTIONAL)

    assert actual_response == expected_response
예제 #18
0
def test_generate_sample_void_method():
    input_type = DummyMessage(
        type="REQUEST TYPE",
        fields={
            "classify_target":
            DummyField(message=DummyMessage(
                type="CLASSIFY TYPE",
                fields={
                    "video":
                    DummyField(message=DummyMessage(type="VIDEO TYPE"), ),
                    "location_annotation":
                    DummyField(message=DummyMessage(type="LOCATION TYPE"), )
                },
            ))
        },
        ident=DummyIdent(name="molluscs.v1.ClassifyRequest"))

    api_naming = naming.NewNaming(name="MolluscClient",
                                  namespace=("molluscs", "v1"))
    service = wrappers.Service(
        service_pb=namedtuple('service_pb', ['name'])('MolluscService'),
        methods={
            "Classify":
            DummyMethod(void=True,
                        input=input_type,
                        output=message_factory("$resp.taxonomy"),
                        flattened_fields={
                            "classify_target":
                            DummyField(name="classify_target")
                        })
        },
        visible_resources={},
    )

    schema = DummyApiSchema(
        services={"animalia.mollusca.v1.Mollusc": service},
        naming=api_naming,
    )

    sample = {
        "service":
        "animalia.mollusca.v1.Mollusc",
        "rpc":
        "Classify",
        "id":
        "mollusc_classify_sync",
        "description":
        "Determine the full taxonomy of input mollusc",
        "request": [{
            "field": "classify_target.video",
            "value": "path/to/mollusc/video.mkv",
            "input_parameter": "video",
            "value_is_file": True
        }, {
            "field": "classify_target.location_annotation",
            "value": "New Zealand",
            "input_parameter": "location"
        }]
    }

    sample_str = samplegen.generate_sample(
        sample, schema, env.get_template('examples/sample.py.j2'))

    assert sample_str == golden_snippet("sample_basic_void_method.py")
예제 #19
0
def make_naming(**kwargs) -> naming.Naming:
    kwargs.setdefault('name', 'Hatstand')
    kwargs.setdefault('namespace', ('Google', 'Cloud'))
    kwargs.setdefault('version', 'v1')
    kwargs.setdefault('product_name', 'Hatstand')
    return naming.NewNaming(**kwargs)
예제 #20
0
def test_generate_sample_basic():
    # Note: the sample integration tests are needfully large
    # and difficult to eyeball parse. They are intended to be integration tests
    # that catch errors in behavior that is emergent from combining smaller features
    # or in features that are sufficiently small and trivial that it doesn't make sense
    # to have standalone tests.
    input_type = DummyMessage(
        type="REQUEST TYPE",
        fields={
            "classify_target":
            DummyField(message=DummyMessage(
                type="CLASSIFY TYPE",
                fields={
                    "video":
                    DummyField(message=DummyMessage(type="VIDEO TYPE"), ),
                    "location_annotation":
                    DummyField(message=DummyMessage(type="LOCATION TYPE"), )
                },
            ))
        })

    api_naming = naming.NewNaming(name="MolluscClient",
                                  namespace=("molluscs", "v1"))
    service = wrappers.Service(
        service_pb=namedtuple('service_pb', ['name'])('MolluscService'),
        methods={
            "Classify":
            DummyMethod(input=input_type,
                        output=message_factory("$resp.taxonomy"),
                        flattened_fields={
                            "classify_target":
                            DummyField(name="classify_target")
                        })
        },
        visible_resources={},
    )

    schema = DummyApiSchema(
        services={"animalia.mollusca.v1.Mollusc": service},
        naming=api_naming,
    )

    sample = {
        "service":
        "animalia.mollusca.v1.Mollusc",
        "rpc":
        "Classify",
        "id":
        "mollusc_classify_sync",
        "description":
        "Determine the full taxonomy of input mollusc",
        "request": [{
            "field": "classify_target.video",
            "value": "path/to/mollusc/video.mkv",
            "input_parameter": "video",
            "value_is_file": True
        }, {
            "field": "classify_target.location_annotation",
            "value": "New Zealand",
            "input_parameter": "location"
        }],
        "response": [{
            "print": ['Mollusc is a "%s"', "$resp.taxonomy"]
        }]
    }

    sample_str = samplegen.generate_sample(
        sample, schema, env.get_template('examples/sample.py.j2'))

    sample_id = ("mollusc_classify_sync")
    expected_str = '''# -*- coding: utf-8 -*-
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# DO NOT EDIT! This is a generated sample ("request",  "%s")
#
# To install the latest published package dependency, execute the following:
#   pip3 install molluscs-v1-molluscclient


# [START %s]
from google import auth
from google.auth import credentials
from molluscs.v1.molluscclient.services.mollusc_service import MolluscServiceClient

def sample_classify(video, location):
    """Determine the full taxonomy of input mollusc"""

    client = MolluscServiceClient(
        credentials=credentials.AnonymousCredentials(),
        transport="grpc",
    )

    classify_target = {}
    # video = "path/to/mollusc/video.mkv"
    with open(video, "rb") as f:
        classify_target["video"] = f.read()

    # location = "New Zealand"
    classify_target["location_annotation"] = location

 
 
    response = client.classify(classify_target=classify_target)
    print("Mollusc is a \\"{}\\"".format(response.taxonomy))
 

# [END %s]

def main():
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument("--video",
                        type=str,
                        default="path/to/mollusc/video.mkv")
    parser.add_argument("--location",
                        type=str,
                        default="New Zealand")
    args = parser.parse_args()

    sample_classify(args.video, args.location)


if __name__ == "__main__":
    main()
''' % (sample_id, sample_id, sample_id)

    assert sample_str == expected_str
def test_dont_generate_in_code_samples(mock_gmtime, mock_generate_sample, fs):
    # These time values are nothing special,
    # they just need to be deterministic.
    returner = mock.MagicMock()
    returner.tm_year = 2112
    returner.tm_mon = 6
    returner.tm_mday = 1
    returner.tm_hour = 13
    returner.tm_min = 13
    returner.tm_sec = 13
    mock_gmtime.return_value = returner

    config_fpath = "samples.yaml"
    fs.create_file(config_fpath,
                   contents=dedent('''
            type: com.google.api.codegen.samplegen.v1p2.SampleConfigProto
            schema_version: 1.2.0
            samples:
            - id: squid_sample
              rpc: IdentifyMollusc
              service: Mollusc.v1.Mollusc
              sample_type:
              - standalone
              - incode/SQUID
            - id: clam_sample
              rpc: IdentifyMollusc
              service: Mollusc.v1.Mollusc
              sample_type:
              - incode/CLAM
            - id: whelk_sample
              rpc: IdentifyMollusc
              service: Mollusc.v1.Mollusc
              sample_type:
              - standalone
            - id: octopus_sample
              rpc: IdentifyMollusc
              service: Mollusc.v1.Mollusc
            '''))

    generator = make_generator(f'samples={config_fpath}')
    generator._env.loader = jinja2.DictLoader({'sample.py.j2': ''})
    api_schema = make_api(
        make_proto(
            descriptor_pb2.FileDescriptorProto(
                name='mollusc.proto',
                package='Mollusc.v1',
                service=[
                    descriptor_pb2.ServiceDescriptorProto(name='Mollusc')
                ],
            ), ),
        naming=naming.NewNaming(name='Mollusc', version='v6'),
    )

    # Note that we do NOT expect a clam sample.
    # There are four tests going on:
    # 1) Just an explicit standalone sample type.
    # 2) Multiple sample types, one of which is standalone.
    # 3) Explicit sample types but NO standalone sample type.
    # 4) Implicit standalone sample type.
    expected = CodeGeneratorResponse(file=[
        CodeGeneratorResponse.File(
            name="samples/squid_sample.py",
            content="\n",
        ),
        CodeGeneratorResponse.File(
            name="samples/whelk_sample.py",
            content="\n",
        ),
        CodeGeneratorResponse.File(
            name="samples/octopus_sample.py",
            content="\n",
        ),
        CodeGeneratorResponse.File(
            name="samples/mollusc.v6.python.21120601.131313.manifest.yaml",
            content=dedent("""                ---
                type: manifest/samples
                schema_version: 3
                python: &python
                  environment: python
                  bin: python3
                  base_path: samples
                  invocation: \'{bin} {path} @args\'
                samples:
                - <<: *python
                  sample: squid_sample
                  path: \'{base_path}/squid_sample.py\'
                - <<: *python
                  sample: whelk_sample
                  path: \'{base_path}/whelk_sample.py\'
                - <<: *python
                  sample: octopus_sample
                  path: \'{base_path}/octopus_sample.py\'
                """))
    ])
    actual = generator.get_response(api_schema=api_schema,
                                    opts=options.Options.build(''))
    assert actual == expected