128 lines
3.9 KiB
Python
128 lines
3.9 KiB
Python
# -*- 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
|