Changeset 3418

Show
Ignore:
Timestamp:
10/04/08 07:26:08 (14 years ago)
Author:
jerome
Message:

pkprinters now supports new style command line handling.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/bin/pkprinters

    r3413 r3418  
    2727 
    2828import pykota.appinit 
    29 from pykota.utils import * 
    30  
     29from pykota.utils import run 
     30from pykota.commandline import PyKotaOptionParser 
    3131from pykota.errors import PyKotaCommandLineError 
    3232from pykota.tool import Percent, PyKotaTool 
     
    3434 
    3535from pkipplib import pkipplib 
    36  
    37 __doc__ = N_("""pkprinters v%(__version__)s (c) %(__years__)s %(__author__)s 
    38  
    39 A Printers Manager for PyKota. 
    40  
    41 command line usage : 
    42  
    43   pkprinters [options] printer1 printer2 printer3 ... printerN 
    44  
    45 options : 
    46  
    47   -v | --version       Prints pkprinters's version number then exits. 
    48   -h | --help          Prints this message then exits. 
    49  
    50   -a | --add           Adds printers if they don't exist on the Quota 
    51                        Storage Server. If they exist, they are modified 
    52                        unless -s|--skipexisting is also used. 
    53  
    54   -d | --delete        Deletes printers from the quota storage. 
    55  
    56   -D | --description d Adds a textual description to printers. 
    57  
    58   -C | --cups          Also modifies the DeviceURI in CUPS' printers.conf 
    59  
    60   -c | --charge p[,j]  Sets the price per page and per job to charge. 
    61                        Job price is optional. 
    62                        If both are to be set, separate them with a comma. 
    63                        Floating point and negative values are allowed. 
    64  
    65   -g | --groups pg1[,pg2...] Adds or Remove the printer(s) to the printer 
    66                        groups pg1, pg2, etc... which must already exist. 
    67                        A printer group is just like a normal printer, 
    68                        only that it is usually unknown from the printing 
    69                        system. Create printer groups exactly the same 
    70                        way that you create printers, then add other 
    71                        printers to them with this option. 
    72                        Accounting is done on a printer and on all 
    73                        the printer groups it belongs to, quota checking 
    74                        is done on a printer and on all the printer groups 
    75                        it belongs to. 
    76                        If the --remove option below is not used, the 
    77                        default action is to add printers to the specified 
    78                        printer groups. 
    79  
    80   -l | --list          List informations about the printer(s) and the 
    81                        printers groups it is a member of. 
    82  
    83   -r | --remove        In combination with the --groups option above, 
    84                        remove printers from the specified printers groups. 
    85  
    86   -s | --skipexisting  In combination with the --add option above, tells 
    87                        pkprinters to not modify existing printers. 
    88  
    89   -m | --maxjobsize s  Sets the maximum job size allowed on the printer 
    90                        to s pages. 
    91  
    92   -p | --passthrough   Activate passthrough mode for the printer. In this 
    93                        mode, users are allowed to print without any impact 
    94                        on their quota or account balance. 
    95  
    96   -n | --nopassthrough Deactivate passthrough mode for the printer. 
    97                        Without -p or -n, printers are created in 
    98                        normal mode, i.e. no passthrough. 
    99  
    100   printer1 through printerN can contain wildcards if the --add option 
    101   is not set. 
    102  
    103 examples : 
    104  
    105   $ pkprinters --add -D "HP Printer" --charge 0.05,0.1 hp2100 hp2200 hp8000 
    106  
    107   Will create three printers named hp2100, hp2200 and hp8000. 
    108   Their price per page will be set at 0.05 unit, and their price 
    109   per job will be set at 0.1 unit. Units are in your own currency, 
    110   or whatever you want them to mean. 
    111   All of their descriptions will be set to the string "HP Printer". 
    112   If any of these printers already exists, it will also be modified 
    113   unless the -s|--skipexisting command line option is also used. 
    114  
    115   $ pkprinters --delete "*" 
    116  
    117   This will completely delete all printers and associated quota information, 
    118   as well as their job history. USE WITH CARE ! 
    119  
    120   $ pkprinters --groups Laser,HP "hp*" 
    121  
    122   This will put all printers which name matches "hp*" into printers groups 
    123   Laser and HP, which MUST already exist. 
    124  
    125   $ pkprinters --groups LexMark --remove hp2200 
    126  
    127   This will remove the hp2200 printer from the LexMark printer group. 
    128 """) 
    12936 
    13037class PKPrinters(PyKotaTool) : 
     
    19097    def main(self, names, options) : 
    19198        """Manage printers.""" 
    192         if not options["list"] : 
     99        islist = (options.action == "list") 
     100        isadd = (options.action == "add") 
     101        isdelete = (options.action == "delete") 
     102 
     103        if not islist : 
    193104            self.adminOnly() 
    194105 
    195         docups = options["cups"] 
    196  
    197         if not options["list"] : 
     106        if not names : 
     107            if isdelete or isadd : 
     108                raise PyKotaCommandLineError, _("You must specify printers names on the command line.") 
     109            names = [u"*"] 
     110 
     111        if not islist : 
    198112            percent = Percent(self) 
    199113 
    200         if not options["add"] : 
    201             if not options["list"] : 
     114        if not isadd : 
     115            if not islist : 
    202116                percent.display("%s..." % _("Extracting datas")) 
    203             if not names :      # NB : can't happen for --delete because it's catched earlier 
    204                 names = ["*"] 
    205117            printers = self.storage.getMatchingPrinters(",".join(names)) 
    206118            if not printers : 
    207                 if not options["list"] : 
     119                if not islist : 
    208120                    percent.display("\n") 
    209121                raise PyKotaCommandLineError, _("There's no printer matching %s") % " ".join(names) 
    210             if not options["list"] : 
     122            if not islist : 
    211123                percent.setSize(len(printers)) 
    212124 
    213         if options["list"] : 
     125        if islist : 
    214126            for printer in printers : 
    215127                parents = ", ".join([p.Name for p in self.storage.getParentPrinters(printer)]) 
    216                 print "%s [%s] (%s + #*%s)" % \ 
    217                       (printer.Name, printer.Description, printer.PricePerJob, \ 
    218                        printer.PricePerPage) 
    219                 print "    %s" % (_("Passthrough mode : %s") % ((printer.PassThrough and _("ON")) or _("OFF"))) 
    220                 print "    %s" % (_("Maximum job size : %s") % ((printer.MaxJobSize and (_("%s pages") % printer.MaxJobSize)) or _("Unlimited"))) 
    221                 print "    %s" % (_("Routed through PyKota : %s") % ((self.isPrinterCaptured(printer.Name) and _("YES")) or _("NO"))) 
     128                self.display("%s [%s] (%s + #*%s)\n" % \ 
     129                                     (printer.Name, 
     130                                      printer.Description, 
     131                                      printer.PricePerJob, 
     132                                      printer.PricePerPage)) 
     133                self.display("    %s\n" % \ 
     134                                     (_("Passthrough mode : %s") % ((printer.PassThrough and _("ON")) or _("OFF")))) 
     135                self.display("    %s\n" % \ 
     136                                     (_("Maximum job size : %s") % ((printer.MaxJobSize and (_("%s pages") % printer.MaxJobSize)) or _("Unlimited")))) 
     137                self.display("    %s\n" % (_("Routed through PyKota : %s") % ((self.isPrinterCaptured(printer.Name) and _("YES")) or _("NO")))) 
    222138                if parents : 
    223                     print "    %s %s" % (_("in"), parents) 
    224                 print 
    225         elif options["delete"] : 
     139                    self.display("    %s %s\n" % (_("in"), parents)) 
     140                self.display("\n") 
     141        elif isdelete : 
    226142            percent.display("\n%s..." % _("Deletion")) 
    227143            self.storage.deleteManyPrinters(printers) 
    228144            percent.display("\n") 
    229             if docups : 
     145            if options.cups : 
    230146                percent.display("%s...\n" % _("Rerouting printers to CUPS")) 
    231147                for printer in printers : 
     
    233149                    percent.oneMore() 
    234150        else : 
    235             if options["groups"] : 
    236                 printersgroups = self.storage.getMatchingPrinters(options["groups"]) 
     151            if options.groups : 
     152                printersgroups = self.storage.getMatchingPrinters(options.groups) 
    237153                if not printersgroups : 
    238                     raise PyKotaCommandLineError, _("There's no printer matching %s") % " ".join(options["groups"].split(',')) 
     154                    raise PyKotaCommandLineError, _("There's no printer matching %s") % " ".join(options.groups.split(',')) 
    239155            else : 
    240156                printersgroups = [] 
    241157 
    242             if options["charge"] : 
     158            if options.charge : 
    243159                try : 
    244                     charges = [float(part) for part in options["charge"].split(',', 1)] 
     160                    charges = [float(part) for part in options.charge.split(',', 1)] 
    245161                except ValueError : 
    246                     raise PyKotaCommandLineError, _("Invalid charge amount value %s") % options["charge"] 
     162                    raise PyKotaCommandLineError, _("Invalid charge amount value %s") % options.charge 
    247163                else : 
    248164                    if len(charges) > 2 : 
     
    254170                charges = perpage = perjob = None 
    255171 
    256             if options["maxjobsize"] : 
     172            if options.maxjobsize : 
    257173                try : 
    258                     maxjobsize = int(options["maxjobsize"]) 
     174                    maxjobsize = int(options.maxjobsize) 
    259175                    if maxjobsize < 0 : 
    260176                        raise ValueError 
    261177                except ValueError : 
    262                     raise PyKotaCommandLineError, _("Invalid maximum job size value %s") % options["maxjobsize"] 
     178                    raise PyKotaCommandLineError, _("Invalid maximum job size value %s") % options.maxjobsize 
    263179            else : 
    264180                maxjobsize = None 
    265181 
    266             description = options["description"] 
     182            description = options.description 
    267183            if description : 
    268184                description = description.strip() 
    269185 
    270             nopassthrough = options["nopassthrough"] 
    271             passthrough = options["passthrough"] 
    272             remove = options["remove"] 
    273             skipexisting = options["skipexisting"] 
    274186            self.storage.beginTransaction() 
    275187            try : 
    276                 if options["add"] : 
     188                if isadd : 
    277189                    percent.display("%s...\n" % _("Creation")) 
    278190                    percent.setSize(len(names)) 
     
    280192                        if self.isValidName(pname) : 
    281193                            printer = StoragePrinter(self.storage, pname) 
    282                             self.modifyPrinter(printer, charges, perpage, perjob, \ 
    283                                            description, passthrough, \ 
    284                                            nopassthrough, maxjobsize) 
     194                            self.modifyPrinter(printer, 
     195                                               charges, 
     196                                               perpage, 
     197                                               perjob, 
     198                                               description, 
     199                                               options.passthrough, 
     200                                               options.nopassthrough, 
     201                                               maxjobsize) 
    285202                            oldprinter = self.storage.addPrinter(printer) 
    286203 
    287                             if docups : 
     204                            if options.cups : 
    288205                                 self.reroutePrinterThroughPyKota(printer) 
    289206 
    290207                            if oldprinter is not None : 
    291                                 if skipexisting : 
     208                                if options.skipexisting : 
    292209                                    self.logdebug(_("Printer %s already exists, skipping.") % pname) 
    293210                                else : 
    294211                                    self.logdebug(_("Printer %s already exists, will be modified.") % pname) 
    295                                     self.modifyPrinter(oldprinter, charges, \ 
    296                                                perpage, perjob, description, \ 
    297                                                passthrough, nopassthrough, \ 
    298                                                maxjobsize) 
     212                                    self.modifyPrinter(oldprinter, 
     213                                                       charges, 
     214                                                       perpage, 
     215                                                       perjob, 
     216                                                       description, 
     217                                                       options.passthrough, 
     218                                                       options.nopassthrough, 
     219                                                       maxjobsize) 
    299220                                    oldprinter.save() 
    300                                     self.managePrintersGroups(printersgroups, oldprinter, remove) 
    301                             elif printersgroups : 
     221                                    self.managePrintersGroups(printersgroups, 
     222                                                              oldprinter, 
     223                                                              options.remove) 
     224                            else : 
    302225                                self.managePrintersGroups(printersgroups, \ 
    303226                                                          self.storage.getPrinter(pname), \ 
    304                                                           remove) 
     227                                                          options.remove) 
    305228                        else : 
    306229                            raise PyKotaCommandLineError, _("Invalid printer name %s") % pname 
     
    309232                    percent.display("\n%s...\n" % _("Modification")) 
    310233                    for printer in printers : 
    311                         self.modifyPrinter(printer, charges, perpage, perjob, \ 
    312                                            description, passthrough, \ 
    313                                            nopassthrough, maxjobsize) 
     234                        self.modifyPrinter(printer, 
     235                                           charges, 
     236                                           perpage, 
     237                                           perjob, 
     238                                           description, 
     239                                           options.passthrough, 
     240                                           options.nopassthrough, 
     241                                           maxjobsize) 
    314242                        printer.save() 
    315                         self.managePrintersGroups(printersgroups, printer, remove) 
    316                         if docups : 
     243                        self.managePrintersGroups(printersgroups, 
     244                                                  printer, 
     245                                                  options.remove) 
     246                        if options.cups : 
    317247                            self.reroutePrinterThroughPyKota(printer) 
    318248                        percent.oneMore() 
     
    323253                self.storage.commitTransaction() 
    324254 
    325         if not options["list"] : 
     255        if not islist : 
    326256            percent.done() 
    327257 
    328258if __name__ == "__main__" : 
    329     retcode = 0 
    330     try : 
    331         short_options = "hvaCc:D:dg:lrsnpm:" 
    332         long_options = ["help", "version", "add", "cups", "charge=", "description=", \ 
    333                         "delete", "groups=", "list", "remove", \ 
    334                         "skipexisting", "passthrough", "nopassthrough", \ 
    335                         "maxjobsize="] 
    336  
    337         # Initializes the command line tool 
    338         manager = PKPrinters(doc=__doc__) 
    339         manager.deferredInit() 
    340  
    341         # parse and checks the command line 
    342         (options, args) = manager.parseCommandline(sys.argv[1:], short_options, long_options) 
    343  
    344         # sets long options 
    345         options["help"] = options["h"] or options["help"] 
    346         options["version"] = options["v"] or options["version"] 
    347         options["add"] = options["a"] or options["add"] 
    348         options["cups"] = options["C"] or options["cups"] 
    349         options["charge"] = options["c"] or options["charge"] 
    350         options["description"] = options["D"] or options["description"] 
    351         options["delete"] = options["d"] or options["delete"] 
    352         options["groups"] = options["g"] or options["groups"] 
    353         options["list"] = options["l"] or options["list"] 
    354         options["remove"] = options["r"] or options["remove"] 
    355         options["skipexisting"] = options["s"] or options["skipexisting"] 
    356         options["maxjobsize"] = options["m"] or options["maxjobsize"] 
    357         options["passthrough"] = options["p"] or options["passthrough"] 
    358         options["nopassthrough"] = options["n"] or options["nopassthrough"] 
    359  
    360         if options["help"] : 
    361             manager.display_usage_and_quit() 
    362         elif options["version"] : 
    363             manager.display_version_and_quit() 
    364         elif (options["delete"] and (options["add"] or options["groups"] or options["charge"] or options["remove"] or options["description"])) \ 
    365            or (options["skipexisting"] and not options["add"]) \ 
    366            or (options["list"] and (options["add"] or options["delete"] or options["groups"] or options["charge"] or options["remove"] or options["description"])) \ 
    367            or (options["passthrough"] and options["nopassthrough"]) \ 
    368            or (options["remove"] and options["add"]) : 
    369             raise PyKotaCommandLineError, _("incompatible options, see help.") 
    370         elif options["remove"] and not options["groups"] : 
    371             raise PyKotaCommandLineError, _("You have to pass printer groups names on the command line") 
    372         elif (not args) and (options["add"] or options["delete"]) : 
    373             raise PyKotaCommandLineError, _("You have to pass printer names on the command line") 
    374         else : 
    375             retcode = manager.main(args, options) 
    376     except KeyboardInterrupt : 
    377         logerr("\nInterrupted with Ctrl+C !\n") 
    378         retcode = -3 
    379     except PyKotaCommandLineError, msg : 
    380         logerr("%s : %s\n" % (sys.argv[0], msg)) 
    381         retcode = -2 
    382     except SystemExit : 
    383         pass 
    384     except : 
    385         try : 
    386             manager.crashed("pkprinters failed") 
    387         except : 
    388             crashed("pkprinters failed") 
    389         retcode = -1 
    390  
    391     try : 
    392         manager.storage.close() 
    393     except (TypeError, NameError, AttributeError) : 
    394         pass 
    395  
    396     sys.exit(retcode) 
     259    parser = PyKotaOptionParser(description=_("Manages PyKota printers."), 
     260                                usage="pkprinters [options] printer1 printer2 ... printerN") 
     261    parser.add_option("-a", "--add", 
     262                            action="store_const", 
     263                            const="add", 
     264                            dest="action", 
     265                            help=_("Add new, or modify existing, printers.")) 
     266    parser.add_option("-c", "--charge", 
     267                            dest="charge", 
     268                            help=_("Set the cost per page, and optionally per job, for printing to the specified printers. If both are to be set, separate them with a comma. Floating point and negative values are allowed.")) 
     269    parser.add_option("-C", "--cups", 
     270                            action="store_true", 
     271                            dest="cups", 
     272                            help=_("Tell CUPS to either start or stop managing the specified printers with PyKota.")) 
     273    parser.add_option("-d", "--delete", 
     274                            action="store_const", 
     275                            const="delete", 
     276                            dest="action", 
     277                            help=_("Delete the specified printers. Also purge the print quota entries and printing history matching the specified printers.")) 
     278    parser.add_option("-D", "--description", 
     279                            dest="description", 
     280                            help=_("Set a textual description for the specified printers.")) 
     281    parser.add_option("-g", "--groups", 
     282                            dest="groups", 
     283                            help=_("If the --remove option is not used, the default action is to add the specified printers to the specified printers groups. Otherwise they are removed from these groups. The specified printers groups must already exist, and should be created beforehand just like normal printers with this very command.")) 
     284    parser.add_option("-l", "--list", 
     285                            action="store_const", 
     286                            const="list", 
     287                            dest="action", 
     288                            help=_("Display detailed informations about the specified printers.")) 
     289    parser.add_option("-m", "--maxjobsize", 
     290                            dest="maxjobsize", 
     291                            help=_("Set the maximum job size in pages allowed on the specified printers.")) 
     292    parser.add_option("-n", "--nopassthrough", 
     293                            action="store_true", 
     294                            dest="nopassthrough", 
     295                            help=_("Deactivate passthrough mode for the specified printers. This is the normal mode of operations, in which print jobs are accounted for, and are checked against printing quotas and available credits.")) 
     296    parser.add_option("-p", "--passthrough", 
     297                            action="store_true", 
     298                            dest="passthrough", 
     299                            help=_("Activate passthrough mode for the specified printers. In this mode, jobs sent to these printers are not accounted for. This can be useful for exams during which no user should be charged for his printouts.")) 
     300    parser.add_option("-r", "--remove", 
     301                            action="store_true", 
     302                            dest="remove", 
     303                            help=_("When combined with the --groups option, remove printers from the specified printers groups.")) 
     304    parser.add_option("-s", "--skipexisting", 
     305                            action="store_true", 
     306                            dest="skipexisting", 
     307                            help=_("If --add is used, ensure that existing printers won't be modified.")) 
     308 
     309    parser.add_example('--add --cups -D "HP Printer" --charge 0.05,0.1 hp2100 hp2200', 
     310                       _("Would create three printers named 'hp2100', and 'hp2200' in PyKota's database, while telling CUPS to route all print jobs through PyKota for these printers. Each of them would have 'HP Printer' as its description. Printing to any of them would cost 0.05 credit per page, plus 0.1 credit for each job.")) 
     311    parser.add_example('--delete "*"', 
     312                       _("Would delete all existing printers and matching print quota entries and printing history from PyKota's database. USE WITH CARE.")) 
     313    parser.add_example('--groups Laser,HP "hp*"', 
     314                       _("Would add all printers which name begins with 'hp' to the 'Laser' and 'HP' printers groups, which must already exist.")) 
     315    parser.add_example("--groups Lexmark --remove hp2200", 
     316                       _("Would remove printer 'hp2200' from the 'Lexmark' printers group.")) 
     317    run(parser, PKPrinters) 
     318