We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Refactor to drop dependency on decorator package
### Description

We have a few decorators defined in `ietf/utils/decorator.py` that use the "decorator" package. This provides the `@decorator` decorator and a `decorate` method. The built-in Python `functools.wraps()` method can fulfill the needs here without the additional dependency. As far as I can tell we're not making use of any of the features provided by the "decorator" package.

The `@decorator` mechanism also seems to interfere with Django's `@method_decorator`, which led to refactoring the `requires_api_key` decorator already.

### Code of Conduct

- [X] I agree to follow the [IETF's Code of Conduct](https://github.com/ietf-tools/.github/blob/main/CODE_OF_CONDUCT.md)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ietf/utils/decorators.py`
Content:
```
1 # Copyright The IETF Trust 2016-2020, All Rights Reserved
2 # -*- coding: utf-8 -*-
3 
4 
5 import datetime
6 
7 from decorator import decorator, decorate
8 from functools import wraps
9 
10 from django.conf import settings
11 from django.contrib.auth import login
12 from django.http import HttpResponse
13 from django.shortcuts import render
14 from django.utils import timezone
15 from django.utils.encoding import force_bytes
16 
17 import debug                            # pyflakes:ignore
18 
19 from ietf.utils.test_runner import set_coverage_checking
20 from ietf.person.models import Person, PersonalApiKey, PersonApiKeyEvent
21 from ietf.utils import log
22 
23 @decorator
24 def skip_coverage(f, *args, **kwargs):
25     if settings.TEST_CODE_COVERAGE_CHECKER:
26         set_coverage_checking(False)
27         result = f(*args, **kwargs)
28         set_coverage_checking(True)
29         return result
30     else:
31         return  f(*args, **kwargs)
32 
33 @decorator
34 def person_required(f, request, *args, **kwargs):
35     if not request.user.is_authenticated:
36         raise ValueError("The @person_required decorator should be called after @login_required.")
37     try:
38         request.user.person
39     except Person.DoesNotExist:
40         return render(request, 'registration/missing_person.html')
41     return  f(request, *args, **kwargs)
42 
43 
44 def require_api_key(f):
45     @wraps(f)
46     def _wrapper(request, *args, **kwargs):
47         def err(code, text):
48             return HttpResponse(text, status=code, content_type='text/plain')
49         # Check method and get hash
50         if request.method == 'POST':
51             hash = request.POST.get('apikey')
52         elif request.method == 'GET':
53             hash = request.GET.get('apikey')
54         else:
55             return err(405, "Method not allowed")
56         if not hash:
57             return err(400, "Missing apikey parameter")
58         # Check hash
59         key = PersonalApiKey.validate_key(force_bytes(hash))
60         if not key:
61             return err(403, "Invalid apikey")
62         # Check endpoint
63         urlpath = request.META.get('PATH_INFO')
64         if not (urlpath and urlpath == key.endpoint):
65             return err(400, "Apikey endpoint mismatch") 
66         # Check time since regular login
67         person = key.person
68         last_login = person.user.last_login
69         if not person.user.is_staff:
70             time_limit = (timezone.now() - datetime.timedelta(days=settings.UTILS_APIKEY_GUI_LOGIN_LIMIT_DAYS))
71             if last_login == None or last_login < time_limit:
72                 return err(400, "Too long since last regular login")
73         # Log in
74         login(request, person.user)
75         # restore the user.last_login field, so it reflects only gui logins
76         person.user.last_login = last_login
77         person.user.save()
78         # Update stats
79         key.count += 1
80         key.latest = timezone.now()
81         key.save()
82         PersonApiKeyEvent.objects.create(person=person, type='apikey_login', key=key, desc="Logged in with key ID %s, endpoint %s" % (key.id, key.endpoint))
83         # Execute decorated function
84         try:
85             ret = f(request, *args, **kwargs)
86         except AttributeError as e:
87             log.log("Bad API call: args: %s, kwargs: %s, exception: %s" % (args, kwargs, e))
88             return err(400, "Bad or missing parameters")
89         return ret
90     return _wrapper
91 
92 
93 def _memoize(func, self, *args, **kwargs):
94     '''Memoize wrapper for instance methods.  Use @lru_cache for functions.'''
95     if kwargs:  # frozenset is used to ensure hashability
96         key = args, frozenset(list(kwargs.items()))
97     else:
98         key = args
99     # instance method, set up cache if needed
100     if not hasattr(self, '_cache'):
101         self._cache = {}
102     if not func in self._cache:
103         self._cache[func] = {}            
104     #
105     cache = self._cache[func]
106     if key not in cache:
107         cache[key] = func(self, *args, **kwargs)
108     return cache[key]
109 def memoize(func):
110     if not hasattr(func, '__class__'):
111         raise NotImplementedError("Use @lru_cache instead of memoize() for functions.")
112     # For methods, we want the cache on the object, not on the class, in order
113     # to not having to think about cache bloat and content becoming stale, so
114     # we cannot set up the cache here.
115     return decorate(func, _memoize)
116 
117 
118 def ignore_view_kwargs(*args):
119     """Ignore the specified kwargs if they are present
120 
121     Usage: 
122       @ignore_view_kwargs("ignore_arg1", "ignore_arg2")
123       def my_view(request, good_arg):
124         ...
125 
126       This will allow my_view() to be used in url() paths that have zero, one, or both of
127       ignore_arg1 and ignore_arg2 captured. These will be ignored, while good_arg will still
128       be captured as usual.
129     """
130     kwargs_to_ignore = args
131 
132     def decorate(view):
133         @wraps(view)
134         def wrapped(*args, **kwargs):
135             for kwarg in kwargs_to_ignore:
136                 kwargs.pop(kwarg, None)
137             return view(*args, **kwargs)
138 
139         return wrapped
140 
141     return decorate
142 
143 
144
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ietf/utils/decorators.py b/ietf/utils/decorators.py
--- a/ietf/utils/decorators.py
+++ b/ietf/utils/decorators.py
@@ -4,7 +4,6 @@
 
 import datetime
 
-from decorator import decorator, decorate
 from functools import wraps
 
 from django.conf import settings
@@ -20,25 +19,29 @@
 from ietf.person.models import Person, PersonalApiKey, PersonApiKeyEvent
 from ietf.utils import log
 
-@decorator
-def skip_coverage(f, *args, **kwargs):
-    if settings.TEST_CODE_COVERAGE_CHECKER:
-        set_coverage_checking(False)
-        result = f(*args, **kwargs)
-        set_coverage_checking(True)
-        return result
-    else:
-        return  f(*args, **kwargs)
-
-@decorator
-def person_required(f, request, *args, **kwargs):
-    if not request.user.is_authenticated:
-        raise ValueError("The @person_required decorator should be called after @login_required.")
-    try:
-        request.user.person
-    except Person.DoesNotExist:
-        return render(request, 'registration/missing_person.html')
-    return  f(request, *args, **kwargs)
+def skip_coverage(f):
+    @wraps(f)
+    def _wrapper(*args, **kwargs):
+        if settings.TEST_CODE_COVERAGE_CHECKER:
+            set_coverage_checking(False)
+            result = f(*args, **kwargs)
+            set_coverage_checking(True)
+            return result
+        else:
+            return  f(*args, **kwargs)
+    return _wrapper
+
+def person_required(f):
+    @wraps(f)
+    def _wrapper(request, *args, **kwargs):
+        if not request.user.is_authenticated:
+            raise ValueError("The @person_required decorator should be called after @login_required.")
+        try:
+            request.user.person
+        except Person.DoesNotExist:
+            return render(request, 'registration/missing_person.html')
+        return  f(request, *args, **kwargs)
+    return _wrapper
 
 
 def require_api_key(f):
@@ -90,29 +93,31 @@
     return _wrapper
 
 
-def _memoize(func, self, *args, **kwargs):
-    '''Memoize wrapper for instance methods.  Use @lru_cache for functions.'''
-    if kwargs:  # frozenset is used to ensure hashability
-        key = args, frozenset(list(kwargs.items()))
-    else:
-        key = args
-    # instance method, set up cache if needed
-    if not hasattr(self, '_cache'):
-        self._cache = {}
-    if not func in self._cache:
-        self._cache[func] = {}            
-    #
-    cache = self._cache[func]
-    if key not in cache:
-        cache[key] = func(self, *args, **kwargs)
-    return cache[key]
 def memoize(func):
+    @wraps(func)
+    def _memoize(self, *args, **kwargs):
+        '''Memoize wrapper for instance methods.  Use @lru_cache for functions.'''
+        if kwargs:  # frozenset is used to ensure hashability
+            key = args, frozenset(list(kwargs.items()))
+        else:
+            key = args
+        # instance method, set up cache if needed
+        if not hasattr(self, '_cache'):
+            self._cache = {}
+        if not func in self._cache:
+            self._cache[func] = {}            
+        #
+        cache = self._cache[func]
+        if key not in cache:
+            cache[key] = func(self, *args, **kwargs)
+        return cache[key]
+
     if not hasattr(func, '__class__'):
         raise NotImplementedError("Use @lru_cache instead of memoize() for functions.")
     # For methods, we want the cache on the object, not on the class, in order
     # to not having to think about cache bloat and content becoming stale, so
     # we cannot set up the cache here.
-    return decorate(func, _memoize)
+    return _memoize
 
 
 def ignore_view_kwargs(*args):

{"golden_diff": "diff --git a/ietf/utils/decorators.py b/ietf/utils/decorators.py\n--- a/ietf/utils/decorators.py\n+++ b/ietf/utils/decorators.py\n@@ -4,7 +4,6 @@\n \n import datetime\n \n-from decorator import decorator, decorate\n from functools import wraps\n \n from django.conf import settings\n@@ -20,25 +19,29 @@\n from ietf.person.models import Person, PersonalApiKey, PersonApiKeyEvent\n from ietf.utils import log\n \n-@decorator\n-def skip_coverage(f, *args, **kwargs):\n-    if settings.TEST_CODE_COVERAGE_CHECKER:\n-        set_coverage_checking(False)\n-        result = f(*args, **kwargs)\n-        set_coverage_checking(True)\n-        return result\n-    else:\n-        return  f(*args, **kwargs)\n-\n-@decorator\n-def person_required(f, request, *args, **kwargs):\n-    if not request.user.is_authenticated:\n-        raise ValueError(\"The @person_required decorator should be called after @login_required.\")\n-    try:\n-        request.user.person\n-    except Person.DoesNotExist:\n-        return render(request, 'registration/missing_person.html')\n-    return  f(request, *args, **kwargs)\n+def skip_coverage(f):\n+    @wraps(f)\n+    def _wrapper(*args, **kwargs):\n+        if settings.TEST_CODE_COVERAGE_CHECKER:\n+            set_coverage_checking(False)\n+            result = f(*args, **kwargs)\n+            set_coverage_checking(True)\n+            return result\n+        else:\n+            return  f(*args, **kwargs)\n+    return _wrapper\n+\n+def person_required(f):\n+    @wraps(f)\n+    def _wrapper(request, *args, **kwargs):\n+        if not request.user.is_authenticated:\n+            raise ValueError(\"The @person_required decorator should be called after @login_required.\")\n+        try:\n+            request.user.person\n+        except Person.DoesNotExist:\n+            return render(request, 'registration/missing_person.html')\n+        return  f(request, *args, **kwargs)\n+    return _wrapper\n \n \n def require_api_key(f):\n@@ -90,29 +93,31 @@\n     return _wrapper\n \n \n-def _memoize(func, self, *args, **kwargs):\n-    '''Memoize wrapper for instance methods.  Use @lru_cache for functions.'''\n-    if kwargs:  # frozenset is used to ensure hashability\n-        key = args, frozenset(list(kwargs.items()))\n-    else:\n-        key = args\n-    # instance method, set up cache if needed\n-    if not hasattr(self, '_cache'):\n-        self._cache = {}\n-    if not func in self._cache:\n-        self._cache[func] = {}            \n-    #\n-    cache = self._cache[func]\n-    if key not in cache:\n-        cache[key] = func(self, *args, **kwargs)\n-    return cache[key]\n def memoize(func):\n+    @wraps(func)\n+    def _memoize(self, *args, **kwargs):\n+        '''Memoize wrapper for instance methods.  Use @lru_cache for functions.'''\n+        if kwargs:  # frozenset is used to ensure hashability\n+            key = args, frozenset(list(kwargs.items()))\n+        else:\n+            key = args\n+        # instance method, set up cache if needed\n+        if not hasattr(self, '_cache'):\n+            self._cache = {}\n+        if not func in self._cache:\n+            self._cache[func] = {}            \n+        #\n+        cache = self._cache[func]\n+        if key not in cache:\n+            cache[key] = func(self, *args, **kwargs)\n+        return cache[key]\n+\n     if not hasattr(func, '__class__'):\n         raise NotImplementedError(\"Use @lru_cache instead of memoize() for functions.\")\n     # For methods, we want the cache on the object, not on the class, in order\n     # to not having to think about cache bloat and content becoming stale, so\n     # we cannot set up the cache here.\n-    return decorate(func, _memoize)\n+    return _memoize\n \n \n def ignore_view_kwargs(*args):\n", "issue": "Refactor to drop dependency on decorator package\n### Description\n\nWe have a few decorators defined in `ietf/utils/decorator.py` that use the \"decorator\" package. This provides the `@decorator` decorator and a `decorate` method. The built-in Python `functools.wraps()` method can fulfill the needs here without the additional dependency. As far as I can tell we're not making use of any of the features provided by the \"decorator\" package.\r\n\r\nThe `@decorator` mechanism also seems to interfere with Django's `@method_decorator`, which led to refactoring the `requires_api_key` decorator already.\n\n### Code of Conduct\n\n- [X] I agree to follow the [IETF's Code of Conduct](https://github.com/ietf-tools/.github/blob/main/CODE_OF_CONDUCT.md)\n", "before_files": [{"content": "# Copyright The IETF Trust 2016-2020, All Rights Reserved\n# -*- coding: utf-8 -*-\n\n\nimport datetime\n\nfrom decorator import decorator, decorate\nfrom functools import wraps\n\nfrom django.conf import settings\nfrom django.contrib.auth import login\nfrom django.http import HttpResponse\nfrom django.shortcuts import render\nfrom django.utils import timezone\nfrom django.utils.encoding import force_bytes\n\nimport debug                            # pyflakes:ignore\n\nfrom ietf.utils.test_runner import set_coverage_checking\nfrom ietf.person.models import Person, PersonalApiKey, PersonApiKeyEvent\nfrom ietf.utils import log\n\n@decorator\ndef skip_coverage(f, *args, **kwargs):\n    if settings.TEST_CODE_COVERAGE_CHECKER:\n        set_coverage_checking(False)\n        result = f(*args, **kwargs)\n        set_coverage_checking(True)\n        return result\n    else:\n        return  f(*args, **kwargs)\n\n@decorator\ndef person_required(f, request, *args, **kwargs):\n    if not request.user.is_authenticated:\n        raise ValueError(\"The @person_required decorator should be called after @login_required.\")\n    try:\n        request.user.person\n    except Person.DoesNotExist:\n        return render(request, 'registration/missing_person.html')\n    return  f(request, *args, **kwargs)\n\n\ndef require_api_key(f):\n    @wraps(f)\n    def _wrapper(request, *args, **kwargs):\n        def err(code, text):\n            return HttpResponse(text, status=code, content_type='text/plain')\n        # Check method and get hash\n        if request.method == 'POST':\n            hash = request.POST.get('apikey')\n        elif request.method == 'GET':\n            hash = request.GET.get('apikey')\n        else:\n            return err(405, \"Method not allowed\")\n        if not hash:\n            return err(400, \"Missing apikey parameter\")\n        # Check hash\n        key = PersonalApiKey.validate_key(force_bytes(hash))\n        if not key:\n            return err(403, \"Invalid apikey\")\n        # Check endpoint\n        urlpath = request.META.get('PATH_INFO')\n        if not (urlpath and urlpath == key.endpoint):\n            return err(400, \"Apikey endpoint mismatch\") \n        # Check time since regular login\n        person = key.person\n        last_login = person.user.last_login\n        if not person.user.is_staff:\n            time_limit = (timezone.now() - datetime.timedelta(days=settings.UTILS_APIKEY_GUI_LOGIN_LIMIT_DAYS))\n            if last_login == None or last_login < time_limit:\n                return err(400, \"Too long since last regular login\")\n        # Log in\n        login(request, person.user)\n        # restore the user.last_login field, so it reflects only gui logins\n        person.user.last_login = last_login\n        person.user.save()\n        # Update stats\n        key.count += 1\n        key.latest = timezone.now()\n        key.save()\n        PersonApiKeyEvent.objects.create(person=person, type='apikey_login', key=key, desc=\"Logged in with key ID %s, endpoint %s\" % (key.id, key.endpoint))\n        # Execute decorated function\n        try:\n            ret = f(request, *args, **kwargs)\n        except AttributeError as e:\n            log.log(\"Bad API call: args: %s, kwargs: %s, exception: %s\" % (args, kwargs, e))\n            return err(400, \"Bad or missing parameters\")\n        return ret\n    return _wrapper\n\n\ndef _memoize(func, self, *args, **kwargs):\n    '''Memoize wrapper for instance methods.  Use @lru_cache for functions.'''\n    if kwargs:  # frozenset is used to ensure hashability\n        key = args, frozenset(list(kwargs.items()))\n    else:\n        key = args\n    # instance method, set up cache if needed\n    if not hasattr(self, '_cache'):\n        self._cache = {}\n    if not func in self._cache:\n        self._cache[func] = {}            \n    #\n    cache = self._cache[func]\n    if key not in cache:\n        cache[key] = func(self, *args, **kwargs)\n    return cache[key]\ndef memoize(func):\n    if not hasattr(func, '__class__'):\n        raise NotImplementedError(\"Use @lru_cache instead of memoize() for functions.\")\n    # For methods, we want the cache on the object, not on the class, in order\n    # to not having to think about cache bloat and content becoming stale, so\n    # we cannot set up the cache here.\n    return decorate(func, _memoize)\n\n\ndef ignore_view_kwargs(*args):\n    \"\"\"Ignore the specified kwargs if they are present\n\n    Usage: \n      @ignore_view_kwargs(\"ignore_arg1\", \"ignore_arg2\")\n      def my_view(request, good_arg):\n        ...\n\n      This will allow my_view() to be used in url() paths that have zero, one, or both of\n      ignore_arg1 and ignore_arg2 captured. These will be ignored, while good_arg will still\n      be captured as usual.\n    \"\"\"\n    kwargs_to_ignore = args\n\n    def decorate(view):\n        @wraps(view)\n        def wrapped(*args, **kwargs):\n            for kwarg in kwargs_to_ignore:\n                kwargs.pop(kwarg, None)\n            return view(*args, **kwargs)\n\n        return wrapped\n\n    return decorate\n\n\n", "path": "ietf/utils/decorators.py"}], "after_files": [{"content": "# Copyright The IETF Trust 2016-2020, All Rights Reserved\n# -*- coding: utf-8 -*-\n\n\nimport datetime\n\nfrom functools import wraps\n\nfrom django.conf import settings\nfrom django.contrib.auth import login\nfrom django.http import HttpResponse\nfrom django.shortcuts import render\nfrom django.utils import timezone\nfrom django.utils.encoding import force_bytes\n\nimport debug                            # pyflakes:ignore\n\nfrom ietf.utils.test_runner import set_coverage_checking\nfrom ietf.person.models import Person, PersonalApiKey, PersonApiKeyEvent\nfrom ietf.utils import log\n\ndef skip_coverage(f):\n    @wraps(f)\n    def _wrapper(*args, **kwargs):\n        if settings.TEST_CODE_COVERAGE_CHECKER:\n            set_coverage_checking(False)\n            result = f(*args, **kwargs)\n            set_coverage_checking(True)\n            return result\n        else:\n            return  f(*args, **kwargs)\n    return _wrapper\n\ndef person_required(f):\n    @wraps(f)\n    def _wrapper(request, *args, **kwargs):\n        if not request.user.is_authenticated:\n            raise ValueError(\"The @person_required decorator should be called after @login_required.\")\n        try:\n            request.user.person\n        except Person.DoesNotExist:\n            return render(request, 'registration/missing_person.html')\n        return  f(request, *args, **kwargs)\n    return _wrapper\n\n\ndef require_api_key(f):\n    @wraps(f)\n    def _wrapper(request, *args, **kwargs):\n        def err(code, text):\n            return HttpResponse(text, status=code, content_type='text/plain')\n        # Check method and get hash\n        if request.method == 'POST':\n            hash = request.POST.get('apikey')\n        elif request.method == 'GET':\n            hash = request.GET.get('apikey')\n        else:\n            return err(405, \"Method not allowed\")\n        if not hash:\n            return err(400, \"Missing apikey parameter\")\n        # Check hash\n        key = PersonalApiKey.validate_key(force_bytes(hash))\n        if not key:\n            return err(403, \"Invalid apikey\")\n        # Check endpoint\n        urlpath = request.META.get('PATH_INFO')\n        if not (urlpath and urlpath == key.endpoint):\n            return err(400, \"Apikey endpoint mismatch\") \n        # Check time since regular login\n        person = key.person\n        last_login = person.user.last_login\n        if not person.user.is_staff:\n            time_limit = (timezone.now() - datetime.timedelta(days=settings.UTILS_APIKEY_GUI_LOGIN_LIMIT_DAYS))\n            if last_login == None or last_login < time_limit:\n                return err(400, \"Too long since last regular login\")\n        # Log in\n        login(request, person.user)\n        # restore the user.last_login field, so it reflects only gui logins\n        person.user.last_login = last_login\n        person.user.save()\n        # Update stats\n        key.count += 1\n        key.latest = timezone.now()\n        key.save()\n        PersonApiKeyEvent.objects.create(person=person, type='apikey_login', key=key, desc=\"Logged in with key ID %s, endpoint %s\" % (key.id, key.endpoint))\n        # Execute decorated function\n        try:\n            ret = f(request, *args, **kwargs)\n        except AttributeError as e:\n            log.log(\"Bad API call: args: %s, kwargs: %s, exception: %s\" % (args, kwargs, e))\n            return err(400, \"Bad or missing parameters\")\n        return ret\n    return _wrapper\n\n\ndef memoize(func):\n    @wraps(func)\n    def _memoize(self, *args, **kwargs):\n        '''Memoize wrapper for instance methods.  Use @lru_cache for functions.'''\n        if kwargs:  # frozenset is used to ensure hashability\n            key = args, frozenset(list(kwargs.items()))\n        else:\n            key = args\n        # instance method, set up cache if needed\n        if not hasattr(self, '_cache'):\n            self._cache = {}\n        if not func in self._cache:\n            self._cache[func] = {}            \n        #\n        cache = self._cache[func]\n        if key not in cache:\n            cache[key] = func(self, *args, **kwargs)\n        return cache[key]\n\n    if not hasattr(func, '__class__'):\n        raise NotImplementedError(\"Use @lru_cache instead of memoize() for functions.\")\n    # For methods, we want the cache on the object, not on the class, in order\n    # to not having to think about cache bloat and content becoming stale, so\n    # we cannot set up the cache here.\n    return _memoize\n\n\ndef ignore_view_kwargs(*args):\n    \"\"\"Ignore the specified kwargs if they are present\n\n    Usage: \n      @ignore_view_kwargs(\"ignore_arg1\", \"ignore_arg2\")\n      def my_view(request, good_arg):\n        ...\n\n      This will allow my_view() to be used in url() paths that have zero, one, or both of\n      ignore_arg1 and ignore_arg2 captured. These will be ignored, while good_arg will still\n      be captured as usual.\n    \"\"\"\n    kwargs_to_ignore = args\n\n    def decorate(view):\n        @wraps(view)\n        def wrapped(*args, **kwargs):\n            for kwarg in kwargs_to_ignore:\n                kwargs.pop(kwarg, None)\n            return view(*args, **kwargs)\n\n        return wrapped\n\n    return decorate\n\n\n", "path": "ietf/utils/decorators.py"}]}