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

Add requests Session to API calls #486

Merged
merged 2 commits into from
Jan 11, 2025
Merged
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
16 changes: 15 additions & 1 deletion src/nba_api/library/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ class NBAHTTP:

headers = None

_session = None

@classmethod
def get_session(cls):
session = cls._session
if session is None:
session = requests.Session()
cls._session = session
return session

@classmethod
def set_session(cls, session) -> None:
cls._session = session

def clean_contents(self, contents):
return contents

Expand Down Expand Up @@ -143,7 +157,7 @@ def send_api_request(
print("loading from file...")

if not contents:
response = requests.get(
response = self.get_session().get(
url=base_url,
params=parameters,
headers=request_headers,
Expand Down
68 changes: 68 additions & 0 deletions tests/unit/test_http.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import pytest
import requests
from unittest.mock import Mock
from nba_api.library.http import NBAHTTP
from nba_api.stats.endpoints import AllTimeLeadersGrids

@pytest.fixture
def mock_session():
session = Mock(spec=requests.Session)
# Mock the get method to return a response-like object
mock_response = Mock()
mock_response.text = '{"resource": "alltimeleadersgrids", "resultSets": {}}'
mock_response.status_code = 200
mock_response.url = "http://stats.nba.com/stats/alltimeleadersgrids"
session.get.return_value = mock_response
return session

def test_nbahttp_session_management():
# Test default session creation
assert NBAHTTP._session is None
session = NBAHTTP.get_session()
assert isinstance(session, requests.Session)

# Test setting custom session
custom_session = requests.Session()
NBAHTTP.set_session(custom_session)
assert NBAHTTP.get_session() == custom_session

def test_endpoint_uses_global_session(mock_session):
# Set up global session
NBAHTTP.set_session(mock_session)

# Create endpoint and make request
try:
_ = AllTimeLeadersGrids(topx=5)
except KeyError:
# This is expected due to the mock response.
pass

# Verify the session's get method was called
assert mock_session.get.called

# Verify the call parameters
call_kwargs = mock_session.get.call_args.kwargs
assert 'params' in call_kwargs
assert 'TopX' in dict(call_kwargs['params'])
assert dict(call_kwargs['params'])['TopX'] == 5

def test_session_headers_persistence():
# Create session with custom headers
session = requests.Session()
custom_user_agent = 'CustomBot/1.0'
session.headers.update({'User-Agent': custom_user_agent})

# Set as global session
NBAHTTP.set_session(session)

# Verify headers are maintained
current_session = NBAHTTP.get_session()
assert current_session.headers['User-Agent'] == custom_user_agent

@pytest.fixture(autouse=True)
def cleanup():
# Reset session before each test
NBAHTTP._session = None
yield
# Clean up after each test
NBAHTTP._session = None