def _update(self, data, key, **kwargs): row = self._row(data, **key) rowdata = self._values(data, changed=False, removed=False, **kwargs) if row is None: data.insert(pd.Row(self._values(data, **key) + rowdata)) elif not row['changed'].value() and any([row[k].value() != v.value() for k, v in rowdata]): data.update((row[0],), pd.Row(rowdata))
def dbinsert(spec, row, transaction=None): """Provede insert do tabulky dané specifikací. Argumenty: spec -- název specifikace datového objektu nad kterým má být proveden insert. row -- sekvence dvouprvkových sekvencí (id, value) nebo instance pd.Row transaction -- instance pd.DBTransactionDefault Vrací počet vložených řádků. """ assert isinstance(row, (pd.Row, tuple, list)), row import pytis.form if isinstance(row, (tuple, list)): for item in row: if not isinstance(item, (tuple, list)) or len(item) != 2: errmsg = 'Column definition must be (ID, VALUE) pair.' raise ProgramError(errmsg) k, v = item if not isinstance(k, basestring): errmsg = 'Invalid column id %s' % k raise ProgramError(errmsg) if not isinstance(v, pd.Value): errmsg = 'Invalid column value %s' % v raise ProgramError(errmsg) row = pd.Row(row) data = pytis.util.data_object(spec) success, result = pytis.form.db_operation(data.insert, row, transaction=transaction) return result
def test_display(self): C = pd.ColumnSpec S = pd.String V = pd.Value rows = [ pd.Row((('x', V(S(), x)), ('y', V(S(), y)))) for x, y in (('1', 'FIRST'), ('2', 'SECOND'), ('3', 'THIRD')) ] edata = pd.DataFactory(pd.MemData, (C('x', S()), C('y', S())), data=rows) enum = pd.DataEnumerator(edata) key = C('a', pd.Integer()) columns = (key, C('b', S(enumerator=enum)), C('c', S(enumerator=enum)), C('d', S(enumerator=enum))) data = pd.Data(columns, key) fields = ( Field('a'), Field('b', display='y'), Field('c', display=lambda x: '-' + x + '-'), Field('d', display=lambda row: row['y'].value().lower()), ) row = pp.PresentedRow(fields, data, None, prefill={ 'b': '2', 'c': '3', 'd': '1' }) self.assertEqual(row.display('a'), '') self.assertEqual(row.display('b'), 'SECOND') self.assertEqual(row.display('c'), '-3-') self.assertEqual(row.display('d'), 'first')
def run(): if '--help' in sys.argv: usage() try: pytis.config.add_command_line_options(sys.argv) if len(sys.argv) > 1: usage() except getopt.GetoptError as e: usage(e.msg) wiking.cfg.user_config_file = pytis.config.config_file wiking.cms.cfg.user_config_file = pytis.config.config_file pytis.config.dblisten = False pytis.config.log_exclude = [pytis.util.ACTION, pytis.util.EVENT, pytis.util.DEBUG, pytis.util.OPERATIONAL] while True: try: data = pd.dbtable('users', ('uid', 'login', 'password'), pytis.config.dbconnection) except pd.DBLoginException as e: if pytis.config.dbconnection.password() is None: import getpass login = pytis.config.dbuser password = getpass.getpass("Enter database password for %s: " % login) pytis.config.dbconnection.update_login_data(user=login, password=password) else: break storage = wiking.Pbkdf2PasswordStorage() transaction = pd.transaction() data.select(transaction=transaction) n = 0 plain = 0 try: while True: row = data.fetchone() if row is None: break orig_prefix, orig_password = row['password'].value().split(':', 1) if orig_prefix == 'md5u': prefix = 'pbkdf2/md5' elif orig_prefix == 'plain': prefix = 'pbkdf2' plain += 1 else: continue password = prefix + ':' + storage.stored_password(orig_password) data.update(row['uid'], pd.Row([('password', pd.sval(password))]), transaction=transaction) n += 1 except Exception: try: transaction.rollback() except Exception: pass sys.stderr.write("Transaction rolled back.\n") raise else: print("Total %d passwords updated (%d from plain text, %d from md5)." % \ (n, plain, n - plain)) transaction.commit() transaction.close()
def test_original_row(self): r = pd.Row([(k, pd.Value(pd.Integer(), v)) for k, v in dict(a=None, b=6, c=None, d=3).items()]) row = self._mega_row(new=True, row=r, b=22, c=33, d=44) r1 = row.original_row() self._check_values(r1, a=None, b=22, c=33, d=44) r2 = row.original_row(initialized=False) self._check_values(r2, a=None, b=6, c=None, d=3)
def __getitem__(self, key): if self._row is None: # Perform the database access only when needed. rows = self._data.get_rows(limit=1, **self._kwargs) if rows: self._row = rows[0] else: self._row = pd.Row(()) return self._row[key].export()
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
def mark_products(product_id=None, mark=True): """Mark/unmark all products.""" assert isinstance(mark, bool) assert product_id is None or isinstance(product_id, (int, tuple, list)) row = pd.Row((('marked', pd.bval(mark)),)) if product_id is None: condition = pd.EQ('marked', pd.bval(not mark)) elif isinstance(product_id, (list, tuple)): condition = pd.OR(*[pd.EQ('product_id', pd.ival(x)) for x in product_id]) else: condition = pd.EQ('product_id', pd.ival(product_id)) import pytis.extensions return pytis.extensions.dbupdate_many('misc.Products', condition=condition, update_row=row)
def dbfunction(name, *args, **kwargs): """Deprecated. Use pytis.data.dbfunction instead. Nová funkce pytis.data.dbfunction má oproti této původní funkci několik odlišností, které je potřeba zohlednit při přepisu starého kódu na použití nové funkce. 1. Tato (původní) funkce vrací None pokud je hodnota některého z argumentů None aniž by došlo ke skutečnému vyvolání DB funkce (čemuž lze zabránit argumentem proceed_with_empty_values=False). Nová funkce toto nedělá a argument proceed_with_empty_values nemá. 2. Argumenty nové funkce se předávají vnitřní hodnotou a nikoliv jako sekvence dvouprvkových tuplů, ale přímo jako argumenty funkce. 3. Funkci je možné předat jako DB specifikaci. V tom případě je prováděna typová kontrola argumentů a výsledek může být jak množina řádků (tabulkové funkce), tak jednoduchá hodnota dle atributu multirow ve specifikaci. 4. pd.dbfunction nepoužívá obalení pomocí pf.db_operation(), takže to je potřeba případně přidat explicitně, kde je to potřeba (většinou by to potřeba být nemělo.). """ # TODO PY3: define keyword arguments in function definition. import pytis.form proceed_with_empty_values = kwargs.pop('proceed_with_empty_values', False) transaction = kwargs.pop('transaction', None) assert not kwargs if not proceed_with_empty_values and args and any(v.value() in (None, '') for k, v in args): return None def conn_spec(): return pytis.config.dbconnection success, function = pytis.form.db_operation(pd.DBFunctionDefault, name, conn_spec) success, result = pytis.form.db_operation(function.call, pd.Row(args), transaction=transaction) if not success: return None if len(result) == 1 and len(result[0]) == 1: return result[0][0].value() return result
def _update_spec_help(self, spec_name): if self._done.get(spec_name): return self._done[spec_name] = True resolver = pytis.util.resolver() try: view_spec = resolver.get(spec_name, 'view_spec') except pytis.util.ResolverError as e: print(e) return description = view_spec.description() help_text = (view_spec.help() or '').strip() or None self._update(self._spec_help_data, dict(spec_name=spec_name), description=description, help=help_text) data = self._spec_help_items_data for kind, items in (('field', view_spec.fields()), ('profile', view_spec.profiles().unnest()), ('binding', view_spec.bindings()), ('action', view_spec.actions(unnest=True))): for item in items: self._update(data, dict(spec_name=spec_name, kind=kind, identifier=item.id()), content=item.descr()) # Items which were modified (content changed by hand) are kept with # the 'removed' flag set, since the texts may be reused for other # items in case of identifier change or other rearrangements. It # will also automatically resurrect texts for items which are # removed temporarily (eg. commented out) which is quite common # during development. Items which were not ever modified or have # no content may be safely deleted (they contain no hand-edited # data). conds = [pd.EQ('spec_name', pd.sval(spec_name)), pd.EQ('kind', pd.sval(kind)), pd.NOT(pd.ANY_OF('identifier', *[pd.sval(item.id()) for item in items])), ] data.delete_many(pd.AND(*(conds + [pd.OR(pd.EQ('changed', pd.bval(False)), pd.EQ('content', pd.sval(None)))]))) data.update_many(pd.AND(*(conds + [pd.EQ('removed', pd.bval(False))])), pd.Row(self._values(data, removed=True)))
def _data_row(self, row, **values): return pd.Row([(f.id(), pd.Value(f.type(), values.get(f.id()))) for f in row.fields() if not f.virtual()])
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), )))
def run(): if '--help' in sys.argv: usage() try: pytis.config.add_command_line_options(sys.argv) if len(sys.argv) > 1: usage() except getopt.GetoptError as e: usage(e.msg) wiking.cfg.user_config_file = pytis.config.config_file pytis.config.dblisten = False pytis.config.log_exclude = [pytis.util.ACTION, pytis.util.EVENT, pytis.util.DEBUG, pytis.util.OPERATIONAL] while True: try: data = pd.dbtable('cms_page_attachments', ('attachment_id', 'filename', 'width', 'height', 'image', 'image_width', 'image_height', 'thumbnail', 'thumbnail_size', 'thumbnail_width', 'thumbnail_height'), pytis.config.dbconnection) except pd.DBLoginException as e: if pytis.config.dbconnection.password() is None: import getpass login = pytis.config.dbuser password = getpass.getpass("Enter database password for %s: " % login) pytis.config.dbconnection.update_login_data(user=login, password=password) else: break image_screen_size = wiking.cms.cfg.image_screen_size image_thumbnail_sizes = wiking.cms.cfg.image_thumbnail_sizes transaction = pd.transaction() data.select(transaction=transaction) try: while True: row = data.fetchone() if row is None: break ext = os.path.splitext(row['filename'].value())[1].lower() path = os.path.join(wiking.cms.cfg.storage, pytis.config.dbname, 'attachments', row['attachment_id'].export() + (ext or '.')) attachment = open(path, 'rb') try: image = PIL.Image.open(attachment) except IOError as e: continue sys.stderr.write("Resizing %s (%dx%d): " % (row['filename'].value(), image.size[0], image.size[1])) thumbnail_size = row['thumbnail_size'].value() if thumbnail_size is None: thumbnail_value, real_thumbnail_size = None, (None, None) else: if thumbnail_size == 'small': size = image_thumbnail_sizes[0] elif thumbnail_size == 'medium': size = image_thumbnail_sizes[1] else: size = image_thumbnail_sizes[2] thumbnail_value, real_thumbnail_size = resize(image, (size, size)) sys.stderr.write("%dx%d, " % real_thumbnail_size) resized_image_value, resized_image_size = resize(image, image_screen_size) sys.stderr.write("%dx%d\n" % resized_image_size) values = dict( width=image.size[0], height=image.size[1], thumbnail=thumbnail_value, thumbnail_width=real_thumbnail_size[0], thumbnail_height=real_thumbnail_size[1], image=resized_image_value, image_width=resized_image_size[0], image_height=resized_image_size[1], ) r = pd.Row([(key, pd.Value(row[key].type(), value)) for key, value in values.items()]) data.update(row['attachment_id'], r, transaction=transaction) except Exception: try: transaction.rollback() except Exception: pass sys.stderr.write("Transaction rolled back.\n") raise else: sys.stderr.write("Transaction commited.\n") transaction.commit() transaction.close()
def _data_row(self, **values): return pd.Row([(c.id(), pd.Value(c.type(), values.get(c.id()))) for c in self._columns])