diff --git a/CadQuery/Libs/cadquery-lib/.travis.yml b/CadQuery/Libs/cadquery-lib/.travis.yml
index 08bce03..e4e38b0 100644
--- a/CadQuery/Libs/cadquery-lib/.travis.yml
+++ b/CadQuery/Libs/cadquery-lib/.travis.yml
@@ -1,27 +1,30 @@
----
 language: python
-
 before_install:
-  - sudo add-apt-repository -y ppa:freecad-maintainers/freecad-daily
-  - sudo apt-get update -qq
+- sudo add-apt-repository -y ppa:freecad-maintainers/freecad-daily
+- sudo apt-get update -qq
 install:
-  - sudo apt-get install -y freecad freecad-doc
-  - gcc --version
-  - g++ --version
-  - python ./setup.py install
-  - pip install coverage
-  - pip install coveralls
-  - pip install Sphinx==1.3.2
-  - pip install travis-sphinx
-
+- sudo apt-get install -y freecad freecad-doc
+- gcc --version
+- g++ --version
+- python ./setup.py install
+- pip install coverage
+- pip install coveralls
+- pip install Sphinx==1.3.2
+- pip install travis-sphinx
 script:
-  - coverage run --source=cadquery ./runtests.py
-  - travis-sphinx --nowarn --source=doc build
-
+- coverage run --source=cadquery ./runtests.py
+- travis-sphinx --nowarn --source=doc build
 after_success:
-  - coveralls
-  - travis-sphinx deploy
-  
+- coveralls
+- travis-sphinx deploy
 branches:
   except:
-    - pythonocc
+  - pythonocc
+  - 2_0_branch
+deploy:
+  provider: pypi
+  user: dcowden
+  password:
+    secure: aP02wBbry1j3hYG/w++siF1lk26teuRQlPAx1c+ec8fxUw+bECa2HbPQHcIvSXB5N6nc6P3L9LjHt9ktm+Dn6FLJu3qWYNGAZx9PTn24ug0iAmB+JyNrsET3nK6WUKR1XpBqvjKgdpukd1Hknh2FSzYoyUvFWH9/CovITCFN3jo=
+  on:
+    tags: true
\ No newline at end of file
diff --git a/CadQuery/Libs/cadquery-lib/MANIFEST b/CadQuery/Libs/cadquery-lib/MANIFEST
index 69b0aae..ce5c215 100644
--- a/CadQuery/Libs/cadquery-lib/MANIFEST
+++ b/CadQuery/Libs/cadquery-lib/MANIFEST
@@ -1,4 +1,5 @@
 README.txt
+README.md
 setup.cfg
 setup.py
 cadquery\cq.py
diff --git a/CadQuery/Libs/cadquery-lib/MANIFEST.in b/CadQuery/Libs/cadquery-lib/MANIFEST.in
index e69de29..bb3ec5f 100644
--- a/CadQuery/Libs/cadquery-lib/MANIFEST.in
+++ b/CadQuery/Libs/cadquery-lib/MANIFEST.in
@@ -0,0 +1 @@
+include README.md
diff --git a/CadQuery/Libs/cadquery-lib/cadquery/cq.py b/CadQuery/Libs/cadquery-lib/cadquery/cq.py
index 59a1180..7293813 100644
--- a/CadQuery/Libs/cadquery-lib/cadquery/cq.py
+++ b/CadQuery/Libs/cadquery-lib/cadquery/cq.py
@@ -742,6 +742,19 @@ class CQ(object):
         return self.newObject([o.rotate(axisStartPoint, axisEndPoint, angleDegrees)
                                for o in self.objects])
 
+    def mirror(self, mirrorPlane="XY", basePointVector=(0, 0, 0)):
+	"""
+	Mirror a single CQ object. This operation is the same as in the FreeCAD PartWB's mirroring
+
+	:param mirrorPlane: the plane to mirror about
+	:type mirrorPlane: string, one of "XY", "YX", "XZ", "ZX", "YZ", "ZY" the planes
+	:param basePointVector: the base point to mirror about
+	:type basePointVector: tuple
+	"""
+	newS = self.newObject([self.objects[0].mirror(mirrorPlane, basePointVector)])
+	return newS.first()
+
+
     def translate(self, vec):
         """
         Returns a copy of all of the items on the stack moved by the specified translation vector.
diff --git a/CadQuery/Libs/cadquery-lib/cadquery/cqgi.py b/CadQuery/Libs/cadquery-lib/cadquery/cqgi.py
index 92fd860..01701db 100644
--- a/CadQuery/Libs/cadquery-lib/cadquery/cqgi.py
+++ b/CadQuery/Libs/cadquery-lib/cadquery/cqgi.py
@@ -44,9 +44,11 @@ class CQModel(object):
         self.ast_tree = ast.parse(script_source, CQSCRIPT)
         self.script_source = script_source
         self._find_vars()
+
         # TODO: pick up other scirpt metadata:
         # describe
         # pick up validation methods
+	self._find_descriptions()
 
     def _find_vars(self):
         """
@@ -65,6 +67,9 @@ class CQModel(object):
             if isinstance(node, ast.Assign):
                 assignment_finder.visit_Assign(node)
 
+    def _find_descriptions(self):
+        description_finder = ParameterDescriptionFinder(self.metadata)
+        description_finder.visit(self.ast_tree)
 
     def validate(self, params):
         """
@@ -75,11 +80,13 @@ class CQModel(object):
         """
         raise NotImplementedError("not yet implemented")
 
-    def build(self, build_parameters=None):
+    def build(self, build_parameters=None, build_options=None):
         """
         Executes the script, using the optional parameters to override those in the model
         :param build_parameters: a dictionary of variables. The variables must be
-        assignable to the underlying variable type.
+        assignable to the underlying variable type. These variables override default values in the script
+        :param build_options: build options for how to build the model. Build options include things like
+        timeouts, tesselation tolerances, etc
         :raises: Nothing. If there is an exception, it will be on the exception property of the result.
         This is the interface so that we can return other information on the result, such as the build time
         :return: a BuildResult object, which includes the status of the result, and either
@@ -95,10 +102,14 @@ class CQModel(object):
             self.set_param_values(build_parameters)
             collector = ScriptCallback()
             env = EnvironmentBuilder().with_real_builtins().with_cadquery_objects() \
-                .add_entry("build_object", collector.build_object).build()
+                .add_entry("build_object", collector.build_object) \
+                .add_entry("debug", collector.debug) \
+                .add_entry("describe_parameter",collector.describe_parameter) \
+                .build()
 
             c = compile(self.ast_tree, CQSCRIPT, 'exec')
             exec (c, env)
+            result.set_debug(collector.debugObjects )
             if collector.has_results():
                 result.set_success_result(collector.outputObjects)
             else:
@@ -139,6 +150,7 @@ class BuildResult(object):
     def __init__(self):
         self.buildTime = None
         self.results = []
+        self.debugObjects = []
         self.first_result = None
         self.success = False
         self.exception = None
@@ -147,6 +159,9 @@ class BuildResult(object):
         self.exception = ex
         self.success = False
 
+    def set_debug(self, debugObjects):
+        self.debugObjects = debugObjects
+
     def set_success_result(self, results):
         self.results = results
         self.first_result = self.results[0]
@@ -164,6 +179,11 @@ class ScriptMetadata(object):
     def add_script_parameter(self, p):
         self.parameters[p.name] = p
 
+    def add_parameter_description(self,name,description):
+        print 'Adding Parameter name=%s, desc=%s' % ( name, description )
+        p = self.parameters[name]
+        p.desc = description
+
 
 class ParameterType(object):
     pass
@@ -204,19 +224,15 @@ class InputParameter:
         self.varType = None
 
         #: help text describing the variable. Only available if the script used describe_parameter()
-        self.shortDesc = None
-
-
+        self.desc = None
 
         #: valid values for the variable. Only available if the script used describe_parameter()
         self.valid_values = []
 
-
-
         self.ast_node = None
 
     @staticmethod
-    def create(ast_node, var_name, var_type, default_value, valid_values=None, short_desc=None):
+    def create(ast_node, var_name, var_type, default_value, valid_values=None, desc=None):
 
         if valid_values is None:
             valid_values = []
@@ -225,10 +241,7 @@ class InputParameter:
         p.ast_node = ast_node
         p.default_value = default_value
         p.name = var_name
-        if short_desc is None:
-            p.shortDesc = var_name
-        else:
-            p.shortDesc = short_desc
+        p.desc = desc
         p.varType = var_type
         p.valid_values = valid_values
         return p
@@ -270,9 +283,9 @@ class ScriptCallback(object):
     the build_object() method is exposed to CQ scripts, to allow them
     to return objects to the execution environment
     """
