We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Runtimeconfig: Update time fails to parse
OS: Linux (Debian 4.9.65)
Python: 3.5.3 / 2.7.13
Version: google-cloud-runtimeconfig==0.28.0, google-cloud==0.32.0

Steps to reproduce:
1. Using gcloud, set a runtimeconfig variable.
2. In Python, load that variable
3. Try to access its update_time property.

```pycon
>>> from google.cloud import runtimeconfig
>>> client = runtimeconfig.Client()
>>> config = client.config('testconfig')
>>> var = config.get_variable('foo')
>>> var.update_time
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/redacted/lib/python3.5/site-packages/google/cloud/runtimeconfig/variable.py", line 160, in update_time
    value = _rfc3339_to_datetime(value)
  File "/redacted/lib/python3.5/site-packages/google/cloud/_helpers.py", line 274, in _rfc3339_to_datetime
    dt_str, _RFC3339_MICROS).replace(tzinfo=UTC)
  File "/usr/lib/python3.5/_strptime.py", line 510, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "/usr/lib/python3.5/_strptime.py", line 343, in _strptime
    (data_string, format))
ValueError: time data '2018-01-22T21:39:44.095040522Z' does not match format '%Y-%m-%dT%H:%M:%S.%fZ'
>>> var._properties
{'text': '43', 'updateTime': '2018-01-22T21:39:44.095040522Z'}
```

Observation: The `%f` format accepts microseconds, not fractions of arbitrary precision. That means six digits at most, but I see nine in the data.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `runtimeconfig/google/cloud/runtimeconfig/variable.py`
Content:
```
1 # Copyright 2016 Google LLC
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 """Create / interact with Google Cloud RuntimeConfig variables.
16 
17 .. data:: STATE_UNSPECIFIED
18 
19     The default variable state.  See
20     https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables#VariableState
21 
22 .. data:: STATE_UPDATED
23 
24     Indicates the variable was updated, while `variables.watch` was executing.
25     See
26     https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables#VariableState
27 
28 .. data:: STATE_DELETED
29 
30     Indicates the variable was deleted, while `variables.watch`_ was executing.
31     See
32     https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables#VariableState
33 
34 .. _variables.watch:
35     https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables/watch
36 """
37 
38 import base64
39 
40 from google.cloud._helpers import _rfc3339_to_datetime
41 from google.cloud.exceptions import NotFound
42 from google.cloud.runtimeconfig._helpers import variable_name_from_full_name
43 
44 
45 STATE_UNSPECIFIED = 'VARIABLE_STATE_UNSPECIFIED'
46 STATE_UPDATED = 'UPDATED'
47 STATE_DELETED = 'DELETED'
48 
49 
50 class Variable(object):
51     """A variable in the Cloud RuntimeConfig service.
52 
53     See
54     https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables
55 
56     :type name: str
57     :param name: The name of the variable.  This corresponds to the
58                  unique path of the variable in the config.
59 
60     :type config: :class:`google.cloud.runtimeconfig.config.Config`
61     :param config: The config to which this variable belongs.
62     """
63 
64     def __init__(self, name, config):
65         self.name = name
66         self.config = config
67         self._properties = {}
68 
69     @classmethod
70     def from_api_repr(cls, resource, config):
71         """Factory:  construct a Variable given its API representation
72 
73         :type resource: dict
74         :param resource: change set representation returned from the API.
75 
76         :type config: :class:`google.cloud.runtimeconfig.config.Config`
77         :param config: The config to which this variable belongs.
78 
79         :rtype: :class:`google.cloud.runtimeconfig.variable.Variable`
80         :returns: Variable parsed from ``resource``.
81         """
82         name = variable_name_from_full_name(resource.get('name'))
83         variable = cls(name=name, config=config)
84         variable._set_properties(resource=resource)
85         return variable
86 
87     @property
88     def full_name(self):
89         """Fully-qualified name of this variable.
90 
91         Example:
92         ``projects/my-project/configs/my-config/variables/my-var``
93 
94         :rtype: str
95         :returns: The full name based on config and variable names.
96 
97         :raises: :class:`ValueError` if the variable is missing a name.
98         """
99         if not self.name:
100             raise ValueError('Missing variable name.')
101         return '%s/variables/%s' % (self.config.full_name, self.name)
102 
103     @property
104     def path(self):
105         """URL path for the variable's APIs.
106 
107         :rtype: str
108         :returns: The URL path based on config and variable names.
109         """
110         return '/%s' % (self.full_name,)
111 
112     @property
113     def client(self):
114         """The client bound to this variable."""
115         return self.config.client
116 
117     @property
118     def value(self):
119         """Value of the variable, as bytes.
120 
121         See
122         https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables
123 
124         :rtype: bytes or ``NoneType``
125         :returns: The value of the variable or ``None`` if the property
126                   is not set locally.
127         """
128         value = self._properties.get('value')
129         if value is not None:
130             value = base64.b64decode(value)
131         return value
132 
133     @property
134     def state(self):
135         """Retrieve the state of the variable.
136 
137         See
138         https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables#VariableState
139 
140         :rtype: str
141         :returns:
142             If set, one of "UPDATED", "DELETED", or defaults to
143             "VARIABLE_STATE_UNSPECIFIED".
144         """
145         return self._properties.get('state', STATE_UNSPECIFIED)
146 
147     @property
148     def update_time(self):
149         """Retrieve the timestamp at which the variable was updated.
150 
151         See
152         https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables
153 
154         :rtype: :class:`datetime.datetime` or ``NoneType``
155         :returns: Datetime object parsed from RFC3339 valid timestamp, or
156                   ``None`` if the property is not set locally.
157         """
158         value = self._properties.get('updateTime')
159         if value is not None:
160             value = _rfc3339_to_datetime(value)
161         return value
162 
163     def _require_client(self, client):
164         """Check client or verify over-ride.
165 
166         :type client: :class:`google.cloud.runtimconfig.client.Client`
167         :param client:
168             (Optional) The client to use.  If not passed, falls back to the
169             ``client`` stored on the current zone.
170 
171         :rtype: :class:`google.cloud.runtimeconfig.client.Client`
172         :returns: The client passed in or the currently bound client.
173         """
174         if client is None:
175             client = self.client
176         return client
177 
178     def _set_properties(self, resource):
179         """Update properties from resource in body of ``api_response``
180 
181         :type resource: dict
182         :param resource: variable representation returned from the API.
183         """
184         self._properties.clear()
185         cleaned = resource.copy()
186         if 'name' in cleaned:
187             self.name = variable_name_from_full_name(cleaned.pop('name'))
188         self._properties.update(cleaned)
189 
190     def exists(self, client=None):
191         """API call:  test for the existence of the variable via a GET request
192 
193         See
194         https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables/get
195 
196         :type client: :class:`~google.cloud.runtimeconfig.client.Client`
197         :param client:
198             (Optional) The client to use.  If not passed, falls back to the
199             ``client`` stored on the variable's config.
200 
201         :rtype: bool
202         :returns: True if the variable exists in Cloud RuntimeConfig.
203         """
204         client = self._require_client(client)
205         try:
206             # We only need the status code (200 or not) so we seek to
207             # minimize the returned payload.
208             query_params = {'fields': 'name'}
209             client._connection.api_request(method='GET', path=self.path,
210                                            query_params=query_params)
211             return True
212         except NotFound:
213             return False
214 
215     def reload(self, client=None):
216         """API call:  reload the variable via a ``GET`` request.
217 
218         This method will reload the newest data for the variable.
219 
220         See
221         https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs/get
222 
223         :type client: :class:`google.cloud.runtimeconfig.client.Client`
224         :param client:
225             (Optional) The client to use.  If not passed, falls back to the
226             client stored on the current config.
227         """
228         client = self._require_client(client)
229 
230         # We assume the variable exists. If it doesn't it will raise a NotFound
231         # exception.
232         resp = client._connection.api_request(method='GET', path=self.path)
233         self._set_properties(resource=resp)
234
```
--- 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/runtimeconfig/google/cloud/runtimeconfig/variable.py b/runtimeconfig/google/cloud/runtimeconfig/variable.py
--- a/runtimeconfig/google/cloud/runtimeconfig/variable.py
+++ b/runtimeconfig/google/cloud/runtimeconfig/variable.py
@@ -36,8 +36,11 @@
 """
 
 import base64
+import datetime
 
-from google.cloud._helpers import _rfc3339_to_datetime
+import pytz
+
+from google.api_core import datetime_helpers
 from google.cloud.exceptions import NotFound
 from google.cloud.runtimeconfig._helpers import variable_name_from_full_name
 
@@ -151,13 +154,28 @@
         See
         https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables
 
-        :rtype: :class:`datetime.datetime` or ``NoneType``
-        :returns: Datetime object parsed from RFC3339 valid timestamp, or
-                  ``None`` if the property is not set locally.
+        Returns:
+            :class:`~api_core.datetime_helpers.DatetimeWithNanoseconds`,
+            :class:`datetime.datetime` or ``NoneType``:
+            Datetime object parsed from RFC3339 valid timestamp, or
+            ``None`` if the property is not set locally.
+
+        Raises:
+            ValueError: if value is not a valid RFC3339 timestamp
         """
         value = self._properties.get('updateTime')
         if value is not None:
-            value = _rfc3339_to_datetime(value)
+            try:
+                value = datetime.datetime.strptime(
+                    value, datetime_helpers._RFC3339_MICROS)
+            except ValueError:
+                DatetimeNS = datetime_helpers.DatetimeWithNanoseconds
+                value = DatetimeNS.from_rfc3339(value)
+            naive = (
+                value.tzinfo is None
+                or value.tzinfo.utcoffset(value) is None)
+            if naive:
+                value = pytz.utc.localize(value)
         return value
 
     def _require_client(self, client):

{"golden_diff": "diff --git a/runtimeconfig/google/cloud/runtimeconfig/variable.py b/runtimeconfig/google/cloud/runtimeconfig/variable.py\n--- a/runtimeconfig/google/cloud/runtimeconfig/variable.py\n+++ b/runtimeconfig/google/cloud/runtimeconfig/variable.py\n@@ -36,8 +36,11 @@\n \"\"\"\n \n import base64\n+import datetime\n \n-from google.cloud._helpers import _rfc3339_to_datetime\n+import pytz\n+\n+from google.api_core import datetime_helpers\n from google.cloud.exceptions import NotFound\n from google.cloud.runtimeconfig._helpers import variable_name_from_full_name\n \n@@ -151,13 +154,28 @@\n         See\n         https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables\n \n-        :rtype: :class:`datetime.datetime` or ``NoneType``\n-        :returns: Datetime object parsed from RFC3339 valid timestamp, or\n-                  ``None`` if the property is not set locally.\n+        Returns:\n+            :class:`~api_core.datetime_helpers.DatetimeWithNanoseconds`,\n+            :class:`datetime.datetime` or ``NoneType``:\n+            Datetime object parsed from RFC3339 valid timestamp, or\n+            ``None`` if the property is not set locally.\n+\n+        Raises:\n+            ValueError: if value is not a valid RFC3339 timestamp\n         \"\"\"\n         value = self._properties.get('updateTime')\n         if value is not None:\n-            value = _rfc3339_to_datetime(value)\n+            try:\n+                value = datetime.datetime.strptime(\n+                    value, datetime_helpers._RFC3339_MICROS)\n+            except ValueError:\n+                DatetimeNS = datetime_helpers.DatetimeWithNanoseconds\n+                value = DatetimeNS.from_rfc3339(value)\n+            naive = (\n+                value.tzinfo is None\n+                or value.tzinfo.utcoffset(value) is None)\n+            if naive:\n+                value = pytz.utc.localize(value)\n         return value\n \n     def _require_client(self, client):\n", "issue": "Runtimeconfig: Update time fails to parse\nOS: Linux (Debian 4.9.65)\r\nPython: 3.5.3 / 2.7.13\r\nVersion: google-cloud-runtimeconfig==0.28.0, google-cloud==0.32.0\r\n\r\nSteps to reproduce:\r\n1. Using gcloud, set a runtimeconfig variable.\r\n2. In Python, load that variable\r\n3. Try to access its update_time property.\r\n\r\n```pycon\r\n>>> from google.cloud import runtimeconfig\r\n>>> client = runtimeconfig.Client()\r\n>>> config = client.config('testconfig')\r\n>>> var = config.get_variable('foo')\r\n>>> var.update_time\r\nTraceback (most recent call last):\r\n  File \"<stdin>\", line 1, in <module>\r\n  File \"/redacted/lib/python3.5/site-packages/google/cloud/runtimeconfig/variable.py\", line 160, in update_time\r\n    value = _rfc3339_to_datetime(value)\r\n  File \"/redacted/lib/python3.5/site-packages/google/cloud/_helpers.py\", line 274, in _rfc3339_to_datetime\r\n    dt_str, _RFC3339_MICROS).replace(tzinfo=UTC)\r\n  File \"/usr/lib/python3.5/_strptime.py\", line 510, in _strptime_datetime\r\n    tt, fraction = _strptime(data_string, format)\r\n  File \"/usr/lib/python3.5/_strptime.py\", line 343, in _strptime\r\n    (data_string, format))\r\nValueError: time data '2018-01-22T21:39:44.095040522Z' does not match format '%Y-%m-%dT%H:%M:%S.%fZ'\r\n>>> var._properties\r\n{'text': '43', 'updateTime': '2018-01-22T21:39:44.095040522Z'}\r\n```\r\n\r\nObservation: The `%f` format accepts microseconds, not fractions of arbitrary precision. That means six digits at most, but I see nine in the data.\n", "before_files": [{"content": "# Copyright 2016 Google LLC\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\n\"\"\"Create / interact with Google Cloud RuntimeConfig variables.\n\n.. data:: STATE_UNSPECIFIED\n\n    The default variable state.  See\n    https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables#VariableState\n\n.. data:: STATE_UPDATED\n\n    Indicates the variable was updated, while `variables.watch` was executing.\n    See\n    https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables#VariableState\n\n.. data:: STATE_DELETED\n\n    Indicates the variable was deleted, while `variables.watch`_ was executing.\n    See\n    https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables#VariableState\n\n.. _variables.watch:\n    https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables/watch\n\"\"\"\n\nimport base64\n\nfrom google.cloud._helpers import _rfc3339_to_datetime\nfrom google.cloud.exceptions import NotFound\nfrom google.cloud.runtimeconfig._helpers import variable_name_from_full_name\n\n\nSTATE_UNSPECIFIED = 'VARIABLE_STATE_UNSPECIFIED'\nSTATE_UPDATED = 'UPDATED'\nSTATE_DELETED = 'DELETED'\n\n\nclass Variable(object):\n    \"\"\"A variable in the Cloud RuntimeConfig service.\n\n    See\n    https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables\n\n    :type name: str\n    :param name: The name of the variable.  This corresponds to the\n                 unique path of the variable in the config.\n\n    :type config: :class:`google.cloud.runtimeconfig.config.Config`\n    :param config: The config to which this variable belongs.\n    \"\"\"\n\n    def __init__(self, name, config):\n        self.name = name\n        self.config = config\n        self._properties = {}\n\n    @classmethod\n    def from_api_repr(cls, resource, config):\n        \"\"\"Factory:  construct a Variable given its API representation\n\n        :type resource: dict\n        :param resource: change set representation returned from the API.\n\n        :type config: :class:`google.cloud.runtimeconfig.config.Config`\n        :param config: The config to which this variable belongs.\n\n        :rtype: :class:`google.cloud.runtimeconfig.variable.Variable`\n        :returns: Variable parsed from ``resource``.\n        \"\"\"\n        name = variable_name_from_full_name(resource.get('name'))\n        variable = cls(name=name, config=config)\n        variable._set_properties(resource=resource)\n        return variable\n\n    @property\n    def full_name(self):\n        \"\"\"Fully-qualified name of this variable.\n\n        Example:\n        ``projects/my-project/configs/my-config/variables/my-var``\n\n        :rtype: str\n        :returns: The full name based on config and variable names.\n\n        :raises: :class:`ValueError` if the variable is missing a name.\n        \"\"\"\n        if not self.name:\n            raise ValueError('Missing variable name.')\n        return '%s/variables/%s' % (self.config.full_name, self.name)\n\n    @property\n    def path(self):\n        \"\"\"URL path for the variable's APIs.\n\n        :rtype: str\n        :returns: The URL path based on config and variable names.\n        \"\"\"\n        return '/%s' % (self.full_name,)\n\n    @property\n    def client(self):\n        \"\"\"The client bound to this variable.\"\"\"\n        return self.config.client\n\n    @property\n    def value(self):\n        \"\"\"Value of the variable, as bytes.\n\n        See\n        https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables\n\n        :rtype: bytes or ``NoneType``\n        :returns: The value of the variable or ``None`` if the property\n                  is not set locally.\n        \"\"\"\n        value = self._properties.get('value')\n        if value is not None:\n            value = base64.b64decode(value)\n        return value\n\n    @property\n    def state(self):\n        \"\"\"Retrieve the state of the variable.\n\n        See\n        https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables#VariableState\n\n        :rtype: str\n        :returns:\n            If set, one of \"UPDATED\", \"DELETED\", or defaults to\n            \"VARIABLE_STATE_UNSPECIFIED\".\n        \"\"\"\n        return self._properties.get('state', STATE_UNSPECIFIED)\n\n    @property\n    def update_time(self):\n        \"\"\"Retrieve the timestamp at which the variable was updated.\n\n        See\n        https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables\n\n        :rtype: :class:`datetime.datetime` or ``NoneType``\n        :returns: Datetime object parsed from RFC3339 valid timestamp, or\n                  ``None`` if the property is not set locally.\n        \"\"\"\n        value = self._properties.get('updateTime')\n        if value is not None:\n            value = _rfc3339_to_datetime(value)\n        return value\n\n    def _require_client(self, client):\n        \"\"\"Check client or verify over-ride.\n\n        :type client: :class:`google.cloud.runtimconfig.client.Client`\n        :param client:\n            (Optional) The client to use.  If not passed, falls back to the\n            ``client`` stored on the current zone.\n\n        :rtype: :class:`google.cloud.runtimeconfig.client.Client`\n        :returns: The client passed in or the currently bound client.\n        \"\"\"\n        if client is None:\n            client = self.client\n        return client\n\n    def _set_properties(self, resource):\n        \"\"\"Update properties from resource in body of ``api_response``\n\n        :type resource: dict\n        :param resource: variable representation returned from the API.\n        \"\"\"\n        self._properties.clear()\n        cleaned = resource.copy()\n        if 'name' in cleaned:\n            self.name = variable_name_from_full_name(cleaned.pop('name'))\n        self._properties.update(cleaned)\n\n    def exists(self, client=None):\n        \"\"\"API call:  test for the existence of the variable via a GET request\n\n        See\n        https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables/get\n\n        :type client: :class:`~google.cloud.runtimeconfig.client.Client`\n        :param client:\n            (Optional) The client to use.  If not passed, falls back to the\n            ``client`` stored on the variable's config.\n\n        :rtype: bool\n        :returns: True if the variable exists in Cloud RuntimeConfig.\n        \"\"\"\n        client = self._require_client(client)\n        try:\n            # We only need the status code (200 or not) so we seek to\n            # minimize the returned payload.\n            query_params = {'fields': 'name'}\n            client._connection.api_request(method='GET', path=self.path,\n                                           query_params=query_params)\n            return True\n        except NotFound:\n            return False\n\n    def reload(self, client=None):\n        \"\"\"API call:  reload the variable via a ``GET`` request.\n\n        This method will reload the newest data for the variable.\n\n        See\n        https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs/get\n\n        :type client: :class:`google.cloud.runtimeconfig.client.Client`\n        :param client:\n            (Optional) The client to use.  If not passed, falls back to the\n            client stored on the current config.\n        \"\"\"\n        client = self._require_client(client)\n\n        # We assume the variable exists. If it doesn't it will raise a NotFound\n        # exception.\n        resp = client._connection.api_request(method='GET', path=self.path)\n        self._set_properties(resource=resp)\n", "path": "runtimeconfig/google/cloud/runtimeconfig/variable.py"}], "after_files": [{"content": "# Copyright 2016 Google LLC\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\n\"\"\"Create / interact with Google Cloud RuntimeConfig variables.\n\n.. data:: STATE_UNSPECIFIED\n\n    The default variable state.  See\n    https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables#VariableState\n\n.. data:: STATE_UPDATED\n\n    Indicates the variable was updated, while `variables.watch` was executing.\n    See\n    https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables#VariableState\n\n.. data:: STATE_DELETED\n\n    Indicates the variable was deleted, while `variables.watch`_ was executing.\n    See\n    https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables#VariableState\n\n.. _variables.watch:\n    https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables/watch\n\"\"\"\n\nimport base64\nimport datetime\n\nimport pytz\n\nfrom google.api_core import datetime_helpers\nfrom google.cloud.exceptions import NotFound\nfrom google.cloud.runtimeconfig._helpers import variable_name_from_full_name\n\n\nSTATE_UNSPECIFIED = 'VARIABLE_STATE_UNSPECIFIED'\nSTATE_UPDATED = 'UPDATED'\nSTATE_DELETED = 'DELETED'\n\n\nclass Variable(object):\n    \"\"\"A variable in the Cloud RuntimeConfig service.\n\n    See\n    https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables\n\n    :type name: str\n    :param name: The name of the variable.  This corresponds to the\n                 unique path of the variable in the config.\n\n    :type config: :class:`google.cloud.runtimeconfig.config.Config`\n    :param config: The config to which this variable belongs.\n    \"\"\"\n\n    def __init__(self, name, config):\n        self.name = name\n        self.config = config\n        self._properties = {}\n\n    @classmethod\n    def from_api_repr(cls, resource, config):\n        \"\"\"Factory:  construct a Variable given its API representation\n\n        :type resource: dict\n        :param resource: change set representation returned from the API.\n\n        :type config: :class:`google.cloud.runtimeconfig.config.Config`\n        :param config: The config to which this variable belongs.\n\n        :rtype: :class:`google.cloud.runtimeconfig.variable.Variable`\n        :returns: Variable parsed from ``resource``.\n        \"\"\"\n        name = variable_name_from_full_name(resource.get('name'))\n        variable = cls(name=name, config=config)\n        variable._set_properties(resource=resource)\n        return variable\n\n    @property\n    def full_name(self):\n        \"\"\"Fully-qualified name of this variable.\n\n        Example:\n        ``projects/my-project/configs/my-config/variables/my-var``\n\n        :rtype: str\n        :returns: The full name based on config and variable names.\n\n        :raises: :class:`ValueError` if the variable is missing a name.\n        \"\"\"\n        if not self.name:\n            raise ValueError('Missing variable name.')\n        return '%s/variables/%s' % (self.config.full_name, self.name)\n\n    @property\n    def path(self):\n        \"\"\"URL path for the variable's APIs.\n\n        :rtype: str\n        :returns: The URL path based on config and variable names.\n        \"\"\"\n        return '/%s' % (self.full_name,)\n\n    @property\n    def client(self):\n        \"\"\"The client bound to this variable.\"\"\"\n        return self.config.client\n\n    @property\n    def value(self):\n        \"\"\"Value of the variable, as bytes.\n\n        See\n        https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables\n\n        :rtype: bytes or ``NoneType``\n        :returns: The value of the variable or ``None`` if the property\n                  is not set locally.\n        \"\"\"\n        value = self._properties.get('value')\n        if value is not None:\n            value = base64.b64decode(value)\n        return value\n\n    @property\n    def state(self):\n        \"\"\"Retrieve the state of the variable.\n\n        See\n        https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables#VariableState\n\n        :rtype: str\n        :returns:\n            If set, one of \"UPDATED\", \"DELETED\", or defaults to\n            \"VARIABLE_STATE_UNSPECIFIED\".\n        \"\"\"\n        return self._properties.get('state', STATE_UNSPECIFIED)\n\n    @property\n    def update_time(self):\n        \"\"\"Retrieve the timestamp at which the variable was updated.\n\n        See\n        https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables\n\n        Returns:\n            :class:`~api_core.datetime_helpers.DatetimeWithNanoseconds`,\n            :class:`datetime.datetime` or ``NoneType``:\n            Datetime object parsed from RFC3339 valid timestamp, or\n            ``None`` if the property is not set locally.\n\n        Raises:\n            ValueError: if value is not a valid RFC3339 timestamp\n        \"\"\"\n        value = self._properties.get('updateTime')\n        if value is not None:\n            try:\n                value = datetime.datetime.strptime(\n                    value, datetime_helpers._RFC3339_MICROS)\n            except ValueError:\n                DatetimeNS = datetime_helpers.DatetimeWithNanoseconds\n                value = DatetimeNS.from_rfc3339(value)\n            naive = (\n                value.tzinfo is None\n                or value.tzinfo.utcoffset(value) is None)\n            if naive:\n                value = pytz.utc.localize(value)\n        return value\n\n    def _require_client(self, client):\n        \"\"\"Check client or verify over-ride.\n\n        :type client: :class:`google.cloud.runtimconfig.client.Client`\n        :param client:\n            (Optional) The client to use.  If not passed, falls back to the\n            ``client`` stored on the current zone.\n\n        :rtype: :class:`google.cloud.runtimeconfig.client.Client`\n        :returns: The client passed in or the currently bound client.\n        \"\"\"\n        if client is None:\n            client = self.client\n        return client\n\n    def _set_properties(self, resource):\n        \"\"\"Update properties from resource in body of ``api_response``\n\n        :type resource: dict\n        :param resource: variable representation returned from the API.\n        \"\"\"\n        self._properties.clear()\n        cleaned = resource.copy()\n        if 'name' in cleaned:\n            self.name = variable_name_from_full_name(cleaned.pop('name'))\n        self._properties.update(cleaned)\n\n    def exists(self, client=None):\n        \"\"\"API call:  test for the existence of the variable via a GET request\n\n        See\n        https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs.variables/get\n\n        :type client: :class:`~google.cloud.runtimeconfig.client.Client`\n        :param client:\n            (Optional) The client to use.  If not passed, falls back to the\n            ``client`` stored on the variable's config.\n\n        :rtype: bool\n        :returns: True if the variable exists in Cloud RuntimeConfig.\n        \"\"\"\n        client = self._require_client(client)\n        try:\n            # We only need the status code (200 or not) so we seek to\n            # minimize the returned payload.\n            query_params = {'fields': 'name'}\n            client._connection.api_request(method='GET', path=self.path,\n                                           query_params=query_params)\n            return True\n        except NotFound:\n            return False\n\n    def reload(self, client=None):\n        \"\"\"API call:  reload the variable via a ``GET`` request.\n\n        This method will reload the newest data for the variable.\n\n        See\n        https://cloud.google.com/deployment-manager/runtime-configurator/reference/rest/v1beta1/projects.configs/get\n\n        :type client: :class:`google.cloud.runtimeconfig.client.Client`\n        :param client:\n            (Optional) The client to use.  If not passed, falls back to the\n            client stored on the current config.\n        \"\"\"\n        client = self._require_client(client)\n\n        # We assume the variable exists. If it doesn't it will raise a NotFound\n        # exception.\n        resp = client._connection.api_request(method='GET', path=self.path)\n        self._set_properties(resource=resp)\n", "path": "runtimeconfig/google/cloud/runtimeconfig/variable.py"}]}