Bolster's Brain, you've been warned π§
A comprehensive Python utility library for data science, web scraping, cloud services, and general development workflows. Originally designed as a personal toolkit, Bolster has evolved into a robust collection of utilities that enhance productivity across data analysis, system administration, and software development tasks.
pip install bolsterimport bolster
# Efficient data processing with built-in progress tracking
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
results = bolster.poolmap(lambda x: x**2, data)
print(results) # {1: 1, 2: 4, 3: 9, 4: 16, ...}
# Smart retry logic with exponential backoff
@bolster.backoff(Exception, tries=3, delay=1, backoff=2)
def unreliable_api_call():
# Your potentially failing code here
return "Success!"
# Efficient tree/dict navigation
nested_data = {
"users": {
"active": [{"name": "Alice", "age": 25}, {"name": "Bob", "age": 30}],
"inactive": [{"name": "Charlie", "age": 35}],
}
}
# Find all ages recursively
ages = bolster.get_recursively(nested_data, "age")
print(ages) # [25, 30, 35]
# Flatten nested structures
flat = bolster.flatten_dict(nested_data)
print(flat["users:active:0:name"]) # 'Alice'poolmap(): ThreadPoolExecutor wrapper with progress monitoring and robust error handlingexceptional_executor(): Graceful handling of failed futures in concurrent operationsbackoff(): Exponential backoff retry decorator for unreliable operationsmemoize(): Instance method caching with hit/miss tracking for performance optimization
aggregate(): Pandas-like groupby operations for dictionaries and liststransform_(): Flexible data transformation with key mapping and function applicationbatch()/chunks(): Efficient sequence partitioning for processing large datasets- Compression utilities:
compress_for_relay()/decompress_from_relay()for data serialization
get_recursively(): Extract values from deeply nested structures by keyflatten_dict(): Convert nested dictionaries to flat key-value pairs- Tree analysis:
breadth(),depth(),leaves(),leaf_paths()for structure inspection - Path navigation:
keys_at(),items_at()for level-specific data access
arg_exception_logger(): Decorator for debugging function calls with automatic argument loggingMultipleErrors: Accumulate and handle multiple exceptions in complex workflowsworking_directory(): Context manager for safe directory operationspretty_print_request(): HTTP request debugging with automatic auth redaction
Bolster includes specialized modules for working with Northern Ireland and UK data sources:
from bolster.data_sources.ni_water import get_water_quality, get_water_quality_by_zone
# Get comprehensive water quality data for all NI supply zones
df = get_water_quality()
print(df.shape) # Shows number of zones and parameters
# Get specific zone data
zone_data = get_water_quality_by_zone("BALM") # Belfast Malone area
print(f"Hardness: {zone_data['NI Hardness Classification']}")from bolster.data_sources.eoni import get_election_results
# Get Assembly election results
results_2016 = get_election_results(2016)
results_2022 = get_election_results(2022)
# Compare party performance across elections
comparison = bolster.diff(results_2022, results_2016)from bolster.data_sources.companies_house import search_companies, get_company_details
# Search for companies
results = search_companies("Technology")
# Get detailed company information
company = get_company_details("12345678") # Company number
print(f"{company['name']} - Status: {company['status']}")from bolster.data_sources.metoffice import get_precipitation_data
# Get weather data for a specific location
weather = get_precipitation_data("Belfast", start_date="2024-01-01", end_date="2024-01-31")from bolster.data_sources.ni_house_price_index import (
get_hpi_trends,
get_sales_volumes,
get_average_prices,
)
# Get HPI index trends over time (Q1 2005 - present)
hpi = get_hpi_trends()
print(hpi[["Period", "NI House Price Index", "Annual Change"]].tail())
# Get property sales volumes by type
sales = get_sales_volumes()
print(f"Total sales in latest quarter: {sales.iloc[-1]['Total']:,}")
# Get average sale prices
prices = get_average_prices()
print(f"Current median price: Β£{prices.iloc[-1]['Simple Median']:,.0f}")Comprehensive access to Northern Ireland Statistics and Research Agency (NISRA) data:
from bolster.data_sources.nisra import population, births, deaths, migration
# Mid-year population estimates by geography and demographics
pop_df = population.get_latest_population()
print(f"NI Population: {pop_df['population'].sum():,}")
# Monthly birth registrations
births_df = births.get_latest_births()
# Weekly death registrations with excess deaths analysis
deaths_df = deaths.get_latest_deaths()
# Migration estimates derived from demographic components
migration_df = migration.get_latest_migration()Additional NISRA modules: labour_market, index_of_production, index_of_services, construction_output, composite_index, marriages, ashe (earnings survey), quarterly_employment_survey, stillbirths.
Department of Health NI modules (under health_ni): emergency_care_waiting_times, elective_waiting_times, cancer_waiting_times, diagnostic_waiting_times, disease_prevalence, child_protection.
See NISRA module documentation for full API reference.
The GOV.UK NISRA statistics RSS feed tracks new NISRA publications. Current implementation status:
| Publication | Module | Status |
|---|---|---|
| Claimant Count (UC + JSA) | nisra.claimant_count |
β |
| Labour Market Statistics | nisra.labour_market |
β |
| Weekly/Monthly Deaths | nisra.deaths |
β |
| Monthly Births/Stillbirths | nisra.births |
β |
| Monthly Marriages & Civil Partnerships | nisra.marriages |
β |
| NI Composite Economic Index | nisra.composite_index |
β |
| Construction Bulletin | nisra.construction_output |
β |
| Index of Production | nisra.index_of_production |
β |
| Index of Services | nisra.index_of_services |
β |
| Quarterly Employment Survey | nisra.quarterly_employment_survey |
β |
| Emergency Care Waiting Times | health_ni.emergency_care_waiting_times |
β |
| Elective/Outpatient Waiting Times | health_ni.elective_waiting_times |
β |
| Monthly Stillbirths | nisra.stillbirths |
β |
| Population Estimates | nisra.population |
β |
| Migration Estimates (Derived + Official LTI) | nisra.migration |
β |
| Population Projections (NI-level, biennial vintage) | nisra.population_projections |
β |
| Population Projections β LGD sub-areas (2022-based, 2022β2047) | nisra.population_projections |
β |
| Annual Survey of Hours & Earnings | nisra.ashe |
β |
| DVA Monthly Tests Statistics | dva |
β |
| UK Gender Pay Gap Reporting | gender_pay_gap |
β |
| Individual Wellbeing | nisra.wellbeing |
β |
| Cancer Waiting Times | health_ni.cancer_waiting_times |
β |
| Diagnostic Waiting Times | health_ni.diagnostic_waiting_times |
β |
| Child Protection Statistics | health_ni.child_protection |
β |
| NI Planning Activity Statistics (DfI) | nisra.planning_statistics |
β |
| NI Housing Stock Statistics (DoF/LPS) | nisra.housing_stock |
β |
| Registrar General Quarterly Tables | nisra.registrar_general |
β |
| Tourism - Hotel Occupancy | nisra.tourism.occupancy |
β |
| Tourism - SSA Occupancy | nisra.tourism.occupancy |
β |
| Tourism - Visitor Statistics | nisra.tourism.visitor_statistics |
β |
| Baby Names NI (annual, 1997βpresent) | nisra.baby_names |
β |
| NI School Suspensions (DE) | education_suspensions |
β |
| NICTS Mortgages Action for Possession (DoJ) | justice.mortgages |
β |
| Work Quality NI (NISRA) | nisra.work_quality |
β |
| NI LAC Municipal Waste Statistics (DAERA) | daera_waste |
β |
| NI Claimant Count (UC + JSA, DfC/ONS) | nisra.claimant_count |
β |
| PSNI Police Ombudsman Complaints | psni.police_ombudsman |
β |
| Public Confidence in Official Statistics (NISRA PCOS) | nisra.public_confidence |
β |
| Disease Prevalence Registers (PHA/DoH) | health_ni.disease_prevalence |
β |
| Drug-Related & Drug Misuse Deaths | nisra.drug_related_deaths |
β |
| PSNI Stop & Search (OpenDataNI) | psni.stop_and_search |
β |
| PSNI PACE Stop & Search / Arrests | psni.pace |
β |
| ONS UK Inflation (CPI / CPIH / RPI) | ons_cpi |
β |
| Bank of England Base Rate | boe_base_rate |
β |
| NI Assembly β MLAs, Parties, Constituencies | niassembly.members |
β |
| NI Assembly β Questions (oral & written, 2007βpresent) | niassembly.questions |
β |
| NI Assembly β Votes/Divisions (per-member records) | niassembly.votes |
β |
| NI Business Register (IDBR, annual) | nisra.business_register |
β |
| NI Multiple Deprivation Measure 2017 (NIMDM, SOA-level) | nisra.deprivation |
β |
| Translink Live Departures & Vehicle Positions | translink |
β |
| Security Situation Statistics | - | β Cloudflare-blocked |
| Anti-social Behaviour | - | β Cloudflare-blocked |
| Domestic Abuse Incidents/Crimes | - | β Cloudflare-blocked |
| Drug Seizures & Arrests | - | β Cloudflare-blocked |
| Hate Incidents & Crimes | - | β Cloudflare-blocked |
| Road Traffic Collisions | psni.road_traffic_collisions |
β |
| PSNI Crime Statistics | psni.crime_statistics |
get_latest raises PSNIDataStaleError |
| Police Ombudsman Complaints | psni.police_ombudsman |
β |
| Stop & Search | psni.stop_and_search |
β |
| PACE Stop & Search / Arrests | psni.pace |
β |
The Infrastructure NI publications portal provides advanced filtering capabilities beyond basic publication types. Analysis of the sidebar filtering system reveals additional organizational dimensions that could enhance data source discovery:
Next Steps Analysis Directions:
- Topic categorization: Publications span transport, environment, planning, and infrastructure domains
- Geographic filtering: Regional breakdown capabilities for localized analysis
- Date range analysis: Historical publication patterns and frequency tracking
- Document format analysis: Structured data availability vs. narrative reports
- Cross-departmental integration: Links with other NI government department publications
This systematic analysis could identify gaps in current DVA coverage and reveal additional structured datasets suitable for bolster integration.
from bolster.aws import get_session, S3Handler, DynamoHandler
# Get configured AWS session
session = get_session(profile="production")
# S3 operations with best practices
s3 = S3Handler(session)
s3.upload_file("local_file.txt", "bucket-name", "remote/path/file.txt")
# DynamoDB operations
dynamo = DynamoHandler(session)
items = dynamo.scan_table("user-data", filters={"status": "active"})from bolster.azure import AzureHandler
# Azure Blob Storage operations
azure = AzureHandler(connection_string="DefaultEndpointsProtocol=https;...")
azure.upload_blob("container", "blob_name", data)from bolster.web import safe_request, parse_html_table
# Robust HTTP requests with automatic retries
response = safe_request("https://api.example.com/data", max_retries=3, timeout=30)
# Parse HTML tables into pandas DataFrames
tables = parse_html_table("https://example.com/tables")
print(tables[0].head()) # First table as DataFrameBolster includes a CLI for common operations:
# Get precipitation data
bolster get-precipitation --location "Belfast" --start-date "2024-01-01"
# Get help on available commands
bolster --helpimport bolster
from datetime import datetime
# Process large datasets with progress tracking
def process_user_data(user_id):
# Simulate data processing
return {"user_id": user_id, "processed_at": datetime.now()}
user_ids = range(1000) # 1000 users to process
# Process with automatic progress bar and error handling
results = bolster.poolmap(
process_user_data,
user_ids,
max_workers=10,
progress=True, # Shows progress bar
)
print(f"Processed {len(results)} users successfully")class DataProcessor:
@bolster.memoize
def expensive_calculation(self, data_hash):
# Expensive operation that we want to cache
import time
time.sleep(2) # Simulate expensive operation
return f"Processed: {data_hash}"
processor = DataProcessor()
# First call - takes 2 seconds
result1 = processor.expensive_calculation("abc123")
# Second call with same input - returns immediately from cache
result2 = processor.expensive_calculation("abc123")
# Check cache performance
print(f"Cache hits: {len(processor._memoize__hits)}")
print(f"Cache misses: {len(processor._memoize__misses)}")import requests
import bolster
@bolster.backoff((requests.RequestException, ConnectionError), tries=5, delay=1, backoff=2)
def fetch_api_data(url):
response = requests.get(url, timeout=10)
response.raise_for_status()
return response.json()
# This will automatically retry with exponential backoff on failure
data = fetch_api_data("https://api.unreliable-service.com/data")# Transform API response to database format
api_response = {
"user_name": "john_doe",
"user_email": "john@example.com",
"account_type": "premium",
"signup_timestamp": "2024-01-01T12:00:00Z",
}
# Define transformation rules
rules = {
"user_name": ("username", str.upper), # Rename and transform
"user_email": ("email", None), # Keep as-is but rename
"account_type": ("tier", lambda x: x.title()), # Transform value
"signup_timestamp": ("created_at", bolster.parse_iso_datetime),
}
# Apply transformation
db_record = bolster.transform_(api_response, rules)
print(db_record)
# {'username': 'JOHN_DOE', 'email': 'john@example.com',
# 'tier': 'Premium', 'created_at': datetime(2024, 1, 1, 12, 0, 0)}- Python 3.9+ (3.10, 3.11, 3.12, 3.13 supported)
- uv (fast Python package manager)
# Clone the repository
git clone https://github.com/andrewbolster/bolster.git
cd bolster
# Install with development dependencies
uv sync --all-extras --dev
# Install pre-commit hooks
uv run pre-commit install
# Run tests
uv run pytest
# Run with coverage
uv run pytest --cov=bolster --cov-report=html
# Build documentation
cd docs && uv run make html# Run all tests
uv run pytest
# Run with verbose output and coverage
uv run pytest -v --cov=bolster --cov-report=term-missing
# Run specific test file
uv run pytest tests/test_core_utilities.py
# Skip network-dependent tests (useful if SSL issues)
uv run pytest -m "not network"- Full Documentation: https://bolster.readthedocs.io
- API Reference: Auto-generated from docstrings
- Examples: See
/notebooksdirectory for Jupyter notebook examples - Data Sources: Detailed documentation for each data source module
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Testing: Ensure all new features have comprehensive tests
- Documentation: Add docstrings and update README for new features
- Code Style: Follow the existing code style (enforced by ruff)
- Type Hints: Include type annotations for all public functions
- Performance: Consider performance implications for data processing functions
This project is licensed under the GNU General Public License v3 (GPLv3) - see the LICENSE file for details.
If you encounter any bugs or issues, please file a bug report at: https://github.com/andrewbolster/bolster/issues
- PyPI: https://pypi.org/project/bolster/
- GitHub: https://github.com/andrewbolster/bolster
- Documentation: https://bolster.readthedocs.io
- Author: Andrew Bolster
Built with β€οΈ for data science, automation, and general productivity enhancement.