diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c
index 43eae8c49a6fc9baaefd092afe689f745230e9c1..070b32557a72d99dd89db4d4827e3eedd596d0b6 100644
--- a/source/blender/python/BPY_menus.c
+++ b/source/blender/python/BPY_menus.c
@@ -63,7 +63,29 @@
 
 #include <errno.h>
 
-#define BPYMENU_DATAFILE ".Bpymenus"
+#define BPYMENU_DATAFILE "Bpymenus"
+
+/* BPyMenuTable holds all registered pymenus, as linked lists for each menu
+ * where they can appear (see PYMENUHOOKS enum in BPY_menus.h).
+*/
+BPyMenu *BPyMenuTable[PYMENU_TOTAL];
+
+/* we can't be sure if BLI_gethome() returned a path
+ * with '.blender' appended or not, so: */
+static char *bpymenu_gethome()
+{
+	static char homedir[FILE_MAXDIR];
+	char *s;
+
+	if (homedir[0] != '\0') return homedir;
+
+	s = BLI_gethome();
+
+	if (strstr(s, ".blender")) PyOS_snprintf(homedir, FILE_MAXDIR, s);
+	else BLI_make_file_string ("/", homedir, s, ".blender/");
+
+	return homedir;
+}
 
 static int bpymenu_group_atoi (char *str)
 {
@@ -282,7 +304,7 @@ static int bpymenu_CreateFromFile (void)
 		BPyMenuTable[group] = NULL;
 
 	/* let's try to open the file with bpymenu data */
-	BLI_make_file_string ("/", line, BLI_gethome(),"/.blender/"BPYMENU_DATAFILE);
+	BLI_make_file_string ("/", line, bpymenu_gethome(), BPYMENU_DATAFILE);
 
 	fp = fopen(line, "rb");
 
@@ -369,7 +391,7 @@ static void bpymenu_WriteDataFile(void)
 	char fname[FILE_MAXDIR+FILE_MAXFILE];
 	int i;
 
-	BLI_make_file_string("/", fname, BLI_gethome(), ".blender/"BPYMENU_DATAFILE);
+	BLI_make_file_string("/", fname, bpymenu_gethome(), BPYMENU_DATAFILE);
 
 	fp = fopen(fname, "w");
 	if (!fp) {
@@ -595,7 +617,7 @@ static int bpymenu_GetStatMTime(char *name, int is_file, time_t* mtime)
 
 /* BPyMenu_Init:
  * import the bpython menus data to Blender, either from:
- * - the BPYMENU_DATAFILE file (~/.Bpymenus) or
+ * - the BPYMENU_DATAFILE file (~/Bpymenus) or
  * - the scripts dir(s), case newer than the datafile (then update the file).
  * then fill the bpymenu table with this data.
  * if param usedir != 0, then the data is recreated from the dir(s) anyway.
@@ -615,7 +637,7 @@ int BPyMenu_Init(int usedir)
 
 	if (U.pythondir[0] == '\0') upydir = NULL;
 
-	BLI_make_file_string ("/", dirname, BLI_gethome(), ".blender/scripts/");
+	BLI_make_file_string ("/", dirname, bpymenu_gethome(), "scripts/");
 
 	res1 = bpymenu_GetStatMTime(dirname, 0, &tdir1);
 
@@ -652,7 +674,7 @@ int BPyMenu_Init(int usedir)
 	printf("\nRegistering scripts in Blender menus ...\n\n");
 
 	if (!usedir) { /* if we're not forced to use the dir */
-		BLI_make_file_string("/", fname, BLI_gethome(),".blender/"BPYMENU_DATAFILE);
+		BLI_make_file_string("/", fname, bpymenu_gethome(), BPYMENU_DATAFILE);
 		resf = bpymenu_GetStatMTime(fname, 1, &tfile);
 		if (resf < 0) tfile = 0;
 	}
diff --git a/source/blender/python/BPY_menus.h b/source/blender/python/BPY_menus.h
index ffeee746b8a032901ceb315f799b9c5355541c9b..682aa929f862c90a040c2c480d2aa0c5d9f55a06 100644
--- a/source/blender/python/BPY_menus.h
+++ b/source/blender/python/BPY_menus.h
@@ -88,7 +88,7 @@ typedef enum {
 /* BPyMenuTable holds all registered pymenus, as linked lists for each menu
  * where they can appear (see PYMENUHOOKS enum above).
 */
-BPyMenu *BPyMenuTable[PYMENU_TOTAL];
+extern BPyMenu *BPyMenuTable[]; /* defined in BPY_menus.c */
 
 /* public functions: */
 int BPyMenu_Init(int usedir);
diff --git a/source/blender/python/api2_2x/Bone.c b/source/blender/python/api2_2x/Bone.c
index c0dade51140be095da2973aeae2020316d5d4325..94ce51cf275883d5e3c558c6eaefaa74b85f088e 100644
--- a/source/blender/python/api2_2x/Bone.c
+++ b/source/blender/python/api2_2x/Bone.c
@@ -455,14 +455,20 @@ PyObject *Bone_setRoll(BPy_Bone *self, PyObject *args)
 static PyObject *Bone_setHead(BPy_Bone *self, PyObject *args)
 {
 	float f1,f2,f3;
+	int status;
 
 	if (!self->bone) (EXPP_ReturnPyObjError (PyExc_RuntimeError,
 													"couldn't get attribute from a NULL bone"));
-		
-	if (!PyArg_ParseTuple(args, "fff", &f1,&f2,&f3))
+
+	if (PyObject_Length (args) == 3)
+		status = PyArg_ParseTuple (args, "fff", &f1, &f2, &f3);
+	else
+		status = PyArg_ParseTuple (args, "(fff)", &f1, &f2, &f3);
+
+	if (!status)
 		return (EXPP_ReturnPyObjError (PyExc_AttributeError,
-						"expected 3 float arguments"));
-	
+						"expected 3 (or a list of 3) float arguments"));
+
 	self->bone->head[0] = f1;
 	self->bone->head[1] = f2;
 	self->bone->head[2] = f3;
@@ -475,14 +481,20 @@ static PyObject *Bone_setHead(BPy_Bone *self, PyObject *args)
 static PyObject *Bone_setTail(BPy_Bone *self, PyObject *args)
 {
 	float f1,f2,f3;
+	int status;
 
 	if (!self->bone) (EXPP_ReturnPyObjError (PyExc_RuntimeError,
 													"couldn't get attribute from a NULL bone"));
-		
-	if (!PyArg_ParseTuple(args, "fff", &f1,&f2,&f3))
+
+	if (PyObject_Length (args) == 3)
+		status = PyArg_ParseTuple (args, "fff", &f1, &f2, &f3);
+	else
+		status = PyArg_ParseTuple (args, "(fff)", &f1, &f2, &f3);
+
+	if (!status)
 		return (EXPP_ReturnPyObjError (PyExc_AttributeError,
-						"expected 3 float arguments"));
-	
+						"expected 3 (or a list of 3) float arguments"));
+
 	self->bone->tail[0] = f1;
 	self->bone->tail[1] = f2;
 	self->bone->tail[2] = f3;
