Ejemplo n.º 1
0
def clear_cache(model: str):
    """Get finder cache pool
    """
    try:
        # Clear finder cache
        cache.get_pool('odm.finder.' + model).clear()

        # Cleanup entities cache
        for k in _ENTITIES_CACHE.keys():
            if k.startswith(model + '.'):
                _ENTITIES_CACHE.rm(k)

        events.fire('*****@*****.**', model=model)
    except cache.error.PoolNotExist:
        pass
Ejemplo n.º 2
0
    def setup_widgets(self):
        """Setup widgets
        """
        # 'Submit' button for the last step
        if self.steps == self._current_step and self._submit_button:
            self.add_widget(self._submit_button)

        # 'Next' button for all steps except the last one
        if self._current_step < self.steps:
            self.add_widget(
                _widget.button.Submit(weight=200,
                                      uid='action_forward_' +
                                      str(self._current_step + 1),
                                      value=_lang.t('form@forward'),
                                      form_area='footer',
                                      color='primary',
                                      css='form-action-forward',
                                      icon='fa fas fa-fw fa-forward',
                                      data={
                                          'to-step': self._current_step + 1,
                                      }))

        # 'Back' button for all steps except the first one
        if self._current_step > 1:
            self.add_widget(
                _widget.button.Button(weight=100,
                                      uid='action_backward_' +
                                      str(self._current_step - 1),
                                      value=_lang.t('form@backward'),
                                      form_area='footer',
                                      form_step=self._current_step,
                                      css='form-action-backward',
                                      icon='fa fas fa-fw fa-backward',
                                      data={
                                          'to-step': self._current_step - 1,
                                      }))

        # Ask form instance to setup widgets
        self._on_setup_widgets()

        # Ask others to setup form's widgets
        _events.fire('form@setup_widgets.' + self.name, frm=self)

        # Restore widgets' values
        if self._cache:
            try:
                for k, v in _cache.get_pool('form.form_values').get_hash(
                        self._uid).items():
                    try:
                        self.get_widget(k).set_val(v)
                    except _error.WidgetNotExistError:
                        pass
            except _cache.error.KeyNotExist:
                pass

        return self
Ejemplo n.º 3
0
    def __init__(self, model: str, query: qu.Query = None):
        """Init
        """
        if not _api.is_model_registered(model):
            raise _error.ModelNotRegistered(model)

        self._model = model
        self._mock = _api.dispense(model)
        self._cache_pool = cache.get_pool('odm.finder.' + model)

        super().__init__(_odm_query.ODMQuery(self._mock, query))
Ejemplo n.º 4
0
def dispense(request: _http.Request, uid: str) -> _form.Form:
    """Dispense a form
    """
    try:
        # Determine form's class
        cid = uid.replace('cid:', '') if uid.startswith(
            'cid:') else _cache.get_pool('form.form_cid').get(uid)
        cls = _util.get_module_attr(cid)

        # Prevent instantiating other classes via HTTP API
        if not issubclass(cls, _form.Form):
            raise RuntimeError('Form class is not found')

        # Instantiate form
        return cls(request) if uid.startswith('cid:') else cls(request,
                                                               _uid=uid)

    except _cache.error.KeyNotExist:
        raise RuntimeError('Invalid form UID')

    # Hide all other exceptions info from outer world
    except Exception as e:
        _logger.error(e)
        raise RuntimeError('Unexpected form exception')
Ejemplo n.º 5
0
"""PytSite ODM Plugin Queue
"""
__author__ = 'Oleksandr Shepetko'
__email__ = '*****@*****.**'
__license__ = 'MIT'

from pymongo.errors import PyMongoError
from bson import errors as bson_errors
from pytsite import mongodb, queue, logger, cache, reg

_QUEUE = queue.Queue('odm')
_ENTITIES_CACHE = cache.get_pool('odm.entities')
_CACHE_TTL = reg.get('odm.cache_ttl', 86400)


def _entity_save(args: dict):
    """Save an entity
    """
    fields_data = args['fields_data']
    collection = mongodb.get_collection(args['collection_name'])

    # Save data to the database
    try:
        # New entity
        if args['is_new']:
            collection.insert_one(fields_data)

        # Existing entity
        else:
            collection.replace_one({'_id': fields_data['_id']}, fields_data)
Ejemplo n.º 6
0
"""PytSite Auth UI Password Plugin Forms
"""
__author__ = 'Oleksandr Shepetko'
__email__ = '*****@*****.**'
__license__ = 'MIT'

from pytsite import reg, router, lang, cache, util, tpl, mail
from plugins import form, widget, auth

_BS_VER = reg.get('auth_ui_password.twitter_bootstrap_version', 4)
_RESET_TOKENS_POOL = cache.get_pool('auth_ui_password.reset_password_tokens')
_RESET_TOKEN_TTL = 86400


