root / pykota / trunk / bin / edpykota @ 2708

Revision 2708, 31.8 kB (checked in by jerome, 19 years ago)

No time to finish the changes right now, so I made edpykota
fail with an explicit error message as soon as it's launched.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3
4# PyKota Print Quota Editor
5#
6# PyKota - Print Quotas for CUPS and LPRng
7#
8# (c) 2003, 2004, 2005, 2006 Jerome Alet <alet@librelogiciel.com>
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22#
23# $Id$
24#
25#
26
27import sys
28import os
29import pwd
30import grp
31from pykota.tool import PyKotaTool, PyKotaToolError, PyKotaCommandLineError, crashed, N_
32from pykota.config import PyKotaConfigError
33from pykota.storage import PyKotaStorageError
34
35__doc__ = N_("""edpykota v%(__version__)s (c) %(__years__)s %(__author__)s
36
37A Print Quota editor for PyKota.
38
39command line usage :
40
41  edpykota [options] user1 user2 ... userN
42 
43  edpykota [options] group1 group2 ... groupN
44
45options :
46
47  -v | --version       Prints edpykota's version number then exits.
48  -h | --help          Prints this message then exits.
49 
50  -a | --add           Adds users and/or printers if they don't
51                       exist on the Quota Storage Server.
52                       
53  -d | --delete        Deletes users/groups from the quota storage.
54                       Printers are never deleted.
55                       
56  -c | --charge p[,j]  Sets the price per page and per job to charge
57                       for a particular printer. Job price is optional.
58                       If both are to be set, separate them with a comma.
59                       Floating point values are allowed.
60                       
61  -o | --overcharge f  Sets the overcharging factor applied to the user
62                       when computing the cost of a print job. Positive or
63                       negative floating point values are allowed,
64                       this allows you to do some really creative
65                       things like giving money to an user whenever
66                       he prints. The number of pages in a print job
67                       is not modified by this coefficient, only the
68                       cost of the job for a particular user.
69                       Only users have a coefficient.
70 
71  -i | --ingroups g1[,g2...]  Puts the users into each of the groups
72                              listed, separated by commas. The groups
73                              must already exist in the Quota Storage.
74 
75  -u | --users         Edit users print quotas, this is the default.
76 
77  -P | --printer p     Edit quotas on printer p only. Actually p can
78                       use wildcards characters to select only
79                       some printers. The default value is *, meaning
80                       all printers.
81                       You can specify several names or wildcards,
82                       by separating them with commas.
83 
84  -G | --pgroups pg1[,pg2...] Adds the printer(s) to the printer groups
85                       pg1, pg2, etc... which must already exist.
86                       A printer group is just like a normal printer,
87                       only that it is usually unknown from the printing
88                       system. Create printer groups exactly the same
89                       way that you create printers, then add other
90                       printers to them with this option.
91                       Accounting is done on a printer and on all
92                       the printer groups it belongs to, quota checking
93                       is done on a printer and on all the printer groups
94                       it belongs to.
95 
96  -g | --groups        Edit users groups print quotas instead of users.
97                         
98  -p | --prototype u|g Uses user u or group g as a prototype to set
99                       print quotas
100                       
101  -n | --noquota       Sets both soft and hard limits to None for a
102                       particular print quota entry.
103                       This is NOT the same as --limitby noquota
104                       which acts on ALL print quota entries for a
105                       particular user.
106 
107  -r | --reset         Resets the actual page counter for the user
108                       or group to zero on the specified printers.
109                       The life time page counter is kept unchanged.
110                       
111  -R | --hardreset     Resets the actual and life time page counters
112                       for the user or group to zero on the specified
113                       printers. This is a shortcut for '--used 0'.
114                       
115  -l | --limitby l     Choose if the user/group is limited in printing                     
116                       by its account balance or by its page quota.
117                       The default value is 'quota'. Allowed values
118                       are 'quota' 'balance' 'noquota' 'noprint' 
119                       and 'nochange' :
120                       
121                         - quota : limit by number of pages per printer.
122                         - balance : limit by number of credits in account.
123                         - noquota : no limit, accounting still done.
124                         - nochange : no limit, accounting not done.
125                         - noprint : printing is denied.
126                       NB : nochange and noprint are not supported for groups.
127                       
128  -b | --balance b     Sets the user's account balance to b.                     
129                       Account balance may be increase or decreased
130                       if b is prefixed with + or -.
131                       WARNING : when decreasing account balance,
132                       the total paid so far by the user is decreased
133                       too.
134                       Groups don't have a real balance, but the
135                       sum of their users' account balance.
136                       
137  -C | --comment txt   Defines some informational text to be associated
138                       with a change to an user's account balance.
139                       Only meaningful if -b | --balance is also used.
140                       
141  -S | --softlimit sl  Sets the quota soft limit to sl pages.                       
142 
143  -H | --hardlimit hl  Sets the quota hard limit to hl pages.
144 
145  -I | --increase v    Increase both Soft and Hard limits by the value
146                       of v. You can prefix v with + or -, if no sign is
147                       used, + is assumed.
148
149  -U | --used usage    Sets the pagecounters for the user to usage pages;
150                       useful for migrating users from a different system
151                       where they have already used some pages. Actual
152                       and Life Time page counters may be increased or decreased
153                       if usage is prefixed with + or -.
154                       WARNING : BOTH page counters are modified in all cases,
155                       so be careful.
156                       NB : if 'usage' equals '0', then the action taken is
157                       the same as if --hardreset was used.
158
159  user1 through userN and group1 through groupN can use wildcards
160  if the --add option is not set.
161 
162examples :                             
163
164  $ edpykota --add -p jerome john paul george ringo/ringo@example.com
165 
166  This will add users john, paul, george and ringo to the quota
167  database, and set their print quotas to the same values than user
168  jerome. User jerome must already exist.
169  User ringo's email address will also be set to 'ringo@example.com'
170 
171  $ edpykota --printer lp -S 50 -H 60 jerome
172 
173  This will set jerome's print quota on the lp printer to a soft limit
174  of 50 pages, and a hard limit of 60 pages. If either user jerome or
175  printer lp doesn't exist on the Quota Storage Server then nothing is done.
176
177  $ edpykota --add --printer lp --ingroups coders,it -S 50 -H 60 jerome
178 
179  Same as above, but if either user jerome or printer lp doesn't exist
180  on the Quota Storage Server they are automatically added. Also
181  user jerome is put into the groups "coders" and "it" which must
182  already exist in the Quota Storage.
183           
184  $ edpykota -g -S 500 -H 550 financial support           
185 
186  This will set print quota soft limit to 500 pages and hard limit
187  to 550 pages for groups financial and support on all printers.
188 
189  $ edpykota --reset jerome "jo*"
190 
191  This will reset jerome's page counter to zero on all printers, as
192  well as every user whose name begins with 'jo'.
193  Their life time page counter on each printer will be kept unchanged.
194  You can also reset the life time page counters by using the
195  --hardreset | -R command line option.
196 
197  $ edpykota --printer hpcolor --noquota jerome
198 
199  This will tell PyKota to not limit jerome when printing on the
200  hpcolor printer. All his jobs will be allowed on this printer, but
201  accounting of the pages he prints will still be kept.
202  Print Quotas for jerome on other printers are unchanged.
203 
204  $ edpykota --limitby balance jerome
205 
206  This will tell PyKota to limit jerome by his account's balance
207  when printing.
208 
209  $ edpykota --balance +10.0 jerome
210 
211  This will increase jerome's account balance by 10.0 (in your
212  own currency). You can decrease the account balance with a
213  dash prefix, and set it to a fixed amount with no prefix.
214 
215  $ edpykota --delete jerome rachel
216 
217  This will completely delete jerome and rachel from the Quota Storage
218  database. All their quotas and jobs will be deleted too.
219 
220  $ edpykota --printer lp --charge 0.1
221 
222  This will set the page price for printer lp to 0.1. Job price
223  will not be changed.
224 
225  $ edpykota --printer hplj1,hplj2 --pgroups Laser,HP
226 
227  This will put printers hplj1 and hplj2 in printers groups Laser and HP.
228  When printing either on hplj1 or hplj2, print quota will also be
229  checked and accounted for on virtual printers Laser and HP.
230 
231  $ edpykota --overcharge 2.5 poorstudent
232 
233  This will overcharge the poorstudent user by a factor of 2.5.
234 
235  $ edpykota --overcharge -1 jerome
236 
237  User jerome will actually earn money whenever he prints.
238 
239  $ edpykota --overcharge 0 boss
240 
241  User boss can print at will, it won't cost him anything because the
242  cost of each print job will be multiplied by zero before charging
243  his account.
244""") 
245       
246class EdPyKota(PyKotaTool) :       
247    """A class for edpykota."""
248    def main(self, names, options) :
249        """Edit user or group quotas."""
250        if not self.config.isAdmin :
251            raise PyKotaCommandLineError, "%s : %s" % (pwd.getpwuid(os.geteuid())[0], _("You're not allowed to use this command."))
252       
253        suffix = (options["groups"] and "Group") or "User"       
254       
255        if options["delete"] :   
256            self.display("%s...\n" % _("Processing"))
257            todelete = getattr(self.storage, "getMatching%ss" % suffix)(",".join(names))
258            nbtotal = len(todelete)
259            for i in range(nbtotal) :
260                todelete[i].delete()
261                percent = 100.0 * float(i) / float(nbtotal)
262                self.display("\r%.02f%%" % percent)
263            self.display("\r100.00%%\r        ")
264            self.display("\r%s\n" % _("Done."))
265        else :
266            softlimit = hardlimit = None
267           
268            limitby = options["limitby"]
269            if limitby :
270                limitby = limitby.strip().lower()
271            if limitby :
272                if limitby not in ('quota', 'balance', 'noquota', \
273                                            'noprint', 'nochange') :
274                    raise PyKotaCommandLineError, _("Invalid limitby value %s") % options["limitby"]
275                if limitby in ('noquota', 'nochange') :   
276                    options["noquota"] = 1
277                if (limitby in ('nochange', 'noprint')) and options["groups"] :   
278                    raise PyKotaCommandLineError, _("Invalid limitby value %s") % options["limitby"]
279           
280            used = options["used"]
281            if used :
282                used = used.strip()
283                try :
284                    int(used)
285                except ValueError :
286                    raise PyKotaCommandLineError, _("Invalid used value %s.") % used
287                   
288            increase = options["increase"]
289            if increase :
290                try :
291                    increase = int(increase.strip())
292                except ValueError :
293                    raise PyKotaCommandLineError, _("Invalid increase value %s.") % increase
294           
295            if not options["noquota"] :
296                if options["softlimit"] :
297                    try :
298                        softlimit = int(options["softlimit"].strip())
299                        if softlimit < 0 :
300                            raise ValueError
301                    except ValueError :   
302                        raise PyKotaCommandLineError, _("Invalid softlimit value %s.") % options["softlimit"]
303                if options["hardlimit"] :
304                    try :
305                        hardlimit = int(options["hardlimit"].strip())
306                        if hardlimit < 0 :
307                            raise ValueError
308                    except ValueError :   
309                        raise PyKotaCommandLineError, _("Invalid hardlimit value %s.") % options["hardlimit"]
310                if (softlimit is not None) and (hardlimit is not None) and (hardlimit < softlimit) :       
311                    # error, exchange them
312                    self.printInfo(_("Hard limit %i is less than soft limit %i, values will be exchanged.") % (hardlimit, softlimit))
313                    (softlimit, hardlimit) = (hardlimit, softlimit)
314               
315            overcharge = options["overcharge"]
316            if overcharge :
317                try :
318                    overcharge = float(overcharge.strip())
319                except (ValueError, AttributeError) :   
320                    raise PyKotaCommandLineError, _("Invalid overcharge value %s") % options["overcharge"]
321                   
322            balance = options["balance"]
323            if balance :
324                balance = balance.strip()
325                try :
326                    balancevalue = float(balance)
327                except ValueError :   
328                    raise PyKotaCommandLineError, _("Invalid balance value %s") % options["balance"]
329               
330            if options["charge"] :
331                try :
332                    charges = [float(part) for part in options["charge"].split(',', 1)]
333                except ValueError :   
334                    raise PyKotaCommandLineError, _("Invalid charge amount value %s") % options["charge"]
335                else :   
336                    if len(charges) > 2 :
337                        charges = charges[:2]
338                    if len(charges) != 2 :
339                        charges = [charges[0], None]
340                       
341            if options["ingroups"] :   
342                groupnames = [gname.strip() for gname in options["ingroups"].split(',')]
343            else :   
344                groupnames = []
345               
346            rejectunknown = self.config.getRejectUnknown()   
347            printeradded = 0
348            printers = self.storage.getMatchingPrinters(options["printer"])
349            if not printers :
350                pname = options["printer"]
351                if options["add"] and pname :
352                    if self.isValidName(pname) :
353                        printers = [ self.storage.addPrinter(pname) ]
354                        if printers[0].Exists :
355                            printeradded = 1
356                        else :   
357                            raise PyKotaToolError, _("Impossible to add printer %s") % pname
358                    else :   
359                        raise PyKotaCommandLineError, _("Invalid printer name %s") % pname
360                else :
361                    raise PyKotaCommandLineError, _("There's no printer matching %s") % pname
362            if not names :   
363                names = getattr(self.storage, "getAll%ssNames" % suffix)() # all users or groups
364                   
365            printersgroups = []       
366            if options["pgroups"] :       
367                printersgroups = self.storage.getMatchingPrinters(options["pgroups"])
368               
369            if options["prototype"] :   
370                protoentry = getattr(self.storage, "get%s" % suffix)(options["prototype"])
371                if not protoentry.Exists :
372                    raise PyKotaCommandLineError, _("Prototype object %s not found in Quota Storage.") % protoentry.Name
373                else :   
374                    limitby = protoentry.LimitBy
375                    balancevalue = protoentry.AccountBalance
376                    if balancevalue is not None :
377                        balance = str(abs(balancevalue))
378                    else :   
379                        balance = None
380                    overcharge = getattr(protoentry, "OverCharge", None)
381               
382            sys.stdout.write(_("Managing print quotas... (this may take a lot of time)"))
383            sys.stdout.flush()
384            missingusers = {}
385            missinggroups = {}   
386            changed = {} # tracks changes made at the user/group level
387            for printer in printers :
388                for pgroup in printersgroups :
389                    pgroup.addPrinterToGroup(printer)   
390                   
391                if options["charge"] :
392                    (perpage, perjob) = charges
393                    printer.setPrices(perpage, perjob)   
394                    printer.save()
395                   
396                if options["prototype"] :
397                    protoquota = getattr(self.storage, "get%sPQuota" % suffix)(protoentry, printer)
398                    if not protoquota.Exists :
399                        self.printInfo(_("Prototype %s not found in Quota Storage for printer %s.") % (protoentry.Name, printer.Name))
400                    else :   
401                        (softlimit, hardlimit) = (protoquota.SoftLimit, protoquota.HardLimit)
402                       
403                if not options["noquota"] :   
404                    if hardlimit is None :   
405                        hardlimit = softlimit
406                        if hardlimit is not None :
407                            self.printInfo(_("Undefined hard limit set to soft limit (%s) on printer %s.") % (str(hardlimit), printer.Name))
408                    if softlimit is None :   
409                        softlimit = hardlimit
410                        if softlimit is not None :
411                            self.printInfo(_("Undefined soft limit set to hard limit (%s) on printer %s.") % (str(softlimit), printer.Name))
412                           
413                if options["add"] :   
414                    allentries = []   
415                    for name in names :
416                        email = ""
417                        if not options["groups"] :
418                            splitname = name.split('/', 1)     # username/email
419                            if len(splitname) == 1 :
420                                splitname.append("")
421                            (name, email) = splitname
422                            if email and (email.count('@') != 1) :
423                                self.printInfo(_("Invalid email address %s") % email)
424                                email = ""
425                        entry = getattr(self.storage, "get%s" % suffix)(name)
426                        if email and not options["groups"] :
427                            entry.Email = email
428                        entrypquota = getattr(self.storage, "get%sPQuota" % suffix)(entry, printer)
429                        allentries.append((entry, entrypquota))
430                else :   
431                    allentries = getattr(self.storage, "getPrinter%ssAndQuotas" % suffix)(printer, names)
432                   
433                # TODO : do this only once !!!   
434                allnames = [entry.Name for (entry, dummy) in allentries]
435                for name in names :   
436                    if not self.matchString(name, allnames) :
437                        if options["groups"] :
438                            missinggroups[name] = 1
439                        else :   
440                            missingusers[name] = 1
441                   
442                for (entry, entrypquota) in allentries :
443                    if not changed.has_key(entry.Name) :
444                        changed[entry.Name] = {}
445                        if not options["groups"] :
446                            changed[entry.Name]["ingroups"] = []
447                           
448                    if not entry.Exists :       
449                        # not found
450                        if options["add"] :
451                            # In case we want to add something, it is crucial
452                            # that we DON'T check with the system accounts files
453                            # like /etc/passwd because users may be defined
454                            # only remotely
455                            if self.isValidName(entry.Name) :
456                                reject = 0
457                                if rejectunknown :
458                                    if options["groups"] :
459                                        try :
460                                            grp.getgrnam(entry.Name)
461                                        except KeyError :   
462                                            self.printInfo(_("Unknown group %s") % entry.Name, "error")
463                                            reject = 1
464                                    else :   
465                                        try :
466                                            pwd.getpwnam(entry.Name)
467                                        except KeyError :   
468                                            self.printInfo(_("Unknown user %s") % entry.Name, "error")
469                                            reject = 1
470                                if not reject :       
471                                    entry = getattr(self.storage, "add%s" % suffix)(entry)
472                            else :   
473                                if options["groups"] :
474                                    self.printInfo(_("Invalid group name %s") % entry.Name)
475                                else :   
476                                    self.printInfo(_("Invalid user name %s") % entry.Name)
477                        else :
478                            if options["groups"] :
479                                missinggroups[entry.Name] = 1
480                            else :   
481                                missingusers[entry.Name] = 1
482                                   
483                    if entry.Exists and (not entrypquota.Exists) :
484                        # not found
485                        if options["add"] :
486                            entrypquota = getattr(self.storage, "add%sPQuota" % suffix)(entry, printer)
487                           
488                    if not entrypquota.Exists :     
489                        self.printInfo(_("Quota not found for object %s on printer %s.") % (entry.Name, printer.Name))
490                    else :   
491                        if options["noquota"] or options["prototype"] \
492                           or ((softlimit is not None) and (hardlimit is not None)) :
493                            entrypquota.setLimits(softlimit, hardlimit)
494                        if increase :
495                           if (entrypquota.SoftLimit is None) \
496                               or (entrypquota.HardLimit is None) :
497                               self.printInfo(_("You can't increase limits by %s when no limit is set.") % increase, "error")
498                           else :
499                               newsoft = entrypquota.SoftLimit + increase         
500                               newhard = entrypquota.HardLimit + increase         
501                               if (newsoft >= 0) and (newhard >= 0) :
502                                   entrypquota.setLimits(newsoft, newhard)
503                               else :   
504                                   self.printInfo(_("You can't set negative limits."), "error")
505                        if limitby :
506                            if changed[entry.Name].get("limitby") is None :
507                                entry.setLimitBy(limitby)
508                                changed[entry.Name]["limitby"] = limitby
509                       
510                        if options["reset"] :
511                            entrypquota.reset()
512                           
513                        if options["hardreset"] :   
514                            entrypquota.hardreset()
515                           
516                        if not options["groups"] :
517                            if used :
518                                entrypquota.setUsage(used)
519                               
520                            if overcharge is not None :   
521                                if changed[entry.Name].get("overcharge") is None :
522                                    entry.setOverChargeFactor(overcharge)
523                                    changed[entry.Name]["overcharge"] = overcharge
524                                   
525                            if balance :
526                                if changed[entry.Name].get("balance") is None :
527                                    if balance.startswith("+") or balance.startswith("-") :
528                                        newbalance = float(entry.AccountBalance or 0.0) + balancevalue
529                                        newlifetimepaid = float(entry.LifeTimePaid or 0.0) + balancevalue
530                                        entry.setAccountBalance(newbalance, newlifetimepaid, options["comment"])
531                                    else :
532                                        diff = balancevalue - float(entry.AccountBalance or 0.0)
533                                        newlifetimepaid = float(entry.LifeTimePaid or 0.0) + diff
534                                        entry.setAccountBalance(balancevalue, newlifetimepaid, options["comment"])
535                                    changed[entry.Name]["balance"] = balance
536                                   
537                            for groupname in groupnames :       
538                                # not executed if option --ingroups is not used
539                                if groupname not in changed[entry.Name]["ingroups"] :
540                                    group = self.storage.getGroup(groupname)
541                                    if group.Exists :
542                                        self.storage.addUserToGroup(entry, group)
543                                        changed[entry.Name]["ingroups"].append(groupname)
544                                    else :
545                                        self.printInfo(_("Group %s not found in the PyKota Storage.") % groupname)
546                           
547            # Now outputs the list of nonexistent users and groups               
548            for name in missingusers.keys() :
549                self.printInfo(_("Nonexistent user %s or missing print quota entry.") % name, level="warn")
550            for name in missinggroups.keys() :
551                self.printInfo(_("Nonexistent group %s or missing print quota entry.") % name, level="warn")
552           
553            sys.stdout.write("\nDone.\n")   
554                     
555if __name__ == "__main__" : 
556    retcode = 0
557    try :
558        raise PyKotaCommandLineError, "This version is not stable, download an earlier one. Operation aborted."
559        defaults = { \
560                     "printer" : "*", \
561                     "comment" : "", \
562                   }
563        short_options = "vhdo:c:C:l:b:i:naugrp:P:S:H:G:RU:I:"
564        long_options = ["help", "version", "comment=", \
565                        "overcharge=", "charge=", "delete", "limitby=", \
566                        "balance=", "ingroups=", "noquota", "add", "users", \
567                        "groups", "reset", "hardreset", "prototype=", \
568                        "printer=", "softlimit=", "hardlimit=", "pgroups=", \
569                        "increase=", "used="]
570       
571        # Initializes the command line tool
572        editor = EdPyKota(doc=__doc__)
573        editor.deferredInit()
574       
575        # parse and checks the command line
576        (options, args) = editor.parseCommandline(sys.argv[1:], short_options, long_options)
577       
578        # sets long options
579        options["help"] = options["h"] or options["help"]
580        options["version"] = options["v"] or options["version"]
581        options["add"] = options["a"] or options["add"]
582        options["users"] = options["u"] or options["users"]
583        options["groups"] = options["g"] or options["groups"]
584        options["prototype"] = options["p"] or options["prototype"]
585        options["printer"] = options["P"] or options["printer"] or defaults["printer"]
586        options["softlimit"] = options["S"] or options["softlimit"]
587        options["hardlimit"] = options["H"] or options["hardlimit"] 
588        options["reset"] = options["r"] or options["reset"] 
589        options["noquota"] = options["n"] or options["noquota"]
590        options["limitby"] = options["l"] or options["limitby"]
591        options["balance"] = options["b"] or options["balance"] 
592        options["delete"] = options["d"] or options["delete"] 
593        options["ingroups"] = options["i"] or options["ingroups"]
594        options["charge"] = options["c"] or options["charge"]
595        options["pgroups"] = options["G"] or options["pgroups"]
596        options["hardreset"] = options["R"] or options["hardreset"] 
597        options["used"] = options["U"] or options["used"]
598        options["overcharge"] = options["o"] or options["overcharge"]
599        options["comment"] = options["C"] or options["comment"] or defaults["comment"]
600        options["increase"] = options["I"] or options["increase"]
601       
602        if options["help"] :
603            editor.display_usage_and_quit()
604        elif options["version"] :
605            editor.display_version_and_quit()
606        elif options["users"] and options["groups"] :   
607            raise PyKotaCommandLineError, _("incompatible options, see help.")
608        elif (options["add"] or options["prototype"]) and options["delete"] :   
609            raise PyKotaCommandLineError, _("incompatible options, see help.")
610        elif (options["reset"] or options["hardreset"] or options["limitby"] or options["used"] or options["balance"] or options["overcharge"] or options["softlimit"] or options["hardlimit"]) and options["prototype"] :
611            raise PyKotaCommandLineError, _("incompatible options, see help.")
612        elif options["noquota"] and (options["prototype"] or options["hardlimit"] or options["softlimit"]) :
613            raise PyKotaCommandLineError, _("incompatible options, see help.")
614        elif options["groups"] and (options["balance"] or options["ingroups"] or options["used"] or options["overcharge"]) :
615            raise PyKotaCommandLineError, _("incompatible options, see help.")
616        elif options["comment"] and not options["balance"] :   
617            raise PyKotaCommandLineError, _("incompatible options, see help.")
618        elif options["delete"] and not args :
619            raise PyKotaCommandLineError, _("You have to pass user or group names on the command line")
620        else :
621            retcode = editor.main(args, options)
622    except KeyboardInterrupt :       
623        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
624        retcode = -3
625    except PyKotaCommandLineError, msg :     
626        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
627        retcode = -2
628    except SystemExit :       
629        pass
630    except :
631        try :
632            editor.crashed("edpykota failed")
633        except :   
634            crashed("edpykota failed")
635        retcode = -1
636
637    try :
638        editor.storage.close()
639    except (TypeError, NameError, AttributeError) :   
640        pass
641       
642    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.