Browse Source

Move time parsing from cmdline into nilmdb.utils.time

tags/nilmdb-1.2
Jim Paris 11 years ago
parent
commit
e3f335dfe5
7 changed files with 81 additions and 76 deletions
  1. +2
    -54
      nilmdb/cmdline/cmdline.py
  2. +1
    -1
      nilmdb/cmdline/extract.py
  3. +2
    -1
      nilmdb/cmdline/insert.py
  4. +2
    -1
      nilmdb/cmdline/list.py
  5. +54
    -0
      nilmdb/utils/time.py
  6. +1
    -0
      nilmdb/utils/timer.py
  7. +19
    -19
      tests/test_cmdline.py

+ 2
- 54
nilmdb/cmdline/cmdline.py View File

@@ -3,9 +3,9 @@
import nilmdb
from nilmdb.utils.printf import *
from nilmdb.utils import datetime_tz
import nilmdb.utils.time

import sys
import re
import argparse
from argparse import ArgumentDefaultsHelpFormatter as def_form

@@ -33,63 +33,11 @@ class Cmdline(object):
def arg_time(self, toparse):
"""Parse a time string argument"""
try:
return self.parse_time(toparse).totimestamp()
return nilmdb.utils.time.parse_time(toparse).totimestamp()
except ValueError as e:
raise argparse.ArgumentTypeError(sprintf("%s \"%s\"",
str(e), toparse))

def parse_time(self, toparse):
"""
Parse a free-form time string and return a datetime_tz object.
If the string doesn't contain a timestamp, the current local
timezone is assumed (e.g. from the TZ env var).
"""
# If string isn't "now" and doesn't contain at least 4 digits,
# consider it invalid. smartparse might otherwise accept
# empty strings and strings with just separators.
if toparse != "now" and len(re.findall(r"\d", toparse)) < 4:
raise ValueError("not enough digits for a timestamp")

# Try to just parse the time as given
try:
return datetime_tz.datetime_tz.smartparse(toparse)
except ValueError:
pass

# Try to extract a substring in a condensed format that we expect
# to see in a filename or header comment
res = re.search(r"(^|[^\d])(" # non-numeric or SOL
r"(199\d|2\d\d\d)" # year
r"[-/]?" # separator
r"(0[1-9]|1[012])" # month
r"[-/]?" # separator
r"([012]\d|3[01])" # day
r"[-T ]?" # separator
r"([01]\d|2[0-3])" # hour
r"[:]?" # separator
r"([0-5]\d)" # minute
r"[:]?" # separator
r"([0-5]\d)?" # second
r"([-+]\d\d\d\d)?" # timezone
r")", toparse)
if res is not None:
try:
return datetime_tz.datetime_tz.smartparse(res.group(2))
except ValueError:
pass

# Could also try to successively parse substrings, but let's
# just give up for now.
raise ValueError("unable to parse timestamp")

def time_string(self, timestamp):
"""
Convert a Unix timestamp to a string for printing, using the
local timezone for display (e.g. from the TZ env var).
"""
dt = datetime_tz.datetime_tz.fromtimestamp(timestamp)
return dt.strftime("%a, %d %b %Y %H:%M:%S.%f %z")

def parser_setup(self):
self.parser = JimArgumentParser(add_help = False,
formatter_class = def_form)


+ 1
- 1
nilmdb/cmdline/extract.py View File

@@ -45,7 +45,7 @@ def cmd_extract(self):
if self.args.timestamp_raw:
time_string = repr
else:
time_string = self.time_string
time_string = nilmdb.utils.time.format_time

if self.args.annotate:
printf("# path: %s\n", self.args.path)


+ 2
- 1
nilmdb/cmdline/insert.py View File

@@ -2,6 +2,7 @@ from nilmdb.utils.printf import *
import nilmdb
import nilmdb.client
import nilmdb.utils.timestamper as timestamper
import nilmdb.utils.time

import sys

@@ -73,7 +74,7 @@ def cmd_insert(self):
start = self.args.start
else:
try:
start = self.parse_time(filename)
start = nilmdb.utils.time.parse_time(filename)
except ValueError:
self.die("error extracting time from filename '%s'",
filename)


+ 2
- 1
nilmdb/cmdline/list.py View File

@@ -1,4 +1,5 @@
from nilmdb.utils.printf import *
import nilmdb.utils.time

import fnmatch
import argparse
@@ -57,7 +58,7 @@ def cmd_list(self):
if self.args.timestamp_raw:
time_string = repr
else:
time_string = self.time_string
time_string = nilmdb.utils.time.format_time

