def migrate_schema_fields(self): for schemata in iterSchemataForType('DashboardPODTemplate'): for fieldName, field in getFieldsInOrder(schemata): # bypass interface methods if not IMethod.providedBy(field): # special handling for file field setattr(self.new, fieldName, getattr(self.old, fieldName, None))
def mapFieldTiles(self, settings, config, kwargs): args = { 'type': None, 'context': None, 'request': None, } args.update(kwargs) if args['type'] is None: return config prefixes = [] registry_omitted = settings.get( '%s.omitted_fields.%s' % (self.prefix, args['type'].replace('.', '_')), default=None, ) if registry_omitted is None: registry_omitted = settings.get( self.prefix + '.default_omitted_fields', default=[], ) for index, schema in enumerate(iterSchemataForType(args['type'])): prefix = '' if index > 0: prefix = schema.__name__ if prefix in prefixes: prefix = schema.__identifier__ prefixes.append(prefix) for fieldconfig in extractFieldInformation(schema, args['context'], args['request'], prefix): if fieldconfig['id'] not in registry_omitted: label = translate(fieldconfig['title'], context=args['request']) tileconfig = { 'id': 'formfield-form-widgets-%s' % (fieldconfig['name'], ), 'name': fieldconfig['name'], 'label': label, 'category': 'fields', 'tile_type': 'field', 'read_only': fieldconfig['readonly'], 'favorite': False, 'widget': fieldconfig['widget'], 'available_actions': self.actionsForWidget(settings, fieldconfig['widget']), } index = getCategoryIndex(config['tiles'], 'fields') if index is not None: config['tiles'][index]['tiles'].append(tileconfig) return config
def has_relation_fields(fti): for schema in iterSchemataForType(fti): for fieldname in schema: field = schema[fieldname] if (IRelationChoice.providedBy(field) or IRelationList.providedBy(field)): return True return False
def get_field_and_schema_for_fieldname(field_id, portal_type): """Get field and its schema from a portal_type.""" # Turn form.widgets.IDublinCore.title into title field_id = field_id.split(".")[-1] for schema in iterSchemataForType(portal_type): field = schema.get(field_id, None) if field is not None: return (field, schema)
def create_destination_document(self): # get all the metadata that will be set on the created file. # We blacklist some fields that should not be copied fields_to_skip = set(("file", "archival_file", "archival_file_state", "thumbnail", "preview", "digitally_available", "changeNote", "changed", "relatedItems",)) metadata = {} for schema in iterSchemataForType(self.context.portal_type): for name, schema_field in getFieldsInOrder(schema): if name in fields_to_skip: continue field_instance = schema_field.bind(self.context) metadata[name] = field_instance.get(self.context) command = CreateDocumentCommand(self.destination, None, None, **metadata) destination_document = command.execute() # We make it in shadow state until its file is set by the callback view destination_document.as_shadow_document() # Add marker interface. This should be useful in the future for # cleanup jobs, retries if the PDF was not delivered and so on. alsoProvides(destination_document, IDocumentSavedAsPDFMarker) # Add annotations needed for the SavePDFDocumentUnder view. annotations = IAnnotations(destination_document) annotations[PDF_SAVE_SOURCE_UUID_KEY] = IUUID(self.context) annotations[PDF_SAVE_SOURCE_VERSION_KEY] = self.version_id # The missing_value attribute of a z3c-form field is used # as soon as an object has no default_value i.e. after creating # an object trough the command-line. # # Because the relatedItems field needs a list as a missing_value, # we will fall into the "mutable keyword argument"-python gotcha. # The relatedItems will be shared between the object-instances. # # Unfortunately the z3c-form field does not provide a # missing_value-factory (like the defaultFactory) which would be # necessary to fix this issue properly. # # As a workaround we make sure that the new document's relatedItems # is different object from the source document's. IRelatedDocuments(destination_document).relatedItems = list( IRelatedDocuments(destination_document).relatedItems) IRelatedDocuments(destination_document).relatedItems.append( RelationValue(getUtility(IIntIds).getId(self.context))) msg = _(u'Document ${document} was successfully created in ${destination}', mapping={"document": destination_document.title, "destination": self.destination.title}) api.portal.show_message(msg, self.request, type='info') return destination_document
def __call__(self): fti = self.context result = { # '@context': 'http://www.w3.org/ns/hydra/context.jsonld', 'title': fti.id, 'type': 'object', '$schema': 'http://json-schema.org/draft-04/hyper-schema#', 'fieldsets': [], 'required': [], 'schemas': {}, 'properties': {}, } for schema in iterSchemataForType(fti.id): schema_serializer = getMultiAdapter((schema, fti, self.request), ISchemaSerializer) result['schemas'][schema_serializer.name] = schema_serializer() fieldsets = schema.queryTaggedValue(FIELDSETS_KEY, []) fieldset_fields = set() for fieldset in fieldsets: fields = fieldset.fields # Keep a list so we can figure out what doesn't belong # to a fieldset fieldset_fields.update(fields) # Write the fieldset and any fields it contains fieldset_serializer = getMultiAdapter( (fieldset, schema, fti, self.request), IFieldsetSerializer) result['fieldsets'].append({ 'id': fieldset_serializer.name, 'title': fieldset_serializer.name, 'fields': fieldset_serializer() }) # Handle any fields that aren't part of a fieldset non_fieldset_fields = [ name for name, field in sortedFields(schema) if name not in fieldset_fields ] for fieldName in non_fieldset_fields: field = schema[fieldName] if field.required: result['required'].append(fieldName) serializer = getMultiAdapter( (field, schema, fti, self.request), IFieldSerializer) result['properties'][fieldName] = serializer() invariants = [] for i in schema.queryTaggedValue('invariants', []): invariants.append("%s.%s" % (i.__module__, i.__name__)) result['invariants'] = invariants if len(result['fieldsets']) == 0: del result['fieldsets'] return result
def mapFieldTiles(self, settings, config, kwargs): args = { 'type': None, 'context': None, 'request': None, } args.update(kwargs) if args['type'] is None: return config prefixes = [] registry_omitted = settings.get( '%s.omitted_fields.%s' % (self.prefix, args['type'].replace('.', '_')), default=None, ) if registry_omitted is None: registry_omitted = settings.get( self.prefix + '.default_omitted_fields', default=[], ) for index, schema in enumerate(iterSchemataForType(args['type'])): prefix = '' if index > 0: prefix = schema.__name__ if prefix in prefixes: prefix = schema.__identifier__ prefixes.append(prefix) for fieldconfig in extractFieldInformation( schema, args['context'], args['request'], prefix): if fieldconfig['id'] not in registry_omitted: label = translate(fieldconfig['title'], context=args['request']) tileconfig = { 'id': 'formfield-form-widgets-%s' % ( fieldconfig['name'], ), 'name': fieldconfig['name'], 'label': label, 'category': 'fields', 'tile_type': 'field', 'read_only': fieldconfig['readonly'], 'favorite': False, 'widget': fieldconfig['widget'], 'available_actions': self.actionsForWidget( settings, fieldconfig['widget'] ), } index = getCategoryIndex(config['tiles'], 'fields') if index is not None: config['tiles'][index]['tiles'].append(tileconfig) return config
def set_field_language_independent(self, portal_type, field, value='1'): """Set the given field in the given portal type language independent or unset from being one """ for schema in iterSchemataForType(portal_type): if field in schema: ob = schema[field] if ILanguageIndependentField.providedBy(ob): if value.lower() not in ('true', 'on', 'yes', 'y', '1'): noLongerProvides(schema[ob], ILanguageIndependentField) else: if value.lower() in ('true', 'on', 'yes', 'y', '1'): alsoProvides(ob, ILanguageIndependentField)
def execute(self): obj = super(CreateDossierFromTemplateCommand, self).execute() schemas = iterSchemataForType(self.portal_type) for schema in schemas: schema_name = BEHAVIOR_INTERFACE_MAPPING.get( schema.getName(), schema.getName()) if schema_name not in self.additional_fields: continue behavior = schema(obj) for prop_name in self.additional_fields[schema_name]: setattr(behavior, prop_name, self.additional_fields[schema_name][prop_name]) return obj
def set_field_language_independent(self, portal_type, field, value="1"): """Set the given field in the given portal type language independent or unset from being one """ for schema in iterSchemataForType(portal_type): if field in schema: ob = schema[field] if ILanguageIndependentField.providedBy(ob): if value.lower() not in ("true", "on", "yes", "y", "1"): noLongerProvides(schema[ob], ILanguageIndependentField) else: if value.lower() in ("true", "on", "yes", "y", "1"): alsoProvides(ob, ILanguageIndependentField)
def set_field_language_independent(self, portal_type, field, value='1'): """Set the given field in the given portal type language independent or unset from being one """ disableCSRFProtection() for schema in iterSchemataForType(portal_type): if field in schema: ob = schema[field] if ILanguageIndependentField.providedBy(ob): if value.lower() not in ('true', 'on', 'yes', 'y', '1'): noLongerProvides(schema[ob], ILanguageIndependentField) else: if value.lower() in ('true', 'on', 'yes', 'y', '1'): alsoProvides(ob, ILanguageIndependentField)
def get_schema_info(portal_type, blacklist=None, whitelist=None): """Get a flat list of all fields in all schemas for a content-type. """ fields = [] for schema in iterSchemataForType(portal_type): for fieldname in schema: if blacklist: if fieldname not in blacklist: fields.append((fieldname, schema.get(fieldname))) elif whitelist: if fieldname in whitelist: fields.append((fieldname, schema.get(fieldname))) elif not blacklist and not whitelist: fields.append((fieldname, schema.get(fieldname))) return fields
def fields_list(context): portal = api.portal.get() ttool = api.portal.getToolByName(portal, 'translation_service') #annotations = IAnnotations(portal.request) #value = annotations.get(FIELD_LIST_CACHE, None) #if value is not None: # return value terms = [] # need to look up all the possible fields we can set on all the content # types we might update in the given folder found = {} terms = [ SimpleVocabulary.createTerm('', '', ''), SimpleVocabulary.createTerm('_path', '_path', 'Path'), SimpleVocabulary.createTerm('_url', '_url', 'URL of Item') ] # path is special and allows us to import to dirs and export resulting path allowed_types = [ IText, IBytes, IInt, IFloat, IDecimal, IChoice, IDatetime, ITime, IDate, IList, IRichText, INamedImageField ] for fti in get_allowed_types(context): portal_type = fti.getId() schemas = iterSchemataForType(portal_type) for _schema in schemas: for fieldid, field in getFieldsInOrder(_schema): if not any( [ftype.providedBy(field) for ftype in allowed_types]): continue if fieldid not in found: found[fieldid] = 1 title = ttool.translate(field.title) if not title: continue terms.append( SimpleVocabulary.createTerm(fieldid, fieldid, title)) value = SimpleVocabulary(terms) #annotations[FIELD_LIST_CACHE] = value return value
def get_field_names_for_type(self, portal_type): names = [] for schema in iterSchemataForType(self.portal_type): for name, field in getFieldsInOrder(schema): if name == 'changeNote': # The changeNote field from p.a.versioningbehavior # is a "fake" field - it never gets persisted, but # written to request annotations instead continue if name == 'reference_number': # reference_number is a special field. It never gets # set directly, but instead acts as a computed field # for all intents and purposes. continue names.append(name) return names
def dump(self, portal_type): log.info("Dumping schemas for portal_type %r" % portal_type) fti = self._get_fti(portal_type) type_title = translate_de(fti.title, domain=fti.i18n_domain) schemas = [] schema_dumper = SchemaDumper() for schema in iterSchemataForType(portal_type): schema_dump = schema_dumper.dump(schema) schemas.append(schema_dump) type_dump = OrderedDict(( ('portal_type', portal_type), ('title', type_title), ('schemas', schemas), )) return type_dump
def fields_list(context): portal = api.portal.get() ttool = api.portal.getToolByName(portal, 'translation_service') #annotations = IAnnotations(portal.request) #value = annotations.get(FIELD_LIST_CACHE, None) #if value is not None: # return value terms = [] # need to look up all the possible fields we can set on all the content # types we might update in the given folder found = {} terms = [SimpleVocabulary.createTerm('', '', ''), SimpleVocabulary.createTerm('_path', '_path', 'Path'), SimpleVocabulary.createTerm('_url', '_url', 'URL of Item')] # path is special and allows us to import to dirs and export resulting path allowed_types = [IText, IBytes, IInt, IFloat, IDecimal, IChoice, IDatetime, ITime, IDate] for fti in get_allowed_types(context): portal_type = fti.getId() schemas = iterSchemataForType(portal_type) for _schema in schemas: for fieldid, field in getFieldsInOrder(_schema): if not any([ftype.providedBy(field) for ftype in allowed_types]): continue if fieldid not in found: found[fieldid] = 1 title = ttool.translate(field.title) if not title: continue terms.append(SimpleVocabulary.createTerm(fieldid, fieldid, title)) value = SimpleVocabulary(terms) #annotations[FIELD_LIST_CACHE] = value return value
def getFieldsForDXType(self, typename): '''Returns schema fields (name and type) for the given DX typename.''' results = [] typesTool = getToolByName(self.context, 'portal_types') fti = typesTool.getTypeInfo(typename) if not fti: return results for schemata in iterSchemataForType(typename): for fieldName, field in schemata.namesAndDescriptions(): # ignore Dublin Core fields if fieldName in self.dx_metadata_fields: continue translated_title = translate(field.title) class_name = field.__class__.__name__ results.append( {'id': fieldName, 'title': '%s (%s)' % (translated_title, class_name), 'type': class_name}) return results
def inject_title_and_description_defaults(kw, portal_type, container): """If 'title' or 'description' fields have defaults, inject them into `kw`. These fields need special handling because they get set to an empty string in a hardcoded fashion in the P.CMFCore.PortalFolder.PortalFolderBase constructor if no *actual* value has been provided for them. This will later fool our set_default_values() because it thinks a legitimate value for these fields has already been persisted on the object, and will therefore not attempt to determine and set defaults for those fields. We therefore handle title and description differently by determining their defaults ahead of object construction time, and inject them into `kw` ( unless *actual* values are already provided in `kw` of course). """ to_check = ['title', 'description'] # Don't do anything for fields that have an *actual* value provided for field_name in kw: if field_name in to_check: to_check.remove(field_name) schemas = iterSchemataForType(portal_type) for schema in schemas: for name, field in getFieldsInOrder(schema): # Return early if no more fields are left to check. No need to # iterate over dozens of irrelevant fields. if not to_check: return for fn_to_check in to_check: if fn_to_check == name: dv = determine_default_value(field, container) # If there is a default, and there is no *actual* value # in `kw` that should be set, inject the default into `kw` if dv is not NO_DEFAULT_MARKER: kw[fn_to_check] = dv to_check.remove(name)
def mapFieldTiles(self, settings, config, kwargs): args = {"type": None, "context": None, "request": None} args.update(kwargs) if args["type"] is None: return config prefixes = [] for index, schema in enumerate(iterSchemataForType(args["type"])): prefix = "" if index > 0: prefix = schema.__name__ if prefix in prefixes: prefix = schema.__identifier__ prefixes.append(prefix) registry_omitted = settings.get( "%s.omitted_fields.%s" % (self.prefix, args["type"].replace(".", "_")), default=None ) if registry_omitted is None: registry_omitted = settings.get(self.prefix + ".default_omitted_fields", default=[]) for fieldconfig in extractFieldInformation(schema, args["context"], args["request"], prefix): if fieldconfig["id"] not in registry_omitted: label = translate(fieldconfig["title"], context=args["request"]) tileconfig = { "id": "formfield-form-widgets-%s" % (fieldconfig["name"],), "name": fieldconfig["name"], "label": label, "category": "fields", "tile_type": "field", "read_only": fieldconfig["readonly"], "favorite": False, "widget": fieldconfig["widget"], "available_actions": self.actionsForWidget(settings, fieldconfig["widget"]), } index = getCategoryIndex(config["tiles"], "fields") if index is not None: config["tiles"][index]["tiles"].append(tileconfig) return config
def execute(self): obj = super(CreateDossierFromTemplateCommand, self).execute() schemas = iterSchemataForType(self.portal_type) for schema in schemas: schema_name = BEHAVIOR_INTERFACE_MAPPING.get( schema.getName(), schema.getName()) if schema_name not in self.additional_fields: continue behavior = schema(obj) for prop_name in self.additional_fields[schema_name]: setattr(behavior, prop_name, self.additional_fields[schema_name][prop_name]) # Set blocking of role inheritance based on the template object if self.block_role_inheritance is not None: obj.__ac_local_roles_block__ = self.block_role_inheritance # Copy the local roles assignations over from the template if self.role_assignments is not None: manager = RoleAssignmentManager(obj) # Passing an empty iterable in here creates an empty mapping manager.add_or_update_assignments(self.role_assignments) return obj
def __getattribute__(self, name): if name.startswith('_') or name.startswith( 'portal_') or name.startswith('@@'): return super(SQLDexterityItem, self).__getattribute__(name) if name == 'id' and not self.sql_virtual: return super(SQLDexterityItem, self).__getattribute__(name) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if connection == None and self.portal_type: fti = queryUtility(IDexterityFTI, name=self.portal_type, default=None) if not fti: return None updateConnectionsForFti(fti) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if not connection: return super(SQLDexterityItem, self).__getattribute__(name) if name == 'UID': return self.portal_type + '-' + connection.sql_table + '-' + str( self.sql_id) if name == 'id' and 'id' not in connection.fieldnames.keys(): fti = ISQLTypeSettings( getUtility(IDexterityFTI, name=self.portal_type)) nameFromTitle = INameFromTitle(self, None) if nameFromTitle is not None and nameFromTitle.title: sql_folder_id = getattr(fti, 'sql_folder_id', 'data-' + self.portal_type) title = nameFromTitle.title if IRelationValue.providedBy(name): folder = sql_folder_id.to_object if folder: return INameChooser(folder).chooseName(title, self) return INameChooser(getSite()).chooseName(title, self) if name in connection.fieldnames.keys(): sql_column = connection.fieldnames[name] sql_item = self.getSQLItem() fieldname = 'name' if sql_item and sql_column: while '.' in sql_column: sql_item = getattr(sql_item, sql_column.split('.')[0], None) if sql_item and ( (isinstance(sql_item, list) and len(sql_item) > 1) or hasattr(sql_item, '_sa_instance_state')): value = sql_item fieldname = sql_column.split('.')[-1] break sql_column = '.'.join(sql_column.split('.')[1:]) else: value = getattr(sql_item, sql_column, None) #this is a relation if value and (isinstance(value, list) or hasattr(value, '_sa_instance_state')): sqlftis = [ a for a in getAllUtilitiesRegisteredFor(IDexterityFTI) if 'collective.behavior.sql.behavior.behaviors.ISQLContent' in a.behaviors and getattr(a, 'sql_table', None) ] if name == 'subject': return tuple( [getattr(a, fieldname, '') for a in value]) tableftis = [] for iface in iterSchemataForType(self.portal_type): if name in iface.names(): field = iface[name] if IList.providedBy(field): return [ getattr(a, fieldname, '') for a in value ] # hope it has name! elif ITuple.providedBy(field): return tuple( [getattr(a, fieldname, '') for a in value]) if IRelationChoice.providedBy( field) or IRelationList.providedBy(field): if IRelationChoice.providedBy(field): allowed_types = field.source.query.get( 'portal_type', []) else: allowed_types = field.value_type.source.query.get( 'portal_type', []) tableftis = [] for sqlfti in sqlftis: adapted = ISQLTypeSettings(sqlfti, None) if isinstance(value, list): classname = value[0].__class__.__name__ else: classname = value.__class__.__name__ if adapted and getattr( adapted, 'sql_table', None) == classname: if not allowed_types or sqlfti.id in allowed_types: tableftis.append(adapted) catalog = getToolByName( getSite(), 'portal_catalog') relations = [] for tablefti in tableftis: sql_id_column = getattr( tablefti, 'sql_id_column', 'id') valueids = [] if isinstance(value, list): valueids = [ getattr(a, sql_id_column, None) for a in value if getattr(a, sql_id_column, None) ] else: valueids = getattr( value, sql_id_column, None) brains = catalog.searchResults( portal_type=tablefti.id, sql_id=valueids) for brain in brains: relations.append( SQLRelationValue( brain.portal_type, brain.sql_id)) if IRelationChoice.providedBy( field) and relations: return relations[0] elif IRelationList.providedBy( field) and relations: return relations for iface in iterSchemataForType(self.portal_type): if name == 'subject': try: return tuple([ a.decode('utf-8') for a in literal_eval(value) ]) except: return tuple([a.strip() for a in value.split(',')]) if name in iface.names(): field = iface[name] if IRichText.providedBy(field): return RichTextValue(value) if INamedBlobImage.providedBy(field): return NamedBlobImage( base64.b64decode(value), filename=unicode(self.portal_type + self.id + ".jpg")) if IList.providedBy(field): try: return [ a.decode('utf-8') for a in literal_eval(value) ] except: return [a.strip() for a in value.split(',')] if ITuple.providedBy(field): try: return tuple([ a.decode('utf-8') for a in literal_eval(value) ]) except: return tuple( [a.strip() for a in value.split(',')]) if isinstance(value, unicode) or name == 'id': try: return str(value) except: pass return value return super(SQLDexterityItem, self).__getattribute__(name)
def reply(self): if len(self.params) not in (1, 2): return self._error( 400, "Bad Request", "Must supply either one (fieldname) or two (portal_type, fieldname) parameters" ) if len(self.params) == 1: # Edit intent # - context is the object to be edited # - schemata need to be determined via context self.intent = 'edit' portal_type = None fieldname = self.params[0] schemata = iterSchemata(self.context) else: # Add intent # - context is the container where the object will be created # - portal_type is the type of object to be created # - schemata need to be determined via portal_type self.intent = 'add' portal_type = self.params[0] fieldname = self.params[1] schemata = iterSchemataForType(portal_type) alsoProvides(self.request, IDuringContentCreation) field = get_field_by_name(fieldname, schemata) if field is None: return self._error(404, "Not Found", "No such field: %r" % fieldname) bound_field = field.bind(self.context) # Look for a source directly on the field first source = getattr(bound_field, 'source', None) # Handle ICollections (like Tuples, Lists and Sets). These don't have # sources themselves, but instead are multivalued, and their # items are backed by a value_type of Choice with a source if ICollection.providedBy(bound_field): source = self._get_value_type_source(bound_field) if not source: ftype = bound_field.__class__.__name__ return self._error( 404, "Not Found", "%r Field %r does not have a value_type of Choice with " "an ISource" % (ftype, fieldname)) if not ISource.providedBy(source): return self._error(404, "Not Found", "Field %r does not have a source" % fieldname) if not IIterableSource.providedBy(source): return self._error( 400, "Bad Request", "Source for field %r is not iterable. " % fieldname) serializer = getMultiAdapter((source, self.request), interface=ISerializeToJson) return serializer("{}/@sources/{}".format(self.context.absolute_url(), fieldname))
def __getattribute__(self, name): if name.startswith('_') or name.startswith('portal_') or name.startswith('@@') or name == 'sql_id': return super(SQLDexterityItem, self).__getattribute__(name) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if connection == None and self.portal_type: fti = queryUtility(IDexterityFTI, name=self.portal_type, default=None) if not fti: return None updateConnectionsForFti(fti) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if name == 'view': #be sure session and sqlitem are up to date self._v_sql_item = None connection.session.close() if not connection: return super(SQLDexterityItem, self).__getattribute__(name) if name == 'UID' and self.sql_virtual: return self.portal_type+'-'+connection.sql_table+'-'+str(self.sql_id) if name == 'id' and 'id' not in connection.fieldnames.keys(): if not self.sql_virtual: return super(SQLDexterityItem, self).__getattribute__(name) fti = ISQLTypeSettings(getUtility(IDexterityFTI, name=self.portal_type)) nameFromTitle = INameFromTitle(self, None) if nameFromTitle is not None and nameFromTitle.title: sql_folder_id = getattr(fti, 'sql_folder_id', 'data-'+self.portal_type) title = nameFromTitle.title folder = None if IRelationValue.providedBy(sql_folder_id): folder = sql_folder_id.to_object elif sql_folder_id and sql_folder_id.startswith('/'): portal = getToolByName(getSite(), 'portal_url').getPortalObject() folder = portal.restrictedTraverse(sql_folder_id) if folder: name = INameChooser(folder).chooseName(title, self) return name # return INameChooser(getSite()).chooseName(title, self) # return getUtility(IURLNormalizer).normalize(title) return self.sql_id if name in connection.fieldnames.keys(): sql_column = connection.fieldnames[name] sql_item = self.getSQLItem() try: sql_id = getattr(sql_item, connection.sql_id_column, None) except orm_exc.DetachedInstanceError: self._v_sql_item = None sql_item = self.getSQLItem() sql_id = getattr(sql_item, connection.sql_id_column, None) fieldname = 'name' if sql_item and sql_column: while '.' in sql_column: sql_key = sql_column.split('.')[0] sql_item = getattr(sql_item, sql_key, None) if isinstance(sql_item, list): value = sql_item fieldname = sql_column.split('.')[-1] break sql_column = '.'.join(sql_column.split('.')[1:]) else: if not isinstance(sql_item, list): value = getattr(sql_item, sql_column, None) if not value and (isinstance(value, list) or hasattr(value, '_sa_instance_state')): value = '' elif (isinstance(value, list) or hasattr(value, '_sa_instance_state')): sqlftis = [a for a in getAllUtilitiesRegisteredFor(IDexterityFTI) if 'collective.behavior.sql.behavior.behaviors.ISQLContent' in a.behaviors and getattr(a, 'sql_table', None)] if name == 'subject': return tuple([getattr(a, fieldname, '') for a in value]) tableftis = [] for iface in iterSchemataForType(self.portal_type): if name in iface.names(): field = iface[name] if IRelationChoice.providedBy(field) or IRelationList.providedBy(field): if IRelationChoice.providedBy(field): allowed_types = field.source.query.get('portal_type', []) else: allowed_types = field.value_type.source.query.get('portal_type', []) tableftis = [] for sqlfti in sqlftis: adapted = ISQLTypeSettings(sqlfti, None) if isinstance(value, list): classname = value[0].__class__.__name__ else: classname = value.__class__.__name__ if adapted and getattr(adapted, 'sql_table', None) == classname: if not allowed_types or sqlfti.id in allowed_types: tableftis.append(adapted) catalog = getToolByName(getSite(), 'portal_catalog') relations = [] for tablefti in tableftis: sql_id_column = getattr(tablefti, 'sql_id_column', 'id') valueids = [] if isinstance(value, list): valueids = [getattr(a, sql_id_column, None) for a in value if getattr(a, sql_id_column, None)] else: valueids = getattr(value, sql_id_column, None) valueids = [str(a) for a in valueids] brains = catalog.unrestrictedSearchResults(portal_type=tablefti.id, sql_id=valueids) for brain in brains: relations.append(SQLRelationValue(brain.portal_type, brain.UID, self)) if IRelationChoice.providedBy(field) and relations: return relations[0] elif IRelationList.providedBy(field) and relations: return relations elif ITuple.providedBy(field): return tuple([getattr(a, fieldname, '') for a in value]) elif IList.providedBy(field): return [getattr(a, fieldname, '') for a in value] elif value and isinstance(value, list): value = getattr(value[0], fieldname, '') for iface in iterSchemataForType(self.portal_type): if name == 'subject': try: return tuple([a.decode('utf-8') for a in literal_eval(value)]) except: return tuple([a.strip() for a in value.split(',')]) if name in iface.names(): field = iface[name] if IRichText.providedBy(field): if not value: return '' if not '<p' in value or not '<br' in value: value = '<p>'+'</p><p>'.join([a for a in value.split('\n') if a.strip()])+'</p>' # try: # value = str(value) # except: # try: # value = value.decode('utf-8') # except: # try: # value = value.encode('utf-8') # except: # pass return RichTextValue(unidecode(value)) elif INamedBlobImage.providedBy(field): return NamedBlobImage(base64.b64decode(value), filename=unicode(self.portal_type+self.id+".jpg")) elif ITuple.providedBy(field): if not value: return tuple([]) try: return tuple([a.decode('utf-8') for a in literal_eval(value)]) except: return tuple([a.strip() for a in value.split(',')]) elif IList.providedBy(field): if not value: return [] try: return [a.decode('utf-8') for a in literal_eval(value)] except: return [a.strip() for a in value.split(',')] elif IDatetime.providedBy(field) and hasattr(value, 'day') and not hasattr(value, 'hour'): value = datetime.datetime.combine(value, datetime.datetime.min.time()) if name in ['expiration_date','effective_date', 'effective', 'expires'] and hasattr(value, 'day') and not hasattr(value, 'hour'): value = datetime.datetime.combine(value, datetime.datetime.min.time()) if isinstance(value, unicode) or name == 'id': try: value = str(value) except: pass return value return super(SQLDexterityItem, self).__getattribute__(name)
def reply(self): if len(self.params) not in (1, 2): return self._error( 400, "Bad Request", "Must supply either one (fieldname) or two (portal_type, fieldname) parameters" ) if len(self.params) == 1: # Edit intent # - context is the object to be edited # - schemata need to be determined via context self.intent = 'edit' portal_type = None fieldname = self.params[0] schemata = iterSchemata(self.context) else: # Add intent # - context is the container where the object will be created # - portal_type is the type of object to be created # - schemata need to be determined via portal_type self.intent = 'add' portal_type = self.params[0] fieldname = self.params[1] schemata = iterSchemataForType(portal_type) alsoProvides(self.request, IDuringContentCreation) field = get_field_by_name(fieldname, schemata) if field is None: return self._error( 404, "Not Found", "No such field: %r" % fieldname ) bound_field = field.bind(self.context) # Look for a source directly on the field first source = getattr(bound_field, 'source', None) # Handle ICollections (like Tuples, Lists and Sets). These don't have # sources themselves, but instead are multivalued, and their # items are backed by a value_type of Choice with a source if ICollection.providedBy(bound_field): source = self._get_value_type_source(bound_field) if not source: ftype = bound_field.__class__.__name__ return self._error( 404, "Not Found", "%r Field %r does not have a value_type of Choice with " "an IQuerySource" % (ftype, fieldname)) if not IQuerySource.providedBy(source): return self._error( 404, "Not Found", "Field %r does not have an IQuerySource" % fieldname ) if 'query' not in self.request.form: return self._error( 400, "Bad Request", u'Enumerating querysources is not supported. Please search ' u'the source using the ?query= QS parameter' ) query = self.request.form['query'] result = source.search(query) terms = [] for term in result: terms.append(term) batch = HypermediaBatch(self.request, terms) serialized_terms = [] for term in batch: serializer = getMultiAdapter( (term, self.request), interface=ISerializeToJson ) serialized_terms.append(serializer()) result = { "@id": batch.canonical_url, "items": serialized_terms, "items_total": batch.items_total, } links = batch.links if links: result["batching"] = links return result
def link_items( # noqa context, source_obj, target_obj, relationship=None, fieldname='relatedItems', ): """Add a relation between two content objects. This uses the field 'relatedItems' and works for Archetypes and Dexterity. By passing a fieldname and a relationship it can be used to create arbitrary relations. Note: for the relatedItems field, Products.ATContentTypes uses 'relatesTo' and plone.app.contenttypes uses 'relatedItems'. We switch between these two, based on the source object. """ # relations from AT to DX and from DX to AT are only possible through # the referenceable-behavior: # plone.app.referenceablebehavior.referenceable.IReferenceable drop_msg = """Dropping reference from %s to %s since plone.app.referenceablebehavior is not enabled!""" if source_obj is target_obj: # Thou shalt not relate to yourself. return if IDexterityContent.providedBy(source_obj): source_type = 'DX' else: source_type = 'AT' if IDexterityContent.providedBy(target_obj): target_type = 'DX' else: target_type = 'AT' if relationship == referencedRelationship: # 'isReferencing' is the relationship for linkintegrity-relations. # Linkintegrity-relations should automatically be (re)created by # plone.app.linkintegrity.handlers.modifiedDexterity or # plone.app.linkintegrity.handlers.modifiedArchetype # when a ObjectModifiedEvent is thrown. # These relations are only created if the source has a richtext-field # with a link to the target and should not be created manually. if source_type == 'AT': modifiedArchetype(source_obj, None) if source_type == 'DX': modifiedDexterity(source_obj, None) return if source_type == 'AT': if relationship == 'relatedItems': relationship = 'relatesTo' # If there is any Archetypes-content there is also the # reference_catalog. For a site without AT content this # might not be there at all. reference_catalog = getToolByName(context, REFERENCE_CATALOG) uid_catalog = getToolByName(context, 'uid_catalog') if target_type == 'DX' and not is_referenceable(target_obj): logger.info(drop_msg % (source_obj.absolute_url(), target_obj.absolute_url())) return # Make sure both objects are properly indexed and referenceable # Some objects that werde just created (migrated) are not yet # indexed properly. source_uid = IUUID(source_obj) target_uid = IUUID(target_obj) _catalog = uid_catalog._catalog if not _catalog.indexes['UID']._index.get(source_uid): uid_catalog.catalog_object(source_obj, source_uid) modified(source_obj) if not _catalog.indexes['UID']._index.get(target_uid): uid_catalog.catalog_object(target_obj, target_uid) modified(target_obj) field = source_obj.getField(fieldname) if field is None: # we can't migrate if it doesn't actually have the field return accessor = field.getAccessor(source_obj) existing_at_relations = accessor() if not isinstance(existing_at_relations, list): existing_at_relations = [i for i in existing_at_relations] if not existing_at_relations: existing_at_relations = [] if target_obj in existing_at_relations: # don't do anything return target_uid = IUUID(target_obj) targetUIDs = [ ref.targetUID for ref in reference_catalog.getReferences( source_obj, relationship) ] if target_uid in targetUIDs: # Drop relation since the old ones are most likely broken. reference_catalog.deleteReference(source_obj, target_uid, relationship) existing_at_relations.append(target_obj) mutator = field.getMutator(source_obj) mutator(existing_at_relations) modified(source_obj) return if source_type is 'DX': if relationship == 'relatesTo': relationship = 'relatedItems' if target_type is 'AT' and not is_referenceable(source_obj): logger.info(drop_msg % (source_obj.absolute_url(), target_obj.absolute_url())) return # handle dx-relation if relationship == 'translationOf': # LinguaPlone relations make no sense for Dexterity return intids = getUtility(IIntIds) to_id = intids.getId(target_obj) # Before we set the fieldname attribute on the source object, # we need to know if this should be a list or a single item. # Might be None at the moment. # We check the field definition. fti = getUtility(IDexterityFTI, name=source_obj.portal_type) field = None for schema in iterSchemataForType(fti): field = schema.get(fieldname, None) if field is not None: break if isinstance(field, RelationList): existing_relations = getattr(source_obj, fieldname, []) if existing_relations is None: existing_relations = [] else: # purge broken relations existing_relations = [ i for i in existing_relations if i.to_id is not None ] if to_id not in [i.to_id for i in existing_relations]: existing_relations.append(RelationValue(to_id)) setattr(source_obj, fieldname, existing_relations) modified(source_obj) return return elif isinstance(field, (Relation, RelationChoice)): setattr(source_obj, fieldname, RelationValue(to_id)) modified(source_obj) return # We should never end up here! logger.warning( 'Ignoring unknown fieldname %s when restoring relation %s from %s to %s', fieldname, relationship, source_obj.absolute_url(), target_obj.absolute_url())
def __getattribute__(self, name): if name.startswith('_') or name.startswith('portal_') or name.startswith('@@'): return super(SQLDexterityItem, self).__getattribute__(name) if name == 'id' and not self.sql_virtual: return super(SQLDexterityItem, self).__getattribute__(name) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if connection == None and self.portal_type: fti = queryUtility(IDexterityFTI, name=self.portal_type, default=None) if not fti: return None updateConnectionsForFti(fti) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if not connection: return super(SQLDexterityItem, self).__getattribute__(name) if name == 'UID': return self.portal_type+'-'+connection.sql_table+'-'+str(self.sql_id) if name == 'id' and 'id' not in connection.fieldnames.keys(): fti = ISQLTypeSettings(getUtility(IDexterityFTI, name=self.portal_type)) nameFromTitle = INameFromTitle(self, None) if nameFromTitle is not None and nameFromTitle.title: sql_folder_id = getattr(fti, 'sql_folder_id', 'data-'+self.portal_type) title = nameFromTitle.title if IRelationValue.providedBy(name): folder = sql_folder_id.to_object if folder: return INameChooser(folder).chooseName(title, self) return INameChooser(getSite()).chooseName(title, self) if name in connection.fieldnames.keys(): sql_column = connection.fieldnames[name] sql_item = self.getSQLItem() fieldname = 'name' if sql_item and sql_column: while '.' in sql_column: sql_item = getattr(sql_item, sql_column.split('.')[0], None) if sql_item and ((isinstance(sql_item, list) and len(sql_item)>1) or hasattr(sql_item, '_sa_instance_state')): value = sql_item fieldname = sql_column.split('.')[-1] break sql_column = '.'.join(sql_column.split('.')[1:]) else: value = getattr(sql_item, sql_column, None) #this is a relation if value and (isinstance(value, list) or hasattr(value, '_sa_instance_state')): sqlftis = [a for a in getAllUtilitiesRegisteredFor(IDexterityFTI) if 'collective.behavior.sql.behavior.behaviors.ISQLContent' in a.behaviors and getattr(a, 'sql_table', None)] if name == 'subject': return tuple([getattr(a, fieldname, '') for a in value]) tableftis = [] for iface in iterSchemataForType(self.portal_type): if name in iface.names(): field = iface[name] if IList.providedBy(field): return [getattr(a, fieldname, '') for a in value] # hope it has name! elif ITuple.providedBy(field): return tuple([getattr(a, fieldname, '') for a in value]) if IRelationChoice.providedBy(field) or IRelationList.providedBy(field): if IRelationChoice.providedBy(field): allowed_types = field.source.query.get('portal_type', []) else: allowed_types = field.value_type.source.query.get('portal_type', []) tableftis = [] for sqlfti in sqlftis: adapted = ISQLTypeSettings(sqlfti, None) if isinstance(value, list): classname = value[0].__class__.__name__ else: classname = value.__class__.__name__ if adapted and getattr(adapted, 'sql_table', None) == classname: if not allowed_types or sqlfti.id in allowed_types: tableftis.append(adapted) catalog = getToolByName(getSite(), 'portal_catalog') relations = [] for tablefti in tableftis: sql_id_column = getattr(tablefti, 'sql_id_column', 'id') valueids = [] if isinstance(value, list): valueids = [getattr(a, sql_id_column, None) for a in value if getattr(a, sql_id_column, None)] else: valueids = getattr(value, sql_id_column, None) brains = catalog.searchResults(portal_type=tablefti.id, sql_id=valueids) for brain in brains: relations.append(SQLRelationValue(brain.portal_type, brain.sql_id)) if IRelationChoice.providedBy(field) and relations: return relations[0] elif IRelationList.providedBy(field) and relations: return relations for iface in iterSchemataForType(self.portal_type): if name == 'subject': try: return tuple([a.decode('utf-8') for a in literal_eval(value)]) except: return tuple([a.strip() for a in value.split(',')]) if name in iface.names(): field = iface[name] if IRichText.providedBy(field): return RichTextValue(value) if INamedBlobImage.providedBy(field): return NamedBlobImage(base64.b64decode(value), filename=unicode(self.portal_type+self.id+".jpg")) if IList.providedBy(field): try: return [a.decode('utf-8') for a in literal_eval(value)] except: return [a.strip() for a in value.split(',')] if ITuple.providedBy(field): try: return tuple([a.decode('utf-8') for a in literal_eval(value)]) except: return tuple([a.strip() for a in value.split(',')]) if isinstance(value, unicode) or name == 'id': try: return str(value) except: pass return value return super(SQLDexterityItem, self).__getattribute__(name)
def create_destination_document(self): # get all the metadata that will be set on the created file. # We blacklist some fields that should not be copied fields_to_skip = set(( "file", "archival_file", "archival_file_state", "thumbnail", "preview", "digitally_available", "changeNote", "changed", "relatedItems", )) metadata = {} for schema in iterSchemataForType(self.context.portal_type): for name, schema_field in getFieldsInOrder(schema): if name in fields_to_skip: continue field_instance = schema_field.bind(self.context) metadata[name] = field_instance.get(self.context) command = CreateDocumentCommand(self.destination, None, None, **metadata) destination_document = command.execute() # We make it in shadow state until its file is set by the callback view destination_document.as_shadow_document() # Add marker interface. This should be useful in the future for # cleanup jobs, retries if the PDF was not delivered and so on. alsoProvides(destination_document, IDocumentSavedAsPDFMarker) # Add annotations needed for the SavePDFDocumentUnder view. annotations = IAnnotations(destination_document) annotations[PDF_SAVE_SOURCE_UUID_KEY] = IUUID(self.context) annotations[PDF_SAVE_SOURCE_VERSION_KEY] = self.version_id # The missing_value attribute of a z3c-form field is used # as soon as an object has no default_value i.e. after creating # an object trough the command-line. # # Because the relatedItems field needs a list as a missing_value, # we will fall into the "mutable keyword argument"-python gotcha. # The relatedItems will be shared between the object-instances. # # Unfortunately the z3c-form field does not provide a # missing_value-factory (like the defaultFactory) which would be # necessary to fix this issue properly. # # As a workaround we make sure that the new document's relatedItems # is different object from the source document's. IRelatedDocuments(destination_document).relatedItems = list( IRelatedDocuments(destination_document).relatedItems) IRelatedDocuments(destination_document).relatedItems.append( RelationValue(getUtility(IIntIds).getId(self.context))) msg = _( u'Document ${document} was successfully created in ${destination}', mapping={ "document": destination_document.title, "destination": self.destination.title }) api.portal.show_message(msg, self.request, type='info') return destination_document
def createObjectOfType(self, root, pt): # Set return list rv = [] # Get the it of the portal_type portal_type = pt.getId() # Check if type is allowed allowed_content_types = [x.getId() for x in root.getAllowedTypes()] # Override for root folder (only structures) if root.portal_type == 'Folder': allowed_content_types = [ 'atlas_category_level_1', 'atlas_county', 'directory' ] if portal_type in allowed_content_types: kwargs = {} for s in iterSchemataForType(portal_type): for (name, field) in getAllSchemaFieldsAndDescriptions(s): if not isinstance(field, Method): kwargs[name] = self.getDefaultForFieldType(field) # Set the id kwargs['id'] = 'X_%s_X' % portal_type # Debug output if self.debug: msg = "Creating %s in %s" % (portal_type, root.portal_type) LOG('API Sample Generator', INFO, msg) # Create a dummy object with default values try: o = createContentInContainer(root, portal_type, **kwargs) except WorkflowException: # For some reason, we're getting a workflow exception on article videos? return rv # Append to return list rv.append(o) # Get the allowed object types _allowed_content_types = pt.allowed_content_types # Override for category level 2 (no products!) if portal_type == 'atlas_category_level_2': _allowed_content_types = ['atlas_category_level_3'] # Create sub-objects for _pt_id in _allowed_content_types: # Prevent recursion... Don't create a type inside itself. if _pt_id == portal_type: continue try: _o = self.createObjectOfType(o, self.portal_types[_pt_id]) rv.extend(_o) except RuntimeError: # Skip if something bombs out from recursive calls pass except TypeError: # Skip if something bombs out with a TypeError pass return rv
def __getattribute__(self, name): if name.startswith('_') or name.startswith( 'portal_') or name.startswith('@@') or name == 'sql_id': return super(SQLDexterityItem, self).__getattribute__(name) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if connection == None and self.portal_type: fti = queryUtility(IDexterityFTI, name=self.portal_type, default=None) if not fti: return None updateConnectionsForFti(fti) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if name == 'view': #be sure session and sqlitem are up to date self._v_sql_item = None connection.session.close() if not connection: return super(SQLDexterityItem, self).__getattribute__(name) if name == 'UID' and self.sql_virtual: return self.portal_type + '-' + connection.sql_table + '-' + str( self.sql_id) if name == 'id' and 'id' not in connection.fieldnames.keys(): if not self.sql_virtual: return super(SQLDexterityItem, self).__getattribute__(name) fti = ISQLTypeSettings( getUtility(IDexterityFTI, name=self.portal_type)) nameFromTitle = INameFromTitle(self, None) if nameFromTitle is not None and nameFromTitle.title: sql_folder_id = getattr(fti, 'sql_folder_id', 'data-' + self.portal_type) title = nameFromTitle.title folder = None if IRelationValue.providedBy(sql_folder_id): folder = sql_folder_id.to_object elif sql_folder_id and sql_folder_id.startswith('/'): portal = getToolByName(getSite(), 'portal_url').getPortalObject() folder = portal.restrictedTraverse(sql_folder_id) if folder: name = INameChooser(folder).chooseName(title, self) return name # return INameChooser(getSite()).chooseName(title, self) # return getUtility(IURLNormalizer).normalize(title) return self.sql_id if name in connection.fieldnames.keys(): sql_column = connection.fieldnames[name] sql_item = self.getSQLItem() try: sql_id = getattr(sql_item, connection.sql_id_column, None) except orm_exc.DetachedInstanceError: self._v_sql_item = None sql_item = self.getSQLItem() sql_id = getattr(sql_item, connection.sql_id_column, None) fieldname = 'name' if sql_item and sql_column: while '.' in sql_column: sql_key = sql_column.split('.')[0] sql_item = getattr(sql_item, sql_key, None) if isinstance(sql_item, list): value = sql_item fieldname = sql_column.split('.')[-1] break sql_column = '.'.join(sql_column.split('.')[1:]) else: if not isinstance(sql_item, list): value = getattr(sql_item, sql_column, None) if not value and (isinstance(value, list) or hasattr(value, '_sa_instance_state')): value = '' elif (isinstance(value, list) or hasattr(value, '_sa_instance_state')): sqlftis = [ a for a in getAllUtilitiesRegisteredFor(IDexterityFTI) if 'collective.behavior.sql.behavior.behaviors.ISQLContent' in a.behaviors and getattr(a, 'sql_table', None) ] if name == 'subject': return tuple( [getattr(a, fieldname, '') for a in value]) tableftis = [] for iface in iterSchemataForType(self.portal_type): if name in iface.names(): field = iface[name] if IRelationChoice.providedBy( field) or IRelationList.providedBy(field): if IRelationChoice.providedBy(field): allowed_types = field.source.query.get( 'portal_type', []) else: allowed_types = field.value_type.source.query.get( 'portal_type', []) tableftis = [] for sqlfti in sqlftis: adapted = ISQLTypeSettings(sqlfti, None) if isinstance(value, list): classname = value[0].__class__.__name__ else: classname = value.__class__.__name__ if adapted and getattr( adapted, 'sql_table', None) == classname: if not allowed_types or sqlfti.id in allowed_types: tableftis.append(adapted) catalog = getToolByName( getSite(), 'portal_catalog') relations = [] for tablefti in tableftis: sql_id_column = getattr( tablefti, 'sql_id_column', 'id') valueids = [] if isinstance(value, list): valueids = [ getattr(a, sql_id_column, None) for a in value if getattr(a, sql_id_column, None) ] else: valueids = getattr( value, sql_id_column, None) valueids = [str(a) for a in valueids] brains = catalog.unrestrictedSearchResults( portal_type=tablefti.id, sql_id=valueids) for brain in brains: relations.append( SQLRelationValue( brain.portal_type, brain.UID, self)) if IRelationChoice.providedBy( field) and relations: return relations[0] elif IRelationList.providedBy( field) and relations: return relations elif ITuple.providedBy(field): return tuple( [getattr(a, fieldname, '') for a in value]) elif IList.providedBy(field): return [ getattr(a, fieldname, '') for a in value ] elif value and isinstance(value, list): value = getattr(value[0], fieldname, '') for iface in iterSchemataForType(self.portal_type): if name == 'subject': try: return tuple([ a.decode('utf-8') for a in literal_eval(value) ]) except: return tuple([a.strip() for a in value.split(',')]) if name in iface.names(): field = iface[name] if IRichText.providedBy(field): if not value: return '' if not '<p' in value or not '<br' in value: value = '<p>' + '</p><p>'.join([ a for a in value.split('\n') if a.strip() ]) + '</p>' # try: # value = str(value) # except: # try: # value = value.decode('utf-8') # except: # try: # value = value.encode('utf-8') # except: # pass return RichTextValue(unidecode(value)) elif INamedBlobImage.providedBy(field): return NamedBlobImage( base64.b64decode(value), filename=unicode(self.portal_type + self.id + ".jpg")) elif ITuple.providedBy(field): if not value: return tuple([]) try: return tuple([ a.decode('utf-8') for a in literal_eval(value) ]) except: return tuple( [a.strip() for a in value.split(',')]) elif IList.providedBy(field): if not value: return [] try: return [ a.decode('utf-8') for a in literal_eval(value) ] except: return [a.strip() for a in value.split(',')] elif IDatetime.providedBy(field) and hasattr( value, 'day') and not hasattr(value, 'hour'): value = datetime.datetime.combine( value, datetime.datetime.min.time()) if name in [ 'expiration_date', 'effective_date', 'effective', 'expires' ] and hasattr(value, 'day') and not hasattr(value, 'hour'): value = datetime.datetime.combine( value, datetime.datetime.min.time()) if isinstance(value, unicode) or name == 'id': try: value = str(value) except: pass return value return super(SQLDexterityItem, self).__getattribute__(name)