1 from distutils
.util
import convert_path
2 from distutils
import log
3 from distutils
.errors
import DistutilsError
, DistutilsOptionError
9 from setuptools
.command
.easy_install
import easy_install
10 from setuptools
import namespaces
14 class develop(namespaces
.DevelopInstaller
, easy_install
):
15 """Set up package for development"""
17 description
= "install package in 'development mode'"
19 user_options
= easy_install
.user_options
+ [
20 ("uninstall", "u", "Uninstall this source package"),
21 ("egg-path=", None, "Set the path to be used in the .egg-link file"),
24 boolean_options
= easy_install
.boolean_options
+ ['uninstall']
26 command_consumes_arguments
= False # override base
30 self
.multi_version
= True
32 self
.uninstall_namespaces()
34 self
.install_for_development()
35 self
.warn_deprecated_options()
37 def initialize_options(self
):
40 easy_install
.initialize_options(self
)
41 self
.setup_path
= None
42 self
.always_copy_from
= '.' # always copy eggs installed in curdir
44 def finalize_options(self
):
45 ei
= self
.get_finalized_command("egg_info")
46 if ei
.broken_egg_info
:
47 template
= "Please rename %r to %r before using 'develop'"
48 args
= ei
.egg_info
, ei
.broken_egg_info
49 raise DistutilsError(template
% args
)
50 self
.args
= [ei
.egg_name
]
52 easy_install
.finalize_options(self
)
53 self
.expand_basedirs()
55 # pick up setup-dir .egg files only: no .egg-info
56 self
.package_index
.scan(glob
.glob('*.egg'))
58 egg_link_fn
= ei
.egg_name
+ '.egg-link'
59 self
.egg_link
= os
.path
.join(self
.install_dir
, egg_link_fn
)
60 self
.egg_base
= ei
.egg_base
61 if self
.egg_path
is None:
62 self
.egg_path
= os
.path
.abspath(ei
.egg_base
)
64 target
= pkg_resources
.normalize_path(self
.egg_base
)
65 egg_path
= pkg_resources
.normalize_path(
66 os
.path
.join(self
.install_dir
, self
.egg_path
)
68 if egg_path
!= target
:
69 raise DistutilsOptionError(
70 "--egg-path must be a relative path from the install"
71 " directory to " + target
74 # Make a distribution for the package's source
75 self
.dist
= pkg_resources
.Distribution(
77 pkg_resources
.PathMetadata(target
, os
.path
.abspath(ei
.egg_info
)),
78 project_name
=ei
.egg_name
,
81 self
.setup_path
= self
._resolve
_setup
_path
(
88 def _resolve_setup_path(egg_base
, install_dir
, egg_path
):
90 Generate a path from egg_base back to '.' where the
91 setup script resides and ensure that path points to the
92 setup path from $install_dir/$egg_path.
94 path_to_setup
= egg_base
.replace(os
.sep
, '/').rstrip('/')
95 if path_to_setup
!= os
.curdir
:
96 path_to_setup
= '../' * (path_to_setup
.count('/') + 1)
97 resolved
= pkg_resources
.normalize_path(
98 os
.path
.join(install_dir
, egg_path
, path_to_setup
)
100 if resolved
!= pkg_resources
.normalize_path(os
.curdir
):
101 raise DistutilsOptionError(
102 "Can't get a consistent path to setup script from"
103 " installation directory",
105 pkg_resources
.normalize_path(os
.curdir
),
109 def install_for_development(self
):
110 self
.run_command('egg_info')
112 # Build extensions in-place
113 self
.reinitialize_command('build_ext', inplace
=1)
114 self
.run_command('build_ext')
116 if setuptools
.bootstrap_install_from
:
117 self
.easy_install(setuptools
.bootstrap_install_from
)
118 setuptools
.bootstrap_install_from
= None
120 self
.install_namespaces()
122 # create an .egg-link in the installation dir, pointing to our egg
123 log
.info("Creating %s (link to %s)", self
.egg_link
, self
.egg_base
)
125 with
open(self
.egg_link
, "w") as f
:
126 f
.write(self
.egg_path
+ "\n" + self
.setup_path
)
127 # postprocess the installed distro, fixing up .pth, installing scripts,
128 # and handling requirements
129 self
.process_distribution(None, self
.dist
, not self
.no_deps
)
131 def uninstall_link(self
):
132 if os
.path
.exists(self
.egg_link
):
133 log
.info("Removing %s (link to %s)", self
.egg_link
, self
.egg_base
)
134 egg_link_file
= open(self
.egg_link
)
135 contents
= [line
.rstrip() for line
in egg_link_file
]
136 egg_link_file
.close()
137 if contents
not in ([self
.egg_path
], [self
.egg_path
, self
.setup_path
]):
138 log
.warn("Link points to %s: uninstall aborted", contents
)
141 os
.unlink(self
.egg_link
)
143 self
.update_pth(self
.dist
) # remove any .pth link to us
144 if self
.distribution
.scripts
:
145 # XXX should also check for entry point scripts!
146 log
.warn("Note: you must uninstall or replace scripts manually!")
148 def install_egg_scripts(self
, dist
):
149 if dist
is not self
.dist
:
150 # Installing a dependency, so fall back to normal behavior
151 return easy_install
.install_egg_scripts(self
, dist
)
153 # create wrapper scripts in the script dir, pointing to dist.scripts
156 self
.install_wrapper_scripts(dist
)
159 for script_name
in self
.distribution
.scripts
or []:
160 script_path
= os
.path
.abspath(convert_path(script_name
))
161 script_name
= os
.path
.basename(script_path
)
162 with io
.open(script_path
) as strm
:
163 script_text
= strm
.read()
164 self
.install_script(dist
, script_name
, script_text
, script_path
)
166 def install_wrapper_scripts(self
, dist
):
167 dist
= VersionlessRequirement(dist
)
168 return easy_install
.install_wrapper_scripts(self
, dist
)
171 class VersionlessRequirement
:
173 Adapt a pkg_resources.Distribution to simply return the project
174 name as the 'requirement' so that scripts will work across
177 >>> from pkg_resources import Distribution
178 >>> dist = Distribution(project_name='foo', version='1.0')
179 >>> str(dist.as_requirement())
181 >>> adapted_dist = VersionlessRequirement(dist)
182 >>> str(adapted_dist.as_requirement())
186 def __init__(self
, dist
):
189 def __getattr__(self
, name
):
190 return getattr(self
.__dist
, name
)
192 def as_requirement(self
):
193 return self
.project_name