Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
SimStadt
simstadtpy
Commits
ace2fe1b
Commit
ace2fe1b
authored
Mar 13, 2026
by
Eric Duminil
Browse files
Create proj folder if needed
parent
36d8921a
Changes
1
Show whitespace changes
Inline
Side-by-side
src/simstadt/runner.py
View file @
ace2fe1b
...
...
@@ -36,6 +36,7 @@ log = logging.getLogger(__name__)
# SimStadt discovery
# ---------------------------------------------------------------------------
def
find_simstadt
(
parent_folder
:
Path
,
simstadt_glob
:
str
=
SIMSTADT2_GLOB
)
->
Path
:
try
:
found
=
next
(
parent_folder
.
glob
(
simstadt_glob
))
...
...
@@ -71,12 +72,17 @@ def get_template_path() -> Path:
# Low-level workflow helpers
# ---------------------------------------------------------------------------
def
_simstadt_script
()
->
str
:
return
"SimStadt.bat"
if
platform
.
system
().
lower
()
==
"windows"
else
"./SimStadt.sh"
def
_regionchooser_script
()
->
str
:
return
"RegionChooser.bat"
if
platform
.
system
().
lower
()
==
"windows"
else
"./RegionChooser.sh"
return
(
"RegionChooser.bat"
if
platform
.
system
().
lower
()
==
"windows"
else
"./RegionChooser.sh"
)
def
check_paths
(
repo_path
:
Path
,
workflow_path
:
Path
)
->
None
:
...
...
@@ -104,7 +110,9 @@ def prepare_workflow(workflow_path: Path, citygmls: list[str]) -> str:
for
child
in
list
(
citygml_node
):
citygml_node
.
remove
(
child
)
else
:
workflow_node
=
root
.
find
(
".//object[@class='eu.simstadt.workflows.CityGmlWorkflow']"
)
workflow_node
=
root
.
find
(
".//object[@class='eu.simstadt.workflows.CityGmlWorkflow']"
)
if
workflow_node
is
None
:
raise
ValueError
(
"Broken workflow!"
)
citygml_node
=
et
.
SubElement
(
workflow_node
,
"void"
)
...
...
@@ -155,7 +163,11 @@ def copy_workflow_from_template(
def
_get_all_files
(
folder
:
Path
)
->
dict
[
Path
,
float
]:
return
{
f
:
f
.
stat
().
st_mtime
for
f
in
folder
.
glob
(
"**/*"
)
if
f
.
is_file
()
and
f
.
name
!=
PARAMS
}
return
{
f
:
f
.
stat
().
st_mtime
for
f
in
folder
.
glob
(
"**/*"
)
if
f
.
is_file
()
and
f
.
name
!=
PARAMS
}
def
_compare_written_files
(
repo_path
:
Path
,
before
:
dict
,
after
:
dict
)
->
list
[
Path
]:
...
...
@@ -173,13 +185,16 @@ def _compare_written_files(repo_path: Path, before: dict, after: dict) -> list[P
# Public execution API
# ---------------------------------------------------------------------------
def
get_simstadt_output
(
path
:
Path
)
->
str
:
"""Run SimStadt with the given path and return stdout regardless of exit code.
Useful for extracting version information from the startup banner.
"""
with
chdir
(
get_simstadt_folder
()):
result
=
subprocess
.
run
([
_simstadt_script
(),
str
(
path
)],
text
=
True
,
capture_output
=
True
,
check
=
False
)
result
=
subprocess
.
run
(
[
_simstadt_script
(),
str
(
path
)],
text
=
True
,
capture_output
=
True
,
check
=
False
)
return
result
.
stdout
...
...
@@ -188,7 +203,10 @@ def run_simstadt(workflow_path: Path, name: str) -> str:
with
chdir
(
get_simstadt_folder
()):
log
.
info
(
"Launching %s:"
,
name
)
result
=
subprocess
.
run
(
[
_simstadt_script
(),
str
(
workflow_path
)],
text
=
True
,
capture_output
=
True
,
check
=
False
[
_simstadt_script
(),
str
(
workflow_path
)],
text
=
True
,
capture_output
=
True
,
check
=
False
,
)
if
result
.
returncode
!=
0
:
log
.
warning
(
" Workflow failed!
\n
%s"
,
result
.
stdout
)
...
...
@@ -197,13 +215,18 @@ def run_simstadt(workflow_path: Path, name: str) -> str:
log
.
info
(
" Workflow finished successfully!
\n
"
)
return
result
.
stdout
#TODO: Add get_hull
# TODO: Add get_hull
def
run_regionchooser
(
*
params
:
str
)
->
str
:
"""Invoke the SimStadt RegionChooser CLI. Returns stdout."""
with
chdir
(
get_simstadt_folder
()):
result
=
subprocess
.
run
(
[
_regionchooser_script
(),
*
params
],
text
=
True
,
capture_output
=
True
,
check
=
True
[
_regionchooser_script
(),
*
params
],
text
=
True
,
capture_output
=
True
,
check
=
True
,
)
log
.
debug
(
result
.
stdout
)
return
result
.
stdout
...
...
@@ -236,6 +259,7 @@ def _resolve_project(citygml_path: Path, project_path: Path | None) -> tuple[Pat
return
citygml_path
.
parent
,
citygml_path
.
name
if
project_path
is
not
None
:
project_path
.
mkdir
(
exist_ok
=
True
,
parents
=
True
)
dest
=
project_path
/
citygml_path
.
name
if
not
dest
.
exists
():
shutil
.
copy
(
citygml_path
,
dest
)
...
...
@@ -283,8 +307,12 @@ def run_workflow_with_citygml(
if
destination
is
None
:
destination
=
random_id
()
+
"_"
+
template_name
.
rsplit
(
"_"
,
1
)[
-
1
]
resolved_project_path
,
citygml_filename
=
_resolve_project
(
citygml_path
,
project_path
)
workflow_path
=
copy_workflow_from_template
(
template_path
,
resolved_project_path
,
destination
,
replaces
)
resolved_project_path
,
citygml_filename
=
_resolve_project
(
citygml_path
,
project_path
)
workflow_path
=
copy_workflow_from_template
(
template_path
,
resolved_project_path
,
destination
,
replaces
)
output_files
=
run_workflow
(
workflow_path
,
[
citygml_filename
])
if
description
is
None
:
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment