def test_generate_sample_config_partial_config(fs):
    expected_path = 'sample.yaml'
    fs.create_file(
        expected_path,
        # Note the typo: SampleConfigPronto
        contents=dedent(
            '''
            ---
            type: com.google.api.codegen.SampleConfigPronto
            schema_version: 1.2.0
            samples:
            - service: google.cloud.language.v1.LanguageService
            ---
            # Note: this one IS a valid config
            type: com.google.api.codegen.SampleConfigProto
            schema_version: 1.2.0
            samples:
            - service: google.cloud.language.v1.LanguageService
            '''
        )
    )
    expected_paths = [expected_path]

    actual_paths = list(gapic_utils.generate_all_sample_fpaths(expected_path))

    assert actual_paths == expected_paths
예제 #2
0
def test_generate_sample_config_fpaths(fs):
    expected_path = 'cfgs/sample_config.yaml'
    fs.create_file(expected_path,
                   contents=dedent('''
            ---
            type: com.google.api.codegen.samplegen.v1p2.SampleConfigProto
            schema_version: 1.2.0
            samples:
            - service: google.cloud.language.v1.LanguageService
            '''))
    actual_paths = list(gapic_utils.generate_all_sample_fpaths(expected_path))

    assert actual_paths == [expected_path]
예제 #3
0
def test_generate_sample_config_fpaths_bad_contents(
    fs,
    # Note the typo: SampleConfigPronto
    contents=dedent('''
            ---
            type: com.google.api.codegen.SampleConfigPronto
            schema_version: 1.2.0
            samples:
            - service: google.cloud.language.v1.LanguageService
            ''')):
    expected_path = 'cfgs/sample_config.yaml'
    fs.create_file(expected_path, contents=contents)

    with pytest.raises(types.InvalidConfig):
        list(gapic_utils.generate_all_sample_fpaths(expected_path))
예제 #4
0
    def build(cls, opt_string: str) -> 'Options':
        """Build an Options instance based on a protoc opt string.

        Args:
            opt_string (str): A string, as passed from the protoc interface
                (through ``--python_gapic_opt``). If multiple options are
                passed, then protoc joins the values with ``,``.
                By convention, we use ``key=value`` strings for such
                options, with an absent value defaulting to ``True``.

        Returns:
            ~.Options: The Options instance.

        Raises:
            gapic.samplegen_utils.types.InvalidConfig:
                        If paths to files or directories that should contain sample
                        configs are passed and no valid sample config is found.
        """
        # Parse out every option beginning with `python-gapic`
        opts: DefaultDict[str, List[str]] = defaultdict(list)
        for opt in opt_string.split(','):
            # Parse out the key and value.
            value = 'true'
            if '=' in opt:
                opt, value = opt.split('=')

            if opt == cls.SAMPLES_OPT:
                opts[cls.SAMPLES_OPT].append(value)

            # Throw away other options not meant for us.
            if not opt.startswith(cls.PYTHON_GAPIC_PREFIX):
                continue

            # Set the option, using a key with the "python-gapic-" prefix
            # stripped.
            #
            # Just assume everything is a list at this point, and the
            # final instantiation step can de-list-ify where appropriate.
            opts[opt[len(cls.PYTHON_GAPIC_PREFIX):]].append(value)

        # If templates are specified, one of the specified directories
        # may be our default; perform that replacement.
        templates = opts.pop('templates', ['DEFAULT'])
        while 'DEFAULT' in templates:
            templates[templates.index('DEFAULT')] = os.path.realpath(
                os.path.join(os.path.dirname(__file__), '..', 'templates'), )

        # Build the options instance.
        sample_paths = opts.pop(cls.SAMPLES_OPT, [])
        answer = Options(
            name=opts.pop('name', ['']).pop(),
            namespace=tuple(opts.pop('namespace', [])),
            templates=tuple(os.path.expanduser(i) for i in templates),
            sample_configs=tuple(
                cfg_path for s in sample_paths
                for cfg_path in samplegen_utils.generate_all_sample_fpaths(s)),
        )

        # Note: if we ever need to recursively check directories for sample configs,
        # check that at least _one_ config is read in.

        # If there are any options remaining, then we failed to recognize
        # them -- complain.
        for key in opts.keys():
            warnings.warn(f'Unrecognized option: `python-gapic-{key}`.')

        # Done; return the built options.
        return answer
