| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  | # ------------------------------------------------------------------------------ | 
					
						
							| 
									
										
										
										
											2009-10-25 21:42:08 +01:00
										 |  |  | import re, time | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  | from appy.gen.utils import sequenceTypes, PageDescr | 
					
						
							| 
									
										
										
										
											2009-11-17 15:46:41 +01:00
										 |  |  | from appy.shared.data import countries | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Default Appy permissions ----------------------------------------------------- | 
					
						
							|  |  |  | r, w, d = ('read', 'write', 'delete') | 
					
						
							| 
									
										
										
										
											2009-11-17 15:46:41 +01:00
										 |  |  | digit = re.compile('[0-9]') | 
					
						
							|  |  |  | alpha = re.compile('[a-zA-Z0-9]') | 
					
						
							|  |  |  | letter = re.compile('[a-zA-Z]') | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Descriptor classes used for refining descriptions of elements in types | 
					
						
							|  |  |  | # (pages, groups,...) ---------------------------------------------------------- | 
					
						
							|  |  |  | class Page: | 
					
						
							| 
									
										
										
										
											2009-10-20 16:57:00 +02:00
										 |  |  |     '''Used for describing a page, its related phase, show condition, etc.''' | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |     def __init__(self, name, phase='main', show=True): | 
					
						
							|  |  |  |         self.name = name | 
					
						
							|  |  |  |         self.phase = phase | 
					
						
							|  |  |  |         self.show = show | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-20 16:57:00 +02:00
										 |  |  | class Import: | 
					
						
							|  |  |  |     '''Used for describing the place where to find the data to use for creating
 | 
					
						
							|  |  |  |        an object.'''
 | 
					
						
							|  |  |  |     def __init__(self, path, columnMethod=None, columnHeaders=(), | 
					
						
							|  |  |  |                  sortMethod=None): | 
					
						
							|  |  |  |         self.id = 'import' | 
					
						
							|  |  |  |         self.path = path | 
					
						
							|  |  |  |         self.columnMethod = columnMethod | 
					
						
							|  |  |  |         # This method allows to split every element into subElements that can | 
					
						
							|  |  |  |         # be shown as column values in a table. | 
					
						
							|  |  |  |         self.columnHeaders = columnHeaders | 
					
						
							|  |  |  |         self.sortMethod = sortMethod | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  | class Search: | 
					
						
							|  |  |  |     '''Used for specifying a search for a given type.''' | 
					
						
							| 
									
										
										
										
											2009-11-06 11:33:56 +01:00
										 |  |  |     def __init__(self, name, group=None, sortBy='', limit=None, **fields): | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |         self.name = name | 
					
						
							| 
									
										
										
										
											2009-11-06 11:33:56 +01:00
										 |  |  |         self.group = group # Searches may be visually grouped in the portlet | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |         self.sortBy = sortBy | 
					
						
							|  |  |  |         self.limit = limit | 
					
						
							|  |  |  |         self.fields = fields # This is a dict whose keys are indexed field | 
					
						
							| 
									
										
										
										
											2009-11-03 15:02:18 +01:00
										 |  |  |         # names and whose values are search values. | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  | # ------------------------------------------------------------------------------ | 
					
						
							|  |  |  | class Type: | 
					
						
							|  |  |  |     '''Basic abstract class for defining any appy type.''' | 
					
						
							|  |  |  |     def __init__(self, validator, multiplicity, index, default, optional, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                  editDefault, show, page, group, move, indexed, searchable, | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |                  specificReadPermission, specificWritePermission, width, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                  height, master, masterValue, focus, historized): | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         # The validator restricts which values may be defined. It can be an | 
					
						
							|  |  |  |         # interval (1,None), a list of string values ['choice1', 'choice2'], | 
					
						
							|  |  |  |         # a regular expression, a custom function, a Selection instance, etc. | 
					
						
							|  |  |  |         self.validator = validator | 
					
						
							|  |  |  |         # Multiplicity is a tuple indicating the minimum and maximum | 
					
						
							|  |  |  |         # occurrences of values. | 
					
						
							|  |  |  |         self.multiplicity = multiplicity | 
					
						
							|  |  |  |         # Type of the index on the values. If you want to represent a simple | 
					
						
							|  |  |  |         # (ordered) list of values, specify None. If you want to | 
					
						
							|  |  |  |         # index your values with unordered integers or with other types like | 
					
						
							|  |  |  |         # strings (thus creating a dictionary of values instead of a list), | 
					
						
							|  |  |  |         # specify a type specification for the index, like Integer() or | 
					
						
							|  |  |  |         # String(). Note that this concept of "index" has nothing to do with | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |         # the concept of "database index" (see fields "indexed" and | 
					
						
							|  |  |  |         # "searchable" below). self.index is not yet used. | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         self.index = index | 
					
						
							|  |  |  |         # Default value | 
					
						
							|  |  |  |         self.default = default | 
					
						
							|  |  |  |         # Is the field optional or not ? | 
					
						
							|  |  |  |         self.optional = optional | 
					
						
							|  |  |  |         # May the user configure a default value ? | 
					
						
							|  |  |  |         self.editDefault = editDefault | 
					
						
							|  |  |  |         # Must the field be visible or not? | 
					
						
							|  |  |  |         self.show = show | 
					
						
							|  |  |  |         # When displaying/editing the whole object, on what page and phase must | 
					
						
							|  |  |  |         # this field value appear? Default is ('main', 'main'). pageShow | 
					
						
							|  |  |  |         # indicates if the page must be shown or not. | 
					
						
							|  |  |  |         self.page, self.phase, self.pageShow = PageDescr.getPageInfo(page, Page) | 
					
						
							|  |  |  |         # Within self.page, in what group of fields must this field value | 
					
						
							|  |  |  |         # appear? | 
					
						
							|  |  |  |         self.group = group | 
					
						
							|  |  |  |         # The following attribute allows to move a field back to a previous | 
					
						
							|  |  |  |         # position (useful for content types that inherit from others). | 
					
						
							|  |  |  |         self.move = move | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |         # If indexed is True, a database index will be set on the field for | 
					
						
							|  |  |  |         # fast access. | 
					
						
							|  |  |  |         self.indexed = indexed | 
					
						
							|  |  |  |         # If specified "searchable", the field will be added to some global | 
					
						
							|  |  |  |         # index allowing to perform application-wide, keyword searches. | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         self.searchable = searchable | 
					
						
							|  |  |  |         # Normally, permissions to read or write every attribute in a type are | 
					
						
							|  |  |  |         # granted if the user has the global permission to read or | 
					
						
							|  |  |  |         # create/edit instances of the whole type. If you want a given attribute | 
					
						
							|  |  |  |         # to be protected by specific permissions, set one or the 2 next boolean | 
					
						
							|  |  |  |         # values to "True". | 
					
						
							|  |  |  |         self.specificReadPermission = specificReadPermission | 
					
						
							|  |  |  |         self.specificWritePermission = specificWritePermission | 
					
						
							|  |  |  |         # Widget width and height | 
					
						
							|  |  |  |         self.width = width | 
					
						
							|  |  |  |         self.height = height | 
					
						
							|  |  |  |         # The behaviour of this field may depend on another, "master" field | 
					
						
							|  |  |  |         self.master = master | 
					
						
							|  |  |  |         if master: | 
					
						
							|  |  |  |             self.master.slaves.append(self) | 
					
						
							|  |  |  |         # When master has some value(s), there is impact on this field. | 
					
						
							|  |  |  |         self.masterValue = masterValue | 
					
						
							| 
									
										
										
										
											2009-10-25 21:42:08 +01:00
										 |  |  |         # If a field must retain attention in a particular way, set focus=True. | 
					
						
							|  |  |  |         # It will be rendered in a special way. | 
					
						
							|  |  |  |         self.focus = focus | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |         # If we must keep track of changes performed on a field, "historized" | 
					
						
							|  |  |  |         # must be set to True. | 
					
						
							|  |  |  |         self.historized = historized | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         self.id = id(self) | 
					
						
							|  |  |  |         self.type = self.__class__.__name__ | 
					
						
							|  |  |  |         self.pythonType = None # The True corresponding Python type | 
					
						
							|  |  |  |         self.slaves = [] # The list of slaves of this field | 
					
						
							|  |  |  |         self.selfClass = None # The Python class to which this Type definition | 
					
						
							|  |  |  |         # is linked. This will be computed at runtime. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def isMultiValued(self): | 
					
						
							|  |  |  |         '''Does this type definition allow to define multiple values?''' | 
					
						
							|  |  |  |         res = False | 
					
						
							|  |  |  |         maxOccurs = self.multiplicity[1] | 
					
						
							|  |  |  |         if (maxOccurs == None) or (maxOccurs > 1): | 
					
						
							|  |  |  |             res = True | 
					
						
							|  |  |  |         return res | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Integer(Type): | 
					
						
							|  |  |  |     def __init__(self, validator=None, multiplicity=(0,1), index=None, | 
					
						
							|  |  |  |                  default=None, optional=False, editDefault=False, show=True, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                  page='main', group=None, move=0, indexed=False, | 
					
						
							|  |  |  |                  searchable=False, specificReadPermission=False, | 
					
						
							|  |  |  |                  specificWritePermission=False, width=None, height=None, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                  master=None, masterValue=None, focus=False, historized=False): | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         Type.__init__(self, validator, multiplicity, index, default, optional, | 
					
						
							| 
									
										
										
										
											2009-11-11 20:22:13 +01:00
										 |  |  |                       editDefault, show, page, group, move, indexed, searchable, | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |                       specificReadPermission, specificWritePermission, width, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                       height, master, masterValue, focus, historized) | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         self.pythonType = long | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Float(Type): | 
					
						
							|  |  |  |     def __init__(self, validator=None, multiplicity=(0,1), index=None, | 
					
						
							|  |  |  |                  default=None, optional=False, editDefault=False, show=True, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                  page='main', group=None, move=0, indexed=False, | 
					
						
							|  |  |  |                  searchable=False, specificReadPermission=False, | 
					
						
							|  |  |  |                  specificWritePermission=False, width=None, height=None, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                  master=None, masterValue=None, focus=False, historized=False): | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         Type.__init__(self, validator, multiplicity, index, default, optional, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                       editDefault, show, page, group, move, indexed, False, | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |                       specificReadPermission, specificWritePermission, width, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                       height, master, masterValue, focus, historized) | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         self.pythonType = float | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class String(Type): | 
					
						
							|  |  |  |     # Some predefined regular expressions that may be used as validators | 
					
						
							|  |  |  |     c = re.compile | 
					
						
							|  |  |  |     EMAIL = c('[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.' \ | 
					
						
							|  |  |  |               '[a-zA-Z][a-zA-Z\.]*[a-zA-Z]') | 
					
						
							|  |  |  |     ALPHANUMERIC = c('[\w-]+') | 
					
						
							|  |  |  |     URL = c('(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*(\.[a-z]{2,5})?' \ | 
					
						
							|  |  |  |             '(([0-9]{1,5})?\/.*)?') | 
					
						
							| 
									
										
										
										
											2009-10-27 14:48:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Some predefined functions that may also be used as validators | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							|  |  |  |     def _MODULO_97(obj, value, complement=False): | 
					
						
							|  |  |  |         '''p_value must be a string representing a number, like a bank account.
 | 
					
						
							|  |  |  |            this function checks that the 2 last digits are the result of | 
					
						
							|  |  |  |            computing the modulo 97 of the previous digits. Any non-digit | 
					
						
							|  |  |  |            character is ignored. If p_complement is True, it does compute the | 
					
						
							|  |  |  |            complement of modulo 97 instead of modulo 97. p_obj is not used; | 
					
						
							|  |  |  |            it will be given by the Appy validation machinery, so it must be | 
					
						
							| 
									
										
										
										
											2009-11-03 15:02:18 +01:00
										 |  |  |            specified as parameter. The function returns True if the check is | 
					
						
							|  |  |  |            successful.'''
 | 
					
						
							| 
									
										
										
										
											2009-10-27 14:48:04 +01:00
										 |  |  |         if not value: return True # Plone calls me erroneously for | 
					
						
							|  |  |  |         # non-mandatory fields. | 
					
						
							|  |  |  |         # First, remove any non-digit char | 
					
						
							|  |  |  |         v = '' | 
					
						
							|  |  |  |         for c in value: | 
					
						
							| 
									
										
										
										
											2009-11-17 15:46:41 +01:00
										 |  |  |             if digit.match(c): v += c | 
					
						
							| 
									
										
										
										
											2009-10-27 14:48:04 +01:00
										 |  |  |         # There must be at least 3 digits for performing the check | 
					
						
							|  |  |  |         if len(v) < 3: return False | 
					
						
							|  |  |  |         # Separate the real number from the check digits | 
					
						
							|  |  |  |         number = int(v[:-2]) | 
					
						
							|  |  |  |         checkNumber = int(v[-2:]) | 
					
						
							|  |  |  |         # Perform the check | 
					
						
							|  |  |  |         if complement: | 
					
						
							|  |  |  |             return (97 - (number % 97)) == checkNumber | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return (number % 97) == checkNumber | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							|  |  |  |     def MODULO_97(obj, value): return String._MODULO_97(obj, value) | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							|  |  |  |     def MODULO_97_COMPLEMENT(obj, value): | 
					
						
							|  |  |  |         return String._MODULO_97(obj, value, True) | 
					
						
							| 
									
										
										
										
											2009-11-17 15:46:41 +01:00
										 |  |  |     @staticmethod | 
					
						
							|  |  |  |     def IBAN(obj, value): | 
					
						
							|  |  |  |         '''Checks that p_value corresponds to a valid IBAN number. IBAN stands
 | 
					
						
							|  |  |  |            for International Bank Account Number (ISO 13616). If the number is | 
					
						
							|  |  |  |            valid, the method returns True.'''
 | 
					
						
							|  |  |  |         if not value: return True # Plone calls me erroneously for | 
					
						
							|  |  |  |         # non-mandatory fields. | 
					
						
							|  |  |  |         # First, remove any non-digit or non-letter char | 
					
						
							|  |  |  |         v = '' | 
					
						
							|  |  |  |         for c in value: | 
					
						
							|  |  |  |             if alpha.match(c): v += c | 
					
						
							|  |  |  |         # Maximum size is 34 chars | 
					
						
							|  |  |  |         if (len(v) < 8) or (len(v) > 34): return False | 
					
						
							|  |  |  |         # 2 first chars must be a valid country code | 
					
						
							|  |  |  |         if not countries.exists(v[:2].lower()): return False | 
					
						
							|  |  |  |         # 2 next chars are a control code whose value must be between 0 and 96. | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             code = int(v[2:4]) | 
					
						
							|  |  |  |             if (code < 0) or (code > 96): return False | 
					
						
							|  |  |  |         except ValueError: | 
					
						
							|  |  |  |             return False | 
					
						
							|  |  |  |         # Perform the checksum | 
					
						
							|  |  |  |         vv = v[4:] + v[:4] # Put the 4 first chars at the end. | 
					
						
							|  |  |  |         nv = '' | 
					
						
							|  |  |  |         for c in vv: | 
					
						
							|  |  |  |             # Convert each letter into a number (A=10, B=11, etc) | 
					
						
							|  |  |  |             # Ascii code for a is 65, so A=10 if we perform "minus 55" | 
					
						
							|  |  |  |             if letter.match(c): nv += str(ord(c.upper()) - 55) | 
					
						
							|  |  |  |             else: nv += c | 
					
						
							|  |  |  |         return int(nv) % 97 == 1 | 
					
						
							|  |  |  |     @staticmethod | 
					
						
							|  |  |  |     def BIC(obj, value): | 
					
						
							|  |  |  |         '''Checks that p_value corresponds to a valid BIC number. BIC stands
 | 
					
						
							|  |  |  |            for Bank Identifier Code (ISO 9362). If the number is valid, the | 
					
						
							|  |  |  |            method returns True.'''
 | 
					
						
							|  |  |  |         if not value: return True # Plone calls me erroneously for | 
					
						
							|  |  |  |         # non-mandatory fields. | 
					
						
							|  |  |  |         # BIC number must be 8 or 11 chars | 
					
						
							|  |  |  |         if len(value) not in (8, 11): return False | 
					
						
							|  |  |  |         # 4 first chars, representing bank name, must be letters | 
					
						
							|  |  |  |         for c in value[:4]: | 
					
						
							|  |  |  |             if not letter.match(c): return False | 
					
						
							|  |  |  |         # 2 next chars must be a valid country code | 
					
						
							|  |  |  |         if not countries.exists(value[4:6].lower()): return False | 
					
						
							|  |  |  |         # Last chars represent some location within a country (a city, a | 
					
						
							|  |  |  |         # province...). They can only be letters or figures. | 
					
						
							|  |  |  |         for c in value[6:]: | 
					
						
							|  |  |  |             if not alpha.match(c): return False | 
					
						
							|  |  |  |         return True | 
					
						
							| 
									
										
										
										
											2009-10-27 14:48:04 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |     # Possible values for "format" | 
					
						
							|  |  |  |     LINE = 0 | 
					
						
							|  |  |  |     TEXT = 1 | 
					
						
							|  |  |  |     XHTML = 2 | 
					
						
							| 
									
										
										
										
											2009-11-25 20:37:22 +01:00
										 |  |  |     PASSWORD = 3 | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |     def __init__(self, validator=None, multiplicity=(0,1), index=None, | 
					
						
							|  |  |  |                  default=None, optional=False, editDefault=False, format=LINE, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                  show=True, page='main', group=None, move=0, indexed=False, | 
					
						
							|  |  |  |                  searchable=False, specificReadPermission=False, | 
					
						
							|  |  |  |                  specificWritePermission=False, width=None, height=None, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                  master=None, masterValue=None, focus=False, historized=False): | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         Type.__init__(self, validator, multiplicity, index, default, optional, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                       editDefault, show, page, group, move, indexed, searchable, | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |                       specificReadPermission, specificWritePermission, width, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                       height, master, masterValue, focus, historized) | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         self.format = format | 
					
						
							| 
									
										
										
										
											2009-11-13 18:21:03 +01:00
										 |  |  |         self.isSelect = self.isSelection() | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |     def isSelection(self): | 
					
						
							|  |  |  |         '''Does the validator of this type definition define a list of values
 | 
					
						
							|  |  |  |            into which the user must select one or more values?'''
 | 
					
						
							|  |  |  |         res = True | 
					
						
							|  |  |  |         if type(self.validator) in (list, tuple): | 
					
						
							|  |  |  |             for elem in self.validator: | 
					
						
							|  |  |  |                 if not isinstance(elem, basestring): | 
					
						
							|  |  |  |                     res = False | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             if not isinstance(self.validator, Selection): | 
					
						
							|  |  |  |                 res = False | 
					
						
							|  |  |  |         return res | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Boolean(Type): | 
					
						
							|  |  |  |     def __init__(self, validator=None, multiplicity=(0,1), index=None, | 
					
						
							|  |  |  |                  default=None, optional=False, editDefault=False, show=True, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                  page='main', group=None, move=0, indexed=False, | 
					
						
							|  |  |  |                  searchable=False, specificReadPermission=False, | 
					
						
							|  |  |  |                  specificWritePermission=False, width=None, height=None, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                  master=None, masterValue=None, focus=False, historized=False): | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         Type.__init__(self, validator, multiplicity, index, default, optional, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                       editDefault, show, page, group, move, indexed, searchable, | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |                       specificReadPermission, specificWritePermission, width, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                       height, master, masterValue, focus, historized) | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         self.pythonType = bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Date(Type): | 
					
						
							|  |  |  |     # Possible values for "format" | 
					
						
							|  |  |  |     WITH_HOUR = 0 | 
					
						
							|  |  |  |     WITHOUT_HOUR = 1 | 
					
						
							|  |  |  |     def __init__(self, validator=None, multiplicity=(0,1), index=None, | 
					
						
							|  |  |  |                  default=None, optional=False, editDefault=False, | 
					
						
							| 
									
										
										
										
											2009-10-25 21:42:08 +01:00
										 |  |  |                  format=WITH_HOUR, startYear=time.localtime()[0]-10, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                  endYear=time.localtime()[0]+10, show=True, page='main', | 
					
						
							|  |  |  |                  group=None, move=0, indexed=False, searchable=False, | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |                  specificReadPermission=False, specificWritePermission=False, | 
					
						
							| 
									
										
										
										
											2009-10-25 21:42:08 +01:00
										 |  |  |                  width=None, height=None, master=None, masterValue=None, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                  focus=False, historized=False): | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         Type.__init__(self, validator, multiplicity, index, default, optional, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                       editDefault, show, page, group, move, indexed, searchable, | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |                       specificReadPermission, specificWritePermission, width, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                       height, master, masterValue, focus, historized) | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         self.format = format | 
					
						
							| 
									
										
										
										
											2009-10-25 21:42:08 +01:00
										 |  |  |         self.startYear = startYear | 
					
						
							|  |  |  |         self.endYear = endYear | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | class File(Type): | 
					
						
							|  |  |  |     def __init__(self, validator=None, multiplicity=(0,1), index=None, | 
					
						
							|  |  |  |                  default=None, optional=False, editDefault=False, show=True, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                  page='main', group=None, move=0, indexed=False, | 
					
						
							|  |  |  |                  searchable=False, specificReadPermission=False, | 
					
						
							|  |  |  |                  specificWritePermission=False, width=None, height=None, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                  master=None, masterValue=None, focus=False, historized=False, | 
					
						
							|  |  |  |                  isImage=False): | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         Type.__init__(self, validator, multiplicity, index, default, optional, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                       editDefault, show, page, group, move, indexed, False, | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |                       specificReadPermission, specificWritePermission, width, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                       height, master, masterValue, focus, historized) | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         self.isImage = isImage | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Ref(Type): | 
					
						
							|  |  |  |     def __init__(self, klass=None, attribute=None, validator=None, | 
					
						
							|  |  |  |                  multiplicity=(0,1), index=None, default=None, optional=False, | 
					
						
							|  |  |  |                  editDefault=False, add=False, link=True, unlink=False, | 
					
						
							|  |  |  |                  back=None, isBack=False, show=True, page='main', group=None, | 
					
						
							|  |  |  |                  showHeaders=False, shownInfo=(), wide=False, select=None, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                  maxPerPage=30, move=0, indexed=False, searchable=False, | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |                  specificReadPermission=False, specificWritePermission=False, | 
					
						
							| 
									
										
										
										
											2009-10-25 21:42:08 +01:00
										 |  |  |                  width=None, height=None, master=None, masterValue=None, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                  focus=False, historized=False): | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         Type.__init__(self, validator, multiplicity, index, default, optional, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                       editDefault, show, page, group, move, indexed, False, | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |                       specificReadPermission, specificWritePermission, width, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                       height, master, masterValue, focus, historized) | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         self.klass = klass | 
					
						
							|  |  |  |         self.attribute = attribute | 
					
						
							|  |  |  |         self.add = add # May the user add new objects through this ref ? | 
					
						
							|  |  |  |         self.link = link # May the user link existing objects through this ref? | 
					
						
							|  |  |  |         self.unlink = unlink # May the user unlink existing objects? | 
					
						
							|  |  |  |         self.back = back | 
					
						
							|  |  |  |         self.isBack = isBack # Should always be False | 
					
						
							|  |  |  |         self.showHeaders = showHeaders # When displaying a tabular list of | 
					
						
							|  |  |  |         # referenced objects, must we show the table headers? | 
					
						
							|  |  |  |         self.shownInfo = shownInfo # When displaying referenced object(s), | 
					
						
							|  |  |  |         # we will display its title + all other fields whose names are listed | 
					
						
							|  |  |  |         # in this attribute. | 
					
						
							|  |  |  |         self.wide = wide # If True, the table of references will be as wide | 
					
						
							|  |  |  |         # as possible | 
					
						
							|  |  |  |         self.select = select # If a method is defined here, it will be used to | 
					
						
							|  |  |  |         # filter the list of available tied objects. | 
					
						
							| 
									
										
										
										
											2009-10-25 21:42:08 +01:00
										 |  |  |         self.maxPerPage = maxPerPage # Maximum number of referenced objects | 
					
						
							|  |  |  |         # shown at once. | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | class Computed(Type): | 
					
						
							|  |  |  |     def __init__(self, validator=None, multiplicity=(0,1), index=None, | 
					
						
							| 
									
										
										
										
											2009-12-17 21:14:52 +01:00
										 |  |  |                  default=None, optional=False, editDefault=False, show='view', | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                  page='main', group=None, move=0, indexed=False, | 
					
						
							|  |  |  |                  searchable=False, specificReadPermission=False, | 
					
						
							|  |  |  |                  specificWritePermission=False, width=None, height=None, | 
					
						
							|  |  |  |                  method=None, plainText=True, master=None, masterValue=None, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                  focus=False, historized=False): | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         Type.__init__(self, None, multiplicity, index, default, optional, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                       False, show, page, group, move, indexed, False, | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |                       specificReadPermission, specificWritePermission, width, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                       height, master, masterValue, focus, historized) | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         self.method = method # The method used for computing the field value | 
					
						
							|  |  |  |         self.plainText = plainText # Does field computation produce pain text | 
					
						
							|  |  |  |         # or XHTML? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Action(Type): | 
					
						
							|  |  |  |     '''An action is a workflow-independent Python method that can be triggered
 | 
					
						
							|  |  |  |        by the user on a given gen-class. For example, the custom installation | 
					
						
							|  |  |  |        procedure of a gen-application is implemented by an action on the custom | 
					
						
							|  |  |  |        tool class. An action is rendered as a button.'''
 | 
					
						
							|  |  |  |     def __init__(self, validator=None, multiplicity=(1,1), index=None, | 
					
						
							|  |  |  |                  default=None, optional=False, editDefault=False, show=True, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                  page='main', group=None, move=0, indexed=False, | 
					
						
							|  |  |  |                  searchable=False, specificReadPermission=False, | 
					
						
							|  |  |  |                  specificWritePermission=False, width=None, height=None, | 
					
						
							|  |  |  |                  action=None, result='computation', master=None, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                  masterValue=None, focus=False, historized=False): | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         Type.__init__(self, None, (0,1), index, default, optional, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                       False, show, page, group, move, indexed, False, | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |                       specificReadPermission, specificWritePermission, width, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                       height, master, masterValue, focus, historized) | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         self.action = action # Can be a single method or a list/tuple of methods | 
					
						
							| 
									
										
										
										
											2009-10-25 21:42:08 +01:00
										 |  |  |         self.result = result # 'computation' means that the action will simply | 
					
						
							|  |  |  |         # compute things and redirect the user to the same page, with some | 
					
						
							|  |  |  |         # status message about execution of the action. 'file' means that the | 
					
						
							|  |  |  |         # result is the binary content of a file that the user will download. | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __call__(self, obj): | 
					
						
							|  |  |  |         '''Calls the action on p_obj.''' | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             if type(self.action) in sequenceTypes: | 
					
						
							|  |  |  |                 # There are multiple Python methods | 
					
						
							|  |  |  |                 res = [True, ''] | 
					
						
							|  |  |  |                 for act in self.action: | 
					
						
							|  |  |  |                     actRes = act(obj) | 
					
						
							|  |  |  |                     if type(actRes) in sequenceTypes: | 
					
						
							|  |  |  |                         res[0] = res[0] and actRes[0] | 
					
						
							| 
									
										
										
										
											2009-10-25 21:42:08 +01:00
										 |  |  |                         if self.result == 'file': | 
					
						
							|  |  |  |                             res[1] = res[1] + actRes[1] | 
					
						
							|  |  |  |                         else: | 
					
						
							|  |  |  |                             res[1] = res[1] + '\n' + actRes[1] | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |                     else: | 
					
						
							|  |  |  |                         res[0] = res[0] and actRes | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 # There is only one Python method | 
					
						
							|  |  |  |                 actRes = self.action(obj) | 
					
						
							|  |  |  |                 if type(actRes) in sequenceTypes: | 
					
						
							|  |  |  |                     res = list(actRes) | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     res = [actRes, ''] | 
					
						
							| 
									
										
										
										
											2009-10-25 21:42:08 +01:00
										 |  |  |             # If res is None (ie the user-defined action did not return | 
					
						
							|  |  |  |             # anything), we consider the action as successfull. | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |             if res[0] == None: res[0] = True | 
					
						
							|  |  |  |         except Exception, e: | 
					
						
							|  |  |  |             res = (False, str(e)) | 
					
						
							|  |  |  |         return res | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Info(Type): | 
					
						
							|  |  |  |     '''An info is a field whose purpose is to present information
 | 
					
						
							|  |  |  |        (text, html...) to the user.'''
 | 
					
						
							|  |  |  |     def __init__(self, validator=None, multiplicity=(1,1), index=None, | 
					
						
							|  |  |  |                  default=None, optional=False, editDefault=False, show=True, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                  page='main', group=None, move=0, indexed=False, | 
					
						
							|  |  |  |                  searchable=False, specificReadPermission=False, | 
					
						
							|  |  |  |                  specificWritePermission=False, width=None, height=None, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                  master=None, masterValue=None, focus=False, historized=False): | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         Type.__init__(self, None, (0,1), index, default, optional, | 
					
						
							| 
									
										
										
										
											2009-10-30 21:31:39 +01:00
										 |  |  |                       False, show, page, group, move, indexed, False, | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |                       specificReadPermission, specificWritePermission, width, | 
					
						
							| 
									
										
										
										
											2009-12-14 20:22:55 +01:00
										 |  |  |                       height, master, masterValue, focus, historized) | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Workflow-specific types ------------------------------------------------------ | 
					
						
							|  |  |  | class State: | 
					
						
							|  |  |  |     def __init__(self, permissions, initial=False, phase='main', show=True): | 
					
						
							|  |  |  |         self.permissions = permissions #~{s_permissionName:[s_roleName]}~ This | 
					
						
							|  |  |  |         # dict gives, for every permission managed by a workflow, the list of | 
					
						
							|  |  |  |         # roles for which the permission is granted in this state. | 
					
						
							|  |  |  |         # Standard permissions are 'read', 'write' and 'delete'. | 
					
						
							|  |  |  |         self.initial = initial | 
					
						
							|  |  |  |         self.phase = phase | 
					
						
							|  |  |  |         self.show = show | 
					
						
							|  |  |  |     def getUsedRoles(self): | 
					
						
							|  |  |  |         res = set() | 
					
						
							|  |  |  |         for roleValue in self.permissions.itervalues(): | 
					
						
							|  |  |  |             if isinstance(roleValue, basestring): | 
					
						
							|  |  |  |                 res.add(roleValue) | 
					
						
							|  |  |  |             elif roleValue: | 
					
						
							|  |  |  |                 for role in roleValue: | 
					
						
							|  |  |  |                     res.add(role) | 
					
						
							|  |  |  |         return list(res) | 
					
						
							|  |  |  |     def getTransitions(self, transitions, selfIsFromState=True): | 
					
						
							|  |  |  |         '''Among p_transitions, returns those whose fromState is p_self (if
 | 
					
						
							|  |  |  |            p_selfIsFromState is True) or those whose toState is p_self (if | 
					
						
							|  |  |  |            p_selfIsFromState is False).'''
 | 
					
						
							|  |  |  |         res = [] | 
					
						
							|  |  |  |         for t in transitions: | 
					
						
							|  |  |  |             if self in t.getStates(selfIsFromState): | 
					
						
							|  |  |  |                 res.append(t) | 
					
						
							|  |  |  |         return res | 
					
						
							|  |  |  |     def getPermissions(self): | 
					
						
							|  |  |  |         '''If you get the permissions mapping through self.permissions, dict
 | 
					
						
							|  |  |  |            values may be of different types (a list of roles, a single role or | 
					
						
							|  |  |  |            None). Iy you call this method, you will always get a list which | 
					
						
							|  |  |  |            may be empty.'''
 | 
					
						
							|  |  |  |         res = {} | 
					
						
							|  |  |  |         for permission, roleValue in self.permissions.iteritems(): | 
					
						
							|  |  |  |             if roleValue == None: | 
					
						
							|  |  |  |                 res[permission] = [] | 
					
						
							|  |  |  |             elif isinstance(roleValue, basestring): | 
					
						
							|  |  |  |                 res[permission] = [roleValue] | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 res[permission] = roleValue | 
					
						
							|  |  |  |         return res | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Transition: | 
					
						
							| 
									
										
										
										
											2009-11-06 11:33:56 +01:00
										 |  |  |     def __init__(self, states, condition=True, action=None, notify=None, | 
					
						
							|  |  |  |                  show=True): | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  |         self.states = states # In its simpler form, it is a tuple with 2 | 
					
						
							|  |  |  |         # states: (fromState, toState). But it can also be a tuple of several | 
					
						
							|  |  |  |         # (fromState, toState) sub-tuples. This way, you may define only 1 | 
					
						
							|  |  |  |         # transition at several places in the state-transition diagram. It may | 
					
						
							|  |  |  |         # be useful for "undo" transitions, for example. | 
					
						
							|  |  |  |         self.condition = condition | 
					
						
							|  |  |  |         self.action = action | 
					
						
							|  |  |  |         self.notify = notify # If not None, it is a method telling who must be | 
					
						
							|  |  |  |         # notified by email after the transition has been executed. | 
					
						
							| 
									
										
										
										
											2009-11-06 11:33:56 +01:00
										 |  |  |         self.show = show # If False, the end user will not be able to trigger | 
					
						
							|  |  |  |         # the transition. It will only be possible by code. | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def getUsedRoles(self): | 
					
						
							|  |  |  |         '''If self.condition is specifies a role.''' | 
					
						
							|  |  |  |         res = [] | 
					
						
							|  |  |  |         if isinstance(self.condition, basestring): | 
					
						
							|  |  |  |             res = [self.condition] | 
					
						
							|  |  |  |         return res | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def isSingle(self): | 
					
						
							|  |  |  |         '''If this transitions is only define between 2 states, returns True.
 | 
					
						
							|  |  |  |            Else, returns False.'''
 | 
					
						
							|  |  |  |         return isinstance(self.states[0], State) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def getStates(self, fromStates=True): | 
					
						
							|  |  |  |         '''Returns the fromState(s) if p_fromStates is True, the toState(s)
 | 
					
						
							|  |  |  |            else. If you want to get the states grouped in tuples | 
					
						
							|  |  |  |            (fromState, toState), simply use self.states.'''
 | 
					
						
							|  |  |  |         res = [] | 
					
						
							|  |  |  |         stateIndex = 1 | 
					
						
							|  |  |  |         if fromStates: | 
					
						
							|  |  |  |             stateIndex = 0 | 
					
						
							|  |  |  |         if self.isSingle(): | 
					
						
							|  |  |  |             res.append(self.states[stateIndex]) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             for states in self.states: | 
					
						
							|  |  |  |                 theState = states[stateIndex] | 
					
						
							|  |  |  |                 if theState not in res: | 
					
						
							|  |  |  |                     res.append(theState) | 
					
						
							|  |  |  |         return res | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def hasState(self, state, isFrom): | 
					
						
							|  |  |  |         '''If p_isFrom is True, this method returns True if p_state is a
 | 
					
						
							|  |  |  |            starting state for p_self. If p_isFrom is False, this method returns | 
					
						
							|  |  |  |            True if p_state is an ending state for p_self.'''
 | 
					
						
							|  |  |  |         stateIndex = 1 | 
					
						
							|  |  |  |         if isFrom: | 
					
						
							|  |  |  |             stateIndex = 0 | 
					
						
							|  |  |  |         if self.isSingle(): | 
					
						
							|  |  |  |             res = state == self.states[stateIndex] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             res = False | 
					
						
							|  |  |  |             for states in self.states: | 
					
						
							|  |  |  |                 if states[stateIndex] == state: | 
					
						
							|  |  |  |                     res = True | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  |         return res | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Permission: | 
					
						
							|  |  |  |     '''If you need to define a specific read or write permission of a given
 | 
					
						
							|  |  |  |        attribute of an Appy type, you use the specific boolean parameters | 
					
						
							|  |  |  |        "specificReadPermission" or "specificWritePermission" for this attribute. | 
					
						
							|  |  |  |        When you want to refer to those specific read or write permissions when | 
					
						
							|  |  |  |        defining a workflow, for example, you need to use instances of | 
					
						
							|  |  |  |        "ReadPermission" and "WritePermission", the 2 children classes of this | 
					
						
							|  |  |  |        class. For example, if you need to refer to write permission of | 
					
						
							|  |  |  |        attribute "t1" of class A, write: "WritePermission("A.t1") or | 
					
						
							|  |  |  |        WritePermission("x.y.A.t1") if class A is not in the same module as | 
					
						
							|  |  |  |        where you instantiate the class.'''
 | 
					
						
							|  |  |  |     def __init__(self, fieldDescriptor): | 
					
						
							|  |  |  |         self.fieldDescriptor = fieldDescriptor | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ReadPermission(Permission): pass | 
					
						
							|  |  |  | class WritePermission(Permission): pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ------------------------------------------------------------------------------ | 
					
						
							|  |  |  | class Selection: | 
					
						
							|  |  |  |     '''Instances of this class may be given as validator of a String, in order
 | 
					
						
							|  |  |  |        to tell Appy that the validator is a selection that will be computed | 
					
						
							|  |  |  |        dynamically.'''
 | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ------------------------------------------------------------------------------ | 
					
						
							|  |  |  | class Tool: | 
					
						
							|  |  |  |     '''If you want so define a custom tool class, she must inherit from this
 | 
					
						
							|  |  |  |        class.'''
 | 
					
						
							|  |  |  | class Flavour: | 
					
						
							|  |  |  |     '''A flavour represents a given group of configuration options. If you want
 | 
					
						
							|  |  |  |        to define a custom flavour class, she must inherit from this class.'''
 | 
					
						
							|  |  |  |     def __init__(self, name): self.name = name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ------------------------------------------------------------------------------ | 
					
						
							|  |  |  | class Config: | 
					
						
							|  |  |  |     '''If you want to specify some configuration parameters for appy.gen and
 | 
					
						
							|  |  |  |        your application, please create an instance of this class and modify its | 
					
						
							|  |  |  |        attributes. You may put your instance anywhere in your application | 
					
						
							|  |  |  |        (main package, sub-package, etc).'''
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # The default Config instance, used if the application does not give one. | 
					
						
							|  |  |  |     defaultConfig = None | 
					
						
							|  |  |  |     def getDefault(): | 
					
						
							|  |  |  |         if not Config.defaultConfig: | 
					
						
							|  |  |  |             Config.defaultConfig = Config() | 
					
						
							|  |  |  |         return Config.defaultConfig | 
					
						
							|  |  |  |     getDefault = staticmethod(getDefault) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self): | 
					
						
							|  |  |  |         # For every language code that you specify in this list, appy.gen will | 
					
						
							|  |  |  |         # produce and maintain translation files. | 
					
						
							|  |  |  |         self.languages = ['en'] | 
					
						
							|  |  |  |         # People having one of these roles will be able to create instances | 
					
						
							|  |  |  |         # of classes defined in your application. | 
					
						
							|  |  |  |         self.defaultCreators = ['Manager', 'Owner'] | 
					
						
							|  |  |  |         # If True, the following flag will produce a minimalist Plone, where | 
					
						
							|  |  |  |         # some actions, portlets or other stuff less relevant for building | 
					
						
							|  |  |  |         # web applications, are removed or hidden. Using this produces | 
					
						
							|  |  |  |         # effects on your whole Plone site! | 
					
						
							|  |  |  |         self.minimalistPlone = False | 
					
						
							|  |  |  |         # If you want to replace the Plone front page with a page coming from | 
					
						
							|  |  |  |         # your application, use the following parameter. Setting | 
					
						
							|  |  |  |         # frontPage = True will replace the Plone front page with a page | 
					
						
							|  |  |  |         # whose content will come fron i18n label "front_page_text". | 
					
						
							|  |  |  |         self.frontPage = False | 
					
						
							| 
									
										
										
										
											2009-08-04 14:39:43 +02:00
										 |  |  |         # If you don't need the portlet that appy.gen has generated for your | 
					
						
							|  |  |  |         # application, set the following parameter to False. | 
					
						
							|  |  |  |         self.showPortlet = True | 
					
						
							| 
									
										
										
										
											2009-11-11 20:22:13 +01:00
										 |  |  |         # Default number of flavours. It will be used for generating i18n labels | 
					
						
							|  |  |  |         # for classes in every flavour. Indeed, every flavour can name its | 
					
						
							|  |  |  |         # concepts differently. For example, class Thing in flavour 2 may have | 
					
						
							|  |  |  |         # i18n label "MyProject_Thing_2". | 
					
						
							|  |  |  |         self.numberOfFlavours = 2 | 
					
						
							| 
									
										
										
										
											2009-06-29 14:06:01 +02:00
										 |  |  | # ------------------------------------------------------------------------------ |