Skip to content

Commit

Permalink
fix: fixed copasi instances
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexPatrie committed Mar 12, 2024
1 parent aa78a5e commit 5174e49
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 64 deletions.
9 changes: 6 additions & 3 deletions biosimulator_processes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from builder import ProcessTypes
import importlib


# Define a list of processes to attempt to import and register
PROCESSES_TO_REGISTER = [
('cobra', 'cobra_process.CobraProcess'),
('copasi', 'copasi_process.CopasiProcess'),
('smoldyn', 'smoldyn_process.SmoldynProcess'),
# ('smoldyn', 'smoldyn_process.SmoldynProcess'),
('tellurium', 'tellurium_process.TelluriumProcess'),
('parameter_scan', 'parameter_scan.DeterministicTimeCourseParameterScan')
]
Expand All @@ -21,13 +22,15 @@
import_statement = f'biosimulator_processes.processes.{module_name}'

module = __import__(
import_statement, fromlist=[class_name])
import_statement, fromlist=[class_name])

# module = importlib.import_module(import_statement)

# Get the class from the module
bigraph_class = getattr(module, class_name)

# Register the process
CORE.process_registry.register(class_name, bigraph_class)
CORE.process_registry.register(process_name, bigraph_class)
print(f"{class_name} registered successfully.")
except ImportError as e:
print(f"{class_name} not available. Error: {e}")
36 changes: 19 additions & 17 deletions biosimulator_processes/experiments/parameter_scan.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from process_bigraph import Composite, Step, pf
from biosimulator_processes import CORE


class ParameterScan(Step):
Expand All @@ -22,6 +23,7 @@ def update(self, inputs):


def test_param_scan_copasi():
CORE.process_registry.register('biosimulator_processes.experiments.parameter_scan.ParameterScan', ParameterScan)
initial_sim_state = {
'parameter_scan': {
'_type': 'step',
Expand All @@ -34,23 +36,23 @@ def test_param_scan_copasi():
'simulations': {}
}
},
'copasi': {
'_type': 'process',
'address': 'local:copasi',
'config': {
'model_file': 'model_files/Caravagna2010.xml'
},
'inputs': {
'floating_species': ['floating_species_store'],
'model_parameters': ['model_parameters_store'],
'time': ['time_store'],
'reactions': ['reactions_store']
},
'outputs': {
'floating_species': ['floating_species_store'],
'time': ['time_store'],
}
},
# 'copasi': {
# '_type': 'process',
# 'address': 'local:copasi',
# 'config': {
# 'model_file': 'model_files/Caravagna2010.xml'
# },
# 'inputs': {
# 'floating_species': ['floating_species_store'],
# 'model_parameters': ['model_parameters_store'],
# 'time': ['time_store'],
# 'reactions': ['reactions_store']
# },
# 'outputs': {
# 'floating_species': ['floating_species_store'],
# 'time': ['time_store'],
# }
# },
}

# 2. Make the composite:
Expand Down
1 change: 0 additions & 1 deletion biosimulator_processes/processes/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@

Binary file not shown.
Binary file not shown.
45 changes: 6 additions & 39 deletions biosimulator_processes/processes/copasi_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
# )
from process_bigraph import Process, Composite, pf
from biosimulator_processes.utils import fetch_biomodel
from biosimulator_processes import CORE
from biosimulator_processes.data_model import (
TimeCourseModel,
TimeCourseProcessConfig,
Expand Down Expand Up @@ -269,48 +270,14 @@ def update(self, inputs, interval):


def test_process():
initial_sim_state = {
'copasi': {
'_type': 'process',
'address': 'local:copasi',
'config': {
'model_file': 'biosimulator_processes/model_files/Caravagna2010.xml'
},
'inputs': {
'floating_species': ['floating_species_store'],
'model_parameters': ['model_parameters_store'],
'time': ['time_store'],
'reactions': ['reactions_store']
},
'outputs': {
'floating_species': ['floating_species_store'],
'time': ['time_store'],
}
},
'emitter': {
'_type': 'step',
'address': 'local:ram-emitter',
'config': {
'emit': {
'floating_species': 'tree[float]',
'time': 'float',
},
},
'inputs': {
'floating_species': ['floating_species_store'],
'time': ['time_store'],
}

}
}

instance = {
'copasi': {
'_type': 'process',
'address': 'local:copasi',
'config': {
'model': {
'model_source': 'biosimulator_processes/model_files/Caravagna2010.xml'
'model_source': {
'value': 'biosimulator_processes/model_files/Caravagna2010.xml'}
}
},
'inputs': {
Expand Down Expand Up @@ -340,13 +307,13 @@ def test_process():
}
}

workflow = Composite({
workflow = Composite(config={
'state': instance # initial_sim_state
})
}, core=CORE)
workflow.run(10)
results = workflow.gather_results()
print(f'RESULTS: {pf(results)}')
assert ('emitter',) in results.keys(), "This instance was not properly configured with an emitter."
# assert ('emitter',) in results.keys(), "This instance was not properly configured with an emitter."


# if __name__ == "__main__":
Expand Down
50 changes: 47 additions & 3 deletions notebooks/playground.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"id": "initial_id",
"metadata": {
"ExecuteTime": {
"end_time": "2024-03-07T18:34:55.910628Z",
"start_time": "2024-03-07T18:34:54.100047Z"
"end_time": "2024-03-12T17:06:29.697817Z",
"start_time": "2024-03-12T17:06:28.212331Z"
},
"collapsed": true
},
Expand All @@ -18,11 +18,18 @@
"text": [
"CobraProcess registered successfully.\n",
"CopasiProcess registered successfully.\n",
"SmoldynProcess registered successfully.\n",
"TelluriumProcess registered successfully.\n",
"DeterministicTimeCourseParameterScan registered successfully.\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/alex/anaconda3/envs/biosimulator-processess/lib/python3.10/site-packages/pydantic/_internal/_generate_schema.py:386: UserWarning: <built-in function any> is not a Python type (it may be an instance of an object), Pydantic will allow any object with no validation since we cannot even enforce that the input is an instance of the given type. To get rid of this error wrap the type with `pydantic.SkipValidation`.\n",
" warn(\n"
]
},
{
"data": {
"text/plain": [
Expand All @@ -49,6 +56,43 @@
"os.path.exists(model_filepath)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "afcf96ec0dcb6024",
"metadata": {
"ExecuteTime": {
"end_time": "2024-03-12T17:06:29.984106Z",
"start_time": "2024-03-12T17:06:29.698933Z"
},
"collapsed": false
},
"outputs": [
{
"ename": "Exception",
"evalue": "process \"CopasiProcess\" not found",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mException\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[2], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mbiosimulator_processes\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mprocesses\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mcopasi_process\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m test_process\n\u001b[0;32m----> 3\u001b[0m \u001b[43mtest_process\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[0;32m~/Desktop/uchc_work/repos/biosimulator-processes/notebooks/../biosimulator_processes/processes/copasi_process.py:343\u001b[0m, in \u001b[0;36mtest_process\u001b[0;34m()\u001b[0m\n\u001b[1;32m 272\u001b[0m initial_sim_state \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 273\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mCopasiProcess\u001b[39m\u001b[38;5;124m'\u001b[39m: {\n\u001b[1;32m 274\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m_type\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mprocess\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 304\u001b[0m }\n\u001b[1;32m 305\u001b[0m }\n\u001b[1;32m 307\u001b[0m instance \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 308\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcopasi\u001b[39m\u001b[38;5;124m'\u001b[39m: {\n\u001b[1;32m 309\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m_type\u001b[39m\u001b[38;5;124m'\u001b[39m: \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mprocess\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 340\u001b[0m }\n\u001b[1;32m 341\u001b[0m }\n\u001b[0;32m--> 343\u001b[0m workflow \u001b[38;5;241m=\u001b[39m \u001b[43mComposite\u001b[49m\u001b[43m(\u001b[49m\u001b[43m{\u001b[49m\n\u001b[1;32m 344\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mstate\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43minstance\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# initial_sim_state\u001b[39;49;00m\n\u001b[1;32m 345\u001b[0m \u001b[43m\u001b[49m\u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 346\u001b[0m workflow\u001b[38;5;241m.\u001b[39mrun(\u001b[38;5;241m10\u001b[39m)\n\u001b[1;32m 347\u001b[0m results \u001b[38;5;241m=\u001b[39m workflow\u001b[38;5;241m.\u001b[39mgather_results()\n",
"File \u001b[0;32m~/anaconda3/envs/biosimulator-processess/lib/python3.10/site-packages/process_bigraph/composite.py:744\u001b[0m, in \u001b[0;36mComposite.__init__\u001b[0;34m(self, config, core)\u001b[0m\n\u001b[1;32m 741\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mglobal_time\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m initial_state:\n\u001b[1;32m 742\u001b[0m initial_state[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mglobal_time\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0.0\u001b[39m\n\u001b[0;32m--> 744\u001b[0m composition, state \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcore\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcomplete\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 745\u001b[0m \u001b[43m \u001b[49m\u001b[43minitial_composition\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 746\u001b[0m \u001b[43m \u001b[49m\u001b[43minitial_state\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 748\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcomposition \u001b[38;5;241m=\u001b[39m copy\u001b[38;5;241m.\u001b[39mdeepcopy(\n\u001b[1;32m 749\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcore\u001b[38;5;241m.\u001b[39maccess(composition))\n\u001b[1;32m 751\u001b[0m \u001b[38;5;66;03m# TODO: add flag to self.core.access(copy=True)\u001b[39;00m\n",
"File \u001b[0;32m~/anaconda3/envs/biosimulator-processess/lib/python3.10/site-packages/bigraph_schema/type_system.py:1334\u001b[0m, in \u001b[0;36mTypeSystem.complete\u001b[0;34m(self, initial_schema, initial_state)\u001b[0m\n\u001b[1;32m 1328\u001b[0m state \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhydrate(\n\u001b[1;32m 1329\u001b[0m full_schema,\n\u001b[1;32m 1330\u001b[0m initial_state)\n\u001b[1;32m 1332\u001b[0m \u001b[38;5;66;03m# fill in the parts of the composition schema\u001b[39;00m\n\u001b[1;32m 1333\u001b[0m \u001b[38;5;66;03m# determined by the state\u001b[39;00m\n\u001b[0;32m-> 1334\u001b[0m schema, state \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minfer_schema\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 1335\u001b[0m \u001b[43m \u001b[49m\u001b[43mfull_schema\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1336\u001b[0m \u001b[43m \u001b[49m\u001b[43mstate\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1338\u001b[0m final_state \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfill(schema, state)\n\u001b[1;32m 1340\u001b[0m \u001b[38;5;66;03m# TODO: add flag to types.access(copy=True)\u001b[39;00m\n",
"File \u001b[0;32m~/anaconda3/envs/biosimulator-processess/lib/python3.10/site-packages/process_bigraph/composite.py:270\u001b[0m, in \u001b[0;36mProcessTypes.infer_schema\u001b[0;34m(self, schema, state, top_state, path)\u001b[0m\n\u001b[1;32m 267\u001b[0m inner_path \u001b[38;5;241m=\u001b[39m path \u001b[38;5;241m+\u001b[39m (key,)\n\u001b[1;32m 268\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m get_path(schema, inner_path) \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mor\u001b[39;00m get_path(state, inner_path) \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mor\u001b[39;00m (\n\u001b[1;32m 269\u001b[0m \u001b[38;5;28misinstance\u001b[39m(value, \u001b[38;5;28mdict\u001b[39m) \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m_type\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;129;01min\u001b[39;00m value):\n\u001b[0;32m--> 270\u001b[0m schema, top_state \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minfer_schema\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 271\u001b[0m \u001b[43m \u001b[49m\u001b[43mschema\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 272\u001b[0m \u001b[43m \u001b[49m\u001b[43mvalue\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 273\u001b[0m \u001b[43m \u001b[49m\u001b[43mtop_state\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtop_state\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 274\u001b[0m \u001b[43m \u001b[49m\u001b[43mpath\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43minner_path\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 276\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(state, \u001b[38;5;28mstr\u001b[39m):\n\u001b[1;32m 277\u001b[0m \u001b[38;5;28;01mpass\u001b[39;00m\n",
"File \u001b[0;32m~/anaconda3/envs/biosimulator-processess/lib/python3.10/site-packages/process_bigraph/composite.py:222\u001b[0m, in \u001b[0;36mProcessTypes.infer_schema\u001b[0;34m(self, schema, state, top_state, path)\u001b[0m\n\u001b[1;32m 219\u001b[0m state_type \u001b[38;5;241m=\u001b[39m state[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m_type\u001b[39m\u001b[38;5;124m'\u001b[39m]\n\u001b[1;32m 220\u001b[0m state_schema \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39maccess(state_type)\n\u001b[0;32m--> 222\u001b[0m hydrated_state \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdeserialize\u001b[49m\u001b[43m(\u001b[49m\u001b[43mstate_schema\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstate\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 223\u001b[0m top_state \u001b[38;5;241m=\u001b[39m set_path(\n\u001b[1;32m 224\u001b[0m top_state,\n\u001b[1;32m 225\u001b[0m path,\n\u001b[1;32m 226\u001b[0m hydrated_state)\n\u001b[1;32m 228\u001b[0m schema \u001b[38;5;241m=\u001b[39m set_path(\n\u001b[1;32m 229\u001b[0m schema,\n\u001b[1;32m 230\u001b[0m path,\n\u001b[1;32m 231\u001b[0m {\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m_type\u001b[39m\u001b[38;5;124m'\u001b[39m: state_type})\n",
"File \u001b[0;32m~/anaconda3/envs/biosimulator-processess/lib/python3.10/site-packages/bigraph_schema/type_system.py:675\u001b[0m, in \u001b[0;36mTypeSystem.deserialize\u001b[0;34m(self, schema, encoded)\u001b[0m\n\u001b[1;32m 672\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m encoded \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 673\u001b[0m encoded \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdefault(schema)\n\u001b[0;32m--> 675\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mdeserialize_function\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 676\u001b[0m \u001b[43m \u001b[49m\u001b[43mfound\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 677\u001b[0m \u001b[43m \u001b[49m\u001b[43mencoded\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 678\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 680\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(encoded, \u001b[38;5;28mdict\u001b[39m):\n\u001b[1;32m 681\u001b[0m result \u001b[38;5;241m=\u001b[39m {}\n",
"File \u001b[0;32m~/anaconda3/envs/biosimulator-processess/lib/python3.10/site-packages/process_bigraph/composite.py:84\u001b[0m, in \u001b[0;36mdeserialize_process\u001b[0;34m(schema, encoded, core)\u001b[0m\n\u001b[1;32m 82\u001b[0m instantiate \u001b[38;5;241m=\u001b[39m process_lookup(core, address)\n\u001b[1;32m 83\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m instantiate:\n\u001b[0;32m---> 84\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mprocess \u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00maddress\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m not found\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 86\u001b[0m config \u001b[38;5;241m=\u001b[39m core\u001b[38;5;241m.\u001b[39mhydrate_state(\n\u001b[1;32m 87\u001b[0m instantiate\u001b[38;5;241m.\u001b[39mconfig_schema,\n\u001b[1;32m 88\u001b[0m encoded\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mconfig\u001b[39m\u001b[38;5;124m'\u001b[39m, {}))\n\u001b[1;32m 90\u001b[0m interval \u001b[38;5;241m=\u001b[39m core\u001b[38;5;241m.\u001b[39mdeserialize(\n\u001b[1;32m 91\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124minterval\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 92\u001b[0m encoded\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124minterval\u001b[39m\u001b[38;5;124m'\u001b[39m))\n",
"\u001b[0;31mException\u001b[0m: process \"CopasiProcess\" not found"
]
}
],
"source": [
"from biosimulator_processes.processes.copasi_process import test_process\n",
"\n",
"test_process()"
]
},
{
"cell_type": "code",
"execution_count": 6,
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ flake8 = "*"
twine = "*"

[tool.pytest.ini_options]
testpaths = ["biosimulator_processes"]
# testpaths = ["biosimulator_processes"]
addopts = "--ignore=setup.py"
python_files = "*.py"
# python_functions = test_*
Expand Down

0 comments on commit 5174e49

Please sign in to comment.