[Python-modules-commits] [fparser] 01/06: upstream release 0.0.6

Alastair McKinstry mckinstry at moszumanska.debian.org
Wed Dec 20 09:54:20 UTC 2017


This is an automated email from the git hooks/post-receive script.

mckinstry pushed a commit to branch debian/master
in repository fparser.

commit 96418942ba2a6bce7155cd839ecb881ace30c468
Author: Alastair McKinstry <mckinstry at debian.org>
Date:   Wed Dec 13 12:53:04 2017 +0000

    upstream release 0.0.6
---
 CHANGELOG.md                                       |   43 +-
 __init__.py                                        |   63 -
 doc/conf.py                                        |   20 +-
 doc/fparser.rst                                    |    5 +-
 setup.py                                           |    4 +-
 src/__init__.py                                    |   63 -
 src/fparser/Fortran2003.py                         |  504 ++++---
 src/fparser/api.py                                 |   86 +-
 src/fparser/base_classes.py                        |  131 +-
 src/fparser/block_statements.py                    |   77 +-
 src/fparser/parsefortran.py                        |   54 +-
 src/fparser/pattern_tools.py                       |   22 +-
 src/fparser/readfortran.py                         |   98 +-
 src/fparser/scripts/f2003.py                       |   10 +-
 src/fparser/scripts/parse.py                       |    4 +-
 src/fparser/scripts/read.py                        |    4 +-
 src/fparser/setup.py                               |   69 -
 src/fparser/sourceinfo.py                          |    2 +-
 src/fparser/splitline.py                           |  378 ++---
 src/fparser/statements.py                          |  832 +++++++----
 src/fparser/tests/__init__.py                      |    0
 .../tests/{ => fparser2}/test_Fortran2003.py       | 1507 +++++++++++---------
 src/fparser/tests/fparser2/test_base_classses.py   |   91 ++
 src/fparser/tests/fparser2/test_deferred_method.py |   78 +
 src/fparser/tests/logging_utils.py                 |   84 ++
 src/fparser/tests/test_api.py                      |   14 +-
 src/fparser/tests/test_base_classes.py             |   72 +
 src/fparser/tests/test_blank_lines.py              |    2 +-
 src/fparser/tests/test_issue11.py                  |    2 +-
 src/fparser/tests/test_issue25.py                  |    2 +-
 src/fparser/tests/test_issue26.py                  |    2 +-
 src/fparser/tests/test_issue33.py                  |    2 +-
 src/fparser/tests/test_issue5.py                   |    4 +-
 src/fparser/tests/test_issue7.py                   |   42 +-
 src/fparser/tests/test_mod_private.py              |    6 +-
 src/fparser/tests/test_parser.py                   |  986 ++++++++-----
 src/fparser/tests/test_readfortran.py              |   75 +
 src/fparser/tests/test_select.py                   |   22 +-
 .../tests/{test_api.py => test_splitline.py}       |  184 +--
 src/fparser/tests/test_utils.py                    |   10 +-
 src/fparser/typedecl_statements.py                 |   61 +-
 src/fparser/utils.py                               |   36 +-
 42 files changed, 3378 insertions(+), 2373 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5499de0..6b249dd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,47 @@
 # Change log for the fparser package #
 
 Original code by Pearu Peterson.
-Modifications by Andrew Porter and Rupert Ford of the Science
-and Technology Facilities Council, UK.
+
+Modifications by:
+
+* R. W. Ford, Science & Technology Facilities Council, UK
+* M. Hambley, UK Met Office
+* J. Henrichs, Australia Bureau of Meteorology
+* I. Kavcic, UK Met Office
+* A. R. Porter, Science & Technology Facilities Council, UK
+* P. Vitt, University of Siegen, Germany
+
+## Release 0.0.6 (04/12/2017) ##
+
+04/12/2017 PRs #61 and #62. Remove the dependence on numpy.
+
+24/11/2017 PR #60. Add fparser2 support for the 'deferred' attribute on a
+           procedure declaration.
+
+24/11/2017 PR #54. Add support for array initialisation using square
+	   brackets in fparser1, e.g. 'integer :: a(2) = [x, y]'
+
+09/11/2017 Issue #40 and PR #56 bug fix for missing comma when
+           generating "USE, intrinsic :: ..."
+
+21/10/2017 issue #36 and PR #47 generate correct open statement in
+           fparser2 when the 'UNIT' keyword is not provided
+
+20/10/2017 PR #49 pep8, pylint and nose->pytest changes for test_parse.py
+
+20/10/2017 issue #43 and PR #48 add support for Python 3.
+
+19/10/2017 issue #45 and PR #46 - bug fix for optional '::'
+           between MODULE PROCEDURE and <procedure name>
+
+13/10/2017 issue #41 and PR #42 - removed __init__.py files from
+           directories that do not contain package code
+
+28/09/2017 issue #35 pr #39 add support for the 'opened' option
+	   in the inquire statement in fparser2.
+
+06/09/2017 issue #34 pr #37 Fix a format statement parsing
+	   bug in fparser2
 
 ## Release 0.0.5 (20/06/2017) ##
 
