source: pyutilib.virtualenv/trunk/pyutilib/virtualenv/header.py @ 2362

Revision 2362, 51.4 KB checked in by wehart, 3 years ago (diff)

Adding the ability to define config files that reference other config files.

The --without-externals flag ignores the external links.

Line 
1#  _________________________________________________________________________
2#
3#  PyUtilib: A Python utility library.
4#  Copyright (c) 2008 Sandia Corporation.
5#  This software is distributed under the BSD License.
6#  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
7#  the U.S. Government retains certain rights in this software.
8#  _________________________________________________________________________
9#
10#
11# This script was created with the virtualenv_install script.
12#
13
14import commands
15import re
16import urllib2
17import zipfile
18import shutil
19import string
20import textwrap
21import sys
22import glob
23import errno
24import stat
25
26using_subversion = True
27
28#
29# Working around error with PYTHONHOME
30#
31if 'PYTHONHOME' in os.environ:
32    del os.environ['PYTHONHOME']
33    print "WARNING: ignoring the value of the PYTHONHOME environment variable!  This value can corrupt the virtual python installation."
34
35print "\nNOTE: this Python executable used to create virtual environment:\n\t%s\n" % sys.executable
36#
37# The following taken from PyUtilib
38#
39if (sys.platform[0:3] == "win"): #pragma:nocover
40    executable_extension=".exe"
41else:                            #pragma:nocover
42    executable_extension=""
43
44
45def search_file(filename, search_path=None, implicitExt=executable_extension, executable=False,         isfile=True):
46    if search_path is None:
47        #
48        # Use the PATH environment if it is defined and not empty
49        #
50        if "PATH" in os.environ and os.environ["PATH"] != "":
51            search_path = string.split(os.environ["PATH"], os.pathsep)
52        else:
53            search_path = os.defpath.split(os.pathsep)
54    for path in search_path:
55        if os.path.exists(os.path.join(path, filename)) and \
56           (not isfile or os.path.isfile(os.path.join(path, filename))):
57            if not executable or os.access(os.path.join(path,filename),os.X_OK):
58                return os.path.abspath(os.path.join(path, filename))
59        if os.path.exists(os.path.join(path, filename+implicitExt)) and \
60           (not isfile or os.path.isfile(os.path.join(path, filename+implicitExt))):
61            if not executable or os.access(os.path.join(path,filename+implicitExt),os.X_OK):
62                return os.path.abspath(os.path.join(path, filename+implicitExt))
63    return None
64
65#
66# PyUtilib Ends
67#
68
69
70#
71# The following taken from pkg_resources
72#
73component_re = re.compile(r'(\d+ | [a-z]+ | \.| -)', re.VERBOSE)
74replace = {'pre':'c', 'preview':'c','-':'final-','rc':'c','dev':'@'}.get
75
76def _parse_version_parts(s):
77    for part in component_re.split(s):
78        part = replace(part,part)
79        if not part or part=='.':
80            continue
81        if part[:1] in '0123456789':
82            yield part.zfill(8)    # pad for numeric comparison
83        else:
84            yield '*'+part
85
86    yield '*final'  # ensure that alpha/beta/candidate are before final
87
88def parse_version(s):
89    parts = []
90    for part in _parse_version_parts(s.lower()):
91        if part.startswith('*'):
92            if part<'*final':   # remove '-' before a prerelease tag
93                while parts and parts[-1]=='*final-': parts.pop()
94            # remove trailing zeros from each series of numeric parts
95            while parts and parts[-1]=='00000000':
96                parts.pop()
97        parts.append(part)
98    return tuple(parts)
99#
100# pkg_resources Ends
101#
102
103#
104# Use pkg_resources to guess version.
105# This allows for parsing version with the syntax:
106#   9.3.2
107#   8.28.rc1
108#
109def guess_release(svndir):
110    if using_subversion:
111        output = commands.getoutput('svn ls '+svndir)
112        if output=="":
113            return None
114        #print output
115        versions = []
116# This allows for parsing version with the syntax:
117#   9.3.2
118#   8.28.rc1
119#
120def guess_release(svndir):
121    if using_subversion:
122        output = commands.getoutput('svn ls '+svndir)
123        if output=="":
124            return None
125        #print output
126        versions = []
127        for link in re.split('/',output.strip()):
128            tmp = link.strip()
129            if tmp != '':
130                versions.append( tmp )
131        #print versions
132    else:
133        if sys.version_info[:2] <= (2,5):
134            output = urllib2.urlopen(svndir).read()
135        else:
136            output = urllib2.urlopen(svndir, timeout=30).read()
137        if output=="":
138            return None
139        links = re.findall('\<li>\<a href[^>]+>[^\<]+\</a>',output)
140        versions = []
141        for link in links:
142            versions.append( re.split('>', link[:-5])[-1] )
143    latest = None
144    latest_str = None
145    for version in versions:
146        if version is '.':
147            continue
148        v = parse_version(version)
149        if latest is None or latest < v:
150            latest = v
151            latest_str = version
152    if latest_str is None:
153        return None
154    if not latest_str[0] in '0123456789':
155        return svndir
156    return svndir+"/"+latest_str
157
158
159
160def zip_file(filename,fdlist):
161    zf = zipfile.ZipFile(filename, 'w')
162    for file in fdlist:
163        if os.path.isdir(file):
164            for root, dirs, files in os.walk(file):
165                if root.startswith(file+os.sep+'lib') or root.startswith(file+os.sep+'bin'):
166                    continue
167                for fname in files:
168                    if fname.endswith('pyc') or fname.endswith('pyo') or fname.endswith('zip'):
169                        continue
170                    if fname.endswith('exe'):
171                        zf.external_attr = (0777 << 16L) | (010 << 28L)
172                    else:
173                        zf.external_attr = (0660 << 16L) | (010 << 28L)
174                    zf.write(join(root,fname))
175        else:
176            zf.write(file)
177    zf.close()
178
179
180def unzip_file(filename, dir=None):
181    fname = os.path.abspath(filename)
182    zf = zipfile.ZipFile(fname, 'r')
183    if dir is None:
184        dir = os.getcwd()
185    for file in zf.infolist():
186        name = file.filename
187        if name.endswith('/') or name.endswith('\\'):
188            outfile = os.path.join(dir, name)
189            if not os.path.exists(outfile):
190                os.makedirs(outfile)
191        else:
192            outfile = os.path.join(dir, name)
193            parent = os.path.dirname(outfile)
194            if not os.path.exists(parent):
195                os.makedirs(parent)
196            OUTPUT = open(outfile, 'wb')
197            OUTPUT.write(zf.read(name))
198            OUTPUT.close()
199    zf.close()
200
201
202
203class Repository(object):
204
205    svn_get='checkout'
206    easy_install_path = ["easy_install"]
207    easy_install_flag = '-q'
208    pip_path = ["pip"]
209    python = "python"
210    svn = "svn"
211    dev = []
212
213    def __init__(self, name, root=None, trunk=None, stable=None, release=None, tag=None, pyname=None, pypi=None, dev=False, username=None, install=True, rev=None, local=None, platform=None):
214        class _TEMP_(object): pass
215        self.config = _TEMP_()
216        self.config.name=name
217        self.config.root=root
218        self.config.trunk=trunk
219        self.config.stable=stable
220        self.config.release=release
221        self.config.tag=tag
222        self.config.pyname=pyname
223        self.config.pypi=pypi
224        self.config.local=local
225        self.config.platform=platform
226        if dev == 'True' or dev is True:
227            self.config.dev=True
228        else:
229            self.config.dev=False
230        self.config.username=username
231        if install == 'False' or install is False:
232            self.config.install=False
233        else:
234            self.config.install=True
235        self.config.rev=rev
236        self.initialize(self.config)
237
238    def initialize(self, config):
239        self.name = config.name
240        self.root = config.root
241        self.trunk = None
242        self.trunk_root = None
243        self.stable = None
244        self.stable_root = None
245        self.release = None
246        self.tag = None
247        self.release_root = None
248        #
249        self.pypi = config.pypi
250        self.local = config.local
251        self.platform = config.platform
252        if config.platform is None:
253            self.platform_re = None
254        else:
255            self.platform_re = re.compile(config.platform)
256        if not config.pypi is None:
257            self.pyname=config.pypi
258        else:
259            self.pyname=config.pyname
260        self.dev = config.dev
261        if config.dev:
262            Repository.dev.append(config.name)
263        self.pkgdir = None
264        self.pkgroot = None
265        if config.username is None or '$' in config.username:
266            self.svn_username = []
267        else:
268            self.svn_username = ['--username', config.username]
269        if config.rev is None:
270            self.rev=''
271            self.revarg=[]
272        else:
273            self.rev='@'+config.rev
274            self.revarg=['-r',config.rev]
275        self.install = config.install
276
277    def guess_versions(self, offline=False):
278        if not self.config.root is None:
279            if not offline:
280                if using_subversion:
281                    rootdir_output = commands.getoutput('svn ls ' + self.config.root)
282                else:
283                    if sys.version_info[:2] <= (2,5):
284                        rootdir_output = urllib2.urlopen(self.config.root).read()
285                    else:
286                        rootdir_output = urllib2.urlopen(self.config.root, timeout=30).read()
287            self.trunk = self.config.root+'/trunk'
288            self.trunk_root = self.trunk
289            try:
290                if offline or not 'stable' in rootdir_output:
291                    raise IOError
292                self.stable = guess_release(self.config.root+'/stable')
293                self.stable_root = self.stable
294            except (urllib2.HTTPError,IOError):
295                self.stable = None
296                self.stable_root = None
297            try:
298                if offline or not 'releases' in rootdir_output:
299                    raise IOError
300                self.release = guess_release(self.config.root+'/releases')
301                self.tag = None
302                self.release_root = self.release
303            except (urllib2.HTTPError,IOError):
304                try:
305                    if offline or not 'tags' in rootdir_output:
306                        raise IOError
307                    self.release = guess_release(self.config.root+'/tags')
308                    self.tag = self.release
309                    self.release_root = self.release
310                except (urllib2.HTTPError,IOError):
311                    self.release = None
312                    self.release_root = None
313        if not self.config.trunk is None:
314            if self.trunk is None:
315                self.trunk = self.config.trunk
316            else:
317                self.trunk += self.config.trunk
318        if not self.config.stable is None:
319            if self.stable is None:
320                self.stable = self.config.stable
321            else:
322                self.stable += self.config.stable
323        if not self.config.release is None:
324            if self.release is None:
325                self.release = self.config.release
326            else:
327                self.release += self.config.release
328        if not self.config.tag is None:
329            if self.release is None:
330                self.release = self.config.tag
331            else:
332                self.release += self.config.tag
333
334
335    def write_config(self, OUTPUT):
336        config = self.config
337        print >>OUTPUT, '[%s]' % config.name
338        if not config.root is None:
339            print >>OUTPUT, 'root=%s' % config.root
340        if not config.trunk is None:
341            print >>OUTPUT, 'trunk=%s' % config.trunk
342        if not config.stable is None:
343            print >>OUTPUT, 'stable=%s' % config.stable
344        if not config.tag is None:
345            print >>OUTPUT, 'tag=%s' % config.tag
346        elif not config.release is None:
347            print >>OUTPUT, 'release=%s' % config.release
348        if not config.local is None:
349            print >>OUTPUT, 'local=%s' % config.local
350        if not config.pypi is None:
351            print >>OUTPUT, 'pypi=%s' % config.pypi
352        elif not config.pyname is None:
353            print >>OUTPUT, 'pypi=%s' % config.pyname
354        print >>OUTPUT, 'dev=%s' % str(config.dev)
355        print >>OUTPUT, 'install=%s' % str(config.install)
356        if not config.rev is None:
357            print >>OUTPUT, 'rev=%s' % str(config.rev)
358        if not config.username is None:
359            print >>OUTPUT, 'username=%s' % str(config.username)
360        if not config.platform is None:
361            print >>OUTPUT, 'platform=%s' % config.platform
362
363
364    def find_pkgroot(self, trunk=False, stable=False, release=False):
365        if trunk:
366            if self.trunk is None:
367                if not self.stable is None:
368                    self.find_pkgroot(stable=True)
369                elif self.pypi is None and self.local is None:
370                    self.find_pkgroot(release=True)
371                else:
372                    # use easy_install
373                    self.pkgdir = None
374                    self.pkgroot = None
375                    return
376            else:
377                self.pkgdir = self.trunk
378                self.pkgroot = self.trunk_root
379                return
380
381        elif stable:
382            if self.stable is None:
383                if not self.release is None:
384                    self.find_pkgroot(release=True)
385                elif self.pypi is None and self.local is None:
386                    self.find_pkgroot(trunk=True)
387                else:
388                    # use easy_install
389                    self.pkgdir = None
390                    self.pkgroot = None
391                    return
392            else:
393                self.pkgdir = self.stable
394                self.pkgroot = self.stable_root
395                return
396
397        elif release:
398            if self.release is None:
399                if not self.stable is None:
400                    self.find_pkgroot(stable=True)
401                elif self.pypi is None and self.local is None:
402                    self.find_pkgroot(trunk=True)
403                else:
404                    # use easy_install
405                    self.pkgdir = None
406                    self.pkgroot = None
407                    return
408            else:
409                self.pkgdir = self.release
410                self.pkgroot = self.release_root
411
412        else:
413            raise IOError, "Must have one of trunk, stable or release specified"
414
415
416    def install_trunk(self, dir=None, install=True, preinstall=False, offline=False):
417        self.find_pkgroot(trunk=True)
418        self.perform_install(dir=dir, install=install, preinstall=preinstall, offline=offline)
419
420    def install_stable(self, dir=None, install=True, preinstall=False, offline=False):
421        self.find_pkgroot(stable=True)
422        self.perform_install(dir=dir, install=install, preinstall=preinstall, offline=offline)
423
424    def install_release(self, dir=None, install=True, preinstall=False, offline=False):
425        self.find_pkgroot(release=True)
426        self.perform_install(dir=dir, install=install, preinstall=preinstall, offline=offline)
427
428    def perform_install(self, dir=None, install=True, preinstall=False, offline=False):
429        if not self.platform_re is None and not self.platform_re.match(sys.platform):
430            return
431        if self.pkgdir is None and self.local is None:
432            self.easy_install(install, preinstall, dir, offline)
433            return
434        if self.local:
435            install = True
436        print "-----------------------------------------------------------------"
437        print "  Installing branch"
438        print "  Checking out source for package",self.name
439        if self.local:
440            print "     Package dir: "+self.local
441        else:
442            print "     Subversion dir: "+self.pkgdir
443        if os.path.exists(dir):
444            print "     No checkout required"
445            print "-----------------------------------------------------------------"
446        elif not using_subversion:
447            print ""
448            print "Error: Cannot checkout software %s with subversion." % self.name
449            print "A problem was detected executing subversion commands."
450            sys.exit(1)
451        else:
452            print "-----------------------------------------------------------------"
453            try:
454                self.run([self.svn]+self.svn_username+[Repository.svn_get,'-q',self.pkgdir+self.rev, dir])
455            except OSError, err:
456                print ""
457                print "Error checkout software %s with subversion at %s" % (self.name,self.pkgdir+self.rev)
458                print str(err)
459                sys.exit(1)
460        if install:
461            try:
462                if self.dev:
463                    if offline:
464                        self.run([self.python, 'setup.py', 'develop', '--no-deps'], dir=dir)
465                    else:
466                        self.run([self.python, 'setup.py', 'develop'], dir=dir)
467                else:
468                    self.run([self.python, 'setup.py', 'install'], dir=dir)
469            except OSError, err:
470                print ""
471                print "Error installing software %s from source using the setup.py file." % self.name
472                print "This is probably due to a syntax or configuration error in this package."
473                print str(err)
474                sys.exit(1)
475
476    def update_trunk(self, dir=None):
477        self.find_pkgroot(trunk=True)
478        self.perform_update(dir=dir)
479
480    def update_stable(self, dir=None):
481        self.find_pkgroot(stable=True)
482        self.perform_update(dir=dir)
483
484    def update_release(self, dir=None):
485        self.find_pkgroot(release=True)
486        self.perform_update(dir=dir)
487
488    def perform_update(self, dir=None):
489        if self.pkgdir is None:
490            self.easy_upgrade()
491            return
492        print "-----------------------------------------------------------------"
493        print "  Updating branch"
494        print "  Updating source for package",self.name
495        print "     Subversion dir: "+self.pkgdir
496        print "     Source dir:     "+dir
497        print "-----------------------------------------------------------------"
498        self.run([self.svn,'update','-q']+self.revarg+[dir])
499        if self.dev:
500            self.run([self.python, 'setup.py', 'develop'], dir=dir)
501        else:
502            self.run([self.python, 'setup.py', 'install'], dir=dir)
503
504    def easy_install(self, install, preinstall, dir, offline):
505        #return self.pip_install(install, preinstall, dir, offline)
506        try:
507            if install:
508                if offline:
509                    self.run([self.python, 'setup.py', 'install'], dir=dir)
510                else:
511                    self.run(self.easy_install_path + [Repository.easy_install_flag, self.pypi], dir=os.path.dirname(dir))
512            elif preinstall:
513                if not os.path.exists(dir):
514                    self.run(self.easy_install_path + [Repository.easy_install_flag, '--exclude-scripts', '--always-copy', '--editable', '--build-directory', '.', self.pypi], dir=os.path.dirname(dir))
515        except OSError, err:
516            print ""
517            print "Error installing package %s with easy_install" % self.name
518            print str(err)
519            sys.exit(1)
520
521    def pip_install(self, install, preinstall, dir, offline):
522        try:
523            if install:
524                if offline:
525                    self.run([self.python, 'setup.py', 'install'], dir=dir)
526                else:
527                    self.run(self.pip_path + ['-v', self.pypi])
528            elif preinstall:
529                if not os.path.exists(dir):
530                    self.run(self.pip_path + ['-v', '--no-install', '--download', '.', self.pypi], dir=os.path.dirname(dir))
531        except OSError, err:
532            print ""
533            print "Error installing package %s with pip" % self.name
534            print str(err)
535            sys.exit(1)
536
537    def easy_upgrade(self):
538        self.run(self.easy_install_path + [Repository.easy_install_flag, '--upgrade', self.pypi])
539
540    def run(self, cmd, dir=None):
541        cwd=os.getcwd()
542        if not dir is None:
543            os.chdir(dir)
544            cwd=dir
545        print "Running command '%s' in directory %s" % (" ".join(cmd), cwd)
546        sys.stdout.flush()
547        call_subprocess(cmd, filter_stdout=filter_python_develop, show_stdout=True)
548        if not dir is None:
549            os.chdir(cwd)
550
551
552if sys.platform.startswith('win'):
553    if not is_jython:
554        Repository.python += 'w.exe'
555    Repository.svn += '.exe'
556
557
558def filter_python_develop(line):
559    if not line.strip():
560        return Logger.DEBUG
561    for prefix in ['Searching for', 'Reading ', 'Best match: ', 'Processing ',
562                   'Moving ', 'Adding ', 'running ', 'writing ', 'Creating ',
563                   'creating ', 'Copying ']:
564        if line.startswith(prefix):
565            return Logger.DEBUG
566    return Logger.NOTIFY
567
568
569def apply_template(str, d):
570    t = string.Template(str)
571    return t.safe_substitute(d)
572
573
574wrapper = textwrap.TextWrapper(subsequent_indent="    ")
575
576
577class Installer(object):
578
579    def __init__(self):
580        self.description="This script manages the installation of packages into a virtual Python installation."
581        self.home_dir = None
582        self.default_dirname='python'
583        self.abshome_dir = None
584        self.sw_packages = []
585        self.sw_dict = {}
586        self.cmd_files = []
587        self.auxdir = []
588        self.srcdir = None
589        self.config=None
590        self.config_file=None
591        self.README="""
592#
593# Virtual Python installation generated by the %s script.
594#
595# This directory is managed with virtualenv, which creates a
596# virtual Python installation.  If the 'bin' directory is put in
597# user's PATH environment, then the bin/python command can be used
598# without further installation.
599#
600# Directories:
601#   admin      Administrative data for maintaining this distribution
602#   bin        Scripts and executables
603#   dist       Python packages that are not intended for development
604#   include    Python header files
605#   lib        Python libraries and installed packages
606#   src        Python packages whose source files can be
607#              modified and used directly within this virtual Python
608#              installation.
609#   Scripts    Python bin directory (used on MS Windows)
610#
611""" % sys.argv[0]
612
613    def add_repository(self, *args, **kwds):
614        if not 'root' in kwds and not 'pypi' in kwds and not 'release' in kwds and not 'trunk' in kwds and not 'stable' in kwds:
615            raise IOError, "No repository info specified for repository "+args[0]
616        repos = Repository( *args, **kwds)
617        self.sw_dict[repos.name] = repos
618        self.sw_packages.append( repos )
619
620    def add_dos_cmd(self, file):
621        self.cmd_files.append( file )
622
623    def add_auxdir(self, package, todir, fromdir):
624        self.auxdir.append( (todir, package, fromdir) )
625
626    def modify_parser(self, parser):
627        self.default_windir = 'C:\\'+self.default_dirname
628        self.default_unixdir = './'+self.default_dirname
629        #
630        parser.add_option('--debug',
631            help='Configure script to generate debugging IO and to raise exceptions.',
632            action='store_true',
633            dest='debug',
634            default=False)
635
636        parser.add_option('--release',
637            help='Install release branches of Python software using subversion.',
638            action='store_true',
639            dest='release',
640            default=False)
641
642        parser.add_option('--trunk',
643            help='Install trunk branches of Python software using subversion.',
644            action='store_true',
645            dest='trunk',
646            default=False)
647
648        parser.add_option('--stable',
649            help='Install stable branches of Python software using subversion.',
650            action='store_true',
651            dest='stable',
652            default=False)
653
654        parser.add_option('--update',
655            help='Update all Python packages.',
656            action='store_true',
657            dest='update',
658            default=False)
659
660        parser.add_option('--proxy',
661            help='Set the HTTP_PROXY environment with this option.',
662            action='store',
663            dest='proxy',
664            default=None)
665
666        parser.add_option('--preinstall',
667            help='Prepare an installation that will be used to build a MS Windows installer.',
668            action='store_true',
669            dest='preinstall',
670            default=False)
671
672        parser.add_option('--offline',
673            help='Perform installation offline, using source extracted from ZIP files.',
674            action='store_true',
675            dest='offline',
676            default=False)
677
678        parser.add_option('--zip',
679            help='Add ZIP files that are use define this installation.',
680            action='append',
681            dest='zip',
682            default=[])
683
684        parser.add_option('--source', '--src',
685            help='Use packages defined in the specified source directory',
686            action='store',
687            dest='source',
688            default=None)
689
690        parser.add_option('--use-pythonpath',
691            help="By default, the PYTHONPATH is ignored when installing.  This option allows the 'easy_install' tool to search this path for related Python packages, which are then installed.",
692            action='store_true',
693            dest='use_pythonpath',
694            default=False)
695
696        parser.add_option(
697            '--site-packages',
698            dest='no_site_packages',
699            action='store_false',
700            help="Setup the virtual environment to use the global site-packages",
701            default=True)
702
703        parser.add_option(
704            '-a', '--add-package',
705            dest='packages',
706            action='append',
707            help='Specify a package that is added to the virtual Python installation.  This option can specify a directory for the Python package source or PyPI package name that is downloaded automatically.  This option can be specified multiple times to declare multiple packages.',
708            default=[])
709
710        parser.add_option('--config',
711            help='Use an INI config file to specify the packages used in this installation.  Using this option clears the initial configuration, but multiple uses of this option will add package specifications.',
712            action='append',
713            dest='config_files',
714            default=[])
715
716        parser.add_option('--keep-config',
717            help='Keep the initial configuration data that was specified if the --config option is specified.',
718            action='store_true',
719            dest='keep_config',
720            default=False)
721
722        parser.add_option('--without-externals',
723            help="Ignore the 'externals' section of the config file.",
724            action='store_false',
725            dest='follow_externals',
726            default=True)
727
728        parser.add_option('--localize',
729            help='Force localization of DOS scripts on Linux platforms',
730            action='store_true',
731            dest='localize',
732            default=False)
733
734        #
735        # Change the virtualenv options
736        #
737        parser.remove_option("--python")
738        parser.add_option("--python",
739            dest='python',
740            metavar='PYTHON_EXE',
741            help="Specify the Python interpreter to use, e.g., --python=python2.5 will install with the python2.5 interpreter.")
742        parser.remove_option("--relocatable")
743        parser.remove_option("--version")
744        parser.remove_option("--unzip-setuptools")
745        parser.remove_option("--no-site-packages")
746        parser.remove_option("--clear")
747        #
748        # Add description
749        #
750        parser.description=self.description
751        parser.epilog="If DEST_DIR is not specified, then a default installation path is used:  "+self.default_windir+" on Windows and "+self.default_unixdir+" on Linux.  This command uses the Python 'setuptools' package to install Python packages.  This package installs packages by downloading files from the internet.  If you are running this from within a firewall, you may need to set the HTTP_PROXY environment variable to a value like 'http://<proxyhost>:<port>'."
752
753
754    def adjust_options(self, options, args):
755        #
756        # Force options.clear to be False.  This allows us to preserve the logic
757        # associated with --clear, which we may want to use later.
758        #
759        options.clear=False
760        #
761        global vpy_main
762        if options.debug:
763            vpy_main.raise_exceptions=True
764        #
765        global logger
766        if options.verbose:
767            Repository.easy_install_flag = '-v'
768        verbosity = options.verbose - options.quiet
769        self.logger = Logger([(Logger.level_for_integer(2-verbosity), sys.stdout)])
770        logger = self.logger
771        #
772        # Determine if the subversion command is available
773        #
774        global using_subversion
775        try:
776            sys.stdout.flush()
777            call_subprocess(['svn'+executable_extension,'help'], show_stdout=False)
778        except OSError, err:
779            print ""
780            print "------------------------------------------------"
781            print "WARNING: problems executing subversion commands."
782            print "Subversion is disabled."
783            print "------------------------------------------------"
784            print ""
785            using_subversion = False
786        #
787        if options.update and (options.stable or options.trunk):
788            self.logger.fatal("ERROR: cannot specify --stable or --trunk when specifying the --update option.")
789            sys.exit(1000)
790        if options.update and len(options.config_files) > 0:
791            self.logger.fatal("ERROR: cannot specify --config when specifying the --update option.")
792            sys.exit(1000)
793        if options.update and options.keep_config:
794            self.logger.fatal("ERROR: cannot specify --keep-config when specifying the --update option.")
795            sys.exit(1000)
796        if len(args) > 1:
797            self.logger.fatal("ERROR: installer script can only have one argument")
798            sys.exit(1000)
799        #
800        # Error checking
801        #
802        if not options.preinstall and (os.path.exists(self.abshome_dir) ^ options.update):
803            if options.update:
804                self.logger.fatal(wrapper.fill("ERROR: The 'update' option is specified, but the installation path '%s' does not exist!" % self.home_dir))
805                sys.exit(1000)
806            elif os.path.exists(join(self.abshome_dir,'bin')):
807                self.logger.fatal(wrapper.fill("ERROR: The installation path '%s' already exists!  Use the --update option if you wish to update, or remove this directory to create a fresh installation." % self.home_dir))
808                sys.exit(1000)
809        if len(args) == 0:
810            args.append(self.abshome_dir)
811        #
812        # Reset the config file if no options are specified
813        #
814        if not self.config_file is None and not (options.trunk or options.stable or options.release):
815            self.config_file = os.path.dirname(self.config_file)+"/pypi.ini"
816        #
817        # Parse config files
818        #
819        if options.update:
820            self.config=None
821            options.config_files.append( join(self.abshome_dir, 'admin', 'config.ini') )
822        if not self.config is None and (len(options.config_files) == 0 or options.keep_config):
823            fp = StringIO.StringIO(self.config)
824            self.read_config_file(fp=fp, follow_externals=options.follow_externals)
825            fp.close()
826        if not self.config_file is None and (len(options.config_files) == 0 or options.keep_config):
827            self.read_config_file(file=self.config_file, follow_externals=options.follow_externals)
828        for file in options.config_files:
829            self.read_config_file(file=file, follow_externals=options.follow_externals)
830        print "-----------------------------------------------------------------"
831        print "Finished processing configuration information."
832        print "-----------------------------------------------------------------"
833        print " START - Configuration summary"
834        print "-----------------------------------------------------------------"
835        self.write_config(stream=sys.stdout)
836        print "-----------------------------------------------------------------"
837        print " END - Configuration summary"
838        print "-----------------------------------------------------------------"
839        #
840        # If applying preinstall, then only do subversion exports
841        #
842        if options.preinstall:
843            Repository.svn_get='export'
844
845    def get_homedir(self, options, args):
846        #
847        # Figure out the installation directory
848        #
849        if len(args) == 0:
850            path = self.guess_path()
851            if path is None or options.preinstall:
852                # Install in a default location.
853                if sys.platform == 'win32':
854                    home_dir = self.default_windir
855                else:
856                    home_dir = self.default_unixdir
857            else:
858                home_dir = os.path.dirname(os.path.dirname(path))
859        else:
860            home_dir = args[0]
861        self.home_dir = home_dir
862        self.abshome_dir = os.path.abspath(home_dir)
863        if options.source is None:
864            self.srcdir = join(self.abshome_dir,'src')
865        else:
866            self.srcdir = os.path.abspath(options.source)
867            if not os.path.exists(self.srcdir):
868                raise ValueError, "Specified source directory does not exist! %s" % self.srcdir
869
870    def guess_path(self):
871        return None
872
873    def setup_installer(self, options):
874        if options.preinstall:
875            print "Creating preinstall zip file in '%s'" % self.home_dir
876        elif options.update:
877            print "Updating existing installation in '%s'" % self.home_dir
878        else:
879            print "Starting fresh installation in '%s'" % self.home_dir
880        #
881        # Setup HTTP proxy
882        #
883        if options.offline:
884            os.environ['HTTP_PROXY'] = ''
885            os.environ['http_proxy'] = ''
886        else:
887            proxy = ''
888            if not options.proxy is None:
889                proxy = options.proxy
890            if proxy is '':
891                proxy = os.environ.get('HTTP_PROXY', '')
892            if proxy is '':
893                proxy = os.environ.get('http_proxy', '')
894            os.environ['HTTP_PROXY'] = proxy
895            os.environ['http_proxy'] = proxy
896            print "  using the HTTP_PROXY environment: %s" % proxy
897            print ""
898        #
899        # Disable the PYTHONPATH, to isolate this installation from
900        # other Python installations that a user may be working with.
901        #
902        if not options.use_pythonpath:
903            try:
904                del os.environ["PYTHONPATH"]
905            except:
906                pass
907        #
908        # If --preinstall is declared, then we remove the directory, and prepare a ZIP file
909        # that contains the full installation.
910        #
911        if options.preinstall:
912            print "-----------------------------------------------------------------"
913            print " STARTING preinstall in directory %s" % self.home_dir
914            print "-----------------------------------------------------------------"
915            rmtree(self.abshome_dir)
916            os.mkdir(self.abshome_dir)
917        #
918        # When preinstalling or working offline, disable the
919        # default install_setuptools() function.
920        #
921        if options.offline:
922            install_setuptools.use_default=False
923            install_pip.use_default=False
924        #
925        # If we're clearing the current installation, then remove a bunch of
926        # directories
927        #
928        elif options.clear and not options.source is None:
929            if os.path.exists(self.srcdir):
930                rmtree(self.srcdir)
931        #
932        # Open up zip files
933        #
934        for file in options.zip:
935            unzip_file(file, dir=self.abshome_dir)
936
937        if options.preinstall or not options.offline:
938            #self.get_packages(options)
939            pass
940        else:
941            self.sw_packages.insert( 0, Repository('virtualenv', pypi='virtualenv') )
942            self.sw_packages.insert( 0, Repository('pip', pypi='pip') )
943            self.sw_packages.insert( 0, Repository('setuptools', pypi='setuptools') )
944            #
945            # Configure the package versions, for offline installs
946            #
947            for pkg in self.sw_packages:
948                pkg.guess_versions(True)
949
950    def get_packages(self, options):
951        #
952        # Setup the 'admin' directory
953        #
954        if not os.path.exists(self.abshome_dir):
955            os.mkdir(self.abshome_dir)
956        if not os.path.exists(join(self.abshome_dir,'admin')):
957            os.mkdir(join(self.abshome_dir,'admin'))
958        if options.update:
959            INPUT=open(join(self.abshome_dir,'admin',"virtualenv.cfg"),'r')
960            options.trunk = INPUT.readline().strip() != 'False'
961            options.stable = INPUT.readline().strip() != 'False'
962            options.release = INPUT.readline().strip() != 'False'
963            INPUT.close()
964        else:
965            OUTPUT=open(join(self.abshome_dir,'admin',"virtualenv.cfg"),'w')
966            print >>OUTPUT, options.trunk
967            print >>OUTPUT, options.stable
968            print >>OUTPUT, options.release
969            OUTPUT.close()
970            self.write_config( join(self.abshome_dir,'admin','config.ini') )
971        #
972        # Setup package directories
973        #
974        if not os.path.exists(join(self.abshome_dir,'dist')):
975            os.mkdir(join(self.abshome_dir,'dist'))
976        if not os.path.exists(self.srcdir):
977            os.mkdir(self.srcdir)
978        if not os.path.exists(self.abshome_dir+os.sep+"bin"):
979            os.mkdir(self.abshome_dir+os.sep+"bin")
980        #
981        # Get source packages
982        #
983        self.sw_packages.insert( 0, Repository('virtualenv', pypi='virtualenv') )
984        self.sw_packages.insert( 0, Repository('pip', pypi='pip') )
985        if options.preinstall:
986            #
987            # When preinstalling, add the setuptools package to the installation list
988            #
989            self.sw_packages.insert( 0, Repository('setuptools', pypi='setuptools') )
990        for _pkg in options.packages:
991            if os.path.exists(_pkg):
992                self.sw_packages.append( Repository(_pkg, local=os.path.abspath(_pkg)) )
993            else:
994                self.sw_packages.append( Repository(_pkg, pypi=_pkg) )
995        #
996        # Add Coopr Forum packages
997        #
998        self.get_other_packages(options)
999        #
1000        # Get package source
1001        #
1002        for pkg in self.sw_packages:
1003            pkg.guess_versions(False)
1004            if not pkg.install:
1005                pkg.find_pkgroot(trunk=options.trunk, stable=options.stable, release=options.release)
1006                continue
1007            if pkg.local:
1008                tmp = pkg.local
1009            elif pkg.dev:
1010                tmp = join(self.srcdir,pkg.name)
1011            else:
1012                tmp = join(self.abshome_dir,'dist',pkg.name)
1013            if options.trunk:
1014                if not options.update:
1015                    pkg.install_trunk(dir=tmp, install=False, preinstall=options.preinstall, offline=options.offline)
1016            elif options.stable:
1017                if not options.update:
1018                    pkg.install_stable(dir=tmp, install=False, preinstall=options.preinstall, offline=options.offline)
1019            else:
1020                if not options.update:
1021                    pkg.install_release(dir=tmp, install=False, preinstall=options.preinstall, offline=options.offline)
1022        if options.update or not os.path.exists(join(self.abshome_dir,'doc')):
1023            self.install_auxdirs(options)
1024        #
1025        # Create a README.txt file
1026        #
1027        OUTPUT=open(join(self.abshome_dir,"README.txt"),"w")
1028        print >>OUTPUT, self.README.strip()
1029        OUTPUT.close()
1030        #
1031        # Finalize preinstall
1032        #
1033        if options.preinstall:
1034            print "-----------------------------------------------------------------"
1035            print " FINISHED preinstall in directory %s" % self.home_dir
1036            print "-----------------------------------------------------------------"
1037            os.chdir(self.abshome_dir)
1038            zip_file(self.default_dirname+'.zip', ['.'])
1039            sys.exit(0)
1040
1041    def get_other_packages(self, options):
1042        #
1043        # Used by subclasses of Installer to
1044        # add packages that were requested through other means....
1045        #
1046        pass
1047
1048    def install_packages(self, options):
1049        #
1050        # Set the bin directory
1051        #
1052        if os.path.exists(self.abshome_dir+os.sep+"Scripts"):
1053            bindir = join(self.abshome_dir,"Scripts")
1054        else:
1055            bindir = join(self.abshome_dir,"bin")
1056        if is_jython:
1057            Repository.python = os.path.abspath(join(bindir, 'jython.bat'))
1058        #elif sys.platform.startswith('win'):
1059            #Repository.python = os.path.abspath(join(bindir, 'python'))
1060        else:
1061            Repository.python = os.path.abspath(join(bindir, 'python'))
1062        if os.path.exists(os.path.abspath(join(bindir, 'easy_install'))):
1063            Repository.easy_install_path = [Repository.python, os.path.abspath(join(bindir, 'easy_install'))]
1064        else:
1065            Repository.easy_install_path = [os.path.abspath(join(bindir, 'easy_install.exe'))]
1066        if os.path.exists(os.path.abspath(join(bindir, 'pip'))):
1067            Repository.pip_path = [Repository.python, os.path.abspath(join(bindir, 'pip'))]
1068        else:
1069            Repository.pip_path = [os.path.abspath(join(bindir, 'pip.exe'))]
1070        #
1071        if options.preinstall or not options.offline:
1072            self.get_packages(options)
1073        #
1074        # Install the related packages
1075        #
1076        for pkg in self.sw_packages:
1077            if not pkg.install:
1078                pkg.find_pkgroot(trunk=options.trunk, stable=options.stable, release=options.release)
1079                continue
1080            if pkg.local:
1081                srcdir = pkg.local
1082            elif pkg.dev:
1083                srcdir = join(self.srcdir,pkg.name)
1084            else:
1085                srcdir = join(self.abshome_dir,'dist',pkg.name)
1086            if options.trunk:
1087                if options.update:
1088                    pkg.update_trunk(dir=srcdir)
1089                else:
1090                    pkg.install_trunk(dir=srcdir, preinstall=options.preinstall, offline=options.offline)
1091            elif options.stable:
1092                if options.update:
1093                    pkg.update_stable(dir=srcdir)
1094                else:
1095                    pkg.install_stable(dir=srcdir, preinstall=options.preinstall, offline=options.offline)
1096            else:
1097                if options.update:
1098                    pkg.update_release(dir=srcdir)
1099                else:
1100                    pkg.install_release(dir=srcdir, preinstall=options.preinstall, offline=options.offline)
1101        #
1102        # Localize DOS cmd files
1103        #
1104        self.localize_cmd_files(self.abshome_dir, options.localize)
1105        #
1106        # Copy the <env>/Scripts/* files into <env>/bin
1107        #
1108        if os.path.exists(self.abshome_dir+os.sep+"Scripts"):
1109            if not os.path.exists(self.abshome_dir+os.sep+"bin"):
1110                os.mkdir(self.abshome_dir+os.sep+"bin")
1111            for file in glob.glob(self.abshome_dir+os.sep+"Scripts"+os.sep+"*"):
1112                shutil.copy(file, self.abshome_dir+os.sep+"bin")
1113        #
1114        # Misc notifications
1115        #
1116        if not options.update:
1117            print ""
1118            print "-----------------------------------------------------------------"
1119            print "  Add %s to the PATH environment variable" % (self.home_dir+os.sep+"bin")
1120            print "-----------------------------------------------------------------"
1121        print ""
1122        print "Finished installation in '%s'" % self.home_dir
1123
1124    def localize_cmd_files(self, dir, force_localization=False):
1125        """
1126        Hard-code the path to Python that is used in the Python CMD files that
1127        are installed.
1128        """
1129        if not (sys.platform.startswith('win') or force_localization):
1130            return
1131        if os.path.exists(dir+os.sep+"Scripts"):
1132            bindir = 'Scripts'
1133        else:
1134            bindir = 'bin'
1135        for file in self.cmd_files:
1136            fname = join(dir,bindir,file)
1137            if not os.path.exists(fname):
1138                print "WARNING: Problem while localizing file '%s'.  This file is missing" % fname
1139                continue
1140            INPUT = open(fname, 'r')
1141            content = "".join(INPUT.readlines())
1142            INPUT.close()
1143            content = content.replace('__VIRTUAL_ENV__',dir)
1144            OUTPUT = open(fname, 'w')
1145            OUTPUT.write(content)
1146            OUTPUT.close()
1147
1148    def svnjoin(*args):
1149        return '/'.join(args[1:])
1150
1151    def install_auxdirs(self, options):
1152        for todir,pkg,fromdir in self.auxdir:
1153            pkgroot = self.sw_dict[pkg].pkgroot
1154            if options.update:
1155                cmd = [Repository.svn,'update','-q',self.svnjoin(self.abshome_dir, todir)]
1156            else:
1157                if options.clear:
1158                    rmtree( join(self.abshome_dir,todir) )
1159                cmd = [Repository.svn,Repository.svn_get,'-q',self.svnjoin(pkgroot,fromdir),join(self.abshome_dir,todir)]
1160            print "Running command '%s'" % " ".join(cmd)
1161            sys.stdout.flush()
1162            call_subprocess(cmd, filter_stdout=filter_python_develop,show_stdout=True)
1163
1164    def read_config_file(self, file=None, fp=None, follow_externals=True):
1165        """
1166        Read a config file.
1167        """
1168        parser = OrderedConfigParser()
1169        if not fp is None:
1170            parser.readfp(fp, '<default configuration>')
1171        elif not os.path.exists(file):
1172            if not '/' in file and not self.config_file is None:
1173                file = os.path.dirname(self.config_file)+"/"+file
1174            try:
1175                if sys.version_info[:2] <= (2,5):
1176                    output = urllib2.urlopen(file).read()
1177                else:
1178                    output = urllib2.urlopen(file, timeout=30).read()
1179            except Exception, err:
1180                print "Problems opening configuration url:",file
1181                raise
1182            fp = StringIO.StringIO(output)
1183            parser.readfp(fp, file)
1184            fp.close()
1185        else:
1186            if not file in parser.read(file):
1187                raise IOError, "Error while parsing file %s." % file
1188        sections = parser.sections()
1189        if 'installer' in sections:
1190            for option, value in parser.items('installer'):
1191                setattr(self, option, apply_template(value, os.environ) )
1192        if follow_externals and 'externals' in sections:
1193            for option, value in parser.items('externals'):
1194                self.read_config_file(file=value, follow_externals=follow_externals)
1195        if 'localize' in sections:
1196            for option, value in parser.items('localize'):
1197                self.add_dos_cmd(option)
1198        for sec in sections:
1199            if sec in ['installer', 'localize', 'externals']:
1200                continue
1201            if sec.endswith(':auxdir'):
1202                auxdir = sec[:-7]
1203                for option, value in parser.items(sec):
1204                    self.add_auxdir(auxdir, option, apply_template(value, os.environ) )
1205            else:
1206                options = {}
1207                for option, value in parser.items(sec):
1208                    options[option] = apply_template(value, os.environ)
1209                self.add_repository(sec, **options)
1210
1211    def write_config(self, filename=None, stream=None):
1212        if not filename is None:
1213            OUTPUT=open(filename,'w')
1214            self.write_config(stream=OUTPUT)
1215            OUTPUT.close()
1216        else:
1217            for repos in self.sw_packages:
1218                repos.write_config(stream)
1219                print >>stream, ""
1220            if len(self.cmd_files) > 0:
1221                print >>stream, "[localize]"
1222                for file in self.cmd_files:
1223                    print >>stream, file+"="
1224                print >>stream, "\n"
1225
1226
1227
1228def configure(installer):
1229    """
1230    A dummy configuration function.
1231    """
1232    return installer
1233
1234def create_installer():
1235    return Installer()
1236
1237def get_installer():
1238    """
1239    Return an instance of the installer object.  If this object
1240    does not already exist, then create the object and use the
1241    configure() function to customize it based on the end-user's
1242    needs.
1243
1244    The argument to this function is the class type that will be
1245    constructed if needed.
1246    """
1247    try:
1248        return get_installer.installer
1249    except:
1250        get_installer.installer = configure( create_installer() )
1251        return get_installer.installer
1252
1253#
1254# Override the default definition of rmtree, to better handle MSWindows errors
1255# that are associated with read-only files
1256#
1257def handleRemoveReadonly(func, path, exc):
1258    excvalue = exc[1]
1259    if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
1260        os.chmod(path, stat.S_IRWXU| stat.S_IRWXG| stat.S_IRWXO) # 0777
1261        func(path)
1262    else:
1263        raise
1264
1265def rmtree(dir):
1266    if os.path.exists(dir):
1267        logger.notify('Deleting tree %s', dir)
1268        shutil.rmtree(dir, ignore_errors=False, onerror=handleRemoveReadonly)
1269    else:
1270        logger.info('Do not need to delete %s; already gone', dir)
1271
1272#
1273# This is a monkey patch, to add control for exception management.
1274#
1275vpy_main = main
1276vpy_main.raise_exceptions=False
1277def main():
1278    if sys.platform != 'win32':
1279        if os.environ.get('TMPDIR','') == '.':
1280            os.environ['TMPDIR'] = '/tmp'
1281        elif os.environ.get('TEMPDIR','') == '.':
1282            os.environ['TEMPDIR'] = '/tmp'
1283    try:
1284        vpy_main()
1285    except Exception, err:
1286        if vpy_main.raise_exceptions:
1287            raise
1288        print ""
1289        print "ERROR:",str(err)
1290
1291#
1292# This is a monkey patch, to control the execution of the install_setuptools()
1293# function that is defined by virtualenv.
1294#
1295default_install_setuptools = install_setuptools
1296
1297def install_setuptools(py_executable, unzip=False):
1298    try:
1299        if install_setuptools.use_default:
1300            default_install_setuptools(py_executable, unzip)
1301    except OSError, err:
1302        print "-----------------------------------------------------------------"
1303        print "Error installing the 'setuptools' package!"
1304        if os.environ['HTTP_PROXY'] == '':
1305            print ""
1306            print "WARNING: you may need to set your HTTP_PROXY environment variable!"
1307        print "-----------------------------------------------------------------"
1308        sys.exit(1)
1309
1310install_setuptools.use_default=True
1311
1312
1313#
1314# This is a monkey patch, to control the execution of the install_pip()
1315# function that is defined by virtualenv.
1316#
1317default_install_pip = install_pip
1318
1319def install_pip(*args, **kwds):
1320    try:
1321        if install_pip.use_default:
1322            default_install_pip(*args, **kwds)
1323    except OSError, err:
1324        print "-----------------------------------------------------------------"
1325        print "Error installing the 'pip' package!"
1326        if os.environ['HTTP_PROXY'] == '':
1327            print ""
1328            print "WARNING: you may need to set your HTTP_PROXY environment variable!"
1329        print "-----------------------------------------------------------------"
1330        sys.exit(1)
1331
1332install_pip.use_default=True
1333
1334
1335#
1336# This is a monkey patch, to catch errors when a directory cannot be created
1337# by virtualenv.
1338#
1339def mkdir(path):
1340    if not os.path.exists(path):
1341        logger.info('Creating %s', path)
1342        try:
1343            os.makedirs(path)
1344        except Exception, e:
1345            print "Cannot create directory '%s'!" % path
1346            print "Verify that you have write permissions to this directory."
1347            sys.exit(1)
1348    else:
1349        logger.info('Directory %s already exists', path)
1350
1351#
1352# The following methods will be called by virtualenv
1353#
1354def extend_parser(parser):
1355    installer = get_installer()
1356    installer.modify_parser(parser)
1357
1358def adjust_options(options, args):
1359    installer = get_installer()
1360    installer.get_homedir(options, args)
1361    installer.adjust_options(options, args)
1362    installer.setup_installer(options)
1363
1364def after_install(options, home_dir):
1365    installer = get_installer()
1366    installer.install_packages(options)
Note: See TracBrowser for help on using the repository browser.