Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functionalities to accept no spam request sessions #377

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions alpha_vantage/alphavantage.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class AlphaVantage(object):
_RAPIDAPI_URL = "https://alpha-vantage.p.rapidapi.com/query?"

def __init__(self, key=None, output_format='json',
treat_info_as_error=True, indexing_type='date', proxy=None, rapidapi=False):
treat_info_as_error=True, indexing_type='date', proxy=None, rapidapi=False, session=None):
""" Initialize the class

Keyword Arguments:
Expand All @@ -43,6 +43,7 @@ def __init__(self, key=None, output_format='json',
the URL of the proxy.
rapidapi: Boolean describing whether or not the API key is
through the RapidAPI platform or not
session: Optional custom requests session for caching and rate limits.
"""
if key is None:
key = os.getenv('ALPHAVANTAGE_API_KEY')
Expand Down Expand Up @@ -73,6 +74,24 @@ def __init__(self, key=None, output_format='json',
self.indexing_type = indexing_type
self.proxy = proxy or {}

if session is None:
self.session = None
else:
try:
from requests_cache import OriginalSession
except ImportError:
OriginalSession = None
def is_valid_session(session):
"""Check if the session is a valid requests session or cached session."""
return (
isinstance(session, requests.Session) or
(OriginalSession is not None and isinstance(session, OriginalSession))
)
if is_valid_session(session):
self.session = session
else:
self.session = None

@classmethod
def _call_api_on_func(cls, func):
""" Decorator for forming the api call with the arguments of the
Expand Down Expand Up @@ -348,7 +367,12 @@ def _handle_api_call(self, url):
meta_data_key: The key for getting the meta data information out
of the json object
"""
response = requests.get(url, proxies=self.proxy, headers=self.headers)
if self.session: # Uses the session if it was defined
response = self.session.get(
url, proxies=self.proxy, headers=self.headers
)
else:
response = requests.get(url, proxies=self.proxy, headers=self.headers)
if 'json' in self.output_format.lower() or 'pandas' in \
self.output_format.lower():
json_response = response.json()
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
test_requires=[
'aioresponses',
'nose',
'requests_mock'
'requests_mock',
'requests_cache'
],
extras_requires={
'pandas': ['pandas'],
Expand Down
101 changes: 73 additions & 28 deletions test_alpha_vantage/test_alphavantage.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@
from ..alpha_vantage.alphavantage import AlphaVantage
from ..alpha_vantage.timeseries import TimeSeries
from ..alpha_vantage.techindicators import TechIndicators
from ..alpha_vantage.sectorperformance import SectorPerformances
# from ..alpha_vantage.sectorperformance import SectorPerformances
from ..alpha_vantage.foreignexchange import ForeignExchange
from ..alpha_vantage.fundamentaldata import FundamentalData

from pandas import DataFrame as df, Timestamp

import requests
import requests_mock
import requests_cache
import unittest
import sys
import collections
from os import path
import requests_mock


class TestAlphaVantage(unittest.TestCase):

Expand Down Expand Up @@ -56,6 +57,50 @@ def test_handle_api_call(self, mock_request):
self.assertIsInstance(
data, dict, 'Result Data must be a dictionary')

@requests_mock.Mocker()
def test_handle_requests_session_call(self, mock_request):
""" Test that session call returns a json file as requested.
"""
session = requests.Session()
av = AlphaVantage(key=TestAlphaVantage._API_KEY_TEST, session=session)
url = "https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=1min&apikey=test"
path_file = self.get_file_from_url("mock_time_series")
with open(path_file) as f:
mock_request.get(url, text=f.read())
data = av._handle_api_call(url)
self.assertIsInstance(
data, dict, 'Result Data must be a dictionary')

@requests_mock.Mocker()
def test_handle_invalid_session_type(self, mock_request):
""" Test that the call functions with invalid session type.
"""
session = 'Session' # Try using string, which is invalid
av = AlphaVantage(key=TestAlphaVantage._API_KEY_TEST, session=session)
self.assertIsNone(av.session, 'Session should default to None')
url = "https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=1min&apikey=test"
path_file = self.get_file_from_url("mock_time_series")
with open(path_file) as f:
mock_request.get(url, text=f.read())
data = av._handle_api_call(url)
self.assertIsInstance(
data, dict, 'Result Data must be a dictionary')

@requests_mock.Mocker()
def test_handle_cached_session_call(self, mock_request):
""" Test that the call functions with cached session.
"""
session = requests_cache.CachedSession(backend='memory', use_memory=True)
av = AlphaVantage(key=TestAlphaVantage._API_KEY_TEST, session=session)
url = "https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=1min&apikey=test"
path_file = self.get_file_from_url("mock_time_series")
with open(path_file) as f:
mock_request.get(url, text=f.read())
data = av._handle_api_call(url)
self.assertIsInstance(
data, dict, 'Result Data must be a dictionary')
self.assertTrue(session.cache.contains(url=url), 'Request should be cached')

@requests_mock.Mocker()
def test_rapidapi_key(self, mock_request):
""" Test that the rapidAPI key calls the rapidAPI endpoint
Expand Down Expand Up @@ -176,32 +221,32 @@ def test_technical_indicator_sma_pandas(self, mock_request):
self.assertIsInstance(
data, df, 'Result Data must be a pandas data frame')

@requests_mock.Mocker()
def test_sector_perfomance_python3(self, mock_request):
""" Test that api call returns a json file as requested
"""
sp = SectorPerformances(key=TestAlphaVantage._API_KEY_TEST)
url = "https://www.alphavantage.co/query?function=SECTOR&apikey=test"
path_file = self.get_file_from_url("mock_sector")
with open(path_file) as f:
mock_request.get(url, text=f.read())
data, _ = sp.get_sector()
self.assertIsInstance(
data, dict, 'Result Data must be a dictionary')
# @requests_mock.Mocker()
# def test_sector_perfomance_python3(self, mock_request):
# """ Test that api call returns a json file as requested
# """
# sp = SectorPerformances(key=TestAlphaVantage._API_KEY_TEST)
# url = "https://www.alphavantage.co/query?function=SECTOR&apikey=test"
# path_file = self.get_file_from_url("mock_sector")
# with open(path_file) as f:
# mock_request.get(url, text=f.read())
# data, _ = sp.get_sector()
# self.assertIsInstance(
# data, dict, 'Result Data must be a dictionary')

@requests_mock.Mocker()
def test_sector_perfomance_pandas(self, mock_request):
""" Test that api call returns a json file as requested
"""
sp = SectorPerformances(
key=TestAlphaVantage._API_KEY_TEST, output_format='pandas')
url = "https://www.alphavantage.co/query?function=SECTOR&apikey=test"
path_file = self.get_file_from_url("mock_sector")
with open(path_file) as f:
mock_request.get(url, text=f.read())
data, _ = sp.get_sector()
self.assertIsInstance(
data, df, 'Result Data must be a pandas data frame')
# @requests_mock.Mocker()
# def test_sector_perfomance_pandas(self, mock_request):
# """ Test that api call returns a json file as requested
# """
# sp = SectorPerformances(
# key=TestAlphaVantage._API_KEY_TEST, output_format='pandas')
# url = "https://www.alphavantage.co/query?function=SECTOR&apikey=test"
# path_file = self.get_file_from_url("mock_sector")
# with open(path_file) as f:
# mock_request.get(url, text=f.read())
# data, _ = sp.get_sector()
# self.assertIsInstance(
# data, df, 'Result Data must be a pandas data frame')

@requests_mock.Mocker()
def test_foreign_exchange(self, mock_request):
Expand Down