Skip to content

Commit 14f7104

Browse files
committed
automated detection of updates to example files
1 parent 6ce1e0a commit 14f7104

File tree

4 files changed

+58
-55
lines changed

4 files changed

+58
-55
lines changed

docs/conf.py

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -296,20 +296,33 @@
296296

297297

298298

299+
def write_example_md_file(agent_filename, model_filename, readme_filename, app_filename, md_filepath, template):
300+
with open(agent_filename) as content_file:
301+
agent_file = content_file.read()
302+
with open(model_filename) as content_file:
303+
model_file = content_file.read()
304+
with open(readme_filename) as content_file:
305+
readme_file = content_file.read()
306+
with open(app_filename) as content_file:
307+
app_file = content_file.read()
308+
309+
with open(md_filepath, "w") as fh:
310+
content = template.substitute(
311+
dict(agent_file=agent_file, model_file=model_file,
312+
readme_file=readme_file, app_file=app_file)
313+
)
314+
fh.write(content)
315+
299316
def setup_examples_pages():
300-
# create rst files for all examples
317+
# create md files for all examples
301318
# check what examples exist
302319
examples_folder = osp.abspath(osp.join(HERE, "..", "examples"))
303-
304-
# fixme shift to walkdir
305-
# we should have a single rst page for each subdirectory
306-
307320
basic_examples = [f.path for f in os.scandir(osp.join(examples_folder, "basic")) if f.is_dir() ]
308321
advanced_examples = []
309322
# advanced_examples = [f.path for f in os.scandir(osp.join(examples_folder, "advanced")) if f.is_dir()]
310323
examples = basic_examples + advanced_examples
311324

312-
# get all existing rst files
325+
# get all existing md files
313326
md_files = glob.glob(os.path.join(HERE, "examples", "*.md"))
314327
md_files = {os.path.basename(os.path.normpath(entry)) for entry in md_files}
315328

@@ -327,33 +340,23 @@ def setup_examples_pages():
327340
app_filename = os.path.join(example, "app.py")
328341

329342
md_filename = f"{base_name}.md"
330-
examples_md.append((base_name, f"./examples/{base_name}"))
331-
332-
# fixme should be replaced with something based on timestep
333-
# so if any(mymodelfiles) is newer then existing_md_filename
334-
if md_filename not in md_files:
335-
with open(agent_filename) as content_file:
336-
agent_file = content_file.read()
337-
with open(model_filename) as content_file:
338-
model_file = content_file.read()
339-
with open(readme_filename) as content_file:
340-
readme_file = content_file.read()
341-
with open(app_filename) as content_file:
342-
app_file = content_file.read()
343-
344-
with open(os.path.join(HERE, "examples", md_filename), "w") as fh:
345-
content = template.substitute(
346-
dict(agent_file=agent_file, model_file=model_file,
347-
readme_file=readme_file, app_file=app_file)
348-
)
349-
fh.write(content)
350-
else:
351-
md_files.remove(md_filename)
352-
353-
# these md files are outdated because the example has been removed
354-
for entry in md_files:
355-
fn = os.path.join(HERE, "examples", entry)
356-
os.remove(fn)
343+
examples_md.append(base_name)
344+
345+
# let's establish the latest update to the example files
346+
timestamps = [osp.getmtime(fh) for fh in [agent_filename, model_filename, readme_filename, app_filename]]
347+
latest_edit = max(timestamps)
348+
349+
md_filepath = os.path.join(HERE, "examples", md_filename)
350+
351+
# if the example is new or the existing example md file is older than the latest update, create a new file
352+
if md_filename not in md_files or latest_edit > osp.getmtime(md_filepath):
353+
write_example_md_file(agent_filename, model_filename, readme_filename, app_filename, md_filepath, template)
354+
355+
356+
# check if any md files should be removed because the example is removed
357+
outdated_md_files = md_files - {f"{entry}.md" for entry in examples_md}
358+
for entry in outdated_md_files:
359+
os.remove(os.path.join(HERE, "examples", entry) )
357360

