예제 #1
0
    def test_with_unordered_argument(self):
        string = metrics.stringify({
            'gl-python': platform.python_version(),
            'gapic': '1.0.0',
            'gax': gax.__version__,
            'grpc': GRPC_VERSION,
        })

        # Assert that each section of the string is present, but
        # ignore ordering.
        self.assertIn('gl-python/%s' % platform.python_version(), string)
        self.assertIn('gapic/1.0.0', string)
        self.assertIn('gax/%s' % gax.__version__, string)
        self.assertIn('grpc/%s' % GRPC_VERSION, string)
예제 #2
0
    def test_with_ordered_argument(self):
        headers = collections.OrderedDict()
        headers['gl-python'] = platform.python_version()
        headers['gapic'] = '1.0.0'
        headers['gax'] = gax.__version__
        headers['grpc'] = GRPC_VERSION
        string = metrics.stringify(headers)

        # Check for the exact string, order and all.
        expected = 'gl-python/{python} gapic/{gapic} gax/{gax} grpc/{grpc}'
        self.assertEqual(
            string,
            expected.format(
                gapic='1.0.0',
                gax=gax.__version__,
                grpc=GRPC_VERSION,
                python=platform.python_version(),
            ))
예제 #3
0
DATA_API_HOST = 'bigtable.googleapis.com'
"""Data API request host."""

OPERATIONS_API_HOST = INSTANCE_ADMIN_HOST

ADMIN_SCOPE = 'https://www.googleapis.com/auth/bigtable.admin'
"""Scope for interacting with the Cluster Admin and Table Admin APIs."""
DATA_SCOPE = 'https://www.googleapis.com/auth/bigtable.data'
"""Scope for reading and writing table data."""
READ_ONLY_SCOPE = 'https://www.googleapis.com/auth/bigtable.data.readonly'
"""Scope for reading table data."""

_METRICS_HEADERS = (
    ('gccl', __version__),
)
_HEADER_STR = metrics.stringify(metrics.fill(_METRICS_HEADERS))
_GRPC_EXTRA_OPTIONS = (
    ('x-goog-api-client', _HEADER_STR),
)
# NOTE: 'grpc.max_message_length' will no longer be recognized in
#       grpcio 1.1 and later.
_MAX_MSG_LENGTH_100MB = 100 * 1024 * 1024
_GRPC_MAX_LENGTH_OPTIONS = _GRPC_EXTRA_OPTIONS + (
    ('grpc.max_message_length', _MAX_MSG_LENGTH_100MB),
    ('grpc.max_receive_message_length', _MAX_MSG_LENGTH_100MB),
)


