diff --git a/.gitignore b/.gitignore
index 723ef36..f28bd65 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,199 @@
-.idea
\ No newline at end of file
+# ApprovalTests
+tests/*.approved.*
+
+
+# Copied from https://github.com/github/gitignore/blob/main/Python.gitignore
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+# in version control.
+# https://pdm.fming.dev/#use-with-ide
+.pdm.toml
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+# and can be added to the global gitignore or merged into this file. For a more nuclear
+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
+#.idea/
+
+# 2023-12-04. MRW commented out at suggestion of Python.gitignore
+# .idea
+
+
+
+# 2023-12-04 - Copied from https://github.com/github/gitignore/blob/main/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ea2923c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/mob-programming-rpg_gregorriegler.iml b/.idea/mob-programming-rpg_gregorriegler.iml
new file mode 100644
index 0000000..3d7e4be
--- /dev/null
+++ b/.idea/mob-programming-rpg_gregorriegler.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..2787959
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.rustup/settings.toml b/.rustup/settings.toml
new file mode 100644
index 0000000..1551bc9
--- /dev/null
+++ b/.rustup/settings.toml
@@ -0,0 +1,4 @@
+profile = "default"
+version = "12"
+
+[overrides]
diff --git a/session-notes/cleanup-notes/.idea/.gitignore b/session-notes/cleanup-notes/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/session-notes/cleanup-notes/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/session-notes/cleanup-notes/.idea/cleanup-notes.iml b/session-notes/cleanup-notes/.idea/cleanup-notes.iml
new file mode 100644
index 0000000..74d515a
--- /dev/null
+++ b/session-notes/cleanup-notes/.idea/cleanup-notes.iml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/session-notes/cleanup-notes/.idea/inspectionProfiles/profiles_settings.xml b/session-notes/cleanup-notes/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/session-notes/cleanup-notes/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/session-notes/cleanup-notes/.idea/misc.xml b/session-notes/cleanup-notes/.idea/misc.xml
new file mode 100644
index 0000000..cd3a88e
--- /dev/null
+++ b/session-notes/cleanup-notes/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/session-notes/cleanup-notes/.idea/modules.xml b/session-notes/cleanup-notes/.idea/modules.xml
new file mode 100644
index 0000000..3855ef9
--- /dev/null
+++ b/session-notes/cleanup-notes/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/session-notes/cleanup-notes/.idea/vcs.xml b/session-notes/cleanup-notes/.idea/vcs.xml
new file mode 100644
index 0000000..b2bdec2
--- /dev/null
+++ b/session-notes/cleanup-notes/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/session-notes/cleanup-notes/cleanup_session_notes.py b/session-notes/cleanup-notes/cleanup_session_notes.py
deleted file mode 100644
index 47f40a6..0000000
--- a/session-notes/cleanup-notes/cleanup_session_notes.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# Python code for the specified tasks
-
-import re
-import os
-import shutil
-import sys
-
-def get_date_from_filename(filename):
- match = re.search(r'(\d{4}-\d{2}-\d{2})', filename, re.IGNORECASE)
- return match.group(1) if match else None
-
-def slurp_file(filename):
- try:
- with open(filename, 'r') as file:
- return file.read()
- except FileNotFoundError:
- return None
-
-def contains_inactive_coauthors(contents):
- return bool(re.search(r'^#+\s*Inactive Co-Authors', contents, re.IGNORECASE | re.MULTILINE))
-
-def contains_active_coauthors(contents):
- return bool(re.search(r'^#+\s*Active Co-Authors', contents, re.IGNORECASE | re.MULTILINE))
-
-def contains_session_date(contents):
- return bool(re.search(r'^#+\s*Session Date', contents, re.IGNORECASE | re.MULTILINE))
-
-def delete_inactive_coauthors(contents):
- return re.sub(r'^#+\s*Inactive Co-Authors.*?(?=^#|\Z)', '', contents, flags=re.IGNORECASE | re.MULTILINE | re.DOTALL)
-
-def normalize_coauthor_heading(contents):
- return re.sub(r'^#+\s*.*Co-Author.*', '## Co-Authors', contents, flags=re.IGNORECASE | re.MULTILINE)
-
-def cleanup_file(filename):
- original_contents = slurp_file(filename)
- if original_contents is None:
- print(f"File not found: {filename}")
- return
-
- contents = original_contents
- date_as_string = get_date_from_filename(filename)
-
- if not contains_session_date(contents):
- contents = f"# Session Date: {date_as_string}\n" + contents
-
- if contains_active_coauthors(contents) and contains_inactive_coauthors(contents):
- contents = delete_inactive_coauthors(contents)
-
- contents = normalize_coauthor_heading(contents)
-
- if contents == original_contents:
- print(f"No changes were needed for the file: {filename}")
- else:
- print(f"Changes were made to the file: {filename}")
- new_filename = filename + ".new"
- with open(new_filename, 'w') as new_file:
- new_file.write(contents)
- shutil.copystat(filename, new_filename)
- original_backup_filename = filename + ".original"
- os.rename(filename, original_backup_filename)
- os.rename(new_filename, filename)
- print(f"You can view changes by issuing this command: diff -u {original_backup_filename} {filename}")
-
-def main():
- for filename in sys.argv[1:]:
- cleanup_file(filename)
-
-if __name__ == "__main__":
- main()
diff --git a/session-notes/session-notes-2023-02-02.md b/session-notes/session-notes-2023-02-02.md
index 840f677..1c43b37 100644
--- a/session-notes/session-notes-2023-02-02.md
+++ b/session-notes/session-notes-2023-02-02.md
@@ -1,4 +1,5 @@
# Session Date: 2023-02-02
+## Co-Authors
Co-Authored-By: Nitsan Avni
Co-Authored-By: Eddie Bush
Co-Authored-By: Michael R. Wolf
diff --git a/session-notes/session-notes-2023-02-09.md b/session-notes/session-notes-2023-02-09.md
index 2b51920..831a825 100644
--- a/session-notes/session-notes-2023-02-09.md
+++ b/session-notes/session-notes-2023-02-09.md
@@ -1,4 +1,5 @@
# Session Date: 2023-02-09
+## Co-Authors
Co-Authored-By: Nitsan Avni
Co-Authored-By: Eddie Bush
Co-Authored-By: Rea
diff --git a/session-notes/session-notes-2023-02-16.md b/session-notes/session-notes-2023-02-16.md
index 9309b55..c65be34 100644
--- a/session-notes/session-notes-2023-02-16.md
+++ b/session-notes/session-notes-2023-02-16.md
@@ -1,4 +1,5 @@
# Session Date: 2023-02-16
+## Co-Authors
Co-Authored-By: Nitsan Avni
Co-Authored-By: Michael R. Wolf
diff --git a/session-notes/session-notes-2023-02-23.md b/session-notes/session-notes-2023-02-23.md
index d05de48..b84c3f2 100644
--- a/session-notes/session-notes-2023-02-23.md
+++ b/session-notes/session-notes-2023-02-23.md
@@ -1,4 +1,5 @@
# Session Date: 2023-02-23
+## Co-Authors
Co-Authored-By: Rea
Co-Authored-By: Tsvetan Tsvetanov
Co-Authored-By: Michael R. Wolf
diff --git a/session-notes/session-notes-2023-03-02.md b/session-notes/session-notes-2023-03-02.md
index eb3f699..fd0215a 100644
--- a/session-notes/session-notes-2023-03-02.md
+++ b/session-notes/session-notes-2023-03-02.md
@@ -1,4 +1,5 @@
# Session Date: 2023-03-02
+## Co-Authors
Co-Authored-By: arrockt
Co-Authored-By: Austin Chadwick
Co-Authored-By: Blessed538
diff --git a/session-notes/session-notes-2023-03-09.md b/session-notes/session-notes-2023-03-09.md
index 7e8bd96..1581570 100644
--- a/session-notes/session-notes-2023-03-09.md
+++ b/session-notes/session-notes-2023-03-09.md
@@ -1,4 +1,5 @@
# Session Date: 2023-03-09
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Michael R. Wolf
diff --git a/session-notes/session-notes-2023-03-16.md b/session-notes/session-notes-2023-03-16.md
index 4eb2169..aa9a26d 100644
--- a/session-notes/session-notes-2023-03-16.md
+++ b/session-notes/session-notes-2023-03-16.md
@@ -1,4 +1,5 @@
# Session Date: 2023-03-16
+## Co-Authors
Co-Authored-By: Eddie Bush
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Nitsan Avni
diff --git a/session-notes/session-notes-2023-03-16.session2.md b/session-notes/session-notes-2023-03-16.session2.md
index 5718844..47c0202 100644
--- a/session-notes/session-notes-2023-03-16.session2.md
+++ b/session-notes/session-notes-2023-03-16.session2.md
@@ -1,4 +1,5 @@
# Session Date: 2023-03-16
+## Co-Authors
Co-Authored-By: Michael R. Wolf
# Agenda
diff --git a/session-notes/session-notes-2023-03-23.md b/session-notes/session-notes-2023-03-23.md
index e247f3f..35671a6 100644
--- a/session-notes/session-notes-2023-03-23.md
+++ b/session-notes/session-notes-2023-03-23.md
@@ -1,4 +1,5 @@
# Session Date: 2023-03-23
+## Co-Authors
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Michael R. Wolf
Co-Authored-By: Nitsan Avni
diff --git a/session-notes/session-notes-2023-03-30.md b/session-notes/session-notes-2023-03-30.md
index c74fd3c..7eeed6d 100644
--- a/session-notes/session-notes-2023-03-30.md
+++ b/session-notes/session-notes-2023-03-30.md
@@ -1,5 +1,6 @@
# Session Date: 2023-03-30
Session 1:
+## Co-Authors
Co-Authored-By: Eddie Bush
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Michael R. Wolf
diff --git a/session-notes/session-notes-2023-04-06.md b/session-notes/session-notes-2023-04-06.md
index cacac98..c31ca32 100644
--- a/session-notes/session-notes-2023-04-06.md
+++ b/session-notes/session-notes-2023-04-06.md
@@ -1,23 +1,11 @@
# Session Date: 2023-04-06
## Active
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Nitsan Avni
-## Inactive
-
-Co-Authored-By: Eddie Bush
-Co-Authored-By: arrockt
-Co-Authored-By: Austin Chadwick
-Co-Authored-By: Blessed538
-Co-Authored-By: Gabriel Mbaiorga
-Co-Authored-By: Idan Melamed
-Co-Authored-By: Michael R. Wolf
-Co-Authored-By: Rea
-Co-Authored-By: Tsvetan Tsvetanov
-Co-Authored-By: Willem Larsen
-
# Agenda
## Bond (~~15~~60 min.)
diff --git a/session-notes/session-notes-2023-04-13.md b/session-notes/session-notes-2023-04-13.md
index ebccccf..08a89de 100644
--- a/session-notes/session-notes-2023-04-13.md
+++ b/session-notes/session-notes-2023-04-13.md
@@ -1,19 +1,10 @@
# Session Date: 2023-04-13
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Nitsan Avni
Co-Authored-By: Michael R. Wolf
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
-Co-Authored-By: arrockt
-Co-Authored-By: Austin Chadwick
-Co-Authored-By: Blessed538
-Co-Authored-By: Eddie Bush
-Co-Authored-By: Gabriel Mbaiorga
-Co-Authored-By: Idan Melamed
-Co-Authored-By: Rea
-Co-Authored-By: Tsvetan Tsvetanov
-Co-Authored-By: Willem Larsen
-
# Agenda
## Bond (15 min.)
diff --git a/session-notes/session-notes-2023-04-27.md b/session-notes/session-notes-2023-04-27.md
index 368b9d8..95d6520 100644
--- a/session-notes/session-notes-2023-04-27.md
+++ b/session-notes/session-notes-2023-04-27.md
@@ -1,12 +1,11 @@
# Session Date: 2023-04-27
-## Co-Authors
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Nitsan Avni
Co-Authored-By: Michael R. Wolf
-## Co-Authors
# Agenda
diff --git a/session-notes/session-notes-2023-05-04.md b/session-notes/session-notes-2023-05-04.md
index 48abb3d..6c7075f 100644
--- a/session-notes/session-notes-2023-05-04.md
+++ b/session-notes/session-notes-2023-05-04.md
@@ -1,8 +1,7 @@
# Session Date: 2023-05-04
-## Co-Authors
-## Co-Authors
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Eddie Bush
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
diff --git a/session-notes/session-notes-2023-05-11.md b/session-notes/session-notes-2023-05-11.md
index 3edfa94..6cc68e1 100644
--- a/session-notes/session-notes-2023-05-11.md
+++ b/session-notes/session-notes-2023-05-11.md
@@ -1,8 +1,7 @@
# Session Date: 2023-05-11
-## Co-Authors
-## Co-Authors
+## Co-Authors
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Michael R. Wolf
Co-Authored-By: Nitsan Avni
diff --git a/session-notes/session-notes-2023-05-18.md b/session-notes/session-notes-2023-05-18.md
index d25e6c8..a7400d1 100644
--- a/session-notes/session-notes-2023-05-18.md
+++ b/session-notes/session-notes-2023-05-18.md
@@ -1,8 +1,7 @@
# Session Date: 2023-05-18
-## Co-Authors
-## Co-Authors
+## Co-Authors
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Michael R. Wolf
Co-Authored-By: Nitsan Avni
diff --git a/session-notes/session-notes-2023-05-25.md b/session-notes/session-notes-2023-05-25.md
index 0e1a0b4..cf74a0b 100644
--- a/session-notes/session-notes-2023-05-25.md
+++ b/session-notes/session-notes-2023-05-25.md
@@ -1,8 +1,7 @@
# Session Date: 2023-05-25
-## Co-Authors
-## Co-Authors
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Nitsan Avni
diff --git a/session-notes/session-notes-2023-06-01.md b/session-notes/session-notes-2023-06-01.md
index 3d8ccfd..9e58252 100644
--- a/session-notes/session-notes-2023-06-01.md
+++ b/session-notes/session-notes-2023-06-01.md
@@ -1,8 +1,7 @@
# Session Date: 2023-06-01
-## Co-Authors
-## Co-Authors
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Michael R. Wolf
Co-Authored-By: 4dsherwood <4dsherwood@users.noreply.github.com>
diff --git a/session-notes/session-notes-2023-06-08.md b/session-notes/session-notes-2023-06-08.md
index 8cc9ac1..42844d3 100644
--- a/session-notes/session-notes-2023-06-08.md
+++ b/session-notes/session-notes-2023-06-08.md
@@ -1,8 +1,7 @@
# Session Date: 2023-06-08
-## Co-Authors
-## Co-Authors
+## Co-Authors
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Michael R. Wolf
Co-Authored-By: Nitsan Avni
diff --git a/session-notes/session-notes-2023-06-15.md b/session-notes/session-notes-2023-06-15.md
index 7bd5fdd..7d36888 100644
--- a/session-notes/session-notes-2023-06-15.md
+++ b/session-notes/session-notes-2023-06-15.md
@@ -1,8 +1,7 @@
# Session Date: 2023-06-15
-## Co-Authors
-## Co-Authors
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Michael R. Wolf
diff --git a/session-notes/session-notes-2023-06-22.md b/session-notes/session-notes-2023-06-22.md
index a34e316..e644514 100644
--- a/session-notes/session-notes-2023-06-22.md
+++ b/session-notes/session-notes-2023-06-22.md
@@ -1,8 +1,7 @@
# Session Date: 2023-06-22
-## Co-Authors
-## Co-Authors
+## Co-Authors
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Nitsan Avni
Co-Authored-By: Gregor Riegler
diff --git a/session-notes/session-notes-2023-07-06.md b/session-notes/session-notes-2023-07-06.md
index f0eda94..cf3c991 100644
--- a/session-notes/session-notes-2023-07-06.md
+++ b/session-notes/session-notes-2023-07-06.md
@@ -1,8 +1,7 @@
# Session Date: 2023-07-06
-## Co-Authors
-## Co-Authors
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: 4dsherwood <4dsherwood@users.noreply.github.com>
diff --git a/session-notes/session-notes-2023-07-13.md b/session-notes/session-notes-2023-07-13.md
index 9b88900..1340c88 100644
--- a/session-notes/session-notes-2023-07-13.md
+++ b/session-notes/session-notes-2023-07-13.md
@@ -1,8 +1,7 @@
# Session Date: 2023-07-13
-## Co-Authors
-## Co-Authors
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Michael R. Wolf
diff --git a/session-notes/session-notes-2023-07-20.md b/session-notes/session-notes-2023-07-20.md
index 824074d..3af7975 100644
--- a/session-notes/session-notes-2023-07-20.md
+++ b/session-notes/session-notes-2023-07-20.md
@@ -1,8 +1,7 @@
# Session Date: 2023-07-20
-## Co-Authors
-## Co-Authors
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Michael R. Wolf
diff --git a/session-notes/session-notes-2023-07-27.md b/session-notes/session-notes-2023-07-27.md
index ee64b32..03c2527 100644
--- a/session-notes/session-notes-2023-07-27.md
+++ b/session-notes/session-notes-2023-07-27.md
@@ -1,5 +1,4 @@
# Session Date: 2023-07-27
-## Co-Authors
## Co-Authors
Co-Authored-By: Michael R. Wolf
diff --git a/session-notes/session-notes-2023-08-17.md b/session-notes/session-notes-2023-08-17.md
index c53787d..aa5cbe7 100644
--- a/session-notes/session-notes-2023-08-17.md
+++ b/session-notes/session-notes-2023-08-17.md
@@ -1,8 +1,7 @@
# Session Date: 2023-08-17
-## Co-Authors
-## Co-Authors
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Nitsan Avni
Co-Authored-By: Michael R. Wolf
diff --git a/session-notes/session-notes-2023-08-24.md b/session-notes/session-notes-2023-08-24.md
index 97c55c2..d2ac8e7 100644
--- a/session-notes/session-notes-2023-08-24.md
+++ b/session-notes/session-notes-2023-08-24.md
@@ -1,7 +1,7 @@
# Session Date: 2023-08-24
-## Co-Authors
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Nitsan Avni
diff --git a/session-notes/session-notes-2023-08-31.md b/session-notes/session-notes-2023-08-31.md
index ccb2e86..cb7a086 100644
--- a/session-notes/session-notes-2023-08-31.md
+++ b/session-notes/session-notes-2023-08-31.md
@@ -1,7 +1,7 @@
# Session Date: 2023-08-31
-## Co-Authors
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Michael R. Wolf
diff --git a/session-notes/session-notes-2023-09-07.md b/session-notes/session-notes-2023-09-07.md
index 3cf106a..7638fdc 100644
--- a/session-notes/session-notes-2023-09-07.md
+++ b/session-notes/session-notes-2023-09-07.md
@@ -1,7 +1,7 @@
# Session Date: 2023-09-07
-## Co-Authors
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
Co-Authored-By: Michael R. Wolf
diff --git a/session-notes/session-notes-2023-09-14.md b/session-notes/session-notes-2023-09-14.md
index 0c2bac9..50386fb 100644
--- a/session-notes/session-notes-2023-09-14.md
+++ b/session-notes/session-notes-2023-09-14.md
@@ -1,7 +1,7 @@
# Session Date: 2023-09-14
-## Co-Authors
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Nitsan Avni
Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
diff --git a/session-notes/session-notes-2023-09-28.md b/session-notes/session-notes-2023-09-28.md
index 1d5266e..e5fa14c 100644
--- a/session-notes/session-notes-2023-09-28.md
+++ b/session-notes/session-notes-2023-09-28.md
@@ -1,7 +1,7 @@
# Session Date: 2023-09-28
-## Co-Authors
+## Co-Authors
Co-Authored-By: Woody Zuill
Co-Authored-By: Michael R. Wolf
Co-Authored-By: Nitsan Avni
diff --git a/session-notes/session-notes-2023-10-05.md b/session-notes/session-notes-2023-10-05.md
index a75622e..d82cb8f 100644
--- a/session-notes/session-notes-2023-10-05.md
+++ b/session-notes/session-notes-2023-10-05.md
@@ -1,7 +1,7 @@
# Session Date: 2023-10-12
-## Co-Authors
+## Co-Authors
Co-Authored-By: Gregor Riegler
Co-Authored-By: Michael R. Wolf
Co-Authored-By: Nitsan Avni
diff --git a/session-notes/session-notes-2023-12-14.md b/session-notes/session-notes-2023-12-14.md
index 074e734..c0e7ed3 100644
--- a/session-notes/session-notes-2023-12-14.md
+++ b/session-notes/session-notes-2023-12-14.md
@@ -2,7 +2,7 @@
## Facilitated by
- Joel Silberman
-## Active Co-Authors
+## Co-Authors
Co-Authored-By: Nathaniel Herman
Co-Authored-By: Blaise Pabon
Co-Authored-By: Gregor Riegler
diff --git a/session-notes/session-notes-YYYY-MM-DD.md b/session-notes/session-notes-YYYY-MM-DD.md
index 244c014..c568887 100644
--- a/session-notes/session-notes-YYYY-MM-DD.md
+++ b/session-notes/session-notes-YYYY-MM-DD.md
@@ -1,5 +1,5 @@
-# Session Date: YYYY-MM-DD
-## Co-Authors
+
+## Active Co-Authors
## Inactive Co-Authors
Co-Authored-By: Nathaniel Herman
diff --git a/session-notes/cleanup-notes/cleanup_session_notes.pl b/src/session_notes_cleanup/cleanup_session_notes.pl
similarity index 100%
rename from session-notes/cleanup-notes/cleanup_session_notes.pl
rename to src/session_notes_cleanup/cleanup_session_notes.pl
diff --git a/session-notes/cleanup-notes/cleanup_session_notes.prompt b/src/session_notes_cleanup/cleanup_session_notes.prompt
similarity index 100%
rename from session-notes/cleanup-notes/cleanup_session_notes.prompt
rename to src/session_notes_cleanup/cleanup_session_notes.prompt
diff --git a/session-notes/cleanup-notes/doit b/src/session_notes_cleanup/doit
similarity index 59%
rename from session-notes/cleanup-notes/doit
rename to src/session_notes_cleanup/doit
index 01b569f..d2a93aa 100644
--- a/session-notes/cleanup-notes/doit
+++ b/src/session_notes_cleanup/doit
@@ -2,11 +2,8 @@
git_toplevel="$(git rev-parse --show-toplevel)"
note_directory="${git_toplevel}/session-notes"
-script_directory="${note_directory}/cleanup-notes"
-script_path="${script_directory}/cleanup_session_notes.py"
-
-cd "${note_directory}" || exit 2
-
+script_directory="${git_toplevel}/src/session_notes_cleanup"
+script_path="${script_directory}/session_notes_cleaner.py"
for arg in "$@"
@@ -18,7 +15,7 @@ do
filename="$arg"
fi
- . "${script_directory}/venv/bin/activate" || exit 3
+ # . "${git_toplevel}/venv/bin/activate" || exit 3
python "${script_path}" "${filename}"
done
diff --git a/src/session_notes_cleanup/session_notes_cleaner.py b/src/session_notes_cleanup/session_notes_cleaner.py
new file mode 100644
index 0000000..08b8e06
--- /dev/null
+++ b/src/session_notes_cleanup/session_notes_cleaner.py
@@ -0,0 +1,133 @@
+import os
+import re
+import shutil
+import sys
+from datetime import datetime
+
+inactive_co_author_header_pattern = r'^#+\s*Inactive\s(Co-Authors)?.*$'
+active_co_author_header_pattern = r'^#+\s*(Active Co-Authors|Co-Authors \(This Session\)).*$'
+
+
+# TODO
+# - Return codes similar to diff(1)
+
+class SessionNotesCleaner:
+ def __init__(self):
+ pass
+
+ def contains_inactive_coauthors(self, text):
+ return bool(re.search(inactive_co_author_header_pattern, text,
+ flags=re.IGNORECASE | re.MULTILINE))
+
+ def delete_inactive_coauthors(self, text):
+ return re.sub(r'^#+\s*Inactive Co-Authors.*?(?=^#|\Z)', '', text,
+ flags=re.IGNORECASE | re.MULTILINE | re.DOTALL)
+
+ def contains_active_coauthors(self, text):
+ return bool(re.search(active_co_author_header_pattern, text,
+ flags=re.IGNORECASE | re.MULTILINE))
+
+ def standardize_coauthor_heading(self, text):
+ # Co-Authors (This Session)
+ # Active Co-Authors
+ # active_co_author_search_pattern = r'^#+\s*((?:Active\s+)?)Co-?Authors.*$'
+ active_co_author_search_pattern = active_co_author_header_pattern
+ active_co_author_replace_pattern = r'## Co-Authors'
+ standardized_text_for_active_authors = \
+ re.sub(active_co_author_search_pattern, active_co_author_replace_pattern, text,
+ flags=re.IGNORECASE | re.MULTILINE)
+
+ # Inactive Co-Authors
+ # Inactive
+ inactive_co_author_search_pattern = inactive_co_author_header_pattern
+ inactive_co_author_replace_pattern = r'## Inactive Co-Authors'
+ standardized_text_for_active_and_inactive_authors \
+ = re.sub(inactive_co_author_search_pattern, inactive_co_author_replace_pattern,
+ standardized_text_for_active_authors,
+ flags=re.IGNORECASE | re.MULTILINE)
+
+ return standardized_text_for_active_and_inactive_authors
+
+ def remove_coauthor_headings(self, text):
+ # Regular expression to match 1st and 2nd level headings with "Co-Authors"
+ # Assumes Markdown formatting where 1st level is '# ' and 2nd level is '## '
+ standard_text = self.standardize_coauthor_heading(text)
+ pattern = r'^#{1,2}\s*Co-Authors.*$\n?'
+ cleaned_text = re.sub(pattern, '', standard_text,
+ flags=re.IGNORECASE | re.MULTILINE)
+
+ return cleaned_text
+
+ def add_coauthor_heading_before_co_authored_by_list(self, text):
+ search_pattern = r'^(Co-Authored-By.*)$'
+ replace_pattern = r'## Co-Authors\n\1'
+ cleaned_text = re.sub(search_pattern, replace_pattern, text,
+ count=1,
+ flags=re.IGNORECASE | re.MULTILINE)
+ return cleaned_text
+
+ def get_date_from_filename(self, filename):
+ match = re.search(r'^session-notes-(\d{4}-\d{2}-\d{2}).*[.]md$', filename)
+
+ if not match:
+ return None
+ else:
+ try:
+ date_str = match.group(1)
+ datetime.strptime(date_str, '%Y-%m-%d')
+ return date_str
+ except ValueError:
+ return None
+
+ def slurp_file(self, filename):
+ try:
+ with open(filename, 'r') as file:
+ return file.read()
+ except FileNotFoundError:
+ return None
+
+ def contains_session_date(self, text):
+ return bool(re.search(r'^#+\s*Session Date', text, re.IGNORECASE | re.MULTILINE))
+
+ def cleanup_contents(self, text, session_date):
+ if not self.contains_session_date(text):
+ text = f"# Session Date: {session_date}\n" + text
+ text = self.standardize_coauthor_heading(text)
+ # if self.contains_active_coauthors(text) and self.contains_inactive_coauthors(text):
+ text = self.delete_inactive_coauthors(text)
+
+ text = self.remove_coauthor_headings(text)
+ text = self.add_coauthor_heading_before_co_authored_by_list(text)
+ return text
+
+ def cleanup_file(self, filename):
+ original_contents = SessionNotesCleaner().slurp_file(filename)
+ if original_contents is None:
+ print(f"File not found: {filename}")
+ return
+
+ contents = original_contents
+ date_as_string = self.get_date_from_filename(filename)
+ contents = self.cleanup_contents(contents, date_as_string)
+ if contents == original_contents:
+ print(f"# No changes were needed for the file: {filename}")
+ else:
+ print(f"# Changes were made to the file: {filename}")
+ new_filename = filename + ".new"
+ with open(new_filename, 'w') as new_file:
+ new_file.write(contents)
+ shutil.copystat(filename, new_filename)
+ original_backup_filename = filename + ".original"
+ os.rename(filename, original_backup_filename)
+ os.rename(new_filename, filename)
+ print(f"# You can view changes by issuing this command:\ndiff -u {original_backup_filename} {filename}")
+
+
+def main():
+ cleaner = SessionNotesCleaner()
+ for filename in sys.argv[1:]:
+ cleaner.cleanup_file(filename)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/TestSessionNotesCleaner.test_import_approvalTests.approved.txt b/tests/TestSessionNotesCleaner.test_import_approvalTests.approved.txt
new file mode 100644
index 0000000..2e6945c
--- /dev/null
+++ b/tests/TestSessionNotesCleaner.test_import_approvalTests.approved.txt
@@ -0,0 +1 @@
+approvalTests::verify is imported
diff --git a/tests/TestSessionNotesCleaner.test_strip_trailing_whitespace.approved.txt b/tests/TestSessionNotesCleaner.test_strip_trailing_whitespace.approved.txt
new file mode 100644
index 0000000..5223074
--- /dev/null
+++ b/tests/TestSessionNotesCleaner.test_strip_trailing_whitespace.approved.txt
@@ -0,0 +1,11 @@
+Line with trailing spaces
+Line with trailing tabs
+ Line with 4 leading spaces
+ Line with 2 leading tabs
+Following line is empty
+
+Following line has 3 tabs
+
+Following line has 4 spaces
+
+This is last line.
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_session_notes_cleaner.py b/tests/test_session_notes_cleaner.py
new file mode 100644
index 0000000..3647e15
--- /dev/null
+++ b/tests/test_session_notes_cleaner.py
@@ -0,0 +1,236 @@
+# test_session_notes_cleaner.py
+import re
+import unittest
+
+from approvaltests import verify
+from approvaltests.reporters import GenericDiffReporterFactory, ClipboardReporter, MultiReporter
+
+from src.session_notes_cleanup.session_notes_cleaner import SessionNotesCleaner
+
+# Set up ApprovalTests reporter(s)
+default_reporter = GenericDiffReporterFactory().get_first_working()
+# TODO - Set reporter for whole file/class
+# from approvaltests.core import approval
+# approval.DEFAULT_REPORTER = default_reporter
+
+first_working_reporter = GenericDiffReporterFactory().get_first_working()
+clipboard_reporter = ClipboardReporter()
+# bc_reporter = GenericDiffReporterFactory().get("Beyond Compare")
+preferred_multi_reporter = MultiReporter(first_working_reporter, clipboard_reporter)
+preferred_multi_reporter = first_working_reporter
+
+
+class TestSessionNotesCleaner(unittest.TestCase):
+ # def setUp(self) -> None:
+
+ # self.addCleanup(first_working_reporter.report)
+
+ def test_initialization(self):
+ cleaner = SessionNotesCleaner()
+ # Add assertions here to test initial conditions
+ self.assertIsNotNone(cleaner)
+
+ def test_import_approvalTests(self):
+ verify("approvalTests::verify is imported\n")
+
+ def test_sample_file_has_no_trailing_whitespace(self):
+ text = self.sample_file_contents()
+ stripped_text = self.strip_trailing_whitespace(text)
+ self.assertEqual(text, stripped_text)
+
+ def test_contains_active_coauthors(self):
+ text = self.sample_file_contents()
+ cleaner = SessionNotesCleaner()
+ self.assertTrue(cleaner.contains_active_coauthors(text))
+
+ def test_contains_inactive_coauthors(self):
+ text = self.sample_file_contents()
+ cleaner = SessionNotesCleaner()
+ self.assertTrue(cleaner.contains_inactive_coauthors(text))
+
+ def test_delete_inactive_coauthors(self):
+ cleaner = SessionNotesCleaner()
+ text = self.sample_file_contents()
+ clean_text = cleaner.delete_inactive_coauthors(text)
+ verify(clean_text, preferred_multi_reporter)
+
+ def test_normalize_coauthor_heading(self):
+ text = ""
+ text += "## Co-Authors (This Session)\n"
+ text += "## Active Co-Authors\n"
+ text += "\n"
+ text += "## Inactive Co-Authors\n"
+ text += "## Inactive\n"
+
+ cleaner = SessionNotesCleaner()
+ clean_text = cleaner.standardize_coauthor_heading(text)
+ acceptance_text = f'Before\n{text}====\nAfter\n{clean_text}====\n'
+ verify(acceptance_text, preferred_multi_reporter)
+
+ def test_remove_coauthor_headings(self):
+ cleaner = SessionNotesCleaner()
+ text = ""
+ text += "## Co-Authors (This Session)\n"
+ text += "## Active Co-Authors\n"
+ text += "\n"
+ text += "## Inactive Co-Authors\n"
+ text += "## Inactive\n"
+ clean_text = cleaner.remove_coauthor_headings(text)
+ acceptance_text = f'Before\n{text}====\nAfter\n{clean_text}====\n'
+ verify(acceptance_text, preferred_multi_reporter)
+
+ def test_add_coauthor_heading_before_co_authored_by_list(self):
+ cleaner = SessionNotesCleaner()
+ text = ""
+ text += "## Facilitator\n"
+ text += "Everyone\n"
+ text += "\n"
+ text += "Co-Authored-By: Manny\n"
+ text += "Co-Authored-By: Moe\n"
+ text += "Co-Authored-By: Jack\n"
+ clean_text = cleaner.add_coauthor_heading_before_co_authored_by_list(text)
+ acceptance_text = f'Before\n{text}====\nAfter\n{clean_text}====\n'
+ verify(acceptance_text, preferred_multi_reporter)
+
+ def test_get_date_from_filename(self):
+ cleaner = SessionNotesCleaner()
+
+ # Test with valid filenames
+ self.assertEqual(cleaner.get_date_from_filename("session-notes-2022-10-20.md"), "2022-10-20")
+ self.assertEqual(cleaner.get_date_from_filename("session-notes-2021-01-01.md"), "2021-01-01")
+ self.assertEqual(cleaner.get_date_from_filename("session-notes-2021-01-01-part2.md"), "2021-01-01")
+
+ # Test with filenames that do not follow the expected pattern
+ self.assertIsNone(cleaner.get_date_from_filename("session-notes.md"), "Missing date part")
+ self.assertIsNone(cleaner.get_date_from_filename("Session-notes-2000-01-01.md"), "Incorrect capitalization")
+ self.assertIsNone(cleaner.get_date_from_filename("session-notes-2000-01-01.txt"), "Invalid extension")
+
+ self.assertIsNone(cleaner.get_date_from_filename("notes-2022-10-20.md"), "Incorrect leading part")
+
+ self.assertIsNone(cleaner.get_date_from_filename("session-notes-2022-13-01.md"), "Invalid month")
+ self.assertIsNone(cleaner.get_date_from_filename("session-notes-2022-00-10.md"), "Invalid month")
+
+ self.assertIsNone(cleaner.get_date_from_filename(""), "Empty")
+ self.assertIsNone(cleaner.get_date_from_filename(" "), "Blank")
+
+ def test_cleanup_contents(self):
+ cleaner = SessionNotesCleaner()
+ text = self.sample_file_contents()
+ clean_text = cleaner.cleanup_contents(text, "2023-12-07")
+ verify(clean_text, preferred_multi_reporter)
+
+ @staticmethod
+ def strip_trailing_whitespace(multi_line_text):
+ # Regular expression pattern to match trailing horizontal whitespace on each line, excluding newline
+ pattern = r'[ \t]+\n'
+ # Replace matched patterns with nothing (i.e., remove them)
+ return re.sub(pattern, '\n', multi_line_text)
+
+ def sample_file_contents(self):
+ text = '''# Session Date: 2023-12-07
+
+## Active Co-Authors
+Co-Authored-By: Nathaniel Herman
+Co-Authored-By: Blaise Pabon
+Co-Authored-By: Gregor Riegler
+Co-Authored-By: Michael R. Wolf
+Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
+Co-Authored-By: 4dsherwood <4dsherwood@users.noreply.github.com>
+Co-Authored-By: Nathaniel Herman
+
+
+## Inactive Co-Authors
+Co-Authored-By: Blaise Pabon
+Co-Authored-By: Gregor Riegler
+Co-Authored-By: Michael R. Wolf
+Co-Authored-By: Nitsan Avni
+Co-Authored-By: Joel Silberman <42779942+jcs-instructor@users.noreply.github.com>
+Co-Authored-By: 4dsherwood <4dsherwood@users.noreply.github.com>
+Co-Authored-By: arrockt
+Co-Authored-By: Austin Chadwick
+Co-Authored-By: Blessed538
+Co-Authored-By: Eddie Bush
+Co-Authored-By: Gabriel Mbaiorga
+Co-Authored-By: Idan Melamed
+Co-Authored-By: Rea
+Co-Authored-By: Tsvetan Tsvetanov
+Co-Authored-By: Willem Larsen
+Co-Authored-By: David Campey
+Co-Authored-by: Zac Ball
+Co-Authored-By: Kitastro
+Co-Authored-By: Woody Zuill
+Co-Authored-By: Llewellyn Falco
+
+# Agenda
+
+## Bond (30 min.)
+
+- Try a [warmup exercise](../docs/warmup-exercises.md)
+
+## Do ?
+FizzBuzz in Clojure
+https://cyber-dojo.org/kata/edit/EtbGU6
+
+
+## Mid Session Retro (10 min.)
+Tips:
+- TRY FOR 10 MIN. LIMIT. HAVE A HELPER ALSO TIME. AT END OF TIME, VOTE TO EXTEND IF NEEDED ONLY
+- Remember "Kindness, consideration and respect" - assume good intent; everyone is doing the best they can
+
+How did that feel (1-2 words / 30 sec)?
+- frustrating, fulfilling, overwhelmed
+- exciting, playful
+- curious, scared, fulfilled
+- rocky, relieved
+- refreshing, collaborative
+
+What did you like so much you want to do more of it / do it again?
+- clojure
+- everybody involved
+- observation doing thinking for another person
+- practicing thinking out loud +1
+- Nn8 doing like a pro:
+ - I feel overwhelmed
+ - Modeled being honest and verbalizing where he was and what he was thinking.
+ - Stream of thought
+- Modeling how we can get off track and on track
+- Copying an old test case to create a new one
+
+What might you want to try differently / experiment?
+- Remind newcomers to enter their author info (eg. Co-Authored-By: Blaise Pabon )
+
+## Do ?
+Continue FizzBuzz in Clojure
+https://cyber-dojo.org/kata/edit/EtbGU6
+
+# 2nd Retro (END OF SESSION)
+
+What to do next? Vote on Proposals:
+- Proposals:
+ - 1. spending less time deciding on what we're doing (more time coding)
+ - 2. shared leadership, dedicated facilitation
+ - 3. consider a checklist for newcomers (was a discussion about this)
+ - 4. consider items in the backlog (reminders, what are we working on, etc.
+'''
+ return self.strip_trailing_whitespace(text)
+
+
+def test_strip_trailing_whitespace(self):
+ text = '''Line with trailing spaces
+Line with trailing tabs
+ Line with 4 leading spaces
+ Line with 2 leading tabs
+Following line is empty
+
+Following line has 3 tabs
+
+Following line has 4 spaces
+
+This is last line.
+'''
+ stripped_text = self.strip_trailing_whitespace(text)
+ verify(stripped_text, preferred_multi_reporter)
+
+
+if __name__ == '__main__':
+ unittest.main()