Skip to content
Draft
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
85 changes: 42 additions & 43 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,48 +1,47 @@
.venv
.env
__pycache__
.pytest_cache
.pypirc
*.db
test
test_state.json
task_flow.egg-info
example_repo
signature.js
git-filter-repo
task/orca/
**/dist/
# yarn.lock
package-lock.json
node_modules
build
migrate.sh
*/dev.js
executables/*
namespace/*
config/*
.env.local
taskStateInfoKeypair.json
localKOIIDB.db
metadata.json
.npmrc
*.pem
.vscode
.cursor
data/chunks
data/process
test_state.csv
todos-example.csv


# Ignore auto-generated repository directories
repos/
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Virtual Environment
venv/
env/
.env
.venv

# Ignore Data
data/*
# IDEs and editors
.idea/
.vscode/
*.swp
*.swo
*.swn

# Logs
*.log

venv
# Testing
.pytest_cache/
.coverage
htmlcov/

**/venv/
# OS generated files
.DS_Store
Thumbs.db
6 changes: 6 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[pytest]
addopts = -v
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
1 change: 1 addition & 0 deletions src/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Mark src as a Python package
76 changes: 76 additions & 0 deletions src/coingecko_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import os
from typing import Optional, Dict, Any
from dotenv import load_dotenv

class CoinGeckoConfig:
"""
Configuration class for CoinGecko API client.

Manages API configuration parameters with support for environment variables and default values.
"""

def __init__(self,
api_key: Optional[str] = None,
base_url: Optional[str] = None,
default_currency: str = 'usd',
timeout: int = 10):
"""
Initialize CoinGecko API configuration.

Args:
api_key (Optional[str]): CoinGecko API key. Defaults to environment variable.
base_url (Optional[str]): Base URL for CoinGecko API. Defaults to environment variable.
default_currency (str): Default currency for price conversions. Defaults to 'usd'.
timeout (int): Request timeout in seconds. Defaults to 10 seconds.
"""
# Load environment variables from .env file
load_dotenv()

# Prioritize passed parameters, then environment variables, then default values
self._api_key = api_key or os.getenv('COINGECKO_API_KEY')
self._base_url = base_url or os.getenv('COINGECKO_BASE_URL', 'https://api.coingecko.com/api/v3')
self._default_currency = default_currency
self._timeout = timeout

@property
def api_key(self) -> Optional[str]:
"""Get the configured API key."""
return self._api_key

@property
def base_url(self) -> str:
"""Get the base URL for the CoinGecko API."""
return self._base_url

@property
def default_currency(self) -> str:
"""Get the default currency for price conversions."""
return self._default_currency

@property
def timeout(self) -> int:
"""Get the request timeout in seconds."""
return self._timeout

def get_config(self) -> Dict[str, Any]:
"""
Retrieve the current configuration as a dictionary.

Returns:
Dict[str, Any]: Configuration parameters
"""
return {
'api_key': self._api_key,
'base_url': self._base_url,
'default_currency': self._default_currency,
'timeout': self._timeout
}

def validate(self) -> bool:
"""
Validate the current configuration.

Returns:
bool: True if configuration is valid, False otherwise
"""
return bool(self._base_url) and self._timeout > 0
1 change: 1 addition & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Ensure tests can import from src
62 changes: 62 additions & 0 deletions tests/test_coingecko_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import os
import pytest
from src.coingecko_config import CoinGeckoConfig

def test_default_configuration():
"""Test default configuration initialization."""
config = CoinGeckoConfig()

assert config.base_url == 'https://api.coingecko.com/api/v3'
assert config.default_currency == 'usd'
assert config.timeout == 10
assert config.api_key is None

def test_custom_configuration():
"""Test custom configuration initialization."""
custom_config = CoinGeckoConfig(
api_key='test_api_key',
base_url='https://custom-api.example.com',
default_currency='eur',
timeout=15
)

assert custom_config.api_key == 'test_api_key'
assert custom_config.base_url == 'https://custom-api.example.com'
assert custom_config.default_currency == 'eur'
assert custom_config.timeout == 15

def test_environment_variable_configuration(monkeypatch):
"""Test configuration using environment variables."""
monkeypatch.setenv('COINGECKO_API_KEY', 'env_api_key')
monkeypatch.setenv('COINGECKO_BASE_URL', 'https://env-api.example.com')

config = CoinGeckoConfig()

assert config.api_key == 'env_api_key'
assert config.base_url == 'https://env-api.example.com'

def test_configuration_get_config():
"""Test get_config method."""
config = CoinGeckoConfig(
api_key='test_key',
base_url='https://test-api.example.com',
default_currency='gbp',
timeout=20
)

config_dict = config.get_config()

assert config_dict == {
'api_key': 'test_key',
'base_url': 'https://test-api.example.com',
'default_currency': 'gbp',
'timeout': 20
}

def test_configuration_validation():
"""Test configuration validation."""
valid_config = CoinGeckoConfig()
assert valid_config.validate() is True

invalid_config = CoinGeckoConfig(base_url='', timeout=0)
assert invalid_config.validate() is False