for (path, layout) in streams:
if not (fnmatch.fnmatch(path, self.args.path) and


+ 54
- 0
nilmdb/utils/time.py View File

@@ -0,0 +1,54 @@
from nilmdb.utils import datetime_tz
import re

def parse_time(toparse):
"""
Parse a free-form time string and return a datetime_tz object.
If the string doesn't contain a timestamp, the current local
timezone is assumed (e.g. from the TZ env var).
"""
# If string isn't "now" and doesn't contain at least 4 digits,
# consider it invalid. smartparse might otherwise accept
# empty strings and strings with just separators.
if toparse != "now" and len(re.findall(r"\d", toparse)) < 4:
raise ValueError("not enough digits for a timestamp")

# Try to just parse the time as given
try:
return datetime_tz.datetime_tz.smartparse(toparse)
except ValueError:
pass

# Try to extract a substring in a condensed format that we expect
# to see in a filename or header comment
res = re.search(r"(^|[^\d])(" # non-numeric or SOL
r"(199\d|2\d\d\d)" # year
r"[-/]?" # separator
r"(0[1-9]|1[012])" # month
r"[-/]?" # separator
r"([012]\d|3[01])" # day
r"[-T ]?" # separator
r"([01]\d|2[0-3])" # hour
r"[:]?" # separator
r"([0-5]\d)" # minute
r"[:]?" # separator
r"([0-5]\d)?" # second
r"([-+]\d\d\d\d)?" # timezone
r")", toparse)
if res is not None:
try:
return datetime_tz.datetime_tz.smartparse(res.group(2))
except ValueError:
pass

# Could also try to successively parse substrings, but let's
# just give up for now.
raise ValueError("unable to parse timestamp")

def format_time(timestamp):
"""
Convert a Unix timestamp to a string for printing, using the
local timezone for display (e.g. from the TZ env var).
"""
dt = datetime_tz.datetime_tz.fromtimestamp(timestamp)
return dt.strftime("%a, %d %b %Y %H:%M:%S.%f %z")

+ 1
- 0
nilmdb/utils/timer.py View File

@@ -6,6 +6,7 @@
# foo.flush()

from __future__ import print_function
from __future__ import absolute_import
import contextlib
import time



+ 19
- 19
tests/test_cmdline.py View File

@@ -192,7 +192,23 @@ class TestCmdline(object):
self.fail("extract --start 2000-01-01 --start 2001-01-02")
self.contain("duplicated argument")

def test_02_info(self):
def test_02_parsetime(self):
os.environ['TZ'] = "America/New_York"
test = datetime_tz.datetime_tz.now()
parse_time = nilmdb.utils.time.parse_time
eq_(parse_time(str(test)), test)
test = datetime_tz.datetime_tz.smartparse("20120405 1400-0400")
eq_(parse_time("hi there 20120405 1400-0400 testing! 123"), test)
eq_(parse_time("20120405 1800 UTC"), test)
eq_(parse_time("20120405 1400-0400 UTC"), test)
for badtime in [ "20120405 1400-9999", "hello", "-", "", "4:00" ]:
with assert_raises(ValueError):
x = parse_time(badtime)
x = parse_time("now")
eq_(parse_time("snapshot-20120405-140000.raw.gz"), test)
eq_(parse_time("prep-20120405T1400"), test)

def test_03_info(self):
self.ok("info")
self.contain("Server URL: http://localhost:12380/")
self.contain("Client version: " + nilmdb.__version__)
@@ -201,7 +217,7 @@ class TestCmdline(object):
self.contain("Server database size")
self.contain("Server database free space")

def test_03_createlist(self):
def test_04_createlist(self):
# Basic stream tests, like those in test_client.

# No streams
@@ -277,7 +293,7 @@ class TestCmdline(object):
self.fail("list /newton/prep --start 2020-01-01 --end 2000-01-01")
self.contain("start must precede end")

def test_04_metadata(self):
def test_05_metadata(self):
# Set / get metadata
self.fail("metadata")
self.fail("metadata --get")
@@ -334,22 +350,6 @@ class TestCmdline(object):
self.fail("metadata /newton/nosuchpath")
self.contain("No stream at path /newton/nosuchpath")

def test_05_parsetime(self):
os.environ['TZ'] = "America/New_York"
cmd = nilmdb.cmdline.Cmdline(None)
test = datetime_tz.datetime_tz.now()
eq_(cmd.parse_time(str(test)), test)
test = datetime_tz.datetime_tz.smartparse("20120405 1400-0400")
eq_(cmd.parse_time("hi there 20120405 1400-0400 testing! 123"), test)
eq_(cmd.parse_time("20120405 1800 UTC"), test)
eq_(cmd.parse_time("20120405 1400-0400 UTC"), test)
for badtime in [ "20120405 1400-9999", "hello", "-", "", "4:00" ]:
with assert_raises(ValueError):
x = cmd.parse_time(badtime)
x = cmd.parse_time("now")
eq_(cmd.parse_time("snapshot-20120405-140000.raw.gz"), test)
eq_(cmd.parse_time("prep-20120405T1400"), test)

def test_06_insert(self):
self.ok("insert --help")



Loading…
Cancel
Save