aboutsummaryrefslogtreecommitdiffstats
path: root/pkg_resources.py
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2013-06-08 12:20:10 -0400
committerJason R. Coombs <jaraco@jaraco.com>2013-06-08 12:20:10 -0400
commit054a029a61fcf8257d0af0619810c2e4b384e30e (patch)
tree196f365bb371d09c745747930cdca1e02c7c42dd /pkg_resources.py
parent1541dc716cc580c95883347832b689d3b8eb009b (diff)
parent468bb206e7a97aecb6df3cfec463b77c94acaf9c (diff)
downloadexternal_python_setuptools-054a029a61fcf8257d0af0619810c2e4b384e30e.tar.gz
external_python_setuptools-054a029a61fcf8257d0af0619810c2e4b384e30e.tar.bz2
external_python_setuptools-054a029a61fcf8257d0af0619810c2e4b384e30e.zip
Merge legacy evaluation as a fallback with markerlib-based evaluation of environment markers. Fixes #14
Diffstat (limited to 'pkg_resources.py')
-rw-r--r--pkg_resources.py101
1 files changed, 100 insertions, 1 deletions
diff --git a/pkg_resources.py b/pkg_resources.py
index cdd732d2..4225ae55 100644
--- a/pkg_resources.py
+++ b/pkg_resources.py
@@ -1211,8 +1211,104 @@ def invalid_marker(text):
return sys.exc_info()[1]
return False
+def _evaluate_marker_legacy(text, extra=None, _ops={}):
+ """
+ Evaluate a PEP 426 environment marker on CPython 2.4+.
+ Return a boolean indicating the marker result in this environment.
+ Raise SyntaxError if marker is invalid.
+
+ This implementation uses the 'parser' module, which is not implemented on
+ Jython and has been superseded by the 'ast' module in Python 2.6 and
+ later.
+ """
+
+ if not _ops:
+
+ from token import NAME, STRING
+ import token, symbol, operator
+
+ def and_test(nodelist):
+ # MUST NOT short-circuit evaluation, or invalid syntax can be skipped!
+ return reduce(operator.and_, [interpret(nodelist[i]) for i in range(1,len(nodelist),2)])
+
+ def test(nodelist):
+ # MUST NOT short-circuit evaluation, or invalid syntax can be skipped!
+ return reduce(operator.or_, [interpret(nodelist[i]) for i in range(1,len(nodelist),2)])
+
+ def atom(nodelist):
+ t = nodelist[1][0]
+ if t == token.LPAR:
+ if nodelist[2][0] == token.RPAR:
+ raise SyntaxError("Empty parentheses")
+ return interpret(nodelist[2])
+ raise SyntaxError("Language feature not supported in environment markers")
+
+ def comparison(nodelist):
+ if len(nodelist)>4:
+ raise SyntaxError("Chained comparison not allowed in environment markers")
+ comp = nodelist[2][1]
+ cop = comp[1]
+ if comp[0] == NAME:
+ if len(nodelist[2]) == 3:
+ if cop == 'not':
+ cop = 'not in'
+ else:
+ cop = 'is not'
+ try:
+ cop = _ops[cop]
+ except KeyError:
+ raise SyntaxError(repr(cop)+" operator not allowed in environment markers")
+ return cop(evaluate(nodelist[1]), evaluate(nodelist[3]))
+
+ _ops.update({
+ symbol.test: test, symbol.and_test: and_test, symbol.atom: atom,
+ symbol.comparison: comparison, 'not in': lambda x,y: x not in y,
+ 'in': lambda x,y: x in y, '==': operator.eq, '!=': operator.ne,
+ })
+ if hasattr(symbol,'or_test'):
+ _ops[symbol.or_test] = test
+
+ def interpret(nodelist):
+ while len(nodelist)==2: nodelist = nodelist[1]
+ try:
+ op = _ops[nodelist[0]]
+ except KeyError:
+ raise SyntaxError("Comparison or logical expression expected")
+ raise SyntaxError("Language feature not supported in environment markers: "+symbol.sym_name[nodelist[0]])
+ return op(nodelist)
+
+ def evaluate(nodelist):
+ while len(nodelist)==2: nodelist = nodelist[1]
+ kind = nodelist[0]
+ name = nodelist[1]
+ #while len(name)==2: name = name[1]
+ if kind==NAME:
+ try:
+ op = _marker_values[name]
+ except KeyError:
+ raise SyntaxError("Unknown name %r" % name)
+ return op()
+ if kind==STRING:
+ s = nodelist[1]
+ if s[:1] not in "'\"" or s.startswith('"""') or s.startswith("'''") \
+ or '\\' in s:
+ raise SyntaxError(
+ "Only plain strings allowed in environment markers")
+ return s[1:-1]
+ raise SyntaxError("Language feature not supported in environment markers")
+
+ import parser
+ return interpret(parser.expr(text).totuple(1)[1])
+
def evaluate_marker(text):
- """Evaluate a PEP 426 environment marker; SyntaxError if marker is invalid"""
+ """
+ Evaluate a PEP 426 environment marker.
+ Return a boolean indicating the marker result in this environment.
+ Raise SyntaxError if marker is invalid.
+
+ Note the implementation is incomplete as it does not support parentheses
+ for grouping.
+ """
import _markerlib
# markerlib implements Metadata 1.2 (PEP 345) environment markers.
# Translate the variables to Metadata 2.0 (PEP 426).
@@ -1222,6 +1318,9 @@ def evaluate_marker(text):
env[new_key] = env.pop(key)
return _markerlib.interpret(text, env)
+# support marker evaluation on Python 2.4+
+if sys.version_info < (2,6) and _pyimp() == 'CPython':
+ evaluate_marker = _evaluate_marker_legacy
class NullProvider:
"""Try to implement resources and metadata for arbitrary PEP 302 loaders"""