prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Has compile_uri_template been removed?
  I can't see it in the code any more.
  
  
  </issue>
  <code>
  [start of falcon/routing/util.py]
  1 # Copyright 2013 by Rackspace Hosting, Inc.
  2 #
  3 # Licensed under the Apache License, Version 2.0 (the "License");
  4 # you may not use this file except in compliance with the License.
  5 # You may obtain a copy of the License at
  6 #
  7 #    http://www.apache.org/licenses/LICENSE-2.0
  8 #
  9 # Unless required by applicable law or agreed to in writing, software
  10 # distributed under the License is distributed on an "AS IS" BASIS,
  11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 # See the License for the specific language governing permissions and
  13 # limitations under the License.
  14 
  15 from falcon import HTTP_METHODS, responders
  16 from falcon.hooks import _wrap_with_hooks
  17 
  18 
  19 def create_http_method_map(resource, before, after):
  20     """Maps HTTP methods (e.g., 'GET', 'POST') to methods of a resource object.
  21 
  22     Args:
  23         resource: An object with *responder* methods, following the naming
  24             convention *on_\**, that correspond to each method the resource
  25             supports. For example, if a resource supports GET and POST, it
  26             should define ``on_get(self, req, resp)`` and
  27             ``on_post(self, req, resp)``.
  28         before: An action hook or ``list`` of hooks to be called before each
  29             *on_\** responder defined by the resource.
  30         after: An action hook or ``list`` of hooks to be called after each
  31             *on_\** responder defined by the resource.
  32 
  33     Returns:
  34         dict: A mapping of HTTP methods to responders.
  35 
  36     """
  37 
  38     method_map = {}
  39 
  40     for method in HTTP_METHODS:
  41         try:
  42             responder = getattr(resource, 'on_' + method.lower())
  43         except AttributeError:
  44             # resource does not implement this method
  45             pass
  46         else:
  47             # Usually expect a method, but any callable will do
  48             if callable(responder):
  49                 responder = _wrap_with_hooks(
  50                     before, after, responder, resource)
  51                 method_map[method] = responder
  52 
  53     # Attach a resource for unsupported HTTP methods
  54     allowed_methods = sorted(list(method_map.keys()))
  55 
  56     # NOTE(sebasmagri): We want the OPTIONS and 405 (Not Allowed) methods
  57     # responders to be wrapped on global hooks
  58     if 'OPTIONS' not in method_map:
  59         # OPTIONS itself is intentionally excluded from the Allow header
  60         responder = responders.create_default_options(
  61             allowed_methods)
  62         method_map['OPTIONS'] = _wrap_with_hooks(
  63             before, after, responder, resource)
  64         allowed_methods.append('OPTIONS')
  65 
  66     na_responder = responders.create_method_not_allowed(allowed_methods)
  67 
  68     for method in HTTP_METHODS:
  69         if method not in allowed_methods:
  70             method_map[method] = _wrap_with_hooks(
  71                 before, after, na_responder, resource)
  72 
  73     return method_map
  74
  [end of falcon/routing/util.py]
  [start of falcon/routing/__init__.py]
  1 # Copyright 2013 by Rackspace Hosting, Inc.
  2 #
  3 # Licensed under the Apache License, Version 2.0 (the "License");
  4 # you may not use this file except in compliance with the License.
  5 # You may obtain a copy of the License at
  6 #
  7 #    http://www.apache.org/licenses/LICENSE-2.0
  8 #
  9 # Unless required by applicable law or agreed to in writing, software
  10 # distributed under the License is distributed on an "AS IS" BASIS,
  11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 # See the License for the specific language governing permissions and
  13 # limitations under the License.
  14 
  15 from falcon.routing.compiled import CompiledRouter
  16 from falcon.routing.util import create_http_method_map  # NOQA
  17 
  18 
  19 DefaultRouter = CompiledRouter
  20
  [end of falcon/routing/__init__.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/falcon/routing/__init__.py b/falcon/routing/__init__.py
  --- a/falcon/routing/__init__.py
  +++ b/falcon/routing/__init__.py
  @@ -14,6 +14,7 @@
   
   from falcon.routing.compiled import CompiledRouter
   from falcon.routing.util import create_http_method_map  # NOQA
  +from falcon.routing.util import compile_uri_template  # NOQA
   
   
   DefaultRouter = CompiledRouter
  diff --git a/falcon/routing/util.py b/falcon/routing/util.py
  --- a/falcon/routing/util.py
  +++ b/falcon/routing/util.py
  @@ -12,10 +12,72 @@
   # See the License for the specific language governing permissions and
   # limitations under the License.
   
  +import re
  +
  +import six
  +
   from falcon import HTTP_METHODS, responders
   from falcon.hooks import _wrap_with_hooks
   
   
  +# NOTE(kgriffs): Published method; take care to avoid breaking changes.
  +def compile_uri_template(template):
  +    """Compile the given URI template string into a pattern matcher.
  +
  +    This function can be used to construct custom routing engines that
  +    iterate through a list of possible routes, attempting to match
  +    an incoming request against each route's compiled regular expression.
  +
  +    Each field is converted to a named group, so that when a match
  +    is found, the fields can be easily extracted using
  +    :py:meth:`re.MatchObject.groupdict`.
  +
  +    This function does not support the more flexible templating
  +    syntax used in the default router. Only simple paths with bracketed
  +    field expressions are recognized. For example::
  +
  +        /
  +        /books
  +        /books/{isbn}
  +        /books/{isbn}/characters
  +        /books/{isbn}/characters/{name}
  +
  +    Also, note that if the template contains a trailing slash character,
  +    it will be stripped in order to normalize the routing logic.
  +
  +    Args:
  +        template(str): The template to compile. Note that field names are
  +            restricted to ASCII a-z, A-Z, and the underscore character.
  +
  +    Returns:
  +        tuple: (template_field_names, template_regex)
  +    """
  +
  +    if not isinstance(template, six.string_types):
  +        raise TypeError('uri_template is not a string')
  +
  +    if not template.startswith('/'):
  +        raise ValueError("uri_template must start with '/'")
  +
  +    if '//' in template:
  +        raise ValueError("uri_template may not contain '//'")
  +
  +    if template != '/' and template.endswith('/'):
  +        template = template[:-1]
  +
  +    expression_pattern = r'{([a-zA-Z][a-zA-Z_]*)}'
  +
  +    # Get a list of field names
  +    fields = set(re.findall(expression_pattern, template))
  +
  +    # Convert Level 1 var patterns to equivalent named regex groups
  +    escaped = re.sub(r'[\.\(\)\[\]\?\*\+\^\|]', r'\\\g<0>', template)
  +    pattern = re.sub(expression_pattern, r'(?P<\1>[^/]+)', escaped)
  +    pattern = r'\A' + pattern + r'\Z'
  +
  +    return fields, re.compile(pattern, re.IGNORECASE)
  +
  +
   def create_http_method_map(resource, before, after):
       """Maps HTTP methods (e.g., 'GET', 'POST') to methods of a resource object.
  
verification_info: {"golden_diff": "diff --git a/falcon/routing/__init__.py b/falcon/routing/__init__.py\n--- a/falcon/routing/__init__.py\n+++ b/falcon/routing/__init__.py\n@@ -14,6 +14,7 @@\n \n from falcon.routing.compiled import CompiledRouter\n from falcon.routing.util import create_http_method_map  # NOQA\n+from falcon.routing.util import compile_uri_template  # NOQA\n \n \n DefaultRouter = CompiledRouter\ndiff --git a/falcon/routing/util.py b/falcon/routing/util.py\n--- a/falcon/routing/util.py\n+++ b/falcon/routing/util.py\n@@ -12,10 +12,72 @@\n # See the License for the specific language governing permissions and\n # limitations under the License.\n \n+import re\n+\n+import six\n+\n from falcon import HTTP_METHODS, responders\n from falcon.hooks import _wrap_with_hooks\n \n \n+# NOTE(kgriffs): Published method; take care to avoid breaking changes.\n+def compile_uri_template(template):\n+    \"\"\"Compile the given URI template string into a pattern matcher.\n+\n+    This function can be used to construct custom routing engines that\n+    iterate through a list of possible routes, attempting to match\n+    an incoming request against each route's compiled regular expression.\n+\n+    Each field is converted to a named group, so that when a match\n+    is found, the fields can be easily extracted using\n+    :py:meth:`re.MatchObject.groupdict`.\n+\n+    This function does not support the more flexible templating\n+    syntax used in the default router. Only simple paths with bracketed\n+    field expressions are recognized. For example::\n+\n+        /\n+        /books\n+        /books/{isbn}\n+        /books/{isbn}/characters\n+        /books/{isbn}/characters/{name}\n+\n+    Also, note that if the template contains a trailing slash character,\n+    it will be stripped in order to normalize the routing logic.\n+\n+    Args:\n+        template(str): The template to compile. Note that field names are\n+            restricted to ASCII a-z, A-Z, and the underscore character.\n+\n+    Returns:\n+        tuple: (template_field_names, template_regex)\n+    \"\"\"\n+\n+    if not isinstance(template, six.string_types):\n+        raise TypeError('uri_template is not a string')\n+\n+    if not template.startswith('/'):\n+        raise ValueError(\"uri_template must start with '/'\")\n+\n+    if '//' in template:\n+        raise ValueError(\"uri_template may not contain '//'\")\n+\n+    if template != '/' and template.endswith('/'):\n+        template = template[:-1]\n+\n+    expression_pattern = r'{([a-zA-Z][a-zA-Z_]*)}'\n+\n+    # Get a list of field names\n+    fields = set(re.findall(expression_pattern, template))\n+\n+    # Convert Level 1 var patterns to equivalent named regex groups\n+    escaped = re.sub(r'[\\.\\(\\)\\[\\]\\?\\*\\+\\^\\|]', r'\\\\\\g<0>', template)\n+    pattern = re.sub(expression_pattern, r'(?P<\\1>[^/]+)', escaped)\n+    pattern = r'\\A' + pattern + r'\\Z'\n+\n+    return fields, re.compile(pattern, re.IGNORECASE)\n+\n+\n def create_http_method_map(resource, before, after):\n     \"\"\"Maps HTTP methods (e.g., 'GET', 'POST') to methods of a resource object.\n", "issue": "Has compile_uri_template been removed?\nI can't see it in the code any more.\n\n", "before_files": [{"content": "# Copyright 2013 by Rackspace Hosting, Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom falcon import HTTP_METHODS, responders\nfrom falcon.hooks import _wrap_with_hooks\n\n\ndef create_http_method_map(resource, before, after):\n    \"\"\"Maps HTTP methods (e.g., 'GET', 'POST') to methods of a resource object.\n\n    Args:\n        resource: An object with *responder* methods, following the naming\n            convention *on_\\**, that correspond to each method the resource\n            supports. For example, if a resource supports GET and POST, it\n            should define ``on_get(self, req, resp)`` and\n            ``on_post(self, req, resp)``.\n        before: An action hook or ``list`` of hooks to be called before each\n            *on_\\** responder defined by the resource.\n        after: An action hook or ``list`` of hooks to be called after each\n            *on_\\** responder defined by the resource.\n\n    Returns:\n        dict: A mapping of HTTP methods to responders.\n\n    \"\"\"\n\n    method_map = {}\n\n    for method in HTTP_METHODS:\n        try:\n            responder = getattr(resource, 'on_' + method.lower())\n        except AttributeError:\n            # resource does not implement this method\n            pass\n        else:\n            # Usually expect a method, but any callable will do\n            if callable(responder):\n                responder = _wrap_with_hooks(\n                    before, after, responder, resource)\n                method_map[method] = responder\n\n    # Attach a resource for unsupported HTTP methods\n    allowed_methods = sorted(list(method_map.keys()))\n\n    # NOTE(sebasmagri): We want the OPTIONS and 405 (Not Allowed) methods\n    # responders to be wrapped on global hooks\n    if 'OPTIONS' not in method_map:\n        # OPTIONS itself is intentionally excluded from the Allow header\n        responder = responders.create_default_options(\n            allowed_methods)\n        method_map['OPTIONS'] = _wrap_with_hooks(\n            before, after, responder, resource)\n        allowed_methods.append('OPTIONS')\n\n    na_responder = responders.create_method_not_allowed(allowed_methods)\n\n    for method in HTTP_METHODS:\n        if method not in allowed_methods:\n            method_map[method] = _wrap_with_hooks(\n                before, after, na_responder, resource)\n\n    return method_map\n", "path": "falcon/routing/util.py"}, {"content": "# Copyright 2013 by Rackspace Hosting, Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom falcon.routing.compiled import CompiledRouter\nfrom falcon.routing.util import create_http_method_map  # NOQA\n\n\nDefaultRouter = CompiledRouter\n", "path": "falcon/routing/__init__.py"}]}