diff --git a/__init__.py b/__init__.py
deleted file mode 100644
index 1814d85..0000000
--- a/__init__.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# Modified work Copyright (c) 2017 Science and Technology Facilities Council
-# Original work Copyright (c) 1999-2008 Pearu Peterson
-
-# All rights reserved.
-
-# Modifications made as part of the fparser project are distributed
-# under the following license:
-
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-
-# 3. Neither the name of the copyright holder nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# --------------------------------------------------------------------
-
-# The original software (in the f2py project) was distributed under
-# the following license:
-
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-
-#   a. Redistributions of source code must retain the above copyright notice,
-#      this list of conditions and the following disclaimer.
-#   b. Redistributions in binary form must reproduce the above copyright
-#      notice, this list of conditions and the following disclaimer in the
-#      documentation and/or other materials provided with the distribution.
-#   c. Neither the name of the F2PY project nor the names of its
-#      contributors may be used to endorse or promote products derived from
-#      this software without specific prior written permission.
-
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
-# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-# DAMAGE.
diff --git a/doc/conf.py b/doc/conf.py
index 182c6d6..6586f3d 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -115,17 +115,17 @@ source_suffix = '.rst'
 master_doc = 'index'
 
 # General information about the project.
-project = u'fparser'
-copyright = u'2017, Science and Technology Facilities Council'
+project = 'fparser'
+copyright = '2017, Science and Technology Facilities Council'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
 # The short X.Y version.
-version = '0.0.5'
+version = '0.0.6'
 # The full version, including alpha/beta/rc tags.