@@ -495,14 +507,20 @@ static PyObject *Bone_setTail(BPy_Bone *self, PyObject *args)
 static PyObject *Bone_setLoc(BPy_Bone *self, PyObject *args)
 {
 	float f1,f2,f3;
+	int status;
 
 	if (!self->bone) (EXPP_ReturnPyObjError (PyExc_RuntimeError,
 													"couldn't get attribute from a NULL bone"));
-		
-	if (!PyArg_ParseTuple(args, "fff", &f1,&f2,&f3))
+
+	if (PyObject_Length (args) == 3)
+		status = PyArg_ParseTuple (args, "fff", &f1, &f2, &f3);
+	else
+		status = PyArg_ParseTuple (args, "(fff)", &f1, &f2, &f3);
+
+	if (!status)
 		return (EXPP_ReturnPyObjError (PyExc_AttributeError,
-						"expected 3 float arguments"));
-	
+						"expected 3 (or a list of 3) float arguments"));
+
 	self->bone->loc[0] = f1;
 	self->bone->loc[1] = f2;
 	self->bone->loc[2] = f3;
@@ -515,14 +533,20 @@ static PyObject *Bone_setLoc(BPy_Bone *self, PyObject *args)
 static PyObject *Bone_setSize(BPy_Bone *self, PyObject *args)
 {
 	float f1,f2,f3;
+	int status;
 
 	if (!self->bone) (EXPP_ReturnPyObjError (PyExc_RuntimeError,
 													"couldn't get attribute from a NULL bone"));
-		
-	if (!PyArg_ParseTuple(args, "fff", &f1,&f2,&f3))
+
+	if (PyObject_Length (args) == 3)
+		status = PyArg_ParseTuple (args, "fff", &f1, &f2, &f3);
+	else
+		status = PyArg_ParseTuple (args, "(fff)", &f1, &f2, &f3);
+
+	if (!status)
 		return (EXPP_ReturnPyObjError (PyExc_AttributeError,
-						"expected 3 float arguments"));
-	
+						"expected 3 (or a list of 3) float arguments"));
+
 	self->bone->size[0] = f1;
 	self->bone->size[1] = f2;
 	self->bone->size[2] = f3;
