From c5eb808059aa07f48761524a715e80a23d902d09 Mon Sep 17 00:00:00 2001
From: Cezary Tarnowski <cezary.tarnowski@tomtom.com>
Date: Fri, 9 Dec 2011 12:08:50 +0100
Subject: [PATCH 01/11] Adding support for height as expression for building
 symbolizer

---
 include/mapnik/attribute_collector.hpp   |  6 ++++++
 include/mapnik/polygon_symbolizer.hpp    | 10 +++++-----
 src/agg/process_building_symbolizer.cpp  |  9 ++++++++-
 src/cairo_renderer.cpp                   |  8 +++++++-
 src/grid/process_building_symbolizer.cpp |  9 ++++++++-
 src/load_map.cpp                         |  5 ++---
 6 files changed, 36 insertions(+), 11 deletions(-)

diff --git a/include/mapnik/attribute_collector.hpp b/include/mapnik/attribute_collector.hpp
index b9b62a89c..70e1a5e8d 100644
--- a/include/mapnik/attribute_collector.hpp
+++ b/include/mapnik/attribute_collector.hpp
@@ -213,6 +213,12 @@ struct symbolizer_attributes : public boost::static_visitor<>
 
     void operator () (building_symbolizer const& sym)
     {
+    	expression_ptr const& height_expr = sym.height();
+		if (height_expr)
+		{
+			expression_attributes f_attr(names_);
+			boost::apply_visitor(f_attr,*height_expr);
+		}
         collect_metawriter(sym);
     }
     // TODO - support remaining syms
diff --git a/include/mapnik/polygon_symbolizer.hpp b/include/mapnik/polygon_symbolizer.hpp
index 809ceced3..a4791eed3 100644
--- a/include/mapnik/polygon_symbolizer.hpp
+++ b/include/mapnik/polygon_symbolizer.hpp
@@ -26,6 +26,7 @@
 // mapnik
 #include <mapnik/color.hpp>
 #include <mapnik/symbolizer.hpp>
+#include <mapnik/filter_factory.hpp>
 
 namespace mapnik 
 {
@@ -79,11 +80,10 @@ struct MAPNIK_DECL building_symbolizer : public symbolizer_base
     explicit building_symbolizer() 
         : symbolizer_base(),
         fill_(color(128,128,128)),
-        height_(0.0),
         opacity_(1.0)
         {}
        
-    building_symbolizer(color const& fill,double height)
+    building_symbolizer(color const& fill, expression_ptr height)
         : symbolizer_base(),
         fill_(fill),
         height_(height),
@@ -97,11 +97,11 @@ struct MAPNIK_DECL building_symbolizer : public symbolizer_base
     {
         fill_ = fill;
     }
-    double height() const
+    expression_ptr height() const
     {
         return height_;
     }
-    void set_height(double height) 
+    void set_height(expression_ptr height)
     {
         height_=height;
     }
@@ -115,7 +115,7 @@ struct MAPNIK_DECL building_symbolizer : public symbolizer_base
     }
 private:
     color fill_;
-    double height_;
+    expression_ptr height_;
     double opacity_;
 };  
 }
diff --git a/src/agg/process_building_symbolizer.cpp b/src/agg/process_building_symbolizer.cpp
index a9b8b0dbd..4546b0d7d 100644
--- a/src/agg/process_building_symbolizer.cpp
+++ b/src/agg/process_building_symbolizer.cpp
@@ -25,6 +25,7 @@
 #include <mapnik/agg_renderer.hpp>
 #include <mapnik/agg_rasterizer.hpp>
 #include <mapnik/segment.hpp>
+#include <mapnik/expression_evaluator.hpp>
 
 // boost
 #include <boost/scoped_ptr.hpp>
