blob: c2d4568e2970f0c1a622ef3359e92923fe6b8cd3 [file] [log] [blame]
#!/usr/bin/env python
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
import os, re, sys, string, platform
from distutils.core import setup, Command
from distutils.command.build import build as _build
from distutils.command.build_py import build_py as _build_py
from distutils.command.clean import clean as _clean
from distutils.command.install_lib import install_lib as _install_lib
from distutils.dep_util import newer
from distutils.dir_util import remove_tree
from distutils.dist import Distribution
from distutils.errors import DistutilsFileError, DistutilsOptionError
from distutils import log
from stat import ST_ATIME, ST_MTIME, ST_MODE, S_IMODE
MAJOR, MINOR = sys.version_info[0:2]
class preprocessor:
def copy_file(self, src, dst, preserve_mode=1, preserve_times=1,
link=None, level=1):
name, actor = self.actor(src, dst)
if actor:
if not os.path.isfile(src):
raise DistutilsFileError, \
"can't copy '%s': doesn't exist or not a regular file" % src
if os.path.isdir(dst):
dir = dst
dst = os.path.join(dst, os.path.basename(src))
else:
dir = os.path.dirname(dst)
if not self.force and not newer(src, dst):
return dst, 0
if os.path.basename(dst) == os.path.basename(src):
log.info("%s %s -> %s", name, src, dir)
else:
log.info("%s %s -> %s", name, src, dst)
if self.dry_run:
return (dst, 1)
else:
try:
fsrc = open(src, 'rb')
except os.error, (errno, errstr):
raise DistutilsFileError, \
"could not open '%s': %s" % (src, errstr)
if os.path.exists(dst):
try:
os.unlink(dst)
except os.error, (errno, errstr):
raise DistutilsFileError, \
"could not delete '%s': %s" % (dst, errstr)
try:
fdst = open(dst, 'wb')
except os.error, (errno, errstr):
raise DistutilsFileError, \
"could not create '%s': %s" % (dst, errstr)
try:
fdst.write(actor(fsrc.read()))
finally:
fsrc.close()
fdst.close()
if preserve_mode or preserve_times:
st = os.stat(src)
if preserve_times:
os.utime(dst, (st[ST_ATIME], st[ST_MTIME]))
if preserve_mode:
os.chmod(dst, S_IMODE(st[ST_MODE]))
return (dst, 1)
else:
return Command.copy_file(self, src, dst, preserve_mode, preserve_times,
link, level)
doc_option = [('build-doc', None, 'build directory for documentation')]
class build(_build):
user_options = _build.user_options + doc_option
def initialize_options(self):
_build.initialize_options(self)
self.build_doc = None
def finalize_options(self):
_build.finalize_options(self)
if self.build_doc is None:
self.build_doc = "%s/doc" % self.build_base
def get_sub_commands(self):
return _build.get_sub_commands(self) + ["build_doc"]
class build_doc(Command):
user_options = doc_option
def initialize_options(self):
self.build_doc = None
def finalize_options(self):
self.set_undefined_options('build', ('build_doc', 'build_doc'))
def run(self):
try:
from epydoc.docbuilder import build_doc_index
from epydoc.docwriter.html import HTMLWriter
except ImportError, e:
log.warn('%s -- skipping build_doc', e)
return
names = ["qpid.messaging"]
doc_index = build_doc_index(names, True, True)
html_writer = HTMLWriter(doc_index, show_private=False)
self.mkpath(self.build_doc)
log.info('epydoc %s to %s' % (", ".join(names), self.build_doc))
html_writer.write(self.build_doc)
class clean(_clean):
user_options = _clean.user_options + doc_option
def initialize_options(self):
_clean.initialize_options(self)
self.build_doc = None
def finalize_options(self):
_clean.finalize_options(self)
self.set_undefined_options('build', ('build_doc', 'build_doc'))
def run(self):
if self.all:
if os.path.exists(self.build_doc):
remove_tree(self.build_doc, dry_run=self.dry_run)
else:
log.debug("%s doesn't exist -- can't clean it", self.build_doc)
_clean.run(self)
if MAJOR <= 2 and MINOR <= 3:
from glob import glob
from distutils.util import convert_path
class distclass(Distribution):
def __init__(self, *args, **kwargs):
self.package_data = None
Distribution.__init__(self, *args, **kwargs)
else:
distclass = Distribution
ann = re.compile(r"([ \t]*)@([_a-zA-Z][_a-zA-Z0-9]*)([ \t\n\r]+def[ \t]+)([_a-zA-Z][_a-zA-Z0-9]*)")
line = re.compile(r"\n([ \t]*)[^ \t\n#]+")
class build_py(preprocessor, _build_py):
if MAJOR <= 2 and MINOR <= 3:
def initialize_options(self):
_build_py.initialize_options(self)
self.package_data = None
def finalize_options(self):
_build_py.finalize_options(self)
self.package_data = self.distribution.package_data
self.data_files = self.get_data_files()
def get_data_files (self):
data = []
if not self.packages:
return data
for package in self.packages:
# Locate package source directory
src_dir = self.get_package_dir(package)
# Compute package build directory
build_dir = os.path.join(*([self.build_lib] + package.split('.')))
# Length of path to strip from found files
plen = 0
if src_dir:
plen = len(src_dir)+1
# Strip directory from globbed filenames
filenames = [file[plen:]
for file in self.find_data_files(package, src_dir)]
data.append((package, src_dir, build_dir, filenames))
return data
def find_data_files (self, package, src_dir):
globs = (self.package_data.get('', [])
+ self.package_data.get(package, []))
files = []
for pattern in globs:
# Each pattern has to be converted to a platform-specific path
filelist = glob(os.path.join(src_dir, convert_path(pattern)))
# Files that match more than one pattern are only added once
files.extend([fn for fn in filelist if fn not in files])
return files
def build_package_data (self):
lastdir = None
for package, src_dir, build_dir, filenames in self.data_files:
for filename in filenames:
target = os.path.join(build_dir, filename)
self.mkpath(os.path.dirname(target))
self.copy_file(os.path.join(src_dir, filename), target,
preserve_mode=False)
def build_packages(self):
_build_py.build_packages(self)
self.build_package_data()
# end if MAJOR <= 2 and MINOR <= 3
def backport(self, input):
output = ""
pos = 0
while True:
m = ann.search(input, pos)
if m:
indent, decorator, idef, function = m.groups()
output += input[pos:m.start()]
output += "%s#@%s%s%s" % (indent, decorator, idef, function)
pos = m.end()
subst = "\n%s%s = %s(%s)\n" % (indent, function, decorator, function)
npos = pos
while True:
n = line.search(input, npos)
if not n:
input += subst
break
if len(n.group(1)) <= len(indent):
idx = n.start()
input = input[:idx] + subst + input[idx:]
break
npos = n.end()
else:
break
output += input[pos:]
return output
def actor(self, src, dst):
base, ext = os.path.splitext(src)
if ext == ".py" and MAJOR <= 2 and MINOR <= 3:
return "backporting", self.backport
else:
return None, None
def pclfile(xmlfile):
return "%s.pcl" % os.path.splitext(xmlfile)[0]
class install_lib(_install_lib):
def get_outputs(self):
outputs = _install_lib.get_outputs(self)
extra = []
for of in outputs:
if os.path.basename(of) == "amqp-0-10-qpid-errata-stripped.xml":
extra.append(pclfile(of))
return outputs + extra
def install(self):
outfiles = _install_lib.install(self)
extra = []
for of in outfiles:
if os.path.basename(of) == "amqp-0-10-qpid-errata-stripped.xml":
tgt = pclfile(of)
if self.force or newer(of, tgt):
log.info("caching %s to %s" % (of, os.path.basename(tgt)))
if not self.dry_run:
from qpid.ops import load_types
load_types(of)
extra.append(tgt)
return outfiles + extra
scripts = ["qpid-python-test"]
if platform.system() == "Windows":
scripts.append("qpid-python-test.bat")
setup(name="qpid-python",
version="1.36.1-SNAPSHOT",
author="Apache Qpid",
author_email="users@qpid.apache.org",
packages=["mllib", "qpid", "qpid.messaging", "qpid.tests",
"qpid.tests.messaging", "qpid.saslmech", "qpid.tests.saslmech",
"qpid_tests", "qpid_tests.broker_1_0", "qpid_tests.broker_0_10",
"qpid_tests.broker_0_9", "qpid_tests.broker_0_8"],
package_data={"qpid": ["specs/*.dtd", "specs/*.xml"]},
scripts=scripts,
url="http://qpid.apache.org/",
license="Apache Software License",
description="Python client implementation and AMQP conformance tests for Apache Qpid",
cmdclass={"build": build,
"build_py": build_py,
"build_doc": build_doc,
"clean": clean,
"install_lib": install_lib},
distclass=distclass)