Skip to content

Commit b882682

Browse files
committed
py26 compatibility
1 parent 4ba54d6 commit b882682

File tree

2 files changed

+50
-13
lines changed

2 files changed

+50
-13
lines changed

pymake/_pymake.py

+13-12
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,19 @@
33
"""
44
from __future__ import absolute_import
55
# import compatibility functions and utilities
6-
from ._utils import ConfigParser, StringIO
6+
from ._utils import ConfigParser, StringIO, shlex
77
import io
88
import re
99
from subprocess import check_call
10-
import shlex
11-
1210

1311
__author__ = {"github.com/": ["casperdcl", "lrq3000"]}
1412
__all__ = ['PymakeTypeError', 'PymakeKeyError',
1513
'parse_makefile_aliases', 'execute_makefile_commands']
1614

1715

18-
RE_MAKE_CMD = re.compile('^\t(@\+?)(make)?', flags=re.M)
19-
RE_MACRO_DEF = re.compile(r"^(\S+)\s*\:?\=\s*(.*?)$", flags=re.M)
20-
RE_MACRO = re.compile(r"\$\(\s*\S+\s*\)", flags=re.M)
16+
RE_MAKE_CMD = re.compile('^\t(@\+?)(make)?')
17+
RE_MACRO_DEF = re.compile(r"^(\S+)\s*\:?\=\s*(.*?)$")
18+
RE_MACRO = re.compile(r"\$\(\s*\S+\s*\)")
2119

2220

2321
class PymakeTypeError(TypeError):
@@ -42,19 +40,22 @@ def parse_makefile_aliases(filepath):
4240

4341
# -- Parsing the Makefile using ConfigParser
4442
# Adding a fake section to make the Makefile a valid Ini file
45-
ini_str = '[root]\n'
43+
ini_lines = ['[root]']
4644
with io.open(filepath, mode='r') as fd:
47-
ini_str = ini_str + RE_MAKE_CMD.sub('\t', fd.read())
45+
ini_lines.extend(RE_MAKE_CMD.sub('\t', i) for i in fd.readlines())
4846

4947
# Substitute macros
50-
macros = dict(RE_MACRO_DEF.findall(ini_str))
48+
macros = dict(found for l in ini_lines
49+
for found in RE_MACRO_DEF.findall(l) if found)
50+
ini_str = '\n'.join(ini_lines)
5151
# allow finite amount of nesting
5252
for _ in range(99):
5353
for (m, expr) in getattr(macros, 'iteritems', macros.items)():
54-
ini_str = re.sub(r"\$\(" + m + "\)", expr, ini_str, flags=re.M)
55-
if not RE_MACRO.match(ini_str):
54+
ini_str = re.sub(r"\$\(" + m + "\)", expr, ini_str)
55+
if not RE_MACRO.search(ini_str):
5656
# Strip macro definitions for rest of parsing
57-
ini_str = RE_MACRO_DEF.sub("", ini_str)
57+
ini_str = '\n'.join(l for l in ini_str.splitlines()
58+
if not RE_MACRO_DEF.search(l))
5859
break
5960
else:
6061
raise PymakeKeyError("No substitution for macros: " +

pymake/_utils.py

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
__all__ = ["ConfigParser", "StringIO", "_sh"]
1+
import sys
2+
3+
__all__ = ["ConfigParser", "StringIO", "_sh", "shlex"]
24

35
if True: # pragma: no cover
46
try:
@@ -18,6 +20,40 @@
1820
except NameError:
1921
_unicode = str
2022

23+
if sys.version_info >= (2, 7): # pragma: no cover
24+
import shlex
25+
else: # pragma: no cover
26+
import re
27+
28+
class shlex(object):
29+
""" Emulate built-in shlex.split using re """
30+
# tokens may be surrounded by unescaped quote pairs
31+
RE_TOKEN = re.compile(r'(?<!\\)(?P<q>[\'"])(.*?)(?<!\\)(?P=q)')
32+
RE_WTSPC = re.compile(r'\s+')
33+
# unescaped hash (designates a comment when unquoted)
34+
RE_CMMNT = re.compile(r'(.*?)(?<!\\)#')
35+
36+
@classmethod
37+
def split(cls, cmd, comments=True):
38+
toks = cls.RE_TOKEN.split(cmd)
39+
res = []
40+
quoted = False
41+
for t in toks:
42+
if quoted:
43+
if t:
44+
res.append(t)
45+
quoted = False
46+
elif t in '\'"':
47+
quoted = True
48+
elif t:
49+
c = cls.RE_CMMNT.split(t)
50+
uncom = (c[0] or c[1]).strip()
51+
if uncom:
52+
res.extend(cls.RE_WTSPC.split(uncom))
53+
if len(c) > 1:
54+
break # rest is comment
55+
return res
56+
2157

2258
def _sh(*cmd, **kwargs):
2359
import subprocess

0 commit comments

Comments
 (0)