-
     def __init__(self):
         self.outputObjects = []
+        self.debugObjects = []
 
     def build_object(self, shape):
         """
@@ -281,10 +294,15 @@ class ScriptCallback(object):
         """
         self.outputObjects.append(shape)
 
-    def describe_parameter(self,var, valid_values, short_desc):
+    def debug(self,obj,args={}):
         """
-        Not yet implemented: allows a script to document
-        extra metadata about the parameters
+        Debug print/output an object, with optional arguments.
+        """
+        self.debugObjects.append(DebugObject(obj,args))
+
+    def describe_parameter(self,var_data ):
+        """
+        Do Nothing-- we parsed the ast ahead of exection to get what we need.
         """
         pass
 
@@ -297,7 +315,15 @@ class ScriptCallback(object):
     def has_results(self):
         return len(self.outputObjects) > 0
 
-
+class DebugObject(object):
+    """
+    Represents a request to debug an object
+    Object is the type of object we want to debug
+    args are parameters for use during debuging ( for example, color, tranparency )
+    """
+    def __init__(self,object,args):
+        self.args = args
+        self.object = object
 
 class InvalidParameterError(Exception):
     """
@@ -371,6 +397,30 @@ class EnvironmentBuilder(object):
     def build(self):
         return self.env
 
+class ParameterDescriptionFinder(ast.NodeTransformer):
+    """
+    Visits a parse tree, looking for function calls to describe_parameter(var, description )
+    """
+    def __init__(self, cq_model):
+        self.cqModel = cq_model
+
+    def visit_Call(self,node):
+       """
+       Called when we see a function call. Is it describe_parameter?
+       """
+       try:
+            if node.func.id == 'describe_parameter':
+                #looks like we have a call to our function.
+                #first parameter is the variable,
+                #second is the description
+                varname = node.args[0].id
+		desc = node.args[1].s
+                self.cqModel.add_parameter_description(varname,desc)
+
+       except:
+            print "Unable to handle function call"
+            pass
+       return node
 
 class ConstantAssignmentFinder(ast.NodeTransformer):
     """
@@ -381,9 +431,6 @@ class ConstantAssignmentFinder(ast.NodeTransformer):
         self.cqModel = cq_model
 
     def handle_assignment(self, var_name, value_node):
-
-
-
         try:
 
             if type(value_node) == ast.Num:
diff --git a/CadQuery/Libs/cadquery-lib/cadquery/freecad_impl/shapes.py b/CadQuery/Libs/cadquery-lib/cadquery/freecad_impl/shapes.py
index 76af1c1..659d4d1 100644
--- a/CadQuery/Libs/cadquery-lib/cadquery/freecad_impl/shapes.py
+++ b/CadQuery/Libs/cadquery-lib/cadquery/freecad_impl/shapes.py
@@ -184,9 +184,23 @@ class Shape(object):
     def isValid(self):
         return self.wrapped.isValid()
 
-    def BoundingBox(self):
+    def BoundingBox(self, tolerance=0.1):
+        self.wrapped.tessellate(tolerance)
         return BoundBox(self.wrapped.BoundBox)
 
