source: main/waeup.sirp/trunk/src/waeup/sirp/interfaces.py @ 7741

Last change on this file since 7741 was 7730, checked in by uli, 13 years ago

Require iterables as input to exporter. This will ease things with
exporting data of certain subareas (i.e. the departments of a certain
faculty only, etc.) and we could use catalog lookups more easily.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 27.7 KB
Line 
1## $Id: interfaces.py 7730 2012-02-29 18:32:57Z uli $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import os
19import re
20import codecs
21import zope.i18nmessageid
22from datetime import datetime
23from hurry.file.interfaces import IFileRetrieval
24from hurry.workflow.interfaces import IWorkflow, IWorkflowInfo
25from zc.sourcefactory.basic import BasicSourceFactory
26from zope import schema
27from zope.pluggableauth.interfaces import IPrincipalInfo
28from zope.security.interfaces import IGroupClosureAwarePrincipal as IPrincipal
29from zope.component import getUtility
30from zope.component.interfaces import IObjectEvent
31from zope.container.interfaces import INameChooser
32from zope.interface import Interface, Attribute, implements
33from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
34
35_ = MessageFactory = zope.i18nmessageid.MessageFactory('waeup.sirp')
36
37CREATED = 'created'
38ADMITTED = 'admitted'
39CLEARANCE = 'clearance started'
40REQUESTED = 'clearance requested'
41CLEARED = 'cleared'
42PAID = 'school fee paid'
43RETURNING = 'returning'
44REGISTERED = 'courses registered'
45VALIDATED = 'courses validated'
46
47default_frontpage = u'' + codecs.open(os.path.join(
48        os.path.dirname(__file__), 'frontpage.rst'),
49        encoding='utf-8', mode='rb').read()
50
51def SimpleSIRPVocabulary(*terms):
52    """A well-buildt vocabulary provides terms with a value, token and
53       title for each term
54    """
55    return SimpleVocabulary([
56            SimpleTerm(value, value, title) for title, value in terms])
57
58def year_range():
59    curr_year = datetime.now().year
60    return range(curr_year - 4, curr_year + 5)
61
62def academic_sessions():
63    curr_year = datetime.now().year
64    year_range = range(curr_year - 10, curr_year + 2)
65    return [('%s/%s' % (year,year+1), year) for year in year_range]
66
67academic_sessions_vocab = SimpleSIRPVocabulary(*academic_sessions())
68
69registration_states_vocab = SimpleSIRPVocabulary(
70    (_('created'), CREATED),
71    (_('admitted'), ADMITTED),
72    (_('clearance started'), CLEARANCE),
73    (_('clearance requested'), REQUESTED),
74    (_('cleared'), CLEARED),
75    (_('school fee paid'), PAID),
76    (_('returning'), RETURNING),
77    (_('courses registered'), REGISTERED),
78    (_('courses validated'), VALIDATED),
79    )
80
81# Define a valiation method for email addresses
82class NotAnEmailAddress(schema.ValidationError):
83    __doc__ = u"Invalid email address"
84
85check_email = re.compile(
86    r"[a-zA-Z0-9._%-']+@([a-zA-Z0-9-]+.)*[a-zA-Z]{2,4}").match
87
88def validate_email(value):
89    if not check_email(value):
90        raise NotAnEmailAddress(value)
91    return True
92
93class FatalCSVError(Exception):
94    """Some row could not be processed.
95    """
96    pass
97
98class DuplicationError(Exception):
99    """An exception that can be raised when duplicates are found.
100
101    When raising :exc:`DuplicationError` you can, beside the usual
102    message, specify a list of objects which are duplicates. These
103    values can be used by catching code to print something helpful or
104    similar.
105    """
106    def __init__(self, msg, entries=[]):
107        self.msg = msg
108        self.entries = entries
109
110    def __str__(self):
111        return '%r' % self.msg
112
113class RoleSource(BasicSourceFactory):
114    """A source for site roles.
115    """
116    def getValues(self):
117        # late import: in interfaces we should not import local modules
118        from waeup.sirp.permissions import get_waeup_role_names
119        return get_waeup_role_names()
120
121    def getTitle(self, value):
122        # late import: in interfaces we should not import local modules
123        from waeup.sirp.permissions import get_all_roles
124        roles = dict(get_all_roles())
125        if value in roles.keys():
126            title = roles[value].title
127            if '.' in title:
128                title = title.split('.', 2)[1]
129        return title
130
131class CaptchaSource(BasicSourceFactory):
132    """A source for captchas.
133    """
134    def getValues(self):
135        captchas = ['No captcha', 'Testing captcha', 'ReCaptcha']
136        try:
137            # we have to 'try' because IConfiguration can only handle
138            # interfaces from w.s.interface.
139            from waeup.sirp.browser.interfaces import ICaptchaManager
140        except:
141            return captchas
142        return sorted(getUtility(ICaptchaManager).getAvailCaptchas().keys())
143
144    def getTitle(self, value):
145        return value
146
147class ISIRPUtils(Interface):
148    """A collection of methods which are subject to customization.
149    """
150
151    def storage():
152        """Return the initial storage path of the data center.
153        """
154
155    def sendContactForm(
156          from_name,from_addr,rcpt_name,rcpt_addr,
157          from_username,usertype,portal,body,subject):
158        """Send an email with data provided by forms.
159        """
160
161    def fullname(firstname,lastname,middlename):
162        """Full name constructor.
163        """
164
165    def sendCredentials(user, password, login_url, msg):
166        """Send credentials as email.
167
168        Input is the applicant for which credentials are sent and the
169        password.
170
171        Returns True or False to indicate successful operation.
172        """
173
174    def genPassword(length, chars):
175        """Generate a random password.
176        """
177
178    def getVerdictsDict():
179        """Provide a dict of verdicts.
180        """
181
182class ISIRPObject(Interface):
183    """A SIRP object.
184
185    This is merely a marker interface.
186    """
187
188class IUniversity(ISIRPObject):
189    """Representation of a university.
190    """
191
192
193class ISIRPContainer(ISIRPObject):
194    """A container for SIRP objects.
195    """
196
197class ISIRPContained(ISIRPObject):
198    """An item contained in an ISIRPContainer.
199    """
200
201class ICSVExporter(Interface):
202    """A CSV file exporter for objects.
203    """
204    fields = Attribute("""List of fieldnames in resulting CSV""")
205   
206    def mangle_value(value, name, obj):
207        """Mangle `value` extracted from `obj` or suobjects thereof.
208
209        This is called by export before actually writing to the result file.
210        """
211
212    def export(iterable, filepath=None):
213        """Export iterables as rows in a CSV file.
214
215        If `filepath` is not given, a string with the data should be returned.
216
217        What kind of iterables are acceptable depends on the specific
218        exporter implementation.
219        """
220
221    def export_all(site, filapath=None):
222        """Export all items in `site` as CSV file.
223
224        if `filepath` is not given, a string with the data should be returned.
225        """
226
227class ISIRPExporter(Interface):
228    """An exporter for objects.
229    """
230    def export(obj, filepath=None):
231        """Export by pickling.
232
233        Returns a file-like object containing a representation of `obj`.
234
235        This is done using `pickle`. If `filepath` is ``None``, a
236        `cStringIO` object is returned, that contains the saved data.
237        """
238
239class ISIRPXMLExporter(Interface):
240    """An XML exporter for objects.
241    """
242    def export(obj, filepath=None):
243        """Export as XML.
244
245        Returns an XML representation of `obj`.
246
247        If `filepath` is ``None``, a StringIO` object is returned,
248        that contains the transformed data.
249        """
250
251class ISIRPXMLImporter(Interface):
252    """An XML import for objects.
253    """
254    def doImport(filepath):
255        """Create Python object from XML.
256
257        Returns a Python object.
258        """
259
260class IBatchProcessor(Interface):
261    """A batch processor that handles mass-operations.
262    """
263    name = schema.TextLine(
264        title = u'Importer name'
265        )
266
267    mode = schema.Choice(
268        title = u'Import mode',
269        values = ['create', 'update', 'remove']
270        )
271
272    def doImport(path, headerfields, mode='create', user='Unknown',
273                 logger=None):
274        """Read data from ``path`` and update connected object.
275
276        `headerfields` is a list of headerfields as read from the file
277        to import.
278
279        `mode` gives the import mode to use (``'create'``,
280        ``'update'``, or ``'remove'``.
281
282        `user` is a string describing the user performing the
283        import. Normally fetched from current principal.
284
285        `logger` is the logger to use during import.
286        """
287
288class IContactForm(ISIRPObject):
289    """A contact form.
290    """
291
292    email_from = schema.ASCIILine(
293        title = u'Email Address:',
294        default = None,
295        required = True,
296        constraint=validate_email,
297        )
298
299    email_to = schema.ASCIILine(
300        title = u'Email to:',
301        default = None,
302        required = True,
303        constraint=validate_email,
304        )
305
306    subject = schema.TextLine(
307        title = u'Subject:',
308        required = True,)
309
310    fullname = schema.TextLine(
311        title = u'Full Name:',
312        required = True,)
313
314    body = schema.Text(
315        title = u'Text:',
316        required = True,)
317
318class ISIRPPrincipalInfo(IPrincipalInfo):
319    """Infos about principals that are users of SIRP SIRP.
320    """
321    email = Attribute("The email address of a user")
322    phone = Attribute("The phone number of a user")
323
324
325class ISIRPPrincipal(IPrincipal):
326    """A principle for SIRP SIRP.
327
328    This interface extends zope.security.interfaces.IPrincipal and
329    requires also an `id` and other attributes defined there.
330    """
331
332    email = schema.TextLine(
333        title = u'Email',
334        description = u'',
335        required=False,)
336
337    phone = schema.TextLine(
338        title = u'Phone',
339        description = u'',
340        required=False,)
341
342class IUserAccount(ISIRPObject):
343    """A user account.
344    """
345    name = schema.TextLine(
346        title = u'User ID',
347        description = u'Login name of user',
348        required = True,)
349
350    title = schema.TextLine(
351        title = u'Full Name',
352        required = False,)
353
354    description = schema.Text(
355        title = u'Description/Notice',
356        required = False,)
357
358    email = schema.ASCIILine(
359        title = u'Email',
360        default = None,
361        required = True,
362        constraint=validate_email,
363        )
364
365    phone = schema.TextLine(
366        title = u'Phone',
367        default = None,
368        required = True,
369        )
370
371    roles = schema.List(
372        title = u'Portal roles',
373        value_type = schema.Choice(source=RoleSource()))
374
375class IPasswordValidator(Interface):
376    """A password validator utility.
377    """
378
379    def validate_password(password, password_repeat):
380        """Validates a password by comparing it with
381        control password and checking some other requirements.
382        """
383
384
385class IUsersContainer(ISIRPObject):
386    """A container for users (principals).
387
388    These users are used for authentication purposes.
389    """
390
391    def addUser(name, password, title=None, description=None):
392        """Add a user.
393        """
394
395    def delUser(name):
396        """Delete a user if it exists.
397        """
398
399class ILocalRolesAssignable(Interface):
400    """The local roles assignable to an object.
401    """
402    def __call__():
403        """Returns a list of dicts.
404
405        Each dict contains a ``name`` referring to the role assignable
406        for the specified object and a `title` to describe the range
407        of users to which this role can be assigned.
408        """
409
410class IConfigurationContainer(ISIRPObject):
411    """A container for session configuration objects.
412    """
413
414    name = schema.TextLine(
415        title = u'Name of University',
416        default = u'Sample University',
417        required = True,
418        )
419
420    acronym = schema.TextLine(
421        title = u'Abbreviated Title of University',
422        default = u'WAeUP.SIRP',
423        required = True,
424        )
425
426    skin = schema.Choice(
427        title = u'Skin',
428        default = u'gray waeup theme',
429        vocabulary = 'waeup.sirp.browser.theming.ThemesVocabulary',
430        required = True,
431        )
432
433    frontpage = schema.Text(
434        title = u'Content in reST format',
435        required = False,
436        default = default_frontpage,
437        )
438
439    frontpage_dict = schema.Dict(
440        title = u'Content as language dictionary with values in html format',
441        required = False,
442        default = {},
443        )
444
445    accommodation_session = schema.Choice(
446        title = u'Accommodation Booking Session',
447        source = academic_sessions_vocab,
448        default = datetime.now().year,
449        required = False,
450        readonly = False,
451        )
452
453    accommodation_states = schema.List(
454        title = u'Allowed States for Accommodation Booking',
455        value_type = schema.Choice(
456            vocabulary = registration_states_vocab,
457            ),
458        default = [],
459        )
460
461    name_admin = schema.TextLine(
462        title = u'Name of Administrator',
463        default = u'Administrator',
464        required = False,
465        )
466
467    email_admin = schema.ASCIILine(
468        title = u'Email Address of Administrator',
469        default = 'contact@waeup.org',
470        required = False,
471        constraint=validate_email,
472        )
473
474    email_subject = schema.TextLine(
475        title = u'Subject of Email to Administrator',
476        default = u'SIRP Contact',
477        required = False,
478        )
479
480    smtp_mailer = schema.Choice(
481        title = u'SMTP mailer to use when sending mail',
482        vocabulary = 'Mail Delivery Names',
483        default = 'No email service',
484        required = True,
485        )
486
487    captcha = schema.Choice(
488        title = u'Captcha used for public registration pages',
489        source = CaptchaSource(),
490        default = u'No captcha',
491        required = True,
492        )
493
494    carry_over = schema.Bool(
495        title = u'Carry-over Course Registration',
496        default = False,
497        )
498
499class ISessionConfiguration(ISIRPObject):
500    """A session configuration object.
501    """
502
503    academic_session = schema.Choice(
504        title = u'Academic Session',
505        source = academic_sessions_vocab,
506        default = None,
507        required = True,
508        readonly = True,
509        )
510
511    school_fee_base = schema.Int(
512        title = u'School Fee',
513        default = 0,
514        )
515
516    surcharge_1 = schema.Int(
517        title = u'Surcharge 1',
518        default = 0,
519        )
520
521    surcharge_2 = schema.Int(
522        title = u'Surcharge 2',
523        default = 0,
524        )
525
526    surcharge_3 = schema.Int(
527        title = u'Surcharge 3',
528        default = 0,
529        )
530
531    clearance_fee = schema.Int(
532        title = u'Clearance Fee',
533        default = 0,
534        )
535
536    booking_fee = schema.Int(
537        title = u'Booking Fee',
538        default = 0,
539        )
540
541    acceptance_fee = schema.Int(
542        title = u'Acceptance Fee',
543        default = 0,
544        )
545
546    def getSessionString():
547        """Returns the session string from the vocabulary.
548        """
549
550
551class ISessionConfigurationAdd(ISessionConfiguration):
552    """A session configuration object in add mode.
553    """
554
555    academic_session = schema.Choice(
556        title = u'Academic Session',
557        source = academic_sessions_vocab,
558        default = None,
559        required = True,
560        readonly = False,
561        )
562
563ISessionConfigurationAdd['academic_session'].order =  ISessionConfiguration[
564    'academic_session'].order
565
566class IDataCenter(ISIRPObject):
567    """A data center.
568
569    TODO : declare methods, at least those needed by pages.
570    """
571    pass
572
573class IDataCenterFile(Interface):
574    """A data center file.
575    """
576
577    name = schema.TextLine(
578        title = u'Filename')
579
580    size = schema.TextLine(
581        title = u'Human readable file size')
582
583    uploaddate = schema.TextLine(
584        title = u'Human readable upload datetime')
585
586    lines = schema.Int(
587        title = u'Number of lines in file')
588
589    def getDate():
590        """Get creation timestamp from file in human readable form.
591        """
592
593    def getSize():
594        """Get human readable size of file.
595        """
596
597    def getLinesNumber():
598        """Get number of lines of file.
599        """
600
601class IDataCenterStorageMovedEvent(IObjectEvent):
602    """Emitted, when the storage of a datacenter changes.
603    """
604
605class IObjectUpgradeEvent(IObjectEvent):
606    """Can be fired, when an object shall be upgraded.
607    """
608
609class ILocalRoleSetEvent(IObjectEvent):
610    """A local role was granted/revoked for a principal on an object.
611    """
612    role_id = Attribute(
613        "The role id that was set.")
614    principal_id = Attribute(
615        "The principal id for which the role was granted/revoked.")
616    granted = Attribute(
617        "Boolean. If false, then the role was revoked.")
618
619class IQueryResultItem(Interface):
620    """An item in a search result.
621    """
622    url = schema.TextLine(
623        title = u'URL that links to the found item')
624    title = schema.TextLine(
625        title = u'Title displayed in search results.')
626    description = schema.Text(
627        title = u'Longer description of the item found.')
628
629class ISIRPPluggable(Interface):
630    """A component that might be plugged into a SIRP SIRP app.
631
632    Components implementing this interface are referred to as
633    'plugins'. They are normally called when a new
634    :class:`waeup.sirp.app.University` instance is created.
635
636    Plugins can setup and update parts of the central site without the
637    site object (normally a :class:`waeup.sirp.app.University` object)
638    needing to know about that parts. The site simply collects all
639    available plugins, calls them and the plugins care for their
640    respective subarea like the applicants area or the datacenter
641    area.
642
643    Currently we have no mechanism to define an order of plugins. A
644    plugin should therefore make no assumptions about the state of the
645    site or other plugins being run before and instead do appropriate
646    checks if necessary.
647
648    Updates can be triggered for instance by the respective form in
649    the site configuration. You normally do updates when the
650    underlying software changed.
651    """
652    def setup(site, name, logger):
653        """Create an instance of the plugin.
654
655        The method is meant to be called by the central app (site)
656        when it is created.
657
658        `site`:
659           The site that requests a setup.
660
661        `name`:
662           The name under which the plugin was registered (utility name).
663
664        `logger`:
665           A standard Python logger for the plugins use.
666        """
667
668    def update(site, name, logger):
669        """Method to update an already existing plugin.
670
671        This might be called by a site when something serious
672        changes. It is a poor-man replacement for Zope generations
673        (but probably more comprehensive and better understandable).
674
675        `site`:
676           The site that requests an update.
677
678        `name`:
679           The name under which the plugin was registered (utility name).
680
681        `logger`:
682           A standard Python logger for the plugins use.
683        """
684
685class IAuthPluginUtility(Interface):
686    """A component that cares for authentication setup at site creation.
687
688    Utilities providing this interface are looked up when a Pluggable
689    Authentication Utility (PAU) for any
690    :class:`waeup.sirp.app.University` instance is created and put
691    into ZODB.
692
693    The setup-code then calls the `register` method of the utility and
694    expects a modified (or unmodified) version of the PAU back.
695
696    This allows to define any authentication setup modifications by
697    submodules or third-party modules/packages.
698    """
699
700    def register(pau):
701        """Register any plugins wanted to be in the PAU.
702        """
703
704    def unregister(pau):
705        """Unregister any plugins not wanted to be in the PAU.
706        """
707
708class IObjectConverter(Interface):
709    """Object converters are available as simple adapters, adapting
710       interfaces (not regular instances).
711
712    """
713
714    def fromStringDict(self, data_dict, context, form_fields=None):
715        """Convert values in `data_dict`.
716
717        Converts data in `data_dict` into real values based on
718        `context` and `form_fields`.
719
720        `data_dict` is a mapping (dict) from field names to values
721        represented as strings.
722
723        The fields (keys) to convert can be given in optional
724        `form_fields`. If given, form_fields should be an instance of
725        :class:`zope.formlib.form.Fields`. Suitable instances are for
726        example created by :class:`grok.AutoFields`.
727
728        If no `form_fields` are given, a default is computed from the
729        associated interface.
730
731        The `context` can be an existing object (implementing the
732        associated interface) or a factory name. If it is a string, we
733        try to create an object using
734        :func:`zope.component.createObject`.
735
736        Returns a tuple ``(<FIELD_ERRORS>, <INVARIANT_ERRORS>,
737        <DATA_DICT>)`` where
738
739        ``<FIELD_ERRORS>``
740           is a list of tuples ``(<FIELD_NAME>, <ERROR>)`` for each
741           error that happened when validating the input data in
742           `data_dict`
743
744        ``<INVARIANT_ERRORS>``
745           is a list of invariant errors concerning several fields
746
747        ``<DATA_DICT>``
748           is a dict with the values from input dict converted.
749
750        If errors happen, i.e. the error lists are not empty, always
751        an empty ``<DATA_DICT>`` is returned.
752
753        If ``<DATA_DICT>` is non-empty, there were no errors.
754        """
755
756class IObjectHistory(Interface):
757
758    messages = schema.List(
759        title = u'List of messages stored',
760        required = True,
761        )
762
763    def addMessage(message):
764        """Add a message.
765        """
766
767class ISIRPWorkflowInfo(IWorkflowInfo):
768    """A :class:`hurry.workflow.workflow.WorkflowInfo` with additional
769       methods for convenience.
770    """
771    def getManualTransitions():
772        """Get allowed manual transitions.
773
774        Get a sorted list of tuples containing the `transition_id` and
775        `title` of each allowed transition.
776        """
777
778class ISiteLoggers(Interface):
779
780    loggers = Attribute("A list or generator of registered SIRPLoggers")
781
782    def register(name, filename=None, site=None, **options):
783        """Register a logger `name` which logs to `filename`.
784
785        If `filename` is not given, logfile will be `name` with
786        ``.log`` as filename extension.
787        """
788
789    def unregister(name):
790        """Unregister a once registered logger.
791        """
792
793class ILogger(Interface):
794    """A logger cares for setup, update and restarting of a Python logger.
795    """
796
797    logger = Attribute("""A :class:`logging.Logger` instance""")
798
799
800    def __init__(name, filename=None, site=None, **options):
801        """Create a SIRP logger instance.
802        """
803
804    def setup():
805        """Create a Python :class:`logging.Logger` instance.
806
807        The created logger is based on the params given by constructor.
808        """
809
810    def update(**options):
811        """Update the logger.
812
813        Updates the logger respecting modified `options` and changed
814        paths.
815        """
816
817class ILoggerCollector(Interface):
818
819    def getLoggers(site):
820        """Return all loggers registered for `site`.
821        """
822
823    def registerLogger(site, logging_component):
824        """Register a logging component residing in `site`.
825        """
826
827    def unregisterLogger(site, logging_component):
828        """Unregister a logger.
829        """
830
831#
832# External File Storage and relatives
833#
834class IFileStoreNameChooser(INameChooser):
835    """See zope.container.interfaces.INameChooser for base methods.
836    """
837    def checkName(name, attr=None):
838        """Check whether an object name is valid.
839
840        Raises a user error if the name is not valid.
841        """
842
843    def chooseName(name, attr=None):
844        """Choose a unique valid file id for the object.
845
846        The given name may be taken into account when choosing the
847        name (file id).
848
849        chooseName is expected to always choose a valid file id (that
850        would pass the checkName test) and never raise an error.
851
852        If `attr` is not ``None`` it might been taken into account as
853        well when generating the file id. Usual behaviour is to
854        interpret `attr` as a hint for what type of file for a given
855        context should be stored if there are several types
856        possible. For instance for a certain student some file could
857        be the connected passport photograph or some certificate scan
858        or whatever. Each of them has to be stored in a different
859        location so setting `attr` to a sensible value should give
860        different file ids returned.
861        """
862
863class IExtFileStore(IFileRetrieval):
864    """A file storage that stores files in filesystem (not as blobs).
865    """
866    root = schema.TextLine(
867        title = u'Root path of file store.',
868        )
869
870    def getFile(file_id):
871        """Get raw file data stored under file with `file_id`.
872
873        Returns a file descriptor open for reading or ``None`` if the
874        file cannot be found.
875        """
876
877    def getFileByContext(context, attr=None):
878        """Get raw file data stored for the given context.
879
880        Returns a file descriptor open for reading or ``None`` if no
881        such file can be found.
882
883        Both, `context` and `attr` might be used to find (`context`)
884        and feed (`attr`) an appropriate file name chooser.
885
886        This is a convenience method.
887        """
888
889    def deleteFile(file_id):
890        """Delete file stored under `file_id`.
891
892        Remove file from filestore so, that it is not available
893        anymore on next call to getFile for the same file_id.
894
895        Should not complain if no such file exists.
896        """
897
898    def deleteFileByContext(context, attr=None):
899        """Delete file for given `context` and `attr`.
900
901        Both, `context` and `attr` might be used to find (`context`)
902        and feed (`attr`) an appropriate file name chooser.
903
904        This is a convenience method.
905        """
906
907    def createFile(filename, f):
908        """Create file given by f with filename `filename`
909
910        Returns a hurry.file.File-based object.
911        """
912
913class IFileStoreHandler(Interface):
914    """Filestore handlers handle specific files for file stores.
915
916    If a file to store/get provides a specific filename, a file store
917    looks up special handlers for that type of file.
918
919    """
920    def pathFromFileID(store, root, filename):
921        """Turn file id into path to store.
922
923        Returned path should be absolute.
924        """
925
926    def createFile(store, root, filename, file_id, file):
927        """Return some hurry.file based on `store` and `file_id`.
928
929        Some kind of callback method called by file stores to create
930        file objects from file_id.
931
932        Returns a tuple ``(raw_file, path, file_like_obj)`` where the
933        ``file_like_obj`` should be a HurryFile, a SIRPImageFile or
934        similar. ``raw_file`` is the (maybe changed) input file and
935        ``path`` the relative internal path to store the file at.
936
937        Please make sure the ``raw_file`` is opened for reading and
938        the file descriptor set at position 0 when returned.
939
940        This method also gets the raw input file object that is about
941        to be stored and is expected to raise any exceptions if some
942        kind of validation or similar fails.
943        """
944
945class IPDF(Interface):
946    """A PDF representation of some context.
947    """
948
949    def __call__(view=None):
950        """Create a bytestream representing a PDF from context.
951
952        If `view` is passed in additional infos might be rendered into
953        the document.
954        """
955
956class IMailService(Interface):
957    """A mail service.
958    """
959
960    def __call__():
961        """Get the default mail delivery.
962        """
963
964from zope.configuration.fields import Path
965class IDataCenterConfig(Interface):
966    path = Path(
967        title = u'Path',
968        description = u"Directory where the datacenter should store"
969                     u"files by default (adjustable in web UI).",
970        required = True,
971        )
972
Note: See TracBrowser for help on using the repository browser.