diff --git a/CHANGELOG.md b/CHANGELOG.md
index 31c4ad432..3a3d55750 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@ For a complete change history, see the git log.
## Future
+- `[attr]` now returns false if attr is an empty string (#1665)
+
- Added 64 bit integer support in expressions and feature ids (#1661,#1662)
- Added support for DBF `Logical` type: #1614
diff --git a/bindings/python/mapnik_expression.cpp b/bindings/python/mapnik_expression.cpp
index 109b21e15..d3bd8b1dd 100644
--- a/bindings/python/mapnik_expression.cpp
+++ b/bindings/python/mapnik_expression.cpp
@@ -59,6 +59,11 @@ mapnik::value expression_evaluate_(mapnik::expr_node const& expr, mapnik::Featur
return boost::apply_visitor(mapnik::evaluate(f),expr);
}
+bool expression_evaluate_to_bool_(mapnik::expr_node const& expr, mapnik::Feature const& f)
+{
+ return boost::apply_visitor(mapnik::evaluate(f),expr).to_bool();
+}
+
// path expression
path_expression_ptr parse_path_(std::string const& path)
{
@@ -82,6 +87,7 @@ void export_expression()
"TODO"
"",no_init)
.def("evaluate", &expression_evaluate_)
+ .def("to_bool", &expression_evaluate_to_bool_)
.def("__str__",&expression_to_string_);
;
diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp
index cb4fa7d33..6cd0944a3 100644
--- a/include/mapnik/value.hpp
+++ b/include/mapnik/value.hpp
@@ -624,8 +624,7 @@ struct to_bool : public boost::static_visitor
value_bool operator() (value_unicode_string const& ustr) const
{
- boost::ignore_unused_variable_warning(ustr);
- return true;
+ return !ustr.isEmpty();
}
value_bool operator() (value_null const& val) const
diff --git a/tests/python_tests/filter_test.py b/tests/python_tests/filter_test.py
index 7fcbdccf0..cf3575d78 100644
--- a/tests/python_tests/filter_test.py
+++ b/tests/python_tests/filter_test.py
@@ -257,7 +257,7 @@ def test_expressions_with_null_equality():
expr = mapnik.Expression("[prop] is null")
eq_(expr.evaluate(f),eq[1])
-def test_expressions_with_null_equality():
+def test_expressions_with_null_equality2():
for eq in null_equality:
context = mapnik.Context()
f = mapnik.Feature(context,0)
@@ -275,5 +275,41 @@ def test_expressions_with_null_equality():
expr = mapnik.Expression("[prop] != null")
eq_(expr.evaluate(f),not eq[1])
+truthyness = [
+ [u'hello',True,unicode],
+ [u'',False,unicode],
+ [0,False,int],
+ [123,True,int],
+ [0.0,False,float],
+ [123.123,True,float],
+ [.1,True,float],
+ [False,False,int], # TODO - should become bool
+ [True,True,int], # TODO - should become bool
+ [None,False,None]
+]
+
+def test_expressions_for_thruthyness():
+ context = mapnik.Context()
+ for eq in truthyness:
+ f = mapnik.Feature(context,0)
+ f["prop"] = eq[0]
+ eq_(f["prop"],eq[0])
+ if eq[0] is None:
+ eq_(f["prop"] is None, True)
+ else:
+ eq_(isinstance(f['prop'],eq[2]),True,'%s is not an instance of %s' % (f['prop'],eq[2]))
+ expr = mapnik.Expression("[prop]")
+ eq_(expr.to_bool(f),eq[1])
+ expr = mapnik.Expression("not [prop]")
+ eq_(expr.to_bool(f),not eq[1])
+ # also test if feature does not have property at all
+ f2 = mapnik.Feature(context,1)
+ # no property existing will return value_null since
+ # https://github.com/mapnik/mapnik/commit/562fada9d0f680f59b2d9f396c95320a0d753479#include/mapnik/feature.hpp
+ eq_(f2["prop"] is None,True)
+ expr = mapnik.Expression("[prop]")
+ eq_(expr.evaluate(f2),None)
+ eq_(expr.to_bool(f2),False)
+
if __name__ == "__main__":
[eval(run)() for run in dir() if 'test_' in run]