Cleanup different places using unix_time()
This commit is contained in:
parent
eabcb3d39c
commit
705ec314a3
@ -1,4 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import datetime
|
||||||
import inspect
|
import inspect
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
@ -103,3 +105,14 @@ def iso_8601_datetime_with_milliseconds(datetime):
|
|||||||
def rfc_1123_datetime(datetime):
|
def rfc_1123_datetime(datetime):
|
||||||
RFC1123 = '%a, %d %b %Y %H:%M:%S GMT'
|
RFC1123 = '%a, %d %b %Y %H:%M:%S GMT'
|
||||||
return datetime.strftime(RFC1123)
|
return datetime.strftime(RFC1123)
|
||||||
|
|
||||||
|
|
||||||
|
def unix_time(dt=None):
|
||||||
|
dt = dt or datetime.datetime.utcnow()
|
||||||
|
epoch = datetime.datetime.utcfromtimestamp(0)
|
||||||
|
delta = dt - epoch
|
||||||
|
return (delta.days * 86400) + (delta.seconds + (delta.microseconds / 1e6))
|
||||||
|
|
||||||
|
|
||||||
|
def unix_time_millis(dt=None):
|
||||||
|
return unix_time(dt) * 1000.0
|
||||||
|
@ -5,8 +5,8 @@ import json
|
|||||||
|
|
||||||
from moto.compat import OrderedDict
|
from moto.compat import OrderedDict
|
||||||
from moto.core import BaseBackend
|
from moto.core import BaseBackend
|
||||||
|
from moto.core.utils import unix_time
|
||||||
from .comparisons import get_comparison_func
|
from .comparisons import get_comparison_func
|
||||||
from .utils import unix_time
|
|
||||||
|
|
||||||
|
|
||||||
class DynamoJsonEncoder(json.JSONEncoder):
|
class DynamoJsonEncoder(json.JSONEncoder):
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
from __future__ import unicode_literals
|
|
||||||
import calendar
|
|
||||||
|
|
||||||
|
|
||||||
def unix_time(dt):
|
|
||||||
return calendar.timegm(dt.timetuple())
|
|
@ -5,8 +5,8 @@ import json
|
|||||||
|
|
||||||
from moto.compat import OrderedDict
|
from moto.compat import OrderedDict
|
||||||
from moto.core import BaseBackend
|
from moto.core import BaseBackend
|
||||||
|
from moto.core.utils import unix_time
|
||||||
from .comparisons import get_comparison_func
|
from .comparisons import get_comparison_func
|
||||||
from .utils import unix_time
|
|
||||||
|
|
||||||
|
|
||||||
class DynamoJsonEncoder(json.JSONEncoder):
|
class DynamoJsonEncoder(json.JSONEncoder):
|
||||||
@ -82,7 +82,7 @@ class Item(object):
|
|||||||
attributes = {}
|
attributes = {}
|
||||||
for attribute_key, attribute in self.attrs.items():
|
for attribute_key, attribute in self.attrs.items():
|
||||||
attributes[attribute_key] = {
|
attributes[attribute_key] = {
|
||||||
attribute.type : attribute.value
|
attribute.type: attribute.value
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -204,7 +204,7 @@ class Table(object):
|
|||||||
keys.append(key['AttributeName'])
|
keys.append(key['AttributeName'])
|
||||||
return keys
|
return keys
|
||||||
|
|
||||||
def put_item(self, item_attrs, expected = None, overwrite = False):
|
def put_item(self, item_attrs, expected=None, overwrite=False):
|
||||||
hash_value = DynamoType(item_attrs.get(self.hash_key_attr))
|
hash_value = DynamoType(item_attrs.get(self.hash_key_attr))
|
||||||
if self.has_range_key:
|
if self.has_range_key:
|
||||||
range_value = DynamoType(item_attrs.get(self.range_key_attr))
|
range_value = DynamoType(item_attrs.get(self.range_key_attr))
|
||||||
@ -228,13 +228,13 @@ class Table(object):
|
|||||||
|
|
||||||
if current is None:
|
if current is None:
|
||||||
current_attr = {}
|
current_attr = {}
|
||||||
elif hasattr(current,'attrs'):
|
elif hasattr(current, 'attrs'):
|
||||||
current_attr = current.attrs
|
current_attr = current.attrs
|
||||||
else:
|
else:
|
||||||
current_attr = current
|
current_attr = current
|
||||||
|
|
||||||
for key, val in expected.items():
|
for key, val in expected.items():
|
||||||
if 'Exists' in val and val['Exists'] == False:
|
if 'Exists' in val and val['Exists'] is False:
|
||||||
if key in current_attr:
|
if key in current_attr:
|
||||||
raise ValueError("The conditional request failed")
|
raise ValueError("The conditional request failed")
|
||||||
elif key not in current_attr:
|
elif key not in current_attr:
|
||||||
@ -361,7 +361,7 @@ class DynamoDBBackend(BaseBackend):
|
|||||||
table.throughput = throughput
|
table.throughput = throughput
|
||||||
return table
|
return table
|
||||||
|
|
||||||
def put_item(self, table_name, item_attrs, expected = None, overwrite = False):
|
def put_item(self, table_name, item_attrs, expected=None, overwrite=False):
|
||||||
table = self.tables.get(table_name)
|
table = self.tables.get(table_name)
|
||||||
if not table:
|
if not table:
|
||||||
return None
|
return None
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
from __future__ import unicode_literals
|
|
||||||
import calendar
|
|
||||||
|
|
||||||
|
|
||||||
def unix_time(dt):
|
|
||||||
return calendar.timegm(dt.timetuple())
|
|
@ -8,8 +8,8 @@ from xml.sax.saxutils import escape
|
|||||||
import boto.sqs
|
import boto.sqs
|
||||||
|
|
||||||
from moto.core import BaseBackend
|
from moto.core import BaseBackend
|
||||||
from moto.core.utils import camelcase_to_underscores, get_random_message_id
|
from moto.core.utils import camelcase_to_underscores, get_random_message_id, unix_time_millis
|
||||||
from .utils import generate_receipt_handle, unix_time_millis
|
from .utils import generate_receipt_handle
|
||||||
from .exceptions import (
|
from .exceptions import (
|
||||||
ReceiptHandleIsInvalid,
|
ReceiptHandleIsInvalid,
|
||||||
MessageNotInflight
|
MessageNotInflight
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import datetime
|
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
|
|
||||||
@ -12,17 +11,6 @@ def generate_receipt_handle():
|
|||||||
return ''.join(random.choice(string.ascii_lowercase) for x in range(length))
|
return ''.join(random.choice(string.ascii_lowercase) for x in range(length))
|
||||||
|
|
||||||
|
|
||||||
def unix_time(dt=None):
|
|
||||||
dt = dt or datetime.datetime.utcnow()
|
|
||||||
epoch = datetime.datetime.utcfromtimestamp(0)
|
|
||||||
delta = dt - epoch
|
|
||||||
return (delta.days * 86400) + (delta.seconds + (delta.microseconds / 1e6))
|
|
||||||
|
|
||||||
|
|
||||||
def unix_time_millis(dt=None):
|
|
||||||
return unix_time(dt) * 1000.0
|
|
||||||
|
|
||||||
|
|
||||||
def parse_message_attributes(querystring, base='', value_namespace='Value.'):
|
def parse_message_attributes(querystring, base='', value_namespace='Value.'):
|
||||||
message_attributes = {}
|
message_attributes = {}
|
||||||
index = 1
|
index = 1
|
||||||
|
@ -2,8 +2,8 @@ from __future__ import unicode_literals
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from moto.core.utils import unix_time
|
||||||
from ..exceptions import SWFWorkflowExecutionClosedError
|
from ..exceptions import SWFWorkflowExecutionClosedError
|
||||||
from ..utils import now_timestamp
|
|
||||||
|
|
||||||
from .timeout import Timeout
|
from .timeout import Timeout
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ class ActivityTask(object):
|
|||||||
self.activity_type = activity_type
|
self.activity_type = activity_type
|
||||||
self.details = None
|
self.details = None
|
||||||
self.input = input
|
self.input = input
|
||||||
self.last_heartbeat_timestamp = now_timestamp()
|
self.last_heartbeat_timestamp = unix_time()
|
||||||
self.scheduled_event_id = scheduled_event_id
|
self.scheduled_event_id = scheduled_event_id
|
||||||
self.started_event_id = None
|
self.started_event_id = None
|
||||||
self.state = "SCHEDULED"
|
self.state = "SCHEDULED"
|
||||||
@ -60,19 +60,18 @@ class ActivityTask(object):
|
|||||||
self.state = "FAILED"
|
self.state = "FAILED"
|
||||||
|
|
||||||
def reset_heartbeat_clock(self):
|
def reset_heartbeat_clock(self):
|
||||||
self.last_heartbeat_timestamp = now_timestamp()
|
self.last_heartbeat_timestamp = unix_time()
|
||||||
|
|
||||||
def first_timeout(self):
|
def first_timeout(self):
|
||||||
if not self.open or not self.workflow_execution.open:
|
if not self.open or not self.workflow_execution.open:
|
||||||
return None
|
return None
|
||||||
# TODO: handle the "NONE" case
|
# TODO: handle the "NONE" case
|
||||||
heartbeat_timeout_at = self.last_heartbeat_timestamp + \
|
heartbeat_timeout_at = (self.last_heartbeat_timestamp +
|
||||||
int(self.timeouts["heartbeatTimeout"])
|
int(self.timeouts["heartbeatTimeout"]))
|
||||||
_timeout = Timeout(self, heartbeat_timeout_at, "HEARTBEAT")
|
_timeout = Timeout(self, heartbeat_timeout_at, "HEARTBEAT")
|
||||||
if _timeout.reached:
|
if _timeout.reached:
|
||||||
return _timeout
|
return _timeout
|
||||||
|
|
||||||
|
|
||||||
def process_timeouts(self):
|
def process_timeouts(self):
|
||||||
_timeout = self.first_timeout()
|
_timeout = self.first_timeout()
|
||||||
if _timeout:
|
if _timeout:
|
||||||
|
@ -2,8 +2,8 @@ from __future__ import unicode_literals
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from moto.core.utils import unix_time
|
||||||
from ..exceptions import SWFWorkflowExecutionClosedError
|
from ..exceptions import SWFWorkflowExecutionClosedError
|
||||||
from ..utils import now_timestamp
|
|
||||||
|
|
||||||
from .timeout import Timeout
|
from .timeout import Timeout
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ class DecisionTask(object):
|
|||||||
|
|
||||||
def start(self, started_event_id):
|
def start(self, started_event_id):
|
||||||
self.state = "STARTED"
|
self.state = "STARTED"
|
||||||
self.started_timestamp = now_timestamp()
|
self.started_timestamp = unix_time()
|
||||||
self.started_event_id = started_event_id
|
self.started_event_id = started_event_id
|
||||||
|
|
||||||
def complete(self):
|
def complete(self):
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from datetime import datetime
|
|
||||||
from time import mktime
|
|
||||||
|
|
||||||
from moto.core.utils import underscores_to_camelcase
|
from moto.core.utils import underscores_to_camelcase, unix_time
|
||||||
|
|
||||||
from ..utils import decapitalize, now_timestamp
|
from ..utils import decapitalize
|
||||||
|
|
||||||
|
|
||||||
# We keep track of which history event types we support
|
# We keep track of which history event types we support
|
||||||
@ -28,6 +26,7 @@ SUPPORTED_HISTORY_EVENT_TYPES = (
|
|||||||
"WorkflowExecutionTimedOut",
|
"WorkflowExecutionTimedOut",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class HistoryEvent(object):
|
class HistoryEvent(object):
|
||||||
def __init__(self, event_id, event_type, event_timestamp=None, **kwargs):
|
def __init__(self, event_id, event_type, event_timestamp=None, **kwargs):
|
||||||
if event_type not in SUPPORTED_HISTORY_EVENT_TYPES:
|
if event_type not in SUPPORTED_HISTORY_EVENT_TYPES:
|
||||||
@ -39,16 +38,16 @@ class HistoryEvent(object):
|
|||||||
if event_timestamp:
|
if event_timestamp:
|
||||||
self.event_timestamp = event_timestamp
|
self.event_timestamp = event_timestamp
|
||||||
else:
|
else:
|
||||||
self.event_timestamp = now_timestamp()
|
self.event_timestamp = unix_time()
|
||||||
# pre-populate a dict: {"camelCaseKey": value}
|
# pre-populate a dict: {"camelCaseKey": value}
|
||||||
self.event_attributes = {}
|
self.event_attributes = {}
|
||||||
for key, value in kwargs.items():
|
for key, value in kwargs.items():
|
||||||
if value:
|
if value:
|
||||||
camel_key = underscores_to_camelcase(key)
|
camel_key = underscores_to_camelcase(key)
|
||||||
if key == "task_list":
|
if key == "task_list":
|
||||||
value = { "name": value }
|
value = {"name": value}
|
||||||
elif key == "workflow_type":
|
elif key == "workflow_type":
|
||||||
value = { "name": value.name, "version": value.version }
|
value = {"name": value.name, "version": value.version}
|
||||||
elif key == "activity_type":
|
elif key == "activity_type":
|
||||||
value = value.to_short_dict()
|
value = value.to_short_dict()
|
||||||
self.event_attributes[camel_key] = value
|
self.event_attributes[camel_key] = value
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from ..utils import now_timestamp
|
from moto.core.utils import unix_time
|
||||||
|
|
||||||
|
|
||||||
class Timeout(object):
|
class Timeout(object):
|
||||||
@ -9,4 +9,4 @@ class Timeout(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def reached(self):
|
def reached(self):
|
||||||
return now_timestamp() >= self.timestamp
|
return unix_time() >= self.timestamp
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from datetime import datetime
|
|
||||||
from time import mktime
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from moto.core.utils import camelcase_to_underscores
|
from moto.core.utils import camelcase_to_underscores, unix_time
|
||||||
|
|
||||||
from ..constants import (
|
from ..constants import (
|
||||||
DECISIONS_FIELDS,
|
DECISIONS_FIELDS,
|
||||||
@ -13,7 +11,7 @@ from ..exceptions import (
|
|||||||
SWFValidationException,
|
SWFValidationException,
|
||||||
SWFDecisionValidationException,
|
SWFDecisionValidationException,
|
||||||
)
|
)
|
||||||
from ..utils import decapitalize, now_timestamp
|
from ..utils import decapitalize
|
||||||
from .activity_task import ActivityTask
|
from .activity_task import ActivityTask
|
||||||
from .activity_type import ActivityType
|
from .activity_type import ActivityType
|
||||||
from .decision_task import DecisionTask
|
from .decision_task import DecisionTask
|
||||||
@ -59,7 +57,7 @@ class WorkflowExecution(object):
|
|||||||
self.latest_execution_context = None
|
self.latest_execution_context = None
|
||||||
self.parent = None
|
self.parent = None
|
||||||
self.start_timestamp = None
|
self.start_timestamp = None
|
||||||
self.tag_list = [] # TODO
|
self.tag_list = [] # TODO
|
||||||
self.timeout_type = None
|
self.timeout_type = None
|
||||||
self.workflow_type = workflow_type
|
self.workflow_type = workflow_type
|
||||||
# args processing
|
# args processing
|
||||||
@ -89,7 +87,7 @@ class WorkflowExecution(object):
|
|||||||
|
|
||||||
def _set_from_kwargs_or_workflow_type(self, kwargs, local_key, workflow_type_key=None):
|
def _set_from_kwargs_or_workflow_type(self, kwargs, local_key, workflow_type_key=None):
|
||||||
if workflow_type_key is None:
|
if workflow_type_key is None:
|
||||||
workflow_type_key = "default_"+local_key
|
workflow_type_key = "default_" + local_key
|
||||||
value = kwargs.get(local_key)
|
value = kwargs.get(local_key)
|
||||||
if not value and hasattr(self.workflow_type, workflow_type_key):
|
if not value and hasattr(self.workflow_type, workflow_type_key):
|
||||||
value = getattr(self.workflow_type, workflow_type_key)
|
value = getattr(self.workflow_type, workflow_type_key)
|
||||||
@ -131,7 +129,7 @@ class WorkflowExecution(object):
|
|||||||
"taskList": {"name": self.task_list}
|
"taskList": {"name": self.task_list}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#configuration
|
# configuration
|
||||||
for key in self._configuration_keys:
|
for key in self._configuration_keys:
|
||||||
attr = camelcase_to_underscores(key)
|
attr = camelcase_to_underscores(key)
|
||||||
if not hasattr(self, attr):
|
if not hasattr(self, attr):
|
||||||
@ -139,9 +137,9 @@ class WorkflowExecution(object):
|
|||||||
if not getattr(self, attr):
|
if not getattr(self, attr):
|
||||||
continue
|
continue
|
||||||
hsh["executionConfiguration"][key] = getattr(self, attr)
|
hsh["executionConfiguration"][key] = getattr(self, attr)
|
||||||
#counters
|
# counters
|
||||||
hsh["openCounts"] = self.open_counts
|
hsh["openCounts"] = self.open_counts
|
||||||
#latest things
|
# latest things
|
||||||
if self.latest_execution_context:
|
if self.latest_execution_context:
|
||||||
hsh["latestExecutionContext"] = self.latest_execution_context
|
hsh["latestExecutionContext"] = self.latest_execution_context
|
||||||
if self.latest_activity_task_timestamp:
|
if self.latest_activity_task_timestamp:
|
||||||
@ -225,7 +223,7 @@ class WorkflowExecution(object):
|
|||||||
return evt
|
return evt
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.start_timestamp = now_timestamp()
|
self.start_timestamp = unix_time()
|
||||||
self._add_event(
|
self._add_event(
|
||||||
"WorkflowExecutionStarted",
|
"WorkflowExecutionStarted",
|
||||||
child_policy=self.child_policy,
|
child_policy=self.child_policy,
|
||||||
@ -403,7 +401,7 @@ class WorkflowExecution(object):
|
|||||||
def complete(self, event_id, result=None):
|
def complete(self, event_id, result=None):
|
||||||
self.execution_status = "CLOSED"
|
self.execution_status = "CLOSED"
|
||||||
self.close_status = "COMPLETED"
|
self.close_status = "COMPLETED"
|
||||||
self.close_timestamp = now_timestamp()
|
self.close_timestamp = unix_time()
|
||||||
self._add_event(
|
self._add_event(
|
||||||
"WorkflowExecutionCompleted",
|
"WorkflowExecutionCompleted",
|
||||||
decision_task_completed_event_id=event_id,
|
decision_task_completed_event_id=event_id,
|
||||||
@ -414,7 +412,7 @@ class WorkflowExecution(object):
|
|||||||
# TODO: implement lenght constraints on details/reason
|
# TODO: implement lenght constraints on details/reason
|
||||||
self.execution_status = "CLOSED"
|
self.execution_status = "CLOSED"
|
||||||
self.close_status = "FAILED"
|
self.close_status = "FAILED"
|
||||||
self.close_timestamp = now_timestamp()
|
self.close_timestamp = unix_time()
|
||||||
self._add_event(
|
self._add_event(
|
||||||
"WorkflowExecutionFailed",
|
"WorkflowExecutionFailed",
|
||||||
decision_task_completed_event_id=event_id,
|
decision_task_completed_event_id=event_id,
|
||||||
@ -470,7 +468,7 @@ class WorkflowExecution(object):
|
|||||||
# find timeouts or default timeout, else fail
|
# find timeouts or default timeout, else fail
|
||||||
timeouts = {}
|
timeouts = {}
|
||||||
for _type in ["scheduleToStartTimeout", "scheduleToCloseTimeout", "startToCloseTimeout", "heartbeatTimeout"]:
|
for _type in ["scheduleToStartTimeout", "scheduleToCloseTimeout", "startToCloseTimeout", "heartbeatTimeout"]:
|
||||||
default_key = "default_task_"+camelcase_to_underscores(_type)
|
default_key = "default_task_" + camelcase_to_underscores(_type)
|
||||||
default_value = getattr(activity_type, default_key)
|
default_value = getattr(activity_type, default_key)
|
||||||
timeouts[_type] = attributes.get(_type, default_value)
|
timeouts[_type] = attributes.get(_type, default_value)
|
||||||
if not timeouts[_type]:
|
if not timeouts[_type]:
|
||||||
@ -504,7 +502,7 @@ class WorkflowExecution(object):
|
|||||||
)
|
)
|
||||||
self.domain.add_to_activity_task_list(task_list, task)
|
self.domain.add_to_activity_task_list(task_list, task)
|
||||||
self.open_counts["openActivityTasks"] += 1
|
self.open_counts["openActivityTasks"] += 1
|
||||||
self.latest_activity_task_timestamp = now_timestamp()
|
self.latest_activity_task_timestamp = unix_time()
|
||||||
|
|
||||||
def _find_activity_task(self, task_token):
|
def _find_activity_task(self, task_token):
|
||||||
for task in self.activity_tasks:
|
for task in self.activity_tasks:
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
from datetime import datetime
|
|
||||||
from time import mktime
|
|
||||||
|
|
||||||
|
|
||||||
def decapitalize(key):
|
def decapitalize(key):
|
||||||
return key[0].lower() + key[1:]
|
return key[0].lower() + key[1:]
|
||||||
|
|
||||||
def now_timestamp():
|
|
||||||
return float(mktime(datetime.utcnow().timetuple()))
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import sure
|
|
||||||
|
|
||||||
from moto.core.utils import camelcase_to_underscores, underscores_to_camelcase
|
import sure # noqa
|
||||||
|
from freezegun import freeze_time
|
||||||
|
|
||||||
|
from moto.core.utils import camelcase_to_underscores, underscores_to_camelcase, unix_time
|
||||||
|
|
||||||
|
|
||||||
def test_camelcase_to_underscores():
|
def test_camelcase_to_underscores():
|
||||||
@ -20,3 +22,8 @@ def test_underscores_to_camelcase():
|
|||||||
}
|
}
|
||||||
for arg, expected in cases.items():
|
for arg, expected in cases.items():
|
||||||
underscores_to_camelcase(arg).should.equal(expected)
|
underscores_to_camelcase(arg).should.equal(expected)
|
||||||
|
|
||||||
|
|
||||||
|
@freeze_time("2015-01-01 12:00:00")
|
||||||
|
def test_unix_time():
|
||||||
|
unix_time().should.equal(1420113600.0)
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
from freezegun import freeze_time
|
import sure # noqa
|
||||||
from sure import expect
|
|
||||||
|
|
||||||
from moto.swf.utils import (
|
from moto.swf.utils import decapitalize
|
||||||
decapitalize,
|
|
||||||
now_timestamp,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_decapitalize():
|
def test_decapitalize():
|
||||||
@ -15,7 +11,3 @@ def test_decapitalize():
|
|||||||
}
|
}
|
||||||
for before, after in cases.items():
|
for before, after in cases.items():
|
||||||
decapitalize(before).should.equal(after)
|
decapitalize(before).should.equal(after)
|
||||||
|
|
||||||
@freeze_time("2015-01-01 12:00:00")
|
|
||||||
def test_now_timestamp():
|
|
||||||
now_timestamp().should.equal(1420113600.0)
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user