@@ -535,14 +559,20 @@ static PyObject *Bone_setSize(BPy_Bone *self, PyObject *args)
 static PyObject *Bone_setQuat(BPy_Bone *self, PyObject *args)
 {
 	float f1,f2,f3,f4;
+	int status;
 
 	if (!self->bone) (EXPP_ReturnPyObjError (PyExc_RuntimeError,
 													"couldn't get attribute from a NULL bone"));
-		
-	if (!PyArg_ParseTuple(args, "ffff", &f1,&f2,&f3,&f4))
+
+	if (PyObject_Length (args) == 4)
+		status = PyArg_ParseTuple (args, "ffff", &f1, &f2, &f3, &f4);
+	else
+		status = PyArg_ParseTuple (args, "(ffff)", &f1, &f2, &f3, &f4);
+
+	if (!status)
 		return (EXPP_ReturnPyObjError (PyExc_AttributeError,
-						"expected 4 float arguments"));
-	
+						"expected 4 (or a list of 4) float arguments"));
+
 	self->bone->quat[0] = f1;
 	self->bone->quat[1] = f2;
 	self->bone->quat[2] = f3;
@@ -552,7 +582,6 @@ static PyObject *Bone_setQuat(BPy_Bone *self, PyObject *args)
 	return Py_None;
 }
 
-
 /*****************************************************************************/
 /* Function:		Bone_dealloc																								 */
 /* Description: This is a callback function for the BPy_Bone type. It is		 */
@@ -707,7 +736,7 @@ int Bone_CheckPyObject (PyObject *py_obj)
 /*****************************************************************************/
 struct Bone* Bone_FromPyObject (PyObject *py_obj)
 {
-	BPy_Bone		* blen_obj;
+	BPy_Bone * blen_obj;
 
 	blen_obj = (BPy_Bone*)py_obj;
 	return (blen_obj->bone);
diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c
index 90ea1924309e83afb940be1e9fe2b7700f617854..38e8e25f6ae0b776809f239c6a5f3f2f5ef2b845 100644
--- a/source/blender/python/api2_2x/Object.c
+++ b/source/blender/python/api2_2x/Object.c
@@ -101,6 +101,7 @@ static PyObject *Object_getMaterials (BPy_Object *self);
 static PyObject *Object_getMatrix (BPy_Object *self);
 static PyObject *Object_getName (BPy_Object *self);
 static PyObject *Object_getParent (BPy_Object *self);
+static PyObject *Object_getSize (BPy_Object *self, PyObject *args);
 static PyObject *Object_getTracked (BPy_Object *self);
 static PyObject *Object_getType (BPy_Object *self);
 static PyObject *Object_getBoundBox (BPy_Object *self);
@@ -116,6 +117,7 @@ static PyObject *Object_setIpo (BPy_Object *self, PyObject *args);
 static PyObject *Object_setLocation (BPy_Object *self, PyObject *args);
 static PyObject *Object_setMaterials (BPy_Object *self, PyObject *args);
 static PyObject *Object_setName (BPy_Object *self, PyObject *args);
+static PyObject *Object_setSize (BPy_Object *self, PyObject *args);
 static PyObject *Object_shareFrom (BPy_Object *self, PyObject *args);
 
 /*****************************************************************************/
@@ -154,6 +156,8 @@ hierarchy (faster)"},
 	"Returns the name of the object"},
   {"getParent", (PyCFunction)Object_getParent, METH_NOARGS,
 	"Returns the object's parent object"},
+  {"getSize", (PyCFunction)Object_getSize, METH_VARARGS,
+	"Returns the object's size (x, y, z)"},
   {"getTracked", (PyCFunction)Object_getTracked, METH_NOARGS,
 	"Returns the object's tracked object"},
   {"getType", (PyCFunction)Object_getType, METH_NOARGS,
@@ -175,7 +179,7 @@ fase:\n\t0: update scene hierarchy automatically\n\t\
 don't update scene hierarchy (faster). In this case, you must\n\t\
 explicitely update the Scene hierarchy."},
   {"materialUsage", (PyCFunction)Object_materialUsage, METH_VARARGS,
-	"Determines the way the material is used and returs status.\n\
+	"Determines the way the material is used and returns status.\n\
 Possible arguments (provide as strings):\n\
 \tData:   Materials assigned to the object's data are shown. (default)\n\
 \tObject: Materials assigned to the object are shown."},
@@ -198,6 +202,9 @@ triple."},
 objects."},
   {"setName", (PyCFunction)Object_setName, METH_VARARGS,
 	"Sets the name of the object"},
+  {"setSize", (PyCFunction)Object_setSize, METH_VARARGS,
+	"Set the object's size. The first argument must be a vector\n\
+triple."},
   {"shareFrom", (PyCFunction)Object_shareFrom, METH_VARARGS,
 	"Link data of self with object specified in the argument. This\n\
 works only if self and the object specified are of the same type."},
@@ -814,6 +821,19 @@ static PyObject *Object_getParent (BPy_Object *self)
 			"couldn't get Object.parent attribute"));
 }
 
+static PyObject *Object_getSize (BPy_Object *self, PyObject *args)
+{
+	PyObject *attr = Py_BuildValue ("fff",
+									self->object->size[0],
+									self->object->size[1],
+									self->object->size[2]);
+
+	if (attr) return (attr);
+
+	return (PythonReturnErrorObject (PyExc_RuntimeError,
+			"couldn't get Object.size attributes"));
+}
+
 static PyObject *Object_getTracked (BPy_Object *self)
 {
 	PyObject	*attr;
@@ -1302,6 +1322,30 @@ static PyObject *Object_setName (BPy_Object *self, PyObject *args)
 	return (Py_None);
 }
 
