Release of libvirt-python 5.5.0
[libvirt-python/ericb.git] / setup.py
blob47b7c0c7471c858958bcfd22b75b0ef1635035f7
1 #!/usr/bin/env python
3 from distutils.core import setup, Extension, Command
4 from distutils.command.build import build
5 from distutils.command.clean import clean
6 from distutils.command.sdist import sdist
7 from distutils.dir_util import remove_tree
8 from distutils.util import get_platform
9 from distutils.spawn import spawn
10 from distutils.errors import DistutilsExecError
11 import distutils
13 import sys
14 import os
15 import os.path
16 import re
17 import shutil
18 import time
20 MIN_LIBVIRT = "0.9.11"
21 MIN_LIBVIRT_LXC = "1.0.2"
23 # Hack to stop 'pip install' failing with error
24 # about missing 'build' dir.
25 if not os.path.exists("build"):
26 os.mkdir("build")
28 _pkgcfg = -1
29 def get_pkgcfg(do_fail=True):
30 global _pkgcfg
31 if _pkgcfg == -1:
32 _pkgcfg = os.getenv('PKG_CONFIG')
33 if _pkgcfg is None:
34 _pkgcfg = distutils.spawn.find_executable("pkg-config")
35 if _pkgcfg is None and do_fail:
36 raise Exception("pkg-config binary is required to compile libvirt-python")
37 return _pkgcfg
39 def check_minimum_libvirt_version():
40 spawn([get_pkgcfg(),
41 "--print-errors",
42 "--atleast-version=%s" % MIN_LIBVIRT,
43 "libvirt"])
45 def have_libvirt_lxc():
46 try:
47 spawn([get_pkgcfg(),
48 "--atleast-version=%s" % MIN_LIBVIRT_LXC,
49 "libvirt"])
50 return True
51 except DistutilsExecError:
52 return False
54 def have_libvirtaio():
55 # This depends on asyncio, which in turn depends on "yield from" syntax.
56 # The asyncio module itself is in standard library since 3.4, but there is
57 # an out-of-tree version compatible with 3.3.
58 return sys.version_info >= (3, 3)
60 def get_pkgconfig_data(args, mod, required=True):
61 """Run pkg-config to and return content associated with it"""
62 f = os.popen("%s %s %s" % (get_pkgcfg(), " ".join(args), mod))
64 line = f.readline()
65 if line is not None:
66 line = line.strip()
68 if line is None or line == "":
69 if required:
70 raise Exception("Cannot determine '%s' from libvirt pkg-config file" % " ".join(args))
71 else:
72 return ""
74 return line
76 def get_api_xml_files():
77 """Check with pkg-config that libvirt is present and extract
78 the API XML file paths we need from it"""
80 libvirt_api = get_pkgconfig_data(["--variable", "libvirt_api"], "libvirt")
82 offset = libvirt_api.index("-api.xml")
83 libvirt_qemu_api = libvirt_api[0:offset] + "-qemu-api.xml"
85 offset = libvirt_api.index("-api.xml")
86 libvirt_lxc_api = libvirt_api[0:offset] + "-lxc-api.xml"
88 return (libvirt_api, libvirt_qemu_api, libvirt_lxc_api)
90 def get_module_lists():
91 """
92 Determine which modules we are actually building, and all their
93 required config
94 """
95 if get_pkgcfg(do_fail=False) is None:
96 return [], []
98 c_modules = []
99 py_modules = []
100 ldflags = get_pkgconfig_data(["--libs-only-L"], "libvirt", False).split()
101 cflags = get_pkgconfig_data(["--cflags"], "libvirt", False).split()
103 module = Extension('libvirtmod',
104 sources = ['libvirt-override.c', 'build/libvirt.c', 'typewrappers.c', 'libvirt-utils.c'],
105 libraries = [ "virt" ],
106 include_dirs = [ "." ])
107 module.extra_compile_args.extend(cflags)
108 module.extra_link_args.extend(ldflags)
110 c_modules.append(module)
111 py_modules.append("libvirt")
113 moduleqemu = Extension('libvirtmod_qemu',
114 sources = ['libvirt-qemu-override.c', 'build/libvirt-qemu.c', 'typewrappers.c', 'libvirt-utils.c'],
115 libraries = [ "virt-qemu" ],
116 include_dirs = [ "." ])
117 moduleqemu.extra_compile_args.extend(cflags)
118 moduleqemu.extra_link_args.extend(ldflags)
120 c_modules.append(moduleqemu)
121 py_modules.append("libvirt_qemu")
123 if have_libvirt_lxc():
124 modulelxc = Extension('libvirtmod_lxc',
125 sources = ['libvirt-lxc-override.c', 'build/libvirt-lxc.c', 'typewrappers.c', 'libvirt-utils.c'],
126 libraries = [ "virt-lxc" ],
127 include_dirs = [ "." ])
128 modulelxc.extra_compile_args.extend(cflags)
129 modulelxc.extra_link_args.extend(ldflags)
131 c_modules.append(modulelxc)
132 py_modules.append("libvirt_lxc")
134 if have_libvirtaio():
135 py_modules.append("libvirtaio")
137 return c_modules, py_modules
140 ###################
141 # Custom commands #
142 ###################
144 class my_build(build):
146 def run(self):
147 check_minimum_libvirt_version()
148 apis = get_api_xml_files()
150 self.spawn([sys.executable, "generator.py", "libvirt", apis[0]])
151 self.spawn([sys.executable, "generator.py", "libvirt-qemu", apis[1]])
152 if have_libvirt_lxc():
153 self.spawn([sys.executable, "generator.py", "libvirt-lxc", apis[2]])
154 if have_libvirtaio():
155 shutil.copy('libvirtaio.py', 'build')
157 build.run(self)
159 class my_sdist(sdist):
160 user_options = sdist.user_options
162 description = "Update libvirt-python.spec; build sdist-tarball."
164 def initialize_options(self):
165 self.snapshot = None
166 sdist.initialize_options(self)
168 def finalize_options(self):
169 if self.snapshot is not None:
170 self.snapshot = 1
171 sdist.finalize_options(self)
173 def gen_rpm_spec(self):
174 f1 = open('libvirt-python.spec.in', 'r')
175 f2 = open('libvirt-python.spec', 'w')
176 for line in f1:
177 f2.write(line
178 .replace('@PY_VERSION@', self.distribution.get_version()))
179 f1.close()
180 f2.close()
182 def gen_authors(self):
183 f = os.popen("git log --pretty=format:'%aN <%aE>'")
184 authors = []
185 for line in f:
186 line = " " + line.strip()
187 if line not in authors:
188 authors.append(line)
190 authors.sort(key=str.lower)
192 f1 = open('AUTHORS.in', 'r')
193 f2 = open('AUTHORS', 'w')
194 for line in f1:
195 f2.write(line.replace('@AUTHORS@', "\n".join(authors)))
196 f1.close()
197 f2.close()
200 def gen_changelog(self):
201 f1 = os.popen("git log '--pretty=format:%H:%ct %an <%ae>%n%n%s%n%b%n'")
202 f2 = open("ChangeLog", 'w')
204 for line in f1:
205 m = re.match(r'([a-f0-9]+):(\d+)\s(.*)', line)
206 if m:
207 t = time.gmtime(int(m.group(2)))
208 f2.write("%04d-%02d-%02d %s\n" % (t.tm_year, t.tm_mon, t.tm_mday, m.group(3)))
209 else:
210 if re.match(r'Signed-off-by', line):
211 continue
212 f2.write(" " + line.strip() + "\n")
214 f1.close()
215 f2.close()
218 def run(self):
219 if not os.path.exists("build"):
220 os.mkdir("build")
222 if os.path.exists(".git"):
223 try:
224 self.gen_rpm_spec()
225 self.gen_authors()
226 self.gen_changelog()
228 sdist.run(self)
230 finally:
231 files = ["libvirt-python.spec",
232 "AUTHORS",
233 "ChangeLog"]
234 for f in files:
235 if os.path.exists(f):
236 os.unlink(f)
237 else:
238 sdist.run(self)
240 class my_rpm(Command):
241 user_options = []
243 description = "Build src and noarch rpms."
245 def initialize_options(self):
246 pass
248 def finalize_options(self):
249 pass
251 def run(self):
253 Run sdist, then 'rpmbuild' the tar.gz
256 self.run_command('sdist')
257 self.spawn(["/usr/bin/rpmbuild", "-ta", "--clean",
258 "dist/libvirt-python-%s.tar.gz" % self.distribution.get_version()])
260 class my_test(Command):
261 user_options = [
262 ('build-base=', 'b',
263 "base directory for build library"),
264 ('build-platlib=', None,
265 "build directory for platform-specific distributions"),
266 ('plat-name=', 'p',
267 "platform name to build for, if supported "
268 "(default: %s)" % get_platform()),
271 description = "Run test suite."
273 def initialize_options(self):
274 self.build_base = 'build'
275 self.build_platlib = None
276 self.plat_name = None
278 def finalize_options(self):
279 if self.plat_name is None:
280 self.plat_name = get_platform()
282 plat_specifier = ".%s-%s" % (self.plat_name, sys.version[0:3])
284 if hasattr(sys, 'gettotalrefcount'):
285 plat_specifier += '-pydebug'
287 if self.build_platlib is None:
288 self.build_platlib = os.path.join(self.build_base,
289 'lib' + plat_specifier)
291 def find_nosetests_path(self):
292 binaries = [
293 "nosetests-%d.%d" % (sys.version_info[0],
294 sys.version_info[1]),
295 "nosetests-%d" % (sys.version_info[0]),
296 "nosetests",
299 for binary in binaries:
300 path = distutils.spawn.find_executable(binary)
301 if path is not None:
302 return path
304 raise Exception("Cannot find any nosetests binary")
306 def run(self):
308 Run test suite
311 apis = get_api_xml_files()
313 if "PYTHONPATH" in os.environ:
314 os.environ["PYTHONPATH"] = self.build_platlib + ":" + os.environ["PYTHONPATH"]
315 else:
316 os.environ["PYTHONPATH"] = self.build_platlib
317 self.spawn([sys.executable, "sanitytest.py", self.build_platlib, apis[0]])
318 nose = self.find_nosetests_path()
319 self.spawn([sys.executable, nose])
322 class my_clean(clean):
323 def run(self):
324 clean.run(self)
326 if os.path.exists("build"):
327 remove_tree("build")
330 ##################
331 # Invoke setup() #
332 ##################
334 _c_modules, _py_modules = get_module_lists()
336 setup(name = 'libvirt-python',
337 version = '5.5.0',
338 url = 'http://www.libvirt.org',
339 maintainer = 'Libvirt Maintainers',
340 maintainer_email = 'libvir-list@redhat.com',
341 description = 'The libvirt virtualization API python binding',
342 long_description =
343 '''The libvirt-python package provides a module that permits applications
344 written in the Python programming language to call the interface
345 supplied by the libvirt library, to manage the virtualization capabilities
346 of recent versions of Linux (and other OSes).''',
347 license = 'LGPLv2+',
348 ext_modules = _c_modules,
349 py_modules = _py_modules,
350 package_dir = {
351 '': 'build'
353 cmdclass = {
354 'build': my_build,
355 'clean': my_clean,
356 'sdist': my_sdist,
357 'rpm': my_rpm,
358 'test': my_test
360 classifiers = [
361 "Development Status :: 5 - Production/Stable",
362 "Intended Audience :: Developers",
363 "License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)",
364 "Programming Language :: Python",
365 "Programming Language :: Python :: 2",
366 "Programming Language :: Python :: 3",