コード例 #1
0
ファイル: test.py プロジェクト: cerha/pytis
    def test_validation_order(self):
        # This test reproduces a previously existing bug in computer input
        # validation dependencies.
        fields = (
            pp.Field('a', type=pd.String(not_null=True)),
            pp.Field('b',
                     type=pd.String(not_null=True, maxlen=1),
                     computer=pp.computer(lambda r, a: a[0].upper(),
                                          validate=True)),
            pp.Field('c',
                     type=pd.String(enumerator=pd.FixedEnumerator(range(10)),
                                    not_null=True),
                     computer=pp.computer(lambda r, b: str(ord(b) % 10),
                                          validate=True)),
        )
        row = self._row(fields, new=True)
        row.validate('a', 'foo')
        assert row['b'].value() == 'F'
        assert row['c'].value() == '0'
        # Set 'b' to an invalid value (violates maxlen=1).
        row.validate('b', 'xxx')

        def cb():
            # This used to fail when the computer for 'c' was not called
            # due to invalid value of 'b' (when 'b' validity was not refreshed
            # correctly).
            assert row['c'].value() == '6'

        row.register_callback(row.CALL_CHANGE, 'c', cb)
        row.validate('a', 'bar')
コード例 #2
0
ファイル: test.py プロジェクト: cerha/pytis
 def test_completer(self):
     completer = self._enumerator(
         ('x', ),
         data=(('Apple', ), ('Bananas', ), ('Basil', ), ('Bacardi', ),
               ('Cinamon', )),
     )
     fields = (
         pp.Field('a', type=pd.Integer(not_null=True)),
         pp.Field('x0',
                  type=pd.String(enumerator=pd.FixedEnumerator(('a', 'b',
                                                                'c')))),
         pp.Field('x1', type=pd.String(), completer=('yes', 'no', 'maybe')),
         pp.Field('x2',
                  type=pd.String(),
                  completer=completer,
                  runtime_filter=pp.computer(lambda r, a: pd.NE(
                      'x', pd.sval('Bacardi')) if a == 1 else None)),
     )
     row = self._row(fields, new=True)
     assert not row.has_completer('a')
     assert row.has_completer('x0')
     assert row.has_completer('x1', static=True)
     assert row.has_completer('x2')
     assert not row.has_completer('x2', static=True)
     assert row.completions('a') == []
     assert row.completions('x0') == ['a', 'b', 'c']
     assert row.completions('x1') == ['maybe', 'no', 'yes']
     assert row.completions('x1', prefix='y') == ['yes']
     assert row.completions('x2') == ('Apple', 'Bananas', 'Basil',
                                      'Bacardi', 'Cinamon')
     assert row.completions('x2',
                            prefix='ba') == ('Bananas', 'Basil', 'Bacardi')
     row['a'] = 1
     assert row.completions('x2', prefix='ba') == ('Bananas', 'Basil')
コード例 #3
0
ファイル: test.py プロジェクト: cerha/pytis
 def test_attachment_storage(self):
     storage = pytis.presentation.AttachmentStorage()
     row = self._row((
         pp.Field('a', type=pd.String()),
         pp.Field('b', type=pd.String(), attachment_storage=storage),
         pp.Field('c',
                  type=pd.String(),
                  attachment_storage=lambda row: storage),
     ))
     assert row.attachment_storage('a') is None
     assert row.attachment_storage('b') == storage
     assert row.attachment_storage('c') == storage
コード例 #4
0
 def _product_filter(self, row, marked, filter):
     condition = pd.WM('product', pd.WMValue(pd.String(), filter
                                             or '*'))
     if marked:
         value = pd.Value(pd.Boolean(), True)
         condition = pd.AND(condition, pd.EQ('marked', value))
     return condition
コード例 #5
0
class Roles(Specification):
    title = _("Uživatelské role")
    help = _(
        "Správa dostupných uživatelských rolí, které je možné přiřazovat uživatelům."
    )
    table = 'cms_roles'

    def fields(self):
        return (
            Field('role_id', default=nextval('cms_roles_role_id_seq')),
            Field('name', _("Title"), width=16),
            Field('system_role',
                  _("Systémová role"),
                  width=16,
                  type=pd.String(not_null=True)),
            Field('description', _("Description"), width=64),
        )

    layout = ('name', 'description')
    columns = ('name', 'description')
    condition = pd.EQ('system_role', pd.Value(pd.String(), None))

    def bindings(self):
        return (Binding('users', _("Uživatelé zařazení do této role"),
                        self._spec_name('RoleUsers'), 'role_id'), )

    cb = CodebookSpec(display='name')
コード例 #6
0
ファイル: test.py プロジェクト: cerha/pytis
 def test_display_functions(self):
     enumerator = self._enumerator(
         ('id', 'title', 'letter'),
         data=(('1', 'First', 'A'), ('2', 'Second', 'B')))
     fields = (
         pp.Field('a'),
         pp.Field('b',
                  type=pd.String(enumerator=enumerator),
                  display=lambda x: '-' + x + '-'),
         pp.Field('c',
                  type=pd.String(enumerator=enumerator),
                  display=lambda row: row['title'].value().lower()),
     )
     row = self._row(fields, None, new=True, prefill=dict(b='1', c='2'))
     assert row.display('b') == '-1-'
     assert row.display('c') == 'second'
コード例 #7
0
ファイル: test.py プロジェクト: cerha/pytis
 def test_permissions(self):
     data = pd.RestrictedMemData(
         [pd.ColumnSpec(c, pd.String()) for c in ('x', 'y', 'z')],
         access_rights=pd.AccessRights(('x', (None, pd.Permission.ALL)),
                                       ('y', (None, pd.Permission.VIEW)),
                                       ('z', ((), pd.Permission.ALL))),
     )
     row = pp.PresentedRow((
         pp.Field('x'),
         pp.Field('y'),
         pp.Field('z'),
         pp.Field('zz',
                  virtual=True,
                  computer=pp.computer(lambda r, z: '-' + z + '-')),
     ),
                           data,
                           None,
                           new=True)
     assert row.permitted('x', pd.Permission.VIEW)
     assert row.permitted('x', True)
     assert row.permitted('y', pd.Permission.VIEW)
     assert not row.permitted('y', pd.Permission.UPDATE)
     assert not row.permitted('z', pd.Permission.VIEW)
     protected_row = row.protected()
     with pytest.raises(protected_row.ProtectionError):
         protected_row['z'].value()
     with pytest.raises(protected_row.ProtectionError):
         protected_row['zz'].value()
     # Cover special cases for a non-permitted field in various methods.
     assert row.get('z', secure=True) is None
     assert row.display('z') == ''
     assert row.enumerate('z') == []
     assert not row.editable('z')
コード例 #8
0
ファイル: test.py プロジェクト: cerha/pytis
 def _enumerator(self, columns, data=()):
     return pd.DataEnumerator(
         pd.DataFactory(
             pd.MemData,
             [pd.ColumnSpec(c, pd.String()) for c in columns],
             data=data,
         ))
コード例 #9
0
 def _customize_fields(self, fields):
     fields.modify_many((
         'id',
         'id3',
         'num',
         'continent',
     ), column_width=6)
     fields.modify_many((
         'id',
         'id3',
         'num',
     ), fixed=True)
     fields.modify_many((
         'id',
         'id3',
     ),
                        filter=TextFilter.ALPHANUMERIC,
                        post_process=PostProcess.UPPER)
     fields.append(
         Field('cname',
               _("Continent name"),
               editable=Editable.NEVER,
               computer=CbComputer('continent', 'name'),
               virtual=True,
               type=pd.String()))
     fields.set_property('width',
                         id=2,
                         num=3,
                         continent=2,
                         name=30,
                         fullname=40,
                         cname=20)
コード例 #10
0
ファイル: test.py プロジェクト: cerha/pytis
 def test_inline_display(self):
     enumerator = self._enumerator(
         ('id', 'title', 'letter'),
         data=(('1', 'First', 'A'), ('2', 'Second', 'B')))
     fields = (
         pp.Field('a',
                  type=pd.String(enumerator=enumerator),
                  display='title',
                  inline_display='b',
                  null_display='-'),
         pp.Field('b', type=pd.String()),
     )
     row = self._row(fields, new=True, prefill=dict(a='1', b='FIRST'))
     assert row.display('a') == 'FIRST'
     assert row.display('a', export=lambda x: x.value().lower()) == 'first'
     row['b'] = None
     assert row.display('a') == '-'
コード例 #11
0
 class Specification(pp.Specification):
     table = 'grid_test'
     fields = (
         pp.Field('id', type=pd.Integer()),
         pp.Field('name', type=pd.String()),
         pp.Field('price', type=pd.Float(precision=2)),
         pp.Field('flag', type=pd.Boolean()),
     )
コード例 #12
0
ファイル: test.py プロジェクト: cerha/pytis
 def test_unique(self):
     data = pd.MemData(
         (pd.ColumnSpec('a', pd.String(not_null=True, unique=True)), ),
         data=(('1', ), ('2', ), ('3', )),
     )
     row = pp.PresentedRow((pp.Field('a'), ), data, None, new=True)
     assert row.validate('a', '1') is not None
     assert row.validate('a', '4') is None
コード例 #13
0
class SystemRoles(Roles):
    title = _("Systémové role")
    help = _("Systémové role jsou uživatelům přiřazeny automaticky.")
    layout = columns = ('name', 'system_role', 'description')
    condition = pd.NE('system_role', pd.Value(pd.String(), None))
    bindings = ()
    access_rights = pd.AccessRights((None, ('cms_admin', pd.Permission.ALL)),
                                    (None, ('cms_user', pd.Permission.VIEW)))
コード例 #14
0
 def fields(self):
     return (
         Field('role_id', default=nextval('cms_roles_role_id_seq')),
         Field('name', _("Title"), width=16),
         Field('system_role',
               _("Systémová role"),
               width=16,
               type=pd.String(not_null=True)),
         Field('description', _("Description"), width=64),
     )
コード例 #15
0
ファイル: test.py プロジェクト: cerha/pytis
 def test_validation_cache(self):
     # This test reproduces a previously existing bug in validation result caching.
     enumerator = self._enumerator(('id', 'title'),
                                   data=(('1', 'First'), ('2', 'Second')))
     row = self._row((pp.Field('a',
                               type=pd.String(not_null=True,
                                              enumerator=enumerator)), ))
     assert not row.validate('a', '3') is None
     data = enumerator._data  # There is currently no need to make this public elsewhere.
     data.insert(pd.Row(
         (('id', pd.sval('3')), ('title', pd.sval('Third')))))
     assert row.validate('a', '3') == None
コード例 #16
0
ファイル: test.py プロジェクト: cerha/pytis
 def test_cbcomputer_display(self):
     enumerator = self._enumerator(('id', 'title'),
                                   data=(('1', 'First'), ('2', 'Second')))
     fields = (
         pp.Field('a',
                  type=pd.String(enumerator=enumerator),
                  display='title'),
         pp.Field('b', computer=pp.CbComputer('a', 'title')),
     )
     row = self._row(fields)
     row['a'] = '1'
     assert row.display('a') == 'First'
     assert row.display('b') == ''
コード例 #17
0
ファイル: test.py プロジェクト: cerha/pytis
 def test_binary_computer(self):
     a = '\x04\x00\x00\x05\x00\x19\x00'
     b = '\x00\x05\x04\xa4\xbb\x10\x00'
     row = self._row((
         pp.Field('x', type=pd.String()),
         pp.Field(
             'data',
             type=pd.Binary(not_null=True),
             computer=pp.computer(
                 lambda r, x: x == 'a' and a or x == 'b' and b or None)),
     ))
     assert row['data'].value() is None
     row['x'] = pd.sval('a')
     assert row['data'].value() == a
     assert isinstance(row['data'].value(), pd.Binary.Data)
     row['x'] = pd.sval('b')
     assert row['data'].value() == b
コード例 #18
0
ファイル: defs.py プロジェクト: cerha/pytis
    def __init__(self, spec_name_prefix=None):
        """
        Arguments:

          spec_name_prefix -- if not None then only specification with given
            prefix (basestring) are tested

        """
        import pytis.output
        self._output_resolver = pytis.output.OutputResolver(
            pytis.config.print_spec_dir, pytis.config.resolver)
        data = pd.dbtable('e_pytis_roles', ('name', 'purposeid'))
        condition = pd.NE('purposeid', pd.Value(pd.String(), 'user'))
        self._application_roles = [
            row[0].value()
            for row in data.select_map(identity, condition=condition)
        ]
        self._spec_name_prefix = spec_name_prefix
コード例 #19
0
ファイル: test.py プロジェクト: cerha/pytis
 def test_editable_always_bool(self):
     row = self._row((
         pp.Field('a', type=pd.String()),
         pp.Field('b', type=pd.Integer()),
         pp.Field('c', editable=pp.computer(lambda r, a, b: a or b)),
     ))
     for a, b, editable in (
         (None, None, False),
         ('', None, False),
         (None, 0, False),
         ('', 0, False),
         (None, 1, True),
         ('', 5, True),
         ('x', None, True),
         ('y', 8, True),
     ):
         row['a'] = a
         row['b'] = b
         assert row.editable('c') is editable
コード例 #20
0
class Continents(Specification):
    """Codebook of continents and their codes.

    Codebook is a regular view.  Any view can be used as a codebook.  It is,
    however, possible to define several properties of a view, which influence
    its use in the codebook context.  They are all covered by the
    'CodebookSpec' instance passed as the 'cb' argument of the specification.
    See the 'CodebookSpec' documentation for more information about the
    available options.

    Using a view as a codebook for a particular field is than done by passing
    its name as the 'codebook' argument in the field specification.  See the
    specification of 'Countries' below for an example.

    """
    public = True
    title = _("Continents")
    table = dbdefs.Continents
    fields = (
        Field('id',
              width=3,
              column_width=6,
              fixed=True,
              filter=TextFilter.ALPHANUMERIC,
              post_process=PostProcess.UPPER),
        Field('name', width=40),
        Field('smallest', codebook='cb.Countries'),
    )
    cb = CodebookSpec(display='name')
    bindings = (
        Binding('all-countries',
                _("All Countries"),
                'cb.Countries',
                'continent',
                search=lambda r: r['id'].value() == 'EU' and pd.sval('CZ') or
                None),
        Binding('islands',
                _("Islands"),
                'cb.Countries',
                'continent',
                condition=lambda r: pd.WM(
                    'name', pd.WMValue(pd.String(), '*island*'))),
        Binding('disabled-countries', _("Disabled Countries"),
                'cb.DisabledCountries', 'continent'),
        Binding('random-numbers',
                _("Random numbers"),
                'misc.RandomNumbers',
                arguments=lambda r: {}),
    )
    prints = (
        (_("Default"),
         'output/None'),  # This spec doen't exist, so defaults are used.
        (_("Countries of the current continent"),
         'cb.PrintContinentCountries'),
        PrintAction('p_countries_continents',
                    _("Countries of the current continent as specification"),
                    'cb.PrintContinentCountries'),
        PrintAction('p_overflow', _("PDF LayoutError"), 'cb.PrintOverflow'),
        (_("Template based"), 'output/Continents'),
        (_("Database template"), 'ContinentsDB'),
        (_("Iterated table"), 'IteratedContinents'),
    )
コード例 #21
0
 def _country_filter(self, row, continent):
     if continent:
         return pd.EQ('continent',
                      pd.Value(pd.String(), continent.upper()))
     else:
         return None
