Changeset 3426 for pykota

Show
Ignore:
Timestamp:
10/04/08 22:29:34 (16 years ago)
Author:
jerome
Message:

pkusers now supports new style command line handling code. Needs more
serious testing...

Location:
pykota/trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/bin/pkusers

    r3413 r3426  
    2222# 
    2323 
     24"""A users and groups manager for PyKota.""" 
     25 
    2426import sys 
    2527import pwd 
     
    2729 
    2830import pykota.appinit 
    29 from pykota.utils import * 
    30  
     31from pykota.utils import run 
     32from pykota.commandline import PyKotaOptionParser 
    3133from pykota.errors import PyKotaCommandLineError 
    3234from pykota.tool import Percent, PyKotaTool 
    3335from pykota.storage import StorageUser, StorageGroup 
    3436 
    35 __doc__ = N_("""pkusers v%(__version__)s (c) %(__years__)s %(__author__)s 
    36  
    37 An Users and Groups Manager for PyKota. 
    38  
    39 command line usage : 
    40  
    41   pkusers [options] user1 user2 user3 ... userN 
    42  
    43 or : 
    44  
    45   pkusers --groups [options] group1 group2 group3 ... groupN 
    46  
    47 options : 
    48  
    49   -v | --version       Prints pkusers's version number then exits. 
    50   -h | --help          Prints this message then exits. 
    51  
    52   -a | --add           Adds users if they don't exist on the database. 
    53                        If they exist, they are modified unless 
    54                        -s|--skipexisting is also used. 
    55  
    56   -d | --delete        Deletes users from the quota storage. 
    57  
    58   -e | --email addr    Sets the email address for the users. 
    59                        If the addr parameter begins with @, then 
    60                        the username is prepended to addr to form 
    61                        a valid email address. 
    62  
    63   -D | --description d Adds a textual description to users or groups. 
    64  
    65   -g | --groups        Edit users groups instead of users. 
    66  
    67   -o | --overcharge f  Sets the overcharging factor applied to the user 
    68                        when computing the cost of a print job. Positive or 
    69                        negative floating point values are allowed, 
    70                        this allows you to do some really creative 
    71                        things like giving money to an user whenever 
    72                        he prints. The number of pages in a print job 
    73                        is not modified by this coefficient, only the 
    74                        cost of the job for a particular user. 
    75                        Only users have such a coefficient. 
    76  
    77   -i | --ingroups g1[,g2...]  Puts the users into each of the groups 
    78                               listed, separated by commas. The groups 
    79                               must already exist in the Quota Storage. 
    80  
    81   -L | --list          Lists users or groups. 
    82  
    83   -l | --limitby l     Choose if the user/group is limited in printing 
    84                        by its account balance or by its page quota. 
    85                        The default value is 'quota'. Allowed values 
    86                        are 'quota' 'balance' 'noquota' 'noprint' 
    87                        and 'nochange' : 
    88  
    89                          - quota : limit by number of pages per printer. 
    90                          - balance : limit by number of credits in account. 
    91                          - noquota : no limit, accounting still done. 
    92                          - nochange : no limit, accounting not done. 
    93                          - noprint : printing is denied. 
    94                        NB : nochange and noprint are not supported for groups. 
    95  
    96   -b | --balance b     Sets the user's account balance to b. 
    97                        Account balance may be increase or decreased 
    98                        if b is prefixed with + or -. 
    99                        WARNING : when decreasing account balance, 
    100                        the total paid so far by the user is decreased 
    101                        too. 
    102                        Groups don't have a real balance, but the 
    103                        sum of their users' account balance. 
    104  
    105   -C | --comment txt   Defines some informational text to be associated 
    106                        with a change to an user's account balance. 
    107                        Only meaningful if -b | --balance is also used. 
    108  
    109  
    110   -r | --remove        In combination with the --ingroups option above, 
    111                        remove users from the specified users groups. 
    112  
    113   -s | --skipexisting  In combination with the --add option above, tells 
    114                        pkusers to not modify existing users. 
    115  
    116   user1 through userN and group1 through groupN can use wildcards 
    117   if the --add option is not set. 
    118  
    119 examples : 
    120  
    121   $ pkusers --add john paul george ringo/ringo@example.com 
    122  
    123   This will add users john, paul, george and ringo to the quota 
    124   database. User ringo's email address will also be set to 
    125   'ringo@example.com' 
    126  
    127   $ pkusers --ingroups coders,it jerome 
    128  
    129   User jerome is put into the groups "coders" and "it" which must 
    130   already exist in the quota database. 
    131  
    132   $ pkusers --limitby balance jerome 
    133  
    134   This will tell PyKota to limit jerome by his account's balance 
    135   when printing. 
    136  
    137   $ pkusers --balance +10.0 --comment "He paid with his blood !" jerome 
    138  
    139   This will increase jerome's account balance by 10.0 (in your 
    140   own currency). You can decrease the account balance with a 
    141   dash prefix, and set it to a fixed amount with no prefix. 
    142   A comment will be stored for this balance change. 
    143  
    144   $ pkusers --delete jerome rachel 
    145  
    146   This will completely delete jerome and rachel from the quota 
    147   database. All their quotas and jobs will be deleted too. 
    148  
    149   $ pkusers --overcharge 2.5 poorstudent 
    150  
    151   This will overcharge the poorstudent user by a factor of 2.5. 
    152  
    153   $ pkusers --overcharge -1 jerome 
    154  
    155   User jerome will actually earn money whenever he prints. 
    156  
    157   $ pkusers --overcharge 0 boss 
    158  
    159   User boss can print at will, it won't cost him anything because the 
    160   cost of each print job will be multiplied by zero before charging 
    161   his account. 
    162  
    163   $ pkusers --email @example.com 
    164  
    165   This will set the email address for each user to username@example.com 
    166 """) 
     37 
    16738 
    16839class PKUsers(PyKotaTool) : 
     
    20172                ugroup.addUserToGroup(user) 
    20273 
     74    def sanitizeNames(self, names, isgroups) : 
     75        """Sanitize users and groups names if needed.""" 
     76        if not self.config.isAdmin : 
     77            username = pwd.getpwuid(os.geteuid())[0] 
     78            if isgroups : 
     79                user = self.storage.getUser(username) 
     80                if user.Exists : 
     81                    return [ g.Name for g in self.storage.getUserGroups(user) ] 
     82            return [ username ] 
     83        return names 
     84 
    20385    def main(self, names, options) : 
    20486        """Manage users or groups.""" 
    205         names = self.sanitizeNames(options, names) 
    206         suffix = (options["groups"] and "Group") or "User" 
    207  
    208         if not options["list"] : 
     87        islist = (options.action == "list") 
     88        isadd = (options.action == "add") 
     89        isdelete = (options.action == "delete") 
     90 
     91        if not islist : 
     92            self.adminOnly() 
     93 
     94        names = self.sanitizeNames(names, options.groups) 
     95        if not names : 
     96            if isdelete or isadd : 
     97                raise PyKotaCommandLineError, _("You must specify users or groups names on the command line.") 
     98            names = [u"*"] 
     99 
     100        if options.remove and not options.ingroups : 
     101            raise PyKotaCommandLineError, _("You must specify users groups names on the command line.") 
     102        elif (((islist or isdelete) and (options.limitby  \ 
     103                                      or options.balance \ 
     104                                      or options.email \ 
     105                                      or options.remove \ 
     106                                      or options.overcharge \ 
     107                                      or options.ingroups \ 
     108                                      or options.description \ 
     109                                      or options.skipexisting \ 
     110                                      or options.comment))) \ 
     111             or (options.groups and (options.ingroups \ 
     112                                  or options.balance \ 
     113                                  or options.email \ 
     114                                  or options.remove \ 
     115                                  or options.overcharge \ 
     116                                  or options.comment)) : 
     117            raise PyKotaCommandLineError, _("Incompatible command line options. Please look at the online help or manual page.") 
     118 
     119        suffix = (options.groups and "Group") or "User" 
     120 
     121        if not islist : 
    209122            percent = Percent(self) 
    210123 
    211         if not options["add"] : 
    212             if not options["list"] : 
     124        if not isadd : 
     125            if not islist : 
    213126                percent.display("%s..." % _("Extracting datas")) 
    214             if not names :      # NB : can't happen for --delete because it's catched earlier 
    215                 names = ["*"] 
    216127            entries = getattr(self.storage, "getMatching%ss" % suffix)(",".join(names)) 
    217128            if not entries : 
    218                 if not options["list"] : 
     129                if not islist : 
    219130                    percent.display("\n") 
    220                 raise PyKotaCommandLineError, _("There's no %s matching %s") % (_(suffix.lower()), " ".join(names)) 
    221             if not options["list"] : 
     131                raise PyKotaCommandLineError, _("There's no %s matching %s") \ 
     132                    % (_(suffix.lower()), " ".join(names)) 
     133            if not islist : 
    222134                percent.setSize(len(entries)) 
    223135 
    224         if options["list"] : 
     136        if islist : 
    225137            if suffix == "User" : 
    226138                maildomain = self.config.getMailDomain() 
     
    238150                    if entry.Description : 
    239151                        msg += " - %s" % entry.Description 
    240                     print msg 
    241                     print "    %s" % (_("Limited by : %s") % entry.LimitBy) 
    242                     print "    %s" % (_("Account balance : %.2f") % (entry.AccountBalance or 0.0)) 
    243                     print "    %s" % (_("Total paid so far : %.2f") % (entry.LifeTimePaid or 0.0)) 
    244                     print "    %s" % (_("Overcharging factor : %.2f") % entry.OverCharge) 
    245                     print 
     152                    self.display("%s\n" % msg) 
     153                    self.display("    %s\n" % (_("Limited by : %s") % entry.LimitBy)) 
     154                    self.display("    %s\n" % (_("Account balance : %.2f") % (entry.AccountBalance or 0))) 
     155                    self.display("    %s\n" % (_("Total paid so far : %.2f") % (entry.LifeTimePaid or 0))) 
     156                    self.display("    %s\n" % (_("Overcharging factor : %.2f") % entry.OverCharge)) 
     157                    self.display("\n") 
    246158            else : 
    247159                for entry in entries : 
     
    249161                    if entry.Description : 
    250162                        msg += " - %s" % entry.Description 
    251                     print msg 
    252                     print "    %s" % (_("Limited by : %s") % entry.LimitBy) 
    253                     print "    %s" % (_("Group balance : %.2f") % (entry.AccountBalance or 0.0)) 
    254                     print "    %s" % (_("Total paid so far : %.2f") % (entry.LifeTimePaid or 0.0)) 
    255                     print 
    256         elif options["delete"] : 
     163                    self.display("%s\n" % msg) 
     164                    self.display("    %s\n" % (_("Limited by : %s") % entry.LimitBy)) 
     165                    self.display("    %s\n" % (_("Group balance : %.2f") % (entry.AccountBalance or 0))) 
     166                    self.display("    %s\n" % (_("Total paid so far : %.2f") % (entry.LifeTimePaid or 0))) 
     167                    self.display("\n") 
     168        elif isdelete : 
    257169            percent.display("\n%s..." % _("Deletion")) 
    258170            getattr(self.storage, "deleteMany%ss" % suffix)(entries) 
    259171            percent.display("\n") 
    260172        else : 
    261             limitby = options["limitby"] 
     173            limitby = options.limitby 
    262174            if limitby : 
    263175                limitby = limitby.strip().lower() 
    264176            if limitby : 
    265                 if limitby not in ('quota', 'balance', 'noquota', \ 
    266                                             'noprint', 'nochange') : 
    267                     raise PyKotaCommandLineError, _("Invalid limitby value %s") % options["limitby"] 
    268                 if (limitby in ('nochange', 'noprint')) and options["groups"] : 
    269                     raise PyKotaCommandLineError, _("Invalid limitby value %s") % options["limitby"] 
    270  
    271             overcharge = options["overcharge"] 
    272             if overcharge : 
    273                 try : 
    274                     overcharge = float(overcharge.strip()) 
    275                 except (ValueError, AttributeError) : 
    276                     raise PyKotaCommandLineError, _("Invalid overcharge value %s") % options["overcharge"] 
    277  
    278             balance = options["balance"] 
     177                if limitby not in ('quota', 
     178                                   'balance', 
     179                                   'noquota', 
     180                                   'noprint', 
     181                                   'nochange') : 
     182                    raise PyKotaCommandLineError, _("Invalid limitby value %s") \ 
     183                        % options.limitby 
     184                if (limitby in ('nochange', 'noprint')) and options.groups : 
     185                    raise PyKotaCommandLineError, _("Invalid limitby value %s") \ 
     186                        % options.limitby 
     187 
     188            balance = options.balance 
    279189            if balance : 
    280190                balance = balance.strip() 
     
    282192                    balancevalue = float(balance) 
    283193                except ValueError : 
    284                     raise PyKotaCommandLineError, _("Invalid balance value %s") % options["balance"] 
     194                    raise PyKotaCommandLineError, _("Invalid balance value %s") \ 
     195                        % options.balance 
    285196            else : 
    286197                balancevalue = None 
    287198 
    288             if options["ingroups"] : 
    289                 usersgroups = self.storage.getMatchingGroups(options["ingroups"]) 
     199            if options.ingroups : 
     200                usersgroups = self.storage.getMatchingGroups(options.ingroups) 
    290201                if not usersgroups : 
    291                     raise PyKotaCommandLineError, _("There's no users group matching %s") % " ".join(options["ingroups"].split(',')) 
     202                    raise PyKotaCommandLineError, _("There's no users group matching %s") \ 
     203                        % " ".join(options.ingroups.split(',')) 
    292204            else : 
    293205                usersgroups = [] 
    294206 
    295             description = options["description"] 
    296             if description : 
    297                 description = description.strip() 
    298  
    299             comment = options["comment"] 
    300             if comment : 
    301                 comment = comment.strip() 
    302             email = options["email"] 
    303             if email : 
    304                 email = email.strip() 
    305             skipexisting = options["skipexisting"] 
    306             groups = options["groups"] 
    307             remove = options["remove"] 
     207            if options.description : 
     208                options.description = options.description.strip() 
     209 
     210            if options.comment : 
     211                options.comment = options.comment.strip() 
     212 
     213            if options.email : 
     214                options.email = options.email.strip() 
     215 
    308216            self.storage.beginTransaction() 
    309217            try : 
    310                 if options["add"] : 
     218                if isadd : 
    311219                    rejectunknown = self.config.getRejectUnknown() 
    312220                    percent.display("%s...\n" % _("Creation")) 
     
    314222                    for ename in names : 
    315223                        useremail = None 
    316                         if not groups : 
     224                        if not options.groups : 
    317225                            splitname = ename.split('/', 1)     # username/email 
    318226                            if len(splitname) == 1 : 
     
    322230                            reject = 0 
    323231                            if rejectunknown : 
    324                                 if groups : 
     232                                if options.groups : 
    325233                                    try : 
    326234                                        grp.getgrnam(ename) 
     
    336244                            if not reject : 
    337245                                entry = globals()["Storage%s" % suffix](self.storage, ename) 
    338                                 if groups : 
    339                                     self.modifyEntry(entry, groups, limitby, \ 
    340                                                      description) 
     246                                if options.groups : 
     247                                    self.modifyEntry(entry, 
     248                                                     options.groups, 
     249                                                     limitby, 
     250                                                     options.description) 
    341251                                else : 
    342                                     self.modifyEntry(entry, groups, limitby, \ 
    343                                                      description, overcharge,\ 
    344                                                      balance, balancevalue, \ 
    345                                                      comment, useremail or email) 
     252                                    self.modifyEntry(entry, 
     253                                                     options.groups, 
     254                                                     limitby, 
     255                                                     options.description, 
     256                                                     options.overcharge, 
     257                                                     balance, 
     258                                                     balancevalue, 
     259                                                     options.comment, 
     260                                                     useremail or options.email) 
    346261                                oldentry = getattr(self.storage, "add%s" % suffix)(entry) 
    347262                                if oldentry is not None : 
    348                                     if skipexisting : 
    349                                         self.logdebug(_("%s %s already exists, skipping.") % (_(suffix), ename)) 
     263                                    if options.skipexisting : 
     264                                        self.logdebug(_("%s %s already exists, skipping.") \ 
     265                                                          % (_(suffix), ename)) 
    350266                                    else : 
    351                                         self.logdebug(_("%s %s already exists, will be modified.") % (_(suffix), ename)) 
    352                                         if groups : 
    353                                             self.modifyEntry(oldentry, groups, \ 
    354                                                      limitby, description) 
     267                                        self.logdebug(_("%s %s already exists, will be modified.") \ 
     268                                                          % (_(suffix), ename)) 
     269                                        if options.groups : 
     270                                            self.modifyEntry(oldentry, 
     271                                                             options.groups, 
     272                                                             limitby, 
     273                                                             options.description) 
    355274                                        else : 
    356                                             self.modifyEntry(oldentry, groups, limitby, \ 
    357                                                      description, overcharge,\ 
    358                                                      balance, balancevalue, \ 
    359                                                      comment, useremail or email) 
     275                                            self.modifyEntry(oldentry, 
     276                                                             options.groups, 
     277                                                             limitby, 
     278                                                             options.description, 
     279                                                             options.overcharge, 
     280                                                             balance, 
     281                                                             balancevalue, 
     282                                                             options.comment, 
     283                                                             useremail or options.email) 
    360284                                        oldentry.save() 
    361                                         if not groups : 
    362                                             self.manageUsersGroups(usersgroups, oldentry, remove) 
    363                                 elif usersgroups and not groups : 
     285                                        if not options.groups : 
     286                                            self.manageUsersGroups(usersgroups, 
     287                                                                   oldentry, 
     288                                                                   options.remove) 
     289                                elif usersgroups and not options.groups : 
    364290                                    self.manageUsersGroups(usersgroups, \ 
    365291                                                           self.storage.getUser(ename), \ 
    366                                                            remove) 
     292                                                           options.remove) 
    367293                        else : 
    368294                            raise PyKotaCommandLineError, _("Invalid name %s") % ename 
     
    371297                    percent.display("\n%s...\n" % _("Modification")) 
    372298                    for entry in entries : 
    373                         if groups : 
    374                             self.modifyEntry(entry, groups, limitby, description) 
     299                        if options.groups : 
     300                            self.modifyEntry(entry, 
     301                                             options.groups, 
     302                                             limitby, 
     303                                             options.description) 
    375304                        else : 
    376                             self.modifyEntry(entry, groups, limitby, description, \ 
    377                                              overcharge, balance, balancevalue, \ 
    378                                              comment, email) 
    379                             self.manageUsersGroups(usersgroups, entry, remove) 
     305                            self.modifyEntry(entry, 
     306                                             options.groups, 
     307                                             limitby, 
     308                                             options.description, 
     309                                             options.overcharge, 
     310                                             balance, 
     311                                             balancevalue, 
     312                                             options.comment, 
     313                                             options.email) 
     314                            self.manageUsersGroups(usersgroups, 
     315                                                   entry, 
     316                                                   options.remove) 
    380317                        entry.save() 
    381318                        percent.oneMore() 
     
    386323                self.storage.commitTransaction() 
    387324 
    388         if not options["list"] : 
     325        if not islist : 
    389326            percent.done() 
    390327 
    391328if __name__ == "__main__" : 
    392     retcode = 0 
    393     try : 
    394         defaults = { \ 
    395                      "comment" : "", \ 
    396                    } 
    397         short_options = "hvaD:dgl:rso:i:b:C:Le:" 
    398         long_options = ["help", "version", "add", "description=", \ 
    399                         "delete", "groups", "list", "remove", \ 
    400                         "skipexisting", "overcharge=", "email=", \ 
    401                         "ingroups=", "limitby=", "balance=", "comment=", \ 
    402                        ] 
    403  
    404  
    405         # Initializes the command line tool 
    406         manager = PKUsers(doc=__doc__) 
    407         manager.deferredInit() 
    408  
    409         # parse and checks the command line 
    410         (options, args) = manager.parseCommandline(sys.argv[1:], short_options, long_options) 
    411  
    412         # sets long options 
    413         options["help"] = options["h"] or options["help"] 
    414         options["version"] = options["v"] or options["version"] 
    415         options["add"] = options["a"] or options["add"] 
    416         options["description"] = options["D"] or options["description"] 
    417         options["delete"] = options["d"] or options["delete"] 
    418         options["groups"] = options["g"] or options["groups"] 
    419         options["list"] = options["L"] or options["list"] 
    420         options["remove"] = options["r"] or options["remove"] 
    421         options["skipexisting"] = options["s"] or options["skipexisting"] 
    422         options["limitby"] = options["l"] or options["limitby"] 
    423         options["balance"] = options["b"] or options["balance"] 
    424         options["ingroups"] = options["i"] or options["ingroups"] 
    425         options["overcharge"] = options["o"] or options["overcharge"] 
    426         options["comment"] = options["C"] or options["comment"] or defaults["comment"] 
    427         options["email"] = options["e"] or options["email"] 
    428  
    429         if options["help"] : 
    430             manager.display_usage_and_quit() 
    431         elif options["version"] : 
    432             manager.display_version_and_quit() 
    433         elif (options["delete"] and (options["add"] or options["remove"] or options["description"] or options["email"])) \ 
    434            or (options["skipexisting"] and not options["add"]) \ 
    435            or (options["list"] and (options["add"] or options["delete"] or options["remove"] or options["description"] or options["email"])) \ 
    436            or (options["groups"] and (options["balance"] or options["ingroups"] or options["overcharge"])) : 
    437             raise PyKotaCommandLineError, _("incompatible options, see help.") 
    438         elif options["remove"] and not options["ingroups"] : 
    439             raise PyKotaCommandLineError, _("You have to pass user groups names on the command line") 
    440         elif (not args) and (options["add"] or options["delete"]) : 
    441             raise PyKotaCommandLineError, _("You have to pass user or group names on the command line") 
    442         else : 
    443             retcode = manager.main(args, options) 
    444     except KeyboardInterrupt : 
    445         logerr("\nInterrupted with Ctrl+C !\n") 
    446         retcode = -3 
    447     except PyKotaCommandLineError, msg : 
    448         logerr("%s : %s\n" % (sys.argv[0], msg)) 
    449         retcode = -2 
    450     except SystemExit : 
    451         pass 
    452     except : 
    453         try : 
    454             manager.crashed("pkusers failed") 
    455         except : 
    456             crashed("pkusers failed") 
    457         retcode = -1 
    458  
    459     try : 
    460         manager.storage.close() 
    461     except (TypeError, NameError, AttributeError) : 
    462         pass 
    463  
    464     sys.exit(retcode) 
     329    parser = PyKotaOptionParser(description=_("Manages PyKota users or users groups."), 
     330                                usage="pkusers [options] name1 name2 ... nameN") 
     331    parser.add_option("-a", "--add", 
     332                            action="store_const", 
     333                            const="add", 
     334                            dest="action", 
     335                            help=_("Add new, or modify existing, users or groups.")) 
     336    parser.add_option("-b", "--balance", 
     337                            dest="balance", 
     338                            help=_("Set an user's account balance. The value can also be increased or decreased when the value is prefixed with '+' or '-'. Users groups don't have a real account balance, instead the sum of their members' account balances is used.")) 
     339    parser.add_option("-C", "--comment", 
     340                            dest="comment", 
     341                            default="", 
     342                            help=_("Associate a textual comment with a change in an user's account balance. Only meaningful when --balance is also used.")) 
     343    parser.add_option("-d", "--delete", 
     344                            action="store_const", 
     345                            const="delete", 
     346                            dest="action", 
     347                            help=_("Delete the specified users or groups. Also purge the print quota entries and printing history matching the specified users or groups.")) 
     348    parser.add_option("-D", "--description", 
     349                            dest="description", 
     350                            help=_("Set a textual description for the specified users or groups.")) 
     351    parser.add_option("-e", "--email", 
     352                            dest="email", 
     353                            help=_("Set an user's email address. If this parameter begins with '@' then the username is prepended to this parameter to form a valid email address.")) 
     354    parser.add_option("-g", "--groups", 
     355                            action="store_true", 
     356                            dest="groups", 
     357                            help=_("Manage users groups instead of users.")) 
     358    parser.add_option("-i", "--ingroups", 
     359                            dest="ingroups", 
     360                            help=_("Put the specified users into the specified groups. When combined with the --remove option, users are removed from the specified groups instead.")) 
     361    parser.add_option("-l", "--limitby", 
     362                            dest="limitby", 
     363                            help=_("Set the limiting factor for the specified users or groups. Can be any of 'quota' (limit by number of pages per printer), 'balance' (limit by number of credits), 'noquota' (no limit but accounting done), 'nochange' (no limit and not accounting), or 'noprint' (printing is denied). The two latter ones are not supported for groups.")) 
     364    parser.add_option("-L", "--list", 
     365                            action="store_const", 
     366                            const="list", 
     367                            dest="action", 
     368                            help=_("Display detailed informations about the specified users or groups.")) 
     369    parser.add_option("-o", "--overcharge", 
     370                            type="float", 
     371                            dest="overcharge", 
     372                            help=_("Set the overcharging factor applied to the specified users when computing the cost of a print job. Any floating point value can be used, allowing you to express your creativity...")) 
     373    parser.add_option("-r", "--remove", 
     374                            action="store_true", 
     375                            dest="remove", 
     376                            help=_("When combined with the --ingroups option, remove users from the specified users groups.")) 
     377    parser.add_option("-s", "--skipexisting", 
     378                            action="store_true", 
     379                            dest="skipexisting", 
     380                            help=_("If --add is used, ensure that existing users or groups won't be modified.")) 
     381 
     382    parser.add_example("--add john paul george ringo/ringo@example.com", 
     383                       _("Would make users 'john', 'paul', 'george' and 'ringo' be known to PyKota. User 'ringo''s email address would be set to 'ringo@example.com'.")) 
     384    parser.add_example("--add --groups coders it", 
     385                       _("Would create two users groups named 'coders' and 'it'.")) 
     386    parser.add_example("--add --ingroups coders,it jerome", 
     387                       _("Would add user 'jerome' and put him into the 'coders' and 'it' groups. Both groups would have to be existing.")) 
     388    parser.add_example("--limitby balance --balance 10.0 john", 
     389                       _("Would give 10.0 credits to 'john' and make his printing be limited by his account balance.")) 
     390    parser.add_example('--balance +10.0 --comment "He paid with his blood." jerome', 
     391                       _("Would add 10.0 credits to 'jerome''s account and register a comment associated with his payment.")) 
     392    parser.add_example('--delete "jer*" "rach*"', 
     393                       _("Would delete all user accounts whose names begin with either 'jer' or 'rach'.")) 
     394    parser.add_example("--overcharge -1.50 theboss", 
     395                       _("Would make the boss earn money whenever he prints.")) 
     396    parser.add_example("--email @example.com", 
     397                       _("Would set the email address for each existing user to username@example.com")) 
     398    parser.add_example("--list", 
     399                       _("Would list all users.")) 
     400    run(parser, PKUsers) 
  • pykota/trunk/pykota/version.py

    r3413 r3426  
    2222"""This module defines some application level constants.""" 
    2323 
    24 __version__ = "1.27alpha5_unofficial" 
     24__version__ = "1.27alpha6_unofficial" 
    2525 
    2626__doc__ = "PyKota : a complete Printing Quota Solution for CUPS."