Skip to content

Commit f267d91

Browse files
stephprincepre-commit-ci[bot]CodyCBakerPhD
authored
Updates to flask app and database updating (#153)
Some minor documentation and code changes that came up when trying to debug the database updating locally. When debugging, I inadvertently pushed the latest results to the nwb-benchmarks-database GitHub repo - I updated the app script to skip pushing new files when in debug mode but let me know your thoughts on if we need any better protections. From what I could tell, the `repackage_as_parquet` function was not saving the values from the network tests - which are stored as a dictionary of several metrics with their associated values. I added an additional column / attribute to the results that saves the variable name of each metric (and in the case of the timing tests, uses the variable name "time") --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Cody Baker <[email protected]>
1 parent d960254 commit f267d91

File tree

4 files changed

+52
-8
lines changed

4 files changed

+52
-8
lines changed

docs/development.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ Development
44
This section covers advanced implementation details for managing the operation of the AirSpeed Velocity testing suite.
55

66

7+
Environment Setup
8+
------------
9+
10+
To setup a development environment, use ``pip install -e . --group all`` to install all dependencies including those for development and testing.
11+
This command will install all packages required for the flask app, database management, and dev testing.
12+
13+
If you would like to run the flask app in debug mode, set the environment variable ``NWB_BENCHMARKS_DEBUG=1``.
14+
15+
716
Coding Style
817
------------
918

docs/running_benchmarks.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ If this fails, you can contribute your results manually by:
9494

9595
.. code-block::
9696
97-
<Fork https://github.com/CodyCBakerPhD/nwb-benchmarks-results on GitHub>
97+
<Fork https://github.com/NeurodataWithoutBorders/nwb-benchmarks-results on GitHub>
9898
git clone https://github.com/<your GitHub username>/nwb-benchmarks-results
9999
git checkout -b new_results_from_<...>
100100
<copy results from ~/.cache/nwb_benchmarks/results>

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ classifiers = [
5656
nwb_benchmarks = "nwb_benchmarks.command_line_interface:main"
5757

5858
[dependency-groups]
59-
app = ["flask", "flask-cors"]
59+
app = ["flask", "flask-cors", "flask_restx"]
6060
database = ["polars"]
6161
dev = ["ipython", "pre-commit"]
6262
all = [

src/nwb_benchmarks/_flask/_app.py

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,24 @@ def __init__(self, repo_name: str):
121121
self.cache_directory = Path.home() / ".cache" / "nwb-benchmarks"
122122
self.cache_directory.mkdir(parents=True, exist_ok=True)
123123
self.repo_path = self.cache_directory / repo_name
124+
self.debug_mode = os.environ.get("NWB_BENCHMARKS_DEBUG") == "1"
124125

125126
def ensure_repo_up_to_date(self) -> typing.Literal[521, 522] | None:
126-
"""Clone repository if it doesn't exist locally."""
127+
"""Pull latest updates from repository. Clone repository first if it doesn't exist locally."""
127128
if not self.repo_path.exists():
128-
return 521
129+
command = f"git clone https://github.com/NeurodataWithoutBorders/nwb-benchmarks-database"
130+
cwd = self.repo_path.parent
131+
cwd.mkdir(parents=True, exist_ok=True)
132+
result = subprocess.run(
133+
args=command,
134+
cwd=cwd,
135+
capture_output=True,
136+
shell=True,
137+
)
138+
if result.returncode != 0:
139+
message = f"Git command ({command}) failed: {traceback.format_exc()}"
140+
print(f"ERROR: {message}")
141+
return 521
129142

130143
command = f"git pull"
131144
cwd = self.repo_path
@@ -160,6 +173,10 @@ def write_file(self, filename: pathlib.Path, json_content: dict) -> None:
160173

161174
def add_and_commit(self, message: str) -> typing.Literal[523] | None:
162175
"""Commit results to git repo."""
176+
if self.debug_mode:
177+
print("Debug mode enabled, skipping git commit.")
178+
return None
179+
163180
command = f"git add . && git commit -m '{message}'"
164181
result = subprocess.run(
165182
args=command,
@@ -174,6 +191,10 @@ def add_and_commit(self, message: str) -> typing.Literal[523] | None:
174191

175192
def push(self):
176193
"""Commit and push results to GitHub repository."""
194+
if self.debug_mode:
195+
print("Debug mode enabled, skipping git push.")
196+
return None
197+
177198
command = "git push"
178199
cwd = self.repo_path
179200
result = subprocess.run(
@@ -264,7 +285,7 @@ def safe_load_from_json(cls, file_path: pathlib.Path) -> typing_extensions.Self
264285
preamble = next(iter(data.keys()))
265286

266287
packages = {
267-
package["name"]: f"{package["version"]} ({package["build"]})"
288+
package["name"]: f'{package["version"]} ({package["build"]})'
268289
for package in data[preamble]
269290
if len(package) == 3
270291
}
@@ -300,6 +321,7 @@ class Result:
300321
benchmark_name: str
301322
parameter_case: str
302323
value: float
324+
variable: str
303325

304326

305327
@dataclasses.dataclass
@@ -322,6 +344,16 @@ def safe_load_from_json(cls, file_path: pathlib.Path) -> typing_extensions.Self
322344
environment_id = data["environment_id"]
323345
machine_id = data["machine_id"]
324346

347+
def normalize_time_and_network_results(benchmark_results) -> dict:
348+
"""Convert benchmark results to a consistent dict format with list values."""
349+
if isinstance(benchmark_results, dict):
350+
value_dict = benchmark_results
351+
else:
352+
value_dict = dict(time=benchmark_results)
353+
354+
# Ensure all values are lists
355+
return {k: v if isinstance(v, list) else [float(v)] for k, v in value_dict.items()}
356+
325357
results = [
326358
Result(
327359
uuid=str(uuid.uuid4()), # TODO: add this to each results file so it is persistent
@@ -332,12 +364,15 @@ def safe_load_from_json(cls, file_path: pathlib.Path) -> typing_extensions.Self
332364
machine_id=machine_id,
333365
benchmark_name=benchmark_name,
334366
parameter_case=parameter_case,
335-
value=benchmark_result,
367+
value=value,
368+
variable=variable_name,
336369
)
337370
for benchmark_name, parameter_cases in data["results"].items()
338371
for parameter_case, benchmark_results in parameter_cases.items()
339-
for benchmark_result in benchmark_results
372+
for variable_name, values in normalize_time_and_network_results(benchmark_results).items()
373+
for value in values
340374
]
375+
341376
return cls(results=results)
342377

343378
def to_dataframe(self) -> "polars.DataFrame":
@@ -352,6 +387,7 @@ def to_dataframe(self) -> "polars.DataFrame":
352387
"benchmark_name": [result.benchmark_name for result in self.results],
353388
"parameter_case": [result.parameter_case for result in self.results],
354389
"value": [result.value for result in self.results],
390+
"variable": [result.variable for result in self.results],
355391
}
356392

357393
data_frame = polars.DataFrame(data=data)
@@ -401,7 +437,6 @@ def repackage_as_parquet(directory: pathlib.Path, output_directory: pathlib.Path
401437

402438
if results is None:
403439
continue
404-
405440
results_data_frame = results.to_dataframe()
406441
all_results_data_frames.append(results_data_frame)
407442
all_results_database = polars.concat(items=all_results_data_frames, how="diagonal")

0 commit comments

Comments
 (0)