コード例 #22
0
ファイル: crypto.py プロジェクト: cerha/wiking
class CryptoKeys(CMSExtensionModule):
    """Management of keys and users.

    It uses a special set of actions that resemble standard editing actions but
    are different from them:

    - Insert new key: This creates initial key for an encryption area.  This
      can be done only once for each of the areas.  The inserted keys can be
      given to other users using copy action.

    - Copy key: Copy an existing key to another user.

    - Change password: Change password of the key for the given user.

    - Delete key: Remove a user from the given key.  This can be only done if
      another copy of the key exists.

    All the actions are performed using special database functions.

    """
    class Spec(wiking.Specification):
        table = 'cms_crypto_keys'
        title = _("Users and Encryption Keys")

        def fields(self):
            return (
                Field('key_id', _("Id"), editable=Editable.NEVER),
                Field('name',
                      _("Name"),
                      not_null=True,
                      codebook='CryptoNames',
                      editable=Editable.NEVER),
                Field('uid',
                      _("User"),
                      not_null=True,
                      codebook='Users',
                      selection_type=SelectionType.CHOICE,
                      editable=Editable.ONCE),
                Field('new_uid',
                      _("New user"),
                      not_null=True,
                      codebook='Users',
                      selection_type=SelectionType.CHOICE,
                      type=pd.Integer,
                      virtual=True,
                      runtime_filter=computer(self._new_uid_filter)),
                Field('key', _("Key")),
                Field('remove',
                      _("Action"),
                      virtual=True,
                      computer=computer(lambda r: _("Remove"))),
                Field('old_password',
                      _("Current password"),
                      type=pd.Password,
                      verify=False,
                      virtual=True),
                Field('new_password',
                      _("New password"),
                      type=pd.Password,
                      virtual=True),
                Field('delete',
                      virtual=True,
                      computer=computer(lambda row: _("Remove"))),
            )

        def _new_uid_filter(self, row, name):
            assigned_users = wiking.module(self._resolver).assigned_users(
                row['name'])
            return pd.AND(*[pd.NE('uid', u) for u in assigned_users])

        sorting = (
            (
                'uid',
                pd.ASCENDENT,
            ),
            (
                'name',
                pd.ASCENDENT,
            ),
        )
        columns = (
            'uid',
            'name',
            'delete',
        )
        actions = (
            Action('password',
                   _("Change password"),
                   descr=_("Change key password")),
            Action('adduser',
                   _("Copy to user"),
                   descr=_("Add another user of the key")),
        )

    _DB_FUNCTIONS = dict(
        CMSExtensionModule._DB_FUNCTIONS,
        cms_crypto_delete_key=(
            (
                'name_',
                pd.String(),
            ),
            (
                'uid_',
                pd.Integer(),
            ),
            (
                'force',
                pd.Boolean(),
            ),
        ),
        cms_crypto_insert_key=(
            (
                'name_',
                pd.String(),
            ),
            (
                'uid_',
                pd.Integer(),
            ),
            (
                'key_',
                pd.String(),
            ),
            (
                'psw',
                pd.String(),
            ),
        ),
        cms_crypto_copy_key=(
            (
                'name_',
                pd.String(),
            ),
            (
                'from_uid',
                pd.Integer(),
            ),
            (
                'to_uid',
                pd.Integer(),
            ),
            (
                'from_psw',
                pd.String(),
            ),
            (
                'to_psw',
                pd.String(),
            ),
        ),
        cms_crypto_change_password=(
            (
                'id_',
                pd.Integer(),
            ),
            (
                'old_psw',
                pd.String(),
            ),
            (
                'new_psw',
                pd.String(),
            ),
        ),
    )

    _TITLE_COLUMN = 'uid'
    _INSERT_LABEL = _("Create key")

    def _authorized(self, req, action, record=None, **kwargs):
        if action == 'view':
            return req.check_roles(Roles.CRYPTO_ADMIN) or self._check_uid(
                req, record, 'uid')
        elif action == 'password':
            return self._check_uid(req, record, 'uid')
        elif action in ('list', 'insert', 'delete', 'adduser'):
            return req.check_roles(Roles.CRYPTO_ADMIN)
        else:
            return False

    def _prefill(self, req):
        return dict(super(CryptoKeys, self)._prefill(req),
                    uid=req.user().uid())

    def _layout(self, req, action, record=None):
        if action == 'insert':
            layout = (
                'name',
                'uid',
                'new_password',
            )
        elif action == 'adduser':
            layout = (
                'key_id',
                'name',
                'uid',
                'new_uid',
                'old_password',
                'new_password',
            )
        elif action == 'password':
            layout = (
                'key_id',
                'name',
                'uid',
                'old_password',
                'new_password',
            )
        else:
            layout = (
                'name',
                'uid',
            )
        return layout

    def _columns(self, req):
        columns = super(CryptoKeys, self)._columns(req)
        if not req.has_param('_crypto_name'):
            columns = [c for c in columns if c != 'delete']
        return columns

    def _link_provider(self, req, uri, record, cid, **kwargs):
        if cid == 'delete':
            return req.make_uri(uri,
                                key_id=record['key_id'].value(),
                                action='delete')
        else:
            return super(CryptoKeys,
                         self)._link_provider(req, uri, record, cid, **kwargs)

    def _list_form_kwargs(self, req, form_cls):
        kwargs = super(CryptoKeys, self)._list_form_kwargs(req, form_cls)
        if issubclass(form_cls, pw.ItemizedView) and req.check_roles(
                Roles.USER_ADMIN):
            kwargs['template'] = lcg.TranslatableText("%%(%s)s [%%(delete)s]" %
                                                      self._TITLE_COLUMN)
        return kwargs

    def related(self, req, binding, record, uri):
        if 'name' in record:
            req.set_param('_crypto_name', record['name'])
        return super(CryptoKeys, self).related(req, binding, record, uri)

    def _actions(self, req, record):
        actions = super(CryptoKeys, self)._actions(req, record)
        if record is None and req.has_param('_crypto_name'):
            condition = pd.EQ('name', req.param('_crypto_name'))
            try:
                count = self._data.select(condition)
            finally:
                try:
                    self._data.close()
                except Exception:
                    pass
            if count > 0:
                actions = [a for a in actions if a.id() != 'insert']
        return actions

    def _insert(self, req, record, transaction):
        key = wiking.generate_random_string(256)
        if not self._call_db_function('cms_crypto_insert_key',
                                      record['name'].value(),
                                      record['uid'].value(),
                                      key,
                                      record['new_password'].value(),
                                      transaction=transaction):
            raise pd.DBException(
                _("New key not created. Maybe it already exists?"))

    def _update(self, req, record, transaction):
        action = req.param('action')
        if action == 'password':
            if not self._call_db_function('cms_crypto_change_password',
                                          record['key_id'].value(),
                                          record['old_password'].value(),
                                          record['new_password'].value(),
                                          transaction=transaction):
                raise pd.DBException(
                    _("Password not changed. Maybe invalid old password?"))
        elif action == 'adduser':
            if not self._call_db_function('cms_crypto_copy_key',
                                          record['name'].value(),
                                          record['uid'].value(),
                                          record['new_uid'].value(),
                                          record['old_password'].value(),
                                          record['new_password'].value(),
                                          transaction=transaction):
                raise pd.DBException(
                    _("User not added. Maybe invalid old password?"))
        else:
            raise Exception('Unexpected action', action)

    def _delete(self, req, record, transaction):
        if not self._call_db_function('cms_crypto_delete_key',
                                      record['name'].value(),
                                      record['uid'].value(),
                                      False,
                                      transaction=transaction):
            raise pd.DBException(
                _("The user couldn't be deleted. "
                  "Maybe he is the last key holder?"))

    def action_adduser(self, req, record, action='adduser'):
        return super(CryptoKeys, self).action_update(req,
                                                     record,
                                                     action=action)

    def action_password(self, req, record=None):
        return self.action_update(req, record=record, action='password')

    def assigned_users(self, name):
        # Internal method for Spec class, don't use it elsewhere
        return self._data.select_map(lambda row: row['uid'],
                                     condition=pd.EQ('name', name))

    def assigned_names(self, uid):
        """Return sequence of crypto names assigned to user identified by uid.

        Arguments:

          uid -- user uid, integer

        """
        return self._data.select_map(lambda row: row['name'],
                                     condition=pd.EQ('uid', pd.ival(uid)))

    def clear_crypto_passwords(self, req, user):
        # Just a hack to allow clearing passwords on logout
        req.set_cookie(self._CRYPTO_COOKIE, None, secure=True)
        self._call_db_function('cms_crypto_lock_passwords', user.uid())
コード例 #23
0
ファイル: test.py プロジェクト: cerha/pytis
class Timezone(datetime.tzinfo):
    _ZERO_DIFF = datetime.timedelta(0)

    def utcoffset(self, dt):
        return self._ZERO_DIFF

    def tzname(self, dt):
        return "XXX"

    def dst(self, dt):
        return self._ZERO_DIFF


tests = (
    (pp.Field('numeric', type=pd.Integer()), (5, '5')),
    (pp.Field('string', type=pd.String()), ('x', 'x')),
    (pp.Field('multiline', type=pd.String(),
              height=4), ('xxx\nxxx', 'xxx\nxxx')),
    (pp.Field('date', type=pd.Date()), (datetime.date(2016, 8,
                                                      30), '30.08.2016')),
    (pp.Field('datetime',
              type=pd.DateTime()), (datetime.datetime(2016,
                                                      8,
                                                      30,
                                                      12,
                                                      40,
                                                      tzinfo=Timezone()),
                                    '30.08.2016 12:40:00')),
    (pp.Field('daterange', type=pd.DateRange()), (pd.DateRange().adjust_value(
        (datetime.date(1975, 8, 30),
         datetime.date(2016, 8, 30))), ('30.08.1975', '30.08.2016'))),
コード例 #24
0
ファイル: misc.py プロジェクト: cerha/pytis
    def fields(self):
        return (
            # Basic fields
            Field('text', _("Text"), type=pd.String(maxlen=50), width=30,
                  editable=computer(self._editable)),
            Field('completion', _("Completion"), type=pd.String(maxlen=20),
                  editable=computer(self._editable),
                  completer=('John', 'Jane', 'Joe', 'Judith', 'Jeremy',
                             'Peter', 'Paul', 'Paula', 'Richard', 'Samantha', 'Samuel',
                             'Steve', 'Sue'),
                  descr=_("Text entry with autocompletion.  The 'completer' provides "
                          "available completions.  As opposed to enumerator (which "
                          "also provides autocompletion values), completer has no "
                          "effect on validation. You can define a static (like here), "
                          "dynamic or database connected list of completions.")),
            Field('multiline', _("Multiline"), type=pd.String(), width=30, height=4,
                  editable=computer(self._editable)),
            Field('password', _("Password"), type=pd.Password(maxlen=20, verify=True),
                  editable=computer(self._editable), width=14,
                  descr=_("Password field doesn't display the current value.  If 'verify' "
                          "is set to True in field's type, the field requires the value to "
                          "be entered twice and validation makes sure both values match.")),
            Field('number', _("Number"), type=pd.Integer(), default=0,
                  editable=computer(self._editable),
                  descr=_("A simple numeric field.")),
            Field('slider', _("Slider"), type=pd.Integer(minimum=20, maximum=50),
                  default=30, slider=True, width=2,
                  editable=computer(self._editable),
                  descr=_("A simple numeric field.")),
            Field('float', _("Decimal"), type=pd.Float(precision=2), default=0,
                  editable=computer(self._editable)),
            Field('date', _("Date"), default=pd.Date.datetime, type=pd.Date(),
                  editable=computer(self._editable),
                  descr=_("Date entry field with a calendar control and a default value.")),
            Field('time', _("Time"), type=pytis.data.Time(),
                  editable=computer(self._editable)),
            Field('datetime', _("Date and time"), type=pytis.data.DateTime(),
                  editable=computer(self._editable)),
            Field('file', _("File"), type=pytis.data.Binary(),
                  editable=computer(self._editable)),
            Field('image', _("Image"), type=pytis.data.Image(),
                  editable=computer(self._editable)),
            Field('color', _("Color"), type=pytis.data.Color(),
                  editable=computer(self._editable)),

            # Enumeration fields
            Field('editable', _("Check box"), type=pd.Boolean(), default=True,
                  descr=_("Check/uncheck this checkbox to enable/disable all other "
                          "form fields.  This field demonstrates a simple boolean "
                          "checkbox field.  It also demonstrates how to make fields "
                          "editable based on the values of some other fields (any "
                          "more complicated logic is possible in the 'computer' of "
                          "the 'editable' property in field specification). "
                          "Finally it demonstrates how all field types look in the "
                          "editable and non-editable state.")),
            Field('choice', _("Choice"), type=pd.String(not_null=True, maxlen=2),
                  codebook='cb.Continents',
                  selection_type=SelectionType.CHOICE,
                  editable=computer(self._editable),
                  descr=_("Simple pull-down menu selection.")),
            Field('radio', _("Radio box"), not_null=True,
                  enumerator=self._Fruits,
                  editable=computer(self._editable),
                  selection_type=SelectionType.RADIO,
                  descr=_("Radio box selection.  The enumeration is defined statically by "
                          "an Enumeration class.")),
            Field('listbox', _("List box"), not_null=True,
                  enumerator=self._Fruits,
                  selection_type=SelectionType.LISTBOX,
                  editable=computer(self._editable),
                  descr=_("List selection which becomes scrollable when the number of "
                          "items exceeds its height.")),
            Field('codebook', _("Codebook"), type=pd.String(not_null=True, maxlen=2),
                  codebook='cb.Countries', width=2,
                  # SelectionType.CODEBOOK is actually the default when 'codebook' is set.
                  selection_type=SelectionType.CODEBOOK,
                  post_process=PostProcess.UPPER,
                  editable=computer(self._editable),
                  descr=_(
                      "This field provides a text entry for writing down the code directly.  "
                      "It most convenient when the codebook contains a relatively large number of "
                      "items while their codes are short and simple.  Then the user most often "
                      "knows the codes without looking them up.  Right from the text entry field, "
                      "there is a codebook invocation button, which allows the user to select the "
                      "item from a codebook form (when he doesn't remember the code or wants to "
                      "see the full listing of all available items for some other reason).  "
                      "Further on the right, there is a gray field called `display'.  It shows "
                      "the description of the currently selected item (eg. the full name for the "
                      "selected code).  Thus it provides immediate feedback when the user "
                      "modifies the value.  It is empty when the entered code is invalid (not "
                      "contained in the codebook).  It is updated with any change of the field "
                      "value.")),
            Field('listfield', _("List Field"), type=pd.String(not_null=True, maxlen=2),
                  codebook='cb.Countries', compact=True, height=6,
                  selection_type=SelectionType.LIST,
                  editable=computer(self._editable),
                  descr=_("This field also allows direct codebook manipulations through the row "
                          "context menu.")),

            # Range fields
            Field('intrange', _("Numeric range"), type=pytis.data.IntegerRange(),
                  editable=computer(self._editable)),
            Field('daterange', _("Date range"), type=pytis.data.DateRange(),
                  editable=computer(self._editable)),

        )
コード例 #25
0
ファイル: profiles.py プロジェクト: cerha/pytis
class FormProfiles(Specification):
    public = True
    table = 'ev_pytis_form_profiles'
    title = _("Profily formulářů")
    fields = (
        Field('id', _("Identifier"), width=25, editable=Editable.NEVER),
        Field('title', _("Title"), width=25, editable=Editable.NEVER),
        Field('username',
              _("User"),
              not_null=True,
              codebook='statistics.FormUserList',
              value_column='login',
              editable=Editable.NEVER),
        Field('fullname',
              _("Fullname"),
              not_null=True,
              codebook='menu.ApplicationMenuM',
              width=80,
              column_width=30,
              editable=Editable.NEVER),
        Field('spec_name',
              _("Specification Name"),
              width=50,
              column_width=30,
              editable=Editable.NEVER),
        Field('form_name',
              _("Form Class"),
              width=50,
              column_width=30,
              editable=Editable.NEVER),
        Field('profile_id', _("Id profilu"), width=25,
              editable=Editable.NEVER),
        Field('pickled_filter', editable=Editable.NEVER),
        Field('pickled_params', editable=Editable.NEVER),
        Field('dump',
              _("Content"),
              width=80,
              height=8,
              editable=Editable.NEVER),
        Field('errors',
              _("Chyby"),
              width=80,
              height=8,
              editable=Editable.NEVER),
        Field('invalid',
              _("Neplatný"),
              type=pd.Boolean,
              virtual=True,
              width=1,
              computer=computer(lambda r, errors: errors is not None),
              editable=Editable.NEVER),
    )
    cb = CodebookSpec(display='title')
    columns = ('title', 'profile_id', 'username', 'spec_name', 'form_name',
               'invalid')
    layout = HGroup(('title', 'profile_id', 'username'),
                    ('spec_name', 'form_name', 'dump', 'errors'))
    profiles = (
        Profile('invalid-profiles',
                _("Neplatné profily"),
                filter=pd.NE('errors', pd.sval(None))),
        Profile('user-profiles',
                _("Uživatelské profily"),
                filter=pd.WM('profile_id',
                             pd.WMValue(pd.String(), '_user_profile_*'))),
        Profile('system-profiles',
                _("Systémové profily"),
                filter=pd.NW('profile_id',
                             pd.WMValue(pd.String(), '_user_profile_*'))),
    )
コード例 #26
0
ファイル: misc.py プロジェクト: cerha/pytis
 def _country_filter(self, row, filter, switch):
     """Return the validity condition as pd.Operator instance."""
     cond = pd.WM('name', pd.WMValue(pd.String(), filter or '*'))
     if switch:
         cond = pd.AND(cond, pd.EQ('continent', pd.Value(pd.String(), 'EU')))
     return cond
コード例 #27
0
ファイル: test.py プロジェクト: cerha/pytis
    def _mega_row(self, new=False, row=None, singleline=False, **prefill):
        # TODO: This all-in-one row was historically used for all tests
        # but it proved to be problematic.  You can not see the definition
        # of the fields from paticular tests so it is hard to guess the test
        # logic.  Morover the specification is getting too complicated
        # and hard to maintain usable in all situations.  Thus new tests should
        # Define their own fields directly just for their purpose.

        class BigString(pd.String, pd.Big):
            pass

        class SpecialEnumerator(pd.FixedEnumerator):
            # This class is overriden just to allow definition of runtime_filter
            # and runtime_arguments for the same field (which is only important
            # to improve test coverage)

            def values(self, a=None):
                # Accepts argument a as returned by runtime_arguments.
                return super(SpecialEnumerator, self).values()

        fields = (
            pp.Field('a', type=pd.Integer(not_null=True)),
            pp.Field('b',
                     type=pd.Integer(not_null=True,
                                     enumerator=SpecialEnumerator(range(101))),
                     runtime_filter=pp.computer(
                         lambda r, a: lambda x: x % a == 0, validate=True),
                     runtime_arguments=pp.computer(lambda r, a: dict(a=a))),
            pp.Field('c', type=pd.Integer(not_null=True), default=lambda: 5),
            pp.Field('d',
                     type=pd.Integer(),
                     editable=pp.computer(lambda r, total: total > 5
                                          if total else False),
                     computer=pp.computer(lambda r, c: c * 2, validate=True)),
            pp.Field('fruit',
                     type=pd.String(),
                     codebook='Fruits',
                     display='title',
                     null_display='none'),
            pp.Field('fruit_code',
                     virtual=True,
                     computer=pp.CbComputer('fruit', 'code')),
            pp.Field('range',
                     type=pd.IntegerRange(),
                     visible=pp.computer(lambda r, a: a != 0)),
            pp.Field('total',
                     type=pd.Integer(),
                     virtual=True,
                     editable=pp.Editable.NEVER,
                     computer=pp.computer(lambda r, b, c: b + c,
                                          validate=True,
                                          fallback=0)),
            pp.Field('half_total',
                     type=pd.Integer(),
                     virtual=True,
                     editable=pp.Editable.NEVER,
                     computer=pp.computer(lambda r, total: total // 2
                                          if total is not None else None)),
            pp.Field('x', type=pd.Integer(), virtual=True, default=88),
            pp.Field('password', type=pd.Password(), virtual=True),
            pp.Field('big', type=BigString(), virtual=True),
            pp.Field('array',
                     type=pd.Array,
                     inner_type=pd.String,
                     codebook='Fruits',
                     display='title',
                     virtual=True),
        )

        class Fruits(pytis.presentation.Specification):
            fields = (
                pp.Field('id'),
                pp.Field('title'),
                pp.Field('code', type=pd.Integer()),
                pp.Field('tropical', type=pd.Boolean()),
            )
            data_cls = pd.MemData
            data = (('apl', 'Apple', 123, False), ('ban', 'Banana', 234, True),
                    ('str', 'Strawberry', 234, False), ('org', 'Orange', 456,
                                                        True))

        class TestResolver(pytis.util.Resolver):
            _specifications = {'Fruits': Fruits}

            def _get_object_by_name(self, name):
                try:
                    return self._specifications[name]
                except KeyError:
                    return super(TestResolver, self)._get_object_by_name(name)

        pytis.config.resolver = TestResolver()
        return self._row(fields,
                         row=row,
                         new=new,
                         singleline=singleline,
                         prefill=prefill)
コード例 #28
0
    def _reload_actions(self, record):
        import wiking

        def action_descr(module, action):
            if issubclass(module, wiking.PytisModule):
                for a in module.Spec.actions:
                    if a.name() == action:
                        return a.descr() or a.title()
            try:
                return dict(self._DEFAULT_ACTIONS)[action]
            except KeyError:
                method = getattr(module, 'action_' + action)
                docstring = method.__doc__
                return docstring and docstring.splitlines()[0] or _(
                    "Neuvedeno")

        module = self._module(record['modname'].value())
        if module:
            from pytis.form import run_dialog, CheckListDialog, create_data_object
            data = create_data_object(self._spec_name('Actions'))
            data.select(condition=pd.EQ('mod_id', record['mod_id']))
            existing_actions = {}
            while True:
                row = data.fetchone()
                if row is None:
                    break
                else:
                    existing_actions[row['name'].value()] = row['action_id']
            data.close()
            actions = [
                attr[7:] for attr in dir(module) if attr.startswith('action_')
                and isinstance(getattr(module, attr), collections.Callable)
            ]
            default_actions = [a[0] for a in self._DEFAULT_ACTIONS]
            # Order default actions first and in the order of self._DEFAULT_ACTIONS.
            order = lambda a: a in default_actions and (default_actions.index(
                a) + 1) or a
            actions.sort(lambda a, b: cmp(order(a), order(b)))
            descriptions = [action_descr(module, action) for action in actions]
            result = run_dialog(
                CheckListDialog,
                title=_("Nalezené akce"),
                message=_("Zaškrtněte akce, které chcete zpřístupnit webovým "
                          "uživatelům:"),
                items=zip([a in existing_actions for a in actions], actions,
                          descriptions),
                columns=(_("Action"), _("Description")))
            if result is not None:
                # TODO: Use a transaction.  Respect existing actions.
                for i, action in enumerate(actions):
                    if result[i]:
                        description_value = pd.Value(pd.String(),
                                                     descriptions[i] or None)
                        try:
                            key = existing_actions[action]
                        except KeyError:
                            rowdata = [('mod_id', record['mod_id']),
                                       ('name', pd.Value(pd.String(), action)),
                                       ('description', description_value)]
                            data.insert(pd.Row(rowdata))
                        else:
                            data.update(
                                (key, ),
                                pd.Row((('description', description_value), )))
コード例 #29
0
 def _parent_filter(self, record, lang):
     return pd.EQ('lang', pd.Value(pd.String(), lang))
コード例 #30
0
 def fields(self):
     return (
         Field('menu_id'),
         Field('menu_item_id'),
         Field('tree_order'),
         Field('tree_order_nsub'),
         Field(
             'identifier',
             _("Identifier"),
             width=20,
             fixed=True,
             editable=ONCE,
             type=pd.RegexString(maxlen=32,
                                 not_null=True,
                                 regex='^[a-zA-Z][0-9a-zA-Z_-]*$'),
             descr=
             _("Identifikátor bude vystupovat jako vnější adresa stránky.  "
               "Může být použit "
               "v odkazech na tuto stránku v rámci textu jiných stránek. Platný "
               "identifikátor může obsahovat pouze písmena bez diakritiky, číslice, "
               "pomlčky a podtržítka a musí začínat písmenem.")),
         Field('lang',
               _("Jazyk"),
               editable=ONCE,
               codebook=self._spec_name('Languages'),
               value_column='lang',
               not_null=True,
               selection_type=pp.SelectionType.CHOICE),
         Field('title_or_identifier',
               _("Title"),
               width=30,
               type=_TreeOrder()),
         Field('title',
               _("Title"),
               width=20,
               type=pd.String(maxlen=32, not_null=True),
               descr=_("Název položky menu - krátký a výstižný.")),
         Field(
             'heading',
             _("Nadpis"),
             width=32,
             type=pd.String(maxlen=40),
             descr=
             _("Hlavní nadpis při zobrazení stránky.  Pokud ponecháte nevyplněné, "
               "použije se název položky.  Ten je ale někdy kvůli použití v menu příliš "
               "krátký, takže zde je možné určit jeho delší variantu.")),
         Field(
             'description',
             _("Description"),
             width=72,
             descr=_(
                 "Stručný popis stránky (zobrazen v menu jako tooltip).")),
         Field(
             'content',
             _("Content"),
             compact=True,
             height=20,
             width=80,
             text_format=pp.TextFormat.LCG,
             attachment_storage=self._attachment_storage,
             descr=
             _("Text stránky formátovaný jako LCG strukturovaný text (wiki)"
               )),
         Field('mod_id',
               _("Modul"),
               type=pd.Integer(),
               not_null=False,
               codebook=self._spec_name('Modules', False),
               allow_codebook_insert=True,
               descr=_(
                   "Vyberte rozšiřující modul zobrazený uvnitř stránky.  "
                   "Ponechte prázdné pro prostou textovou stránku.")),
         Field('modname', _("Modul")),
         Field(
             'parent',
             _("Parent item"),
             type=pd.Integer(),
             not_null=False,
             codebook=self._spec_name('MenuParents', False),
             value_column='menu_item_id',
             runtime_filter=computer(self._parent_filter),
             descr=_(
                 "Vyberte bezprostředně nadřízenou položku v hierarchii menu.  Ponechte "
                 "prázdné pro stránky na nejvyšší úrovni menu.")),
         Field(
             'published',
             _("Zveřejněno"),
             width=6,
             default=True,
             fixed=True,
             descr=_(
                 "Umožňuje řídit dostupnost dané položky nezávisle pro kažou jazykovou "
                 "verzi.")),
         Field(
             'ord',
             _("Ordering"),
             width=8,
             editable=ALWAYS,
             fixed=True,
             descr=
             _("Enter a number denoting the order of the item in menu between "
               "pages of the same hierarchy level.  Leave empty to put the item "
               "automatically to bottom.")),
     )