Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
markers.py168 linesDownload Raw Back to distlib
1# -*- coding: utf-8 -*-2#3# Copyright (C) 2012-2023 Vinay Sajip.4# Licensed to the Python Software Foundation under a contributor agreement.5# See LICENSE.txt and CONTRIBUTORS.txt.6#7"""8Parser for the environment markers micro-language defined in PEP 508.9"""10 11# Note: In PEP 345, the micro-language was Python compatible, so the ast12# module could be used to parse it. However, PEP 508 introduced operators such13# as ~= and === which aren't in Python, necessitating a different approach.14 15import os16import re17import sys18import platform19 20from .compat import string_types21from .util import in_venv, parse_marker22from .version import LegacyVersion as LV23 24__all__ = ['interpret']25 26_VERSION_PATTERN = re.compile(27    r'((\d+(\.\d+)*\w*)|\'(\d+(\.\d+)*\w*)\'|\"(\d+(\.\d+)*\w*)\")')28_VERSION_MARKERS = {'python_version', 'python_full_version'}29 30 31def _is_version_marker(s):32    return isinstance(s, string_types) and s in _VERSION_MARKERS33 34 35def _is_literal(o):36    if not isinstance(o, string_types) or not o:37        return False38    return o[0] in '\'"'39 40 41def _get_versions(s):42    return {LV(m.groups()[0]) for m in _VERSION_PATTERN.finditer(s)}43 44 45class Evaluator(object):46    """47    This class is used to evaluate marker expressions.48    """49 50    operations = {51        '==': lambda x, y: x == y,52        '===': lambda x, y: x == y,53        '~=': lambda x, y: x == y or x > y,54        '!=': lambda x, y: x != y,55        '<': lambda x, y: x < y,56        '<=': lambda x, y: x == y or x < y,57        '>': lambda x, y: x > y,58        '>=': lambda x, y: x == y or x > y,59        'and': lambda x, y: x and y,60        'or': lambda x, y: x or y,61        'in': lambda x, y: x in y,62        'not in': lambda x, y: x not in y,63    }64 65    def evaluate(self, expr, context):66        """67        Evaluate a marker expression returned by the :func:`parse_requirement`68        function in the specified context.69        """70        if isinstance(expr, string_types):71            if expr[0] in '\'"':72                result = expr[1:-1]73            else:74                if expr not in context:75                    raise SyntaxError('unknown variable: %s' % expr)76                result = context[expr]77        else:78            assert isinstance(expr, dict)79            op = expr['op']80            if op not in self.operations:81                raise NotImplementedError('op not implemented: %s' % op)82            elhs = expr['lhs']83            erhs = expr['rhs']84            if _is_literal(expr['lhs']) and _is_literal(expr['rhs']):85                raise SyntaxError('invalid comparison: %s %s %s' %86                                  (elhs, op, erhs))87 88            lhs = self.evaluate(elhs, context)89            rhs = self.evaluate(erhs, context)90            if ((_is_version_marker(elhs) or _is_version_marker(erhs))91                    and op in ('<', '<=', '>', '>=', '===', '==', '!=', '~=')):92                lhs = LV(lhs)93                rhs = LV(rhs)94            elif _is_version_marker(elhs) and op in ('in', 'not in'):95                lhs = LV(lhs)96                rhs = _get_versions(rhs)97            result = self.operations[op](lhs, rhs)98        return result99 100 101_DIGITS = re.compile(r'\d+\.\d+')102 103 104def default_context():105 106    def format_full_version(info):107        version = '%s.%s.%s' % (info.major, info.minor, info.micro)108        kind = info.releaselevel109        if kind != 'final':110            version += kind[0] + str(info.serial)111        return version112 113    if hasattr(sys, 'implementation'):114        implementation_version = format_full_version(115            sys.implementation.version)116        implementation_name = sys.implementation.name117    else:118        implementation_version = '0'119        implementation_name = ''120 121    ppv = platform.python_version()122    m = _DIGITS.match(ppv)123    pv = m.group(0)124    result = {125        'implementation_name': implementation_name,126        'implementation_version': implementation_version,127        'os_name': os.name,128        'platform_machine': platform.machine(),129        'platform_python_implementation': platform.python_implementation(),130        'platform_release': platform.release(),131        'platform_system': platform.system(),132        'platform_version': platform.version(),133        'platform_in_venv': str(in_venv()),134        'python_full_version': ppv,135        'python_version': pv,136        'sys_platform': sys.platform,137    }138    return result139 140 141DEFAULT_CONTEXT = default_context()142del default_context143 144evaluator = Evaluator()145 146 147def interpret(marker, execution_context=None):148    """149    Interpret a marker and return a result depending on environment.150 151    :param marker: The marker to interpret.152    :type marker: str153    :param execution_context: The context used for name lookup.154    :type execution_context: mapping155    """156    try:157        expr, rest = parse_marker(marker)158    except Exception as e:159        raise SyntaxError('Unable to interpret marker syntax: %s: %s' %160                          (marker, e))161    if rest and rest[0] != '#':162        raise SyntaxError('unexpected trailing data in marker: %s: %s' %163                          (marker, rest))164    context = dict(DEFAULT_CONTEXT)165    if execution_context:166        context.update(execution_context)167    return evaluator.evaluate(expr, context)168 
codekingpro/portable-devtools · Team Ai