This repository has been archived by the owner on Apr 21, 2019. It is now read-only.
/
__init__.py
310 lines (239 loc) · 14.6 KB
/
__init__.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
#
# =====================================================
# |==| PROVIDENCE/CLARITY DATA ANALYSIS PLATFORM |==|
# |==| ----------------------------------- |==|
# |==| Author: Sam Gammon <sg@samgammon.com> |==|
# |==| Version: 0.1 DEV |==|
# |==| ------------------------------------------- |==|
# |==| COPYRIGHT (c) 2010. ALL RIGHTS RESERVED |==|
# =====================================================
#
import os, sys, logging, exceptions
from google.appengine.api import namespace_manager, capabilities
import core
from ProvidenceClarity.core import api as c_api
from ProvidenceClarity.core import bridge as c_bridge
from ProvidenceClarity.core import clock as c_clock
from ProvidenceClarity.core import config as c_config
from ProvidenceClarity.core import controller as c_controller
from ProvidenceClarity.core import ext as c_ext
from ProvidenceClarity.core import log as c_log
from ProvidenceClarity.core import state as c_state
from ProvidenceClarity.api.util import import_helper
## Import Details
__all__ = ['Platform']
__protos__ = ['data']
## Declare Globals
version_major = '0.1'
version_minor = '6.000'
config_module = None
build = 'DEV'
## Expose Import-able Variables
VERSION = str(version_major)+'.'+str(version_minor)+' '+str(build)
PC_PATH = os.path.join(os.path.dirname(__file__))
# Controls the creation of the Platform class and object
class ProvidenceClarityPlatform(type):
def __new__(meta, classname, bases, classDict, *args, **kwargs):
return type.__new__(meta, classname, bases, classDict)
def _platformName(self):
return self.__name__
def __repr__(self):
return '<ProvidenceClarityPlatform "%s">' % self._platformName()
def __str__(self):
return '<ProvidenceClarityPlatform "%s">' % self._platformName()
def __unicode__(self):
return u'<ProvidenceClarityPlatform "%s">' % self._platformName()
# Providence Clarity Platform!
class Platform(core.ProvidenceClarityObject):
"""
================================== Providence/Clarity ==================================
Main Class:
Everything is initialized and operated on from this master class,
which stores references to internal APIs and handlers.
Properties:
-- version: Stores a dict of version values for P/C.
-- full: A string of the system's full version. (ex: 0.5.131 DEV, r: string)
-- major: The system's 'major' version. (ex: 0.5, r: int/float)
-- minor: The system's 'minor' version. (ex: 131, r: int/float)
-- build: The system's build release type. (ex: DEV, r: string)
-- config: Stores a ref to P/C's config module (most useful for config.get, r: module)
-- config_p: Stores a path to P/C's config module. (r: string)
-- namespace: The current operating namespace for GAE APIs. (r: string)
-- api: Stores references to loaded API controllers. (r: dynamic module)
-- state: Stores registry-like (key=>value) information for later use (r: varies)
-- clock: Measures and stores timepoints taken during runtime, along with cpu and cpu_api usage.
Keyword Parameters:
-- namespace: Sets the current namespace to this string value.
-- version: Overrides the computed version for the platform.
"""
__metaclass__ = ProvidenceClarityPlatform
## ===== 1: Properties/Platform Extension Proxies (Initialized Externally)
config = c_config.PCConfigProxy
log = c_log.PCLogProxy
clock = c_clock.PCClockProxy
state = c_state.PCStateProxy
api = c_api.PCAPIProxy
ext = c_ext.PCExtProxy
## ===== 2: Internals
__log_map = logging._levelNames
## ===== 3: Internal Methods
def __init__(self,config_override=None, *args, **kwargs):
## Setup globals
global version_major
global version_minor
global config_module
global import_item
global build
version = {'major':version_major,'minor':version_minor,'full':str(version_major)+'.'+str(version_minor)+' '+str(build),'build':build}
## Path Inserts
if '.' not in sys.path:
sys.path.insert(0,'.')
sys.path.insert(1,'lib')
sys.path.insert(2, 'distlib')
## Setup capabilities sets
_cap = capabilities.CapabilitySet
## Setup object proxies
self.config = c_config.PCConfigProxy()
self.log = c_log.PCLogProxy()
self.clock = c_clock.PCClockProxy()
self.state = c_state.PCStateProxy()
self.api = c_api.PCAPIProxy()
self.ext = c_ext.PCExtProxy()
## Link up with Platform
self.api._setPlatformParent(self)
self.log._setPlatformParent(self)
self.state._setPlatformParent(self)
self.clock._setPlatformParent(self)
self.ext._setPlatformParent(self)
self.config._setPlatformParent(self)
## Setup initial state
self.state.set('env',os.environ)
self.state.set('quotas', None)
self.state.set('namespace',namespace_manager.get_namespace())
self.state.set('capabilities', {'api':{
'images':{
'enabled':_cap('images').is_enabled(),
'crop':_cap('images',methods=['crop']).is_enabled(),
'get_serving_url':_cap('images',methods=['get_serving_url']).is_enabled(),
'resize':_cap('images',methods=['resize']).is_enabled(),
'rotate':_cap('images',methods=['rotate']).is_enabled()},
'datastore_v3':{
'enabled':_cap('datastore_v3').is_enabled(),
'write':_cap('datastore_v3',capabilities=['write']).is_enabled(),
'read':_cap('datastore_v3',capabilities=['read']).is_enabled(),
'put':_cap('datastore_v3',methods=['put']).is_enabled(),
'delete':_cap('datastore_v3',methods=['delete']).is_enabled(),
'get':_cap('datastore_v3',methods=['get']).is_enabled(),
'run_in_transaction':_cap('datastore_v3',methods=['run_in_transaction']).is_enabled(),
'run_in_transaction_custom_retries':_cap('datastore_v3',methods=['run_in_transaction']).is_enabled()},
'users':{
'enabled':_cap('users').is_enabled(),
'get_current_user':_cap('users',methods=['get_current_user']).is_enabled(),
'is_current_user_admin':_cap('users',methods=['is_current_user_admin']).is_enabled()},
'mail':{
'enabled':_cap('mail').is_enabled(),
'send_mail':_cap('mail',methods=['send_mail']).is_enabled(),
'send_mail_to_admins':_cap('mail',methods=['send_mail_to_admins']).is_enabled()},
'memcache':{
'enabled':_cap('memcache').is_enabled(),
'get':_cap('memcache',methods=['get']).is_enabled(),
'set':_cap('memcache',methods=['set']).is_enabled(),
'delete':_cap('memcache',methods=['delete']).is_enabled()},
'oauth':{
'enabled':_cap('oauth').is_enabled(),
'get_current_user':_cap('oauth',methods=['get_current_user']).is_enabled(),
'is_current_user_admin':_cap('oauth',methods=['is_current_user_admin']).is_enabled()},
'multitenancy':{
'enabled':_cap('multitenancy').is_enabled(),
'get_namespace':_cap('multitenancy',methods=['get_namespace']).is_enabled(),
'set_namespace':_cap('multitenancy',methods=['set_namespace']).is_enabled()},
'blobstore':{
'enabled':_cap('blobstore').is_enabled(),
'get':_cap('blobstore',methods=['get']).is_enabled(),
'delete':_cap('blobstore',methods=['delete']).is_enabled()},
'xmpp':{
'enabled':_cap('xmpp').is_enabled(),
'send_message':_cap('xmpp',methods=['send_message']).is_enabled(),
'send_invite':_cap('xmpp',methods=['send_invite']).is_enabled()},
'urlfetch':{
'enabled':_cap('urlfetch').is_enabled(),
'fetch':_cap('urlfetch',methods=['fetch']).is_enabled()}
}
})
## Load/resolve Config
if config_override is None:
config_mod, props = import_helper(['ProvidenceClarity','pc_config'],['get','dump','config'])
elif config_override is False or config_override == '':
raise exceptions.ConfigRequired()
else:
if isinstance(config_override, type(os)):
config_mod = config_override
elif isinstance(config_override, (str, basestring, unicode)):
config_mod, props = import_helper(config_override,['get','dump','config'])
elif isinstance(config_override, list):
config_mod, props = import_helper('.'.join(config_override))
else:
try:
config_mod, props = import_helper(['ProvidenceClarity',config_override],['get','dump','config'])
except ImportError: raise exceptions.InvalidConfig()
## Set configuration
self.config.setConfig(config_mod)
## Environment Vars - Split for Namespace
software_t = '/'.split(os.environ['SERVER_SOFTWARE'])
if software_t[0].lower() == 'development': platform = 'Dev';
else: platform = 'Production'
domain = os.environ['HTTP_HOST'].split(':')[0].split('.')
if domain[-1] == 'com':
subdomain = domain[0]
else:
subdomain = None
# :: Namespace is usually extracted from subdomain - set via initialized keyword parameter
if self.config.get('enable','multitenancy',False):
_m_log = self.config.get('logging','multitenancy',False)
if self.config.get('force_namespace','multitenancy', False):
if isinstance(self.config.get('force_namespace','multitenancy',False), (str, unicode)) and self.config.get('force_namespace','multitenancy',False) is not '':
if namespace_manager.validate_namespace(self.config.get('force_namespace','multitenancy',False)):
if _m_log: self.log.info('Setting request namespace to "%s".' % config_get('force_namespace','multitenancy',False))
namespace_manager.set_namespace(self.config.get('force_namespace','multitenancy',False))
else:
if 'namespace' in kwargs or self.config.get('apps_mode_force', 'multitenancy', False):
if kwargs['namespace'] == self.config.get('apps_subdomain','multitenancy','apps') or self.config.get('apps_mode_force', 'multitenancy', False):
if _m_log: self.log.info('Setting request namespace to Google Apps domain "%s".' % namespace_manager.google_apps_namespace())
namespace_manager.set_namespace(namespace_manager.google_apps_namespace())
else:
if isinstance(kwargs['namespace'], (str, unicode)) and namespace_manager.validate_namespace(kwargs['namespace']):
if _m_log: self.log.info('Setting request namespace to split domain "%s".' % kwargs['namespace'])
namespace_manager.set_namespace(kwargs['namespace'])
else:
if kwargs['namespace'] is not None:
if _m_log: self.log.info('Given namespace "%s" failed to pass validation. Ignoring.' % str(kwargs['namespace']))
if 'version' in kwargs:
self.version = kwargs['version']
else:
self.version = version
super(Platform, self).__init__(*args, **kwargs)
def __repr__(self):
return '<ProvidenceClarityPlatform "%s">' % self.__class__.__name__
def __str__(self):
return '<ProvidenceClarityPlatform "%s">' % self.__class__.__name__
def __unicode__(self):
return u'<ProvidenceClarityPlatform "%s">' % self.__class__.__name__
## ===== 4: Class Methods
@classmethod
def config(cls):
return cls.config
@classmethod
def version(cls):
return cls.version
## Master Controller Object
PCController = c_controller.PCController
## Master Adapter Object
PCAdapter = c_controller.PCAdapter
## Init and return a ProvidenceClarity object
def initialize(platform_profile=None,namespace=None,config='pc_config'):
if platform_profile is not None:
if isinstance(platform_profile, ProvidenceClarityPlatform):
p = platform_profile(namespace=namespace,config=config)
else:
p = Platform(config)
return p