@@ -66,7 +67,13 @@ void agg_renderer<T>::process(building_symbolizer const& sym,
     ras_ptr->reset();
     ras_ptr->gamma(agg::gamma_linear());
     
-    double height = sym.height() * scale_factor_;
+    double height = 0.0;
+    expression_ptr height_expr = sym.height();
+    if (height_expr)
+    {
+    	value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr);
+    	height = result.to_double() * scale_factor_;
+    }
     
     for (unsigned i=0;i<feature.num_geometries();++i)
     {
diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp
index f47d78e7e..6e2f86fbb 100644
--- a/src/cairo_renderer.cpp
+++ b/src/cairo_renderer.cpp
@@ -779,7 +779,13 @@ void cairo_renderer_base::process(building_symbolizer const& sym,
     cairo_context context(context_);
 
     color const& fill = sym.get_fill();
-    double height = 0.7071 * sym.height(); // height in meters
+    double height = 0.0;
+	expression_ptr height_expr = sym.height();
+	if (height_expr)
+	{
+		value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr);
+		height = 0.7071 * result.to_double();
+	}
 
     for (unsigned i = 0; i < feature.num_geometries(); ++i)
     {
diff --git a/src/grid/process_building_symbolizer.cpp b/src/grid/process_building_symbolizer.cpp
index 27c156a27..dcbb3665e 100644
--- a/src/grid/process_building_symbolizer.cpp
+++ b/src/grid/process_building_symbolizer.cpp
@@ -28,6 +28,7 @@
 #include <mapnik/grid/grid_pixel.hpp>
 #include <mapnik/grid/grid.hpp>
 #include <mapnik/segment.hpp>
+#include <mapnik/expression_evaluator.hpp>
 
 // boost
 #include <boost/scoped_ptr.hpp>
@@ -59,7 +60,13 @@ void grid_renderer<T>::process(building_symbolizer const& sym,
 
     ras_ptr->reset();
 
-    double height = sym.height() * scale_factor_;
+    double height = 0.0;
+    expression_ptr height_expr = sym.height();
+    if (height_expr)
+    {
+        value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr);
+        height = result.to_double() * scale_factor_;
+    }
     
     for (unsigned i=0;i<feature.num_geometries();++i)
     {
diff --git a/src/load_map.cpp b/src/load_map.cpp
index 49913ef2b..15a5a5ee5 100644
--- a/src/load_map.cpp
+++ b/src/load_map.cpp
@@ -1915,9 +1915,8 @@ void map_parser::parse_building_symbolizer( rule & rule, ptree const & sym )
         optional<double> opacity = get_opt_attr<double>(sym, "fill-opacity");
         if (opacity) building_sym.set_opacity(*opacity);
         // height
-        // TODO - expression
-        optional<double> height = get_opt_attr<double>(sym, "height");
-        if (height) building_sym.set_height(*height);
+        optional<std::string> height = get_opt_attr<std::string>(sym, "height");
+        if (height) building_sym.set_height(parse_expression(*height, "utf8"));
 
         parse_metawriter_in_symbolizer(building_sym, sym);
         rule.append(building_sym);

From 143efad7cd61744e369f94ef717a7958558c27e8 Mon Sep 17 00:00:00 2001
From: Dane Springmeyer <dane@dbsgeo.com>
Date: Mon, 12 Dec 2011 15:55:33 -0800
Subject: [PATCH 02/11] csv plugin: allow values with leading zeros to stay as
 strings - closes #993 - refs https://github.com/mapbox/tilemill/issues/1007

---
 plugins/input/csv/csv_datasource.cpp | 69 ++++++++++++++++------------
 tests/python_tests/csv_test.py       | 19 ++++++++
 2 files changed, 58 insertions(+), 30 deletions(-)

diff --git a/plugins/input/csv/csv_datasource.cpp b/plugins/input/csv/csv_datasource.cpp
index 6280d16f4..1d44b90c2 100644
--- a/plugins/input/csv/csv_datasource.cpp
+++ b/plugins/input/csv/csv_datasource.cpp
@@ -489,10 +489,12 @@ void csv_datasource::parse_csv(T& stream,
                             std::string::const_iterator str_beg = value.begin();
                             std::string::const_iterator str_end = value.end();
                             bool r = qi::phrase_parse(str_beg,str_end,
-                                                      (
-                                                          qi::lit("POINT") >> '(' >> double_[ref(x) = _1] >>  double_[ref(y) = _1] >> ')'
-                                                          ),
-                                                      ascii::space);
+                                      (
+                                          qi::lit("POINT") >> '('
+                                              >> double_[ref(x) = _1]
+                                              >>  double_[ref(y) = _1] >> ')'
+                                      ),
+                                      ascii::space);
 
                             if (r && (str_beg == str_end))
                             {
@@ -615,28 +617,27 @@ void csv_datasource::parse_csv(T& stream,
                     }
                 }
 
-                // add all values as attributes
-                // here we detect numbers and treat everything else as pure strings
-                // this is intentional since boolean and null types are not common in csv editors
-                if (value.empty())
-                {
-                    UnicodeString ustr = tr.transcode(value.c_str());
-                    boost::put(*feature,fld_name,ustr);
-                    if (feature_count == 1)
-                    {
-                        desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
-                    }
-                }
-                // only true strings are this long
-                else if (value_length > 20)
-                {
-                    UnicodeString ustr = tr.transcode(value.c_str());
-                    boost::put(*feature,fld_name,ustr);
-                    if (feature_count == 1)
-                    {
-                        desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
-                    }
+                // now, add all values as attributes
+                /* First we detect likely strings, then try parsing likely numbers,
+                   finally falling back to string type
+                   * We intentionally do not try to detect boolean or null types
+                     since they are not common in csv
+                   * Likely strings are either empty values, very long values
+                     or value with leading zeros like 001 (which are not safe
+                     to assume are numbers)
+                */
 
+                bool has_dot = value.find(".") != std::string::npos;
+                if (value.empty() ||
+                   (value_length > 20) ||
+                   (value_length > 1 && !has_dot && value[0] == '0'))
+                {
+                    UnicodeString ustr = tr.transcode(value.c_str());
+                    boost::put(*feature,fld_name,ustr);
+                    if (feature_count == 1)
+                    {
+                        desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
+                    }
                 }
                 else if ((value[0] >= '0' && value[0] <= '9') || value[0] == '-')
                 {
@@ -646,12 +647,14 @@ void csv_datasource::parse_csv(T& stream,
                     bool r = qi::phrase_parse(str_beg,str_end,qi::double_,ascii::space,float_val);
                     if (r && (str_beg == str_end))
                     {
-                        if (value.find(".") != std::string::npos)
+                        if (has_dot)
                         {
                             boost::put(*feature,fld_name,float_val);
                             if (feature_count == 1)
                             {
-                                desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::Double));
+                                desc_.add_descriptor(
+                                    mapnik::attribute_descriptor(
+                                        fld_name,mapnik::Double));
                             }
                         }
                         else
@@ -660,7 +663,9 @@ void csv_datasource::parse_csv(T& stream,
                             boost::put(*feature,fld_name,val);
                             if (feature_count == 1)
                             {
-                                desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::Integer));
+                                desc_.add_descriptor(
+                                    mapnik::attribute_descriptor(
+                                        fld_name,mapnik::Integer));
                             }
                         }
                     }
@@ -671,7 +676,9 @@ void csv_datasource::parse_csv(T& stream,
                         boost::put(*feature,fld_name,ustr);
                         if (feature_count == 1)
                         {
-                            desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
+                            desc_.add_descriptor(
+                                mapnik::attribute_descriptor(
+                                    fld_name,mapnik::String));
                         }
                     }
                 }
@@ -682,7 +689,9 @@ void csv_datasource::parse_csv(T& stream,
                     boost::put(*feature,fld_name,ustr);
                     if (feature_count == 1)
                     {
-                        desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String));
+                        desc_.add_descriptor(
+                            mapnik::attribute_descriptor(
+                                fld_name,mapnik::String));
                     }
                 }
             }
