@ -24,6 +24,27 @@ else:
basestring = str
basestring = str
class ConstantString ( object ) :
def __init__ ( self , value ) :
self . value = value
def __format__ ( self , format_spec ) :
del format_spec
return self . value
def __repr__ ( self ) :
return " Str( ' " + self . value + " ' ) "
def __eq__ ( self , other ) :
if isinstance ( other , ConstantString ) :
return self . value == other . value
else :
return self . value == other
def __hash__ ( self ) :
return self . value . __hash__ ( )
class _NodeDict ( collections_abc . MutableMapping ) :
class _NodeDict ( collections_abc . MutableMapping ) :
""" Dict-like type that also stores information on AST nodes and tokens. """
""" Dict-like type that also stores information on AST nodes and tokens. """
def __init__ ( self , data = None , tokens = None ) :
def __init__ ( self , data = None , tokens = None ) :
@ -114,7 +135,7 @@ _GCLIENT_DEPS_SCHEMA = _NodeDictSchema({
_GCLIENT_HOOKS_SCHEMA = [
_GCLIENT_HOOKS_SCHEMA = [
_NodeDictSchema ( {
_NodeDictSchema ( {
# Hook action: list of command-line arguments to invoke.
# Hook action: list of command-line arguments to invoke.
' action ' : [ basestring] ,
' action ' : [ schema. Or ( basestring) ] ,
# Name of the hook. Doesn't affect operation.
# Name of the hook. Doesn't affect operation.
schema . Optional ( ' name ' ) : basestring ,
schema . Optional ( ' name ' ) : basestring ,
@ -220,7 +241,9 @@ _GCLIENT_SCHEMA = schema.Schema(
# Variables that can be referenced using Var() - see 'deps'.
# Variables that can be referenced using Var() - see 'deps'.
schema . Optional ( ' vars ' ) : _NodeDictSchema ( {
schema . Optional ( ' vars ' ) : _NodeDictSchema ( {
schema . Optional ( basestring ) : schema . Or ( basestring , bool ) ,
schema . Optional ( basestring ) : schema . Or ( ConstantString ,
basestring ,
bool ) ,
} ) ,
} ) ,
} ) )
} ) )
@ -228,6 +251,8 @@ _GCLIENT_SCHEMA = schema.Schema(
def _gclient_eval ( node_or_string , filename = ' <unknown> ' , vars_dict = None ) :
def _gclient_eval ( node_or_string , filename = ' <unknown> ' , vars_dict = None ) :
""" Safely evaluates a single expression. Returns the result. """
""" Safely evaluates a single expression. Returns the result. """
_allowed_names = { ' None ' : None , ' True ' : True , ' False ' : False }
_allowed_names = { ' None ' : None , ' True ' : True , ' False ' : False }
if isinstance ( node_or_string , ConstantString ) :
return node_or_string . value
if isinstance ( node_or_string , basestring ) :
if isinstance ( node_or_string , basestring ) :
node_or_string = ast . parse ( node_or_string , filename = filename , mode = ' eval ' )
node_or_string = ast . parse ( node_or_string , filename = filename , mode = ' eval ' )
if isinstance ( node_or_string , ast . Expression ) :
if isinstance ( node_or_string , ast . Expression ) :
@ -269,16 +294,23 @@ def _gclient_eval(node_or_string, filename='<unknown>', vars_dict=None):
node , ast . NameConstant ) : # Since Python 3.4
node , ast . NameConstant ) : # Since Python 3.4
return node . value
return node . value
elif isinstance ( node , ast . Call ) :
elif isinstance ( node , ast . Call ) :
if not isinstance ( node . func , ast . Name ) or node . func . id != ' Var ' :
if ( not isinstance ( node . func , ast . Name ) or
( node . func . id not in ( ' Str ' , ' Var ' ) ) ) :
raise ValueError (
raise ValueError (
' Var is the only allowed function (file %r , line %s ) ' % (
' Str and Var are the only allowed functions (file %r , line %s ) ' % (
filename , getattr ( node , ' lineno ' , ' <unknown> ' ) ) )
filename , getattr ( node , ' lineno ' , ' <unknown> ' ) ) )
if node . keywords or getattr ( node , ' starargs ' , None ) or getattr (
if node . keywords or getattr ( node , ' starargs ' , None ) or getattr (
node , ' kwargs ' , None ) or len ( node . args ) != 1 :
node , ' kwargs ' , None ) or len ( node . args ) != 1 :
raise ValueError (
raise ValueError (
' Var takes exactly one argument (file %r , line %s ) ' % (
' %s takes exactly one argument (file %r , line %s ) ' % (
filename , getattr ( node , ' lineno ' , ' <unknown> ' ) ) )
node . func . id , filename , getattr ( node , ' lineno ' , ' <unknown> ' ) ) )
arg = _convert ( node . args [ 0 ] )
if node . func . id == ' Str ' :
if isinstance ( node . args [ 0 ] , ast . Str ) :
return ConstantString ( node . args [ 0 ] . s )
raise ValueError ( ' Passed a non-string to Str() (file %r , line %s ) ' % (
filename , getattr ( node , ' lineno ' , ' <unknown> ' ) ) )
else :
arg = _convert ( node . args [ 0 ] )
if not isinstance ( arg , basestring ) :
if not isinstance ( arg , basestring ) :
raise ValueError (
raise ValueError (
' Var \' s argument must be a variable name (file %r , line %s ) ' % (
' Var \' s argument must be a variable name (file %r , line %s ) ' % (
@ -290,7 +322,10 @@ def _gclient_eval(node_or_string, filename='<unknown>', vars_dict=None):
' %s was used as a variable, but was not declared in the vars dict '
' %s was used as a variable, but was not declared in the vars dict '
' (file %r , line %s ) ' % (
' (file %r , line %s ) ' % (
arg , filename , getattr ( node , ' lineno ' , ' <unknown> ' ) ) )
arg , filename , getattr ( node , ' lineno ' , ' <unknown> ' ) ) )
return vars_dict [ arg ]
val = vars_dict [ arg ]
if isinstance ( val , ConstantString ) :
val = val . value
return val
elif isinstance ( node , ast . BinOp ) and isinstance ( node . op , ast . Add ) :
elif isinstance ( node , ast . BinOp ) and isinstance ( node . op , ast . Add ) :
return _convert ( node . left ) + _convert ( node . right )
return _convert ( node . left ) + _convert ( node . right )
elif isinstance ( node , ast . BinOp ) and isinstance ( node . op , ast . Mod ) :
elif isinstance ( node , ast . BinOp ) and isinstance ( node . op , ast . Mod ) :
@ -601,6 +636,8 @@ def RenderDEPSFile(gclient_dict):
def _UpdateAstString ( tokens , node , value ) :
def _UpdateAstString ( tokens , node , value ) :
if isinstance ( node , ast . Call ) :
node = node . args [ 0 ]
position = node . lineno , node . col_offset
position = node . lineno , node . col_offset
quote_char = ' '
quote_char = ' '
if isinstance ( node , ast . Str ) :
if isinstance ( node , ast . Str ) :
@ -810,7 +847,10 @@ def GetVar(gclient_dict, var_name):
raise KeyError (
raise KeyError (
" Could not find any variable called %s . " % var_name )
" Could not find any variable called %s . " % var_name )
return gclient_dict [ ' vars ' ] [ var_name ]
val = gclient_dict [ ' vars ' ] [ var_name ]
if isinstance ( val , ConstantString ) :
return val . value
return val
def GetCIPD ( gclient_dict , dep_name , package_name ) :
def GetCIPD ( gclient_dict , dep_name , package_name ) :