Skip to content
Merged
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
69 changes: 63 additions & 6 deletions refractiveindex/refractiveindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,47 @@
from yaml import BaseLoader


# Latest commit as of 2026-02-17
# https://github.com/polyanskiy/refractiveindex.info-database/commits/master/
_DATABASE_SHA = "a66ef8805cdb200973fc7ae9181587e1d89d14eb"
# Default database SHA. Latest SHA will be found automatically if this is not set.
# https://github.com/polyanskiy/refractiveindex.info-database/commits/main
_DATABASE_SHA = None

_DEFAULT_DB_PATH = Path.home() / ".refractiveindex.info-database"

# Module-level cache: db_path -> {(shelf, book, page): filepath}
_catalog_cache = {}


def _download_database(db_path, ssl_certificate_location=None):
def _get_latest_commit_hash():
"""Get the latest commit hash from the main branch of the refractiveindex.info-database repository."""
try:
# Use GitHub API to get the latest commit SHA
import urllib.request
import json

url = "https://api.github.com/repos/polyanskiy/refractiveindex.info-database/commits/main"
with urllib.request.urlopen(url) as response:
data = json.loads(response.read().decode('utf-8'))
return data['sha']
except Exception as e:
print(f"Failed to get latest commit hash: {e}", file=sys.stderr)
return None


def _download_database(db_path, ssl_certificate_location=None, commit_hash=_DATABASE_SHA):
import shutil
import ssl
import tempfile
import urllib.request
import zipfile

url = f"https://github.com/polyanskiy/refractiveindex.info-database/archive/{_DATABASE_SHA}.zip"
# Use provided commit hash or get the latest one
if commit_hash is None:
commit_hash = _get_latest_commit_hash()
if commit_hash is None:
# Fallback to a known good commit if we can't fetch the latest
commit_hash = "ff11b5897ef0754b15d939d921eb6c745693cbd1"

url = f"https://github.com/polyanskiy/refractiveindex.info-database/archive/{commit_hash}.zip"

if ssl_certificate_location is not None:
if ssl_certificate_location == "":
Expand All @@ -52,8 +75,14 @@ def _download_database(db_path, ssl_certificate_location=None):
print("removing old database...", file=sys.stderr)
shutil.rmtree(db_path)

extracted = Path(tempdir) / f"refractiveindex.info-database-{_DATABASE_SHA}" / "database"
extracted = Path(tempdir) / f"refractiveindex.info-database-{commit_hash}" / "database"
shutil.move(str(extracted), str(db_path))

# Save the commit hash to version file
version_file = db_path / ".version"
with open(version_file, 'w') as f:
f.write(commit_hash)

print("done", file=sys.stderr)


Expand All @@ -63,6 +92,30 @@ def _ensure_database(db_path, auto_download, update_database, ssl_certificate_lo
return db_path


def _check_for_updates(db_path, ssl_certificate_location=None):
"""Check if there's a newer version of the database available and update if needed."""
try:
# Get the current commit hash from the database directory
version_file = db_path / ".version"
if version_file.exists():
with open(version_file, 'r') as f:
current_hash = f.read().strip()
else:
current_hash = None

# Get the latest commit hash
latest_hash = _get_latest_commit_hash()

if latest_hash and (current_hash is None or current_hash != latest_hash):
print(f"Updating database from {current_hash or 'unknown'} to {latest_hash}", file=sys.stderr)
_download_database(db_path, ssl_certificate_location, commit_hash=latest_hash)
return True
return False
except Exception as e:
print(f"Failed to check for updates: {e}", file=sys.stderr)
return False


def _load_catalog(db_path):
key = str(db_path)
if key in _catalog_cache:
Expand Down Expand Up @@ -266,6 +319,10 @@ def __init__(self, shelf, book, page, *,
db_path = Path(db_path)

_ensure_database(db_path, auto_download, update_database, ssl_certificate_location)

# Check for updates if requested
if update_database:
_check_for_updates(db_path, ssl_certificate_location)
catalog = _load_catalog(db_path)

key = (shelf, book, page)
Expand Down
22 changes: 22 additions & 0 deletions tests/test_refractiveindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,3 +340,25 @@ def test_epsilon_n_ik_consistency(self):
# Real parts should be equal, imaginary parts opposite sign
self.assertAlmostEqual(eps_minus.real, eps_plus.real)
self.assertAlmostEqual(eps_minus.imag, -eps_plus.imag)


class TestDatabaseUpdates(unittest.TestCase):
"""Tests for database update functionality."""

def test_database_version_file_exists(self):
"""Test that database version file exists after material loading."""
from pathlib import Path
version_file = Path.home() / '.refractiveindex.info-database' / '.version'

# Load a material (this should create/update the version file)
m = ri.RefractiveIndexMaterial(shelf='main', book='SiO2', page='Malitson')

# Check that version file exists
self.assertTrue(version_file.exists())

# Check that it contains some content (hash)
with open(version_file, 'r') as f:
hash_content = f.read().strip()

# Should not be empty
self.assertGreater(len(hash_content), 0)
Loading