+    def mirror(self, mirrorPlane="XY", basePointVector=(0, 0, 0)):
+        if mirrorPlane == "XY" or mirrorPlane== "YX":
+            mirrorPlaneNormalVector = FreeCAD.Base.Vector(0, 0, 1)
+        elif mirrorPlane == "XZ" or mirrorPlane == "ZX":
+            mirrorPlaneNormalVector = FreeCAD.Base.Vector(0, 1, 0)
+        elif mirrorPlane == "YZ" or mirrorPlane == "ZY":
+            mirrorPlaneNormalVector = FreeCAD.Base.Vector(1, 0, 0)
+
+        if type(basePointVector) == tuple:
+            basePointVector = Vector(basePointVector)
+
+        return Shape.cast(self.wrapped.mirror(basePointVector.wrapped, mirrorPlaneNormalVector))
+
     def Center(self):
         # A Part.Shape object doesn't have the CenterOfMass function, but it's wrapped Solid(s) does
         if isinstance(self.wrapped, FreeCADPart.Shape):
@@ -223,8 +237,8 @@ class Shape(object):
 
         :param objects: a list of objects with mass
         """
-        total_mass = sum(o.wrapped.Mass for o in objects)
-        weighted_centers = [o.wrapped.CenterOfMass.multiply(o.wrapped.Mass) for o in objects]
+        total_mass = sum(Shape.computeMass(o) for o in objects)
+        weighted_centers = [o.wrapped.CenterOfMass.multiply(Shape.computeMass(o)) for o in objects]
 
         sum_wc = weighted_centers[0]
         for wc in weighted_centers[1:] :
@@ -232,6 +246,17 @@ class Shape(object):
 
         return Vector(sum_wc.multiply(1./total_mass))
 
+    @staticmethod
+    def computeMass(object):
+        """
+        Calculates the 'mass' of an object. in FreeCAD < 15, all objects had a mass.
+        in FreeCAD >=15, faces no longer have mass, but instead have area.
+        """
+        if object.wrapped.ShapeType == 'Face':
+          return object.wrapped.Area
+        else:
+          return object.wrapped.Mass
+
     @staticmethod
     def CombinedCenterOfBoundBox(objects):
         """
diff --git a/CadQuery/Libs/cadquery-lib/doc/cqgi.rst b/CadQuery/Libs/cadquery-lib/doc/cqgi.rst
index 6e47b91..310f7d2 100644
--- a/CadQuery/Libs/cadquery-lib/doc/cqgi.rst
+++ b/CadQuery/Libs/cadquery-lib/doc/cqgi.rst
@@ -32,10 +32,26 @@ CQGI compliant containers provide an execution environment for scripts. The envi
 
  * the cadquery library is automatically imported as 'cq'.
  * the :py:meth:`cadquery.cqgi.ScriptCallback.build_object()` method is defined that should be used to export a shape to the execution environment
+ * the :py:meth:`cadquery.cqgi.ScriptCallBack.debug()` method is defined, which can be used by scripts to debug model output during execution.
 
 Scripts must call build_output at least once. Invoking build_object more than once will send multiple objects to
 the container.  An error will occur if the script does not return an object using the build_object() method.
 
+This CQGI compliant script produces a cube with a circle on top, and displays a workplane as well as an intermediate circle as debug output::
+
+    base_cube = cq.Workplane('XY').rect(1.0,1.0).extrude(1.0)
+    top_of_cube_plane = base_cube.faces(">Z").workplane()
+    debug(top_of_cube_plane, { 'color': 'yellow', } )
+    debug(top_of_cube_plane.center, { 'color' : 'blue' } )
+
+    circle=top_of_cube_plane.circle(0.5)
+    debug(circle, { 'color': 'red' } )
+
+    build_object( circle.extrude(1.0) )
+
+Note that importing cadquery is not required. 
+At the end of this script, one object will be displayed, in addition to a workplane, a point, and a circle
+
 Future enhancements will include several other methods, used to provide more metadata for the execution environment:
   * :py:meth:`cadquery.cqgi.ScriptCallback.add_error()`, indicates an error with an input parameter
   * :py:meth:`cadquery.cqgi.ScriptCallback.describe_parameter()`, provides extra information about a parameter in the script,