def _make_data_stub(client):
    """Creates gRPC stub to make requests to the Data API.
def construct_settings(
        service_name, client_config, config_override,
        retry_names, bundle_descriptors=None, page_descriptors=None,
        metrics_headers=(), kwargs=None):
    """Constructs a dictionary mapping method names to _CallSettings.

    The ``client_config`` parameter is parsed from a client configuration JSON
    file of the form:

    .. code-block:: json

       {
         "interfaces": {
           "google.fake.v1.ServiceName": {
             "retry_codes": {
               "idempotent": ["UNAVAILABLE", "DEADLINE_EXCEEDED"],
               "non_idempotent": []
             },
             "retry_params": {
               "default": {
                 "initial_retry_delay_millis": 100,
                 "retry_delay_multiplier": 1.2,
                 "max_retry_delay_millis": 1000,
                 "initial_rpc_timeout_millis": 2000,
                 "rpc_timeout_multiplier": 1.5,
                 "max_rpc_timeout_millis": 30000,
                 "total_timeout_millis": 45000
               }
             },
             "methods": {
               "CreateFoo": {
                 "retry_codes_name": "idempotent",
                 "retry_params_name": "default",
                 "timeout_millis": 30000
               },
               "Publish": {
                 "retry_codes_name": "non_idempotent",
                 "retry_params_name": "default",
                 "bundling": {
                   "element_count_threshold": 40,
                   "element_count_limit": 200,
                   "request_byte_threshold": 90000,
                   "request_byte_limit": 100000,
                   "delay_threshold_millis": 100
                 }
               }
             }
           }
         }
       }

    Args:
      service_name (str): The fully-qualified name of this service, used as a
        key into the client config file (in the example above, this value
        would be ``google.fake.v1.ServiceName``).
      client_config (dict): A dictionary parsed from the standard API client
        config file.
      bundle_descriptors (Mapping[str, BundleDescriptor]): A dictionary of
        method names to BundleDescriptor objects for methods that are
        bundling-enabled.
      page_descriptors (Mapping[str, PageDescriptor]): A dictionary of method
        names to PageDescriptor objects for methods that are page
        streaming-enabled.
      config_override (str): A dictionary in the same structure of
        client_config to override the settings. Usually client_config is
        supplied from the default config and config_override will be
        specified by users.
      retry_names (Mapping[str, object]): A dictionary mapping the strings
        referring to response status codes to the Python objects representing
        those codes.
      metrics_headers (Mapping[str, str]): Dictionary of headers to be passed
        for analytics. Sent as a dictionary; eventually becomes a
        space-separated string (e.g. 'foo/1.0.0 bar/3.14.1').
      kwargs (dict): The keyword arguments to be passed to the API calls.

    Returns:
      dict: A dictionary mapping method names to _CallSettings.

    Raises:
      KeyError: If the configuration for the service in question cannot be
        located in the provided ``client_config``.
    """
    # pylint: disable=too-many-locals
    # pylint: disable=protected-access
    defaults = {}
    bundle_descriptors = bundle_descriptors or {}
    page_descriptors = page_descriptors or {}
    kwargs = kwargs or {}

    # Sanity check: It is possible that we got this far but some headers
    # were specified with an older library, which sends them as...
    #   kwargs={'metadata': [('x-goog-api-client', 'foo/1.0 bar/3.0')]}
    #
    # Note: This is the final format we will send down to GRPC shortly.
    #
    # Remove any x-goog-api-client header that may have been present
    # in the metadata list.
    if 'metadata' in kwargs:
        kwargs['metadata'] = [value for value in kwargs['metadata']
                              if value[0].lower() != 'x-goog-api-client']

    # Fill out the metrics headers with GAX and GRPC info, and convert
    # to a string in the format that the GRPC layer expects.
    kwargs.setdefault('metadata', [])
    kwargs['metadata'].append(
        ('x-goog-api-client', metrics.stringify(metrics.fill(metrics_headers)))
    )

    try:
        service_config = client_config['interfaces'][service_name]
    except KeyError:
        raise KeyError('Client configuration not found for service: {}'
                       .format(service_name))

    overrides = config_override.get('interfaces', {}).get(service_name, {})

    for method in service_config.get('methods'):
        method_config = service_config['methods'][method]
        overriding_method = overrides.get('methods', {}).get(method, {})
        snake_name = _upper_camel_to_lower_under(method)

        if overriding_method and overriding_method.get('timeout_millis'):
            timeout = overriding_method['timeout_millis']
        else:
            timeout = method_config['timeout_millis']
        timeout /= _MILLIS_PER_SECOND

        bundle_descriptor = bundle_descriptors.get(snake_name)
        bundling_config = method_config.get('bundling', None)
        if overriding_method and 'bundling' in overriding_method:
            bundling_config = overriding_method['bundling']
        bundler = _construct_bundling(bundling_config, bundle_descriptor)

        retry_options = _merge_retry_options(
            _construct_retry(method_config, service_config['retry_codes'],
                             service_config['retry_params'], retry_names),
            _construct_retry(overriding_method, overrides.get('retry_codes'),
                             overrides.get('retry_params'), retry_names))

        defaults[snake_name] = gax._CallSettings(
            timeout=timeout, retry=retry_options,
            page_descriptor=page_descriptors.get(snake_name),
            bundler=bundler, bundle_descriptor=bundle_descriptor,
            kwargs=kwargs)
    return defaults
예제 #5
0
 def test_no_argument(self):
     self.assertEqual(metrics.stringify(), '')
예제 #6
0
def construct_settings(service_name,
                       client_config,
                       config_override,
                       retry_names,
                       bundle_descriptors=None,
                       page_descriptors=None,
                       metrics_headers=(),
                       kwargs=None):
    """Constructs a dictionary mapping method names to _CallSettings.

    The ``client_config`` parameter is parsed from a client configuration JSON
    file of the form:

    .. code-block:: json

       {
         "interfaces": {
           "google.fake.v1.ServiceName": {
             "retry_codes": {
               "idempotent": ["UNAVAILABLE", "DEADLINE_EXCEEDED"],
               "non_idempotent": []
             },
             "retry_params": {
               "default": {
                 "initial_retry_delay_millis": 100,
                 "retry_delay_multiplier": 1.2,
                 "max_retry_delay_millis": 1000,
                 "initial_rpc_timeout_millis": 2000,
                 "rpc_timeout_multiplier": 1.5,
                 "max_rpc_timeout_millis": 30000,
                 "total_timeout_millis": 45000
               }
             },
             "methods": {
               "CreateFoo": {
                 "retry_codes_name": "idempotent",
                 "retry_params_name": "default",
                 "timeout_millis": 30000
               },
               "Publish": {
                 "retry_codes_name": "non_idempotent",
                 "retry_params_name": "default",
                 "bundling": {
                   "element_count_threshold": 40,
                   "element_count_limit": 200,
                   "request_byte_threshold": 90000,
                   "request_byte_limit": 100000,
                   "delay_threshold_millis": 100
                 }
               }
             }
           }
         }
       }

    Args:
      service_name (str): The fully-qualified name of this service, used as a
        key into the client config file (in the example above, this value
        would be ``google.fake.v1.ServiceName``).
      client_config (dict): A dictionary parsed from the standard API client
        config file.
      bundle_descriptors (Mapping[str, BundleDescriptor]): A dictionary of
        method names to BundleDescriptor objects for methods that are
        bundling-enabled.
      page_descriptors (Mapping[str, PageDescriptor]): A dictionary of method
        names to PageDescriptor objects for methods that are page
        streaming-enabled.
      config_override (str): A dictionary in the same structure of
        client_config to override the settings. Usually client_config is
        supplied from the default config and config_override will be
        specified by users.
      retry_names (Mapping[str, object]): A dictionary mapping the strings
        referring to response status codes to the Python objects representing
        those codes.
      metrics_headers (Mapping[str, str]): Dictionary of headers to be passed
        for analytics. Sent as a dictionary; eventually becomes a
        space-separated string (e.g. 'foo/1.0.0 bar/3.14.1').
      kwargs (dict): The keyword arguments to be passed to the API calls.

    Returns:
      dict: A dictionary mapping method names to _CallSettings.

    Raises:
      KeyError: If the configuration for the service in question cannot be
        located in the provided ``client_config``.
    """
    # pylint: disable=too-many-locals
    # pylint: disable=protected-access
    defaults = {}
    bundle_descriptors = bundle_descriptors or {}
    page_descriptors = page_descriptors or {}
    kwargs = kwargs or {}

    # Sanity check: It is possible that we got this far but some headers
    # were specified with an older library, which sends them as...
    #   kwargs={'metadata': [('x-goog-api-client', 'foo/1.0 bar/3.0')]}
    #
    # Note: This is the final format we will send down to GRPC shortly.
    #
    # Remove any x-goog-api-client header that may have been present
    # in the metadata list.
    if 'metadata' in kwargs:
        kwargs['metadata'] = [
            value for value in kwargs['metadata']
            if value[0].lower() != 'x-goog-api-client'
        ]

    # Fill out the metrics headers with GAX and GRPC info, and convert
    # to a string in the format that the GRPC layer expects.
    kwargs.setdefault('metadata', [])
    kwargs['metadata'].append(
        ('x-goog-api-client',
         metrics.stringify(metrics.fill(metrics_headers))))

    try:
        service_config = client_config['interfaces'][service_name]
    except KeyError:
        raise KeyError('Client configuration not found for service: {}'.format(
            service_name))

    overrides = config_override.get('interfaces', {}).get(service_name, {})

    for method in service_config.get('methods'):
        method_config = service_config['methods'][method]
        overriding_method = overrides.get('methods', {}).get(method, {})
        snake_name = _upper_camel_to_lower_under(method)

        if overriding_method and overriding_method.get('timeout_millis'):
            timeout = overriding_method['timeout_millis']
        else:
            timeout = method_config['timeout_millis']
        timeout /= _MILLIS_PER_SECOND

        bundle_descriptor = bundle_descriptors.get(snake_name)
        bundling_config = method_config.get('bundling', None)
        if overriding_method and 'bundling' in overriding_method:
            bundling_config = overriding_method['bundling']
        bundler = _construct_bundling(bundling_config, bundle_descriptor)

        retry_options = _merge_retry_options(
            _construct_retry(method_config, service_config['retry_codes'],
                             service_config['retry_params'], retry_names),
            _construct_retry(overriding_method, overrides.get('retry_codes'),
                             overrides.get('retry_params'), retry_names))

        defaults[snake_name] = gax._CallSettings(
            timeout=timeout,
            retry=retry_options,
            page_descriptor=page_descriptors.get(snake_name),
            bundler=bundler,
            bundle_descriptor=bundle_descriptor,
            kwargs=kwargs)
    return defaults