remove _setup

This commit is contained in:
ndparker 2014-11-01 23:57:47 +01:00
parent 1ce76d20dd
commit 5d86fbf444
40 changed files with 0 additions and 6492 deletions

View File

@ -1,39 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
================
Package _setup
================
This package provides tools for main package setup.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import os as _os
import sys as _sys
if _sys.version_info[0] == 2:
__path__ = [_os.path.join(__path__[0], 'py2')]
__author__ = __author__.decode('latin-1')
elif _sys.version_info[0] == 3:
__path__ = [_os.path.join(__path__[0], 'py3')]
else:
raise RuntimeError("Unsupported python version")
del _os, _sys
from _setup.setup import run # pylint: disable = W0611

View File

@ -1,244 +0,0 @@
/*
* Copyright 2006, 2007, 2008, 2009, 2010, 2011
* Andr\xe9 Malo or his licensors, as applicable
*
* Licensed 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.
*/
/*
* central naming stuff
*/
#ifndef SETUP_CEXT_H
#define SETUP_CEXT_H
#ifndef EXT_MODULE
#error EXT_MODULE must be defined outside of this file (-DEXT_MODULE=...)
#endif
/*
* include core header files
*/
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "structmember.h"
/*
* define our helper macros depending on the stuff above
*/
#define STRINGIFY(n) STRINGIFY_HELPER(n)
#define STRINGIFY_HELPER(n) #n
#define CONCATENATE(first, second) CONCATENATE_HELPER(first, second)
#define CONCATENATE_HELPER(first, second) first##second
#define EXT_MODULE_NAME STRINGIFY(EXT_MODULE)
#ifdef EXT_PACKAGE
#define EXT_PACKAGE_NAME STRINGIFY(EXT_PACKAGE)
#define EXT_MODULE_PATH EXT_PACKAGE_NAME "." EXT_MODULE_NAME
#else
#define EXT_PACKAGE_NAME ""
#define EXT_MODULE_PATH EXT_MODULE_NAME
#endif
#define EXT_DOCS_VAR CONCATENATE(var, CONCATENATE(EXT_MODULE, __doc__))
#define EXT_METHODS_VAR CONCATENATE(var, CONCATENATE(EXT_MODULE, _methods))
#define EXT_METHODS static PyMethodDef EXT_METHODS_VAR[]
#define EXT_DEFINE_VAR CONCATENATE(var, CONCATENATE(EXT_MODULE, _module))
/* Py3K Support */
#if PY_MAJOR_VERSION >= 3
#define EXT3
#ifndef PyMODINIT_FUNC
#define EXT_INIT_FUNC PyObject *CONCATENATE(PyInit_, EXT_MODULE)(void)
#else
#define EXT_INIT_FUNC PyMODINIT_FUNC CONCATENATE(PyInit_, EXT_MODULE)(void)
#endif
#define EXT_DEFINE(name, methods, doc) \
static struct PyModuleDef EXT_DEFINE_VAR = { \
PyModuleDef_HEAD_INIT, \
name, \
doc, \
-1, \
methods, \
NULL, \
NULL, \
NULL, \
NULL \
}
#define EXT_CREATE(def) (PyModule_Create(def))
#define EXT_INIT_ERROR(module) do {Py_XDECREF(module); return NULL;} while(0)
#define EXT_INIT_RETURN(module) return module
#else /* end py3k */
#define EXT2
#ifndef PyMODINIT_FUNC
#define EXT_INIT_FUNC void CONCATENATE(init, EXT_MODULE)(void)
#else
#define EXT_INIT_FUNC PyMODINIT_FUNC CONCATENATE(init, EXT_MODULE)(void)
#endif
#define EXT_DEFINE__STRUCT \
CONCATENATE(struct, CONCATENATE(EXT_MODULE, _module))
struct EXT_DEFINE__STRUCT {
char *m_name;
char *m_doc;
PyMethodDef *m_methods;
};
#define EXT_DEFINE(name, methods, doc) \
static struct EXT_DEFINE__STRUCT EXT_DEFINE_VAR = { \
name, \
doc, \
methods \
}
#define EXT_CREATE(def) ((def)->m_doc \
? Py_InitModule3((def)->m_name, (def)->m_methods, (def)->m_doc) \
: Py_InitModule((def)->m_name, (def)->m_methods) \
)
#define EXT_INIT_ERROR(module) return
#define EXT_INIT_RETURN(module) return
#endif /* end py2K */
#define EXT_INIT_TYPE(module, type) do { \
if (PyType_Ready(type) < 0) \
EXT_INIT_ERROR(module); \
} while (0)
#define EXT_ADD_TYPE(module, name, type) do { \
Py_INCREF(type); \
if (PyModule_AddObject(module, name, (PyObject *)(type)) < 0) \
EXT_INIT_ERROR(module); \
} while (0)
#define EXT_ADD_UNICODE(module, name, string, encoding) do { \
if (PyModule_AddObject( \
module, \
name, \
PyUnicode_Decode( \
string, \
sizeof(string) - 1, \
encoding, \
"strict" \
)) < 0) \
EXT_INIT_ERROR(module); \
} while (0)
#define EXT_ADD_STRING(module, name, string) do { \
if (PyModule_AddStringConstant(module, name, string) < 0) \
EXT_INIT_ERROR(module); \
} while (0)
#define EXT_ADD_INT(module, name, number) do { \
if (PyModule_AddIntConstant(module, name, number) < 0) \
EXT_INIT_ERROR(module); \
} while (0)
/* PEP 353 support, implemented as of python 2.5 */
#if PY_VERSION_HEX < 0x02050000
typedef int Py_ssize_t;
#define PyInt_FromSsize_t(arg) PyInt_FromLong((long)arg)
#define PyInt_AsSsize_t(arg) (int)PyInt_AsLong(arg)
#define PY_SSIZE_T_MAX ((Py_ssize_t)INT_MAX)
#endif
/*
* some helper macros (Python 2.4)
*/
#ifndef Py_VISIT
#define Py_VISIT(op) do { \
if (op) { \
int vret = visit((op), arg); \
if (vret) return vret; \
} \
} while (0)
#endif
#ifdef Py_CLEAR
#undef Py_CLEAR
#endif
#define Py_CLEAR(op) do { \
if (op) { \
PyObject *tmp__ = (PyObject *)(op); \
(op) = NULL; \
Py_DECREF(tmp__); \
} \
} while (0)
#ifndef Py_RETURN_NONE
#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
#endif
#ifndef Py_RETURN_FALSE
#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
#endif
#ifndef Py_RETURN_TRUE
#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
#endif
/* Macros for inline documentation. (Python 2.3) */
#ifndef PyDoc_VAR
#define PyDoc_VAR(name) static char name[]
#endif
#ifndef PyDoc_STRVAR
#define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str)
#endif
#ifndef PyDoc_STR
#ifdef WITH_DOC_STRINGS
#define PyDoc_STR(str) str
#else
#define PyDoc_STR(str) ""
#endif
#endif
/* Basestring check (basestring introduced in Python 2.3) */
#if PY_VERSION_HEX < 0x02030000
#define BaseString_Check(type) ( \
PyObject_TypeCheck((type), &PyString_Type) \
|| PyObject_TypeCheck((type), &PyUnicode_Type) \
)
#else
#define BaseString_Check(type) PyObject_TypeCheck((type), &PyBaseString_Type)
#endif
#define GENERIC_ALLOC(type) \
((void *)((PyTypeObject *)type)->tp_alloc(type, (Py_ssize_t)0))
/* PyPy doesn't define it */
#ifndef PyType_IS_GC
#define PyType_IS_GC(t) PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
#endif
#define DEFINE_GENERIC_DEALLOC(prefix) \
static void prefix##_dealloc(void *self) \
{ \
if (PyType_IS_GC(((PyObject *)self)->ob_type)) \
PyObject_GC_UnTrack(self); \
(void)prefix##_clear(self); \
((PyObject *)self)->ob_type->tp_free((PyObject *)self); \
}
#endif /* SETUP_CEXT_H */

View File

@ -1,27 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
================
Package _setup
================
This package provides tools for main package setup.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
from _setup.setup import run # pylint: disable = W0611

View File

@ -1,267 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
===================
Command extenders
===================
Command extenders.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
__test__ = False
from distutils import fancy_getopt as _fancy_getopt
from distutils.command import build as _build
from distutils.command import build_ext as _build_ext
from distutils.command import install as _install
from distutils.command import install_data as _install_data
from distutils.command import install_lib as _install_lib
import os as _os
from _setup.util import log
_option_defaults = {}
_option_inherits = {}
_option_finalizers = {}
_command_mapping = {
'install': 'Install',
'install_data': 'InstallData',
'install_lib': 'InstallLib',
'build': 'Build',
'build_ext': 'BuildExt',
}
def add_option(command, long_name, help_text, short_name=None, default=None,
inherit=None):
""" Add an option """
try:
command_class = globals()[_command_mapping[command]]
except KeyError:
raise ValueError("Unknown command %r" % (command,))
for opt in command_class.user_options:
if opt[0] == long_name:
break
else:
opt = (long_name, short_name, help_text)
command_class.user_options.append(opt)
if not long_name.endswith('='):
command_class.boolean_options.append(long_name)
attr_name = _fancy_getopt.translate_longopt(long_name)
else:
attr_name = _fancy_getopt.translate_longopt(long_name[:-1])
if not _option_defaults.has_key(command):
_option_defaults[command] = []
if inherit is not None:
if isinstance(inherit, (str, unicode)):
inherit = [inherit]
for i_inherit in inherit:
add_option(
i_inherit, long_name, help_text, short_name, default
)
default = None
if not _option_inherits.has_key(command):
_option_inherits[command] = []
for i_inherit in inherit:
for i_command, opt_name in _option_inherits[command]:
if i_command == i_inherit and opt_name == attr_name:
break
else:
_option_inherits[command].append((i_inherit, attr_name))
_option_defaults[command].append((attr_name, default))
def add_finalizer(command, key, func):
""" Add finalizer """
if not _option_finalizers.has_key(command):
_option_finalizers[command] = {}
if not _option_finalizers[command].has_key(key):
_option_finalizers[command][key] = func
class Install(_install.install):
""" Extended installer to reflect the additional data options """
user_options = _install.install.user_options + [
('single-version-externally-managed', None,
"Compat option. Does not a thing."),
]
boolean_options = _install.install.boolean_options + [
'single-version-externally-managed'
]
def initialize_options(self):
""" Prepare for new options """
_install.install.initialize_options(self)
self.single_version_externally_managed = None
if _option_defaults.has_key('install'):
for opt_name, default in _option_defaults['install']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_install.install.finalize_options(self)
if _option_inherits.has_key('install'):
for parent, opt_name in _option_inherits['install']:
self.set_undefined_options(parent, (opt_name, opt_name))
if _option_finalizers.has_key('install'):
for func in _option_finalizers['install'].values():
func(self)
class InstallData(_install_data.install_data):
""" Extended data installer """
user_options = _install_data.install_data.user_options + []
boolean_options = _install_data.install_data.boolean_options + []
def initialize_options(self):
""" Prepare for new options """
_install_data.install_data.initialize_options(self)
if _option_defaults.has_key('install_data'):
for opt_name, default in _option_defaults['install_data']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_install_data.install_data.finalize_options(self)
if _option_inherits.has_key('install_data'):
for parent, opt_name in _option_inherits['install_data']:
self.set_undefined_options(parent, (opt_name, opt_name))
if _option_finalizers.has_key('install_data'):
for func in _option_finalizers['install_data'].values():
func(self)
class InstallLib(_install_lib.install_lib):
""" Extended lib installer """
user_options = _install_lib.install_lib.user_options + []
boolean_options = _install_lib.install_lib.boolean_options + []
def initialize_options(self):
""" Prepare for new options """
_install_lib.install_lib.initialize_options(self)
if _option_defaults.has_key('install_lib'):
for opt_name, default in _option_defaults['install_lib']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_install_lib.install_lib.finalize_options(self)
if _option_inherits.has_key('install_lib'):
for parent, opt_name in _option_inherits['install_lib']:
self.set_undefined_options(parent, (opt_name, opt_name))
if _option_finalizers.has_key('install_lib'):
for func in _option_finalizers['install_lib'].values():
func(self)
class BuildExt(_build_ext.build_ext):
"""
Extended extension builder class
This class allows extensions to provide a ``check_prerequisites`` method
which is called before actually building it. The method takes the
`BuildExt` instance and returns whether the extension should be skipped or
not.
"""
def initialize_options(self):
""" Prepare for new options """
_build_ext.build_ext.initialize_options(self)
if _option_defaults.has_key('build_ext'):
for opt_name, default in _option_defaults['build_ext']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_build_ext.build_ext.finalize_options(self)
if _option_inherits.has_key('build_ext'):
for parent, opt_name in _option_inherits['build_ext']:
self.set_undefined_options(parent, (opt_name, opt_name))
if _option_finalizers.has_key('build_ext'):
for func in _option_finalizers['build_ext'].values():
func(self)
def build_extension(self, ext):
"""
Build C extension - with extended functionality
The following features are added here:
- ``ext.check_prerequisites`` is called before the extension is being
built. See `Extension` for details. If the method does not exist,
simply no check will be run.
- The macros ``EXT_PACKAGE`` and ``EXT_MODULE`` will be filled (or
unset) depending on the extensions name, but only if they are not
already defined.
:Parameters:
`ext` : `Extension`
The extension to build. If it's a pure
``distutils.core.Extension``, simply no prequisites check is
applied.
:Return: whatever ``distutils.command.build_ext.build_ext`` returns
:Rtype: any
"""
# handle name macros
macros = dict(ext.define_macros or ())
tup = ext.name.split('.')
if len(tup) == 1:
pkg, mod = None, tup[0]
else:
pkg, mod = '.'.join(tup[:-1]), tup[-1]
if pkg is not None and 'EXT_PACKAGE' not in macros:
ext.define_macros.append(('EXT_PACKAGE', pkg))
if 'EXT_MODULE' not in macros:
ext.define_macros.append(('EXT_MODULE', mod))
if pkg is None:
macros = dict(ext.undef_macros or ())
if 'EXT_PACKAGE' not in macros:
ext.undef_macros.append('EXT_PACKAGE')
# handle prereq checks
try:
checker = ext.check_prerequisites
except AttributeError:
pass
else:
if checker(self):
log.info("Skipping %s extension" % ext.name)
return
return _build_ext.build_ext.build_extension(self, ext)
class Build(_build.build):
def initialize_options(self):
""" Prepare for new options """
_build.build.initialize_options(self)
if _option_defaults.has_key('build'):
for opt_name, default in _option_defaults['build']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_build.build.finalize_options(self)
if _option_inherits.has_key('build'):
for parent, opt_name in _option_inherits['build']:
self.set_undefined_options(parent, (opt_name, opt_name))
if _option_finalizers.has_key('build'):
for func in _option_finalizers['build'].values():
func(self)

View File

@ -1,165 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
===================
Data distribution
===================
This module provides tools to simplify data distribution.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
from distutils import filelist as _filelist
import os as _os
import posixpath as _posixpath
import sys as _sys
from _setup import commands as _commands
def splitpath(path):
""" Split a path """
drive, path = '', _os.path.normpath(path)
try:
splitunc = _os.path.splitunc
except AttributeError:
pass
else:
drive, path = splitunc(path)
if not drive:
drive, path = _os.path.splitdrive(path)
elems = []
try:
sep = _os.path.sep
except AttributeError:
sep = _os.path.join('1', '2')[1:-1]
while 1:
prefix, path = _os.path.split(path)
elems.append(path)
if prefix in ('', sep):
drive = _os.path.join(drive, prefix)
break
path = prefix
elems.reverse()
return drive, elems
def finalizer(installer):
""" Finalize install_data """
data_files = []
for item in installer.data_files:
if not isinstance(item, Data):
data_files.append(item)
continue
data_files.extend(item.flatten(installer))
installer.data_files = data_files
class Data(object):
""" File list container """
def __init__(self, files, target=None, preserve=0, strip=0,
prefix=None):
""" Initialization """
self._files = files
self._target = target
self._preserve = preserve
self._strip = strip
self._prefix = prefix
self.fixup_commands()
def fixup_commands(self):
pass
def from_templates(cls, *templates, **kwargs):
""" Initialize from template """
files = _filelist.FileList()
for tpl in templates:
for line in tpl.split(';'):
files.process_template_line(line.strip())
files.sort()
files.remove_duplicates()
result = []
for filename in files.files:
_, elems = splitpath(filename)
if '.svn' in elems or '.git' in elems:
continue
result.append(filename)
return cls(result, **kwargs)
from_templates = classmethod(from_templates)
def flatten(self, installer):
""" Flatten the file list to (target, file) tuples """
# pylint: disable = W0613
if self._prefix:
_, prefix = splitpath(self._prefix)
telems = prefix
else:
telems = []
tmap = {}
for fname in self._files:
(_, name), target = splitpath(fname), telems
if self._preserve:
if self._strip:
name = name[max(0, min(self._strip, len(name) - 1)):]
if len(name) > 1:
target = telems + name[:-1]
tmap.setdefault(_posixpath.join(*target), []).append(fname)
return tmap.items()
class Documentation(Data):
""" Documentation container """
def fixup_commands(self):
_commands.add_option('install_data', 'without-docs',
help_text='Do not install documentation files',
inherit='install',
)
_commands.add_finalizer('install_data', 'documentation', finalizer)
def flatten(self, installer):
""" Check if docs should be installed at all """
if installer.without_docs:
return []
return Data.flatten(self, installer)
class Manpages(Documentation):
""" Manpages container """
def dispatch(cls, files):
""" Automatically dispatch manpages to their target directories """
mpmap = {}
for manpage in files:
normalized = _os.path.normpath(manpage)
_, ext = _os.path.splitext(normalized)
if ext.startswith(_os.path.extsep):
ext = ext[len(_os.path.extsep):]
mpmap.setdefault(ext, []).append(manpage)
return [cls(manpages, prefix=_posixpath.join(
'share', 'man', 'man%s' % section,
)) for section, manpages in mpmap.items()]
dispatch = classmethod(dispatch)
def flatten(self, installer):
""" Check if manpages are suitable """
if _sys.platform == 'win32':
return []
return Documentation.flatten(self, installer)

View File

@ -1,25 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
====================
Package _setup.dev
====================
Development tools, not distributed.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"

View File

@ -1,258 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2006, 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
=================================
Support for code analysis tools
=================================
Support for code analysis tools.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import re as _re
import sys as _sys
from _setup import term as _term
from _setup import shell as _shell
class NotFinished(Exception):
""" Exception used for message passing in the stream filter """
class NotParseable(Exception):
""" Exception used for message passing in the stream filter """
class SpecialMessage(Exception):
""" Exception used for message passing in the stream filter """
class FilterStream(object):
""" Stream filter """
_LINERE = _re.compile(r'''
(?P<name>[^:]+)
:
(?P<lineno>\d+)
:\s+
\[(?P<mid>[^\],]+)(?:,\s+(?P<func>[^\]]+))?\]
\s+
(?P<desc>.*)
''', _re.X)
_SIMRE = _re.compile(r'in (?P<number>\d+) files')
_CYCRE = _re.compile(r'\((?P<cycle>[^)]+)\)')
def __init__(self, term, stream=_sys.stdout):
self.written = False
self._stream = stream
self._lastname = None
self._cycled = False
self._term = dict(term)
self._buffer = ''
def write(self, towrite):
""" Stream write function """
self._buffer += towrite
term = self._term
while True:
try:
name, lineno, mid, func, desc = self._parse()
except NotFinished:
break
except SpecialMessage, e:
self._dospecial(e)
continue
except NotParseable, e:
self._print_literal(str(e.args[0]))
continue
if name != self._lastname:
if self._lastname is not None:
self._stream.write("\n")
term['path'] = name
self._stream.write(
"%(BOLD)s>>> %(path)s%(NORMAL)s\n" % term
)
self._lastname = name
self.written = True
term['mid'] = mid
if mid.startswith('E') or mid.startswith('F'):
self._stream.write("%(BOLD)s%(RED)s%(mid)s%(NORMAL)s" % term)
elif mid == 'W0511':
self._stream.write(
"%(BOLD)s%(GREEN)s%(mid)s%(NORMAL)s" % term
)
else:
self._stream.write(
"%(BOLD)s%(YELLOW)s%(mid)s%(NORMAL)s" % term
)
if int(lineno) != 0:
term['lineno'] = lineno
self._stream.write(" (%(lineno)s" % term)
if func:
term['func'] = func
self._stream.write(
", %(BOLD)s%(YELLOW)s%(func)s%(NORMAL)s" % term
)
self._stream.write(')')
self._stream.write(": %s\n" % desc)
self._stream.flush()
return
def _print_literal(self, line):
""" Print literal """
suppress = (
line.startswith('Unable to get imported names for ') or
line.startswith("Exception exceptions.RuntimeError: 'generator "
"ignored GeneratorExit' in <generator object at") or
line.startswith("Exception RuntimeError: 'generator "
"ignored GeneratorExit' in <generator object") or
not line.strip()
)
if not suppress:
self._stream.write("%s\n" % line)
self._stream.flush()
self.written = True
def _dospecial(self, e):
""" Deal with special messages """
if e.args[0] == 'R0401':
pos = self._buffer.find('\n')
line, self._buffer = (
self._buffer[:pos + 1], self._buffer[pos + 1:]
)
term = self._term
term['mid'] = e.args[0]
if not self._cycled:
self._cycled = True
self._stream.write('\n')
self._stream.write(
"%(BOLD)s%(YELLOW)s%(mid)s%(NORMAL)s" % term
)
self._stream.write(": Cyclic imports\n")
match = self._CYCRE.search(e.args[1])
term['cycle'] = match.group('cycle')
self._stream.write("%(BOLD)s@@@ %(NORMAL)s%(cycle)s\n" % term)
self._stream.flush()
self.written = True
elif e.args[0] == 'R0801':
match = self._SIMRE.search(e.args[1])
if not match:
raise AssertionError(
'Could not determine number of similar files'
)
numfiles = int(match.group('number'))
pos = -1
for _ in range(numfiles + 1):
pos = self._buffer.find('\n', pos + 1)
if pos >= 0:
lines = self._buffer[:pos + 1]
self._buffer = self._buffer[pos + 1:]
term = self._term
self._stream.write("\n")
for name in lines.splitlines()[1:]:
name = name.rstrip()[2:]
term['path'] = name
self._stream.write(
"%(BOLD)s=== %(path)s%(NORMAL)s\n" % term
)
self._lastname = name
term['mid'] = e.args[0]
self._stream.write(
"%(BOLD)s%(YELLOW)s%(mid)s%(NORMAL)s" % term
)
self._stream.write(": %s\n" % e.args[1])
self._stream.flush()
self.written = True
def _parse(self):
""" Parse output """
if '\n' not in self._buffer:
raise NotFinished()
line = self._buffer[:self._buffer.find('\n') + 1]
self._buffer = self._buffer[len(line):]
line = line.rstrip()
match = self._LINERE.match(line)
if not match:
raise NotParseable(line)
mid = match.group('mid')
if mid in ('R0801', 'R0401'):
self._buffer = "%s\n%s" % (line, self._buffer)
raise SpecialMessage(mid, match.group('desc'))
return match.group('name', 'lineno', 'mid', 'func', 'desc')
def run(config, *args):
""" Run pylint """
try:
from pylint import lint
from pylint.reporters import text
except ImportError:
return 2
if config is None:
config = _shell.native('pylint.conf')
argv = ['--rcfile', config,
'--reports', 'no',
'--output-format', 'parseable',
'--include-ids', 'yes'
]
stream = FilterStream(_term.terminfo())
old_stderr = _sys.stderr
try:
# pylint: disable = E1101
_sys.stderr = stream
from pylint import __pkginfo__
if __pkginfo__.numversion < (0, 13):
# The lint tool is not very user friendly, so we need a hack here.
lint.REPORTER_OPT_MAP['parseable'] = \
lambda: text.TextReporter2(stream)
reporter = text.TextReporter2(stream)
else:
reporter = text.ParseableTextReporter(stream)
lint.REPORTER_OPT_MAP['parseable'] = lambda: reporter
for path in args:
try:
try:
lint.Run(argv + [path], reporter=reporter)
except SystemExit:
pass # don't accept the exit. strange errors happen...
if stream.written:
print
stream.written = False
except KeyboardInterrupt:
print
raise
finally:
_sys.stderr = old_stderr
return 0

View File

@ -1,31 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2006, 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
=================================
Support for code analysis tools
=================================
Support for code analysis tools.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
def pylint(config, *args):
""" Run pylint """
from _setup.dev import _pylint
return _pylint.run(config, *args)

View File

@ -1,131 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
==================
API doc builders
==================
API doc builders.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import os as _os
import re as _re
from _setup import shell as _shell
from _setup import term as _term
from _setup import util as _util
def _cleanup_epydoc(target):
"""
Cleanup epydoc generated files
This removes the epydoc-footer. It changes every release because of the
timestamp. That creates bad diffs (accidently it's also invalid html).
"""
search = _re.compile(r'<table[^<>]+width="100%%"').search
for filename in _shell.files(target, '*.html'):
fp = open(filename, 'r')
try:
html = fp.read()
finally:
fp.close()
match = search(html)
if match:
start = match.start()
end = html.find('</table>', start)
if end >= 0:
end += len('</table>') + 1
html = html[:start] + html[end:]
fp = open(filename, 'w')
try:
fp.write(html)
finally:
fp.close()
_VERSION_SEARCH = _re.compile(
r'\bversion\s+(?P<major>\d+)\.(?P<minor>\d+)'
).search
def epydoc(**kwargs):
""" Run epydoc """
# pylint: disable = R0912
prog = kwargs.get('epydoc') or 'epydoc'
if not _os.path.dirname(_os.path.normpath(prog)):
prog = _shell.frompath(prog)
if not prog:
_term.red("%(epydoc)s not found",
epydoc=kwargs.get('epydoc') or 'epydoc',
)
return False
version = _VERSION_SEARCH(_shell.spawn(prog, "--version", stdout=True))
if version is not None:
try:
version = tuple(map(int, version.group('major', 'minor')))
except (TypeError, ValueError):
version = None
if version is None:
_term.red("%(prog)s version not recognized" % locals())
return False
if version < (3, 0):
_term.red("%(prog)s is too old %(version)r < (3, 0)" % locals())
return False
env = dict(_os.environ)
prepend = kwargs.get('prepend')
if prepend:
toprepend = _os.pathsep.join(map(str, prepend))
if 'PYTHONPATH' in env:
env['PYTHONPATH'] = _os.pathsep.join((
toprepend, env['PYTHONPATH']
))
else:
env['PYTHONPATH'] = toprepend
append = kwargs.get('append')
if append:
toappend = _os.pathsep.join(map(str, append))
if 'PYTHONPATH' in env:
env['PYTHONPATH'] = _os.pathsep.join((
env['PYTHONPATH'], toappend
))
else:
env['PYTHONPATH'] = toappend
moreenv = kwargs.get('env')
if moreenv:
env.update(moreenv)
config = kwargs.get('config') or _shell.native('docs/epydoc.conf')
argv = [prog, '--config', config]
res = not _shell.spawn(*argv, **{'env': env})
if res:
cfg = _util.SafeConfigParser()
cfg.read(config)
try:
target = dict(cfg.items('epydoc'))['target']
except KeyError:
pass
else:
_cleanup_epydoc(target)
return res

View File

@ -1,50 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
===================
User doc builders
===================
User doc builders.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import os as _os
from _setup import shell as _shell
from _setup import term as _term
def sphinx(**kwargs):
""" Run sphinx """
prog = _shell.frompath('sphinx-build')
if prog is None:
_term.red("sphinx-build not found")
return False
env = dict(_os.environ)
argv = [
prog, '-a',
'-d', _os.path.join(kwargs['build'], 'doctrees'),
'-b', 'html',
kwargs['source'],
kwargs['target'],
]
return not _shell.spawn(*argv, **{'env': env})

View File

@ -1,51 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
================
dist utilities
================
dist utilities.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import sys as _sys
from _setup import shell as _shell
def run_setup(*args, **kwargs):
""" Run setup """
if 'setup' in kwargs:
script = kwargs.get('setup') or 'setup.py'
del kwargs['setup']
else:
script = 'setup.py'
if 'fakeroot' in kwargs:
fakeroot = kwargs['fakeroot']
del kwargs['fakeroot']
else:
fakeroot = None
if kwargs:
raise TypeError("Unrecognized keyword parameters")
script = _shell.native(script)
argv = [_sys.executable, script] + list(args)
if fakeroot:
argv.insert(0, fakeroot)
return not _shell.spawn(*argv)

View File

@ -1,254 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
===================
C extension tools
===================
C extension tools.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
__test__ = False
from distutils import core as _core
from distutils import errors as _distutils_errors
import os as _os
import posixpath as _posixpath
import shutil as _shutil
import tempfile as _tempfile
from _setup import commands as _commands
from _setup.util import log
def _install_finalizer(installer):
if installer.without_c_extensions:
installer.distribution.ext_modules = []
def _build_finalizer(builder):
if builder.without_c_extensions:
builder.extensions = []
class Extension(_core.Extension):
"""
Extension with prerequisite check interface
If your check is cacheable (during the setup run), override
`cached_check_prerequisites`, `check_prerequisites` otherwise.
:IVariables:
`cached_check` : ``bool``
The cached check result
"""
cached_check = None
def __init__(self, *args, **kwargs):
""" Initialization """
if kwargs.has_key('depends'):
self.depends = kwargs['depends'] or []
else:
self.depends = []
_core.Extension.__init__(self, *args, **kwargs)
# add include path
included = _posixpath.join('_setup', 'include')
if included not in self.include_dirs:
self.include_dirs.append(included)
# add cext.h to the dependencies
cext_h = _posixpath.join(included, 'cext.h')
if cext_h not in self.depends:
self.depends.append(cext_h)
_commands.add_option('install_lib', 'without-c-extensions',
help_text='Don\'t install C extensions',
inherit='install',
)
_commands.add_finalizer('install_lib', 'c-extensions',
_install_finalizer
)
_commands.add_option('build_ext', 'without-c-extensions',
help_text='Don\'t build C extensions',
inherit=('build', 'install_lib'),
)
_commands.add_finalizer('build_ext', 'c-extensions', _build_finalizer)
def check_prerequisites(self, build):
"""
Check prerequisites
The check should cover all dependencies needed for the extension to
be built and run. The method can do the following:
- return a false value: the extension will be built
- return a true value: the extension will be skipped. This is useful
for optional extensions
- raise an exception. This is useful for mandatory extensions
If the check result is cacheable (during the setup run), override
`cached_check_prerequisites` instead.
:Parameters:
`build` : `BuildExt`
The extension builder
:Return: Skip the extension?
:Rtype: ``bool``
"""
if self.cached_check is None:
log.debug("PREREQ check for %s" % self.name)
self.cached_check = self.cached_check_prerequisites(build)
else:
log.debug("PREREQ check for %s (cached)" % self.name)
return self.cached_check
def cached_check_prerequisites(self, build):
"""
Check prerequisites
The check should cover all dependencies needed for the extension to
be built and run. The method can do the following:
- return a false value: the extension will be built
- return a true value: the extension will be skipped. This is useful
for optional extensions
- raise an exception. This is useful for mandatory extensions
If the check result is *not* cacheable (during the setup run),
override `check_prerequisites` instead.
:Parameters:
`build` : `BuildExt`
The extension builder
:Return: Skip the extension?
:Rtype: ``bool``
"""
# pylint: disable = W0613
log.debug("Nothing to check for %s!" % self.name)
return False
class ConfTest(object):
"""
Single conftest abstraction
:IVariables:
`_tempdir` : ``str``
The tempdir created for this test
`src` : ``str``
Name of the source file
`target` : ``str``
Target filename
`compiler` : ``CCompiler``
compiler instance
`obj` : ``list``
List of object filenames (``[str, ...]``)
"""
_tempdir = None
def __init__(self, build, source):
"""
Initialization
:Parameters:
`build` : ``distuils.command.build_ext.build_ext``
builder instance
`source` : ``str``
Source of the file to compile
"""
self._tempdir = tempdir = _tempfile.mkdtemp()
src = _os.path.join(tempdir, 'conftest.c')
fp = open(src, 'w')
try:
fp.write(source)
finally:
fp.close()
self.src = src
self.compiler = compiler = build.compiler
self.target = _os.path.join(tempdir, 'conftest')
self.obj = compiler.object_filenames([src], output_dir=tempdir)
def __del__(self):
""" Destruction """
self.destroy()
def destroy(self):
""" Destroy the conftest leftovers on disk """
tempdir, self._tempdir = self._tempdir, None
if tempdir is not None:
_shutil.rmtree(tempdir)
def compile(self, **kwargs):
"""
Compile the conftest
:Parameters:
`kwargs` : ``dict``
Optional keyword parameters for the compiler call
:Return: Was the compilation successful?
:Rtype: ``bool``
"""
kwargs['output_dir'] = self._tempdir
try:
self.compiler.compile([self.src], **kwargs)
except _distutils_errors.CompileError:
return False
return True
def link(self, **kwargs):
r"""
Link the conftest
Before you can link the conftest objects they need to be `compile`\d.
:Parameters:
`kwargs` : ``dict``
Optional keyword parameters for the linker call
:Return: Was the linking successful?
:Rtype: ``bool``
"""
try:
self.compiler.link_executable(self.obj, self.target, **kwargs)
except _distutils_errors.LinkError:
return False
return True
def pipe(self, mode="r"):
r"""
Execute the conftest binary and connect to it using a pipe
Before you can pipe to or from the conftest binary it needs to
be `link`\ed.
:Parameters:
`mode` : ``str``
Pipe mode - r/w
:Return: The open pipe
:Rtype: ``file``
"""
return _os.popen(self.compiler.executable_filename(self.target), mode)

View File

@ -1,28 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
=====================
Package _setup.make
=====================
Make tools, not distributed.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
# pylint: disable = W0611
from _setup.make._make import main, fail, warn, fatal, Target

View File