358361
# create overview of examples.md
359362
with open(os.path.join(HERE, "examples_overview_template.txt")) as fh:
@@ -362,7 +365,7 @@ def setup_examples_pages():
362365
with open(os.path.join(HERE, "examples.md"), "w") as fh:
363366
content = template.substitute(
364367
dict(
365-
examples="\n".join([f"{' '.join(base_name.split('_'))} <{file_path[2::]}>" for base_name, file_path in examples_md]),
368+
examples="\n".join([f"{' '.join(base_name.split('_'))} </examples/<base_name>>" for base_name in examples_md]),
366369
)
367370
)
368371
fh.write(content)

docs/examples.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
```{toctree}
66
:maxdepth: 1
77
8-
boid flockers <examples/boid_flockers>
9-
virus on network <examples/virus_on_network>
10-
conways game of life <examples/conways_game_of_life>
11-
schelling <examples/schelling>
12-
boltzmann wealth model <examples/boltzmann_wealth_model>
8+
boid flockers </examples/<base_name>>
9+
virus on network </examples/<base_name>>
10+
conways game of life </examples/<base_name>>
11+
schelling </examples/<base_name>>
12+
boltzmann wealth model </examples/<base_name>>
1313
1414
```

docs/examples/conways_game_of_life.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ class Cell(Agent):
5353
super().__init__(model)
5454
self.x, self.y = pos
5555
self.state = init_state
56-
self._nextState = None
56+
self._next_state = None
5757

5858
@property
59-
def isAlive(self):
59+
def is_alive(self):
6060
return self.state == self.ALIVE
6161

6262
@property
@@ -72,20 +72,20 @@ class Cell(Agent):
7272
"""
7373
# Get the neighbors and apply the rules on whether to be alive or dead
7474
# at the next tick.
75-
live_neighbors = sum(neighbor.isAlive for neighbor in self.neighbors)
75+
live_neighbors = sum(neighbor.is_alive for neighbor in self.neighbors)
7676

7777
# Assume nextState is unchanged, unless changed below.
78-
self._nextState = self.state
79-
if self.isAlive:
78+
self._next_state = self.state
79+
if self.is_alive:
8080
if live_neighbors < 2 or live_neighbors > 3:
81-
self._nextState = self.DEAD
81+
self._next_state = self.DEAD
8282
else:
8383
if live_neighbors == 3:
84-
self._nextState = self.ALIVE
84+
self._next_state = self.ALIVE
8585

8686
def assume_state(self):
8787
"""Set the state to the new computed state -- computed in step()."""
88-
self.state = self._nextState
88+
self.state = self._next_state
8989

9090
```
9191

examples/basic/conways_game_of_life/agents.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ def __init__(self, pos, model, init_state=DEAD):
1212
super().__init__(model)
1313
self.x, self.y = pos
1414
self.state = init_state
15-
self._nextState = None
15+
self._next_state = None
1616

1717
@property
18-
def isAlive(self):
18+
def is_alive(self):
1919
return self.state == self.ALIVE
2020

2121
@property
@@ -31,17 +31,17 @@ def determine_state(self):
3131
"""
3232
# Get the neighbors and apply the rules on whether to be alive or dead
3333
# at the next tick.
34-
live_neighbors = sum(neighbor.isAlive for neighbor in self.neighbors)
34+
live_neighbors = sum(neighbor.is_alive for neighbor in self.neighbors)
3535

3636
# Assume nextState is unchanged, unless changed below.
37-
self._nextState = self.state
38-
if self.isAlive:
37+
self._next_state = self.state
38+
if self.is_alive:
3939
if live_neighbors < 2 or live_neighbors > 3:
40-
self._nextState = self.DEAD
40+
self._next_state = self.DEAD
4141
else:
4242
if live_neighbors == 3:
43-
self._nextState = self.ALIVE
43+
self._next_state = self.ALIVE
4444

4545
def assume_state(self):
4646
"""Set the state to the new computed state -- computed in step()."""
47-
self.state = self._nextState
47+
self.state = self._next_state

0 commit comments

Comments
 (0)