root / pykota / trunk / setup.py @ 1476

Revision 1476, 22.3 kB (checked in by jalet, 20 years ago)

Warning about changed accounter and requester directives

  • 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
5#
6# PyKota : Print Quotas for CUPS and LPRng
7#
8# (c) 2003-2004 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22#
23# $Id$
24#
25# $Log$
26# Revision 1.41  2004/05/13 14:17:32  jalet
27# Warning about changed accounter and requester directives
28#
29# Revision 1.40  2004/05/13 13:59:27  jalet
30# Code simplifications
31#
32# Revision 1.39  2004/04/08 17:07:41  jalet
33# pkpgcounter added
34#
35# Revision 1.38  2004/03/18 09:18:09  jalet
36# Installation now checks for old scripts
37#
38# Revision 1.37  2004/03/03 19:35:36  jalet
39# Spelling problem. Thanks to Jurandy Martins
40#
41# Revision 1.36  2004/02/25 15:10:38  jalet
42# Preliminary snmpprinterstatus command added.
43#
44# Revision 1.35  2004/02/12 22:43:58  jalet
45# Better integration in Debian and more LSB compliance, thanks to
46# Peter Hawkins.
47#
48# Revision 1.34  2004/02/07 13:45:51  jalet
49# Preliminary work on the pkhint command
50#
51# Revision 1.33  2004/02/04 11:16:59  jalet
52# pkprinters command line tool added.
53#
54# Revision 1.32  2004/01/18 20:52:50  jalet
55# Portuguese portuguese translation replaces brasilian portuguese one, which
56# moves in its own directory.
57# Installation script modified to reorganise installed documentation and include
58# the documentation on OpenOffice.org + ODBC
59#
60# Revision 1.31  2004/01/15 12:50:41  jalet
61# Installation scripts now tells where the documentation was installed.
62#
63# Revision 1.30  2004/01/12 15:45:03  jalet
64# Now installs documentation in /usr/share/doc/pykota too.
65#
66# Revision 1.29  2004/01/08 14:10:32  jalet
67# Copyright year changed.
68#
69# Revision 1.28  2003/12/27 16:49:25  uid67467
70# Should be ok now.
71#
72# Revision 1.28  2003/12/06 09:03:43  jalet
73# Added Perl script to retrieve printer's internal page counter via PJL,
74# contributed by Ren�und Jensen.
75#
76# Revision 1.27  2003/11/28 08:31:28  jalet
77# Shell script to wait for AppleTalk enabled printers being idle was added.
78#
79# Revision 1.26  2003/11/08 16:05:31  jalet
80# CUPS backend added for people to experiment.
81#
82# Revision 1.25  2003/10/08 07:01:19  jalet
83# Job history can be disabled.
84# Some typos in README.
85# More messages in setup script.
86#
87# Revision 1.24  2003/10/07 09:07:27  jalet
88# Character encoding added to please latest version of Python
89#
90# Revision 1.23  2003/07/29 20:55:17  jalet
91# 1.14 is out !
92#
93# Revision 1.22  2003/07/29 09:54:03  jalet
94# Added configurable LDAP mail attribute support
95#
96# Revision 1.21  2003/07/28 09:11:12  jalet
97# PyKota now tries to add its attributes intelligently in existing LDAP
98# directories.
99#
100# Revision 1.20  2003/07/23 16:51:32  jalet
101# waitprinter.sh is now included to prevent PyKota from asking the
102# printer's internal page counter while a job is still being printer.
103#
104# Revision 1.19  2003/07/16 21:53:07  jalet
105# Really big modifications wrt new configuration file's location and content.
106#
107# Revision 1.18  2003/07/03 09:44:00  jalet
108# Now includes the pykotme utility
109#
110# Revision 1.17  2003/06/30 12:46:15  jalet
111# Extracted reporting code.
112#
113# Revision 1.16  2003/06/06 20:49:15  jalet
114# Very latest schema. UNTESTED.
115#
116# Revision 1.15  2003/05/17 16:32:30  jalet
117# Also outputs the original import error message.
118#
119# Revision 1.14  2003/05/17 16:31:38  jalet
120# Dies gracefully if DistUtils is not present.
121#
122# Revision 1.13  2003/04/29 18:37:54  jalet
123# Pluggable accounting methods (actually doesn't support external scripts)
124#
125# Revision 1.12  2003/04/23 22:13:56  jalet
126# Preliminary support for LPRng added BUT STILL UNTESTED.
127#
128# Revision 1.11  2003/04/17 13:49:29  jalet
129# Typo
130#
131# Revision 1.10  2003/04/17 13:48:39  jalet
132# Better help
133#
134# Revision 1.9  2003/04/17 13:47:28  jalet
135# Help added during installation.
136#
137# Revision 1.8  2003/04/15 17:49:29  jalet
138# Installation script now checks the presence of Netatalk
139#
140# Revision 1.7  2003/04/03 20:03:37  jalet
141# Installation script now allows to install the sample configuration file.
142#
143# Revision 1.6  2003/03/29 13:45:26  jalet
144# GPL paragraphs were incorrectly (from memory) copied into the sources.
145# Two README files were added.
146# Upgrade script for PostgreSQL pre 1.01 schema was added.
147#
148# Revision 1.5  2003/03/29 13:08:28  jalet
149# Configuration is now expected to be found in /etc/pykota.conf instead of
150# in /etc/cups/pykota.conf
151# Installation script can move old config files to the new location if needed.
152# Better error handling if configuration file is absent.
153#
154# Revision 1.4  2003/03/29 09:47:00  jalet
155# More powerful installation script.
156#
157# Revision 1.3  2003/03/26 17:48:36  jalet
158# First shot at trying to detect the availability of the needed software
159# during the installation.
160#
161# Revision 1.2  2003/03/09 16:49:04  jalet
162# The installation script installs the man pages too now.
163#
164# Revision 1.1  2003/02/05 21:28:17  jalet
165# Initial import into CVS
166#
167#
168#
169
170import sys
171import glob
172import os
173import shutil
174try :
175    from distutils.core import setup
176except ImportError, msg :   
177    sys.stderr.write("%s\n" % msg)
178    sys.stderr.write("You need the DistUtils Python module.\nunder Debian, you may have to install the python-dev package.\nOf course, YMMV.\n")
179    sys.exit(-1)
180
181from distutils import sysconfig
182sys.path.insert(0, "pykota")
183from pykota.version import __version__, __doc__
184
185ACTION_CONTINUE = 0
186ACTION_ABORT = 1
187
188def checkOldModule(path) :
189    """Checks if an old PyKota module is still in the destination (in case of upgrade)."""
190    fname = os.path.join(sysconfig.get_python_lib(), "pykota", path)
191    for ext in ["py", "pyc", "pyo"] :
192        fullname = "%s.%s" % (fname, ext)
193        if os.path.isfile(fullname) :
194            sys.stderr.write("ERROR : old module %s still exists. Remove it and restart installation.\n" % fullname)
195            sys.stderr.write("INSTALLATION ABORTED !\n")
196            sys.exit(-1)
197   
198def checkOldScript(cmd) :
199    """Checks if an old shell script is still around in /usr/bin."""
200    return os.path.isfile(os.path.join("/usr/bin", cmd))
201
202def checkModule(module) :
203    """Checks if a Python module is available or not."""
204    try :
205        exec "import %s" % module
206    except ImportError :   
207        return 0
208    else :   
209        return 1
210       
211def checkCommand(command) :
212    """Checks if a command is available or not."""
213    input = os.popen("type %s 2>/dev/null" % command)
214    result = input.read().strip()
215    input.close()
216    return result
217   
218def checkWithPrompt(prompt, module=None, command=None, helper=None) :
219    """Tells the user what will be checked, and asks him what to do if something is absent."""
220    sys.stdout.write("Checking for %s availability : " % prompt)
221    sys.stdout.flush()
222    if command is not None :
223        result = checkCommand(command)
224    elif module is not None :   
225        result = checkModule(module)
226    if result :   
227        sys.stdout.write("OK\n")
228        return ACTION_CONTINUE
229    else :   
230        sys.stdout.write("NO.\n")
231        sys.stderr.write("ERROR : %s not available !\n" % prompt)
232        if helper is not None :
233            sys.stdout.write("%s\n" % helper)
234            sys.stdout.write("You may continue safely if you don't need this functionnality.\n")
235        answer = raw_input("%s is missing. Do you want to continue anyway (y/N) ? " % prompt)
236        if answer[0:1].upper() == 'Y' :
237            return ACTION_CONTINUE
238        else :
239            return ACTION_ABORT
240   
241if ("install" in sys.argv) and not ("help" in sys.argv) :
242    # checks if Python version is correct, we need >= 2.1
243    if not (sys.version > "2.1") :
244        sys.stderr.write("PyKota needs at least Python v2.1 !\nYour version seems to be older than that, please update.\nAborted !\n")
245        sys.exit(-1)
246       
247    # checks if a configuration file is present in the new location
248    if not os.path.isfile("/etc/pykota/pykota.conf") :
249        if not os.path.isdir("/etc/pykota") :
250            try :
251                os.mkdir("/etc/pykota")
252            except OSError, msg :   
253                sys.stderr.write("An error occured while creating the /etc/pykota directory.\n%s\n" % msg)
254                sys.exit(-1)
255               
256        if os.path.isfile("/etc/pykota.conf") :
257            # upgrade from pre-1.14 to 1.14 and above
258            sys.stdout.write("From version 1.14 on, PyKota expects to find its configuration\nfile in /etc/pykota/ instead of /etc/\n")
259            sys.stdout.write("It seems that you've got a configuration file in the old location,\nso it will not be used anymore,\nand there's no configuration file in the new location.\n")
260            answer = raw_input("Do you want to move /etc/pykota.conf to /etc/pykota/pykota.conf (y/N) ? ")
261            if answer[0:1].upper() == 'Y' :
262                try :
263                    os.rename("/etc/pykota.conf", "/etc/pykota/pykota.conf")
264                except OSError :   
265                    sys.stderr.write("ERROR : An error occured while moving /etc/pykota.conf to /etc/pykota/pykota.conf\nAborted !\n")
266                    sys.exit(-1)
267                else :   
268                    sys.stdout.write("Configuration file /etc/pykota.conf moved to /etc/pykota/pykota.conf.\n")
269            else :
270                sys.stderr.write("WARNING : Configuration file /etc/pykota.conf won't be used ! Move it to /etc/pykota/ instead.\n")
271                sys.stderr.write("PyKota installation will continue anyway,\nbut the software won't run until you put a proper configuration file in /etc/pykota/\n")
272            dummy = raw_input("Please press ENTER when you have read the message above. ")
273        else :
274            # first installation
275            if os.path.isfile("conf/pykota.conf.sample") :
276                answer = raw_input("Do you want to install\n\tconf/pykota.conf.sample as /etc/pykota/pykota.conf (y/N) ? ")
277                if answer[0:1].upper() == 'Y' :
278                    try :
279                        shutil.copy("conf/pykota.conf.sample", "/etc/pykota/pykota.conf")       
280                        shutil.copy("conf/pykotadmin.conf.sample", "/etc/pykota/pykotadmin.conf")       
281                    except IOError, msg :   
282                        sys.stderr.write("WARNING : Problem while installing sample configuration files in /etc/pykota/, please do it manually.\n%s\n" % msg)
283                    else :   
284                        sys.stdout.write("Configuration file /etc/pykota/pykota.conf and /etc/pykota/pykotadmin.conf installed.\nDon't forget to adapt these files to your needs.\n")
285                else :       
286                    sys.stderr.write("WARNING : PyKota won't run without a configuration file !\n")
287            else :       
288                # Problem ?
289                sys.stderr.write("WARNING : PyKota's sample configuration file cannot be found.\nWhat you have downloaded seems to be incomplete,\nor you are not in the pykota directory.\nPlease double check, and restart the installation procedure.\n")
290            dummy = raw_input("Please press ENTER when you have read the message above. ")
291    else :   
292        # already at 1.14 or above.
293        # Now check if old scripts are still in /usr/bin
294        for script in ["cupspykota", "pykota", "waitprinter.sh", "papwaitprinter.sh", "mailandpopup.sh", "pagecount.pl"] :
295            if checkOldScript(script) :
296                sys.stderr.write("WARNING : the %s script is still present in /usr/bin, but the new version will be installed in /usr/share/pykota, please remove the %s script from /usr/bin and double check that your configuration is correct.\n" % (script, script))
297                if script == "cupspykota" :
298                    sys.stderr.write("\nBe sure to also remove the old symbolic link from /usr/lib/cups/backend/cupspykota to /usr/bin/cupspykota. You'll have to recreate it once the installation has finished successfully.\n")
299                sys.stderr.write("\nINSTALLATION ABORTED !\nPlease correct the problem and restart installation.\n")
300                sys.exit(-1)
301               
302        # now checks if pre-1.19alpha8 code is still there       
303        for module in ["accounters/querying", "accounters/external", "requesters/snmp"] :
304            checkOldModule(module)
305       
306    # Second stage, we will fail if onfiguration is incorrect for security reasons
307    from pykota.config import PyKotaConfig,PyKotaConfigError
308    try :
309        conf = PyKotaConfig("/etc/pykota/")
310    except PyKotaConfigError, msg :   
311        sys.stedrr.write("%s\nINSTALLATION ABORTED !\nPlease restart installation.\n" % msg)
312        sys.exit(-1)
313    else :
314        hasadmin = conf.getGlobalOption("storageadmin", ignore=1)
315        hasadminpw = conf.getGlobalOption("storageadminpw", ignore=1)
316        hasuser = conf.getGlobalOption("storageuser", ignore=1)
317        if hasadmin or hasadminpw : 
318            sys.stderr.write("From version 1.14 on, PyKota expects that /etc/pykota/pykota.conf doesn't contain the Quota Storage Administrator's name and optional password.\n")
319            sys.stderr.write("Please put these in a [global] section in /etc/pykota/pykotadmin.conf\n")
320            sys.stderr.write("Then replace these values with 'storageuser' and 'storageuserpw' in /etc/pykota/pykota.conf\n")
321            sys.stderr.write("These two fields were re-introduced to allow any user to read to his own quota, without allowing them to modify it.\n")
322            sys.stderr.write("You can look at the conf/pykota.conf.sample and conf/pykotadmin.conf.sample files for examples.\n")
323            sys.stderr.write("YOU HAVE TO DO THESE MODIFICATIONS MANUALLY, AND RESTART THE INSTALLATION.\n")
324            sys.stderr.write("INSTALLATION ABORTED FOR SECURITY REASONS.\n")
325            sys.exit(-1)
326        if not hasuser :
327            sys.stderr.write("From version 1.14 on, PyKota expects that /etc/pykota/pykota.conf contains the Quota Storage Normal User's name and optional password.\n")
328            sys.stderr.write("Please put these in a [global] section in /etc/pykota/pykota.conf\n")
329            sys.stderr.write("These fields are respectively named 'storageuser' and 'storageuserpw'.\n")
330            sys.stderr.write("These two fields were re-introduced to allow any user to read to his own quota, without allowing them to modify it.\n")
331            sys.stderr.write("You can look at the conf/pykota.conf.sample and conf/pykotadmin.conf.sample files for examples.\n")
332            sys.stderr.write("YOU HAVE TO DO THESE MODIFICATIONS MANUALLY, AND RESTART THE INSTALLATION.\n")
333            sys.stderr.write("INSTALLATION ABORTED FOR SECURITY REASONS.\n")
334            sys.exit(-1)
335           
336        sb = conf.getStorageBackend()
337        if (sb.get("storageadmin") is None) or (sb.get("storageuser") is None) :
338            sys.stderr.write("From version 1.14 on, PyKota expects that /etc/pykota/pykota.conf contains the Quota Storage Normal User's name and optional password which gives READONLY access to the Print Quota DataBase,")
339            sys.stderr.write("and that /etc/pykota/pykotadmin.conf contains the Quota Storage Administrator's name and optional password which gives READ/WRITE access to the Print Quota DataBase.\n")
340            sys.stderr.write("Your configuration doesn't seem to be OK, please modify your configuration files in /etc/pykota/\n")
341            sys.stderr.write("AND RESTART THE INSTALLATION.\n")
342            sys.stderr.write("INSTALLATION ABORTED FOR SECURITY REASONS.\n")
343            sys.exit(-1)
344           
345        # warns for new LDAP fields   
346        if sb.get("storagebackend") == "ldapstorage" :   
347            usermail = conf.getGlobalOption("usermail", ignore=1)
348            newuser = conf.getGlobalOption("newuser", ignore=1)
349            newgroup = conf.getGlobalOption("newgroup", ignore=1)
350            if not (usermail and newuser and newgroup) :
351                sys.stderr.write("From version 1.14 on, PyKota LDAP Support needs three additional configuration fields.\n")
352                sys.stderr.write("Please put the 'usermail', 'newuser' and 'newgroup' configuration fields in a\n[global] section in /etc/pykota/pykota.conf\n")
353                sys.stderr.write("You can look at the conf/pykota.conf.sample file for examples.\n")
354                sys.stderr.write("YOU HAVE TO DO THESE MODIFICATIONS MANUALLY, AND RESTART THE INSTALLATION.\n")
355                sys.stderr.write("INSTALLATION ABORTED BECAUSE CONFIGURATION INCOMPLETE.\n")
356                sys.exit(-1)
357               
358        # Say something about caching mechanism and disabling job history
359        sys.stdout.write("You can now activate the database caching mechanism\nwhich is disabled by default.\nIt is especially recommended with the LDAP backend.\n")
360        sys.stdout.write("You can now disable the preservation of the complete\njob history which is enabled by default.\nIt is probably more useful with the LDAP backend.\n")
361        sys.stdout.write("PLEASE LOOK AT THE SAMPLE CONFIGURATION FILE conf/pykota.conf.sample\n")
362        sys.stdout.write("TO LEARN HOW TO DO\n")
363        dummy = raw_input("Please press ENTER when you have read the message above. ")
364        sys.stdout.write("\n")
365           
366    # change files permissions   
367    os.chmod("/etc/pykota/pykota.conf", 0644)
368    os.chmod("/etc/pykota/pykotadmin.conf", 0640)
369   
370    # WARNING MESSAGE   
371    sys.stdout.write("WARNING : IF YOU ARE UPGRADING FROM A PRE-1.19alpha7 TO 1.19alpha7 OR ABOVE\n")
372    sys.stdout.write("AND USE THE POSTGRESQL BACKEND, THEN YOU HAVE TO MODIFY YOUR\n")
373    sys.stdout.write("DATABASE SCHEMA USING initscripts/postgresql/upgrade-to-1.19.sql\n")
374    sys.stdout.write("PLEASE READ DOCUMENTATION IN initscripts/postgresql/ TO LEARN HOW TO DO.\n")
375    sys.stdout.write("YOU CAN DO THAT AFTER THE INSTALLATION IS FINISHED, OR PRESS CTRL+C NOW.\n")
376    sys.stdout.write("\n\nYOU DON'T HAVE ANYTHING SPECIAL TO DO IF THIS IS YOUR FIRST INSTALLATION\nOR IF YOU ARE ALREADY RUNNING VERSION 1.19alpha7 OR ABOVE.\n\n")
377    dummy = raw_input("Please press ENTER when you have read the message above. ")
378   
379    sys.stdout.write("\n\nWARNING : IF YOU ARE UPGRADING FROM A PRE-1.19alpha8 TO 1.19alpha8 OR ABOVE\n")
380    sys.stdout.write("YOU **MUST** MODIFY YOUR /etc/pykota/pykota.conf FILE BECAUSE accounter\n")
381    sys.stdout.write("AND requester DIRECTIVES SUPPORTED VALUES HAVE CHANGED.\n\n")
382    sys.stdout.write("YOU CAN DO THAT AFTER THE INSTALLATION IS FINISHED, OR PRESS CTRL+C NOW.\n")
383    sys.stdout.write("\n\nYOU DON'T HAVE ANYTHING SPECIAL TO DO IF THIS IS YOUR FIRST INSTALLATION\nOR IF YOU ARE ALREADY RUNNING VERSION 1.19alpha8 OR ABOVE.\n\n")
384    dummy = raw_input("Please press ENTER when you have read the message above. ")
385   
386    # checks if some needed Python modules are there or not.
387    modulestocheck = [ ("PygreSQL", "pg", "PygreSQL is mandatory if you want to use PostgreSQL as the quota storage backend."),                                           
388                       ("mxDateTime", "mx.DateTime", "eGenix' mxDateTime is mandatory for PyKota to work."), 
389                       ("Python-LDAP", "ldap", "Python-LDAP is mandatory if you plan to use an LDAP\ndirectory as the quota storage backend.")
390                     ]
391    commandstocheck = [("SNMP Tools", "snmpget", "SNMP Tools are needed if you want to use SNMP enabled printers."), ("Netatalk", "pap", "Netatalk is needed if you want to use AppleTalk enabled printers.")]
392    for (name, module, helper) in modulestocheck :
393        action = checkWithPrompt(name, module=module, helper=helper)
394        if action == ACTION_ABORT :
395            sys.stderr.write("Aborted !\n")
396            sys.exit(-1)
397           
398    # checks if some software are there or not.
399    for (name, command, helper) in commandstocheck :
400        action = checkWithPrompt(name, command=command, helper=helper)
401        if action == ACTION_ABORT :
402            sys.stderr.write("Aborted !\n")
403            sys.exit(-1)
404           
405data_files = []
406mofiles = glob.glob(os.sep.join(["po", "*", "*.mo"]))
407for mofile in mofiles :
408    lang = mofile.split(os.sep)[1]
409    directory = os.sep.join(["share", "locale", lang, "LC_MESSAGES"])
410    data_files.append((directory, [ mofile ]))
411   
412docdir = "/usr/share/doc/pykota"   
413docfiles = ["README", "FAQ", "SECURITY", "COPYING", "LICENSE", "CREDITS", "TODO", "NEWS"]
414data_files.append((docdir, docfiles))
415
416docfiles = glob.glob(os.sep.join(["docs", "*.pdf"]))
417data_files.append((docdir, docfiles))
418
419docfiles = glob.glob(os.sep.join(["docs", "spanish", "*.pdf"]))
420docfiles += glob.glob(os.sep.join(["docs", "spanish", "*.sxw"]))
421data_files.append((os.path.join(docdir, "spanish"), docfiles))
422
423docfiles = glob.glob(os.sep.join(["docs", "pykota", "*.html"]))
424data_files.append((os.path.join(docdir, "html"), docfiles))
425
426docfiles = glob.glob(os.sep.join(["openoffice", "*.sxw"]))
427docfiles += glob.glob(os.sep.join(["openoffice", "*.png"]))
428docfiles += glob.glob(os.sep.join(["openoffice", "README"]))
429data_files.append((os.path.join(docdir, "openoffice"), docfiles))
430
431directory = os.sep.join(["share", "man", "man1"])
432manpages = glob.glob(os.sep.join(["man", "*.1"]))   
433data_files.append((directory, manpages))
434
435directory = os.sep.join(["share", "pykota"])
436data_files.append((directory, ["bin/cupspykota", "bin/pykota", "bin/waitprinter.sh", "bin/papwaitprinter.sh", "bin/mailandpopup.sh", "contributed/pagecount.pl", "untested/pjl/pagecount.pjl", "untested/pjl/status.pjl", "untested/netatalk/netatalk.sh", "untested/netatalk/pagecount.ps"]))
437
438setup(name = "pykota", version = __version__,
439      license = "GNU GPL",
440      description = __doc__,
441      author = "Jerome Alet",
442      author_email = "alet@librelogiciel.com",
443      url = "http://www.librelogiciel.com/software/",
444      packages = [ "pykota", "pykota.storages", "pykota.requesters", "pykota.loggers", "pykota.accounters", "pykota.reporters" ],
445      scripts = [ "bin/pkpgcounter", "bin/snmpprinterstatus", "bin/edpykota", "bin/repykota", "bin/warnpykota", "bin/pykotme", "bin/pkprinters", "bin/pkhint" ],
446      data_files = data_files)
447
448if ("install" in sys.argv) and not ("help" in sys.argv) :
449    sys.stdout.write("\n\nYou can give a look at PyKota's documentation in:\n%s\n\n" % docdir)
Note: See TracBrowser for help on using the browser.