summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--attoconf/_version.py4
-rw-r--r--attoconf/classy.py4
-rw-r--r--attoconf/core.py14
-rw-r--r--attoconf/lib/arches.py23
-rw-r--r--attoconf/lib/c.py26
-rw-r--r--attoconf/lib/install.py124
-rw-r--r--attoconf/tests/test_core.py25
-rw-r--r--attoconf/types.py23
8 files changed, 136 insertions, 107 deletions
diff --git a/attoconf/_version.py b/attoconf/_version.py
index 28024a6..18e1fb6 100644
--- a/attoconf/_version.py
+++ b/attoconf/_version.py
@@ -7,11 +7,11 @@ major = 0
# Incremented for releases with compatible API additions.
# This is the number that is usually incremented.
-minor = 8
+minor = 9
# Incremented if there is a bugfix release.
# Might not be contiguous.
-patch = 6
+patch = 0
# Reserved for distributors and forks.
# Contains arbitrary text, but no parentheses or newlines.
diff --git a/attoconf/classy.py b/attoconf/classy.py
index a2891dc..a27230d 100644
--- a/attoconf/classy.py
+++ b/attoconf/classy.py
@@ -68,9 +68,9 @@ class ClassyProject(Project):
self.add_help('General:', hidden=False)
self.add_alias('--help', ['--help=default'],
help='display standard help, then exit', hidden=False)
- self.add_option('--help', init=None,
+ self.add_option('--help', init='none',
type=self.do_help, check=None,
- help='display some kind of help', hidden=False,
+ help='just display some kind of help instead of configuring', hidden=False,
help_var='KIND')
self.help.add_option('--help=hidden',
help='display help you should never ever ever care about',
diff --git a/attoconf/core.py b/attoconf/core.py
index bb9d2ba..0d196e9 100644
--- a/attoconf/core.py
+++ b/attoconf/core.py
@@ -103,8 +103,9 @@ class Project(object):
# used by some tests ... should this be fixed there instead?
if help_var is None:
help_var = var
- if init is not None:
- init = type(init)
+ assert init is not None
+ init = type(init)
+ assert init is not None
self.options[name] = Option(init=init, type=type)
if check is not None:
self.order.append(var)
@@ -113,10 +114,11 @@ class Project(object):
if help_var is None:
help_var = var
+
if help_def is None:
help_def = init
- if help_def is not None:
- help = '%s [%s]' % (help, help_def)
+ assert help_def is not None
+ help = '%s [%s]' % (help, help_def)
if help_var != name:
help_opt = '%s=%s' % (name, help_var)
@@ -127,12 +129,14 @@ class Project(object):
def do_help(self, opt):
''' Pseudo type-hook to be registered for --help (calls sys.exit).
'''
+ if opt == 'none':
+ return opt
if opt == 'default':
hidden = False
elif opt == 'hidden':
hidden = True
else:
- raise ValueError
+ raise ValueError('Unknown value for opt: %r' % opt)
self.help.print(sys.stdout, hidden)
sys.exit()
# sneaky
diff --git a/attoconf/lib/arches.py b/attoconf/lib/arches.py
index cffd8ca..8c70f0b 100644
--- a/attoconf/lib/arches.py
+++ b/attoconf/lib/arches.py
@@ -18,21 +18,19 @@
from __future__ import print_function, division, absolute_import
from ..classy import ClassyProject
-from ..types import triple
+from ..types import triple, maybe
-# TODO: see if there's a way to expose them sanely, without using Nones
-# (currently I never emit them: instead I pop the order)
def build(build, BUILD):
pass
def host(build, HOST):
- if HOST is None:
+ if not HOST:
BUILD = build.vars['BUILD']
build.vars['HOST'] = BUILD
def target(build, TARGET):
- if TARGET is None:
+ if not TARGET:
HOST = build.vars['HOST']
build.vars['TARGET'] = HOST
@@ -42,24 +40,21 @@ class Arches2(ClassyProject):
def arches(self):
super(Arches2, self).arches()
self.add_help('System types:', hidden=False)
- self.add_option('--build', init=None,
- type=triple, check=build,
+ self.add_option('--build', init='',
+ type=maybe(triple), check=build,
help='configure for building on BUILD', hidden=False,
help_def='native')
- self.order.pop()
- self.add_option('--host', init=None,
- type=triple, check=host,
+ self.add_option('--host', init='',
+ type=maybe(triple), check=host,
help='cross-compile to build programs to run on HOST',
hidden=False, help_def='BUILD')
- self.order.pop()
# TODO figure out the mro implications when I use this
class Arches3(Arches2):
__slots__ = ()
def arches(self):
super(Arches3, self).arches()
- self.add_option('--target', init=None,
- type=triple, check=target,
+ self.add_option('--target', init='',
+ type=maybe(triple), check=target,
help='configure for building compilers for TARGET',
hidden=False, help_def='HOST')
- self.order.pop()
diff --git a/attoconf/lib/c.py b/attoconf/lib/c.py
index 3b6f05f..bc32c49 100644
--- a/attoconf/lib/c.py
+++ b/attoconf/lib/c.py
@@ -208,7 +208,12 @@ def cppflags(build, CPPFLAGS):
pass
def cc(build, CC):
- pass
+ if CC.list == []:
+ HOST = build.vars['HOST']
+ if HOST:
+ build.vars['CC'].list = [HOST + '-gcc']
+ else:
+ build.vars['CC'].list = ['gcc']
def cflags(build, CFLAGS):
try_compile_c(build, 'int main() {}\n')
@@ -216,7 +221,12 @@ def cflags(build, CFLAGS):
try_compile_link2_c(build, 'int main() {}\n')
def cxx(build, CXX):
- pass
+ if CXX.list == []:
+ HOST = build.vars['HOST']
+ if HOST:
+ build.vars['CXX'].list = [HOST + '-g++']
+ else:
+ build.vars['CXX'].list = ['g++']
def cxxflags(build, CXXFLAGS):
try_compile_cxx(build, 'int main() {}\n')
@@ -235,7 +245,7 @@ class Link(Arches2):
type=ShellList, check=libs,
help='libraries to pass to the linker, e.g. -l<library>',
hidden=False)
- self.order.append('LDLIBS')
+ self.order.append('LDLIBS') #TODO remove for 1.0
class Preprocess(Arches2):
__slots__ = ()
@@ -250,9 +260,10 @@ class C(Link, Preprocess):
__slots__ = ()
def vars(self):
super(C, self).vars()
- self.add_option('CC', init=['gcc'],
+ self.add_option('CC', init=[],
type=ShellList, check=cc,
- help='C compiler command', hidden=False)
+ help='C compiler command', hidden=False,
+ help_def='HOST-gcc')
self.add_option('CFLAGS', init=['-O2', '-g'],
type=ShellList, check=cflags,
help='C compiler flags', hidden=False)
@@ -261,9 +272,10 @@ class Cxx(Link, Preprocess):
__slots__ = ()
def vars(self):
super(Cxx, self).vars()
- self.add_option('CXX', init=['g++'],
+ self.add_option('CXX', init=[],
type=ShellList, check=cxx,
- help='C++ compiler command', hidden=False)
+ help='C++ compiler command', hidden=False,
+ help_def='HOST-g++')
self.add_option('CXXFLAGS', init=['-O2', '-g'],
type=ShellList, check=cxxflags,
help='C++ compiler flags', hidden=False)
diff --git a/attoconf/lib/install.py b/attoconf/lib/install.py
index 1a55c29..f43b2a1 100644
--- a/attoconf/lib/install.py
+++ b/attoconf/lib/install.py
@@ -20,7 +20,7 @@ from __future__ import print_function, division, absolute_import
import os
from ..classy import ClassyProject
-from ..types import shell_word, filepath, quoted_string
+from ..types import shell_word, filepath, quoted_string, maybe
def package(build, PACKAGE):
@@ -33,48 +33,48 @@ def prefix(build, PREFIX):
pass
def exec_prefix(build, EPREFIX):
- if EPREFIX is None:
+ if not EPREFIX:
PREFIX = build.vars['PREFIX']
build.vars['EXEC_PREFIX'] = PREFIX
build.vars['EPREFIX'] = build.vars['EXEC_PREFIX']
def bindir(build, DIR):
- if DIR is None:
+ if not DIR:
EPREFIX = build.vars['EPREFIX']
build.vars['BINDIR'] = os.path.join(EPREFIX, 'bin')
def sbindir(build, DIR):
- if DIR is None:
+ if not DIR:
EPREFIX = build.vars['EPREFIX']
build.vars['SBINDIR'] = os.path.join(EPREFIX, 'sbin')
def libexecdir(build, DIR):
- if DIR is None:
+ if not DIR:
EPREFIX = build.vars['EPREFIX']
build.vars['LIBEXECDIR'] = os.path.join(EPREFIX, 'libexec')
def sysconfdir(build, DIR):
- if DIR is None:
+ if not DIR:
PREFIX = build.vars['PREFIX']
build.vars['SYSCONFDIR'] = os.path.join(PREFIX, 'etc')
def sharedstatedir(build, DIR):
- if DIR is None:
+ if not DIR:
PREFIX = build.vars['PREFIX']
build.vars['SHAREDSTATEDIR'] = os.path.join(PREFIX, 'com')
def localstatedir(build, DIR):
- if DIR is None:
+ if not DIR:
PREFIX = build.vars['PREFIX']
build.vars['LOCALSTATEDIR'] = os.path.join(PREFIX, 'var')
def libdir(build, DIR):
- if DIR is None:
+ if not DIR:
EPREFIX = build.vars['EPREFIX']
build.vars['LIBDIR'] = os.path.join(EPREFIX, 'lib')
def includedir(build, DIR):
- if DIR is None:
+ if not DIR:
PREFIX = build.vars['PREFIX']
build.vars['INCLUDEDIR'] = os.path.join(PREFIX, 'include')
@@ -82,59 +82,59 @@ def oldincludedir(build, DIR):
pass
def datarootdir(build, DIR):
- if DIR is None:
+ if not DIR:
PREFIX = build.vars['PREFIX']
build.vars['DATAROOTDIR'] = os.path.join(PREFIX, 'share')
def datadir(build, DIR):
- if DIR is None:
+ if not DIR:
DATAROOTDIR = build.vars['DATAROOTDIR']
build.vars['DATADIR'] = DATAROOTDIR
def packagedatadir(build, DIR):
- if DIR is None:
+ if not DIR:
DATADIR = build.vars['DATADIR']
PACKAGE = build.vars['PACKAGE']
build.vars['PACKAGEDATADIR'] = os.path.join(DATADIR, PACKAGE)
def infodir(build, DIR):
- if DIR is None:
+ if not DIR:
DATAROOTDIR = build.vars['DATAROOTDIR']
build.vars['INFODIR'] = os.path.join(DATAROOTDIR, 'info')
def localedir(build, DIR):
- if DIR is None:
+ if not DIR:
DATAROOTDIR = build.vars['DATAROOTDIR']
build.vars['LOCALEDIR'] = os.path.join(DATAROOTDIR, 'locale')
def mandir(build, DIR):
- if DIR is None:
+ if not DIR:
DATAROOTDIR = build.vars['DATAROOTDIR']
build.vars['MANDIR'] = os.path.join(DATAROOTDIR, 'man')
def docdir(build, DIR):
- if DIR is None:
+ if not DIR:
DATAROOTDIR = build.vars['DATAROOTDIR']
PACKAGE = build.vars['PACKAGE']
build.vars['DOCDIR'] = os.path.join(DATAROOTDIR, 'doc', PACKAGE)
def htmldir(build, DIR):
- if DIR is None:
+ if not DIR:
DOCDIR = build.vars['DOCDIR']
build.vars['HTMLDIR'] = DOCDIR
def dvidir(build, DIR):
- if DIR is None:
+ if not DIR:
DOCDIR = build.vars['DOCDIR']
build.vars['DVIDIR'] = DOCDIR
def pdfdir(build, DIR):
- if DIR is None:
+ if not DIR:
DOCDIR = build.vars['DOCDIR']
build.vars['PDFDIR'] = DOCDIR
def psdir(build, DIR):
- if DIR is None:
+ if not DIR:
DOCDIR = build.vars['DOCDIR']
build.vars['PSDIR'] = DOCDIR
@@ -179,93 +179,93 @@ class Install(ClassyProject):
type=filepath, check=prefix,
help='install architecture-independent files in PREFIX',
hidden=False)
- self.add_option('--exec-prefix', init=None,
- type=filepath, check=exec_prefix,
+ self.add_option('--exec-prefix', init='',
+ type=maybe(filepath), check=exec_prefix,
help='install architecture-dependent files in EPREFIX',
hidden=False,
help_var='EPREFIX', help_def='PREFIX')
- self.order.append('EPREFIX')
+ self.order.append('EPREFIX') # TODO remove for 1.0
self.order.append(None)
self.add_help('Fine tuning of the installation directories:',
hidden=False)
- self.add_option('--bindir', init=None,
- type=filepath, check=bindir,
+ self.add_option('--bindir', init='',
+ type=maybe(filepath), check=bindir,
help='user executables', hidden=False,
help_var='DIR', help_def='EPREFIX/bin')
- self.add_option('--sbindir', init=None,
- type=filepath, check=sbindir,
+ self.add_option('--sbindir', init='',
+ type=maybe(filepath), check=sbindir,
help='system admin executables', hidden=False,
help_var='DIR', help_def='EPREFIX/sbin')
- self.add_option('--libexecdir', init=None,
- type=filepath, check=libexecdir,
+ self.add_option('--libexecdir', init='',
+ type=maybe(filepath), check=libexecdir,
help='program executables', hidden=False,
help_var='DIR', help_def='EPREFIX/libexec')
- self.add_option('--sysconfdir', init=None,
- type=filepath, check=sysconfdir,
+ self.add_option('--sysconfdir', init='',
+ type=maybe(filepath), check=sysconfdir,
help='read-only single-machine data', hidden=False,
help_var='DIR', help_def='PREFIX/etc')
- self.add_option('--sharedstatedir', init=None,
- type=filepath, check=sharedstatedir,
+ self.add_option('--sharedstatedir', init='',
+ type=maybe(filepath), check=sharedstatedir,
help='modifiable architecture-independent data', hidden=False,
help_var='DIR', help_def='PREFIX/com')
- self.add_option('--localstatedir', init=None,
- type=filepath, check=localstatedir,
+ self.add_option('--localstatedir', init='',
+ type=maybe(filepath), check=localstatedir,
help='modifiable single-machine data', hidden=False,
help_var='DIR', help_def='PREFIX/var')
- self.add_option('--libdir', init=None,
- type=filepath, check=libdir,
+ self.add_option('--libdir', init='',
+ type=maybe(filepath), check=libdir,
help='object code libraries', hidden=False,
help_var='DIR', help_def='EPREFIX/lib')
- self.add_option('--includedir', init=None,
- type=filepath, check=includedir,
+ self.add_option('--includedir', init='',
+ type=maybe(filepath), check=includedir,
help='C header files', hidden=False,
help_var='DIR', help_def='PREFIX/include')
self.add_option('--oldincludedir', init='/usr/include',
type=filepath, check=oldincludedir,
help='C header files for non-gcc', hidden=False,
help_var='DIR')
- self.add_option('--datarootdir', init=None,
- type=filepath, check=datarootdir,
+ self.add_option('--datarootdir', init='',
+ type=maybe(filepath), check=datarootdir,
help='read-only arch.-independent data root', hidden=False,
help_var='DIR', help_def='PREFIX/share')
- self.add_option('--datadir', init=None,
- type=filepath, check=datadir,
+ self.add_option('--datadir', init='',
+ type=maybe(filepath), check=datadir,
help='read-only architecture-independent data', hidden=False,
help_var='DIR', help_def='DATAROOTDIR')
- self.add_option('--packagedatadir', init=None,
- type=filepath, check=packagedatadir,
+ self.add_option('--packagedatadir', init='',
+ type=maybe(filepath), check=packagedatadir,
help='data specific to this package (please set datadir instead)', hidden=False,
help_var='DIR', help_def='DATADIR/PACKAGE')
- self.add_option('--infodir', init=None,
- type=filepath, check=infodir,
+ self.add_option('--infodir', init='',
+ type=maybe(filepath), check=infodir,
help='info documentation', hidden=False,
help_var='DIR', help_def='DATAROOTDIR/info')
- self.add_option('--localedir', init=None,
- type=filepath, check=localedir,
+ self.add_option('--localedir', init='',
+ type=maybe(filepath), check=localedir,
help='locale-dependent data', hidden=False,
help_var='DIR', help_def='DATAROOTDIR/locale')
- self.add_option('--mandir', init=None,
- type=filepath, check=mandir,
+ self.add_option('--mandir', init='',
+ type=maybe(filepath), check=mandir,
help='man documentation', hidden=False,
help_var='DIR', help_def='DATAROOTDIR/man')
- self.add_option('--docdir', init=None,
- type=filepath, check=docdir,
+ self.add_option('--docdir', init='',
+ type=maybe(filepath), check=docdir,
help='documentation root', hidden=False,
help_var='DIR', help_def='DATAROOTDIR/doc/PACKAGE')
- self.add_option('--htmldir', init=None,
- type=filepath, check=htmldir,
+ self.add_option('--htmldir', init='',
+ type=maybe(filepath), check=htmldir,
help='html documentation', hidden=False,
help_var='DIR', help_def='DOCDIR')
- self.add_option('--dvidir', init=None,
- type=filepath, check=dvidir,
+ self.add_option('--dvidir', init='',
+ type=maybe(filepath), check=dvidir,
help='dvi documentation', hidden=False,
help_var='DIR', help_def='DOCDIR')
- self.add_option('--pdfdir', init=None,
- type=filepath, check=pdfdir,
+ self.add_option('--pdfdir', init='',
+ type=maybe(filepath), check=pdfdir,
help='pdf documentation', hidden=False,
help_var='DIR', help_def='DOCDIR')
- self.add_option('--psdir', init=None,
- type=filepath, check=psdir,
+ self.add_option('--psdir', init='',
+ type=maybe(filepath), check=psdir,
help='ps documentation', hidden=False,
help_var='DIR', help_def='DOCDIR')
diff --git a/attoconf/tests/test_core.py b/attoconf/tests/test_core.py
index f60aab6..09c2c64 100644
--- a/attoconf/tests/test_core.py
+++ b/attoconf/tests/test_core.py
@@ -20,7 +20,7 @@ from __future__ import print_function, division, absolute_import
import unittest
from attoconf.core import Project, Build
-from attoconf.types import uint, shell_word, shell_partial_word
+from attoconf.types import uint, shell_word, shell_partial_word, maybe
import os
from cStringIO import StringIO
@@ -44,7 +44,7 @@ class TestProject(unittest.TestCase):
proj.add_help('General:', False)
proj.add_alias('--help', ['--help=default'],
help='display standard help, then exit', hidden=False)
- proj.add_option('--help', init=None,
+ proj.add_option('--help', init='none',
type=proj.do_help, check=None,
help='display some subset of help', hidden=False,
help_var='TYPE')
@@ -54,8 +54,8 @@ class TestProject(unittest.TestCase):
proj.add_option('--foo', init='asdf',
type=shell_word, check=None,
help='set frob target', hidden=False)
- proj.add_option('--bar', init=None,
- type=shell_word, check=None,
+ proj.add_option('--bar', init='',
+ type=maybe(shell_word), check=None,
help='set frob source', hidden=False,
help_def='FOO')
@@ -68,7 +68,7 @@ class TestProject(unittest.TestCase):
self.assertEqual(out.getvalue(), '''
General:
--help display standard help, then exit
- --help=TYPE display some subset of help
+ --help=TYPE display some subset of help [none]
--foo=FOO set frob target [asdf]
--bar=BAR set frob source [FOO]
@@ -81,7 +81,7 @@ General:
self.assertEqual(out.getvalue(), '''
General:
--help display standard help, then exit
- --help=TYPE display some subset of help
+ --help=TYPE display some subset of help [none]
--help=hidden display help you should never ever ever care about
--foo=FOO set frob target [asdf]
--bar=BAR set frob source [FOO]
@@ -101,22 +101,23 @@ General:
def check_bar(bld, BAR):
self.assertEqual(BAR, 1)
def check_qux(bld, QUX):
- self.assertEqual(QUX, None)
+ self.assertEqual(QUX, '')
def check_var(bld, VAR):
self.assertEqual(VAR, 'value')
proj = Project('.')
proj.add_alias('--alias', ['--foo=A', '--bar=1', '--foo=B'],
help=None, hidden=False)
- proj.add_option('--foo', init=None,
+ proj.add_option('--foo', init='X',
type=shell_word, check=check_foo,
help='help for string foo', hidden=False)
proj.add_option('--bar', init=0,
type=uint, check=check_bar,
help='help for int bar', hidden=False)
- proj.add_option('--qux', init=None,
- type=uint, check=check_qux,
- help='help for int qux', hidden=False)
+ proj.add_option('--qux', init='',
+ type=maybe(uint), check=check_qux,
+ help='help for int qux', hidden=False,
+ help_def='auto')
proj.add_option('VAR', init='',
type=shell_partial_word, check=check_var,
help='help for string VAR', hidden=False)
@@ -133,6 +134,6 @@ General:
{
'FOO': 'B',
'BAR': 1,
- 'QUX': None,
+ 'QUX': '',
'VAR': 'value',
})
diff --git a/attoconf/types.py b/attoconf/types.py
index 3e73d86..e7c8465 100644
--- a/attoconf/types.py
+++ b/attoconf/types.py
@@ -51,6 +51,18 @@ class enum(object):
raise ValueError('%r not in {%s}' % (s, ', '.join(self.args)))
+class maybe(object):
+ __slots__ = ('inferior')
+
+ def __init__(self, inferior):
+ self.inferior = inferior
+
+ def __call__(self, s):
+ if not s:
+ return s
+ return (self.inferior)(s)
+
+
class ShellList(object):
''' An argument type representing a sequence of 0 or more arguments
'''
@@ -96,9 +108,14 @@ def quoted_string(s):
def filepath(s):
s = trim_trailing_slashes(s)
- # must be absolute *and* canonical
- if s != os.path.abspath(s):
- raise ValueError('Not an absolute, canonical pathname: %s' % s)
+ # must be absolute *and* canonical, except joinable
+ a = os.path.abspath(s)
+ if a == '/':
+ # filepaths often directly cat a subpath
+ # @me@/whatever is invalid if @me@ == /
+ a = '/.'
+ if s != a:
+ raise ValueError('Not an absolute, canonical (except joinable) pathname: %r != %r' % (s, a))
return s