diff --git a/tests/python_tests/csv_test.py b/tests/python_tests/csv_test.py
index f84442ebb..66df0564e 100644
--- a/tests/python_tests/csv_test.py
+++ b/tests/python_tests/csv_test.py
@@ -227,6 +227,25 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names():
         query.add_property_name('bogus')
         fs = ds.features(query)
 
+    def test_that_leading_zeros_mean_strings(**kwargs):
+        ds = get_csv_ds('leading_zeros.csv')
+        eq_(len(ds.fields()),3)
+        eq_(ds.fields(),['x','y','fips'])
+        eq_(ds.field_types(),['int','int','str'])
+        fs = ds.featureset()
+        feat = fs.next()
+        eq_(feat['x'],0)
+        eq_(feat['y'],0)
+        eq_(feat['fips'],'001')
+        feat = fs.next()
+        eq_(feat['x'],0)
+        eq_(feat['y'],0)
+        eq_(feat['fips'],'003')
+        feat = fs.next()
+        eq_(feat['x'],0)
+        eq_(feat['y'],0)
+        eq_(feat['fips'],'005')
+
 if __name__ == "__main__":
     setup()
     [eval(run)(visual=True) for run in dir() if 'test_' in run]

From 7ea7838f21d14eda0e72043cae3274ec2b0cec9d Mon Sep 17 00:00:00 2001
From: Dane Springmeyer <dane@dbsgeo.com>
Date: Mon, 12 Dec 2011 16:00:53 -0800
Subject: [PATCH 03/11] add new csv test

---
 tests/data/csv/leading_zeros.csv | 4 ++++
 1 file changed, 4 insertions(+)
 create mode 100644 tests/data/csv/leading_zeros.csv

diff --git a/tests/data/csv/leading_zeros.csv b/tests/data/csv/leading_zeros.csv
new file mode 100644
index 000000000..f0d8615dc
--- /dev/null
+++ b/tests/data/csv/leading_zeros.csv
@@ -0,0 +1,4 @@
+x,y,fips
+0,0,001
+0,0,003
+0,0,005

From e3d9bc2c6eff3445ebd85d39eb60396e3a21c750 Mon Sep 17 00:00:00 2001
From: Dane Springmeyer <dane@dbsgeo.com>
Date: Mon, 12 Dec 2011 16:02:12 -0800
Subject: [PATCH 04/11] add readme to svg test dir

---
 tests/data/svg/README.md | 6 ++++++
 1 file changed, 6 insertions(+)
 create mode 100644 tests/data/svg/README.md

diff --git a/tests/data/svg/README.md b/tests/data/svg/README.md
new file mode 100644
index 000000000..328d72ae9
--- /dev/null
+++ b/tests/data/svg/README.md
@@ -0,0 +1,6 @@
+Other good sources of svg for tests include:
+
+ * http://intertwingly.net/svg/
+ * http://www.w3.org/Graphics/SVG/Test/20110816/
+ * http://croczilla.com/bits_and_pieces/svg/samples/
+ * http://www.w3schools.com/svg/svg_examples.asp
\ No newline at end of file

From 79af8fdbc958b905fcd39d16a701f1d89c085d9b Mon Sep 17 00:00:00 2001
From: Cezary Tarnowski <cezary.tarnowski@tomtom.com>
Date: Tue, 13 Dec 2011 15:28:18 +0100
Subject: [PATCH 05/11] refactoring following comment on pull request

---
 include/mapnik/attribute_collector.hpp  | 12 ++++++------
 src/agg/process_building_symbolizer.cpp |  4 ++--
 src/cairo_renderer.cpp                  | 12 ++++++------
 src/save_map.cpp                        |  7 +++----
 4 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/include/mapnik/attribute_collector.hpp b/include/mapnik/attribute_collector.hpp
index 70e1a5e8d..e256a6c9e 100644
--- a/include/mapnik/attribute_collector.hpp
+++ b/include/mapnik/attribute_collector.hpp
@@ -213,12 +213,12 @@ struct symbolizer_attributes : public boost::static_visitor<>
 
     void operator () (building_symbolizer const& sym)
     {
-    	expression_ptr const& height_expr = sym.height();
-		if (height_expr)
-		{
-			expression_attributes f_attr(names_);
-			boost::apply_visitor(f_attr,*height_expr);
-		}
+        expression_ptr const& height_expr = sym.height();
+        if (height_expr)
+        {
+            expression_attributes f_attr(names_);
+            boost::apply_visitor(f_attr,*height_expr);
+        }
         collect_metawriter(sym);
     }
     // TODO - support remaining syms
diff --git a/src/agg/process_building_symbolizer.cpp b/src/agg/process_building_symbolizer.cpp
index 4546b0d7d..0a5b573a7 100644
--- a/src/agg/process_building_symbolizer.cpp
+++ b/src/agg/process_building_symbolizer.cpp
@@ -71,8 +71,8 @@ void agg_renderer<T>::process(building_symbolizer const& sym,
     expression_ptr height_expr = sym.height();
     if (height_expr)
     {
-    	value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr);
-    	height = result.to_double() * scale_factor_;
+        value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr);
+        height = result.to_double() * scale_factor_;
     }
     
     for (unsigned i=0;i<feature.num_geometries();++i)
diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp
index 6e2f86fbb..f0baeef3d 100644
--- a/src/cairo_renderer.cpp
+++ b/src/cairo_renderer.cpp
@@ -780,12 +780,12 @@ void cairo_renderer_base::process(building_symbolizer const& sym,
 
     color const& fill = sym.get_fill();
     double height = 0.0;
-	expression_ptr height_expr = sym.height();
-	if (height_expr)
-	{
-		value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr);
-		height = 0.7071 * result.to_double();
-	}
+    expression_ptr height_expr = sym.height();
+    if (height_expr)
+    {
+        value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr);
+        height = 0.7071 * result.to_double();
+    }
 
     for (unsigned i = 0; i < feature.num_geometries(); ++i)
     {
diff --git a/src/save_map.cpp b/src/save_map.cpp
index 63edbfce8..63f1b84ff 100644
--- a/src/save_map.cpp
+++ b/src/save_map.cpp
@@ -241,10 +241,9 @@ public:
         {
             set_attr( sym_node, "fill-opacity", sym.get_opacity() );
         }
-        if ( sym.height() != dfl.height() || explicit_defaults_ )
-        {
-            set_attr( sym_node, "height", sym.height() );
-        }
+
+        set_attr( sym_node, "height", to_expression_string(*sym.height()) );
+
         add_metawriter_attributes(sym_node, sym);
     }
 

From fbe8829791d0311cb8a030de3e1124bb510dbd2c Mon Sep 17 00:00:00 2001
From: Cezary Tarnowski <cezary.tarnowski@tomtom.com>
Date: Tue, 13 Dec 2011 15:40:47 +0100
Subject: [PATCH 06/11] Changing the gamma for better visual effect

---
 src/agg/process_polygon_symbolizer.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/agg/process_polygon_symbolizer.cpp b/src/agg/process_polygon_symbolizer.cpp
