Merge remote-tracking branch 'github/pr/19'
diff --git a/doc/build/changelog.rst b/doc/build/changelog.rst
index 9cf8089..0f164d0 100644
--- a/doc/build/changelog.rst
+++ b/doc/build/changelog.rst
@@ -6,6 +6,17 @@
 ===
 
 .. changelog::
+    :version: 1.0.4
+    :released:
+
+    .. change::
+        :tags: feature
+        :pullreq: bitbucket:16
+
+      Added new method :meth:`.Template.list_defs`.   Pull request courtesy
+      Jonathan Vanasco.
+
+.. changelog::
     :version: 1.0.3
     :released: Tue Oct 27 2015
 
diff --git a/mako/__init__.py b/mako/__init__.py
index 74526ec..850f2a6 100644
--- a/mako/__init__.py
+++ b/mako/__init__.py
@@ -5,4 +5,4 @@
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
 
 
-__version__ = '1.0.3'
+__version__ = '1.0.4'
diff --git a/mako/template.py b/mako/template.py
index afb679a..6b34514 100644
--- a/mako/template.py
+++ b/mako/template.py
@@ -475,6 +475,14 @@
 
         return DefTemplate(self, getattr(self.module, "render_%s" % name))
 
+    def list_defs(self):
+        """return a list of defs in the template.
+
+        .. versionadded:: 1.0.4
+
+        """
+        return [i[7:] for i in dir(self.module) if i[:7] == 'render_']
+
     def _get_def_callable(self, name):
         return getattr(self.module, "render_%s" % name)
 
diff --git a/test/test_def.py b/test/test_def.py
index 8b32561..19142c8 100644
--- a/test/test_def.py
+++ b/test/test_def.py
@@ -123,6 +123,41 @@
                         filters=flatten_result,
                         template_args={'q': 5, 'zq': 'test'})
 
+    def test_def_operations(self):
+        """test get/list/has def"""
+
+        template = Template("""
+
+            this is the body
+
+            <%def name="a()">
+                this is a
+            </%def>
+
+            <%def name="b(x, y)">
+                this is b, ${x} ${y}
+            </%def>
+
+        """)
+
+        assert template.get_def("a")
+        assert template.get_def("b")
+        assert_raises(AttributeError,
+                      template.get_def,
+                      ("c")
+                      )
+
+        assert template.has_def("a")
+        assert template.has_def("b")
+        assert not template.has_def("c")
+
+        defs = template.list_defs()
+        assert "a" in defs
+        assert "b" in defs
+        assert "body" in defs
+        assert "c" not in defs
+
+
 class ScopeTest(TemplateTest):
     """test scoping rules.  The key is, enclosing
     scope always takes precedence over contextual scope."""