Merge branch 'master' into yaml

This commit is contained in:
Radovan Bast 2016-04-19 12:30:51 +02:00
commit 4e0d0730d8
18 changed files with 170 additions and 172 deletions

View File

@ -10,4 +10,4 @@
- Dan Jonsson (idea for configuration file approach) - Dan Jonsson (idea for configuration file approach)
- Roberto Di Remigio (design ideas and testing, OS X testing, Boost) - Roberto Di Remigio (design ideas and testing, OS X testing, Boost)
For a list of all the contributions see https://github.com/scisoft/autocmake/contributors. For a list of all the contributions see https://github.com/coderefinery/autocmake/contributors.

View File

@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/scisoft/autocmake.svg?branch=master)](https://travis-ci.org/scisoft/autocmake/builds) [![Build Status](https://travis-ci.org/coderefinery/autocmake.svg?branch=master)](https://travis-ci.org/coderefinery/autocmake/builds)
[![Documentation Status](https://readthedocs.org/projects/autocmake/badge/?version=latest)](http://autocmake.readthedocs.org) [![Documentation Status](https://readthedocs.org/projects/autocmake/badge/?version=latest)](http://autocmake.readthedocs.org)
[![License](https://img.shields.io/badge/license-%20BSD--3-blue.svg)](../master/LICENSE) [![License](https://img.shields.io/badge/license-%20BSD--3-blue.svg)](../master/LICENSE)

View File

@ -10,11 +10,11 @@ This documentation is refreshed upon each push to the central repository.
The module reference documentation is generated from the module sources using The module reference documentation is generated from the module sources using
``#.rst:`` tags (compare for instance ``#.rst:`` tags (compare for instance
http://autocmake.readthedocs.org/en/latest/module-reference.html#cc-cmake with http://autocmake.readthedocs.org/en/latest/module-reference.html#cc-cmake with
https://github.com/scisoft/autocmake/blob/master/modules/cc.cmake). https://github.com/coderefinery/autocmake/blob/master/modules/cc.cmake).
Please note that the lines following ``# autocmake.cfg configuration::`` are Please note that the lines following ``# autocmake.cfg configuration::`` are
understood by the ``update.py`` script to infer autocmake.cfg code from the understood by the ``update.py`` script to infer autocmake.cfg code from the
documentation. As an example consider documentation. As an example consider
https://github.com/scisoft/autocmake/blob/master/modules/cc.cmake#L20-L25. https://github.com/coderefinery/autocmake/blob/master/modules/cc.cmake#L20-L25.
Here, ``update.py`` will infer the configurations for ``docopt``, ``export``, Here, ``update.py`` will infer the configurations for ``docopt``, ``export``,
and ``define``. and ``define``.

View File

@ -5,7 +5,7 @@ Testing Autocmake
You will need to install `pytest <http://pytest.org/>`__. You will need to install `pytest <http://pytest.org/>`__.
Check also the `Travis <https://github.com/scisoft/autocmake/blob/master/.travis.yml>`__ Check also the `Travis <https://github.com/coderefinery/autocmake/blob/master/.travis.yml>`__
build and test recipe for other requirements. build and test recipe for other requirements.
Your contributions and changes should preserve the test set. You can run locally all tests with:: Your contributions and changes should preserve the test set. You can run locally all tests with::
@ -19,5 +19,5 @@ You can also select individual tests, for example those with ``fc_blas`` string
For more options, see the ``py.test`` flags. For more options, see the ``py.test`` flags.
This test set is run upon each push to the central repository. This test set is run upon each push to the central repository.
See also the `Travis <https://travis-ci.org/scisoft/autocmake/builds>`__ See also the `Travis <https://travis-ci.org/coderefinery/autocmake/builds>`__
build and test history. build and test history.

View File

@ -12,12 +12,12 @@ infrastructure files which will be needed to build the project::
$ mkdir cmake # does not have to be called "cmake" - take the name you prefer $ mkdir cmake # does not have to be called "cmake" - take the name you prefer
$ cd cmake $ cd cmake
$ wget https://github.com/scisoft/autocmake/raw/master/update.py $ wget https://github.com/coderefinery/autocmake/raw/master/update.py
$ python update.py --self $ python update.py --self
On the MS Windows system, you can use the PowerShell wget-replacement:: On the MS Windows system, you can use the PowerShell wget-replacement::
$ Invoke-WebRequest https://github.com/scisoft/autocmake/raw/master/update.py -OutFile update.py $ Invoke-WebRequest https://github.com/coderefinery/autocmake/raw/master/update.py -OutFile update.py
This creates (or updates) the following files (an existing ``autocmake.cfg`` is This creates (or updates) the following files (an existing ``autocmake.cfg`` is
not overwritten by the script):: not overwritten by the script)::

View File

@ -13,38 +13,38 @@ below::
min_cmake_version: 2.8 min_cmake_version: 2.8
[fc] [fc]
source: https://github.com/scisoft/autocmake/raw/master/modules/fc.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/fc.cmake
[cc] [cc]
source: https://github.com/scisoft/autocmake/raw/master/modules/cc.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/cc.cmake
[cxx] [cxx]
source: https://github.com/scisoft/autocmake/raw/master/modules/cxx.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/cxx.cmake
[flags] [flags]
source: https://github.com/scisoft/autocmake/raw/master/compilers/GNU.CXX.cmake source: https://github.com/coderefinery/autocmake/raw/master/compilers/GNU.CXX.cmake
https://github.com/scisoft/autocmake/raw/master/compilers/Intel.CXX.cmake https://github.com/coderefinery/autocmake/raw/master/compilers/Intel.CXX.cmake
[rpath] [rpath]
source: custom/rpath.cmake source: custom/rpath.cmake
[definitions] [definitions]
source: https://github.com/scisoft/autocmake/raw/master/modules/definitions.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/definitions.cmake
[coverage] [coverage]
source: https://github.com/scisoft/autocmake/raw/master/modules/code_coverage.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/code_coverage.cmake
[safeguards] [safeguards]
source: https://github.com/scisoft/autocmake/raw/master/modules/safeguards.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/safeguards.cmake
[default_build_paths] [default_build_paths]
source: https://github.com/scisoft/autocmake/raw/master/modules/default_build_paths.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/default_build_paths.cmake
[src] [src]
source: https://github.com/scisoft/autocmake/raw/master/modules/src.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/src.cmake
[googletest] [googletest]
source: https://github.com/scisoft/autocmake/raw/master/modules/googletest.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/googletest.cmake
[custom] [custom]
source: custom/api.cmake source: custom/api.cmake
@ -71,13 +71,13 @@ The names of the other sections do not matter to Autocmake. You could name them
min_cmake_version: 2.8 min_cmake_version: 2.8
[one] [one]
source: https://github.com/scisoft/autocmake/raw/master/modules/fc.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/fc.cmake
[two] [two]
source: https://github.com/scisoft/autocmake/raw/master/modules/cc.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/cc.cmake
[whatever] [whatever]
source: https://github.com/scisoft/autocmake/raw/master/modules/cxx.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/cxx.cmake
But it would not make much sense. It is better to choose names that are But it would not make much sense. It is better to choose names that are
meaningful to you. meaningful to you.
@ -163,7 +163,7 @@ The preferred way to extend ``CMakeLists.txt`` is by editing ``autocmake.cfg``
and using the ``source`` option:: and using the ``source`` option::
[fc] [fc]
source: https://github.com/scisoft/autocmake/raw/master/modules/fc.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/fc.cmake
This will download ``fc.cmake`` and include it in ``CMakeLists.txt``. This will download ``fc.cmake`` and include it in ``CMakeLists.txt``.
@ -175,8 +175,8 @@ You can also include local CMake modules, e.g.::
It is also OK to include several modules at once:: It is also OK to include several modules at once::
[flags] [flags]
source: https://github.com/scisoft/autocmake/raw/master/compilers/GNU.CXX.cmake source: https://github.com/coderefinery/autocmake/raw/master/compilers/GNU.CXX.cmake
https://github.com/scisoft/autocmake/raw/master/compilers/Intel.CXX.cmake https://github.com/coderefinery/autocmake/raw/master/compilers/Intel.CXX.cmake
The modules will be included in the same order as they appear in ``autocmake.cfg``. The modules will be included in the same order as they appear in ``autocmake.cfg``.
@ -187,7 +187,7 @@ Fetching files without including them in CMakeLists.txt
Sometimes you want to fetch a file without including it in ``CMakeLists.txt``. Sometimes you want to fetch a file without including it in ``CMakeLists.txt``.
This can be done with the ``fetch`` option. This is for instance done by the This can be done with the ``fetch`` option. This is for instance done by the
``git_info.cmake`` module (see ``git_info.cmake`` module (see
https://github.com/scisoft/autocmake/blob/master/modules/git_info/git_info.cmake#L10-L11). https://github.com/coderefinery/autocmake/blob/master/modules/git_info/git_info.cmake#L10-L11).
If ``fetch`` is invoked in ``autocmake.cfg``, then the fetched file is placed If ``fetch`` is invoked in ``autocmake.cfg``, then the fetched file is placed
under ``downloaded/``. If ``fetch`` is invoked from within a CMake module under ``downloaded/``. If ``fetch`` is invoked from within a CMake module
@ -241,7 +241,7 @@ for many core modules which come with own options once you have sourced them.
The lines following ``# autocmake.cfg configuration::`` are The lines following ``# autocmake.cfg configuration::`` are
understood by the ``update.py`` script to infer ``autocmake.cfg`` code from the understood by the ``update.py`` script to infer ``autocmake.cfg`` code from the
documentation. As an example consider documentation. As an example consider
https://github.com/scisoft/autocmake/blob/master/modules/cc.cmake#L20-L25. https://github.com/coderefinery/autocmake/blob/master/modules/cc.cmake#L20-L25.
Here, ``update.py`` will infer the configurations for ``docopt``, ``export``, Here, ``update.py`` will infer the configurations for ``docopt``, ``export``,
and ``define``. and ``define``.
@ -251,6 +251,6 @@ Overriding documented configurations
Configurable documented defaults can be achieved using interpolations. See for Configurable documented defaults can be achieved using interpolations. See for
instance instance
https://github.com/scisoft/autocmake/blob/master/modules/boost/boost.cmake#L33-L36. https://github.com/coderefinery/autocmake/blob/master/modules/boost/boost.cmake#L33-L36.
These can be modified within ``autocmake.cfg`` with a dictionary, e.g.: These can be modified within ``autocmake.cfg`` with a dictionary, e.g.:
https://github.com/scisoft/autocmake/blob/master/test/boost_libs/cmake/autocmake.cfg#L9 https://github.com/coderefinery/autocmake/blob/master/test/boost_libs/cmake/autocmake.cfg#L9

View File

@ -38,9 +38,9 @@ Overriding defaults
------------------- -------------------
Some modules use interpolations to set defaults, see for instance Some modules use interpolations to set defaults, see for instance
https://github.com/scisoft/autocmake/blob/master/modules/boost/boost.cmake#L33-L36. https://github.com/coderefinery/autocmake/blob/master/modules/boost/boost.cmake#L33-L36.
These can be modified within ``autocmake.cfg``, e.g.: These can be modified within ``autocmake.cfg``, e.g.:
https://github.com/scisoft/autocmake/blob/master/test/boost_libs/cmake/autocmake.cfg#L9 https://github.com/coderefinery/autocmake/blob/master/test/boost_libs/cmake/autocmake.cfg#L9
Create own CMake modules Create own CMake modules
@ -54,5 +54,5 @@ Contribute customizations to the "standard library"
If you think that your customization will be useful for other users as well, If you think that your customization will be useful for other users as well,
you may consider contributing the changes directly to you may consider contributing the changes directly to
https://github.com/scisoft/autocmake/. We very much encourage such https://github.com/coderefinery/autocmake/. We very much encourage such
contributions. But we also strive for generality and portability. contributions. But we also strive for generality and portability.

View File

@ -25,7 +25,7 @@ Now we create ``cmake/`` and fetch ``update.py``::
$ mkdir cmake $ mkdir cmake
$ cd cmake/ $ cd cmake/
$ wget https://raw.githubusercontent.com/scisoft/autocmake/master/update.py $ wget https://raw.githubusercontent.com/coderefinery/autocmake/master/update.py
$ python update.py --self $ python update.py --self
Now from top-level our file tree looks like this:: Now from top-level our file tree looks like this::
@ -50,13 +50,13 @@ Now we edit ``cmake/autocmake.cfg`` to look like this::
min_cmake_version: 2.8 min_cmake_version: 2.8
[fc] [fc]
source: https://github.com/scisoft/autocmake/raw/master/modules/fc.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/fc.cmake
[cc] [cc]
source: https://github.com/scisoft/autocmake/raw/master/modules/cc.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/cc.cmake
[src] [src]
source: https://github.com/scisoft/autocmake/raw/master/modules/src.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/src.cmake
What we have specified here is the project name and that we wish Fortran and C What we have specified here is the project name and that we wish Fortran and C
support. The ``src.cmake`` module tells CMake to include a ``src/CMakeLists.txt``. support. The ``src.cmake`` module tells CMake to include a ``src/CMakeLists.txt``.

View File

@ -107,7 +107,7 @@ overwritten at some point. A good standard is to organize your sources under
can include the latter in ``autocmake.cfg`` using:: can include the latter in ``autocmake.cfg`` using::
[src] [src]
source: https://github.com/scisoft/autocmake/raw/master/modules/src.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/src.cmake
If you really don't like to do it this way, you can describe your sources and If you really don't like to do it this way, you can describe your sources and
targets in a custom module in a local file and include it like this:: targets in a custom module in a local file and include it like this::

View File

@ -21,10 +21,10 @@ rather fetch an older version, for example with the hash ``abcd123``. To
achieve this, instead of:: achieve this, instead of::
[foo] [foo]
source: https://github.com/scisoft/autocmake/raw/master/modules/foo.cmake source: https://github.com/coderefinery/autocmake/raw/master/modules/foo.cmake
pin the version to ``abcd123`` (you do not need to specify the full Git hash, a unique pin the version to ``abcd123`` (you do not need to specify the full Git hash, a unique
beginning will do):: beginning will do)::
[foo] [foo]
source: https://github.com/scisoft/autocmake/raw/abcd123/modules/foo.cmake source: https://github.com/coderefinery/autocmake/raw/abcd123/modules/foo.cmake

View File

@ -73,7 +73,7 @@ def main():
if s_out != '': if s_out != '':
output.append('\n\n%s' % file_name) output.append('\n\n%s' % file_name)
output.append('-'*len(file_name)) output.append('-'*len(file_name))
output.append('`[Source code] <https://github.com/scisoft/autocmake/blob/master/modules/%s>`__' % full_file_name) output.append('`[Source code] <https://github.com/coderefinery/autocmake/blob/master/modules/%s>`__' % full_file_name)
output.append(s_out) output.append(s_out)
with open(os.path.join(THIS_DIR, 'module-reference.rst'), 'w') as f: with open(os.path.join(THIS_DIR, 'module-reference.rst'), 'w') as f:

View File

@ -11,7 +11,7 @@ import re
__all__ = ['docopt'] __all__ = ['docopt']
__version__ = '0.6.1' __version__ = '0.6.2'
class DocoptLanguageError(Exception): class DocoptLanguageError(Exception):
@ -47,18 +47,18 @@ class Pattern(object):
if not hasattr(self, 'children'): if not hasattr(self, 'children'):
return self return self
uniq = list(set(self.flat())) if uniq is None else uniq uniq = list(set(self.flat())) if uniq is None else uniq
for i, child in enumerate(self.children): for i, c in enumerate(self.children):
if not hasattr(child, 'children'): if not hasattr(c, 'children'):
assert child in uniq assert c in uniq
self.children[i] = uniq[uniq.index(child)] self.children[i] = uniq[uniq.index(c)]
else: else:
child.fix_identities(uniq) c.fix_identities(uniq)
def fix_repeating_arguments(self): def fix_repeating_arguments(self):
"""Fix elements that should accumulate/increment values.""" """Fix elements that should accumulate/increment values."""
either = [list(child.children) for child in transform(self).children] either = [list(c.children) for c in self.either.children]
for case in either: for case in either:
for e in [child for child in case if case.count(child) > 1]: for e in [c for c in case if case.count(c) > 1]:
if type(e) is Argument or type(e) is Option and e.argcount: if type(e) is Argument or type(e) is Option and e.argcount:
if e.value is None: if e.value is None:
e.value = [] e.value = []
@ -68,40 +68,47 @@ class Pattern(object):
e.value = 0 e.value = 0
return self return self
@property
def transform(pattern): def either(self):
"""Expand pattern into an (almost) equivalent one, but with single Either. """Transform pattern into an equivalent, with only top-level Either."""
# Currently the pattern will not be equivalent, but more "narrow",
Example: ((-a | -b) (-c | -d)) => (-a -c | -a -d | -b -c | -b -d) # although good enough to reason about list arguments.
Quirks: [-a] => (-a), (-a...) => (-a -a) ret = []
groups = [[self]]
""" while groups:
result = [] children = groups.pop(0)
groups = [[pattern]] types = [type(c) for c in children]
while groups: if Either in types:
children = groups.pop(0) either = [c for c in children if type(c) is Either][0]
parents = [Required, Optional, OptionsShortcut, Either, OneOrMore] children.pop(children.index(either))
if any(t in map(type, children) for t in parents): for c in either.children:
child = [c for c in children if type(c) in parents][0]
children.remove(child)
if type(child) is Either:
for c in child.children:
groups.append([c] + children) groups.append([c] + children)
elif type(child) is OneOrMore: elif Required in types:
groups.append(child.children * 2 + children) required = [c for c in children if type(c) is Required][0]
children.pop(children.index(required))
groups.append(list(required.children) + children)
elif Optional in types:
optional = [c for c in children if type(c) is Optional][0]
children.pop(children.index(optional))
groups.append(list(optional.children) + children)
elif AnyOptions in types:
optional = [c for c in children if type(c) is AnyOptions][0]
children.pop(children.index(optional))
groups.append(list(optional.children) + children)
elif OneOrMore in types:
oneormore = [c for c in children if type(c) is OneOrMore][0]
children.pop(children.index(oneormore))
groups.append(list(oneormore.children) * 2 + children)
else: else:
groups.append(child.children + children) ret.append(children)
else: return Either(*[Required(*e) for e in ret])
result.append(children)
return Either(*[Required(*e) for e in result])
class LeafPattern(Pattern): class ChildPattern(Pattern):
"""Leaf/terminal node of a pattern tree."""
def __init__(self, name, value=None): def __init__(self, name, value=None):
self.name, self.value = name, value self.name = name
self.value = value
def __repr__(self): def __repr__(self):
return '%s(%r, %r)' % (self.__class__.__name__, self.name, self.value) return '%s(%r, %r)' % (self.__class__.__name__, self.name, self.value)
@ -130,9 +137,7 @@ class LeafPattern(Pattern):
return True, left_, collected + [match] return True, left_, collected + [match]
class BranchPattern(Pattern): class ParentPattern(Pattern):
"""Branch/inner node of a pattern tree."""
def __init__(self, *children): def __init__(self, *children):
self.children = list(children) self.children = list(children)
@ -144,15 +149,15 @@ class BranchPattern(Pattern):
def flat(self, *types): def flat(self, *types):
if type(self) in types: if type(self) in types:
return [self] return [self]
return sum([child.flat(*types) for child in self.children], []) return sum([c.flat(*types) for c in self.children], [])
class Argument(LeafPattern): class Argument(ChildPattern):
def single_match(self, left): def single_match(self, left):
for n, pattern in enumerate(left): for n, p in enumerate(left):
if type(pattern) is Argument: if type(p) is Argument:
return n, Argument(self.name, pattern.value) return n, Argument(self.name, p.value)
return None, None return None, None
@classmethod @classmethod
@ -165,23 +170,25 @@ class Argument(LeafPattern):
class Command(Argument): class Command(Argument):
def __init__(self, name, value=False): def __init__(self, name, value=False):
self.name, self.value = name, value self.name = name
self.value = value
def single_match(self, left): def single_match(self, left):
for n, pattern in enumerate(left): for n, p in enumerate(left):
if type(pattern) is Argument: if type(p) is Argument:
if pattern.value == self.name: if p.value == self.name:
return n, Command(self.name, True) return n, Command(self.name, True)
else: else:
break break
return None, None return None, None
class Option(LeafPattern): class Option(ChildPattern):
def __init__(self, short=None, long=None, argcount=0, value=False): def __init__(self, short=None, long=None, argcount=0, value=False):
assert argcount in (0, 1) assert argcount in (0, 1)
self.short, self.long, self.argcount = short, long, argcount self.short, self.long = short, long
self.argcount, self.value = argcount, value
self.value = None if value is False and argcount else value self.value = None if value is False and argcount else value
@classmethod @classmethod
@ -202,9 +209,9 @@ class Option(LeafPattern):
return class_(short, long, argcount, value) return class_(short, long, argcount, value)
def single_match(self, left): def single_match(self, left):
for n, pattern in enumerate(left): for n, p in enumerate(left):
if self.name == pattern.name: if self.name == p.name:
return n, pattern return n, p
return None, None return None, None
@property @property
@ -216,34 +223,34 @@ class Option(LeafPattern):
self.argcount, self.value) self.argcount, self.value)
class Required(BranchPattern): class Required(ParentPattern):
def match(self, left, collected=None): def match(self, left, collected=None):
collected = [] if collected is None else collected collected = [] if collected is None else collected
l = left l = left
c = collected c = collected
for pattern in self.children: for p in self.children:
matched, l, c = pattern.match(l, c) matched, l, c = p.match(l, c)
if not matched: if not matched:
return False, left, collected return False, left, collected
return True, l, c return True, l, c
class Optional(BranchPattern): class Optional(ParentPattern):
def match(self, left, collected=None): def match(self, left, collected=None):
collected = [] if collected is None else collected collected = [] if collected is None else collected
for pattern in self.children: for p in self.children:
m, left, collected = pattern.match(left, collected) m, left, collected = p.match(left, collected)
return True, left, collected return True, left, collected
class OptionsShortcut(Optional): class AnyOptions(Optional):
"""Marker/placeholder for [options] shortcut.""" """Marker/placeholder for [options] shortcut."""
class OneOrMore(BranchPattern): class OneOrMore(ParentPattern):
def match(self, left, collected=None): def match(self, left, collected=None):
assert len(self.children) == 1 assert len(self.children) == 1
@ -265,13 +272,13 @@ class OneOrMore(BranchPattern):
return False, left, collected return False, left, collected
class Either(BranchPattern): class Either(ParentPattern):
def match(self, left, collected=None): def match(self, left, collected=None):
collected = [] if collected is None else collected collected = [] if collected is None else collected
outcomes = [] outcomes = []
for pattern in self.children: for p in self.children:
matched, _, _ = outcome = pattern.match(left, collected) matched, _, _ = outcome = p.match(left, collected)
if matched: if matched:
outcomes.append(outcome) outcomes.append(outcome)
if outcomes: if outcomes:
@ -279,18 +286,12 @@ class Either(BranchPattern):
return False, left, collected return False, left, collected
class Tokens(list): class TokenStream(list):
def __init__(self, source, error=DocoptExit): def __init__(self, source, error):
self += source.split() if hasattr(source, 'split') else source self += source.split() if hasattr(source, 'split') else source
self.error = error self.error = error
@staticmethod
def from_pattern(source):
source = re.sub(r'([\[\]\(\)\|]|\.\.\.)', r' \1 ', source)
source = [s for s in re.split('\s+|(\S*<.*?>)', source) if s]
return Tokens(source, error=DocoptLanguageError)
def move(self): def move(self):
return self.pop(0) if len(self) else None return self.pop(0) if len(self) else None
@ -323,7 +324,7 @@ def parse_long(tokens, options):
raise tokens.error('%s must not have an argument' % o.long) raise tokens.error('%s must not have an argument' % o.long)
else: else:
if value is None: if value is None:
if tokens.current() in [None, '--']: if tokens.current() is None:
raise tokens.error('%s requires argument' % o.long) raise tokens.error('%s requires argument' % o.long)
value = tokens.move() value = tokens.move()
if tokens.error is DocoptExit: if tokens.error is DocoptExit:
@ -354,7 +355,7 @@ def parse_shorts(tokens, options):
value = None value = None
if o.argcount != 0: if o.argcount != 0:
if left == '': if left == '':
if tokens.current() in [None, '--']: if tokens.current() is None:
raise tokens.error('%s requires argument' % short) raise tokens.error('%s requires argument' % short)
value = tokens.move() value = tokens.move()
else: else:
@ -367,7 +368,8 @@ def parse_shorts(tokens, options):
def parse_pattern(source, options): def parse_pattern(source, options):
tokens = Tokens.from_pattern(source) tokens = TokenStream(re.sub(r'([\[\]\(\)\|]|\.\.\.)', r' \1 ', source),
DocoptLanguageError)
result = parse_expr(tokens, options) result = parse_expr(tokens, options)
if tokens.current() is not None: if tokens.current() is not None:
raise tokens.error('unexpected ending: %r' % ' '.join(tokens)) raise tokens.error('unexpected ending: %r' % ' '.join(tokens))
@ -414,7 +416,7 @@ def parse_atom(tokens, options):
return [result] return [result]
elif token == 'options': elif token == 'options':
tokens.move() tokens.move()
return [OptionsShortcut()] return [AnyOptions()]
elif token.startswith('--') and token != '--': elif token.startswith('--') and token != '--':
return parse_long(tokens, options) return parse_long(tokens, options)
elif token.startswith('-') and token not in ('-', '--'): elif token.startswith('-') and token not in ('-', '--'):
@ -450,26 +452,27 @@ def parse_argv(tokens, options, options_first=False):
def parse_defaults(doc): def parse_defaults(doc):
defaults = [] # in python < 2.7 you can't pass flags=re.MULTILINE
for s in parse_section('options:', doc): split = re.split('\n *(<\S+?>|-\S+?)', doc)[1:]
# FIXME corner case "bla: options: --foo" split = [s1 + s2 for s1, s2 in zip(split[::2], split[1::2])]
_, _, s = s.partition(':') # get rid of "options:" options = [Option.parse(s) for s in split if s.startswith('-')]
split = re.split('\n[ \t]*(-\S+?)', '\n' + s)[1:] #arguments = [Argument.parse(s) for s in split if s.startswith('<')]
split = [s1 + s2 for s1, s2 in zip(split[::2], split[1::2])] #return options, arguments
options = [Option.parse(s) for s in split if s.startswith('-')] return options
defaults += options
return defaults
def parse_section(name, source): def printable_usage(doc):
pattern = re.compile('^([^\n]*' + name + '[^\n]*\n?(?:[ \t].*?(?:\n|$))*)', # in python < 2.7 you can't pass flags=re.IGNORECASE
re.IGNORECASE | re.MULTILINE) usage_split = re.split(r'([Uu][Ss][Aa][Gg][Ee]:)', doc)
return [s.strip() for s in pattern.findall(source)] if len(usage_split) < 3:
raise DocoptLanguageError('"usage:" (case-insensitive) not found.')
if len(usage_split) > 3:
raise DocoptLanguageError('More than one "usage:" (case-insensitive).')
return re.split(r'\n\s*\n', ''.join(usage_split[1:]))[0].strip()
def formal_usage(section): def formal_usage(printable_usage):
_, _, section = section.partition(':') # drop "usage:" pu = printable_usage.split()[1:] # split and drop "usage:"
pu = section.split()
return '( ' + ' '.join(') | (' if s == pu[0] else s for s in pu[1:]) + ' )' return '( ' + ' '.join(') | (' if s == pu[0] else s for s in pu[1:]) + ' )'
@ -509,7 +512,7 @@ def docopt(doc, argv=None, help=True, version=None, options_first=False):
If passed, the object will be printed if --version is in If passed, the object will be printed if --version is in
`argv`. `argv`.
options_first : bool (default: False) options_first : bool (default: False)
Set to True to require options precede positional arguments, Set to True to require options preceed positional arguments,
i.e. to forbid options and positional arguments intermix. i.e. to forbid options and positional arguments intermix.
Returns Returns
@ -523,15 +526,15 @@ def docopt(doc, argv=None, help=True, version=None, options_first=False):
------- -------
>>> from docopt import docopt >>> from docopt import docopt
>>> doc = ''' >>> doc = '''
... Usage: Usage:
... my_program tcp <host> <port> [--timeout=<seconds>] my_program tcp <host> <port> [--timeout=<seconds>]
... my_program serial <port> [--baud=<n>] [--timeout=<seconds>] my_program serial <port> [--baud=<n>] [--timeout=<seconds>]
... my_program (-h | --help | --version) my_program (-h | --help | --version)
...
... Options: Options:
... -h, --help Show this screen and exit. -h, --help Show this screen and exit.
... --baud=<n> Baudrate [default: 9600] --baud=<n> Baudrate [default: 9600]
... ''' '''
>>> argv = ['tcp', '127.0.0.1', '80', '--timeout', '30'] >>> argv = ['tcp', '127.0.0.1', '80', '--timeout', '30']
>>> docopt(doc, argv) >>> docopt(doc, argv)
{'--baud': '9600', {'--baud': '9600',
@ -550,15 +553,9 @@ def docopt(doc, argv=None, help=True, version=None, options_first=False):
at https://github.com/docopt/docopt#readme at https://github.com/docopt/docopt#readme
""" """
argv = sys.argv[1:] if argv is None else argv if argv is None:
argv = sys.argv[1:]
usage_sections = parse_section('usage:', doc) DocoptExit.usage = printable_usage(doc)
if len(usage_sections) == 0:
raise DocoptLanguageError('"usage:" (case-insensitive) not found.')
if len(usage_sections) > 1:
raise DocoptLanguageError('More than one "usage:" (case-insensitive).')
DocoptExit.usage = usage_sections[0]
options = parse_defaults(doc) options = parse_defaults(doc)
pattern = parse_pattern(formal_usage(DocoptExit.usage), options) pattern = parse_pattern(formal_usage(DocoptExit.usage), options)
# [default] syntax for argument is disabled # [default] syntax for argument is disabled
@ -566,13 +563,14 @@ def docopt(doc, argv=None, help=True, version=None, options_first=False):
# same_name = [d for d in arguments if d.name == a.name] # same_name = [d for d in arguments if d.name == a.name]
# if same_name: # if same_name:
# a.value = same_name[0].value # a.value = same_name[0].value
argv = parse_argv(Tokens(argv), list(options), options_first) argv = parse_argv(TokenStream(argv, DocoptExit), list(options),
options_first)
pattern_options = set(pattern.flat(Option)) pattern_options = set(pattern.flat(Option))
for options_shortcut in pattern.flat(OptionsShortcut): for ao in pattern.flat(AnyOptions):
doc_options = parse_defaults(doc) doc_options = parse_defaults(doc)
options_shortcut.children = list(set(doc_options) - pattern_options) ao.children = list(set(doc_options) - pattern_options)
#if any_options: #if any_options:
# options_shortcut.children += [Option(o.short, o.long, o.argcount) # ao.children += [Option(o.short, o.long, o.argcount)
# for o in argv if type(o) is Option] # for o in argv if type(o) is Option]
extras(help, version, argv, doc) extras(help, version, argv, doc)
matched, left, collected = pattern.fix().match(argv) matched, left, collected = pattern.fix().match(argv)

View File

@ -9,7 +9,7 @@
# #
# [boost] # [boost]
# override: {'major': 1, 'minor': 59, 'patch': 0, 'components': 'chrono;timer;system'} # override: {'major': 1, 'minor': 59, 'patch': 0, 'components': 'chrono;timer;system'}
# source: https://github.com/scisoft/autocmake/raw/master/modules/boost/boost.cmake # source: https://github.com/coderefinery/autocmake/raw/master/modules/boost/boost.cmake
# #
# Cross-dependencies between required components are not checked for. # Cross-dependencies between required components are not checked for.
# For example, Boost.Timer depends on Boost.Chrono and Boost.System thus you # For example, Boost.Timer depends on Boost.Chrono and Boost.System thus you
@ -49,13 +49,13 @@
# minor=48 # minor=48
# patch=0 # patch=0
# components='' # components=''
# fetch: https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_unpack.cmake # fetch: https://github.com/coderefinery/autocmake/raw/master/modules/boost/boost_unpack.cmake
# https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_userconfig.cmake # https://github.com/coderefinery/autocmake/raw/master/modules/boost/boost_userconfig.cmake
# https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_configure.cmake # https://github.com/coderefinery/autocmake/raw/master/modules/boost/boost_configure.cmake
# https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_build.cmake # https://github.com/coderefinery/autocmake/raw/master/modules/boost/boost_build.cmake
# https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_install.cmake # https://github.com/coderefinery/autocmake/raw/master/modules/boost/boost_install.cmake
# https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_headers.cmake # https://github.com/coderefinery/autocmake/raw/master/modules/boost/boost_headers.cmake
# https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_cleanup.cmake # https://github.com/coderefinery/autocmake/raw/master/modules/boost/boost_cleanup.cmake
# http://sourceforge.net/projects/boost/files/boost/%(major)s.%(minor)s.%(patch)s/boost_%(major)s_%(minor)s_%(patch)s.zip # http://sourceforge.net/projects/boost/files/boost/%(major)s.%(minor)s.%(patch)s/boost_%(major)s_%(minor)s_%(patch)s.zip
# docopt: --boost-headers=<BOOST_INCLUDEDIR> Include directories for Boost [default: '']. # docopt: --boost-headers=<BOOST_INCLUDEDIR> Include directories for Boost [default: ''].
# --boost-libraries=<BOOST_LIBRARYDIR> Library directories for Boost [default: '']. # --boost-libraries=<BOOST_LIBRARYDIR> Library directories for Boost [default: ''].

View File

@ -7,8 +7,8 @@
# #
# autocmake.cfg configuration:: # autocmake.cfg configuration::
# #
# fetch: https://github.com/scisoft/autocmake/raw/master/modules/git_info/git_info_sub.cmake # fetch: https://github.com/coderefinery/autocmake/raw/master/modules/git_info/git_info_sub.cmake
# https://github.com/scisoft/autocmake/raw/master/modules/git_info/git_info.h.in # https://github.com/coderefinery/autocmake/raw/master/modules/git_info/git_info.h.in
# CMAKE_CURRENT_LIST_DIR is undefined in CMake 2.8.2 # CMAKE_CURRENT_LIST_DIR is undefined in CMake 2.8.2
# see https://public.kitware.com/Bug/print_bug_page.php?bug_id=11675 # see https://public.kitware.com/Bug/print_bug_page.php?bug_id=11675

View File

@ -12,8 +12,8 @@
# #
# docopt: --accelerate Find and link to ACCELERATE [default: False]. # docopt: --accelerate Find and link to ACCELERATE [default: False].
# define: '-DENABLE_ACCELERATE=%s' % arguments['--accelerate'] # define: '-DENABLE_ACCELERATE=%s' % arguments['--accelerate']
# fetch: https://github.com/scisoft/autocmake/raw/master/modules/find/find_libraries.cmake # fetch: https://github.com/coderefinery/autocmake/raw/master/modules/find/find_libraries.cmake
# https://github.com/scisoft/autocmake/raw/master/modules/find/find_include_files.cmake # https://github.com/coderefinery/autocmake/raw/master/modules/find/find_include_files.cmake
option(ENABLE_ACCELERATE "Find and link to ACCELERATE" OFF) option(ENABLE_ACCELERATE "Find and link to ACCELERATE" OFF)

View File

@ -12,8 +12,8 @@
# #
# docopt: --cblas Find and link to CBLAS [default: False]. # docopt: --cblas Find and link to CBLAS [default: False].
# define: '-DENABLE_CBLAS=%s' % arguments['--cblas'] # define: '-DENABLE_CBLAS=%s' % arguments['--cblas']
# fetch: https://github.com/scisoft/autocmake/raw/master/modules/find/find_libraries.cmake # fetch: https://github.com/coderefinery/autocmake/raw/master/modules/find/find_libraries.cmake
# https://github.com/scisoft/autocmake/raw/master/modules/find/find_include_files.cmake # https://github.com/coderefinery/autocmake/raw/master/modules/find/find_include_files.cmake
option(ENABLE_CBLAS "Find and link to CBLAS" OFF) option(ENABLE_CBLAS "Find and link to CBLAS" OFF)

View File

@ -12,8 +12,8 @@
# #
# docopt: --lapacke Find and link to LAPACKE [default: False]. # docopt: --lapacke Find and link to LAPACKE [default: False].
# define: '-DENABLE_LAPACKE=%s' % arguments['--lapacke'] # define: '-DENABLE_LAPACKE=%s' % arguments['--lapacke']
# fetch: https://github.com/scisoft/autocmake/raw/master/modules/find/find_libraries.cmake # fetch: https://github.com/coderefinery/autocmake/raw/master/modules/find/find_libraries.cmake
# https://github.com/scisoft/autocmake/raw/master/modules/find/find_include_files.cmake # https://github.com/coderefinery/autocmake/raw/master/modules/find/find_include_files.cmake
option(ENABLE_LAPACKE "Find and link to LAPACKE" OFF) option(ENABLE_LAPACKE "Find and link to LAPACKE" OFF)

View File

@ -28,7 +28,7 @@ else:
sys.exit(-1) sys.exit(-1)
AUTOCMAKE_GITHUB_URL = 'https://github.com/scisoft/autocmake' AUTOCMAKE_GITHUB_URL = 'https://github.com/coderefinery/autocmake'
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------