+static PyObject *Object_setSize (BPy_Object *self, PyObject *args)
+{
+	float	sizex;
+	float	sizey;
+	float	sizez;
+	int		status;
+
+	if (PyObject_Length (args) == 3)
+		status = PyArg_ParseTuple (args, "fff", &sizex, &sizey, &sizez);
+	else
+		status = PyArg_ParseTuple (args, "(fff)", &sizex, &sizey, &sizez);
+
+	if (!status)
+		return EXPP_ReturnPyObjError (PyExc_AttributeError,
+				"expected list argument of 3 floats");
+
+	self->object->size[0] = sizex;
+	self->object->size[1] = sizey;
+	self->object->size[2] = sizez;
+
+	Py_INCREF (Py_None);
+	return (Py_None);
+}
+
 static PyObject *Object_shareFrom (BPy_Object *self, PyObject *args)
 {
 	BPy_Object		* object;
diff --git a/source/blender/python/api2_2x/doc/Blender.py b/source/blender/python/api2_2x/doc/Blender.py
index c72c9eb0331585a9aeec779109478815d6fd61ec..cc03ef5b3f1906c968ea68143f75c13286b90836 100644
--- a/source/blender/python/api2_2x/doc/Blender.py
+++ b/source/blender/python/api2_2x/doc/Blender.py
@@ -33,6 +33,7 @@ The Blender Python API Reference
   - L{Metaball}
   - L{NMesh}
   - L{Object}
+  - L{Registry}
   - L{Scene}
   - L{Text}
   - L{Texture}
diff --git a/source/blender/python/api2_2x/doc/Registry.py b/source/blender/python/api2_2x/doc/Registry.py
new file mode 100644
index 0000000000000000000000000000000000000000..c7e981a69d080fd723b7551a3c52cb5515d30379
--- /dev/null
+++ b/source/blender/python/api2_2x/doc/Registry.py
@@ -0,0 +1,95 @@
+# Blender.Registry module
+
+"""
+The Blender.Registry submodule.
+
+Registry
+========
+
+This module provides a way to create, retrieve and edit B{persistent data} in
+Blender. When a script runs in Blender, it has its own private global
+dictionary, which is deleted when the script finishes. This is done to avoid
+problems with name clashes and garbage collecting.  But the result is that
+data created by a script isn't kept after it leaves, for itself or others to
+access later: the data isn't persistent. The Registry module was created to
+give script authors a way around this limitation. In Python terms, the
+Registry holds a dictionary of dictionaries.
+
+You should use it to save Python objects only, not BPython (Blender Python)
+objects -- but you can save BPython object names, since those are strings.
+Also, if you need to save a considerable amount of data, please save to a
+file instead. There's no need to keep huge blocks of memory around when they
+can simply be read from a file.
+
+Two uses for this module:
+
+a) Save configuration data from your script's gui (button values) so that the
+next time the user runs your script, the changes will still be there. Later we
+can make Blender save the Registry so that its data won't be lost after users
+quit the program. And also add an option to save as a Text that can be kept in
+a .blend file, letting users keep script data there.
+
+b) Save data from a script that another one will need to access later.
+
+Example::
+
+  import Blender
+  from Blender import Registry
+
+  # first declare your global variables:
+  myvar1 = 0
+  myvar2 = 3.2
+  mystr = "hello"
+  #
+  # then check if they are already at the Registry (saved on a
+  # previous execution of your script):
+  dict = Registry.GetKey('MyScript')
+  if dict: # if found, get the values saved there
+    myvar1 = dict['myvar1']
+    myvar2 = dict['myvar2']
+    mystr = dict['mystr']
+  #
+  # let's create a function to update the Registry when we need to:
+  def update_Registry():
+    d = {}
+    d['myvar1'] = myvar1
+    d['myvar2'] = myvar2
+    d['mystr'] = mystr
+    Blender.Registry.SetKey('MyScript', d)
+  # ...
+  # here goes the main part of your script ...
+  # ...
+  # at the end, before exiting, we use our helper function:
+  update_Registry()
+  # note1: better not update the Registry when the user cancels the script
+  # note2: most scripts shouldn't need to register more than one key.
+"""
+
+def Keys ():
+  """
+  Get all keys currently in the Registry's dictionary.
+  """
+
+def GetKey (key):
+  """
+  Get key 'key' from the Registry.
+  @type key: string
+  @param key: a key from the Registry dictionary.
+  @return: the dictionary called 'key'.
+  """
+
+def SetKey (key, dict):
+  """
+  Store a new entry in the Registry.
+  @type key: string
+  @param key: the name of the new entry, tipically your script's name.
+  @type dict: dictionary
+  @param dict: a dict with all data you want to save in the Registry.
+  """
+
+def RemoveKey (key):
+  """
+  Remove the dictionary with key 'key' from the Registry.
+  @type key: string
+  @param key: the name of an existing Registry key.
+  """