Skip to content

Commit f79b0e8

Browse files
author
John Miller
committed
Add utils
1 parent 0f693ab commit f79b0e8

3 files changed

Lines changed: 97 additions & 1 deletion

File tree

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77
setup(name="singer-python",
8-
version="0.2.1",
8+
version="0.2.2",
99
description="Singer.io utility library",
1010
author="Stitch",
1111
classifiers=['Programming Language :: Python :: 3 :: Only'],

singer/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import logging
55
import logging.config
66

7+
from singer import utils
8+
79

810
class Message(object):
911
def __init__(self, **kwargs):

singer/utils.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import argparse
2+
import collections
3+
import datetime
4+
import functools
5+
import json
6+
import os
7+
import time
8+
9+
DATETIME_FMT = "%Y-%m-%dT%H:%M:%SZ"
10+
11+
12+
def strptime(dt):
13+
return datetime.datetime.strptime(dt, DATETIME_FMT)
14+
15+
16+
def strftime(dt):
17+
return dt.strftime(DATETIME_FMT)
18+
19+
20+
def ratelimit(limit, every):
21+
def limitdecorator(fn):
22+
times = collections.deque()
23+
24+
@functools.wraps(fn)
25+
def wrapper(*args, **kwargs):
26+
if len(times) >= limit:
27+
t0 = times.pop()
28+
t = time.time()
29+
sleep_time = every - (t - t0)
30+
if sleep_time > 0:
31+
time.sleep(sleep_time)
32+
33+
times.appendleft(time.time())
34+
return fn(*args, **kwargs)
35+
36+
return wrapper
37+
38+
return limitdecorator
39+
40+
41+
def chunk(l, n):
42+
for i in range(0, len(l), n):
43+
yield l[i:i + n]
44+
45+
46+
def get_abs_path(path):
47+
return os.path.join(os.path.dirname(os.path.realpath(__file__)), path)
48+
49+
50+
def load_json(path):
51+
with open(path) as f:
52+
return json.load(f)
53+
54+
55+
def load_schema(entity):
56+
return load_json(get_abs_path("schemas/{}.json".format(entity)))
57+
58+
59+
def update_state(state, entity, dt):
60+
if dt is None:
61+
return
62+
63+
if isinstance(dt, datetime.datetime):
64+
dt = strftime(dt)
65+
66+
if entity not in state:
67+
state[entity] = dt
68+
69+
if dt >= state[entity]:
70+
state[entity] = dt
71+
72+
73+
def parse_args(required_config_keys):
74+
parser = argparse.ArgumentParser()
75+
parser.add_argument('-c', '--config', help='Config file', required=True)
76+
parser.add_argument('-s', '--state', help='State file')
77+
args = parser.parse_args()
78+
79+
config = load_json(args.config)
80+
check_config(config, required_config_keys)
81+
82+
if args.state:
83+
state = utils.load_json(args.state)
84+
else:
85+
state = {}
86+
87+
return config, state
88+
89+
90+
def check_config(config, required_keys):
91+
missing_keys = [key for key in required_keys if key not in config]
92+
if missing_keys:
93+
raise Exception("Config is missing required keys: {}".format(missing_keys))
94+

0 commit comments

Comments
 (0)