Commit 9f75521a authored by Kirill Smelkov's avatar Kirill Smelkov Committed by Xavier Thompson

[feat] zc.recipe.egg: Support environment in :develop

Currently only zc.recipe.egg:custom supports setting environment
variables, and zc.recipe.egg:develop does not.

My motivation for allowing setting environment in :develop is
wendelin.core

    https://lab.nexedi.cn/nexedi/slapos/blob/b5faab3b/component/wendelin.core/buildout.cfg

There we have [wendelin.core] part which installs released egg from
pypi, and [wendelin.core-dev] part which installs wendelin.core from
its latest git version via zc.recipe.egg:develop .

The problem is, wendelin.core for setup.py to work, needs git available,
and with slapos we usually don't have git available on base system, so
we build it by our own and do something like

    [wendelin.core-dev]
    recipe = zc.recipe.egg:develop
    environment = wendelin.core-dev-env

    [wendelin.core-dev-env]
    # wendelin.core-dev needs git to build
    PATH = ${git:location}/bin:%(PATH)s

and the problem is environment does not currently work for
zc.recipe.egg:develop, and thus git is not found -> build fails.

~~~~

In order to support environment in :develop, we just move environment
setting/restoring bits from Custom to Base, and provide Base.install() which
uses this bits. Custom & Develop .install() becomes ._install() which gets
hooked into Base.install() .

I've tested the patch only manually, because currently automated tests are
broken in a lot of places for slapos.buildout and zc.recipe.egg .

/cc @kazuhiko, @Tyagov
parent 04b4df66
...@@ -29,11 +29,47 @@ class Base: ...@@ -29,11 +29,47 @@ class Base:
options['_d'] = buildout['buildout']['develop-eggs-directory'] options['_d'] = buildout['buildout']['develop-eggs-directory']
environment_section = options.get('environment')
if environment_section:
self.environment = buildout[environment_section]
else:
self.environment = {}
environment_data = list(self.environment.items())
environment_data.sort()
options['_environment-data'] = repr(environment_data)
self.build_ext = build_ext(buildout, options) self.build_ext = build_ext(buildout, options)
def install(self):
self._set_environment()
try:
return self._install()
finally:
self._restore_environment()
def update(self): def update(self):
return self.install() return self.install()
def _set_environment(self):
self._saved_environment = {}
for key, value in list(self.environment.items()):
if key in os.environ:
self._saved_environment[key] = os.environ[key]
# Interpolate value with variables from environment. Maybe there
# should be a general way of doing this in buildout with something
# like ${environ:foo}:
os.environ[key] = value % os.environ
def _restore_environment(self):
for key in self.environment:
if key in self._saved_environment:
os.environ[key] = self._saved_environment[key]
else:
try:
del os.environ[key]
except KeyError:
pass
class Custom(Base): class Custom(Base):
...@@ -54,23 +90,14 @@ class Custom(Base): ...@@ -54,23 +90,14 @@ class Custom(Base):
options['index'] = index options['index'] = index
self.index = index self.index = index
environment_section = options.get('environment')
if environment_section:
self.environment = buildout[environment_section]
else:
self.environment = {}
environment_data = list(self.environment.items())
environment_data.sort()
options['_environment-data'] = repr(environment_data)
options['_e'] = buildout['buildout']['eggs-directory'] options['_e'] = buildout['buildout']['eggs-directory']
if buildout['buildout'].get('offline') == 'true': if buildout['buildout'].get('offline') == 'true':
self.install = lambda: () self._install = lambda: ()
self.newest = buildout['buildout'].get('newest') == 'true' self.newest = buildout['buildout'].get('newest') == 'true'
def install(self): def _install(self):
options = self.options options = self.options
distribution = options.get('egg') distribution = options.get('egg')
if distribution is None: if distribution is None:
...@@ -100,36 +127,11 @@ class Custom(Base): ...@@ -100,36 +127,11 @@ class Custom(Base):
extra_path = os.pathsep.join(ws.entries) extra_path = os.pathsep.join(ws.entries)
self.environment['PYTHONEXTRAPATH'] = os.environ['PYTHONEXTRAPATH'] = extra_path self.environment['PYTHONEXTRAPATH'] = os.environ['PYTHONEXTRAPATH'] = extra_path
self._set_environment() return zc.buildout.easy_install.build(
try: distribution, options['_d'], self.build_ext,
return zc.buildout.easy_install.build( self.links, self.index, sys.executable,
distribution, options['_d'], self.build_ext, [options['_e']], newest=self.newest,
self.links, self.index, sys.executable, )
[options['_e']], newest=self.newest,
)
finally:
self._restore_environment()
def _set_environment(self):
self._saved_environment = {}
for key, value in list(self.environment.items()):
if key in os.environ:
self._saved_environment[key] = os.environ[key]
# Interpolate value with variables from environment. Maybe there
# should be a general way of doing this in buildout with something
# like ${environ:foo}:
os.environ[key] = value % os.environ
def _restore_environment(self):
for key in self.environment:
if key in self._saved_environment:
os.environ[key] = self._saved_environment[key]
else:
try:
del os.environ[key]
except KeyError:
pass
class Develop(Base): class Develop(Base):
...@@ -139,7 +141,7 @@ class Develop(Base): ...@@ -139,7 +141,7 @@ class Develop(Base):
options['setup'] = os.path.join(buildout['buildout']['directory'], options['setup'] = os.path.join(buildout['buildout']['directory'],
options['setup']) options['setup'])
def install(self): def _install(self):
options = self.options options = self.options
return zc.buildout.easy_install.develop( return zc.buildout.easy_install.develop(
options['setup'], options['_d'], self.build_ext) options['setup'], options['_d'], self.build_ext)
......
...@@ -503,6 +503,10 @@ swig-cpp ...@@ -503,6 +503,10 @@ swig-cpp
swig-opts swig-opts
List of SWIG command line options List of SWIG command line options
environment
The name of a section with additional environment variables. The
environment variables are set before the egg is built.
To illustrate this, we'll use a directory containing the extdemo To illustrate this, we'll use a directory containing the extdemo
example from the earlier section: example from the earlier section:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment