feat: set up Python project structure with pyproject.toml

- Add pyproject.toml with core and dev dependencies
- Configure Ruff for linting and formatting
- Configure MyPy for strict type checking
- Configure pytest with asyncio support
- Create src/polymarket_insider_tracker package structure
- Add py.typed marker for PEP 561 compliance
- Add pre-commit hooks configuration
- Add comprehensive .gitignore
- Create test directory structure with basic tests

Closes #25

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Patrick Selamy
2026-01-04 14:34:37 -05:00
parent 9c4006b9aa
commit 8211e57b61
18 changed files with 284 additions and 0 deletions
+118
View File
@@ -0,0 +1,118 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# PEP 582
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# Environment
.env
.env.local
.venv
env/
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# Ruff
.ruff_cache/
# IDE
.idea/
.vscode/
*.swp
*.swo
*~
# OS
.DS_Store
Thumbs.db
# Local development
*.local
.direnv/
+23
View File
@@ -0,0 +1,23 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: check-merge-conflict
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.9
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
hooks:
- id: mypy
additional_dependencies:
- pydantic>=2.0.0
+96
View File
@@ -0,0 +1,96 @@
[project]
name = "polymarket-insider-tracker"
version = "0.1.0"
description = "Detect insider activity on Polymarket"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"py-clob-client>=0.1.0",
"web3>=6.0.0",
"httpx>=0.25.0",
"redis>=5.0.0",
"sqlalchemy>=2.0.0",
"alembic>=1.13.0",
"pydantic>=2.0.0",
"python-dotenv>=1.0.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"pytest-asyncio>=0.21.0",
"pytest-cov>=4.0.0",
"ruff>=0.1.0",
"mypy>=1.7.0",
"pre-commit>=3.0.0",
]
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[tool.setuptools.packages.find]
where = ["src"]
[tool.ruff]
line-length = 100
target-version = "py311"
src = ["src", "tests"]
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # Pyflakes
"I", # isort
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"UP", # pyupgrade
"ARG", # flake8-unused-arguments
"SIM", # flake8-simplify
]
ignore = [
"E501", # line too long (handled by formatter)
]
[tool.ruff.lint.isort]
known-first-party = ["polymarket_insider_tracker"]
[tool.mypy]
python_version = "3.11"
strict = true
warn_return_any = true
warn_unused_ignores = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
check_untyped_defs = true
disallow_untyped_decorators = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_configs = true
plugins = ["pydantic.mypy"]
[[tool.mypy.overrides]]
module = ["py_clob_client.*", "web3.*", "redis.*"]
ignore_missing_imports = true
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
addopts = "-v --tb=short"
markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
"integration: marks tests as integration tests",
]
[tool.coverage.run]
source = ["src"]
branch = true
[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise NotImplementedError",
"if TYPE_CHECKING:",
]
@@ -0,0 +1,3 @@
"""Polymarket Insider Tracker - Detect insider activity on Polymarket."""
__version__ = "0.1.0"
@@ -0,0 +1 @@
"""Alerting layer - Real-time notification delivery."""
@@ -0,0 +1 @@
"""Anomaly detection layer - Suspicious activity identification."""
@@ -0,0 +1 @@
"""Data ingestion layer - Real-time Polymarket trade streaming."""
@@ -0,0 +1 @@
"""Wallet profiler layer - Blockchain analysis for trader intelligence."""
@@ -0,0 +1 @@
"""Storage layer - Database schemas and repositories."""
+1
View File
@@ -0,0 +1 @@
"""Test suite for Polymarket Insider Tracker."""
+1
View File
@@ -0,0 +1 @@
"""Tests for alerter module."""
+9
View File
@@ -0,0 +1,9 @@
"""Pytest configuration and fixtures."""
import pytest
@pytest.fixture
def sample_market_id() -> str:
"""Sample market ID for testing."""
return "0x1234567890abcdef1234567890abcdef12345678"
+1
View File
@@ -0,0 +1 @@
"""Tests for detector module."""
+1
View File
@@ -0,0 +1 @@
"""Tests for ingestor module."""
+1
View File
@@ -0,0 +1 @@
"""Tests for profiler module."""
+1
View File
@@ -0,0 +1 @@
"""Tests for storage module."""
+24
View File
@@ -0,0 +1,24 @@
"""Test that the project setup is working correctly."""
import polymarket_insider_tracker
def test_version() -> None:
"""Test that version is defined."""
assert polymarket_insider_tracker.__version__ == "0.1.0"
def test_import_modules() -> None:
"""Test that all submodules can be imported."""
from polymarket_insider_tracker import ingestor
from polymarket_insider_tracker import profiler
from polymarket_insider_tracker import detector
from polymarket_insider_tracker import alerter
from polymarket_insider_tracker import storage
# Just verify imports work
assert ingestor is not None
assert profiler is not None
assert detector is not None
assert alerter is not None
assert storage is not None