root / pykota / trunk / bin / pykotme @ 3549

Revision 3549, 6.1 kB (checked in by jerome, 14 years ago)

Removed support for the MaxJobSize? attribute for users group print quota
entries : I couldn't see a real use for this at the moment, and it would
complexify the code. This support might reappear later however. Added full
support for the MaxJobSize? attribute for user print quota entries,
editable with edpykota's new --maxjobsize command line switch. Changed
the internal handling of the MaxJobSize? attribute for printers :
internally 0 used to mean unlimited, it now allows one to forbid
printing onto a particular printer. The database upgrade script (only
for PostgreSQL) takes care of this.
IMPORTANT : the database schema changes. A database upgrade script is
provided for PostgreSQL only. The LDAP schema doesn't change to not
break any existing LDAP directory, so the pykotaMaxJobSize attribute is
still allowed on group print quota entries, but never used.
Seems to work as expected, for a change :-)
Fixes #15.

  • 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: utf-8 -*-
3#
4# PyKota : Print Quotas for CUPS
5#
6# (c) 2003-2009 Jerome Alet <alet@librelogiciel.com>
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19#
20# $Id$
21#
22#
23
24"""A print quote generator for PyKota"""
25
26import sys
27import os
28import pwd
29
30import pykota.appinit
31from pykota.utils import run
32from pykota.commandline import PyKotaOptionParser
33from pykota.errors import PyKotaCommandLineError
34from pykota.tool import PyKotaTool
35from pykota.accounter import openAccounter
36
37class PyKotMe(PyKotaTool) :
38    """A class for pykotme."""
39    def main(self, files, options) :
40        """Gives print quotes."""
41        if (not sys.stdin.isatty()) and ("-" not in files) :
42            # TODO : create a named temporary file for standard input
43            # TODO : because if there are several printers on the command
44            # TODO : line and they have different preaccounter directives,
45            # TODO : the standard input will already be consumed when looping
46            # TODO : over the second printer below.
47            files.append("-")
48
49        printers = self.storage.getMatchingPrinters(options.printer)
50        if not printers :
51            raise PyKotaCommandLineError, _("There's no printer matching %s") % options.printer
52
53        username = pwd.getpwuid(os.getuid())[0]
54        if options.user :
55            if not self.config.isAdmin :
56                self.printInfo(_("The --user command line option will be ignored because you are not a PyKota Administrator."), "warn")
57            else :
58                username = options.user
59
60        user = self.storage.getUser(username)
61        if not user.Exists :
62            self.printInfo(_("There's no user matching '%(username)s'.") \
63                                              % locals(),
64                           "error")
65        else :
66            if user.LimitBy and (user.LimitBy.lower() == "balance"):
67                self.display("%s\n" % (_("Your account balance : %.2f") % (user.AccountBalance or 0.0)))
68
69            sizeprinted = False
70            done = {}
71            for printer in printers :
72                # Now fake some values. TODO : improve API to not need this anymore
73                printername = printer.Name
74                self.PrinterName = printer.Name
75                self.JobSizeBytes = 1
76                self.preaccounter = openAccounter(self, ispreaccounter=1)
77                key = self.preaccounter.name + self.preaccounter.arguments
78                if not done.has_key(key) :
79                    totalsize = 0
80                    inkusage = []
81                    for filename in files :
82                        self.DataFile = filename
83                        self.preaccounter.beginJob(None)
84                        self.preaccounter.endJob(None)
85                        totalsize += self.preaccounter.getJobSize(None)
86                        inkusage.extend(self.preaccounter.inkUsage)
87                    done[key] = (totalsize, inkusage)
88                (totalsize, inkusage) = done[key]
89                if not sizeprinted :
90                    self.display("%s\n" % (_("Job size : %i pages") % totalsize))
91                    sizeprinted = True
92                userpquota = self.storage.getUserPQuota(user, printer)
93                if userpquota.Exists :
94                    if (printer.MaxJobSize and (totalsize > printer.MaxJobSize)) \
95                            or (userpquota.MaxJobSize and (totalsize > userpquota.MaxJobSize)) :
96                        self.display("%s\n" % (_("User %(username)s is not allowed to print so many pages on printer %(printername)s at this time.") % locals()))
97                    else :
98                        cost = userpquota.computeJobPrice(totalsize, inkusage)
99                        msg = _("Cost on printer %s : %.2f") % (printer.Name, cost)
100                        if printer.PassThrough :
101                            msg = "%s (%s)" % (msg, _("won't be charged, printer is in passthrough mode"))
102                        elif user.LimitBy == "nochange" :
103                            msg = "%s (%s)" % (msg, _("won't be charged, account is immutable"))
104                        self.display("%s\n" % msg)
105            if user.LimitBy == "noprint" :
106                self.display("%s\n" % (_("User %(username)s is forbidden to print at this time.") % locals()))
107
108if __name__ == "__main__" :
109    parser = PyKotaOptionParser(description=_("Generates print quotes for end users."),
110                                usage="pykotme [options] [files]")
111    parser.add_option("-P", "--printer",
112                            dest="printer",
113                            default="*",
114                            help=_("Acts on this printer only. You can specify several printer names by separating them with commas. The default value is '%default', which means all printers."))
115    parser.add_option("-u", "--user",
116                            dest="user",
117                            help=_("Acts on this user only. Only one username can be specified this way. The default value is the name of the user who launched this command. This option is ignored when the command is not launched by a PyKota Administrator."))
118
119    parser.add_example("--printer apple file1.ps <file2.pclxl",
120                       _("This would show the number of pages needed to print these two files, as well as the cost of printing them to the 'apple' printer for the user who launched this command."))
121    parser.add_example("--user john",
122                       _("This would show the number of pages needed to print the content of the standard input, and the cost of printing this on all printers for user 'john'."))
123    run(parser, PyKotMe)
Note: See TracBrowser for help on using the browser.