-release = '0.0.5'
+release = '0.0.6'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
@@ -268,8 +268,8 @@ latex_elements = {
 # (source start file, target name, title,
 #  author, documentclass [howto, manual, or own class]).
 latex_documents = [
-  ('index', 'fparser.tex', u'fparser Documentation',
-   u'Andrew Porter, Rupert Ford and Pearu Peterson', 'manual'),
+  ('index', 'fparser.tex', 'fparser Documentation',
+   'Andrew Porter, Rupert Ford and Pearu Peterson', 'manual'),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
@@ -298,8 +298,8 @@ latex_documents = [
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 man_pages = [
-    ('index', 'fparser', u'fparser Documentation',
-     [u'Andrew Porter, Rupert Ford and Pearu Peterson'], 1)
+    ('index', 'fparser', 'fparser Documentation',
+     ['Andrew Porter, Rupert Ford and Pearu Peterson'], 1)
 ]
 
 # If true, show URL addresses after external links.
@@ -312,8 +312,8 @@ man_pages = [
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 texinfo_documents = [
-  ('index', 'fparser', u'fparser Documentation',
-   u'Andrew Porter, Rupert Ford and Pearu Peterson', 'fparser', 'One line description of project.',
+  ('index', 'fparser', 'fparser Documentation',
+   'Andrew Porter, Rupert Ford and Pearu Peterson', 'fparser', 'One line description of project.',
    'Miscellaneous'),
 ]
 
diff --git a/doc/fparser.rst b/doc/fparser.rst
index 933b651..f70c49b 100644
--- a/doc/fparser.rst
+++ b/doc/fparser.rst
@@ -80,9 +80,8 @@ order to support some of the aspects of more recent versions of
 Fortran (see :ref:`beyond_f90`). In order to use it you will need to
 have installed the fparser package which is available from the Python
 Packagage Index (pypi) or github (https://github.com/stfc/fparser). In
-turn fparser requires the numpy and nose packages. When installing
-using pip these dependencies should be installed automatically for
-you.
+turn fparser requires the "nose" and "six" packages. When installing using pip
+these dependencies should be installed automatically for you.
 
 Once installed, you should be able to open the python interpreter and
 try it out, e.g.:
diff --git a/setup.py b/setup.py
index 539d732..dffe732 100644
--- a/setup.py
+++ b/setup.py
@@ -102,7 +102,7 @@ CLASSIFIERS = [
 
 MAJOR = 0
 MINOR = 0
-MICRO = 5
+MICRO = 6
 VERSION = '%d.%d.%d' % (MAJOR, MINOR, MICRO)
 
 if __name__ == '__main__':
@@ -119,7 +119,7 @@ if __name__ == '__main__':
         classifiers=CLASSIFIERS,
         packages=PACKAGES,
         package_dir={"": "src"},
-        install_requires=['numpy', 'nose'],
+        install_requires=['nose', 'six'],
         # We need the following line to ensure we get the fparser/log.config
         # file installed.
         include_package_data=True)
diff --git a/src/__init__.py b/src/__init__.py
deleted file mode 100644
index 1814d85..0000000
--- a/src/__init__.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# Modified work Copyright (c) 2017 Science and Technology Facilities Council
-# Original work Copyright (c) 1999-2008 Pearu Peterson
-
-# All rights reserved.
-
-# Modifications made as part of the fparser project are distributed
-# under the following license:
-
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-
-# 3. Neither the name of the copyright holder nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# --------------------------------------------------------------------
-
-# The original software (in the f2py project) was distributed under
-# the following license:
-
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-
-#   a. Redistributions of source code must retain the above copyright notice,
-#      this list of conditions and the following disclaimer.
-#   b. Redistributions in binary form must reproduce the above copyright
-#      notice, this list of conditions and the following disclaimer in the
-#      documentation and/or other materials provided with the distribution.
-#   c. Neither the name of the F2PY project nor the names of its
-#      contributors may be used to endorse or promote products derived from
-#      this software without specific prior written permission.
-
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
-# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-# DAMAGE.
diff --git a/src/fparser/Fortran2003.py b/src/fparser/Fortran2003.py
index 461836e..c0beb81 100644
--- a/src/fparser/Fortran2003.py
+++ b/src/fparser/Fortran2003.py
@@ -71,9 +71,9 @@
 
 import re
 import logging
-from splitline import string_replace_map
-import pattern_tools as pattern
-from readfortran import FortranReaderBase
+from .splitline import string_replace_map
+from . import pattern_tools as pattern
+from .readfortran import FortranReaderBase
 
 logger = logging.getLogger("fparser")
 
@@ -92,11 +92,65 @@ def show_result(func):
     def new_func(cls, string, **kws):
         r = func(cls, string, **kws)
         if r is not None and isinstance(r, StmtBase):
-            print '%s(%r) -> %r' % (cls.__name__, string, str(r))
+            print('%s(%r) -> %r' % (cls.__name__, string, str(r)))
         return r
     return new_func
 
-class Base(object):
+
+class ComparableMixin(object):
+    """ Mixin class to provide rich comparison operators.
+
+    This mixin provides a set of rich comparison operators. Each class using
+    this mixin has to provide a _cmpkey() method that returns a key of objects
+    that can be compared.
+
+    See also http://python3porting.com/preparing.html#richcomparisons
+    """
+    # pylint: disable=too-few-public-methods
+
+    def _compare(self, other, method):
+        """ Call the method, if other is able to be used within it.
+
+        :param object other: The other object to compare with
+        :type other: object
+        :param method: The method to call to compare self and other.
+        :type method: LambdaType
+        :return: NotImplemented, when the comparison for the given type
+                 combination can't be performed.
+        :rtype: :py:type:`NotImplementedType`
+        """
+        try:
+            # This routine's purpose is to access the protected method _cmpkey()
+            # from client classes, therefore:
+            # pylint: disable=protected-access
+            return method(self._cmpkey(), other._cmpkey())
+        except (AttributeError, TypeError):
+            # _cmpkey not implemented, or return different type,
+            # so I can't compare with "other".
+            # According to the Python Language Reference Manual
+            # (http://www.network-theory.co.uk/docs/pylang/Coercionrules.html)
+            # return NotImplemented
+            return NotImplemented
+
+    def __lt__(self, other):
+        return self._compare(other, lambda s, o: s < o)
+
+    def __le__(self, other):
+        return self._compare(other, lambda s, o: s <= o)
+
+    def __eq__(self, other):
+        return self._compare(other, lambda s, o: s == o)
+
+    def __ge__(self, other):
+        return self._compare(other, lambda s, o: s >= o)
+
+    def __gt__(self, other):
+        return self._compare(other, lambda s, o: s > o)
+
+    def __ne__(self, other):
+        return self._compare(other, lambda s, o: s != o)
+
+class Base(ComparableMixin):
     """ Base class for Fortran 2003 syntax rules.
 
     All Base classes have the following attributes:
@@ -107,8 +161,16 @@ class Base(object):
     subclasses = {}
 
     @show_result
-    def __new__(cls, string, parent_cls = None):
+    def __new__(cls, string, parent_cls=None):
         """
+        Create a new instance of this object.
+
+        :param cls: the class of object to create
+        :type cls: :py:type:`type`
+        :param string: (source of) Fortran string to parse
+        :type string: str or :py:class:`FortranReaderBase`
+        :param parent_cls: the parent class of this object
+        :type parent_cls: :py:type:`type`
         """
         if parent_cls is None:
             parent_cls = [cls]
@@ -140,7 +202,7 @@ class Base(object):
             # restore readers content when no match is found.
             try:
                 result = cls.match(string)
-            except NoMatchError, msg:
+            except NoMatchError as msg:
                 if str(msg)=='%s: %r' % (cls.__name__, string): # avoid recursion 1.
                     raise
 
@@ -160,17 +222,14 @@ class Base(object):
                 #print '%s:%s: %r' % (cls.__name__,subcls.__name__,string)
                 try:
                     obj = subcls(string, parent_cls = parent_cls)
-                except NoMatchError, msg:
+                except NoMatchError as msg:
                     obj = None
                 if obj is not None:
                     return obj
-
         else:
-            raise AssertionError,`result`
+            raise AssertionError(repr(result))
         errmsg = '%s: %r' % (cls.__name__, string)
-        #if isinstance(string, FortranReaderBase) and string.fifo_item:
-        #    errmsg += ' while reaching %s' % (string.fifo_item[-1])
-        raise NoMatchError, errmsg
+        raise NoMatchError(errmsg)
 
 ##     def restore_reader(self):
 ##         self._item.reader.put_item(self._item)
@@ -183,17 +242,14 @@ class Base(object):
         return '%s(%s)' % (self.__class__.__name__, ', '.join(map(repr,
                                                                   self.items)))
 
-    def compare(self, other):
-        return cmp(self.items,other.items)
-
     def __str__(self): return self.tostr()
 
     def __repr__(self): return self.torepr()
 
-    def __cmp__(self, other):
-        if self is other: return 0
-        if not isinstance(other, self.__class__): return cmp(self.__class__, other.__class__)
-        return self.compare(other)
+    def _cmpkey(self):
+        """ Provides a key of objects to be used for comparing.
+        """
+        return self.items
 
     def tofortran(self, tab='', isfix=None):
         return tab + str(self)
@@ -224,7 +280,7 @@ content : tuple
               enable_select_type_construct_hook = False,
               enable_case_construct_hook = False
               ):
-        assert isinstance(reader,FortranReaderBase),`reader`
+        assert isinstance(reader, FortranReaderBase), repr(reader)
         content = []
         if startcls is not None:
             try:
@@ -363,11 +419,15 @@ content : tuple
     def init(self, content):
         self.content = content
         return
-    def compare(self, other):
-        return cmp(self.content,other.content)
+
+    def _cmpkey(self):
+        """ Provides a key of objects to be used for comparing.
+        """
+        return self.content
 
     def tostr(self):
         return self.tofortran()
+
     def torepr(self):
         return '%s(%s)' % (self.__class__.__name__,', '.join(map(repr, self.content)))
 
@@ -426,8 +486,11 @@ class SequenceBase(Base):
         else: s = ' ' + s + ' '
         return s.join(map(str, self.items))
     def torepr(self): return '%s(%r, %r)' % (self.__class__.__name__, self.separator, self.items)
-    def compare(self, other):
-        return cmp((self.separator,self.items),(other.separator,self.items))
+
+    def _cmpkey(self):
+        """ Provides a key of objects to be used for comparing.
+        """
+        return (self.separator, self.items)
 
 class UnaryOpBase(Base):
     """
@@ -523,37 +586,48 @@ class SeparatorBase(Base):
             s += ' %s' % (self.items[1])
         return s
 
+
 class KeywordValueBase(Base):
     """
 ::
     <keyword-value-base> = [ <lhs> = ] <rhs>
     """
-    def match(lhs_cls, rhs_cls, string, require_lhs = True, upper_lhs = False):
-        if require_lhs and '=' not in string: return
+    @staticmethod
+    def match(lhs_cls, rhs_cls, string, require_lhs=True, upper_lhs=False):
+        if require_lhs and '=' not in string:
+            return
         if isinstance(lhs_cls, (list, tuple)):
             for s in lhs_cls:
-                try:
-                    obj = KeywordValueBase.match(s, rhs_cls, string, require_lhs=require_lhs, upper_lhs=upper_lhs)
-                except NoMatchError:
-                    obj = None
-                if obj is not None: return obj
+                obj = KeywordValueBase.match(s, rhs_cls, string,
+                                             require_lhs=require_lhs,
+                                             upper_lhs=upper_lhs)
+                if obj:
+                    return obj
             return obj
-        lhs,rhs = string.split('=',1)
-        lhs = lhs.rstrip()
+        if "=" in string:
+            lhs, rhs = string.split('=', 1)
+            lhs = lhs.rstrip()
+        else:
+            lhs = None
+            rhs = string.rstrip()
         rhs = rhs.lstrip()
-        if not rhs: return
+        if not rhs:
+            return
         if not lhs:
-            if require_lhs: return
+            if require_lhs:
+                return
             return None, rhs_cls(rhs)
         if isinstance(lhs_cls, str):
             if upper_lhs:
                 lhs = lhs.upper()
-            if lhs_cls!=lhs: return
+            if lhs_cls != lhs:
+                return
             return lhs, rhs_cls(rhs)
-        return lhs_cls(lhs),rhs_cls(rhs)
-    match = staticmethod(match)
+        return lhs_cls(lhs), rhs_cls(rhs)
+
     def tostr(self):
-        if self.items[0] is None: return str(self.items[1])
+        if self.items[0] is None:
+            return str(self.items[1])
         return '%s = %s' % tuple(self.items)
 
 class BracketBase(Base):
@@ -565,7 +639,7 @@ class BracketBase(Base):
     def match(brackets, cls, string, require_cls=True):
         ''' The generic match method for all types of bracketed
         expressions '''
-        bracket_len = len(brackets)/2
+        bracket_len = len(brackets)//2
         left = brackets[:bracket_len]
         right = brackets[-bracket_len:]
 
@@ -625,8 +699,11 @@ class NumberBase(Base):
     def tostr(self):
         if self.items[1] is None: return str(self.items[0])
         return '%s_%s' % tuple(self.items)
-    def compare(self, other):
-        return cmp(self.items[0], other.items[0])
+
+    def _cmpkey(self):
+        """ Provides a key of objects to be used for comparing.
+        """
+        return self.items[0]
 
 class CallBase(Base):
     """
@@ -701,8 +778,11 @@ string
         return
     def tostr(self): return str(self.string)
     def torepr(self): return '%s(%r)' % (self.__class__.__name__, self.string)
-    def compare(self, other):
-        return cmp(self.string,other.string)
+
+    def _cmpkey(self):
+        """ Provides a key of objects to be used for comparing.
+        """
+        return self.string
 
 class STRINGBase(StringBase):
     """
@@ -1870,7 +1950,7 @@ class Component_Decl(Base): # R442
         if newline.startswith('='):
             init = Component_Initialization(newline)
         else:
-            assert newline=='',`newline`
+            assert newline=='', repr(newline)
         return name, array_spec, char_length, init
     match = staticmethod(match)
     def tostr(self):
@@ -2009,7 +2089,7 @@ class Specific_Binding(StmtBase): # R451
         if line.startswith('('):
             i = line.find(')')
             if i==-1: return
-            iname = Interface_Name(line[1:-1].strip())
+            iname = Interface_Name(line[1:i].strip())
             line = line[i+1:].lstrip()
         l = None
         i = line.find('::')
@@ -2074,10 +2154,13 @@ class Binding_Attr(STRINGBase): # R453
     <binding-attr> = PASS [ ( <arg-name> ) ]
                      | NOPASS
                      | NON_OVERRIDABLE
+                     | DEFERRED
                      | <access-spec>
     """
     subclass_names = ['Access_Spec', 'Binding_PASS_Arg_Name']
-    def match(string): return STRINGBase.match(['PASS', 'NOPASS', 'NON_OVERRIDABLE'], string)
+    def match(string):
+        return STRINGBase.match(['PASS', 'NOPASS',
+                                 'NON_OVERRIDABLE', 'DEFERRED'], string)
     match = staticmethod(match)
 
 class Final_Binding(StmtBase, WORDClsBase): # R454
@@ -2465,7 +2548,7 @@ class Entity_Decl(Base): # R504
         elif newline:
             return
         else:
-            assert newline=='',`newline, string`
+            assert newline=='', repr((newline, string))
         return name, array_spec, char_length, init
     match = staticmethod(match)
     def tostr(self):
@@ -3188,7 +3271,7 @@ items : (Namelist_Group_Name, Namelist_Group_Object_List)-tuple
         parts = line.split('/')
         items = []
         fst = parts.pop(0)
-        assert not fst,`fst, parts`
+        assert not fst, repr((fst, parts))
         while len(parts)>=2:
             name,lst = parts[:2]
             del parts[:2]
@@ -3197,7 +3280,7 @@ items : (Namelist_Group_Name, Namelist_Group_Object_List)-tuple
             if lst.endswith(','):
                 lst = lst[:-1].rstrip()
             items.append((Namelist_Group_Name(name),Namelist_Group_Object_List(lst)))
-        assert not parts,`parts`
+        assert not parts, repr(parts)
         return tuple(items)
 
     def tostr(self):
@@ -3551,7 +3634,7 @@ class Allocate_Stmt(StmtBase): # R623
         opts = None
         if i!=-1:
             j = line[:i].rfind(',')
-            assert j!=-1,`i,j,line`
+            assert j !=- 1, repr((i, j, line))
             opts = Alloc_Opt_List(repmap(line[j+1:].lstrip()))
             line = line[:j].rstrip()        
         return spec, Allocation_List(repmap(line)), opts
@@ -3694,7 +3777,7 @@ class Deallocate_Stmt(StmtBase): # R635
         opts = None
         if i!=-1:
             j = line[:i].rfind(',')
-            assert j!=-1,`i,j,line`
+            assert j != -1, repr((i, j, line))
             opts = Dealloc_Opt_List(repmap(line[j+1:].lstrip()))
             line = line[:j].rstrip()
         return Allocate_Object_List(repmap(line)), opts
@@ -3782,7 +3865,7 @@ class Defined_Op(STRINGBase): # R703, 723
     subclass_names = []
     def match(string):
         if pattern.non_defined_binary_op.match(string):
-            raise NoMatchError,'%s: %r' % (Defined_Unary_Op.__name__, string)
+            raise NoMatchError('%s: %r' % (Defined_Unary_Op.__name__, string))
         return STRINGBase.match(pattern.abs_defined_op, string)
     match = staticmethod(match)
 
@@ -4034,13 +4117,13 @@ class Pointer_Assignment_Stmt(StmtBase): # R735
             l = repmap(lhs[i+1:-1].strip())
             try:
                 return Data_Pointer_Object(o), Bounds_Spec_List(l), Data_Target(rhs)
-            except NoMatchError, msg:
+            except NoMatchError as msg:
                 return Data_Pointer_Object(o), Bounds_Remapping_List(l), Data_Target(rhs)
         else:
             lhs = repmap(lhs)
         try:
             return Data_Pointer_Object(lhs), None, Data_Target(rhs)
-        except NoMatchError, msg:
+        except NoMatchError as msg:
             return Proc_Pointer_Object(lhs), None, Proc_Target(rhs)
 
     def tostr(self):
@@ -4351,7 +4434,7 @@ class Forall_Triplet_Spec(Base): # R755
         if i==-1: return
         n = Index_Name(repmap(line[:i].rstrip()))
         line = line[i+1:].lstrip()
-        s = map(lambda s: repmap(s.strip()), line.split(':'))
+        s = [repmap(s.strip()) for s in line.split(':')]
         if len(s)==2:
             return n, Subscript(s[0]), Subscript(s[1]), None
         if len(s)==3:
@@ -5016,7 +5099,8 @@ class Loop_Control(Base): # R830
         var,rhs = line.split('=')
         rhs = [s.strip() for s in rhs.lstrip().split(',')]
         if not 2<=len(rhs)<=3: return
-        return Variable(repmap(var.rstrip())),map(Scalar_Int_Expr, map(repmap,rhs))
+        return Variable(repmap(var.rstrip())), \
+                list(map(Scalar_Int_Expr, list(map(repmap,rhs))))
     match = staticmethod(match)
     def tostr(self):
         if len(self.items)==1: return ', WHILE (%s)' % (self.items[0])
@@ -5303,6 +5387,7 @@ class Internal_File_Variable(Base): # R903
     """
     subclass_names = ['Char_Variable']
 
+
 class Open_Stmt(StmtBase, CALLBase): # R904
     """
     <open-stmt> = OPEN ( <connect-spec-list> )
@@ -5311,10 +5396,15 @@ class Open_Stmt(StmtBase, CALLBase): # R904
     use_names = ['Connect_Spec_List']
     @staticmethod
     def match(string):
-        return CALLBase.match('OPEN', Connect_Spec_List, string, require_rhs=True)
+        # The Connect_Spec_List class is generated automatically
+        # by code at the end of this module
+        return CALLBase.match('OPEN', Connect_Spec_List, string,
+                              require_rhs=True)
 
-class Connect_Spec(KeywordValueBase): # R905
+
+class Connect_Spec(KeywordValueBase):
     """
+    R905
     <connect-spec> = [ UNIT = ] <file-unit-number>
                      | ACCESS = <scalar-default-char-expr>
                      | ACTION = <scalar-default-char-expr>
@@ -5336,26 +5426,40 @@ class Connect_Spec(KeywordValueBase): # R905
                      | STATUS = <scalar-default-char-expr>
     """
     subclass_names = []
-    use_names = ['File_Unit_Number', 'Scalar_Default_Char_Expr', 'Label', 'File_Name_Expr', 'Iomsg_Variable',
+    use_names = ['File_Unit_Number', 'Scalar_Default_Char_Expr', 'Label',
+                 'File_Name_Expr', 'Iomsg_Variable',
                  'Scalar_Int_Expr', 'Scalar_Int_Variable']
+
+    @staticmethod
     def match(string):
-        for (k,v) in [\
-            (['ACCESS','ACTION','ASYNCHRONOUS','BLANK','DECIMAL','DELIM','ENCODING',
-              'FORM','PAD','POSITION','ROUND','SIGN','STATUS'], Scalar_Default_Char_Expr),
-            ('ERR', Label),
-            ('FILE',File_Name_Expr),
-            ('IOSTAT', Scalar_Int_Variable),
-            ('IOMSG', Iomsg_Variable),
-            ('RECL', Scalar_Int_Expr),
-            ('UNIT', File_Unit_Number),
-            ]:
+        '''
+        :param str string: Fortran code to check for a match
+        :return: 2-tuple containing the keyword and value or None if the
+                 supplied string is not a match
+        :rtype: 2-tuple containing keyword (e.g. "UNIT") and associated value
+        '''
+        if "=" not in string:
+            # The only argument which need not be named is the unit number
+            return 'UNIT', File_Unit_Number(string)
+        # We have a keyword-value pair. Check whether it is valid...
+        for (keyword, value) in [
+                (['ACCESS', 'ACTION', 'ASYNCHRONOUS', 'BLANK', 'DECIMAL',
+                  'DELIM', 'ENCODING', 'FORM', 'PAD', 'POSITION', 'ROUND',
+                  'SIGN', 'STATUS'], Scalar_Default_Char_Expr),
+                ('ERR', Label),
+                ('FILE', File_Name_Expr),
+                ('IOSTAT', Scalar_Int_Variable),
+                ('IOMSG', Iomsg_Variable),
+                ('RECL', Scalar_Int_Expr),
+                ('UNIT', File_Unit_Number)]:
             try:
-                obj = KeywordValueBase.match(k, v, string, upper_lhs = True)
+                obj = KeywordValueBase.match(keyword, value, string,
+                                             upper_lhs=True)
             except NoMatchError:
                 obj = None
-            if obj is not None: return obj
-        return 'UNIT', File_Unit_Number
-    match = staticmethod(match)
+            if obj is not None:
+                return obj
+        return None
 
 
 class File_Name_Expr(Base): # R906
@@ -5407,6 +5511,7 @@ class Close_Spec(KeywordValueBase): # R909
         return 'UNIT', File_Unit_Number(string)
     match = staticmethod(match)
 
+
 class Read_Stmt(StmtBase): # R910
     """
 :F03R:`910`::
@@ -5421,34 +5526,47 @@ items : (Io_Control_Spec_List, Format, Input_Item_List)
     use_names = ['Io_Control_Spec_List', 'Input_Item_List', 'Format']
     @staticmethod
     def match(string):
-        if string[:4].upper()!='READ': return
+        if string[:4].upper() != 'READ':
+            return
         line = string[4:].lstrip()
         if line.startswith('('):
             line, repmap = string_replace_map(line)
-            i = line.find(')')
-            if i==-1: return
-            l = line[1:i].strip()
-            if not l: return
-            if i==len(line)-1:
-                return Io_Control_Spec_List(repmap(l)),None,None
-            return Io_Control_Spec_List(repmap(l)), None, Input_Item_List(repmap(line[i+1:].lstrip()))
-        if not line: return
-        c = line[0].upper()
-        if 'A'<=c<='Z' or c=='_' or '0'<=c<='9': return
+            idx = line.find(')')
+            if idx == -1:
+                return
+            trimline = line[1:idx].strip()
+            if not trimline:
+                return
+            if idx == len(line) - 1:
+                return Io_Control_Spec_List(repmap(trimline)), None, None
+            return Io_Control_Spec_List(repmap(trimline)), None, \
+                Input_Item_List(repmap(line[idx+1:].lstrip()))
+        if not line:
+            return
+        char = line[0].upper()
+        # No parentheses therefore first argument must be a format
+        # specifier (either a string or a line/label number
+        if 'A' <= char <= 'Z' or char == '_':
+            return
         line, repmap = string_replace_map(line.lstrip())
-        i = line.find(',')
-        if i==-1: return Format(repmap(line)),None,None
-        l = repmap(line[i+1:].lstrip())
-        if not l: return
-        return None, Format(repmap(line[:i].rstrip())), Output_Item_List(l)
+        # There must be a comma betwee the format specifier and the following
+        # list of values/variables
+        idx = line.find(',')
+        if idx == -1:
+            return None
+        trimline = repmap(line[idx+1:].lstrip())
+        if not trimline:
+            return
+        return (None, Format(repmap(line[:idx].rstrip())),
+                Output_Item_List(trimline))
     
     def tostr(self):
         if self.items[0] is not None:
-            assert self.items[1] is None,`self.items`
+            assert self.items[1] is None, repr(self.items)
             if self.items[2] is None:
                 return 'READ(%s)' % (self.items[0])
             return 'READ(%s) %s' % (self.items[0], self.items[2])
-        assert self.items[1] is not None, `self.items`
+        assert self.items[1] is not None, repr(self.items)
         if self.items[2] is None:
             return 'READ %s' % (self.items[1])
         return 'READ %s, %s' % (self.items[1], self.items[2])
@@ -5506,42 +5624,51 @@ items : (Format, Output_Item_List)
         if not l: return
         return Format(repmap(line[:i].rstrip())), Output_Item_List(l)
     match = staticmethod(match)
+
     def tostr(self):
         if self.items[1] is None: return 'PRINT %s' % (self.items[0])
         return 'PRINT %s, %s' % tuple(self.items)
 
+
 class Io_Control_Spec_List(SequenceBase): # R913-list
     """
     <io-control-spec-list> is a list taking into account C910, C917, C918
     """
     subclass_names = []
     use_names = ['Io_Control_Spec']
+    @staticmethod
     def match(string):
         line, repmap = string_replace_map(string)
         splitted = line.split(',')
-        if not splitted: return
         lst = []
-        for i in range(len(splitted)):
-            p = splitted[i].strip()
-            if i==0:
-                if '=' not in p: p = 'UNIT=%s' % (repmap(p))
-                else: p = repmap(p)
-            elif i==1:
-                if '=' not in p:
-                    p = repmap(p)
-                    try:
-                        f = Format(p)
-                        # todo: make sure that f is char-expr, if not, raise NoMatchError
-                        p = 'FMT=%s' % (Format(p))
-                    except NoMatchError:
-                        p = 'NML=%s' % (Namelist_Group_Name(p))
-                else:
-                    p = repmap(p)
+        unit_is_positional = False
+        for idx in range(len(splitted)):
+            spec = splitted[idx].strip()
+            spec = repmap(spec)
+            if idx == 0 and "=" not in spec:
+                # Must be a unit number. However, we do not prepend "UNIT="
+                # to it in case the following Io_Control_Spec is positional
+                # (and therefore either a Format or Namelist spec).
+                lst.append(Io_Control_Spec(spec))
+                unit_is_positional = True
+            elif idx == 1 and "=" not in spec:
+                if not unit_is_positional:
+                    # Cannot have a positional argument following a
+                    # named argument
+                    return
+                # Without knowing the type of the variable named in spec
+                # we have no way of knowing whether this is a format or
+                # a namelist specifier. However, if it is a character
+                # constant or "*" then it must be a Format spec and we can
+                # prepend "FMT=" to it.
+                spec = spec.lstrip().rstrip()
+                if Char_Literal_Constant.match(spec) or \
+                   StringBase.match("*", spec):
+                    spec = "FMT={0}".format(spec)
+                lst.append(Io_Control_Spec(spec))
             else:
-                p = repmap(p)
-            lst.append(Io_Control_Spec(p))
+                lst.append(Io_Control_Spec(spec))
         return ',', tuple(lst)
-    match = staticmethod(match)
 
 class Io_Control_Spec(KeywordValueBase): # R913
     """
@@ -5567,28 +5694,34 @@ class Io_Control_Spec(KeywordValueBase): # R913
                         | SIZE = <scalar-int-variable>
     """
     subclass_names = []
-    use_names = ['Io_Unit', 'Format', 'Namelist_Group_Name', 'Scalar_Default_Char_Expr',
-                 'Scalar_Char_Initialization_Expr', 'Label', 'Scalar_Int_Variable',
+    use_names = ['Io_Unit', 'Format', 'Namelist_Group_Name',
+                 'Scalar_Default_Char_Expr',
+                 'Scalar_Char_Initialization_Expr', 'Label',
+                 'Scalar_Int_Variable',
                  'Iomsg_Variable', 'Scalar_Int_Expr']
+    @staticmethod
     def match(string):
-        for (k,v) in [\
... 10724 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/fparser.git



More information about the Python-modules-commits mailing list