@ -1,338 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
==================
Simple make base
==================
Simple make base.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import sys as _sys
from _setup import term as _term
class Failure(SystemExit):
""" Failure exception """
def fail(reason):
""" Fail for a reason """
raise Failure(reason)
def warn(message, name=None):
""" Warn """
_term.red("%(NAME)sWarning: %(msg)s",
NAME=name and "%s:" % name or '', msg=message
)
def fatal(reason):
""" Fatal error, immediate stop """
print >> _sys.stderr, reason
_sys.exit(1)
class Target(object):
""" Target base class """
NAME = None
DEPS = None
HIDDEN = False
ERROR = None
def __init__(self, runner):
""" Base __init__ """
self.runner = runner
self.init()
def init(self):
""" Default init hook """
pass
def run(self):
""" Default run hook """
pass
def clean(self, scm=True, dist=False):
""" Default clean hook """
pass
class _Runner(object):
""" Runner """
def __init__(self, *targetscollection):
""" Initialization """
tdict = {}
if not targetscollection:
import __main__
targetscollection = [__main__]
from _setup.make import default_targets
if default_targets not in targetscollection:
targetscollection.append(default_targets)
for targets in targetscollection:
for value in vars(targets).values():
if isinstance(value, type) and issubclass(value, Target) and \
value.NAME is not None:
if value.NAME in tdict:
if issubclass(value, tdict[value.NAME]):
pass # override base target
elif issubclass(tdict[value.NAME], value):
continue # found base later. ignore
else:
warn('Ambiguous target name', value.NAME)
continue
tdict[value.NAME] = value
self._tdict = tdict
self._itdict = {}
def print_help(self):
""" Print make help """
import textwrap as _textwrap
targets = self.targetinfo()
keys = []
for key, info in targets.items():
if not info['hide']:
keys.append(key)
keys.sort()
length = max(map(len, keys))
info = []
for key in keys:
info.append("%s%s" % (
(key + " " * length)[:length + 2],
_textwrap.fill(
targets[key]['desc'].strip(),
subsequent_indent=" " * (length + 2)
),
))
print "Available targets:\n\n" + "\n".join(info)
def targetinfo(self):
""" Extract target information """
result = {}
for name, cls in self._tdict.items():
result[name] = {
'desc': cls.__doc__ or "no description",
'hide': cls.HIDDEN,
'deps': cls.DEPS or (),
}
return result
def _topleveltargets(self):
""" Find all top level targets """
rev = {} # key is a dep of [values]
all_ = self.targetinfo()
for target, info in all_.items():
for dep in info['deps']:
if dep not in all_:
fatal("Unknown target '%s' (dep of %s) -> exit" % (
dep, target
))
rev.setdefault(dep, []).append(target)
return [target for target, info in rev.items() if not info]
def _run(self, target, seen=None):
""" Run a target """
if target.DEPS:
self(*target.DEPS, **{'seen': seen})
if not target.HIDDEN:
_term.yellow(">>> %(name)s", name=target.NAME)
try:
result = target.run()
except KeyboardInterrupt:
result, target.ERROR = False, "^C -> exit"
except Failure, e:
result, target.ERROR = False, "%s: %s" % (target.NAME, e)
except (SystemExit, MemoryError):
raise
except:
import traceback
target.ERROR = "%s errored:\n%s" % (target.NAME, ''.join(
traceback.format_exception(*_sys.exc_info())
))
result = False
else:
if result is None:
result = True
return result
def _clean(self, target, scm, dist, seen=None):
""" Run a target """
if target.DEPS:
self.run_clean(
*target.DEPS, **{'scm': scm, 'dist': dist, 'seen': seen}
)
try:
result = target.clean(scm, dist)
except KeyboardInterrupt:
result, target.ERROR = False, "^C -> exit"
except Failure, e:
result, target.ERROR = False, "%s: %s" % (target.NAME, e)
except (SystemExit, MemoryError):
raise
except:
import traceback
target.ERROR = "%s errored:\n%s" % (target.NAME, ''.join(
traceback.format_exception(*_sys.exc_info())
))
result = False
else:
if result is None:
result = True
return result
def _make_init(self, seen):
""" Make init mapper """
def init(target):
""" Return initialized target """
if target not in seen:
try:
seen[target] = self._tdict[target](self)
except KeyError:
fatal("Unknown target '%s' -> exit" % target)
else:
seen[target] = None
return seen[target]
return init
def run_clean(self, *targets, **kwargs):
""" Run targets """
def pop(name, default=None):
""" Pop """
if name in kwargs:
value = kwargs[name]
del kwargs[name]
if value is None:
return default
return value
else:
return default
seen = pop('seen', {})
scm = pop('scm', True)
dist = pop('dist', False)
if kwargs:
raise TypeError('Unknown keyword parameters')
if not targets:
top_targets = self._topleveltargets()
targets = self.targetinfo()
for item in top_targets:
del targets[item]
targets = targets.keys()
targets.sort()
top_targets.sort()
targets = top_targets + targets
init = self._make_init(seen)
for name in targets:
target = init(name)
if target is not None:
if not self._clean(target, scm=scm, dist=dist, seen=seen):
msg = target.ERROR
if msg is None:
msg = "Clean target %s returned error -> exit" % name
fatal(msg)
def __call__(self, *targets, **kwargs):
""" Run targets """
if 'seen' in kwargs:
seen = kwargs['seen']
del kwargs['seen']
else:
seen = None
if seen is None:
seen = self._itdict
if kwargs:
raise TypeError('Unknown keyword parameters')
init = self._make_init(seen)
for name in targets:
target = init(name)
if target is not None:
if not self._run(target, seen):
msg = target.ERROR
if msg is None:
msg = "Target %s returned error -> exit" % name
fatal(msg)
def main(*args, **kwargs):
"""
main(argv=None, *args, name=None)
Main start point. This function parses the command line and executes the
targets given through `argv`. If there are no targets given, a help output
is generated.
:Parameters:
`argv` : sequence
Command line arguments. If omitted or ``None``, they are picked from
``sys.argv``.
`args` : ``tuple``
The list of modules with targets. If omitted, ``__main__``
is imported and treated as target module. Additionally the mechanism
always adds the `_setup.make` module (this one) to the list in order
to grab some default targets.
`name` : ``str``
Name of the executing module. If omitted or ``None``, ``'__main__'``
is assumed. If the final name is not ``'__main__'``, the function
returns immediately.
"""
try:
name = kwargs['name']
except KeyError:
name = '__main__'
else:
del kwargs['name']
if name is None:
name = '__main__'
try:
argv = kwargs['argv']
except KeyError:
if not args:
args = (None,)
else:
del kwargs['argv']
args = (argv,) + args
if kwargs:
raise TypeError("Unrecognized keyword arguments for main()")
if name == '__main__':
argv, args = args[0], args[1:]
if argv is None:
argv = _sys.argv[1:]
runner = _Runner(*args)
if argv:
runner(*argv)
else:
runner.print_help()

View File

@ -1,110 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
==================
Simple make base
==================
Simple make base.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import os as _os
import sys as _sys
from _setup import make as _make
from _setup import shell as _shell
class MakefileTarget(_make.Target):
""" Create a make file """
NAME = 'makefile'
def run(self):
def escape(value):
""" Escape for make and shell """
return '"%s"' % value.replace(
'\\', '\\\\').replace(
'"', '\\"').replace(
'$', '\\$$')
def decorate(line, prefix='# ', width=78, char='~', padding=' '):
""" Decorate a line """
line = line.center(width - len(prefix))
return '%s%s%s%s%s%s' % (
prefix,
char * (len(line) - len(line.lstrip()) - len(padding)),
padding,
line.strip(),
padding,
char * (len(line) - len(line.rstrip()) - len(padding)),
)
python = escape(_sys.executable)
script = escape(_sys.argv[0])
targets = self.runner.targetinfo()
names = []
for name, info in targets.items():
if not info['hide']:
names.append(name)
names.sort()
fp = open(_shell.native('Makefile'), 'w')
print >> fp, decorate("Generated Makefile, DO NOT EDIT")
print >> fp, decorate("python %s %s" % (
_os.path.basename(script), self.NAME
))
print >> fp
print >> fp, "_default_:"
print >> fp, "\t@%s %s" % (python, script)
for name in names:
print >> fp, "\n"
print >> fp, "# %s" % \
targets[name]['desc'].splitlines()[0].strip()
print >> fp, "%s:" % name
print >> fp, "\t@%s %s %s" % (python, script, escape(name))
print >> fp
extension = self.extend(names)
if extension is not None:
print >> fp, extension
print >> fp
print >> fp, ".PHONY: _default_ %s\n\n" % ' '.join(names)
fp.close()
def extend(self, names):
pass
class CleanTarget(_make.Target):
""" Clean the mess """
NAME = 'clean'
_scm, _dist = True, False
def run(self):
self.runner.run_clean(scm=self._scm, dist=self._dist)
class DistCleanTarget(CleanTarget):
""" Clean as freshly unpacked dist package """
NAME = 'distclean'
_scm, _dist = False, True
class ExtraCleanTarget(CleanTarget):
""" Clean everything """
NAME = 'extraclean'
_scm, _dist = True, True

View File

@ -1,324 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007 - 2013
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
==================
Standard targets
==================
Standard targets.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import os as _os
import sys as _sys
from _setup import dist as _dist
from _setup import make as _make
from _setup import shell as _shell
from _setup import term as _term
class Distribution(_make.Target):
""" Build a distribution """
NAME = "dist"
DEPS = ["MANIFEST"]
_dist, _ebuilds, _changes = None, None, None
def init(self):
raise NotImplementedError()
def run(self):
exts = self.dist_pkg()
digests = self.digest_files(exts)
self.sign_digests(digests)
self.copy_ebuilds()
self.copy_changes()
def dist_pkg(self):
_term.green("Building package...")
_dist.run_setup("sdist", "--formats", "tar,zip",
fakeroot=_shell.frompath('fakeroot')
)
exts = ['.zip']
for name in _shell.files(self._dist, '*.tar', False):
exts.extend(self.compress(name))
_shell.rm(name)
return exts
def compress(self, filename):
""" Compress file """
ext = _os.path.splitext(filename)[1]
exts = []
exts.append('.'.join((ext, self.compress_gzip(filename))))
exts.append('.'.join((ext, self.compress_bzip2(filename))))
exts.append('.'.join((ext, self.compress_xz(filename))))
return exts
def compress_xz(self, filename):
outfilename = filename + '.xz'
self.compress_external(filename, outfilename, 'xz', '-c9')
return 'xz'
def compress_bzip2(self, filename):
outfilename = filename + '.bz2'
try:
import bz2 as _bz2
except ImportError:
self.compress_external(filename, outfilename, 'bzip2', '-c9')
else:
outfile = _bz2.BZ2File(outfilename, 'w')
self.compress_internal(filename, outfile, outfilename)
return 'bz2'
def compress_gzip(self, filename):
outfilename = filename + '.gz'
try:
import gzip as _gzip
except ImportError:
self.compress_external(filename, outfilename, 'gzip', '-c9')
else:
outfile = _gzip.GzipFile(filename, 'wb',
fileobj=open(outfilename, 'wb')
)
self.compress_internal(filename, outfile, outfilename)
return 'gz'
def compress_external(self, infile, outfile, *argv):
argv = list(argv)
argv[0] = _shell.frompath(argv[0])
if argv[0] is not None:
return not _shell.spawn(*argv, **{
'filepipe': True, 'stdin': infile, 'stdout': outfile,
})
return None
def compress_internal(self, filename, outfile, outfilename):
infile = open(filename, 'rb')
try:
try:
while 1:
chunk = infile.read(8192)
if not chunk:
break
outfile.write(chunk)
outfile.close()
except:
e = _sys.exc_info()
try:
_shell.rm(outfilename)
finally:
try:
raise e[0], e[1], e[2]
finally:
del e
finally:
infile.close()
def digest_files(self, exts):
""" digest files """
digests = {}
digestnames = {}
for ext in exts:
for name in _shell.files(self._dist, '*' + ext, False):
basename = _os.path.basename(name)
if basename not in digests:
digests[basename] = []
digests[basename].extend(self.digest(name))
digestname = basename[:-len(ext)]
if digestname not in digestnames:
digestnames[digestname] = []
digestnames[digestname].append(basename)
result = []
for name, basenames in digestnames.items():
result.append(_os.path.join(self._dist, name + '.digests'))
fp = open(result[-1], 'wb')
try:
fp.write(
'\n# The file may contain MD5, SHA1 and SHA256 digests\n'
)
fp.write('# Check archive integrity with, e.g. md5sum -c\n')
fp.write('# Check digest file integrity with PGP\n\n')
basenames.sort()
for basename in basenames:
for digest in digests[basename]:
fp.write("%s *%s\n" % (digest, basename))
finally:
fp.close()
return result
def digest(self, filename):
result = []
for method in (self.md5, self.sha1, self.sha256):
digest = method(filename)
if digest is not None:
result.append(digest)
return result
def do_digest(self, hashfunc, name, filename):
filename = _shell.native(filename)
_term.green("%(digest)s-digesting %(name)s...",
digest=name, name=_os.path.basename(filename))
fp = open(filename, 'rb')
sig = hashfunc()
block = fp.read(8192)
while block:
sig.update(block)
block = fp.read(8192)
fp.close()
return sig.hexdigest()
param = {'sig': sig.hexdigest(), 'file': _os.path.basename(filename)}
fp = open("%s.%s" % (filename, name), "w")
fp.write("%(sig)s *%(file)s\n" % param)
fp.close()
return True
def md5(self, filename):
try:
from hashlib import md5
except ImportError:
try:
from md5 import new as md5
except ImportError:
_make.warn("md5 not found -> skip md5 digests", self.NAME)
return None
return self.do_digest(md5, "md5", filename)
def sha1(self, filename):
try:
from hashlib import sha1
except ImportError:
try:
from sha import new as sha1
except ImportError:
_make.warn("sha1 not found -> skip sha1 digests", self.NAME)
return None
return self.do_digest(sha1, "sha1", filename)
def sha256(self, filename):
try:
from hashlib import sha256
except ImportError:
try:
from Crypto.Hash.SHA256 import new as sha256
except ImportError:
_make.warn(
"sha256 not found -> skip sha256 digests", self.NAME
)
return None
return self.do_digest(sha256, "sha256", filename)
def copy_ebuilds(self):
if self._ebuilds is not None:
for src in _shell.files(self._ebuilds, '*.ebuild'):
_shell.cp(src, self._dist)
def copy_changes(self):
if self._changes is not None:
_shell.cp(self._changes, self._dist)
def sign_digests(self, digests):
for digest in digests:
self.sign(digest, detach=False)
def sign(self, filename, detach=True):
filename = _shell.native(filename)
try:
from pyme import core, errors
from pyme.constants.sig import mode
except ImportError:
return self.sign_external(filename, detach=detach)
_term.green("signing %(name)s...", name=_os.path.basename(filename))
sigmode = [mode.CLEAR, mode.DETACH][bool(detach)]
fp = core.Data(file=filename)
sig = core.Data()
try:
c = core.Context()
except errors.GPGMEError:
return self.sign_external(filename, detach=detach)
c.set_armor(1)
try:
c.op_sign(fp, sig, sigmode)
except errors.GPGMEError, e:
_make.fail(str(e))
sig.seek(0, 0)
if detach:
open("%s.asc" % filename, "w").write(sig.read())
else:
open(filename, "w").write(sig.read())
return True
def sign_external(self, filename, detach=True):
""" Sign calling gpg """
gpg = _shell.frompath('gpg')
if gpg is None:
_make.warn('GPG not found -> cannot sign')
return False
if detach:
_shell.spawn(gpg,
'--armor',
'--output', filename + '.asc',
'--detach-sign',
'--',
filename,
)
else:
_shell.spawn(gpg,
'--output', filename + '.signed',
'--clearsign',
'--',
filename,
)
_os.rename(filename + '.signed', filename)
return True
def clean(self, scm, dist):
_term.green("Removing dist files...")
_shell.rm_rf(self._dist)
class Manifest(_make.Target):
""" Create manifest """
NAME = "MANIFEST"
HIDDEN = True
DEPS = ["doc"]
def run(self):
_term.green("Creating %(name)s...", name=self.NAME)
dest = _shell.native(self.NAME)
dest = open(dest, 'w')
for name in self.manifest_names():
dest.write("%s\n" % name)
dest.close()
def manifest_names(self):
import setup
for item in setup.manifest():
yield item
def clean(self, scm, dist):
""" Clean manifest """
if scm:
_term.green("Removing MANIFEST")
_shell.rm(self.NAME)

View File

