File: //snap/google-cloud-cli/396/lib/googlecloudsdk/api_lib/app/runtime_registry.py
# -*- coding: utf-8 -*- #
# Copyright 2018 Google LLC. All Rights Reserved.
#
# 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.
"""Defines a registry for storing per-runtime information.
A registry is essentially a wrapper around a Python dict that stores a mapping
from (runtime, environment) to arbitrary data. Its main feature is that it
supports lookups by matching both the runtime and the environment.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from six.moves import map # pylint:disable=redefined-builtin
class RegistryEntry(object):
"""An entry in the Registry.
Attributes:
runtime: str or re.RegexObject, the runtime to be staged
envs: set(env.Environment), the environments to be staged
"""
def __init__(self, runtime, envs):
self.runtime = runtime
self.envs = envs
def _RuntimeMatches(self, runtime):
try:
return self.runtime.match(runtime)
except AttributeError:
return self.runtime == runtime
def _EnvMatches(self, env):
return env in self.envs
def Matches(self, runtime, env):
"""Returns True iff the given runtime and environment match this entry.
The runtime matches if it is an exact string match.
The environment matches if it is an exact Enum match or if this entry has a
"wildcard" (that is, None) for the environment.
Args:
runtime: str, the runtime to match
env: env.Environment, the environment to match
Returns:
bool, whether the given runtime and environment match.
"""
return self._RuntimeMatches(runtime) and self._EnvMatches(env)
def __hash__(self):
# Sets are unhashable; Environments are unorderable
return hash((self.runtime, sum(sorted(map(hash, self.envs)))))
def __eq__(self, other):
return self.runtime == other.runtime and self.envs == other.envs
def __ne__(self, other):
return not self.__eq__(other)
class Registry(object):
"""A registry to store values for various runtimes and environments.
The registry is a map from (runtime, app-engine-environment) to
user-specified values. As an example, storing Booleans for different
runtimes/environments would look like:
REGISTRY = {
RegistryEntry('php72', {env.STANDARD}): True,
RegistryEntry('php55', {env.STANDARD}): False,
RegistryEntry('nodejs8', {env.FLEX}): False,
}
Attributes:
mappings: dict, where keys are RegistryEntry objects and values can be
of any type
override: object or None; if specified, this value will always be returned
by Get()
default: object or None; if specified, will be returned if Get() could not
find a matching registry entry
"""
def __init__(self, mappings=None, override=None, default=None):
self.mappings = mappings or {}
self.override = override
self.default = default
def Get(self, runtime, env):
"""Return the associated value for the given runtime/environment.
Args:
runtime: str, the runtime to get a stager for
env: env, the environment to get a stager for
Returns:
object, the matching entry, or override if one was specified. If no
match is found, will return default if specified or None otherwise.
"""
if self.override:
return self.override
for entry, value in self.mappings.items():
if entry.Matches(runtime, env):
return value
if self.default is not None:
return self.default
else:
return None