106 lines
2.9 KiB
Python
106 lines
2.9 KiB
Python
|
# Copyright 2012 Google Inc. All Rights Reserved.
|
||
|
|
||
|
__author__ = 'benvanik@google.com (Ben Vanik)'
|
||
|
|
||
|
|
||
|
import os
|
||
|
import string
|
||
|
import sys
|
||
|
import time
|
||
|
|
||
|
|
||
|
# Unfortunately there is no one-true-timer in python
|
||
|
# This should always be preferred over direct use of the time module
|
||
|
if sys.platform == 'win32' or sys.platform == 'cygwin':
|
||
|
timer = time.clock # pragma: no cover
|
||
|
else:
|
||
|
timer = time.time # pragma: no cover
|
||
|
|
||
|
|
||
|
def find_build_path(): # pragma: no cover
|
||
|
"""Scans up the current path for the anvil/ folder.
|
||
|
|
||
|
Returns:
|
||
|
The 'anvil/' folder.
|
||
|
"""
|
||
|
path = sys.path[0]
|
||
|
while True:
|
||
|
if os.path.exists(os.path.join(path, 'anvil')):
|
||
|
return os.path.join(path, 'anvil')
|
||
|
path = os.path.dirname(path)
|
||
|
if not len(path):
|
||
|
return None
|
||
|
|
||
|
|
||
|
def is_rule_path(value):
|
||
|
"""Detects whether the given value is a rule name.
|
||
|
|
||
|
Returns:
|
||
|
True if the string is a valid rule name.
|
||
|
"""
|
||
|
# NOTE: in the future this could be made to support modules/etc by looking
|
||
|
# for any valid use of ':'
|
||
|
return isinstance(value, str) and len(value) and string.find(value, ':') >= 0
|
||
|
|
||
|
|
||
|
def validate_names(values, require_semicolon=False):
|
||
|
"""Validates a list of rule names to ensure they are well-defined.
|
||
|
|
||
|
Args:
|
||
|
values: A list of values to validate.
|
||
|
require_semicolon: Whether to require a :
|
||
|
|
||
|
Raises:
|
||
|
NameError: A rule value is not valid.
|
||
|
"""
|
||
|
if not values:
|
||
|
return
|
||
|
for value in values:
|
||
|
if not isinstance(value, str) or not len(value):
|
||
|
raise TypeError('Names must be a string of non-zero length')
|
||
|
if len(value.strip()) != len(value):
|
||
|
raise NameError(
|
||
|
'Names cannot have leading/trailing whitespace: "%s"' % (value))
|
||
|
if require_semicolon and string.find(value, ':') == -1:
|
||
|
raise NameError('Names must be a rule (contain a :): "%s"' % (value))
|
||
|
|
||
|
|
||
|
def underscore_to_pascalcase(value):
|
||
|
"""Converts a string from underscore_case to PascalCase.
|
||
|
|
||
|
Args:
|
||
|
value: Source string value.
|
||
|
Example - hello_world
|
||
|
|
||
|
Returns:
|
||
|
The string, converted to PascalCase.
|
||
|
Example - hello_world -> HelloWorld
|
||
|
"""
|
||
|
if not value:
|
||
|
return value
|
||
|
def __CapWord(seq):
|
||
|
for word in seq:
|
||
|
yield word.capitalize()
|
||
|
return ''.join(__CapWord(word if word else '_' for word in value.split('_')))
|
||
|
|
||
|
|
||
|
def which(executable_name):
|
||
|
"""Gets the full path to the given executable.
|
||
|
If the given path exists in the CWD or is already absolute it is returned.
|
||
|
Otherwise this method will look through the system PATH to try to find it.
|
||
|
|
||
|
Args:
|
||
|
executable_name: Name or path to the executable.
|
||
|
|
||
|
Returns:
|
||
|
The full path to the executable or None if it was not found.
|
||
|
"""
|
||
|
if (os.path.exists(executable_name) and
|
||
|
not os.path.isdir(executable_name)):
|
||
|
return os.path.abspath(executable_name)
|
||
|
for path in os.environ.get('PATH', '').split(':'):
|
||
|
if (os.path.exists(os.path.join(path, executable_name)) and
|
||
|
not os.path.isdir(os.path.join(path, executable_name))):
|
||
|
return os.path.join(path, executable_name)
|
||
|
return None
|