source: main/waeup.kofa/trunk/src/waeup/kofa/interfaces.py @ 7839

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

Use dictionaries from KofaUtils?.

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