root / pykota / trunk / pykota / config.py @ 3180

Revision 3180, 34.3 kB (checked in by jerome, 17 years ago)

Now the various delays are configurable when using hardware accounting,
through the newly introduced 'statusstabilizationdelay' and 'statusstabilizationloops'
directives in pykota.conf

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1# PyKota
2# -*- coding: ISO-8859-15 -*-
3#
4# PyKota : Print Quotas for CUPS and LPRng
5#
6# (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet <alet@librelogiciel.com>
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20#
21# $Id$
22#
23#
24
25import os
26import tempfile
27import ConfigParser
28
29class PyKotaConfigError(Exception):
30    """An exception for PyKota config related stuff."""
31    def __init__(self, message = ""):
32        self.message = message
33        Exception.__init__(self, message)
34    def __repr__(self):
35        return self.message
36    __str__ = __repr__
37   
38class PyKotaConfig :
39    """A class to deal with PyKota's configuration."""
40    def __init__(self, directory) :
41        """Reads and checks the configuration file."""
42        self.isAdmin = 0
43        self.directory = directory
44        self.filename = os.path.join(directory, "pykota.conf")
45        self.adminfilename = os.path.join(directory, "pykotadmin.conf")
46        if not os.access(self.filename, os.R_OK) :
47            raise PyKotaConfigError, _("Configuration file %s can't be read. Please check that the file exists and that your permissions are sufficient.") % self.filename
48        if not os.path.isfile(self.adminfilename) :
49            raise PyKotaConfigError, _("Configuration file %s not found.") % self.adminfilename
50        if os.access(self.adminfilename, os.R_OK) :   
51            self.isAdmin = 1
52        self.config = ConfigParser.ConfigParser()
53        self.config.read([self.filename])
54           
55    def isTrue(self, option) :       
56        """Returns True if option is set to true, else False."""
57        if (option is not None) and (option.strip().upper() in ['Y', 'YES', '1', 'ON', 'T', 'TRUE']) :
58            return True
59        else :   
60            return False
61                       
62    def isFalse(self, option) :       
63        """Returns True if option is set to false, else False."""
64        if (option is not None) and (option.strip().upper() in ['N', 'NO', '0', 'OFF', 'F', 'FALSE']) :
65            return True
66        else :   
67            return False
68                       
69    def getPrinterNames(self) :   
70        """Returns the list of configured printers, i.e. all sections names minus 'global'."""
71        return [pname for pname in self.config.sections() if pname != "global"]
72       
73    def getGlobalOption(self, option, ignore=0) :   
74        """Returns an option from the global section, or raises a PyKotaConfigError if ignore is not set, else returns None."""
75        try :
76            return self.config.get("global", option, raw=1)
77        except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :   
78            if ignore :
79                return None
80            else :
81                raise PyKotaConfigError, _("Option %s not found in section global of %s") % (option, self.filename)
82               
83    def getPrinterOption(self, printername, option) :   
84        """Returns an option from the printer section, or the global section, or raises a PyKotaConfigError."""
85        globaloption = self.getGlobalOption(option, ignore=1)
86        try :
87            return self.config.get(printername, option, raw=1)
88        except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :   
89            if globaloption is not None :
90                return globaloption
91            else :
92                raise PyKotaConfigError, _("Option %s not found in section %s of %s") % (option, printername, self.filename)
93       
94    def getStorageBackend(self) :   
95        """Returns the storage backend information as a Python mapping."""       
96        backendinfo = {}
97        backend = self.getGlobalOption("storagebackend").lower()
98        backendinfo["storagebackend"] = backend
99        if backend == "sqlitestorage" :
100            issqlite = 1
101            backendinfo["storagename"] = self.getGlobalOption("storagename")
102            for option in ["storageserver", "storageuser", "storageuserpw"] :
103                backendinfo[option] = None         
104        else :
105            issqlite = 0
106            for option in ["storageserver", "storagename", "storageuser"] :
107                backendinfo[option] = self.getGlobalOption(option)
108            backendinfo["storageuserpw"] = self.getGlobalOption("storageuserpw", ignore=1)  # password is optional
109           
110        backendinfo["storageadmin"] = None
111        backendinfo["storageadminpw"] = None
112        if self.isAdmin :
113            adminconf = ConfigParser.ConfigParser()
114            adminconf.read([self.adminfilename])
115            if adminconf.sections() : # were we able to read the file ?
116                try :
117                    backendinfo["storageadmin"] = adminconf.get("global", "storageadmin", raw=1)
118                except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :   
119                    if not issqlite :
120                        raise PyKotaConfigError, _("Option %s not found in section global of %s") % ("storageadmin", self.adminfilename)
121                try :
122                    backendinfo["storageadminpw"] = adminconf.get("global", "storageadminpw", raw=1)
123                except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :   
124                    pass # Password is optional
125                # Now try to overwrite the storagebackend, storageserver
126                # and storagename. This allows admins to use the master LDAP
127                # server directly and users to use the replicas transparently.
128                try :
129                    backendinfo["storagebackend"] = adminconf.get("global", "storagebackend", raw=1)
130                except ConfigParser.NoOptionError :
131                    pass
132                try :
133                    backendinfo["storageserver"] = adminconf.get("global", "storageserver", raw=1)
134                except ConfigParser.NoOptionError :
135                    pass
136                try :
137                    backendinfo["storagename"] = adminconf.get("global", "storagename", raw=1)
138                except ConfigParser.NoOptionError :
139                    pass
140        return backendinfo
141       
142    def getLDAPInfo(self) :   
143        """Returns some hints for the LDAP backend."""       
144        ldapinfo = {}
145        for option in [ "userbase", "userrdn", \
146                        "balancebase", "balancerdn", \
147                        "groupbase", "grouprdn", "groupmembers", \
148                        "printerbase", "printerrdn", \
149                        "userquotabase", "groupquotabase", \
150                        "jobbase", "lastjobbase", "billingcodebase", \
151                        "newuser", "newgroup", \
152                        "usermail", \
153                      ] :
154            ldapinfo[option] = self.getGlobalOption(option).strip()
155        for field in ["newuser", "newgroup"] :
156            if ldapinfo[field].lower().startswith('attach(') :
157                ldapinfo[field] = ldapinfo[field][7:-1]
158               
159        # should we use TLS, by default (if unset) value is NO       
160        ldapinfo["ldaptls"] = self.isTrue(self.getGlobalOption("ldaptls", ignore=1))
161        ldapinfo["cacert"] = self.getGlobalOption("cacert", ignore=1)
162        if ldapinfo["cacert"] :
163            ldapinfo["cacert"] = ldapinfo["cacert"].strip()
164        if ldapinfo["ldaptls"] :   
165            if not os.access(ldapinfo["cacert"] or "", os.R_OK) :
166                raise PyKotaConfigError, _("Option ldaptls is set, but certificate %s is not readable.") % str(ldapinfo["cacert"])
167        return ldapinfo
168       
169    def getLoggingBackend(self) :   
170        """Returns the logging backend information."""
171        validloggers = [ "stderr", "system" ] 
172        try :
173            logger = self.getGlobalOption("logger").lower()
174        except PyKotaConfigError :   
175            logger = "system"
176        if logger not in validloggers :             
177            raise PyKotaConfigError, _("Option logger only supports values in %s") % str(validloggers)
178        return logger   
179       
180    def getLogoURL(self) :
181        """Returns the URL to use for the logo in the CGI scripts."""
182        url = self.getGlobalOption("logourl", ignore=1) or \
183                   "http://www.pykota.com/pykota.png"
184        return url.strip()           
185       
186    def getLogoLink(self) :
187        """Returns the URL to go to when the user clicks on the logo in the CGI scripts."""
188        url = self.getGlobalOption("logolink", ignore=1) or \
189                   "http://www.pykota.com/"
190        return url.strip()           
191   
192    def getPreAccounterBackend(self, printername) :   
193        """Returns the preaccounter backend to use for a given printer."""
194        validaccounters = [ "software", "ink" ]     
195        try :
196            fullaccounter = self.getPrinterOption(printername, "preaccounter").strip()
197        except PyKotaConfigError :   
198            return ("software", "")
199        else :   
200            flower = fullaccounter.lower()
201            for vac in validaccounters :
202                if flower.startswith(vac) :   
203                    try :
204                        (accounter, args) = [x.strip() for x in fullaccounter.split('(', 1)]
205                    except ValueError :   
206                        raise PyKotaConfigError, _("Invalid preaccounter %s for printer %s") % (fullaccounter, printername)
207                    if args.endswith(')') :
208                        args = args[:-1].strip()
209                    if (vac == "ink") and not args :   
210                        raise PyKotaConfigError, _("Invalid preaccounter %s for printer %s") % (fullaccounter, printername)
211                    return (vac, args)
212            raise PyKotaConfigError, _("Option preaccounter in section %s only supports values in %s") % (printername, str(validaccounters))
213       
214    def getAccounterBackend(self, printername) :   
215        """Returns the accounter backend to use for a given printer."""
216        validaccounters = [ "hardware", "software", "ink" ]     
217        try :
218            fullaccounter = self.getPrinterOption(printername, "accounter").strip()
219        except PyKotaConfigError :   
220            return ("software", "")
221        else :   
222            flower = fullaccounter.lower()
223            for vac in validaccounters :
224                if flower.startswith(vac) :   
225                    try :
226                        (accounter, args) = [x.strip() for x in fullaccounter.split('(', 1)]
227                    except ValueError :   
228                        raise PyKotaConfigError, _("Invalid accounter %s for printer %s") % (fullaccounter, printername)
229                    if args.endswith(')') :
230                        args = args[:-1].strip()
231                    if (vac in ("hardware", "ink")) and not args :
232                        raise PyKotaConfigError, _("Invalid accounter %s for printer %s") % (fullaccounter, printername)
233                    return (vac, args)
234            raise PyKotaConfigError, _("Option accounter in section %s only supports values in %s") % (printername, str(validaccounters))
235       
236    def getPreHook(self, printername) :   
237        """Returns the prehook command line to launch, or None if unset."""
238        try :
239            return self.getPrinterOption(printername, "prehook").strip()
240        except PyKotaConfigError :   
241            return      # No command to launch in the pre-hook
242           
243    def getPostHook(self, printername) :   
244        """Returns the posthook command line to launch, or None if unset."""
245        try :
246            return self.getPrinterOption(printername, "posthook").strip()
247        except PyKotaConfigError :   
248            return      # No command to launch in the post-hook
249           
250    def getStripTitle(self, printername) :   
251        """Returns the striptitle directive's content, or None if unset."""
252        try :
253            return self.getPrinterOption(printername, "striptitle").strip()
254        except PyKotaConfigError :   
255            return      # No prefix to strip off
256           
257    def getAskConfirmation(self, printername) :       
258        """Returns the askconfirmation directive's content, or None if unset."""
259        try :
260            return self.getPrinterOption(printername, "askconfirmation").strip()
261        except PyKotaConfigError :   
262            return      # No overwriting will be done
263           
264    def getOverwriteJobTicket(self, printername) :       
265        """Returns the overwrite_jobticket directive's content, or None if unset."""
266        try :
267            return self.getPrinterOption(printername, "overwrite_jobticket").strip()
268        except PyKotaConfigError :   
269            return      # No overwriting will be done
270       
271    def getUnknownBillingCode(self, printername) :       
272        """Returns the unknown_billingcode directive's content, or the default value if unset."""
273        validvalues = [ "CREATE", "DENY" ]
274        try :
275            fullvalue = self.getPrinterOption(printername, "unknown_billingcode")
276        except PyKotaConfigError :   
277            return ("CREATE", None)
278        else :   
279            try :
280                value = [x.strip() for x in fullvalue.split('(', 1)]
281            except ValueError :   
282                raise PyKotaConfigError, _("Invalid unknown_billingcode directive %s for printer %s") % (fullvalue, printername)
283            if len(value) == 1 :   
284                value.append("")
285            (value, args) = value   
286            if args.endswith(')') :
287                args = args[:-1]
288            value = value.upper()   
289            if (value == "DENY") and not args :
290                return ("DENY", None)
291            if value not in validvalues :
292                raise PyKotaConfigError, _("Directive unknown_billingcode in section %s only supports values in %s") % (printername, str(validvalues))
293            return (value, args)
294       
295    def getPrinterEnforcement(self, printername) :   
296        """Returns if quota enforcement should be strict or laxist for the current printer."""
297        validenforcements = [ "STRICT", "LAXIST" ]     
298        try :
299            enforcement = self.getPrinterOption(printername, "enforcement")
300        except PyKotaConfigError :   
301            return "LAXIST"
302        else :   
303            enforcement = enforcement.upper()
304            if enforcement not in validenforcements :
305                raise PyKotaConfigError, _("Option enforcement in section %s only supports values in %s") % (printername, str(validenforcements))
306            return enforcement   
307           
308    def getPrinterOnBackendError(self, printername) :   
309        """Returns what must be done whenever the real CUPS backend fails."""
310        validactions = [ "CHARGE", "NOCHARGE" ]     
311        try :
312            action = self.getPrinterOption(printername, "onbackenderror")
313        except PyKotaConfigError :   
314            return ["NOCHARGE"]
315        else :   
316            action = action.upper().split(",")
317            error = False
318            for act in action :
319                if act not in validactions :
320                    if act.startswith("RETRY:") :
321                        try :
322                            (num, delay) = [int(p) for p in act[6:].split(":", 2)]
323                        except ValueError :   
324                            error = True
325                    else :       
326                        error = True
327            if error :
328                raise PyKotaConfigError, _("Option onbackenderror in section %s only supports values 'charge', 'nocharge', and 'retry:num:delay'") % printername
329            return action 
330           
331    def getPrinterOnAccounterError(self, printername) :   
332        """Returns what must be done whenever the accounter fails."""
333        validactions = [ "CONTINUE", "STOP" ]     
334        try :
335            action = self.getPrinterOption(printername, "onaccountererror")
336        except PyKotaConfigError :   
337            return "STOP"
338        else :   
339            action = action.upper()
340            if action not in validactions :
341                raise PyKotaConfigError, _("Option onaccountererror in section %s only supports values in %s") % (printername, str(validactions))
342            return action 
343           
344    def getPrinterPolicy(self, printername) :   
345        """Returns the default policy for the current printer."""
346        validpolicies = [ "ALLOW", "DENY", "EXTERNAL" ]     
347        try :
348            fullpolicy = self.getPrinterOption(printername, "policy")
349        except PyKotaConfigError :   
350            return ("DENY", None)
351        else :   
352            try :
353                policy = [x.strip() for x in fullpolicy.split('(', 1)]
354            except ValueError :   
355                raise PyKotaConfigError, _("Invalid policy %s for printer %s") % (fullpolicy, printername)
356            if len(policy) == 1 :   
357                policy.append("")
358            (policy, args) = policy   
359            if args.endswith(')') :
360                args = args[:-1]
361            policy = policy.upper()   
362            if (policy == "EXTERNAL") and not args :
363                raise PyKotaConfigError, _("Invalid policy %s for printer %s") % (fullpolicy, printername)
364            if policy not in validpolicies :
365                raise PyKotaConfigError, _("Option policy in section %s only supports values in %s") % (printername, str(validpolicies))
366            return (policy, args)
367       
368    def getCrashRecipient(self) :   
369        """Returns the email address of the software crash messages recipient."""
370        try :
371            return self.getGlobalOption("crashrecipient")
372        except :   
373            return
374           
375    def getSMTPServer(self) :   
376        """Returns the SMTP server to use to send messages to users."""
377        try :
378            return self.getGlobalOption("smtpserver")
379        except PyKotaConfigError :   
380            return "localhost"
381       
382    def getMailDomain(self) :   
383        """Returns the mail domain to use to send messages to users."""
384        try :
385            return self.getGlobalOption("maildomain")
386        except PyKotaConfigError :   
387            return 
388       
389    def getAdminMail(self, printername) :   
390        """Returns the Email address of the Print Quota Administrator."""
391        try :
392            return self.getPrinterOption(printername, "adminmail")
393        except PyKotaConfigError :   
394            return "root@localhost"
395       
396    def getAdmin(self, printername) :   
397        """Returns the full name of the Print Quota Administrator."""
398        try :
399            return self.getPrinterOption(printername, "admin")
400        except PyKotaConfigError :   
401            return "root"
402       
403    def getMailTo(self, printername) :   
404        """Returns the recipient of email messages."""
405        validmailtos = [ "EXTERNAL", "NOBODY", "NONE", "NOONE", "BITBUCKET", "DEVNULL", "BOTH", "USER", "ADMIN" ]
406        try :
407            fullmailto = self.getPrinterOption(printername, "mailto")
408        except PyKotaConfigError :   
409            return ("BOTH", None)
410        else :   
411            try :
412                mailto = [x.strip() for x in fullmailto.split('(', 1)]
413            except ValueError :   
414                raise PyKotaConfigError, _("Invalid option mailto %s for printer %s") % (fullmailto, printername)
415            if len(mailto) == 1 :   
416                mailto.append("")
417            (mailto, args) = mailto   
418            if args.endswith(')') :
419                args = args[:-1]
420            mailto = mailto.upper()   
421            if (mailto == "EXTERNAL") and not args :
422                raise PyKotaConfigError, _("Invalid option mailto %s for printer %s") % (fullmailto, printername)
423            if mailto not in validmailtos :
424                raise PyKotaConfigError, _("Option mailto in section %s only supports values in %s") % (printername, str(validmailtos))
425            return (mailto, args)
426       
427    def getMaxDenyBanners(self, printername) :   
428        """Returns the maximum number of deny banners to be printed for a particular user on a particular printer."""
429        try :
430            maxdb = self.getPrinterOption(printername, "maxdenybanners")
431        except PyKotaConfigError :   
432            return 0 # default value is to forbid printing a deny banner.
433        try :
434            value = int(maxdb.strip())
435            if value < 0 :
436                raise ValueError
437        except (TypeError, ValueError) :   
438            raise PyKotaConfigError, _("Invalid maximal deny banners counter %s") % maxdb
439        else :   
440            return value
441
442    def getPrintCancelledBanners(self, printername) :
443        """Returns True if a banner should be printed when a job is cancelled, else False."""
444        try :
445            return self.isTrue(self.getPrinterOption(printername, "printcancelledbanners"))
446        except PyKotaConfigError :
447            return True
448             
449    def getGraceDelay(self, printername) :   
450        """Returns the grace delay in days."""
451        try :
452            gd = self.getPrinterOption(printername, "gracedelay")
453        except PyKotaConfigError :   
454            gd = 7      # default value of 7 days
455        try :
456            return int(gd)
457        except (TypeError, ValueError) :   
458            raise PyKotaConfigError, _("Invalid grace delay %s") % gd
459           
460    def getPoorMan(self) :   
461        """Returns the poor man's threshold."""
462        try :
463            pm = self.getGlobalOption("poorman")
464        except PyKotaConfigError :   
465            pm = 1.0    # default value of 1 unit
466        try :
467            return float(pm)
468        except (TypeError, ValueError) :   
469            raise PyKotaConfigError, _("Invalid poor man's threshold %s") % pm
470           
471    def getBalanceZero(self) :   
472        """Returns the value of the zero for balance limitation."""
473        try :
474            bz = self.getGlobalOption("balancezero")
475        except PyKotaConfigError :   
476            bz = 0.0    # default value, zero is 0.0
477        try :
478            return float(bz)
479        except (TypeError, ValueError) :   
480            raise PyKotaConfigError, _("Invalid balancezero value %s") % bz
481           
482    def getPoorWarn(self) :   
483        """Returns the poor man's warning message."""
484        try :
485            return self.getGlobalOption("poorwarn")
486        except PyKotaConfigError :   
487            return _("Your Print Quota account balance is Low.\nSoon you'll not be allowed to print anymore.\nPlease contact the Print Quota Administrator to solve the problem.")
488           
489    def getHardWarn(self, printername) :   
490        """Returns the hard limit error message."""
491        try :
492            return self.getPrinterOption(printername, "hardwarn")
493        except PyKotaConfigError :   
494            return _("You are not allowed to print anymore because\nyour Print Quota is exceeded on printer %s.") % printername
495           
496    def getSoftWarn(self, printername) :   
497        """Returns the soft limit error message."""
498        try :
499            return self.getPrinterOption(printername, "softwarn")
500        except PyKotaConfigError :   
501            return _("You will soon be forbidden to print anymore because\nyour Print Quota is almost reached on printer %s.") % printername
502           
503    def getPrivacy(self) :       
504        """Returns True if privacy is activated, else False."""
505        return self.isTrue(self.getGlobalOption("privacy", ignore=1))
506       
507    def getDebug(self) :         
508        """Returns True if debugging is activated, else False."""
509        return self.isTrue(self.getGlobalOption("debug", ignore=1))
510           
511    def getCaching(self) :         
512        """Returns True if database caching is enabled, else False."""
513        return self.isTrue(self.getGlobalOption("storagecaching", ignore=1))
514           
515    def getLDAPCache(self) :         
516        """Returns True if low-level LDAP caching is enabled, else False."""
517        return self.isTrue(self.getGlobalOption("ldapcache", ignore=1))
518           
519    def getDisableHistory(self) :         
520        """Returns True if we want to disable history, else False."""
521        return self.isTrue(self.getGlobalOption("disablehistory", ignore=1))
522           
523    def getUserNameToLower(self) :         
524        """Deprecated."""
525        return self.getGlobalOption("utolower", ignore=1)
526       
527    def getUserNameCase(self) :
528        """Returns value for user name case: upper, lower or native"""
529        validvalues = [ "upper", "lower", "native" ]
530        try :
531            value = self.getGlobalOption("usernamecase", ignore=1).strip().lower()
532        except AttributeError :   
533            value = "native"
534        if value not in validvalues :
535            raise PyKotaConfigError, _("Option usernamecase only supports values in %s") % str(validvalues)
536        return value
537       
538    def getRejectUnknown(self) :         
539        """Returns True if we want to reject the creation of unknown users or groups, else False."""
540        return self.isTrue(self.getGlobalOption("reject_unknown", ignore=1))
541       
542    def getPrinterKeepFiles(self, printername) :         
543        """Returns True if files must be kept on disk, else False."""
544        try : 
545            return self.isTrue(self.getPrinterOption(printername, "keepfiles"))
546        except PyKotaConfigError :   
547            return False
548           
549    def getPrinterDirectory(self, printername) :         
550        """Returns the path to our working directory, else a directory suitable for temporary files."""
551        try : 
552            return self.getPrinterOption(printername, "directory").strip()
553        except PyKotaConfigError :   
554            return tempfile.gettempdir()
555           
556    def getDenyDuplicates(self, printername) :         
557        """Returns True or a command if we want to deny duplicate jobs, else False."""
558        try : 
559            denyduplicates = self.getPrinterOption(printername, "denyduplicates")
560        except PyKotaConfigError :   
561            return False
562        else :   
563            if self.isTrue(denyduplicates) :
564                return True
565            elif self.isFalse(denyduplicates) :
566                return False
567            else :   
568                # it's a command to run.
569                return denyduplicates
570               
571    def getDuplicatesDelay(self, printername) :         
572        """Returns the number of seconds after which two identical jobs are not considered a duplicate anymore."""
573        try : 
574            duplicatesdelay = self.getPrinterOption(printername, "duplicatesdelay")
575        except PyKotaConfigError :   
576            return 0
577        else :   
578            try :
579                return int(duplicatesdelay)
580            except (TypeError, ValueError) :
581                raise PyKotaConfigError, _("Incorrect value %s for the duplicatesdelay directive in section %s") % (str(duplicatesdelay), printername)
582       
583    def getNoPrintingMaxDelay(self, printername) :         
584        """Returns the max number of seconds to wait for the printer to be in 'printing' mode."""
585        try : 
586            maxdelay = self.getPrinterOption(printername, "noprintingmaxdelay")
587        except PyKotaConfigError :   
588            return None         # tells to use hardcoded value
589        else :   
590            try :
591                maxdelay = int(maxdelay)
592                if maxdelay < 0 :
593                    raise ValueError
594            except (TypeError, ValueError) :
595                raise PyKotaConfigError, _("Incorrect value %s for the noprintingmaxdelay directive in section %s") % (str(maxdelay), printername)
596            else :   
597                return maxdelay
598       
599    def getStatusStabilizationLoops(self, printername) :   
600        """Returns the number of times the printer must return the 'idle' status to consider it stable."""
601        try : 
602            stab = self.getPrinterOption(printername, "statusstabilizationloops")
603        except PyKotaConfigError :   
604            return None         # tells to use hardcoded value
605        else :   
606            try :
607                stab = int(stab)
608                if stab < 1 :
609                    raise ValueError
610            except (TypeError, ValueError) :
611                raise PyKotaConfigError, _("Incorrect value %s for the statusstabilizationloops directive in section %s") % (str(stab), printername)
612            else :   
613                return stab
614       
615    def getStatusStabilizationDelay(self, printername) :   
616        """Returns the number of seconds to wait between two checks of the printer's status."""
617        try : 
618            stab = self.getPrinterOption(printername, "statusstabilizationdelay")
619        except PyKotaConfigError :   
620            return None         # tells to use hardcoded value
621        else :   
622            try :
623                stab = float(stab)
624                if stab < 0.25 :
625                    raise ValueError
626            except (TypeError, ValueError) :
627                raise PyKotaConfigError, _("Incorrect value %s for the statusstabilizationdelay directive in section %s") % (str(stab), printername)
628            else :   
629                return stab
630       
631    def getWinbindSeparator(self) :         
632        """Returns the winbind separator's value if it is set, else None."""
633        return self.getGlobalOption("winbind_separator", ignore=1)
634
635    def getAccountBanner(self, printername) :
636        """Returns which banner(s) to account for: NONE, BOTH, STARTING, ENDING."""
637        validvalues = [ "NONE", "BOTH", "STARTING", "ENDING" ]     
638        try :
639            value = self.getPrinterOption(printername, "accountbanner")
640        except PyKotaConfigError :   
641            return "BOTH"       # Default value of BOTH
642        else :   
643            value = value.strip().upper()
644            if value not in validvalues :
645                raise PyKotaConfigError, _("Option accountbanner in section %s only supports values in %s") % (printername, str(validvalues))
646            return value 
647
648    def getAvoidDuplicateBanners(self, printername) :
649        """Returns normalized value for avoiding extra banners. """
650        try :
651            avoidduplicatebanners = self.getPrinterOption(printername, "avoidduplicatebanners").upper()
652        except PyKotaConfigError :
653            return "NO"
654        else :
655            try :
656                value = int(avoidduplicatebanners)
657                if value < 0 :
658                    raise ValueError
659            except ValueError :
660                if avoidduplicatebanners not in ["YES", "NO"] :
661                    raise PyKotaConfigError, _("Option avoidduplicatebanners only accepts 'yes', 'no', or a positive integer.")
662                else :
663                    value = avoidduplicatebanners
664            return value
665
666    def getStartingBanner(self, printername) :
667        """Returns the startingbanner value if set, else None."""
668        try :
669            return self.getPrinterOption(printername, "startingbanner").strip()
670        except PyKotaConfigError :
671            return None
672
673    def getEndingBanner(self, printername) :
674        """Returns the endingbanner value if set, else None."""
675        try :
676            return self.getPrinterOption(printername, "endingbanner").strip()
677        except PyKotaConfigError :
678            return None
679           
680    def getTrustJobSize(self, printername) :
681        """Returns the normalized value of the trustjobsize's directive."""
682        try :
683            value = self.getPrinterOption(printername, "trustjobsize").strip().upper()
684        except PyKotaConfigError :
685            return (None, "YES")
686        else :   
687            if value == "YES" :
688                return (None, "YES")
689            try :   
690                (limit, replacement) = [p.strip() for p in value.split(">")[1].split(":")]
691                limit = int(limit)
692                try :
693                    replacement = int(replacement) 
694                except ValueError :   
695                    if replacement != "PRECOMPUTED" :
696                        raise
697                if limit < 0 :
698                    raise ValueError
699                if (replacement != "PRECOMPUTED") and (replacement < 0) :
700                    raise ValueError
701            except (IndexError, ValueError, TypeError) :
702                raise PyKotaConfigError, _("Option trustjobsize for printer %s is incorrect") % printername
703            return (limit, replacement)   
704           
705    def getPrinterCoefficients(self, printername) :
706        """Returns a mapping of coefficients for a particular printer."""
707        branchbasename = "coefficient_"
708        try :
709            globalbranches = [ (k, self.config.get("global", k)) for k in self.config.options("global") if k.startswith(branchbasename) ]
710        except ConfigParser.NoSectionError, msg :
711            raise PyKotaConfigError, "Invalid configuration file : %s" % msg
712        try :
713            sectionbranches = [ (k, self.config.get(printername, k)) for k in self.config.options(printername) if k.startswith(branchbasename) ]
714        except ConfigParser.NoSectionError, msg :
715            sectionbranches = []
716        branches = {}
717        for (k, v) in globalbranches :
718            k = k.split('_', 1)[1]
719            value = v.strip()
720            if value :
721                try :
722                    branches[k] = float(value)
723                except ValueError :   
724                    raise PyKotaConfigError, "Invalid coefficient %s (%s) for printer %s" % (k, value, printername)
725               
726        for (k, v) in sectionbranches :
727            k = k.split('_', 1)[1]
728            value = v.strip()
729            if value :
730                try :
731                    branches[k] = float(value) # overwrite any global option or set a new value
732                except ValueError :   
733                    raise PyKotaConfigError, "Invalid coefficient %s (%s) for printer %s" % (k, value, printername)
734            else :
735                del branches[k] # empty value disables a global option
736        return branches
737       
738    def getPrinterSkipInitialWait(self, printername) :
739        """Returns True if we want to skip the initial waiting loop, else False."""
740        try :
741            return self.isTrue(self.getPrinterOption(printername, "skipinitialwait"))
742        except PyKotaConfigError :
743            return False
Note: See TracBrowser for help on using the browser.