Skip to content
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
93 changes: 92 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,92 @@
.DS_Store
.DS_Store

# Testing
.pytest_cache/
.coverage
htmlcov/
coverage.xml
.tox/
.nox/

# Claude settings
.claude/*

# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Virtual environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# pipenv
Pipfile.lock

# PEP 582
__pypackages__/

# Celery
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/
1,568 changes: 1,568 additions & 0 deletions poetry.lock

Large diffs are not rendered by default.

76 changes: 76 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
[tool.poetry]
name = "streamlit-auto-filter"
version = "0.1.0"
description = "Auto filter dataframes in Streamlit"
authors = ["Your Name <[email protected]>"]
readme = "README.md"
packages = [{include = "streamlit_app.py"}]

[tool.poetry.dependencies]
python = ">=3.9,<3.9.7 || >3.9.7,<4.0"
streamlit = "^1.28.0"
pandas = "^2.0.0"

[tool.poetry.group.test.dependencies]
pytest = "^7.4.0"
pytest-cov = "^4.1.0"
pytest-mock = "^3.11.0"

# Note: Use 'poetry run pytest' for running tests instead of scripts

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"--strict-markers",
"--strict-config",
"--cov=.",
"--cov-report=html:htmlcov",
"--cov-report=xml:coverage.xml",
"--cov-report=term-missing",
"--cov-fail-under=80",
"-v"
]
markers = [
"unit: Unit tests",
"integration: Integration tests",
"slow: Slow running tests"
]

[tool.coverage.run]
source = ["."]
omit = [
"tests/*",
".venv/*",
"venv/*",
"*/site-packages/*",
"conftest.py"
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if self.debug:",
"if settings.DEBUG",
"raise AssertionError",
"raise NotImplementedError",
"if 0:",
"if __name__ == .__main__.:",
"class .*\\bProtocol\\):",
"@(abc\\.)?abstractmethod"
]
show_missing = true
skip_covered = false

[tool.coverage.html]
directory = "htmlcov"

[tool.coverage.xml]
output = "coverage.xml"
Empty file added tests/__init__.py
Empty file.
139 changes: 139 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import pytest
import pandas as pd
import tempfile
import os
from unittest.mock import Mock


@pytest.fixture
def sample_dataframe():
"""Fixture that provides a sample pandas DataFrame for testing."""
return pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'age': [25, 30, 35, 28],
'city': ['New York', 'Los Angeles', 'Chicago', 'Houston'],
'score': [85.5, 92.0, 78.3, 88.7],
'date': pd.to_datetime(['2023-01-01', '2023-02-15', '2023-03-10', '2023-04-22'])
})


@pytest.fixture
def empty_dataframe():
"""Fixture that provides an empty pandas DataFrame."""
return pd.DataFrame()


@pytest.fixture
def numeric_dataframe():
"""Fixture that provides a DataFrame with only numeric columns."""
return pd.DataFrame({
'col1': [1, 2, 3, 4, 5],
'col2': [10.1, 20.2, 30.3, 40.4, 50.5],
'col3': [100, 200, 300, 400, 500]
})


@pytest.fixture
def categorical_dataframe():
"""Fixture that provides a DataFrame with categorical columns."""
df = pd.DataFrame({
'category': ['A', 'B', 'A', 'C', 'B'],
'size': ['small', 'medium', 'large', 'small', 'medium']
})
df['category'] = df['category'].astype('category')
df['size'] = df['size'].astype('category')
return df


@pytest.fixture
def datetime_dataframe():
"""Fixture that provides a DataFrame with datetime columns."""
return pd.DataFrame({
'date1': pd.date_range('2023-01-01', periods=5, freq='D'),
'date2': pd.date_range('2023-06-01', periods=5, freq='W'),
'value': [1, 2, 3, 4, 5]
})


@pytest.fixture
def mixed_types_dataframe():
"""Fixture that provides a DataFrame with mixed data types."""
return pd.DataFrame({
'string_col': ['apple', 'banana', 'cherry', 'date'],
'int_col': [1, 2, 3, 4],
'float_col': [1.1, 2.2, 3.3, 4.4],
'bool_col': [True, False, True, False],
'date_col': pd.date_range('2023-01-01', periods=4, freq='D')
})


@pytest.fixture
def temp_dir():
"""Fixture that provides a temporary directory."""
with tempfile.TemporaryDirectory() as temp_dir:
yield temp_dir


@pytest.fixture
def temp_file():
"""Fixture that provides a temporary file."""
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
yield temp_file.name
os.unlink(temp_file.name)


@pytest.fixture
def mock_streamlit():
"""Fixture that provides a mock streamlit module."""
mock_st = Mock()

# Mock common streamlit functions
mock_st.checkbox = Mock(return_value=True)
mock_st.multiselect = Mock(return_value=[])
mock_st.columns = Mock(return_value=(Mock(), Mock()))
mock_st.slider = Mock(return_value=(0, 100))
mock_st.date_input = Mock(return_value=())
mock_st.text_input = Mock(return_value="")
mock_st.container = Mock()
mock_st.dataframe = Mock()
mock_st.title = Mock()
mock_st.write = Mock()

return mock_st


@pytest.fixture
def mock_pandas():
"""Fixture that provides mock pandas functions."""
mock_pd = Mock()
mock_pd.DataFrame = pd.DataFrame
mock_pd.to_datetime = pd.to_datetime
mock_pd.read_csv = Mock()
return mock_pd


@pytest.fixture(autouse=True)
def reset_environment():
"""Fixture that resets the environment before each test."""
yield
# Cleanup code can go here if needed


@pytest.fixture
def large_dataframe():
"""Fixture that provides a large DataFrame for performance testing."""
return pd.DataFrame({
'id': range(1000),
'value': [i * 2 for i in range(1000)],
'category': ['A'] * 500 + ['B'] * 500
})


@pytest.fixture(params=[
pd.DataFrame({'col': [1, 2, 3]}),
pd.DataFrame({'col': ['a', 'b', 'c']}),
pd.DataFrame({'col': pd.date_range('2023-01-01', periods=3)})
])
def parametrized_dataframe(request):
"""Parametrized fixture that provides different types of DataFrames."""
return request.param
Empty file added tests/integration/__init__.py
Empty file.
Loading