diff options
author | Josh Bell <josh@lindenlab.com> | 2008-02-15 18:47:45 +0000 |
---|---|---|
committer | Josh Bell <josh@lindenlab.com> | 2008-02-15 18:47:45 +0000 |
commit | 8eea75dc3f4138a0b216e8d662089d2c930d5d45 (patch) | |
tree | 91dfcb8e0e0400a737d30d3aad88e63633aa2742 | |
parent | 383f92e54369a47a96afb3467c680f870df700a1 (diff) |
svn merge -r 79841:79886 svn+ssh://svn.lindenlab.com/svn/linden/branches/self-contained-unit-test --> release
QAR-291/QAR-284/QAR-246 - Self-Contained Unit Test
-rw-r--r-- | indra/lib/python/indra/base/config.py | 25 | ||||
-rw-r--r-- | indra/lib/python/indra/base/lluuid.py | 21 | ||||
-rw-r--r-- | indra/lib/python/indra/ipc/mysql_pool.py | 5 | ||||
-rw-r--r-- | indra/lib/python/indra/util/named_query.py | 48 | ||||
-rw-r--r-- | indra/lib/python/indra/util/shutil2.py | 84 |
5 files changed, 175 insertions, 8 deletions
diff --git a/indra/lib/python/indra/base/config.py b/indra/lib/python/indra/base/config.py index c6872fa251..a28c59c702 100644 --- a/indra/lib/python/indra/base/config.py +++ b/indra/lib/python/indra/base/config.py @@ -47,6 +47,25 @@ def load(indra_xml_file=None): config_file.close() #print "loaded config from",indra_xml_file,"into",_g_config_dict +def dump(indra_xml_file, indra_cfg={}, update_in_mem=False): + ''' + Dump config contents into a file + Kindof reverse of load. + Optionally takes a new config to dump. + Does NOT update global config unless requested. + ''' + global _g_config_dict + if not indra_cfg: + indra_cfg = _g_config_dict + if not indra_cfg: + return + config_file = open(indra_xml_file, 'w') + _config_xml = llsd.format_xml(indra_cfg) + config_file.write(_config_xml) + config_file.close() + if update_in_mem: + update(indra_cfg) + def update(new_conf): """Load an XML file and apply its map as overrides or additions to the existing config. The dataserver does this with indra.xml @@ -69,6 +88,12 @@ def get(key, default = None): load() return _g_config_dict.get(key, default) +def set(key, newval): + global _g_config_dict + if _g_config_dict == None: + load() + _g_config_dict[key] = newval + def as_dict(): global _g_config_dict return _g_config_dict diff --git a/indra/lib/python/indra/base/lluuid.py b/indra/lib/python/indra/base/lluuid.py index 609c8cc261..019ccfc215 100644 --- a/indra/lib/python/indra/base/lluuid.py +++ b/indra/lib/python/indra/base/lluuid.py @@ -227,16 +227,31 @@ def printTranslatedMemory(four_hex_uints): uuid.setFromMemoryDump(four_hex_uints) print uuid.toString() -def isPossiblyID(id_str): +def isUUID(id_str): """ - This function returns 1 if the string passed has some uuid-like - characteristics. Otherwise returns 0. + This function returns: + - 1 if the string passed is a UUID + - 0 is the string passed is not a UUID + - None if it neither of the if's below is satisfied """ if not id_str or len(id_str) < 5 or len(id_str) > 36: return 0 if isinstance(id_str, UUID) or UUID.uuid_regex.match(id_str): return 1 + + return None + +def isPossiblyID(id_str): + """ + This function returns 1 if the string passed has some uuid-like + characteristics. Otherwise returns 0. + """ + + is_uuid = isUUID(id_str) + if is_uuid is not None: + return is_uuid + # build a string which matches every character. hex_wildcard = r"[0-9a-fA-F]" chars = len(id_str) diff --git a/indra/lib/python/indra/ipc/mysql_pool.py b/indra/lib/python/indra/ipc/mysql_pool.py index 6288a4c732..827b6d42e9 100644 --- a/indra/lib/python/indra/ipc/mysql_pool.py +++ b/indra/lib/python/indra/ipc/mysql_pool.py @@ -64,12 +64,13 @@ connection pools keyed on host,databasename""" else: return self._credentials.get('default', None) - def get(self, host, dbname): - key = (host, dbname) + def get(self, host, dbname, port=3306): + key = (host, dbname, port) if key not in self._databases: new_kwargs = self._kwargs.copy() new_kwargs['db'] = dbname new_kwargs['host'] = host + new_kwargs['port'] = port new_kwargs.update(self.credentials_for(host)) dbpool = ConnectionPool(self._min_size, self._max_size, *self._args, **new_kwargs) self._databases[key] = dbpool diff --git a/indra/lib/python/indra/util/named_query.py b/indra/lib/python/indra/util/named_query.py index c3bdd046fd..471998388d 100644 --- a/indra/lib/python/indra/util/named_query.py +++ b/indra/lib/python/indra/util/named_query.py @@ -495,9 +495,51 @@ class _RewriteQueryForArray(object): if type(value) in (list,tuple): rv = [] for idx in range(len(value)): - new_key = "_" + key + "_" + str(idx) - self.new_params[new_key] = value[idx] - rv.append("%(" + new_key + ")s") + # if the value@idx is array-like, we are + # probably dealing with a VALUES + new_key = "_%s_%s"%(key, str(idx)) + val_item = value[idx] + if type(val_item) in (list, tuple, dict): + if type(val_item) is dict: + # this is because in Python, the order of + # key, value retrieval from the dict is not + # guaranteed to match what the input intended + # and for VALUES, order is important. + # TODO: Implemented ordered dict in LLSD parser? + raise ExpectationFailed('Only lists/tuples allowed,\ + received dict') + values_keys = [] + for value_idx, item in enumerate(val_item): + # we want a key of the format : + # key_#replacement_#value_row_#value_col + # ugh... so if we are replacing 10 rows in user_note, + # the first values clause would read (for @:user_notes) :- + # ( :_user_notes_0_1_1, :_user_notes_0_1_2, :_user_notes_0_1_3 ) + # the input LLSD for VALUES will look like: + # <llsd>... + # <map> + # <key>user_notes</key> + # <array> + # <array> <!-- row 1 for VALUES --> + # <string>...</string> + # <string>...</string> + # <string>...</string> + # </array> + # ... + # </array> + # </map> + # ... </llsd> + values_key = "%s_%s"%(new_key, value_idx) + self.new_params[values_key] = item + values_keys.append("%%(%s)s"%values_key) + # now collapse all these new place holders enclosed in () + # from [':_key_0_1_1', ':_key_0_1_2', ':_key_0_1_3,...] + # rv will have [ '(:_key_0_1_1, :_key_0_1_2, :_key_0_1_3)', ] + # which is flattened a few lines below join(rv) + rv.append('(%s)' % ','.join(values_keys)) + else: + self.new_params[new_key] = val_item + rv.append("%%(%s)s"%new_key) return ','.join(rv) else: # not something that can be expanded, so just drop the diff --git a/indra/lib/python/indra/util/shutil2.py b/indra/lib/python/indra/util/shutil2.py new file mode 100644 index 0000000000..3acb44bf6f --- /dev/null +++ b/indra/lib/python/indra/util/shutil2.py @@ -0,0 +1,84 @@ +''' +@file shutil2.py +@brief a better shutil.copytree replacement + +$LicenseInfo:firstyear=2007&license=mit$ + +Copyright (c) 2007, Linden Research, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +$/LicenseInfo$ +''' + +# +# shutil2.py +# Taken from http://www.scons.org/wiki/AccumulateBuilder +# the stock copytree sucks because it insists that the +# target dir not exist +# + +import os.path +import shutil + +def copytree(src, dest, symlinks=False): + """My own copyTree which does not fail if the directory exists. + + Recursively copy a directory tree using copy2(). + + If the optional symlinks flag is true, symbolic links in the + source tree result in symbolic links in the destination tree; if + it is false, the contents of the files pointed to by symbolic + links are copied. + + Behavior is meant to be identical to GNU 'cp -R'. + """ + def copyItems(src, dest, symlinks=False): + """Function that does all the work. + + It is necessary to handle the two 'cp' cases: + - destination does exist + - destination does not exist + + See 'cp -R' documentation for more details + """ + for item in os.listdir(src): + srcPath = os.path.join(src, item) + if os.path.isdir(srcPath): + srcBasename = os.path.basename(srcPath) + destDirPath = os.path.join(dest, srcBasename) + if not os.path.exists(destDirPath): + os.makedirs(destDirPath) + copyItems(srcPath, destDirPath) + elif os.path.islink(item) and symlinks: + linkto = os.readlink(item) + os.symlink(linkto, dest) + else: + shutil.copy2(srcPath, dest) + + # case 'cp -R src/ dest/' where dest/ already exists + if os.path.exists(dest): + destPath = os.path.join(dest, os.path.basename(src)) + if not os.path.exists(destPath): + os.makedirs(destPath) + # case 'cp -R src/ dest/' where dest/ does not exist + else: + os.makedirs(dest) + destPath = dest + # actually copy the files + copyItems(src, destPath) |