@ -1,419 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007 - 2013
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
===================
Main setup runner
===================
This module provides a wrapper around the distutils core setup.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import ConfigParser as _config_parser
from distutils import core as _core
import os as _os
import posixpath as _posixpath
import sys as _sys
from _setup import commands as _commands
from _setup import data as _data
from _setup import ext as _ext
from _setup import util as _util
from _setup import shell as _shell
def check_python_version(impl, version_min, version_max):
""" Check python version """
if impl == 'python':
version_info = _sys.version_info
elif impl == 'pypy':
version_info = getattr(_sys, 'pypy_version_info', None)
if not version_info:
return
elif impl == 'jython':
if not 'java' in _sys.platform.lower():
return
version_info = _sys.version_info
else:
raise AssertionError("impl not in ('python', 'pypy', 'jython')")
pyversion = map(int, version_info[:3])
if version_min:
min_required = \
map(int, '.'.join((version_min, '0.0.0')).split('.')[:3])
if pyversion < min_required:
raise EnvironmentError("Need at least %s %s (vs. %s)" % (
impl, version_min, '.'.join(map(str, pyversion))
))
if version_max:
max_required = map(int, version_max.split('.'))
max_required[-1] += 1
if pyversion >= max_required:
raise EnvironmentError("Need at max %s %s (vs. %s)" % (
impl,
version_max,
'.'.join(map(str, pyversion))
))
def find_description(docs):
"""
Determine the package description from DESCRIPTION
:Parameters:
`docs` : ``dict``
Docs config section
:Return: Tuple of summary, description and license
(``('summary', 'description', 'license')``)
(all may be ``None``)
:Rtype: ``tuple``
"""
summary = None
filename = docs.get('meta.summary', 'SUMMARY').strip()
if filename and _os.path.isfile(filename):
fp = open(filename)
try:
try:
summary = fp.read().strip().splitlines()[0].rstrip()
except IndexError:
summary = ''
finally:
fp.close()
description = None
filename = docs.get('meta.description', 'DESCRIPTION').strip()
if filename and _os.path.isfile(filename):
fp = open(filename)
try:
description = fp.read().rstrip()
finally:
fp.close()
if summary is None and description:
from docutils import core
summary = core.publish_parts(
source=description,
source_path=filename,
writer_name='html',
)['title'].encode('utf-8')
return summary, description
def find_classifiers(docs):
"""
Determine classifiers from CLASSIFIERS
:return: List of classifiers (``['classifier', ...]``)
:rtype: ``list``
"""
filename = docs.get('meta.classifiers', 'CLASSIFIERS').strip()
if filename and _os.path.isfile(filename):
fp = open(filename)
try:
content = fp.read()
finally:
fp.close()
content = [item.strip() for item in content.splitlines()]
return [item for item in content if item and not item.startswith('#')]
return []
def find_provides(docs):
"""
Determine provides from PROVIDES
:return: List of provides (``['provides', ...]``)
:rtype: ``list``
"""
filename = docs.get('meta.provides', 'PROVIDES').strip()
if filename and _os.path.isfile(filename):
fp = open(filename)
try:
content = fp.read()
finally:
fp.close()
content = [item.strip() for item in content.splitlines()]
return [item for item in content if item and not item.startswith('#')]
return []
def find_license(docs):
"""
Determine license from LICENSE
:return: License text
:rtype: ``str``
"""
filename = docs.get('meta.license', 'LICENSE').strip()
if filename and _os.path.isfile(filename):
fp = open(filename)
try:
return fp.read().rstrip()
finally:
fp.close()
return None
def find_packages(manifest):
""" Determine packages and subpackages """
packages = {}
collect = manifest.get('packages.collect', '').split()
lib = manifest.get('packages.lib', '.')
try:
sep = _os.path.sep
except AttributeError:
sep = _os.path.join('1', '2')[1:-1]
for root in collect:
for dirpath, _, filenames in _shell.walk(_os.path.join(lib, root)):
if dirpath.find('.svn') >= 0 or dirpath.find('.git') >= 0:
continue
if '__init__.py' in filenames:
packages[
_os.path.normpath(dirpath).replace(sep, '.')
] = None
packages = packages.keys()
packages.sort()
return packages
def find_data(name, docs):
""" Determine data files """
result = []
if docs.get('extra', '').strip():
result.append(_data.Documentation(docs['extra'].split(),
prefix='share/doc/%s' % name,
))
if docs.get('examples.dir', '').strip():
tpl = ['recursive-include %s *' % docs['examples.dir']]
if docs.get('examples.ignore', '').strip():
tpl.extend(["global-exclude %s" % item
for item in docs['examples.ignore'].split()
])
strip = int(docs.get('examples.strip', '') or 0)
result.append(_data.Documentation.from_templates(*tpl, **{
'strip': strip,
'prefix': 'share/doc/%s' % name,
'preserve': 1,
}))
if docs.get('userdoc.dir', '').strip():
tpl = ['recursive-include %s *' % docs['userdoc.dir']]
if docs.get('userdoc.ignore', '').strip():
tpl.extend(["global-exclude %s" % item
for item in docs['userdoc.ignore'].split()
])
strip = int(docs.get('userdoc.strip', '') or 0)
result.append(_data.Documentation.from_templates(*tpl, **{
'strip': strip,
'prefix': 'share/doc/%s' % name,
'preserve': 1,
}))
if docs.get('apidoc.dir', '').strip():
tpl = ['recursive-include %s *' % docs['apidoc.dir']]
if docs.get('apidoc.ignore', '').strip():
tpl.extend(["global-exclude %s" % item
for item in docs['apidoc.ignore'].split()
])
strip = int(docs.get('apidoc.strip', '') or 0)
result.append(_data.Documentation.from_templates(*tpl, **{
'strip': strip,
'prefix': 'share/doc/%s' % name,
'preserve': 1,
}))
if docs.get('man', '').strip():
result.extend(_data.Manpages.dispatch(docs['man'].split()))
return result
def make_manifest(manifest, config, docs, kwargs):
""" Create file list to pack up """
# pylint: disable = R0912
kwargs = kwargs.copy()
kwargs['script_args'] = ['install']
kwargs['packages'] = list(kwargs.get('packages') or ()) + [
'_setup', '_setup.py2', '_setup.py3',
] + list(manifest.get('packages.extra', '').split() or ())
_core._setup_stop_after = "commandline"
try:
dist = _core.setup(**kwargs)
finally:
_core._setup_stop_after = None
result = ['MANIFEST', 'PKG-INFO', 'setup.py'] + list(config)
# TODO: work with default values:
for key in ('classifiers', 'description', 'summary', 'provides',
'license'):
filename = docs.get('meta.' + key, '').strip()
if filename and _os.path.isfile(filename):
result.append(filename)
cmd = dist.get_command_obj("build_py")
cmd.ensure_finalized()
#from pprint import pprint; pprint(("build_py", cmd.get_source_files()))
for item in cmd.get_source_files():
result.append(_posixpath.sep.join(
_os.path.normpath(item).split(_os.path.sep)
))
cmd = dist.get_command_obj("build_ext")
cmd.ensure_finalized()
#from pprint import pprint; pprint(("build_ext", cmd.get_source_files()))
for item in cmd.get_source_files():
result.append(_posixpath.sep.join(
_os.path.normpath(item).split(_os.path.sep)
))
for ext in cmd.extensions:
if ext.depends:
result.extend([_posixpath.sep.join(
_os.path.normpath(item).split(_os.path.sep)
) for item in ext.depends])
cmd = dist.get_command_obj("build_clib")
cmd.ensure_finalized()
if cmd.libraries:
#import pprint; pprint.pprint(("build_clib", cmd.get_source_files()))
for item in cmd.get_source_files():
result.append(_posixpath.sep.join(
_os.path.normpath(item).split(_os.path.sep)
))
for lib in cmd.libraries:
if lib[1].get('depends'):
result.extend([_posixpath.sep.join(
_os.path.normpath(item).split(_os.path.sep)
) for item in lib[1]['depends']])
cmd = dist.get_command_obj("build_scripts")
cmd.ensure_finalized()
#import pprint; pprint.pprint(("build_scripts", cmd.get_source_files()))
if cmd.get_source_files():
for item in cmd.get_source_files():
result.append(_posixpath.sep.join(
_os.path.normpath(item).split(_os.path.sep)
))
cmd = dist.get_command_obj("install_data")
cmd.ensure_finalized()
#from pprint import pprint; pprint(("install_data", cmd.get_inputs()))
try:
strings = basestring
except NameError:
strings = (str, unicode)
for item in cmd.get_inputs():
if isinstance(item, strings):
result.append(item)
else:
result.extend(item[1])
for item in manifest.get('dist', '').split():
result.append(item)
if _os.path.isdir(item):
for filename in _shell.files(item):
result.append(filename)
result = dict([(item, None) for item in result]).keys()
result.sort()
return result
def run(config=('package.cfg',), ext=None, script_args=None, manifest_only=0):
""" Main runner """
if ext is None:
ext = []
cfg = _util.SafeConfigParser()
cfg.read(config)
pkg = dict(cfg.items('package'))
python_min = pkg.get('python.min') or None
python_max = pkg.get('python.max') or None
check_python_version('python', python_min, python_max)
pypy_min = pkg.get('pypy.min') or None
pypy_max = pkg.get('pypy.max') or None
check_python_version('pypy', pypy_min, pypy_max)
jython_min = pkg.get('jython.min') or None
jython_max = pkg.get('jython.max') or None
check_python_version('jython', jython_min, jython_max)
manifest = dict(cfg.items('manifest'))
try:
docs = dict(cfg.items('docs'))
except _config_parser.NoSectionError:
docs = {}
summary, description = find_description(docs)
scripts = manifest.get('scripts', '').strip() or None
if scripts:
scripts = scripts.split()
modules = manifest.get('modules', '').strip() or None
if modules:
modules = modules.split()
keywords = docs.get('meta.keywords', '').strip() or None
if keywords:
keywords = keywords.split()
revision = pkg.get('version.revision', '').strip()
if revision:
revision = "-r%s" % (revision,)
kwargs = {
'name': pkg['name'],
'version': "%s%s" % (
pkg['version.number'],
["", "-dev%s" % (revision,)][_util.humanbool(
'version.dev', pkg.get('version.dev', 'false')
)],
),
'provides': find_provides(docs),
'description': summary,
'long_description': description,
'classifiers': find_classifiers(docs),
'keywords': keywords,
'author': pkg['author.name'],
'author_email': pkg['author.email'],
'maintainer': pkg.get('maintainer.name'),
'maintainer_email': pkg.get('maintainer.email'),
'url': pkg.get('url.homepage'),
'download_url': pkg.get('url.download'),
'license': find_license(docs),
'package_dir': {'': manifest.get('packages.lib', '.')},
'packages': find_packages(manifest),
'py_modules': modules,
'ext_modules': ext,
'scripts': scripts,
'script_args': script_args,
'data_files': find_data(pkg['name'], docs),
'cmdclass': {
'build' : _commands.Build,
'build_ext' : _commands.BuildExt,
'install' : _commands.Install,
'install_data': _commands.InstallData,
'install_lib' : _commands.InstallLib,
}
}
for key in ('provides',):
if key not in _core.setup_keywords:
del kwargs[key]
if manifest_only:
return make_manifest(manifest, config, docs, kwargs)
# monkey-patch crappy manifest writer away.
from distutils.command import sdist
sdist.sdist.get_file_list = sdist.sdist.read_manifest
return _core.setup(**kwargs)

View File

@ -1,478 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007 - 2013
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
=================
Shell utilities
=================
Shell utilities.
"""
from __future__ import generators
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import errno as _errno
import fnmatch as _fnmatch
import os as _os
import shutil as _shutil
import sys as _sys
import tempfile as _tempfile
cwd = _os.path.dirname(_os.path.abspath(_sys.argv[0]))
class ExitError(RuntimeError):
""" Exit error """
def __init__(self, code):
RuntimeError.__init__(self, code)
self.code = code
self.signal = None
class SignalError(ExitError):
""" Signal error """
def __init__(self, code, signal):
ExitError.__init__(self, code)
import signal as _signal
self.signal = signal
for key, val in vars(_signal).iteritems():
if key.startswith('SIG') and not key.startswith('SIG_'):
if val == signal:
self.signalstr = key[3:]
break
else:
self.signalstr = '%04d' % signal
def native(path):
""" Convert slash path to native """
path = _os.path.sep.join(path.split('/'))
return _os.path.normpath(_os.path.join(cwd, path))
def cp(src, dest):
""" Copy src to dest """
_shutil.copy2(native(src), native(dest))
def cp_r(src, dest):
""" Copy -r src to dest """
_shutil.copytree(native(src), native(dest))
def rm(dest):
""" Remove a file """
try:
_os.unlink(native(dest))
except OSError, e:
if _errno.ENOENT != e.errno:
raise
def rm_rf(dest):
""" Remove a tree """
dest = native(dest)
if _os.path.exists(dest):
for path in files(dest, '*'):
_os.chmod(native(path), 0644)
_shutil.rmtree(dest)
try:
mkstemp = _tempfile.mkstemp
except AttributeError:
# helpers stolen from 2.4 tempfile module
try:
import fcntl as _fcntl
except ImportError:
def _set_cloexec(fd):
""" Set close-on-exec (not implemented, but not an error) """
# pylint: disable = W0613
pass
else:
def _set_cloexec(fd):
""" Set close-on-exec """
try:
flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
except IOError:
pass
else:
# flags read successfully, modify
flags |= _fcntl.FD_CLOEXEC
_fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
_text_openflags |= getattr(_os, 'O_NOINHERIT', 0)
_text_openflags |= getattr(_os, 'O_NOFOLLOW', 0)
_bin_openflags = _text_openflags
_bin_openflags |= getattr(_os, 'O_BINARY', 0)
def mkstemp(suffix="", prefix=_tempfile.gettempprefix(), dir=None,
text=False):
""" Create secure temp file """
# pylint: disable = W0622
if dir is None:
dir = _tempfile.gettempdir()
if text:
flags = _text_openflags
else:
flags = _bin_openflags
count = 100
while count > 0:
j = _tempfile._counter.get_next() # pylint: disable = E1101, W0212
fname = _os.path.join(dir, prefix + str(j) + suffix)
try:
fd = _os.open(fname, flags, 0600)
except OSError, e:
if e.errno == _errno.EEXIST:
count -= 1
continue
raise
_set_cloexec(fd)
return fd, _os.path.abspath(fname)
raise IOError, (_errno.EEXIST, "No usable temporary file name found")
def _pipespawn(argv, env):
""" Pipe spawn """
# pylint: disable = R0912
import pickle as _pickle
fd, name = mkstemp('.py')
try:
_os.write(fd, (r"""
import os
import pickle
try:
import subprocess
except ImportError:
subprocess = None
import sys
argv = pickle.loads(%(argv)s)
env = pickle.loads(%(env)s)
if 'X_JYTHON_WA_PATH' in env:
env['PATH'] = env['X_JYTHON_WA_PATH']
if subprocess is None:
pid = os.spawnve(os.P_NOWAIT, argv[0], argv, env)
result = os.waitpid(pid, 0)[1]
else:
p = subprocess.Popen(argv, env=env)
result = p.wait()
if result < 0:
print "\n%%d 1" %% (-result)
sys.exit(2)
if result == 0:
sys.exit(0)
signalled = getattr(os, 'WIFSIGNALED', None)
if signalled is not None:
if signalled(result):
print "\n%%d %%d" %% (os.WTERMSIG(result), result & 7)
sys.exit(2)
print "\n%%d" %% (result & 7,)
sys.exit(3)
""".strip() + "\n") % {
'argv': repr(_pickle.dumps(argv)),
'env': repr(_pickle.dumps(env)),
})
fd, _ = None, _os.close(fd)
if _sys.platform == 'win32':
argv = []
for arg in [_sys.executable, name]:
if ' ' in arg or arg.startswith('"'):
arg = '"%s"' % arg.replace('"', '\\"')
argv.append(arg)
argv = ' '.join(argv)
shell = True
close_fds = False
else:
argv = [_sys.executable, name]
shell = False
close_fds = True
res = 0
try:
import subprocess
except ImportError:
import popen2 as _popen2
proc = _popen2.Popen3(argv, False)
try:
proc.tochild.close()
result = proc.fromchild.read()
finally:
res = proc.wait()
else:
if 'X_JYTHON_WA_PATH' in env:
env['PATH'] = env['X_JYTHON_WA_PATH']
proc = subprocess.Popen(argv,
shell=shell,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
close_fds=close_fds,
env=env,
)
try:
proc.stdin.close()
result = proc.stdout.read()
finally:
res = proc.wait()
if res != 0:
if res == 2:
signal, code = map(int, result.splitlines()[-1].split())
raise SignalError(code, signal)
elif res == 3:
code = int(result.splitlines()[-1].strip())
raise ExitError(code)
raise ExitError(res)
return result
finally:
try:
if fd is not None:
_os.close(fd)
finally:
_os.unlink(name)
def _filepipespawn(infile, outfile, argv, env):
""" File Pipe spawn """
try:
import subprocess
except ImportError:
subprocess = None
import pickle as _pickle
fd, name = mkstemp('.py')
try:
_os.write(fd, ("""
import os
import pickle
import sys
infile = pickle.loads(%(infile)s)
outfile = pickle.loads(%(outfile)s)
argv = pickle.loads(%(argv)s)
env = pickle.loads(%(env)s)
if infile is not None:
infile = open(infile, 'rb')
os.dup2(infile.fileno(), 0)
infile.close()
if outfile is not None:
outfile = open(outfile, 'wb')
os.dup2(outfile.fileno(), 1)
outfile.close()
pid = os.spawnve(os.P_NOWAIT, argv[0], argv, env)
result = os.waitpid(pid, 0)[1]
sys.exit(result & 7)
""".strip() + "\n") % {
'infile': repr(_pickle.dumps(_os.path.abspath(infile))),
'outfile': repr(_pickle.dumps(_os.path.abspath(outfile))),
'argv': repr(_pickle.dumps(argv)),
'env': repr(_pickle.dumps(env)),
})
fd, _ = None, _os.close(fd)
if _sys.platform == 'win32':
argv = []
for arg in [_sys.executable, name]:
if ' ' in arg or arg.startswith('"'):
arg = '"%s"' % arg.replace('"', '\\"')
argv.append(arg)
argv = ' '.join(argv)
close_fds = False
shell = True
else:
argv = [_sys.executable, name]
close_fds = True
shell = False
if subprocess is None:
pid = _os.spawnve(_os.P_NOWAIT, argv[0], argv, env)
return _os.waitpid(pid, 0)[1]
else:
p = subprocess.Popen(
argv, env=env, shell=shell, close_fds=close_fds
)
return p.wait()
finally:
try:
if fd is not None:
_os.close(fd)
finally:
_os.unlink(name)
def spawn(*argv, **kwargs):
""" Spawn a process """
try:
import subprocess
except ImportError:
subprocess = None
if _sys.platform == 'win32':
newargv = []
for arg in argv:
if not arg or ' ' in arg or arg.startswith('"'):
arg = '"%s"' % arg.replace('"', '\\"')
newargv.append(arg)
argv = newargv
close_fds = False
shell = True
else:
close_fds = True
shell = False
env = kwargs.get('env')
if env is None:
env = dict(_os.environ)
if 'X_JYTHON_WA_PATH' in env:
env['PATH'] = env['X_JYTHON_WA_PATH']
echo = kwargs.get('echo')
if echo:
print ' '.join(argv)
filepipe = kwargs.get('filepipe')
if filepipe:
return _filepipespawn(
kwargs.get('stdin'), kwargs.get('stdout'), argv, env
)
pipe = kwargs.get('stdout')
if pipe:
return _pipespawn(argv, env)
if subprocess is None:
pid = _os.spawnve(_os.P_NOWAIT, argv[0], argv, env)
return _os.waitpid(pid, 0)[1]
else:
p = subprocess.Popen(argv, env=env, shell=shell, close_fds=close_fds)
return p.wait()
try:
walk = _os.walk
except AttributeError:
# copy from python 2.4 sources (modulo docs and comments)
def walk(top, topdown=True, onerror=None):
""" directory tree walker """
# pylint: disable = C0103
join, isdir, islink = _os.path.join, _os.path.isdir, _os.path.islink
listdir, error = _os.listdir, _os.error
try:
names = listdir(top)
except error, err:
if onerror is not None:
onerror(err)
return
dirs, nondirs = [], []
for name in names:
if isdir(join(top, name)):
dirs.append(name)
else:
nondirs.append(name)
if topdown:
yield top, dirs, nondirs
for name in dirs:
path = join(top, name)
if not islink(path):
for x in walk(path, topdown, onerror):
yield x
if not topdown:
yield top, dirs, nondirs
def files(base, wildcard='[!.]*', recursive=1, prune=('.git', '.svn', 'CVS')):
""" Determine a filelist """
for dirpath, dirnames, filenames in walk(native(base)):
for item in prune:
if item in dirnames:
dirnames.remove(item)
filenames.sort()
for name in _fnmatch.filter(filenames, wildcard):
dest = _os.path.join(dirpath, name)
if dest.startswith(cwd):
dest = dest.replace(cwd, '', 1)
aslist = []
head, tail = _os.path.split(dest)
while tail:
aslist.append(tail)
head, tail = _os.path.split(head)
aslist.reverse()
dest = '/'.join(aslist)
yield dest
if not recursive:
break
dirnames.sort()
def dirs(base, wildcard='[!.]*', recursive=1, prune=('.git', '.svn', 'CVS')):
""" Determine a filelist """
for dirpath, dirnames, filenames in walk(native(base)):
for item in prune:
if item in dirnames:
dirnames.remove(item)
dirnames.sort()
for name in _fnmatch.filter(dirnames, wildcard):
dest = _os.path.join(dirpath, name)
if dest.startswith(cwd):
dest = dest.replace(cwd, '', 1)
aslist = []
head, tail = _os.path.split(dest)
while tail:
aslist.append(tail)
head, tail = _os.path.split(head)
aslist.reverse()
dest = '/'.join(aslist)
yield dest
if not recursive:
break
def frompath(executable):
""" Find executable in PATH """
# Based on distutils.spawn.find_executable.
path = _os.environ.get('PATH', '')
paths = [
_os.path.expanduser(item)
for item in path.split(_os.pathsep)
]
ext = _os.path.splitext(executable)[1]
exts = ['']
if _sys.platform == 'win32' or _os.name == 'os2':
eext = ['.exe', '.bat', '.py']
if ext not in eext:
exts.extend(eext)
for ext in exts:
if not _os.path.isfile(executable + ext):
for path in paths:
fname = _os.path.join(path, executable + ext)
if _os.path.isfile(fname):
# the file exists, we have a shot at spawn working
return fname
else:
return executable + ext
return None

View File

@ -1,28 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
=====================
Package _setup.term
=====================
Terminal tools, not distributed.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
# pylint: disable = W0611
from _setup.term._term import terminfo, write, green, red, yellow, announce

View File

@ -1,115 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
=================
Terminal writer
=================
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import sys as _sys
class _INFO(dict):
""" Terminal info dict """
def __init__(self):
""" Initialization """
dict.__init__(self, {
'NORMAL': '',
'BOLD': '',
'ERASE': '\n',
'RED': '',
'YELLOW': '',
'GREEN': '',
})
try:
import curses as _curses
except ImportError:
# fixup if a submodule of curses failed.
if 'curses' in _sys.modules:
del _sys.modules['curses']
else:
try:
_curses.setupterm()
except (TypeError, _curses.error):
pass
else:
def make_color(color):
""" Make color control string """
seq = _curses.tigetstr('setaf')
if seq is not None:
# XXX may fail - need better logic
seq = seq.replace("%p1", "") % color
return seq
self['NORMAL'] = _curses.tigetstr('sgr0')
self['BOLD'] = _curses.tigetstr('bold')
erase = _curses.tigetstr('el1')
if erase is not None:
self['ERASE'] = erase + _curses.tigetstr('cr')
self['RED'] = make_color(_curses.COLOR_RED)
self['YELLOW'] = make_color(_curses.COLOR_YELLOW)
self['GREEN'] = make_color(_curses.COLOR_GREEN)
def __getitem__(self, key):
""" Deliver always """
dict.get(self, key) or ""
def terminfo():
""" Get info singleton """
# pylint: disable = E1101, W0612
if terminfo.info is None:
terminfo.info = _INFO()
return terminfo.info
terminfo.info = None
def write(fmt, **kwargs):
""" Write stuff on the terminal """
parm = dict(terminfo())
parm.update(kwargs)
_sys.stdout.write(fmt % parm)
_sys.stdout.flush()
def green(bmt, **kwargs):
""" Write something in green on screen """
announce("%%(GREEN)s%s%%(NORMAL)s" % bmt, **kwargs)
def red(bmt, **kwargs):
""" Write something in red on the screen """
announce("%%(BOLD)s%%(RED)s%s%%(NORMAL)s" % bmt, **kwargs)
def yellow(fmt, **kwargs):
""" Write something in yellow on the screen """
announce("%%(BOLD)s%%(YELLOW)s%s%%(NORMAL)s" % fmt, **kwargs)
def announce(fmt, **kwargs):
""" Announce something """
write(fmt, **kwargs)
_sys.stdout.write("\n")
_sys.stdout.flush()

View File

@ -1,73 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
=================
Setup utilities
=================
Setup utilities.
"""
__author__ = u"Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
try:
from distutils import log
except ImportError:
class log(object):
def info(self, value):
print value
def debug(self, value):
pass
log = log()
from distutils import util as _util
try:
from ConfigParser import SafeConfigParser
except ImportError:
import ConfigParser as _config_parser
class SafeConfigParser(_config_parser.ConfigParser):
""" Safe config parser """
def _interpolate(self, section, option, rawval, vars):
return rawval
def items(self, section):
return [(key, self.get(section, key))
for key in self.options(section)
]
def humanbool(name, value):
"""
Determine human boolean value
:Parameters:
`name` : ``str``
The config key (used for error message)
`value` : ``str``
The config value
:Return: The boolean value
:Rtype: ``bool``
:Exceptions:
- `ValueError` : The value could not be recognized
"""
try:
return _util.strtobool(str(value).strip().lower() or 'no')
except ValueError:
raise ValueError("Unrecognized config value: %s = %s" % (name, value))