@@ -54,10 +70,29 @@ run code like this::
 
 The :py:meth:`cadquery.cqgi.parse()` method returns a :py:class:`cadquery.cqgi.CQModel` object.
 
+The `metadata`p property of the object contains a `cadquery.cqgi.ScriptMetaData` object, which can be used to discover the
+user parameters available. This is useful if the execution environment would like to present a GUI to allow the user to change the 
+model parameters.  Typically, after collecting new values, the environment will supply them in the build() method.
+
+This code will return a dictionary of parameter values in the model text SCRIPT::
+     
+     parameters = cqgi.parse(SCRIPT).metadata.parameters
+
+The dictionary you get back is a map where key is the parameter name, and value is an InputParameter object, 
+which has a name, type, and default value. 
+
+The type is an object which extends ParameterType-- you can use this to determine what kind of widget to render ( checkbox for boolean, for example ).
+
+The parameter object also has a description, valid values, minimum, and maximum values, if the user has provided them using the
+describe_parameter() method.
+
+
+
 Calling :py:meth:`cadquery.cqgi.CQModel.build()` returns a :py:class:`cadquery.cqgi.BuildResult` object,
 ,which includes the script execution time, and a success flag.
 
-If the script was successful, the results property will include a list of results returned by the script.
+If the script was successful, the results property will include a list of results returned by the script,
+as well as any debug the script produced
 
 If the script failed, the exception property contains the exception object.
 
@@ -67,12 +102,16 @@ with new values::
     from cadquery import cqgi
 
     user_script = ...
-    build_result = cqgi.parse(user_script).build({ 'param': 2 } )
+    build_result = cqgi.parse(user_script).build(build_parameters={ 'param': 2 }, build_options={} )
 
 If a parameter called 'param' is defined in the model, it will be assigned the value 2 before the script runs.
 An error will occur if a value is provided that is not defined in the model, or if the value provided cannot
 be assigned to a variable with the given name.
 
+build_options is used to set server-side settings like timeouts, tesselation tolerances, and other details about
+how the model should be built.
+
+
 More about script variables
 -----------------------------
 
diff --git a/CadQuery/Libs/cadquery-lib/doc/examples.rst b/CadQuery/Libs/cadquery-lib/doc/examples.rst
index 0705da5..06c79aa 100644
--- a/CadQuery/Libs/cadquery-lib/doc/examples.rst
+++ b/CadQuery/Libs/cadquery-lib/doc/examples.rst
@@ -312,6 +312,64 @@ introduce horizontal and vertical lines, which make for slightly easier coding.
         * :py:meth:`Workplane`
         * :py:meth:`Workplane.extrude`
 
+Mirroring 3D Objects
+-----------------------------
+
+.. cq_plot::
+
+    result0 = (cadquery.Workplane("XY")
+               .moveTo(10,0)
+               .lineTo(5,0)
+               .threePointArc((3.9393,0.4393),(3.5,1.5))
+               .threePointArc((3.0607,2.5607),(2,3))
+               .lineTo(1.5,3)
+               .threePointArc((0.4393,3.4393),(0,4.5))
+               .lineTo(0,13.5)
+               .threePointArc((0.4393,14.5607),(1.5,15))
+               .lineTo(28,15)
+               .lineTo(28,13.5)
+               .lineTo(24,13.5)
+               .lineTo(24,11.5)
+               .lineTo(27,11.5)
+               .lineTo(27,10)
+               .lineTo(22,10)
+               .lineTo(22,13.2)
+               .lineTo(14.5,13.2)
+               .lineTo(14.5,10)
+               .lineTo(12.5,10 )
+               .lineTo(12.5,13.2)
+               .lineTo(5.5,13.2)
+               .lineTo(5.5,2)
+               .threePointArc((5.793,1.293),(6.5,1))
+               .lineTo(10,1)
+               .close())
+    result = result0.extrude(100)
+    
+    result = result.rotate((0, 0, 0),(1, 0, 0), 90)
+
+    result = result.translate(result.val().BoundingBox().center.multiply(-1))
+
+    mirXY_neg = result.mirror(mirrorPlane="XY", basePointVector=(0, 0, -30))
+    mirXY_pos = result.mirror(mirrorPlane="XY", basePointVector=(0, 0, 30))
+    mirZY_neg = result.mirror(mirrorPlane="ZY", basePointVector=(-30,0,0))
+    mirZY_pos = result.mirror(mirrorPlane="ZY", basePointVector=(30,0,0))
+
+    result = result.union(mirXY_neg).union(mirXY_pos).union(mirZY_neg).union(mirZY_pos) 
+    
+    build_object(result)
+
+.. topic:: Api References
+
+    .. hlist::
+        :columns: 2
+
+        * :py:meth:`Workplane.moveTo` 
+        * :py:meth:`Workplane.lineTo`
+        * :py:meth:`Workplane.threePointArc`
+        * :py:meth:`Workplane.extrude`        
+        * :py:meth:`Workplane.mirror`
+        * :py:meth:`Workplane.union`        
+        * :py:meth:`CQ.rotate`        
 
 Creating Workplanes on Faces
 -----------------------------