예제 #5
0
    def build(cls, opt_string: str) -> 'Options':
        """Build an Options instance based on a protoc opt string.

        Args:
            opt_string (str): A string, as passed from the protoc interface
                (through ``--python_gapic_opt``). If multiple options are
                passed, then protoc joins the values with ``,``.
                By convention, we use ``key=value`` strings for such
                options, with an absent value defaulting to ``True``.

        Returns:
            ~.Options: The Options instance.

        Raises:
            gapic.samplegen_utils.types.InvalidConfig:
                If paths to files or directories that should contain sample
                configs are passed and no valid sample config is found.
        """
        # Parse out every option beginning with `python-gapic`
        opts: DefaultDict[str, List[str]] = defaultdict(list)
        for opt in opt_string.split(','):
            opt = opt.strip()
            # Parse out the key and value.
            value = 'true'
            if '=' in opt:
                opt, value = opt.split('=')

            # Save known, expected keys.
            if opt in cls.OPT_FLAGS:
                opts[opt].append(value)

            # Throw away other options not meant for us.
            if not opt.startswith(cls.PYTHON_GAPIC_PREFIX):
                continue

            # Set the option, using a key with the "python-gapic-" prefix
            # stripped.
            #
            # Just assume everything is a list at this point, and the
            # final instantiation step can de-list-ify where appropriate.
            opts[opt[len(cls.PYTHON_GAPIC_PREFIX):]].append(value)

        # If templates are specified, one of the specified directories
        # may be our default; perform that replacement.
        default_token = 'DEFAULT'
        templates = opts.pop('templates', [default_token])
        pwd = path.join(path.dirname(__file__), '..')
        default_path = path.realpath(path.join(pwd, 'templates'))

        def tweak_path(p):
            if p == default_token:
                return default_path

            if path.isabs(p):
                return path.normpath(p)

            return path.normpath(path.join(pwd, p))

        templates = [tweak_path(p) for p in templates]

        retry_cfg = None
        retry_paths = opts.pop('retry-config', None)
        if retry_paths:
            # Just use the last config specified.
            with open(retry_paths[-1]) as f:
                retry_cfg = json.load(f)

        # Build the options instance.
        sample_paths = opts.pop('samples', [])
        answer = Options(
            name=opts.pop('name', ['']).pop(),
            namespace=tuple(opts.pop('namespace', [])),
            retry=retry_cfg,
            sample_configs=tuple(
                cfg_path for s in sample_paths
                for cfg_path in samplegen_utils.generate_all_sample_fpaths(s)),
            templates=tuple(path.expanduser(i) for i in templates),
            lazy_import=bool(opts.pop('lazy-import', False)),
            old_naming=bool(opts.pop('old-naming', False)),
        )

        # Note: if we ever need to recursively check directories for sample
        # configs, check that at least _one_ config is read in.

        # If there are any options remaining, then we failed to recognize
        # them -- complain.
        for key in opts.keys():
            warnings.warn(f'Unrecognized option: `python-gapic-{key}`.')

        # Done; return the built options.
        return answer
예제 #6
0
def test_generate_sample_config_fpaths_no_such_file(fs):
    with pytest.raises(types.InvalidConfig):
        list(gapic_utils.generate_all_sample_fpaths('cfgs/sample_config.yaml'))
예제 #7
0
def test_generate_sample_config_fpaths_not_yaml(fs):
    expected_path = 'cfgs/sample_config.not_yaml'
    fs.create_file(expected_path)

    with pytest.raises(types.InvalidConfig):
        list(gapic_utils.generate_all_sample_fpaths(expected_path))
