def __init__(self, user, initial=None): if user is not None: initial = forms.fill_dict( initial, username=user.username, real_name=user.real_name, display_name=user._display_name, gender_male=user.gender_male, birthday=user.birthday, height=user.height, address=user.address, zip=user.zip, city=user.city, country=user.country, email=user.email, www=user.www, notes=user.notes, userpictype=user.userpictype, ) _UserBoundForm.__init__(self, user, initial) self.user = user self.display_name.choices = [ (u"$username", user and user.username or _("Username")), (u"$real_name", user and user.real_name or _("Realname")), ] self.gender_male.choices = [(1, _("Male")), (0, _("Female"))] self.country.choices = sorted(get_application().locale.territories.iteritems(), key=itemgetter(1)) self.country.choices.insert(0, ("", "")) self.userpictype.choices = [(u"", _("No change")), (u"None", _("No Picture")), (u"Gravatar", _("Gravatar.com"))]
def __getitem__(self, name): locale = str(get_application().locale) if name in self._i18n_values.get(locale, ()): return self._i18n_values[locale][name] if name in self._values: return self._values[name] raise KeyError(name)
def make_config_form(): """Returns the form for the configuration editor.""" app = get_application() fields = {} values = {} use_default_label = lazy_gettext(u"Use default value") for category in app.cfg.get_detail_list(): items = {} values[category["name"]] = category_values = {} for item in category["items"]: items[item["name"]] = forms.Mapping(value=item["field"], use_default=forms.BooleanField(use_default_label)) category_values[item["name"]] = {"value": item["value"], "use_default": False} fields[category["name"]] = forms.Mapping(**items) class _ConfigForm(forms.Form): values = forms.Mapping(**fields) cfg = app.cfg def apply(self): t = self.cfg.edit() for category, items in self.data["values"].iteritems(): for key, d in items.iteritems(): if category != "pyClanSphere": key = "%s/%s" % (category, key) if d["use_default"]: t.revert_to_default(key) else: t[key] = d["value"] t.commit() return _ConfigForm({"values": values})
def __init__(self, initial=None): self.app = get_application() if initial is None: initial = {} for name in self.fields: initial[name] = self.app.cfg[name] forms.Form.__init__(self, initial)
def __init__(self, initial=None): self.app = app = get_application() self.active_plugins.choices = sorted( [(x.name, x.display_name) for x in app.plugins.values()], key=lambda x: x[1].lower() ) if initial is None: initial = dict(active_plugins=[x.name for x in app.plugins.itervalues() if x.active]) forms.Form.__init__(self, initial)
def get_engine(): """Return the active database engine (the database engine of the active application). If no application is enabled this has an undefined behavior. If you are not sure if the application is bound to the active thread, use :func:`~pyClanSphere.application.get_application` and check it for `None`. The database engine is stored on the application object as `database_engine`. """ from pyClanSphere.application import get_application return get_application().database_engine
def gen_slug(text, delim=u'-'): """Generates a proper slug for the given text. It calls either `gen_ascii_slug` or `gen_unicode_slug` depending on the application configuration. """ from pyClanSphere.application import get_application if get_application().cfg['ascii_slugs']: return gen_ascii_slug(text, delim) return gen_unicode_slug(text, delim)
def log(message, module=None): try: logger = get_application().log except AttributeError: warn(UnboundLogging('Tried to log %r but no application ' 'was bound to the calling thread' % message), stacklevel=2) return if level >= logger.level: logger.log(name, message, module, currentframe(1))
def exception(message=None, module=None, exc_info=None): """Logs an error plus the current or given exc info.""" if exc_info is None: exc_info = sys.exc_info() try: logger = get_application().log except AttributeError: # no application, write the exception to stderr return print_exception(*exc_info) if LEVELS['error'] >= logger.level: message = (message and message + '\n' or '') + \ ''.join(format_exception(*exc_info)) \ .decode('utf-8', 'ignore') logger.log('error', message, module, currentframe(1))
def open_url(url, data=None, timeout=None, allow_internal_requests=True, **kwargs): """This function parses the URL and opens the connection. The following protocols are supported: - `http` - `https` Per default requests to pyClanSphere itself trigger an internal request. This can be disabled by setting `allow_internal_requests` to False. """ app = get_application() if timeout is None: timeout = app.cfg["default_network_timeout"] parts = urlparse.urlsplit(url) if app is not None: site_url = urlparse.urlsplit(app.cfg["site_url"]) if ( allow_internal_requests and parts.scheme in ("http", "https") and site_url.netloc == parts.netloc and parts.path.startswith(site_url.path) ): path = parts.path[len(site_url.path) :].lstrip("/") method = kwargs.pop("method", None) if method is None: method = data is not None and "POST" or "GET" make_response = lambda *a: URLResponse(url, *a) return app.perform_subrequest( path.decode("utf-8"), url_decode(parts.query), method, data, timeout=timeout, response_wrapper=make_response, **kwargs ) handler = _url_handlers.get(parts.scheme) if handler is None: raise URLError("unsupported URL schema %r" % parts.scheme) if isinstance(data, basestring): data = StringIO(data) try: obj = handler(parts, timeout, **kwargs) return obj.open(data) except Exception, e: if not isinstance(e, NetException): e = NetException("%s: %s" % (e.__class__.__name__, str(e))) raise e
def bind_privileges(container, privileges, user=None): """Binds the privileges to the container. The privileges can be a list of privilege names, the container must be a set. This is called for the HTTP round-trip in the form validation. """ if not user: user = get_request().user app = get_application() notification_types = app.notification_manager.notification_types current_map = dict((x.name, x) for x in container) currently_attached = set(x.name for x in container) new_privileges = set(privileges) # remove out-dated privileges for name in currently_attached.difference(new_privileges): container.remove(current_map[name]) # remove any privilege dependencies that are not attached to other # privileges if current_map[name].dependencies: for privilege in current_map[name].dependencies.iter_privileges(): try: container.remove(privilege) except KeyError: # privilege probably already removed pass # remove notification subscriptions that required the privilege # being deleted. for notification in user.notification_subscriptions: privs = notification_types[notification.notification_id].privileges if current_map[name] in privs.iter_privileges(): db.session.delete(notification) break for privilege in current_map[name].dependencies: if privilege in privs.iter_privileges(): db.session.delete(notification) # add new privileges for name in new_privileges.difference(currently_attached): privilege = app.privileges[name] container.add(privilege) # add dependable privileges if privilege.dependencies: for privilege in privilege.dependencies.iter_privileges(): container.add(privilege)
def __init__(self, subject=None, text='', to_addrs=None): self.app = app = get_application() self.subject = u' '.join(subject.splitlines()) self.text = text from_addr = app.cfg['clan_email'] if not from_addr: from_addr = 'noreply@' + urlparse(app.cfg['site_url']) \ [1].split(':')[0] self.from_addr = u'%s <%s>' % ( app.cfg['clan_title'], from_addr ) self.to_addrs = [] if isinstance(to_addrs, basestring): self.add_addr(to_addrs) else: for addr in to_addrs: self.add_addr(addr)
def make_notification_form(user): """Creates a notification form.""" app = get_application() fields = {} subscriptions = {} systems = [(s.key, s.name) for s in sorted(app.notification_manager.systems.values(), key=lambda x: x.name.lower())] for obj in app.notification_manager.types(user): fields[obj.name] = forms.MultiChoiceField(choices=systems, label=obj.description, widget=forms.CheckboxGroup) for ns in user.notification_subscriptions: subscriptions.setdefault(ns.notification_id, []).append(ns.notification_system) class _NotificationForm(forms.Form): subscriptions = forms.Mapping(**fields) system_choices = systems def apply(self): user_subscriptions = {} for subscription in user.notification_subscriptions: user_subscriptions.setdefault(subscription.notification_id, set()).add(subscription.notification_system) for key, active in self["subscriptions"].iteritems(): currently_set = user_subscriptions.get(key, set()) active = set(active) # remove outdated for system in currently_set.difference(active): for subscription in user.notification_subscriptions.filter_by( notification_id=key, notification_system=system ): db.session.delete(subscription) # add new for system in active.difference(currently_set): user.notification_subscriptions.append( NotificationSubscription(user=user, notification_id=key, notification_system=system) ) return _NotificationForm({"subscriptions": subscriptions})
def redirect(url, code=302, allow_external_redirect=False, force_scheme_change=False): """Return a redirect response. Like Werkzeug's redirect but this one checks for external redirects too. If a redirect to an external target was requested `BadRequest` is raised unless `allow_external_redirect` was explicitly set to `True`. Leading slashes are ignored which makes it unsuitable to redirect to URLs returned from `url_for` and others. Use `redirect_to` to redirect to arbitrary endpoints or `_redirect` to redirect to unchecked resources outside the URL root. By default the redirect will not change the URL scheme of the current request (if there is one). This behavior can be changed by setting the force_scheme_change to False. """ # leading slashes are ignored, if we redirect to "/foo" or "foo" # does not matter, in both cases we want to be below our clanwebsite root. url = url.lstrip('/') if not allow_external_redirect: #: check if the url is on the same server #: and make it an external one try: url = check_external_url(get_application(), url) except ValueError: raise BadRequest() # keep the current URL schema if we have an active request if we # should. If https enforcement is set we suppose that the site_url # is already set to an https value. request = get_request() if request and not force_scheme_change and \ not request.app.cfg['force_https']: url = request.environ['wsgi.url_scheme'] + ':' + url.split(':', 1)[1] return _redirect(url, code)
def privilege(self): return get_application().privileges.get(self.name)
def init_database(): """ This is for inserting our new table""" from pyClanSphere.application import get_application engine = get_application().database_engine metadata.create_all(engine)
def _strip_url(url): """Strip an URL so that only the path is left.""" cfg = get_application().cfg if url.startswith(cfg['site_url']): url = url[len(cfg['site_url']):] return url.lstrip('/')
def make_external_url(path): """Return an external url for the given path.""" return urljoin(get_application().cfg['site_url'], path.lstrip('/'))
def __init__(self, group, initial=None): forms.Form.__init__(self, initial) self.app = get_application() self.group = group
def as_dict(self): result = self._values.copy() result.update(self._i18n_values.get(str(get_application().locale), {})) return result
def generate(self, **options): """This method generates the pagination. It accepts some keyword arguments that override the theme pagination settings. These arguments have the same name as the theme setting variables without the `pagination.` prefix. """ from pyClanSphere.application import url_for, get_application, DEFAULT_THEME_SETTINGS if self._skip_theme_defaults: settings = DEFAULT_THEME_SETTINGS else: settings = get_application().theme.settings def _getopt(name): value = options.pop(name, None) if value is not None: return value return settings["pagination." + name] normal = _getopt("normal") active = _getopt("active") commata = _getopt("commata") ellipsis = _getopt("ellipsis") threshold = _getopt("threshold") left_threshold = _getopt("left_threshold") right_threshold = _getopt("right_threshold") prev_link = _getopt("prev_link") next_link = _getopt("next_link") gray_prev_link = _getopt("gray_prev_link") gray_next_link = _getopt("gray_next_link") simple = _getopt("simple") if options: raise TypeError("generate() got an unexpected keyword " "argument %r" % iter(options).next()) was_ellipsis = False result = [] prev = None next = None get_link = lambda x: url_for( self.endpoint, page=x, per_page=self.per_page, post_id=self.post_id, **self.url_args ) if simple: result.append(active % {"url": get_link(self.page), "page": self.page}) if self.page > 1: prev = self.page - 1 if self.page < self.pages: next = self.page + 1 else: for num in xrange(1, self.pages + 1): if num == self.page: was_ellipsis = False if num - 1 == self.page: next = num if num + 1 == self.page: prev = num if num <= left_threshold or num > self.pages - right_threshold or abs(self.page - num) < threshold: if result and result[-1] != ellipsis: result.append(commata) link = get_link(num) template = num == self.page and active or normal result.append(template % {"url": link, "page": num}) elif not was_ellipsis: was_ellipsis = True result.append(ellipsis) if next_link: if next is not None: result.append(u' <a href="%s" class="next">%s</a>' % (get_link(next), _(u"Next »"))) elif gray_next_link: result.append(u' <span class="disabled next">%s</span>' % _(u"Next »")) if prev_link: if prev is not None: result.insert(0, u'<a href="%s" class="prev">%s</a> ' % (get_link(prev), _(u"« Previous"))) elif gray_prev_link: result.insert(0, u'<span class="disabled prev">%s</span> ' % _(u"« Previous")) return Markup(u"".join(result))
def __init__(self, imaccount, initial=None): forms.Form.__init__(self, initial) self.app = get_application() self.imaccount = imaccount