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

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

Lots of trash to sketch filtered imports.

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