This repository has been archived by the owner on Feb 25, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 30
/
config.py
116 lines (88 loc) · 3.66 KB
/
config.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/python
# Copyright 2012 Google Inc. 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 distrib-
# uted 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
# specific language governing permissions and limitations under the License.
"""Storage for configuration settings."""
__author__ = '[email protected] (Ka-Ping Yee)'
import binascii
import json
import os
import cache
from google.appengine.ext import db
# Config settings are written offline, so users never expect to see immediate
# effects. Because they are so frequently read, we set the ULL a bit higher;
# developers need to wait 5 s after changing a config setting in the console.
CACHE = cache.Cache('config', 300, 5)
class Config(db.Model):
"""A configuration setting.
Each configuration setting has a string key and a value that can be anything
representable in JSON (string, number, boolean, None, or arbitrarily nested
lists or dictionaries thereof). The value is stored internally using JSON.
"""
value_json = db.TextProperty() # the value, serialized to JSON
def Get(key, default=None, stale_ok=True):
"""Fetches the configuration value for a given key.
Args:
key: A string, the name of the configuration item to get.
default: An optional default value to return.
stale_ok: Optional; if False, get the latest value from the datastore.
Default is True: the returned value may be up to 1 second stale.
Returns:
The configuration value, or the specified default value if not found.
"""
def GetFromDatastore():
config = Config.get_by_key_name(key)
return config and json.loads(config.value_json)
value = CACHE.Get(key, GetFromDatastore) if stale_ok else GetFromDatastore()
if value is None:
return default
return value
def GetAll():
"""Returns a dictionary containing all the configuration values."""
results = {c.key().name(): json.loads(c.value_json) for c in Config.all()}
for key, value in results.items():
CACHE.Set(key, value)
return results
def Set(key, value):
"""Sets a configuration value.
Args:
key: A string, the name of the configuration item to get.
value: Any Python data structure that can be serialized to JSON.
"""
Config(key_name=key, value_json=json.dumps(value)).put()
CACHE.Set(key, value)
def Delete(key):
"""Deletes a configuration value."""
Config(key_name=key).delete()
CACHE.Delete(key)
def GetGeneratedKey(key):
"""Gets a string of 32 hex digits that is randomly generated on first use.
The first time this is called, it generates a random string and stores it in
a configuration item with the given key; thereafter, the stored string is
returned. The result is suitable for use as a cryptographic key (e.g.
HMAC key or encryption key): it is generated at runtime, doesn't exist in
the source code, and is unique to the application instance.
Args:
key: A string, the name of the configuration item to use.
Returns:
A string of 32 hex digits.
"""
@db.transactional
def PutGeneratedKey():
"""Transactionally ensures the key is written exactly once."""
value = Get(key, stale_ok=False)
if not value:
value = binascii.b2a_hex(os.urandom(16))
Set(key, value)
return value
value = Get(key)
if not value:
value = PutGeneratedKey()
return str(value) # avoid Unicode; it's just hex digits