A modular toolkit for managing project paths, cloud services, and configuration in Python projects
Project description
project-toolkit
A modular Python toolkit for managing project paths, cloud services (Google Cloud, Cloudflare R2), HashiCorp Vault, and configuration — powered by pydantic-settings.
Features
- ⚙️ Auto-Initialized Settings — Just import and use, no setup needed
- 🔑 Dynamic Env Access — Read any env var or
.envvalue withsettings.env("KEY") - 🔐 Vault Integration — Read secrets like
vault kv get/vault kv get -field= - 📁 Project Path Management — Create and navigate project directory structures
- ☁️ Cloudflare R2 — Upload/download files with
boto3andrequestsclients - 📊 Google Services — BigQuery, Drive, and Sheets integrations
- 🌐 WAN IP Tracker — Detect and log public IP address changes
Installation
# Core only
pip install project-toolkit
# With specific extras
pip install "project-toolkit[google]"
pip install "project-toolkit[cloudflare]"
pip install "project-toolkit[vault]"
pip install "project-toolkit[wan-ip]"
# Everything
pip install "project-toolkit[all]"
API Usage Guide
1. Auto-Initialized Settings (No Setup Needed)
Settings auto-initialize on first use — no boilerplate required:
from project_toolkit import settings
# Access any module setting directly
print(settings.cloudflare.r2_access_token)
print(settings.google.google_service_account_json)
print(settings.vault.is_configured)
Environment detection is automatic:
- If
AIRFLOW_HOMEis set → loadsconfig/.env.airflow - Otherwise → loads
config/.env.dev
2. Dynamic Environment Variable Access
Read any env var or .env value — no need to pre-define it in code:
from project_toolkit import settings
# Read API keys (from env vars or .env file)
openai_key = settings.env("OPENAI_API_KEY")
gemini_key = settings.env("GEMINI_API_KEY")
claude_key = settings.env("CLAUDE_API_KEY")
# With a default fallback
db_host = settings.env("DATABASE_HOST", "localhost")
debug = settings.env("DEBUG_MODE", "false")
Priority: Environment variable > .env file value > default
Your config/.env.dev can contain any key:
OPENAI_API_KEY=sk-xxxxx
GEMINI_API_KEY=AIza-xxxxx
CLAUDE_API_KEY=sk-ant-xxxxx
DATABASE_HOST=db.example.com
3. HashiCorp Vault
Read secrets from Vault — same env vars as the vault CLI.
Setup — Add to config/.env.dev:
VAULT_ADDR=http://192.168.12.2:8200
VAULT_TOKEN=hvs.your-vault-token
Read all fields (like vault kv get secret/my-credentials):
from project_toolkit import settings
secret = settings.vault.read_secret("secret/my-credentials")
print(secret)
# {'username': 'admin', 'password': 'secret-password-123'}
Read a single field (like vault kv get -field=OPENAI_API_KEY secret/api):
from project_toolkit import settings
# Single field reads
api_key = settings.vault.read_field("secret/api", "OPENAI_API_KEY")
password = settings.vault.read_field("secret/my-credentials", "password")
# With fallback default
db_pass = settings.vault.read_field("secret/db", "password", "default-pw")
Use the hvac client directly for advanced operations:
from project_toolkit import settings
client = settings.vault.get_vault_client()
if client:
# Write a secret
client.secrets.kv.v2.create_or_update_secret(
path="my-new-secret",
secret={"api_key": "abc123"},
)
# List secrets
secrets = client.secrets.kv.v2.list_secrets(path="", mount_point="secret")
print(secrets["data"]["keys"])
4. Manual Settings Override
For testing or custom configurations, construct AppSettings directly:
from project_toolkit.settings.base import AppSettings
from project_toolkit.settings.cloudflare import CloudflareSettings
from project_toolkit.settings.google import GoogleSettings
from project_toolkit.settings.path import PathSettings
from project_toolkit.settings.vault import VaultSettings
from project_toolkit.settings.wan_ip import WanIpSettings
custom_settings = AppSettings(
path_config=PathSettings(
data_dir="/custom/data",
project_name="my-project",
),
cloudflare=CloudflareSettings(
r2_access_token="custom-token",
r2_account_id="custom-id",
),
google=GoogleSettings(),
vault=VaultSettings(),
wan_ip=WanIpSettings(),
)
# Use the custom settings
print(custom_settings.cloudflare.r2_access_token) # "custom-token"
print(custom_settings.env("R2_ACCESS_TOKEN")) # reads from env/dotenv
To reset the cached auto-initialized singleton:
from project_toolkit import settings, get_settings
# Reset cached settings (e.g., after changing env vars)
get_settings.cache_clear()
settings._reset()
# Next access will re-initialize
print(settings.cloudflare.r2_access_token)
5. Project Path Management
Manage project directory structures with automatic creation:
from project_toolkit import DataPathConfig
# Direct usage
dpc = DataPathConfig(
project_name="my-project",
subproject="etl",
data_dir="/data",
)
print(dpc.data_dir()) # /data
print(dpc.project_dir()) # /data/my-project
print(dpc.sub_project_dir()) # /data/my-project/etl
# Get a timestamped file path
filepath = dpc.get_filepath("output", "csv")
# /data/my-project/etl/output_20260209.csv
From auto-initialized settings (recommended):
from project_toolkit import settings, DataPathConfig
dpc = DataPathConfig.from_settings(
settings.path_config,
project_name="my-project",
)
6. Cloudflare R2
from project_toolkit import settings
from project_toolkit.cloudflare.boto3_client import CloudflareBoto3Client
# From auto-initialized settings
client = CloudflareBoto3Client.from_settings(settings.cloudflare)
# Upload a file
client.upload_file("my-bucket", "file.csv", open("/path/to/file.csv", "rb").read())
# List buckets
buckets = client.list_buckets()
7. Google Sheets
from project_toolkit import settings
from project_toolkit.google.sheet import GoogleSheetsManager
sheets = GoogleSheetsManager.from_settings(settings.google)
# Read a sheet as a DataFrame
df = sheets.sheet_df(sheet_id="your-sheet-id")
print(df.head())
8. Google BigQuery
from project_toolkit import settings
from project_toolkit.google.bigquery import BigQueryManager
bq = BigQueryManager.from_settings(settings.google)
# Run a query
df = bq.query_table("SELECT * FROM my_dataset.my_table LIMIT 10")
9. Google Drive
from project_toolkit import settings
from project_toolkit.google.drive import GoogleDriveManager
drive = GoogleDriveManager.from_settings(settings.google)
# List files in a folder
files = drive.list_files(folder_id="your-folder-id")
10. WAN IP Tracker
from project_toolkit.wan_ip import WanIpTracker
tracker = WanIpTracker(log_dir="/tmp/ip-logs")
# Get current IPs (includes datetime)
print(tracker)
# Date: 2026-02-09 22:31:45
# IPv4: 1.2.3.4
# IPv6: 2001:db8::1
# Log only if changed
entry = tracker.log_if_changed()
Configuration
Environment Variables
| Variable | Module | Description |
|---|---|---|
R2_ACCESS_TOKEN |
Cloudflare | Cloudflare R2 API token |
R2_ACCOUNT_ID |
Cloudflare | Cloudflare account ID |
R2_DOMAIN |
Cloudflare | R2 custom domain URL |
GOOGLE_SERVICE_ACCOUNT_JSON |
Path to service account JSON | |
TEST_GOOGLE_SHEET_ID |
Test sheet ID (dev only) | |
VAULT_ADDR |
Vault | Vault server address (e.g., http://192.168.12.2:8200) |
VAULT_TOKEN |
Vault | Vault authentication token |
WAN_IP_LOG_DIR |
WAN IP | Directory for IP change logs |
AIRFLOW_HOME |
Core | Auto-detected for env switching |
Any key in your
.envfile or environment can be read dynamically viasettings.env("KEY")— no need to define it in Python code.
.env Files
Place config files in the config/ directory:
config/
├── .env.dev # Local development (loaded when no AIRFLOW_HOME)
└── .env.airflow # Airflow production (loaded when AIRFLOW_HOME is set)
Priority Order
Environment variables > .env files > Vault secrets > defaults
Development
# Install with all dependencies
pip install -e ".[all]"
# Run tests
pytest
# Run specific tests
pytest tests/test_settings.py -s -vv
pytest tests/test_vault.py -s -vv
pytest tests/test_auto_settings.py -s -vv
Project Structure
project_toolkit/
├── __init__.py # Package exports + auto-initialized settings singleton
├── project_path.py # Project path management (DataPathConfig)
├── settings/
│ ├── __init__.py # Settings exports
│ ├── base.py # AppSettings + get_settings() + env()
│ ├── path.py # PathSettings
│ ├── cloudflare.py # CloudflareSettings
│ ├── google.py # GoogleSettings
│ ├── vault.py # VaultSettings + read_secret() + read_field()
│ └── wan_ip.py # WanIpSettings
├── cloudflare/
│ ├── boto3_client.py # R2 via boto3
│ └── requests_client.py # R2 via requests
├── google/
│ ├── bigquery.py # BigQuery operations
│ ├── drive.py # Google Drive operations
│ └── sheet.py # Google Sheets operations
└── wan_ip/
└── tracker.py # WAN IP detection + logging
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file project_toolkit-1.0.2.tar.gz.
File metadata
- Download URL: project_toolkit-1.0.2.tar.gz
- Upload date:
- Size: 35.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b32ea8ce8906eab4e0f035c5b2f53bf476487f7e776b9bb1caf9c6df1751db25
|
|
| MD5 |
cfd31799ea2732686d1836ce502f38f7
|
|
| BLAKE2b-256 |
c5b434043160941e6ddab50acd8bf6e29db49782061876d1e0358f5733135ba8
|
File details
Details for the file project_toolkit-1.0.2-py3-none-any.whl.
File metadata
- Download URL: project_toolkit-1.0.2-py3-none-any.whl
- Upload date:
- Size: 28.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de3e1be8337330e0f02fb154ac6747f53d96193b89e51018197e9418f483592b
|
|
| MD5 |
ab3ff3f4a1ad5493f9ac1456f13f93e9
|
|
| BLAKE2b-256 |
3afae1d9a41e11da1a32b9b9af7b897ca1777ecbbee328f48cf9607f4d9adbea
|