def __init__(self, *args, **kwargs): self.apps = {} super(WSGIApplication, self).__init__(*args, **kwargs) gripe.sessionbridge.set_sessionbridge(SessionBridge()) self.pipeline = [] config = gripe.Config.app self.icon = config.get("icon", "/icon.png") logger.info("Application icon: %s", self.icon) route = webapp2.Route("/favicon.ico", handler=grit.statichandler.StaticHandler) route.grit_params = {"root": self, "roles": [], "alias": self.icon} self.router.add(route) container = config.get("container") if container: pline = container.get("pipeline") if pline: assert isinstance(pline, list), "Pipeline entry in app.container config must be list" for p in pline: logger.info("Adding pipeline entry %s", p) pipeline_class = gripe.resolve(p) assert pipeline_class, "Invalid entry %s in pipeline config" % p assert hasattr(pipeline_class, "begin"), "Pipeline entry %s has no 'begin' method" % p self.pipeline.append(pipeline_class) self.pipeline.append(grit.pipeline.Dispatcher) # Sort mounts so that when two paths have matching prefixes the longer path appears before the shorter one. config["mounts"].sort(cmp=lambda m1, m2: cmp(m2["path"], m1["path"])) # Reverse sort for mp in config["mounts"]: raw_path = mp.get("path") app_path = mp.get("app") assert raw_path, "Must specify a path for each mount in app.conf" path = "<:^%s$>" % raw_path roles = mp.get("roles", []) roles = roles.split() if isinstance(roles, basestring) else roles defaults = {"root": self, "roles": roles} if app_path: logger.debug("WSGIApplication(): Mounting app %s at path %s", app_path, raw_path) wsgi_sub_app = gripe.resolve(app_path, None) assert wsgi_sub_app, "WSGI app %s not found" % app_path defaults["app"] = app_path logger.info("WSGIApplication(): Adding handler app %s for path %s", app_path, raw_path) elif "abspath" in mp or "relpath" in mp or "static" in mp: logger.debug("WSGIApplication(): Redirecting %s to StaticHandler", raw_path) defaults["handler"] = grit.statichandler.StaticHandler defaults["path"] = raw_path if "abspath" in mp: defaults["abspath"] = mp["abspath"] if "relpath" in mp: defaults["relpath"] = mp["relpath"] else: logger.debug("WSGIApplication(): mount for path %s ignored", raw_path) continue route = webapp2.Route(path, handler=handle_request, defaults=defaults) route.grit_params = defaults self.router.add(route) self.error_handlers[404] = grit.requesthandler.handle_404
def get_interval_part_type(self, profile): node = profile.get_node(SessionType, self.name) part = node.get_root_property("intervalpart") if part: if part not in self._resolved_parts: gripe.resolve(part) self._resolved_parts.add(part) return grumble.Model.for_name(part) else: return None
def __init__(self, *args, **kwargs): self.apps = {} super(WSGIApplication, self).__init__(*args, **kwargs) gripe.sessionbridge.set_sessionbridge(SessionBridge()) self.pipeline = [] config = gripe.Config.app self.icon = config.get("icon", "/icon.png") logger.info("Application icon: %s", self.icon) self.router.add(webapp2.Route("/favicon.ico", handler = grit.statichandler.StaticHandler, defaults = { "root": self, "roles": [], "alias": self.icon })) container = config.get("container") if container: pipeline = container.get("pipeline") if pipeline: assert isinstance(pipeline, list), "Pipeline entry in app.container config must be list" for p in pipeline: logger.info("Adding pipeline entry %s", p) pipeline_class = gripe.resolve(p) assert pipeline_class, "Invalid entry %s in pipeline config" % p assert hasattr(pipeline_class, "begin"), "Pipeline entry %s has no 'begin' method" % p self.pipeline.append(pipeline_class) self.pipeline.append(grit.pipeline.Dispatcher) for mp in config["mounts"]: raw_path = mp.get("path") app_path = mp.get("app") logger.debug("WSGIApplication(): Mounting app %s at path %s", app_path, raw_path) assert raw_path, "Must specify a path for each mount in app.conf" path = "<:^%s$>" % raw_path roles = mp.get("roles", []) roles = roles.split() if isinstance(roles, basestring) else roles defaults = { "root": self, "roles": roles } if app_path: wsgi_sub_app = gripe.resolve(app_path, None) assert wsgi_sub_app, "WSGI app %s not found" % app_path defaults["app"] = app_path logger.info("WSGIApplication(): Adding handler app %s for path %s", app_path, raw_path) else: defaults["handler"] = grit.statichandler.StaticHandler if "abspath" in mp: defaults["abspath"] = mp["abspath"] if "relpath" in mp: defaults["relpath"] = mp["relpath"] logger.info("WSGIApplication(): Adding static handler for path %s", raw_path) self.router.add(webapp2.Route(path, handler = handle_request, defaults = defaults)) self.error_handlers[404] = grit.requesthandler.handle_404
def get(cls, parent, kind, propname, **kwargs): property = getattr(kind, propname) # Allow for custom bridges. Note that if you configure # a custom bridge, you have to deal with read-onliness and # multiple-choiciness yourself. bridge = kwargs.get("bridge", property.config.get("bridge")) if bridge: if not isinstance(bridge, WidgetBridgeFactory): bridge = gripe.resolve(bridge) return bridge(parent, kind, propname, **kwargs) if "readonly" in kwargs or \ property.is_key or \ property.readonly: return Label(parent, kind, propname, **kwargs) if property.config.get("choices") or kwargs.get("choices"): if kwargs.get("style", "combo").lower() == "combo": return ComboBox(parent, kind, propname, **kwargs) elif kwargs["style"].lower() == "radio": return RadioButtons(parent, kind, propname, **kwargs) # else we fall down to default processing... bridge = cls._widgetbridgetypes.get(property.__class__) assert bridge, "I'm not ready to handle properties of type '%s'" % type(property) return bridge(parent, kind, propname, **kwargs)
def get(mcs, parent, kind, prop_name, **kwargs): prop = getattr(kind, prop_name) \ if prop_name and prop_name not in "^$" and kind and hasattr(kind, prop_name) \ else None config = dict(prop.config if prop and hasattr(prop, "config") else {}) config.update(**kwargs) # Allow for custom bridges. Note that if you configure # a custom bridge, you have to deal with read-onliness and # multiple-choiciness yourself. bridge = config.get("bridge") if bridge: if not isinstance(bridge, WidgetBridgeFactory): bridge = gripe.resolve(bridge) return bridge(parent, kind, prop_name, **kwargs) if "choices" in config: if config.get("style", "combo").lower() == "combo": return ComboBox(parent, kind, prop_name, **kwargs) elif config["style"].lower() == "radio": return RadioButtons(parent, kind, prop_name, **kwargs) # else we fall down to default processing... bridge = mcs.get_widget_bridge_type(prop, prop_name) assert bridge, "I'm not ready to handle properties of type '%s'" % type( prop) return bridge(parent, kind, prop_name, **kwargs)
def get(cls, parent, kind, propname, **kwargs): prop = getattr(kind, propname) # Allow for custom bridges. Note that if you configure # a custom bridge, you have to deal with read-onliness and # multiple-choiciness yourself. bridge = kwargs.get("bridge", prop.config.get("bridge")) if bridge: if not isinstance(bridge, WidgetBridgeFactory): bridge = gripe.resolve(bridge) return bridge(parent, kind, propname, **kwargs) if "readonly" in kwargs or \ prop.is_key or \ prop.readonly: return Label(parent, kind, propname, **kwargs) if prop.config.get("choices") or kwargs.get("choices"): if kwargs.get("style", "combo").lower() == "combo": return ComboBox(parent, kind, propname, **kwargs) elif kwargs["style"].lower() == "radio": return RadioButtons(parent, kind, propname, **kwargs) # else we fall down to default processing... bridge = cls.getWidgetBridgeType(prop) assert bridge, "I'm not ready to handle properties of type '%s'" % type(prop) return bridge(parent, kind, propname, **kwargs)
def authenticate(self, **kwargs): authenticator = kwargs.get( "authenticator", gripe.Config.grizzle.get("authenticator", "grizzle.qt.authenticate")) authenticator = gripe.resolve(authenticator) return authenticator(**kwargs)
def post(self, **kwargs): logger.debug("%s --> grudge.control.Startup::post", self.request.path) if not self.request.headers.get("ST-JSON-Request"): logger.debug("Non-JSON post to %s", self.request.path) params = self.request.params do_json = False else: logger.debug("%s: JSON body %s", self.request.path, self.request.body) params = json.loads(self.request.body) do_json = True logger.debug("%s: params %s", self.request.path, params) self._wf = gripe.resolve(kwargs.get("process")) if self._wf: self._process = self._wf.instantiate() mapping = kwargs.get("mapping", []) for param in mapping: val = params.get(param) try: mapped = mapping[param] or param except: mapped = param setattr(self._process, mapped, val) self._process.put() self._process.start() if do_json: self.json_dump({ "status": "OK" }) else: self._template = kwargs.get("started_template", kwargs.get("template")) self.render() else: logger.error("No process defined") self.response_status_int = 500
def post(self, **kwargs): logger.debug("%s --> grudge.control.Startup::post", self.request.path) if not self.request.headers.get("ST-JSON-Request"): logger.debug("Non-JSON post to %s", self.request.path) params = self.request.params do_json = False else: logger.debug("%s: JSON body %s", self.request.path, self.request.body) params = json.loads(self.request.body) do_json = True logger.debug("%s: params %s", self.request.path, params) self._wf = gripe.resolve(kwargs.get("process")) if self._wf: self._process = self._wf.instantiate() mapping = kwargs.get("mapping", []) for param in mapping: val = params.get(param) try: mapped = mapping[param] or param except: mapped = param setattr(self._process, mapped, val) self._process.put() self._process.start() if do_json: self.json_dump({"status": "OK"}) else: self._template = kwargs.get("started_template", kwargs.get("template")) self.render() else: logger.error("No process defined") self.response_status_int = 500
def __init__(self): super(BackgroundThread, self).__init__() self._queue = Queue.Queue() if ("sweattrails" in gripe.Config.app and "background" in gripe.Config.app.sweattrails and "plugins" in gripe.Config.app.sweattrails.background): for plugin in gripe.Config.app.sweattrails.background.plugins: logger.debug("Initializing backgroung plugin '%s'", plugin) plugin = gripe.resolve(plugin) self._plugins.append(plugin(self))
def customize_user_class(cls): for (partname, partdef) in gripe.Config.app.grizzle.userparts.items(): (_, _, name) = partname.rpartition(".") name = name.lower() partcls = gripe.resolve(partname) if "urls" in partdef and partdef.urls: partcls._urls = gripe.url.UrlCollection(name, partdef.label, 9, partdef.urls) if partdef.configurable: propdef = UserPartToggle(name, verbose_name = partdef.label, default = partdef.default) cls.add_property(name, propdef)
def getPartPluginClass(cls, part): if part.__class__ in cls._plugins: logger.debug("Hardcoded plugin %s", cls._plugins[part.__class__]) return cls._plugins[part.__class__] pluginclass = None pluginname = gripe.Config.sweattrails.get(part.__class__.__name__) if pluginname: logger.debug("Configured plugin %s", pluginname) pluginclass = gripe.resolve(pluginname) cls._plugins[part.__class__] = pluginclass else: logger.debug("No plugin") return pluginclass
def getPartPluginClass(cls, part): if part.__class__ in cls._plugins: logger.debug("Hardcoded plugin %s", cls._plugins[part.__class__]) return cls._plugins[part.__class__] plugin_class = None plugin_name = gripe.Config.sweattrails.get(part.__class__.__name__) if plugin_name: logger.debug("Configured plugin %s", plugin_name) plugin_class = gripe.resolve(plugin_name) cls._plugins[part.__class__] = plugin_class else: logger.debug("No plugin") return plugin_class
def customize_user_class(cls): for (partname, partdef) in gripe.Config.key("app.grizzle.userparts").items(): (_, _, name) = partname.rpartition(".") name = name.lower() partcls = gripe.resolve(partname) if "urls" in partdef and partdef.urls: partcls._urls = gripe.url.UrlCollection(name, partdef.label, 9, partdef.urls) if partdef.configurable: propdef = UserPartToggle(name, verbose_name=partdef.label, default=partdef.default) cls.add_property(name, propdef)
def authenticate(self, **kwargs): uid = kwargs.get("uid") password = kwargs.get("password") if uid and password: user = self.get(uid) if user and user.authenticate(password=password): return user, password, kwargs.get("savecredentials", False) else: return None, None, None else: authenticator = kwargs.get( "authenticator", gripe.Config.grizzle.get("authenticator", "grizzle.qt.authenticate")) authenticator = gripe.resolve(authenticator) return authenticator(**kwargs)
def do_subhandler(self): parsed_path = urllib.parse.urlparse(self.path) subhandler = None for h in self.handlers: p = h["path"] if parsed_path.path.startswith(p): subhandler = h["handler"] break if subhandler: subhandler = gripe.resolve(subhandler)(self) if subhandler: try: subhandler = getattr(subhandler, "do_" + self.command) except AttributeError: subhandler = getattr(subhandler, "do") subhandler() if subhandler is None: self.send_response(404)
def post(self, action=None, param="file", **kwargs): if not self.user: self.error(401) elif not action: logger.error("No action specified for upload") self.error(500) else: logger.info("Uploader.post(%s, %s)", action, param) process_class = gripe.resolve(action) if not process_class: logger.error("Action class '%s' specified in upload not found", action) self.error(500) elif not grudge.is_process(process_class): logger.error( "Class '%s' specified as action class in upload is not a grudge process class", process_class) self.error(500) else: uploads = self.request.POST.get(param) def instantiate_activity(upload): uploaded_file = UploadedFile() uploaded_file.user = self.user.uid() uploaded_file.action = action uploaded_file.content = upload.file.read() uploaded_file.filename = os.path.basename(upload.filename) uploaded_file.content_type = upload.type uploaded_file.put() p = process_class.instantiate(uploadedFile=uploaded_file, **kwargs) p.start() try: for upload in uploads: instantiate_activity(upload) except TypeError: instantiate_activity(uploads)
def get_parser(filename): f = os.path.basename(filename) parser = None (_, _, extension) = f.rpartition(".") if extension: extension = extension.lower() factory = _parser_factories_by_ext.get(extension) if factory: factory = gripe.resolve(factory) if hasattr(factory, "create_parser"): parser = factory.create_parser(filename) else: parser = factory(filename) if not parser: for factory in _parser_factories: if hasattr(factory, "create_parser"): parser = factory.create_parser(filename) else: parser = factory(filename) if parser: break return parser
def _init_schema(cls): c = cls.config[cls.database_type] if not cls._adapter_class: cls._adapter_class = gripe.resolve(cls._adapter_name) if cls._adapter_class and hasattr(cls._adapter_class, "setup"): cls._adapter_class.setup(c)
def __init__(self, datatype=None, prop=None): super(EnumConverter, self).__init__(datatype, prop) self._enum = gripe.resolve(self.prop.config.get("enum")) assert self._enum and isinstance(self._enum, enum.EnumMeta)
def setup_parts(): for (part, partdef) in gripe.Config.app.sweattrails.activityprofileparts.items(): NodeTypeDefinition(part, gripe.resolve(partdef.refClass), gripe.resolve(partdef.nodeClass))
def convert(self, value): ret = gripe.resolve(value) if not callable(ret): raise TypeError("Cannot convert '%s' to a PythonProperty" % value) return ret
def __init__(self, *args, **kwargs): super(EnumProperty, self).__init__(*args, **kwargs) self._enum = gripe.resolve(self.config.get("enum")) assert self._enum and isinstance(self._enum, enum.EnumMeta) and list(self._enum) self.sqltype = SQLTypes(type(list(self._enum)[0].value)).name
def from_jsonvalue(self, value): assert (value is None) or isinstance( value, str), "PythonConverter.from_jsonvalue(): value must be a string" return gripe.resolve(value)
for p in grumble.Query(grumble.Model.for_name(self.partname), keys_only=True, include_subclasses=True) \ .set_parent(kennel): p.set_parent(instance) p.put() if p is None: p = grumble.Model.for_name(self.partname)(parent=instance) p.put() instance._parts[n] = p def getvalue(self, instance): return instance.get_part(self.name.lower()) is not None _userpart_classes = {} for pn in gripe.Config.key("app.grizzle.userparts"): _userpart_classes[pn.lower()] = gripe.resolve(pn) def customize_user_class(cls): for (partname, partdef) in gripe.Config.key("app.grizzle.userparts").items(): (_, _, name) = partname.rpartition(".") name = name.lower() partcls = _userpart_classes[partname.lower()] if "urls" in partdef and partdef.urls: partcls._urls = gripe.url.UrlCollection(name, partdef.label, 9, partdef.urls) if partdef.configurable: propdef = UserPartToggle(name, verbose_name=partdef.label, default=partdef.default)
class ModelManager(object): modelconfig = gripe.Config.model models = modelconfig.get("datamodel", {}) def_recon_policy = modelconfig.get("reconcile", "none") _adapter_names = { "sqlite3": "grumble.sqlite3.Sqlite3Adapter", "postgresql": "grumble.postgresql.PostgresqlAdapter" } _adapter_factory = gripe.resolve(_adapter_names[gripe.db.Tx.database_type]) assert _adapter_factory, "Misconfiguration: No Grumble database adapter for db type %s" % gripe.db.Tx.database_type def __init__(self, name): logger.debug("ModelManager.__init__(%s)", name) self.my_config = self.models.get(name, {}) self.name = name self._adapter = self._adapter_factory(self) self.table = name self.tablename = self.tableprefix + '"' + name + '"' self.columns = None self._prep_columns = [] self.kind = None self.key_col = None self.flat = False self.audit = True def __str__(self): return "ModelManager <%s>" % self.name def set_tablename(self, tablename): self.table = tablename self.tablename = self.tableprefix + '"' + tablename + '"' def _set_columns(self): self.key_col = None for c in self._prep_columns: if c.is_key: self.key_col = c c.required = True self.columns = [] if not self.key_col: kc = ColumnDefinition("_key_name", "TEXT", True, None, False) kc.is_key = True kc.scoped = False self.key_col = kc self.columns.append(kc) if not self.flat: self.columns += (ColumnDefinition("_parent", "TEXT", False, None, True), ) self.columns += self._prep_columns if self.audit: self.columns += (ColumnDefinition("_ownerid", "TEXT", False, None, True), ColumnDefinition("_acl", "TEXT", False, None, False), ColumnDefinition("_createdby", "TEXT", False, None, False), ColumnDefinition("_created", "TIMESTAMP", False, None, False), ColumnDefinition("_updatedby", "TEXT", False, None, False), ColumnDefinition("_updated", "TIMESTAMP", False, None, False)) self.column_names = [c.name for c in self.columns] def add_column(self, column): assert self.kind, "ModelManager for %s without kind set??" % self.name assert not self.kind._sealed, "Kind %s is sealed" % self.name if isinstance(column, (tuple, list)): for c in column: self.add_column(c) else: self._prep_columns.append(column) def reconcile(self): self._set_columns() self._recon = self.my_config.get("reconcile", self.def_recon_policy) if self._recon != "none": with gripe.db.Tx.begin() as tx: cur = tx.get_cursor() if self._recon == "drop": logger.info("%s: reconcile() drops table", self) cur.execute('DROP TABLE IF EXISTS ' + self.tablename) self._create_table(cur) else: # _recon is 'all' or 'add' if not self._table_exists(cur): self._create_table(cur) else: self._update_table(cur) cur = tx.get_cursor() cur.execute( '''INSERT INTO {} (kind, key, tablename, audit, flat) VALUES (%s, %s, %s, %s, %s) ON CONFLICT (kind) DO UPDATE SET "key" = %s, tablename = %s, audit = %s, flat = %s''' .format(self.tableprefix + '"ModelRegistry"'), (self.kind.kind(), self.kind.key_prop if hasattr( self.kind, "key_prop") else None, self.tablename, self.kind.audit(), self.kind.flat(), self.kind.key_prop if hasattr(self.kind, "key_prop") else None, self.tablename, self.kind.audit(), self.kind.flat())) def _table_exists(self, cur): return self._adapter.table_exists(cur) def _create_table(self, cur): logger.info("%s: reconcile() creates table", self) sql = 'CREATE TABLE %s (' % self.tablename v = [] cols = [] key_col = '_key_name' for c in self.columns: csql = '\n"%s" %s' % (c.name, c.data_type) if c.required: csql += " NOT NULL" if c.defval: csql += " DEFAULT ( %s )" v.append(c.defval) if c.is_key: if not c.scoped: csql += " PRIMARY KEY" key_col = c.name cols.append(csql) sql += ",".join(cols) + "\n)" cur.execute(sql, v) for c in self.columns: if c.indexed and not c.is_key: cur.execute('CREATE INDEX "%s_%s" ON %s ( "%s" )' % (self.table, c.name, self.tablename, c.name)) # if c.is_key and c.scoped: # cur.execute('CREATE UNIQUE INDEX "%s_%s" ON %s ( "_parent", "%s" )' % (self.table, c.name, self.tablename, c.name)) template_text = gripe.read_file('conf/register.sql') if template_text: template = string.Template(template_text) sql = template.safe_substitute(schema=self.schema, table=self.tablename, kind=self.kind.kind(), key_column=key_col) cur.execute(sql) def _update_table(self, cur, table_existed=False): self._adapter.update_table(cur, table_existed) def seal(self): return self.kind.seal() def getModelQueryRenderer(self, query): return self._adapter.getModelQueryRenderer(query) modelmanagers_byname = {} @classmethod def for_name(cls, obj): set_mm = False manager = None name = None if hasattr(obj, "modelmanager"): if obj.modelmanager: manager = obj.modelmanager else: set_mm = True if manager is None and hasattr(obj, "kind"): if callable(obj.kind): name = obj.kind() else: name = obj.kind if isinstance(obj, str): name = obj if manager is not None: if name and name not in cls.modelmanagers_byname: cls.modelmanagers_byname[name] = manager return manager assert name, "Cannot get modelmanager for '%s' since I cannot determine the name to use" % obj manager = cls.modelmanagers_byname.get(name) if not manager: manager = ModelManager(name) cls.modelmanagers_byname[name] = manager if set_mm: obj.modelmanager = manager return manager
def get(self, process = None, **kwargs): self._wf = gripe.resolve(process) logger.debug("%s --> grudge.control.Startup::get", self.request.path) self._template = kwargs.get("template") self.render()
def get(self, process=None, **kwargs): self._wf = gripe.resolve(process) logger.debug("%s --> grudge.control.Startup::get", self.request.path) self._template = kwargs.get("template") self.render()
def add_plugin(self, plugin_class): logger.debug("Initializing background plugin '%s'", plugin_class) plugin_class = gripe.resolve(plugin_class) self._plugins.append(plugin_class(self))
class GearTypeNode(TreeNodeBase): gearType = grumble.ReferenceProperty(GearType, serialize = False) partOf = grumble.SelfReferenceProperty(collection_name = "parts") usedFor = grumble.ReferenceProperty(SessionTypeNode) class CriticalPowerIntervalNode(NodeBase): criticalPowerInterval = grumble.ReferenceProperty(CriticalPowerInterval, serialize = False) class CriticalPaceNode(NodeBase): criticalPace = grumble.ReferenceProperty(CriticalPace, serialize = False) for (part, partdef) in gripe.Config.app.sweattrails.activityprofileparts.items(): definition = NodeTypeDefinition(part, gripe.resolve(partdef.refClass), gripe.resolve(partdef.nodeClass)) class ActivityProfile(grizzle.UserPart): name = grumble.StringProperty(is_key = True) description = grumble.StringProperty() isdefault = grumble.BooleanProperty() icon = grumble.image.ImageProperty() def sub_to_dict(self, descriptor, **flags): for part in grumble.Query(NodeBase, False, True).set_ancestor(self): node_type = NodeTypeRegistry.get_by_node_class(part.__class__) if node_type.name() not in descriptor: descriptor[node_type.name()] = [] descriptor[node_type.name()].append(part.to_dict(**flags)) return descriptor