View File

@ -1,27 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
================
Package _setup
================
This package provides tools for main package setup.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
from _setup.setup import run # pylint: disable = W0611

View File

@ -1,266 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
===================
Command extenders
===================
Command extenders.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
__test__ = False
from distutils import fancy_getopt as _fancy_getopt
from distutils import log
from distutils.command import build as _build
from distutils.command import build_ext as _build_ext
from distutils.command import install as _install
from distutils.command import install_data as _install_data
from distutils.command import install_lib as _install_lib
import os as _os
_option_defaults = {}
_option_inherits = {}
_option_finalizers = {}
_command_mapping = {
'install': 'Install',
'install_data': 'InstallData',
'install_lib': 'InstallLib',
'build': 'Build',
'build_ext': 'BuildExt',
}
def add_option(command, long_name, help_text, short_name=None, default=None,
inherit=None):
""" Add an option """
try:
command_class = globals()[_command_mapping[command]]
except KeyError:
raise ValueError("Unknown command %r" % (command,))
for opt in command_class.user_options:
if opt[0] == long_name:
break
else:
opt = (long_name, short_name, help_text)
command_class.user_options.append(opt)
if not long_name.endswith('='):
command_class.boolean_options.append(long_name)
attr_name = _fancy_getopt.translate_longopt(long_name)
else:
attr_name = _fancy_getopt.translate_longopt(long_name[:-1])
if command not in _option_defaults:
_option_defaults[command] = []
if inherit is not None:
if isinstance(inherit, str):
inherit = [inherit]
for i_inherit in inherit:
add_option(
i_inherit, long_name, help_text, short_name, default
)
default = None
if command not in _option_inherits:
_option_inherits[command] = []
for i_inherit in inherit:
for i_command, opt_name in _option_inherits[command]:
if i_command == i_inherit and opt_name == attr_name:
break
else:
_option_inherits[command].append((i_inherit, attr_name))
_option_defaults[command].append((attr_name, default))
def add_finalizer(command, key, func):
""" Add finalizer """
if command not in _option_finalizers:
_option_finalizers[command] = {}
if key not in _option_finalizers[command]:
_option_finalizers[command][key] = func
class Install(_install.install):
""" Extended installer to reflect the additional data options """
user_options = _install.install.user_options + [
('single-version-externally-managed', None,
"Compat option. Does not a thing."),
]
boolean_options = _install.install.boolean_options + [
'single-version-externally-managed'
]
def initialize_options(self):
""" Prepare for new options """
_install.install.initialize_options(self)
self.single_version_externally_managed = None
if 'install' in _option_defaults:
for opt_name, default in _option_defaults['install']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_install.install.finalize_options(self)
if 'install' in _option_inherits:
for parent, opt_name in _option_inherits['install']:
self.set_undefined_options(parent, (opt_name, opt_name))
if 'install' in _option_finalizers:
for func in list(_option_finalizers['install'].values()):
func(self)
class InstallData(_install_data.install_data):
""" Extended data installer """
user_options = _install_data.install_data.user_options + []
boolean_options = _install_data.install_data.boolean_options + []
def initialize_options(self):
""" Prepare for new options """
_install_data.install_data.initialize_options(self)
if 'install_data' in _option_defaults:
for opt_name, default in _option_defaults['install_data']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_install_data.install_data.finalize_options(self)
if 'install_data' in _option_inherits:
for parent, opt_name in _option_inherits['install_data']:
self.set_undefined_options(parent, (opt_name, opt_name))
if 'install_data' in _option_finalizers:
for func in list(_option_finalizers['install_data'].values()):
func(self)
class InstallLib(_install_lib.install_lib):
""" Extended lib installer """
user_options = _install_lib.install_lib.user_options + []
boolean_options = _install_lib.install_lib.boolean_options + []
def initialize_options(self):
""" Prepare for new options """
_install_lib.install_lib.initialize_options(self)
if 'install_lib' in _option_defaults:
for opt_name, default in _option_defaults['install_lib']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_install_lib.install_lib.finalize_options(self)
if 'install_lib' in _option_inherits:
for parent, opt_name in _option_inherits['install_lib']:
self.set_undefined_options(parent, (opt_name, opt_name))
if 'install_lib' in _option_finalizers:
for func in list(_option_finalizers['install_lib'].values()):
func(self)
class BuildExt(_build_ext.build_ext):
"""
Extended extension builder class
This class allows extensions to provide a ``check_prerequisites`` method
which is called before actually building it. The method takes the
`BuildExt` instance and returns whether the extension should be skipped or
not.
"""
def initialize_options(self):
""" Prepare for new options """
_build_ext.build_ext.initialize_options(self)
if 'build_ext' in _option_defaults:
for opt_name, default in _option_defaults['build_ext']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_build_ext.build_ext.finalize_options(self)
if 'build_ext' in _option_inherits:
for parent, opt_name in _option_inherits['build_ext']:
self.set_undefined_options(parent, (opt_name, opt_name))
if 'build_ext' in _option_finalizers:
for func in list(_option_finalizers['build_ext'].values()):
func(self)
def build_extension(self, ext):
"""
Build C extension - with extended functionality
The following features are added here:
- ``ext.check_prerequisites`` is called before the extension is being
built. See `Extension` for details. If the method does not exist,
simply no check will be run.
- The macros ``EXT_PACKAGE`` and ``EXT_MODULE`` will be filled (or
unset) depending on the extensions name, but only if they are not
already defined.
:Parameters:
`ext` : `Extension`
The extension to build. If it's a pure
``distutils.core.Extension``, simply no prequisites check is
applied.
:Return: whatever ``distutils.command.build_ext.build_ext`` returns
:Rtype: any
"""
# handle name macros
macros = dict(ext.define_macros or ())
tup = ext.name.split('.')
if len(tup) == 1:
pkg, mod = None, tup[0]
else:
pkg, mod = '.'.join(tup[:-1]), tup[-1]
if pkg is not None and 'EXT_PACKAGE' not in macros:
ext.define_macros.append(('EXT_PACKAGE', pkg))
if 'EXT_MODULE' not in macros:
ext.define_macros.append(('EXT_MODULE', mod))
if pkg is None:
macros = dict(ext.undef_macros or ())
if 'EXT_PACKAGE' not in macros:
ext.undef_macros.append('EXT_PACKAGE')
# handle prereq checks
try:
checker = ext.check_prerequisites
except AttributeError:
pass
else:
if checker(self):
log.info("Skipping %s extension" % ext.name)
return
return _build_ext.build_ext.build_extension(self, ext)
class Build(_build.build):
def initialize_options(self):
""" Prepare for new options """
_build.build.initialize_options(self)
if 'build' in _option_defaults:
for opt_name, default in _option_defaults['build']:
setattr(self, opt_name, default)
def finalize_options(self):
""" Finalize options """
_build.build.finalize_options(self)
if 'build' in _option_inherits:
for parent, opt_name in _option_inherits['build']:
self.set_undefined_options(parent, (opt_name, opt_name))
if 'build' in _option_finalizers:
for func in list(_option_finalizers['build'].values()):
func(self)

View File

@ -1,165 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
===================
Data distribution
===================
This module provides tools to simplify data distribution.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
from distutils import filelist as _filelist
import os as _os
import posixpath as _posixpath
import sys as _sys
from _setup import commands as _commands
def splitpath(path):
""" Split a path """
drive, path = '', _os.path.normpath(path)
try:
splitunc = _os.path.splitunc
except AttributeError:
pass
else:
drive, path = splitunc(path)
if not drive:
drive, path = _os.path.splitdrive(path)
elems = []
try:
sep = _os.path.sep
except AttributeError:
sep = _os.path.join('1', '2')[1:-1]
while 1:
prefix, path = _os.path.split(path)
elems.append(path)
if prefix in ('', sep):
drive = _os.path.join(drive, prefix)
break
path = prefix
elems.reverse()
return drive, elems
def finalizer(installer):
""" Finalize install_data """
data_files = []
for item in installer.data_files:
if not isinstance(item, Data):
data_files.append(item)
continue
data_files.extend(item.flatten(installer))
installer.data_files = data_files
class Data(object):
""" File list container """
def __init__(self, files, target=None, preserve=0, strip=0,
prefix=None):
""" Initialization """
self._files = files
self._target = target
self._preserve = preserve
self._strip = strip
self._prefix = prefix
self.fixup_commands()
def fixup_commands(self):
pass
def from_templates(cls, *templates, **kwargs):
""" Initialize from template """
files = _filelist.FileList()
for tpl in templates:
for line in tpl.split(';'):
files.process_template_line(line.strip())
files.sort()
files.remove_duplicates()
result = []
for filename in files.files:
_, elems = splitpath(filename)
if '.svn' in elems or '.git' in elems:
continue
result.append(filename)
return cls(result, **kwargs)
from_templates = classmethod(from_templates)
def flatten(self, installer):
""" Flatten the file list to (target, file) tuples """
# pylint: disable = W0613
if self._prefix:
_, prefix = splitpath(self._prefix)
telems = prefix
else:
telems = []
tmap = {}
for fname in self._files:
(_, name), target = splitpath(fname), telems
if self._preserve:
if self._strip:
name = name[max(0, min(self._strip, len(name) - 1)):]
if len(name) > 1:
target = telems + name[:-1]
tmap.setdefault(_posixpath.join(*target), []).append(fname)
return list(tmap.items())
class Documentation(Data):
""" Documentation container """
def fixup_commands(self):
_commands.add_option('install_data', 'without-docs',
help_text='Do not install documentation files',
inherit='install',
)
_commands.add_finalizer('install_data', 'documentation', finalizer)
def flatten(self, installer):
""" Check if docs should be installed at all """
if installer.without_docs:
return []
return Data.flatten(self, installer)
class Manpages(Documentation):
""" Manpages container """
def dispatch(cls, files):
""" Automatically dispatch manpages to their target directories """
mpmap = {}
for manpage in files:
normalized = _os.path.normpath(manpage)
_, ext = _os.path.splitext(normalized)
if ext.startswith(_os.path.extsep):
ext = ext[len(_os.path.extsep):]
mpmap.setdefault(ext, []).append(manpage)
return [cls(manpages, prefix=_posixpath.join(
'share', 'man', 'man%s' % section,
)) for section, manpages in list(mpmap.items())]
dispatch = classmethod(dispatch)
def flatten(self, installer):
""" Check if manpages are suitable """
if _sys.platform == 'win32':
return []
return Documentation.flatten(self, installer)

View File

@ -1,25 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
====================
Package _setup.dev
====================
Development tools, not distributed.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"

View File

