diff --git a/.gitignore b/.gitignore index 78bef46..c0e1247 100644 --- a/.gitignore +++ b/.gitignore @@ -130,3 +130,5 @@ dmypy.json .idea/ .vscode/ + +*.py.lprof diff --git a/perf/perf_demo.py b/perf/perf_demo.py new file mode 100755 index 0000000..a4955b7 --- /dev/null +++ b/perf/perf_demo.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +import os + +from rich.console import Console + +from spiel.main import DEMO_SOURCE +from spiel.present import render_slide +from spiel.state import State + +CYCLES_PER_SLIDE = 10 +TRIGGERS_PER_SLIDE = 10 + + +def render_demo_repeatedly() -> None: + with open(os.devnull, "w") as f: + state = State.from_file(DEMO_SOURCE, console=Console(file=f)) + + for _ in range(CYCLES_PER_SLIDE): + for slide in state.deck: + for _ in range(TRIGGERS_PER_SLIDE): + rendered = render_slide(state, slide) + state.console.print(rendered) + state.trigger() + state.reset_trigger() + + +if __name__ == "__main__": + render_demo_repeatedly() diff --git a/perf/perf_image.py b/perf/perf_image.py new file mode 100755 index 0000000..876cd87 --- /dev/null +++ b/perf/perf_image.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +import os + +from rich.console import Console + +from spiel.main import DEMO_SOURCE +from spiel.present import render_slide +from spiel.state import State + +CYCLES_PER_SLIDE = 100 + + +def render_image_repeatedly() -> None: + with open(os.devnull, "w") as f: + state = State.from_file(DEMO_SOURCE, console=Console(file=f)) + + for _ in range(CYCLES_PER_SLIDE): + slide = [slide for slide in state.deck.slides if "Image" in slide.title][0] + rendered = render_slide(state, slide) + state.console.print(rendered) + + +if __name__ == "__main__": + render_image_repeatedly() diff --git a/perf/perf_plot.py b/perf/perf_plot.py new file mode 100755 index 0000000..99d5afe --- /dev/null +++ b/perf/perf_plot.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python + +import os + +from rich.console import Console + +from spiel.main import DEMO_SOURCE +from spiel.present import render_slide +from spiel.state import State + +CYCLES_PER_SLIDE = 100 + + +def render_image_repeatedly() -> None: + with open(os.devnull, "w") as f: + state = State.from_file(DEMO_SOURCE, console=Console(file=f)) + + state.trigger() + state.trigger() + for _ in range(CYCLES_PER_SLIDE): + slide = [slide for slide in state.deck.slides if "Plot" in slide.title][0] + rendered = render_slide(state, slide) + state.console.print(rendered) + state.trigger() + + +if __name__ == "__main__": + render_image_repeatedly() diff --git a/poetry.lock b/poetry.lock index e2ee076..9a28451 100644 --- a/poetry.lock +++ b/poetry.lock @@ -133,7 +133,7 @@ toml = ["toml"] [[package]] name = "decorator" -version = "5.0.8" +version = "5.0.9" description = "Decorators for Humans" category = "main" optional = false @@ -179,7 +179,7 @@ python-versions = "*" [[package]] name = "hypothesis" -version = "6.12.0" +version = "6.13.3" description = "A library for property-based testing" category = "dev" optional = false @@ -304,14 +304,14 @@ testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<6.0.0)"] [[package]] name = "jinja2" -version = "3.0.0" +version = "3.0.1" description = "A very fast and expressive template engine." category = "dev" optional = false python-versions = ">=3.6" [package.dependencies] -MarkupSafe = ">=2.0.0rc2" +MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] @@ -364,6 +364,22 @@ rich = "*" [package.extras] test = ["xeus-python", "ipykernel", "pytest", "pytest-asyncio", "mypy", "flake8"] +[[package]] +name = "line-profiler" +version = "3.2.6" +description = "Line-by-line profiler." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +IPython = {version = ">=0.13", markers = "python_version >= \"3.7\""} + +[package.extras] +all = ["cython", "scikit-build", "cmake", "ninja", "pytest (>=4.6.11)", "pytest-cov (>=2.10.1)", "coverage[toml] (>=5.3)", "ubelt (>=0.8.7)", "IPython (>=0.13,<=7.7.0)", "IPython (>=0.13)"] +build = ["cython", "scikit-build", "cmake", "ninja"] +tests = ["pytest (>=4.6.11)", "pytest-cov (>=2.10.1)", "coverage[toml] (>=5.3)", "ubelt (>=0.8.7)"] + [[package]] name = "livereload" version = "2.6.3" @@ -378,7 +394,7 @@ tornado = {version = "*", markers = "python_version > \"2.7\""} [[package]] name = "markupsafe" -version = "2.0.0" +version = "2.0.1" description = "Safely add untrusted strings to HTML/XML markup." category = "dev" optional = false @@ -751,7 +767,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] [[package]] name = "rich" -version = "10.2.0" +version = "10.2.2" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" category = "main" optional = false @@ -783,7 +799,7 @@ python-versions = "*" [[package]] name = "sortedcontainers" -version = "2.3.0" +version = "2.4.0" description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" category = "dev" optional = false @@ -877,11 +893,11 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" -version = "1.0.3" +version = "2.0.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" category = "dev" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" [package.extras] lint = ["flake8", "mypy", "docutils-stubs"] @@ -912,7 +928,7 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-serializinghtml" -version = "1.1.4" +version = "1.1.5" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." category = "dev" optional = false @@ -1014,7 +1030,7 @@ brotli = ["brotlipy (>=0.6.0)"] [[package]] name = "watchdog" -version = "2.1.1" +version = "2.1.2" description = "Filesystem events monitoring" category = "main" optional = false @@ -1034,7 +1050,7 @@ python-versions = "*" [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "533e48018a7ca2101e98d2b8643587bace73062096e54d4b9159017b8d868a6c" +content-hash = "1902025d1f63c0be7fc1277e3c97d34aa0c1546ded48c24b69713d9a5e949169" [metadata.files] alabaster = [ @@ -1179,8 +1195,8 @@ coverage = [ {file = "coverage-5.5.tar.gz", hash = "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c"}, ] decorator = [ - {file = "decorator-5.0.8-py3-none-any.whl", hash = "sha256:77a3141f7f5837b5de43569c35508ca4570022ba501db8c8a2a8b292bd35772a"}, - {file = "decorator-5.0.8.tar.gz", hash = "sha256:bff00cfb18698f9a19fa6400451fd7ea894f3845cedd7b8b7b0ce9c53171fefb"}, + {file = "decorator-5.0.9-py3-none-any.whl", hash = "sha256:6e5c199c16f7a9f0e3a61a4a54b3d27e7dad0dbdde92b944426cb20914376323"}, + {file = "decorator-5.0.9.tar.gz", hash = "sha256:72ecfba4320a893c53f9706bebb2d55c270c1e51a28789361aa93e4a21319ed5"}, ] docopt = [ {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"}, @@ -1198,8 +1214,8 @@ filelock = [ {file = "filelock-3.0.12.tar.gz", hash = "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59"}, ] hypothesis = [ - {file = "hypothesis-6.12.0-py3-none-any.whl", hash = "sha256:d26f2b7bb6e3edebc6eded70ff99cd15425bf4266608e7a041d75f00b58ac7cb"}, - {file = "hypothesis-6.12.0.tar.gz", hash = "sha256:a24b2ccb7b84860762df3fabb8faa196bf627cbee62917a5095f3de8ff71050b"}, + {file = "hypothesis-6.13.3-py3-none-any.whl", hash = "sha256:63fa82cf29a5d0e169df1ede5d8d8c9e718d1213f3a3d9bf6879224886c2328c"}, + {file = "hypothesis-6.13.3.tar.gz", hash = "sha256:49fbede48837cbee2160a83d1c99c0a9094d74bad0e2f6f5f351ac80ff559a79"}, ] idna = [ {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, @@ -1230,8 +1246,8 @@ jedi = [ {file = "jedi-0.18.0.tar.gz", hash = "sha256:92550a404bad8afed881a137ec9a461fed49eca661414be45059329614ed0707"}, ] jinja2 = [ - {file = "Jinja2-3.0.0-py3-none-any.whl", hash = "sha256:2f2de5285cf37f33d33ecd4a9080b75c87cd0c1994d5a9c6df17131ea1f049c6"}, - {file = "Jinja2-3.0.0.tar.gz", hash = "sha256:ea8d7dd814ce9df6de6a761ec7f1cac98afe305b8cdc4aaae4e114b8d8ce24c5"}, + {file = "Jinja2-3.0.1-py3-none-any.whl", hash = "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4"}, + {file = "Jinja2-3.0.1.tar.gz", hash = "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"}, ] jupyter-client = [ {file = "jupyter_client-6.2.0-py3-none-any.whl", hash = "sha256:9715152067e3f7ea3b56f341c9a0f9715c8c7cc316ee0eb13c3c84f5ca0065f5"}, @@ -1245,44 +1261,55 @@ kernel-driver = [ {file = "kernel_driver-0.0.5-py3-none-any.whl", hash = "sha256:ad607187d7dca9581a26ffa9a183ceae6a98f6ba12459331801deddab6cea031"}, {file = "kernel_driver-0.0.5.tar.gz", hash = "sha256:f7c58743b1df06066beaed038804a30bebb05587fc014a94fa382e7bfba748ca"}, ] +line-profiler = [ + {file = "line_profiler-3.2.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1bab74bb0943167ab4d3e75918fa57c57f8327d9c7955bec4d425e0578dfbc7c"}, + {file = "line_profiler-3.2.6-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:27ec2092d19b94f36d4249806e2200647de2e22af8ac653f1c6a82075ee879cf"}, + {file = "line_profiler-3.2.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0365a1800980a53f9633453eae73a8bb7565f25443b0196acdf5144d2523301f"}, + {file = "line_profiler-3.2.6-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:9454302cd20ed76d4f76081d35652df993f41f1d0a0f5765cb2ffe4198bced45"}, + {file = "line_profiler-3.2.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2511f25d26272749d3baa523f669a809e22a0ee6cca0f2b1dd37d36115b73e81"}, + {file = "line_profiler-3.2.6-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:0e86f91b63629fa594cc9eed6d36625c9beb16a92cee7b55bf8fbc0657ebde3d"}, + {file = "line_profiler-3.2.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3f96ca5802eb144c1dd7857da1b2a06df4398d1a9f2a212c2f50edf8e5f00abc"}, + {file = "line_profiler-3.2.6-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:4915a2731c95e584788513d340497f79a4e3a22ef78ecedb60816a71dc39529a"}, + {file = "line_profiler-3.2.6.tar.gz", hash = "sha256:dbc831754699ef6a3ae16a38c79f87823380770cd41a6e4c02345be5a5ea4a0d"}, +] livereload = [ {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, ] markupsafe = [ - {file = "MarkupSafe-2.0.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2efaeb1baff547063bad2b2893a8f5e9c459c4624e1a96644bbba08910ae34e0"}, - {file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:441ce2a8c17683d97e06447fcbccbdb057cbf587c78eb75ae43ea7858042fe2c"}, - {file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:45535241baa0fc0ba2a43961a1ac7562ca3257f46c4c3e9c0de38b722be41bd1"}, - {file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:90053234a6479738fd40d155268af631c7fca33365f964f2208867da1349294b"}, - {file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3b54a9c68995ef4164567e2cd1a5e16db5dac30b2a50c39c82db8d4afaf14f63"}, - {file = "MarkupSafe-2.0.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:f58b5ba13a5689ca8317b98439fccfbcc673acaaf8241c1869ceea40f5d585bf"}, - {file = "MarkupSafe-2.0.0-cp36-cp36m-win32.whl", hash = "sha256:a00dce2d96587651ef4fa192c17e039e8cfab63087c67e7d263a5533c7dad715"}, - {file = "MarkupSafe-2.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:007dc055dbce5b1104876acee177dbfd18757e19d562cd440182e1f492e96b95"}, - {file = "MarkupSafe-2.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a08cd07d3c3c17cd33d9e66ea9dee8f8fc1c48e2d11bd88fd2dc515a602c709b"}, - {file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:3c352ff634e289061711608f5e474ec38dbaa21e3e168820d53d5f4015e5b91b"}, - {file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:32200f562daaab472921a11cbb63780f1654552ae49518196fc361ed8e12e901"}, - {file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:fef86115fdad7ae774720d7103aa776144cf9b66673b4afa9bcaa7af990ed07b"}, - {file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:e79212d09fc0e224d20b43ad44bb0a0a3416d1e04cf6b45fed265114a5d43d20"}, - {file = "MarkupSafe-2.0.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:79b2ae94fa991be023832e6bcc00f41dbc8e5fe9d997a02db965831402551730"}, - {file = "MarkupSafe-2.0.0-cp37-cp37m-win32.whl", hash = "sha256:3261fae28155e5c8634dd7710635fe540a05b58f160cef7713c7700cb9980e66"}, - {file = "MarkupSafe-2.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e4570d16f88c7f3032ed909dc9e905a17da14a1c4cfd92608e3fda4cb1208bbd"}, - {file = "MarkupSafe-2.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f806bfd0f218477d7c46a11d3e52dc7f5fdfaa981b18202b7dc84bbc287463b"}, - {file = "MarkupSafe-2.0.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e77e4b983e2441aff0c0d07ee711110c106b625f440292dfe02a2f60c8218bd6"}, - {file = "MarkupSafe-2.0.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:031bf79a27d1c42f69c276d6221172417b47cb4b31cdc73d362a9bf5a1889b9f"}, - {file = "MarkupSafe-2.0.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:83cf0228b2f694dcdba1374d5312f2277269d798e65f40344964f642935feac1"}, - {file = "MarkupSafe-2.0.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4cc563836f13c57f1473bc02d1e01fc37bab70ad4ee6be297d58c1d66bc819bf"}, - {file = "MarkupSafe-2.0.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:d00a669e4a5bec3ee6dbeeeedd82a405ced19f8aeefb109a012ea88a45afff96"}, - {file = "MarkupSafe-2.0.0-cp38-cp38-win32.whl", hash = "sha256:161d575fa49395860b75da5135162481768b11208490d5a2143ae6785123e77d"}, - {file = "MarkupSafe-2.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:58bc9fce3e1557d463ef5cee05391a05745fd95ed660f23c1742c711712c0abb"}, - {file = "MarkupSafe-2.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3fb47f97f1d338b943126e90b79cad50d4fcfa0b80637b5a9f468941dbbd9ce5"}, - {file = "MarkupSafe-2.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dab0c685f21f4a6c95bfc2afd1e7eae0033b403dd3d8c1b6d13a652ada75b348"}, - {file = "MarkupSafe-2.0.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:664832fb88b8162268928df233f4b12a144a0c78b01d38b81bdcf0fc96668ecb"}, - {file = "MarkupSafe-2.0.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:df561f65049ed3556e5b52541669310e88713fdae2934845ec3606f283337958"}, - {file = "MarkupSafe-2.0.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:24bbc3507fb6dfff663af7900a631f2aca90d5a445f272db5fc84999fa5718bc"}, - {file = "MarkupSafe-2.0.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:87de598edfa2230ff274c4de7fcf24c73ffd96208c8e1912d5d0fee459767d75"}, - {file = "MarkupSafe-2.0.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:a19d39b02a24d3082856a5b06490b714a9d4179321225bbf22809ff1e1887cc8"}, - {file = "MarkupSafe-2.0.0-cp39-cp39-win32.whl", hash = "sha256:4aca81a687975b35e3e80bcf9aa93fe10cd57fac37bf18b2314c186095f57e05"}, - {file = "MarkupSafe-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:70820a1c96311e02449591cbdf5cd1c6a34d5194d5b55094ab725364375c9eb2"}, - {file = "MarkupSafe-2.0.0.tar.gz", hash = "sha256:4fae0677f712ee090721d8b17f412f1cbceefbf0dc180fe91bab3232f38b4527"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, + {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, + {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, + {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, + {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, + {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, ] matplotlib-inline = [ {file = "matplotlib-inline-0.1.2.tar.gz", hash = "sha256:f41d5ff73c9f5385775d5c0bc13b424535c8402fe70ea8210f93e11f3683993e"}, @@ -1542,8 +1569,8 @@ requests = [ {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"}, ] rich = [ - {file = "rich-10.2.0-py3-none-any.whl", hash = "sha256:2701b69b9646a12b05d80f9d96a48615d4b68678fbfa67a60aa2834a62ad01e7"}, - {file = "rich-10.2.0.tar.gz", hash = "sha256:a30429d82363d42e7c64e324c2c8735c045f190cba609feee91a7b9f563a64b5"}, + {file = "rich-10.2.2-py3-none-any.whl", hash = "sha256:203e79c9012f57e0148a2132d0b43fe070a5c213cf080982c186e1d3ae4f8e1d"}, + {file = "rich-10.2.2.tar.gz", hash = "sha256:17b3f486c38e79cc219d8848974b277ef532a82d12b3ad6eb37bb8c6f22ab5fc"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, @@ -1554,8 +1581,8 @@ snowballstemmer = [ {file = "snowballstemmer-2.1.0.tar.gz", hash = "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914"}, ] sortedcontainers = [ - {file = "sortedcontainers-2.3.0-py2.py3-none-any.whl", hash = "sha256:37257a32add0a3ee490bb170b599e93095eed89a55da91fa9f48753ea12fd73f"}, - {file = "sortedcontainers-2.3.0.tar.gz", hash = "sha256:59cc937650cf60d677c16775597c89a960658a09cf7c1a668f86e1e4464b10a1"}, + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, ] sphinx = [ {file = "Sphinx-3.5.4-py3-none-any.whl", hash = "sha256:2320d4e994a191f4b4be27da514e46b3d6b420f2ff895d064f52415d342461e8"}, @@ -1578,8 +1605,8 @@ sphinxcontrib-devhelp = [ {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, ] sphinxcontrib-htmlhelp = [ - {file = "sphinxcontrib-htmlhelp-1.0.3.tar.gz", hash = "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b"}, - {file = "sphinxcontrib_htmlhelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f"}, + {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"}, + {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"}, ] sphinxcontrib-jsmath = [ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, @@ -1590,8 +1617,8 @@ sphinxcontrib-qthelp = [ {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, ] sphinxcontrib-serializinghtml = [ - {file = "sphinxcontrib-serializinghtml-1.1.4.tar.gz", hash = "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc"}, - {file = "sphinxcontrib_serializinghtml-1.1.4-py2.py3-none-any.whl", hash = "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a"}, + {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, + {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, ] toml = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, @@ -1694,23 +1721,23 @@ urllib3 = [ {file = "urllib3-1.26.4.tar.gz", hash = "sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937"}, ] watchdog = [ - {file = "watchdog-2.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f3edbe1e15e229d2ba8ff5156908adba80d1ba21a9282d9f72247403280fc799"}, - {file = "watchdog-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c1325b47463fce231d88eb74f330ab0cb4a1bab5defe12c0c80a3a4f197345b4"}, - {file = "watchdog-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5b391bac7edbdf96fb82a381d04829bbc0d1bb259c206b2b283ef8989340240f"}, - {file = "watchdog-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:22c13c19599b0dec7192f8f7d26404d5223cb36c9a450e96430483e685dccd7e"}, - {file = "watchdog-2.1.1-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:604ca364a79c27a694ab10947cd41de81bf229cff507a3156bf2c56c064971a1"}, - {file = "watchdog-2.1.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:dca75d12712997c713f76e6d68ff41580598c7df94cedf83f1089342e7709081"}, - {file = "watchdog-2.1.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:aa59afc87a892ed92d7d88d09f4b736f1336fc35540b403da7ee00c3be74bd07"}, - {file = "watchdog-2.1.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:a1b3f76e2a0713b406348dd5b9df2aa02bdd741a6ddf54f4c6410b395e077502"}, - {file = "watchdog-2.1.1-py3-none-manylinux2014_i686.whl", hash = "sha256:9f1b124fe2d4a1f37b7068f6289c2b1eba44859eb790bf6bd709adff224a5469"}, - {file = "watchdog-2.1.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:a9005f968220b715101d5fcdde5f5deda54f0d1873f618724f547797171f5e97"}, - {file = "watchdog-2.1.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:027c532e2fd3367d55fe235510fc304381a6cc88d0dcd619403e57ffbd83c1d2"}, - {file = "watchdog-2.1.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:4d83c89ba24bd67b7a7d5752a4ef953ec40db69d4d30582bd1f27d3ecb6b61b0"}, - {file = "watchdog-2.1.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:67c645b1e500cc74d550e9aad4829309c5084dc55e8dc4e1c25d5da23e5be239"}, - {file = "watchdog-2.1.1-py3-none-win32.whl", hash = "sha256:12645d41d7307601b318c48861e776ce7a9fdcad9f74961013ec39037050582c"}, - {file = "watchdog-2.1.1-py3-none-win_amd64.whl", hash = "sha256:16078cd241a95124acd4d8d3efba2140faec9300674b12413cc08be11b825d56"}, - {file = "watchdog-2.1.1-py3-none-win_ia64.whl", hash = "sha256:20d4cabfa2ad7239995d81a0163bc0264a3e104a64f33c6f0a21ad75a0d915d9"}, - {file = "watchdog-2.1.1.tar.gz", hash = "sha256:2894440b4ea95a6ef4c5d152deedbe270cae46092682710b7028a04d6a6980f6"}, + {file = "watchdog-2.1.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:581e3548159fe7d2a9f377a1fbcb41bdcee46849cca8ab803c7ac2e5e04ec77c"}, + {file = "watchdog-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:edcd9ef3fd460bb8a98eb1fcf99941e9fd9f275f45f1a82cb1359ec92975d647"}, + {file = "watchdog-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d34ce2261f118ecd57eedeef95fc2a495fc4a40b3ed7b3bf0bd7a8ccc1ab4f8f"}, + {file = "watchdog-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:668391e6c32742d76e5be5db6bf95c455fa4b3d11e76a77c13b39bccb3a47a72"}, + {file = "watchdog-2.1.2-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6ef9fe57162c4c361692620e1d9167574ba1975ee468b24051ca11c9bba6438e"}, + {file = "watchdog-2.1.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:58ebb1095ee493008a7789d47dd62e4999505d82be89fc884d473086fccc6ebd"}, + {file = "watchdog-2.1.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:91387ee2421f30b75f7ff632c9d48f76648e56bf346a7c805c0a34187a93aab4"}, + {file = "watchdog-2.1.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:a6471517315a8541a943c00b45f1d252e36898a3ae963d2d52509b89a50cb2b9"}, + {file = "watchdog-2.1.2-py3-none-manylinux2014_i686.whl", hash = "sha256:a42e6d652f820b2b94cd03156c62559a2ea68d476476dfcd77d931e7f1012d4a"}, + {file = "watchdog-2.1.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:3d6405681471ebe0beb3aa083998c4870e48b57f8afdb45ea1b5957cc5cf1014"}, + {file = "watchdog-2.1.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:598d772beeaf9c98d0df946fbabf0c8365dd95ea46a250c224c725fe0c4730bc"}, + {file = "watchdog-2.1.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:4b219d46d89cfa49af1d73175487c14a318a74cb8c5442603fd13c6a5b418c86"}, + {file = "watchdog-2.1.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:188145185c08c73c56f1478ccf1f0f0f85101191439679b35b6b100886ce0b39"}, + {file = "watchdog-2.1.2-py3-none-win32.whl", hash = "sha256:255a32d44bbbe62e52874ff755e2eefe271b150e0ec240ad7718a62a7a7a73c4"}, + {file = "watchdog-2.1.2-py3-none-win_amd64.whl", hash = "sha256:1a62a4671796dc93d1a7262286217d9e75823c63d4c42782912d39a506d30046"}, + {file = "watchdog-2.1.2-py3-none-win_ia64.whl", hash = "sha256:104266a778906ae0e971368d368a65c4cd032a490a9fca5ba0b78c6c7ae11720"}, + {file = "watchdog-2.1.2.tar.gz", hash = "sha256:0237db4d9024859bea27d0efb59fe75eef290833fd988b8ead7a879b0308c2db"}, ] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, diff --git a/pyproject.toml b/pyproject.toml index 0afaadf..9194861 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ line_length = 100 [tool.poetry] name = "spiel" -version = "0.2.0" +version = "0.2.1" description = "A framework for building and presenting richly-styled presentations in your terminal using Python." readme="README.md" homepage="https://github.com/JoshKarpel/spiel" @@ -34,7 +34,7 @@ include = ["py.typed", "demo/*"] [tool.poetry.dependencies] python = "^3.9" -rich = "^10.0.0" +rich = "^10.2.2" typer = "^0.3.2" watchdog = "^2.0.2" pendulum = "^2.1.2" @@ -58,6 +58,7 @@ hypothesis = "^6.8.3" Sphinx = "^3.5.3" sphinx-rtd-theme = "^0.5.2" sphinx-autobuild = "^2021.3.14" +line-profiler = "^3.2.6" [tool.poetry.scripts] spiel = 'spiel.main:app' diff --git a/spiel/demo/demo.py b/spiel/demo/demo.py index d673ea1..081bfdf 100644 --- a/spiel/demo/demo.py +++ b/spiel/demo/demo.py @@ -519,7 +519,7 @@ def options_(): {SPIEL} has a variety of options that can be adjusted at runtime. For example, - profiling information can be displayed in the footer to help you debug a slides that is rendering too slowly. + profiling information can be displayed in the footer to help you debug a slide that is rendering too slowly. To see your current options, press `p`. From that mode you can edit your options by pressing `e`. diff --git a/spiel/footer.py b/spiel/footer.py index 0599541..ec97ae5 100644 --- a/spiel/footer.py +++ b/spiel/footer.py @@ -65,7 +65,9 @@ class Footer: ) ), self.state.message, - Text(f"{self.rps_counter.renders_per_second() :.2f} RPS") + Text( + f"Render Time: {self.rps_counter.last_elapsed_render_time() * 1e3:>3.3f} ms | {self.rps_counter.renders_per_second():.2f} RPS" + ) if self.state.options.profiling else None, now().format(self.state.options.footer_time_format), diff --git a/spiel/image.py b/spiel/image.py index 60227ce..bcd5445 100644 --- a/spiel/image.py +++ b/spiel/image.py @@ -1,16 +1,16 @@ from __future__ import annotations from dataclasses import dataclass +from functools import lru_cache from math import floor from pathlib import Path -from typing import Iterable, NamedTuple +from typing import Iterable, List, NamedTuple, Tuple, Union from PIL import Image as Img from rich.color import Color -from rich.console import Console, ConsoleOptions, JustifyMethod +from rich.console import Console, ConsoleOptions from rich.segment import Segment from rich.style import Style -from rich.text import Text from .utils import chunks @@ -20,14 +20,44 @@ class ImageSize(NamedTuple): height: int +Pixels = Tuple[Union[Tuple[int, int, int], None], ...] + + +@lru_cache(maxsize=2 ** 8) +def _pixels_to_segments(pixels: Pixels, size: ImageSize) -> List[Segment]: + line = Segment.line() + + segments = [] + pixel_row_pairs = chunks(chunks(pixels, size.width), 2, fill_value=[None] * size.width) + for top_pixel_row, bottom_pixel_row in pixel_row_pairs: + for top_pixel, bottom_pixel in zip(top_pixel_row, bottom_pixel_row): + # use upper-half-blocks for the top pixel row and the background color for the bottom pixel row + segments.append( + Segment( + text="▀", + style=Style( + color=Color.from_rgb(*top_pixel) if top_pixel else None, + bgcolor=Color.from_rgb(*bottom_pixel) if bottom_pixel else None, + ), + ) + ) + segments.append(line) + + return list(Segment.simplify(segments)) + + +@lru_cache(maxsize=2 ** 4) +def _load_image(path: Path) -> Image: + return Img.open(path) + + @dataclass(frozen=True) class Image: img: Img - justify: JustifyMethod = "center" @classmethod - def from_file(cls, path: Path, justify: JustifyMethod = "center") -> Image: - return cls(img=Img.open(path), justify=justify) + def from_file(cls, path: Path) -> Image: + return cls(img=_load_image(path)) def _determine_size(self, options: ConsoleOptions) -> ImageSize: width, height = self.img.size @@ -51,25 +81,5 @@ class Image: def __rich_console__(self, console: Console, options: ConsoleOptions) -> Iterable[Segment]: size = self._determine_size(options) resized = self._resize(size) - - rows = [ - [ - Text( - "▀", - Style( - color=Color.from_rgb(*top), - bgcolor=Color.from_rgb(*bottom) if bottom else None, - ), - ) - # ... produce one row of text, using upper-half-blocks for the top image row and the background for the bottom image row - for top, bottom in zip(top_row, bottom_row) - ] - # for each pair of rows in the image... - for top_row, bottom_row in chunks( - chunks(resized.getdata(), size.width), 2, fill_value=[None] * size.width - ) - ] - - text = Text("\n", justify=self.justify).join(Text("").join(row) for row in rows) - - yield from text.__rich_console__(console, options) + pixels = tuple(resized.getdata()) + yield from _pixels_to_segments(pixels, size) diff --git a/spiel/plot.py b/spiel/plot.py index 6e9b5a3..48059b1 100644 --- a/spiel/plot.py +++ b/spiel/plot.py @@ -1,5 +1,7 @@ +import pickle import re -from typing import Any, Iterable, Sequence, Union +from functools import lru_cache +from typing import Any, Iterable, List, Sequence, Union import numpy as np import uniplot @@ -8,7 +10,6 @@ from colorama import Style as CStyle from rich.console import Console, ConsoleOptions from rich.segment import Segment from rich.style import Style -from rich.text import Text Plottable = Union[ np.ndarray, @@ -17,18 +18,47 @@ Plottable = Union[ RE_ANSI_ESCAPE = re.compile(r"(\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~]))") -COLOR_MAP = { - Fore.RED: "red", - Fore.GREEN: "green", - Fore.BLUE: "blue", - Fore.CYAN: "cyan", - Fore.YELLOW: "yellow", - Fore.MAGENTA: "magenta", - Fore.BLACK: "black", - Fore.WHITE: "white", +ANSI_COLOR_TO_STYLE = { + CStyle.RESET_ALL: Style.null(), + Fore.RED: Style(color="red"), + Fore.GREEN: Style(color="green"), + Fore.BLUE: Style(color="blue"), + Fore.CYAN: Style(color="cyan"), + Fore.YELLOW: Style(color="yellow"), + Fore.MAGENTA: Style(color="magenta"), + Fore.BLACK: Style(color="black"), + Fore.WHITE: Style(color="white"), } +@lru_cache(maxsize=2 ** 8) +def _ansi_to_text(s: str) -> List[Segment]: + segments = [] + tmp = "" + null_style = Style.null() + style = null_style + for char in RE_ANSI_ESCAPE.split(s): + if char in ANSI_COLOR_TO_STYLE: + segments.append(Segment(tmp, style=style)) + style = ANSI_COLOR_TO_STYLE[char] + tmp = "" + else: + tmp += char + + # catch leftovers + segments.append(Segment(tmp, style=style)) + + return list(Segment.simplify(segments)) + + +@lru_cache(maxsize=2 ** 8) +def _make_plot(pickled_plot_args: bytes) -> List[str]: + # This is kind of ugly, but we pickle the args before passing them as an easy + # way to make them hashable. This helps a lot for performance on static plots, + # and doesn't have toooooo much impact on dynamic plots. + return uniplot.plot_to_string(**pickle.loads(pickled_plot_args)) + + class Plot: def __init__( self, @@ -36,27 +66,6 @@ class Plot: ) -> None: self.plot_args = plot_args - def _ansi_to_text(self, s: str) -> Text: - pieces = [] - tmp = "" - style = Style.null() - for char in RE_ANSI_ESCAPE.split(s): - if char == CStyle.RESET_ALL: - pieces.append(Text(tmp, style=style)) - style = Style.null() - tmp = "" - elif char in COLOR_MAP: - pieces.append(Text(tmp, style=style)) - style = Style(color=COLOR_MAP[char]) - tmp = "" - else: - tmp += char - - # catch leftovers - pieces.append(Text(tmp, style=style)) - - return Text("", no_wrap=True).join(pieces) - def __rich_console__(self, console: Console, options: ConsoleOptions) -> Iterable[Segment]: if self.plot_args.get("height") is None and options.height is None: height = None @@ -74,8 +83,7 @@ class Plot: ), } - plot = "\n".join(uniplot.plot_to_string(**plot_args)) - - text = self._ansi_to_text(plot) + plot = "\n".join(_make_plot(pickled_plot_args=pickle.dumps(plot_args))) + # plot = "\n".join(uniplot.plot_to_string(plot_args)) - yield from text.__rich_console__(console, options) + yield from _ansi_to_text(plot) diff --git a/spiel/rps.py b/spiel/rps.py index 42e074e..dd432e2 100644 --- a/spiel/rps.py +++ b/spiel/rps.py @@ -12,12 +12,21 @@ class RPSCounter: self.render_time_history: Deque[float] = deque(maxlen=render_history_length) + @property + def num_samples(self) -> int: + return len(self.render_time_history) + def mark(self) -> None: self.render_time_history.append(monotonic()) def renders_per_second(self) -> float: - num_samples = len(self.render_time_history) - if num_samples < 2: + if self.num_samples < 2: + return 0 + + return self.num_samples / (self.render_time_history[-1] - self.render_time_history[0]) + + def last_elapsed_render_time(self) -> float: + if self.num_samples < 2: return 0 - return num_samples / (self.render_time_history[-1] - self.render_time_history[0]) + return self.render_time_history[-1] - self.render_time_history[-2] diff --git a/spiel/state.py b/spiel/state.py index f67943a..601e3f5 100644 --- a/spiel/state.py +++ b/spiel/state.py @@ -33,9 +33,9 @@ class State: trigger_times: List[float] = field(default_factory=list) @classmethod - def from_file(cls, path: Path) -> State: + def from_file(cls, path: Path, console: Optional[Console] = None) -> State: deck, options = load_deck_and_options(path) - return cls(console=Console(), deck=deck, options=options) + return cls(console=console or Console(), deck=deck, options=options) @property def mode(self) -> Mode: diff --git a/tests/test_rps.py b/tests/test_rps.py index 2dc1d54..8835743 100644 --- a/tests/test_rps.py +++ b/tests/test_rps.py @@ -8,14 +8,14 @@ def counter() -> RPSCounter: return RPSCounter() -def test_internals(counter: RPSCounter) -> None: +def test_renders_per_second(counter: RPSCounter) -> None: # 3 renders in 4 seconds counter.render_time_history.extend([1, 2, 5]) assert counter.renders_per_second() == 3 / 4 -def test_not_enough_samples(counter: RPSCounter) -> None: +def test_not_enough_samples_for_renders_per_second(counter: RPSCounter) -> None: counter.render_time_history.extend([1]) # 1 sample isn't enough @@ -23,5 +23,19 @@ def test_not_enough_samples(counter: RPSCounter) -> None: assert counter.renders_per_second() == 0 +def test_last_elapsed_render_time(counter: RPSCounter) -> None: + counter.render_time_history.extend([1, 2, 5]) + + assert counter.last_elapsed_render_time() == 3 + + +def test_not_enough_samples_last_elapsed_render_time(counter: RPSCounter) -> None: + counter.render_time_history.extend([1]) + + # 1 sample isn't enough + + assert counter.last_elapsed_render_time() == 0 + + def test_custom_length() -> None: assert RPSCounter(render_history_length=5).render_time_history.maxlen == 5