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

Last change on this file since 7702 was 7702, checked in by Henrik Bettermann, 13 years ago

Internationalize ReSTDisplayWidget which now returns a dictionary with different tranlations.

Different languages must be separated by <<xy>> whereas
xy is the language code. Text parts without correct leading
language separator - usually the first part has no language
descriptor - are interpreted as texts in the portal's language.
The latter can be configured in waeup.srp.utils.utils.SIRPUtils.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 27.1 KB
Line 
1## $Id: interfaces.py 7702 2012-02-25 10:21:54Z henrik $
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 ISIRPExporter(Interface):
202    """An exporter for objects.
203    """
204    def export(obj, filepath=None):
205        """Export by pickling.
206
207        Returns a file-like object containing a representation of `obj`.
208
209        This is done using `pickle`. If `filepath` is ``None``, a
210        `cStringIO` object is returned, that contains the saved data.
211        """
212
213class ISIRPXMLExporter(Interface):
214    """An XML exporter for objects.
215    """
216    def export(obj, filepath=None):
217        """Export as XML.
218
219        Returns an XML representation of `obj`.
220
221        If `filepath` is ``None``, a StringIO` object is returned,
222        that contains the transformed data.
223        """
224
225class ISIRPXMLImporter(Interface):
226    """An XML import for objects.
227    """
228    def doImport(filepath):
229        """Create Python object from XML.
230
231        Returns a Python object.
232        """
233
234class IBatchProcessor(Interface):
235    """A batch processor that handles mass-operations.
236    """
237    name = schema.TextLine(
238        title = u'Importer name'
239        )
240
241    mode = schema.Choice(
242        title = u'Import mode',
243        values = ['create', 'update', 'remove']
244        )
245
246    def doImport(path, headerfields, mode='create', user='Unknown',
247                 logger=None):
248        """Read data from ``path`` and update connected object.
249
250        `headerfields` is a list of headerfields as read from the file
251        to import.
252
253        `mode` gives the import mode to use (``'create'``,
254        ``'update'``, or ``'remove'``.
255
256        `user` is a string describing the user performing the
257        import. Normally fetched from current principal.
258
259        `logger` is the logger to use during import.
260        """
261
262class IContactForm(ISIRPObject):
263    """A contact form.
264    """
265
266    email_from = schema.ASCIILine(
267        title = u'Email Address:',
268        default = None,
269        required = True,
270        constraint=validate_email,
271        )
272
273    email_to = schema.ASCIILine(
274        title = u'Email to:',
275        default = None,
276        required = True,
277        constraint=validate_email,
278        )
279
280    subject = schema.TextLine(
281        title = u'Subject:',
282        required = True,)
283
284    fullname = schema.TextLine(
285        title = u'Full Name:',
286        required = True,)
287
288    body = schema.Text(
289        title = u'Text:',
290        required = True,)
291
292class ISIRPPrincipalInfo(IPrincipalInfo):
293    """Infos about principals that are users of SIRP SIRP.
294    """
295    email = Attribute("The email address of a user")
296    phone = Attribute("The phone number of a user")
297
298
299class ISIRPPrincipal(IPrincipal):
300    """A principle for SIRP SIRP.
301
302    This interface extends zope.security.interfaces.IPrincipal and
303    requires also an `id` and other attributes defined there.
304    """
305
306    email = schema.TextLine(
307        title = u'Email',
308        description = u'',
309        required=False,)
310
311    phone = schema.TextLine(
312        title = u'Phone',
313        description = u'',
314        required=False,)
315
316class IUserAccount(ISIRPObject):
317    """A user account.
318    """
319    name = schema.TextLine(
320        title = u'User ID',
321        description = u'Login name of user',
322        required = True,)
323
324    title = schema.TextLine(
325        title = u'Full Name',
326        required = False,)
327
328    description = schema.Text(
329        title = u'Description/Notice',
330        required = False,)
331
332    email = schema.ASCIILine(
333        title = u'Email',
334        default = None,
335        required = True,
336        constraint=validate_email,
337        )
338
339    phone = schema.TextLine(
340        title = u'Phone',
341        default = None,
342        required = True,
343        )
344
345    roles = schema.List(
346        title = u'Portal roles',
347        value_type = schema.Choice(source=RoleSource()))
348
349class IPasswordValidator(Interface):
350    """A password validator utility.
351    """
352
353    def validate_password(password, password_repeat):
354        """Validates a password by comparing it with
355        control password and checking some other requirements.
356        """
357
358
359class IUsersContainer(ISIRPObject):
360    """A container for users (principals).
361
362    These users are used for authentication purposes.
363    """
364
365    def addUser(name, password, title=None, description=None):
366        """Add a user.
367        """
368
369    def delUser(name):
370        """Delete a user if it exists.
371        """
372
373class ILocalRolesAssignable(Interface):
374    """The local roles assignable to an object.
375    """
376    def __call__():
377        """Returns a list of dicts.
378
379        Each dict contains a ``name`` referring to the role assignable
380        for the specified object and a `title` to describe the range
381        of users to which this role can be assigned.
382        """
383
384class IConfigurationContainer(ISIRPObject):
385    """A container for session configuration objects.
386    """
387
388    name = schema.TextLine(
389        title = u'Name of University',
390        default = u'Sample University',
391        required = True,
392        )
393
394    acronym = schema.TextLine(
395        title = u'Abbreviated Title of University',
396        default = u'WAeUP.SIRP',
397        required = True,
398        )
399
400    title = schema.TextLine(
401        title = u'Title of Frontpage',
402        default = u'Welcome to the Student Information and Registration ' +
403                  u'Portal of Sample University',
404        required = False,
405        )
406
407    skin = schema.Choice(
408        title = u'Skin',
409        default = u'gray waeup theme',
410        vocabulary = 'waeup.sirp.browser.theming.ThemesVocabulary',
411        required = True,
412        )
413
414    frontpage = schema.Text(
415        title = u'Content in reST format',
416        required = False,
417        default = default_frontpage,
418        )
419
420    frontpage_dict = schema.Dict(
421        title = u'Content as language dictionary with values in html format',
422        required = False,
423        default = {},
424        )
425
426    accommodation_session = schema.Choice(
427        title = u'Accommodation Booking Session',
428        source = academic_sessions_vocab,
429        default = datetime.now().year,
430        required = False,
431        readonly = False,
432        )
433
434    accommodation_states = schema.List(
435        title = u'Allowed States for Accommodation Booking',
436        value_type = schema.Choice(
437            vocabulary = registration_states_vocab,
438            ),
439        default = [],
440        )
441
442    name_admin = schema.TextLine(
443        title = u'Name of Administrator',
444        default = u'Administrator',
445        required = False,
446        )
447
448    email_admin = schema.ASCIILine(
449        title = u'Email Address of Administrator',
450        default = 'contact@waeup.org',
451        required = False,
452        constraint=validate_email,
453        )
454
455    email_subject = schema.TextLine(
456        title = u'Subject of Email to Administrator',
457        default = u'SIRP Contact',
458        required = False,
459        )
460
461    smtp_mailer = schema.Choice(
462        title = u'SMTP mailer to use when sending mail',
463        vocabulary = 'Mail Delivery Names',
464        default = 'No email service',
465        required = True,
466        )
467
468    captcha = schema.Choice(
469        title = u'Captcha used for public registration pages',
470        source = CaptchaSource(),
471        default = u'No captcha',
472        required = True,
473        )
474
475    carry_over = schema.Bool(
476        title = u'Carry-over Course Registration',
477        default = False,
478        )
479
480class ISessionConfiguration(ISIRPObject):
481    """A session configuration object.
482    """
483
484    academic_session = schema.Choice(
485        title = u'Academic Session',
486        source = academic_sessions_vocab,
487        default = None,
488        required = True,
489        readonly = True,
490        )
491
492    school_fee_base = schema.Int(
493        title = u'School Fee',
494        default = 0,
495        )
496
497    surcharge_1 = schema.Int(
498        title = u'Surcharge 1',
499        default = 0,
500        )
501
502    surcharge_2 = schema.Int(
503        title = u'Surcharge 2',
504        default = 0,
505        )
506
507    surcharge_3 = schema.Int(
508        title = u'Surcharge 3',
509        default = 0,
510        )
511
512    clearance_fee = schema.Int(
513        title = u'Clearance Fee',
514        default = 0,
515        )
516
517    booking_fee = schema.Int(
518        title = u'Booking Fee',
519        default = 0,
520        )
521
522    acceptance_fee = schema.Int(
523        title = u'Acceptance Fee',
524        default = 0,
525        )
526
527    def getSessionString():
528        """Returns the session string from the vocabulary.
529        """
530
531
532class ISessionConfigurationAdd(ISessionConfiguration):
533    """A session configuration object in add mode.
534    """
535
536    academic_session = schema.Choice(
537        title = u'Academic Session',
538        source = academic_sessions_vocab,
539        default = None,
540        required = True,
541        readonly = False,
542        )
543
544ISessionConfigurationAdd['academic_session'].order =  ISessionConfiguration[
545    'academic_session'].order
546
547class IDataCenter(ISIRPObject):
548    """A data center.
549
550    TODO : declare methods, at least those needed by pages.
551    """
552    pass
553
554class IDataCenterFile(Interface):
555    """A data center file.
556    """
557
558    name = schema.TextLine(
559        title = u'Filename')
560
561    size = schema.TextLine(
562        title = u'Human readable file size')
563
564    uploaddate = schema.TextLine(
565        title = u'Human readable upload datetime')
566
567    lines = schema.Int(
568        title = u'Number of lines in file')
569
570    def getDate():
571        """Get creation timestamp from file in human readable form.
572        """
573
574    def getSize():
575        """Get human readable size of file.
576        """
577
578    def getLinesNumber():
579        """Get number of lines of file.
580        """
581
582class IDataCenterStorageMovedEvent(IObjectEvent):
583    """Emitted, when the storage of a datacenter changes.
584    """
585
586class IObjectUpgradeEvent(IObjectEvent):
587    """Can be fired, when an object shall be upgraded.
588    """
589
590class ILocalRoleSetEvent(IObjectEvent):
591    """A local role was granted/revoked for a principal on an object.
592    """
593    role_id = Attribute(
594        "The role id that was set.")
595    principal_id = Attribute(
596        "The principal id for which the role was granted/revoked.")
597    granted = Attribute(
598        "Boolean. If false, then the role was revoked.")
599
600class IQueryResultItem(Interface):
601    """An item in a search result.
602    """
603    url = schema.TextLine(
604        title = u'URL that links to the found item')
605    title = schema.TextLine(
606        title = u'Title displayed in search results.')
607    description = schema.Text(
608        title = u'Longer description of the item found.')
609
610class ISIRPPluggable(Interface):
611    """A component that might be plugged into a SIRP SIRP app.
612
613    Components implementing this interface are referred to as
614    'plugins'. They are normally called when a new
615    :class:`waeup.sirp.app.University` instance is created.
616
617    Plugins can setup and update parts of the central site without the
618    site object (normally a :class:`waeup.sirp.app.University` object)
619    needing to know about that parts. The site simply collects all
620    available plugins, calls them and the plugins care for their
621    respective subarea like the applicants area or the datacenter
622    area.
623
624    Currently we have no mechanism to define an order of plugins. A
625    plugin should therefore make no assumptions about the state of the
626    site or other plugins being run before and instead do appropriate
627    checks if necessary.
628
629    Updates can be triggered for instance by the respective form in
630    the site configuration. You normally do updates when the
631    underlying software changed.
632    """
633    def setup(site, name, logger):
634        """Create an instance of the plugin.
635
636        The method is meant to be called by the central app (site)
637        when it is created.
638
639        `site`:
640           The site that requests a setup.
641
642        `name`:
643           The name under which the plugin was registered (utility name).
644
645        `logger`:
646           A standard Python logger for the plugins use.
647        """
648
649    def update(site, name, logger):
650        """Method to update an already existing plugin.
651
652        This might be called by a site when something serious
653        changes. It is a poor-man replacement for Zope generations
654        (but probably more comprehensive and better understandable).
655
656        `site`:
657           The site that requests an update.
658
659        `name`:
660           The name under which the plugin was registered (utility name).
661
662        `logger`:
663           A standard Python logger for the plugins use.
664        """
665
666class IAuthPluginUtility(Interface):
667    """A component that cares for authentication setup at site creation.
668
669    Utilities providing this interface are looked up when a Pluggable
670    Authentication Utility (PAU) for any
671    :class:`waeup.sirp.app.University` instance is created and put
672    into ZODB.
673
674    The setup-code then calls the `register` method of the utility and
675    expects a modified (or unmodified) version of the PAU back.
676
677    This allows to define any authentication setup modifications by
678    submodules or third-party modules/packages.
679    """
680
681    def register(pau):
682        """Register any plugins wanted to be in the PAU.
683        """
684
685    def unregister(pau):
686        """Unregister any plugins not wanted to be in the PAU.
687        """
688
689class IObjectConverter(Interface):
690    """Object converters are available as simple adapters, adapting
691       interfaces (not regular instances).
692
693    """
694
695    def fromStringDict(self, data_dict, context, form_fields=None):
696        """Convert values in `data_dict`.
697
698        Converts data in `data_dict` into real values based on
699        `context` and `form_fields`.
700
701        `data_dict` is a mapping (dict) from field names to values
702        represented as strings.
703
704        The fields (keys) to convert can be given in optional
705        `form_fields`. If given, form_fields should be an instance of
706        :class:`zope.formlib.form.Fields`. Suitable instances are for
707        example created by :class:`grok.AutoFields`.
708
709        If no `form_fields` are given, a default is computed from the
710        associated interface.
711
712        The `context` can be an existing object (implementing the
713        associated interface) or a factory name. If it is a string, we
714        try to create an object using
715        :func:`zope.component.createObject`.
716
717        Returns a tuple ``(<FIELD_ERRORS>, <INVARIANT_ERRORS>,
718        <DATA_DICT>)`` where
719
720        ``<FIELD_ERRORS>``
721           is a list of tuples ``(<FIELD_NAME>, <ERROR>)`` for each
722           error that happened when validating the input data in
723           `data_dict`
724
725        ``<INVARIANT_ERRORS>``
726           is a list of invariant errors concerning several fields
727
728        ``<DATA_DICT>``
729           is a dict with the values from input dict converted.
730
731        If errors happen, i.e. the error lists are not empty, always
732        an empty ``<DATA_DICT>`` is returned.
733
734        If ``<DATA_DICT>` is non-empty, there were no errors.
735        """
736
737class IObjectHistory(Interface):
738
739    messages = schema.List(
740        title = u'List of messages stored',
741        required = True,
742        )
743
744    def addMessage(message):
745        """Add a message.
746        """
747
748class ISIRPWorkflowInfo(IWorkflowInfo):
749    """A :class:`hurry.workflow.workflow.WorkflowInfo` with additional
750       methods for convenience.
751    """
752    def getManualTransitions():
753        """Get allowed manual transitions.
754
755        Get a sorted list of tuples containing the `transition_id` and
756        `title` of each allowed transition.
757        """
758
759class ISiteLoggers(Interface):
760
761    loggers = Attribute("A list or generator of registered SIRPLoggers")
762
763    def register(name, filename=None, site=None, **options):
764        """Register a logger `name` which logs to `filename`.
765
766        If `filename` is not given, logfile will be `name` with
767        ``.log`` as filename extension.
768        """
769
770    def unregister(name):
771        """Unregister a once registered logger.
772        """
773
774class ILogger(Interface):
775    """A logger cares for setup, update and restarting of a Python logger.
776    """
777
778    logger = Attribute("""A :class:`logging.Logger` instance""")
779
780
781    def __init__(name, filename=None, site=None, **options):
782        """Create a SIRP logger instance.
783        """
784
785    def setup():
786        """Create a Python :class:`logging.Logger` instance.
787
788        The created logger is based on the params given by constructor.
789        """
790
791    def update(**options):
792        """Update the logger.
793
794        Updates the logger respecting modified `options` and changed
795        paths.
796        """
797
798class ILoggerCollector(Interface):
799
800    def getLoggers(site):
801        """Return all loggers registered for `site`.
802        """
803
804    def registerLogger(site, logging_component):
805        """Register a logging component residing in `site`.
806        """
807
808    def unregisterLogger(site, logging_component):
809        """Unregister a logger.
810        """
811
812#
813# External File Storage and relatives
814#
815class IFileStoreNameChooser(INameChooser):
816    """See zope.container.interfaces.INameChooser for base methods.
817    """
818    def checkName(name, attr=None):
819        """Check whether an object name is valid.
820
821        Raises a user error if the name is not valid.
822        """
823
824    def chooseName(name, attr=None):
825        """Choose a unique valid file id for the object.
826
827        The given name may be taken into account when choosing the
828        name (file id).
829
830        chooseName is expected to always choose a valid file id (that
831        would pass the checkName test) and never raise an error.
832
833        If `attr` is not ``None`` it might been taken into account as
834        well when generating the file id. Usual behaviour is to
835        interpret `attr` as a hint for what type of file for a given
836        context should be stored if there are several types
837        possible. For instance for a certain student some file could
838        be the connected passport photograph or some certificate scan
839        or whatever. Each of them has to be stored in a different
840        location so setting `attr` to a sensible value should give
841        different file ids returned.
842        """
843
844class IExtFileStore(IFileRetrieval):
845    """A file storage that stores files in filesystem (not as blobs).
846    """
847    root = schema.TextLine(
848        title = u'Root path of file store.',
849        )
850
851    def getFile(file_id):
852        """Get raw file data stored under file with `file_id`.
853
854        Returns a file descriptor open for reading or ``None`` if the
855        file cannot be found.
856        """
857
858    def getFileByContext(context, attr=None):
859        """Get raw file data stored for the given context.
860
861        Returns a file descriptor open for reading or ``None`` if no
862        such file can be found.
863
864        Both, `context` and `attr` might be used to find (`context`)
865        and feed (`attr`) an appropriate file name chooser.
866
867        This is a convenience method.
868        """
869
870    def deleteFile(file_id):
871        """Delete file stored under `file_id`.
872
873        Remove file from filestore so, that it is not available
874        anymore on next call to getFile for the same file_id.
875
876        Should not complain if no such file exists.
877        """
878
879    def deleteFileByContext(context, attr=None):
880        """Delete file for given `context` and `attr`.
881
882        Both, `context` and `attr` might be used to find (`context`)
883        and feed (`attr`) an appropriate file name chooser.
884
885        This is a convenience method.
886        """
887
888    def createFile(filename, f):
889        """Create file given by f with filename `filename`
890
891        Returns a hurry.file.File-based object.
892        """
893
894class IFileStoreHandler(Interface):
895    """Filestore handlers handle specific files for file stores.
896
897    If a file to store/get provides a specific filename, a file store
898    looks up special handlers for that type of file.
899
900    """
901    def pathFromFileID(store, root, filename):
902        """Turn file id into path to store.
903
904        Returned path should be absolute.
905        """
906
907    def createFile(store, root, filename, file_id, file):
908        """Return some hurry.file based on `store` and `file_id`.
909
910        Some kind of callback method called by file stores to create
911        file objects from file_id.
912
913        Returns a tuple ``(raw_file, path, file_like_obj)`` where the
914        ``file_like_obj`` should be a HurryFile, a SIRPImageFile or
915        similar. ``raw_file`` is the (maybe changed) input file and
916        ``path`` the relative internal path to store the file at.
917
918        Please make sure the ``raw_file`` is opened for reading and
919        the file descriptor set at position 0 when returned.
920
921        This method also gets the raw input file object that is about
922        to be stored and is expected to raise any exceptions if some
923        kind of validation or similar fails.
924        """
925
926class IPDF(Interface):
927    """A PDF representation of some context.
928    """
929
930    def __call__(view=None):
931        """Create a bytestream representing a PDF from context.
932
933        If `view` is passed in additional infos might be rendered into
934        the document.
935        """
936
937class IMailService(Interface):
938    """A mail service.
939    """
940
941    def __call__():
942        """Get the default mail delivery.
943        """
944
945from zope.configuration.fields import Path
946class IDataCenterConfig(Interface):
947    path = Path(
948        title = u'Path',
949        description = u"Directory where the datacenter should store"
950                     u"files by default (adjustable in web UI).",
951        required = True,
952        )
953
Note: See TracBrowser for help on using the repository browser.