index c376d9544..a3c3f9d1d 100644
--- a/src/agg/process_polygon_symbolizer.cpp
+++ b/src/agg/process_polygon_symbolizer.cpp
@@ -62,7 +62,7 @@ void agg_renderer<T>::process(polygon_symbolizer const& sym,
     renderer ren(renb);
 
     ras_ptr->reset();
-    ras_ptr->gamma(agg::gamma_linear(0.0, sym.get_gamma()));
+    ras_ptr->gamma(agg::gamma_power(sym.get_gamma()));
     metawriter_with_properties writer = sym.get_metawriter();
     for (unsigned i=0;i<feature.num_geometries();++i)
     {

From c8a71cb07c519b11379ec34899165f0908e69b32 Mon Sep 17 00:00:00 2001
From: Dane Springmeyer <dane@dbsgeo.com>
Date: Tue, 13 Dec 2011 11:17:44 -0800
Subject: [PATCH 07/11] python: also include uninstall target for deprecated
 module name

---
 bindings/python/build.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/bindings/python/build.py b/bindings/python/build.py
index 5a3c4af98..2c4846cc3 100644
--- a/bindings/python/build.py
+++ b/bindings/python/build.py
@@ -41,6 +41,7 @@ def is_py3():
 
 prefix = env['PREFIX']
 target_path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik')
+target_path_deprecated = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2')
 
 libraries = ['mapnik','png']
 
@@ -152,8 +153,7 @@ if 'install' in COMMAND_LINE_TARGETS:
     init_module = env.Install(target_path, init_files)
     env.Alias(target='install', source=init_module)
     # install mapnik2 module which redirects to mapnik and issues DeprecatedWarning
-    path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2')
-    init_mapnik2 = env.Install(path, 'mapnik2/__init__.py')
+    init_mapnik2 = env.Install(target_path_deprecated, 'mapnik2/__init__.py')
     env.Alias(target='install', source=init_mapnik2)
       
 # fix perms and install the custom generated 'paths.py' 
@@ -204,4 +204,5 @@ if 'uninstall' not in COMMAND_LINE_TARGETS:
 
 
 env['create_uninstall_target'](env, target_path)
+env['create_uninstall_target'](env, target_path_deprecated)
     

From 9ac6e4b12ee805df9e6c34e5c912f50ef2de4424 Mon Sep 17 00:00:00 2001
From: Dane Springmeyer <dane@dbsgeo.com>
Date: Tue, 13 Dec 2011 13:52:11 -0800
Subject: [PATCH 08/11] tests: no need to test sqlite through ogr anymore -
 native impl is robust and has its own tests now

---
 tests/data/good_maps/sqlite.xml | 14 ++------------
 1 file changed, 2 insertions(+), 12 deletions(-)

diff --git a/tests/data/good_maps/sqlite.xml b/tests/data/good_maps/sqlite.xml
index dac315cc0..a8270c32e 100644
--- a/tests/data/good_maps/sqlite.xml
+++ b/tests/data/good_maps/sqlite.xml
@@ -7,25 +7,15 @@
         </Rule>
     </Style>
 
-    <!-- layer created by ogr like: ogr2ogr -t_srs EPSG:4326 -f SQLite ../sqlite/world.sqlite world_merc.shp -->
-    <!-- here we read with the ogr plugin -->
-    <Layer name="world_borders1" srs="+init=epsg:4326">
-        <StyleName>world_borders_style1</StyleName>
-        <Datasource>
-            <Parameter name="type">ogr</Parameter>
-            <Parameter name="file">../sqlite/world.sqlite</Parameter>
-            <Parameter name="layer">world_merc</Parameter>
-        </Datasource>
-    </Layer>
-
     <Style name="world_borders_style2">
         <Rule>
             <PolygonSymbolizer fill="yellow" gamma="0.5"/>
         </Rule>
     </Style>
 
-    <!-- here we read with native sqlite plugin -->
+    <!-- layer created by ogr like: ogr2ogr -t_srs EPSG:4326 -f SQLite ../sqlite/world.sqlite world_merc.shp -->
     <Layer name="world_borders2" srs="+init=epsg:4326">
+        <StyleName>world_borders_style1</StyleName>
         <StyleName>world_borders_style2</StyleName>
         <Datasource>
             <Parameter name="type">sqlite</Parameter>

From 53dd1be72ad89345056a12144fa1dcc030a95315 Mon Sep 17 00:00:00 2001
From: Dane Springmeyer <dane@dbsgeo.com>
Date: Tue, 13 Dec 2011 17:02:00 -0800
Subject: [PATCH 09/11] python 2.5 compatibility

---
 tests/run_tests.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/run_tests.py b/tests/run_tests.py
index f1f9c222d..a4be7190d 100755
--- a/tests/run_tests.py
+++ b/tests/run_tests.py
@@ -12,7 +12,7 @@ def usage():
 def main():
     try:
         opts, args = getopt.getopt(sys.argv[1:], "hvqp:", ["help", "prefix="])
-    except getopt.GetoptError as err:
+    except getopt.GetoptError,err:
         print(str(err))
         usage()
         sys.exit(2)

From 61453b38426d3695e4577df8bbf6a41176bd8c8c Mon Sep 17 00:00:00 2001
From: Dane Springmeyer <dane@dbsgeo.com>
Date: Tue, 13 Dec 2011 17:51:40 -0800
Subject: [PATCH 10/11] removed unused file remaining from old automake system

---
 bindings/python/mapnik/paths.py.in | 3 ---
 1 file changed, 3 deletions(-)
 delete mode 100644 bindings/python/mapnik/paths.py.in

diff --git a/bindings/python/mapnik/paths.py.in b/bindings/python/mapnik/paths.py.in
deleted file mode 100644
index 0100d6a83..000000000
--- a/bindings/python/mapnik/paths.py.in
+++ /dev/null
@@ -1,3 +0,0 @@
-mapniklibpath = '@PACKAGE_LIB_DIR@'
-inputpluginspath = mapniklibpath + '/input'
-fontscollectionpath = '@SYSTEM_FONTS_DIR@/truetype/ttf-dejavu'

From b45c0322b6b65d4d7d0d8c644af0f5baee6861f3 Mon Sep 17 00:00:00 2001
From: Dane Springmeyer <dane@dbsgeo.com>
Date: Tue, 13 Dec 2011 17:53:31 -0800
Subject: [PATCH 11/11] serialize relative path to fonts/plugins in python
 paths.py and re-assemble absolute path dynamically at load time to provide
 greatest portability

---
 bindings/python/build.py | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/bindings/python/build.py b/bindings/python/build.py
index 2c4846cc3..f65ff69f1 100644
--- a/bindings/python/build.py
+++ b/bindings/python/build.py
@@ -43,7 +43,8 @@ prefix = env['PREFIX']
 target_path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik')
 target_path_deprecated = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2')
 
-libraries = ['mapnik','png']
+libraries = ['mapnik']
+libraries.append('png')
 
 if env['JPEG']:
     libraries.append('jpeg')
@@ -122,22 +123,24 @@ else:
 paths = '''
 """Configuration paths of Mapnik fonts and input plugins (auto-generated by SCons)."""
 
-import os
+from os.path import normpath,join,dirname
 
 mapniklibpath = '%s'
+mapniklibpath = normpath(join(dirname(__file__),mapniklibpath))
 '''
 
-paths += "inputpluginspath = os.path.normpath(mapniklibpath + '/input')\n"
+paths += "inputpluginspath = join(mapniklibpath,'input')\n"
 
 if env['SYSTEM_FONTS']:
-    paths += "fontscollectionpath = os.path.normpath('%s')" % env['SYSTEM_FONTS']
+    paths += "fontscollectionpath = normpath('%s')\n" % env['SYSTEM_FONTS']
 else:
-    paths += "fontscollectionpath = os.path.normpath(mapniklibpath + '/fonts')"
+    paths += "fontscollectionpath = join(mapniklibpath,'fonts')\n"
 
+paths += "__all__ = [mapniklibpath,inputpluginspath,fontscollectionpath]\n"
 
 if not os.path.exists('mapnik'):
     os.mkdir('mapnik')
-file('mapnik/paths.py','w').write(paths % (env['MAPNIK_LIB_DIR']))
+file('mapnik/paths.py','w').write(paths % (os.path.relpath(env['MAPNIK_LIB_DIR'],target_path)))
 
 # force open perms temporarily so that `sudo scons install`
 # does not later break simple non-install non-sudo rebuild