@ -1,258 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2006, 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
=================================
Support for code analysis tools
=================================
Support for code analysis tools.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import re as _re
import sys as _sys
from _setup import term as _term
from _setup import shell as _shell
class NotFinished(Exception):
""" Exception used for message passing in the stream filter """
class NotParseable(Exception):
""" Exception used for message passing in the stream filter """
class SpecialMessage(Exception):
""" Exception used for message passing in the stream filter """
class FilterStream(object):
""" Stream filter """
_LINERE = _re.compile(r'''
(?P<name>[^:]+)
:
(?P<lineno>\d+)
:\s+
\[(?P<mid>[^\],]+)(?:,\s+(?P<func>[^\]]+))?\]
\s+
(?P<desc>.*)
''', _re.X)
_SIMRE = _re.compile(r'in (?P<number>\d+) files')
_CYCRE = _re.compile(r'\((?P<cycle>[^)]+)\)')
def __init__(self, term, stream=_sys.stdout):
self.written = False
self._stream = stream
self._lastname = None
self._cycled = False
self._term = dict(term)
self._buffer = ''
def write(self, towrite):
""" Stream write function """
self._buffer += towrite
term = self._term
while True:
try:
name, lineno, mid, func, desc = self._parse()
except NotFinished:
break
except SpecialMessage as e:
self._dospecial(e)
continue
except NotParseable as e:
self._print_literal(str(e.args[0]))
continue
if name != self._lastname:
if self._lastname is not None:
self._stream.write("\n")
term['path'] = name
self._stream.write(
"%(BOLD)s>>> %(path)s%(NORMAL)s\n" % term
)
self._lastname = name
self.written = True
term['mid'] = mid
if mid.startswith('E') or mid.startswith('F'):
self._stream.write("%(BOLD)s%(RED)s%(mid)s%(NORMAL)s" % term)
elif mid == 'W0511':
self._stream.write(
"%(BOLD)s%(GREEN)s%(mid)s%(NORMAL)s" % term
)
else:
self._stream.write(
"%(BOLD)s%(YELLOW)s%(mid)s%(NORMAL)s" % term
)
if int(lineno) != 0:
term['lineno'] = lineno
self._stream.write(" (%(lineno)s" % term)
if func:
term['func'] = func
self._stream.write(
", %(BOLD)s%(YELLOW)s%(func)s%(NORMAL)s" % term
)
self._stream.write(')')
self._stream.write(": %s\n" % desc)
self._stream.flush()
return
def _print_literal(self, line):
""" Print literal """
suppress = (
line.startswith('Unable to get imported names for ') or
line.startswith("Exception exceptions.RuntimeError: 'generator "
"ignored GeneratorExit' in <generator object at") or
line.startswith("Exception RuntimeError: 'generator "
"ignored GeneratorExit' in <generator object") or
not line.strip()
)
if not suppress:
self._stream.write("%s\n" % line)
self._stream.flush()
self.written = True
def _dospecial(self, e):
""" Deal with special messages """
if e.args[0] == 'R0401':
pos = self._buffer.find('\n')
line, self._buffer = (
self._buffer[:pos + 1], self._buffer[pos + 1:]
)
term = self._term
term['mid'] = e.args[0]
if not self._cycled:
self._cycled = True
self._stream.write('\n')
self._stream.write(
"%(BOLD)s%(YELLOW)s%(mid)s%(NORMAL)s" % term
)
self._stream.write(": Cyclic imports\n")
match = self._CYCRE.search(e.args[1])
term['cycle'] = match.group('cycle')
self._stream.write("%(BOLD)s@@@ %(NORMAL)s%(cycle)s\n" % term)
self._stream.flush()
self.written = True
elif e.args[0] == 'R0801':
match = self._SIMRE.search(e.args[1])
if not match:
raise AssertionError(
'Could not determine number of similar files'
)
numfiles = int(match.group('number'))
pos = -1
for _ in range(numfiles + 1):
pos = self._buffer.find('\n', pos + 1)
if pos >= 0:
lines = self._buffer[:pos + 1]
self._buffer = self._buffer[pos + 1:]
term = self._term
self._stream.write("\n")
for name in lines.splitlines()[1:]:
name = name.rstrip()[2:]
term['path'] = name
self._stream.write(
"%(BOLD)s=== %(path)s%(NORMAL)s\n" % term
)
self._lastname = name
term['mid'] = e.args[0]
self._stream.write(
"%(BOLD)s%(YELLOW)s%(mid)s%(NORMAL)s" % term
)
self._stream.write(": %s\n" % e.args[1])
self._stream.flush()
self.written = True
def _parse(self):
""" Parse output """
if '\n' not in self._buffer:
raise NotFinished()
line = self._buffer[:self._buffer.find('\n') + 1]
self._buffer = self._buffer[len(line):]
line = line.rstrip()
match = self._LINERE.match(line)
if not match:
raise NotParseable(line)
mid = match.group('mid')
if mid in ('R0801', 'R0401'):
self._buffer = "%s\n%s" % (line, self._buffer)
raise SpecialMessage(mid, match.group('desc'))
return match.group('name', 'lineno', 'mid', 'func', 'desc')
def run(config, *args):
""" Run pylint """
try:
from pylint import lint
from pylint.reporters import text
except ImportError:
return 2
if config is None:
config = _shell.native('pylint.conf')
argv = ['--rcfile', config,
'--reports', 'no',
'--output-format', 'parseable',
'--include-ids', 'yes'
]
stream = FilterStream(_term.terminfo())
old_stderr = _sys.stderr
try:
# pylint: disable = E1101
_sys.stderr = stream
from pylint import __pkginfo__
if __pkginfo__.numversion < (0, 13):
# The lint tool is not very user friendly, so we need a hack here.
lint.REPORTER_OPT_MAP['parseable'] = \
lambda: text.TextReporter2(stream)
reporter = text.TextReporter2(stream)
else:
reporter = text.ParseableTextReporter(stream)
lint.REPORTER_OPT_MAP['parseable'] = lambda: reporter
for path in args:
try:
try:
lint.Run(argv + [path], reporter=reporter)
except SystemExit:
pass # don't accept the exit. strange errors happen...
if stream.written:
print()
stream.written = False
except KeyboardInterrupt:
print()
raise
finally:
_sys.stderr = old_stderr
return 0

View File

@ -1,31 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2006, 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
=================================
Support for code analysis tools
=================================
Support for code analysis tools.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
def pylint(config, *args):
""" Run pylint """
from _setup.dev import _pylint
return _pylint.run(config, *args)

View File

@ -1,131 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
==================
API doc builders
==================
API doc builders.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import os as _os
import re as _re
from _setup import shell as _shell
from _setup import term as _term
from _setup import util as _util
def _cleanup_epydoc(target):
"""
Cleanup epydoc generated files
This removes the epydoc-footer. It changes every release because of the
timestamp. That creates bad diffs (accidently it's also invalid html).
"""
search = _re.compile(r'<table[^<>]+width="100%%"').search
for filename in _shell.files(target, '*.html'):
fp = open(filename, 'r')
try:
html = fp.read()
finally:
fp.close()
match = search(html)
if match:
start = match.start()
end = html.find('</table>', start)
if end >= 0:
end += len('</table>') + 1
html = html[:start] + html[end:]
fp = open(filename, 'w')
try:
fp.write(html)
finally:
fp.close()
_VERSION_SEARCH = _re.compile(
r'\bversion\s+(?P<major>\d+)\.(?P<minor>\d+)'
).search
def epydoc(**kwargs):
""" Run epydoc """
# pylint: disable = R0912
prog = kwargs.get('epydoc') or 'epydoc'
if not _os.path.dirname(_os.path.normpath(prog)):
prog = _shell.frompath(prog)
if not prog:
_term.red("%(epydoc)s not found",
epydoc=kwargs.get('epydoc') or 'epydoc',
)
return False
version = _VERSION_SEARCH(_shell.spawn(prog, "--version", stdout=True))
if version is not None:
try:
version = tuple(map(int, version.group('major', 'minor')))
except (TypeError, ValueError):
version = None
if version is None:
_term.red("%(prog)s version not recognized" % locals())
return False
if version < (3, 0):
_term.red("%(prog)s is too old %(version)r < (3, 0)" % locals())
return False
env = dict(_os.environ)
prepend = kwargs.get('prepend')
if prepend:
toprepend = _os.pathsep.join(map(str, prepend))
if 'PYTHONPATH' in env:
env['PYTHONPATH'] = _os.pathsep.join((
toprepend, env['PYTHONPATH']
))
else:
env['PYTHONPATH'] = toprepend
append = kwargs.get('append')
if append:
toappend = _os.pathsep.join(map(str, append))
if 'PYTHONPATH' in env:
env['PYTHONPATH'] = _os.pathsep.join((
env['PYTHONPATH'], toappend
))
else:
env['PYTHONPATH'] = toappend
moreenv = kwargs.get('env')
if moreenv:
env.update(moreenv)
config = kwargs.get('config') or _shell.native('docs/epydoc.conf')
argv = [prog, '--config', config]
res = not _shell.spawn(*argv, **{'env': env})
if res:
cfg = _util.SafeConfigParser()
cfg.read(config)
try:
target = dict(cfg.items('epydoc'))['target']
except KeyError:
pass
else:
_cleanup_epydoc(target)
return res

View File

@ -1,50 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
===================
User doc builders
===================
User doc builders.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import os as _os
from _setup import shell as _shell
from _setup import term as _term
def sphinx(**kwargs):
""" Run sphinx """
prog = _shell.frompath('sphinx-build')
if prog is None:
_term.red("sphinx-build not found")
return False
env = dict(_os.environ)
argv = [
prog, '-a',
'-d', _os.path.join(kwargs['build'], 'doctrees'),
'-b', 'html',
kwargs['source'],
kwargs['target'],
]
return not _shell.spawn(*argv, **{'env': env})

View File

@ -1,51 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
================
dist utilities
================
dist utilities.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import sys as _sys
from _setup import shell as _shell
def run_setup(*args, **kwargs):
""" Run setup """
if 'setup' in kwargs:
script = kwargs.get('setup') or 'setup.py'
del kwargs['setup']
else:
script = 'setup.py'
if 'fakeroot' in kwargs:
fakeroot = kwargs['fakeroot']
del kwargs['fakeroot']
else:
fakeroot = None
if kwargs:
raise TypeError("Unrecognized keyword parameters")
script = _shell.native(script)
argv = [_sys.executable, script] + list(args)
if fakeroot:
argv.insert(0, fakeroot)
return not _shell.spawn(*argv)

View File

@ -1,253 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
===================
C extension tools
===================
C extension tools.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
__test__ = False
from distutils import core as _core
from distutils import errors as _distutils_errors
from distutils import log
import os as _os
import posixpath as _posixpath
import shutil as _shutil
import tempfile as _tempfile
from _setup import commands as _commands
def _install_finalizer(installer):
if installer.without_c_extensions:
installer.distribution.ext_modules = []
def _build_finalizer(builder):
if builder.without_c_extensions:
builder.extensions = []
class Extension(_core.Extension):
"""
Extension with prerequisite check interface
If your check is cacheable (during the setup run), override
`cached_check_prerequisites`, `check_prerequisites` otherwise.
:IVariables:
`cached_check` : ``bool``
The cached check result
"""
cached_check = None
def __init__(self, *args, **kwargs):
""" Initialization """
if 'depends' in kwargs:
self.depends = kwargs['depends'] or []
else:
self.depends = []
_core.Extension.__init__(self, *args, **kwargs)
# add include path
included = _posixpath.join('_setup', 'include')
if included not in self.include_dirs:
self.include_dirs.append(included)
# add cext.h to the dependencies
cext_h = _posixpath.join(included, 'cext.h')
if cext_h not in self.depends:
self.depends.append(cext_h)
_commands.add_option('install_lib', 'without-c-extensions',
help_text='Don\'t install C extensions',
inherit='install',
)
_commands.add_finalizer('install_lib', 'c-extensions',
_install_finalizer
)
_commands.add_option('build_ext', 'without-c-extensions',
help_text='Don\'t build C extensions',
inherit=('build', 'install_lib'),
)
_commands.add_finalizer('build_ext', 'c-extensions', _build_finalizer)
def check_prerequisites(self, build):
"""
Check prerequisites
The check should cover all dependencies needed for the extension to
be built and run. The method can do the following:
- return a false value: the extension will be built
- return a true value: the extension will be skipped. This is useful
for optional extensions
- raise an exception. This is useful for mandatory extensions
If the check result is cacheable (during the setup run), override
`cached_check_prerequisites` instead.
:Parameters:
`build` : `BuildExt`
The extension builder
:Return: Skip the extension?
:Rtype: ``bool``
"""
if self.cached_check is None:
log.debug("PREREQ check for %s" % self.name)
self.cached_check = self.cached_check_prerequisites(build)
else:
log.debug("PREREQ check for %s (cached)" % self.name)
return self.cached_check
def cached_check_prerequisites(self, build):
"""
Check prerequisites
The check should cover all dependencies needed for the extension to
be built and run. The method can do the following:
- return a false value: the extension will be built
- return a true value: the extension will be skipped. This is useful
for optional extensions
- raise an exception. This is useful for mandatory extensions
If the check result is *not* cacheable (during the setup run),
override `check_prerequisites` instead.
:Parameters:
`build` : `BuildExt`
The extension builder
:Return: Skip the extension?
:Rtype: ``bool``
"""
# pylint: disable = W0613
log.debug("Nothing to check for %s!" % self.name)
return False
class ConfTest(object):
"""
Single conftest abstraction
:IVariables:
`_tempdir` : ``str``
The tempdir created for this test
`src` : ``str``
Name of the source file
`target` : ``str``
Target filename
`compiler` : ``CCompiler``
compiler instance
`obj` : ``list``
List of object filenames (``[str, ...]``)
"""
_tempdir = None
def __init__(self, build, source):
"""
Initialization
:Parameters:
`build` : ``distuils.command.build_ext.build_ext``
builder instance
`source` : ``str``
Source of the file to compile
"""
self._tempdir = tempdir = _tempfile.mkdtemp()
src = _os.path.join(tempdir, 'conftest.c')
fp = open(src, 'w')
try:
fp.write(source)
finally:
fp.close()
self.src = src
self.compiler = compiler = build.compiler
self.target = _os.path.join(tempdir, 'conftest')
self.obj = compiler.object_filenames([src], output_dir=tempdir)
def __del__(self):
""" Destruction """
self.destroy()
def destroy(self):
""" Destroy the conftest leftovers on disk """
tempdir, self._tempdir = self._tempdir, None
if tempdir is not None:
_shutil.rmtree(tempdir)
def compile(self, **kwargs):
"""
Compile the conftest
:Parameters:
`kwargs` : ``dict``
Optional keyword parameters for the compiler call
:Return: Was the compilation successful?
:Rtype: ``bool``
"""
kwargs['output_dir'] = self._tempdir
try:
self.compiler.compile([self.src], **kwargs)
except _distutils_errors.CompileError:
return False
return True
def link(self, **kwargs):
r"""
Link the conftest
Before you can link the conftest objects they need to be `compile`\d.
:Parameters:
`kwargs` : ``dict``
Optional keyword parameters for the linker call
:Return: Was the linking successful?
:Rtype: ``bool``
"""
try:
self.compiler.link_executable(self.obj, self.target, **kwargs)
except _distutils_errors.LinkError:
return False
return True
def pipe(self, mode="r"):
r"""
Execute the conftest binary and connect to it using a pipe
Before you can pipe to or from the conftest binary it needs to
be `link`\ed.
:Parameters:
`mode` : ``str``
Pipe mode - r/w
:Return: The open pipe
:Rtype: ``file``
"""
return _os.popen(self.compiler.executable_filename(self.target), mode)

View File

@ -1,28 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
=====================
Package _setup.make
=====================
Make tools, not distributed.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
# pylint: disable = W0611
from _setup.make._make import main, fail, warn, fatal, Target

View File

@ -1,338 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
==================
Simple make base
==================
Simple make base.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import sys as _sys
from _setup import term as _term
class Failure(SystemExit):
""" Failure exception """
def fail(reason):
""" Fail for a reason """
raise Failure(reason)
def warn(message, name=None):
""" Warn """
_term.red("%(NAME)sWarning: %(msg)s",
NAME=name and "%s:" % name or '', msg=message
)
def fatal(reason):
""" Fatal error, immediate stop """
print(reason, file=_sys.stderr)
_sys.exit(1)
class Target(object):
""" Target base class """
NAME = None
DEPS = None
HIDDEN = False
ERROR = None
def __init__(self, runner):
""" Base __init__ """
self.runner = runner
self.init()
def init(self):
""" Default init hook """
pass
def run(self):
""" Default run hook """
pass
def clean(self, scm=True, dist=False):
""" Default clean hook """
pass
class _Runner(object):
""" Runner """
def __init__(self, *targetscollection):
""" Initialization """
tdict = {}
if not targetscollection:
import __main__
targetscollection = [__main__]
from _setup.make import default_targets
if default_targets not in targetscollection:
targetscollection.append(default_targets)
for targets in targetscollection:
for value in list(vars(targets).values()):
if isinstance(value, type) and issubclass(value, Target) and \
value.NAME is not None:
if value.NAME in tdict:
if issubclass(value, tdict[value.NAME]):
pass # override base target
elif issubclass(tdict[value.NAME], value):
continue # found base later. ignore
else:
warn('Ambiguous target name', value.NAME)
continue
tdict[value.NAME] = value
self._tdict = tdict
self._itdict = {}
def print_help(self):
""" Print make help """
import textwrap as _textwrap
targets = self.targetinfo()
keys = []
for key, info in list(targets.items()):
if not info['hide']:
keys.append(key)
keys.sort()
length = max(list(map(len, keys)))
info = []
for key in keys:
info.append("%s%s" % (
(key + " " * length)[:length + 2],
_textwrap.fill(
targets[key]['desc'].strip(),
subsequent_indent=" " * (length + 2)
),
))
print("Available targets:\n\n" + "\n".join(info))
def targetinfo(self):
""" Extract target information """
result = {}
for name, cls in list(self._tdict.items()):
result[name] = {
'desc': cls.__doc__ or "no description",
'hide': cls.HIDDEN,
'deps': cls.DEPS or (),
}
return result
def _topleveltargets(self):
""" Find all top level targets """
rev = {} # key is a dep of [values]
all_ = self.targetinfo()
for target, info in list(all_.items()):
for dep in info['deps']:
if dep not in all_:
fatal("Unknown target '%s' (dep of %s) -> exit" % (
dep, target
))
rev.setdefault(dep, []).append(target)
return [target for target, info in list(rev.items()) if not info]
def _run(self, target, seen=None):
""" Run a target """
if target.DEPS:
self(*target.DEPS, **{'seen': seen})
if not target.HIDDEN:
_term.yellow(">>> %(name)s", name=target.NAME)
try:
result = target.run()
except KeyboardInterrupt:
result, target.ERROR = False, "^C -> exit"
except Failure as e:
result, target.ERROR = False, "%s: %s" % (target.NAME, e)
except (SystemExit, MemoryError):
raise
except:
import traceback
target.ERROR = "%s errored:\n%s" % (target.NAME, ''.join(
traceback.format_exception(*_sys.exc_info())
))
result = False
else:
if result is None:
result = True
return result
def _clean(self, target, scm, dist, seen=None):
""" Run a target """
if target.DEPS:
self.run_clean(
*target.DEPS, **{'scm': scm, 'dist': dist, 'seen': seen}
)
try:
result = target.clean(scm, dist)
except KeyboardInterrupt:
result, target.ERROR = False, "^C -> exit"
except Failure as e:
result, target.ERROR = False, "%s: %s" % (target.NAME, e)
except (SystemExit, MemoryError):
raise
except:
import traceback
target.ERROR = "%s errored:\n%s" % (target.NAME, ''.join(
traceback.format_exception(*_sys.exc_info())
))
result = False
else:
if result is None:
result = True
return result
def _make_init(self, seen):
""" Make init mapper """
def init(target):
""" Return initialized target """
if target not in seen:
try:
seen[target] = self._tdict[target](self)
except KeyError:
fatal("Unknown target '%s' -> exit" % target)
else:
seen[target] = None
return seen[target]
return init
def run_clean(self, *targets, **kwargs):
""" Run targets """
def pop(name, default=None):
""" Pop """
if name in kwargs:
value = kwargs[name]
del kwargs[name]
if value is None:
return default
return value
else:
return default
seen = pop('seen', {})
scm = pop('scm', True)
dist = pop('dist', False)
if kwargs:
raise TypeError('Unknown keyword parameters')
if not targets:
top_targets = self._topleveltargets()
targets = self.targetinfo()
for item in top_targets:
del targets[item]
targets = list(targets.keys())
targets.sort()
top_targets.sort()
targets = top_targets + targets
init = self._make_init(seen)
for name in targets:
target = init(name)
if target is not None:
if not self._clean(target, scm=scm, dist=dist, seen=seen):
msg = target.ERROR
if msg is None:
msg = "Clean target %s returned error -> exit" % name
fatal(msg)
def __call__(self, *targets, **kwargs):
""" Run targets """
if 'seen' in kwargs:
seen = kwargs['seen']
del kwargs['seen']
else:
seen = None
if seen is None:
seen = self._itdict
if kwargs:
raise TypeError('Unknown keyword parameters')
init = self._make_init(seen)
for name in targets:
target = init(name)
if target is not None:
if not self._run(target, seen):
msg = target.ERROR
if msg is None:
msg = "Target %s returned error -> exit" % name
fatal(msg)
def main(*args, **kwargs):
"""
main(argv=None, *args, name=None)
Main start point. This function parses the command line and executes the
targets given through `argv`. If there are no targets given, a help output
is generated.
:Parameters:
`argv` : sequence
Command line arguments. If omitted or ``None``, they are picked from
``sys.argv``.
`args` : ``tuple``
The list of modules with targets. If omitted, ``__main__``
is imported and treated as target module. Additionally the mechanism
always adds the `_setup.make` module (this one) to the list in order
to grab some default targets.
`name` : ``str``
Name of the executing module. If omitted or ``None``, ``'__main__'``
is assumed. If the final name is not ``'__main__'``, the function
returns immediately.
"""
try:
name = kwargs['name']
except KeyError:
name = '__main__'
else:
del kwargs['name']
if name is None:
name = '__main__'
try:
argv = kwargs['argv']
except KeyError:
if not args:
args = (None,)
else:
del kwargs['argv']
args = (argv,) + args
if kwargs:
raise TypeError("Unrecognized keyword arguments for main()")
if name == '__main__':
argv, args = args[0], args[1:]
if argv is None:
argv = _sys.argv[1:]
runner = _Runner(*args)
if argv:
runner(*argv)
else:
runner.print_help()

