mirror of
https://github.com/kennethreitz/pipenv.git
synced 2026-06-05 22:50:18 +00:00
Purge strict-rfc3339 and timestamp from prettytoml
And replace the date/time dumping with built-in datetime operations.
This commit is contained in:
@@ -5,11 +5,8 @@ A converter of python values to TOML Token instances.
|
||||
import codecs
|
||||
import datetime
|
||||
import six
|
||||
import strict_rfc3339
|
||||
import timestamp
|
||||
from prettytoml import tokens
|
||||
import re
|
||||
from prettytoml.elements.metadata import NewlineElement
|
||||
from prettytoml.errors import TOMLError
|
||||
from prettytoml.tokens import Token
|
||||
from prettytoml.util import chunkate_string
|
||||
@@ -49,8 +46,10 @@ def create_primitive_token(value, multiline_strings_allowed=True):
|
||||
elif isinstance(value, float):
|
||||
return tokens.Token(tokens.TYPE_FLOAT, u'{}'.format(value))
|
||||
elif isinstance(value, (datetime.datetime, datetime.date, datetime.time)):
|
||||
ts = timestamp(value) // 1000
|
||||
return tokens.Token(tokens.TYPE_DATE, strict_rfc3339.timestamp_to_rfc3339_utcoffset(ts))
|
||||
s = value.isoformat()
|
||||
if s.endswith('+00:00'):
|
||||
s = s[:-6] + 'Z'
|
||||
return tokens.Token(tokens.TYPE_DATE, s)
|
||||
elif isinstance(value, six.string_types):
|
||||
return create_string_token(value, multiline_strings_allowed=multiline_strings_allowed)
|
||||
|
||||
|
||||
Vendored
-202
@@ -1,202 +0,0 @@
|
||||
# Copyright 2012 (C) Daniel Richman, Adam Greig
|
||||
#
|
||||
# This file is part of strict_rfc3339.
|
||||
#
|
||||
# strict_rfc3339 is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# strict_rfc3339 is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with strict_rfc3339. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
Super simple lightweight RFC3339 functions
|
||||
"""
|
||||
|
||||
import re
|
||||
import time
|
||||
import calendar
|
||||
|
||||
__all__ = ["validate_rfc3339",
|
||||
"InvalidRFC3339Error",
|
||||
"rfc3339_to_timestamp",
|
||||
"timestamp_to_rfc3339_utcoffset",
|
||||
"timestamp_to_rfc3339_localoffset",
|
||||
"now_to_rfc3339_utcoffset",
|
||||
"now_to_rfc3339_localoffset"]
|
||||
|
||||
rfc3339_regex = re.compile(
|
||||
r"^(\d\d\d\d)\-(\d\d)\-(\d\d)T"
|
||||
r"(\d\d):(\d\d):(\d\d)(\.\d+)?(Z|([+\-])(\d\d):(\d\d))$")
|
||||
|
||||
|
||||
def validate_rfc3339(datestring):
|
||||
"""Check an RFC3339 string is valid via a regex and some range checks"""
|
||||
|
||||
m = rfc3339_regex.match(datestring)
|
||||
if m is None:
|
||||
return False
|
||||
|
||||
groups = m.groups()
|
||||
|
||||
year, month, day, hour, minute, second = [int(i) for i in groups[:6]]
|
||||
|
||||
if not 1 <= year <= 9999:
|
||||
# Have to reject this, unfortunately (despite it being OK by rfc3339):
|
||||
# calendar.timegm/calendar.monthrange can't cope (since datetime can't)
|
||||
return False
|
||||
|
||||
if not 1 <= month <= 12:
|
||||
return False
|
||||
|
||||
(_, max_day) = calendar.monthrange(year, month)
|
||||
if not 1 <= day <= max_day:
|
||||
return False
|
||||
|
||||
if not (0 <= hour <= 23 and 0 <= minute <= 59 and 0 <= second <= 59):
|
||||
# forbid leap seconds :-(. See README
|
||||
return False
|
||||
|
||||
if groups[7] != "Z":
|
||||
(offset_sign, offset_hours, offset_mins) = groups[8:]
|
||||
if not (0 <= int(offset_hours) <= 23 and 0 <= int(offset_mins) <= 59):
|
||||
return False
|
||||
|
||||
# all OK
|
||||
return True
|
||||
|
||||
|
||||
class InvalidRFC3339Error(ValueError):
|
||||
"""Subclass of ValueError thrown by rfc3339_to_timestamp"""
|
||||
pass
|
||||
|
||||
|
||||
def rfc3339_to_timestamp(datestring):
|
||||
"""Convert an RFC3339 date-time string to a UTC UNIX timestamp"""
|
||||
|
||||
if not validate_rfc3339(datestring):
|
||||
raise InvalidRFC3339Error
|
||||
|
||||
groups = rfc3339_regex.match(datestring).groups()
|
||||
|
||||
time_tuple = [int(p) for p in groups[:6]]
|
||||
timestamp = calendar.timegm(time_tuple)
|
||||
|
||||
seconds_part = groups[6]
|
||||
if seconds_part is not None:
|
||||
timestamp += float("0" + seconds_part)
|
||||
|
||||
if groups[7] != "Z":
|
||||
(offset_sign, offset_hours, offset_mins) = groups[8:]
|
||||
offset_seconds = int(offset_hours) * 3600 + int(offset_mins) * 60
|
||||
if offset_sign == '-':
|
||||
offset_seconds = -offset_seconds
|
||||
timestamp -= offset_seconds
|
||||
|
||||
return timestamp
|
||||
|
||||
|
||||
def _seconds_and_microseconds(timestamp):
|
||||
"""
|
||||
Split a floating point timestamp into an integer number of seconds since
|
||||
the epoch, and an integer number of microseconds (having rounded to the
|
||||
nearest microsecond).
|
||||
|
||||
If `_seconds_and_microseconds(x) = (y, z)` then the following holds (up to
|
||||
the error introduced by floating point operations):
|
||||
|
||||
* `x = y + z / 1_000_000.`
|
||||
* `0 <= z < 1_000_000.`
|
||||
"""
|
||||
|
||||
if isinstance(timestamp, int):
|
||||
return (timestamp, 0)
|
||||
else:
|
||||
timestamp_us = int(round(timestamp * 1e6))
|
||||
return divmod(timestamp_us, 1000000)
|
||||
|
||||
def _make_datestring_start(time_tuple, microseconds):
|
||||
ds_format = "{0:04d}-{1:02d}-{2:02d}T{3:02d}:{4:02d}:{5:02d}"
|
||||
datestring = ds_format.format(*time_tuple)
|
||||
|
||||
seconds_part_str = "{0:06d}".format(microseconds)
|
||||
# There used to be a bug here where it could be 1000000
|
||||
assert len(seconds_part_str) == 6 and seconds_part_str[0] != '-'
|
||||
seconds_part_str = seconds_part_str.rstrip("0")
|
||||
if seconds_part_str != "":
|
||||
datestring += "." + seconds_part_str
|
||||
|
||||
return datestring
|
||||
|
||||
|
||||
def timestamp_to_rfc3339_utcoffset(timestamp):
|
||||
"""Convert a UTC UNIX timestamp to RFC3339, with the offset as 'Z'"""
|
||||
|
||||
seconds, microseconds = _seconds_and_microseconds(timestamp)
|
||||
|
||||
time_tuple = time.gmtime(seconds)
|
||||
datestring = _make_datestring_start(time_tuple, microseconds)
|
||||
datestring += "Z"
|
||||
|
||||
assert abs(rfc3339_to_timestamp(datestring) - timestamp) < 0.000001
|
||||
return datestring
|
||||
|
||||
|
||||
def timestamp_to_rfc3339_localoffset(timestamp):
|
||||
"""
|
||||
Convert a UTC UNIX timestamp to RFC3339, using the local offset.
|
||||
|
||||
localtime() provides the time parts. The difference between gmtime and
|
||||
localtime tells us the offset.
|
||||
"""
|
||||
|
||||
seconds, microseconds = _seconds_and_microseconds(timestamp)
|
||||
|
||||
time_tuple = time.localtime(seconds)
|
||||
datestring = _make_datestring_start(time_tuple, microseconds)
|
||||
|
||||
gm_time_tuple = time.gmtime(seconds)
|
||||
offset = calendar.timegm(time_tuple) - calendar.timegm(gm_time_tuple)
|
||||
|
||||
if abs(offset) % 60 != 0:
|
||||
raise ValueError("Your local offset is not a whole minute")
|
||||
|
||||
offset_minutes = abs(offset) // 60
|
||||
offset_hours = offset_minutes // 60
|
||||
offset_minutes %= 60
|
||||
|
||||
offset_string = "{0:02d}:{1:02d}".format(offset_hours, offset_minutes)
|
||||
|
||||
if offset < 0:
|
||||
datestring += "-"
|
||||
else:
|
||||
datestring += "+"
|
||||
|
||||
datestring += offset_string
|
||||
assert abs(rfc3339_to_timestamp(datestring) - timestamp) < 0.000001
|
||||
|
||||
return datestring
|
||||
|
||||
|
||||
def now_to_rfc3339_utcoffset(integer=True):
|
||||
"""Convert the current time to RFC3339, with the offset as 'Z'"""
|
||||
|
||||
timestamp = time.time()
|
||||
if integer:
|
||||
timestamp = int(timestamp)
|
||||
return timestamp_to_rfc3339_utcoffset(timestamp)
|
||||
|
||||
|
||||
def now_to_rfc3339_localoffset(integer=True):
|
||||
"""Convert the current time to RFC3339, using the local offset."""
|
||||
|
||||
timestamp = time.time()
|
||||
if integer:
|
||||
timestamp = int(timestamp)
|
||||
return timestamp_to_rfc3339_localoffset(timestamp)
|
||||
Vendored
-9
@@ -1,9 +0,0 @@
|
||||
import sys
|
||||
|
||||
def timestamp(d=None):
|
||||
import datetime
|
||||
import time
|
||||
return int(time.mktime(d.timetuple()) * 1000) if d else int(time.time() * 1000)
|
||||
|
||||
sys.modules[__name__] = timestamp
|
||||
|
||||
Reference in New Issue
Block a user