Skip to content

Commit

Permalink
add more tests for config
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinsulzer committed Oct 28, 2024
1 parent 75d403d commit 1bf5b89
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 18 deletions.
1 change: 1 addition & 0 deletions docs/source/user_guide/installation/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Package Minimum supp
`typing-extensions <https://pypi.org/project/typing-extensions/>`__ 4.10.0
`pandas <https://pypi.org/project/pandas/>`__ 1.5.0
`pooch <https://www.fatiando.org/pooch/>`__ 1.8.1
`posthog <https://posthog.com/>`__ 3.6.5
=================================================================== ==========================

.. _install.optional_dependencies:
Expand Down
1 change: 1 addition & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def set_iree_state():
"IREE_INDEX_URL": os.getenv(
"IREE_INDEX_URL", "https://iree.dev/pip-release-links.html"
),
"PYBAMM_DISABLE_TELEMETRY": "true",
}
VENV_DIR = Path("./venv").resolve()

Expand Down
4 changes: 2 additions & 2 deletions src/pybamm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@
import os
import pathlib
import sysconfig
os.environ["CASADIPATH"] = str(pathlib.Path(sysconfig.get_path('purelib')) / 'casadi')

os.environ["CASADIPATH"] = str(pathlib.Path(sysconfig.get_path("purelib")) / "casadi")

__all__ = [
"batch_study",
Expand Down Expand Up @@ -232,5 +233,4 @@
"pybamm_data",
]


pybamm.config.generate()
57 changes: 41 additions & 16 deletions src/pybamm/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
import platformdirs
from pathlib import Path
import pybamm
import select
import sys
import threading
import time


def is_running_tests(): # pragma: no cover
Expand All @@ -14,8 +15,6 @@ def is_running_tests(): # pragma: no cover
Returns:
bool: True if running tests or building docs, False otherwise.
"""
import sys

# Check if pytest or unittest is running
if any(
test_module in sys.modules for test_module in ["pytest", "unittest", "nose"]
Expand All @@ -33,11 +32,14 @@ def is_running_tests(): # pragma: no cover

# Check for common test runner names in command-line arguments
test_runners = ["pytest", "unittest", "nose", "trial", "nox", "tox"]
if any(runner in sys.argv[0].lower() for runner in test_runners):
if any(runner in arg.lower() for arg in sys.argv for runner in test_runners):
return True

# Check if building docs with Sphinx
if "sphinx" in sys.modules:
if any(mod == "sphinx" or mod.startswith("sphinx.") for mod in sys.modules):
print(
f"Found Sphinx module: {[mod for mod in sys.modules if mod.startswith('sphinx')]}"
)
return True

return False
Expand Down Expand Up @@ -67,24 +69,47 @@ def ask_user_opt_in(timeout=10):
"For more information, see https://docs.pybamm.org/en/latest/source/user_guide/index.html#telemetry"
)

def get_input():
try:
user_input = (

Check warning on line 74 in src/pybamm/config.py

View check run for this annotation

Codecov / codecov/patch

src/pybamm/config.py#L73-L74

Added lines #L73 - L74 were not covered by tests
input("Do you want to enable telemetry? (Y/n): ").strip().lower()
)
answer.append(user_input)
except Exception:

Check warning on line 78 in src/pybamm/config.py

View check run for this annotation

Codecov / codecov/patch

src/pybamm/config.py#L77-L78

Added lines #L77 - L78 were not covered by tests
# Handle any input errors
pass

Check warning on line 80 in src/pybamm/config.py

View check run for this annotation

Codecov / codecov/patch

src/pybamm/config.py#L80

Added line #L80 was not covered by tests

time_start = time.time()

while True:
print("Do you want to enable telemetry? (Y/n): ", end="", flush=True)
if time.time() - time_start > timeout:
print("\nTimeout reached. Defaulting to not enabling telemetry.")
return False

answer = []
# Create and start input thread
input_thread = threading.Thread(target=get_input)
input_thread.daemon = True
input_thread.start()

# Wait for either timeout or input
input_thread.join(timeout)

rlist, _, _ = select.select([sys.stdin], [], [], timeout)
if rlist:
user_input = sys.stdin.readline().strip().lower()
if user_input in ["yes", "y", ""]:
if answer:
if answer[0] in ["yes", "y", ""]:
print("\nTelemetry enabled.\n")
return True
elif user_input in ["no", "n"]:
elif answer[0] in ["no", "n"]:
print("\nTelemetry disabled.\n")
return False
else:
print("Invalid input. Please enter 'yes/y' for yes or 'no/n' for no.")
print("\nInvalid input. Please enter 'yes/y' for yes or 'no/n' for no.")
else:
print("\nTimeout reached. Defaulting to not enabling telemetry.")
return False


def generate(): # pragma: no cover
def generate():
if is_running_tests():
return

Expand All @@ -101,7 +126,7 @@ def generate(): # pragma: no cover
pybamm.telemetry.capture("user-opted-in")


def read(): # pragma: no cover
def read():
config_file = Path(platformdirs.user_config_dir("pybamm")) / "config.yml"
return read_uuid_from_file(config_file)

Expand All @@ -121,7 +146,7 @@ def write_uuid_to_file(config_file, opt_in):

def read_uuid_from_file(config_file):
# Check if the config file exists
if not config_file.exists(): # pragma: no cover
if not config_file.exists():
return None

# Read the UUID from the config file
Expand All @@ -134,5 +159,5 @@ def read_uuid_from_file(config_file):

config = yaml.safe_load(content)
return config["pybamm"]
except (yaml.YAMLError, ValueError): # pragma: no cover
except (yaml.YAMLError, ValueError):
return None
51 changes: 51 additions & 0 deletions tests/unit/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import pybamm
import uuid
from pathlib import Path
import platformdirs


class TestConfig:
Expand Down Expand Up @@ -104,3 +106,52 @@ def mock_select(*args, **kwargs):
captured = capsys.readouterr()
assert "Do you want to enable telemetry? (Y/n):" in captured.out
assert "Timeout reached. Defaulting to not enabling telemetry." in captured.out

def test_generate_and_read(self, monkeypatch, tmp_path):
# Mock is_running_tests to return False
monkeypatch.setattr(pybamm.config, "is_running_tests", lambda: False)

# Mock ask_user_opt_in to return True
monkeypatch.setattr(pybamm.config, "ask_user_opt_in", lambda: True)

# Mock telemetry capture
capture_called = False

def mock_capture(event):
nonlocal capture_called
assert event == "user-opted-in"
capture_called = True

monkeypatch.setattr(pybamm.telemetry, "capture", mock_capture)

# Mock config directory
monkeypatch.setattr(platformdirs, "user_config_dir", lambda x: str(tmp_path))

# Test generate() creates new config
pybamm.config.generate()

# Verify config was created
config = pybamm.config.read()
assert config is not None
assert config["enable_telemetry"] is True
assert "uuid" in config
assert capture_called is True

# Test generate() does nothing if config exists
capture_called = False
pybamm.config.generate()
assert capture_called is False

def test_read_uuid_from_file_no_file(self):
config_dict = pybamm.config.read_uuid_from_file(Path("nonexistent_file.yml"))
assert config_dict is None

def test_read_uuid_from_file_invalid_yaml(self, tmp_path):
# Create a temporary directory and file with invalid YAML content
invalid_yaml = tmp_path / "invalid_yaml.yml"
with open(invalid_yaml, "w") as f:
f.write("invalid: yaml: content:")

config_dict = pybamm.config.read_uuid_from_file(invalid_yaml)

assert config_dict is None

0 comments on commit 1bf5b89

Please sign in to comment.