View File

@ -1,110 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
==================
Simple make base
==================
Simple make base.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import os as _os
import sys as _sys
from _setup import make as _make
from _setup import shell as _shell
class MakefileTarget(_make.Target):
""" Create a make file """
NAME = 'makefile'
def run(self):
def escape(value):
""" Escape for make and shell """
return '"%s"' % value.replace(
'\\', '\\\\').replace(
'"', '\\"').replace(
'$', '\\$$')
def decorate(line, prefix='# ', width=78, char='~', padding=' '):
""" Decorate a line """
line = line.center(width - len(prefix))
return '%s%s%s%s%s%s' % (
prefix,
char * (len(line) - len(line.lstrip()) - len(padding)),
padding,
line.strip(),
padding,
char * (len(line) - len(line.rstrip()) - len(padding)),
)
python = escape(_sys.executable)
script = escape(_sys.argv[0])
targets = self.runner.targetinfo()
names = []
for name, info in list(targets.items()):
if not info['hide']:
names.append(name)
names.sort()
fp = open(_shell.native('Makefile'), 'w')
print(decorate("Generated Makefile, DO NOT EDIT"), file=fp)
print(decorate("python %s %s" % (
_os.path.basename(script), self.NAME
)), file=fp)
print(file=fp)
print("_default_:", file=fp)
print("\t@%s %s" % (python, script), file=fp)
for name in names:
print("\n", file=fp)
print("# %s" % \
targets[name]['desc'].splitlines()[0].strip(), file=fp)
print("%s:" % name, file=fp)
print("\t@%s %s %s" % (python, script, escape(name)), file=fp)
print(file=fp)
extension = self.extend(names)
if extension is not None:
print(extension, file=fp)
print(file=fp)
print(".PHONY: _default_ %s\n\n" % ' '.join(names), file=fp)
fp.close()
def extend(self, names):
pass
class CleanTarget(_make.Target):
""" Clean the mess """
NAME = 'clean'
_scm, _dist = True, False
def run(self):
self.runner.run_clean(scm=self._scm, dist=self._dist)
class DistCleanTarget(CleanTarget):
""" Clean as freshly unpacked dist package """
NAME = 'distclean'
_scm, _dist = False, True
class ExtraCleanTarget(CleanTarget):
""" Clean everything """
NAME = 'extraclean'
_scm, _dist = True, True

View File

@ -1,326 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007 - 2013
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
==================
Standard targets
==================
Standard targets.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import os as _os
import sys as _sys
from _setup import dist as _dist
from _setup import make as _make
from _setup import shell as _shell
from _setup import term as _term
class Distribution(_make.Target):
""" Build a distribution """
NAME = "dist"
DEPS = ["MANIFEST"]
_dist, _ebuilds, _changes = None, None, None
def init(self):
raise NotImplementedError()
def run(self):
exts = self.dist_pkg()
digests = self.digest_files(exts)
self.sign_digests(digests)
self.copy_ebuilds()
self.copy_changes()
def dist_pkg(self):
_term.green("Building package...")
_dist.run_setup("sdist", "--formats", "tar,zip",
fakeroot=_shell.frompath('fakeroot')
)
exts = ['.zip']
for name in _shell.files(self._dist, '*.tar', False):
exts.extend(self.compress(name))
_shell.rm(name)
return exts
def compress(self, filename):
""" Compress file """
ext = _os.path.splitext(filename)[1]
exts = []
exts.append('.'.join((ext, self.compress_gzip(filename))))
exts.append('.'.join((ext, self.compress_bzip2(filename))))
exts.append('.'.join((ext, self.compress_xz(filename))))
return exts
def compress_xz(self, filename):
outfilename = filename + '.xz'
self.compress_external(filename, outfilename, 'xz', '-c9')
return 'xz'
def compress_bzip2(self, filename):
outfilename = filename + '.bz2'
try:
import bz2 as _bz2
except ImportError:
self.compress_external(filename, outfilename, 'bzip2', '-c9')
else:
outfile = _bz2.BZ2File(outfilename, 'w')
self.compress_internal(filename, outfile, outfilename)
return 'bz2'
def compress_gzip(self, filename):
outfilename = filename + '.gz'
try:
import gzip as _gzip
except ImportError:
self.compress_external(filename, outfilename, 'gzip', '-c9')
else:
outfile = _gzip.GzipFile(filename, 'wb',
fileobj=open(outfilename, 'wb')
)
self.compress_internal(filename, outfile, outfilename)
return 'gz'
def compress_external(self, infile, outfile, *argv):
argv = list(argv)
argv[0] = _shell.frompath(argv[0])
if argv[0] is not None:
return not _shell.spawn(*argv, **{
'filepipe': True, 'stdin': infile, 'stdout': outfile,
})
return None
def compress_internal(self, filename, outfile, outfilename):
infile = open(filename, 'rb')
try:
try:
while 1:
chunk = infile.read(8192)
if not chunk:
break
outfile.write(chunk)
outfile.close()
except:
e = _sys.exc_info()
try:
_shell.rm(outfilename)
finally:
try:
raise e[0](e[1]).with_traceback(e[2])
finally:
del e
finally:
infile.close()
def digest_files(self, exts):
""" digest files """
digests = {}
digestnames = {}
for ext in exts:
for name in _shell.files(self._dist, '*' + ext, False):
basename = _os.path.basename(name)
if basename not in digests:
digests[basename] = []
digests[basename].extend(self.digest(name))
digestname = basename[:-len(ext)]
if digestname not in digestnames:
digestnames[digestname] = []
digestnames[digestname].append(basename)
result = []
for name, basenames in digestnames.items():
result.append(_os.path.join(self._dist, name + '.digests'))
fp = open(result[-1], 'wb')
try:
fp.write(
b'\n# The file may contain MD5, SHA1 and SHA256 digests\n'
)
fp.write(b'# Check archive integrity with, e.g. md5sum -c\n')
fp.write(b'# Check digest file integrity with PGP\n\n')
basenames.sort()
for basename in basenames:
for digest in digests[basename]:
fp.write((
"%s *%s\n" % (digest, basename)).encode('utf-8')
)
finally:
fp.close()
return result
def digest(self, filename):
result = []
for method in (self.md5, self.sha1, self.sha256):
digest = method(filename)
if digest is not None:
result.append(digest)
return result
def do_digest(self, hashfunc, name, filename):
filename = _shell.native(filename)
_term.green("%(digest)s-digesting %(name)s...",
digest=name, name=_os.path.basename(filename))
fp = open(filename, 'rb')
sig = hashfunc()
block = fp.read(8192)
while block:
sig.update(block)
block = fp.read(8192)
fp.close()
return sig.hexdigest()
param = {'sig': sig.hexdigest(), 'file': _os.path.basename(filename)}
fp = open("%s.%s" % (filename, name), "w")
fp.write("%(sig)s *%(file)s\n" % param)
fp.close()
return True
def md5(self, filename):
try:
from hashlib import md5
except ImportError:
try:
from md5 import new as md5
except ImportError:
_make.warn("md5 not found -> skip md5 digests", self.NAME)
return None
return self.do_digest(md5, "md5", filename)
def sha1(self, filename):
try:
from hashlib import sha1
except ImportError:
try:
from sha import new as sha1
except ImportError:
_make.warn("sha1 not found -> skip sha1 digests", self.NAME)
return None
return self.do_digest(sha1, "sha1", filename)
def sha256(self, filename):
try:
from hashlib import sha256
except ImportError:
try:
from Crypto.Hash.SHA256 import new as sha256
except ImportError:
_make.warn(
"sha256 not found -> skip sha256 digests", self.NAME
)
return None
return self.do_digest(sha256, "sha256", filename)
def copy_ebuilds(self):
if self._ebuilds is not None:
for src in _shell.files(self._ebuilds, '*.ebuild'):
_shell.cp(src, self._dist)
def copy_changes(self):
if self._changes is not None:
_shell.cp(self._changes, self._dist)
def sign_digests(self, digests):
for digest in digests:
self.sign(digest, detach=False)
def sign(self, filename, detach=True):
filename = _shell.native(filename)
try:
from pyme import core, errors
from pyme.constants.sig import mode
except ImportError:
return self.sign_external(filename, detach=detach)
_term.green("signing %(name)s...", name=_os.path.basename(filename))
sigmode = [mode.CLEAR, mode.DETACH][bool(detach)]
fp = core.Data(file=filename)
sig = core.Data()
try:
c = core.Context()
except errors.GPGMEError:
return self.sign_external(filename, detach=detach)
c.set_armor(1)
try:
c.op_sign(fp, sig, sigmode)
except errors.GPGMEError as e:
_make.fail(str(e))
sig.seek(0, 0)
if detach:
open("%s.asc" % filename, "w").write(sig.read())
else:
open(filename, "w").write(sig.read())
return True
def sign_external(self, filename, detach=True):
""" Sign calling gpg """
gpg = _shell.frompath('gpg')
if gpg is None:
_make.warn('GPG not found -> cannot sign')
return False
if detach:
_shell.spawn(gpg,
'--armor',
'--output', filename + '.asc',
'--detach-sign',
'--',
filename,
)
else:
_shell.spawn(gpg,
'--output', filename + '.signed',
'--clearsign',
'--',
filename,
)
_os.rename(filename + '.signed', filename)
return True
def clean(self, scm, dist):
_term.green("Removing dist files...")
_shell.rm_rf(self._dist)
class Manifest(_make.Target):
""" Create manifest """
NAME = "MANIFEST"
HIDDEN = True
DEPS = ["doc"]
def run(self):
_term.green("Creating %(name)s...", name=self.NAME)
dest = _shell.native(self.NAME)
dest = open(dest, 'w')
for name in self.manifest_names():
dest.write("%s\n" % name)
dest.close()
def manifest_names(self):
import setup
for item in setup.manifest():
yield item
def clean(self, scm, dist):
""" Clean manifest """
if scm:
_term.green("Removing MANIFEST")
_shell.rm(self.NAME)

View File

