diff --git a/docs/modules.rst b/docs/modules.rst index 467d763..5a06717 100644 --- a/docs/modules.rst +++ b/docs/modules.rst @@ -4,6 +4,7 @@ Rush Modules :maxdepth: 1 rush.exess + rush.xtb rush.nnxtb rush.prepare_protein rush.prepare_complex diff --git a/docs/rush.xtb.rst b/docs/rush.xtb.rst new file mode 100644 index 0000000..8604599 --- /dev/null +++ b/docs/rush.xtb.rst @@ -0,0 +1,7 @@ +Grimme Lab xTB +============== + +.. automodule:: rush.xtb + :members: + :show-inheritance: + :undoc-members: diff --git a/src/rush/client.py b/src/rush/client.py index 27c67bf..aff5447 100644 --- a/src/rush/client.py +++ b/src/rush/client.py @@ -97,6 +97,30 @@ def _get_project_id() -> str: "nnxtb_rex": "github:talo/tengu-nnxtb/4e733660264d38faab5d23eadc41ca86fd6ff97a#nnxtb_rex", "pbsa_rex": "github:talo/pbsa-cuda/f8b1c357fddfebf7e0c51a84f8d4e70958440c00#pbsa_rex", "prepare_protein_rex": "github:talo/tengu-prepare-protein/911d9fb69c269f8783b7cce2de3e87ee9333fb08#prepare_protein_rex", + "grimme_lab_xtb_single_point_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_single_point_rex", + "grimme_lab_xtb_gradient_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_gradient_rex", + "grimme_lab_xtb_optimize_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_optimize_rex", + "grimme_lab_xtb_hessian_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_hessian_rex", + "grimme_lab_xtb_optimized_hessian_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_optimized_hessian_rex", + "grimme_lab_xtb_biased_hessian_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_biased_hessian_rex", + "grimme_lab_xtb_md_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_md_rex", + "grimme_lab_xtb_metadyn_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_metadyn_rex", + "grimme_lab_xtb_optimized_md_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_optimized_md_rex", + "grimme_lab_xtb_metaopt_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_metaopt_rex", + "grimme_lab_xtb_path_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_path_rex", + "grimme_lab_xtb_mode_following_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_mode_following_rex", + "grimme_lab_xtb_reactor_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_reactor_rex", + "grimme_lab_xtb_dipro_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_dipro_rex", + "grimme_lab_xtb_vip_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_vip_rex", + "grimme_lab_xtb_vea_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_vea_rex", + "grimme_lab_xtb_vipea_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_vipea_rex", + "grimme_lab_xtb_vfukui_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_vfukui_rex", + "grimme_lab_xtb_vomega_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_vomega_rex", + "grimme_lab_xtb_ceh_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_ceh_rex", + "grimme_lab_xtb_esp_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_esp_rex", + "grimme_lab_xtb_stm_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_stm_rex", + "grimme_lab_xtb_raman_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_raman_rex", + "grimme_lab_xtb_oniom_rex": "github:talo/xtb_rex/50ce82ade05cd50def1bc8373e9f9fdace570eaf#grimme_lab_xtb_oniom_rex", } if "staging" in GRAPHQL_ENDPOINT else { diff --git a/src/rush/xtb.py b/src/rush/xtb.py new file mode 100644 index 0000000..1a5222d --- /dev/null +++ b/src/rush/xtb.py @@ -0,0 +1,607 @@ +#!/usr/bin/env python3 +""" +Grimme lab xTB module helpers for the Rush Python client. + +These wrappers accept raw Rex config expressions to avoid guessing module-specific +config structures. Use the module repo's test.rex files as references for config +shapes and defaults. +""" + +import sys +from pathlib import Path + +from gql.transport.exceptions import TransportQueryError + +from .client import ( + RunOpts, + RunSpec, + _get_project_id, + _submit_rex, + collect_run, + upload_object, +) + + +def _run_xtb_module( + module_key: str, + input_json: Path | str, + config_rex: str, + run_spec: RunSpec, + run_opts: RunOpts, + collect: bool, +): + input_vobj = upload_object(input_json) + rex = f"""let + obj_j = \u03bb j \u2192 + VirtualObject {{ path = j, format = ObjectFormat::json, size = 0 }}, + input = obj_j \"{input_vobj['path']}\", + cfg = {config_rex}, + result = {module_key}_s + ({run_spec._to_rex()}) + cfg + input +in + result +""" + try: + run_id = _submit_rex(_get_project_id(), rex, run_opts) + if collect: + return collect_run(run_id) + return run_id + except TransportQueryError as e: + if e.errors: + for error in e.errors: + print(f"Error: {error['message']}", file=sys.stderr) + raise + + +def grimme_lab_xtb_single_point_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_single_point_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_single_point_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_single_point_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_gradient_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_gradient_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_gradient_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_gradient_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_optimize_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_optimize_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_optimize_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_optimize_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_hessian_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_hessian_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_hessian_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_hessian_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_optimized_hessian_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_optimized_hessian_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_optimized_hessian_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_optimized_hessian_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_biased_hessian_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_biased_hessian_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_biased_hessian_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_biased_hessian_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_md_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_md_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_md_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_md_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_metadyn_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_metadyn_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_metadyn_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_metadyn_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_optimized_md_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_optimized_md_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_optimized_md_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_optimized_md_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_metaopt_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_metaopt_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_metaopt_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_metaopt_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_path_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_path_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_path_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_path_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_mode_following_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_mode_following_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_mode_following_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_mode_following_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_reactor_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_reactor_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_reactor_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_reactor_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_dipro_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_dipro_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_dipro_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_dipro_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_vip_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_vip_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_vip_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_vip_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_vea_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_vea_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_vea_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_vea_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_vipea_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_vipea_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_vipea_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_vipea_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_vfukui_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_vfukui_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_vfukui_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_vfukui_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_vomega_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_vomega_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_vomega_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_vomega_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_ceh_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_ceh_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_ceh_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_ceh_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_esp_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_esp_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_esp_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_esp_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_stm_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_stm_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_stm_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_stm_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_raman_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_raman_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_raman_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_raman_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) + + +def grimme_lab_xtb_oniom_rex( + input_json: Path | str, + config_rex: str, + run_spec: RunSpec = RunSpec(target="Bullet3"), + run_opts: RunOpts = RunOpts(), + collect: bool = False, +): + """ + Run the grimme_lab_xtb_oniom_rex module. + + config_rex should be a Rex expression like: + (grimme_lab_xtb_oniom_rex::WrapperConfig { ... }) + """ + return _run_xtb_module( + "grimme_lab_xtb_oniom_rex", + input_json, + config_rex, + run_spec, + run_opts, + collect, + ) diff --git a/tests/fixtures/xtb_rex/objects/input.json b/tests/fixtures/xtb_rex/objects/input.json new file mode 100644 index 0000000..795e19d --- /dev/null +++ b/tests/fixtures/xtb_rex/objects/input.json @@ -0,0 +1,62 @@ +{ + "topology": { + "schema_version": "0.2.0", + "symbols": [ + "O", + "H", + "H" + ], + "geometry": [ + 0.0, + 0.0, + 0.0, + 0.7586, + 0.0, + 0.5043, + -0.7586, + 0.0, + 0.5043 + ], + "labels": null, + "partial_charges": null, + "formal_charges": null, + "connectivity": null, + "stereochemistry": null, + "velocities": null, + "fragments": null, + "fragment_formal_charges": null, + "fragment_partial_charges": null, + "fragment_multiplicities": null + }, + "residues": { + "residues": [ + [ + 0, + 1, + 2 + ] + ], + "seqs": [ + "LIG" + ], + "seq_ns": [ + 1 + ], + "insertion_codes": [ + "" + ], + "labeled": null, + "labels": null + }, + "chains": { + "chains": [ + [ + 0 + ] + ], + "alpha_helices": null, + "beta_sheets": null, + "labeled": null, + "labels": null + } +} diff --git a/tests/test_onboarding_xtb_rex.py b/tests/test_onboarding_xtb_rex.py new file mode 100644 index 0000000..7178290 --- /dev/null +++ b/tests/test_onboarding_xtb_rex.py @@ -0,0 +1,82 @@ +import importlib +import os +from pathlib import Path + +import pytest + +MODULE_KEYS = [ + "grimme_lab_xtb_single_point_rex", + "grimme_lab_xtb_gradient_rex", + "grimme_lab_xtb_optimize_rex", + "grimme_lab_xtb_hessian_rex", + "grimme_lab_xtb_optimized_hessian_rex", + "grimme_lab_xtb_biased_hessian_rex", + "grimme_lab_xtb_md_rex", + "grimme_lab_xtb_metadyn_rex", + "grimme_lab_xtb_optimized_md_rex", + "grimme_lab_xtb_metaopt_rex", + "grimme_lab_xtb_path_rex", + "grimme_lab_xtb_mode_following_rex", + "grimme_lab_xtb_reactor_rex", + "grimme_lab_xtb_dipro_rex", + "grimme_lab_xtb_vip_rex", + "grimme_lab_xtb_vea_rex", + "grimme_lab_xtb_vipea_rex", + "grimme_lab_xtb_vfukui_rex", + "grimme_lab_xtb_vomega_rex", + "grimme_lab_xtb_ceh_rex", + "grimme_lab_xtb_esp_rex", + "grimme_lab_xtb_stm_rex", + "grimme_lab_xtb_raman_rex", + "grimme_lab_xtb_oniom_rex", +] + +FIXTURE_INPUT = ( + Path(__file__).resolve().parent / "fixtures" / "xtb_rex" / "objects" / "input.json" +) + + +def _load_client(endpoint: str): + os.environ["RUSH_ENDPOINT"] = endpoint + import rush.client as client + + return importlib.reload(client) + + +def test_xtb_rex_onboarding(): + endpoint = os.environ.get("RUSH_ENDPOINT", "") + if "staging" not in endpoint: + pytest.skip("RUSH_ENDPOINT must contain 'staging' for xtb_rex onboarding test.") + if not os.environ.get("RUSH_TOKEN") or not os.environ.get("RUSH_PROJECT"): + pytest.skip("RUSH_TOKEN and RUSH_PROJECT are required for xtb_rex onboarding test.") + + client = _load_client(endpoint) + for key in MODULE_KEYS: + assert key in client.MODULE_LOCK + + import rush.xtb as xtb + + xtb = importlib.reload(xtb) + for key in MODULE_KEYS: + assert hasattr(xtb, key) + + config_rex = """(grimme_lab_xtb_single_point_rex::WrapperConfig { + common = (grimme_lab_xtb_single_point_rex::CommonConfig { + method = None, + charge = None, + uhf = None, + spin_polarized = None, + solvation = None + }), + use_scc = None +})""" + + result = xtb.grimme_lab_xtb_single_point_rex( + FIXTURE_INPUT, + config_rex, + run_spec=client.RunSpec(target="Bullet3"), + run_opts=client.RunOpts(), + collect=True, + ) + + assert not isinstance(result, client.RunError)