Skip to content

Commit 1b98bea

Browse files
author
Dario Varotto
committed
Additional datafile examples and iterate_results method
1 parent 9a55788 commit 1b98bea

File tree

5 files changed

+96
-10
lines changed

5 files changed

+96
-10
lines changed

ravenpackapi/core.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,20 @@
1313
from ravenpackapi.utils.constants import JSON_AVAILABLE_FIELDS
1414

1515
_VALID_METHODS = ('get', 'post', 'put', 'delete')
16+
VERSION = '1.0.9'
1617

1718
logger = logging.getLogger("ravenpack.core")
1819

1920

2021
class RPApi(object):
21-
_BASE_URL = os.environ.get('RP_API_ENDPOINT',
22-
'https://api.ravenpack.com/1.0')
23-
_FEED_BASE_URL = os.environ.get('RP_FEED_ENDPOINT',
24-
'https://feed.ravenpack.com/data')
25-
2622
def __init__(self, api_key=None):
23+
self._BASE_URL = os.environ.get(
24+
'RP_API_ENDPOINT',
25+
'https://api.ravenpack.com/1.0')
26+
self._FEED_BASE_URL = os.environ.get(
27+
'RP_FEED_ENDPOINT',
28+
'https://feed.ravenpack.com/1.0/json'
29+
)
2730
api_key = api_key or os.environ.get('RP_API_KEY')
2831
if api_key is None:
2932
raise ValueError(
@@ -32,6 +35,12 @@ def __init__(self, api_key=None):
3235
)
3336
self.api_key = api_key
3437

38+
@property
39+
def headers(self):
40+
return {"API_KEY": self.api_key,
41+
'User-Agent': 'RavenPack Python v%s' % VERSION,
42+
}
43+
3544
def request(self, endpoint, data=None, params=None, method='get'):
3645
assert method in _VALID_METHODS, 'Method {used} not accepted. Please use {valid_methods}'
3746
logger.debug("Request to %s" % endpoint)
@@ -40,7 +49,7 @@ def request(self, endpoint, data=None, params=None, method='get'):
4049
endpoint=endpoint))
4150
response = requests_call(
4251
url=self._BASE_URL + endpoint,
43-
headers=dict(API_KEY=self.api_key),
52+
headers=self.headers,
4453
data=json.dumps(data) if data else None,
4554
params=params,
4655
)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import logging
2+
3+
from ravenpackapi import RPApi, Dataset
4+
from ravenpackapi.models.job import Job
5+
6+
logging.basicConfig(level=logging.INFO)
7+
# initialize the API (here we use the RP_API_KEY in os.environ)
8+
api = RPApi()
9+
10+
# query the realtime feed
11+
eu_600 = api.get_dataset(dataset_id='eu600') # get the EU600 filters
12+
13+
dataset_id = None # put here a dataset_id if you have it already
14+
15+
if dataset_id is None:
16+
dataset = Dataset(
17+
api=api,
18+
filters=eu_600.filters,
19+
name='EU600 average sentiment',
20+
frequency='daily',
21+
fields=[{'average_ess': {'avg': {'field': 'EVENT_SENTIMENT_SCORE'}}}]
22+
)
23+
dataset_id = dataset.save()
24+
else:
25+
dataset = api.get_dataset(dataset_id)
26+
27+
# job = Job(api=api, token='xxx') # if you already have a job you can use this
28+
# ... or request a new one
29+
job = dataset.request_datafile(
30+
start_date='2018-01-01 00:00:00',
31+
end_date='2018-01-02 00:00:00',
32+
)
33+
34+
# write only the ROLLOUT rows
35+
for line in job.iterate_results():
36+
timestamp, entity_id, entity_name, avg_sentiment = line.split(',')
37+
if entity_name == 'ROLLOUT':
38+
print(line)

ravenpackapi/models/dataset.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ def delete(self):
9292
method='delete',
9393
)
9494

95+
@api_method
96+
def save(self):
97+
response = self.api.request(
98+
endpoint="/datasets",
99+
data=self.as_dict(),
100+
method='post'
101+
)
102+
103+
dataset_id = response.json()['dataset_uuid']
104+
logger.info("Created dataset %s" % dataset_id)
105+
self._data['uuid'] = dataset_id
106+
95107
@api_method
96108
def json(self,
97109
start_date,
@@ -161,7 +173,7 @@ def request_realtime(self):
161173
dataset_id=self.id)
162174
logger.debug("Connecting with RT feed: %s" % endpoint)
163175
r = requests.get(endpoint,
164-
headers=dict(API_KEY=api.api_key),
176+
headers=api.headers,
165177
stream=True,
166178
)
167179

ravenpackapi/models/job.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ def is_ready(self):
3636
def is_processing(self):
3737
return self.status in {'enqueued', 'processing'}
3838

39+
@property
40+
def is_undefined(self):
41+
return self.status in {'unknown'}
42+
3943
def __str__(self):
4044
return "Job {status}: {token}".format(status=self.status,
4145
token=self.token)
@@ -57,9 +61,14 @@ def wait_for_completion(self, timeout_seconds=None):
5761
max_end_date = datetime.datetime.utcnow() + datetime.timedelta(
5862
seconds=timeout_seconds
5963
) if timeout_seconds else None
64+
65+
if self.is_undefined:
66+
self.get_status()
67+
6068
while True:
6169
if self.is_ready:
6270
break
71+
sleep(self._FILE_AVAILABILIY_SECONDS_DELAY)
6372
try:
6473
self.get_status()
6574
except APIException: # keep waiting if API raises exceptions
@@ -72,7 +81,6 @@ def wait_for_completion(self, timeout_seconds=None):
7281
if not printed_once:
7382
logger.info("Waiting for the job to be ready...")
7483
printed_once = True
75-
sleep(self._FILE_AVAILABILIY_SECONDS_DELAY)
7684

7785
@api_method
7886
def save_to_file(self, filename):
@@ -85,10 +93,27 @@ def save_to_file(self, filename):
8593
# this is a different request than the normal API
8694
# streaming the file in chunks
8795
r = requests.get(job.url,
88-
headers=dict(API_KEY=api.api_key),
96+
headers=api.headers,
8997
stream=True,
9098
)
9199

92100
for chunk in r.iter_content(chunk_size=self._CHUNK_SIZE):
93101
if chunk:
94102
output.write(chunk)
103+
104+
@api_method
105+
def iterate_results(self):
106+
api = self.api
107+
job = self # just to be clear
108+
job.wait_for_completion()
109+
110+
with requests.Session() as s:
111+
r = s.get(job.url,
112+
headers=api.headers,
113+
stream=True,
114+
)
115+
iterator = r.iter_lines(chunk_size=self._CHUNK_SIZE)
116+
header = next(iterator) # discard the header
117+
118+
for line in iterator:
119+
yield line.decode('utf-8')

setup.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
from setuptools import setup, find_packages
22

3+
from ravenpackapi.core import VERSION
4+
35
with open('README.rst') as readme_file:
46
readme = readme_file.read()
57

68
setup(
79
name='ravenpackapi',
8-
version='1.0.8',
10+
version=VERSION,
911
packages=find_packages(include=['ravenpackapi']),
1012
include_package_data=True,
1113

0 commit comments

Comments
 (0)