def test_hidden(self): row, fields = self._fields(( pp.Field('numeric', type=pd.Integer()), pp.Field('string', type=pd.String()), pp.Field('multiline', type=pd.String(), height=4), pp.Field('date', type=pd.Date()), pp.Field('datetime', type=pd.DateTime()), pp.Field('boolean', type=pd.Boolean()), pp.Field('checklist', type=pd.Array(inner_type=pd.Integer()), enumerator=pd.FixedEnumerator(range(10)), selection_type=pp.SelectionType.CHECKLIST), pp.Field('choice', type=pd.Integer(), enumerator=pd.FixedEnumerator(range(10)), selection_type=pp.SelectionType.CHOICE), pp.Field('radio', type=pd.Integer(), enumerator=pd.FixedEnumerator(range(10)), selection_type=pp.SelectionType.RADIO), )) context = self._export_context('cs') for fid, value, exported in ( ('numeric', 5, '5'), ('string', 'x', 'x'), ('multiline', 'xxx\nxxx', 'xxx\nxxx'), ('date', datetime.date(2016, 8, 30), '30.08.2016'), ('datetime', datetime.datetime(2016, 8, 30, 12, 40, tzinfo=context.timezone()), '30.08.2016 12:40:00'), ('boolean', True, 'T'), ('boolean', False, 'F'), ('checklist', (pd.ival(1), pd.ival(4)), ('1', '4')), ('choice', 5, '5'), ('radio', 5, '5'), ): field = pu.find(fid, fields, key=lambda f: f.id) row[fid] = pd.Value(row.type(fid), value) self.assertEqual(context.localize(field.hidden(context)), ''.join('<input type="hidden" name="%s" value=%s/>' % (fid, saxutils.quoteattr(v)) for v in pu.xtuple(exported))) error = field.validate(self.Request(params={fid: exported}), context.locale_data()) self.assertIs(error, None, "%s: %s" % (error and error.message(), exported)) self.assertEqual(row[fid].value(), value)
def _find_column(self, cid): return find(cid, self._columns, key=lambda c: c.id())
def cmd_type_kwargs(filename, lines, type_map=None): """Convert type kwargs in field specifications to type instance aruments. The optional argument 'type_map' may be used to supply type classes to fields where the type can not be determined from the field specification itself. The value of the argument is a file name as a string. The current type map file format follows the format of pytis/tools/dump-specifications.py output. """ lines_to_delete = [] type_kwargs = ('not_null', 'unique', 'constraints', 'minlen', 'maxlen', 'minimum', 'maximum', 'encrypted', 'precision', 'format', 'mindate', 'maxdate', 'utc', 'validation_messages', 'inner_type', 'minsize', 'maxsize', 'formats', 'strength', 'md5', 'verify', 'text',) if type_map: type_dict = make_type_map(type_map) else: type_dict = None for node, args, cls in FieldLocator().search_fields(lines, filename): #print "*", filename, node.lineno, node.args and unparse(node.args[0]) or '?' type_cls = None type_arg = find('type', args, key=lambda a: a.name) type_args = [arg for arg in args if arg.name in type_kwargs] if args and args[-1].end is None and (args[-1] in type_args or args[-1] == type_arg and type_args): # The end of the last argument may not be always obvious! print ("File %s, line %d\n" " Can't determine end of '%s' argument when it is the last argument.\n" " Please reformat the source code.") % \ (filename, args[-1].start.ln + 1, args[-1].name) continue if type_args and not type_arg: argnames = [a.name for a in type_args] if all(name in ('not_null', 'unique') for name in argnames): continue if 'maxlen' in argnames: type_cls = 'pd.String' elif 'precision' in argnames: type_cls = 'pd.Float' elif 'utc' in argnames: type_cls = 'pd.DateTime' elif 'format' in argnames: fmt = unparse(find('format', type_args, key=lambda a: a.name).value) if fmt.startswith('pd.Date.'): type_cls = 'pd.Date' elif fmt.startswith('pd.Time.'): type_cls = 'pd.Time' elif fmt.startswith('pd.DateTime.'): type_cls = 'pd.DateTime' if type_cls is None: field_id = '.'.join((os.path.splitext(os.path.split(filename)[-1])[0], cls, node.args and eval(unparse(node.args[0])) or '?')) if type_dict: type_cls = type_dict.get(field_id) #if type_cls: # print ("File %s, line %d\n" # " Data type %s of field %s taken from type map %s.") % \ # (filename, node.lineno, type_cls, field_id, type_map) if type_cls is None: print ("File %s, line %d\n" " Can't determine type for %s (%s)") % \ (filename, node.lineno, field_id, ', '.join([unparse(a.kw) for a in type_args])) continue # Remove all directly passed type kwargs. for arg in type_args: lines[arg.start.ln] = (lines[arg.start.ln][:arg.start.offset] + lines[arg.end.ln][arg.end.offset:]) for ln in range(arg.start.ln + 1, arg.end.ln + 1): if ln not in lines_to_delete: lines_to_delete.append(ln) if range(arg.start.ln + 1, arg.end.ln + 1): lx = lines_to_delete[-1]+1 for a in args[args.index(arg)+1:]: if a.start.ln == arg.end.ln: if arg.start.ln == arg.end.ln: a.start.offset -= arg.end.offset - arg.start.offset if a.end and a.end.ln == a.start.ln: a.end.offset -= arg.end.offset - arg.start.offset else: start_ln, start_offset = a.start.ln, a.start.offset a.start.ln = arg.start.ln a.start.offset = arg.start.offset + a.start.offset - arg.end.offset if a.end and a.end.ln == start_ln: a.end.ln = arg.start.ln a.end.offset = a.start.offset + a.end.offset - start_offset # Move type direct kwargs to type instance kwargs. if type_arg and (type_args or not isinstance(type_arg.value, ast.Call)): if type_arg.start.ln == type_arg.end.ln: x = lines[type_arg.start.ln][type_arg.start.offset:type_arg.end.offset] else: x = (lines[type_arg.start.ln][type_arg.start.offset:].strip() + ' ' + ''.join([lines[ln].strip() + ' ' for ln in range(type_arg.start.ln+1, type_arg.end.ln) if ln not in lines_to_delete]) + lines[type_arg.end.ln][:type_arg.end.offset].strip()) x = x.strip(',').strip() if x != unparse(type_arg.kw): print ("File %s, line %d\n" " Warning: Can't verify position, please check this change.\n" " '%s'\n '%s'") % \ (filename, type_arg.start.ln - len([l for l in lines_to_delete if l < type_arg.start.ln]), x, unparse(type_arg.kw)) ln, offset = type_arg.end.ln, type_arg.end.offset if isinstance(type_arg.value, ast.Call): offset -= 1 insert = ', '.join([unparse(a.kw) for a in type_args if unparse(a.kw) not in unparse(type_arg.value)]) if lines[ln][offset - 1] != '(': insert = ', ' + insert else: insert = '(' + ', '.join([unparse(a.kw) for a in type_args]) + ')' # Insert type kwarg as an instance. elif type_args: assert type_cls is not None ln, offset = type_args[0].start.ln, type_args[0].start.offset insert = ', type=%s(%s)' % (type_cls, ', '.join([unparse(a.kw) for a in type_args])) else: insert = None if insert: lines[ln] = lines[ln][:offset] + insert + lines[ln][offset:] for i, ln in enumerate(sorted(lines_to_delete)): del lines[ln - i]