Skip to content

Commit 1bf5b89

Browse files
add more tests for config
1 parent 75d403d commit 1bf5b89

File tree

5 files changed

+96
-18
lines changed

5 files changed

+96
-18
lines changed

docs/source/user_guide/installation/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ Package Minimum supp
7171
`typing-extensions <https://pypi.org/project/typing-extensions/>`__ 4.10.0
7272
`pandas <https://pypi.org/project/pandas/>`__ 1.5.0
7373
`pooch <https://www.fatiando.org/pooch/>`__ 1.8.1
74+
`posthog <https://posthog.com/>`__ 3.6.5
7475
=================================================================== ==========================
7576

7677
.. _install.optional_dependencies:

noxfile.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def set_iree_state():
4949
"IREE_INDEX_URL": os.getenv(
5050
"IREE_INDEX_URL", "https://iree.dev/pip-release-links.html"
5151
),
52+
"PYBAMM_DISABLE_TELEMETRY": "true",
5253
}
5354
VENV_DIR = Path("./venv").resolve()
5455

src/pybamm/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@
203203
import os
204204
import pathlib
205205
import sysconfig
206-
os.environ["CASADIPATH"] = str(pathlib.Path(sysconfig.get_path('purelib')) / 'casadi')
206+
207+
os.environ["CASADIPATH"] = str(pathlib.Path(sysconfig.get_path("purelib")) / "casadi")
207208

208209
__all__ = [
209210
"batch_study",
@@ -232,5 +233,4 @@
232233
"pybamm_data",
233234
]
234235

235-
236236
pybamm.config.generate()

src/pybamm/config.py

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
import platformdirs
44
from pathlib import Path
55
import pybamm
6-
import select
76
import sys
7+
import threading
8+
import time
89

910

1011
def is_running_tests(): # pragma: no cover
@@ -14,8 +15,6 @@ def is_running_tests(): # pragma: no cover
1415
Returns:
1516
bool: True if running tests or building docs, False otherwise.
1617
"""
17-
import sys
18-
1918
# Check if pytest or unittest is running
2019
if any(
2120
test_module in sys.modules for test_module in ["pytest", "unittest", "nose"]
@@ -33,11 +32,14 @@ def is_running_tests(): # pragma: no cover
3332

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

3938
# Check if building docs with Sphinx
40-
if "sphinx" in sys.modules:
39+
if any(mod == "sphinx" or mod.startswith("sphinx.") for mod in sys.modules):
40+
print(
41+
f"Found Sphinx module: {[mod for mod in sys.modules if mod.startswith('sphinx')]}"
42+
)
4143
return True
4244

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

72+
def get_input():
73+
try:
74+
user_input = (
75+
input("Do you want to enable telemetry? (Y/n): ").strip().lower()
76+
)
77+
answer.append(user_input)
78+
except Exception:
79+
# Handle any input errors
80+
pass
81+
82+
time_start = time.time()
83+
7084
while True:
71-
print("Do you want to enable telemetry? (Y/n): ", end="", flush=True)
85+
if time.time() - time_start > timeout:
86+
print("\nTimeout reached. Defaulting to not enabling telemetry.")
87+
return False
88+
89+
answer = []
90+
# Create and start input thread
91+
input_thread = threading.Thread(target=get_input)
92+
input_thread.daemon = True
93+
input_thread.start()
94+
95+
# Wait for either timeout or input
96+
input_thread.join(timeout)
7297

73-
rlist, _, _ = select.select([sys.stdin], [], [], timeout)
74-
if rlist:
75-
user_input = sys.stdin.readline().strip().lower()
76-
if user_input in ["yes", "y", ""]:
98+
if answer:
99+
if answer[0] in ["yes", "y", ""]:
100+
print("\nTelemetry enabled.\n")
77101
return True
78-
elif user_input in ["no", "n"]:
102+
elif answer[0] in ["no", "n"]:
103+
print("\nTelemetry disabled.\n")
79104
return False
80105
else:
81-
print("Invalid input. Please enter 'yes/y' for yes or 'no/n' for no.")
106+
print("\nInvalid input. Please enter 'yes/y' for yes or 'no/n' for no.")
82107
else:
83108
print("\nTimeout reached. Defaulting to not enabling telemetry.")
84109
return False
85110

86111

87-
def generate(): # pragma: no cover
112+
def generate():
88113
if is_running_tests():
89114
return
90115

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

103128

104-
def read(): # pragma: no cover
129+
def read():
105130
config_file = Path(platformdirs.user_config_dir("pybamm")) / "config.yml"
106131
return read_uuid_from_file(config_file)
107132

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

122147
def read_uuid_from_file(config_file):
123148
# Check if the config file exists
124-
if not config_file.exists(): # pragma: no cover
149+
if not config_file.exists():
125150
return None
126151

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

135160
config = yaml.safe_load(content)
136161
return config["pybamm"]
137-
except (yaml.YAMLError, ValueError): # pragma: no cover
162+
except (yaml.YAMLError, ValueError):
138163
return None

tests/unit/test_config.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import pybamm
66
import uuid
7+
from pathlib import Path
8+
import platformdirs
79

810

911
class TestConfig:
@@ -104,3 +106,52 @@ def mock_select(*args, **kwargs):
104106
captured = capsys.readouterr()
105107
assert "Do you want to enable telemetry? (Y/n):" in captured.out
106108
assert "Timeout reached. Defaulting to not enabling telemetry." in captured.out
109+
110+
def test_generate_and_read(self, monkeypatch, tmp_path):
111+
# Mock is_running_tests to return False
112+
monkeypatch.setattr(pybamm.config, "is_running_tests", lambda: False)
113+
114+
# Mock ask_user_opt_in to return True
115+
monkeypatch.setattr(pybamm.config, "ask_user_opt_in", lambda: True)
116+
117+
# Mock telemetry capture
118+
capture_called = False
119+
120+
def mock_capture(event):
121+
nonlocal capture_called
122+
assert event == "user-opted-in"
123+
capture_called = True
124+
125+
monkeypatch.setattr(pybamm.telemetry, "capture", mock_capture)
126+
127+
# Mock config directory
128+
monkeypatch.setattr(platformdirs, "user_config_dir", lambda x: str(tmp_path))
129+
130+
# Test generate() creates new config
131+
pybamm.config.generate()
132+
133+
# Verify config was created
134+
config = pybamm.config.read()
135+
assert config is not None
136+
assert config["enable_telemetry"] is True
137+
assert "uuid" in config
138+
assert capture_called is True
139+
140+
# Test generate() does nothing if config exists
141+
capture_called = False
142+
pybamm.config.generate()
143+
assert capture_called is False
144+
145+
def test_read_uuid_from_file_no_file(self):
146+
config_dict = pybamm.config.read_uuid_from_file(Path("nonexistent_file.yml"))
147+
assert config_dict is None
148+
149+
def test_read_uuid_from_file_invalid_yaml(self, tmp_path):
150+
# Create a temporary directory and file with invalid YAML content
151+
invalid_yaml = tmp_path / "invalid_yaml.yml"
152+
with open(invalid_yaml, "w") as f:
153+
f.write("invalid: yaml: content:")
154+
155+
config_dict = pybamm.config.read_uuid_from_file(invalid_yaml)
156+
157+
assert config_dict is None

0 commit comments

Comments
 (0)