Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8621e6b
ci: use uv for dependency management
eywalker May 27, 2025
ec442bd
build: make use of dependency-groups for dev setup
eywalker May 27, 2025
56f2199
build: use updated uv.lock
eywalker May 27, 2025
1b4defc
refactor: apply ruff format and use updated typehint style
eywalker May 28, 2025
c77f4fe
style: consistently apply ruff
eywalker May 28, 2025
d2934b4
style: apply ruff to notebooks
eywalker May 28, 2025
88da4e1
test: add testing for pathset and packet hashing
eywalker May 28, 2025
0b4db59
test: cleanup imports and typing
eywalker May 28, 2025
50a949e
feat: add hahser and cacher
eywalker May 29, 2025
f6b0a9c
feat: use default file hasher in dir data store
eywalker May 29, 2025
eebf897
build: update project dependencies and lock
eywalker May 29, 2025
c5f2692
feat: add file sqlite and redis-based cachers
eywalker May 29, 2025
2100c7b
test: reorganize and add tests for cachers
eywalker May 29, 2025
2697083
feat: reimplementation of hasher through finer protocol separations
eywalker May 29, 2025
548805f
refactor: separate out prefix logic outside of packet hasher
eywalker May 29, 2025
048b1cd
feat: remove non file hash methods from cached file hasher
eywalker May 29, 2025
ddade10
test: update test cases but pending few fixes
eywalker May 29, 2025
83710a0
test: adjust testing
eywalker May 29, 2025
6bfd402
test: remove coverage inclusion for pytest baseline
eywalker May 29, 2025
76933d7
feat: use real value for timestamp to get millisecond resolution
eywalker May 30, 2025
d212433
build: update uv.lock
eywalker May 30, 2025
92f97fc
test: add functioning redis cacher tests
eywalker May 30, 2025
113fd26
test: add tests for hasher factory
eywalker May 30, 2025
a042a6d
style: apply ruff formatting
eywalker May 30, 2025
b47db3f
refactor: apply ruff fix
eywalker May 30, 2025
bc28b40
test: suppress warning on intentionally unused variables
eywalker May 30, 2025
f36fc04
fix: handling of function components
eywalker May 30, 2025
ee654ed
Update src/orcabridge/hashing/file_hashers.py
eywalker May 30, 2025
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
47 changes: 23 additions & 24 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ name: Run Tests

on:
push:
branches: [ main ]
branches: [main]
pull_request:
branches: [ main ]
workflow_dispatch: # Allows manual triggering
branches: [main]
workflow_dispatch: # Allows manual triggering

jobs:
test:
Expand All @@ -15,24 +15,23 @@ jobs:
python-version: ["3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v3

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[test]"

- name: Run tests
run: |
pytest -v --cov=src --cov-report=term-missing --cov-report=xml

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}

- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: uv sync --locked --all-extras --dev

- name: Run tests
run: uv run pytest -v --cov=src --cov-report=term-missing --cov-report=xml

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
122 changes: 122 additions & 0 deletions misc/demo_redis_mocking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#!/usr/bin/env python3
"""
Demonstration script showing that RedisCacher tests work without a real Redis server.

This script shows how the mock Redis setup allows testing of Redis functionality
without requiring an actual Redis installation or server.
"""

from unittest.mock import patch


# Mock Redis exceptions
class MockRedisError(Exception):
"""Mock for redis.RedisError"""

pass


class MockConnectionError(Exception):
"""Mock for redis.ConnectionError"""

pass


class MockRedis:
"""Mock Redis client for testing."""

def __init__(self, fail_connection=False, fail_operations=False):
self.data = {}
self.fail_connection = fail_connection
self.fail_operations = fail_operations
self.ping_called = False

def ping(self):
self.ping_called = True
if self.fail_connection:
raise MockConnectionError("Connection failed")
return True

def set(self, key, value, ex=None):
if self.fail_operations:
raise MockRedisError("Operation failed")
self.data[key] = value
return True

def get(self, key):
if self.fail_operations:
raise MockRedisError("Operation failed")
return self.data.get(key)

def delete(self, *keys):
if self.fail_operations:
raise MockRedisError("Operation failed")
deleted = 0
for key in keys:
if key in self.data:
del self.data[key]
deleted += 1
return deleted

def keys(self, pattern):
if self.fail_operations:
raise MockRedisError("Operation failed")
if pattern.endswith("*"):
prefix = pattern[:-1]
return [key for key in self.data.keys() if key.startswith(prefix)]
return [key for key in self.data.keys() if key == pattern]


def demonstrate_redis_mocking():
"""Demonstrate that RedisCacher works with mocked Redis."""

# Patch the Redis availability and exceptions
with (
patch("orcabridge.hashing.string_cachers.REDIS_AVAILABLE", True),
patch("orcabridge.hashing.string_cachers.redis.RedisError", MockRedisError),
patch(
"orcabridge.hashing.string_cachers.redis.ConnectionError",
MockConnectionError,
),
):
from orcabridge.hashing.string_cachers import RedisCacher

# Create a mock Redis instance
mock_redis = MockRedis()

print("🎭 Creating RedisCacher with mocked Redis...")
cacher = RedisCacher(connection=mock_redis, key_prefix="demo:")

print("✅ RedisCacher created successfully (no real Redis server needed!)")
print(f"🔗 Connection status: {cacher.is_connected()}")

# Test basic operations
print("\n📝 Testing basic operations...")
cacher.set_cached("test_key", "test_value")
result = cacher.get_cached("test_key")
print(f" Set and retrieved: test_key -> {result}")

# Show the mock Redis data
print(f" Mock Redis data: {dict(mock_redis.data)}")

# Test failure simulation
print("\n💥 Testing failure simulation...")
mock_redis.fail_operations = True
result = cacher.get_cached("test_key")
print(f" After simulated failure: {result}")
print(f"🔗 Connection status after failure: {cacher.is_connected()}")

# Test recovery
print("\n🔄 Testing connection recovery...")
mock_redis.fail_operations = False
success = cacher.reset_connection()
print(f" Reset successful: {success}")
print(f"🔗 Connection status after reset: {cacher.is_connected()}")

print(
"\n🎉 All operations completed successfully without requiring a Redis server!"
)


if __name__ == "__main__":
demonstrate_redis_mocking()
Loading