Skip to content

Commit

Permalink
Moving _pb_timestamp_to_datetime into core.
Browse files Browse the repository at this point in the history
This is in advance of `v1beta3`, where it will be needed
to parse `Value.timestamp_value` (which is of type
`timestamp_pb2.Timestamp`). Also adding `_datetime_to_pb_timestamp`
for the other direction.
  • Loading branch information
dhermes committed Jan 7, 2016
1 parent 8edeeb9 commit 01c3d91
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 41 deletions.
34 changes: 34 additions & 0 deletions gcloud/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import socket
import sys

from google.protobuf import timestamp_pb2

This comment has been minimized.

Copy link
@tseaver

tseaver Jan 14, 2016

I'm missing how that module is being generated under the changes for googleapis#1353: are we relying on it being importable from a dependency, somehow?

This comment has been minimized.

Copy link
@dhermes

dhermes Jan 14, 2016

Author Owner

It ships with https://pypi.python.org/pypi/protobuf in the latest version (3.0.0b2). I should've updated setup.py, good find.

This comment has been minimized.

Copy link
@dhermes

dhermes Jan 14, 2016

Author Owner

Scratch that, one of the commits this has as a diffbase already upgraded setup.py.

import six
from six.moves.http_client import HTTPConnection # pylint: disable=F0401

Expand Down Expand Up @@ -329,6 +330,39 @@ def _to_bytes(value, encoding='ascii'):
raise TypeError('%r could not be converted to bytes' % (value,))


def _pb_timestamp_to_datetime(timestamp):
"""Convert a Timestamp protobuf to a datetime object.
:type timestamp: :class:`google.protobuf.timestamp_pb2.Timestamp`
:param timestamp: A Google returned timestamp protobuf.
:rtype: :class:`datetime.datetime`
:returns: A UTC datetime object converted from a protobuf timestamp.
"""
return (
_EPOCH +
datetime.timedelta(
seconds=timestamp.seconds,
microseconds=(timestamp.nanos / 1000.0),
)
)


def _datetime_to_pb_timestamp(when):
"""Convert a datetime object to a Timestamp protobuf.
:type when: :class:`datetime.datetime`
:param when: the datetime to convert
:rtype: :class:`google.protobuf.timestamp_pb2.Timestamp`
:returns: A timestamp protobuf corresponding to the object.
"""
ms_value = _microseconds_from_datetime(when)
seconds, micros = divmod(ms_value, 10**6)
nanos = micros * 10**3
return timestamp_pb2.Timestamp(seconds=seconds, nanos=nanos)


try:
from pytz import UTC # pylint: disable=unused-import,wrong-import-position
except ImportError:
Expand Down
21 changes: 1 addition & 20 deletions gcloud/bigtable/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@
"""User friendly container for Google Cloud Bigtable Cluster."""


import datetime
import re

from google.longrunning import operations_pb2

from gcloud._helpers import _EPOCH
from gcloud._helpers import _pb_timestamp_to_datetime
from gcloud.bigtable._generated import bigtable_cluster_data_pb2 as data_pb2
from gcloud.bigtable._generated import (
bigtable_cluster_service_messages_pb2 as messages_pb2)
Expand Down Expand Up @@ -93,24 +92,6 @@ def _prepare_create_request(cluster):
)


def _pb_timestamp_to_datetime(timestamp):
"""Convert a Timestamp protobuf to a datetime object.
:type timestamp: :class:`google.protobuf.timestamp_pb2.Timestamp`
:param timestamp: A Google returned timestamp protobuf.
:rtype: :class:`datetime.datetime`
:returns: A UTC datetime object converted from a protobuf timestamp.
"""
return (
_EPOCH +
datetime.timedelta(
seconds=timestamp.seconds,
microseconds=(timestamp.nanos / 1000.0),
)
)


def _parse_pb_any_to_native(any_val, expected_type=None):
"""Convert a serialized "google.protobuf.Any" value to actual type.
Expand Down
21 changes: 0 additions & 21 deletions gcloud/bigtable/test_cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -686,27 +686,6 @@ def test_it(self):
self.assertEqual(request_pb.cluster.serve_nodes, serve_nodes)


class Test__pb_timestamp_to_datetime(unittest2.TestCase):

def _callFUT(self, timestamp):
from gcloud.bigtable.cluster import _pb_timestamp_to_datetime
return _pb_timestamp_to_datetime(timestamp)

def test_it(self):
import datetime
from google.protobuf.timestamp_pb2 import Timestamp
from gcloud._helpers import UTC

# Epoch is midnight on January 1, 1970 ...
dt_stamp = datetime.datetime(1970, month=1, day=1, hour=0,
minute=1, second=1, microsecond=1234,
tzinfo=UTC)
# ... so 1 minute and 1 second after is 61 seconds and 1234
# microseconds is 1234000 nanoseconds.
timestamp = Timestamp(seconds=61, nanos=1234000)
self.assertEqual(self._callFUT(timestamp), dt_stamp)


class Test__parse_pb_any_to_native(unittest2.TestCase):

def _callFUT(self, any_val, expected_type=None):
Expand Down
42 changes: 42 additions & 0 deletions gcloud/test__helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,48 @@ def test_with_nonstring_type(self):
self.assertRaises(TypeError, self._callFUT, value)


class Test__pb_timestamp_to_datetime(unittest2.TestCase):

def _callFUT(self, timestamp):
from gcloud._helpers import _pb_timestamp_to_datetime
return _pb_timestamp_to_datetime(timestamp)

def test_it(self):
import datetime
from google.protobuf.timestamp_pb2 import Timestamp
from gcloud._helpers import UTC

# Epoch is midnight on January 1, 1970 ...
dt_stamp = datetime.datetime(1970, month=1, day=1, hour=0,
minute=1, second=1, microsecond=1234,
tzinfo=UTC)
# ... so 1 minute and 1 second after is 61 seconds and 1234
# microseconds is 1234000 nanoseconds.
timestamp = Timestamp(seconds=61, nanos=1234000)
self.assertEqual(self._callFUT(timestamp), dt_stamp)


class Test__datetime_to_pb_timestamp(unittest2.TestCase):

def _callFUT(self, when):
from gcloud._helpers import _datetime_to_pb_timestamp
return _datetime_to_pb_timestamp(when)

def test_it(self):
import datetime
from google.protobuf.timestamp_pb2 import Timestamp
from gcloud._helpers import UTC

# Epoch is midnight on January 1, 1970 ...
dt_stamp = datetime.datetime(1970, month=1, day=1, hour=0,
minute=1, second=1, microsecond=1234,
tzinfo=UTC)
# ... so 1 minute and 1 second after is 61 seconds and 1234
# microseconds is 1234000 nanoseconds.
timestamp = Timestamp(seconds=61, nanos=1234000)
self.assertEqual(self._callFUT(dt_stamp), timestamp)


class _AppIdentity(object):

def __init__(self, app_id):
Expand Down

1 comment on commit 01c3d91

@tseaver
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except for the question about the source of google.protos.timestamp_pb, this commit LGTM.

Please sign in to comment.