summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Bell <josh@lindenlab.com>2008-02-15 18:47:45 +0000
committerJosh Bell <josh@lindenlab.com>2008-02-15 18:47:45 +0000
commit8eea75dc3f4138a0b216e8d662089d2c930d5d45 (patch)
tree91dfcb8e0e0400a737d30d3aad88e63633aa2742
parent383f92e54369a47a96afb3467c680f870df700a1 (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.py25
-rw-r--r--indra/lib/python/indra/base/lluuid.py21
-rw-r--r--indra/lib/python/indra/ipc/mysql_pool.py5
-rw-r--r--indra/lib/python/indra/util/named_query.py48
-rw-r--r--indra/lib/python/indra/util/shutil2.py84
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)