Skip to content
Snippets Groups Projects
Commit 70c5bde3 authored by safer-lgtm's avatar safer-lgtm
Browse files

Add tests for DynamoDB connection and configuration

parent 7a783348
No related branches found
No related tags found
No related merge requests found
...@@ -101,3 +101,5 @@ ENV/ ...@@ -101,3 +101,5 @@ ENV/
# pytest # pytest
.pytest_cache .pytest_cache
# Ignore config file with sensitive information
config.ini
...@@ -2,3 +2,37 @@ Formula One Module Repository ...@@ -2,3 +2,37 @@ Formula One Module Repository
======================== ========================
This Ptyhon project downloads and prepares formula one data from the API ergast.com. This Ptyhon project downloads and prepares formula one data from the API ergast.com.
# Formula One Module Repository
## Setup
1. Clone the repository:
```bash
git clone https://github.com/safer-lgtm/formulaone.git
cd formulaone
```
2. Create a `config.ini` file in the root directory of the project:
```ini
[AWS]
aws_access_key_id = your_access_key_id
aws_secret_access_key = your_secret_access_key
region_name = your_region
[DYNAMODB]
table_name = your_table_name
```
3. Install the dependencies:
```bash
pip install -r requirements.txt
```
4. Run the tests:
```bash
pytest
```
sample.helpers
==============
.. automodule:: sample.helpers
:members:
:undoc-members:
:show-inheritance:
.. rubric:: Functions
.. autosummary::
:toctree: _autosummary
get_raw_data_path
get_dynamodb_resource
list_dynamodb_tables
get_movies_table
get_movie_item
query_movies_by_year
.. _ergast:
Ergast API Interface
====================
.. currentmodule::
fastf1.ergast
Introduction
------------
This module can be used to interface with the Ergast F1 API
(https://ergast.com/mrd/). All Ergast endpoints are supported.
The :class:`Ergast` object provides access to all API Endpoints of the
Ergast API.
The terms of use of Ergast apply (https://ergast.com/mrd/terms/).
Especially take care not to exceed the specified rate limits.
FastF1 will handle caching and it will try to enforce rate limits where
possible. Make sure to know what limits apply. For more information on how
FastF1 handles caching and rate limiting see :ref:`requests-and-caching`.
import boto3
import configparser
from boto3.dynamodb.conditions import Key
def get_config():
"""
Reads the configuration file and returns the config object.
Returns:
config: The config object.
"""
config = configparser.ConfigParser()
config.read('config.ini')
return config
def get_dynamodb_resource():
"""
Creates a DynamoDB resource using the AWS session.
Returns:
dynamo_resource: The DynamoDB resource.
"""
config = get_config()
aws_access_key_id = config['AWS']['aws_access_key_id']
aws_secret_access_key = config['AWS']['aws_secret_access_key']
region_name = config['AWS']['region_name']
session = boto3.Session(
aws_access_key_id=aws_access_key_id,
aws_secret_access_key=aws_secret_access_key,
region_name=region_name
)
dynamo_resource = session.resource('dynamodb')
return dynamo_resource
def list_dynamodb_tables(dynamo_resource):
"""
Lists all tables in the DynamoDB resource.
Args:
dynamo_resource: The DynamoDB resource.
Returns:
list: List of table names.
"""
tables = [table.name for table in dynamo_resource.tables.all()]
return tables
def get_movies_table(dynamo_resource):
"""
Gets the movies table from DynamoDB.
Args:
dynamo_resource: The DynamoDB resource.
Returns:
table: The DynamoDB table resource for movies.
"""
config = get_config()
table_name = config['DYNAMODB']['table_name']
return dynamo_resource.Table(table_name)
def get_movie_item(table, year, title):
"""
Gets a movie item from the DynamoDB table.
Args:
table: The DynamoDB table resource.
year: The year of the movie.
title: The title of the movie.
Returns:
dict: The movie item.
"""
response = table.get_item(Key={'year': year, 'title': title})
return response.get('Item')
def query_movies_by_year(table, year):
"""
Queries movies by year from the DynamoDB table.
Args:
table: The DynamoDB table resource.
year: The year to query.
Returns:
list: List of movies for the given year.
"""
response = table.query(
KeyConditionExpression=Key('year').eq(year)
)
return response.get('Items', [])
[pytest]
minversion = 6.0
testpaths =
formulaone
docs
tests
norecursedirs =
_build
build
python_files = test_*.py
addopts =
--doctest-glob="*.rst"
--doctest-plus
filterwarnings =
error
ignore:.*df.iloc.*will attempt to set the values inplace.*:FutureWarning
ignore:.*Attribute s is deprecated and will be removed in Python 3.14.*:DeprecationWarning
ignore:(?s).*Pyarrow will become a required dependency of pandas.*:DeprecationWarning
ignore:(?s).*Passing 'weights' as positional argument.*:FutureWarning
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
...@@ -13,7 +13,7 @@ with open('LICENSE') as f: ...@@ -13,7 +13,7 @@ with open('LICENSE') as f:
setup( setup(
name='formulaone', name='formulaone',
version='0.1.0', version='0.1.1', # increase version by 0.0.1
description='Downloads and prepares formula one data', description='Downloads and prepares formula one data',
long_description=readme, long_description=readme,
author='Timo Schuerg', author='Timo Schuerg',
......
# content of test_sample.py # content of test_sample.py
import os
import sys
from sample.helpers import get_tidy_data_path # add the formulaone model directory to python path
import pandas as pd sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
#from formulaone.sample.helpers import get_tidy_data_path
from formulaone.helpers import get_tidy_data_path
import pandas as pd
def test_check_dataframe_size(): def test_check_dataframe_size():
df = pd.read_parquet(get_tidy_data_path() / 'current_race.parquet') df = pd.read_parquet(get_tidy_data_path() / 'current_race.parquet')
assert df.shape[1] == 26 assert df.shape[1] == 26
def test_file_format():
# Assuming get_tidy_data_path returns a Path object
file_path = get_tidy_data_path() / 'current_race.parquet'
# Check if the file extension is .parquet
assert file_path.suffix == '.parquet', "File format should be .parquet"
import os
import sys
import pytest
import configparser
import boto3
from botocore.exceptions import NoCredentialsError, PartialCredentialsError
# Add the formulaone model directory to the Python path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from formulaone.dynamodb_helpers import (
get_dynamodb_resource,
list_dynamodb_tables,
get_movies_table,
get_movie_item,
query_movies_by_year
)
def test_aws_config_keys():
"""Test the necessary AWS config keys."""
config = configparser.ConfigParser()
config.read(os.path.join(os.path.dirname(__file__), '../config.ini'))
assert 'AWS' in config, "AWS section is missing"
assert 'aws_access_key_id' in config['AWS'], "aws_access_key_id is missing in AWS"
assert 'aws_secret_access_key' in config['AWS'], "aws_secret_access_key is missing in AWS"
assert 'region_name' in config['AWS'], "region_name is missing in AWS"
def test_dynamodb_config_keys():
"""Test the necessary DynamoDB config keys."""
config = configparser.ConfigParser()
config.read(os.path.join(os.path.dirname(__file__), '../config.ini'))
assert 'DYNAMODB' in config, "DYNAMODB section is missing"
assert 'table_name' in config['DYNAMODB'], "table_name is missing in DYNAMODB"
def test_dynamodb_connection():
"""Test the DynamoDB connection using the provided credentials and configuration."""
# Read the config file
config = configparser.ConfigParser()
config.read(os.path.join(os.path.dirname(__file__), '../config.ini'))
# Credentials and region
aws_access_key_id = config['AWS']['aws_access_key_id']
aws_secret_access_key = config['AWS']['aws_secret_access_key']
region_name = config['AWS']['region_name']
table_name = config['DYNAMODB']['table_name']
# Create session with credentials
session = boto3.Session(
aws_access_key_id=aws_access_key_id,
aws_secret_access_key=aws_secret_access_key,
region_name=region_name
)
# DynamoDB object resource
dynamo_resource = session.resource('dynamodb')
# Describe the table
try:
table = dynamo_resource.Table(table_name)
response = table.table_status
assert response in ['ACTIVE', 'CREATING', 'UPDATING', 'DELETING'], "Table status should be valid"
except NoCredentialsError:
assert False, "NO CREDENTIALS FOUND!"
except PartialCredentialsError:
assert False, "INCOMPLETE CREDENTIALS!!"
except Exception as e:
assert False, f"UNEXPECTED ERROR: {str(e)}"
def test_dynamodb_resource():
"""Test the DynamoDB resource initialization."""
dynamo_resource = get_dynamodb_resource()
assert dynamo_resource is not None, "DynamoDB resource should be initialized"
if __name__ == "__main__":
pytest.main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment