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

Revision 3288, 35.0 kB (checked in by jerome, 16 years ago)

Moved all exceptions definitions to a dedicated module.

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