summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2018-06-12 20:17:34 -0600
committerGitHub <noreply@github.com>2018-06-12 20:17:34 -0600
commitf2f5cfcab003a56f6294a34155083f101e29e957 (patch)
treecfcf2a8b5660d6c2ca12f025793ec30bf80a0997
parent26049e08d3dc0e82c8be187f43c8a26248526f5d (diff)
parent8d41d3b7d27bb0202a153d734e6d26ff271c78c9 (diff)
downloadnumpy-f2f5cfcab003a56f6294a34155083f101e29e957.tar.gz
Merge pull request #11319 from charris/revert-problem-f2py-fixes
REL, REV: Revert f2py fixes that exposed SciPy bug.
-rwxr-xr-xnumpy/f2py/crackfortran.py85
-rw-r--r--numpy/f2py/tests/test_quoted_character.py30
2 files changed, 37 insertions, 78 deletions
diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py
index 19ce8c145..78802ef07 100755
--- a/numpy/f2py/crackfortran.py
+++ b/numpy/f2py/crackfortran.py
@@ -346,6 +346,8 @@ def readfortrancode(ffile, dowithline=show, istop=1):
cont = 0
finalline = ''
ll = ''
+ commentline = re.compile(
+ r'(?P<line>([^"]*["][^"]*["][^"!]*|[^\']*\'[^\']*\'[^\'!]*|[^!\'"]*))!{1}(?P<rest>.*)')
includeline = re.compile(
r'\s*include\s*(\'|")(?P<name>[^\'"]*)(\'|")', re.I)
cont1 = re.compile(r'(?P<line>.*)&\s*\Z')
@@ -389,10 +391,17 @@ def readfortrancode(ffile, dowithline=show, istop=1):
break
l = l[:-1]
if not strictf77:
- (l, rl) = split_by_unquoted(l, '!')
- l += ' '
- if rl[:5].lower() == '!f2py': # f2py directive
- l, _ = split_by_unquoted(l + 4 * ' ' + rl[5:], '!')
+ r = commentline.match(l)
+ if r:
+ l = r.group('line') + ' ' # Strip comments starting with `!'
+ rl = r.group('rest')
+ if rl[:4].lower() == 'f2py': # f2py directive
+ l = l + 4 * ' '
+ r = commentline.match(rl[4:])
+ if r:
+ l = l + r.group('line')
+ else:
+ l = l + rl[4:]
if l.strip() == '': # Skip empty line
cont = 0
continue
@@ -609,25 +618,6 @@ multilinepattern = re.compile(
r"\s*(?P<before>''')(?P<this>.*?)(?P<after>''')\s*\Z", re.S), 'multiline'
##
-def split_by_unquoted(line, characters):
- """
- Splits the line into (line[:i], line[i:]),
- where i is the index of first occurrence of one of the characters
- not within quotes, or len(line) if no such index exists
- """
- assert not (set('"\'') & set(characters)), "cannot split by unquoted quotes"
- r = re.compile(
- r"\A(?P<before>({single_quoted}|{double_quoted}|{not_quoted})*)"
- r"(?P<after>{char}.*)\Z".format(
- not_quoted="[^\"'{}]".format(re.escape(characters)),
- char="[{}]".format(re.escape(characters)),
- single_quoted=r"('([^'\\]|(\\.))*')",
- double_quoted=r'("([^"\\]|(\\.))*")'))
- m = r.match(line)
- if m:
- d = m.groupdict()
- return (d["before"], d["after"])
- return (line, "")
def _simplifyargs(argsline):
a = []
@@ -652,17 +642,12 @@ def crackline(line, reset=0):
global filepositiontext, currentfilename, neededmodule, expectbegin
global skipblocksuntil, skipemptyends, previous_context, gotnextfile
- _, has_semicolon = split_by_unquoted(line, ";")
- if has_semicolon and not (f2pyenhancementspattern[0].match(line) or
- multilinepattern[0].match(line)):
- # XXX: non-zero reset values need testing
- assert reset == 0, repr(reset)
- # split line on unquoted semicolons
- line, semicolon_line = split_by_unquoted(line, ";")
- while semicolon_line:
- crackline(line, reset)
- line, semicolon_line = split_by_unquoted(semicolon_line[1:], ";")
- crackline(line, reset)
+ if ';' in line and not (f2pyenhancementspattern[0].match(line) or
+ multilinepattern[0].match(line)):
+ for l in line.split(';'):
+ # XXX: non-zero reset values need testing
+ assert reset == 0, repr(reset)
+ crackline(l, reset)
return
if reset < 0:
groupcounter = 0
@@ -817,22 +802,26 @@ def markouterparen(line):
def markoutercomma(line, comma=','):
l = ''
f = 0
- before, after = split_by_unquoted(line, comma + '()')
- l += before
- while after:
- if (after[0] == comma) and (f == 0):
- l += '@' + comma + '@'
- else:
- l += after[0]
- if after[0] == '(':
- f += 1
- elif after[0] == ')':
- f -= 1
- before, after = split_by_unquoted(after[1:], comma + '()')
- l += before
- assert not f, repr((f, line, l))
+ cc = ''
+ for c in line:
+ if (not cc or cc == ')') and c == '(':
+ f = f + 1
+ cc = ')'
+ elif not cc and c == '\'' and (not l or l[-1] != '\\'):
+ f = f + 1
+ cc = '\''
+ elif c == cc:
+ f = f - 1
+ if f == 0:
+ cc = ''
+ elif c == comma and f == 0:
+ l = l + '@' + comma + '@'
+ continue
+ l = l + c
+ assert not f, repr((f, line, l, cc))
return l
+
def unmarkouterparen(line):
r = line.replace('@(@', '(').replace('@)@', ')')
return r
diff --git a/numpy/f2py/tests/test_quoted_character.py b/numpy/f2py/tests/test_quoted_character.py
deleted file mode 100644
index 09fc7328f..000000000
--- a/numpy/f2py/tests/test_quoted_character.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from __future__ import division, absolute_import, print_function
-
-import sys
-import pytest
-
-from numpy.testing import assert_equal
-from . import util
-
-class TestQuotedCharacter(util.F2PyTest):
- code = """
- SUBROUTINE FOO(OUT1, OUT2, OUT3, OUT4, OUT5, OUT6)
- CHARACTER SINGLE, DOUBLE, SEMICOL, EXCLA, OPENPAR, CLOSEPAR
- PARAMETER (SINGLE="'", DOUBLE='"', SEMICOL=';', EXCLA="!",
- 1 OPENPAR="(", CLOSEPAR=")")
- CHARACTER OUT1, OUT2, OUT3, OUT4, OUT5, OUT6
-Cf2py intent(out) OUT1, OUT2, OUT3, OUT4, OUT5, OUT6
- OUT1 = SINGLE
- OUT2 = DOUBLE
- OUT3 = SEMICOL
- OUT4 = EXCLA
- OUT5 = OPENPAR
- OUT6 = CLOSEPAR
- RETURN
- END
- """
-
- @pytest.mark.skipif(sys.platform=='win32',
- reason='Fails with MinGW64 Gfortran (Issue #9673)')
- def test_quoted_character(self):
- assert_equal(self.module.foo(), (b"'", b'"', b';', b'!', b'(', b')'))