@ -1,420 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007 - 2013
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
===================
Main setup runner
===================
This module provides a wrapper around the distutils core setup.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import configparser as _config_parser
from distutils import core as _core
import os as _os
import posixpath as _posixpath
import sys as _sys
from _setup import commands as _commands
from _setup import data as _data
from _setup import ext as _ext
from _setup import util as _util
from _setup import shell as _shell
def check_python_version(impl, version_min, version_max):
""" Check python version """
if impl == 'python':
version_info = _sys.version_info
elif impl == 'pypy':
version_info = getattr(_sys, 'pypy_version_info', None)
if not version_info:
return
elif impl == 'jython':
if not 'java' in _sys.platform.lower():
return
version_info = _sys.version_info
else:
raise AssertionError("impl not in ('python', 'pypy', 'jython')")
pyversion = list(map(int, version_info[:3]))
if version_min:
min_required = list(
map(int, '.'.join((version_min, '0.0.0')).split('.')[:3])
)
if pyversion < min_required:
raise EnvironmentError("Need at least %s %s (vs. %s)" % (
impl, version_min, '.'.join(map(str, pyversion))
))
if version_max:
max_required = list(map(int, version_max.split('.')))
max_required[-1] += 1
if pyversion >= max_required:
raise EnvironmentError("Need at max %s %s (vs. %s)" % (
impl,
version_max,
'.'.join(map(str, pyversion))
))
def find_description(docs):
"""
Determine the package description from DESCRIPTION
:Parameters:
`docs` : ``dict``
Docs config section
:Return: Tuple of summary, description and license
(``('summary', 'description', 'license')``)
(all may be ``None``)
:Rtype: ``tuple``
"""
summary = None
filename = docs.get('meta.summary', 'SUMMARY').strip()
if filename and _os.path.isfile(filename):
fp = open(filename)
try:
try:
summary = fp.read().strip().splitlines()[0].rstrip()
except IndexError:
summary = ''
finally:
fp.close()
description = None
filename = docs.get('meta.description', 'DESCRIPTION').strip()
if filename and _os.path.isfile(filename):
fp = open(filename)
try:
description = fp.read().rstrip()
finally:
fp.close()
if summary is None and description:
from docutils import core
summary = core.publish_parts(
source=description,
source_path=filename,
writer_name='html',
)['title'].encode('utf-8')
return summary, description
def find_classifiers(docs):
"""
Determine classifiers from CLASSIFIERS
:return: List of classifiers (``['classifier', ...]``)
:rtype: ``list``
"""
filename = docs.get('meta.classifiers', 'CLASSIFIERS').strip()
if filename and _os.path.isfile(filename):
fp = open(filename)
try:
content = fp.read()
finally:
fp.close()
content = [item.strip() for item in content.splitlines()]
return [item for item in content if item and not item.startswith('#')]
return []
def find_provides(docs):
"""
Determine provides from PROVIDES
:return: List of provides (``['provides', ...]``)
:rtype: ``list``
"""
filename = docs.get('meta.provides', 'PROVIDES').strip()
if filename and _os.path.isfile(filename):
fp = open(filename)
try:
content = fp.read()
finally:
fp.close()
content = [item.strip() for item in content.splitlines()]
return [item for item in content if item and not item.startswith('#')]
return []
def find_license(docs):
"""
Determine license from LICENSE
:return: License text
:rtype: ``str``
"""
filename = docs.get('meta.license', 'LICENSE').strip()
if filename and _os.path.isfile(filename):
fp = open(filename)
try:
return fp.read().rstrip()
finally:
fp.close()
return None
def find_packages(manifest):
""" Determine packages and subpackages """
packages = {}
collect = manifest.get('packages.collect', '').split()
lib = manifest.get('packages.lib', '.')
try:
sep = _os.path.sep
except AttributeError:
sep = _os.path.join('1', '2')[1:-1]
for root in collect:
for dirpath, _, filenames in _shell.walk(_os.path.join(lib, root)):
if dirpath.find('.svn') >= 0 or dirpath.find('.git') >= 0:
continue
if '__init__.py' in filenames:
packages[
_os.path.normpath(dirpath).replace(sep, '.')
] = None
packages = list(packages.keys())
packages.sort()
return packages
def find_data(name, docs):
""" Determine data files """
result = []
if docs.get('extra', '').strip():
result.append(_data.Documentation(docs['extra'].split(),
prefix='share/doc/%s' % name,
))
if docs.get('examples.dir', '').strip():
tpl = ['recursive-include %s *' % docs['examples.dir']]
if docs.get('examples.ignore', '').strip():
tpl.extend(["global-exclude %s" % item
for item in docs['examples.ignore'].split()
])
strip = int(docs.get('examples.strip', '') or 0)
result.append(_data.Documentation.from_templates(*tpl, **{
'strip': strip,
'prefix': 'share/doc/%s' % name,
'preserve': 1,
}))
if docs.get('userdoc.dir', '').strip():
tpl = ['recursive-include %s *' % docs['userdoc.dir']]
if docs.get('userdoc.ignore', '').strip():
tpl.extend(["global-exclude %s" % item
for item in docs['userdoc.ignore'].split()
])
strip = int(docs.get('userdoc.strip', '') or 0)
result.append(_data.Documentation.from_templates(*tpl, **{
'strip': strip,
'prefix': 'share/doc/%s' % name,
'preserve': 1,
}))
if docs.get('apidoc.dir', '').strip():
tpl = ['recursive-include %s *' % docs['apidoc.dir']]
if docs.get('apidoc.ignore', '').strip():
tpl.extend(["global-exclude %s" % item
for item in docs['apidoc.ignore'].split()
])
strip = int(docs.get('apidoc.strip', '') or 0)
result.append(_data.Documentation.from_templates(*tpl, **{
'strip': strip,
'prefix': 'share/doc/%s' % name,
'preserve': 1,
}))
if docs.get('man', '').strip():
result.extend(_data.Manpages.dispatch(docs['man'].split()))
return result
def make_manifest(manifest, config, docs, kwargs):
""" Create file list to pack up """
# pylint: disable = R0912
kwargs = kwargs.copy()
kwargs['script_args'] = ['install']
kwargs['packages'] = list(kwargs.get('packages') or ()) + [
'_setup', '_setup.py2', '_setup.py3',
] + list(manifest.get('packages.extra', '').split() or ())
_core._setup_stop_after = "commandline"
try:
dist = _core.setup(**kwargs)
finally:
_core._setup_stop_after = None
result = ['MANIFEST', 'PKG-INFO', 'setup.py'] + list(config)
# TODO: work with default values:
for key in ('classifiers', 'description', 'summary', 'provides',
'license'):
filename = docs.get('meta.' + key, '').strip()
if filename and _os.path.isfile(filename):
result.append(filename)
cmd = dist.get_command_obj("build_py")
cmd.ensure_finalized()
#from pprint import pprint; pprint(("build_py", cmd.get_source_files()))
for item in cmd.get_source_files():
result.append(_posixpath.sep.join(
_os.path.normpath(item).split(_os.path.sep)
))
cmd = dist.get_command_obj("build_ext")
cmd.ensure_finalized()
#from pprint import pprint; pprint(("build_ext", cmd.get_source_files()))
for item in cmd.get_source_files():
result.append(_posixpath.sep.join(
_os.path.normpath(item).split(_os.path.sep)
))
for ext in cmd.extensions:
if ext.depends:
result.extend([_posixpath.sep.join(
_os.path.normpath(item).split(_os.path.sep)
) for item in ext.depends])
cmd = dist.get_command_obj("build_clib")
cmd.ensure_finalized()
if cmd.libraries:
#import pprint; pprint.pprint(("build_clib", cmd.get_source_files()))
for item in cmd.get_source_files():
result.append(_posixpath.sep.join(
_os.path.normpath(item).split(_os.path.sep)
))
for lib in cmd.libraries:
if lib[1].get('depends'):
result.extend([_posixpath.sep.join(
_os.path.normpath(item).split(_os.path.sep)
) for item in lib[1]['depends']])
cmd = dist.get_command_obj("build_scripts")
cmd.ensure_finalized()
#import pprint; pprint.pprint(("build_scripts", cmd.get_source_files()))
if cmd.get_source_files():
for item in cmd.get_source_files():
result.append(_posixpath.sep.join(
_os.path.normpath(item).split(_os.path.sep)
))
cmd = dist.get_command_obj("install_data")
cmd.ensure_finalized()
#from pprint import pprint; pprint(("install_data", cmd.get_inputs()))
try:
strings = str
except NameError:
strings = (str, str)
for item in cmd.get_inputs():
if isinstance(item, strings):
result.append(item)
else:
result.extend(item[1])
for item in manifest.get('dist', '').split():
result.append(item)
if _os.path.isdir(item):
for filename in _shell.files(item):
result.append(filename)
result = list(dict([(item, None) for item in result]).keys())
result.sort()
return result
def run(config=('package.cfg',), ext=None, script_args=None, manifest_only=0):
""" Main runner """
if ext is None:
ext = []
cfg = _util.SafeConfigParser()
cfg.read(config)
pkg = dict(cfg.items('package'))
python_min = pkg.get('python.min') or None
python_max = pkg.get('python.max') or None
check_python_version('python', python_min, python_max)
pypy_min = pkg.get('pypy.min') or None
pypy_max = pkg.get('pypy.max') or None
check_python_version('pypy', pypy_min, pypy_max)
jython_min = pkg.get('jython.min') or None
jython_max = pkg.get('jython.max') or None
check_python_version('jython', jython_min, jython_max)
manifest = dict(cfg.items('manifest'))
try:
docs = dict(cfg.items('docs'))
except _config_parser.NoSectionError:
docs = {}
summary, description = find_description(docs)
scripts = manifest.get('scripts', '').strip() or None
if scripts:
scripts = scripts.split()
modules = manifest.get('modules', '').strip() or None
if modules:
modules = modules.split()
keywords = docs.get('meta.keywords', '').strip() or None
if keywords:
keywords = keywords.split()
revision = pkg.get('version.revision', '').strip()
if revision:
revision = "-r%s" % (revision,)
kwargs = {
'name': pkg['name'],
'version': "%s%s" % (
pkg['version.number'],
["", "-dev%s" % (revision,)][_util.humanbool(
'version.dev', pkg.get('version.dev', 'false')
)],
),
'provides': find_provides(docs),
'description': summary,
'long_description': description,
'classifiers': find_classifiers(docs),
'keywords': keywords,
'author': pkg['author.name'],
'author_email': pkg['author.email'],
'maintainer': pkg.get('maintainer.name'),
'maintainer_email': pkg.get('maintainer.email'),
'url': pkg.get('url.homepage'),
'download_url': pkg.get('url.download'),
'license': find_license(docs),
'package_dir': {'': manifest.get('packages.lib', '.')},
'packages': find_packages(manifest),
'py_modules': modules,
'ext_modules': ext,
'scripts': scripts,
'script_args': script_args,
'data_files': find_data(pkg['name'], docs),
'cmdclass': {
'build' : _commands.Build,
'build_ext' : _commands.BuildExt,
'install' : _commands.Install,
'install_data': _commands.InstallData,
'install_lib' : _commands.InstallLib,
}
}
for key in ('provides',):
if key not in _core.setup_keywords:
del kwargs[key]
if manifest_only:
return make_manifest(manifest, config, docs, kwargs)
# monkey-patch crappy manifest writer away.
from distutils.command import sdist
sdist.sdist.get_file_list = sdist.sdist.read_manifest
return _core.setup(**kwargs)

View File

@ -1,351 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007 - 2013
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
=================
Shell utilities
=================
Shell utilities.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import errno as _errno
import fnmatch as _fnmatch
import os as _os
import shutil as _shutil
import subprocess as _subprocess
import sys as _sys
import tempfile as _tempfile
cwd = _os.path.dirname(_os.path.abspath(_sys.argv[0]))
class ExitError(RuntimeError):
""" Exit error """
def __init__(self, code):
RuntimeError.__init__(self, code)
self.code = code
self.signal = None
class SignalError(ExitError):
""" Signal error """
def __init__(self, code, signal):
ExitError.__init__(self, code)
import signal as _signal
self.signal = signal
for key, val in vars(_signal).items():
if key.startswith('SIG') and not key.startswith('SIG_'):
if val == signal:
self.signalstr = key[3:]
break
else:
self.signalstr = '%04d' % signal
def native(path):
""" Convert slash path to native """
path = _os.path.sep.join(path.split('/'))
return _os.path.normpath(_os.path.join(cwd, path))
def cp(src, dest):
""" Copy src to dest """
_shutil.copy2(native(src), native(dest))
def cp_r(src, dest):
""" Copy -r src to dest """
_shutil.copytree(native(src), native(dest))
def rm(dest):
""" Remove a file """
try:
_os.unlink(native(dest))
except OSError as e:
if _errno.ENOENT != e.errno:
raise
def rm_rf(dest):
""" Remove a tree """
dest = native(dest)
if _os.path.exists(dest):
for path in files(dest, '*'):
_os.chmod(native(path), 0o644)
_shutil.rmtree(dest)
mkstemp = _tempfile.mkstemp
def _pipespawn(argv, env):
""" Pipe spawn """
# pylint: disable = R0912
import pickle as _pickle
fd, name = mkstemp('.py')
try:
_os.write(fd, ((r"""
import os
import pickle
import subprocess
import sys
argv = pickle.loads(%(argv)s)
env = pickle.loads(%(env)s)
if 'X_JYTHON_WA_PATH' in env:
env['PATH'] = env['X_JYTHON_WA_PATH']
p = subprocess.Popen(argv, env=env)
result = p.wait()
if result < 0:
print("\n%%d 1" %% (-result))
sys.exit(2)
if result == 0:
sys.exit(0)
print("\n%%d" %% (result & 7,))
sys.exit(3)
""".strip() + "\n") % {
'argv': repr(_pickle.dumps(argv)),
'env': repr(_pickle.dumps(dict(env))),
}).encode('utf-8'))
fd, _ = None, _os.close(fd)
if _sys.platform == 'win32':
argv = []
for arg in [_sys.executable, name]:
if ' ' in arg or arg.startswith('"'):
arg = '"%s"' % arg.replace('"', '\\"')
argv.append(arg)
argv = ' '.join(argv)
shell = True
close_fds = False
else:
argv = [_sys.executable, name]
shell = False
close_fds = True
res = 0
if 'X_JYTHON_WA_PATH' in env:
env['PATH'] = env['X_JYTHON_WA_PATH']
proc = _subprocess.Popen(argv,
shell=shell,
stdin=_subprocess.PIPE,
stdout=_subprocess.PIPE,
close_fds=close_fds,
env=env,
)
try:
proc.stdin.close()
result = proc.stdout.read()
finally:
res = proc.wait()
if res != 0:
if res == 2:
signal, code = list(map(int, result.splitlines()[-1].split()))
raise SignalError(code, signal)
elif res == 3:
code = int(result.splitlines()[-1].strip())
raise ExitError(code)
raise ExitError(res)
return result.decode('latin-1')
finally:
try:
if fd is not None:
_os.close(fd)
finally:
_os.unlink(name)
def _filepipespawn(infile, outfile, argv, env):
""" File Pipe spawn """
import pickle as _pickle
fd, name = mkstemp('.py')
try:
_os.write(fd, (("""
import os
import pickle
import sys
infile = pickle.loads(%(infile)s)
outfile = pickle.loads(%(outfile)s)
argv = pickle.loads(%(argv)s)
env = pickle.loads(%(env)s)
if infile is not None:
infile = open(infile, 'rb')
os.dup2(infile.fileno(), 0)
infile.close()
if outfile is not None:
outfile = open(outfile, 'wb')
os.dup2(outfile.fileno(), 1)
outfile.close()
pid = os.spawnve(os.P_NOWAIT, argv[0], argv, env)
result = os.waitpid(pid, 0)[1]
sys.exit(result & 7)
""".strip() + "\n") % {
'infile': repr(_pickle.dumps(_os.path.abspath(infile))),
'outfile': repr(_pickle.dumps(_os.path.abspath(outfile))),
'argv': repr(_pickle.dumps(argv)),
'env': repr(_pickle.dumps(env)),
}))
fd, _ = None, _os.close(fd)
if _sys.platform == 'win32':
argv = []
for arg in [_sys.executable, name]:
if ' ' in arg or arg.startswith('"'):
arg = '"%s"' % arg.replace('"', '\\"')
argv.append(arg)
argv = ' '.join(argv)
close_fds = False
shell = True
else:
argv = [_sys.executable, name]
close_fds = True
shell = False
p = _subprocess.Popen(
argv, env=env, shell=shell, close_fds=close_fds
)
return p.wait()
finally:
try:
if fd is not None:
_os.close(fd)
finally:
_os.unlink(name)
def spawn(*argv, **kwargs):
""" Spawn a process """
if _sys.platform == 'win32':
newargv = []
for arg in argv:
if not arg or ' ' in arg or arg.startswith('"'):
arg = '"%s"' % arg.replace('"', '\\"')
newargv.append(arg)
argv = newargv
close_fds = False
shell = True
else:
close_fds = True
shell = False
env = kwargs.get('env')
if env is None:
env = dict(_os.environ)
if 'X_JYTHON_WA_PATH' in env:
env['PATH'] = env['X_JYTHON_WA_PATH']
echo = kwargs.get('echo')
if echo:
print(' '.join(argv))
filepipe = kwargs.get('filepipe')
if filepipe:
return _filepipespawn(
kwargs.get('stdin'), kwargs.get('stdout'), argv, env
)
pipe = kwargs.get('stdout')
if pipe:
return _pipespawn(argv, env)
p = _subprocess.Popen(argv, env=env, shell=shell, close_fds=close_fds)
return p.wait()
walk = _os.walk
def files(base, wildcard='[!.]*', recursive=1, prune=('.git', '.svn', 'CVS')):
""" Determine a filelist """
for dirpath, dirnames, filenames in walk(native(base)):
for item in prune:
if item in dirnames:
dirnames.remove(item)
filenames.sort()
for name in _fnmatch.filter(filenames, wildcard):
dest = _os.path.join(dirpath, name)
if dest.startswith(cwd):
dest = dest.replace(cwd, '', 1)
aslist = []
head, tail = _os.path.split(dest)
while tail:
aslist.append(tail)
head, tail = _os.path.split(head)
aslist.reverse()
dest = '/'.join(aslist)
yield dest
if not recursive:
break
dirnames.sort()
def dirs(base, wildcard='[!.]*', recursive=1, prune=('.git', '.svn', 'CVS')):
""" Determine a filelist """
for dirpath, dirnames, filenames in walk(native(base)):
for item in prune:
if item in dirnames:
dirnames.remove(item)
dirnames.sort()
for name in _fnmatch.filter(dirnames, wildcard):
dest = _os.path.join(dirpath, name)
if dest.startswith(cwd):
dest = dest.replace(cwd, '', 1)
aslist = []
head, tail = _os.path.split(dest)
while tail:
aslist.append(tail)
head, tail = _os.path.split(head)
aslist.reverse()
dest = '/'.join(aslist)
yield dest
if not recursive:
break
def frompath(executable):
""" Find executable in PATH """
# Based on distutils.spawn.find_executable.
path = _os.environ.get('PATH', '')
paths = [
_os.path.expanduser(item)
for item in path.split(_os.pathsep)
]
ext = _os.path.splitext(executable)[1]
exts = ['']
if _sys.platform == 'win32' or _os.name == 'os2':
eext = ['.exe', '.bat', '.py']
if ext not in eext:
exts.extend(eext)
for ext in exts:
if not _os.path.isfile(executable + ext):
for path in paths:
fname = _os.path.join(path, executable + ext)
if _os.path.isfile(fname):
# the file exists, we have a shot at spawn working
return fname
else:
return executable + ext
return None

View File

@ -1,28 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
=====================
Package _setup.term
=====================
Terminal tools, not distributed.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
# pylint: disable = W0611
from _setup.term._term import terminfo, write, green, red, yellow, announce

View File

@ -1,116 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
=================
Terminal writer
=================
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
import sys as _sys
class _INFO(dict):
""" Terminal info dict """
def __init__(self):
""" Initialization """
dict.__init__(self, {
'NORMAL': '',
'BOLD': '',
'ERASE': '\n',
'RED': '',
'YELLOW': '',
'GREEN': '',
})
try:
import curses as _curses
except ImportError:
# fixup if a submodule of curses failed.
if 'curses' in _sys.modules:
del _sys.modules['curses']
else:
try:
_curses.setupterm()
except (TypeError, _curses.error):
pass
else:
def make_color(color):
""" Make color control string """
seq = _curses.tigetstr('setaf').decode('ascii')
if seq is not None:
# XXX may fail - need better logic
seq = seq.replace("%p1", "") % color
return seq
self['NORMAL'] = _curses.tigetstr('sgr0').decode('ascii')
self['BOLD'] = _curses.tigetstr('bold').decode('ascii')
erase = _curses.tigetstr('el1').decode('ascii')
if erase is not None:
self['ERASE'] = erase + \
_curses.tigetstr('cr').decode('ascii')
self['RED'] = make_color(_curses.COLOR_RED)
self['YELLOW'] = make_color(_curses.COLOR_YELLOW)
self['GREEN'] = make_color(_curses.COLOR_GREEN)
def __getitem__(self, key):
""" Deliver always """
dict.get(self, key) or ""
def terminfo():
""" Get info singleton """
# pylint: disable = E1101, W0612
if terminfo.info is None:
terminfo.info = _INFO()
return terminfo.info
terminfo.info = None
def write(fmt, **kwargs):
""" Write stuff on the terminal """
parm = dict(terminfo())
parm.update(kwargs)
_sys.stdout.write(fmt % parm)
_sys.stdout.flush()
def green(bmt, **kwargs):
""" Write something in green on screen """
announce("%%(GREEN)s%s%%(NORMAL)s" % bmt, **kwargs)
def red(bmt, **kwargs):
""" Write something in red on the screen """
announce("%%(BOLD)s%%(RED)s%s%%(NORMAL)s" % bmt, **kwargs)
def yellow(fmt, **kwargs):
""" Write something in yellow on the screen """
announce("%%(BOLD)s%%(YELLOW)s%s%%(NORMAL)s" % fmt, **kwargs)
def announce(fmt, **kwargs):
""" Announce something """
write(fmt, **kwargs)
_sys.stdout.write("\n")
_sys.stdout.flush()

View File

@ -1,63 +0,0 @@
# -*- coding: ascii -*-
#
# Copyright 2007, 2008, 2009, 2010, 2011
# Andr\xe9 Malo or his licensors, as applicable
#
# Licensed 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.
"""
=================
Setup utilities
=================
Setup utilities.
"""
__author__ = "Andr\xe9 Malo"
__docformat__ = "restructuredtext en"
from distutils import util as _util
try:
from configparser import SafeConfigParser
except ImportError:
import configparser as _config_parser
class SafeConfigParser(_config_parser.ConfigParser):
""" Safe config parser """
def _interpolate(self, section, option, rawval, vars):
return rawval
def items(self, section):
return [(key, self.get(section, key))
for key in self.options(section)
]
def humanbool(name, value):
"""
Determine human boolean value
:Parameters:
`name` : ``str``
The config key (used for error message)
`value` : ``str``
The config value
:Return: The boolean value
:Rtype: ``bool``
:Exceptions:
- `ValueError` : The value could not be recognized
"""
try:
return _util.strtobool(str(value).strip().lower() or 'no')
except ValueError:
raise ValueError("Unrecognized config value: %s = %s" % (name, value))