Currently writing a program using an API from MarketStack.com. This is for school, so I am still learning.
I am writing a stock prediction program using Python on PyCharm and I have written the connection between the program and the API without issues. So, I can certainly get the High, Name, Symbols, etc. What I am trying to do now is call a range of dates. The API says I can call up to 30 years of historical data, so I want to call all 30 years for a date that is entered by the user. Then the program will average the high on that date in order to give a trend prediction.
So, the problem I am having is calling more than one date. As I said, I want to call all 30 dates, and then I will do the math, etc.
Can someone help me call a range of dates? I tried installing Pandas and that wasn't being accepted by PyCharm for some reason.. Any help is greatly appreciated.
import tkinter as tk
import requests
# callouts for window size
HEIGHT = 650
WIDTH = 600
# function for response
def format_response(selected_stock):
try:
name1 = selected_stock['data']['name']
symbol1 = selected_stock['data']['symbol']
high1 = selected_stock['data']['eod'][1]['high']
final_str = 'Name: %s \nSymbol: %s \nEnd of Day ($ USD): %s' % (name1, symbol1, high1)
except:
final_str = 'There was a problem retrieving that information'
return final_str
# function linking to API
def stock_data(entry):
params = {'access_key': 'xxx'}
response = requests.get('http://api.marketstack.com/v1/tickers/' + entry + '/' + 'eod', params=params)
selected_stock = response.json()
label2['text'] = format_response(selected_stock)
# function for response
def format_response2(stock_hist_data):
try:
name = stock_hist_data['data']['name']
symbol = stock_hist_data['data']['symbol']
high = stock_hist_data['data']['eod'][1]['high']
name3 = stock_hist_data['data']['name']
symbol3 = stock_hist_data['data']['symbol']
high3 = stock_hist_data['data']['eod'][1]['high']
final_str2 = 'Name: %s \nSymbol: %s \nEnd of Day ($ USD): %s' % (name, symbol, high)
final_str3 = '\nName: %s \nSymbol: %s \nEnd of Day ($ USD): %s' % (name3, symbol3, high3)
except:
final_str2 = 'There was a problem retrieving that information'
final_str3 = 'There was a problem retrieving that information'
return final_str2 + final_str3
# function for response in lower window
def stock_hist_data(entry2):
params2 = {'access_key': 'xxx'}
response2 = requests.get('http://api.marketstack.com/v1/tickers/' + entry2 + '/' + 'eod', params=params2)
hist_data = response2.json()
label4['text'] = format_response2(hist_data)
I am trying to modify the statecounts.py from pyral examples to pull all the defined/accepted/in progress/completed stories point for each release. I am keep getting query exception error. Is there anything that I have missed?
state = 'ScheduleState'
state_values = rally.getAllowedValues('HierarchicalRequirement', state)
output = []
for rel in sorted(release_names):
for state_value in sorted(state_values):
response = rally.get(artifact_type, fetch="FormattedID", query='(Release.Name= %s ) AND %s = %s' % (rel, state, state_value),
projectScopeUp=False, projectScopeDown=False)
output.append("%20s : %16s : %5d" % (rel, state, state_value, response.resultCount))
Thanks!!!
If you are ANDing multiple terms it's easiest to create a list of terms like so:
query=['Release.Name = %s' % (rel), '%s = %s' % (state, state_value)]
Also, whitespace matters. You were missing a space before the first =.
I am editing a python-script to control home appliances (sonos, hue etc.) with the log of a plex mediaserver.
So far things went well, now i am struggeling with a question i could not find an answer to. These are my first steps, please bear with me.
I have a log file, which collects session information in this format:
...
2014-09-13 14:40:02 johnedoe is watching 30c3 Keynote
2014-09-13 14:48:06 thomas is watching Band of Brothers
2014-09-13 15:28:03 johnedoe is watching The Zero Theorem
...
if a new session is detected, the script evaluates if the part "johnedoe is watching 30c3 Keynote" is already present. i would like to include a timestamp-check, which would not only examine if the session is present, but also if a already logged session is older than two hours.
In pseudocode: if (alert not in log) or (if alert in log and older than two hours):
Can i access the corresponding timestamp directly, or to i have to regex the line? Any help is greatly appreciated. Many thanks in advance.
This is the tail of code:
logLocation = '/storage/downloads/plexMon.log'
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S', filename=logLocation, level=logging.INFO)
log = open(logLocation).read()
server = urllib2.urlopen('http://127.0.0.1:32400/status/sessions')
data = server.read()
server.close()
tree = ET.fromstring(data)
for video in tree.iter('Video'):
show = video.get('grandparentTitle')
episode = video.get('title')
if show == "None":
title = episode
else:
title = '%s - %s' % (show, episode)
user = video.find('User').get('title').split('#')[0]
alert = '%s is watching %s' % (user, title)
if alert not in log:
logging.info(alert)
if all(i not in alert for i in ignoreAlertList):
sendAlert(alert)
if user == "johnedoe":
b = Bridge('192.168.1.109')
b.set_light(1, 'bri', 50)
my_zone = SoCo('192.168.1.105')
my_zone.unjoin()
my_zone.pause()
Without regexes, this may be easier to achieve, if you use:
log_lines = open(logLocation).readlines() # read log files as a list[] of lines
instead of:
log = open(logLocation).read()
and then use something like:
for line in log_lines:
if(line.__contains__(alert)):
partsOfLine = str(line).split()
dateParts = str(partsOfLine[0]).split("-")
timeParts = str(partsOfLine[1]).split(":")
alerttime = datetime.datetime(int(dateParts[0]),int(dateParts[1]),int(dateParts[2]),int(timeParts[0]),int(timeParts[1]),int(timeParts[2]))
timediff_in_min = (alerttime - datetime.now()).total_seconds()/60
if(timediff_in_min >= 120):
print "ignoring older than 2 hours"
else:
print "new alert in the last 2 hours"
In my django application, I'm trying to write a unit test that performs an action and then checks the messages in the response.
As far as I can tell, there is no nice way of doing this.
I'm using the CookieStorage storage method, and I'd like to do something similar to the following:
response = self.client.post('/do-something/', follow=True)
self.assertEquals(response.context['messages'][0], "fail.")
The problem is, all I get back is a
print response.context['messages']
<django.contrib.messages.storage.cookie.CookieStorage object at 0x3c55250>
How can I turn this into something useful, or am I doing it all wrong?
Thanks,
Daniel
I found a really easy approach:
response = self.client.post('/foo/')
messages = list(response.context['messages'])
self.assertEqual(len(messages), 1)
self.assertEqual(str(messages[0]), 'my message')
If you need to check for messages on a response that has no context you can use the following:
from django.contrib.messages import get_messages
messages = list(get_messages(response.wsgi_request))
self.assertEqual(len(messages), 1)
self.assertEqual(str(messages[0]), 'my message')
The fallback storage doesn't support indexing, however it is an iterable.
From django documentation:
Outside of templates, you can use get_messages()
So, you could write something like:
from django.contrib.messages import get_messages
[...]
messages = [m.message for m in get_messages(response.wsgi_request)]
self.assertIn('My message', messages)
This works for me (displays all messages):
print [m.message for m in list(response.context['messages'])]
Also here are a couple of utility methods I have in a test class inherited from Django's TestCase. If you'd prefer to have them as functions, remove the self arguments and replace self.fail()'s with a raise.
def assert_message_count(self, response, expect_num):
"""
Asserts that exactly the given number of messages have been sent.
"""
actual_num = len(response.context['messages'])
if actual_num != expect_num:
self.fail('Message count was %d, expected %d' %
(actual_num, expect_num))
def assert_message_contains(self, response, text, level=None):
"""
Asserts that there is exactly one message containing the given text.
"""
messages = response.context['messages']
matches = [m for m in messages if text in m.message]
if len(matches) == 1:
msg = matches[0]
if level is not None and msg.level != level:
self.fail('There was one matching message but with different'
'level: %s != %s' % (msg.level, level))
return
elif len(matches) == 0:
messages_str = ", ".join('"%s"' % m for m in messages)
self.fail('No message contained text "%s", messages were: %s' %
(text, messages_str))
else:
self.fail('Multiple messages contained text "%s": %s' %
(text, ", ".join(('"%s"' % m) for m in matches)))
def assert_message_not_contains(self, response, text):
""" Assert that no message contains the given text. """
messages = response.context['messages']
matches = [m for m in messages if text in m.message]
if len(matches) > 0:
self.fail('Message(s) contained text "%s": %s' %
(text, ", ".join(('"%s"' % m) for m in matches)))
Update
My original answer was written when django was still 1.1 or so. This answer is no longer relevant. See #daveoncode's answer for a better solution.
Original Answer
I did an experiment to test this. I changed the MESSAGE_STORAGE setting in one of my projects to 'django.contrib.messages.storage.cookie.CookieStorage' and executed a test that I had written to check for messages. It worked.
The key difference from what you were doing is the way I retrieved messages. See below:
def test_message_sending(self):
data = dict(...)
response = self.client.post(reverse('my_view'), data)
messages = self.user.get_and_delete_messages()
self.assertTrue(messages)
self.assertEqual('Hey there!', messages[0])
This may be worth a try.
I created a python class to simplify messages testing :
class TestMessageCase(TestCase):
""" class inherited from TestCase to add a function to test messages response """
def assertMessageContains(self, response, messages_list, debug=False):
"""
Function to test messages returned by the response view
:param response: The response of the view
:param messages_list: An ordered list of messages to test
:type messages_list: list of string
:param debug: Show all response messages
:type debug: bool
"""
response_messages = list(response.context['messages'])
if debug:
print(
" ---------------------------------------------------------------------\n",
"| DEBUG MESSAGES RETURNED BY THE RESPONSE |\n",
"---------------------------------------------------------------------"
)
for i in range(len(response_messages)):
print(f"Message n°{i + 1} :\n{response_messages[i]}\n\n")
print(
" ---------------------------------------------------------------------\n",
"| END DEBUG |\n",
"---------------------------------------------------------------------"
)
self.assertEqual(len(response_messages), len(messages_list))
for i in range(len(response_messages)):
self.assertEqual(str(response_messages[i]), messages_list[i])
And in test function :
response = self.client.post('/foo/')
self.assertMessageContains(response, ["Foo"])
Simpler version of the stalemate one:
class TestCaseMessagesMixture(object):
def assertMessageCount(self, response, expect_num):
"""
Asserts that exactly the given number of messages have been sent.
"""
actual_num = len(response.context['messages'])
if actual_num != expect_num:
self.fail('Message count was %d, expected %d' %
(actual_num, expect_num)
)
def assertMessageEqual(self, response, text):
"""
Asserts that the response includes the message text.
"""
messages = [m.message for m in response.context['messages']]
if text not in messages:
self.fail(
'No message with text "%s", messages were: %s' %
(text, messages)
)
def assertMessageNotEqual(self, response, text):
"""
Asserts that the response does not include the message text.
"""
messages = [m.message for m in response.context['messages']]
if text in messages:
self.fail(
'Message with text "%s" found, messages were: %s' %
(text, messages)
)
Test helpers for validation of response messages count and content
def get_response_messages(self, response):
from django.contrib.messages import get_messages
return list(get_messages(response.wsgi_request))
def check_response_messages(self, response, message_index=None, message_value=None, exp_count=None):
messages = self.get_response_messages(response)
if exp_count is not None:
self.assertEqual(len(messages), exp_count)
if message_index is not None:
message = messages[message_index]
self.assertIn(message_value, str(message))
Can be used like this
message_value = "You can not switch to another type of account"
self.check_response_messages(response, exp_count=1, message_index=0, message_value=message_value)
I'm struggling a little bit with the syntax for iterating through all comments on a youtube video. I'm using the python and have found little documentation on the GetYouTubeVideoCommentFeed() function.
What I'm really trying to do is search all comments of a video for an instance of a word and increase a counter (eventually the comment will be printed out). It functions for the 25 results returned, but I need to access the rest of the comments.
import gdata.youtube
import gdata.youtube.service
video_id = 'hMnk7lh9M3o'
yt_service = gdata.youtube.service.YouTubeService()
comment_feed = yt_service.GetYouTubeVideoCommentFeed(video_id=video_id)
for comment_entry in comment_feed.entry:
comment = comment_entry.content.text
if comment.find('hi') != -1:
counter = counter + 1
print "hi: "
print counter
I tried to set the start_index of GetYouTubeVideoCommentFeed() in addition to the video_id but it didn't like that.
Is there something I'm missing?
Thanks!
Steve
Here's the code snippet for the same:
# Comment feed URL
comment_feed_url = "http://gdata.youtube.com/feeds/api/videos/%s/comments"
''' Get the comment feed of a video given a video_id'''
def WriteCommentFeed(video_id, data_file):
url = comment_feed_url % video_id
comment_feed = yt_service.GetYouTubeVideoCommentFeed(uri=url)
try:
while comment_feed:
for comment_entry in comment_feed.entry:
print comment_entry.id.text
print comment_entry.author[0].name.text
print comment_entry.title.text
print comment_entry.published.text
print comment_entry.updated.text
print comment_entry.content.text
comment_feed = yt_service.Query(comment_feed.GetNextLink().href)
except:
pass
Found out how to do it. Instead of passing a video_id to the GetYouTubeVideoCommentFeed function, you can pass it a URL. You can iterate through the comments by changing the URL parameters.
There must be an API limitation though; I can only access the last 1000 comments on the video.