class SignIn(form.Form):
    """Password Sign In Form
    """
    def _on_setup_form(self):
        """Hook
        """
        self.title_css = 'text-center'
        self.area_footer_css = 'text-center'

    def _on_setup_widgets(self):
        """Hook
        """

        self.add_widget(
            widget.input.Email(
                uid='login',
                weight=10,
Ejemplo n.º 7
0
    def __init__(self, request: _http.Request, **kwargs):
        """Init
        """
        # Request
        self._request = request

        # Cache pools
        self._cids_cache = _cache.get_pool('form.form_cid')
        self._attrs_cache = _cache.get_pool('form.form_attrs')
        self._values_cache = _cache.get_pool('form.form_values')

        # Widgets
        self._widgets = []  # type: _List[_widget.Abstract]

        # Form's areas where widgets can be placed
        self._areas = ('hidden', 'header', 'body', 'footer')

        # Last widget's weight
        self._last_widget_weight = {k: 0 for k in self._areas}

        # Form's class ID
        self._cid = '{}.{}'.format(self.__module__, self.__class__.__name__)

        # Form's UID
        self._uid = None  # type: str

        # Current step
        self._current_step = 1

        # Should form be cached
        self._cache = False

        # Default submit button
        self._submit_button = _widget.button.Submit(
            weight=200,
            uid='action_submit',
            value=_lang.t('form@save'),
            color='primary',
            form_area='footer',
            css='form-action-submit',
            icon='fa fas fa-fw fa-check',
        )

        # Form's attributes. This dict holds all form's attributes that can be set from outside.
        # Using dict instead of separate object's properties motivated by large amount of variables and necessity of
        # caching them in convenient manner
        self._attrs = {
            'created': _datetime.now(),
            'name': '',
            'enctype': 'application/x-www-form-urlencoded',
            'method': 'post',
            'action': '',
            'data': {},
            'location': request.url,
            'referer': request.referrer,
            'redirect': self._request.inp.get('__redirect'),
            'steps': 1,
            'update_location_hash': False,
            'css': 'pytsite-form',
            'area_hidden_css': '',
            'area_header_css': '',
            'area_body_css': '',
            'area_footer_css': '',
            'messages_css': 'form-messages',
            'get_widgets_ep': 'form/widgets',
            'validation_ep': 'form/validate',
            'tpl': 'form@form',
            'title': '',
            'hide_title': False,
            'title_css': '',
        }

        # Presence of '_uid' kwarg means that form's is being reconstructed by _api.dispense()
        if '_uid' in kwargs:
            self._uid = kwargs.pop('_uid')

            # Restore form's attributes from cache
            if self._attrs_cache.has(self._uid):
                self._cache = True
                self._attrs.update(self._attrs_cache.get_hash(self._uid))

            # This attributes must be overwritten
            for k in ('location', 'referer', 'redirect'):
                v = request.inp.get('__' + k)
                if v:
                    self.set_attr(k, v)

            # Perform form's setup
            self._on_setup_form()

            # Form setup event
            _events.fire('form@setup_form.' + self.name, frm=self)

        # Normal form initialization
        else:
            # Set attributes from kwargs
            for k, v in kwargs.items():
                self.set_attr(k, v)

            # Perform form's setup
            self._on_setup_form()

            # Set form's UID if it still not set
            if not self._uid:
                self._uid = self._build_uid()

            # Set form's name if it still not set
            if not self.name:
                self.name = _F_NAME_SUB_RE.sub('_', self._uid.lower()).replace(
                    '__', '_')

            # Set default action
            if not self.action:
                try:
                    self.action = _http_api.url('form@post_submit',
                                                {'__form_uid': self._uid})
                except _routing.error.RuleNotFound:
                    pass

            # Form setup event
            _events.fire('form@setup_form.' + self.name, frm=self)

            # Add convenient CSS classes
            self.css += ' form-cid-{}'.format(
                _CSS_SUB_RE.sub('-', self._cid.lower()).replace('--', '-'))
Ejemplo n.º 8
0
__email__ = '*****@*****.**'
__license__ = 'MIT'

from typing import Any, Dict, List, Tuple, Union, Generator
from abc import ABC, abstractmethod
from collections import OrderedDict
from copy import deepcopy
from datetime import datetime
from pymongo import ASCENDING as I_ASC, DESCENDING as I_DESC, GEO2D as I_GEO2D, TEXT as I_TEXT, GEOSPHERE as I_GEOSPHERE
from bson.objectid import ObjectId
from pymongo.collection import Collection
from pymongo.errors import OperationFailure
from pytsite import mongodb, events, lang, errors, cache, reg
from . import _error, _field, _queue

_CACHE_POOL = cache.get_pool('odm.entities')
_CACHE_TTL = reg.get('odm.cache_ttl', 86400)


class Entity(ABC):
    """ODM Entity
    """
    _collection_name = None
    _history_fields = None  # type: List[str]
    _deprecated_methods = {
        '_pre_save': '_on_pre_save',
        '_after_save': '_on_after_save',
        '_pre_delete': '_on_after_delete',
        '_after_delete': '_on_after_delete',
        '_created': '_on_created',
        '_modified': '_on_modified',