We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
st2kv does not resolve in Jinja cast expression
In the rule: 
` {{ "2" | int }} - 2` Dah
`{{ trigger.count | int }} -> 2` OK
`{{ st2kv.system.count | int }} -> 0` Wrong.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `st2common/st2common/services/keyvalues.py`
Content:
```
1 # Licensed to the StackStorm, Inc ('StackStorm') under one or more
2 # contributor license agreements.  See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License.  You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 from st2common import log as logging
17 
18 from st2common.constants.keyvalue import SYSTEM_SCOPE, FULL_SYSTEM_SCOPE
19 from st2common.constants.keyvalue import USER_SCOPE, FULL_USER_SCOPE
20 from st2common.constants.keyvalue import ALLOWED_SCOPES
21 from st2common.constants.keyvalue import DATASTORE_KEY_SEPARATOR
22 from st2common.exceptions.keyvalue import InvalidScopeException, InvalidUserException
23 from st2common.models.system.keyvalue import UserKeyReference
24 from st2common.persistence.keyvalue import KeyValuePair
25 
26 __all__ = [
27     'get_kvp_for_name',
28     'get_values_for_names',
29 
30     'KeyValueLookup',
31     'UserKeyValueLookup'
32 ]
33 
34 LOG = logging.getLogger(__name__)
35 
36 
37 def get_kvp_for_name(name):
38     try:
39         kvp_db = KeyValuePair.get_by_name(name)
40     except ValueError:
41         kvp_db = None
42 
43     return kvp_db
44 
45 
46 def get_values_for_names(names, default_value=None):
47     """
48     Retrieve values for the provided key names (multi get).
49 
50     If a KeyValuePair objects for a particular name doesn't exist, the dictionary will contain
51     default_value for that name.
52 
53     :rtype: ``dict``
54     """
55     result = {}
56     kvp_dbs = KeyValuePair.get_by_names(names=names)
57 
58     name_to_kvp_db_map = {}
59     for kvp_db in kvp_dbs:
60         name_to_kvp_db_map[kvp_db.name] = kvp_db.value
61 
62     for name in names:
63         result[name] = name_to_kvp_db_map.get(name, default_value)
64 
65     return result
66 
67 
68 class KeyValueLookup(object):
69 
70     def __init__(self, prefix=None, key_prefix=None, cache=None, scope=FULL_SYSTEM_SCOPE):
71         if not scope:
72             scope = FULL_SYSTEM_SCOPE
73 
74         if scope == SYSTEM_SCOPE:
75             scope = FULL_SYSTEM_SCOPE
76 
77         self._prefix = prefix
78         self._key_prefix = key_prefix or ''
79         self._value_cache = cache or {}
80         self._scope = scope
81 
82     def __str__(self):
83         return self._value_cache[self._key_prefix]
84 
85     def __getitem__(self, key):
86         return self._get(key)
87 
88     def __getattr__(self, name):
89         return self._get(name)
90 
91     def _get(self, name):
92         # get the value for this key and save in value_cache
93         if self._key_prefix:
94             key = '%s.%s' % (self._key_prefix, name)
95         else:
96             key = name
97 
98         if self._prefix:
99             kvp_key = DATASTORE_KEY_SEPARATOR.join([self._prefix, key])
100         else:
101             kvp_key = key
102 
103         value = self._get_kv(kvp_key)
104         self._value_cache[key] = value
105         # return a KeyValueLookup as response since the lookup may not be complete e.g. if
106         # the lookup is for 'key_base.key_value' it is likely that the calling code, e.g. Jinja,
107         # will expect to do a dictionary style lookup for key_base and key_value as subsequent
108         # calls. Saving the value in cache avoids extra DB calls.
109         return KeyValueLookup(prefix=self._prefix, key_prefix=key, cache=self._value_cache,
110                               scope=self._scope)
111 
112     def _get_kv(self, key):
113         scope = self._scope
114         LOG.debug('Lookup system kv: scope: %s and key: %s', scope, key)
115         kvp = KeyValuePair.get_by_scope_and_name(scope=scope, name=key)
116         if kvp:
117             LOG.debug('Got value %s from datastore.', kvp.value)
118         return kvp.value if kvp else ''
119 
120 
121 class UserKeyValueLookup(object):
122 
123     def __init__(self, user, prefix=None, key_prefix=None, cache=None, scope=FULL_USER_SCOPE):
124         if not scope:
125             scope = FULL_USER_SCOPE
126 
127         if scope == USER_SCOPE:
128             scope = FULL_USER_SCOPE
129 
130         self._prefix = prefix
131         self._key_prefix = key_prefix or ''
132         self._value_cache = cache or {}
133         self._user = user
134         self._scope = scope
135 
136     def __str__(self):
137         return self._value_cache[self._key_prefix]
138 
139     def __getitem__(self, key):
140         return self._get(key)
141 
142     def __getattr__(self, name):
143         return self._get(name)
144 
145     def _get(self, name):
146         # get the value for this key and save in value_cache
147         if self._key_prefix:
148             key = '%s.%s' % (self._key_prefix, name)
149         else:
150             key = UserKeyReference(name=name, user=self._user).ref
151 
152         if self._prefix:
153             kvp_key = DATASTORE_KEY_SEPARATOR.join([self._prefix, key])
154         else:
155             kvp_key = key
156 
157         value = self._get_kv(kvp_key)
158         self._value_cache[key] = value
159         # return a KeyValueLookup as response since the lookup may not be complete e.g. if
160         # the lookup is for 'key_base.key_value' it is likely that the calling code, e.g. Jinja,
161         # will expect to do a dictionary style lookup for key_base and key_value as subsequent
162         # calls. Saving the value in cache avoids extra DB calls.
163         return UserKeyValueLookup(prefix=self._prefix, user=self._user, key_prefix=key,
164                                   cache=self._value_cache, scope=self._scope)
165 
166     def _get_kv(self, key):
167         scope = self._scope
168         kvp = KeyValuePair.get_by_scope_and_name(scope=scope, name=key)
169         return kvp.value if kvp else ''
170 
171 
172 def get_key_reference(scope, name, user=None):
173     """
174     Given a key name and user this method returns a new name (string ref)
175     to address the key value pair in the context of that user.
176 
177     :param user: User to whom key belongs.
178     :type name: ``str``
179 
180     :param name: Original name of the key.
181     :type name: ``str``
182 
183     :rtype: ``str``
184     """
185     if (scope == SYSTEM_SCOPE or scope == FULL_SYSTEM_SCOPE):
186         return name
187     elif (scope == USER_SCOPE or scope == FULL_USER_SCOPE):
188         if not user:
189             raise InvalidUserException('A valid user must be specified for user key ref.')
190         return UserKeyReference(name=name, user=user).ref
191     else:
192         raise InvalidScopeException('Scope "%s" is not valid. Allowed scopes are %s.' %
193                                     (scope, ALLOWED_SCOPES))
194
```
--- 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/st2common/st2common/services/keyvalues.py b/st2common/st2common/services/keyvalues.py
--- a/st2common/st2common/services/keyvalues.py
+++ b/st2common/st2common/services/keyvalues.py
@@ -82,6 +82,12 @@
     def __str__(self):
         return self._value_cache[self._key_prefix]
 
+    def __int__(self):
+        return int(float(self))
+
+    def __float__(self):
+        return float(str(self))
+
     def __getitem__(self, key):
         return self._get(key)

{"golden_diff": "diff --git a/st2common/st2common/services/keyvalues.py b/st2common/st2common/services/keyvalues.py\n--- a/st2common/st2common/services/keyvalues.py\n+++ b/st2common/st2common/services/keyvalues.py\n@@ -82,6 +82,12 @@\n     def __str__(self):\n         return self._value_cache[self._key_prefix]\n \n+    def __int__(self):\n+        return int(float(self))\n+\n+    def __float__(self):\n+        return float(str(self))\n+\n     def __getitem__(self, key):\n         return self._get(key)\n", "issue": "st2kv does not resolve in Jinja cast expression\nIn the rule: \r\n` {{ \"2\" | int }} - 2` Dah\r\n`{{ trigger.count | int }} -> 2` OK\r\n`{{ st2kv.system.count | int }} -> 0` Wrong.\r\n\n", "before_files": [{"content": "# Licensed to the StackStorm, Inc ('StackStorm') under one or more\n# contributor license agreements.  See the NOTICE file distributed with\n# this work for additional information regarding copyright ownership.\n# The ASF licenses this file to You under the Apache License, Version 2.0\n# (the \"License\"); you may not use this file except in compliance with\n# the License.  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 st2common import log as logging\n\nfrom st2common.constants.keyvalue import SYSTEM_SCOPE, FULL_SYSTEM_SCOPE\nfrom st2common.constants.keyvalue import USER_SCOPE, FULL_USER_SCOPE\nfrom st2common.constants.keyvalue import ALLOWED_SCOPES\nfrom st2common.constants.keyvalue import DATASTORE_KEY_SEPARATOR\nfrom st2common.exceptions.keyvalue import InvalidScopeException, InvalidUserException\nfrom st2common.models.system.keyvalue import UserKeyReference\nfrom st2common.persistence.keyvalue import KeyValuePair\n\n__all__ = [\n    'get_kvp_for_name',\n    'get_values_for_names',\n\n    'KeyValueLookup',\n    'UserKeyValueLookup'\n]\n\nLOG = logging.getLogger(__name__)\n\n\ndef get_kvp_for_name(name):\n    try:\n        kvp_db = KeyValuePair.get_by_name(name)\n    except ValueError:\n        kvp_db = None\n\n    return kvp_db\n\n\ndef get_values_for_names(names, default_value=None):\n    \"\"\"\n    Retrieve values for the provided key names (multi get).\n\n    If a KeyValuePair objects for a particular name doesn't exist, the dictionary will contain\n    default_value for that name.\n\n    :rtype: ``dict``\n    \"\"\"\n    result = {}\n    kvp_dbs = KeyValuePair.get_by_names(names=names)\n\n    name_to_kvp_db_map = {}\n    for kvp_db in kvp_dbs:\n        name_to_kvp_db_map[kvp_db.name] = kvp_db.value\n\n    for name in names:\n        result[name] = name_to_kvp_db_map.get(name, default_value)\n\n    return result\n\n\nclass KeyValueLookup(object):\n\n    def __init__(self, prefix=None, key_prefix=None, cache=None, scope=FULL_SYSTEM_SCOPE):\n        if not scope:\n            scope = FULL_SYSTEM_SCOPE\n\n        if scope == SYSTEM_SCOPE:\n            scope = FULL_SYSTEM_SCOPE\n\n        self._prefix = prefix\n        self._key_prefix = key_prefix or ''\n        self._value_cache = cache or {}\n        self._scope = scope\n\n    def __str__(self):\n        return self._value_cache[self._key_prefix]\n\n    def __getitem__(self, key):\n        return self._get(key)\n\n    def __getattr__(self, name):\n        return self._get(name)\n\n    def _get(self, name):\n        # get the value for this key and save in value_cache\n        if self._key_prefix:\n            key = '%s.%s' % (self._key_prefix, name)\n        else:\n            key = name\n\n        if self._prefix:\n            kvp_key = DATASTORE_KEY_SEPARATOR.join([self._prefix, key])\n        else:\n            kvp_key = key\n\n        value = self._get_kv(kvp_key)\n        self._value_cache[key] = value\n        # return a KeyValueLookup as response since the lookup may not be complete e.g. if\n        # the lookup is for 'key_base.key_value' it is likely that the calling code, e.g. Jinja,\n        # will expect to do a dictionary style lookup for key_base and key_value as subsequent\n        # calls. Saving the value in cache avoids extra DB calls.\n        return KeyValueLookup(prefix=self._prefix, key_prefix=key, cache=self._value_cache,\n                              scope=self._scope)\n\n    def _get_kv(self, key):\n        scope = self._scope\n        LOG.debug('Lookup system kv: scope: %s and key: %s', scope, key)\n        kvp = KeyValuePair.get_by_scope_and_name(scope=scope, name=key)\n        if kvp:\n            LOG.debug('Got value %s from datastore.', kvp.value)\n        return kvp.value if kvp else ''\n\n\nclass UserKeyValueLookup(object):\n\n    def __init__(self, user, prefix=None, key_prefix=None, cache=None, scope=FULL_USER_SCOPE):\n        if not scope:\n            scope = FULL_USER_SCOPE\n\n        if scope == USER_SCOPE:\n            scope = FULL_USER_SCOPE\n\n        self._prefix = prefix\n        self._key_prefix = key_prefix or ''\n        self._value_cache = cache or {}\n        self._user = user\n        self._scope = scope\n\n    def __str__(self):\n        return self._value_cache[self._key_prefix]\n\n    def __getitem__(self, key):\n        return self._get(key)\n\n    def __getattr__(self, name):\n        return self._get(name)\n\n    def _get(self, name):\n        # get the value for this key and save in value_cache\n        if self._key_prefix:\n            key = '%s.%s' % (self._key_prefix, name)\n        else:\n            key = UserKeyReference(name=name, user=self._user).ref\n\n        if self._prefix:\n            kvp_key = DATASTORE_KEY_SEPARATOR.join([self._prefix, key])\n        else:\n            kvp_key = key\n\n        value = self._get_kv(kvp_key)\n        self._value_cache[key] = value\n        # return a KeyValueLookup as response since the lookup may not be complete e.g. if\n        # the lookup is for 'key_base.key_value' it is likely that the calling code, e.g. Jinja,\n        # will expect to do a dictionary style lookup for key_base and key_value as subsequent\n        # calls. Saving the value in cache avoids extra DB calls.\n        return UserKeyValueLookup(prefix=self._prefix, user=self._user, key_prefix=key,\n                                  cache=self._value_cache, scope=self._scope)\n\n    def _get_kv(self, key):\n        scope = self._scope\n        kvp = KeyValuePair.get_by_scope_and_name(scope=scope, name=key)\n        return kvp.value if kvp else ''\n\n\ndef get_key_reference(scope, name, user=None):\n    \"\"\"\n    Given a key name and user this method returns a new name (string ref)\n    to address the key value pair in the context of that user.\n\n    :param user: User to whom key belongs.\n    :type name: ``str``\n\n    :param name: Original name of the key.\n    :type name: ``str``\n\n    :rtype: ``str``\n    \"\"\"\n    if (scope == SYSTEM_SCOPE or scope == FULL_SYSTEM_SCOPE):\n        return name\n    elif (scope == USER_SCOPE or scope == FULL_USER_SCOPE):\n        if not user:\n            raise InvalidUserException('A valid user must be specified for user key ref.')\n        return UserKeyReference(name=name, user=user).ref\n    else:\n        raise InvalidScopeException('Scope \"%s\" is not valid. Allowed scopes are %s.' %\n                                    (scope, ALLOWED_SCOPES))\n", "path": "st2common/st2common/services/keyvalues.py"}], "after_files": [{"content": "# Licensed to the StackStorm, Inc ('StackStorm') under one or more\n# contributor license agreements.  See the NOTICE file distributed with\n# this work for additional information regarding copyright ownership.\n# The ASF licenses this file to You under the Apache License, Version 2.0\n# (the \"License\"); you may not use this file except in compliance with\n# the License.  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 st2common import log as logging\n\nfrom st2common.constants.keyvalue import SYSTEM_SCOPE, FULL_SYSTEM_SCOPE\nfrom st2common.constants.keyvalue import USER_SCOPE, FULL_USER_SCOPE\nfrom st2common.constants.keyvalue import ALLOWED_SCOPES\nfrom st2common.constants.keyvalue import DATASTORE_KEY_SEPARATOR\nfrom st2common.exceptions.keyvalue import InvalidScopeException, InvalidUserException\nfrom st2common.models.system.keyvalue import UserKeyReference\nfrom st2common.persistence.keyvalue import KeyValuePair\n\n__all__ = [\n    'get_kvp_for_name',\n    'get_values_for_names',\n\n    'KeyValueLookup',\n    'UserKeyValueLookup'\n]\n\nLOG = logging.getLogger(__name__)\n\n\ndef get_kvp_for_name(name):\n    try:\n        kvp_db = KeyValuePair.get_by_name(name)\n    except ValueError:\n        kvp_db = None\n\n    return kvp_db\n\n\ndef get_values_for_names(names, default_value=None):\n    \"\"\"\n    Retrieve values for the provided key names (multi get).\n\n    If a KeyValuePair objects for a particular name doesn't exist, the dictionary will contain\n    default_value for that name.\n\n    :rtype: ``dict``\n    \"\"\"\n    result = {}\n    kvp_dbs = KeyValuePair.get_by_names(names=names)\n\n    name_to_kvp_db_map = {}\n    for kvp_db in kvp_dbs:\n        name_to_kvp_db_map[kvp_db.name] = kvp_db.value\n\n    for name in names:\n        result[name] = name_to_kvp_db_map.get(name, default_value)\n\n    return result\n\n\nclass KeyValueLookup(object):\n\n    def __init__(self, prefix=None, key_prefix=None, cache=None, scope=FULL_SYSTEM_SCOPE):\n        if not scope:\n            scope = FULL_SYSTEM_SCOPE\n\n        if scope == SYSTEM_SCOPE:\n            scope = FULL_SYSTEM_SCOPE\n\n        self._prefix = prefix\n        self._key_prefix = key_prefix or ''\n        self._value_cache = cache or {}\n        self._scope = scope\n\n    def __str__(self):\n        return self._value_cache[self._key_prefix]\n\n    def __int__(self):\n        return int(float(self))\n\n    def __float__(self):\n        return float(str(self))\n\n    def __getitem__(self, key):\n        return self._get(key)\n\n    def __getattr__(self, name):\n        return self._get(name)\n\n    def _get(self, name):\n        # get the value for this key and save in value_cache\n        if self._key_prefix:\n            key = '%s.%s' % (self._key_prefix, name)\n        else:\n            key = name\n\n        if self._prefix:\n            kvp_key = DATASTORE_KEY_SEPARATOR.join([self._prefix, key])\n        else:\n            kvp_key = key\n\n        value = self._get_kv(kvp_key)\n        self._value_cache[key] = value\n        # return a KeyValueLookup as response since the lookup may not be complete e.g. if\n        # the lookup is for 'key_base.key_value' it is likely that the calling code, e.g. Jinja,\n        # will expect to do a dictionary style lookup for key_base and key_value as subsequent\n        # calls. Saving the value in cache avoids extra DB calls.\n        return KeyValueLookup(prefix=self._prefix, key_prefix=key, cache=self._value_cache,\n                              scope=self._scope)\n\n    def _get_kv(self, key):\n        scope = self._scope\n        LOG.debug('Lookup system kv: scope: %s and key: %s', scope, key)\n        kvp = KeyValuePair.get_by_scope_and_name(scope=scope, name=key)\n        if kvp:\n            LOG.debug('Got value %s from datastore.', kvp.value)\n        return kvp.value if kvp else ''\n\n\nclass UserKeyValueLookup(object):\n\n    def __init__(self, user, prefix=None, key_prefix=None, cache=None, scope=FULL_USER_SCOPE):\n        if not scope:\n            scope = FULL_USER_SCOPE\n\n        if scope == USER_SCOPE:\n            scope = FULL_USER_SCOPE\n\n        self._prefix = prefix\n        self._key_prefix = key_prefix or ''\n        self._value_cache = cache or {}\n        self._user = user\n        self._scope = scope\n\n    def __str__(self):\n        return self._value_cache[self._key_prefix]\n\n    def __getitem__(self, key):\n        return self._get(key)\n\n    def __getattr__(self, name):\n        return self._get(name)\n\n    def _get(self, name):\n        # get the value for this key and save in value_cache\n        if self._key_prefix:\n            key = '%s.%s' % (self._key_prefix, name)\n        else:\n            key = UserKeyReference(name=name, user=self._user).ref\n\n        if self._prefix:\n            kvp_key = DATASTORE_KEY_SEPARATOR.join([self._prefix, key])\n        else:\n            kvp_key = key\n\n        value = self._get_kv(kvp_key)\n        self._value_cache[key] = value\n        # return a KeyValueLookup as response since the lookup may not be complete e.g. if\n        # the lookup is for 'key_base.key_value' it is likely that the calling code, e.g. Jinja,\n        # will expect to do a dictionary style lookup for key_base and key_value as subsequent\n        # calls. Saving the value in cache avoids extra DB calls.\n        return UserKeyValueLookup(prefix=self._prefix, user=self._user, key_prefix=key,\n                                  cache=self._value_cache, scope=self._scope)\n\n    def _get_kv(self, key):\n        scope = self._scope\n        kvp = KeyValuePair.get_by_scope_and_name(scope=scope, name=key)\n        return kvp.value if kvp else ''\n\n\ndef get_key_reference(scope, name, user=None):\n    \"\"\"\n    Given a key name and user this method returns a new name (string ref)\n    to address the key value pair in the context of that user.\n\n    :param user: User to whom key belongs.\n    :type name: ``str``\n\n    :param name: Original name of the key.\n    :type name: ``str``\n\n    :rtype: ``str``\n    \"\"\"\n    if (scope == SYSTEM_SCOPE or scope == FULL_SYSTEM_SCOPE):\n        return name\n    elif (scope == USER_SCOPE or scope == FULL_USER_SCOPE):\n        if not user:\n            raise InvalidUserException('A valid user must be specified for user key ref.')\n        return UserKeyReference(name=name, user=user).ref\n    else:\n        raise InvalidScopeException('Scope \"%s\" is not valid. Allowed scopes are %s.' %\n                                    (scope, ALLOWED_SCOPES))\n", "path": "st2common/st2common/services/keyvalues.py"}]}