def add_document(self, data, properties, request=None): """Add new document""" if request is None: request = check_request() registry = request.registry # check required properties properties = properties.copy() title = properties.get('title') application_name = properties.get('application_name') if (not title) or (not application_name) or (data is None): raise HTTPBadRequest("Missing arguments") owner = properties.get('owner') if owner and not request.has_permission( CREATE_DOCUMENT_WITH_OWNER_PERMISSION, context=self): raise HTTPForbidden() if not owner: properties['owner'] = request.principal.id properties['creator'] = request.principal.id # check storage folders folder = self._get_folder(datetime.utcnow()) # create document and first version document, version = self._create_document(registry, folder) # update document data and properties version.update(data, properties) # store document document.get_oid() folder[document.oid] = document registry.notify(ObjectAddedEvent(version, folder, document.oid)) # return return version
def resize(self, width, height, keep_ratio=True): """Resize image to given dimensions""" with self as blob: try: image = Image.open(blob) image_size = image.size if width >= image_size[0] and height >= image_size[1]: return new_image = BytesIO() w_ratio = 1. * width / image_size[0] h_ratio = 1. * height / image_size[1] if keep_ratio: ratio = min(w_ratio, h_ratio) image.resize((round(ratio * image_size[0]), round(ratio * image_size[1])), Image.ANTIALIAS) \ .save(new_image, image.format, quality=99) else: image.resize((round(w_ratio * image_size[0]), round(h_ratio * image_size[1])), Image.ANTIALIAS) \ .save(new_image, image.format, quality=99) self.data = new_image request = check_request() request.registry.notify(FileModifiedEvent(self)) finally: blob.close()
def __init__(self, context): request = check_request() terms = [] versions = IWorkflowVersions(context.__parent__, None) if versions is not None: # check for first version first_version_label = request.localizer.translate( VERSION_DISPLAY[DISPLAY_FIRST_VERSION]) try: first_version = versions.get_version(1) # pylint: disable=assignment-from-no-return except VersionError: pass else: info = IWorkflowPublicationInfo(first_version, None) if info is not None and info.publication_effective_date: first_version_label = '{1} (= {0})'.format( first_version_label.lower(), format_date(info.publication_effective_date, format_string=SH_DATE_FORMAT)) terms.append( SimpleTerm(DISPLAY_FIRST_VERSION, title=first_version_label)) # check for current version current_version_label = request.localizer.translate( VERSION_DISPLAY[DISPLAY_CURRENT_VERSION]) info = IWorkflowPublicationInfo(context, None) if info is not None and info.publication_effective_date: current_version_label = '{1} (= {0})'.format( current_version_label.lower(), format_date(info.publication_effective_date, format_string=SH_DATE_FORMAT)) terms.append( SimpleTerm(DISPLAY_CURRENT_VERSION, title=current_version_label)) super().__init__(terms)
def notify_user_activation(user, request=None): """Send mail for user activation""" security = query_utility(ISecurityManager) settings = INotificationSettings(security) if not settings.enable_notifications: # pylint: disable=assignment-from-no-return LOGGER.info("Security notifications disabled, no message sent...") return mailer = settings.get_mailer() # pylint: disable=assignment-from-no-return if mailer is None: LOGGER.warning("Can't find mailer utility, no notification message sent!") return if request is None: request = check_request() translate = request.localizer.translate i18n_settings = II18n(settings) message_text, template_name = None, None if user.self_registered: # pylint: disable=assignment-from-no-return message_text = i18n_settings.query_attribute('registration_template', request=request) if not message_text: template_name = 'templates/register-message.pt' elif user.wait_confirmation: # pylint: disable=assignment-from-no-return message_text = i18n_settings.query_attribute('confirmation_template', request=request) if not message_text: template_name = 'templates/register-info.pt' site = get_parent(request.context, ISite) if message_text is not None: message_text = message_text.format(**user.to_dict()) elif template_name is not None: message_text = render(template_name, request=request, value={ 'user': user, 'site': site, 'settings': settings }) html_body = render('templates/register-body.pt', request=request, value={ 'user': user, 'site': site, 'settings': settings, 'message': message_text }) message = Message( subject=translate(_("{prefix}Please confirm registration")).format( prefix="{prefix} ".format(prefix=settings.subject_prefix) if settings.subject_prefix else ''), sender='{name} <{email}>'.format(name=settings.sender_name, email=settings.sender_email), recipients=("{firstname} {lastname} <{email}>".format(firstname=user.firstname, lastname=user.lastname, email=user.email),), html=Attachment(data=html_body, content_type='text/html; charset=utf-8', disposition='inline', transfer_encoding='quoted-printable'), body=Attachment(data=html_to_text(html_body), content_type='text/plain; charset=utf-8', disposition='inline', transfer_encoding='quoted-printable')) mailer.send(message)
def permission(self): """Object permission getter""" request = getattr(self, 'request', None) or check_request() context = ISecurityContext(self, None) if context is None: context = getattr(self, 'context', request.context) view = getattr(self, 'view', None) or getattr(self, 'table', None) return get_edit_permission(request, context, view, self.action_type)
def get_layer_skin(layer): """Get skin matching given layer""" request = check_request() registry = request.registry for name, util in registry.getUtilitiesFor(ISkin): # pylint: disable=unused-variable if util.layer is layer: return util return None
def public_profile_factory(context): # pylint: disable=unused-argument """Generic public profile factory Applied on any context, this adapter returns public profile associated with the current request principal. """ request = check_request() return IPublicProfile(request.principal)
def get_age(value, request=None): """Get 'human' age of a given datetime (including timezone) compared to current datetime (in UTC) :param datetime value: input datetime to be compared with current datetime :return: str; the delta value, converted to months, weeks, days, hours or minutes >>> from datetime import datetime, timedelta >>> from pyams_utils.date import get_age >>> now = datetime.utcnow() >>> get_age(now) 'less than 5 minutes ago' >>> get_age(now - timedelta(minutes=10)) '10 minutes ago' >>> get_age(now - timedelta(hours=2)) '2 hours ago' >>> get_age(now - timedelta(days=1)) 'yesterday' >>> get_age(now - timedelta(days=2)) 'the day before yesterday' >>> get_age(now - timedelta(days=4)) '4 days ago' >>> get_age(now - timedelta(weeks=2)) '2 weeks ago' >>> get_age(now - timedelta(days=80)) '3 months ago' >>> get_age(None) '--' """ if not value: return '--' if request is None: request = check_request() translate = request.localizer.translate now = gmtime(datetime.utcnow()) delta = now - gmtime(value) if delta.days > 60: result = translate(_("%d months ago")) % int( round(delta.days * 1.0 / 30)) elif delta.days > 10: result = translate(_("%d weeks ago")) % int(round( delta.days * 1.0 / 7)) elif delta.days > 2: result = translate(_("%d days ago")) % delta.days elif delta.days == 2: result = translate(_("the day before yesterday")) elif delta.days == 1: result = translate(_("yesterday")) else: # less than one day hours = int(round(delta.seconds * 1.0 / 3600)) if hours > 1: result = translate(_("%d hours ago")) % hours elif delta.seconds > 300: result = translate(_("%d minutes ago")) % int( round(delta.seconds * 1.0 / 60)) else: result = translate(_("less than 5 minutes ago")) return result
def update_document(self, oid, version=None, data=None, properties=None, request=None, check_permission=True): # pylint: disable=too-many-arguments """Update document data or properties""" if not oid: return None document = self.get_document(oid, version) if document is None: raise HTTPNotFound() if request is None: request = check_request() if check_permission and \ not request.has_permission(MANAGE_DOCUMENT_PERMISSION, context=document): raise HTTPForbidden() if properties is None: properties = {} if data is not None: document_hash = get_hash(data) if document_hash == document.hash: # unmodified file content data = None _filename = properties.pop('filename', None) else: # modified file content, check state and create new version if required if request is None: request = check_request() state = IWorkflowState(document) if state.state != DRAFT_STATE: translate = request.localizer.translate workflow_info = IWorkflowInfo(document) document = workflow_info.fire_transition_toward( # pylint: disable=assignment-from-no-return DRAFT_STATE, comment=translate(_("Document content update")), request=request) request.response.status = HTTPCreated.code state = document.update(data, properties) request.registry.notify(ObjectModifiedEvent(document)) if state.state == DELETED_STATE: return None return document
def __init__(self, context=None, **kw): # pylint: disable=super-init-not-called,unused-argument request = check_request() registry = request.registry translate = request.localizer.translate utils = [(name, translate(util.label)) for (name, util) in registry.getUtilitiesFor(self.interface)] self._terms = dict( (title, UtilityTerm(name, title)) for name, title in utils)
def fire_transition(self, transition_id, comment=None, side_effect=None, check_security=True, principal=None, request=None): # pylint: disable=too-many-arguments """Fire transition with given ID""" versions = IWorkflowVersions(self.parent) state = IWorkflowState(self.context) if request is None: request = check_request() # this raises InvalidTransitionError if id is invalid for current state transition = self.wf.get_transition(state.state, transition_id) # check whether we may execute this workflow transition if check_security and transition.permission: if not request.has_permission(transition.permission, context=self.context): raise HTTPUnauthorized() # now make sure transition can still work in this context if not transition.condition(self, self.context): raise ConditionFailedError() # perform action, return any result as new version if principal is None: principal = request.principal result = transition.action(self, self.context) if result is not None: # stamp it with version versions.add_version(result, transition.destination, principal) # execute any side effect: if side_effect is not None: side_effect(result) event = WorkflowVersionTransitionEvent(result, self.wf, principal, self.context, transition.source, transition.destination, transition, comment) else: versions.set_state(state.version_id, transition.destination, principal) # execute any side effect if side_effect is not None: side_effect(self.context) event = WorkflowTransitionEvent(self.context, self.wf, principal, transition.source, transition.destination, transition, comment) # change state of context or new object registry = request.registry registry.notify(event) # send modified event for original or new object if result is None: registry.notify(ObjectModifiedEvent(self.context)) else: registry.notify(ObjectModifiedEvent(result)) return result
def __init__(self, context=None): # pylint: disable=unused-argument request = check_request() translate = request.localizer.translate terms = sorted([ SimpleTerm(v, title=translate(t)) for v, t in ISO_LANGUAGES.items() ], key=lambda x: x.title) super(ISOLanguagesVocabulary, self).__init__(terms)
def __init__(self, context=None): # pylint: disable=unused-argument request = check_request() registry = request.registry translate = request.localizer.translate terms = [] append = terms.append for name, adapter in registry.getAdapters(('', request), IHTMLRenderer): if hasattr(adapter, 'label'): append(SimpleTerm(name, title=translate(adapter.label))) super().__init__(terms)
def __init__(self, *args, **kwargs): # pylint: disable=unused-argument request = check_request() registry = request.registry translate = request.localizer.translate terms = [ SimpleTerm(p.id, title=translate(p.title)) for n, p in registry.getUtilitiesFor(self.interface) ] terms.sort(key=lambda x: x.title) super().__init__(terms)
def publication(self): """Publication label used to display workflow publication state""" request = check_request() translate = request.localizer.translate sm = get_utility(ISecurityManager) # pylint: disable=invalid-name return translate(_('{date} by {principal}')).format( date=format_datetime(tztime( IWorkflowPublicationInfo(self).publication_date), request=request), principal=translate(sm.get_principal(self.publisher).title))
def get_label(item, request=None): """Get sort label of a given viewlet""" _, viewlet = item try: label = getattr(viewlet, 'label', None) if not label: return '--' if request is None: request = check_request() return request.localizer.translate(label) except AttributeError: return '--'
def __init__(self, context=None): # pylint: disable=unused-argument terms = [] negotiator = query_utility(INegotiator) if negotiator is not None: translate = check_request().localizer.translate for lang in negotiator.offered_languages: terms.append( SimpleTerm(lang, title=translate( BASE_LANGUAGES.get(lang) or _("<unknown>")))) super(I18nOfferedLanguages, self).__init__(terms)
def crop(self, x1, y1, x2, y2): # pylint: disable=invalid-name """Crop image to given coordinates""" with self as blob: try: image = Image.open(blob) new_image = BytesIO() image.crop((x1, y1, x2, y2)) \ .save(new_image, image.format, quelity=99) self.data = new_image request = check_request() request.registry.notify(FileModifiedEvent(self)) finally: blob.close()
def rotate(self, angle=-90): """Rotate image of given angle, in clockwise degrees""" with self as blob: try: image = Image.open(blob) new_image = BytesIO() image.rotate(angle, expand=True) \ .save(new_image, image.format, quality=99) self.data = new_image request = check_request() request.registry.notify(FileModifiedEvent(self)) finally: blob.close()
def wrapper(obj, app, key, *args, **kwargs): request = check_request() if callable(key): key = key(obj, *args, **kwargs) if not key: key = '{1}::{0!r}'.format(obj, prefix or func.__name__) data = get_session_data(request, app, key, _MARKER) if data is _MARKER: data = func if callable(data): data = data(obj, *args, **kwargs) set_session_data(request, app, key, data) return data
def get_manual_transition_ids(self, check_security=True): """Getter for available transitions IDs""" if check_security: request = check_request() permission_checker = request.has_permission else: permission_checker = granted_permission return [ transition.transition_id for transition in sorted( self._get_transitions(MANUAL_TRANSITION), key=lambda x: x.user_data.get('order', 999)) if transition.condition(self, self.context) and permission_checker(transition.permission, context=self.context) ]
def delete_document(self, oid, request=None): """Delete document or version""" if not oid: return None document = self.get_document(oid) if document is None: raise HTTPNotFound() if request is None: request = check_request() if not request.has_permission(MANAGE_DOCUMENT_PERMISSION, context=document): raise HTTPForbidden() folder = get_parent(document, IDocumentFolder) del folder[document.oid] return document
def publish_action(wf, context): # pylint: disable=invalid-name,unused-argument """Publish version""" request = check_request() translate = request.localizer.translate publication_info = IWorkflowPublicationInfo(context) publication_info.publication_date = datetime.utcnow() publication_info.publisher = request.principal.id version_id = IWorkflowState(context).version_id for version in IWorkflowVersions(context).get_versions( (PUBLISHED_STATE, )): if version is not context: IWorkflowInfo(version).fire_transition_toward( ARCHIVED_STATE, comment=translate( _("Published version {0}")).format(version_id))
def get_label(content, request=None, format=True): # pylint: disable=redefined-builtin """Workflow state label getter""" if request is None: request = check_request() translate = request.localizer.translate state = IWorkflowState(content) header = STATES_HEADERS.get(state.state) if header is not None: state_label = translate(header) if format: state_label = translate(_('{state} {date}')).format( state=state_label, date=format_datetime(state.state_date)) else: state_label = translate(_("Unknown state")) return state_label
def text_to_html(text, renderer='text', **kwargs): """Convert text to HTML using the given renderer Renderer name can be any registered HTML renderer adapter. You can provide several renderers by giving their names separated by semicolon; renderers will then act as in a pipe, each renderer transforming output of the previous one. """ request = check_request() registry = request.registry for renderer_name in renderer.split(';'): renderer = registry.queryMultiAdapter((text, request), IHTMLRenderer, name=renderer_name) if renderer is not None: text = renderer.render(**kwargs) or text return text
def handle_removed_task(event): """Handle removed task""" request = check_request() if request.registry is not None: handler = request.registry.settings.get(SCHEDULER_HANDLER_KEY, False) if handler: task = event.object scheduler_util = query_utility(IScheduler) zmq_settings = { 'zodb_name': scheduler_util.zodb_name, 'task_name': task.__name__, 'job_id': task.internal_id } LOGGER.debug("Removing task {0.name} with {1!r}".format(task, zmq_settings)) socket = zmq_socket(handler, auth=request.registry.settings.get(SCHEDULER_AUTH_KEY)) socket.send_json(['remove_task', zmq_settings]) zmq_response(socket)
def is_visible(self, request=None, check_parent=True): """Check if content is published and visible to given request""" if request is None: request = check_request() # associated workflow? content = IWorkflowManagedContent(self.__parent__, None) if content is not None: wf_name = content.workflow_name if not wf_name: return True # check workflow? if content.view_permission and \ not request.has_permission(content.view_permission, context=self.__parent__): return False else: if not request.has_permission(VIEW_PERMISSION, context=self.__parent__): return False return self.is_published(check_parent)
def remove_version(self, version_id, state='deleted', comment=None, principal=None, request=None): # pylint: disable=too-many-arguments """Remove version with given ID""" if str(version_id) not in self: return # update version state version = self[str(version_id)] wf_state = IWorkflowState(version) if comment: if request is None: request = check_request() translate = request.localizer.translate workflow = get_utility( IWorkflow, name=get_parent(self, IWorkflowManagedContent).workflow_name) item = WorkflowHistoryItem( date=datetime.utcnow(), source_version=wf_state.version_id, source_state=translate( workflow.states.getTerm(wf_state.state).title), target_state=translate(workflow.states.getTerm(state).title), principal=request.principal.id, comment=comment) wf_state.history.append(item) # pylint: disable=no-member wf_state.state = state if principal is not None: wf_state.state_principal = principal # remove given version state = self.state_by_version[version_id] versions = self.versions_by_state[state] versions.remove(version_id) if versions: self.versions_by_state[state] = versions else: del self.versions_by_state[state] del self.state_by_version[version_id] self.deleted[version_id] = self[str(version_id)] del self[str(version_id)]
def get_geometry(self, selection_name): """Get geometry matching given selection name""" geometries = get_annotation_adapter(self.image, THUMBNAIL_GEOMETRY_KEY, default={}) # get default geometry for custom thumbnails if ':' in selection_name: selection_name, options = selection_name.split(':', 1) else: options = None if selection_name in geometries: return geometries[selection_name] registry = check_request().registry thumbnailer = registry.queryAdapter(self.image, IThumbnailer, name=selection_name) if thumbnailer is not None: return thumbnailer.get_default_geometry(options) return None
def update(self, data, properties, request=None): """Document data setter""" if properties: if request is None: request = check_request() self.updater = request.principal.id if data is not None: if 'filename' in properties: data = (properties.pop('filename'), data) self.data = data if (not self.title) or ('title' in properties): self.title = properties.pop('title', '<UNDEFINED>') if (not self.application_name) or ('application_name' in properties): self.application_name = properties.pop('application_name', '<UNDEFINED>') self.update_roles(properties, request) self.update_security_policy(properties, request) self.update_status(properties, request) self.update_properties(properties, request) return IWorkflowState(self)