예제 #8
0
    def build(cls, opt_string: str) -> 'Options':
        """Build an Options instance based on a protoc opt string.

        Args:
            opt_string (str): A string, as passed from the protoc interface
                (through ``--python_gapic_opt``). If multiple options are
                passed, then protoc joins the values with ``,``.
                By convention, we use ``key=value`` strings for such
                options, with an absent value defaulting to ``True``.

        Returns:
            ~.Options: The Options instance.

        Raises:
            gapic.samplegen_utils.types.InvalidConfig:
                If paths to files or directories that should contain sample
                configs are passed and no valid sample config is found.
        """
        # Parse out every option beginning with `python-gapic`
        opts: DefaultDict[str, List[str]] = defaultdict(list)
        for opt in opt_string.split(','):
            opt = opt.strip()
            # Parse out the key and value.
            value = 'true'
            if '=' in opt:
                opt, value = opt.split('=')

            # Save known, expected keys.
            if opt in cls.OPT_FLAGS:
                opts[opt].append(value)

            # Throw away other options not meant for us.
            if not opt.startswith(cls.PYTHON_GAPIC_PREFIX):
                continue

            # Set the option, using a key with the "python-gapic-" prefix
            # stripped.
            #
            # Just assume everything is a list at this point, and the
            # final instantiation step can de-list-ify where appropriate.
            opts[opt[len(cls.PYTHON_GAPIC_PREFIX):]].append(value)

        # If templates are specified, one of the specified directories
        # may be our default; perform that replacement.
        default_token = 'DEFAULT'
        templates = opts.pop('templates', [default_token])
        pwd = path.join(path.dirname(__file__), '..')
        default_path = path.realpath(path.join(pwd, 'templates'))

        def tweak_path(p):
            if p == default_token:
                return default_path

            if path.isabs(p):
                return path.normpath(p)

            return path.normpath(path.join(pwd, p))

        templates = [tweak_path(p) for p in templates]

        retry_cfg = None
        retry_paths = opts.pop('retry-config', None)
        if retry_paths:
            # Just use the last config specified.
            with open(retry_paths[-1]) as f:
                retry_cfg = json.load(f)

        service_yaml_config = {}
        service_yaml_paths = opts.pop('service-yaml', None)
        if service_yaml_paths:
            # Just use the last file specified.
            with open(service_yaml_paths[-1]) as f:
                service_yaml_config = yaml.load(f, Loader=yaml.Loader)
        # The yaml service files typically have this field,
        # but it is not a field in the gogle.api.Service proto.
        service_yaml_config.pop('type', None)

        # Build the options instance.
        sample_paths = opts.pop('samples', [])

        # autogen-snippets is True by default, so make sure users can disable
        # by passing `autogen-snippets=false`
        autogen_snippets = opts.pop("autogen-snippets",
                                    ["True"])[0] in ("True", "true", "T", "t",
                                                     "TRUE")

        # NOTE: Snippets are not currently correct for the alternative (Ads) templates
        # so always disable snippetgen in that case
        # https://github.com/googleapis/gapic-generator-python/issues/1052
        old_naming = bool(opts.pop('old-naming', False))
        if old_naming:
            autogen_snippets = False

        answer = Options(
            name=opts.pop('name', ['']).pop(),
            namespace=tuple(opts.pop('namespace', [])),
            warehouse_package_name=opts.pop('warehouse-package-name',
                                            ['']).pop(),
            retry=retry_cfg,
            sample_configs=tuple(
                cfg_path for s in sample_paths
                for cfg_path in samplegen_utils.generate_all_sample_fpaths(s)),
            autogen_snippets=autogen_snippets,
            templates=tuple(path.expanduser(i) for i in templates),
            lazy_import=bool(opts.pop('lazy-import', False)),
            old_naming=old_naming,
            add_iam_methods=bool(opts.pop('add-iam-methods', False)),
            metadata=bool(opts.pop('metadata', False)),
            # transport should include desired transports delimited by '+', e.g. transport='grpc+rest'
            transport=opts.pop('transport', ['grpc'])[0].split('+'),
            service_yaml_config=service_yaml_config,
        )

        # Note: if we ever need to recursively check directories for sample
        # configs, check that at least _one_ config is read in.

        # If there are any options remaining, then we failed to recognize
        # them -- complain.
        for key in opts.keys():
            warnings.warn(f'Unrecognized option: `python-gapic-{key}`.')

        # Done; return the built options.
        return answer