diff --git a/CadQuery/Libs/cadquery-lib/runtests.py b/CadQuery/Libs/cadquery-lib/runtests.py
index ad516ce..ee90ce4 100644
--- a/CadQuery/Libs/cadquery-lib/runtests.py
+++ b/CadQuery/Libs/cadquery-lib/runtests.py
@@ -8,11 +8,11 @@ import unittest
 #on py 2.7.x on win
 suite = unittest.TestSuite()
 
+suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestCQGI.TestCQGI))
 suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestCadObjects.TestCadObjects))
 suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestWorkplanes.TestWorkplanes))
 suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestCQSelectors.TestCQSelectors))
 suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestCadQuery.TestCadQuery))
 suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestExporters.TestExporters))
 suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestImporters.TestImporters))
-suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestCQGI.TestCQGI))
 unittest.TextTestRunner().run(suite)
diff --git a/CadQuery/Libs/cadquery-lib/setup.py b/CadQuery/Libs/cadquery-lib/setup.py
index e68a6e6..9a25b9e 100644
--- a/CadQuery/Libs/cadquery-lib/setup.py
+++ b/CadQuery/Libs/cadquery-lib/setup.py
@@ -11,12 +11,19 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-
+import os
 from setuptools import setup
 
+
+#if we are building in travis, use the build number as the sub-minor version
+version = '0.5-SNAPSHOT'
+if 'TRAVIS_TAG' in os.environ.keys():
+    version= os.environ['TRAVIS_TAG']
+ 
+
 setup(
     name='cadquery',
-    version='0.4.0',
+    version=version,
     url='https://github.com/dcowden/cadquery',
     license='Apache Public License 2.0',
     author='David Cowden',
diff --git a/CadQuery/Libs/cadquery-lib/tests/TestCQGI.py b/CadQuery/Libs/cadquery-lib/tests/TestCQGI.py
index 35d8906..7cc967f 100644
--- a/CadQuery/Libs/cadquery-lib/tests/TestCQGI.py
+++ b/CadQuery/Libs/cadquery-lib/tests/TestCQGI.py
@@ -23,6 +23,18 @@ TESTSCRIPT = textwrap.dedent(
     """
 )
 
+TEST_DEBUG_SCRIPT = textwrap.dedent(
+    """
+        height=2.0
+        width=3.0
+        (a,b) = (1.0,1.0)
+        foo="bar"
+        debug(foo, { "color": 'yellow' } )
+        result =  "%s|%s|%s|%s" % ( str(height) , str(width) , foo , str(a) )
+        build_object(result)
+        debug(height )
+    """
+)
 
 class TestCQGI(BaseTest):
     def test_parser(self):
@@ -31,6 +43,16 @@ class TestCQGI(BaseTest):
 
         self.assertEquals(set(metadata.parameters.keys()), {'height', 'width', 'a', 'b', 'foo'})
 
+    def test_build_with_debug(self):
+        model = cqgi.CQModel(TEST_DEBUG_SCRIPT)
+        result = model.build()
+        debugItems = result.debugObjects
+        self.assertTrue(len(debugItems) == 2)
+        self.assertTrue( debugItems[0].object == "bar" )
+        self.assertTrue( debugItems[0].args == { "color":'yellow' } )
+        self.assertTrue( debugItems[1].object == 2.0 )
+        self.assertTrue( debugItems[1].args == {} )
+
     def test_build_with_empty_params(self):
         model = cqgi.CQModel(TESTSCRIPT)
         result = model.build()
@@ -44,6 +66,30 @@ class TestCQGI(BaseTest):
         result = model.build({'height': 3.0})
         self.assertTrue(result.results[0] == "3.0|3.0|bar|1.0")
 
+    def test_describe_parameters(self):
+        script = textwrap.dedent(
+            """
+                a = 2.0
+                describe_parameter(a,'FirstLetter')
+            """
+        )
+        model = cqgi.CQModel(script)
+        a_param = model.metadata.parameters['a']
+        self.assertTrue(a_param.default_value == 2.0)
+        self.assertTrue(a_param.desc == 'FirstLetter')
+        self.assertTrue(a_param.varType == cqgi.NumberParameterType )
+
+    def test_describe_parameter_invalid_doesnt_fail_script(self):
+        script = textwrap.dedent(
+            """
+                a = 2.0
+                describe_parameter(a, 2 - 1 )
+            """
+        )
+        model = cqgi.CQModel(script)
+        a_param = model.metadata.parameters['a']
+        self.assertTrue(a_param.name == 'a' )
+     
     def test_build_with_exception(self):
         badscript = textwrap.dedent(
             """
diff --git a/CadQuery/Libs/cadquery-lib/tests/TestCadQuery.py b/CadQuery/Libs/cadquery-lib/tests/TestCadQuery.py
index 01e7753..f8b9b2a 100644
--- a/CadQuery/Libs/cadquery-lib/tests/TestCadQuery.py
+++ b/CadQuery/Libs/cadquery-lib/tests/TestCadQuery.py
@@ -550,6 +550,43 @@ class TestCadQuery(BaseTest):
 
         self.assertEqual(10,currentS.faces().size())
 
+    def testBoundingBox(self):
+	"""
+	Tests the boudingbox center of a model
+	"""
+	result0 = (Workplane("XY")
+           	   .moveTo(10,0)
+                   .lineTo(5,0)
+                   .threePointArc((3.9393,0.4393),(3.5,1.5))
+                   .threePointArc((3.0607,2.5607),(2,3))
+                   .lineTo(1.5,3)
+                   .threePointArc((0.4393,3.4393),(0,4.5))
+                   .lineTo(0,13.5)
+                   .threePointArc((0.4393,14.5607),(1.5,15))
+                   .lineTo(28,15)
+                   .lineTo(28,13.5)
+                   .lineTo(24,13.5)
+                   .lineTo(24,11.5)
+                   .lineTo(27,11.5)
+                   .lineTo(27,10)
+                   .lineTo(22,10)
+                   .lineTo(22,13.2)
+                   .lineTo(14.5,13.2)
+                   .lineTo(14.5,10)
+                   .lineTo(12.5,10 )
+                   .lineTo(12.5,13.2)
+                   .lineTo(5.5,13.2)
+                   .lineTo(5.5,2)
+                   .threePointArc((5.793,1.293),(6.5,1))
+                   .lineTo(10,1)
+                   .close())
+	result = result0.extrude(100)
+	bb_center = result.val().BoundingBox().center
+	self.saveModel(result)
+	self.assertAlmostEqual(14.0, bb_center.x, 3)
+	self.assertAlmostEqual(7.5, bb_center.y, 3)
+	self.assertAlmostEqual(50.0, bb_center.z, 3)
+
     def testCutThroughAll(self):
         """
             Tests a model that uses more than one workplane