From b37a233f711f1107ce6c3bf85fc6c42fdb8c58ef Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 22 Jun 2023 16:49:25 +0200 Subject: [PATCH 001/154] Initialized mkdocs --- docs/admin/command-line.md | 76 ++ docs/admin/containers.md | 112 ++ docs/admin/install.md | 33 + docs/admin/systemd.md | 39 + docs/asab/alert.md | 83 ++ docs/asab/application.md | 204 ++++ docs/asab/config.md | 243 ++++ docs/asab/index.md | 47 + docs/asab/library.md | 360 ++++++ docs/asab/log.md | 243 ++++ docs/asab/metrics.md | 632 +++++++++++ docs/asab/module.md | 53 + docs/asab/pubsub.md | 274 +++++ docs/asab/service.md | 53 + docs/asab/storage.md | 528 +++++++++ docs/asab/various.md | 51 + docs/asab/web/auth.md | 18 + docs/asab/web/cors.md | 23 + docs/asab/web/index.md | 148 +++ docs/asab/web/restapidocs.md | 141 +++ docs/asab/zookeeper.md | 190 ++++ docs/get-started.md | 101 ++ docs/index.md | 45 + docs/tutorial/chapter1.md | 66 ++ docs/tutorial/chapter2.md | 661 +++++++++++ mkdocs.yml | 43 + {doc => old_docs}/Makefile | 0 {doc => old_docs}/TODO.md | 0 .../doctrees/admin/command-line.doctree | Bin 0 -> 14162 bytes .../_build/doctrees/admin/containers.doctree | Bin 0 -> 14810 bytes .../_build/doctrees/admin/install.doctree | Bin 0 -> 5195 bytes .../_build/doctrees/admin/systemd.doctree | Bin 0 -> 6718 bytes old_docs/_build/doctrees/asab/alert.doctree | Bin 0 -> 12257 bytes .../_build/doctrees/asab/application.doctree | Bin 0 -> 54173 bytes old_docs/_build/doctrees/asab/config.doctree | Bin 0 -> 32587 bytes old_docs/_build/doctrees/asab/index.doctree | Bin 0 -> 8814 bytes old_docs/_build/doctrees/asab/library.doctree | Bin 0 -> 94946 bytes old_docs/_build/doctrees/asab/log.doctree | Bin 0 -> 86139 bytes old_docs/_build/doctrees/asab/metrics.doctree | Bin 0 -> 161386 bytes old_docs/_build/doctrees/asab/module.doctree | Bin 0 -> 10705 bytes old_docs/_build/doctrees/asab/pubsub.doctree | Bin 0 -> 58312 bytes old_docs/_build/doctrees/asab/service.doctree | Bin 0 -> 11799 bytes old_docs/_build/doctrees/asab/storage.doctree | Bin 0 -> 179597 bytes old_docs/_build/doctrees/asab/various.doctree | Bin 0 -> 65371 bytes .../_build/doctrees/asab/web/cors.doctree | Bin 0 -> 4708 bytes .../_build/doctrees/asab/web/index.doctree | Bin 0 -> 21509 bytes .../doctrees/asab/web/restapidocs.doctree | Bin 0 -> 16339 bytes .../_build/doctrees/asab/zookeeper.doctree | Bin 0 -> 40038 bytes old_docs/_build/doctrees/environment.pickle | Bin 0 -> 1627983 bytes old_docs/_build/doctrees/get-started.doctree | Bin 0 -> 14516 bytes old_docs/_build/doctrees/index.doctree | Bin 0 -> 12410 bytes .../doctrees/tutorial/web/chapter1.doctree | Bin 0 -> 17854 bytes .../doctrees/tutorial/web/chapter2.doctree | Bin 0 -> 58108 bytes old_docs/_build/html/.buildinfo | 4 + .../html/.doctrees/admin/command-line.doctree | Bin 0 -> 14162 bytes .../html/.doctrees/admin/containers.doctree | Bin 0 -> 14810 bytes .../html/.doctrees/admin/install.doctree | Bin 0 -> 5195 bytes .../html/.doctrees/admin/systemd.doctree | Bin 0 -> 6718 bytes .../_build/html/.doctrees/asab/alert.doctree | Bin 0 -> 12257 bytes .../html/.doctrees/asab/application.doctree | Bin 0 -> 54173 bytes .../_build/html/.doctrees/asab/config.doctree | Bin 0 -> 32587 bytes .../_build/html/.doctrees/asab/index.doctree | Bin 0 -> 8814 bytes .../html/.doctrees/asab/library.doctree | Bin 0 -> 85615 bytes .../_build/html/.doctrees/asab/log.doctree | Bin 0 -> 86139 bytes .../html/.doctrees/asab/metrics.doctree | Bin 0 -> 137737 bytes .../_build/html/.doctrees/asab/module.doctree | Bin 0 -> 10705 bytes .../_build/html/.doctrees/asab/pubsub.doctree | Bin 0 -> 56316 bytes .../html/.doctrees/asab/service.doctree | Bin 0 -> 11799 bytes .../html/.doctrees/asab/storage.doctree | Bin 0 -> 178410 bytes .../html/.doctrees/asab/various.doctree | Bin 0 -> 65371 bytes .../html/.doctrees/asab/web/authn.doctree | Bin 0 -> 15013 bytes .../html/.doctrees/asab/web/cors.doctree | Bin 0 -> 4708 bytes .../html/.doctrees/asab/web/index.doctree | Bin 0 -> 21509 bytes .../.doctrees/asab/web/restapidocs.doctree | Bin 0 -> 12295 bytes .../html/.doctrees/asab/zookeeper.doctree | Bin 0 -> 35104 bytes .../_build/html/.doctrees/environment.pickle | Bin 0 -> 1576019 bytes .../_build/html/.doctrees/get-started.doctree | Bin 0 -> 14516 bytes old_docs/_build/html/.doctrees/index.doctree | Bin 0 -> 12443 bytes .../.doctrees/tutorial/web/chapter1.doctree | Bin 0 -> 17854 bytes .../.doctrees/tutorial/web/chapter2.doctree | Bin 0 -> 58108 bytes .../_build/html/_modules/asab/abc/module.html | 148 +++ .../html/_modules/asab/abc/service.html | 150 +++ .../html/_modules/asab/abc/singleton.html | 155 +++ .../html/_modules/asab/application.html | 823 ++++++++++++++ .../_build/html/_modules/asab/config.html | 519 +++++++++ .../asab/library/providers/azurestorage.html | 368 ++++++ .../asab/library/providers/filesystem.html | 330 ++++++ .../_modules/asab/library/providers/git.html | 331 ++++++ .../asab/library/providers/zookeeper.html | 427 +++++++ .../html/_modules/asab/library/service.html | 532 +++++++++ old_docs/_build/html/_modules/asab/log.html | 603 ++++++++++ .../html/_modules/asab/metrics/metrics.html | 688 +++++++++++ .../html/_modules/asab/metrics/service.html | 299 +++++ old_docs/_build/html/_modules/asab/pdict.html | 199 ++++ .../_build/html/_modules/asab/pubsub.html | 386 +++++++ .../_build/html/_modules/asab/socket.html | 171 +++ .../_modules/asab/storage/elasticsearch.html | 649 +++++++++++ .../html/_modules/asab/storage/inmemory.html | 285 +++++ .../html/_modules/asab/storage/mongodb.html | 340 ++++++ .../html/_modules/asab/storage/service.html | 335 ++++++ .../html/_modules/asab/storage/upsertor.html | 301 +++++ old_docs/_build/html/_modules/asab/timer.html | 215 ++++ .../html/_modules/asab/web/service.html | 196 ++++ .../_modules/asab/zookeeper/container.html | 361 ++++++ old_docs/_build/html/_modules/index.html | 152 +++ .../html/_sources/admin/command-line.rst.txt | 0 .../html/_sources/admin/containers.rst.txt | 0 .../html/_sources/admin/install.rst.txt | 0 .../html/_sources/admin/systemd.rst.txt | 0 .../_build/html/_sources/asab/alert.rst.txt | 0 .../html/_sources/asab/application.rst.txt | 0 .../_build/html/_sources/asab/config.rst.txt | 0 .../_build/html/_sources/asab/index.rst.txt | 0 .../_build/html/_sources/asab/library.rst.txt | 206 ++++ .../_build/html/_sources/asab/log.rst.txt | 0 .../_build/html/_sources/asab/metrics.rst.txt | 425 +++++++ .../_build/html/_sources/asab/module.rst.txt | 0 .../_build/html/_sources/asab/pubsub.rst.txt | 225 ++++ .../_build/html/_sources/asab/service.rst.txt | 0 .../_build/html/_sources/asab/storage.rst.txt | 0 .../_build/html/_sources/asab/various.rst.txt | 0 .../html/_sources/asab/web/authn.rst.txt | 75 ++ .../html/_sources/asab/web/cors.rst.txt | 0 .../html/_sources/asab/web/index.rst.txt | 0 .../_sources/asab/web/restapidocs.rst.txt | 0 .../html/_sources/asab/zookeeper.rst.txt | 0 .../_build/html/_sources/get-started.rst.txt | 0 old_docs/_build/html/_sources/index.rst.txt | 54 + .../_sources/tutorial/web/chapter1.rst.txt | 0 .../_sources/tutorial/web/chapter2.rst.txt | 0 old_docs/_build/html/_static/alabaster.css | 703 ++++++++++++ .../html}/_static/asab-architecture.png | Bin old_docs/_build/html/_static/basic.css | 903 +++++++++++++++ old_docs/_build/html/_static/custom.css | 1 + old_docs/_build/html/_static/doctools.js | 156 +++ .../html/_static/documentation_options.js | 14 + old_docs/_build/html/_static/file.png | Bin 0 -> 286 bytes old_docs/_build/html/_static/language_data.js | 199 ++++ old_docs/_build/html/_static/minus.png | Bin 0 -> 90 bytes old_docs/_build/html/_static/plus.png | Bin 0 -> 90 bytes old_docs/_build/html/_static/pygments.css | 74 ++ old_docs/_build/html/_static/searchtools.js | 566 ++++++++++ .../_build/html/_static/sphinx_highlight.js | 144 +++ old_docs/_build/html/admin/command-line.html | 209 ++++ old_docs/_build/html/admin/containers.html | 234 ++++ old_docs/_build/html/admin/install.html | 165 +++ old_docs/_build/html/admin/systemd.html | 172 +++ old_docs/_build/html/asab/alert.html | 211 ++++ old_docs/_build/html/asab/application.html | 372 ++++++ old_docs/_build/html/asab/config.html | 353 ++++++ old_docs/_build/html/asab/index.html | 170 +++ old_docs/_build/html/asab/library.html | 501 ++++++++ old_docs/_build/html/asab/log.html | 454 ++++++++ old_docs/_build/html/asab/metrics.html | 718 ++++++++++++ old_docs/_build/html/asab/module.html | 200 ++++ old_docs/_build/html/asab/pubsub.html | 431 +++++++ old_docs/_build/html/asab/service.html | 206 ++++ old_docs/_build/html/asab/storage.html | 741 ++++++++++++ old_docs/_build/html/asab/various.html | 358 ++++++ old_docs/_build/html/asab/web/authn.html | 200 ++++ old_docs/_build/html/asab/web/cors.html | 152 +++ old_docs/_build/html/asab/web/index.html | 288 +++++ .../_build/html/asab/web/restapidocs.html | 240 ++++ old_docs/_build/html/asab/zookeeper.html | 308 +++++ old_docs/_build/html/genindex.html | 1006 +++++++++++++++++ old_docs/_build/html/get-started.html | 215 ++++ old_docs/_build/html/index.html | 354 ++++++ old_docs/_build/html/objects.inv | Bin 0 -> 2477 bytes old_docs/_build/html/py-modindex.html | 178 +++ old_docs/_build/html/search.html | 152 +++ old_docs/_build/html/searchindex.js | 1 + .../_build/html/tutorial/web/chapter1.html | 213 ++++ .../_build/html/tutorial/web/chapter2.html | 673 +++++++++++ old_docs/_build/htmln/.buildinfo | 4 + .../.doctrees/admin/command-line.doctree | Bin 0 -> 14162 bytes .../htmln/.doctrees/admin/containers.doctree | Bin 0 -> 14810 bytes .../htmln/.doctrees/admin/install.doctree | Bin 0 -> 5195 bytes .../htmln/.doctrees/admin/systemd.doctree | Bin 0 -> 6718 bytes .../_build/htmln/.doctrees/asab/alert.doctree | Bin 0 -> 12257 bytes .../htmln/.doctrees/asab/application.doctree | Bin 0 -> 54173 bytes .../htmln/.doctrees/asab/config.doctree | Bin 0 -> 32587 bytes .../_build/htmln/.doctrees/asab/index.doctree | Bin 0 -> 8814 bytes .../htmln/.doctrees/asab/library.doctree | Bin 0 -> 85615 bytes .../_build/htmln/.doctrees/asab/log.doctree | Bin 0 -> 86139 bytes .../htmln/.doctrees/asab/metrics.doctree | Bin 0 -> 137737 bytes .../htmln/.doctrees/asab/module.doctree | Bin 0 -> 10705 bytes .../htmln/.doctrees/asab/pubsub.doctree | Bin 0 -> 56316 bytes .../htmln/.doctrees/asab/service.doctree | Bin 0 -> 11799 bytes .../htmln/.doctrees/asab/storage.doctree | Bin 0 -> 39711 bytes .../htmln/.doctrees/asab/various.doctree | Bin 0 -> 65371 bytes .../htmln/.doctrees/asab/web/authn.doctree | Bin 0 -> 15013 bytes .../htmln/.doctrees/asab/web/cors.doctree | Bin 0 -> 4708 bytes .../htmln/.doctrees/asab/web/index.doctree | Bin 0 -> 21509 bytes .../.doctrees/asab/web/restapidocs.doctree | Bin 0 -> 12295 bytes .../htmln/.doctrees/asab/zookeeper.doctree | Bin 0 -> 35104 bytes .../_build/htmln/.doctrees/environment.pickle | Bin 0 -> 1333481 bytes .../htmln/.doctrees/get-started.doctree | Bin 0 -> 14516 bytes old_docs/_build/htmln/.doctrees/index.doctree | Bin 0 -> 12435 bytes .../.doctrees/tutorial/web/chapter1.doctree | Bin 0 -> 17854 bytes .../.doctrees/tutorial/web/chapter2.doctree | Bin 0 -> 58108 bytes .../htmln/_modules/asab/abc/module.html | 149 +++ .../htmln/_modules/asab/abc/service.html | 151 +++ .../htmln/_modules/asab/abc/singleton.html | 156 +++ .../htmln/_modules/asab/application.html | 750 ++++++++++++ .../_build/htmln/_modules/asab/config.html | 519 +++++++++ .../asab/library/providers/azurestorage.html | 369 ++++++ .../asab/library/providers/filesystem.html | 326 ++++++ .../_modules/asab/library/providers/git.html | 330 ++++++ .../asab/library/providers/zookeeper.html | 416 +++++++ .../htmln/_modules/asab/library/service.html | 527 +++++++++ old_docs/_build/htmln/_modules/asab/log.html | 605 ++++++++++ .../htmln/_modules/asab/metrics/metrics.html | 656 +++++++++++ .../htmln/_modules/asab/metrics/service.html | 290 +++++ .../_build/htmln/_modules/asab/pdict.html | 200 ++++ .../_build/htmln/_modules/asab/pubsub.html | 359 ++++++ .../_build/htmln/_modules/asab/socket.html | 172 +++ .../_build/htmln/_modules/asab/timer.html | 216 ++++ .../htmln/_modules/asab/web/service.html | 197 ++++ .../_modules/asab/zookeeper/container.html | 346 ++++++ old_docs/_build/htmln/_modules/index.html | 148 +++ .../htmln/_sources/admin/command-line.rst.txt | 66 ++ .../htmln/_sources/admin/containers.rst.txt | 121 ++ .../htmln/_sources/admin/install.rst.txt | 37 + .../htmln/_sources/admin/systemd.rst.txt | 45 + .../_build/htmln/_sources/asab/alert.rst.txt | 81 ++ .../htmln/_sources/asab/application.rst.txt | 239 ++++ .../_build/htmln/_sources/asab/config.rst.txt | 251 ++++ .../_build/htmln/_sources/asab/index.rst.txt | 43 + .../htmln/_sources/asab/library.rst.txt | 159 +++ .../_build/htmln/_sources/asab/log.rst.txt | 232 ++++ .../htmln/_sources/asab/metrics.rst.txt | 347 ++++++ .../_build/htmln/_sources/asab/module.rst.txt | 65 ++ .../_build/htmln/_sources/asab/pubsub.rst.txt | 218 ++++ .../htmln/_sources/asab/service.rst.txt | 72 ++ .../htmln/_sources/asab/storage.rst.txt | 227 ++++ .../htmln/_sources/asab/various.rst.txt | 60 + .../htmln/_sources/asab/web/authn.rst.txt | 75 ++ .../htmln/_sources/asab/web/cors.rst.txt | 21 + .../htmln/_sources/asab/web/index.rst.txt | 163 +++ .../_sources/asab/web/restapidocs.rst.txt | 93 ++ .../htmln/_sources/asab/zookeeper.rst.txt | 154 +++ .../_build/htmln/_sources/get-started.rst.txt | 107 ++ old_docs/_build/htmln/_sources/index.rst.txt | 54 + .../_sources/tutorial/web/chapter1.rst.txt | 69 ++ .../_sources/tutorial/web/chapter2.rst.txt | 629 +++++++++++ old_docs/_build/htmln/_static/alabaster.css | 703 ++++++++++++ .../htmln/_static/asab-architecture.png | Bin 0 -> 39024 bytes old_docs/_build/htmln/_static/basic.css | 903 +++++++++++++++ old_docs/_build/htmln/_static/custom.css | 1 + old_docs/_build/htmln/_static/doctools.js | 156 +++ .../htmln/_static/documentation_options.js | 14 + old_docs/_build/htmln/_static/file.png | Bin 0 -> 286 bytes .../_build/htmln/_static/language_data.js | 199 ++++ old_docs/_build/htmln/_static/minus.png | Bin 0 -> 90 bytes old_docs/_build/htmln/_static/plus.png | Bin 0 -> 90 bytes old_docs/_build/htmln/_static/pygments.css | 74 ++ old_docs/_build/htmln/_static/searchtools.js | 566 ++++++++++ .../_build/htmln/_static/sphinx_highlight.js | 144 +++ old_docs/_build/htmln/admin/command-line.html | 210 ++++ old_docs/_build/htmln/admin/containers.html | 235 ++++ old_docs/_build/htmln/admin/install.html | 166 +++ old_docs/_build/htmln/admin/systemd.html | 173 +++ old_docs/_build/htmln/asab/alert.html | 212 ++++ old_docs/_build/htmln/asab/application.html | 373 ++++++ old_docs/_build/htmln/asab/config.html | 354 ++++++ old_docs/_build/htmln/asab/index.html | 171 +++ old_docs/_build/htmln/asab/library.html | 456 ++++++++ old_docs/_build/htmln/asab/log.html | 455 ++++++++ old_docs/_build/htmln/asab/metrics.html | 565 +++++++++ old_docs/_build/htmln/asab/module.html | 201 ++++ old_docs/_build/htmln/asab/pubsub.html | 427 +++++++ old_docs/_build/htmln/asab/service.html | 207 ++++ old_docs/_build/htmln/asab/storage.html | 313 +++++ old_docs/_build/htmln/asab/various.html | 359 ++++++ old_docs/_build/htmln/asab/web/authn.html | 201 ++++ old_docs/_build/htmln/asab/web/cors.html | 153 +++ old_docs/_build/htmln/asab/web/index.html | 289 +++++ .../_build/htmln/asab/web/restapidocs.html | 217 ++++ old_docs/_build/htmln/asab/zookeeper.html | 284 +++++ old_docs/_build/htmln/genindex.html | 908 +++++++++++++++ old_docs/_build/htmln/get-started.html | 216 ++++ old_docs/_build/htmln/index.html | 357 ++++++ old_docs/_build/htmln/objects.inv | Bin 0 -> 2225 bytes old_docs/_build/htmln/py-modindex.html | 179 +++ old_docs/_build/htmln/search.html | 153 +++ old_docs/_build/htmln/searchindex.js | 1 + .../_build/htmln/tutorial/web/chapter1.html | 214 ++++ .../_build/htmln/tutorial/web/chapter2.html | 674 +++++++++++ old_docs/_static/asab-architecture.png | Bin 0 -> 39024 bytes old_docs/admin/command-line.rst | 66 ++ old_docs/admin/containers.rst | 121 ++ old_docs/admin/install.rst | 37 + old_docs/admin/systemd.rst | 45 + {doc => old_docs}/asab-openrc | 0 {doc => old_docs}/asab.service | 0 old_docs/asab/alert.rst | 81 ++ old_docs/asab/application.rst | 239 ++++ old_docs/asab/config.rst | 251 ++++ old_docs/asab/index.rst | 43 + {doc => old_docs}/asab/library.rst | 0 old_docs/asab/log.rst | 232 ++++ {doc => old_docs}/asab/metrics.rst | 0 old_docs/asab/module.rst | 65 ++ {doc => old_docs}/asab/pubsub.rst | 0 old_docs/asab/service.rst | 72 ++ old_docs/asab/storage.rst | 381 +++++++ old_docs/asab/various.rst | 60 + {doc => old_docs}/asab/web/auth.rst | 0 old_docs/asab/web/cors.rst | 21 + old_docs/asab/web/index.rst | 163 +++ old_docs/asab/web/restapidocs.rst | 122 ++ old_docs/asab/zookeeper.rst | 173 +++ {doc => old_docs}/conf.py | 0 old_docs/get-started.rst | 107 ++ {doc => old_docs}/index.rst | 0 {doc => old_docs}/make.bat | 0 {doc => old_docs}/openapi3-swagger.jpg | Bin old_docs/web/chapter1.rst | 69 ++ old_docs/web/chapter2.rst | 629 +++++++++++ {doc/tutorial => old_docs}/web/web1/app.py | 0 .../web/web2/asab.webservice.md | 0 transfer_docs.py | 13 + 322 files changed, 51641 insertions(+) create mode 100644 docs/admin/command-line.md create mode 100644 docs/admin/containers.md create mode 100644 docs/admin/install.md create mode 100644 docs/admin/systemd.md create mode 100644 docs/asab/alert.md create mode 100644 docs/asab/application.md create mode 100644 docs/asab/config.md create mode 100644 docs/asab/index.md create mode 100644 docs/asab/library.md create mode 100644 docs/asab/log.md create mode 100644 docs/asab/metrics.md create mode 100644 docs/asab/module.md create mode 100644 docs/asab/pubsub.md create mode 100644 docs/asab/service.md create mode 100644 docs/asab/storage.md create mode 100644 docs/asab/various.md create mode 100644 docs/asab/web/auth.md create mode 100644 docs/asab/web/cors.md create mode 100644 docs/asab/web/index.md create mode 100644 docs/asab/web/restapidocs.md create mode 100644 docs/asab/zookeeper.md create mode 100644 docs/get-started.md create mode 100644 docs/index.md create mode 100644 docs/tutorial/chapter1.md create mode 100644 docs/tutorial/chapter2.md create mode 100644 mkdocs.yml rename {doc => old_docs}/Makefile (100%) rename {doc => old_docs}/TODO.md (100%) create mode 100644 old_docs/_build/doctrees/admin/command-line.doctree create mode 100644 old_docs/_build/doctrees/admin/containers.doctree create mode 100644 old_docs/_build/doctrees/admin/install.doctree create mode 100644 old_docs/_build/doctrees/admin/systemd.doctree create mode 100644 old_docs/_build/doctrees/asab/alert.doctree create mode 100644 old_docs/_build/doctrees/asab/application.doctree create mode 100644 old_docs/_build/doctrees/asab/config.doctree create mode 100644 old_docs/_build/doctrees/asab/index.doctree create mode 100644 old_docs/_build/doctrees/asab/library.doctree create mode 100644 old_docs/_build/doctrees/asab/log.doctree create mode 100644 old_docs/_build/doctrees/asab/metrics.doctree create mode 100644 old_docs/_build/doctrees/asab/module.doctree create mode 100644 old_docs/_build/doctrees/asab/pubsub.doctree create mode 100644 old_docs/_build/doctrees/asab/service.doctree create mode 100644 old_docs/_build/doctrees/asab/storage.doctree create mode 100644 old_docs/_build/doctrees/asab/various.doctree create mode 100644 old_docs/_build/doctrees/asab/web/cors.doctree create mode 100644 old_docs/_build/doctrees/asab/web/index.doctree create mode 100644 old_docs/_build/doctrees/asab/web/restapidocs.doctree create mode 100644 old_docs/_build/doctrees/asab/zookeeper.doctree create mode 100644 old_docs/_build/doctrees/environment.pickle create mode 100644 old_docs/_build/doctrees/get-started.doctree create mode 100644 old_docs/_build/doctrees/index.doctree create mode 100644 old_docs/_build/doctrees/tutorial/web/chapter1.doctree create mode 100644 old_docs/_build/doctrees/tutorial/web/chapter2.doctree create mode 100644 old_docs/_build/html/.buildinfo create mode 100644 old_docs/_build/html/.doctrees/admin/command-line.doctree create mode 100644 old_docs/_build/html/.doctrees/admin/containers.doctree create mode 100644 old_docs/_build/html/.doctrees/admin/install.doctree create mode 100644 old_docs/_build/html/.doctrees/admin/systemd.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/alert.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/application.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/config.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/index.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/library.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/log.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/metrics.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/module.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/pubsub.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/service.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/storage.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/various.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/web/authn.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/web/cors.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/web/index.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/web/restapidocs.doctree create mode 100644 old_docs/_build/html/.doctrees/asab/zookeeper.doctree create mode 100644 old_docs/_build/html/.doctrees/environment.pickle create mode 100644 old_docs/_build/html/.doctrees/get-started.doctree create mode 100644 old_docs/_build/html/.doctrees/index.doctree create mode 100644 old_docs/_build/html/.doctrees/tutorial/web/chapter1.doctree create mode 100644 old_docs/_build/html/.doctrees/tutorial/web/chapter2.doctree create mode 100644 old_docs/_build/html/_modules/asab/abc/module.html create mode 100644 old_docs/_build/html/_modules/asab/abc/service.html create mode 100644 old_docs/_build/html/_modules/asab/abc/singleton.html create mode 100644 old_docs/_build/html/_modules/asab/application.html create mode 100644 old_docs/_build/html/_modules/asab/config.html create mode 100644 old_docs/_build/html/_modules/asab/library/providers/azurestorage.html create mode 100644 old_docs/_build/html/_modules/asab/library/providers/filesystem.html create mode 100644 old_docs/_build/html/_modules/asab/library/providers/git.html create mode 100644 old_docs/_build/html/_modules/asab/library/providers/zookeeper.html create mode 100644 old_docs/_build/html/_modules/asab/library/service.html create mode 100644 old_docs/_build/html/_modules/asab/log.html create mode 100644 old_docs/_build/html/_modules/asab/metrics/metrics.html create mode 100644 old_docs/_build/html/_modules/asab/metrics/service.html create mode 100644 old_docs/_build/html/_modules/asab/pdict.html create mode 100644 old_docs/_build/html/_modules/asab/pubsub.html create mode 100644 old_docs/_build/html/_modules/asab/socket.html create mode 100644 old_docs/_build/html/_modules/asab/storage/elasticsearch.html create mode 100644 old_docs/_build/html/_modules/asab/storage/inmemory.html create mode 100644 old_docs/_build/html/_modules/asab/storage/mongodb.html create mode 100644 old_docs/_build/html/_modules/asab/storage/service.html create mode 100644 old_docs/_build/html/_modules/asab/storage/upsertor.html create mode 100644 old_docs/_build/html/_modules/asab/timer.html create mode 100644 old_docs/_build/html/_modules/asab/web/service.html create mode 100644 old_docs/_build/html/_modules/asab/zookeeper/container.html create mode 100644 old_docs/_build/html/_modules/index.html rename doc/admin/command-line.rst => old_docs/_build/html/_sources/admin/command-line.rst.txt (100%) rename doc/admin/containers.rst => old_docs/_build/html/_sources/admin/containers.rst.txt (100%) rename doc/admin/install.rst => old_docs/_build/html/_sources/admin/install.rst.txt (100%) rename doc/admin/systemd.rst => old_docs/_build/html/_sources/admin/systemd.rst.txt (100%) rename doc/asab/alert.rst => old_docs/_build/html/_sources/asab/alert.rst.txt (100%) rename doc/asab/application.rst => old_docs/_build/html/_sources/asab/application.rst.txt (100%) rename doc/asab/config.rst => old_docs/_build/html/_sources/asab/config.rst.txt (100%) rename doc/asab/index.rst => old_docs/_build/html/_sources/asab/index.rst.txt (100%) create mode 100644 old_docs/_build/html/_sources/asab/library.rst.txt rename doc/asab/log.rst => old_docs/_build/html/_sources/asab/log.rst.txt (100%) create mode 100644 old_docs/_build/html/_sources/asab/metrics.rst.txt rename doc/asab/module.rst => old_docs/_build/html/_sources/asab/module.rst.txt (100%) create mode 100644 old_docs/_build/html/_sources/asab/pubsub.rst.txt rename doc/asab/service.rst => old_docs/_build/html/_sources/asab/service.rst.txt (100%) rename doc/asab/storage.rst => old_docs/_build/html/_sources/asab/storage.rst.txt (100%) rename doc/asab/various.rst => old_docs/_build/html/_sources/asab/various.rst.txt (100%) create mode 100644 old_docs/_build/html/_sources/asab/web/authn.rst.txt rename doc/asab/web/cors.rst => old_docs/_build/html/_sources/asab/web/cors.rst.txt (100%) rename doc/asab/web/index.rst => old_docs/_build/html/_sources/asab/web/index.rst.txt (100%) rename doc/asab/web/restapidocs.rst => old_docs/_build/html/_sources/asab/web/restapidocs.rst.txt (100%) rename doc/asab/zookeeper.rst => old_docs/_build/html/_sources/asab/zookeeper.rst.txt (100%) rename doc/get-started.rst => old_docs/_build/html/_sources/get-started.rst.txt (100%) create mode 100644 old_docs/_build/html/_sources/index.rst.txt rename doc/tutorial/web/chapter1.rst => old_docs/_build/html/_sources/tutorial/web/chapter1.rst.txt (100%) rename doc/tutorial/web/chapter2.rst => old_docs/_build/html/_sources/tutorial/web/chapter2.rst.txt (100%) create mode 100644 old_docs/_build/html/_static/alabaster.css rename {doc => old_docs/_build/html}/_static/asab-architecture.png (100%) create mode 100644 old_docs/_build/html/_static/basic.css create mode 100644 old_docs/_build/html/_static/custom.css create mode 100644 old_docs/_build/html/_static/doctools.js create mode 100644 old_docs/_build/html/_static/documentation_options.js create mode 100644 old_docs/_build/html/_static/file.png create mode 100644 old_docs/_build/html/_static/language_data.js create mode 100644 old_docs/_build/html/_static/minus.png create mode 100644 old_docs/_build/html/_static/plus.png create mode 100644 old_docs/_build/html/_static/pygments.css create mode 100644 old_docs/_build/html/_static/searchtools.js create mode 100644 old_docs/_build/html/_static/sphinx_highlight.js create mode 100644 old_docs/_build/html/admin/command-line.html create mode 100644 old_docs/_build/html/admin/containers.html create mode 100644 old_docs/_build/html/admin/install.html create mode 100644 old_docs/_build/html/admin/systemd.html create mode 100644 old_docs/_build/html/asab/alert.html create mode 100644 old_docs/_build/html/asab/application.html create mode 100644 old_docs/_build/html/asab/config.html create mode 100644 old_docs/_build/html/asab/index.html create mode 100644 old_docs/_build/html/asab/library.html create mode 100644 old_docs/_build/html/asab/log.html create mode 100644 old_docs/_build/html/asab/metrics.html create mode 100644 old_docs/_build/html/asab/module.html create mode 100644 old_docs/_build/html/asab/pubsub.html create mode 100644 old_docs/_build/html/asab/service.html create mode 100644 old_docs/_build/html/asab/storage.html create mode 100644 old_docs/_build/html/asab/various.html create mode 100644 old_docs/_build/html/asab/web/authn.html create mode 100644 old_docs/_build/html/asab/web/cors.html create mode 100644 old_docs/_build/html/asab/web/index.html create mode 100644 old_docs/_build/html/asab/web/restapidocs.html create mode 100644 old_docs/_build/html/asab/zookeeper.html create mode 100644 old_docs/_build/html/genindex.html create mode 100644 old_docs/_build/html/get-started.html create mode 100644 old_docs/_build/html/index.html create mode 100644 old_docs/_build/html/objects.inv create mode 100644 old_docs/_build/html/py-modindex.html create mode 100644 old_docs/_build/html/search.html create mode 100644 old_docs/_build/html/searchindex.js create mode 100644 old_docs/_build/html/tutorial/web/chapter1.html create mode 100644 old_docs/_build/html/tutorial/web/chapter2.html create mode 100644 old_docs/_build/htmln/.buildinfo create mode 100644 old_docs/_build/htmln/.doctrees/admin/command-line.doctree create mode 100644 old_docs/_build/htmln/.doctrees/admin/containers.doctree create mode 100644 old_docs/_build/htmln/.doctrees/admin/install.doctree create mode 100644 old_docs/_build/htmln/.doctrees/admin/systemd.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/alert.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/application.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/config.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/index.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/library.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/log.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/metrics.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/module.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/pubsub.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/service.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/storage.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/various.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/web/authn.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/web/cors.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/web/index.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/web/restapidocs.doctree create mode 100644 old_docs/_build/htmln/.doctrees/asab/zookeeper.doctree create mode 100644 old_docs/_build/htmln/.doctrees/environment.pickle create mode 100644 old_docs/_build/htmln/.doctrees/get-started.doctree create mode 100644 old_docs/_build/htmln/.doctrees/index.doctree create mode 100644 old_docs/_build/htmln/.doctrees/tutorial/web/chapter1.doctree create mode 100644 old_docs/_build/htmln/.doctrees/tutorial/web/chapter2.doctree create mode 100644 old_docs/_build/htmln/_modules/asab/abc/module.html create mode 100644 old_docs/_build/htmln/_modules/asab/abc/service.html create mode 100644 old_docs/_build/htmln/_modules/asab/abc/singleton.html create mode 100644 old_docs/_build/htmln/_modules/asab/application.html create mode 100644 old_docs/_build/htmln/_modules/asab/config.html create mode 100644 old_docs/_build/htmln/_modules/asab/library/providers/azurestorage.html create mode 100644 old_docs/_build/htmln/_modules/asab/library/providers/filesystem.html create mode 100644 old_docs/_build/htmln/_modules/asab/library/providers/git.html create mode 100644 old_docs/_build/htmln/_modules/asab/library/providers/zookeeper.html create mode 100644 old_docs/_build/htmln/_modules/asab/library/service.html create mode 100644 old_docs/_build/htmln/_modules/asab/log.html create mode 100644 old_docs/_build/htmln/_modules/asab/metrics/metrics.html create mode 100644 old_docs/_build/htmln/_modules/asab/metrics/service.html create mode 100644 old_docs/_build/htmln/_modules/asab/pdict.html create mode 100644 old_docs/_build/htmln/_modules/asab/pubsub.html create mode 100644 old_docs/_build/htmln/_modules/asab/socket.html create mode 100644 old_docs/_build/htmln/_modules/asab/timer.html create mode 100644 old_docs/_build/htmln/_modules/asab/web/service.html create mode 100644 old_docs/_build/htmln/_modules/asab/zookeeper/container.html create mode 100644 old_docs/_build/htmln/_modules/index.html create mode 100644 old_docs/_build/htmln/_sources/admin/command-line.rst.txt create mode 100644 old_docs/_build/htmln/_sources/admin/containers.rst.txt create mode 100644 old_docs/_build/htmln/_sources/admin/install.rst.txt create mode 100644 old_docs/_build/htmln/_sources/admin/systemd.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/alert.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/application.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/config.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/index.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/library.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/log.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/metrics.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/module.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/pubsub.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/service.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/storage.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/various.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/web/authn.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/web/cors.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/web/index.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/web/restapidocs.rst.txt create mode 100644 old_docs/_build/htmln/_sources/asab/zookeeper.rst.txt create mode 100644 old_docs/_build/htmln/_sources/get-started.rst.txt create mode 100644 old_docs/_build/htmln/_sources/index.rst.txt create mode 100644 old_docs/_build/htmln/_sources/tutorial/web/chapter1.rst.txt create mode 100644 old_docs/_build/htmln/_sources/tutorial/web/chapter2.rst.txt create mode 100644 old_docs/_build/htmln/_static/alabaster.css create mode 100644 old_docs/_build/htmln/_static/asab-architecture.png create mode 100644 old_docs/_build/htmln/_static/basic.css create mode 100644 old_docs/_build/htmln/_static/custom.css create mode 100644 old_docs/_build/htmln/_static/doctools.js create mode 100644 old_docs/_build/htmln/_static/documentation_options.js create mode 100644 old_docs/_build/htmln/_static/file.png create mode 100644 old_docs/_build/htmln/_static/language_data.js create mode 100644 old_docs/_build/htmln/_static/minus.png create mode 100644 old_docs/_build/htmln/_static/plus.png create mode 100644 old_docs/_build/htmln/_static/pygments.css create mode 100644 old_docs/_build/htmln/_static/searchtools.js create mode 100644 old_docs/_build/htmln/_static/sphinx_highlight.js create mode 100644 old_docs/_build/htmln/admin/command-line.html create mode 100644 old_docs/_build/htmln/admin/containers.html create mode 100644 old_docs/_build/htmln/admin/install.html create mode 100644 old_docs/_build/htmln/admin/systemd.html create mode 100644 old_docs/_build/htmln/asab/alert.html create mode 100644 old_docs/_build/htmln/asab/application.html create mode 100644 old_docs/_build/htmln/asab/config.html create mode 100644 old_docs/_build/htmln/asab/index.html create mode 100644 old_docs/_build/htmln/asab/library.html create mode 100644 old_docs/_build/htmln/asab/log.html create mode 100644 old_docs/_build/htmln/asab/metrics.html create mode 100644 old_docs/_build/htmln/asab/module.html create mode 100644 old_docs/_build/htmln/asab/pubsub.html create mode 100644 old_docs/_build/htmln/asab/service.html create mode 100644 old_docs/_build/htmln/asab/storage.html create mode 100644 old_docs/_build/htmln/asab/various.html create mode 100644 old_docs/_build/htmln/asab/web/authn.html create mode 100644 old_docs/_build/htmln/asab/web/cors.html create mode 100644 old_docs/_build/htmln/asab/web/index.html create mode 100644 old_docs/_build/htmln/asab/web/restapidocs.html create mode 100644 old_docs/_build/htmln/asab/zookeeper.html create mode 100644 old_docs/_build/htmln/genindex.html create mode 100644 old_docs/_build/htmln/get-started.html create mode 100644 old_docs/_build/htmln/index.html create mode 100644 old_docs/_build/htmln/objects.inv create mode 100644 old_docs/_build/htmln/py-modindex.html create mode 100644 old_docs/_build/htmln/search.html create mode 100644 old_docs/_build/htmln/searchindex.js create mode 100644 old_docs/_build/htmln/tutorial/web/chapter1.html create mode 100644 old_docs/_build/htmln/tutorial/web/chapter2.html create mode 100644 old_docs/_static/asab-architecture.png create mode 100644 old_docs/admin/command-line.rst create mode 100644 old_docs/admin/containers.rst create mode 100644 old_docs/admin/install.rst create mode 100644 old_docs/admin/systemd.rst rename {doc => old_docs}/asab-openrc (100%) rename {doc => old_docs}/asab.service (100%) create mode 100644 old_docs/asab/alert.rst create mode 100644 old_docs/asab/application.rst create mode 100644 old_docs/asab/config.rst create mode 100644 old_docs/asab/index.rst rename {doc => old_docs}/asab/library.rst (100%) create mode 100644 old_docs/asab/log.rst rename {doc => old_docs}/asab/metrics.rst (100%) create mode 100644 old_docs/asab/module.rst rename {doc => old_docs}/asab/pubsub.rst (100%) create mode 100644 old_docs/asab/service.rst create mode 100644 old_docs/asab/storage.rst create mode 100644 old_docs/asab/various.rst rename {doc => old_docs}/asab/web/auth.rst (100%) create mode 100644 old_docs/asab/web/cors.rst create mode 100644 old_docs/asab/web/index.rst create mode 100644 old_docs/asab/web/restapidocs.rst create mode 100644 old_docs/asab/zookeeper.rst rename {doc => old_docs}/conf.py (100%) create mode 100644 old_docs/get-started.rst rename {doc => old_docs}/index.rst (100%) rename {doc => old_docs}/make.bat (100%) rename {doc => old_docs}/openapi3-swagger.jpg (100%) create mode 100644 old_docs/web/chapter1.rst create mode 100644 old_docs/web/chapter2.rst rename {doc/tutorial => old_docs}/web/web1/app.py (100%) rename {doc/tutorial => old_docs}/web/web2/asab.webservice.md (100%) create mode 100644 transfer_docs.py diff --git a/docs/admin/command-line.md b/docs/admin/command-line.md new file mode 100644 index 000000000..1f8b3b946 --- /dev/null +++ b/docs/admin/command-line.md @@ -0,0 +1,76 @@ +ASAB Command-line interface +=========================== + +ASAB-based application provides the command-line interface by default. +Here is an overview of the common command-line arguments. + +%TODO: option% +-h , \--help +xxx + +Show a help. + +Configuration +------------- + +%TODO: option% +-c \,\--config \ +xxx + +Load configuration file from a file CONFIG. + +Logging +------- + +%TODO: option% +-v , \--verbose +xxx + +Increase the logging level to DEBUG aka be more verbose about what is +happening. + +%TODO: option% +-l \,\--log-file \ +xxx + +Log to a file LOG\_FILE. + +%TODO: option% +-s , \--syslog +xxx + +Log to a syslog. + +Daemon +------ + +Python module :py`python-daemon`{.interpreted-text role="mod"} has to be +installed in order to support daemonosation functions. + +``` {.bash} +$ pip3 install asab python-daemon +``` + +%TODO: option% +-d , \--daemonize +xxx + +Launch the application in the background aka daemonized. + +Daemon-related section of `Config`{.interpreted-text role="any"} file: + + [daemon] + pidfile=/var/run/myapp.pid + uid=nobody + gid=nobody + working_dir=/tmp + +Configuration options `pidfile`, `uid` , `gid` and `working_dir` are +supported. + +%TODO: option% +-k , \--kill +xxx + +Shutdown the application running in the background (started previously +with `-d` argument). diff --git a/docs/admin/containers.md b/docs/admin/containers.md new file mode 100644 index 000000000..40039a755 --- /dev/null +++ b/docs/admin/containers.md @@ -0,0 +1,112 @@ +Containerisation +================ + +ASAB is designed for deployment into containers such as LXC/LXD or +Docker. It allows to build e.g. microservices that provides REST +interface or consume MQ messages while being deployed into a container +for a sake of the infrastructure flexibility. + +ASAB in a LXC/LXD container +--------------------------- + +1. Prepare LXC/LXD container based on Alpine Linux + +``` {.bash} +$ lxc launch images:alpine/3.10 asab +``` + +2. Swich into a container + +``` {.bash} +$ lxc exec asab -- /bin/ash +``` + +3. Prepare Python3 environment + +``` {.bash} +$ apk update +$ apk upgrade +$ apk add --no-cache python3 + +$ python3 -m ensurepip +``` + +4. Deploy ASAB + +``` {.bash} +$ apk add --virtual .buildenv python3-dev gcc musl-dev git +$ pip3 install git+https://github.com/TeskaLabs/asab +$ apk del .buildenv +``` + +5. Deploy dependencies + +``` {.bash} +$ pip3 install python-daemon +``` + +7. Use OpenRC to automatically start/stop ASAB application + +``` {.bash} +$ vi /etc/init.d/asab-app +``` + +Adjust the example of [OpenRC init +file](https://github.com/TeskaLabs/asab/blob/master/doc/asab-openrc). + +``` {.bash} +$ chmod a+x /etc/init.d/asab-app +$ rc-update add asab-app +``` + +*Note*: If you need to install python packages that require compilation +using C compiler, you have to add following dependencies: + +``` {.bash} +$ apk add --virtual .buildenv python3-dev +$ apk add --virtual .buildenv gcc +$ apk add --virtual .buildenv musl-dev +``` + +And removal of the build tools after pip install: + +``` {.bash} +$ apk del .buildenv +``` + +Docker Remote API +----------------- + +In order for ASAB applications to read the Docker container name as well +as other information related to the container to be used in logs, +metrics and other analysis, the Docker Remote API must be enabled. + +To do so: + +1. Open the docker service file + +``` {.bash} +vi /lib/systemd/system/docker.service +``` + +2. Find the line which starts with ExecStart and add + [-H=tcp://0.0.0.0:2375]{.title-ref} +3. Save the file +4. Reload the docker daemon and restart the Docker service + +``` {.bash} +sudo systemctl daemon-reload && sudo service docker restart +``` + +Then in the ASAB application\'s configuration, provide the Docker Socket +path in [docker\_socket]{.title-ref} configuration option: + +``` {.bash} +[general] +docker_socket= +``` + +Thus, the metric service as well as log manager can use the container +name as hostname instead of container ID, which provides better +readability when analyzing the logs and metrics, typically using +InfluxDB and Grafana. diff --git a/docs/admin/install.md b/docs/admin/install.md new file mode 100644 index 000000000..1b2ee91a4 --- /dev/null +++ b/docs/admin/install.md @@ -0,0 +1,33 @@ +Installation +============ + +ASAB is distributed via [pypi](https://pypi.org/project/asab/). + +Install ASAB using pip +---------------------- + +This is the recommended installation method. + +``` {.bash} +$ pip install asab +``` + +Install ASAB using easy\_install +-------------------------------- + +``` {.bash} +$ easy_install asab +``` + +Install ASAB for a GitHub +------------------------- + +To install ASAB from a master branch of the GIT repository, use +following command. + +*Note*: Git has to be installed in order to successfuly complete the +installation. + +``` {.bash} +$ pip install git+https://github.com/TeskaLabs/asab.git +``` diff --git a/docs/admin/systemd.md b/docs/admin/systemd.md new file mode 100644 index 000000000..ba6c71961 --- /dev/null +++ b/docs/admin/systemd.md @@ -0,0 +1,39 @@ +systemd +======= + +1. Create a new Systemd unit file in /etc/systemd/system/: + +``` {.bash} +$ sudo vi /etc/systemd/system/asab.service +``` + +Adjust the example of [SystemD unit +file](https://github.com/TeskaLabs/asab/blob/master/doc/asab.service). + +2. Let systemd know that there is a new service: + +``` {.bash} +$ sudo systemctl enable asab +``` + +To reload existing unit file after changing, use this: + +``` {.bash} +$ sudo systemctl daemon-reload +``` + +3. ASAB Application Server service for systemd is now ready. + +Start of ASAB Server +-------------------- + +``` {.bash} +$ sudo service asab start +``` + +Stop of ASAB Server +------------------- + +``` {.bash} +$ sudo service asab stop +``` diff --git a/docs/asab/alert.md b/docs/asab/alert.md new file mode 100644 index 000000000..c2372b575 --- /dev/null +++ b/docs/asab/alert.md @@ -0,0 +1,83 @@ +Alert Service +============= + +Integrate ASAB Application with alert managers. + +There are currently two possible target systems for the alerts +available: + +- Opsgenie - +- PagerDuty - + +Everything you need to do is to import the service, trigger the alert +and specify the target in the **configuration**. + +``` {.python} +class MyApplication(asab.Application): + async def initialize(self): + from asab.alert import AlertService + self.AlertService = AlertService(self) + self.AlertService.trigger( + source="my-tenant", + alert_cls="my-class", + alert_id="deduplication-id01", + title="Something went wrong.", + detail={ + "example1": "additional-info", + "example2": "additional-info", + }, + ) + +if __name__ == '__main__': + app = MyApplication() + app.run() +``` + +Opsgenie +-------- + +- Create an account at Opsgenie. +- In your Opsgenie account, create a new **Team**. +- Add integration to your Team - choose **API**. +- API Key will be generated for you. + +*myapplication.conf* + +``` {.} +[asab:alert:opsgenie] +api_key=my-api-key +tags=my-tag, my-application +url=https://api.eu.opsgenie.com # this is default value +``` + +PagerDuty +--------- + +- Create an account at PagerDuty. +- In your PagerDuty account, generate **Api Key** (Integrations \> + Developer Tools \> Api Access Keys). +- Create a new Service in Service Directory and add integration in the + Integrations folder. +- Choose **Events API V2**. An **Integration Key** will be generated + for you. + +*myapplication.conf* + +``` {.} +[asab:alert:pagerduty] +api_key=my-api-key +integration_key=my-integration-key +url=https://events.pagerduty.com # this is default value +``` + +De-duplication +-------------- + +[alert\_id]{.title-ref} argument serves as a de-duplication ID for the +third-party services. It enables the grouping of alerts and prevents +noise. More about alert grouping: + +- Opsgenie: + +- PagerDuty: + diff --git a/docs/asab/application.md b/docs/asab/application.md new file mode 100644 index 000000000..f85abcffc --- /dev/null +++ b/docs/asab/application.md @@ -0,0 +1,204 @@ +Application +=========== + +The :py`Application`{.interpreted-text role="class"} class maintains the +global application state. You can provide your own implementation by +creating a subclass. There should be only one +:py`Application`{.interpreted-text role="class"} object in the process. + +Subclassing: + +``` {.python} +import asab + +class MyApplication(asab.Application): + pass + +if __name__ == '__main__': + app = MyApplication() + app.run() +``` + +Direct use of :py`Application`{.interpreted-text role="class"} object: + +``` {.python} +import asab + +if __name__ == '__main__': + app = asab.Application() + app.run() +``` + +Event Loop +---------- + +The :py`asyncio`{.interpreted-text role="mod"} event loop that is used +by this application. + +``` {.python} +asyncio.ensure_future(my_coro()) +``` + +Application Lifecycle +--------------------- + +The ASAB is designed around the [Inversion of +control](https://en.wikipedia.org/wiki/Inversion_of_control) principle. +It means that the ASAB is in control of the application lifecycle. The +custom-written code receives the flow from ASAB via callbacks or +handlers. Inversion of control is used to increase modularity of the +code and make it extensible. + +The application lifecycle is divided into 3 phases: init-time, run-time +and exit-time. + +### Init-time + +The init-time happens during :py`Application`{.interpreted-text +role="class"} constructor call. The Publish-Subscribe message +`Application.init!`{.interpreted-text role="any"} is published during +init-time. The `Config`{.interpreted-text role="class"} is loaded during +init-time. + +The application object executes asynchronous callback +`Application.initialize()`, which can be overriden by an user. + +``` {.python} +class MyApplication(asab.Application): + async def initialize(self): + # Custom initialization + from module_sample import Module + self.add_module(Module) +``` + +### Run-time + +Enter a run-time. This is where the application spends the most time +typically. The Publish-Subscribe message +`Application.run!`{.interpreted-text role="any"} is published when +run-time begins. + +The method returns the value of `Application.ExitCode`{.interpreted-text +role="any"}. + +The application object executes asynchronous callback +`Application.main()`, which can be overriden. If `main()` method is +completed without calling `stop()`, then the application server will run +forever (this is the default behaviour). + +``` {.python} +class MyApplication(asab.Application): + async def main(self): + print("Hello world!") + self.stop() +``` + +The method `Application.stop()` gracefully terminates the run-time and +commence the exit-time. This method is automatically called by `SIGINT` +and `SIGTERM`. It also includes a response to `Ctrl-C` on UNIX-like +system. When this method is called 3x, it abruptly exits the application +(aka emergency abort). + +The parameter `exit_code` allows you to specify the application exit +code (see *Exit-Time* chapter). + +*Note:* You need to install :py`win32api`{.interpreted-text role="mod"} +module to use `Ctrl-C` or an emergency abord properly with ASAB on +Windows. It is an optional dependency of ASAB. + +### Exit-time + +The application object executes asynchronous callback +`Application.finalize()`, which can be overriden by an user. + +``` {.python} +class MyApplication(asab.Application): + async def finalize(self): + # Custom finalization + ... +``` + +The Publish-Subscribe message `Application.exit!`{.interpreted-text +role="any"} is published when exit-time begins. + +Set the exit code of the application, see `os.exit()` in the Python +documentation. If `force` is `False`, the exit code will be set only if +the previous value is lower than the new one. If `force` is `True`, the +exit code value is set to a `exit_code` disregarding the previous value. + +The actual value of the exit code. + +The example of the exit code handling in the `main()` function of the +application. + +``` {.python} +if __name__ == '__main__': + app = asab.Application() + exit_code = app.run() + sys.exit(exit_code) +``` + +Module registry +--------------- + +For more details see :py`Module`{.interpreted-text role="class"} class. + +Initialize and add a new module. The `module_class` class will be +instantiated during the method call. + +``` {.python} +class MyApplication(asab.Application): + async def initialize(self): + from my_module import MyModule + self.add_module(MyModule) +``` + +A list of modules that has been added to the application. + +Service registry +---------------- + +Each service is identified by its unique service name. For more details +see :py`Service`{.interpreted-text role="class"} class. + +Locate a service by its service name in a registry and return the +`Service` object. + +``` {.python} +svc = app.get_service("service_sample") +svc.hello() +``` + +A dictionary of registered services. + +Command-line parser +------------------- + +Creates an `argparse.ArgumentParser`. This method can be overloaded to +adjust command-line argument parser. + +Please refer to Python standard library `argparse` for more details +about function arguments. + +The application object calls this method during init-time to process a +command-line arguments. :py`argparse`{.interpreted-text role="mod"} is +used to process arguments. You can overload this method to provide your +own implementation of command-line argument parser. + +The :py`Description`{.interpreted-text role="data"} attribute is a text +that will be displayed in a help text (`--help`). It is expected that +own value will be provided. The default value is `""` (empty string). + +UTC Time +-------- + +Return the current \"event loop time\" in seconds since the epoch as a +floating point number. The specific date of the epoch and the handling +of leap seconds is platform dependent. On Windows and most Unix systems, +the epoch is January 1, 1970, 00:00:00 (UTC) and leap seconds are not +counted towards the time in seconds since the epoch. This is commonly +referred to as Unix time. + +A call of the `time.time()` function could be expensive. This method +provides a cheaper version of the call that returns a current wall time +in UTC. diff --git a/docs/asab/config.md b/docs/asab/config.md new file mode 100644 index 000000000..6cea44e79 --- /dev/null +++ b/docs/asab/config.md @@ -0,0 +1,243 @@ +Configuration {#configuration-ref} +============= + +The configuration is provided by :py`Config`{.interpreted-text +role="obj"} object which is a singleton. It means that you can access +:py`Config`{.interpreted-text role="obj"} from any place of your code, +without need of explicit initialisation. + +``` {.python} +import asab + +# Initialize application object and hence the configuration +app = asab.Application() + +# Access configuration values anywhere +my_conf_value = asab.Config['section_name']['key1'] +``` + +Based on ConfigParser +--------------------- + +The :py`Config`{.interpreted-text role="obj"} is inherited from Python +Standard Library :py`configparser.ConfigParser`{.interpreted-text +role="class"} class. which implements a basic configuration language +which provides a structure similar to what's found in Microsoft Windows +INI files. + +Example of the configuration file: + +``` {.ini} +[bitbucket.org] +User = hg + +[topsecret.server.com] +Port = 50022 +ForwardX11 = no +``` + +And this is how you access configuration values: + +``` {.python} +>>> asab.Config['topsecret.server.com']['ForwardX11'] +'no' +``` + +Multiline configuration entry +----------------------------- + +A multiline configuration entries are supported. An example: + +``` {.ini} +[section] +key= + line1 + line2 + line3 +another_key=foo +``` + +Automatic load of configuration +------------------------------- + +If a configuration file name is specified, the configuration is +automatically loaded from a configuration file during initialiation time +of :py`Application`{.interpreted-text role="class"}. The configuration +file name can be specified by one of `-c` command-line argument (1), +`ASAB_CONFIG` environment variable (2) or config `[general] config_file` +default value (3). + +``` {.shell} +./sample_app.py -c ./etc/sample.conf +``` + +Including other configuration files +----------------------------------- + +You can specify one or more additional configuration files that are +loaded and merged from an main configuration file. It is done by +`[general] include` configuration value. Multiple paths are separated by +`os.pathsep` (`:` on Unix). The path can be specified as a glob (e.g. +use of `*` and `?` wildcard characters), it will be expanded by `glob` +module from Python Standard Library. Included configuration files may +not exists, this situation is silently ignored. + +``` {.ini} +[general] +include=./etc/site.conf:./etc/site.d/*.conf +``` + +You can also use a multiline configuration entry: + +``` {.ini} +[general] +include= + ./etc/site.conf + ./etc/site.d/*.conf +``` + +Configuration default values +---------------------------- + +This is how you can extend configuration default values: + +``` {.python} +asab.Config.add_defaults( + { + 'section_name': { + 'key1': 'value', + 'key2': 'another value' + }, + 'other_section': { + 'key3': 'value', + }, + } +) +``` + +Only simple types (`string`, `int` and `float`) are allowed in the +configuration values. Don\'t use complex types such as lists, +dictionaries or objects because these are impossible to provide via +configuration files etc. + +Environment variables in configration +------------------------------------- + +Environment variables found in values are automatically expanded. + +``` {.ini} +[section_name] +persistent_dir=${HOME}/.myapp/ +``` + +``` {.python} +>>> asab.Config['section_name']['persistent_dir'] +'/home/user/.myapp/' +``` + +There is a special environment variable [\${THIS\_DIR}]{.title-ref} that +is expanded to a directory that contains a current configuration file. +It is useful in complex configurations that utilizes included +configuration files etc. + +``` {.ini} +[section_name] +my_file=${THIS_DIR}/my_file.txt +``` + +Another environment variable [\${HOSTNAME}]{.title-ref} contains the +application hostname to be used f. e. in logging file path. + +``` {.ini} +[section_name] +my_file=${THIS_DIR}/${HOSTNAME}/my_file.txt +``` + +Passwords in configration +------------------------- + +\[passwords\] section in the configuration serves to securely store +passwords, which are then not shown publicly in the default API config +endpoint\'s output. + +It is convenient for the user to store passwords at one place, so that +they are not repeated in many sections of the config file(s). + +Usage is as follows: + +``` {.ini} +[connection:KafkaConnection] +password=${passwords:kafka_password} + +[passwords] +kafka_password= +``` + +Obtaining seconds +----------------- + +The seconds can be obtained using [getseconds()]{.title-ref} method for +values with different time units specified in the configuration: + +``` {.ini} +[sleep] +sleep_time=5.2s +another_sleep_time=10d +``` + +The available units are: + +> - `y` \... years +> - `M` \... months +> - `w` \... weeks +> - `d` \... days +> - `h` \... hours +> - `m` \... minutes +> - `s` \... seconds +> - `ms` .. miliseconds + +If no unit is specified, float of seconds is expected. + +The obtainment of the second value in the code can be achieved in two +ways: + +``` {.python} +self.SleepTime = asab.Config["sleep"].getseconds("sleep_time") +self.AnotherSleepTime = asab.Config.getseconds("sleep", "another_sleep_time") +``` + +Obtaining URLs +-------------- + +A URL can be obtained using a [geturl()]{.title-ref} method that takes +the URL from the config and removes leading and trailing whitespaces and +trailing backslashes. + +There is an optional parameter called [scheme]{.title-ref} that can have +any URL scheme like http, https, mongodb etc. Setting it to None, scheme +validation gets bypassed. + +Setting the scheme parameter to the same scheme as in the config, it +will return the URL. If it\'s not the same it will raise an error. + +There are two ways of obtaining the URL: + +``` {.py} +asab.Config["urls"].geturl("teskalabs", scheme="https") +asab.Config.geturl("urls", "github", scheme=None) +``` + +Example: + +``` {.python} +>>> asab.Config["urls"].geturl("teskalabs", scheme="https") + 'https://www.teskalabs.com' +``` + +For reference this would be the configuration file: + +``` {.ini} +[urls] +teskalabs=https://www.teskalabs.com/ +github=github.com +``` diff --git a/docs/asab/index.md b/docs/asab/index.md new file mode 100644 index 000000000..9f63ae730 --- /dev/null +++ b/docs/asab/index.md @@ -0,0 +1,47 @@ +Asynchronous Server Application Boilerplate\'s documentation +============================================================ + +Asynchronous Server App Boilerplate (or ASAB for short) is a +microservice platform for Python 3.7+ and [asyncio]{.title-ref}. ASAB +aims to minimize the amount of code that needs to be written when +building a microservice or an application server. ASAB is fully +asynchronous using async/await syntax from Python 3, making your code +modern, non-blocking, speedy and hence scalable. We make every effort to +build ASAB container-friendly so that you can deploy ASAB-based +microservice via Docker or Kubernetes in a breeze. + +ASAB is free and open-source software, available under BSD licence. It +means that anyone is freely licenced to use, copy, study, and change the +software in any way, and the source code is openly shared so that people +could voluntarily improve the design of the software. Anyone can (and is +encouraged to) use ASAB in his or her projects, for free. A current +maintainer is a [TeskaLabs Ltd](https://teskalabs.com) company. + +ASAB is developed [on GitHub](https://github.com/TeskaLabs/asab/). +Contributions are welcome! + +ASAB is designed to be powerful yet simple +------------------------------------------ + +Here is a complete example of a fully working microservice: + +``` {.python} +import asab + +class MyApplication(asab.Application): + async def main(self): + print("Hello world!") + self.stop() + +if __name__ == "__main__": + app = MyApplication() + app.run() +``` + +ASAB is the right choice when +----------------------------- + +> - using Python 3.7+. +> - building the microservice or the application server. +> - utilizing asynchronous I/O (aka +> [asyncio](https://docs.python.org/3/library/asyncio.html)). diff --git a/docs/asab/library.md b/docs/asab/library.md new file mode 100644 index 000000000..01fe8434e --- /dev/null +++ b/docs/asab/library.md @@ -0,0 +1,360 @@ +Library {#library-ref} +======= + +The ASAB Library ([asab.library]{.title-ref}) is a concept of the shared +data content across microservices in the cluster. In the cluster/cloud +microservice architectures, all microservices must have access to +unified resources. The [asab.library]{.title-ref} provides a read-only +interface for listing and reading this content. + +[asab.library]{.title-ref} is designed to be read-only. It also allows +to \"stack\" various libraries into one view (overlayed) that merges the +content of each library into one united space. + +The library can also notify the ASAB microservice about changes, e.g. +for automated update/reload. + +There is a companion microservice [asab-library]{.title-ref} that can be +used for the management and editing of the library content. The +[asab.library]{.title-ref} can however operate without +[asab-library]{.title-ref} microservice. + +Library structure +----------------- + +The library content is organized in a simplified filesystem manner, with +directories and files. + +Example of the library structure: + +``` {.} ++ /folder1/ + - /folder1/item1.yaml + - /folder1/item2.json ++ /folder2/ + - /folder2/item3.yaml + + /folder2/folder2.3/ + - /folder2/folder2.3/item4.json +``` + +Library path rules +------------------ + +- Any path must start with [/]{.title-ref}, including the root path + ([/]{.title-ref}). +- The folder path must end with [/]{.title-ref}. +- The item path must end with an extension (e.g. [.json]{.title-ref}). + +Layers +------ + +The library content can be organized into an unlimited number of layers. +Each layer is represented by a [provider]{.title-ref} with a specific +configuration. + +The layers of the library are like slices of Swiss cheese layered on top +of each other. Only if there is a hole in the top layer can you see the +layer that shows through underneath. It means that files of the upper +layer overwrite files with the same path in the lower layers. + +The first provider is responsible for providing +[/.disabled.yaml]{.title-ref} that controls the visibility of items. If +[/.disabled.yaml]{.title-ref} is not present, then is considered empty. + +Library service +--------------- + +Example of the use: + +``` {.python} +import asab +import asab.library + + +# this substitutes configuration file +asab.Config.read_string( + """ +[library] +providers=git+https://github.com/TeskaLabs/asab-maestro-library.git +""" + ) + + +class MyApplication(asab.Application): + + def __init__(self): + super().__init__() + # Initialize the library service + self.LibraryService = asab.library.LibraryService(self, "LibraryService") + self.PubSub.subscribe("Library.ready!", self.on_library_ready) + + async def on_library_ready(self, event_name, library): + print("# Library\n") + + for item in await self.LibraryService.list("/", recursive=True): + print(" *", item) + if item.type == 'item': + itemio = await self.LibraryService.read(item.name) + if itemio is not None: + with itemio: + content = itemio.read() + print(" - content: {} bytes".format(len(content))) + else: + print(" - (DISABLED)") + +if __name__ == '__main__': + app = MyApplication() + app.run() +``` + +The library service may exist in multiple instances, with different +[paths]{.title-ref} setups. For that reason, you have to provide a +unique [service\_name]{.title-ref} and there is no default value for +that. + +For more examples of Library usage, please see [ASAB +examples](https://github.com/TeskaLabs/asab/tree/master/examples) + +Library configuration +--------------------- + +Example: + +``` {.ini} +[library] +providers: + provider+1://... + provider+2://... + provider+3://... +``` + +PubSub messages +--------------- + +Read more about `PubSub`{.interpreted-text role="ref"} in +ASAB. + +%TODO: option% +Library.ready! +xxx + +A library is created in a "not ready" state. Only after all providers +are ready, the library itself becomes ready. The library indicates that +by the PubSub event [Library.ready!]{.title-ref}. + +%TODO: option% +Library.not\_ready! +xxx + +The readiness of the library (connection to external technologies) can +be lost. You can also subscribe to [Library.not\_ready!]{.title-ref} +event. + +%TODO: option% +Library.change! +xxx + +You can get [Notification on Changes](#notification-on-changes) in the +library. Specify a path or paths that you would like to \"listen to\". +Then subscribe to [Library.change!]{.title-ref} PubSub event. Available +for Git and FileSystem providers for now. + +Notification on changes +----------------------- + +# TODO: autofunction% +LibraryService.subscribe +xxx + +Providers +--------- + +The library can be configured to work with the following \"backends\" +(aka providers): + +### Filesystem + +The most basic provider that reads data from the local filesystem. The +notification on changes functionality is available only for Linux +systems, as it implements +[inotify](https://en.wikipedia.org/wiki/Inotify) + +Configuration examples: + +``` {.ini} +[library] +providers: /home/user/directory +``` + +``` {.ini} +[library] +providers: ./this_directory +``` + +``` {.ini} +[library] +providers: file:///home/user/directory +``` + +### Apache Zookeeper + +ZooKeeper as a consensus technology is vital for microservices in the +cluster. + +There are several configuration strategies: + +1) Configuration from \[zookeeper\] section. + +``` {.ini} +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/library + +[library] +providers: + zk:// +``` + +2) Specify a path of a ZooKeeper node where only library lives. + + > The library path will be [/library]{.title-ref}. + +``` {.ini} +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/else + +[library] +providers: + zk:///library + + +The library path will be `/`. +``` + +``` {.ini} +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/else + +[library] +providers: + zk:/// +``` + +3) Configuration from the URL in the \[library\] section. + +``` {.ini} +[library] +providers: + zk://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/library +``` + +4) Configuration from \[zookeeper\] section and joined + [path]{.title-ref} from \[zookeeper\] and \[library\] sections. + + > The resulting path will be [/else/library]{.title-ref}. + +``` {.ini} +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/else + +[library] +providers: + zk://./library +``` + +If a [path]{.title-ref} from the \[zookeeper\] section is missing, an +application class name will be used E.g. +[/BSQueryApp/library]{.title-ref} + +### Microsoft Azure Storage + +Reads from the Microsoft Azure Storage container. + +Configuration: + +``` {.ini} +[library] +providers: azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER +``` + +If Container Public Access Level is not set to \"Public access\", then +\"Access Policy\" must be created with \"Read\" and \"List\" permissions +and \"Shared Access Signature\" (SAS) query string must be added to a +URL in a configuration: + +``` {.ini} +[library] +providers: azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER?sv=2020-10-02&si=XXXX&sr=c&sig=XXXXXXXXXXXXXX +``` + +### Git repository + +Connection to git repositories requires +[pygit2](https://www.pygit2.org/) library to be installed. + +Configuration: + +``` {.ini} +[library] +providers: git+https://github.com/john/awesome_project.git +``` + +#### Deploy tokens in GitLab + +GitLab uses deploy tokens to enable authentication of deployment tasks, +independent of a user account. Authentication through deploy tokens is +the only supported option for now. + +If you want to create a deploy token for your GitLab repository, follow +these steps from the +[manual](https://docs.gitlab.com/ee/user/project/deploy_tokens/#create-a-deploy-token): + +1. Go to **Settings \> Repository \> Deploy tokens** section in your + repository. (Note that you have to possess a \"Maintainer\" or + \"Owner\" role for the repository.) +2. Expand the \"Deploy tokens\" section. The list of current Active + Deploy Tokens will be displayed. +3. Complete the fields and scopes. We recommend a custom \"username\", + as you will need it later for the URL in the configuration. +4. Record the deploy token\'s values *before leaving or refreshing the + page*! After that, you cannot access it again. + +After the deploy token is created, use the URL for the repository in the +following format: + +``` {.ini} +[library] +providers: git+https://:@gitlab.example.com/john/awesome_project.git +``` + +#### Where does the repository clone? + +The git provider clones the repository into a temporary directory. The +default path for the cloned repository is +[/tmp/asab.library.git/]{.title-ref} and it can be changed manually: + +``` {.ini} +[library:git] +repodir=path/to/repository/cache +``` + +### Reference + +# TODO: autoclass% +LibraryService + +# TODO: autofunction% +read +xxx + +# TODO: autofunction% +list +xxx + +# TODO: autofunction% +export +xxx +xxx diff --git a/docs/asab/log.md b/docs/asab/log.md new file mode 100644 index 000000000..e155fe57b --- /dev/null +++ b/docs/asab/log.md @@ -0,0 +1,243 @@ +Logging +======= + +ASAB logging is built on top of a standard Python `logging` module. It +means that it logs to `stderr` when running on a console and ASAB also +provides file and syslog output (both RFC5424 and RFC3164) for +background mode of operations. + +Log timestamps are captured with sub-second precision (depending on the +system capabilities) and displayed including microsecond part. + +Recommended use +--------------- + +We recommend to create a logger `L` in every module that captures all +necessary logging output. Alternative logging strategies are also +supported. + +``` {.python} +import logging +L = logging.getLogger(__name__) + +... + +L.warning("Hello world!") +``` + +Example of the output to the console: + +`25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule Hello world!` + +Logging Levels +-------------- + +ASAB uses Python logging levels with the addition of `LOG_NOTICE` level. +`LOG_NOTICE` level is similar to `logging.INFO` level but it is visible +in even in non-verbose mode. + +``` {.python} +L.log(asab.LOG_NOTICE, "This message will be visible regardless verbose configuration.") +``` + + --------------------------------------------------------------- + Level Numeric value Syslog Severity level + ---------------- --------------- ------------------------------ + `CRITICAL` 50 Critical / `crit` / 2 + + `ERROR` 40 Error / `err` / 3 + + `WARNING` 30 Warning / `warning` / 4 + + `LOG_NOTICE` 25 Notice / `notice` / 5 + + `INFO` 20 Informational / `info` / 6 + + `DEBUG` 10 Debug / `debug` / 7 + + `NOTSET` 0 + --------------------------------------------------------------- + +Example of a custom level configuration: + +``` {.ini} +[logging] +levels= + myApp.module1 DEBUG + myApp.module2 WARNING + customLogger ERROR +``` + +The logger name and the corresponding logging level are separated by a +space, each logger is on a separate line. + +Verbose mode +------------ + +The command-line argument `-v` enables verbose logging. It means that +log entries with levels `DEBUG` and `INFO` will be visible. It also +enables `asyncio` debug logging. + +The actual verbose mode is avaiable at +`asab.Config["logging"]["verbose"]` boolean option. + +``` {.python} +L.debug("This message will be visible only in verbose mode.") +``` + +Structured data +--------------- + +ASAB supports a structured data to be added to a log entry. It follows +the [RFC 5424](https://tools.ietf.org/html/rfc5424), section +`STRUCTURED-DATA`. Structured data are a dictionary, that has to be +seriazable to JSON. + +``` {.python} +L.warning("Hello world!", struct_data={'key1':'value1', 'key2':2}) +``` + +Example of the output to the console: + +`25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule [sd key1="value1" key2="2"] Hello world!` + +Logging to file +--------------- + +The command-line argument `-l` on command-line enables logging to file. +Also non-empty `path` option in the section `[logging:file]` of +configuration file enables logging to file as well. + +Example of the configuration file section: + +``` {.ini} +[logging:file] +path=/var/log/asab.log +format="%%(asctime)s %%(levelname)s %%(name)s %%(struct_data)s%%(message)s", +datefmt="%%d-%%b-%%Y %%H:%%M:%%S.%%f" +backup_count=3 +rotate_every=1d +``` + +When the deployment expects more instances of the same application to be +logging into the same file, it is recommended, that the variable +hostname is used in the file path: + +``` {.ini} +[logging:file] +path=/var/log/${HOSTNAME}/asab.log +``` + +In this way, the applications will log to seperate log files in +different folders, which is an intended behavior, since race conditions +may occur when different application instances log into the same file. + +Logging to console +------------------ + +ASAB will log to the console only if it detects that it runs in the +foreground respectively on the terminal using `os.isatty` or if the +environment variable `ASABFORCECONSOLE` is set to `1`. This is useful +setup for eg. PyCharm. + +### Log rotation + +ASAB supports a [log +rotation](https://en.wikipedia.org/wiki/Log_rotation). The log rotation +is triggered by a UNIX signal `SIGHUP`, which can be used e.g. to +integrate with `logrotate` utility. It is implemented using +`logging.handlers.RotatingFileHandler` from a Python standard library. +Also, a time-based log rotation can be configured using `rotate_every` +option. + +`backup_count` specifies a number of old files to be kept prior their +removal. The system will save old log files by appending the extensions +'.1', '.2' etc., to the filename. + +`rotate_every` specifies an time interval of a log rotation. Default +value is empty string, which means that the time-based log rotation is +disabled. The interval is specified by an integer value and an unit, +e.g. 1d (for 1 day) or 30M (30 minutes). Known units are [H]{.title-ref} +for hours, [M]{.title-ref} for minutes, [d]{.title-ref} for days and +[s]{.title-ref} for seconds. + +Logging to syslog +----------------- + +The command-line argument `-s` enables logging to syslog. + +A configuration section `[logging:syslog]` can be used to specify +details about desired syslog logging. + +Example of the configuration file section: + +``` {.ini} +[logging:syslog] +enabled=true +format=5 +address=tcp://syslog.server.lan:1554/ +``` + +`enabled` is equivalent to command-line switch `-s` and it enables +syslog logging target. + +`format` speficies which logging format will be used. Possible values +are: + +- `5` for (new) syslog format ([RFC + 5424](https://tools.ietf.org/html/rfc5424) ) , +- `3` for old BSD syslog format ([RFC + 3164](https://tools.ietf.org/html/rfc3164) ), typically used by + `/dev/log` and +- `m` for Mac OSX syslog flavour that is based on BSD syslog format + but it is not fully compatible. + +The default value is `3` on Linux and `m` on Mac OSX. + +`address` specifies the location of the Syslog server. It could be a +UNIX path such as `/dev/log` or URL. Possible URL values: + +- `tcp://syslog.server.lan:1554/` for Syslog over TCP +- `udp://syslog.server.lan:1554/` for Syslog over UDP +- `unix-connect:///path/to/syslog.socket` for Syslog over UNIX socket + (stream) +- `unix-sendto:///path/to/syslog.socket` for Syslog over UNIX socket + (datagram), equivalent to `/path/to/syslog.socket`, used by a + `/dev/log`. + +The default value is a `/dev/log` on Linux or `/var/run/syslog` on Mac +OSX. + +Logging of obsolete features +---------------------------- + +It proved to be essential to inform operators about features that are +going to be obsoleted. ASAB offers the unified \"obsolete\" logger. This +logger can indicate that a particular feature is marked as \"obsolete\" +thru logs. Such a log message can then be \"grepped\" from logs +uniformly. + +It is recommended to include [eol]{.title-ref} attribute in the +[struct\_data]{.title-ref} of the log with a [YYYY-MM-DD]{.title-ref} +date/time of the planned obsoletion of the feature. + +Hint: We suggest automating the detection of obsolete warnings in logs +so that the operations are informed well ahead of the actual removal of +the feature. The string to seek in logs is \" OBSOLETE \". + +Example of the use: + +``` {.python} +asab.LogObsolete.warning("Use of the obsolete function", struct_data={'eol':'2022-31-12'}) +``` + +Log example: + +`21-Jul-2022 14:32:40.983884 WARNING OBSOLETE [eol="2022-31-12"] Use of the obsolete function` + +Reference +--------- + +# TODO: automodule members="" undoc-members="" show-inheritance=""} +asab.log +xxx diff --git a/docs/asab/metrics.md b/docs/asab/metrics.md new file mode 100644 index 000000000..e48a0c169 --- /dev/null +++ b/docs/asab/metrics.md @@ -0,0 +1,632 @@ +xxx {.currentmodule} +asab.metrics +xxx + +Metrics +======= + +Metrics document the state of the application in a timescale manner. For +further analysis, connect your ASAB application to a time-series +database. [Influx](https://www.influxdata.com/) and +[Prometheus](https://prometheus.io/) are supported. + +Metrics Service +--------------- + +Create new metrics using `MetricsService`{.interpreted-text +role="class"}. + +*example of counter initialization:* + +``` {.python} +class MyApplication(asab.Application): + async def initialize(self): + from asab.metrics import Module + self.add_module(Module) + self.MetricsService = self.get_service('asab.MetricsService') + self.MyCounter = self.MetricsService.create_counter("mycounter", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0}) + +if __name__ == '__main__': + app = MyApplication() + app.run() +``` + +See the full example here: + + +Types of Metrics +---------------- + +- `Gauge`{.interpreted-text role="class"} stores single numerical + values which can go up and down. Implements `set`{.interpreted-text + role="func"} method to set the metric values. +- `Counter`{.interpreted-text role="class"} is a cumulative metric + whose values can increase or decrease. Implements + `add`{.interpreted-text role="func"} and `sub`{.interpreted-text + role="func"} methods. +- Event per Second Counter (`EPSCounter`{.interpreted-text + role="class"}) divides all values by delta time. +- `DutyCycle`{.interpreted-text role="class"} + +- `AggregationCounter`{.interpreted-text role="class"} allows to + `set`{.interpreted-text role="func"} values based on an aggregation + function. `max`{.interpreted-text role="func"} function is default. +- `Histogram`{.interpreted-text role="class"} represents cumulative + histogram with `set`{.interpreted-text role="func"} method. + +`Counter`{.interpreted-text role="class"}, +`AggregationCounter`{.interpreted-text role="class"} and +`Histogram`{.interpreted-text role="class"} come also in variants +respecting dynamic tags. (See section +`Dynamic Tags`{.interpreted-text role="ref"}.) + +All methods that create new metrics objects can be found in the Metrics +Service reference. You should never initiate a new metrics object on its +own, but always through Metrics Service. Metris initialization is meant +to be done in the init time of your application and **should not be done +during runtime**. + +ASAB Metrics Interpretation +--------------------------- + +Metrics Service not only creates new metrics but also periodically +collects their values and sends them to selected databases. Every 60 +seconds in the application lifetime, Metrics Service gathers values of +all ASAB metrics. All Counters (and metric types that inherit from +`Counter`{.interpreted-text role="class"}) reset at this event to their +initial values by default. Interpretation of ASAB Counters is affected +by their resetable nature. Even though they monotonously increase, +resetting every minute gives them a different meaning. In a long-term +observation (that\'s how you most probably monitor the metrics in +time-series databases), these metrics count **events per minute**. Thus, +resettable Counters are presented to Prometheus database as gauge-type +metrics. Set the [reset]{.title-ref} argument to [False]{.title-ref} +when creating a new Counter to disable Counter resetting. This periodic +\"flush\" cycle also causes 60s delay of metric propagation into +supported time-series databases. + +Initial Values +-------------- + +You can initiate your metric instance with or without initial values. +When providing initial values, these values are always present and +presented to databases even when these values were untouched during the +last 60 seconds. You will always see these values in the data, with +initial state or changed by occasion. However, the lifetime of values +(name and value pairs) added during runtime is only 60 s. Thus, if this +value is not set during 60s period, you won\'t see it in your database +anymore. + +Built-in Tags {#dynamic_tags} +------------- + +Tags help you to sort and group metrics in a selected target database, +and analyze the data easily. Several \"static\" tags are provided +directly by ASAB. + +%TODO: option% +host +xxx + +This is a hostname of the server or machine where the application is +running + +%TODO: option% +appclass +xxx + +This is the name of the application. It is literally the name of the +class that inherits from the ASAB Application object. + +%TODO: option% +node\_id +xxx + +Present if NODE\_ID environmental variable is specified. Meant to +specify a node in the cluster. Automatically set by the Remote Control. + +%TODO: option% +service\_id +xxx + +Present if SERVICE\_ID environmental variable is specified. Meant to +specify a service in the cluster. Automatically set by the Remote +Control. + +%TODO: option% +instance\_id +xxx + +Present if INSTANCE\_ID environmental variable is specified. Meant to +specify an instance in the cluster. Automatically set by the Remote +Control. + +You can use with convenience the three last tags even without Remote +Control by adding the respective environmental variables to Docker +containers (or any other technology you use to run ASAB microservices). + +Dynamic Tags +------------ + +Some metric types (Counter, AggregationCounter, Histogram) allow you to +use dynamic tags. All metrics in ASAB carry some tags - Hostname by +default and others added by custom. Using dynamic tags allows you to +create values with a specific tag-set during runtime. Specific tag-sets +expire after defined period. This might be spotted in your time-series +database like a mysterious disappearance of unused tags. Specify +expiration period in confiuration. Default is 60 s. + +*example configuration* + +``` {.} +[asab:metrics] +expiration=60 +``` + +Timestamp +--------- + +**Timestamp** contains the record of the precise moment the metric\'s +value was created or committed to the database. There are two types of +metrics: resettable ([is\_reset]{.title-ref} = True) and non-resettable +([is\_reset]{.title-ref} = False). To reset a metric means to set it +back to its initial value (for example, back to 0). The metric\'s type +is determined by the `reset: bool = True` parameter of the metric\'s +constructor at the moment it is created. We measure non-resettable +metrics at the time of their creation ([there are several possible +methods depending on the metric\'s general logic]{.title-ref}), while +the resettable ones are measured when we send data to the database +([which is also the moment of them being reset]{.title-ref}). + ++---+--------+---------------------+--------------+--------------+-----+ +| | Met | Description / | Time is | Timestamp | is\ | +| | ric\'s | Methods | Measured | Value | _re | +| | Type | | | Appears | set | ++===+========+=====================+==============+==============+=====+ +| 1 | **G | Stores single | when metric | **set()** | **F | +| F | auge** | numerical values | is created | for actual | als | +| | | which can go up and | [(actual | time | e** | +| | | down. | time)] | | | +| | | | {.title-ref} | | | +| | | **add\_field() /** | | | | +| | | **set()** | | | | ++---+--------+---------------------+--------------+--------------+-----+ +| 2 | **Cou | A cumulative | when metric | **add()** or | **F | +| F | nter** | metric; values can | is created | **sub()** | als | +| | | increase or | [(actual | for actual | e** | +| | [ | decrease Never | time)] | time | | +| | Allows | stops. | {.title-ref} | | | +| | d | | | | | +| | ynamic | **add\_field() /** | | | | +| | tags] | **add() / sub() / | | | | +| | {.titl | flush()** | | | | +| | e-ref} | | | | | ++---+--------+---------------------+--------------+--------------+-----+ +| 2 | **Cou | A cumulative | every 60 | **flush()** | ** | +| T | nter** | metric; values can | seconds | - time of | Tru | +| | | increase or | | the test | e** | +| | [ | decrease Set to 0 | | flush | | +| | Allows | every 60 seconds. | | | | +| | d | | | | | +| | ynamic | [AgregationCounter | | | | +| | tags] | behavior is based | | | | +| | {.titl | on the resettable | | | | +| | e-ref} | Co | | | | +| | | unter.]{.title-ref} | | | | ++---+--------+---------------------+--------------+--------------+-----+ +| 3 | ** | There is an | [\*\*\*\*\*] | [\*\*\*\*\*] | **F | +| F | EPSCou | adjustable reset | {.title-ref} | {.title-ref} | als | +| | nter** | parameter in the | | | e** | +| | | metric's | | | | +| | | constructor. | | | | +| | | | | | | +| | | [reset: bool = | | | | +| | | True]{.title-ref} | | | | +| | | [reset: bool = | | | | +| | | False]{.title-ref} | | | | ++---+--------+---------------------+--------------+--------------+-----+ +| 3 | ** | Divides the count | every 60 | **flush()** | ** | +| T | EPSCou | of events by the | seconds | | Tru | +| | nter** | time difference | | | e** | +| | | between | | | | +| | | measurements. | | | | +| | | | | | | +| | | **flush()** | | | | ++---+--------+---------------------+--------------+--------------+-----+ +| 4 | * | The fraction of one | every 60 | **flush()** | ** | +| T | *DutyC | period in which a | seconds | | Tru | +| | ycle** | signal/system is | | | e** | +| | | active. A 60% DC | | | | +| | | means the signal is | | | | +| | | on 60% and off 40% | | | | +| | | of the time. | | | | +| | | | | | | +| | | **add\_field() /** | | | | +| | | **set() / flush()** | | | | ++---+--------+---------------------+--------------+--------------+-----+ +| 5 | * | Keeps track of max | when metric | **set()** | **F | +| F | *Aggre | or min value of the | is created | | als | +| | gation | Counter. Maximum | [(actual | | e** | +| | Cou | value is a default. | time)] | | | +| | nter** | | {.title-ref} | | | +| | | **set() /** | | | | +| | [ | [+inherits from the | | | | +| | Allows | C | | | | +| | d | ounter]{.title-ref} | | | | +| | ynamic | **add()/sub()** | | | | +| | tags] | [are | | | | +| | {.titl | overw | | | | +| | e-ref} | ritten]{.title-ref} | | | | ++---+--------+---------------------+--------------+--------------+-----+ +| 5 | * | [\*\* | every 60 | **flush()** | ** | +| T | *Aggre | \*\*\*]{.title-ref} | seconds | | Tru | +| | gation | | | | e** | +| | Cou | | | | | +| | nter** | | | | | +| | | | | | | +| | [ | | | | | +| | Allows | | | | | +| | d | | | | | +| | ynamic | | | | | +| | tags] | | | | | +| | {.titl | | | | | +| | e-ref} | | | | | ++---+--------+---------------------+--------------+--------------+-----+ +| 6 | * | Represents | when metric | **set()** | **F | +| F | *Histo | cumulative | is created | | als | +| | gram** | histogram with a | [(actual | | e** | +| | | set() method. | time)] | | | +| | [ | | {.title-ref} | | | +| | Allows | **add\_field() /** | | | | +| | d | **set() / flush()** | | | | +| | ynamic | | | | | +| | tags] | | | | | +| | {.titl | | | | | +| | e-ref} | | | | | ++---+--------+---------------------+--------------+--------------+-----+ +| 6 | * | [\*\* | every 60 | **flush()** | ** | +| T | *Histo | \*\*\*]{.title-ref} | seconds | | Tru | +| | gram** | | | | e** | +| | | | | | | +| | [ | | | | | +| | Allows | | | | | +| | d | | | | | +| | ynamic | | | | | +| | tags] | | | | | +| | {.titl | | | | | +| | e-ref} | | | | | ++---+--------+---------------------+--------------+--------------+-----+ + +InfluxDB +-------- + +Metrics can be collected in the Influx time-series database. + +*configuration example:* + +``` {.} +[asab:metrics] +target=influxdb + +[asab:metrics:influxdb] +url=http://localhost:8086/ +bucket=my_bucket +org=my_org +token=my_token +``` + +**InfluxDB 2.0 API parameters**: + +- **url** - \[required\] url string of your influxDB + +- **bucket** - \[required\] the destination bucket for writes + +- **org** - \[required\] specifies the destination organization for + writes + +- + + **orgid** - \[optional\] specifies the ID of the destination organization for writes + + : (NOTE: If both orgID and org are specified, org takes + precedence) + +- **token** - \[required\] API token to authenticate to the InfluxDB + +**InfluxDB \<1.8 API parameters**: + +- **url** - \[required\] url string of your influxDB +- **username** - \[required\] name of influxDB user +- **password** - \[required\] password of influxDB user + +Prometheus +---------- + +Prometheus is a \"pull model\" time-series database. Prometheus accesses +`asab/v1/metrics` endpoint of ASAB ApiService. Thus, connecting ASAB to +Prometheus requires APIService initialization. However, no more +configuration is needed. ASAB metrics are presented to Prometheus in +[OpenMetrics](https://openmetrics.io/) standard format. + +*prometheus.yaml configuration file example:* + +``` {.yaml} +global: + scrape_interval: 15s + scrape_timeout: 10s + evaluation_interval: 15s + +scrape_configs: +- job_name: 'metrics_example' + metrics_path: '/asab/v1/metrics' + scrape_interval: 10s + static_configs: + - targets: ['127.0.0.1:8080'] +``` + +xxx {.note} +xxx {.title} +Note +xxx + +To satisfy the OpenMetrics format required by Prometheus, you should +follow the instructions below: + +- Metrics names must fit regex `[a-zA-Z:][a-zA-Z0-9_:]*`. (Any other + characters are replaced by an underscore. Leading underscores and + numbers are stripped. These changes proceed without warning.) +- Metrics names MUST NOT end with "total" or "created". +- Tags SHOULD contain items "unit" and "help" providing metadata to + Prometheus. +- Values MUST be float or integer. +xxx + +Metrics Endpoints +----------------- + +The **API Service** in ASAB offers several endpoints that monitor +internal ASAB functionality. Some of them present the current state of +metrics. Check for Swagger documentation of your ASAB Application REST +API by visiting the [/doc]{.title-ref} endpoint. + +`/asab/v1/metrics` + +- This endpoint returns metrics in OpenMetrics format and its primary + purpose is to satisfy Prometheus database needs. + +`/asab/v1/metrics.json` + +- This endpoint presents metrics data in JSON format. + +`/asab/v1/watch_metrics` + +- Use this endpoint for developing or monitoring your app from the + terminal. It returns a simple table of ASAB metrics. You can filter + metrics by name using the `filter` parameter and `tags` parameter to + show or hide tags. + +*example commands:* + +``` {.} +watch curl localhost:8080/asab/v1/watch_metrics +``` + +``` {.} +watch curl localhost:8080/asab/v1/watch_metrics?name=web_requests_duration_max,tags=True +``` + +HTTP Target +----------- + +For use cases requiring a push model of metrics digestion, there is an +HTTP Target. HTTP Target creates a POST request to configured URL with +current metrics state sent as JSON body. Configuration is required. + +*configuration example:* + +``` {.} +[asab:metrics] +target=http + +[asab:metrics:http] +url=http://consumer_example:8080/consume +``` + +Web Requests Metrics +-------------------- + +ASAB `WebService`{.interpreted-text role="class"} class automatically +provides metrics counting web requests. There are 5 metrics quantifying +requests to all ASAB endpoints. + +- [web\_requests]{.title-ref} - Counts requests to asab endpoints as + events per minute. +- [web\_requests\_duration]{.title-ref} - Counts total requests + duration to asab endpoints per minute. +- [web\_requests\_duration\_min]{.title-ref} - Counts minimal request + duration to asab endpoints per minute. +- [web\_requests\_duration\_max]{.title-ref} - Counts maximum request + duration to asab endpoints per minute. +- [web\_requests\_duration\_hist]{.title-ref} - Cumulative histogram + counting requests in buckets defined by the request duration. + +Native Metrics +-------------- + +You can opt out of Native Metrics through configuration by setting +[native\_metrics]{.title-ref} to [false]{.title-ref}. Default is +[true]{.title-ref}. + +*example configuration* + +``` {.} +[asab:metrics] +native_metrics=true +``` + +**Memory Metrics** + +A gauge with the name `os.stat` gathers information about memory usage +by your application. + +You can find several metric values there: + +- VmPeak - Peak virtual memory size +- VmLck - Locked memory size +- VmPin - Pinned memory size +- VmHWM - Peak resident set size (\"high water mark\") +- VmRSS - Resident set size +- VmData, VmStk, VmExe - Size of data, stack, and text segments +- VmLib - Shared library code size +- VmPTE - Page table entries size +- VmPMD - Size of second-level page tables +- VmSwap - Swapped-out virtual memory size by anonymous private pages; + shmem swap usage is not included + +**Logs Counter** + +There is a default Counter named `logs` with values `warnings`, +`errors`, and `critical`, counting logs with respective levels. It is a +humble tool for application health monitoring. + +Reference +--------- + +# TODO: autoclass show-inheritance=""} +MetricsService + +{.automethod} +create\_gauge + +Creates `Gauge`{.interpreted-text role="class"} object. +xxx + +{.automethod} +create\_counter + +Creates `Counter`{.interpreted-text role="class"} or +`CounterWithDynamicTags`{.interpreted-text role="class"} object. +xxx + +{.automethod} +create\_eps\_counter + +Creates `EPSCounter`{.interpreted-text role="class"} object. +xxx + +{.automethod} +create\_duty\_cycle + +Creates `DutyCycle`{.interpreted-text role="class"} object. +xxx + +{.automethod} +create\_aggregation\_counter + +Creates `AggregationCounter`{.interpreted-text role="class"} or +`AggregationCounterWithDynamicTags`{.interpreted-text role="class"} +object. +xxx + +{.automethod} +create\_histogram + +Creates `Histogram`{.interpreted-text role="class"} or +`HistogramWithDynamicTags`{.interpreted-text role="class"} object. +xxx +xxx + +# TODO: autoclass show-inheritance=""} +Gauge + +Argument [init\_values]{.title-ref} is a dictionary with initial values +and value names as keys. + +{.automethod} +set +xxx + +param name + +: name of the value + +param value + +: value itself +xxx + +# TODO: autoclass show-inheritance=""} +Counter + +Argument [init\_values]{.title-ref} is a dictionary with initial values +and value names as keys. If reset is True, Counter resets every 60 +seconds. + +{.automethod} +add +xxx + +{.automethod} +sub +xxx +xxx + +# TODO: autoclass show-inheritance=""} +EPSCounter +xxx + +# TODO: autoclass show-inheritance=""} +DutyCycle +xxx + +# TODO: autoclass show-inheritance=""} +AggregationCounter + +Values (their names and init\_values) can be provided when initializing +the metrics or added with `set`{.interpreted-text role="func"} method. +`add`{.interpreted-text role="func"} and `sub`{.interpreted-text +role="func"} methods are not implemented. + +{.automethod} +set +xxx + +Applies aggregation function on recent Counter value and value in +argument and sets the result as new value of the Counter. +xxx + +# TODO: autoclass show-inheritance=""} +Histogram + +{.automethod} +set +xxx +xxx + +# TODO: autoclass show-inheritance=""} +CounterWithDynamicTags + +{.automethod} +add +xxx + +{.automethod} +sub +xxx +xxx + +# TODO: autoclass show-inheritance=""} +AggregationCounterWithDynamicTags + +{.automethod} +set +xxx +xxx + +# TODO: autoclass show-inheritance=""} +HistogramWithDynamicTags + +{.automethod} +set +xxx +xxx diff --git a/docs/asab/module.md b/docs/asab/module.md new file mode 100644 index 000000000..9e8f0ca9c --- /dev/null +++ b/docs/asab/module.md @@ -0,0 +1,53 @@ +Module +====== + +Modules are registered at the module registry, managed by an application +object. See `Application.Modules`{.interpreted-text role="any"} for more +details. Module can be loaded by ASAB and typically provides one or more +`Service`{.interpreted-text role="any"} objects. + +Structure +--------- + +Recommended structure of the ASAB module: + + mymodule/ + __init__.py + myservice.py + +Content of the \`\_\_init\_\_.py\`: + +``` {.python} +import asab +from .myservice import MyService + +# Extend ASAB configuration defaults +asab.Config.add_defaults({ + 'mymodule': { + 'foo': 'bar' + } +}) + +class MyModule(asab.Module): + def __init__(self, app): + super().__init__(app) + self.service = MyService(app, "MyService") +``` + +And this is how the module is loaded: + +``` {.python} +from mymodule import MyModule +app.add_module(MyModule) +``` + +For more details see `Application.add_module`{.interpreted-text +role="any"}. + +Lifecycle +--------- + +Called when the module is initialized. It can be overriden by an user. + +Called when the module is finalized e.g. during application exit-time. +It can be overriden by an user. diff --git a/docs/asab/pubsub.md b/docs/asab/pubsub.md new file mode 100644 index 000000000..d46f657ed --- /dev/null +++ b/docs/asab/pubsub.md @@ -0,0 +1,274 @@ +Publish-Subscribe {#pubsub_page} +================= + +Publish--subscribe is a messaging pattern where senders of messages, +called publishers, send the messages to receivers, called subscribers, +via PubSub message bus. Publishers don\'t directly interact with +subscribers in any way. Similarly, subscribers express interest in one +or more message types and only receive messages that are of interest, +without knowledge of which publishers, if any, there are. + +ASAB `PubSub` operates with a simple messages, defined by their *message +type*, which is a string. We recommend to add `!` (explamation mark) at +the end of the message type in order to distinguish this object from +other types such as Python class names or functions. Example of the +message type is e.g. `Application.run!`{.interpreted-text role="any"} or +`Application.tick/600!`{.interpreted-text role="any"}. + +The message can carry an optional positional and keyword arguments. The +delivery of a message is implemented as a the standard Python function. + +*Note:* There is an default, application-wide Publish-Subscribe message +bus at `Application.PubSub`{.interpreted-text role="any"} that can be +used to send messages. Alternatively, you can create your own instance +of :py`PubSub`{.interpreted-text role="class"} and enjoy isolated PubSub +delivery space. + +Subscription +------------ + +Subscribe to a message type. Messages will be delivered to a `callback` +callable (function or method). The `callback` can be a standard callable +or an `async` coroutine. Asynchronous `callback` means that the delivery +of the message will happen in a `Future`, asynchronously. + +`Callback` callable will be called with the first argument + +Example of a subscription to an `Application.tick!`{.interpreted-text +role="any"} messages. + +``` {.python} +class MyClass(object): + def __init__(self, app): + app.PubSub.subscribe("Application.tick!", self.on_tick) + + def on_tick(self, message_type): + print(message_type) +``` + +Asynchronous version of the above: + +``` {.python} +class MyClass(object): + def __init__(self, app): + app.PubSub.subscribe("Application.tick!", self.on_tick) + + async def on_tick(self, message_type): + await asyncio.sleep(5) + print(message_type) +``` + +To simplify the process of subscription to `PubSub`{.interpreted-text +role="any"}, ASAB offers the decorator-based *\"subscribe all\"* +functionality. + +In the followin example, both `on_tick()` and `on_exit()` methods are +subscribed to `Application.PubSub`{.interpreted-text role="any"} message +bus. + +``` {.python} +class MyClass(object): + def __init__(self, app): + app.PubSub.subscribe_all(self) + + @asab.subscribe("Application.tick!") + async def on_tick(self, message_type): + print(message_type) + + @asab.subscribe("Application.exit!") + def on_exit(self, message_type): + print(message_type) +``` + +Unsubscribe from a message delivery. + +# TODO: autoclass members="" undoc-members=""} +asab.Subscriber +xxx + +The subscriber object can be also used as [an asynchonous +generator]{.title-ref}. The example of the subscriber object usage in +[async for]{.title-ref} statement: + +``` {.python} +async def my_coroutine(self): + # Subscribe for a two application events + subscriber = asab.Subscriber( + self.PubSub, + "Application.tick!", + "Application.exit!" + ) + async for message_type, args, kwargs in subscriber: + if message_type == "Application.exit!": + break; + print("Tick.") +``` + +Publishing +---------- + +Publish a message to the PubSub message bus. It will be delivered to +each subscriber synchronously. It means that the method returns after +each subscribed `callback` is called. + +The example of a message publish to the +`Application.PubSub`{.interpreted-text role="any"} message bus: + +``` {.python} +def my_function(app): + app.PubSub.publish("mymessage!") +``` + +Asynchronous publishing of a message is requested by +`asynchronously=True` argument. The `publish()` method returns +immediatelly and the delivery of the message to subscribers happens, +when control returns to the event loop. + +The example of a **asynchronous version** of a message publish to the +`Application.PubSub`{.interpreted-text role="any"} message bus: + +``` {.python} +def my_function(app): + app.PubSub.publish("mymessage!", asynchronously=True) +``` + +Synchronous vs. asynchronous messaging +-------------------------------------- + +ASAB PubSub supports both modes of a message delivery: synchronous and +asynchronous. Moreover, PubSub also deals with modes, when asynchronous +code (coroutine) does publish to synchronous code and vice versa. + + -------------- ---------------------- ------------------------------------ + Sync publish Async publish + + Sync subscribe Called immediately `call_soon(...)` + + Async `ensure_future(...)` `call_soon(...)` & + subscribe `ensure_future(...)` + -------------- ---------------------- ------------------------------------ + +Application-wide PubSub +----------------------- + +The ASAB provides the application-wide Publish-Subscribe message bus. + +### Well-Known Messages + +This is a list of well-known messages, that are published on a +`Application.PubSub` by ASAB itself. + +%TODO: option% +Application.init! +xxx + +This message is published when application is in the init-time. It is +actually one of the last things done in init-time, so the application +environment is almost ready for use. It means that configuration is +loaded, logging is setup, the event loop is constructed etc. + +%TODO: option% +Application.run! +xxx + +This message is emitted when application enters the run-time. + +%TODO: option% +Application.stop! +xxx + +This message is emitted when application wants to stop the run-time. It +can be sent multiple times because of a process of graceful run-time +termination. The first argument of the message is a counter that +increases with every `Application.stop!` event. + +%TODO: option% +Application.exit! +xxx + +This message is emitted when application enter the exit-time. + +%TODO: option% +Application.tick! +xxx + +%TODO: option% +Application.tick/10! +xxx + +%TODO: option% +Application.tick/60! +xxx + +%TODO: option% +Application.tick/300! +xxx + +%TODO: option% +Application.tick/600! +xxx + +%TODO: option% +Application.tick/1800! +xxx + +%TODO: option% +Application.tick/3600! +xxx + +%TODO: option% +Application.tick/43200! +xxx + +%TODO: option% +Application.tick/86400! +xxx + +The application publish periodically \"tick\" messages. The default tick +frequency is 1 second but you can change it by configuration +`[general] tick_period`. `Application.tick!`{.interpreted-text +role="any"} is published every tick. +`Application.tick/10!`{.interpreted-text role="any"} is published every +10th tick and so on. + +%TODO: option% +Application.hup! +xxx + +This message is emitted when application receives UNIX signal `SIGHUP` +or equivalent. + +%TODO: option% +Application.housekeeping! +xxx + +This message is published when application is on the time for +housekeeping. The time for housekeeping is set to 03:00 AM UTC by +default. + +The app listens every ten minutes to see if it\'s time for housekeeping. +If the UTC time reaches the value for housekeeping, the app will publish +it and set the time for the next housekeeping for the next day at the +same time. There is also a time limit, which is set to 05:00 AM UTC by +default. If the computer is in a sleep state, housekeeping will not be +performed. Then, when the computer is reawakened again, it will check if +it has exceeded the time limit. If not, then housekeeping will be +published. If it has exceeded it, it simply informs the user and sets +the housekeeping time for the next day. Note that this only limits the +time when the housekeeping can start. If the housekeeping event triggers +a procedure that takes a long time to finish, it will not be terminated +when the time limit is reached. + +Both housekeeping time and time limit can be changed in the +configuration file: + +``` {.ini} +[housekeeping] +at=19:30 +limit=21:00 +``` + +This sets the housekeeping time to 7:30 PM UTC and the time limit to +9:00 PM UTC. The time must be written in the format \'HH:MM\'. Remind +yourself that the time is set to UTC, so you should be careful when +operating in a different timezone. diff --git a/docs/asab/service.md b/docs/asab/service.md new file mode 100644 index 000000000..48c98523d --- /dev/null +++ b/docs/asab/service.md @@ -0,0 +1,53 @@ +Service +======= + +Service objects are registered at the service registry, managed by an +application object. See `Application.Services`{.interpreted-text +role="any"} for more details. + +An example of a typical service class skeleton: + +``` {.python} +class MyService(asab.Service): + + def __init__(self, app, service_name): + super().__init__(app, service_name) + ... + + async def initialize(self, app): + ... + + + async def finalize(self, app): + ... + + + def service_method(self): + .... +``` + +This is how a service is created and registered: + +``` {.python} +mysvc = MyService(app, "my_service") +``` + +This is how a service is located and used: + +``` {.python} +mysvc = app.get_service("my_service") +mysvc.service_method() +``` + +Each service is identified by its name. + +A reference to an :py`Application`{.interpreted-text role="class"} +object instance. + +Lifecycle +--------- + +Called when the service is initialized. It can be overriden by an user. + +Called when the service is finalized e.g. during application exit-time. +It can be overriden by an user. diff --git a/docs/asab/storage.md b/docs/asab/storage.md new file mode 100644 index 000000000..9cde30414 --- /dev/null +++ b/docs/asab/storage.md @@ -0,0 +1,528 @@ +xxx {.currentmodule} +asab.storage +xxx + +Storage +======= + +The ASAB\'s Storage Service supports data storage in-memory or in +dedicated document databases, including +[MongoDB](https://www.mongodb.com/) and +[ElasticSearch](https://www.elastic.co/). + +Configuration +------------- + +First, specify the storage type in the configuration. The options for +the storage type are: + +- \`inmemory\`: Collects data directly in memory +- \`mongodb\`: Collects data using MongoDB database. Depends on + [pymongo](https://pymongo.readthedocs.io/en/stable/) and + [motor](https://motor.readthedocs.io/en/stable/api-asyncio/asyncio_motor_collection.html) + libraries. +- \`elasticsearch\`: Collects data using ElasticSearch database. + Depends on [aiohttp](https://docs.aiohttp.org/en/latest/) library. + +Storage Service provides a unified interface for accessing and +manipulating collections across multiple database technologies. + +``` {.ini} +[asab:storage] +type=mongodb +``` + +For accessing the storage, simply add +[asab.storage.Module]{.title-ref}\` when initializing and register the +service. + +``` {.python} +class MyApplication(asab.Application): + + async def initialize(self): + + self.add_module(asab.storage.Module) + + async def main(self): + storage = self.get_service("asab.StorageService") +``` + +Manipulation with databases +--------------------------- + +### Upsertor + +Upsertor is an object that works like a pointer to the specified +database and optionally to object id. It is used for inserting new +objects, updating existing objects and deleting them. + +``` {.python} +u = storage.upsertor("test-collection") +``` + +The `StorageService.upsertor()`{.interpreted-text role="func"} method +creates an upsertor object associated with the specified collection. It +takes [collection]{.title-ref} as an argument and can have two +parameters [obj\_id]{.title-ref} and [version]{.title-ref}, which are +used for getting an existing object by its ID and version. + +### Inserting an object + +For inserting an object to the collection, use the +`Upsertor.set()`{.interpreted-text role="func"} method. + +``` {.python} +u.set("key", "value") +``` + +To execute these procedures, simply run the +`Upsertor.execute()`{.interpreted-text role="func"} coroutine method, +which commits the upsertor data to the storage and returns the ID of the +object. Since it is a coroutine, it must be awaited. + +``` {.python} +object_id = await u.execute() +``` + +The [Upsertor.execute()]{.title-ref} method has optional parameters +[custom\_data]{.title-ref} and [event\_type]{.title-ref}, which are used +for webhook requests. + +``` {.python} +object_id = await u.execute( + custom_data= {"foo": "bar"}, + event_type="object_created" + ) +``` + +### Getting a single object + +For getting a single object, use +`StorageService.get()`{.interpreted-text role="func"} coroutine method +that takes two arguments [collection]{.title-ref} and +[obj\_id]{.title-ref} and finds an object by its ID in collection. + +``` {.python} +obj = await storage.get(collection="test-collection", obj_id=object_id) +print(obj) +``` + +When the requested object is not found in the collection, the method +raises `KeyError`. Remember to handle this exception properly when using +databases in your services and prevent them from crashing! + +xxx {.note} +xxx {.title} +Note +xxx + +MongoDB storage service in addition provides a coroutine method +`get_by()`{.interpreted-text role="func"} which is used for accessing an +object by finding its key-value pair. + +``` {.python} +obj = await storage.get_by(database="test-collection", key="key", value="value") +``` +xxx + +### Updating an object + +For updating an object, first obtain the upsertor specifying its +[obj\_id]{.title-ref} and [version]{.title-ref}. + +``` {.python} +u = storage.upsertor( + collection="test-collection", + obj_id=object_id, + version=obj['_v'] +) +``` + +We strongly recommend to read the version from the object such as above. +That creates a soft lock on the record. It means that if the object is +updated by other component in meanwhile, your upsertor will fail and you +should retry the whole operation. The new objects should have a version +set to 0, which is done by default. + +After obtaining an upsertor, you can update the object via the +`Upsertor.set()`{.interpreted-text role="func"} coroutine. + +``` {.python} +u.set("key", "new_value") +object_id = await u.execute() +``` + +### Deleting an object + +For deleting an object from database, use the +`StorageService.delete()`{.interpreted-text role="func"} coroutine +method which takes arguments [collection]{.title-ref} and +[obj\_id]{.title-ref}, deletes the object and returns its ID. + +``` {.python} +deleted_id = await u.delete("test-collection", object_id) +``` + +Storing data in memory +---------------------- + +If the option [inmemory]{.title-ref} is set, ASAB will store data in its +own memory. In particular, [asab.StorageService]{.title-ref} is +initialized with an attribute [InMemoryCollections]{.title-ref} which is +a dictionary where all the collections are stored in. + +xxx {.note} +xxx {.title} +Note +xxx + +You can go through all the databases directly by accessing +[InMemoryCollections]{.title-ref} attribute, although we do not +recommend that. + +``` {.python} +import pprint + +storage = self.get_service("asab.StorageService") +pprint.pprint(storage.InMemoryCollections, indent=2) +``` +xxx + +Storing data in MongoDB +----------------------- + +If the option [mongodb]{.title-ref} is set, ASAB will store data in +MongoDB database. + +ASAB uses [motor library](https://pypi.org/project/motor/) which +provides non-blocking MongoDB driver for [asyncio]{.title-ref}. + +You can specify the database name and URL for MongoDB in config file +(the following example is the default configuration): + +``` {.ini} +[asab:storage] +type=mongodb +mongodb_uri=mongodb://localhost:27017 +mongodb_database=asabdb +``` + +You can use all the methods from the abstract class. MongoDB Storage +class provides in addition two methods, +`StorageService.get_by()`{.interpreted-text role="func"} and +`StorageService.collection()`{.interpreted-text role="func"}. + +The method `StorageService.get_by()`{.interpreted-text role="func"} is +used in the same way as `StorageService.get()`{.interpreted-text +role="func"} except that it takes the arguments [key]{.title-ref} and +[value]{.title-ref} instead of [obj\_id]{.title-ref}. + +``` {.python} +obj = await storage.get_by(database="test-collection", key="key", value="value") +``` + +The method `collection()`{.interpreted-text role="func"} is used for +accessing the database directly. It takes [collection]{.title-ref} as +the argument and returns +[motor.motor\_asyncio.AsyncIOMotorCollection]{.title-ref} object, which +can be used for calling MongoDB directives. + +``` {.python} +collection = await storage.collection("test-collection") +cursor = collection.find({}) +while await cursor.fetch_next: + data = cursor.next_object() + pprint.pprint(data) +``` + +The full list of methods suitable for this object is described in the +[official +documentation](https://motor.readthedocs.io/en/stable/api-asyncio/asyncio_motor_collection.html). + +Storing data in ElasticSearch +----------------------------- + +When using ElasticSearch, add configurations for URL, username and +password. + +``` {.ini} +[asab:storage] +type=elasticsearch +elasticsearch_url=http://localhost:9200/ +elasticsearch_username=JohnDoe +elasticsearch_password=lorem_ipsum_dolor?sit_amet!2023 +``` + +You can also specify the [refreshing +parameter](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-refresh.html#docs-refresh) +and scroll timeout for [ElasticSearch Scroll +API](https://www.elastic.co/guide/en/elasticsearch//reference/current/scroll-api.html). + +``` {.ini} +[asab:storage] +refresh=true +scroll_timeout=1m +``` + +ElasticSearch Storage provides in addition other methods for creating +index templates, mappings etc (see the Reference section). + +Encryption and decryption +------------------------- + +Data stored in the database can be encrypted using an algorithm that +adheres to the Advanced Encryption Standard (AES). + +### AES Key settings + +In order to use encryption, first make sure you have the [cryptography +package](https://pypi.org/project/cryptography/) installed. Then specify +the AES Key in the config file. + +``` {.ini} +[asab:storage] +aes_key=random_key_string +``` + +xxx {.note} +xxx {.title} +Note +xxx + +The AES Key is used as both an encryption and decryption key. It is +recommended to keep it in [a separate configuration +file](https://asab.readthedocs.io/en/latest/asab/config.html#including-other-configuration-files) +that is not exposed anywhere publicly. + +The actual binary AES Key is obtained from the [aes\_key]{.title-ref} +specified in the config file by encoding and hashing it using the +standard [hashlib](https://docs.python.org/3/library/hashlib.html) +algorithms, so do not worry about the length and type of the key. +xxx + +### Encrypting data + +The `Upsertor.set()`{.interpreted-text role="func"} method has an +optional boolean parameter [encrypt]{.title-ref} for encrypting the data +before they are stored. Only values of the type `bytes` can be +encrypted. If you want to encrypt other values, encode them first. + +``` {.python} +message = "This is a super secret message!" +number = 2023 +message_binary = message.encode("ascii") +number_binary = number.encode("ascii") + +u.set("message", message_binary, encrypt=True) +u.set("number", number_binary, encrypt=True) +object_id = await u.execute() +``` + +### Decrypting data + +The `StorageService.get()`{.interpreted-text role="func"} coroutine +method has an optional parameter [decrypt]{.title-ref} which takes an +`iterable` object (i.e. a list, tuple, set, \...) with the names of keys +whose values are to be decrypted. + +``` {.python} +data = await storage.get( + collection="test-collection", + obj_id=object_id, + decrypt=["message", "number"] + ) +``` + +If some of the keys to be decrypted are missing in the required +document, the method will ignore them and continue. + +xxx {.note} +xxx {.title} +Note +xxx + +Data that has been encrypted can be identified by the prefix +\"\$aes-cbc\$\" and are stored in a binary format. +xxx + +### Under the hood + +For encrypting data, we use the certified symmetric AES-CBC algorithm. +In fact, the abstract base class `StorageServiceABC`{.interpreted-text +role="class"} provides two methods `aes_encrypt()`{.interpreted-text +role="func"} and `aes_decrypt()`{.interpreted-text role="func"} that are +called automatically in `Upsertor.set()`{.interpreted-text role="func"} +and `StorageService.get()`{.interpreted-text role="func"} methods when +the parameter [encrypt]{.title-ref} or [decrypt]{.title-ref} is +specified. + +AES-CBC is a mode of operation for the Advanced Encryption Standard +(AES) algorithm that provides confidentiality and integrity for data. In +AES-CBC, the plaintext is divided into blocks of fixed size (usually 128 +bits), and each block is encrypted using the AES algorithm with a secret +key. + +CBC stands for \"Cipher Block Chaining\" and it is a technique that adds +an extra step to the encryption process to ensure that each ciphertext +block depends on the previous one. This means that any modification to +the ciphertext will produce a completely different plaintext after +decryption. + +The algorithm is a symmetric cipher, which is suitable for encrypting +large amounts of data. It requires much less computation power than +asymmetric ciphers and is much more useful for bulk encrypting large +amounts of data. + +Reference +--------- + +### StorageService + +Here is a list of methods of the abstract StorageService class which can +be used for all types of storages. + +xxx {.currentmodule} +asab.storage.service +xxx + +# TODO: autoclass% +StorageServiceABC + +# TODO: automethod% +upsertor +xxx + +# TODO: automethod% +get +xxx + +# TODO: automethod% +delete +xxx + +# TODO: automethod% +aes\_encrypt +xxx + +# TODO: automethod% +aes\_decrypt +xxx +xxx + +### Upsertor + +Here is a list of methods of the abstract Upsertor class which can be +used for all types of storages. + +xxx {.currentmodule} +asab.storage.upsertor +xxx + +# TODO: autoclass% +UpsertorABC + +# TODO: automethod% +set +xxx + +# TODO: automethod% +unset +xxx + +# TODO: automethod% +generate\_id +xxx + +# TODO: automethod% +execute +xxx +xxx + +### In-memory storage + +Here is a list of methods that are specific for the in-memory storage. + +xxx {.currentmodule} +asab.storage.inmemory +xxx + +# TODO: autoclass show-inheritance=""} +StorageService +xxx + +### MongoDB Storage + +Here is a list of methods that are specific for the MongoDB storage. + +xxx {.currentmodule} +asab.storage.mongodb +xxx + +# TODO: autoclass show-inheritance=""} +StorageService + +# TODO: automethod% +get\_by +xxx + +# TODO: automethod% +collection +xxx +xxx + +### ElasticSearch Storage + +Here is a list of methods that are specific for the ElasticSearch +storage. + +xxx {.currentmodule} +asab.storage.elasticsearch +xxx + +# TODO: autoclass show-inheritance=""} +StorageService + +# TODO: automethod% +session +xxx + +# TODO: automethod% +finalize +xxx + +# TODO: automethod% +mapping +xxx + +# TODO: automethod% +get\_index\_template +xxx + +# TODO: automethod% +put\_index\_template +xxx + +# TODO: automethod% +reindex +xxx + +# TODO: automethod% +scroll +xxx + +# TODO: automethod% +list +xxx + +# TODO: automethod% +count +xxx + +# TODO: automethod% +indices +xxx + +# TODO: automethod% +empty\_index +xxx +xxx diff --git a/docs/asab/various.md b/docs/asab/various.md new file mode 100644 index 000000000..1c82ddbd5 --- /dev/null +++ b/docs/asab/various.md @@ -0,0 +1,51 @@ +Various utility classes +======================= + +# TODO: automodule members="" undoc-members="" show-inheritance=""} +asab.abc +xxx + +Singleton +--------- + +# TODO: automodule members="" undoc-members=""} +asab.abc.singleton +xxx + +Usage: + +``` {.python} +import asab + +class MyClass(metaclass=asab.Singleton): + ... +``` + +Persistent dictionary +--------------------- + +# TODO: automodule members="" undoc-members="" show-inheritance=""} +asab.pdict +xxx + +*Note*: A recommended way of initializing the persistent dictionary: + +``` {.python} +PersistentState = asab.PersistentDict("some.file") +PersistentState.setdefault('foo', 0) +PersistentState.setdefault('bar', 2) +``` + +Timer +----- + +# TODO: automodule members="" undoc-members="" show-inheritance=""} +asab.timer +xxx + +Sockets +------- + +# TODO: automodule members="" undoc-members="" show-inheritance=""} +asab.socket +xxx diff --git a/docs/asab/web/auth.md b/docs/asab/web/auth.md new file mode 100644 index 000000000..c92e015d9 --- /dev/null +++ b/docs/asab/web/auth.md @@ -0,0 +1,18 @@ +Authorization +============= + +# TODO: autofunction% +require +xxx + +# TODO: autofunction% +noauth +xxx + +# TODO: autoclass% +AuthService + +# TODO: automethod% +install +xxx +xxx diff --git a/docs/asab/web/cors.md b/docs/asab/web/cors.md new file mode 100644 index 000000000..5ec171940 --- /dev/null +++ b/docs/asab/web/cors.md @@ -0,0 +1,23 @@ +Cross-Origin Resource Sharing (CORS) +==================================== + +When you create a web container, you specify a config section name. In +the example below it's \`myapp:web\`: + +``` {.python} +asab.web.WebContainer(self.WebService, "myapp:web") +``` + +You can then configure CORS by running your app with a config file with +this contents: + +``` {.INI} +[myapp:web] +cors=* +cors_preflight_paths=/* +``` + +- **cors**: contents of the Access-Control-Allow-Origin header +- **cors\_preflight\_paths**: a pattern for endpoints that shall + return responses to pre-flight requests (OPTIONS). Value must start + with \"/\". diff --git a/docs/asab/web/index.md b/docs/asab/web/index.md new file mode 100644 index 000000000..190bcd206 --- /dev/null +++ b/docs/asab/web/index.md @@ -0,0 +1,148 @@ +The web server +============== + +ASAB provides a web server in a :py`asab.web`{.interpreted-text +role="mod"} module. This module offers an integration of a +:py`aiohttp`{.interpreted-text role="mod"} [web +server](http://aiohttp.readthedocs.io/en/stable/web.html). + +1. Before you start, make sure that you have + :py`aiohttp`{.interpreted-text role="mod"} module installed. + +``` {.bash} +$ pip3 install aiohttp +``` + +2. The following code creates a simple web server application + +``` {.python} +#!/usr/bin/env python3 +import asab +import asab.web +import aiohttp + +class MyApplication(asab.Application): + + def __init__(self): + super().__init__() + + # Load the ASAB Web module + self.add_module(asab.web.Module) + + # Locate the ASAB Web service + websvc = self.get_service("asab.WebService") + + # Create the Web container + container = asab.web.WebContainer(websvc, 'my:web', config={"listen": "0.0.0.0:8080"}) + + # Add a route to the handler + container.WebApp.router.add_get('/hello', self.hello) + + # This is the web request handler + async def hello(self, request): + return aiohttp.web.Response(text='Hello!\n') + +if __name__ == '__main__': + app = MyApplication() + app.run() +``` + +3. Test it with [curl]{.title-ref} + +``` {.bash} +$ curl http://localhost:8080/hello +Hello! +``` + +Web Service +----------- + +Service location example: + +``` {.python} +from asab.web import Module +self.add_module(Module) +svc = self.get_service("asab.WebService") +``` + +Configuration +------------- + +The default configuration of the [web]{.title-ref} container in ASAB is +following: + +``` {.ini} +[web] +listen=0.0.0.0:8080 +``` + +Multiple listening interfaces can be specified: + +``` {.ini} +[web] +listen: + 0.0.0.0:8080 + :: 8080 +``` + +Multiple listening interfaces, one with HTTPS (TLS/SSL) can be +specified: + +``` {.ini} +[web] +listen: + 0.0.0.0 8080 + :: 8080 + 0.0.0.0 8443 ssl:web + +[ssl:web] +cert=... +key=... +... +``` + +Multiple interfaces, one with HTTPS (inline): + +``` {.ini} +[web] +listen: + 0.0.0.0 8080 + :: 8080 + 0.0.0.0 8443 ssl + +# The SSL parameters are inside of the WebContainer section +cert=... +key=... +... +``` + +Other available options are: + +> - [backlog]{.title-ref} +> - [rootdir]{.title-ref} +> - [servertokens]{.title-ref} (default value [full]{.title-ref}) +> - [cors]{.title-ref} +> - [cors\_preflight\_paths]{.title-ref} + +TLS/SSL paramereters: + +> - [cert]{.title-ref} +> - [key]{.title-ref} +> - [password]{.title-ref} +> - [cafile]{.title-ref} +> - [capath]{.title-ref} +> - [ciphers]{.title-ref} +> - [dh\_params]{.title-ref} +> - \`verify\_mode\`: one of [CERT\_NONE]{.title-ref}, +> [CERT\_OPTIONAL]{.title-ref} or [CERT\_REQUIRED]{.title-ref} +> - [check\_hostname]{.title-ref} +> - [options]{.title-ref} + +Sessions +-------- + +ASAB Web Service provides an implementation of the web sessions. + +TODO: \... + +TODO: \... diff --git a/docs/asab/web/restapidocs.md b/docs/asab/web/restapidocs.md new file mode 100644 index 000000000..a5aa6ff23 --- /dev/null +++ b/docs/asab/web/restapidocs.md @@ -0,0 +1,141 @@ +REST API Docs +============= + +ASAB\'s API service generates a [Swagger +documentation](https://swagger.io/specification) which automatically +shows all of your endpoints and you can add summaries, descriptions, +tags and more. + +If you want Authorization in Swagger docs, you will need an +OpenIDConnect endpoint. + +In your microservice +-------------------- + +First you need to initialize the API Service: + +``` {.python} +# Initialize API service +self.ApiService = asab.api.ApiService(self) + +# Introduce Web to API Service +self.ApiService.initialize_web() +``` + +After initializing the API Service a **/doc** endpoint will become +available. You will notice that some or none of your endpoints have +summaries, tags or descriptions. + +That\'s because you need to add a docstring to your endpoint method: + +``` {.python} +async def endpoint(self, request): + """ + Summary looks like this and takes the first line from docstring. + + Description of what this endpoint does. + + --- + tags: [asab.mymicroservice] + """ +``` + +Also by adding a docstring to your ASAB Application, a description will +be automatically added to the top of the Swagger docs: + +``` {.python} +class TutorialApp(asab.Application): + """ + TutorialApp is the best microservice in the world! + + The description supports HTML tags + """ +``` + +Authorization in Swagger +------------------------ + +Authorization requires making an OpenIDConnect endpoint with an +Authorization and Token endpoint (like with using [SeaCat +Auth](https://github.com/TeskaLabs/seacat-auth)). + +After your endpoint has authorization, [here\'s an +example](https://github.com/TeskaLabs/asab/blob/master/examples/web-authz-userinfo.py), +add the Authorization and Token endpoints into your +[config](#configuration). + +For the authorization bearer token to be added to the request, a scope +is needed to be put into the security parameter in a docstring. It does +not matter what it is called or if it exists, but it\'s needed to be +there. But \"[- oAuth:]{.title-ref}\" always needs to be there. + +``` {.python} +@asab.web.authz.required("resource:topsecret") +async def top_secret_endpoint(self, request): + """ + Top secret! + + --- + tags: [asab.coolestmicroservice] + security: + - oAuth: + - read + """ +``` + +After setting up Authorization, a green [Authorize]{.title-ref} button +should appear in the Swagger docs. + +Configuration +------------- + +For authorization you will need to add a [authorizationUrl]{.title-ref} +and \`tokenUrl\`: + +``` {.ini} +[asab:doc] +authorizationUrl=http://localhost:8080/openidconnect/authorize +tokenUrl=http://localhost:8080/openidconnect/token +``` + +If you have an endpoint that requires a scope, you can add it with the +configuration file: + +``` {.ini} +[asab:doc] +scopes=read,write +``` + +Tags +---- + +You can label your handler methods with custom tags. These tags are used +for grouping and sorting your endpoints on the documentation page. + +``` {.python} +async def my_method(self, request): +""" +--- +tags: ['custom tag 1', 'custom tag 2', 'custom tag 3'] +""" +``` + +(Remember to use exactly three dashes on the separate line and put tags +in array with [\[\]]{.title-ref} even if you want to have a single tag). + +If there is no custom tag defined, the tag name is automatically set to +be [module\_name]{.title-ref}. If you do not want to use custom tags but +still would like to sort the routes, you can configure the options in +the config file: + +``` {.ini} +[asab:doc] +default_route_tag=class_name +``` + +There are two options for \`default\_route\_tag\`: + +- \`module\_name\`: All tags without custom name are displayed with + the name of the **module** where the handler is defined. +- \`class\_name\`: All tags without custom name are displayed with the + name of the **class** where the handler is defined. diff --git a/docs/asab/zookeeper.md b/docs/asab/zookeeper.md new file mode 100644 index 000000000..d3a9a0f9f --- /dev/null +++ b/docs/asab/zookeeper.md @@ -0,0 +1,190 @@ +Zookeeper {#zookeeper-ref} +========= + +The [asab.zookeeper]{.title-ref} is a [Apache +Zookeeper](https://zookeeper.apache.org) asynchronous client based on +[Kazoo](https://github.com/python-zk/kazoo) library. + +Apache ZooKeeper is a distributed coordination service that provides a +hierarchical key-value data store, called a znode tree, to store and +manage configuration, coordination, and synchronization data. The znode +tree is similar to a file system tree, where each znode is like a file +or a directory. + +Apache ZooKeeper can be used to design microservices in a stateless +manner by managing and coordinating the state information between +microservices. In this design, each microservice does not store any +state information, but instead relies on ZooKeeper for state management. + +Zookeeper container +------------------- + +A Zookeeper container represents a connectivity to Apache Zookeeper +server(s). The application can operate multiple instances of Zookeeper +container. + +This code illustrates the typical way how to create Zookeeper container: + +``` {.python} +import asab.zookeeper + +class MyApplication(asab.Application): + + def __init__(self): + ... + + # Load the ASAB Zookeeper module + self.add_module(asab.zookeeper.Module) + + # Initialize ZooKeeper Service + self.ZooKeeperService = self.get_service("asab.ZooKeeperService") + + # Create the Zookeeper container + self.ZooKeeperContainer = asab.zookeeper.ZooKeeperContainer(self.ZooKeeperService) + + # Subscribe to Zookeeper container ready event + self.PubSub.subscribe("ZooKeeperContainer.state/CONNECTED!", self._on_zk_connected) + + + async def _on_zk_connected(self, event_name, zookeeper): + if zookeeper != self.ZooKeeperContainer: + return + + print("Connected to Zookeeper!") +``` + +# TODO: autoclass% +ZooKeeperContainer +xxx + +Specifications are obtained from: + +1. [z\_path]{.title-ref} argument, which is Zookeeper URL (see below) +2. the configuration section specified by + [config\_section\_name]{.title-ref} argument +3. [ASAB\_ZOOKEEPER\_SERVERS]{.title-ref} environment variable + +The [z\_path]{.title-ref} argument has precedence over config but the +implementation will look at configuration if [z\_path]{.title-ref} URL +is missing completely or partially. Also, if configuration section +doesn\'t provide information about servers, +[ASAB\_ZOOKEEPER\_SERVERS]{.title-ref} environment variable is used. + +### Example of configuration section + +``` {.ini} +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=myfolder +``` + +### Example of [ASAB\_ZOOKEEPER\_SERVERS]{.title-ref} environment variable + +``` {.ini} +ASAB_ZOOKEEPER_SERVERS=zookeeper-1:2181,zookeeper-2:2181 +``` + +### Supported types of [z\_path]{.title-ref} URLs + +1. Absolute URL + + > [zookeeper://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/etc/configs/file1]{.title-ref} + > + > The URL contains all information for a connectivity. + +2. URL without servers with absolute path + + > [zookeepers:///etc/configs/file1]{.title-ref} + > + > In this case the relative url is expanded as follows: + > [zookeeper://{zookeeper\_servers}/etc/configs/file1]{.title-ref} + > + > Where [{zookeeper\_servers}]{.title-ref} is substituted with the + > [servers]{.title-ref} entry of the \[zookeeper\] configuration + > file section. + +3. URL without servers with relative path + + > [zookeeper:./etc/configs/file1]{.title-ref} + > + > In this case, the relative URL is expanded as follows: + > [zookeper://{zookeeper\_servers}/{zookeeper\_path}/etc/configs/file1]{.title-ref} + > + > Where {zookeeper\_servers} is substituted with the + > [servers]{.title-ref} entry of the \[zookeeper\] configuration + > file section and {zookeeper\_path} is substituted with the + > \"path\" entry of the \[zookeeper\] configuration file section. + +# TODO: automethod% +ZooKeeperContainer.is\_connected +xxx + +Reading from Zookeeeper +----------------------- + +# TODO: automethod% +ZooKeeperContainer.get\_children +xxx + +# TODO: automethod% +ZooKeeperContainer.get\_data +xxx + +# TODO: automethod% +ZooKeeperContainer.get\_raw\_data +xxx + +Advertisement into Zookeeper +---------------------------- + +# TODO: automethod% +ZooKeeperContainer.advertise +xxx + +PubSub messages +--------------- + +%TODO: option% +ZooKeeperContainer.state/CONNECTED! +xxx + +%TODO: option% +ZooKeeperContainer.state/LOST! +xxx + +%TODO: option% +ZooKeeperContainer.state/SUSPENDED! +xxx + +When a Zookeeper connection is first created, it is in the LOST state. +After a connection is established it transitions to the CONNECTED state. +If any connection issues come up or if it needs to connect to a +different Zookeeper cluster node, it will transition to SUSPENDED to let +you know that commands cannot currently be run. The connection will also +be lost if the Zookeeper node is no longer part of the quorum, resulting +in a SUSPENDED state. + +Upon re-establishing a connection the client could transition to LOST if +the session has expired, or CONNECTED if the session is still valid. + +For mor info, visit: + + +Kazoo +----- + +Kazoo is the synchronous Python library for Apache Zookeeper. + +It can be used directly for a more complicated tasks. Kazoo +[client]{.title-ref} is accessible at +[ZooKeeperContainer.ZooKeeper.Client]{.title-ref}. Synchronous methods +of Kazoo client must be executed using [ProactorService]{.title-ref}. + +Here is the example: + +``` {.python} +def write_to_zk(): + self.ZooKeeperContainer.ZooKeeper.Client.create(path, data, sequence=True, ephemeral=True, makepath=True) + +await self.ZooKeeperContainer.ZooKeeper.ProactorService.execute(write_to_zk) +``` diff --git a/docs/get-started.md b/docs/get-started.md new file mode 100644 index 000000000..4fa1f908e --- /dev/null +++ b/docs/get-started.md @@ -0,0 +1,101 @@ +Getting started +=============== + +Make sure you have both [pip](https://pip.pypa.io/en/stable/installing/) +and at least version 3.7 of Python before starting. ASAB uses the new +`async`/`await` syntax, so earlier versions of python won\'t work. + +1. Install ASAB: + +``` {.bash} +$ pip3 install asab +``` + +2. Create a file called `main.py` with the following code: + +``` {.python} +#!/usr/bin/env python3 +import asab + +class MyApplication(asab.Application): + async def main(self): + print("Hello world") + +if __name__ == '__main__': + app = MyApplication() + app.run() +``` + +3. Run the server: + +``` {.bash} +$ python3 main.py +Hello world +``` + +You are now successfully runinng an ASAB application server. + +4. Stop the application by `Control-C`. + +Note: The ASAB is designed around a so-called [event +loop](https://en.wikipedia.org/wiki/Event_loop). It is meant primarily +for server architectures. For that reason, it doesn\'t terminate and +continue running and serving eventual requests. + +Going into details +------------------ + +``` {.python} +#!/usr/bin/env python3 +``` + +ASAB application uses a Python 3.7+. This is specified a by hashbang +line at the very begginig of the file, on the line number 1. + +``` {.python} +import asab +``` + +ASAB is included from as [asab]{.title-ref} module via an import +statement. + +``` {.python} +class MyApplication(asab.Application): +``` + +Every ASAB Application needs to have an application object. It is a +singleton; it means that the application must create and operate +precisely one instance of the application. ASAB provides the base +`Application`{.interpreted-text role="any"} class that you need to +inherit from to implement your custom application class. + +``` {.python} +async def main(self): + print("Hello world") +``` + +The `Application.main()`{.interpreted-text role="any"} method is one of +the application lifecycle methods, that you can override to implement +desired application functionality. The [main]{.title-ref} method is a +coroutine, so that you can await any tasks etc. in fully asynchronous +way. This method is called when ASAB application is executed and +initialized. The lifecycle stage is called \"runtime\". + +In this example, we just print a message to a screen. + +``` {.python} +if __name__ == '__main__': + app = MyApplication() + app.run() +``` + +This part of the code is executed when the Python program is launched. +It creates the application object and executes the +`Application.run()`{.interpreted-text role="any"} method. This is a +standard way of how ASAB application is started. + +Next steps +---------- + +Check out tutorials about how to build ASAB based +`web server `{.interpreted-text role="doc"}. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..ec4a7b6f8 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,45 @@ +# Asynchronous Server Application Boilerplate\'s documentation + + +Asynchronous Server App Boilerplate (or ASAB for short) is a +microservice platform for Python 3.7+ and [asyncio]{.title-ref}. ASAB +aims to minimize the amount of code that needs to be written when +building a microservice or an application server. ASAB is fully +asynchronous using async/await syntax from Python 3, making your code +modern, non-blocking, speedy and hence scalable. We make every effort to +build ASAB container-friendly so that you can deploy ASAB-based +microservice via Docker or Kubernetes in a breeze. + +ASAB is free and open-source software, available under BSD licence. It +means that anyone is freely licenced to use, copy, study, and change the +software in any way, and the source code is openly shared so that people +could voluntarily improve the design of the software. Anyone can (and is +encouraged to) use ASAB in his or her projects, for free. A current +maintainer is a [TeskaLabs Ltd](https://teskalabs.com) company. + +ASAB is developed [on GitHub](https://github.com/TeskaLabs/asab/). +Contributions are welcome! + +# ASAB is designed to be powerful yet simple + + +Here is a complete example of a fully working microservice: + +``` python +import asab + +class MyApplication(asab.Application): + async def main(self): + print("Hello world!") + self.stop() + +if __name__ == "__main__": + app = MyApplication() + app.run() +``` + +# ASAB is the right choice when + +- using Python 3.7+. +- building the microservice or the application server. +- utilizing asynchronous I/O (aka [asyncio](https://docs.python.org/3/library/asyncio.html)). diff --git a/docs/tutorial/chapter1.md b/docs/tutorial/chapter1.md new file mode 100644 index 000000000..ef26144b6 --- /dev/null +++ b/docs/tutorial/chapter1.md @@ -0,0 +1,66 @@ +Web Server Tutorial +=================== + +Create a simple web server with ASAB. + +The code +-------- + +``` {.python} +``` + +| To start the application, store above code in a file `app.py`. +| Execute `$ python3 ./app.py` to run it. + +The ASAB web server is now available at . + +Deeper look +----------- + +**ASAB Application** + +``` {.python} +#!/usr/bin/env python3 +import asab.web.rest + +class MyWebApplication(asab.Application): + + def __init__(self): + super().__init__() + +if __name__ == '__main__': + app = MyWebApplication() + app.run() +``` + +This is a ASAB code that declares the application class and runs it. + +**Create a Web server** + +The `asab.web` module provides a `create_web_server()` function that +simplifies creation of the Web server in the ASAB application. + +``` {.python} +web = asab.web.create_web_server(self) +``` + +**Install the handler** + +``` {.python} +web.add_get('/hello', self.hello) + +... + +async def hello(self, request): + return asab.web.rest.json_response( + request, + data="Hello, world!\n" + ) +``` + +The handler method `hello()` is installed at the web server at `/hello` +endpoint. HTTP method is `GET`. + +It means that if you access the web server with a path `/hello`, it will +be handled by a `hello(...)` method. A handler method must be a +coroutine. diff --git a/docs/tutorial/chapter2.md b/docs/tutorial/chapter2.md new file mode 100644 index 000000000..f87362046 --- /dev/null +++ b/docs/tutorial/chapter2.md @@ -0,0 +1,661 @@ +Create microservice with REST API +================================= + +With this tutorial, you will create a basic ASAB microservice that +provides a REST HTTP API. This microservice will implement Create, Read, +Update and Delete functionality, in another words CRUD. MongoDB will be +used as the database. + +Prerequisites +------------- + +1. Python version 3.6 or later +2. Asynchronous Server App Boilerplate (ASAB) version 20.3 or later +3. MongoDB instance +4. Postman + +xxx {.note} +xxx {.title} +Note +xxx + +We will use Docker to run MongoDB. Docker installation is not covered in +this tutorial, but there are scores of good ones online should you run +into any trouble. If you\'re not familiar with Docker yet, it is a great +opportunity to start (). + +Otherwise, you can install MongoDB following one of these tutorials: + +xxx + +Components +---------- + +The microservice consists of several modules (aka Python files). These +modules are as follows (and also indicate the file structure) and will +be discussed in more detail in the respective sections below, going from +top to bottom: + +``` {.} +. +└── myrestapi.py +─── myrestapi + └── __init__.py + ─── app.py + ─── tutorial + └── handler.py + └── service.py +``` + +MongoDB +------- + +To make things simple, let\'s use a Docker image. + +Pull this image: + +You can simply use the command below to run it. If you choose to run the +instance without a password, don\'t forget to adjust the related +**asab.Config** in [./myrestapi/app.py]{.title-ref}. + +``` {.bash} +docker run -d -p 27017:27017 \ + -e MONGO_INITDB_ROOT_USERNAME=user \ + -e MONGO_INITDB_ROOT_PASSWORD=secret \ + mongo +``` + +Postman +------- + +We use Postman to test the webservice REST API. + +You can download it here: + +The Postman is fairly straightforward to use. You can create your +collection of HTTP requests, save them, or automatically generate +documentation. + +myrestapi.py +------------ + +This is where everything starts. Begin with the shebang line, which +tells the executing operating system **python** should execute this +program. + +``` {.python} +#!/usr/bin/env python3 +``` + +Imports follow. All you need here is the application. It is called +**TutorialApp**: + +``` {.python} +from myrestapi import TutorialApp +``` + +Next, instantiate an application class [TutorialApp]{.title-ref} in the +\_\_[main](#init__.py) of the application, and run it: + +``` {.python} +if __name__ == '__main__': + app = TutorialApp() + app.run() +``` + +app.py +------ + +[./myrestapi/app.py]{.title-ref} + +Define the application class [TutorialApp]{.title-ref}. + +Imports first: + +``` {.python} +import asab +import asab.web +import asab.web.rest +import asab.storage +``` + +Add some default configuration: + +``` {.python} +asab.Config.add_defaults( +{ + 'asab:storage': { + 'type': 'mongodb', + 'mongodb_uri': 'mongodb://mongouser:mongopassword@mongoipaddress:27017', + 'mongodb_database': 'mongodatabase' + }, +}) +``` + +xxx {.note} +xxx {.title} +Note +xxx + +To make things more simple, Mongo credentials are stored here as a +default configuration. Usually, you provide your app with a +configuration file using [-c]{.title-ref} commandline option. Learn more +in section `configuration-ref`{.interpreted-text role="ref"}. +xxx + +Next, describe the class, it inherits from the basic ASAB Application +class, but you need to expand it a little: + +``` {.python} +class TutorialApp(asab.Application): + + def __init__(self): + super().__init__() + # Register modules + self.add_module(asab.web.Module) + self.add_module(asab.storage.Module) + + # Locate the web service + self.WebService = self.get_service("asab.WebService") + self.WebContainer = asab.web.WebContainer( + self.WebService, "web" + ) + self.WebContainer.WebApp.middlewares.append( + asab.web.rest.JsonExceptionMiddleware + ) + + # Initialize services + from .tutorial.handler import CRUDWebHandler + from .tutorial.service import CRUDService + self.CRUDService = CRUDService(self) + self.CRUDWebHandler = CRUDWebHandler( + self, self.CRUDService + ) +``` + +\_\_init\_\_.py +--------------- + +[./myrestapi/\_\_init\_\_.py]{.title-ref} + +Init file is needed so myrestapi will work as a module. Just import the +TutorialApp. + +``` {.python} +from .app import TutorialApp + +__all__ = [ + "TutorialApp", +] +``` + +handler.py +---------- + +[./myrestapi/tutorial/handler.py]{.title-ref} + +The handler is where HTTP Rest calls are handled and transformed into +the actual (internal) service calls. From another perspective, the +handler should contain only translation between REST calls and the +service interface. No actual \'business logic\' should be here. It is +strongly suggested to build these CRUD methods one by one and test them +straight away. If you haven\'t set up your database test instance yet, +now is the time to do it. + +As usual, we start by importing modules: + +``` {.python} +import asab +import asab.web.rest +``` + +Let\'s start with two methods - [create]{.title-ref} and +[read]{.title-ref} which allow us to write into database and check the +record. + +``` {.python} +class CRUDWebHandler(object): + def __init__(self, app, mongo_svc): + self.CRUDService = mongo_svc + web_app = app.WebContainer.WebApp + web_app.router.add_put( + '/crud-myrestapi/{collection}', + self.create + ) + web_app.router.add_get( + '/crud-myrestapi/{collection}/{id}', + self.read + ) + + + @asab.web.rest.json_schema_handler({ + 'type': 'object', + 'properties': { + '_id': {'type': 'string'}, + 'field1': {'type': 'string'}, + 'field2': {'type': 'number'}, + 'field3': {'type': 'number'} + }}) + async def create(self, request, *, json_data): + collection = request.match_info['collection'] + + result = await self.CRUDService.create( + collection, json_data + ) + if result: + return asab.web.rest.json_response( + request, {"result": "OK"} + ) + else: + asab.web.rest.json_response( + request, {"result": "FAILED"} + ) + + + async def read(self, request): + collection = request.match_info['collection'] + key = request.match_info['id'] + response = await self.CRUDService.read( + collection, key + ) + return asab.web.rest.json_response( + request, response + ) +``` + +The handler only accepts the incoming requests and returns appropriate +responses. All of the \"logic\", be it the specifics of the database +connection, additional validations and other operations take place in +the CRUDService. + +POST and PUT requests typically come with data in their body. Providing +your [WebContainer]{.title-ref} with +[JsonExceptionMiddleware]{.title-ref} enables you to validate a JSON +input using [\@asab.web.rest.json\_schema\_handler]{.title-ref} +decorator and JSON schema (). + +xxx {.note} +xxx {.title} +Note +xxx + +ASAB WebServer is built on top of the aiohttp library. For further +details please visit . +xxx + +service.py +---------- + +[./myrestapi/tutorial/service.py]{.title-ref} + +As mentioned above, this is where the inner workings of the microservice +request processing are. Let\'s start as usual, by importing the desired +modules: + +``` {.python} +import asab +import asab.storage.exceptions +``` + +We want to start logging in here: + +``` {.python} +import logging +# + +L = logging.getLogger(__name__) + +# +``` + +Now define the CRUDService class which inherits from the +[asab.Service]{.title-ref} class. + +xxx {.note} +xxx {.title} +Note +xxx + +[asab.Service]{.title-ref} is a lightweight yet powerful abstract class +providing your object with 3 functionalities: + +- Name of the [asab.Service]{.title-ref} is registered in the app and + can be called from the [app]{.title-ref} object anywhere in your + code. +- [asab.Service]{.title-ref} class implements + [initialize()]{.title-ref} and [finalize()]{.title-ref} coroutines + which help you to handle asynchronous operations in init and exit + time of your application. +- [asab.Service]{.title-ref} registers application object as + [self.App]{.title-ref} for you. +xxx + +``` {.python} +class CRUDService(asab.Service): + + def __init__(self, app, service_name='crud.CRUDService'): + super().__init__(app, service_name) + self.MongoDBStorageService = app.get_service( + "asab.StorageService" + ) + + async def create(self, collection, json_data): + obj_id = json_data.pop("_id") + + cre = self.MongoDBStorageService.upsertor( + collection, obj_id + ) + + for key, value in zip( + json_data.keys(), json_data.values() + ): + cre.set(key, value) + + try: + await cre.execute() + return "OK" + except asab.storage.exceptions.DuplicateError: + L.warning( + "Document you are trying to create already exists." + ) + return None + + async def read(self, collection, obj_id): + response = await self.MongoDBStorageService.get( + collection, obj_id + ) + return response +``` + +[asab.StorageService]{.title-ref} initialized in [app.py]{.title-ref} as +part of the [asab.storage.Module]{.title-ref} enables connection to +MongoDB. Further on, two methods provide the handler with the desired +functionalities. + +Now test it! +------------ + +The application is implicitly running on an **8080** port. Open the +Postman and set a new request. + +Try the PUT method: + +``` {.} +127.0.0.1:8080/crud-myrestapi/movie +``` + +Insert into the request body: + +``` {.} +{ +"_id": "1", +"field1": "something new", +"field2": 5555, +"field3": 44424 +} +``` + +When there\'s a record in your database, try to read it! For example +with this GET request: + +``` {.} +127.0.0.1:8080/crud-myrestapi/movie/1 +``` + +Is your response with a 200 status code? Does it return desired data? + +xxx {.note} +xxx {.title} +Note +xxx + +**TROUBLESHOOTING** + +**ERROR** + +``` {.} +ModuleNotFoundError: No module named 'pymongo.mongo_replica_set_client' +``` + +Try: + +``` {.} +pip install motor +``` + +**ERROR** + +``` {.} +OSError: [Errno 98] error while attempting to bind on address ('0.0.0.0', 8080): address already in use +``` + +Try to kill process listening on 8080 or add \[web\] section into +configuration: + +``` {.} +asab.Config.add_defaults( +{ + 'asab:storage': { + 'type': 'mongodb', + 'mongodb_uri': 'mongodb://mongouser:mongopassword@mongoipaddress:27017', + 'mongodb_database': 'mongodatabase' + }, + 'web': { + 'listen': '0.0.0.0 8081' + } +}) +``` + +**ERROR** + +No error at all, no response either. + +Try to check the Mongo database credentials. Do your credentials in the +configuration in [app.py]{.title-ref} fit the ones you entered when +running the Mongo Docker image? +xxx + +Up and running! Congratulation on your first ASAB microservice! + +Oh, wait\... + +**C**, **R**\... What about **Update** and **Delete** you ask? + +You already know everything to add the next functionality! Accept the +challenge and try it yourself! Or check out the code below. + +Update and Delete +----------------- + +**handler.py** + +[./myrestapi/tutorial/handler.py]{.title-ref} + +``` {.python} +import asab +import asab.web.rest + + +class CRUDWebHandler(object): + def __init__(self, app, mongo_svc): + self.CRUDService = mongo_svc + web_app = app.WebContainer.WebApp + web_app.router.add_put( + '/crud-myrestapi/{collection}', + self.create + ) + web_app.router.add_get( + '/crud-myrestapi/{collection}/{id}', + self.read + ) + web_app.router.add_put( + '/crud-myrestapi/{collection}/{id}', + self.update + ) + web_app.router.add_delete( + '/crud-myrestapi/{collection}/{id}', + self.delete + ) + + + @asab.web.rest.json_schema_handler({ + 'type': 'object', + 'properties': { + '_id': {'type': 'string'}, + 'field1': {'type': 'string'}, + 'field2': {'type': 'number'}, + 'field3': {'type': 'number'} + }}) + async def create(self, request, *, json_data): + collection = request.match_info['collection'] + + result = await self.CRUDService.create( + collection, json_data + ) + if result: + return asab.web.rest.json_response( + request, {"result": "OK"} + ) + else: + asab.web.rest.json_response( + request, {"result": "FAILED"} + ) + + + async def read(self, request): + collection = request.match_info['collection'] + key = request.match_info['id'] + response = await self.CRUDService.read( + collection, key + ) + return asab.web.rest.json_response( + request, response + ) + + + @asab.web.rest.json_schema_handler({ + 'type': 'object', + 'properties': { + '_id': {'type': 'string'}, + 'field1': {'type': 'string'}, + 'field2': {'type': 'number'}, + 'field3': {'type': 'number'} + }}) + async def update(self, request, *, json_data): + collection = request.match_info['collection'] + obj_id = request.match_info["id"] + + result = await self.CRUDService.update( + collection, obj_id, json_data + ) + if result: + return asab.web.rest.json_response( + request, {"result": "OK"} + ) + else: + asab.web.rest.json_response( + request, {"result": "FAILED"} + ) + + + async def delete(self, request): + collection = request.match_info['collection'] + obj_id = request.match_info["id"] + result = await self.CRUDService.delete( + collection, obj_id + ) + + if result: + return asab.web.rest.json_response( + request, {"result": "OK"} + ) + else: + asab.web.rest.json_response( + request, {"result": "FAILED"} + ) +``` + +**service.py** + +[./myrestapi/tutorial/service.py]{.title-ref} + +``` {.python} +import asab +import asab.storage.exceptions + +import logging +# + +L = logging.getLogger(__name__) + +# + + +class CRUDService(asab.Service): + + def __init__(self, app, service_name='crud.CRUDService'): + super().__init__(app, service_name) + self.MongoDBStorageService = app.get_service( + "asab.StorageService" + ) + + async def create(self, collection, json_data): + obj_id = json_data.pop("_id") + + cre = self.MongoDBStorageService.upsertor( + collection, obj_id + ) + + for key, value in zip( + json_data.keys(), json_data.values() + ): + cre.set(key, value) + + try: + await cre.execute() + return "OK" + except asab.storage.exceptions.DuplicateError: + L.warning( + "Document you are trying to create already exists." + ) + return None + + + async def read(self, collection, obj_id): + response = await self.MongoDBStorageService.get( + collection, obj_id + ) + return response + + + async def update(self, collection, obj_id, document): + original = await self.read( + collection, obj_id + ) + + cre = self.MongoDBStorageService.upsertor( + collection, original["_id"], original["_v"] + ) + + for key, value in zip( + document.keys(), document.values() + ): + cre.set(key, value) + + try: + await cre.execute() + return "OK" + + except KeyError: + return None + + + async def delete(self, collection, obj_id): + try: + await self.MongoDBStorageService.delete( + collection, obj_id + ) + return True + except KeyError: + return False +``` diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 000000000..982cdf07f --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,43 @@ +site_name: My Docs + +theme: + name: "material" + +plugins: + - mkdocstrings + +nav: + - Introduction: index.md + + - Get Started: + - get-started.md + - tutorial/chapter1.md + - tutorial/chapter2.md + + - Services: + - asab/web/index.md + - asab/web/auth.md + - asab/web/cors.md + - asab/web/restapidocs.md + - asab/library.md + + - Reference: + - asab/application.md + - asab/config.md + - asab/log.md + - asab/metrics.md + - asab/module.md + - asab/pubsub.md + - asab/service.md + - asab/storage.md + - asab/various.md + - asab/zookeeper.md + + - Administration: + - admin/command-line.md + - admin/containers.md + - admin/install.md + - admin/systemd.md + + - asab/index.md + - asab/alert.md \ No newline at end of file diff --git a/doc/Makefile b/old_docs/Makefile similarity index 100% rename from doc/Makefile rename to old_docs/Makefile diff --git a/doc/TODO.md b/old_docs/TODO.md similarity index 100% rename from doc/TODO.md rename to old_docs/TODO.md diff --git a/old_docs/_build/doctrees/admin/command-line.doctree b/old_docs/_build/doctrees/admin/command-line.doctree new file mode 100644 index 0000000000000000000000000000000000000000..f9f0b7f32a3ab0df47b8380ef7bd273f0e6dfc66 GIT binary patch literal 14162 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

RLE1P=Bx*##ExQ_N>rqD{_1*LH3aMtWdkd zx)mI(Z^>P(Em4SHU(bWYW&W=5^R!6ul_6riw-8y2oe92B!5~0;Z)*>De@WA21Zqe+ zG}vDof?X9v)B7nP@d@xSHWfGogcGF#-oFzpZRuwXweEX=4KQPu{nx$!rnv?AL+knP zLoFmDv7R@ij5QXA#aA`Of8vKwo6zMKu7S=`08Y+s^6Eu~JqabDi!qF!G z%RLb?0U>L^j-^DXqof2^+T{PaCrT!Tk~MJkv@8voLqXG=W+WQ0-`*2#OT)%CUUw&p z3fQ;TqQcqw1!@x6ok}9RqY~M1eOx=P?`Ph%3vi4x=dg3F9g)KdSQL(`=_{xx($^hL zF{_00jOlB$oGa4TPux@bS_^D+`g*g(fBN)w1Ui+zqM@pkB0^emsjTkSF_`O;))AP` zp0pkXrW~Lt3`*~{5=_C!}66!nN zm*{X;9!`<3-hP>-i5>3A^iqApdv{Vv4u~g0>_R5Z4aH%|C zn4YRCht}V+TkM%i+*NaULuO)H?}!?CQuX8xH;tf9r~$c3Wfb&PsiyIkY8qEHQ1Mt% zQW)+nxAYcZLN_6!qlj>5w;nINvXPvvA{k>3!1279)30^Ou+ALN&MVVDGA;%GNte1I>|n@^DT&3#mh`WZ$RV{|bOOcE}p z#sGO$jyS#}Moe-HvuKY8#(YBFFTcs>BZtbbrr21|UOdldndO(4ll-Ey??P4yT9M=8 zp-DbzJDqeJ=oYDPNGUhqI#wSeGf9NjU}7qJoiDn-jSAg)d{)69jGQj2*{1DK%^7H@t$dR=x}sr>B;wj8LRHV* zN6Nt$tuzTuHN?*&UE~XP+8>yu;X$xsKsZWZ`2=uDj6k|UOzKxdgV;&!&_r7{o?1p> z7mZ4$K2umpH!*kJ*p()_gjXbZrSE_dYHP#9slp-HDxU{4FqdQuR8C(Xp^Lp_P;Mt26SCw}MmAkW39 z*Bt^+BMSWc3h;1Ni%fRMiPl^v=?NV4eFsbWK9J2MRtH{WCoFq$nyPg3}G3_(38uH~hPQnZzecBRYk;Yb&|5Ypcu zWg$Y$-bn{25z|*Z;?tZw4jjUI!mbK>p@KHQR2h}cE{_VLwFyjpKqd|;QbB#e2Z@UEq+oyL$hcfM0`9X<{gSThvNA|@hrMQ zuYEad3V>*#-oOV9-(ar_sOTwvhy7ZDr5;7mu_Zdhyf^8R`s_qAhez!mV&~PP%~|h@ z^druQ5b=s5DwiHrO1&@8k2s?@4Uck1&n?bUzMvbM;C=zyHo`N>z~uA@;m4FEFxYPg-4h*y@rL@ z2b3Fp(B{p2{0->#tJzENUVJ%#IDk(IV%V!hSO&hz@LV}8Om5B%x_)YtiEq=#V6!&G N<~)p1%8+)}{tvO!c!2-_ literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/admin/containers.doctree b/old_docs/_build/doctrees/admin/containers.doctree new file mode 100644 index 0000000000000000000000000000000000000000..57f0f75956b553f8ea430f03e2a04dcbc887e73b GIT binary patch literal 14810 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/admin/install.doctree b/old_docs/_build/doctrees/admin/install.doctree new file mode 100644 index 0000000000000000000000000000000000000000..658073e0312553b0d9800f4db10ce3bf62c5f3c7 GIT binary patch literal 5195 zcmcIo+io1k5hX<~$>p7tMA(ohjpCbZle>8c;6wC@({p)fqX%}!GHk+`GS0bAAwnBY$?uzP%ATk=OFf>O8E|+) z27bz;{G;5g6T6my>Xq*=D(-0+NA>HXBNoKsNBMoxH61N=z*}2p_1#Em76i<`LwsPH zKjLR}{?zW%ywGPMVK`mqV#{>hT3s<`7D_D-&3qsuo*!ldW|o=OsT^b)){!-H(pRMU zq8BiwK*Vz=Vqx*Lq&KX!Y0;rt!*!t+Gs zrDI`Lzp(01+=1^%DOk_pY=pjogXoz1S3TUGEq2U2sn=zD3hf!H+L?#I?u$L;w`eq+OVKmI^qqUVZgobbX=i%rC6x}s}!u) zm7{tO#bO zOe)7lJX10nIf+cFXgqJbfq}SMd`LCQ1zxaQ6_=n|uhwMmNC3O|uLXBf?!_TWi_d+h zOaYtrPRNljet}e=<@>$VXnlHhtt*EvSK3>otOZi@lm+e}h`p0G;XBWN_ea`)--rBJEgDpN$Y)!hJ8XqgXW6E+T}EOVO1j1A>^vE=+%L~1cP@k zz#wPp+%2`K-1nV)O?>}x_4pDhzi6Ry8}WTwqw@O8PFt0Ua9+4q$Mc_;#Z%y>P9@^6K&bvn_ zFG;MVj??o!V3<3@I0)h=RQssxu&608{}0iP2mXC^4^(An7s#-lnDoFKhq2~wJfJW* zf}x1U&VW}=u|?F0Qycl5bFw!HxaQV1C5&vPt(t+ZS>j;=ky5p*+(L0+ zm74Q(eCvbt->Vz;9~krvjM*`depK}vFMrckrb(yj3*AnH%FB0KUT%uPTa%@IB=wtB zdx2+>4SI0rR4>=VPUWTl`TeS>9Cv4DW`0Or`AK6};|TNOL|s8X@3Z~FpjPFtn2L&0 zBz?_vNi9LDwvJkDW2_~8nm#3Pu9f@ffiL+`R*k*bqrx_8*1asH5x}h*{?&?7H2!8u zajlX2m}s`@5d{?_(&#^Ov+$S&89M&Dsogj<-4T!Q^+y58vG5rN2F=0*ixEglpN-Ts*-}N zdWjv2?Ub6Eo5X1q0H>?*Il>))?Spx;|H@B)27j)nLvKnvQ5x~DR^pMYj39f$)1Ksd zXwRT|Tj((81F@P7kVU>0`N5Le1tvqcPS4r^w`j%3W>cLtg9*XkevlcRhh=-b46`e1n&*3-R_zmY}t#dlP#ZQr3Yn&=Y$y8Uh1V zVc4cpp|ZggpA0b(;4oHXBVBczeO zGh5{)4Zs=B002MOwsnbWD80GS{fHWfQ?TVB%h$* zO;C$V6p$fpSTAT!ru!Gr7l~Lr-#>m8Nq+ni{)oroL-D!zyZB0cd3=Ycx9}%3UEh1d|^e1uQRjOj=5E0&67Y5Spmfg z3Z-_%S6JJo6nwav07k+=9MmwftT(2JHFtMHVz)ZgzO+3dA5}Wl^jWw$Evwv_G0P}C zUYt>J$jyp}HW%@M4fyyh{-&gV3O7B?KR^=US_$ch>n#P?6bIJzXM(&^lWpWzWaI^z VPe>cl9oe!^C947Rs>Xez zyV`3bMOq#rtwo8KG|CISBJsfQfS6IiBGT7@e*9}6KCz+miLnrllpt29M8^6ik&o*^CW{;CFjUArp3z*>u z>A5ivvUfAxq3KF`Nv~KxmvBePFsPP`mY5ZD?`E5#ty@Yek2i+&T(X}i?z9$=RQcUaF;%wV`#*+chw$lOA3rwk44pN0X(H*9xo6vdZ z9FHXlI`Q2Kn4f>myJ=K62F%%s`H<$MdQPzs4P|0QyeO8$hL{%D^xeJ)ectzF+zBr5>2sRKd0DS>bgGn`a;hDc`FBbTf9W76rYFw#LHmE7x426eqP1T4d_OES=|Mx_@bIH-7LUlbNDV(P)G%A3 zfZM;3dk@jl-aU7mCdyKRTYQiC5!e|Ht@m=yez(EdZwjTNWUJpFNhQ)j&k6m*_5>sc zeV@T;#JO!Xkh=Sx-7{!yigmqy^sZUWv#7~4vNLFx!^hz2wH4~O|1ak(mAdvR5E=*k zb@PD78-kuO4oV*(OV8p?X)H5+_t~H|YTko-BSY+21?}^ux6=2lXVqSgNonqSt#FuK z@@ZZ2X&EbhKs8vC2ZM!Us4gvjOXSpgp;D}yJ(wyku}-FY3>o;ToX%o{?Y)xi`C}(; zmu=m9lPjyZinSAjk6{PQ7()yvofQ7Nu=UbA*T&O5)AEv5XIxdo@R!q3uIYO_fZ@-l z@x6aKrSBDw#M|N>0Qpn#Gu=u+HI?DHgenhv*$&9~iwfzD!l&k7JIb?ozy@$OQU`{aoXS z$6Mhy?mfKs9qV2cdD3ANpIQ&;t&6R~@GLxem6gIO$xabpx%<6^B4DZ&`Np|rmB>7U zgj${dJ-a$LfYrZGW2&E=!&JpzA50%*q#H2O#nMR2Twt~A&{rOkfm1+WV9nK10(JCY zg~9lRsS6iQ4+A3j@pIJ*6Q@}d9^`W+vGd5wI1Vd!Kt&LC!isi|prmm_Z8P2om={WGDIzwy{|U;u{7{9_F}gW&tX9qa z3h2`W@}!z?S1XKaHYZf`{L!ijqmnAePpB00<7ZUNYmGxrDCTkkn2y(r89tL*aQBAZ zt0cLOe;Qqfv^!m!F6EdfgpFn5EN+t7PU()5#*|{)RYJW~_T-7Ro=>=MD9(+1Bk54=BG4;|vWK87oNaM`$eO+aT=?cFhTS{eMB;m6a?s{+9L6?c z1J{E=Bl*PL9F^&nFjbRMT1HByuN@jWBx0Pw6m%z-Tc4p^y)ij(Xt7?UJ0t)~03y$1 zkIQAI2*h2aix*KI(wAfIgt2S8JOV$kjRZNi^{f*HLtGPxNY}1&>JCd)XxCl(q6Ddy z-PDilig*ClbVzV64wy#*S4<*86lB=QFgX&pA`5rcF zD>i@?xk_XY=Jhpj(zh$~tS(^Z^@Rhyn(POP?b%fY0YwEbBm1P4mTaEV++k`4~d zlRnBE*o@`YNTtM`44m-?sLUm5A4d=z8SjC<>R{H6&3z_48--JpO{k#w6gep*lgbnB z4Rg14pr?7TOC?D?pSu&-FQ_O3SHd`yo#)YpIBPf*sHIR&g$$Ppknh9cP4wnPN_0co zuxe0}PxVdo&rxUoy*UnGN4qF+P$<=|JU+cclbT&7HFRvd_ro|?%A zX5v9AUPc8jm$M`?@w;3I1yV+cdAC!&+*G|e%d#UuAi50Bm-mo`m-F&VH+%AVsLX;Y z{vh-!Hkqkc4s}+u+Y=Jo<*sJYr3v|YC}~q7vRHjct9eD*swk<;{alYnR?p zqZ&(+&zPckDvVE*2ho&I3cEv*!}~Jo<5kqgJ9@i z#G#Wyj8^e@PU)GvmOAr;?eG7HUaRHRLAI${P&vi}2o|F($$ literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/asab/alert.doctree b/old_docs/_build/doctrees/asab/alert.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4b1c43bfa24a375ec6523855331bc97b5b0b1c02 GIT binary patch literal 12257 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 HT(ABIzeV;m literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/asab/application.doctree b/old_docs/_build/doctrees/asab/application.doctree new file mode 100644 index 0000000000000000000000000000000000000000..90779e3a76b364d961899723b26b1614ef34933b GIT binary patch literal 54173 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 V8tM27+3A@YO-{m&^D|E7|1a~u>x}>a literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/asab/config.doctree b/old_docs/_build/doctrees/asab/config.doctree new file mode 100644 index 0000000000000000000000000000000000000000..f589b3fba2415231246ce25dd031b26a4fd2d314 GIT binary patch literal 32587 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/asab/index.doctree b/old_docs/_build/doctrees/asab/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..de8f584db20fabef260741fada61ae070c901e8a GIT binary patch literal 8814 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/asab/metrics.doctree b/old_docs/_build/doctrees/asab/metrics.doctree new file mode 100644 index 0000000000000000000000000000000000000000..234aa2d424fcc62f9828aee11b448dbf6d47813d GIT binary patch literal 161386 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/asab/pubsub.doctree b/old_docs/_build/doctrees/asab/pubsub.doctree new file mode 100644 index 0000000000000000000000000000000000000000..dc9d6b40b97566f7ecd48ef156141f875fb08d3c GIT binary patch literal 58312 zcmeHw3z!^Nb*5!$W;72yZOaeYrX*vlHJ%yCHW(NzgD^NY#+}VTxAHhq&%OekyEXyvC@K`<)Z-4-s-F!<(R$zZDkg(s9C43t+ z?0@c~?yYC{bZfK*tnbrQclCXod+s^so^$TG=bjq+jZc2_0`@Q5;x}!ladO72RvTW` z@;l+is#j^(twzv!xU=_{I^7a)$JjB*dBSXQ?f_Hp}+}hmiAM)?Qna(=J@vXk@mb_X*u&&hYF+YhNIR= z0wSx(uXZ?O!%Y)#1RZ-@I9iSXx7UZm0^UR6hMLo`I)~cxW;kXB0eWZ$7$=Quy;JpR z3?r4A>HBzz&qEEf&OdFewwvn9yjeNkvKFXJI~)njMf#~@Z?SjU6ZVz%di$#ImVLHY zxAxVY*1p3n&jlL%eTSC=+iUDQYWc^_mzneaKGQen_W@G=p@~7a=Vw|zhH&*=7q;gy z?oo`%Tx^+5Tf@__hu2+jfk4%nQxBsON0#CEhG_s|-&}MWi$)Vev|0^g$+lXS;aiQW z)$$E*K@_q4DWhW6YF5=i*MxWcJjKcxfo(;ljKDKmR>g8ou-`?Ms8_0U!Z8g1glUtt zjQO@dL+?bpM%8QV35=?PmV(-{;WPl6SqY3KC$J5zG5lhfjb&rWT%IwGICZCHwra}& zOO6sluue8x7$tAS@&l^lH7vtx8FddsV7X}lC5BwlQgiO0TE#Df~dI$|F6aWJ@~&D>}_9fPuo}7Q{c#9$==}13&J4>>~vD& zN-o%PTM9=Yn_3PNCnbm^FerpyxI?f_iHRLX{16IzJK;D9hZ+8B#~wZubW8%~fCR$6 zio*_2Hb7QaQjnDJ%Vzqe>^l%pLAw=`wd1_$lG$wTWrR!Rx3KbNqu~W+LT-mQ-hazA z0i^J(v4_FB=hi9X7TJE;Z<-Zr)`*H2dv3iIC}g63M>xc4bQJpU*U_&7${W%K6RtA^ zU(qMkf~B_*pTKb4QpZfrVg-o1zddi|PtfSedTo}C1Iro-7^`){VifR7)V-JY$0%VV zqksvHEG(8J{pA8_4~0W)>Lk?Sn}Yle`H+{waZJ`UI%jQ$o2UzhJNDhu2W7w3{zamQ z*JT1X%79BkHZ19hR@EJ${HkDkYY}W42{sPcMruAEriU_N+Rk926|HVT`eS8KdIiw7 z9;C>TCJ8qxs$*9##_&V*T~3ZvmD<4@R%86V{4s{>8fnV;Fb4Bzk&uux@qQG1q?dxf zlSWT?kx;(CVKXNjYpDVatP^gLAIoN=VtXwO5#8j?C^VG7Y%N+rC%m{^_p0rhB~*?k z(=?#ppomlL*l!Pq@d=8E5Ig%s0V1zISFmz{qjAv7Op=$-oiGEPaE!>qnZuXUiv(JN7az&Rp>@kW4k zm?lzV#fk@|Leo{HvYE^B)ZqV=4atU+GNKe-*j$caP7JK-)lH|-vHvL?!N^J9=-5Ak z+6?ZHUq%`pUn)+A6XGMS1k0V%;g*IcV1{zWUJ*ox7=4l|DMkDY*S+nbW5=Od96WOH zMaJA5XXUv$!)rp5f*Q+JDbw(sdb1WOLD0^snB@kvy!mBPR-BeGsVhj6(0G_~!?Z^q zYgA)#X6!zT)FrPD<-bY_AZ!BkxeMKupncWMI$Ix%y4gCu*MJs93L_PTCZ*|)Oao)u zSqr)+wNnMtqk}fIO%z0zoM4QFmRC1C(xrsf=C`45nZCi5W`j|TL4<%REn}hGV1|W1 zGxm~`CL3>N&(IZT7H5oEXlk=_2b;~BQ(=J5wAzhbKwT^2r@*Nk-*@x={k!J4MpuHQ z9AZdU%a3~@CPJ4Z(A7t34(YTtjYq>VHBWLqNC{ncBGFcSHPdB2$ip3@(mNRdp#2@; zO??nR@jy0O^`>q5j<1hobDU`8XeM-0(wa3^HKwZ*W7^v@O=?{xr^FpctCDlVAx6Ct z>~*`eiZ`wb)+GM__@|O1wBaZ526b$r30?-9mQP|`(5c|k98O|*jUn8e5PNQ%vPiGCK%$&vtkvqzX|nld6utXhr%)WnR^QKWj8%;0{X=?Vs285>5ROA z#F2)X`az+ZQf{@C~v=8Uii`|D;j1SCG_WMNY0Am*7B0qs=}wR$eeFjO&LilM&$!U;AWVUPY^}ytiD#7%UQ?;bWN_ilqw}>2Cr0AsCPAFo)I)0`J zp0|v)kGX)lLryo@0;cg`jT~~&Ku%cX(^~f0oFZBl6gc|YGQ6b*6egOz3UfToO7Su) zH9qFhvKp=jFPiVwP!p5Poo^9|Ff&%DFYYsd&PZ;I2zqP|q2ZoY(J)LxW zS(LtjHu@BSS;I@nzwKCkqKUh2jp$dyY4JR6Pg8ov1b#zJU|Ny>yIv-ZS#wyxr}+XN zGw3v(;_LlQpZgt}vPi9vrf%*eo{q0$Z1s`@E1Is!RY(CPSd%l*+qwoiiPp7oDM;i# z&Q|#%oPhhEHX_)nCdEtqrGjMi!Z=Uo^9is(J1g#RRD=28E`_+cRrcM@7oz)K?U#mX zGoiHCC~1yXh-z%nRN;QTM0-0E?LEXDu^LFi7kf_}ppt!5z6eWP#HhAP!g4B;{>gV@ zXkSS>V_zTD91%4oN~7-zn^O^PG8H!awEgB7olB1ue1~o+s>|?tIq>?HsP9p2=v-`S zZ&d%YQ5)I)ztetKX8-ULX7&HxsQ(?=NMfic*&m3?Ni&oolOyUQML+Hc<2BS!4i^r^ z{&>o<4ELb>GE^#3cO|~zA$0FxWi{A0(vBKUeG=}(4?D2gDoZMO?S9~`t{UEaNg>Au zr)Jh%J}#%B8;|OSQ?b7?+?wR2j<%SRynxeEgN4(i8i9KahR_TSjwh*RbncpkqM zdB*K0+=mFkPr~SvVmZ`U;MY6$x5Mp8a7ugGwt@6jUJhuk71IRn`c97+p@G0V8C4ZF zBN$W-h5KLGk~Yj`SKLUpf9!sMdOqtuN{B56ZAI*8VC`-~PVLP{6^m1D# zQJ(44@N7z(CTal|GZgN*In!TmRH$jMg{@n7JE3dSE4$@2JSgt5_Ue||5SzbnI7(2N zT}9ueM{CK!P;6KT7HQ-d^4#3*ZQ4egn}gw?wO(6Rj=}>2p-EGgJ}d}EI)P)(m2g5I zkX#tD#KRvYnkigorEih?X4?ESdzq_q5A^2;0(v*IsX&AI1k*FfqY-IIBx5@dbfq=$ z-v$Eq@?4VDx;RI)@STAmeI6L2KfdXCB=D9?4wL8}<}b7+emu}9wxwBDt))pk$K|YU zyphb5aRECaqor~Ru2G(!Tju6&6AQL3^_W}%d6E!=d}IMIBzG1Zg#JWMABKQZitAN_ z5$a$6C5fInlS z;`D$?od>n}1>srY(1J&isHeltwzFv0@INTSZB8MbWS4{+YbG|E%|(P#3^!T$C28jF z9NHD?^fhtXQPO*NOo61>M>y-{{!52=1k*qVYC$p1Zq}x5`Y%;B-wiBJGIq z|2}1inkh%*UPr_wBlzA(+gvgoEPbR|Io^z4v#e(6*?S{akvvzx0YA?uh}h+q2V@u5 zM+13`vM)w}ef!>?8F`e-(0_9MZAv}KDf)1hB^ZQYd~L4w+|NbajDSh_Wr0Y zbGpr9NmNd^O)(TnA(MEkH|_I1mL>00#$eaNJ9Tjum1TLT6g(*p)q63lo;_6mNJx%(s1mfo zyi_96SZOPq|6-o1SzzhkP-{G}Znd5&Sye2ppz65(CPL}*JXM=Epy#vhW_qmf$7(%Q z;cJg#)0H;Fodp){W;9z~h0Y3K(>!TDa4nwC7F;?k#LHV)phFVeF9dIr8F;Pfd6Twt zCwE7DX+RF`o{XZ(PIyW?=r&96Z)rq!O zZ(Ur07K)g%7we*gHu|(K@9_uPH1;>`#c)LmLyH7DNK?_oV5}SN6raCkY*Yw_4W;SHW-yJc(t0h1plVR z<0z+$d4yrY*C`daz3^R7R0?}zopgc{z2VMgL_{E_BEkj>c}UyFg2SZ2$BqUuY*J+9 z)x~gVm_3@nY|PFMH^m^9lQkNRLTl)OL_=|ANMKTWN2qs3WkU=bT64X?CGn=i#ouWS zH3oufXTh9kour_RMU|~8nBrd&yuAcd{7T`#dhuC;0n#S6e_ z5shq$)4F2fB=&n_VrpA4am@BRHjk~DwKV^jmOw5H&2{lYrkqD?U&?TMDC4b9lQ6^9 zQ@)cz0En-4?N$H?Ym~7Y_vrNPXn7jjIFlQn?lr+SXBbfZqu|*=96*H@?ZFsZ^=;Aa zZZ{Mweee&gxCu3>cJYd;a4}eo#1+98387s8pnM>z43$S=nS$OhV6g`wfKRnB5*@17@{LXMzS& zBD&--Ao_wJF7VlEZFX5z*z91{_>^?9*z$qsiOID~`< zQ_)F378mDBH|MLOor80EsM~ENP;FPEezFg7yRS{uNK8&M6>Nu7+^m}`gq*KCte+X58IW>FH$xtq2_yoG2K{3VtlX6(=CN(tvL*ba* zFXHE<1dw?A4u?XK$tK;X!})Pe_=&d)oj)$@I)`X@r>j9z_p+qkWHZwmXgKbBFzgJC zMgfr0XdE^Pbj&{^R#qJ7x4(tp-X~b&_LJ`3VI0Gwj(!cnvFrmWP6&pL#1)2oT;M;g zv6NH<)v*ycH@H7h$uykWW;q7P2k$MxRqr8$4hlq_9o|AY>3gC4Kq|Tpr?2h|l&jJ= z5IJC+Fk23Vhsuyo3dN@bVpZ8B+X<+%syLE&9NP#D!Y)1e3ho%1`0WGa2C+lW1LXJKkgs`wJOhY#k_Uf zQn+DsA9IYl&%$&FZpdB+Zl(gc8d5Lbxf{_!k=n0OTyEsi3(-aw?;NKrI`GM;N*(%S zXK+P^3*_YDXF&DAs$GM%R|7!YGYlVaZvXL5C9P@_nnt42MvSy5yMd%?DR9%v^L>dX z5;|U70hiwP2!qe*mtB;oPmUp9CX<{(ROfl2k?RFo+Ve4gZdelnU>=z;4j?23>ZX!? zr6?pug`Z7D?=sx5IY0V=*W9&xEQ%jHzn$`_0iQI1gSGJPxgH^xW$bblp8I$3327b$ ztEdSPdoDOI#vOd>ml;thVbw`+WLUplaAfS_bZfBvNtTy1ciKqQ5m$Ml?}`I{vycT# zc9Ek0a8x&}tf2*^(8bLeWl3Bp#+;kQN7{R&NhxUE-{mwwX4x8OQsMUW?EuB?1KaMr7c|lSqx9|S$yH@3YA>Wt}Fsx>+Wlb?s{6}2u4unjxd&cA_;l-fG0*{uZE&nZv;u;?RK7mK1RocSR#Fi;D3)12t z*jKZdx21ZL6SpM+g4V}BCHg3ytN%l#ce(@^o2wx{7A0JhAa|WF_j}aj)pu=(p);lh z9Q!DgT(xmpUoJ-n+gQRz6|a7c5iz`A(_jh5^Hf?3!#aV?AbzAI_{t+$pkBy`+blIh z{#K}NWESFkg%K!fixvsUAS#Zw+LjubY(Y?wI3}%257LiV;IJB#Tt-T&ZP^a;wdze7 z2M!pq5pdwr{mc6ENYZgUf?dAl+tj;{BDQ~Kx74Seo<4~lBZhOFrO<@`Q*ins&2-Di z8fm72_lIM=Uo0}{46t0S;Y3k-O}tu{jhab}2pcum(_@7{@;7RjmMV_{_nT!wMS2%1 z&OFjPl430tpqi^Xht^tZqLDO#S0BlNi!}7fEU?86%v6l@(|Wshid?v7v^Q#bc?nHe zzIUcjcRv`_J%1Qu`yfhtznD7+;>Zv-jB+7MuK`1Z^6AE2BVDc72~fy+AR1uSHcE~c z_ZTV_d8?#7LC)@@tgPnjj;D=Cz?<=7exiw>AK06#hCMDMvYh&4Hz`VSj}Tnk2wMxg zNjGX0r)eHSa>CFqy8u@n@kEv$q)buk*mIW6tkENBT*2S^lIwipm9H=b(gs^l~E0>$_EovuRkFG_B zn&$jLG3soiswZ#YV~Hk;m2Z)2llo=K_oy1P5&}u6@+n^U_uK;n1V|hc`2hh>kwBno zvMfj`K+gbN(^jP7KZi}!077J0lC!LcefO1ns+iFQx699?~%<4cgM{ z{t$*+w5NGRKJ?NEy)18hS||UI=%kn-gf&W#F^1T`T106*7Y}b-L#Z6kXoO|0nF}_? zv9!7YjO){-csdDNG40Dt3>5K^7bi_QC37rl7Tv52zcn_g*>Uj0EMKGY&P#hKW|6WK z0lT{t%C)JZxr*tb2@?#gqqs_;K!W3(3!C}*JsQnV&rp_+<0&yioH4;&mx0;WV#kJs z2|o~HU&Zp_grHHLS&(UdwEU&s@4>AW;?kBV7q5tGq;!GfQg)|v7mk4;>82v&yq3aF zf29P|vsWYSSl+@LqZ(|GH2~7DMSV34Ac8Wor@0sr3M4k6F4CjSMd5@Mt-#@Gb&+|y zkGD_pZme6~e>P=2Fv-0+4@^!9Z@#eWR21BZXh7mL`mPXqEJ9C~30HiI`e;;_p|%0k zsxY{bX#8SdOnz5=FGTgT`!3oS%jjEKy}J_I2DzwGCUA!Bs0`tZAM*{%*AF4}ARUc}H3@9;mmQ(@MuGg{en5V7 z)gUY3m%NcmP6S!)88o;SCi`Z=#gc(CjCBP`%2>Y#gU>bAlgSppLgiel@i~yX96Lix0c|otS1jM6W#aA>rPmqpT!mCEk;+YYAX;)KcL8b2jd&|` z0GM18l&BOzY;ap}M}^wIedkjccFkV-UxGlgofthQR{T+-nPRg?I5Mbj5ay0>Tt}di zE=kzp^p`aGrPhM-NV2dqknank@L#?)uBRz6= zeOaiIIHxOh!$F(j(+)Ua2pp`LjdCJ}2#wdibx@PC@}f|f6YS7PB(@i(;T2Za4kkyX2TWys-<2)J3Q>hsn@Nl1D96~SDaGlGBLC~HYHtW0^P*# zYF+R}c3Xtw;EGs^mBuAxUM*@_2nQBGVAMRXsbu}L`x>oAhA+n?#e8ey@Xtv5EW9)a zFOpVZ=cweqwPl7it?^eS8jtgRLX66gQ-X-G&Xy?Tlw)6OxEN}rpwQ+?!a5qg(;BJ` z1mWw1#TU)gd8Gj*Uz6zQO_os7c_m9U7OJI|mB~qcq79LRZ*nruRD&&M+fu!1^Ykl; zc|ttWFb;!xa1&@@NSEcoDQV#1tYK)~Je26Bm|#OHz0)Pw7{Ojuhz_lr(NH&WzoStJskxwKXMeSGM<8wea9u+N^D%d+1f6h~Or!QWWyI7njEa2u;ju zt3NMHdd~?5H)hciVRAhMX4cQ%z!VMqAezxE=Vg)xq^A*r4EaEbSX6mOB-E~^=YJSs7-#VTfrH{)?yc(`p3+&Ea+sJYmA7iW7Mm%r^W&#hX z{&l-4L~H4?bJo&yswIY;d9S*hiGlSkZz=PKA%2ywQV+Tehx&as$Hk2t7dNMIp?GzI zWQ*hlsb9ojDjK@vCqQ<()2vnZ20Y?KT5<~~Ycrdy$l{XIm3*xR{#xp9)f4tsfVjj!>}kRR zKAJ+vx6`cxuu+v|u`Hp_`bmx8ZGDg6p>sR}?yoHSp4TYN%*^1d2^&G|B#8S#0+;Kt zo5`W6ifelFhgUNuX-_`deK--v(FFc(_wthC_yn#g9#h{x~aI%ym2F<}4ftZ&`3j(S1Gnv;Q3eSy(aYDjEfRZ#83+6!7it!-}EdiSFek z1@wZ3>(dNiTnCR+dZ2C213(Sy^j?>SG1d)> zrWv~5_VhTlrms#kT`V|-`<}yD$ak>`9b)4uZdxq;d_oJGjxR>VMXx7%-RW}WD!*vB zf%Le}UF&JB8|HP^_dtc~cu}cH@(r_Ch+=rHrlU`v@TYYJA4ddzMDCFZq>QiYvA@m(Us0#a#iK2yAmtR%S|0=4T-E&dUN4jUlTkZ)oT)fdeu3@NSKM`hP zm3F^l1*3}xX$RbW1ig^5E-x2+2iW|i7!nY%+C6VsRqS~Kmuf`X<$|LTeWmUfe2h9j z>wc6TEBuka?agQ|z3u%H^1(7E1k$yiz&+eN1G|~Qt+YFyeLHt#^`E2G6v=!{;8$)L z7fSSK1$ZZBM)Fv(Si0ywY~D=Y)u6k-?-n;HN(RdOO@a1>Re?tL=>Dgu2IHRh05oM? zTI@gqcBxDQhz`i{vqZ2RXRwJ~B1w{Xh9Qb1-Lx*|~{aUpiForRq)HoH#1 zqF>qA=p^t92JB8-(ElnL7H8{}u8;+oL~<4*Dja_!(RAVTOPz+`0cv-ITT`P~EhmAF z^Io10=e^o2qKm#3lW;@RbXuM8x{6oFQIjgByMg=WS%l^D4INjMm}plgyt-1a@}H*> z_BWj@kyu+4k#%2NVi$+;-uTiI33YdD0>Xvs=^3RJJ}0PLuK8S?=wf43m+{5>fY~UJ zF~fyZyhNoNQ&U@V*Q2W>LQPH95fUJ0Gm~zG8)2n3Ot2zlIwHiF_LF<ddUwJv4zs;nih!ybCD~Sch6@6*kltoW(Yd zw9wUIs8sXJs#TrBbCI-PdgWsqzexfWkveozpKY|$50um_XtgU8DPRQ^xw<`#mn2>k z``;oces$|Ko%59Ps$X&Hu0z-1wOxg2tKEPsy((XpqQC&6bgM3wSzk#>`XHf*OVV^< zg~@UuCW{5>{ZU;eNIx`?AWb)>BvHwI1z|mbO^s)#37a``)ZL4^kf4N+ED8D{P{lDZ zl0GD;tSTfZkf7l1MS`BDuFtw}rpF3@tX6`C2a@8`syhLRla%m;+>y5)0cBixO5JF{ zRuoM=B(S+U?)=C(N1P6ivkM@@LpK-zf;#| z-LKPQg+Er!qCe@GMVCxu@nP|MAVH=sM4UEPOlBa8I@> zK?4Tb5st`dQ4J;`jq^yJiTc=il-leBY@yVq66Z>4^WKtD`=U+RQk$1n*t~?w^=Y7P zi|R6|{jq_hcDgY&u_bo`T@^`fhR`ljn^2M^wLb>Z*er(9ht!r;h13QX6yUu`?H5qj zXWbXlV}(CfEwxvv5^>`WG&qoAm25>3)r$o-r7$Vv`N%!_@$<-{{IdHbMd`}|l{i-{ z%6m()s6|-HP^@@qh0Vo6Y!)k4m8dRb(N7G-qUpvIrI*}SqpKuBb<>9-viVqvSM*rnkEaYx-`opL z-+XRqn)*!A^xqS5@@SeWD4PDhn8|)<`nyqGM$?}fh^EtxDY_`RPok@?G!4vlp=m-) z7EON&H2rNcnm%Y+Ruwc2L@3yMq3O#vGn&4F9xE<;tUXOn_9mxq+D}BiyNjSksR1PQ zB`HbGdQFn`4TK*~);Tp4UEf4y`?L@CMRgfn|H(jfoo-CgM#-H-S4rfiWHlkT3t>HlTDEpc&BAbd0K-xP}GMo3Cr0tIria2fO zRZ+zKAH|IJL);&W>N4W~^gzU&ZcNcf$$bo6g$ewoq&CBE7wRVDWKs90LEV2O#?uFN z%c_F9feHnEFVy`6b$!--k{&Dk@sy$No0vRIVn0cY(^Tx7QaA56N!@1&MS0ZCt0?OJ ziI~xTsQaIzx{SI%GZ1yB8&mXAa({@flK4$gH^Xli>L%o5QTJy+-9HlJ>4UmuRYBcA zg@V2p>fXDBQTHT0R$TU2d+MI*O?E%)rW={?er6Zp&B_fx-+FxZ4D-i`o|6QAkg&uF zJhzUb@Y|?#pIY||qPmR2KRXbGryEl=QgUa}RhU3=io!XHyO21cCyT^C3lhIY45$wh zmsJIc0~ZSXUP!!7U7vLu^jP7KrwoZd_vUByMB=R6IVEw?bCSe=m9UgY;-Zcs@n09S z+K&+b<)|(r@y`uJ;_1c|jg;IspsTJV&QaWj#0foFB>p*&_$e`3YpmH3yty4ClMrD~c^KU>fBBBnFn5Z2X%U+uW6;y1qLBW>+g)zqi8t3Nj=NY?e z53<(EymQ>?HI_~&M&0dVdE->bIFApYUuH5=kkNbceP>p>VSixrAyDu#!Zp2y3MP0H zjZ>41GDv}!2z@VUV!q6Vl0WKR z(!_iNZ48_yCS#m*yza%|S|K$)4;d6;{t9BfY@X2YQ#>O(vuA{HPsXJDqnea%n@2w! zcwYYZIhdCVww{A|$sTIa)ReNOCR6gLg*G`+@#P^eUWO>*e8nK!?PhTdG71c!z{J9e zSzk%bWg4?7WJ0>I!sI?G)~8l}eN>mJERPSQvZNbRlUj1GBiby8K_+Z=(Nzc`S-Q&O zpo)?hNguk3tSY1qkf7l1MOS$xb$!--6+Kq?W3{?Ucwf(PeJ!hEIVTW0c<-S*j~TwR z*uZV*b8|=T{DnL2J&b@s+(8Om#W`Wt5aX!U`dbIey71Vt{%!~BKT z#6qHp{MCrWjyP3L{jxQ9OLB~g7m~2WCo)f}{KYwwDl=XE0Jeu1)8m%a#JLuTm+SI9 z0eZ;+ zSt(nogAgc)lUj5bi(;qQxh@@xbYWM{Poyf~EEh#+@4snw|9<1(-NwB~ZzHQoSX^9Y zLDzoj0HjF%Gh&XV@GF#DQ4HZ<#s!QrQK#3_;XP)Av4h0O#X+IPhz1XkXcj@{$W*|i z*)7J|Q2$U_E z$8oz>)i4)L2gQI3)(kKSHvpRfWCO+|ovc_E&L}DjvGL3hnCOyWwvho2fx=TN5-2E) z4r1*QPVmlm>P>hioCZP7Px)ir!1dx}#and30ieg`A)*R>GG@jOc>$(@4jlx<-d+Q( zGEjLFtQKSMRD*O>0(XS90tRR5XLc~bKsJrVMLH8@8tlkK6?ue2cR(b)t|195pK-AK z0?v;5wnD3z9eJQap1GpV6p_$Wb7HPa*>G&%su}0ZsdqfhI#09C&oS$$RqV@stzuuz zS;fM8UgW{cn3hH)tTZ+jXRo-Y6e;t#0ulF>F5rT5et`lMfOFoi!oWBB!oYuxVIZDb z_?r851Uxuq1_y3<-t0~L$C$J|aN`YF*Q7<%Q&|oydi)+>9X$2#dWhZ*nNxERokGw2 z>)3d-{3hRLx?sUV16lqY49+;rwKq1?aiNV8&!eTBm*75iMhx{f@&RBSTx!uNTS_Ou z7BgDtuuAQ@uvx9!#6T6)*N)04P7I}EI9xm1GIAqPWrlDOS z8Kc%qst74yyhyw!dxCq>m_3T@V_G-cgw8gt@;s_xWd4|FdcD^4g~b=8_#pU-)v>3* ztMfA>U9cn$DqcBiNLP+wX+is$QiXI5mG}0Vz1ZT$Fp{6{P$7 zDhKbDL*Zz2gDmQgR&gl?6uo*AU&eViWwd=9U&qAPcB_VOn*y&=ri+c}SHHuOEQZ?` zJTHJAXKBCOwJzL*J+h$Du9r^|V|VaoGtzW8%`$mNFdiT6?c{H)8oP$pFE2TPU9KSI z2u{XQccMb{Vxna=y;e}JLHDe6?z%7>v&~xcbtv3M=k3aLuWj3xg@(eRsx{wUM0=Z; z%vJ-4LJ6pob-Wo3=xi^IsPm?9v(tcjRK_kJHU=Auop7`rEKEOl8ZNd@cxC*@vejyN ztuprfsx=Ggf#|XWrxJ9+EnYi_w=%?9K{AWPFNr4H+qc0>v6;84V34)1jQ^0R9B!pC z_&}5m6xA@MPPnOt4aqhV!T{q{e813Y;NnAg54~2kT(z1Y4s_!%Ob_!#m@wj0%T0(* z=OkQC;byZPcxCk}ywCwfZK}5G&2mI_KrDOV(D`OKBWdckus6VN!)FFe^s4Dw?W$Kk zStokhYMpF)zE#$1GAgMA#uk*(XEySMHMH#eS>0w)0exg0nR>hUUM)+)iUokRsB zYoeS}C*q}4K#UtVFp&hBsn1(gu<$ZKuq`VUi0zn@+84R;w-KhGSrFqn2sP zNrT`r?R2;v8Hzec!WnMl;spE)QiQJIfH{IPEZ#*J*hDznNZbP|h*Y!z_mtmxeJ9)= zd&^Ty;Wb)Yh`tOH3sqV15qil#m)u=oa`$TbvkzCCxl{D#Z;_zh{W|@51#+ReN9fPx zRAdMJ*+zdh<4-#rrIv!_CWiL<4sYu;Yv(j;<20*(n$YZ-eyQm~}h}G?7_PxAE zy8GF^hW?c3&wHT|y6>kypWlE#kJBG#2!9&%=OMaV>tXuyeB7q(9;81ETDoJyrCSTx z{fZoJ%5=)%ri^|p)uT(vAlV4m&K*nYm!eOU5yPdV8SbA& zpXj``OGmQZ>F5(3@O0@6sQbp~6P=NB=@^~++2|9UF>>h`k~@OnME;4+XSj5P!@Vo| zM4|02MZddmi9S(8u=_Fk^VR4R#ZkHxYUy5zom>8iBF|h3PIK>%K2fNSOVK>;d!kRY z7v|D-nfnXTC-PFeEF-t^ z#2C;|UXLB3mqQ#jO=$dOnM9EoaeK6q#9og_uNe=IBdtcQT_u^ZNVUeQwAhJtffTUz H{LKFYOg&gW literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/asab/service.doctree b/old_docs/_build/doctrees/asab/service.doctree new file mode 100644 index 0000000000000000000000000000000000000000..ac255d985bfc11fae052c27699a89a9fd0a49604 GIT binary patch literal 11799 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 wpMXoDX$#H?)xA9osc2D=v zi=+XY7zkU^Z1I>t0s#^N`B($QEM|L(;%u zyGK&q3%^9}x%XDpsZ*!UUZ);h^6;V)7M(!<>#S+cmddpw`NGsxtv(es=R3=%>c#d< zRBO#YG{5C}^AF4qcUCkChnw|wqZrM1PQVw%Qn@exfade)}AbMh6=4#qdeJeVNNuMlgd*~f_GW5T4*-$ z5Wkny3N!rI@~QT${$sLGysr^W(>LwTvR2_By_zqrDXlN9DxF(8skEW9eQT*c6K$O- zH@4ow&0wU*XomWOHkwS(w}kNcoQ@pJ=|(#2n7MWpR5F(_Mi{ z6%IBEvn3NLA3sovay$3$ynb^tC-9ToA2kk@i&3uGo}H~XTFu;4p;gF*2$P^E32tYBFD}&urZ>F`g^brg9T|fVoz=xIZd1iY5E|h`+-3^m(2w=5T3krz$7% z*n_WK@TtrTO2IO1<;!$i={yhvp&82=fqFo}lB!EfIv1syJg3aHon-=3#xU2I!xTyz zL1?A(LB<#0|1ZM-Z^r*`0ii8s1f+ZDECoF6MtQz-Rvgyn+oelOSJ7111eUf6jf0Wi zlYoA`y#&^hahN4Mon_+Xd_jU{K9W#Mph`E>*tc|s6w;>VZ&@TjS=(8{sKLO3jqIyA z(*S^%q^B5(^@`Cz+I zV62+)-nH&iy`6qF9rg(jVv;ZBpEH0~0Fb;I_nsTdV1FaI=4@0fPtWCA;B%6NwdQ6c zVqNsCXo8o|5f`b?5~$7GG#Ff0Gf0LpNka=dhQ`Tj(&I!f&Ps_Jwxw52wyV{sHC`=4 zAZV^67Yj^_-i()9(TwrBGcr-GaaKPumfKZF7mz(%7)+HL_@g>USmd8@oGAR4-Yo_3 z8YYOx)ebjD7}6t1oGzDR8r1pz^a%JvO#D5V^xDp*6fkQXzsDRR-3B-rL%kCUKybIb z9UuL^CQ_0S?@%=QcN2nJcHy_(B#|k^fRd;A-0o;Ls!cU>^;&LXc8;~y>_a@rH=@E6 z=oaF*nJ?G3MzyWYR$;OlY56)+hlZdVvOnXS6=ut$h2~tXh|a`+$61r{A}0#$mVBu- zQziLbEl)NIjdIlFqFL|A(pNY|Jffz*LQP*TzLFk#VZLTAOc>X+_J7UR{t52dr@*H{ zZ+~r$S<+(W%HD9UW+xWN80q`wNb$2%VqNwCF|$RAnZ#vRf`^c!1K{Q;_OnHq1 zlH4MWj;YqNvM2RcA@Tr^uIwaIArXCzpG~J&0%NOEZ{}7t`1Q7lj4LH4yG*n*hIyJZ zObTW#I{{C)K=OnDrO0hA@uNBQ#px)GL$6ISIlkV$YF-6pFiKOba*$SqtTApSNGR5J zR){@3XBZ6Zt%>z?n;0s4WjkB_c=Qnr-C9$8|DB~=yPfYW8f7Sai!e|~KV$X*Xiaaq z=ek~w*+%_P8UCnTA=j>zr^|3;lxwZ1F`m@})4r{X(~W3wtM@vKYB2bENz@&o#a{wBXRtRh-v-kH7fTiotu3gw#Yi29)ai6*)2yhnK9#)(kjiyhv? z0Nl?VyTU=cX^UL6|C^?yHvAW{XuWRu%Dd3G@^1R)5AaWC=`8b@yBqu*O(UA9IwxB` zA=A(1z7Se4k=+ow5-xk?jS9HM*6&kt1h)L)a;u~SMpLe8@Eg57{ud@_isJB&BoX|$ zYQaF=jNKUkb@^Shph8fdgiAlrK%8)5Rv>y7)G&`Iu#AhKucOjzeyb?&NT-aeAyQgdhQm3#CGRj_7!C^{=o<#T&mG(fwF1|;gs zHJT|gBClZ&)kmQNjVZB&pfi=b+n4Y1?TjPomajS42 zdYRBqCm^|~S13R%#L6hOhzF&@p(xinT+dNB5Ku%7v;#Shm#5H%f^UcL2qJNU#B~|r zH+a1D4uMQ!w2q#f&5)afHyHlmy}MaAq8F{iEGEPlibUR_tB;^C_0L24FAoT`(WFkjh=PCCng6jGlNho0Ct5nD(LHrx=-60`E-KNUid81LOW8D}w}8>h6v5BJ={!zruc)(f%txW7IFe-} z8AApDUoQ8X1bQjoe@5#=y#wqzR@rKqlQ(RE6>76fP?m{(Yryi7-eI|6Ks-cCBp0n( zZIkh4>De%C0U}y0k#w8Ra>;eImPhTa=Lo9{1PNto;-C zG!<*F+(n&IW{70ypQi`u8G7X&d|&w``sZH!b6e$^)P9vYNtaI}p`${GWqf+M;M1lD z&&9gl6``F(-AXcZb-Od$j6gQs7tL)N$!$7RsJ0`m$;G@?dfWE^>;mg;*I2-7y{+?= z19hk~5z@;T-Gln!6)Z+mZFq{5Q>W4983QgoiiWf?iuFbvDQdMy;9IgkBsa~FZbW;k zEtFnnp~%fAq(0M}8d0m=K>7iF3}vc5&3a+{m79cF zbhrS2+?3v+BU$EWY?hy6O-#{Y@62=JG2z*r%T7|e^E5@c3U|h!E9k>mVV!A*E+Fmfp&9k-zA#c_)boT6cOz#?Q6n``Ga zJqSjg@Ri~oTd`aV%srlDO~&9J_mgEa;V!inl(4ywvB8px3RTPQDq_RdXU54_A&jr+ z5E4(vNzM1$Ux%Z~QoVj39LCRT!)6v)7L)+#+E+WBZDgo@XZV1XT1j|w?sa;##ivh` zCO8;*=cKU^hYo`W1b{zz!o-?{dZqEu=;xl^!R^wc12CVe~ZxX$6 zH^|f`_Fj3lkIGnzgS-$6v%nl=kA+yh7@gCVUOrl=jdG-Di^O;h1wk4SDuf$joRIb( z@anF+QF?L^w5lCMz)}n=7;o%*O@@ zLKC0v1+59rV(u6tf0y)xxo$FYd130x|218v1UrRi!>xr}M{Oi&c+PPAHw-Jrz#nl2wi$OOt?Gm5szW^g@yJ&1Roz*KN|NuU5kDSS#l=pB+#W|*Yj8Jb175Nn$fs!{1(X|pU zOBXM=czKG2HiNVN+0!WLfb2=3HX_``F+tI=X7JUTW8zLSOJaAI9B5rAXaZ$7X|4y?Ne>)!}&T8mURf~ zXEL8%Y+JeLLrIhiHSG5B$vKkwJV0eeaLr^bN#h7i5$mE5EjeM} zo*HGoDVSpAMt*20pND{$ipIuxk^s-t!2a;D85&qpuaD25^XUugxxt2wP5JO~ zi4C>Cp4=~Z#%9>zYzEtnbc#@V)UtXMotvl!uIMb6-x&kk>!qPjUs@c7h>^kQSW|jj)2e<;bgORA|3IKnocUa6rrVK)p9yED}jDey- z7p^f7d9#VQ8%iBb^N4Bo1t$h=5^(R7h=0@Ldp3_B+I;VjvJZ~ZXo}r@0eBCwn^4BH zW<|jS$jCyj-fVa8MkdqK=)`OT=kuYwbfH{jMl7t2T(eYfS1IYbg(?OFz~NGz z9AL0hST-;}25h7N$`&kns*sb@MmU_%u}%7Ap@>ca9s&>SCN2AaqpKcWh|87?K+6uMPSimn zgjgm`S8C^>nLXhmKAkM1o~4chS@tXpqVin!*vhhyQTC}PZaSde zlq|XcSP#h}EpH6fS58%=4jyVxYBY6Dld7CItOX^}skKHX3wUzFu^jOa; z&1kN}+)cg3rhA_rdyQ(r^w=Yo9{YaMGF8&Jf`toF>09W^!E$`wtbOE-dvK=+4}7Eu zdW>*b;Mp?-I6srb^H6wFuV!EQZ15Z0>Sl!&U+`n2Klq_$>TwGkpbk0Pa`RVZGh_It zI>X!Rn2CSgiLQF&UlVBBx0m2dFFCkQgJ*-?5Y8DR8`g|W2IBpcVqnZ&FvEt)5CS_4xM9S6M3}OS^+30`0KHyugjnc`B zQOT2=Mo8ZJ%ss#5I$W%SVF{Bb`2F)mH zF(S^#+I)<4st(7()MF=KAR<+Xz1+m!+P;V|vP&8GO(PIc$e|h?1riD{?GSMSJUI5n zM4Ju}!Z5{i1}z1>v}jvxPuAdsUs5>g^5&!~VpRE>(}OL2d|Z&mWUTwi{o*>^M9!S> z95S7dly|!4rP1&Ad!ODWnqGL-je!Cyai*6z)C4?~WAyur-Y4)R?T_z`{`Bs3XQw$+ zNMyXw*u@YT*BExi-KWEo^K>{p$a+0UrzDZ0d=TClu`3jF!^ROcz2LskVKgsF^?t>a+hD9HF&vH{e$|?AZwqMTWp&5^R?y*G@qf!cNU)u*9205=^Y8x$v>ekmb zxxnc+nT-)7jE&{9kxgJS>2}3Su`AZG!R;KzwnKQ?iLPgY!}=bh(UtOcEikgc%G<9g z#0M8jhP|}@(G~VuOKU^Q9R=)kE+t9qd(Fq6 znQ5Dl7Iu$n!L+b>OAFg;D<-ONUZP?kqxh1|r_pt)3X(2eCr!z|O3P`V%pzz+#v(57 zVL}?|F5p4xQ>AQPZ6M!5`XQ=|OlRSc^u%k>i9%kw9MkOFY?&4OLfQ&NKDM&&SkW(T zT&r}J8mtLc9f#;jtxBVeSOP0O0NsmKSe(!+G^EEjcwxuEu2Jvm^6X$rl0Mm*pfTLM zGhF;)$|8kMSEzoqQC7c-K^F^5)5$WL84J`}e2DzYGK`u&v;$3rD)W z@tU~3@ocH3nDuoflgUvLY8Gv~>&{ylbxVSWS;%XsAZU+>+c3Etr(wv|57V}YjucQn z38&k*FH*$NL<>+1hL=kpM@es4Mhk`1 z5lk&qOZ8@J?DDI&U3QiFN-oHDvfZX8C7CVY2ujWPI`A?mHN#h%>va|eb>zD9h@?z9 z#4N2Gp2CWf&Xi0_M2DjJtwsT%YE}y&uQ>94VSw-&QEJ13ZdHaN9VQU{jmVTl(QLn{ z+$B@g_@OSpUt7B);KkQWf99xyZ!nr4ID~A65@Ve6YNCv^tX$d3e^Q5j=e%rY4F3~n zcw5e7a?bw;y6Vw6zj)aKIOq9nUFZDof`AFI;f}}hvaxP{kR%E?H zu_iSdV4O!SVpF&>t;#v*s>f9s9>l7+rC;=ngDYbRQFm3+2~k>Usoh%&<~t666N&74 z|BA|u!W^TlOcgj0@vkOH*uw>QYMSvph{A(B5g%i82=Q3wbbEuUD)CQ^Sc1Wdf{&5?1n3{jw;SApg|F{)h^+>7DK+}N-_x$|h z_dr#IbH+c;C7mgbK2k4I*5hXl!Z}}|q~m8T`gAaiWR^|ZUSHFF9>~ysE}HheJSmQ! zS!;7)nmrg;Bg1pIgl$!+#+`(HYqXmWqS(Zcv=kKibcr8#GaE20n_!73DlV{u{b|7Q zmfqo5WpW;)%K$hjqP`#O9UzPQyHKR#{zMC!``fDi9mwTTSv=(Gg72FSv-Nk%1Wv}m zcdQiqzXUc1rP#-m<$SA!GDEljM?>@ofvLqfNju2}r;%c#V;Cebr75Js9D%xd^t}|1 zOfi!sS-5`%cUEDk#)Yk(-${;}y|?e9hr3izazf<7%G^*2zo0Y==DC@)zwe@}9%br(qG{hu z+pG&m8EQsFI}{tQ5K5UKy{bnNGO*?@kHI@LB+aZ|9uk;7Zm#CAft12n8cql4NET9; z0_hUAF;Z<01BzVlGac(=lW7-@yI|?~I+0BrUw?<*P+ja@zw(ql9V)gPO>l?paC*r@ zxOqCfIQ*OkwhXcKc2O&bf0&<+TE)_M4L2E%u}~v%vD`oz_wt^5}gekEU_C7RnLR5u|D97{UpNGP`q$c|X~SXpt@s35ClB zinuTm=`F&To2XAuqlhPp1ECNoE7!`7A!y$>-&e8sI%T<_N!xKZ3A1*Ixcf&?+tX#z%QMNDXI$5OCe`bo!#AF+0)Zqr#u8Z~q*9X#gFb7Knf6CFKPpNKgS z)NXBeip>VX#~aAEM!Fqi#@OT5g*K8n6TZ^o>4m9jlwhS$^7B;-7D|2;;Ob+Pyl?`q z!(ai1R32PgVU@V&cOW8&!_v_kDy%b$;?yX^E-DPd-WY7BdhQRYneb3_{Qji5%jn8S z3>>%_v~To9S0aAt6Tet<$odPBmg;tjUs_?7YcAimZL9ksGL;BJ+i$LyYP;)^^IGC; zdlgBNGvnpiW*e2?a4$^bNzF2DDuEyH{L8mp{sc)M$3LJ-1iuNZG$;}5i}ifWT2D>O zcb{eCwiT+)x^>&<1nRA#ekYX;(M9*POr^_*#Y)phKvQ~d9mDpyt`EG?u zMVCU;Ez8YO(KWmE@B;IRyuug~9tvEpRi24Z5tK*x_gGhp?dMs9bHP&dSEDV`cEv$VmoI?9Zf-Sq3x|kI~w93j|=|3{jwQJKN(vo z8MnRlWD0U)(gh|YVJWft2=2N=0uSA2GJ=cp zW@qsNrNCOn9B#Veho50&ZQei*PyNX-veC1>xc6&rK>6c4|)Nd75FH}HkV%(hIJA!}q*wP4oB z7cFb#@NRNg5qh*cgv=(obd?=hfX_VQfa3#hwa|H>>Oq)Ttr8{kAh2DSqLV&wdh%PK zc1|5Cpi25w&Y1H47A9S2Oy!1m?%A)2?wF0QF}g$HCyR~qWdpO}g+B!o&fOBt(P=H( zs_K5R?iU)U+cN=0%Y3V9!It@})-u0mFY4Adrg)t|O3V^#%4!Vq`aLta!U%3N9L$=- zX%&7=5xi>?j7sYV8->}@95j*QeZ-xvlX_ZLMydHZ%fqEy2ET*pyuQ*FsnrX1lCyV`X5ph#98r7Y(r z`2=|W6)(1mJG<(1<6xmS$4{uvwkL6kR}~k84-pQKmfA)vV6w~(u^JfRwQ0~&rLj&3 zI+ze_jo)6(f`0}xqk=?WxOG+nlVm?C@H4jvFvCS^3&VmuaQ8n_b7Qd^8Dx? zJMHjGqPSDfzyk}S|Gz~U0xc+ZNEEVgxG?0!?>h3ra0xwdOgEEcaT|g=+L+1PotY#{ zzJ#tJ0-qs8;Nba%5}ULFme{;kZ^^+A>l*SKP-;>zOb=HxWNreoJi_M2@R0Crld9aYx@wGl9w$Lg47uC`>By2-P)=X z@Fz&*)@&0&t8}tk@f?9jt*T$9c}}{nTt1?pDoEwGV?62#75|)8(%=nhWv?HAa-mgp zcRkawjek&VBlx{M*=*ayw^@Z|P664ELgN9G6=u1{54|I8NSo}6i4tlMk9NH(WNrtX zKWn5XL`0<}*>yeF2)cMEiwlfA02inh%meTpfTVb9=R3qrL~5eCDofNz6h|Pi1xU|V zH)T!MQI!)9RCppcA>0NNETATR2$&OTk1X0g86mlnxf-Ewsv-0d|KF=d&`C`!Y% zO{RHHOia$fT{(ff`!JH}Y=T8G&0G%LB`Hqsm}TOD(S9O`YS&pz(n-bXIWCpE7em{diJDDbZ)Vd0y0!%W z2cx2mLckQCK-xD5ihXhZrlDG!U39WNM_C#};`z9+(znYG^Pmr0CPC$DiskaAEuxwJ zj(5}b*^nssDf-0)s`dzs(~$pu`vJtCw#d(UZ}^)35W~11rzsiw-}qqnzYcE^8v&H_ ztJnvFa)`wob@;wTpqi*VYXqMm&k{*C!`?DpF`mDz)w}MsoR26x_>_RGC-6Q_y>V3_=>*;7@m1SwA7 z{S5nxP|ehW5jcG9io~H%GslbtdG9cVpTTn2HFE5fgg$(c?eYjg0^9G|q{a9qA)@bPJ*(3e#}ERJSYT)6 z$_1Bi|HoPc!yatHx@y*Oh+X^sS^VDQqRfJuDL3iH8+lfOZm`2qxha)%4z3OMEKEpN zhO~UJCTzeN7AZm`1aa?n#4R)Uh>pqFnw&QP?U|EH_AOmxq0%by*tu^vrBSdT6LGf5 z2!U>)Kmb+3v_*m|5HU?LA_Rm8Yq)4{x_l(J=|b{F6eo)pZej@2hBINkAR|$*tY=Wp zk@FN~*;htsI$Q?T`vT*!2VbWEdF;X0rvXJHb!$&Z9U`P&il!lP2A7L;=tzFTE85!* zoi$?j`!qKFDxJng>QO*rTYVR@t#IcemJqjrPf0HCKGxXTmkB%M%(+>$AboA$>P4o) zcJ~BqryG#|rIl1RFC2DdM_d_X#R$cI8MQU%a5WgB(?tqgjqbXBm-ghbvcS{uGV^V$ z%JT61A0$kpyalVpGd5u>hC8p{HKCK#jG8>s$wXdd0Ujxk6!sMECwe0mgx>HBBIs~* zBo}+5(8itYNNS@$=V$}Oc&&^cZP1t;LB}#rj$M4owi}|)c!-so5RgHN;tv4~JHE`* zQ?N(1AE|V-Fl{IY_o(Ifsj270uL+|?OCza7)E8$Er`njpA{t{JbjFO=P?yinjWVj3 zj~p#Z>M2F^724B*A`#C*Q$s~v!UyWCq>Sq$vk26eTk|hv9~>?;YV$9x+=JYO$}iDB z_u`-1D$m5f9nVaOkLYv9`%WR=LwII7>RLZB8|Voy$(aUmYqIyO#!Csyd^JwC_J}dm zuhBPysn+pgHbHwS%{2=w#KUN6EX3mJcC9#{bsbh3bEF_g{0ejx!AOsA%}qQAf2V_R z^|68QcMlHXZ|@!99~v0K#T>&3-;~UH4HSh}Bfad6aGlbO3XUfYA@$}>Wl@;)nnFKp;~Ssa>*`Z zZ$$@@8p23_Lt+mYRQb$IP;64q5`gKWG$#4K}Be!a|0>iOy}J5TRCKeL}l&an#2D_ z7c+el(WMD?XQo{sd|UfYC*3iYV9CN_*_{0R_NHCsS-LLsdUogLt`cYlHYzvuDL0m4 zUahEDs+FJBrbsqBP%*{)qadvY0%9#>(SoSRh7r^uu4*qLI>uw;EOVc=Wz8$~-;TKvV4^vXtQ9 zrOLsr2*izM?9481mQdTH!0vVwJP5E$SJ2&?vA-R3!42U>m~=_}KZ`O=w72&}v}eW< zZRZ;YKv|lW{cFjH^W=Xms7L1c6@ zEpoD(jAGg?PF}P1!_1w66cAMPlFkY~F6{#_RnZhT4>1o1ioP(uJlU?^r}jiF2vQ3E zUq4SxBKP)0BI|4t(bBuKx=k*xQLvy<=JL|XQv3~LPU6jG`?_=c02*^;86BT32?z!H zvC^ZONf;ql<0D26)<^bm)@5IG*e&44TcM6aN(wQaXk0!w6E4Yn_Z-!NdGF38?_B_n z)wWwk0^>f`5WPb6&)q}u_C2YQ1W`w|U=VGz{E40WZlasI*uHlwDT(-i@(kLb^7`E( zSmxH)gRaBQ7cgGXOu2H=B@n)CP04|kSQOr;vlcP_K>36ETEm=`}M*FR3XYBwc-mIoK<4r_!3b=?gGQR0t z*frKLP8(C;zHz8rjK(Qg&m(Qr5ghaAs8FlbIlDJ|y8NE&E+8#sEVr4>dh?Ev+;wu` z@g@$KMPoVjNpACw9pEkSo>79d@C@pu{fx7;<|KGu=Fp3Ba-ZRs?&M2OC-&CrEIJIf zbP<5iT&MB{j$InwOfhvSz`mpRPkEz1Qp0sxTT2MYZJjAMw%)<7Gih$UV-B}_)wUjp zn)elM#UA7bplJQK3cA=TkdE^~W0WAwPN9+TO-m%_-9o(Jgw86yOjA>|dM2XI^!6l? z7xPvl^m}TCz703rSqTywg+9uL?VLeg(Zr5XIT6H?%>_BNYqNJX`EOud*x!h?%L{NLfi1J#|dfGC(IvCCg|2zG=DJ2yK{PT76%BA zTCO!&uiO;j{wLl@_V*t@+M|aoB!sDCwNpIDBTlvxK77 zQ}dNyfQaqz0g0O1UAXzK*VC>%igrwW9PXS15}fZ0(eB|1VRk^Nvy?+J-#Np_g8&K- z4waU6mQxu>w(U4vL*uPF+d{48eB~fuVvk=m-&w(4=r0N8PtbPUpb!kSe~g}hHVn>4 zX$%nIT}U0SyaOLg5=}z1sRdL%h=!f9_AICx+R^Zq+^}z&-I856E1?RoC301S?gn`| zMz>B-r}Z*+LFJ=evl*^@(spDJX^4%>NL!w)ak>!SSTe;dT`hD4^O2tYqXeh1lN^Ex z$&>e^DPuKfFv(AXc^1)DoI|I(lns{CS)}gY!Y@7cp9RP6ESl|>&7YnnWdN}3(< zH^D)IJ3@?NA@(FN2rk2~Ld0G!t6-qeKIpZc;rD`rn<{ySgc+(bz|T70IdOJwUI(!& zCG^7HOJT=GVL@#X&nP0fU2zD60EQMGdgrNfuQQZF`>m_ zSPKxk(0kb^Htnu7SgVh2m-6@Q751zAQ)Bd$)jiYeDl}#Eda9yV9+0t=j?SX(a&-LC z1LuMRcNW#ViS;~cvc4k5UC~)uuAzLtWu`1986(Hzf9N4E3l9maW4h3;w#NBo8WvxN zvellYo07+yGq^wfS?xLwtj)iaXke=e)c}_C6jwm{)^(ZqNKRG#t!H~naJE76yb(>2 zt@{}eoZOLdJm=}*QT_^DScoKy38o`PNyBswhDQmBVKIu$bf9`L%voV|&2;FsM&w*@ z@HnPZ`QMm&km=AUeK4IiTcix~B?G=63Qjr50u_uO-wvjL|{c6@7#_mrtXnL?5JLkk( z5c9DXr3SUjqI@o6H5b4wSSjFVWfK3`D&{nv#2ArGCt%iLrA&?g0qa$%(67hw%a=%K z=)NzWuT-h)bK_@(6K#f#DV13Wvj@?T+nALae#$Mw5pI;=>0GsosyrgHR?A5(T%Mnz z+yn{>t7Hts)ud7^gRH%`*NpJrf;4V2Ld=zpe;yAu3~>BI0XLKtl`((!vk`R0@rU*- zvO4H!1MnIhfsc)Tb2r2YV%HIsK;(Eu8ZrW!6I`LQ4I&`Kp6xcy_3C;U9Kr6E%~JbJOv)N_73)K6mT3I?GJ29JA0qf zi6dqxDL|pANMe8QfQ;uBcH0jO*-`Iv974d6v7xz?NKZk|hkFM{)LZv3JS|3Diip?N zgcz-yNC2I8%SpB@ThUp`(z?c(HEQ~Y+M`rA1u6mJ`7B2Ze4o;@aN8X#Kgi`9l6^=( zp}-A96U$k|M?y?Nc0@Vl8yv&wM|k+Z}0CNQma6{3svf^w-j6NHEi->B+-R*4<~$A`8BAX zl@9)){rwiioW%a7L0*;6n5>9b5H_q|kmfmx~X&40o@;H^p8zReH zMhk}kpOP%ntt}Qr{;B8xLY-1<@qPrG@-Z+b~XE2k~AiHBEFWD%AH#oHt z@u#FEyZe)1O~R<9W!o?GD`*h>`Xyz`iL^kePQVyNad)JGQ(`%y&<-5{NK}I+zJJ?P(55gMHgl-lP5!tu4*hxdJxt#O!Gz=UJrE_fpm$OBOIV4dUiJk zipD^*sZY0ZEc;%hzf+lNT%VTPO9iG1HM*`94a&SQog_z;z$Om?)FT|%=T~o-bD-ap z_Kv6n<_klbdSX|Ej!@k?Kq%t+hM**)oh)oIcNDn7o}gKypiLG035Bm%#Lt`yjdK8> zXxkqd*xaUPRr{^?^Wdi^H#bI< z%ZRLb#xkt73CK&szdGexD zZLx2!)^L_2Fg^Xs3Dm163GAX&8-ts7cK*yjbHCOFCmqbVI2}z>W?Wnp9wn4JRpp<0CzgY_41ynd=4&F~=2ijlajJyf6U5|`*oGE)sJe~PE)fk3R{gx* z=kWl?XquFiSA<6irKE^atYnd3I@;^QWA%_S!a?YX-qJP_DI;E{tj-U?q-{59P1A3- zSZO5woGboblkLZX$T6uf6AR$O^uYrjWwd1T023N}PkfMOvA*KPR%M|RY|iv5k@2}T z8p^KRn$JK5;iokQky`_#h};_d^5)hsZ9=Bitn<#p&Zv=^0g(M!p)Nt3hBIm|x)EVI z;pbtFCapz~vxm|t_U=~sGbz8;6#Q?r_Gz8rEL-N-YIi{04+Y3T-QUBoloq}S5LEuj z^Xz-Zv-E+26{lsujSLhlrA8a15=iROPmRHa<2gfc;8J6~hoKt4a2n0+(g6d62B6@w z{2i||Ep;g1!c4Oj-sc<|F{99I*wK5lwK=M)*hz*WGgMOwC4u}ZmzzTo87 zU+eT9&*#WQzlOeEU%8S&8vm)upt(Q6Q^t?G3f#>6%69Z^bL*GzQh$#V6QNRnENPFR z5xMvZZ;NCR`C-85qRr>k_k6Q1jvVwhcU#2^QUHl{0bleTd7sW<-vvS|#Jq5> zipchM5k0XYD_*LV8e(j$q=jKk3X5M@!n&Z=Sq`fwRzh#g?tuBVG0NI>P`6 z!kP}L7YfyrMLtMCOyf!!#8X*`9r4bK*c3YK>m6JK!Ih|eZ7gc(jf2{=_s4>)vFo-= z#_p>#VK>|#IZW3j_a_~u#Pwabq^WQb5ekRtN$k^PF}3VYp`S`?L;kH%^ksBqqBguz zB9i?DYLq0Pba47Y3g`&^gMvV11kK!ZQKf#Q`&dulAH5TJc*O|_zTkhQ^KpI;xzY|M z8Gm|=p)ovT;mxKQ4|s8w-dQL&akfVCC-JAA*@>t3ur$BOwlr7Y63wx+CgK7N0#qMD zy*bWrk+Fy}7AQT0ayS(8(|Uwt4Bcnh>^R(V*}t5oexN6MPNsH8katd3l zAciC}rfrmIzXwOJ$mo@0DTNz}=#@0{G{Z#&6T9UwCvb1{s`3GtiR^vlgY@e`AffUh z_3KgmdTHgu?B9>jza(ZBCM0$BR76GddWlMnri@DQ5e5;M>aJ9j7vO7>w_;N=U&lJ# ze_TYNUh8bVR8gomIgRXH6O2O9c>X9n?ppPJ2nS^?j8O#+RF%AZoNo^aHwGG63~>c$828 zN{o^w0QHmbD4_t97{!V(D5rICP6z78X5vD0ifdl!cCdhALRFjC}SCbZA5ac&F zs2&eIy)nDPm}h!D@CHiVHpwXcIvYO-s)5pQf8-*5X>xzkD?yCMwf!9yE?vZJ_US-e z#OIu8qcu2n$s^ZMqa+@wUBqYa-Aw@qIvl`7>68$GO5_E;&;)g97EqZFco;2QP18lG z@B!1528{hgAMj0CCM0pchZ?2F{dVc2HGIJA7CEuyQRtd{gE(5d(2n4VOtTgI;9j;Y z@kD6~g3ABEwup5ES1yB^X8D09(RV6A@N@=*kI~Z`hbdhq{JvxV%vo+-!r{i>_ZgU7_VXW&p)9<|DRUXTK@KKI&?ZYN&bULm|@ z&%vTjqTd?3Ur;FVxeSADi@!kAl)kiYghvVa(!?lfd}-egj}r2wiBT-9Ez#8Lv2Tdm z^A9vKe-Q-0R4gp9l;lqns)|R3fCbAJtQxfTA;ZZ_FDn>~|q)!Tu5+YJDibbTW7!3;6E0Ee9miH0s zQ-XjTLt@>>mn;o3qu?BZaVjy2UHtQYNq>v(H^{FU9wkH=8Rqi5@F*d|5Tkh4-K`G$ zir_FQm%VcmtOF})qQl4OgGcd6*eoZ=qcUu|w*@C1q!Tepno|`Y4382zRgqyXe-a)g zL?>dD^k+A|93HEOvl|=)dzDS13ka69jYO&ZFz=j`13mp#H5VS4g4{m5^yJAA`!2%B~CUo{X7>leZ>iPKPjR{$% ziVO^G49?3w$RQ~b2KxJmIB|diT1xmJ#}f|}?qh{f3ynqrRXV1*1;#2gii_oNnnM%| z5qGyL2U>59wF$n=up~ zYh%6z(3>hZ1&YJeSg^LFASRqk$#ZD7XPV9-<22O<9N?_ z*LkIn;`3DWtq^3jPb;9U_Q%)B)%`DMoIdG#`o3(C~lYj`<{T9ByDkAE1|1W5WTNBX=rZOfRqjkNKWPYQYW2kYn4k*8{OCQ8`Mnr3 z<1s(>>uAUP#2Lzkj`_(7B3<_%XTR(4YQOy|C!(0J2=}E3@G0PU!aB2>FI)>(_oS`pg{uCFBj2+q`6aP2Ec0Te7)sbST`iaKv2NXgwhxguxrYR#Q zp9+r>a*&Hr(m4CS6dony_!Og9krTtF^yufr$=&eYKL!CXeIS;|S@`hY-?OE%_f61s z&hZh?%586<$T)wuXB2bNb|c}1)jP8CE<)cxys&G|wneHva}%bcybvn^SV)1iQ6#*u zeiR)eFRWx7wfMqoQttM$X8*mf-%W%rwmlAp`(43k!t<*QAp0n{@gOPEymp^?XLOOH)c#v?Z~ z`E7s2=`Ws-lf@$ZTF+y!#eZtD{H%W47ol&{+#}ZG_1h{0S$-`SKR$EN^UeJ|kkw-k zzFrX)e)mCIn)kS%#p?&0_pGm!64t^nG->~(G&B#ePY2?n`WU)0DK?&L2vp&s`Y<(0 z&nlQ3O7H;eX$rQeu$%Xt#`x#6fX7@^f6j0do`!Hy(KIq)Jh zxh8SxS2aiVU08F8I<+m2(r6l87pTem>~Pa!;jDE7!_k$bR!O`;V|fP_QZADy1i0~m z`C(s`qs}raGG9i8A-XB{gJ{?pk%&W`_1rK=9{jmhg1NlMW6ON!eD90A(Mflrxr9~H zZ{?$15D!;AX*}y(Y4nHFkL)^}5u?=5h^R(1A}>qf#orleIz`_v*G1pif}{vj#; z9lR!UM0Hh}q@UdLV4p&;<|CYx<}(f0vs7<>z?S2(iOLH669DX|A;7G209#V;1hEmU zDhA6$Yxd4|8(OcRo~pm~OkW(FY0$0o0yItU{t#}ZUuKPL7pQrHnbJ}0Nw{w@5A%_p z${Tv0%5M#7D)QWG_cY8mn1cLMga3iv!GGVNz+WZqsEV&?Err;jwzii{&6_eNSq4C85jN{NLI-X&VWTte-FT>TW!5e5O9t zu13wR#QL`i&a+iYjQP$I@_9_nSDHXstW#0L)a6v%j&>=Wif4Ky&pf;EzO)({U+J*31ZP3l)!)(c@n;gcMSHal5N99PhAm0i91u(63Q^tvWvVE zHNVZH({9ylJ*I3b?8&OxlMP8oeGVh%{|2fN3tg;GZAT;01-ktPToA7R94{ZTlr&4^ zp2UFTqL%&E?CuE;gtqpSDGs<*b=7GdZN-SApKBYIP~Vyne?HN^T=wCS?e;rJ6#YOW z`DTR~pB@vG?l+)mX6b%CYh+9JC5(JLGcaBNeDRlteX@7hpE)SlPZoY*PV-`kthgc! zFLnzEdxvSLzx70(-TOoiaeSr`h%X6`5)z1F6iXm3VY^(;O8lkg^y=_vJ%~gOL|W-4 zM52%0)`%66jLElZL;4#zMe~uK=exu6yci}x!LjEnXY-rr-kyH#J{le+w02??Ywdy; zw0t%^Ru3!3LFj4a(l!#xjArzeoiq*3b{ATi>8x=?WBj2N4PcjMa|rsH+|iAJbCBZSd3G0{ysr>1hawU`}6Va%Pv zVl8BDwuLKEdEU}|syEw-=h{k(tr9rfj739_owx_WexVW8ebOX3o?+fLE)HRsk2G4= zWkHLKYMeohHpp!PN$v}PX1G`6JgJIM;TRN=k$ze{Mh3q(WT_PrF+Kf2Pww(elM?~U zJQ}fpW!E_gdSmLnkjSTbpw;8M4dOWxch#=1T*?Ly(2QK>)!%xezvAE~I01?32PLZQ^CR@w#B*Yt zeKE~Y>Mi^a4cTj*-olWHDEq4!WbvQ&6J`G`^le7jNnr6PJDKEUhKoyX6nd;EyNew% z72MNNo^LKpwfGusZWqav`#=KDh+m}Q1G}{{Y7p-(q?XiYVlqT5LZEr9v&26H?3T6LElXbMxSe1MjT1dX2;pZSn`Gk%bU4G zbkF^n;xE0^o`NMdIiJmdGI=!jsjiM85^n*)S1h0A3WXo0eb|0J_od|~b6$e&8Ba6{ zOKRSk{gqQ_n%Q4Dk*SgJLg>Y*j1#;^$qQi_@|+T5BP<%kER{{2|#+tX}NMu4md6Ddk7ef_wYd z#juWeufGPgOWOVkh-ProHV-s%X?rDpInvhJ3{vKv9WxpGWRxUr$hl98y#t|9LmbP_ zKOHti?|~bIP(TiEyHa5HO-d{*AhUCZ3JA2|d?WX!D&un3UHBFiUGQZ8 zO*=;~zv9XqZgeiGxWU47t~tbx)EkA2T{?Gl>=_~!=UM?a7N?hpLy9Y6_h&(jj5XXr zjW$RIiH+`yHR$B;k)4uE8WGM&HIcfkD1@R&lF?6@H`Qlrq*r<>%Y@jOivn7NconfV zapr<19+I+#yJBC8UWL0tuCnCfsoWKE-|BVfc31H8Q2~YXWdM>ZoG+(eOyOj|(kYxm zIqOf^d}4GYDz-gWN48~f(O_xXVX-CIVIevmgnGH(fFUmdE;5hpIGqR@%T1MWcEKu< zjs&VhAoX!Nr@(HLv|me)gQbri7k5g&6|`XbHB#xW?{*s5sz^|GrSW)luh5*U6%8%A zCrCcgFC_8%&(`dO7X7VDcL#?_yXwDd_$azXpmORy}+Z;d5woXGPjo_SvWFj_Pnmo`4!=r?92{SN{mxo6Qk%<^3ea7PJ z!ejN2vB*KNSJ|XFTds>-(|_O$+!8k%f-0R)*bM0wlJ}dBw5WL`JnK;A>3h&LrKtI% z@F*dsB1TC=`CkZ+5~3C{iY01>;AKd02ZnR=; zAOjJjq>(dAazVWyL=qY1a(Z}_5J`wpQpuU~gTtg<^ufy+J_nlv1?5bJ-F9to&OtH} zqok2Dd&8rIE%om9;*jA!$GiD*`&FEoJreAgcJPM)`I)Wt&pxX zFJq(98ptj``ENtG4$e>B!Af#J`8<9(esX2@N+0=|K4*>aBl`6|mE>3Z9GN0Qy-HIBA3ympUtp`UaIm8b~lcjq7zFZ@MPaU-}4wqXc z(F?iJr=nJ&Tx}{>`GSw5Rg%{QH;75t(rbQf9Uxe)*9wraT-_e?;Q=P;zb6ZBq~rWu z)M$hBkC4vhsZy39N&kAolR?BuPoZ=Q>VZgVn=Q;$>jnQk z5tcJVB$8UsG>QCqCNzjl(odt2Kb@c6n65|o51!D=q%?qTkMVq#)A0Jrrx2J4V*K}?H5CH5-kvSDWbyMw>rEM%Jc5BWqqdDisC zS&q$Vr=gd??In2$e!w6K0?$&d`4WWtqm0y#C-)~qJhVkqhIro2K27E+iIv|+&bQGV zoVesATc}YIFVR7`1H0R^)p8L@J*xb>xT&~2ox@=+S)Qqg;)UfYRwjm>^g*emMpT%Z zVRkb)9tv3@_hJp5{VY-tC(k2S^Y&V&%bRd%9LD2``Zc?p#Ry9&kMfWFNva8fh8 zXBxIMAbeTg^v2ms*AHL?G}7Dw!rOuh$&V#q%!qsvwPo5C!O>;4IVr6(MLwlQris5h z@>zL0;0;xqqxU@W`6BwoBA@J6mdIy#jx+pNu&givaCM;~yJcdvxrY?A^9ow_D+yXw zv8%h<+)3rB%XEo3Dne3u%Za3r$Cs6R;-bTJF@nwb7YqrjGj~%o;`54W2ie zaDNALGIvIh{jp+mZ%{2*A+;L_F3sw0h%YwRDivC|O9%@2Y*Z{ymy4{L9BJrf7j&g? z52`yo;XhE|`=V~Hu7PY6Hp`nREmh7Os$+j)_pSSRHMae{;9y+ExN?mzD3Urav?A{E zMc(eGJJ>EEMovw$xA3SMDp?~PmtQzBZtuPaLby6vqH(eA%g;~lHzWXBW&b?Fo#NIk=@OQ&D!4f#VgDc^?7 zRF_WUr}8htBei=5_ZOI>y-bg=W+o%ZeSv!nFir0L8scR2;dpO+~)vei=9M4iv@*@*UxYU$r*>(#ky;vclHec8KC)>(1hqGgld|duuUYjqZ7FY z+yN79li$FQ+>&|?{bH6B`;}yyFvUR~z_c`7?ag7bWrB$+WWQOpVCwu+Y@=m& zFGh<5TOdi9EQ9GxPxcW7x=%lHCo2t>{baDnS@&(QIGi-jV40znoSKBaa)Gtm#dD{Z zZgWM#E7vvo=-D2dhjv>IRPeesT|PM8MCBZK<(WCLot?NI6DzlQ;jN3mcGfVJb@5H7 zkxk`6>w?BJH+8t=sjx1-tj6m+t2bj&u5-{3;EQ>T-gX>GS97HhCM|t1r z{j|6DS?}R1k|x*XY2i^qxh`T9D+^_{&Fke<-N$;CQF#0wGE+EMTEz-;V~d8 zpAYnEaBlDypcZ^s+nY;(G24b9HTQPzg4ZB**_)pSCrx2*p5fCa?DEqD0XH`vqF?l< zG&kutfg{XK$-SW+eL;u^ueoWSzFZ)C^EH5M!R^i8p+QpEn{Rf2afMM9d-IKi@=3b~ zQ%|*N#j-cwg{IluQmkwQpcBQu5$#vVHe9~Sgs1$(yJIvk7V z?BmuPmH(SXjukEms^unT=NQwNV8@UrX6mpjC%C~h3@N)gWjBU<}StjNxAz8wvZnS-@cQ_X1jecAh z;^oHiL`r>z(XPNTl<~>At|}?gP;kgfRY)KFRCp8GuILPsp6$(BFM zX=LxGpsh;dg?OK>;R{=Jl^US1}?l(#^#FI1< zDkIdZ=hSCD8M` zQ9`FG#3*TKemp!%C|zERV&RaTZDDq)_ppU?z~))O!7XiT1>E;j^_fDsHeX4qK9hLB zhEy%H_KZ}oMeUgxwn)zI4;`Q4n1~lw_U;$9(Y0(8n@pEW_UWU~lkif?VD?*6y+`Mcp!LKG=RNkftE36Bz@NHIzu6!}NN!H*e5ew-~*28!gE7yv~Y1;lMv zlko!DZ`WNc{~SbQkRre3nXHNV)VpbwxO6xEZZdU4ITv)xeMPd}oT@<{|V|{q69$Z5lgr0~kZ6o0t@+%8g4K#j?KVAg6)da?Z=rHNd zvhkB-P;xba1R-=K;0pO4>|G!Vp!xB$z^=2-nO@rSm9Y-+le#&nNIuLfj;0HHGiWFT~5k6yhn3vT3biRV+J4bn&< zExx~_R~KoMgq^%nmNZ>80m{q~sR;j)eHy~FN`i*U8#B#QoPu~A8VMiKV-G%L`iSU_ z>Fb5uU$-j;Y)y!6t9X{r2@yx|7zDNqG#N2{N9U(r%^{6HKXn!~W_kMzkUCwi;_M`R zd0wmr)a%bU6AywW4@G^7L+3dZMQng z5#i2uoFkoL@+7B@-bqhFs&DlQ7qfuRs$)(hudrMZn&yC4B=P9vgIOjd*W&?dlzu&K z1b6own&d0=90;i~eq-(fxniMKtG9BK5yDVyL}+l{TB`|?Idr?$Y#zK^4ky=GKhO*L znoRQ+y1~P2f#ONlG?B8Nko-;bZJv-Mot>YMblh{VVnC47!M)Xq-Z*S)n?50#4&6pP zs;fI4pIbGdmxbqJ10GW^(}@0%15`ZrNUxzNUDvp4J64>`eIMqEbWZc-3}wNQr*I>YTr3SNz0*ABG~Wq$L+3QM zGO&AZ-$ya}UCKfcPIaqZu5tdZ|ES~A%{Ko@l_9&@X=LxxVAPSu3++|gMb^c{iJ2&rtMUOf>=Z}`v--FQD4wteQQXLn6-c0up?6=<3= z!gynNlu$fJjFKjvb60qjP&`MB(nmb!U~q8LsbH!u3m#!CvPE)sdMLukF%d5{?VTGJ^AZn=VM=EBKbX3 z_sCrT4&}rrrbGeY&CY ze`qEUVwlt)i^dD?QU6*ND5Vws*VIVCOH#|@QP*A#1LThJmD?KRet5R_>xgOnrT#adIIX^7&ym8+ zY!wIArBBItq9=Z9#)+$SUTQI`(u&T>Q*|s`6REM)dhx#bhvrpk^m}*g*uhvqZhNk9 zxPXG0O@6}HNE001L~Tbkm)^8xh&5|Bn)L=6(wqErxi&TYoCo-;!=-XH5*-%VXZh)< zRV&dPiAKu9ZTiJr zKzJ@9 zIDz-ygdcUUnJ`rWS4s4Z&cIpc{I%J1!ALvG;Fq$q~=Ks zK!fV9rq>f~y*ciPe8g9{$yOK#u1v@1HO?yEpk6%(DBM&tVR^WZHF!Tr058LV3O{(q%`y7LTSELj=-NC1O+!ku zP2s``_A_7>e9eOIS*Oa2zCJuk zC@)%!V&z4<=jG+LbWYdnwY?)eeh<0Q9ISYgEI`9)8wp3QpAYovNxZ;+jNanO`Y`>! zVAI(Lq)9;*hv_w7U5>*?(JqDK@SJ$LU>~U`IJocdxmd{x{V9*s({BPw9I2O_9NN@J z@FtZfaDk50zrZ0n%X>bk5^gV}LHMbMU_Kt?2)i}s28 zLb+aQwPq)B)$(Mc(3le*UI=5ytVrs~Na}f?08H8&)}ebjpj0lGi3dje4?FGc4Ph$W zv>=quLnAUL@d`Z;En-}F;<^0sy1;$foY$cYW)rcJuFM!qwzvzf&cR<6FAJPDc`;D8 z4JwHh#VKBROsyadV!B+Jv+NBen%T19j+R2xsihIS^g3~u@@L07QpYADVm!vZ3!Kt~HV zQka$^KJe8y=-!-SwM_pJn?S{V62H^CVuRUZ@70l3cTX=H0jK|dyq=aPCnM;3m}eQLbU z@w2$y>5a?f(n$qVKhSKZrsm>zRc7!7YP3{ls8>&Fqb`JLxybZmJNr%+?S~HTROkPd zAlO02-h*fw;)`CV$o-ib3CZn8$kCD9?(t$p3%1=$LO^&*G_+l!`$o)uz@qzY=#o22 z-iu$|qFd9dl-+LHn4FQFWF;vNLhxpE9P3&!(hbhvRjoIpG~zqOmwIPCDu$P~pUss_ zCL?UE%3f;0bE!U{U=KEv0$ffN0$d`%_$2#pJskbaLN1X9Je7#!@d3f9aW=7o15@x}JlkP~p>5cp3?h5;_qe zMoDubU@SaJ=tO`R#nwrhtp>+;_rXX~Q|PruAsZqM#ATb|Xp_Kd= z3gtftN#*qhndPr9y;Gcn&xtNkaRKUTnPus-@Ik#scQ`^dP_Cg&Z8V2@M{430TITU2 zWP#KFPrwhHE^HZ|Ph>%qJT&kzYP3PhU=nP>LjxPxlIDgX1fcDq@CLuOlifqC*4nLM z5*Ec@$pp4IDey%!VnLu2bHj!-qQ|C7(TeqQpJrw3H0|c((o6(y9m)1Rr!QNWm~5U* z%xlmq7W>-_uJ}()A((KYzXW$I`@B_XpnlPO<@@N{Jkd`)fS>4hgr7prqAda3K$dr% z_;>M#Z%*l2V!bup&*Q}>-OAj%A>+VrV7WbtA4Y4Rb9#Of6njo9=P zzmPP#IAXDh8fDl*dyW*NSz?s@*bO^TL4QpbkTO3dg0eo!wNB#Tz<}sRD!IlJy+qqH z%}DI7F*FJ}kW4DBoPdvgm%p*w;VNA>cRvZAr=sF384x}yr8nj-$2T|()P+Zl1h+vl zoj!pL9$tPyr?mW;=rlOGJU}9)hBRz(hGUHuvE$Wpvt^v(5aF5?oim(o#>=f}#`v&v z83cE`QEQG3k)b}8+s8c-UE-Tx!K_(2#$SwTUshksWnYp4^#hIj=R1oP#_5Cf^@hr$ z*w8Qumw}_+&(MqEhxF8p33UakhBM6zq?5jZp47uxCPm5Raz@KBqhDt;3gh9GG=Q9Z zm|&hwpQ-@}WrtG?(B=bZG7}J{J(eLgMa}p;#Y7luSjuw?<~`>!=sowxeT;rFe;oUj z&L1Z{SN-Ma-w4?{&NP&9Y?aw+q19_x?Yi_~weB$o;h}S`-e3hcoteogvMcW#r`b^=OhaZcyX4^U!zPc}|@j9ljdnOFWKmAe3%~SSE)I_pa`uT)`f&DL9UR;=i7X9qp`CqC zWQ&w}RpZ5~%^8HV??lfi=9KM5!rABF8GSkXCKqNA`gZm`GZTJ41=(GVVH=@7BJ zAC9aS9z5r%rj1W#ny2uBd<=~|K1Otj^Nv3!g!ZhYPw&o^7r(}G@8x1V@%&iDKJ%7+sWM>rNv9is7& z?LeOj=i^)1rvq?4o|?A_D}IG(bm4qlO^woT#%q<=kerXYn5!u4LT*TGy+XB$#NNgs zRCmAY&Rd(zGbw5>4G+pOxh2zV#g@DnjZ!-%AIHLEa78t_d% zBaStFyPYM|_r?V581zkKGhq5oQLOu!4t`Qm_&wApJ%w)&C!j>V3|kpdvB-q4^eWV| zfXr$SRT*l-QxjZmG9u{yg`R(C$%&rNX5Bc_T`R8e?~Z>ZH7d_V2yN*($00dmnNd z+50Bw-=pzDyT>-jg@5mzYP@5u{&%mYEZSimGds=qo$&8@UTMztIW^P1{d*c|mA{}~ zJ^npZ2;m@(LvZRrhu=5RG^NAuU&Et>9DZVyFQ#z#ov_u`DKcyj zF-ji}zte()oA!xmbo5{EHzBWVHNbM!z!a+*F9>Z`Asl{R=cHgcs8>re=gd`*w1wg2 z@)PO5)erRMyfTQ`;9M?elTVd@x;s2dh(g6EX(;s0@F*ddv>3(0U)JQuso?NE(`euR z&1aBi2jOu3w@gzO-mQN@Bj#}K%FCoT zj$`TUcj!#P8@Acl2tq4wJv(yrH4DOTUS|MuGuDQeE* zasVApbRX+=i?RU4+n8C`zz-PDi5bh!&oUv2o>9KtL1Py*O(`*G>{SCG( z@#JTkt_kt7u59Mlp>H#2K$?&@UiJ_J!WT54HxB#hJ!s%|7Um;#m)$E9utUs2xT}e5 zGSPQ%bm^{^YDgw`wNwH%6?@#(?*_b~yX@#acUOO%ezEjZ_UkCRtFLQBOen<5-@^GJp>}D!y~4b%6D8!%Re=@f4`bV z-vMBakjf*}t4By*n1;@L^18o5E`J`JWKcAJ8co6I(iC#}+wdr%K$;jOO(5;t;ZZ_? zG%<=5NMq;O$&Kbo*@K4Q9C!aoaBy?WnD+95hkE~mEt0e0Ls2x2iL^S0P`Lh>jbbZY zXT>o~LBtlW7t_b=1u)D1&>Qi*%Wa;QVK(QWX-XO$36Bz@Q87vy8XXId5~5KtiiNk8 zbXr%)B7xWLbZSB=D=Vf^dTS7jo~gC(pzlq5z0zQEA~=PhP!prroa=r`ev9rm&WqK; zqlBm;!(8qUj}oE^F^YfHNkuUx^Q*yO(ysb%uZ8Zsq7hAt!Wx~$Y?#p1#0mK*d=56x z35uQ!8}7})IS0u^jIwdHd8}}|B9rX~X5SkgC3G`PhPnKY@F*cN5u;f5&+v5naky%4TzS6et$f~#W-IX)taq2j~| zyRt;`r+&K7Y~TW*!L&DR-OHqV%$VhC96uHx5S|m@1K|r>JnZT$c#?6%E2xno5K>h8 z%h5QGC+Mi^VwB>*AL-Mg*@}zp&onI&FuWa&JO}^iu}MlEvnut$zmn5ekSyiFzlgyV z|EbBj69SoC#l_YDe=csIvUer1c)nTVuCU&??$_}mlyBVim0J_g zL*G&A%3k(eAXR8P8FM*S7l;+P+tqHi>NCuF)|JGP+Z|087(2tcInpD&X)QtX@Qr}S zq^tM^CZ;TC^mTj^YddxUJbG;Ql}MvpfJ+_9v9ca zcuq_c8qP8yiRFu^QF<&NKWRcw&NN%WQMV_oU=^V-WRr=$gQLqdA*l&xN)wXyil$;unh=vgfm5yYo`)l!hnewk zB>Qy~!;#le!N(qhk@@t&NLE&|wDh*te1R79?PLJz%O@r3lkbX{a*SjKy%``HpKjD= z#-QA{5P{q_l565NEBWVT+wi~RAy)aD&X!A+Q}jDdBU_#Y{dF{6Xye!pCK0QAwHmMU z{9_xdhLQ9`sS zMoB}P*M>(4(WV&1!rVy^VGM5`OB*U0d#w?% zP~baF{Hh%uB^1BPKszr8kCK9RtoYTUZF0xqmnM=|g-7Wja>b`O09JBpm!9V1CX4AS zIW_)=p55ERvkP&=x1ecCUh={4C?Q@VMoB~4e-a)gL=R$=K6uGr2M0f9yyVMlkuva- z4EX-n;FN>BM2wP#mz;2AP}+rfNrt(s4v&(8b}U}9gjr2;(}}|s~3hx2~kCcxjYmeB}5fslvH_EZwd~RcGZ7-?V$6l_#AAW6SRyo zY`6~x=Nu#xF-jWQ@|o}`A=#2)E?*6g5+V~ZiX~fuc~<`z9;*k*!a=ZC*`&FE;hVOR z$g}c0jQYy6T6|SVc`&Du$@|bZ!#n|Sh2m2-QbnGXA3sMY&+2rK3pqZ^N<-R}W%Vk! zLp z$uR1z)M$frNt2q{UzXI_JS7TcRl2U`qdbmm2~w3zGZLZFX*BZJQlU2{8Nme>xZ~XKom-Gk%jLvcX%liKgns_DqDpRDF878MX3O zhR-%{dQXD;^dSc+LFi?I&nx%@+yozbY$Dj>c65@^q=T~C8~OWAUtzdJde84MxZ*!G z#ah-Rw6~#eGfYn0)tiK-kYlCyxVXWLyOPj6-wf|hyY!k}y4@rbZYKe6MBu3icL#ab zG~H4LU9CMciCXQ*tu2+2Sj#U@z%73^?J^I6mwtl|yKe$;lj7o+o%*nCbSlW=bdmLpf&R2RSe1_ckJktYe5 z9%rK9V1ngNr?)Ugd%n3e%j#?Lb$d!C--{AZ zXOnNZKgzDWH+ehAtUuBML&+UPdLp}WFZ*;L*_AKKL|`Jj@&(i=NnzF5m1hwL!j5gs zi6b21goiRh;y=)9`5RdPWf_Kr;PQK}yP$>hd1JZFh2~tXxOvA&?z*X{ zSsZVc4~{oy3q>Sms!wv8ckH;A$NXu_uogz@!o^rFbIYX4n9MtkY=#i@ywi9g!neJe zB4cus8n5$$W1BH4*4~pcxkS9;Ig{cqEiHGcDfFE*sj*SHo_h5pO)g~F|p6& zuVyCXh{%8+IY%claE6c3#fJtos9m9f4Ve0XLj$izmpnA^d-&BI8W3Aq#s=JibDU{g z!2!7|p%QFFm&9HZg99TsMlBW%(4HX{B#7jxYknCk+m}jB&(=uq=64FHq@G~&ZPi8@rGzdOUjW$Tm49@3^9cWW*16xt5xK1`%b2ciLr_0fl z85GJE9{6e|poL!lB{cGf2k4EdA3!*q;e}LFm)j($g)+nNFWK-xDwK*dp*N&I7)JR= z*rx+A%1<1#u@DAT80Ehp)TO6{VcRX3y!+EP&}(ygmWi;nIR!03;@dE4Xu<k8Ig^;#_|w&>#3=|Z_0O>uTSuxnOt$}}Uff%hb=lBu60#CW<4 z^PADPX_%9k^u~C0G9XBO%suwtLpj6Bpf?T|In9GdO{Z>yWFE330Rsk|((-4b)8OdR z_?BWx3e|8UVSH~S9s&J8Q=`ZDz8CO@s-n|-ZhZeL{bI&9`*jqJ@9QAP%EjpaZ|-VC z?6}IXyV>v0Y+|$~*|14%zRd2bjZ#x1T3dr%H<6SEL1dhrJG(QJxp!`7=5BVewN)wJ zv4aY|BGxn^wuM5eAV>=(5{)SMK`gbc;vY+piXeg?=${&Vo_D_Q?%v%^)5IV9?3pv? z^PT6s=Y7wdJIA}qUp&5V?e2G6(Y0{E_cz(4Ngtx`+9;my;`Q=jzQTCxKZpJV9$kKj ztjQ67rYTc#UTW!xv%Xe?U|C1}Y+B!q{v3MBf@NIs?(}BljHlO`e))0QkvHv*XEL!a zu+(MT@l8t!wTy4RQmVbhZ=nws3QP8nH^pW>eYIszTYByscLF0Uf|M(=DX5)iHx_bau2$r}hX-3sf@_&+! z-%gXgf0$Ktwd|!%{B^1=(+K+@-uz6nGKCZG|KS_E=$a6fsuj<1cietF$EE)N>h50O zr&U)i>v&vVqCE3anVded9yukh#qG>An#=@LpUZ3=%-sL?7nC`d0X~+zl8vm7bTCT(d+ z++@Lk52TfyL%$$?i+|f1N_}k@ea$$yE@MAYKp8)l8vBuR*5Xau*U-qw*nfl}G4>^N z9gY2u;^c6DF*+#dDh>V*tli+xRo2Sr4}%-4r3%g5aTFu}N4d9lMpv}c_hK$C+}Y%R zQ*1H`~fkgSSyC%2e*``dzf!NaRV12EIW6^4g-~XLU>-+zD$Ws`<)*JaJ z+Mj!b$?Q^y%e3Cbv{P@|1Ls{FZ*j%gEYlNwLU**xY_` zU72EYdwIcJA9H)_%7c65S6^9!mzdn&g#fOx$$bSyMkaUHhnF+C3(QT-?(Hl0t9VLL zLPboMXHXHf42H|n-^du5IkYu70J<_J11UQLIyIMDCCLWY5c-o>Yefx}chh1U*Ls{y zj10{FICCqG(rk#=@RH79T2H#%tl?HaLFpFM8BOcE8IoyTLTj7W;q19Ua4c0i?%~GokIeq}!=mXil0EHYqd*gtyWBT(2BTE*-byu%w`J#EY zKpI&r&KSs*wY^wYch-iR(FQg$7u8hGhOC^aj#ktPyF91nqJ72zcBw5K(rPYR>??8n z(QqJ%u}vJea5U_}&tCXb7_SkI@YgWDX?qj+U|Yr4DkA}T- zdPR3tNE!Ki;hExqXSH0#MSoO{g0fHIvM;`@xi+o_eMeL1+wv}|>qNWU#YVVk)^Yrb zbSllo_S-cJ?t}7JH6}-NAv{~vhr0Q=UT>zI>XMAK2w`Rc|)gEw*pylc^8g2 zVtRcSd#2c_Mm-!dD?HjB1aaucH^SbUKRbTgIQCXG!tKSIitf6Os~BpfWa}>E%%*Di zu+K172#Te2N-2$SwCPS$5tfIs6b?n@W^G7vZ!g|x${cQFA3O-kfQW4LsSys^YGtm5 zfdq+{aNVv~8sTPF*BrN`l=Le2foe<fG`e(1LzF2M@5!sQ0QQsOqsmDDgCo4j z@cpWHXmS$K-b8iLH=N3ZLjgWpe;FoYM; z1Vh(-RI)`ws*{Rd##>oMEtPO;0To6)9AU|Pq=;9D6NqjdWqwrp9niJ;T z0ON#lkFjXXTYqUo%LQ1_$RLpZBRx7>mwwl!&vofsqz+5!J%NLcVRFNFnXNeW@X*GURt z!H1YlSa6XcVZmop7Cgm}ut4L(78ZP&Az{I<84?!!jUi#dI3KpK;8P3<3+5RT7My2D zSa5|QVZqI$g0SF8hJ*!olN7=N+HVmHLWW)-{FLxTz8v@p;TJSOFA=`E8SpK_54HfF zBYgWNz-hu`I{}+WsKbOi2>Z7ICJ9GI0n>z^6MjWFvjgx1LD+Ye1^klmB0+fgBx(5@ z!pns2cLN3pZ|nxN?*Wjd7VTW?1;PcwYx@AN6OQZ$OcO2>{!F-Z0PtJF(-VMa2|SP1 z;(4_e&z-S&E{(-+BUt=)g2kLc$WsOB2(V`Do3kUNWUsTYbW@6r;4ue{X zVmPrU=^|a1kBQP@>ck9Do^kAS5|N~DZ;DJ)_ZCX*O=^`)n+oN_Mss}{gLEQ)A`>x~1kDzbsCd5or0+@x~Q+P72B-8<3O>fF_HxSUMF1f zS8+3T2$qWAJ$KfswyD7{7&FTZnb@DIx^vj3O67ZKY*#V??MlTmxmupf51meOU4H2C ziQEpMf3I6y|6D~}GWgXn5n5X!w2n_6{lu|MX0RP2flVK5%Snt%BXihzZ$=L{rKW5` hA|Z8u8ZAadfAkWNM#~%x&%P3^?btA7nYEdT{{cmd-g*E4 literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/asab/various.doctree b/old_docs/_build/doctrees/asab/various.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4375a3626f0f3a59cc281ad433f10fb086beba0f GIT binary patch literal 65371 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/asab/web/index.doctree b/old_docs/_build/doctrees/asab/web/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..fa6ef2626ccce3be93e47185588d37985a74ae17 GIT binary patch literal 21509 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 TxkNWx=E^kh$5W(OS`_{VnhkUV literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/asab/web/restapidocs.doctree b/old_docs/_build/doctrees/asab/web/restapidocs.doctree new file mode 100644 index 0000000000000000000000000000000000000000..54463b67bb27b68235b38ecc0634b553866e5d42 GIT binary patch literal 16339 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

y|xjUULQd(rHrtFvpP%Sv=fVMIDwidm< z$Qy8)h(&?rQ_Csd0_g@ZEx&5QrfBMfCT?}0*J-vh#Qh>uf0LucPR#pW?BRGU(J~Rn z(6tIogf>jjbW$pWyPC~oGDx-pUQ)udg`%5DrBQzCbBVrT5S){uLrqv=qUK=9=Wyq> z{0WGjA*}*(f*yeAdjl`YUq8K^Ee_dGZFAFP=BcG)fp=1l>?wKj2hB0gVIdj|T4B^{ z=h->x$r(UT69FBT2X#$cW?{qTv(NoB}&T@*=dEWFS+NSTWeZ*QeT+|Qw#!{V5LumgKQPiWI| zHDwsilBtN(POYCeKzR^@Swb7>s_#|~%%FhdK!ta)x-Mf0203S=*Oti!xPN0}(+Y-~ zF8n^s&JblU1xL@*H_nk)a`biHMjX+0Bj)C^%10Ermj6$6%5 iu+ltNHgo*Vd4cVx4&l8=H`N;s8S28OQT%|j&i@B{TEvwA literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/asab/zookeeper.doctree b/old_docs/_build/doctrees/asab/zookeeper.doctree new file mode 100644 index 0000000000000000000000000000000000000000..7846fc894a44f6ad55b130780bb166806b0604a1 GIT binary patch literal 40038 zcmeHwe~cX0eIH5jj(5l3q$JC>C=O4SxU}!~C@FR&T9nIBl%-In7?QGSD#YIG?%d7H z?e45*c1hmZtmUSTMf=Hi;h!+cJM!t?^c%y%$2Orv%?}#&*lYDJ5ibDpjEc5 z)^L*qFY!Fla+~65s@`pzA62)uf|f)XJOuR~+nMU5*Jax}?lM*B`7>;5BWQWO)0^33 z+XeKUo_`0MuIS<7*Q6TdhZg*(=`A#ac;Rdugt7VRzl7AHF0W3X(kmEK&fWF-v#TD>|2YQ2h6-R?5_hd&XaDJ5S zN{`%X{=;_j#rQr2d>;pnkFrUDIjfm0l+(HJJv=_H)d==vsbqEj!f0b)Te;A%{-)R@ z!0pCCkKJ2Ddd_tpmsr>?^a!wi(9k-UVZ;y=C$l|*m*#cZo~yW9eRJ$@lH)aueuJ2Q zhRtXc*CGF!Hun{Cr-imO%`WNj%#X#via-;b?XBiNH6B%DeSd|`DjE!yoB@=0z))gv z-6t~inBcN#5kbG`!~7RH=KVDb-P1;b2gs~fsKh?#&vNB8rIZ;2>~Teki|^gMX_I06 z)7;Vs*{cVMG%|Ik7DaJAXt|`8oy3c;1U1j;_-@B($I+Dl77%LA4?HLuShp69|<2p$vioH1pUmDP1uCqo~&*{V-UUnk!*>PKSr|GubWe**;mV)JO%zH#V ztN%G(PU**BO#nr`lpWG+rfC{S5;TK`8&fB)vlKKuCs|E8UQ_mc)rXFAJg8?`4^!s8xqQ1Xk8f*k%c*)!m+T}64z>)I zTTU~m#gSy%#0grUXwq>zUc*Zg;Uo*w%g!?`lm{1y&gTSg*&sOe2;$O;I-2WO`&*xL;N77+u&P^kVhg+2gEMHSY0XAyKUIIQLZH?D0^0Ti5omCPRV+17hBr#rG zN{*CgNUgfVf6Xb%5~X&>C;jcd@1 z_KopJd$%>(X|}TwbifOZO0^NyR;<~=#s9Ho)25)=j^YknMtfp3Gs9=9&PP^H7`7_$ zGS-VD$7W_6{8#suoJu8V1)WNzlz5FLe4zLAU%6Zsh3Loq&a)BJCF$!E=TH2wh011B z?>0PLiyEQHdqun#J!_Y^{1IOIh~4lr=sj>7!5Sx!)WPS4CzNhht7!SvIS!8r-C=TH zkyfZQ%ZHjRIh*S7q+kacOb$y7=<}pfIp{Tw^0Mwtm*KcH?Rs)l6mbMl9cHO%u8dUfinnZ_Yk4Sa@Hv98w!rSam^7H=_`wQCw8}S!OL4b`-z=cJ0=?2^72g`l~ z|92{gfl^45O81) z)xB$$Jrd5^z{xV(2Hg?E(dGf#$pmu&L>k##zj|;=!hF$OB4yW(^w^>F8>3#e+U@z1 zXF5F>bDVG+W-$t8f0kVzIeto=nBd_86s7Pq%k9-;h^^Ah9TOKgVi{;m!TwS8ctq6S z#I|DYQtQK8314>6mkQ0QT&ToUWN@*+!P1&?g_Yr>nLJJG@tcQuxu!mTSeHAj3LHNZ zwMd0m+HS|^KZI5#Aa-*gFmH=6i%Z9e*~2e9et!qi-(${UPNKt4%sG!MpevlAjybxB zbNGoT5bfom<)dtZ*D&#=@Ij)E6)d(9AlkB!#5Oz1&Bv2=ufn65M$!>bw)raJLg}z` zSms>8yYE&92Y13dP%hkxKg3G!5tSVJhr|5lbJOX~@P;?B9fDq1DxnnxE10}H!<-6# zeeVr6pVq_6i{F>ncJSsr^o5AS?xdbMRrznvMsyl`Pi3(eo}xDgt}g2 zguG8?6qkmKVv0r~hA>4v4}<<c)O-fbhPVEl& z_H`)Gwuy0qk$&NdVU#*YSx##P)7J_y%{I6CrSFPBW{iJ|)`!yk(-xH)yi)ig{?P$} zgF{rFz*uBgNGyAds|-XOjDEgQyBm2m+(Y!{^EHZ70zlj6G?tNLk%`MZU~ zEF|#1LDgeCj|3h&vKabCSY$VAkd-(;sm#t*a)tJN&Gon8&?(0{weGR9U z0AVAjWqBaE)Dqv-$R_1aGq%kLfvi&;{}$sOky^Wpdnuxp>}7On9VqT=9n=yatczNs zRtky5oX~hjmVF01iEIw|jpZwWca;KmJ+@mtRuI+nQz~%SM1t0)WjY5tBx6i6@j;tD zPLG zk_7F2g!NgCY5@LjdIRfZIfl@89Zb9|3nS617b)3?Wh~6i4MANEIzFxGw7pueBtz6Z z2u-0gw64S4Is(06?HM`0TqqT`;|avj+E#cEp#lyjuyRROF7h`BpBDx76%sAfX6Fed zwxzwQ>6jsVJ!)cEq8E119NPxgKrq_tgmXR^VWF}SU6rvy&FbM-X%Kuu`jj@&Q>x{`X69$c8awiA!kao%&pmhg)Ty(l&Q;Ez zI``32=gu!WUh7JL1UOpPcCNT_;8wAKlc5xwAFDdAU9!k=&!FmxB6sIQXCd*=#wN=5 z6;bZW9i!DYl^kEf9tVNmxCsIcW&<`w>XBOqHi>XTHGrEkiEztOa1BvSB!YIA=#gzM zb8qDpf?7EU`Kb=vidP%AzuV$ib?Q?t%0#6mm02D8P$?)C!V8Rvn}akY9sUzQ$^K=0qcj z=BTF79I7d$T_}m8by(*=r7}a@YJ}tsTI=)TWDe<{V{kaZM)@nkSIJ4&4ENuWW(td) zM=%uc&eSfHVXi}{KdwVA-8$-6Jb!b;n_vI%y3R(j#v3nvZ6xLxZR8uEr#`fP%-ol& zrwpeWmmo{L!Ky@h!902838f>zW(Aow&Z%oI2`epY?K1J1ewGF@|FRQYHIl#4D z&i5$3lFNfcssjFc)Z(wPbhdOWjI7fd+_s%)`qnLtz0e-Dg z`7$h!o|gX1iE0uxus@5sN8-?;*7)|GpOMYMg4d~0yb!b8WPy^{A6le@DDs@iXTcW= zo*=6e9)1f}cZ6C*9T1Z_yV3k&NxG?x31u2T~x14gt zU%*VAhcHltQW9kjZ6Vb^8d5|f-|AgjCWpu9RclI&9uVyi)Jl_*ZS)tfv2nAUe z1ETr-qO^n*`aw9E3?03;JnD?wFShfDa9^HcdvG-TDMlN$xM8h_*Tq_k;FB_H!jSwG zct9DFi(5c(gYAKYR2xjjqoZjU43a~ZTr$2TsCdYLJ^&|KMfwzxMJUpPnql+nT6*#6 zv4}}}@kvg^(ez>!<^LfsZ!Lrbw~dw@MHEf?!1}th@bp3kPgeZt5ksnxxlBplLz+^f zR<&TNWne0%3DJ&5VSDJx&$hi~Wee(gw2N=QaA+bSvir#9!0PbmR4-~987=TZetolE>e)!(ME;D2GorS&7>g(-{ z%bJ-A%iE3x=?-BqimQy~SiD~3SZJT1&#^dG&NUG!w*q^4VX$=@WPXSE71%^JK-?|9 zBv=al46CeUk?RAQPjl6J$WMDiXB?|L4%)!JX6f_ndOCtT(?3xg?4W3rQ-?}iMlEjq znQxCJO-en6V9#ITQlIu`DEHDb2>JYDo1-z zGa3CoVg=zt9Wa(ThlZ9y{Qa@mhph1LaJDHnDvHe-DF0i$yyZcyy?Ok@F-9)cKUgOW z7Utf_V9qk%CpUoAl}0$hDS0zeW5N7q8JLTyNYtiLj_Px@@~HiXe_th5^U}lPkI*8? z|H+WVVxy6~smTcyk{BhpM!Mk_$;k6VVwBE5pL&jT@JKVw#+qLM(2(jB-V^pWH=6*BY+*5_p zTnf*lpYQ_yq|!spN-pt{+!yu3x~aDq=4pRc_;DLyJJLKPT$uDrgQDm4xbhTUDf9?M zOT{RXo39Lt!VAs#)XXZH z4WFl{Pva@KAWL(>XM5qtsLc`Nl13(T*%fV}*gr&M=DF-+6vDl zqv63W65nkti{}KHqteb3dq5Wqi_*gD6JjL#l zySKdhJYT1#T#~hUau(*Xwvkw?=%%Du(H3djvb+QKW4q& zd{*nTNaX2j-acKD&hRN%jDN>D9JN6yiMyJ41ZOL~vSER@diFLe#R z_`P=X4g?*8qE15Hcn896z2AW_qY-K;9BQ;nIV#ZZqeM)0{P1CAyC1Oiy|o#gA6zol zW^`V|@>&0*ri6rj!R~6n=JP+!R7#6^_(3$$w~J5iKBxX{e$NKT)3!?PKL11A-<$0x z*hIp?2Ha2BD97rr^(gbbhA|u~gRt4HVZHXUd1P2O7P`JJIou~>0HOltZ_Z9b2v|&>AlG-r2 z$J58t0LL>0e39d67sPDAay*rKfKmPfsefqd14k+2c&cN7vy4G) z$qj_60XTB1*{rG`?#Qjtz_}y$33}p=9Df?-$Z;zy&)>euaK!rwUv%{An4ZLYhle6m z%NyZEJTkzG;E^g>bcl>a-vo!zcZEz@hpqjn8C>+J1_%0_s4$X%?!orQ)U>#kuWce(fZC1kj99L zE__L6dswn?R?2Bv?TaZPVaYom-}S%;$} z02$L!62u#|l5~{vnf!J*O7AW(EZCWexF4M)k&Vt7c>A2B&x7!{z)3m^>Ix_6Q9R{4 zNk$VX2kAh;=+e%SQg?8UUXiT3Zs$lf0Ov?Gn>Aa*oueP20dwc*G(B61Y{>}eVnBZdX4QCH8Pbl+N&teLj7g=Yp7easQY^> z#90)DHagDoX+6rDc8v_e!k4Jk9M@<^nxU;YiyogbS6>_g+88cUK4>Wy$?|(%w4;93 z`;;eP-XlFl{4k)uUI==jKlB=^j_nVt%E_c+qQw*n?^S=2bPDRe!_H>z~lT zxq1CQJ#q8OpT;q-#>->xpkvH2`<|z@6}dN)udSH%992XtzpU}KA6X=`WMr@DV8Ntl zP3PVdb(|5=2@-ye1@`XQr>rY)xww!K?7x(x$&dZoHU*&|y4x)L3tfY+?);ORUfubC ztHv{CK<0hJ12VelerLmsLrC8G)^&6TC5p?;;V=;6Z*0`k!97!H?;`CejFppdr*4XU z_RS5AXv8T8AhmumZG9F-)p}#N_plyLzOf&}q8iME4^peb*rzP&j3Kd{il+@LedZrB zfd>7a3@iU(MsU1v1ciq6F;pGfu)d#HN(UN@<<9_4%&Zhj)+2a+{eb`I`T;lUHyf!= zhgGCUkWbXx;St=MGchqdJ_rzhu98Du+3TcTZB4c$3|+xkm=uQq~ElK`wiU`rym3TY!4+T zuXilhqQ7|~BBk(G(Rr3;n)h`o)I6s%rAEmFH;>f(prk)Gg|jQ@@L0NhgX7rcn(PSA z(eo$GLZ}!p6wr4i4%Qv$Qw_-N`#_=@C5IIU=yq^B@}%I+ykxfj2^fU>`Ad4@>W4oK zQ$L(vZ+Z>%UlS!B8Bg$@eeV2)Lp}Ds5oL~wZ-ltz85yAo1VAKGrBo(wxMNyN+OXP2 z$aYbsfydvEl>jrNo8mn8g$)+6{^kw)mBI;ho+Z*iA!|gq(Vk?!VDo=H1P^d4r?tR{@Kos*oB?|FykW^w_zXH9*`y_1 z95qe{rHm$Wgxx}s`w~R%v>g4qMNTy!MGojQ;~P=rJ_#6v$X%x=E^_>79Fa47GcW!s zLe<#LM)&Q)*OEE!(jTCEq>=u<6vPP*Yvnf`){!BPD{uJ?y_6?Uc0t^5i^Eu#aBmIT zN!RvZK&m*4+s7#~sEXS)TM2GyjBpYb;%L-{_83(|&)`O^)@r()q>GcyU_@~cPMZ#a z#hI^Yt>t-j-j3{(nxw0smzHq%F^(j*hD0}e0zA6Xnva2>L~Ed-np%432hN*yR->-7 z(xQt$=@xBi!T|=q*2<}MW9kHl(&FaDxZ4s}uv(+%UAQ=+mI{#iC#ciA3-}G&KxYdb zMy+K4NT=JXQ+06qR@`mQVY7Zh7r3^TF^9qU44m9JtF1`{wL}s_rNotZvxZx&Avv|E+rWW>T3QLGT-YTG zCz$z?exM_uaV8ZmUx#XdTpD4{6a& zhO*yjHtz4jvOy_hCQs`jytbIinZq9M%I(m~dVV!CK>w1;QDx_D5nQ16t!Ua1?e)x< z(vf>xWOzid8wb7co2Wx;EguKz2q#&iY}cZ4O3=QRBDFE(YvaMgqk=_T%+Q}@|VHIZ;Xr!wbJxmU4wgfucp+;ao!u5e$o=jDz4kX!T(V= zanABPJ`qx?#x72Tqw_4Y_mnFW#cr|{GrI3-So7jEgJ|{*&`gaoHM-w^1}YC1ro&Lv z!R~M&aI8I3Z2Oh&2wwGTs;YJ4T1xgVG#~U zHngT+l}~b2yI7t%Z(&nx%HyZFiq@qd@VskYjUUO^Gj}izKlj9alj8fjCFmKH|1CLal}i zz8^ORCdhx{dUf}zi%HM$4l{%!&e^@q$d6m3>!6D!qgH!MA6qHx}HQN1X8Y!{qH8mga`3HF1 zkmM)zp6%3S=8;B>P)8=qL<>q`VdnX)qShWg@()1YDwp6OC;u6>Ez3@EA%Z`M- zBexW8zPk=MP{4*VE7iDMChF3C;r{)k%{Q}Ma*|w;@6WIu>J7g{^bDIyybeumlOEd( z&$o*?LQ+PC58XFMas7|F4NU#b5!6S{u<2#5Mc04fx^^O z8Tk{t#_?+>U5ZzAYb*2>-A!PggA38vzNIMY;GSyF`gnRX+eud&;3l2QHTVF{9^UMt z8@t;$TBS+rjtQE4w|L`;D{hhsodaCq*YW{m^e8Jd+ywI_yx0+Y`~uU4cg1V;PH$l| zzKhFF<*R4mDYfWOQJ&=_s@hWyr&LxmCKE>lKy1P;jaGgNIqf>csJUl9HQv%`N z&vsxim>T1@c1)=8ZKo_&p`(*&sg2!DPv`_k-%%M*m|ClYf5bbb24zbC~UFdu=23oD=B{=9ONBgoE9qW_);^;C_0X2GlA?@$y2C-9;ri04Q0( zeR?2I2jrN-`}qfs{t)oFD_*K)nx{9W`3F_=WcG+3!c%3EQ2gH7XrnTs78o@$H z5vIYt(^KpKc(Pg1;;HqPyx08(+k<&X$GukZgJr*g|G~doDUQ}-JNO;J;{5sqh}v)6 z8C+>ZHCLkcK+VS;Sv3$|$Q!WCQHUFcSGsLnptuXr;S_A(U+94w;GU>Pvv{Kz_K~W9 zV$75anwYSoGoH0bkdamb&oryhyh&#jAo!lwK__?BP->;(;mXHG#jV#7@FRusGTSTf zR{^s&mV{cn!S28<6g?cS!KQ>df&79MaRVfuv{b~Urkrv1>Z4tWZE&}80xiz=rQV7K zUA#tXOZo?GO9|>!+&=)%ZHJq%ZS+yR!$LJ#iv!^~{1ZM$&sY4!|C;~R@LyoxYxpht z^Qk-V=acm3m+8;9>CZo>5C4q*{8!2e{d4;B4O*4`I{o<$T3)EPe~1R#j+ zUgo{s@UOh=f9+-7&kf$k4c`6@-u4aN?hW4N4c;D3DA|V=V7eX@fIbL7oBmh*FL5aS zU*ngt@=Iq0uyl2h0G6&v5x~+BUHnj-kPgieVABrSkoGHww4XVoO*tWL+6gI-IHWvd zF(^u62`QNASNQi0jr!CdC_4gQ}e14Ev2J2So#UYF49$7CBz@&df_)dOFqOwCa^t+Lvk{ z7A@|O3B4=Zmi)4b%|J;b=twHK$8i64qXC%$*TPV5J1O6P8N3jF9z#F9Ir&WQ925_t zH-V_Q~MZ6)(-LCF=v+hZL>Ol zF*mFN&cEYTZ~&e?G5TW?k%24T{Szb1f>EO|+mKkmWfRhO*vz(yEC04WbLOe%$et@l zjO!h*cluR$WZ{1zI7|#gE<_>Hbti1SN2Ay1ZCid^%MXoY^^9dK*ACT2@v=ZmL=KUk0dMs5;pn% z=Tz0bx9UE+Z$CyPiywDx-&?op)Twh$opb8csb^QbVaa7nE~9_kO^sTyR5?FkSI(8{ z)ykY*X|~<5`&y-P;b`E|>)X43vi(eZ++CKd)!HZB(Ly!ftlM^>RByX?PZq0l_T*ft zKKV$!>e%^aWAc%OX0ckCJYzS`=1%0M8~&g%Izjv zU5$G{GYbk6pD(8-+r|5yM9JLoB~)f3Dl1iHs)V{=Q^l)__Z6+;RjzfaVq4`BE}+zW zy;P%?tm=#<2?lhq?%`4+ZurZ*8)W=j<@0Q95LzTmF6Ypv;QzR}3elt3{= z0qYra+M{*+$O#l$S82_Gsj@TG`dqHbEWfHD2m>^9THIMT65FC!3!~_+y1z6#!H-rn zbJH}6BWLI@KN=!`LmN`s5DefxXEM9Gp zjB8hbSfCQj(Q3|Q?#MJC3AspdvUrOqJEn*tz?JUOJ$qEo))wrUT&vv7)~gsbffx7k zT%iD1D=Z5@(si(B(QaUzF34J`z+AP^0?r5x-U|?7K3kn8`Jcr{^^*VU+VHDvqX?vk z`iYtf)wx^=e8mHQHNKt$4OW|#YSYfv?HP!p3dyTlE^oIlic)L23LzOA@?r5g#oL%B z+)YJD)G|p`Z|Fd)vdglajeeOba~n}3S6;lKc%!IigOZ!sX-pxI;wQ!Pb!Tn6mYvVl zD;NgVyt}c{s@3W?_|AI+5x||=2BfjP1Ub*mRUt3XF9=_}Cn9!7Az`z2tyHegs=?q# zV1mG-O^h0d5D52XcBY&|+j3;q*MPNLeF2oixOA7+zyaL$+6v}sNLilj+b2&_dt>5R zU=n-=Z}4I*gc-}SY^x4N6E%!fO3hj+e|DjLkqfPtzq6&;3JLQk#kX7Z#~8Xs3{S?c64F^sTAgsB{Of`$d`W4t@^JEFr7Apd?+9ytm$}R7ISC$jluL-o zw)pkp*Xh|N|5-M`8~jd|FEt@H& z@OePkUn8Dx;JTr|Rhp%l5rc&dZ0zM~kQVZShR;F>!N8@lH{G1D6LE*K>OR zwu-8u&t_Y-0`yVLx2%_NGeRY6fF7rFU~NoC{8)U1sTbI-R&r%jNhF|NZ{|9M+^3N& zv0rH}$O?G64`Z zX1oy9F+jewk!ZPGz(d-JXb0cU(X^@n_Gk+Q#C$5h6cj?NL9$y7jX-m?)vUEhFH&mT z3Rc@>_XNp9Er5Chbp=|oH%emQ#S}?1pt9JOPFV6|(SU^2leH2BvZsu&pd4q!iDp$V z^O(lL%{zH|m!m?OaY4u%faMRG=qgP$q#~$+xQbCn8b2%i^o3oiD&x-C3ZH`*G0`wj z)6nb4)~u`PmTP`amc$4iO3H#p(kwcVaBR)GcNLq>TI0avWWG?Da2f@>Tsl{usMyWP zN^NdZmc4iXq}{k}5@V5>n=5DX1RDxVq_I{(HJTD;y=qE|Nt%+EzIYtA`-^wCZ2`Xb zaiP?}M7+TB_R<$WL4}@Fg}jPD5TuC60a4%H3N0||`F``cvLYmPfC|sk{5+m|gQMfbp_30hcIW|ocjCmo z<> zc8E75L&V)2Odp86a%-*vG;tZ}3!pME)eF#d#q%q~7tLy|Y@f5s5DcvIk^Oa2l-MFl zgd}jV+Q1~dv{IE|Z5AK$JCf;8XK7}q?}`VD_lVlJi9!MK?eKSEcw1cFHc%$?sHIFmd@#ld;Y(qm7!7Ej&1N(j(>;0NY`y`s>kFW5b z*X^g^XlQ1Oc8>LBh-NObF<3+xtS~>!SIyEKoGoMzm~ZB*^|PdZA72rAm8;~Te2^69 zk1qFHl5c#3xJzGh9ZYgAca>kR4vL2aox?1vAb8;3`bSxL=fcIK#rwrq>&W}$Q$Heav8mrs{vb zNE(&9YR|#UkMF#BO3Jo%T%=;p1NBgv+~utbjB+9OHuF1jcz6>qRXt4tm>}b-rD>{7 z%v@shJY1MC@|#W1=G>6amI_%oNm+SDb4tQ)B4;M%!l-v+`K(YQ&)N$hxq`40S3#Sb zt>mafd{>|ppZ9?)D-CfDU^G8IY{(q7yVveTQbI;_ie(tiqGh4l-Izget7l`c67J8M?A-si>(3(Yy)w8gC6g|>s;sw(Ltq`bpS2TdM zS{8n;N)ElS;or@lg)6O5LTOV(l`+gzwASCuTe6=V#uXD@N9 zQjnf3*s^dnt2b;JZ}xs-(&U1eQ%^d#EWPY9qJb^`>wF>Au z-wG#{l3*9TDz5O0%#|vb$Ln+1vR#>l(DhLgz*qzGrJ&d1m0l$Q7=@!1UIFjr2EPSq zwXJ3w??H@|-_0FM7i;AURscYK z6&RxDlo1kq7gDM>lG@3t0cp2bbR*&ws)AtMEmQysKz7b%KOdwVw10PPt_+9Qv<*Ft z90)=zsiLAjPadGgxzc$X-X6V}a&iZ>87{Cx)q`e9w7_TK*Cl1V4;I!hUUF6C4;*w14-4J|cZDiK{%pH`4of6ry+C=Mil?OE zyPn35?Za%fQYP&}n3w$6CJn}OhRatQ)WWGms#31Dc+atPN6IYul++Ahc`s+MS_%7H z3= zxT_k?!T}&tF0!;*)9yN9>G2vRriJ56+|Ak(F}p+IaaY2+ATl}`SR`IAoD36kEetI@ zBG-?-^=-9+UR+HJMeYci7b`Qbg%PlhSKjCC=}8#)pwPAa8?w0$YeW4!m#dd(K~cTM zaKm_lm6k1usEHy;)eHvrCS62)vcUzTXW8_EXW zskjBNHiT##A91%Bp9n;u{1wIvCwDFMvFHO6 zEHDNh7q{X6?J%=0$N#q-zq93Tk;)KBV2q6LaJDbHo3!U}jbW7uE2a`I@UuGtJPgQ*lHHu)3cwhXWQwjNkOf4Wgw zfDOAmBOG}b;hWE4?Ux-IkbUkpRv^H%U^fsJT$Ln%3+Vpl;A)mo+E~=_f_-tB+iA7d zU8lT~7+xW}_3eN2;RvB5-hHR`@01Kt zvPZo5`~ULO>V*<6;>GtK{h%gg#MAHp%4Z_P4ZnM2=PLPR`X|MqJ&aU`B@{NFzn z5SQZFeS034LRQHT@%)A799glHG~)4(-MK+NmZD8O&O0|5qFOw+k9c>j*ieq4U(OGWYK*IrT9MXPxH?q7XR zw7lNe76snFaxA*Qt+K!e>J!dy!z82PzyII&eR0zHE$`R<|FOO0BGQ5Uf$+XlP(pFs zT_aT)xCkl2Ni4xalwev~MiTe+?N_uPZI3(ugnDQa9h;aC5o}}%5YK}_)gw%W{J<+i zIzycvz0Ub(`TdouupIPBQm8P)@`s_9vXH1^$ua@LMpcC%1o3j2eCbso=XI_A9qLQ< zvQ;A{uQH5o=xqs6fOBvX>9DD95x6j0Ell%E%dFUjISyT2tSATwmz&@>pi0|K{{C|H zeQr8GDO^#_YK32I4Zac_!Oyn`pJ(BofO47THy-+HG^qS&Td;5t<6haoP>o1HuTdX) zg=o>MDVu)S`8H^P$a=_)v^SOma8zs2p>)dTw z3c8_1IGXC=4x@;bqD|V*(RGZpfbK+vHy2Om;grwHj?UC+%o zI2@Erkdb^5;kocck}*U2g^+mS^Wx*`E5}BUiaVVd{J~O#Q^a2c-SJYpR>s}I9-PAn zc~bhY#YWT&MRLjS#plbN>3`130M z({e82uNxQz9%|=j@KlV{@+f-1=uM$SaYADdkBL$M;I4w3fCDVSd*kl%T8`rIx63gR zF~q{(b(fVXLIUUK3gS0@!Ex9`H-C+~up|1DOpzU~?PJG$N^nbXZ`D zBss|)t!op3%yV0{`F3Af&Ux1fIp6^MC82&kodEn{@> zKpUOE2&2Ozs~9F7cfLR${TVLNBVu;O`7)Jfk=+^lzk{;DF09n)(P1J}54EoRPiiHd zycu^sK_C4AE?suzkEnc?T`@+Z6Wt6Gt+qj{;|@t1cYQ!okqok>9L8J?8iwXelq`bG z@h+14$dy2ZO*8el^ASSN|3~PgEih1(Fm=Mix*Hk;{bCL%?vylcN+VOOj|fD+pX&6+ zRcBCgmD2h~8U~H*hsJiQ)~NPFK(?k$RI&JuwHza|3fLy^cH6m* zezNcj{9aY53N7}cyH?)P+=N8{cSEHr;l@TBekA)O<^>;vqF1auk;>$;yYsX76=c1& zrxBKC3{^varLo~&z#V8zYa&LXB#emjW*U8}Bp{_n16>FbMoI60$8h6LMStV2 zJIvu=ErflLTUVRGjCWe+4i2_+ucm&nG&vBiIMCtsp!&DyUGO?*aCVX=r71E(C5h2u zuoW+$#pHz+lM@8xyeA22pPb$o1Ms->0sW18btZ4!efZSL`;R?v&)!T1WQ-6#?}-|n zamSn+mS*zmrI;7!fi_-KVYGSx#t>sabHa_nr45Mhw3GNQBoADhNeM>BbIwT)o2mo_RN;<0u+!0)&XBcNKUco|`=8x9ny4%@+tC~ifG5jzk#F*f! z7tyPrgxEx%vqh_$)G3%qGQm|;HM6eXNC=WX=LhFTYUs6exrr{XqsuPuZX9eV?bC+-EO8Z$zwFEw&)>!4}? z#_(v`31d?L0UlDq1EbcC)wG~!R5llW9c8C_8#qOq5l)JLNFc%9{j9a>M0FPNWwW}_ z^PXy0{f)t5)t{-}9j-Xgp>0E$sigHBGgY0_rYc0p1PtzLVhnCLS*EKEC|RFCXM#3& zU~Y@(rzb_7?&r4knR9GZdrd04Iy{-3)5mpb=A1s6eKw4F526@G>1Q(gqi}P9fxbLE znRQS}`mq~R!{U6EloWw$sT-K4?_Y=e*BPC?Pm`UyU{b{DOva!Z(UZV)jpe`FONV+l zfID}{PscP*z6m} zQZUVi76(;W&8l_e=zWhpVCBx{tZCcAqN;7lLA7$z)mGD*FXo!$XGee%7O3&5p~DQm zdW}DK5pF#7gGZv1z)7p2to@OkF;S8PVKPqr~|2^BgF)JeWr{} zO{X5n-hb@GQ8FJv78%xA{ikYTjWQt-YphKZnX*3XK9qjc`k8g_4>uQ>b*~Q3y6$yd zcVA2&U6j|z_VF-8oyfMIslFouLh|Ym092~_c$ZS!Il&)wDX*^(rti?uWI*>)?h7pNmFub-wnme+hYV0pbA1`7#hX*en_HNKKCtfp!pkZRh8Kq~Y2#>oN_tXH<*v<_xyv=z_JO z3)Xj}AJBdT>s!Ok1qAEPuwWgcx|$l6F3gz^hWj^6G2OWfra3c`$>>BQrX&Bc#_k{Q zr8~VFGo8D$c*aaeSj-tzPvpeOrC$)(u6k96gc9O7v!`rM-)YA76AiS`F)j`<$ab>WHw zGtD@g2RWfd6#69B9N{AVw?R)fs zvY}y5nkC9t8@#w_sq}IUkHW@<^$jGooa)lfic+&eZ)-hxkvPk1|B5JaW;qgCpnGfl8DNb zD@hC4a*^xJEQ%nvbjs7HvWxPf z^8&9g23{Mf0w4W2Dt84o98oI9V0zo-2s}l!;d(!-A_7BcbCw)!qq8QW_6o25n(CCVd-hC-@FV+jj?z1j_EUG3ir}jroi@&kg42gyvc(A z^q|~YnkneQ>Qw+Y<&@Kp$@B7XbAgFyAGl)il-ks=bYb%RQn-KK92F<~`-rmZ+y&F* zS(6D8YmhXwH=2xmcQ2jl-SFw$sUIR5G3SVJ7691b?FC%>Y?|Koxk#A*bzHi(ef9|% z`m8o&V5?!QyEL{B3*O{)oI6hBkn_06t2mUY zLv5UZGE18tX!FNxy^0htyqM#SDRQ%G^0oJBG>-eCHhlU_5hF&@dKUM`Otz*WFmZ%c z{S30pQ>sc!?j)w&AO~`lg#%L}ZgGkOaSj|%=#UEimGNKe^Uz-<^w`;jmw^~5cb(R< zYSPK*#hhE;)lhv~KIw^UM35mbhfdYb@~hC!*?E5(p@KTa|1o|ZBtD9p5;F$|!d0Bk`j zc<2eihEI+nqXaFl9h}7G=E-`iGC8-v8!=0TQRF~8SgB4|3k##O{w*bLBRdfZ(GE^F z=a5?{NG5}WV8#Yh*LXFK6cjxK-5QSl>}X{d@`Z(7>-V& zQJ;wkYQ-J2kwudusk*dEB3kdxGRoMgReESKy0Q$ztv8#tFH9;%U+_$?^z>r%Wd#$g z-f*hkY%qvj@70xJGvSx8jbmVUdnCNFU6FqK6W=# z80PN|_ivbndFL*ehB-D621!PEJJmyt&3~(xuJmq>ckap$5oMTSZk#zjxT}znoZb?D zBO(2RxO8oa-z!Ar&uXIuJ{pE4t~X-p_TXLQzA46-p@ zfPYgPc-@8%skkczpyr%lXi$HXP-S0=Ey1c3+cnTJL^cOtOA|avJ&GZ)B)vLnt>nIF z{lcsr$3=-XRda#Yf8NjfE*3;XE$*Pj7iB56I@NFoPb4PXrDwb0&(;p=i$RilJX~K zBX-x(o@{cq(OZO_A(Jv~9CkOUwBUi4$Yi*Vyis&^lt_PvC+kI)Xc{McN|`iwh$kvJ zIgZD{aZ)PZ%SlRwO=+e52W#s#Em^C?cuUPZc^i=l9q2;#zE(pOTH&tXtkr04y-anA z5{L_*qux`RKb+=*6Yws$W)i>P@onx^dWOF&XKc+P4J0yDBfrN=0u}kn+zkjF*HQtx zE5vCc?$yQ{qYCG49R7r}0Vxw~_$(6lD*c7=u{%b6;EdZq5uHDUWKVi#KXJh2W@MR1 z1OU>-29mCw^v>%9M*Jj=@MW2K8=Wsx>Y{ap)*P~Z+cLo;5X%pkjgT{$Ms@=~;nOH6 z`=S2`>CIY5NQ*2SD21~rab^>pZzQrUQ!%CzoV0ST)F=rO-2h(@7#taA#a2TU!l9Ca zCzy5IwUoCPDdNQbY!Hqt=^X}@kU?<`QY?816+xwR@Bq@za_(%Aqb+ zp3i#gx5y}8M!q*>Ak*_TMyG^yzD2cOO=a#zz=BEv8xD5CE!@;4W`{6#K%u_e-3Q33YP3KyRmvV;JAl&mT`++&jbRS>#{EFy?!(l^ z;I|b?o*@XsIVi%fHQn%+i3V6{c{ANIP8PtD7sd)dYUSzz=@g{NRcS-I%!mz7IMxjj2Y2G}!;>c-KZ4*lIxCp+ z`i>rJT1ZBNLw7hxu7$*UmOX*Pa_35PV2Q}*NIBWC3CzpThQpK2_}U`XhPH47nQcA% zd`l4$HjdFA_-UK$Apsjl-to=`4>pE8XEksJjLO~yF4Xl(?w)l;zC@VCIgbcE8qiJ3 z#FARaKQ`Eo`wab&aK(;~jMeBk2gYr{F+WJ7OKZ;1kdRT_Gcar*%@=T7cr}&CB6M?3 zFXrCz2&Q#fu2RhD;RQ?jlq3FP#;Yu?pxFbXioOH@v3FUGcC%q#|meeXb z6Ap%vJjQ;>gbFnbk&l2XnfTU#_{>%28*Z@5=kr!sgolWeR}bJ=5|GT~{)v6Ja8RZ` z*xh|1Mp%IL10bu{NKD6ps&&yhi!085q5w>14)-eP((#v!eJ)!Ug$;E6Gk_yfjrhF& z!rgv)zJytir^1{+8OF2Ew&)LZ#KjfTm|^qkfodAQ7s^MEOwO_aEu|w=sl9xQXrIGA z)`o%YnG2l1r)s}Tm+#>M5%_(&{|8)f^b4I4&J_w0vD;Ow|STac86F|da()X6AzNew@tCX}C8xrRwXd1^<$Jhk=+ z+fWwSSMfZwCQwSpruIhTk#k|P8#Ir|t!H(#)aR5?4Ffwo9$B7}M{bDVk(Ud$5R3pR z*u=q#*2FYfvyh644Kg^M&YI2VtvRf|i65mVaY=9k3$pRwtPa4zeX%t?0Z;wp8M|>d zcLL|s@);YF@o=iM--=ENKNJuJdGU3N%!@bm%Zpnim%(-5or@CBlba(->mw3bLgUe2 z4U_$#c{C%i@{ay_^lf2ahsUEUQu1gff=9117%gFwSaQ)IRsZfHQ}txORDH)|$is9B z6#eL7&hY{NF-|X|vm+4?z#8%-jt!~t3=}*bA)fMY@3BUmJ9@4~v8yz_U9%sbDG z;T_YB8x5wPjUoIQX$5CR0;LOU1&G z)@NxkR;;_#?WbB;>!)C?S_xa+u()rv=qx(xuzY6M_i}Z`+&N@YuB;ncEd1x1~xZm%$Po{x8r$93t!@q#cNmTV4Z4;Yk$sm!(Wa zL89GH_w-g;F45Ia-NYtr2>#%~nCAJ(HF&!%l1dgPeS(-H4A+WO_e(w4vQ{?>5C zfli)|m{31;Or>(75Ezb&3G9vMpcXo{l8p)3Yj1!oQett+r8RGt%M>0{Ma+I3{78{c zVwzQ3$}y*kg9YW-(j<$FQY~7a$ABUNs<9W5FMQ%UZ|@UT4glH;she8y@LFdkP*CJgn1H1PQG^Q?&}n16DO8aNxNH`iF-P`io*f z?|Sk3YBJ22WMTCp&I>sa_%LTSoa22-S0#O>%ZTKn8p1w1e1ttA5cWrCsn4~KPlkc@ zMNrD1kc8!MDc}7?aGgxWmI~htdjfQ8POCSPGYH2CPa+i}!ioy=FZnqrvQLh%i)l(dnUeO$9W(Od`27fuX5yz9c8Wtp90>bXA?j(%)ltL^oTg|57S*H? zPh}oF*v!`sOitc1!T%n(b^q9oIv2KzrUlY<4Jkcrx*Z2@* ziZ_mQQ*DpIh5}T~PFo{Urh~FR0hIJgsJp?0TaXHMIJ_OIM~BC>sPi(eGd+xsA6WB$ zI!KZb-EKI|<~uY6+B%Uyd+W4<`mh-9G(nsh=x_v18T18}Ezr075}@ynN9{5l#6_x> zob|*OJmzvbj-5C@pomEc8PDUl_gJGoB0blljos1Vk6lrW-J#)+ooPoU@oK^(DuQgn z0cFW^>2$=9^`i43;uV5k=i}6C&v8y;PzkbxD%aN4u|@g7a<`!?2k1 zt|LZY$6bWF+&WW)Y6+u%Dnj$|QJ$xTzyw?JCi^+KP7_^uk#V?&Hw%}zTwiBKPPaXwa81O_` zb8tJ%!sg58Xq`YD`{X%2M#WW(d2ttdmtAHoRnTE>)4UKQgQZn{Y+z{D{3Wo z3c}lIKhEepi2`ycX!aRsH23zN3jlRH5aL4XPs(N;K9IxgYU z3&Anwk)hh=7g}eHD3J^WZ~2RLpZ1)wfD~WZ<7>%5YvFRzxsI

RLE1P=Bx*##ExQ_N>rqD{_1*LH3aMtWdkd zx)mI(Z^>P(Em4SHU(bWYW&W=5^R!6ul_6riw-8y2oe92B!5~0;Z)*>De@WA21Zqe+ zG}vDof?X9v)B7nP@d@xSHWfGogcGF#-oFzpZRuwXweEX=4KQPu{nx$!rnv?AL+knP zLoFmDv7R@ij5QXA#aA`Of8vKwo6zMKu7S=`08Y+s^6Eu~JqabDi!qF!G z%RLb?0U>L^j-^DXqof2^+T{PaCrT!Tk~MJkv@8voLqXG=W+WQ0-`*2#OT)%CUUw&p z3fQ;TqQcqw1!@x6ok}9RqY~M1eOx=P?`Ph%3vi4x=dg3F9g)KdSQL(`=_{xx($^hL zF{_00jOlB$oGa4TPux@bS_^D+`g*g(fBN)w1Ui+zqM@pkB0^emsjTkSF_`O;))AP` zp0pkXrW~Lt3`*~{5=_C!}66!nN zm*{X;9!`<3-hP>-i5>3A^iqApdv{Vv4u~g0>_R5Z4aH%|C zn4YRCht}V+TkM%i+*NaULuO)H?}!?CQuX8xH;tf9r~$c3Wfb&PsiyIkY8qEHQ1Mt% zQW)+nxAYcZLN_6!qlj>5w;nINvXPvvA{k>3!1279)30^Ou+ALN&MVVDGA;%GNte1I>|n@^DT&3#mh`WZ$RV{|bOOcE}p z#sGO$jyS#}Moe-HvuKY8#(YBFFTcs>BZtbbrr21|UOdldndO(4ll-Ey??P4yT9M=8 zp-DbzJDqeJ=oYDPNGUhqI#wSeGf9NjU}7qJoiDn-jSAg)d{)69jGQj2*{1DK%^7H@t$dR=x}sr>B;wj8LRHV* zN6Nt$tuzTuHN?*&UE~XP+8>yu;X$xsKsZWZ`2=uDj6k|UOzKxdgV;&!&_r7{o?1p> z7mZ4$K2umpH!*kJ*p()_gjXbZrSE_dYHP#9slp-HDxU{4FqdQuR8C(Xp^Lp_P;Mt26SCw}MmAkW39 z*Bt^+BMSWc3h;1Ni%fRMiPl^v=?NV4eFsbWK9J2MRtH{WCoFq$nyPg3}G3_(38uH~hPQnZzecBRYk;Yb&|5Ypcu zWg$Y$-bn{25z|*Z;?tZw4jjUI!mbK>p@KHQR2h}cE{_VLwFyjpKqd|;QbB#e2Z@UEq+oyL$hcfM0`9X<{gSThvNA|@hrMQ zuYEad3V>*#-oOV9-(ar_sOTwvhy7ZDr5;7mu_Zdhyf^8R`s_qAhez!mV&~PP%~|h@ z^druQ5b=s5DwiHrO1&@8k2s?@4Uck1&n?bUzMvbM;C=zyHo`N>z~uA@;m4FEFxYPg-4h*y@rL@ z2b3Fp(B{p2{0->#tJzENUVJ%#IDk(IV%V!hSO&hz@LV}8Om5B%x_)YtiEq=#V6!&G N<~)p1%8+)}{tvO!c!2-_ literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/admin/containers.doctree b/old_docs/_build/html/.doctrees/admin/containers.doctree new file mode 100644 index 0000000000000000000000000000000000000000..57f0f75956b553f8ea430f03e2a04dcbc887e73b GIT binary patch literal 14810 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/admin/install.doctree b/old_docs/_build/html/.doctrees/admin/install.doctree new file mode 100644 index 0000000000000000000000000000000000000000..658073e0312553b0d9800f4db10ce3bf62c5f3c7 GIT binary patch literal 5195 zcmcIo+io1k5hX<~$>p7tMA(ohjpCbZle>8c;6wC@({p)fqX%}!GHk+`GS0bAAwnBY$?uzP%ATk=OFf>O8E|+) z27bz;{G;5g6T6my>Xq*=D(-0+NA>HXBNoKsNBMoxH61N=z*}2p_1#Em76i<`LwsPH zKjLR}{?zW%ywGPMVK`mqV#{>hT3s<`7D_D-&3qsuo*!ldW|o=OsT^b)){!-H(pRMU zq8BiwK*Vz=Vqx*Lq&KX!Y0;rt!*!t+Gs zrDI`Lzp(01+=1^%DOk_pY=pjogXoz1S3TUGEq2U2sn=zD3hf!H+L?#I?u$L;w`eq+OVKmI^qqUVZgobbX=i%rC6x}s}!u) zm7{tO#bO zOe)7lJX10nIf+cFXgqJbfq}SMd`LCQ1zxaQ6_=n|uhwMmNC3O|uLXBf?!_TWi_d+h zOaYtrPRNljet}e=<@>$VXnlHhtt*EvSK3>otOZi@lm+e}h`p0G;XBWN_ea`)--rBJEgDpN$Y)!hJ8XqgXW6E+T}EOVO1j1A>^vE=+%L~1cP@k zz#wPp+%2`K-1nV)O?>}x_4pDhzi6Ry8}WTwqw@O8PFt0Ua9+4q$Mc_;#Z%y>P9@^6K&bvn_ zFG;MVj??o!V3<3@I0)h=RQssxu&608{}0iP2mXC^4^(An7s#-lnDoFKhq2~wJfJW* zf}x1U&VW}=u|?F0Qycl5bFw!HxaQV1C5&vPt(t+ZS>j;=ky5p*+(L0+ zm74Q(eCvbt->Vz;9~krvjM*`depK}vFMrckrb(yj3*AnH%FB0KUT%uPTa%@IB=wtB zdx2+>4SI0rR4>=VPUWTl`TeS>9Cv4DW`0Or`AK6};|TNOL|s8X@3Z~FpjPFtn2L&0 zBz?_vNi9LDwvJkDW2_~8nm#3Pu9f@ffiL+`R*k*bqrx_8*1asH5x}h*{?&?7H2!8u zajlX2m}s`@5d{?_(&#^Ov+$S&89M&Dsogj<-4T!Q^+y58vG5rN2F=0*ixEglpN-Ts*-}N zdWjv2?Ub6Eo5X1q0H>?*Il>))?Spx;|H@B)27j)nLvKnvQ5x~DR^pMYj39f$)1Ksd zXwRT|Tj((81F@P7kVU>0`N5Le1tvqcPS4r^w`j%3W>cLtg9*XkevlcRhh=-b46`e1n&*3-R_zmY}t#dlP#ZQr3Yn&=Y$y8Uh1V zVc4cpp|ZggpA0b(;4oHXBVBczeO zGh5{)4Zs=B002MOwsnbWD80GS{fHWfQ?TVB%h$* zO;C$V6p$fpSTAT!ru!Gr7l~Lr-#>m8Nq+ni{)oroL-D!zyZB0cd3=Ycx9}%3UEh1d|^e1uQRjOj=5E0&67Y5Spmfg z3Z-_%S6JJo6nwav07k+=9MmwftT(2JHFtMHVz)ZgzO+3dA5}Wl^jWw$Evwv_G0P}C zUYt>J$jyp}HW%@M4fyyh{-&gV3O7B?KR^=US_$ch>n#P?6bIJzXM(&^lWpWzWaI^z VPe>cl9oe!^C947Rs>Xez zyV`3bMOq#rtwo8KG|CISBJsfQfS6IiBGT7@e*9}6KCz+miLnrllpt29M8^6ik&o*^CW{;CFjUArp3z*>u z>A5ivvUfAxq3KF`Nv~KxmvBePFsPP`mY5ZD?`E5#ty@Yek2i+&T(X}i?z9$=RQcUaF;%wV`#*+chw$lOA3rwk44pN0X(H*9xo6vdZ z9FHXlI`Q2Kn4f>myJ=K62F%%s`H<$MdQPzs4P|0QyeO8$hL{%D^xeJ)ectzF+zBr5>2sRKd0DS>bgGn`a;hDc`FBbTf9W76rYFw#LHmE7x426eqP1T4d_OES=|Mx_@bIH-7LUlbNDV(P)G%A3 zfZM;3dk@jl-aU7mCdyKRTYQiC5!e|Ht@m=yez(EdZwjTNWUJpFNhQ)j&k6m*_5>sc zeV@T;#JO!Xkh=Sx-7{!yigmqy^sZUWv#7~4vNLFx!^hz2wH4~O|1ak(mAdvR5E=*k zb@PD78-kuO4oV*(OV8p?X)H5+_t~H|YTko-BSY+21?}^ux6=2lXVqSgNonqSt#FuK z@@ZZ2X&EbhKs8vC2ZM!Us4gvjOXSpgp;D}yJ(wyku}-FY3>o;ToX%o{?Y)xi`C}(; zmu=m9lPjyZinSAjk6{PQ7()yvofQ7Nu=UbA*T&O5)AEv5XIxdo@R!q3uIYO_fZ@-l z@x6aKrSBDw#M|N>0Qpn#Gu=u+HI?DHgenhv*$&9~iwfzD!l&k7JIb?ozy@$OQU`{aoXS z$6Mhy?mfKs9qV2cdD3ANpIQ&;t&6R~@GLxem6gIO$xabpx%<6^B4DZ&`Np|rmB>7U zgj${dJ-a$LfYrZGW2&E=!&JpzA50%*q#H2O#nMR2Twt~A&{rOkfm1+WV9nK10(JCY zg~9lRsS6iQ4+A3j@pIJ*6Q@}d9^`W+vGd5wI1Vd!Kt&LC!isi|prmm_Z8P2om={WGDIzwy{|U;u{7{9_F}gW&tX9qa z3h2`W@}!z?S1XKaHYZf`{L!ijqmnAePpB00<7ZUNYmGxrDCTkkn2y(r89tL*aQBAZ zt0cLOe;Qqfv^!m!F6EdfgpFn5EN+t7PU()5#*|{)RYJW~_T-7Ro=>=MD9(+1Bk54=BG4;|vWK87oNaM`$eO+aT=?cFhTS{eMB;m6a?s{+9L6?c z1J{E=Bl*PL9F^&nFjbRMT1HByuN@jWBx0Pw6m%z-Tc4p^y)ij(Xt7?UJ0t)~03y$1 zkIQAI2*h2aix*KI(wAfIgt2S8JOV$kjRZNi^{f*HLtGPxNY}1&>JCd)XxCl(q6Ddy z-PDilig*ClbVzV64wy#*S4<*86lB=QFgX&pA`5rcF zD>i@?xk_XY=Jhpj(zh$~tS(^Z^@Rhyn(POP?b%fY0YwEbBm1P4mTaEV++k`4~d zlRnBE*o@`YNTtM`44m-?sLUm5A4d=z8SjC<>R{H6&3z_48--JpO{k#w6gep*lgbnB z4Rg14pr?7TOC?D?pSu&-FQ_O3SHd`yo#)YpIBPf*sHIR&g$$Ppknh9cP4wnPN_0co zuxe0}PxVdo&rxUoy*UnGN4qF+P$<=|JU+cclbT&7HFRvd_ro|?%A zX5v9AUPc8jm$M`?@w;3I1yV+cdAC!&+*G|e%d#UuAi50Bm-mo`m-F&VH+%AVsLX;Y z{vh-!Hkqkc4s}+u+Y=Jo<*sJYr3v|YC}~q7vRHjct9eD*swk<;{alYnR?p zqZ&(+&zPckDvVE*2ho&I3cEv*!}~Jo<5kqgJ9@i z#G#Wyj8^e@PU)GvmOAr;?eG7HUaRHRLAI${P&vi}2o|F($$ literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/asab/alert.doctree b/old_docs/_build/html/.doctrees/asab/alert.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4b1c43bfa24a375ec6523855331bc97b5b0b1c02 GIT binary patch literal 12257 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 HT(ABIzeV;m literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/asab/application.doctree b/old_docs/_build/html/.doctrees/asab/application.doctree new file mode 100644 index 0000000000000000000000000000000000000000..90779e3a76b364d961899723b26b1614ef34933b GIT binary patch literal 54173 zcmeHw3zQ^Rd7gH6-uu>SSC7>~?Mh;2#m+1sKxV9!vIxltNo!eJ34spu)O6QORc%jq z(^b8@LyoW@!DvE(KyH(#9l|3C7>s3(vCZKT!!A~Ag0V3qCWa(B3C0AI;C_L|9k7P@t=G0E0?kVvYkmQj2h?W{aUTjtOZFo zo2oUdoz9;kDtG@IZFrSlC<*j;%)RWB0Y2 zF@~NTyKgNGn~h_qg5n7Ysf9W0`G<)zZ7G#^wc72l%M7jqEYG*01o-`lI zrq8X`7uYzUL9KR>1no0Hm)hQiws&xN;ZaD#1S9-5PAupp37tWyamGQ3wfLnmZ}i4| zHronz%>g*;Guuue812~az{EFVZ&d zLziJj@LW{uhHuFx@E7!5XxlOKDWd7SHP&224Y9e!CpCwi0u8#^3{j%FM0TZXu_v40 zcyzNd5(fb1IuK4|Q_G!toskTf%v925wE~NoCf)GE;ah&D3!_Pw!~=xR?co6~cR=fJ z5nl}Xt2P^{ITuJ{-c!!0!(Wyi$&T}iF`I2}ttp&y1FJPx{ix9mKa)*j*JEji8pl@phjT(@soP+q9G`X?|J-7{;&L-XkmWn`+gHpfNV5))$TA41H&iaEZgEGj(=-wPjx zRFX^9x3Wq6V!|Z#CfkZD!8vk8q7-6851jSe4g5I`VGzm|ei)`(h(`A$>r)yA%k~j= zUlGDT1uTCD8nrKb{I84r^pt@=;0_ipcE}x4xZMy6-C#T~r^aOL3xaQgHnhpQU zKz#n;2z-vW1N1Pg4!;i*`4=a{AK0^2IXAELdZ?S8iY)~*Y<$j-qyGQ3AuY_egv9)| zq;j_H0bvxNoeOg2w=XKF@ewD%%{kr#ybWS10Z(V!g+^DF>doqDL$9;PV7!{`l(~~L zGu$BFyJlF)*}Q{!WMRg`e=WG%Gc(b$S7CEcrQ#hw?j5dFNF^(k!~7vwQSZ2C_jiOf z$DR3hry;yaXw#1#5l-@OfBZ5~JaO5f@#Q83PwUx^Fj@)g_?K4TP*6ldepWVB_Zur6 ze+7QZM2kfa`6DRrHyu)CRmW#PpL~XbRUMIoqu-tRn;)2QrXBMQ}VK>v}AigIj zJK^va;UVgR;<#S6KYlm|WF(6apF%IA7=FBVHXx0WF5>Fpj)Yu z@sFWn2 z29B3^PqW#QhSa>I&FIepR_}Q$Z$^<5h~K4JFn9Ve#9>~-?H6O1p?tWI9VGm`f+_V> zG6RwP-aJp|`Jl{j-oQ!ty|>vI&4#a#7qVT36&HQ60DDzEvCVu!lFz=V3HS*`j`E3r zEqtTp(istF{41(0Bjpj0@~0IRVe28RlLcYZN~Y`xGyHt~Cj|U_{2ltbz`wq*9{$#P`1Cpf5kVD~F&S6s z$?4@3ZcyX^=Xqh#Pu3dMsJZ9`O#kX6-)ZQlUX;-Eg#c#_zwrYTz03#p3|->y39_hg zPR~=j3n00mYM=Els4<_RCIwoCt^Uhg*F9z@SfM!#%%&Mp1yM=-ztG1hbJN&nYi`;? z0D4Cz+Fez{AOvLK@q8dcbYip8+;DW)`jn@%Ekk)TDBW0sEzMzP$)3I7IxL ziK~Zsu9g@xBWEa~ku*U#W~#l0vGwkWmV@eA75QBuxjpV`#vKPqhMT_@R10QwZvuKs zn;-TeNu!N_B7(s{qGW#NuGCu%e3oy4!JyoR z!~&@f2?h}9j$uB$x+EIQrFhj&k~UZ8&bFfzIW06qP6qCC5S)5&3DFWp%9u+Yy4R1?hQYd9u}w_zNNrIv16f|g97f{!o{PyJDTh~-k;1_4!5ntB zIW_G^HpWxFx1rjXs(Ve3HIv0? zO+d%NmQe$!>njyvNu@G-q$G@54X{F6Lkx9wA%>Fe>}62{wf=F`K4apZm;I?_&=I4l zUsbdzk851f)KjW0qw8&;tB$6oB!-fi`hw===T#5o&|Ohg3G~ad%h>`Vt-yd6LAxGd zA>1&;n`NF)TGhNJi(oPSJwj}MTms|C0mCILi$B2fUUo$pdy%+m_=Gk_;#SUp7mI!A{Q}9 z+ns6(AC4S4?hfA9S%TPwbI7eHRg{RpS;KM}lCa)_-&nI&{^kkf!9}wFE#3+qn z;l0Xr!`qvUDk@X1rL6$M1xNIprU2VxzTNnDf42tgMC62~GL<1p4Tidw5*r9GxtF5jSC2;YI3Pj~ zu^_F}K5`^I34ARPxTpEiDxW8;ZP881AyCqTCSFRHZ3C{_^GNa|zaG6Ya64=J3(lHu zxdC_Ws=O9TT!eid(P4W}AE9zNY)`7T%wfCJa@c0fQFB9LUea9sfa+y%%V{QK}3 zq)(L%>!20;3on_2W;sCyu?(w6VoWZYMyueWy#v%6&P98g=v{QtOy)2rt+&7tTGCCs zle9~4a0E9^HWh9fM95ZZQG(UWP5Vy-`F#8geO=&RL%3;Y@*%V+l?cuSC>BPxjirFY zcC*p!Br3<|Et=I<%;%D-xVU)KI~zvTkQG!>Eff-sZ3N;CS~ozA6_ya%I(_!i(cl|X z!nXwF)dGW>z_V*zX!3byU)Gz)T0g&+gVB4wCb^(_ov>nF%=H72Lxai>$Cia&2L6?n zfw!~x9~+|dgK--f<7MW$3!WxHeOZ)-Pkkf)f*CmvD{aRTitYcx2OLKv_P^NMTwR zMc$HR6e}DmrzQ*!C2<_Nq^bKwwoEFHzM!S|I*h!xE1Z{J$|QNJ1)D%m0f|vFNzY|f zN3JB&6$QTpO>z#2Mu<-|p<^B1a-kXYjd>z>Dq@uT0WMGE<*F?sXOhTM;&f~hhu-PElRA@WoL)(r4vO(`A$mioH>FWajDswZK_7t;0|MCtLr?)*{ zrQGMSZia{l|DR>G(`hb~pHPJ}U+Y_KCRj>D!rnt2F!mqS>ubZOg}~r^RtSI_3LjK$ zub@s`J0^{17h}Vrd5_?+a%gnL#FfR=1sfPQ$;$DG-%DL^ZMRB==wSoW`*M(Mw}$dZ zy%QI|fVLxKjj-!M1<>(F&`00IMSLGzsraYJ1N(tpsKZ7>8X{8`4?{zUdeDx2*>!fx zqMX~>4CbkBD@T6jl7TfrloJM^szvzh7V>L(VihabD4P&_5YG7Z4zB<$WG?T(0@UqT z>0Z=A$QGAfy%@~=LXMe6#&Lg9Y!tA(=zN*F;i6-u&t(Gx;_v4m4kJEaVr;Tom_#;= zanHQhAEA%o#HV~jrU*R(h7u*22yL1-Mw_SaU;;w@83Hn@Yr}T3xN|PWB167~!YVS9 zs3_awaBeO)CrIjRqYGnO$01sdJgLjOnN)3=ck_DiM|(G8e571z`46qwSF4u8`!_|X z8}o09{arf$#xnejK!#3{$WvBDBUEs3HiK@%IXK6O(nSY{GlY3KWg=y|IIjmvV}f7c z@USk9Y${wF2#KwveKIKz5#;mntLf_k{~E%@`5&WYGVBxuSF_$Z6x1^aI^T9Ghf$kdTf7d8|~_K@`pTZfk3%j z+nZ%op6HvLGvoyPPCbR66#8c(?2kL5r>Tu6aUKy&S9VGHGTFXz3dtz6Or*5(S9AUL zo^VJEDRD!XFynuqSK@~8z?c{uxX)--Nqi?b?~L}H(Q&+CAOSF7xp9?pqHyIGjP`FE z9oL_{*wUxDoFA2~^`=`vT$aAuqBS+!IkWaiIWxxET(*pgBh%SKuMFz-rgyg4uGbD8 z;yXGhSH@Ccg37|{`cZ)9qy#VAC#{GgqFc=nGMs4J3N5H+>-n zpUTBh1X~Lhz~AF1vDsIio-pDn)EAtpH5mD0^9U1uKan99o@5HSH9R$k?Q|e&R0;`iFf$ zQ*C+<^#8FypHi!O<%eO!J0^f>PZv8}%=b^HVTf_Xe+p2l|1BUrC!@+fh|Mhfa4-w* z=}~!Zn8tw2NRIC%R=EId$}tabU?5m*heS{{T8^r&?cHS6zk-2W3rzAkiTDQ?R({wy zj`k(%kGqHHA}hpYw-T3T3!Cpz+hof7rsGmv@t3CR-A<6%re;xA?xH4=onhZWz19iA zDJxWy9W~g|J%$2~DMdy4h5yjwiJj0$t(kvWVF?m@Y&a*R)1n2WO0tUMG2YN=(h)(l zu_+GCA@`p4WewuDxHdh5ue_X?iYFfzC5uHn_bf$i%vP5~Z5p9M)b?p6?Q|~5fP3HK zCy9h5Q5yqZjN0fj5&@)ga{c=>gzmFMSs0!XqBhx7L~WS7Y)1Bp+J2GnKOcXDzAo^u z!K1c^e_U*q5lOb(!Zsi5;-ZJcN2&px)`G2XL3=gAK}upL3IZlwLyjN}hlNy;sYb*^ z(-FHx*=j^l0tEi@JJ{WVNrUCGS)7Kj4Xfjeix1rO6L+0F1%OnM&VHV{m)f0HiUAVdJmxcl#99Be@8KvE9In%-Vj+JC`e=lJ+bH^#L^RCU zFB4mg2`TIu*hyMTYiI>_Lh7_R`So1C{R2C~gavjh&k{EWqXI%i$#gmL34Xz7|J$RF zcASZl(U*fGTMdbm$V>tml0l<~KN=mIgM9_rfaAavRFm>95uM-{jP~Cf9naNgSBtb< z=f`ZDLUWQL3oJv~Rajt|+J%hkWr$@`OXX(6N+=(hYz#uuvk4t`L>7cQTC}y--cv&@ z_zt|;BnZ44?;x{w3d?afdR0_)!yFoBV22IQV8+B`PeZWXLQC?q)Op{L>!rWi6I`bD zFCA^Xt|3fkQ^6|jD~b}+quXlGNR393&FJvZFr$e*dK$$gazHZ%{j~t)={%SKy`h%? zz3;}8@U|9i^yrAJMu6#p?U}^6Sx6SD{o7}w#!WBsThSulMagC)I_X4fDQ(I`@s~Y; z)ac|ZxWt%rC~3*}a$@>=HI58}WHMVp(JJ9Ntw6XknO5LD;29n@dF+GCl~p zsPJV{pe@Ni&PHL7{?<`QzaUA!x0D=4_w=MS?Wrg#ySzv>j-{FzOK$ZPF_r2f8hGMrgt&8Dxno(Q)dbHCkxY@w_-t{SXZ@RX{@tAW7GxH>zCo9_b*g0?kbe+a>+uC z8V|W#Rbf_Dv+Qr9i>IGdv?)*2xzdB5P;D7q*FaajcseC9l+4r@G%uf4J(NRt6^Rw0 z+iAjK3)GAKUAl1GDi~0NGK?eH3tC9kNEJfzr$D>m7E-@U)GmhPnlUUa?7Aw2c{{W^8;4<2WBr(ANe2RTi2v-740MrQ}PRA?PTj>5^xB z`SV#VOrN1)mxsRB*lU_5l2QwMaaZf)<+=WQPv&w`Ba9#g`?6t+((^;Hr650l%BbXT z8zwz}v`k~91vW*f+#;JQNf!^;1?lti+(*Q~pKY+5TcE>@ApIpo7tq^u>xzxRI`k#gPW zy6&6%NTSPedsMY$j@#qlf_B`t=Sah~B6n5Gz!R#k;a#{Q9<~ej+&&~^T09&7F%}6_ zh`vL&p>AxcPn@$itR^-GGEW!=3dixbO%pR+^@jQmB^8goR_4aoeFKk0S0P}j=GP#T=R{egS z^=}K|9_A=eDYSQFI7OmZ))=0;D$Pq400Glmk=BTD*3s80RHu->}~EbmX{C+ z%DxK9rtD^qdVzbL{l^cLnI};&FsN`m;soIqj>sIsxYjfHhWhsX&h?&OEkzdnGE za7ath|8Y?tP@EkvT|(mOo^DLp{xywRAuDkXc4xS(#Jh+s#jHfm;b5r=^TkHQuWE6d|dO2ozR; z{M=GvElS$Kir=P}l9ZsJOT}*-oMJ{a_e(j8U{n!c@z5YFpKqp}6jy^Jz#6m!lB|{vi78kh&NwSX7PXqJ68XfkbJXMQYX#jFa;SdY%yJlQI zXCIyEYZbJx<*~Kxcpi?-F#f%ZlcBib4%lVddRbCauFhO9J%ds<+(2T&T4K=sA)22J zM=T{j?qr&~l>B9?ElW8(VWk|VEd1cR=?j{bcdH(TPc#&vYe9%#jE;wLS?mKKHSR?x zMvvodbiV&0AeqZ3Pe9IIDuy+JnAK<4fJ(^e+}-bWQW*F z3Kgo?g-am3lt8*IDnUNTqngznK@+)c%RQq?t)=xcBd@5dl}-_!!8v|rOddskrZ@Q) z!g68Rkjk@+15+(Xlx z$m3`WSTFn8wK!pKfr>Wrwi*&FmhMGT1Y)8+dt~ou=I9ANLQ?PharEZyX>LglnvU8OHS^EWb zkF%@n1hfhhp$+aAJh0W}nY*35t5sX3SRVkT^}5oG##d^!c}Xku^HndyJ9=mVL zCZ!k}cH+L|zLkG2-iNnpU(^FR;T(uF{d*iuUAmZCgLv71kBiJ=kxG{?vuG8Z7$RU; z6HIL1o?dYX8O9ozslTnW=V<#PvKqacwM$>1A|1OjdFEd8ThGJaC;3Sf(#+Aq>;Hm z9AcIF4V=P(;LIP)6@f@n-&Zxy6fHc(A`*{(cd(s=aJx_9LI zvL{1xLL<2&x0s-_>E@mu+J+4f`5mrg_;3 zgn>9!5jmDsW>ILrCtlcwtxP!J2S)^9>fu{`O0y|o@&_Mk6X&E z3775UW0_Misg8ifEgh~pW8e3JrH$g6%yeXmOuHIUVs!s5y_eCk5(8=Qrm%x8-ZlaQi0o;&Sl~2iYtK zjZdK6XyLXRiWzVJ21J6W1u=k)EymkME_cFc-p!-QQb!lWS z=ziybkBgwYNTo{`bYIy+YRigwG+u?MJHiNua)aVe5%r5+k0o?0?6wMy3^C2c-JgOT zIZb_z7I(|0!Xbio*ygKG-2GL8d_MjfeO=&RW!@08C&jq?!F!rjgv*Gvg{aCIRQ{x? zlUAMR$PJ$EX7M>c*B71>Rrfr=%?#pkzD-FdoL|22?u|L^>w?J2CaTFWqvIPS7Sf8S zsYEN@Gr1n@Sur2|Qrt~2*|amI2B*8rBV;o!-<@>gK4Z;0b})TYa;7TQjZA?%B-kNd zDuGk<@Z5Yz2kVK=m9RD=wdI2WMt_NcUb3L{Us*#Qd8)lZ@VH-8THM+y8*X5hwTcyV ze;bKQ4{qmHLkhGlj_$bhfNIMo)h}3+>Xd~aWJ6!j(tAwxF#L2{gsx>jz6u==Ws>b; z1&w>rNb7O1*z^^EWX7gnAUPAm0zrn2O=VMIia}F7s=;E@Qw02c{2+Z@;9o;nZ_7eXc~8w5 z?)6p*?;J7bp4)M>6b^;L`fh`r=mN;n#+TmHV{Q*MW{NzUss&T4F9Nku1A`aQ+tt&c z;3Eg*K8wRiR@lj&NAc1sylqtc zO{e*_BX%H(xDvFYx_T7Fx69GF3eLu9C&v%Z9ma+-yr+ISss|P879Ey%)Khd3=iiAQ z@gCIWI<%l7USxm#FkYh7Y@;(;`M{jlI!<+k-Vtx^R_cRMb^e4P@_mfPOgu)eA^SNc z1LcO%73;iPwPo`2CCe=DE2p*;=3ck8JilM{UXGdTEP^6tb_DePzX3ewe6=I9X@$4A zYsF<_bXO9X|Ip<84JSFBaoDe-DR$2dvOVRu+)!NGQv?)i2Z{5j$*;O$jj(@&qo56c zKBJNgIG^Hlv9>$TXcJP#qH%Ux@<{yBO!}UCNUk$Zzr&Fkgh~I~4aLPI0cCI|&FpZw zeWPsh;V5i~NxSm4y^K{`jfW(|tZSNW*SQDjV%u}kbU@vDp&N>eZ34>RY`e`3YXsfm zC~SyrTa5|0jAIl0zGRmCsrmGZ=0vlr6 zHN73!G6wD~eOz*~$6ZZ=&$&t9V(DiFXX%&SP+Tk(P%M@@{gH3FVU564j>3kRy0bD-(E8P%BU?)dpL+spcMfYVq zoRUw-q3H{HY`%MJE}p$^aGo{YP+U9{P%NJDjgn$9Kfi18Q8%m+xW!Qzl3V>B7i);c zJOkbXv5f+Uig+8Od0_CBt_+UeexT0J==r=BfnRVE%uIAzH4DyTU3!8Y`jm}-#H7s5 z^qV-zc={jEDE7xC)O^ye1PGt|D7H%;#Hps@v{SjafQ>E%eS@@{T`lSAiZV#_Vr zehHL)r-=ARSSOH8#X13!e0t2rI>7`lJnjY-e?K38gT{D1{w950;9q5n1T3dpT(Vug zou!r8+0cuNJ=6!UO|ag)P{rv7I4z-xciYvQz9?|>YcbwtPp{9@>2>Mw(8=jYR_mqQ ztp-?QP4*cYgi*(4Y!KYb~qJE*23qHu>?|j5irg z*vKW{FB>Zhz)aV&Rqm??K28gV2GSuFO-~$)L51u!oGF1?#icea25DMinH`(_?d@N9 zB?aDksJ4PiCK~T_o*fjB!Q0Kddh&LgiH~IFloUpzkC|K_{kca_8TXz)%s4fN@>mbX zA$o_BTtor%QP+H)$JBD?d=xRTS3ZV4g}KR7W!CN^lODxs(4-BU z`g-%*To(Ttg!=`8fFS>{%i^-BnC`$qJ>CJPyADAF&SN)^)>O5oI{+ z)j?Fcjrw1)zenu&p`9iCxK@}`to~Gkgx(lbI?E;VGwPKD(s;3Rhwugm_PPhvUMw%7 z0lf`^rc*hWS~zf!XHbz$?-pr$&9e>K!BWS|9~vn;Gi$Q3!{u z4bYCa@y-TCAg-yZ_$vOp)S6c!mrVgblk41`0#qro^PLTEK_9NN$6kfV??OAH5P9%- zHps!Uw|&WjX#XAbh)Bhzr=OvNOwPlmuH>^o-YaT_os@65l+22+D z3_tA^anN!R|2jGzZkp;%EN~LK#TI!&n7Pi61`|{4w8F|=U zB)6#ISg2OrU&G|WYHF#Pg+DdBxHvaQKNlB|;B2~-Itb3;1)#K-m32W=2|x8pc81A` zW||t`94p^au1>~UTs(9L!NM%w)0D2^&B1sZ^NR7lsxcaeF$erWaHC`n*jGN>{5-H_ zx0(km0np++PEQ!oVvng{vb8o>AW`?J-@sIp(~#jrR^&w}pe}u7#w6 zLq{#-)PtvP_vj6Dl4$yZ9^-3=A{|vdzFM_l)77_t#HbOlM=wWm$G*i^l=BxVO`J@- zKIzw-g%Y3nTt|*rXRZqPC=Ogks!JTMKI(CDk1E2H&%Z7oU`@4UMEy31ssrCKK4k7S z^BY@D$=g>_38$3BLfDE0A ze?M?>O(eNge325DZgbQw)2U{nVnjHkB6JpsMu>}vwo7q}p$+BU#s7vFQ}pDxXp#$; zS#PD~T4ucq`P)G0j9@Qheb_96Y${wjsEZzt;nMX=s(*_hpO62TzAo^uGN+DNxZ+S3B)C0(S3EaE89>%_iJ5*tJ9Cwj}}9jB7Y^D^jmJZZ)wZ85_ub zZgc3QzE%@&cJLaV)g@%nk&DM}Wbrz853UVT@%+5vfH!TBlNac7{%{wG;g*60ZxDWC zip1}#dJkke@BO5DVI(3Fc6o(3bkY3RRZzfbFZB zmYVF5^pw71Ox-X7dZpt%Cs@i(%KhRZ<2-$^Q^D2R1w^fmef)G7CSG@%L}##b-+YI- z2zppbFNBI<*#wJPiE#oZo%6#(Cb8a3**~GsXW2a=xsZ9izO}=~&+tTlkRyb##I-Xw z4C$3^H3nz&wCQqJ_>(6obIk!8WZajn>D8TQn?hP7@|3U*bRK^x5`Sumgl>~fb<(Ol z^ijR36W5rjb-T&%P>qhZ8u?+v`_5fHY`yq1+`dr5F85KA^iA0g zAx#x={baUHUZE{Y-ILiA&WcYl3nblaH=S^w;*7?5)CR(cHn7k>@sMBd1jdV#cb?3q z@pAc~?WfH)+E3FIfi=L@7Jh8yU@GYQG=9#ApPhCczqY5%YGuiB&vxWRLGKMJN!=CtmsSG zW~$!UUhAy3a1ezMJP?*$fEN<9@jh5$-A;A|)NLfhetoHx1f5#5a&DDGY8NbTGYKkY zOC}}QlXWIaA}*pkE68Q}OW4|_u$+_%5gyI9VK50)fUS9;)9vE13hf3HK1Fn0l*$u|QC6|_)NgoSf3hD#z{ zS;BgHg_I+^DooQ>vT*DeE+_M?wKQxt=9}%6W8G{oJ;@Njla&-HGI&>D&lIlD-SC1J zgPuFu%T%#sc28Gy_s^5vQ>uzY_B1@bC`gwX45*u8ryI{=wn zttj^J{esbeR< zAngI#f#)N2*yj2MRx%Qz_32IvAa($|G)lodZU@#OJm zThF!xjWgYooh7`#nVA#p@q{SiZRin{Bdzc{CMGz$ffPh5g;hl#NP8yTM`7@+t8{Du zyNuqJ)sG4Mh-&QmBwgfx&&JP#lE>H4$IYAZ@nZV;9L{%*KT98N`q`w917rBOhCben z7t6-)q>oS1Bfmx;S7HZ!d-fCtmk#s>v|_Vh!QY10GwldOLzw#!Mos1#~-DSU!e~+ zmIXDIi2h<@d4m4>2z@+7AMeoS2$LHvSjh;?5 zkLi8C?0vv7y<;b)ckr;I>tj0Hp3{a7fQ;#=Om>teJH;%fbIv%ut|9W#ksdJ}`N4LQ z$F$d+(~wedtfq{W#j&OKm=@#NYDP@!9gM;(oy9_679w}D?WVRd_HVC7d^wghoL?cM zDxc$WW?tdX!E8Z0SC^V~rNHdbD{>dr)6-Uu(-JCcbh*_(=ErtQ6Y}1CU*gVX*$hlR zkHp&DY-_byuX8=Zv_E+}i_qFAt$Y*?=lw8WypjNFK>K$&KxO$W=H;#GGSj)O2y5$| V8tM27+3A@YO-{m&^D|E7|1a~u>x}>a literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/asab/config.doctree b/old_docs/_build/html/.doctrees/asab/config.doctree new file mode 100644 index 0000000000000000000000000000000000000000..f589b3fba2415231246ce25dd031b26a4fd2d314 GIT binary patch literal 32587 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/asab/index.doctree b/old_docs/_build/html/.doctrees/asab/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..de8f584db20fabef260741fada61ae070c901e8a GIT binary patch literal 8814 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ξ3Ot3|*@0giTrS6C*bjnE5JH}($IVjxnn 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 M(9szy&B@&V2M&d*XaE2J literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/asab/log.doctree b/old_docs/_build/html/.doctrees/asab/log.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e1ef00a64501d177bd0d1196e82b496cccfcdc41 GIT binary patch literal 86139 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/asab/metrics.doctree b/old_docs/_build/html/.doctrees/asab/metrics.doctree new file mode 100644 index 0000000000000000000000000000000000000000..33b18a67e45e4eeb9c17336928115e17bd15098a GIT binary patch literal 137737 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 Hn$G=SbXe$B literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/asab/module.doctree b/old_docs/_build/html/.doctrees/asab/module.doctree new file mode 100644 index 0000000000000000000000000000000000000000..b96f99197bb878609a4a6b5670efe01ace05c4a6 GIT binary patch literal 10705 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/asab/pubsub.doctree b/old_docs/_build/html/.doctrees/asab/pubsub.doctree new file mode 100644 index 0000000000000000000000000000000000000000..9033bfad60d398785d86a1e163c602028a81af53 GIT binary patch literal 56316 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/asab/service.doctree b/old_docs/_build/html/.doctrees/asab/service.doctree new file mode 100644 index 0000000000000000000000000000000000000000..ac255d985bfc11fae052c27699a89a9fd0a49604 GIT binary patch literal 11799 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 R=TME-c4nBe%+}oWe*k~T3Dp1q literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/asab/various.doctree b/old_docs/_build/html/.doctrees/asab/various.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4375a3626f0f3a59cc281ad433f10fb086beba0f GIT binary patch literal 65371 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/asab/web/cors.doctree b/old_docs/_build/html/.doctrees/asab/web/cors.doctree new file mode 100644 index 0000000000000000000000000000000000000000..fdf55106be21d00d634457a934b12b4b308e77aa GIT binary patch literal 4708 zcmcgwZEGFJ6}Bv2NmnmdmST%QtaPI$jil<{TWFxIXbQofj9b~YOhPDTJ-a*i&P4l` znOVJj2)G{tc9^ylZ{MK(8>IyLXAFV-j6P@f?%tKaMlqyHOu> z^(*eruIgOK^mM?YD9s|SOS=$dVUh6El+VkZ-(-@fcY8YHpdu~kUJd~p|3}Rp;$KE7q z9@#ta?xda(+~cP#$z$#XJkCx$X-%geUdu#dm*UCT)>5y)W` z$OG{<(uFvzI!yTpJ4cp*(Hgg+W0zXiRv_B2-Nu2I(qFWdGVuc>Uc3X${Sd$R@OvM> z9VAu!Sp1A^z|I?XX1}H3oLT&p8v0^W>>-cWYFIcwR$^(mVzD2@S$Nd;;->_M0U|#5 zga^0lOm1r)k4SRJ)v*lup10L_wlyi44f|Sat6;;rLmj+47`8LYs3$zLJt4;;#?San zjj3#G_cV$3b|t%wY&?t?6T{3*eiIZ&n( z#1@Ks)Em6u%u_|0QnLW+l?QNoC(?*1wnq{eb|NFBcBO!Bpeytujo+90DP+av(N$w( zu@#92O(b@I*QEH-BDI7Mcilf95gt_u$e9uP!{KfX_wTZ#$@}r^=3PXBi;A1boLcLKP#A~!~tJwd3`Go!zo~^^XnWzN$iT5nz-9<^gMHS*eFU;PEud zGl{xFKA7>eU~%jzZVHT}{PQfu+3A_g162DJRw4hq;2KM|@7;fR=ib5L&cOSa#Rd10 zLPLjP%2buRHQX9p%;0~j4F0XL_05;rTBq>_rSYOGt+f8P9pP68jnewHOY8CfHxe(N z{B!u?$-f3Iv%hYeeK}yYo6zKD6UHi%NYi&p);^`Ff6h)pO`PfF32lg=*rOAE z#`eNO5oPong1B5uDxzo?G&csOf-$c(6nKP2Vo(S;+#HPcw5hBf*zTBvfH9M)5-$Aa%qwH zr>M%LgrtWCCv!i{5~B4QD&MLkJmyZ~)8XjX^cFi#7EJi=fn8QS&lLJKKjv|H_o`h) zbvLgayT(r?Vr7^qbUmqKI}s0xF}CZSFhvJ6W`L6>kaUd#Ga#qRr?w~4yf8kvTNYs! zxI#PhB5gFaU(Q@&tn6r-mjaqulPrCrSmb6!iwX({dIg^>#?KI_d~xng^j z-l+}s>RaarE-bd!$p?)<34|ziY-gpWIEZ)zo^ur!CHscr0BPh$JO@6ojl}igz|K|l zn<643*O=sKDdudC6(;kiB70Q=R4Y-D1kp`3rGF~QH7}yf z2P?y@>-;p&H22#p9ZEvuA4@GOh_3pP1o4bH9HC1B7S7iNA@=MtoY5!&=5BjH&19NS ze9PUEHs}ePfcw!LWSF!?Ncj?Ol+7z3x<*w6;2&nVm+t`R>ea`+fK5WX8KU>G5Q(qq4N-O>#Ok9WCrS?M zs*6$82c7{vSt!#HFi9DuxlaPD@u+HR&+IHukLikS7piuG`UMna8c7s~@p0IXIocDh z*K05e&@%Y20N6xyp~jVB{hYMAbVCenqvmA}FLYmre4d2Wv-nngqivT2<}8PWUzFn8 zXIi|2|KEsZZCBdKa;sNDiImg!&{#>RChK{XnQcim55^<8Nsz@&{@v6Y7lh61?m3O! zdRMn-{hWTshNz$4yr^q3a>Xv9V}w~j{h+iTQ!YKu2y74E_gT(hHLS literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/asab/web/index.doctree b/old_docs/_build/html/.doctrees/asab/web/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..fa6ef2626ccce3be93e47185588d37985a74ae17 GIT binary patch literal 21509 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 TxkNWx=E^kh$5W(OS`_{VnhkUV literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/asab/web/restapidocs.doctree b/old_docs/_build/html/.doctrees/asab/web/restapidocs.doctree new file mode 100644 index 0000000000000000000000000000000000000000..2fb6d165dd49a9d00b4b2e53dfb3596f67636e8b GIT binary patch literal 12295 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/asab/zookeeper.doctree b/old_docs/_build/html/.doctrees/asab/zookeeper.doctree new file mode 100644 index 0000000000000000000000000000000000000000..89a748c2947e05a8d5efc219570627d4c950f5cf GIT binary patch literal 35104 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 Ra=b>+K-|uFLIfPk{}0=I3)lbv literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/environment.pickle b/old_docs/_build/html/.doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..0f52b7d0c2a66741c8118893e1073c1baf182111 GIT binary patch literal 1576019 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

jjykuxdO#l+= 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

ZN&Sa*t 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⪻(kP_1>h* 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�Z%RF@Cw(dr}VphVGRnhchbI)SXZ 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 N=y>yVmYZ#HAu>^#~+_QW#nr#Z(Bzu+Y;pT{G3Q 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 bkcihFv$rh5Y+ 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 LvO`05+-?6462Ji_ literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/.doctrees/tutorial/web/chapter2.doctree b/old_docs/_build/html/.doctrees/tutorial/web/chapter2.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4855a8fdc95d814688c8bddb20fb10f7a7b0a2e2 GIT binary patch literal 58108 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 + + + + + + asab.abc.module — ASAB documentation + + + + + + + + + + + + + + + + +

+
+
+ + +
+ +

Source code for asab.abc.module

+import abc
+
+
+
[docs]class Module(abc.ABC): + """ + Abstract module class + """ + + def __init__(self, app): + pass + + # Lifecycle + +
[docs] async def initialize(self, app): + pass
+ +
[docs] async def finalize(self, app): + pass
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/abc/service.html b/old_docs/_build/html/_modules/asab/abc/service.html new file mode 100644 index 000000000..cbe76bec2 --- /dev/null +++ b/old_docs/_build/html/_modules/asab/abc/service.html @@ -0,0 +1,150 @@ + + + + + + + + asab.abc.service — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.abc.service

+import abc
+
+
+
[docs]class Service(abc.ABC): + """ + Abstract service class + """ + + def __init__(self, app, service_name): + self.Name = service_name + self.App = app + app._register_service(self) + + # Lifecycle + +
[docs] async def initialize(self, app): + pass
+ +
[docs] async def finalize(self, app): + pass
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/abc/singleton.html b/old_docs/_build/html/_modules/asab/abc/singleton.html new file mode 100644 index 000000000..2ecf81eac --- /dev/null +++ b/old_docs/_build/html/_modules/asab/abc/singleton.html @@ -0,0 +1,155 @@ + + + + + + + + asab.abc.singleton — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.abc.singleton

+
+
[docs]class Singleton(type): + + """ +The `singleton pattern <https://en.wikipedia.org/wiki/Singleton_pattern>`_ is a software design pattern that restricts the instantiation of a class to one object. + +*Note*: The implementation idea is borrowed from "`Creating a singleton in Python <https://stackoverflow.com/questions/6760685/creating-a-singleton-in-python>`_" question on StackOverflow. + """ + + _instances = {} + + def __call__(cls, *args, **kwargs): + if cls not in cls._instances: + cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) + return cls._instances[cls] + +
[docs] @classmethod + def delete(cls, singleton_cls): + ''' + The method for an intentional removal of the singleton object. + It shouldn't be used unless you really know what you are doing. + + One use case is a unit test, which removes an Application object after each iteration. + ''' + del cls._instances[singleton_cls]
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/application.html b/old_docs/_build/html/_modules/asab/application.html new file mode 100644 index 000000000..c906adb74 --- /dev/null +++ b/old_docs/_build/html/_modules/asab/application.html @@ -0,0 +1,823 @@ + + + + + + + + asab.application — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.application

+import os
+import sys
+import time
+import signal
+import random
+import logging
+import asyncio
+import argparse
+import itertools
+import platform
+import datetime
+
+try:
+	import daemon
+	import daemon.pidfile
+	import lockfile
+except ImportError:
+	daemon = None
+
+from .config import Config
+from .abc.singleton import Singleton
+from .log import Logging, _loop_exception_handler, LOG_NOTICE
+from .task import TaskService
+
+L = logging.getLogger(__name__)
+
+
+
[docs]class Application(metaclass=Singleton): + + Description = "This app is based on ASAB." + +
[docs] def __init__(self, args=None, modules=[]): + ''' + Argument `modules` allows to specify a list of ASAB modules that will be added by `app.add_module()` call. + + Example: + + class MyApplication(asab.Application): + def __init__(self): + super().__init__(modules=[asab.web.Module, asab.zookeeper.Module]) + ''' + + try: + # EX_OK code is not available on Windows + self.ExitCode = os.EX_OK + except AttributeError: + self.ExitCode = 0 + + # Queue of Services to be initialized + self.InitServicesQueue = [] + # Queue of Modules to be initialized + self.InitModulesQueue = [] + + # Parse command line + self.Args = self.parse_arguments(args=args) + + # Load configuration + + # Obtain HostName + self.HostName = platform.node() + os.environ['HOSTNAME'] = self.HostName + Config._load() + + if hasattr(self.Args, "daemonize") and self.Args.daemonize: + self.daemonize() + + elif hasattr(self.Args, "kill") and self.Args.kill: + self.daemon_kill() + + # Seed the random generator + random.seed() + + # Obtain the event loop + self.Loop = asyncio.get_event_loop() + if self.Loop.is_closed(): + self.Loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.Loop) + + self.LaunchTime = time.time() + self.BaseTime = self.LaunchTime - self.Loop.time() + + self.Modules = [] + self.Services = {} + + # Setup logging + self.Logging = Logging(self) + + # Configure the event loop + self.Loop.set_exception_handler(_loop_exception_handler) + if Config["logging"].getboolean("verbose"): + self.Loop.set_debug(True) + + # Adding a handler to listen to the interrupt event + if platform.system() == "Windows": + + try: + + # Windows win32api import + import win32api + + def handler(type): + self.stop() + return True + + win32api.SetConsoleCtrlHandler(handler, True) + + except ImportError as e: + L.warning("win32api module could not be loaded, because '{}'".format( + e + )) + + else: + + # POSIX and other reasonable systems + self.Loop.add_signal_handler(signal.SIGINT, self.stop) + self.Loop.add_signal_handler(signal.SIGTERM, self.stop) + self.Loop.add_signal_handler(signal.SIGHUP, self._hup) + + self._stop_event = asyncio.Event() + self._stop_event.clear() + self._stop_counter = 0 + + from .pubsub import PubSub + self.PubSub = PubSub(self) + + L.info("Initializing ...") + + self.TaskService = TaskService(self) + + for module in modules: + self.add_module(module) + + # Set housekeeping time and time limit + self.HousekeepingTime, self.HousekeepingTimeLimit, self.HousekeepingId = self._initialize_housekeeping_schedule() + self.HousekeepingMissedEvents: list = [] + # Every 10 minutes listen for housekeeping + self.PubSub.subscribe("Application.tick/600!", self._on_housekeeping_tick)
+ + +
[docs] def create_argument_parser( + self, + prog=None, + usage=None, + description=None, + epilog=None, + prefix_chars='-', + fromfile_prefix_chars=None, + argument_default=None, + conflict_handler='error', + add_help=True + ): + ''' + This method can be overriden to adjust argparse configuration. + Refer to the Python standard library to `argparse.ArgumentParser` for details of arguments. + ''' + + parser = argparse.ArgumentParser( + prog=prog, + usage=usage, + description=description if description is not None else self.Description, + epilog=epilog, + formatter_class=argparse.RawDescriptionHelpFormatter, + prefix_chars=prefix_chars, + fromfile_prefix_chars=fromfile_prefix_chars, + argument_default=argument_default, + conflict_handler=conflict_handler, + add_help=add_help + ) + parser.add_argument('-c', '--config', help='specify a path to a configuration file') + parser.add_argument('-v', '--verbose', action='store_true', help='print more information (enable debug output)') + parser.add_argument('-s', '--syslog', action='store_true', help='enable logging to a syslog') + parser.add_argument('-l', '--log-file', help='specify a path to a log file') + parser.add_argument('-w', '--web-api', help='activate Asab web API (default listening port is 0.0.0.0:8080)', const="0.0.0.0:8080", nargs="?") + + + if daemon is not None: + parser.add_argument('-d', '--daemonize', action='store_true', help='run daemonized (in the background)') + parser.add_argument('-k', '--kill', action='store_true', help='kill a running daemon and quit') + + return parser
+ + + def parse_arguments(self, args=None): + """ + It parses the command line arguments and sets the default values for the configuration accordingly. + + :param args: The arguments to parse. If not set, sys.argv[1:] will be used + :return: The arguments that were parsed. + """ + + parser = self.create_argument_parser() + args = parser.parse_args(args=args) + + if args.config is not None: + Config._default_values['general']['config_file'] = args.config + + if args.verbose: + Config._default_values['logging']['verbose'] = True + + if args.syslog: + Config._default_values['logging:syslog']['enabled'] = True + + if args.log_file: + Config._default_values['logging:file']['path'] = args.log_file + + if args.web_api: + if 'web' not in Config._default_values: + Config._default_values['web'] = {} + Config._default_values['web']['listen'] = args.web_api + + return args + + + def get_pidfile_path(self): + """ + Return the `pidfile` path from the configuration. + + Example from the configuration: + + ``` + [general] + pidfile=/tmp/my.pid + ``` + + `pidfile` is a file that contains process id of the ASAB process. + It is used for interaction with OS respective it's control of running services. + + If the `pidfile` is set to "", then return None. + + If it's set to "!", then return the default pidfile path (in `/var/run/` folder). + This is the default value. + + :return: The path to the `pidfile`. + """ + + pidfilepath = Config['general']['pidfile'] + if pidfilepath == "": + return None + elif pidfilepath == "!": + return os.path.join('/var/run', os.path.basename(sys.argv[0]) + '.pid') + else: + return pidfilepath + + + def daemonize(self): + if daemon is None: + print("Install 'python-daemon' module to support daemonizing.", file=sys.stderr) + sys.exit(1) + + pidfilepath = self.get_pidfile_path() + if pidfilepath is not None: + pidfile = daemon.pidfile.TimeoutPIDLockFile(pidfilepath) + + working_dir = Config['general']['working_dir'] + + uid = Config['general']['uid'] + if uid == "": + uid = None + + gid = Config['general']['gid'] + if gid == "": + gid = None + + signal_map = { + signal.SIGTTIN: None, + signal.SIGTTOU: None, + signal.SIGTSTP: None, + } + + self.DaemonContext = daemon.DaemonContext( + working_directory=working_dir, + signal_map=signal_map, + pidfile=pidfile, + uid=uid, + gid=gid, + ) + + try: + self.DaemonContext.open() + except lockfile.AlreadyLocked as e: + print("Cannot create a PID file '{}':".format(pidfilepath), e, file=sys.stderr) + sys.exit(1) + + + def daemon_kill(self): + if daemon is None: + print("Install 'python-daemon' module to support daemonising.", file=sys.stderr) + sys.exit(1) + + pidfilepath = self.get_pidfile_path() + if pidfilepath is None: + sys.exit(0) + + try: + pid = open(pidfilepath, "r").read() + except FileNotFoundError: + print("Pid file '{}' not found.".format(pidfilepath), file=sys.stderr) + sys.exit(0) + + pid = int(pid) + + for sno in [signal.SIGINT, signal.SIGINT, signal.SIGINT, signal.SIGINT, signal.SIGTERM]: + try: + os.kill(pid, sno) + except ProcessLookupError: + print("Process with pid '{}' not found.".format(pid), file=sys.stderr) + sys.exit(0) + for i in range(10): + if not os.path.exists(pidfilepath): + sys.exit(0) + time.sleep(0.1) + print("Daemon process (pid: {}) still running ...".format(pid), file=sys.stderr) + + print("Pid file '{}' not found.".format(pidfilepath), file=sys.stderr) + sys.exit(1) + + + +
[docs] def run(self): + # Comence init-time + self.PubSub.publish("Application.init!") + self.Loop.run_until_complete(asyncio.gather( + self._init_time_governor(), + self.initialize(), + + )) + + try: + # Comence run-time and application main() function + L.log(LOG_NOTICE, "is ready.") + self._stop_event.clear() + self.Loop.run_until_complete(asyncio.gather( + self._run_time_governor(), + self.main(), + )) + + # Comence exit-time + if self.ExitCode == "!RESTART!": + L.log(LOG_NOTICE, "is restarting ...") + else: + L.log(LOG_NOTICE, "is exiting ...", struct_data={'exit_code': self.ExitCode}) + self.Loop.run_until_complete(asyncio.gather( + self.finalize(), + self._exit_time_governor(), + )) + + # Python 3.5 lacks support for shutdown_asyncgens() + if hasattr(self.Loop, "shutdown_asyncgens"): + self.Loop.run_until_complete(self.Loop.shutdown_asyncgens()) + self.Loop.close() + + finally: + if self.ExitCode == "!RESTART!": + os.execv(sys.executable, [os.path.basename(sys.executable)] + sys.argv) + else: + return self.ExitCode
+ + +
[docs] def stop(self, exit_code: int = None): + if exit_code is not None: + self.set_exit_code(exit_code) + + self._stop_event.set() + self._stop_counter += 1 + self.PubSub.publish("Application.stop!", self._stop_counter) + + if self._stop_counter >= 3: + L.fatal("Emergency exit") + for task in asyncio.all_tasks(): + L.warning("Pending task during emergency exit: {}".format(task)) + try: + # EX_SOFTWARE code is not available on Windows + return os._exit(os.EX_SOFTWARE) + except AttributeError: + return os._exit(0) + + elif self._stop_counter > 1: + L.warning("{} tasks still active".format(len(asyncio.all_tasks())))
+ + + def _do_restart(self, event_name): + self.stop("!RESTART!") + + def restart(self): + ''' + Schedules a hard restart of the whole application. + + This function works by using os.execv(), which replaces the current process with a new one (without creating a new process ID). + Arguments and environment variables will be retained. + + IMPORTANT: Please note that this will work on Unix-based systems only, as it uses a feature specific to Unix. + + A piece of advice: Be careful while using this function, make sure you have some control over when and how this function is being called to avoid any unexpected process restarts. + It is not common to use these types of function calls in Python applications. + ''' + self.PubSub.subscribe("Application.tick/10!", self._do_restart) + + + def _hup(self): + self.Logging.rotate() + self.PubSub.publish("Application.hup!") + + + # Modules + +
[docs] def add_module(self, module_class): + """ + Load a new module. + """ + + for module in self.Modules: + if isinstance(module, module_class): + # Already loaded and registered + return + + module = module_class(self) + self.Modules.append(module) + + # Enqueue module for initialization (happens in run phase) + self.InitModulesQueue.append(module)
+ + + # Services + +
[docs] def get_service(self, service_name): + """ + Get a new service by its name. + + Returns `None` if the service is not registered. + """ + return self.Services.get(service_name)
+ + + def _register_service(self, service): + """ + Register a new service using its name. + """ + + if service.Name in self.Services: + L.error("Service '{}' already registered (existing:{} new:{})".format( + service.Name, self.Services[service.Name], service)) + raise RuntimeError("Service {} already registered".format(service.Name)) + + self.Services[service.Name] = service + + # Enqueue service for initialization (happens in run phase) + self.InitServicesQueue.append(service) + + + # Lifecycle callback + +
[docs] async def initialize(self): + pass
+ +
[docs] async def main(self): + pass
+ +
[docs] async def finalize(self): + pass
+ + + # Governors + + async def _init_time_governor(self): + # Initialize all services that has been created during application construction + await self._ensure_initialization() + + + async def _run_time_governor(self): + timeout = Config.getint('general', 'tick_period') + self.PubSub.publish("Application.run!") + + # Wait for stop event & tick in meanwhile + for cycle_no in itertools.count(1): + + await self._ensure_initialization() + + try: + await asyncio.wait_for(self._stop_event.wait(), timeout=timeout) + break + except asyncio.TimeoutError: + self.PubSub.publish("Application.tick!") + if (cycle_no % 10) == 0: + self.PubSub.publish("Application.tick/10!") + if (cycle_no % 60) == 0: + # Rebase a Loop time + self.BaseTime = time.time() - self.Loop.time() + self.PubSub.publish("Application.tick/60!") + if (cycle_no % 300) == 0: + self.PubSub.publish("Application.tick/300!") + if (cycle_no % 600) == 0: + self.PubSub.publish("Application.tick/600!") + if (cycle_no % 1800) == 0: + self.PubSub.publish("Application.tick/1800!") + if (cycle_no % 3600) == 0: + self.PubSub.publish("Application.tick/3600!") + if (cycle_no % 43200) == 0: + self.PubSub.publish("Application.tick/43200!") + if (cycle_no % 86400) == 0: + self.PubSub.publish("Application.tick/86400!") + continue + + + async def _exit_time_governor(self): + self.PubSub.publish("Application.exit!") + + # Finalize services + futures = set() + for service in self.Services.values(): + futures.add( + asyncio.ensure_future(service.finalize(self)) + ) + + while len(futures) > 0: + done, futures = await asyncio.wait(futures, return_when=asyncio.FIRST_EXCEPTION) + for fut in done: + try: + fut.result() + except Exception: + L.exception("Error during finalize call") + + + # Finalize modules + futures = set() + for module in self.Modules: + futures.add( + asyncio.ensure_future(module.finalize(self)) + ) + + while len(futures) > 0: + done, futures = await asyncio.wait(futures, return_when=asyncio.FIRST_EXCEPTION) + for fut in done: + try: + fut.result() + except Exception: + L.exception("Error during finalize call") + + + # Wait for non-finalized tasks + tasks_awaiting = 0 + for i in range(3): + try: + ts = asyncio.all_tasks(self.Loop) + except AttributeError: + # Compatibility for Python 3.6- + ts = asyncio.Task.all_tasks(self.Loop) + tasks_awaiting = 0 + for t in ts: + if t.done(): + continue + tasks_awaiting += 1 + if tasks_awaiting <= 1: + # 2 is for _exit_time_governor and wait() + break + + await asyncio.sleep(1) + + else: + L.warning("Exiting but {} async task(s) are still waiting".format(tasks_awaiting)) + + + async def _ensure_initialization(self): + ''' + This method ensures that any newly add module or registered service is initialized. + It is called from: + (1) init-time for modules&services added during application construction. + (2) run-time for modules&services added during aplication lifecycle. + ''' + + # Initialize modules + while len(self.InitModulesQueue) > 0: + module = self.InitModulesQueue.pop() + try: + await module.initialize(self) + except Exception: + L.exception("Error during module initialization") + + # Initialize services + while len(self.InitServicesQueue) > 0: + service = self.InitServicesQueue.pop() + try: + await service.initialize(self) + except Exception: + L.exception("Error during service initialization") + + +
[docs] def set_exit_code(self, exit_code: int, force: bool = False): + if self.ExitCode == "!RESTART!": + return + + if exit_code == "!RESTART!": + self.ExitCode = exit_code + + elif (self.ExitCode < exit_code) or force: + L.debug("Exit code set to {}".format(exit_code)) + self.ExitCode = exit_code
+ + + # Time + +
[docs] def time(self): + ''' + Return UTC unix timestamp using a loop time (a fast way how to get a wall clock time). + ''' + return self.BaseTime + self.Loop.time()
+ + + # Housekeeping + + def _initialize_housekeeping_schedule(self): + """ + Set the next housekeeping time and time limit from configuration. + Returns: (next_housekeeping_time, next_time_limit, next_housekeeping_id) + """ + config_house_time = datetime.datetime.strptime(Config['housekeeping']['at'], "%H:%M") # default: 03:00 + config_time_limit = datetime.datetime.strptime(Config['housekeeping']['limit'], "%H:%M") # default: 05:00 + + now = datetime.datetime.now(datetime.timezone.utc) + + next_housekeeping_time = now.replace( + hour=config_house_time.hour, + minute=config_house_time.minute, + second=0, + microsecond=0) + + # if the app started after the housekeeping time, set it to the next day + if now > next_housekeeping_time: + next_housekeeping_time += datetime.timedelta(days=1) + + # compute the time limit for the housekeeping + time_delta_limit = config_time_limit - config_house_time + if time_delta_limit < datetime.timedelta(hours=0): + time_delta_limit += datetime.timedelta(days=1) + + next_time_limit = next_housekeeping_time + time_delta_limit + + # Each time has its id that prevents from accidental executing housekeeping twice. + next_housekeeping_id = housekeeping_id(now) + + + return (next_housekeeping_time, next_time_limit, next_housekeeping_id) + + def _on_housekeeping_tick(self, message_type): + """ + Check if it's time for publishing the 'Application.housekeeping!' message. + If so, publish the message and set housekeeping time, the time limit and time id for the next day. + """ + now = datetime.datetime.now(datetime.timezone.utc) + today_id = housekeeping_id(now) + + if self.HousekeepingTime < now: + if now < self.HousekeepingTimeLimit and self.HousekeepingId <= today_id: + self.PubSub.publish("Application.housekeeping!") + else: + L.warning( + "Housekeeping has not been executed: It is past the time limit.", + struct_data={ + "housekeeping_time": self.HousekeepingTime.strftime("%Y-%m-%d %H:%M:%S"), + "time_limit": self.HousekeepingTimeLimit.strftime("%Y-%m-%d %H:%M:%S"), + "housekeeping_id": self.HousekeepingId, + } + ) + self.HousekeepingMissedEvents.append(today_id) + + self.HousekeepingTime += datetime.timedelta(days=1) + self.HousekeepingTimeLimit += datetime.timedelta(days=1) + self.HousekeepingId = housekeeping_id(self.HousekeepingTime) + L.log( + LOG_NOTICE, + "Setting time for the next housekeeping.", + struct_data={ + "next_housekeeping_time": self.HousekeepingTime.strftime("%Y-%m-%d %H:%M:%S"), + "next_time_limit": self.HousekeepingTimeLimit.strftime("%Y-%m-%d %H:%M:%S"), + "next_housekeeping_id": self.HousekeepingId, + } + ) + + if len(self.HousekeepingMissedEvents) > 0: + L.warning( + "One or more Housekeeping events have not been executed.", + struct_data={ + "missed_housekeeping_events": self.HousekeepingMissedEvents + })
+ + +def housekeeping_id(dt: datetime.datetime) -> int: + """ + Create a unique ID for each date. Utility function for housekeeping. + + >>> housekeeping_id(datetime.datetime.now()) + 20230418 + """ + return int(dt.strftime("%Y%m%d")) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/config.html b/old_docs/_build/html/_modules/asab/config.html new file mode 100644 index 000000000..0080ed856 --- /dev/null +++ b/old_docs/_build/html/_modules/asab/config.html @@ -0,0 +1,519 @@ + + + + + + + + asab.config — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.config

+import os
+import sys
+import glob
+import logging
+import inspect
+import platform
+import configparser
+import urllib.parse
+import collections.abc
+
+from . import utils
+
+
+L = logging.getLogger(__name__)
+
+
+
[docs]class ConfigParser(configparser.ConfigParser): + _syslog_sockets = { + 'Darwin': '/var/run/syslog' + } + + _syslog_format = { + 'Darwin': 'm' + } + + _default_values = { + + 'general': { + 'config_file': os.environ.get('ASAB_CONFIG', ''), + 'tick_period': 1, # In seconds + 'var_dir': os.path.expanduser('~/.' + os.path.splitext(os.path.basename(sys.argv[0]))[0]), + + 'changelog': '', + 'manifest': '', + + # Daemonization + 'pidfile': '!', # '!' has a special meaning => it transforms into platform specific location of pid file + 'working_dir': '.', + 'uid': '', + 'gid': '', + }, + + "asab:metrics": { + "native_metrics": "true", + "web_requests_metrics": False, # False is a default, web_requests_metrics won't be generated. + "expiration": 60, + }, + + "asab:doc": { + "default_route_tag": "module_name" + }, + + "logging": { + 'verbose': os.environ.get('ASAB_VERBOSE', False), + "app_name": os.path.basename(sys.argv[0]), + "sd_id": "sd", # Structured data id, see RFC5424 + "level": "NOTICE", + "levels": "", + }, + + "logging:console": { + "format": "%(asctime)s %(levelname)s %(name)s %(struct_data)s%(message)s", + "datefmt": "%d-%b-%Y %H:%M:%S.%f", + }, + + "logging:syslog": { + "enabled": "false", + # TODO: "facility": 'local1', + "address": _syslog_sockets.get(platform.system(), "/dev/log"), + "format": _syslog_format.get(platform.system(), "3"), + }, + + "logging:file": { + "path": "", + "format": "%(asctime)s %(levelname)s %(name)s %(struct_data)s%(message)s", + "datefmt": "%d-%b-%Y %H:%M:%S.%f", + "backup_count": 3, + "backup_max_bytes": 0, + "rotate_every": "", + }, + + "library": { + "azure_cache": "false", # true or the actual path of where the cache should be located + }, + + # "passwords" section serves to securely store passwords + # in the configuration file; the passwords are not + # shown in the default API + # + # Usage in the configuration file: + # + # [connection:KafkaConnection] + # password=${passwords:kafka_password} + # + # [passwords] + # kafka_password=<MY_SECRET_PASSWORD> + "passwords": { + }, + + "housekeeping": { + "at": "03:00", + "limit": "05:00" + } + + } + + if 'ASAB_ZOOKEEPER_SERVERS' in os.environ: + # If `ASAB_ZOOKEEPER_SERVERS` are specified, use that as a default value + _default_values['zookeeper'] = {'servers': os.environ['ASAB_ZOOKEEPER_SERVERS']} + + def add_defaults(self, dictionary): + """ Add defaults to a current configuration """ + + for section, keys in dictionary.items(): + section = str(section) + + if section not in self._sections: + try: + self.add_section(section) + except ValueError: + if self._strict: + raise + + for key, value in keys.items(): + + key = self.optionxform(str(key)) + if key in self._sections[section]: + # Value exists, no default needed + continue + + if value is not None: + value = str(value) + + if value is not None and "$" in value: + self.set(section, key, os.path.expandvars(value)) + else: + self.set(section, key, value) + + + def _traverse_includes(self, includes, this_dir): + """ Reads included config files. Supports nested including. """ + if '\n' in includes: + sep = '\n' + else: + sep = os.pathsep + + for include_glob in includes.split(sep): + include_glob = include_glob.strip() + + if len(include_glob) == 0: + continue + + if include_glob.startswith("zookeeper"): + self._include_from_zookeeper(include_glob) + + include_glob = os.path.expandvars(include_glob.strip()) + + for include in glob.glob(include_glob): + include = os.path.abspath(include) + + if include in self._included: + # Preventing infinite dependency looping + L.warn("Config file '{}' can be included only once.".format(include)) + continue + + self._included.add(include) + self.set('general', 'include', '') + + self._load_dir_stack.append(os.path.dirname(include)) + try: + self.read(include) + finally: + self._load_dir_stack.pop() + + includes = self.get('general', 'include', fallback='') + self._traverse_includes(includes, os.path.dirname(include_glob)) + + + def _load(self): + """ This method should be called only once, any subsequent call will lead to undefined behaviour """ + self._load_dir_stack = [] + self.config_contents_list = [] + self.config_name_list = [] + + config_fname = ConfigParser._default_values['general']['config_file'] + if config_fname != '': + if not os.path.isfile(config_fname): + print("Config file '{}' not found".format(config_fname), file=sys.stderr) + sys.exit(1) + + self._load_dir_stack.append(os.path.dirname(config_fname)) + try: + self.read(config_fname) + finally: + self._load_dir_stack.pop() + + includes = self.get('general', 'include', fallback='') + + self._included = set() + self._traverse_includes(includes, this_dir=os.path.dirname(config_fname)) + + self.add_defaults(ConfigParser._default_values) + + del self._load_dir_stack + + + def _include_from_zookeeper(self, zkurl): + # parse include value into hostname and path + url_pieces = urllib.parse.urlparse(zkurl) + url_path = url_pieces.path + url_netloc = url_pieces.netloc + + if not url_netloc: + if "asab:zookeeper" in self: + # Backward compatibility + url_netloc = self["asab:zookeeper"]["servers"] + else: + url_netloc = self["zookeeper"]["servers"] + + if url_path.startswith("./"): + if "asab:zookeeper" in self: + # Backward compatibility + url_path = self["asab:zookeeper"]["path"] + url_path[1:] + else: + url_path = self["zookeeper"]["path"] + url_path[1:] + + head, tail = os.path.split(url_path) + self.config_name_list.append(tail) + + try: + # Delayed import to minimize a hard dependecy footprint + import kazoo.client + zk = kazoo.client(url_netloc) + zk.start() + data = zk.get(url_path) + # convert bytes to string + encode_config = str(data, 'utf-8') + self.read_string(encode_config) + # Include in the list of config file contents + self.config_contents_list.append(encode_config) + zk.close() + except Exception as e: + L.error("Failed to obtain configuration from Zookeeper server(s): '{}'.".format(e)) + sys.exit(1) + + + def get_config_contents_list(self): + return self.config_contents_list, self.config_name_list + + + def getseconds(self, section, option, *, raw=False, vars=None, fallback=None, **kwargs): + if fallback is None: + fallback = configparser._UNSET + + return self._get_conv(section, option, utils.convert_to_seconds, raw=raw, vars=vars, fallback=fallback, **kwargs) + + + def geturl(self, section, option, raw=False, vars=None, fallback=None, scheme=None, **kwargs): + """Gets URL from config and removes all leading and trailing + whitespaces and trailing slashes. + + :param scheme: URL scheme(s) awaited. If None, scheme validation is bypassed. + :type scheme: str, tuple + :return: validated URL, raises ValueError when scheme requirements are not met if set. + """ + return utils.validate_url(self.get(section, option, raw=False, vars=None, fallback=fallback), scheme)
+ + +class _Interpolation(configparser.ExtendedInterpolation): + """Interpolation which expands environment variables in values.""" + + + def before_read(self, parser, section, option, value): + # Expand environment variables + if '$' in value: + os.environ['THIS_DIR'] = os.path.abspath(parser._load_dir_stack[-1]) + + value = os.path.expandvars(value) + + return super().before_read(parser, section, option, value) + + +Config = ConfigParser(interpolation=_Interpolation()) + + +class Configurable(object): + ''' + Usage: + class ConfigurableObject(asab.Configurable): + + ConfigDefaults = { + 'foo': 'bar', + } + + def __init__(self, config_section_name, config=None): + super().__init__(config_section_name=config_section_name, config=config) + + config_foo = self.Config.get('foo') + + ''' + + ConfigDefaults = {} + + + def __init__(self, config_section_name, config=None): + self.Config = ConfigObjectDict() + + for base_class in inspect.getmro(self.__class__): + if not hasattr(base_class, 'ConfigDefaults'): + continue + if len(base_class.ConfigDefaults) == 0: + continue + + # Merge config defaults of each base class in the 'inheritance' way + for key, value in base_class.ConfigDefaults.items(): + + if value is None: + raise ValueError("None value not allowed in ConfigDefaults. Found in %s:%s " % ( + config_section_name, key)) + + if key not in self.Config: + self.Config[key] = value + + if Config.has_section(config_section_name): + for key, value in Config.items(config_section_name): + self.Config[key] = value + + if config is not None: + self.Config.update(config) + + +# This is for backward compatibility +ConfigObject = Configurable + + +class ConfigObjectDict(collections.abc.MutableMapping): + + + def __init__(self): + self._data = {} + + + def __getitem__(self, key): + return self._data[key] + + + def __setitem__(self, key, value): + self._data[key] = value + + + def __delitem__(self, key): + del self._data[key] + + + def __iter__(self): + return iter(self._data) + + + def __len__(self): + return len(self._data) + + + def getboolean(self, key): + value = self._data[key] + return utils.string_to_boolean(value) + + + def getseconds(self, key): + value = self._data[key] + return utils.convert_to_seconds(value) + + + def getint(self, key): + value = self._data[key] + return int(value) + + + def getfloat(self, key): + value = self._data[key] + return float(value) + + + def geturl(self, key, scheme): + value = self._data[key] + return utils.validate_url(value, scheme) + + + def __repr__(self): + return "<%s %r>" % (self.__class__.__name__, self._data) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/library/providers/azurestorage.html b/old_docs/_build/html/_modules/asab/library/providers/azurestorage.html new file mode 100644 index 000000000..6be648022 --- /dev/null +++ b/old_docs/_build/html/_modules/asab/library/providers/azurestorage.html @@ -0,0 +1,368 @@ + + + + + + + + asab.library.providers.azurestorage — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.library.providers.azurestorage

+import os
+import io
+import typing
+import hashlib
+import logging
+import tempfile
+import dataclasses
+import urllib.parse
+import xml.dom.minidom
+
+import aiohttp
+
+from ...config import Config
+from ..item import LibraryItem
+from .abc import LibraryProviderABC
+
+#
+
+L = logging.getLogger(__name__)
+
+
+#
+
+
+
[docs]class AzureStorageLibraryProvider(LibraryProviderABC): + ''' + AzureStorageLibraryProvider is a library provider that reads + from an Microsoft Azure Storage container. + + Configure by: + + azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER + + If Container Public Access Level is not set to "Public access", + then "Access Policy" must be created with "Read" and "List" permissions + and "Shared Access Signature" (SAS) query string must be added to a URL in a configuration: + + azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER?sv=2020-10-02&si=XXXX&sr=c&sig=XXXXXXXXXXXXXX + + ''' + + def __init__(self, library, path): + super().__init__(library) + assert path[:6] == "azure+" + + self.URL = urllib.parse.urlparse(path[6:]) + self.Model = None # Will be set by `_load_model` method + self.Path = path + + self.CacheDir = Config.get("library", "azure_cache") + if self.CacheDir == 'false': + self.CacheDir = None + elif self.CacheDir == 'true': + self.CacheDir = os.path.join(tempfile.gettempdir(), "asab.library.azure.{}".format(hashlib.sha256(path.encode('utf-8')).hexdigest())) + + # Ensure that the case directory exists + if self.CacheDir is not None: + try: + os.makedirs(self.CacheDir) + except FileExistsError: + pass # Cache directory already exists + + self.App.TaskService.schedule(self._start()) + + + async def _start(self): + await self._load_model() + if self.Model is not None: + await self._set_ready() + + + # TODO: Call this periodically + async def _load_model(self): + url = urllib.parse.urlunparse(urllib.parse.ParseResult( + scheme=self.URL.scheme, + netloc=self.URL.netloc, + path=self.URL.path, + params='', + query=self.URL.query + "&restype=container&comp=list", + fragment='' + )) + + async with aiohttp.ClientSession() as session: + async with session.get(url) as resp: + if resp.status == 200: + content = await resp.text() + else: + err = await resp.text() + L.warning("Failed to list blobs from `{}`:\n{}".format(url, err)) + return + + model = AzureDirectory("/", sub=dict()) + + dom = xml.dom.minidom.parseString(content) + for blob in dom.getElementsByTagName("Blob"): + path = get_xml_text(blob.getElementsByTagName("Name")) + + path = path.split('/') + curmodel = model + for i in range(len(path) - 1): + newmodel = curmodel.sub.get(path[i]) + if newmodel is None: + curmodel.sub[path[i]] = newmodel = AzureDirectory( + name='/' + '/'.join(path[:i + 1]), + sub=dict() + ) + + curmodel = newmodel + + curmodel.sub[path[-1]] = AzureItem( + name='/' + '/'.join(path) + ) + + self.Model = model + + # TODO: If the cache is active, remove items from the cache that: + # 1) are not in the list + # 2) their etag differs + + L.info("is connected.", struct_data={'path': self.Path}) + + + async def list(self, path: str) -> list: + if self.Model is None: + L.warning("Azure Storage library provider is not ready. Cannot list {}".format(path)) + raise RuntimeError("Not ready") + + assert path[:1] == '/' + assert '//' not in path + assert len(path) == 1 or path[-1:] != '/' + + if path == '/': + pathparts = [] + else: + pathparts = path.split("/")[1:] + + curmodel = self.Model + for p in pathparts: + curmodel = curmodel.sub.get(p) + if curmodel is None: + raise KeyError("Not '{}' found".format(path)) + if curmodel.type != 'dir': + raise KeyError("Not '{}' found".format(path)) + + items = [] + for i in curmodel.sub.values(): + items.append(LibraryItem( + name=i.name, + type=i.type, + providers=[self], + )) + + return items + + + async def read(self, path: str) -> typing.IO: + + assert path[:1] == '/' + assert '//' not in path + assert len(path) == 1 or path[-1:] != '/' + + headers = {} + + pathhash = hashlib.sha256(path.encode('utf-8')).hexdigest() + cachefname = os.path.join(self.CacheDir, pathhash) + if self.CacheDir is not None: + try: + with open(cachefname + '.etag', "r") as etagf: + etag = etagf.read() + # We found a local cached file with the etag, we will use that in the request + # if the request returns "304 Not Modified" then we will ship the local version of the file + headers['If-None-Match'] = etag + except FileNotFoundError: + pass + + + url = urllib.parse.urlunparse(urllib.parse.ParseResult( + scheme=self.URL.scheme, + netloc=self.URL.netloc, + path=self.URL.path + path, + params='', + query=self.URL.query, + fragment='' + )) + + async with aiohttp.ClientSession() as session: + async with session.get(url, headers=headers) as resp: + if resp.status == 200: + + etag = resp.headers.get('ETag') + + if self.CacheDir is not None and etag is not None: + output = open(cachefname, "w+b") + + with open(cachefname + '.etag', "w") as etagf: + etagf.write(etag) + + else: + # Store the response into the temporary file + # ... that's to avoid storing the whole (and possibly large) file in the memory + output = tempfile.TemporaryFile() + + async for chunk in resp.content.iter_chunked(16 * io.DEFAULT_BUFFER_SIZE): + output.write(chunk) + + elif resp.status == 304 and self.CacheDir is not None: # 304 is Not Modified + # The file should be read from cache + output = open(cachefname, "r+b") + + else: + L.warning("Failed to get blob:\n{}".format(await resp.text()), struct_data={'status': resp.status}) + return None + + # Rewind the file so the reader can start consuming from the beginning + output.seek(0) + return output
+ + +@dataclasses.dataclass +class AzureDirectory: + name: str + sub: dict + type: str = "dir" + + +@dataclasses.dataclass +class AzureItem: + name: str + type: str = "item" + + +def get_xml_text(nodelist): + rc = [] + for node in nodelist: + for textnode in node.childNodes: + if textnode.nodeType == textnode.TEXT_NODE: + rc.append(textnode.data) + return ''.join(rc) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/library/providers/filesystem.html b/old_docs/_build/html/_modules/asab/library/providers/filesystem.html new file mode 100644 index 000000000..e6efb12a9 --- /dev/null +++ b/old_docs/_build/html/_modules/asab/library/providers/filesystem.html @@ -0,0 +1,330 @@ + + + + + + + + asab.library.providers.filesystem — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.library.providers.filesystem

+import io
+import os
+import os.path
+import stat
+import glob
+import struct
+import typing
+import logging
+
+from .abc import LibraryProviderABC
+from ..item import LibraryItem
+from ...timer import Timer
+
+try:
+	from .filesystem_inotify import inotify_init, inotify_add_watch, IN_CREATE, IN_ISDIR, IN_ALL_EVENTS, EVENT_FMT, EVENT_SIZE, IN_MOVED_TO, IN_IGNORED
+except OSError:
+	inotify_init = None
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+
[docs]class FileSystemLibraryProvider(LibraryProviderABC): + + def __init__(self, library, path, *, set_ready=True): + ''' + `set_ready` can be used to disable/defer `self._set_ready` call. + ''' + + super().__init__(library) + self.BasePath = os.path.abspath(path) + while self.BasePath.endswith("/"): + self.BasePath = self.BasePath[:-1] + + L.info("is connected.", struct_data={'path': path}) + # Filesystem is always ready (or you have a serious problem) + if set_ready: + self.App.TaskService.schedule(self._set_ready()) + + # Open inotify file descriptor + if inotify_init is not None: + init = inotify_init() + if init == -1: + L.warning("Subscribing to library changes in filesystem provider is not available. Inotify was not initialized.") + self.FD = None + else: + self.FD = init + self.App.Loop.add_reader(self.FD, self._on_inotify_read) + self.AggrTimer = Timer(self.App, self._on_aggr_timer) + else: + self.FD = None + + self.AggrEvents = [] + self.WDs = {} + + + async def read(self, path: str) -> typing.IO: + + node_path = self.BasePath + path + + # File path must start with '/' + assert node_path[:1] == '/', "File path must start with a forward slash (/). For example: /library/Templates/file.json" + # File path must end with the extension + assert len(os.path.splitext(node_path)[1]) > 0, "File path must end with an extension. For example: /library/Templates/item.json" + # File cannot contain '//' + assert '//' not in node_path + + try: + return io.FileIO(node_path, 'rb') + + except FileNotFoundError: + return None + + except IsADirectoryError: + return None + + + async def list(self, path: str) -> list: + # This list method is completely synchronous, but it should look like asynchronous to make all list methods unified among providers. + return self._list(path) + + + def _list(self, path: str): + + node_path = self.BasePath + path + + # Directory path must start with '/' + assert node_path[:1] == '/', "Directory path must start with a forward slash (/). For example: /library/Templates/" + # Directory path must end with '/' + assert node_path[-1:] == '/', "Directory path must end with a forward slash (/). For example: /library/Templates/" + # Directory cannot contain '//' + assert '//' not in node_path + + exists = os.access(node_path, os.R_OK) and os.path.isdir(node_path) + if not exists: + raise KeyError(" '{}' not found".format(path)) + + items = [] + for fname in glob.iglob(os.path.join(node_path, "*")): + + fstat = os.stat(fname) + + assert fname.startswith(self.BasePath) + fname = fname[len(self.BasePath):] + + if stat.S_ISREG(fstat.st_mode): + ftype = "item" + elif stat.S_ISDIR(fstat.st_mode): + ftype = "dir" + fname += '/' + else: + ftype = "?" + + # Remove any component that starts with '.' + if any(x.startswith('.') for x in fname.split('/')): + continue + + items.append(LibraryItem( + name=fname, + type=ftype, + providers=[self], + )) + + return items + + + def _on_inotify_read(self): + data = os.read(self.FD, 64 * 1024) + + pos = 0 + while pos < len(data): + wd, mask, cookie, namesize = struct.unpack_from(EVENT_FMT, data, pos) + pos += EVENT_SIZE + namesize + name = (data[pos - namesize: pos].split(b'\x00', 1)[0]).decode() + + if mask & IN_ISDIR == IN_ISDIR and ((mask & IN_CREATE == IN_CREATE) or (mask & IN_MOVED_TO == IN_MOVED_TO)): + subscribed_path, child_path = self.WDs[wd] + self._subscribe_recursive(subscribed_path, "/".join([child_path, name])) + + if mask & IN_IGNORED == IN_IGNORED: + # cleanup + del self.WDs[wd] + continue + + self.AggrEvents.append((wd, mask, cookie, os.fsdecode(name))) + + self.AggrTimer.restart(0.2) + + + async def _on_aggr_timer(self): + to_advertise = set() + for wd, mask, cookie, name in self.AggrEvents: + # When wathed directory is being removed, more than one inotify events are being produced. + # When IN_IGNORED event occurs, respective wd is removed from self.WDs, + # but some other events (like IN_DELETE_SELF) get to this point, without having its reference in self.WDs. + subscribed_path, _ = self.WDs.get(wd, (None, None)) + to_advertise.add(subscribed_path) + self.AggrEvents.clear() + + for path in to_advertise: + if path is None: + continue + self.App.PubSub.publish("Library.change!", self, path) + + + async def subscribe(self, path): + if not os.path.isdir(self.BasePath + path): + return + if self.FD is None: + L.warning("Cannot subscribe to changes in the filesystem layer of the library: '{}'".format(self.BasePath)) + return + self._subscribe_recursive(path, path) + + + def _subscribe_recursive(self, subscribed_path, path_to_be_listed): + binary = (self.BasePath + path_to_be_listed).encode() + wd = inotify_add_watch(self.FD, binary, IN_ALL_EVENTS) + if wd == -1: + L.error("Error in inotify_add_watch") + return + self.WDs[wd] = (subscribed_path, path_to_be_listed) + + try: + items = self._list(path_to_be_listed) + except KeyError: + # subscribing to non-existing directory is silent + return + + for item in items: + if item.type == "dir": + self._subscribe_recursive(subscribed_path, item.name) + + + async def finalize(self, app): + if self.FD is not None: + self.App.Loop.remove_reader(self.FD) + os.close(self.FD)
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/library/providers/git.html b/old_docs/_build/html/_modules/asab/library/providers/git.html new file mode 100644 index 000000000..a2f268e2e --- /dev/null +++ b/old_docs/_build/html/_modules/asab/library/providers/git.html @@ -0,0 +1,331 @@ + + + + + + + + asab.library.providers.git — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.library.providers.git

+import os
+import tempfile
+import logging
+import hashlib
+
+from .filesystem import FileSystemLibraryProvider
+from ...config import Config
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+try:
+	import pygit2
+except ImportError:
+	L.critical("Please install pygit2 package to enable Git Library Provider. >>> pip install pygit2")
+	raise SystemExit("Application exiting... .")
+
+
+
[docs]class GitLibraryProvider(FileSystemLibraryProvider): + """ + Read-only git provider to read from remote repository. + It clones a remote git repository to a temporary directory and then uses the + FileSystemLibraryProvider to read the files. + To read from local git repository, please use FileSystemProvider. + + Configuration: + (Use either deploytoken, publickey+privatekey for SSH option, or username and password and HTTP access.) + + ``` + [library] + providers=git+<URL or deploy token>#<branch name> + + [library:git] + publickey=<absolute path to file> + privatekey=<absolute path to file> + username=johnsmith + password=secretpassword + repodir=<optional location of the repository cache> + ``` + """ + def __init__(self, library, path): + + # The branch can be optionally specified in the URL fragment (after '#') + split_path = path.split("#", 1) + if len(split_path) > 1: + self.Branch = split_path[-1] + self.URL = split_path[0][4:] # omit 'git+' part + else: + self.Branch = None + self.URL = path[4:] + + self.Callbacks = pygit2.RemoteCallbacks(get_git_credentials(self.URL)) + + repodir = Config.get("library:git", "repodir", fallback=None) + if repodir is not None: + self.RepoPath = os.path.abspath(repodir) + else: + tempdir = tempfile.gettempdir() + self.RepoPath = os.path.join( + tempdir, + "asab.library.git", + hashlib.sha256(path.encode('utf-8')).hexdigest() + ) + + super().__init__(library, self.RepoPath, set_ready=False) + + self.GitRepository = None + + from ...proactor import Module + self.App.add_module(Module) + self.ProactorService = self.App.get_service("asab.ProactorService") + self.PullLock = False + + self.SubscribedPaths = set() + + self.App.TaskService.schedule(self.intialize_git_repo()) + self.App.PubSub.subscribe("Application.tick/60!", self._periodic_pull) + + + async def _periodic_pull(self, event_name): + """ + Changes in remote repository are being pulled every minute. `PullLock` flag ensures that only if previous "pull" has finished, new one can start. + """ + if self.GitRepository is None: + return + + if self.PullLock: + return + + self.PullLock = True + + try: + await self.ProactorService.execute(self.pull) + except pygit2.GitError: + L.warning("Periodic pull from the remote repository failed.") + finally: + self.PullLock = False + + + async def intialize_git_repo(self): + + def init_task(): + if pygit2.discover_repository(self.RepoPath) is None: + # For a new repository, clone the remote bit + try: + os.makedirs(self.RepoPath, mode=0o700) + except FileExistsError: + pass + self.GitRepository = pygit2.clone_repository(self.URL, self.RepoPath, callbacks=self.Callbacks, checkout_branch=self.Branch) + else: + # For existing repository, pull the latest changes + self.GitRepository = pygit2.Repository(self.RepoPath) + self.pull() + + try: + await self.ProactorService.execute(init_task) + except Exception: + L.exception("Initialize git repo failed.") + + try: + assert self.GitRepository.remotes["origin"] is not None + except (KeyError, AssertionError): + L.error("Connection to remote git repository failed.") + # The library will not get ready ... maybe we can retry init_test() in a while + return + + await self._set_ready() + + + def fetch(self): + """ + It fetches the remote repository and returns the commit ID of the remote branch + + :return: The commit id of the latest commit on the remote repository. + """ + if self.GitRepository is None: + return None + + self.GitRepository.remotes["origin"].fetch(callbacks=self.Callbacks) + if self.Branch is None: + reference = self.GitRepository.lookup_reference("refs/remotes/origin/HEAD") + else: + reference = self.GitRepository.lookup_reference("refs/remotes/origin/{}".format(self.Branch)) + commit_id = reference.peel().id + return commit_id + + + def pull(self): + new_commit_id = self.fetch() + + # Before new head is set, check the diffs. If changes in subscribed directory occured, set `publish` flag. + + to_publish = [] + for path in self.SubscribedPaths: + for i in self.GitRepository.diff(self.GitRepository.head.target, new_commit_id).deltas: + if path == "/": + to_publish.append(path) + elif ("/" + i.old_file.path).startswith(path): + to_publish.append(path) + + if new_commit_id == self.GitRepository.head.target: + return + + # Reset HEAD + self.GitRepository.head.set_target(new_commit_id) + self.GitRepository.reset(new_commit_id, pygit2.GIT_RESET_HARD) + + # Once reset of the head is finished, PubSub message about the change in the subsrcibed directory gets published. + for path in to_publish: + self.App.PubSub.publish("Library.change!", self, path) + + async def subscribe(self, path): + if not os.path.isdir(self.BasePath + path): + return + self.SubscribedPaths.add(path)
+ + +def get_git_credentials(url): + """ + Returns a pygit2.Credentials object that can be used to authenticate with the git repository + + :param url: The URL of the repository you want to clone + :return: A pygit2.Keypair object or a pygit2.UserPass object + """ + username = Config.get("library:git", "username", fallback=None) + password = Config.get("library:git", "password", fallback=None) + publickey = Config.get("library:git", "publickey", fallback=None) + privatekey = Config.get("library:git", "privatekey", fallback=None) + + if publickey is not None and privatekey is not None: + return pygit2.Keypair(username_from_url(url), publickey, privatekey, "") + + elif username is not None and password is not None: + return pygit2.UserPass(username, password) + + +def username_from_url(url): + return url.split("@")[0] +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/library/providers/zookeeper.html b/old_docs/_build/html/_modules/asab/library/providers/zookeeper.html new file mode 100644 index 000000000..caf04ac4f --- /dev/null +++ b/old_docs/_build/html/_modules/asab/library/providers/zookeeper.html @@ -0,0 +1,427 @@ + + + + + + + + asab.library.providers.zookeeper — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.library.providers.zookeeper

+import io
+import typing
+import logging
+import functools
+import os.path
+import urllib.parse
+
+import kazoo.exceptions
+
+from .abc import LibraryProviderABC
+from ..item import LibraryItem
+from ...zookeeper import ZooKeeperContainer
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+
[docs]class ZooKeeperLibraryProvider(LibraryProviderABC): + + """ + + Configuration variant: + + + 1) ZooKeeper provider is fully configured from [zookeeper] section + + ``` + [zookeeper] + servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 + path=/library + + [library] + providers: + zk:// + ``` + + + 2) ZooKeeper provider is configured by `servers` from [zookeeper] section and path from URL + + Path will be `/library'. + + ``` + [zookeeper] + servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 + path=/else + + [library] + providers: + zk:///library + ``` + + + 2.1) ZooKeeper provider is configured by `servers` from [zookeeper] section and path from URL + + Path will be `/', this is a special case to 2) + + ``` + [zookeeper] + servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 + path=/else + + [library] + providers: + zk:/// + ``` + + 3) ZooKeeper provider is fully configured from URL + + ``` + [library] + providers: + zk://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/library + ``` + + 4) ZooKeeper provider is configured by `servers` from [zookeeper] section and joined `path` from [zookeeper] and + path from URL + + Path will be `/else/library' + + ``` + [zookeeper] + servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 + path=/else + + [library] + providers: + zk://./library + ``` + + If `path` from [zookeeper] section is missing, an application class name will be used + Ex. `/BSQueryApp/library' + + """ + + def __init__(self, library, path): + super().__init__(library) + + url_pieces = urllib.parse.urlparse(path) + + self.FullPath = url_pieces.scheme + '://' + self.BasePath = url_pieces.path.lstrip("/") + while self.BasePath.endswith("/"): + self.BasePath = self.BasePath[:-1] + + self.BasePath = '/' + self.BasePath + if self.BasePath == '/': + self.BasePath = '' + + if url_pieces.netloc in ["", "."]: + # if netloc is not provided `zk:///path`, then use `zookeeper` section from config + config_section_name = 'zookeeper' + z_url = None + else: + config_section_name = '' + z_url = path + + # Initialize ZooKeeper client + zksvc = self.App.get_service("asab.ZooKeeperService") + self.ZookeeperContainer = ZooKeeperContainer( + zksvc, + config_section_name=config_section_name, + z_path=z_url + ) + self.Zookeeper = self.ZookeeperContainer.ZooKeeper + + if config_section_name == 'zookeeper': + self.FullPath += self.ZookeeperContainer.Config['servers'] + else: + self.FullPath += url_pieces.netloc + + # Handle `zk://` configuration + if z_url is None and url_pieces.netloc == "" and url_pieces.path == "" and self.ZookeeperContainer.Path != '': + self.BasePath = '/' + self.ZookeeperContainer.Path + + # Handle `zk://./path` configuration + if z_url is None and url_pieces.netloc == "." and self.ZookeeperContainer.Path != '': + self.BasePath = '/' + self.ZookeeperContainer.Path + self.BasePath + + self.FullPath += self.BasePath + + self.VersionNodePath = self.build_path('/.version.yaml') + self.Version = None # Will be read when a library become ready + self.VersionWatch = None + + self.App.PubSub.subscribe("ZooKeeperContainer.state/CONNECTED!", self._on_zk_connected) + self.App.PubSub.subscribe("ZooKeeperContainer.state/LOST!", self._on_zk_lost) + self.App.PubSub.subscribe("ZooKeeperContainer.state/SUSPENDED!", self._on_zk_lost) + self.App.PubSub.subscribe("Application.tick/60!", self._get_version_counter) + + + async def finalize(self, app): + """ + The `finalize` function is called when the application is shutting down + """ + await self.Zookeeper._stop() + + + async def _on_zk_connected(self, event_name, zkcontainer): + """ + When the Zookeeper container is connected, set the self.Zookeeper property to the Zookeeper object. + """ + if zkcontainer != self.ZookeeperContainer: + return + + L.info("is connected.", struct_data={'path': self.FullPath}) + + def on_version_changed(version, event): + self.App.Loop.call_soon_threadsafe(self._check_version_counter, version) + + def install_watcher(): + return kazoo.recipe.watchers.DataWatch(self.Zookeeper.Client, self.VersionNodePath, on_version_changed) + + self.VersionWatch = await self.Zookeeper.ProactorService.execute(install_watcher) + + await self._set_ready() + + + async def _on_zk_lost(self, event_name, zkcontainer): + if zkcontainer != self.ZookeeperContainer: + return + + await self._set_ready(ready=False) + + + async def _get_version_counter(self, event_name=None): + if self.Zookeeper is None: + return + + version = await self.Zookeeper.get_data(self.VersionNodePath) + self._check_version_counter(version) + + + def _check_version_counter(self, version): + # If version is `None` aka `/.version.yaml` doesn't exists, then assume version -1 + if version is not None: + try: + version = int(version) + except ValueError: + version = 1 + else: + version = 1 + + if self.Version is None: + # Initial grab of the version + self.Version = version + return + + if self.Version == version: + # The version has not changed + return + + L.info("Version changed", struct_data={'version': version, 'name': self.Library.Name}) + self.App.PubSub.publish("Library.change!", self, "TODO") + + + async def read(self, path: str) -> typing.IO: + if self.Zookeeper is None: + L.warning("Zookeeper Client has not been established (yet). Cannot read {}".format(path)) + raise RuntimeError("Zookeeper Client has not been established (yet). Not ready.") + + node_path = self.build_path(path) + + try: + node_data = await self.Zookeeper.get_data(node_path) + except kazoo.exceptions.ConnectionClosedError: + L.warning("Zookeeper library provider is not ready") + raise RuntimeError("Zookeeper library provider is not ready") + except kazoo.exceptions.NoNodeError: + return None + + # Consider adding other exceptions from Kazoo to indicate common non-critical errors + + if node_data is not None: + return io.BytesIO(initial_bytes=node_data) + else: + return None + + + async def list(self, path: str) -> list: + if self.Zookeeper is None: + L.warning("Zookeeper Client has not been established (yet). Cannot list {}".format(path)) + raise RuntimeError("Zookeeper Client has not been established (yet). Not ready.") + + node_path = self.build_path(path) + + nodes = await self.Zookeeper.get_children(node_path) + if nodes is None: + raise KeyError("Not '{}' found".format(node_path)) + + items = [] + for node in nodes: + + # Remove any component that starts with '.' + startswithdot = functools.reduce(lambda x, y: x or y.startswith('.'), node.split(os.path.sep), False) + if startswithdot: + continue + + if '.' in node: # We detect files in zookeeper by presence of the dot in the filename, + fname = path + node + ftype = "item" + else: + fname = path + node + '/' + ftype = "dir" + + items.append(LibraryItem( + name=fname, + type=ftype, + providers=[self], + )) + + return items + + + def build_path(self, path): + """ + It takes a path in the library and transforms in into a path within Zookeeper. + It does also series of sanity checks (asserts). + + IMPORTANT: If you encounter asserting failure, don't remove assert. + It means that your code is incorrect. + """ + assert path[:1] == '/' + if path != '/': + node_path = self.BasePath + path + else: + node_path = self.BasePath + + # Zookeeper path should not have forward slash at the end of path + node_path = node_path.rstrip("/") + + assert '//' not in node_path + assert node_path[0] == '/' + + return node_path
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/library/service.html b/old_docs/_build/html/_modules/asab/library/service.html new file mode 100644 index 000000000..bf374b14d --- /dev/null +++ b/old_docs/_build/html/_modules/asab/library/service.html @@ -0,0 +1,532 @@ + + + + + + + + asab.library.service — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.library.service

+import re
+import io
+import time
+import os.path
+import typing
+import tarfile
+import asyncio
+import logging
+import tempfile
+import functools
+import configparser
+
+import yaml
+
+from ..abc import Service
+from ..config import Config
+from ..log import LOG_NOTICE
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+
[docs]class LibraryService(Service): + """ + ASAB library (aka LibraryService) is an abstration for unified filesystem-like access to resources. + In the cluster/cloud microservice architectures, it is imperative that all microservices have access to unified resources. + There are technologies such as Apache Zookeeper that provides means for it. + + ASAB library builts on top of this concept and brings that into the ASAB microservice. + + ASAB library is designed to be read-only. + It also allows to "stack" various libraries into one view (overlayed) that merges content of each library into one united space. + + Configuration: + + ``` + [library] + providers: + provider+1:// + provider+2:// + provider+3:// + ``` + + The order of providers *IS* important, the priority (or layering) is top-down. + + Each library provider is specified by URL/URI schema: + + * `zk://` or `zookeeper://` for ZooKeeper provider + * `file://` or local path for FileSystem provider + * `azure+https://` for Microsoft Azure Storage provider. + + The first provider is also responsible for providing `/.disabled.yaml` that controls a visibility of items. + If `/.disabled.yaml` is not present, then is considered empty. + + A library is created in "not ready" state, each provider then inform library when it is ready (eg. Zookeeper provider needs to connect to Zookeeper servers). + Only after all providers are ready, the library itself become ready. + The library indicates that by the PubSub event `Library.ready!`. + """ + + def __init__(self, app, service_name, paths=None): + """ + The library service is designed to "exists" in multiple instances, + with different `paths` setup. + For that reason, you have to provide unique `service_name` + and there is no _default_ value for that. + + If `paths` are not provided, they are fetched from `[library]providers` configuration. + """ + + super().__init__(app, service_name) + self.Libraries = list() + self.Disabled = {} + + if paths is None: + try: + paths = Config.get("library", "providers") + except configparser.NoOptionError: + L.critical("'providers' option is not present in configuration section 'library'.") + raise SystemExit("Exit due to a critical configuration error.") + + if isinstance(paths, str): + paths = re.split(r"\s+", paths) + + for path in paths: + self._create_library(path) + app.PubSub.subscribe("Application.tick/60!", self.on_tick) + + + async def finalize(self, app): + while len(self.Libraries) > 0: + lib = self.Libraries.pop(-1) + await lib.finalize(self.App) + + + async def on_tick(self, message_type): + await self._read_disabled() + + + def _create_library(self, path): + library_provider = None + if path.startswith('zk://') or path.startswith('zookeeeper://'): + from .providers.zookeeper import ZooKeeperLibraryProvider + library_provider = ZooKeeperLibraryProvider(self, path) + + elif path.startswith('./') or path.startswith('/') or path.startswith('file://'): + from .providers.filesystem import FileSystemLibraryProvider + library_provider = FileSystemLibraryProvider(self, path) + + elif path.startswith('azure+https://'): + from .providers.azurestorage import AzureStorageLibraryProvider + library_provider = AzureStorageLibraryProvider(self, path) + + elif path.startswith('git+'): + from .providers.git import GitLibraryProvider + library_provider = GitLibraryProvider(self, path) + + elif path == '' or path.startswith("#") or path.startswith(";"): + # This is empty or commented line + return + + else: + L.error("Incorrect/unknown provider for '{}'".format(path)) + raise SystemExit("Exit due to a critical configuration error.") + + self.Libraries.append(library_provider) + + + def is_ready(self): + """ + It checks if all the libraries are ready. + + :return: A boolean value. + """ + if len(self.Libraries) == 0: + return False + + return functools.reduce( + lambda x, provider: provider.IsReady and x, + self.Libraries, + True + ) + + + async def _set_ready(self, provider): + if len(self.Libraries) == 0: + return + + if (provider == self.Libraries[0]) and provider.IsReady: + await self._read_disabled() + + if self.is_ready(): + L.log(LOG_NOTICE, "is ready.", struct_data={'name': self.Name}) + self.App.PubSub.publish("Library.ready!", self) + elif not provider.IsReady: + L.log(LOG_NOTICE, "is NOT ready.", struct_data={'name': self.Name}) + self.App.PubSub.publish("Library.not_ready!", self) + + + +
[docs] async def read(self, path: str, tenant: str = None) -> typing.IO: + """ + Read the content of the library item specified by `path`. + `None` is returned if the item is not found in the library. + + If the item is disabled (globally or for specified tenant) then None is returned. + + Example of use: + + ``` + itemio = await library.read('/path', 'tenant') + if itemio is not None: + with itemio: + return itemio.read() + ``` + + :param path: The path to the file, `LibraryItem.name` can be used directly + :param tenant: The tenant to apply. If not specified, the global access is assumed + :return: I/O stream (read) with the content of the libary item. + """ + # item path must start with '/' + assert path[:1] == '/', "Item path must start with a forward slash (/). For example: /library/Templates/item.json" + # Item path must end with the extension + assert len(os.path.splitext(path)[1]) > 0, "Item path must end with an extension. For example: /library/Templates/item.json" + + if self.check_disabled(path, tenant=tenant): + return None + + for library in self.Libraries: + itemio = await library.read(path) + if itemio is None: + continue + return itemio + + return None
+ + +
[docs] async def list(self, path="/", tenant=None, recursive=False): + """ + List the directory of the library specified by the path. + It returns a list of `LibraryItem` entris. + + Tenant is an optional parameter to list method for "disable" evaluation. + and default recursive is False. + + When tenant=None + The method returns list of items that are enabled (not disabled). + + When tenant='xxxxx' + The method returns list of items that are enabled (not disabled) for tenant 'xxxxx'. + + When recursive=True + The method returns list of items that are located at `path` and in subdirectories of that location. + + When recursive=False + The method returns list of items that are located at `path` + """ + + # Directory path must start with '/' + assert path[:1] == '/', "Directory path must start with a forward slash (/). For example: /library/Templates/" + # Directory path must end with '/' + assert path[-1:] == '/', "Directory path must end with a forward slash (/). For example: /library/Templates/" + # Directory path cannot contain '//' + assert '//' not in path + + # List requested level using all available providers + items = await self._list(path, tenant, providers=self.Libraries) + + if recursive: + # If recursive scan is requested, then iterate thru list of items + # find 'dir' types there and list them. + # Output of this list is attached to the list for recursive scan + # and also to the final output + recitems = list(items[:]) + + while len(recitems) > 0: + + item = recitems.pop(0) + if item.type != 'dir': + continue + + child_items = await self._list(item.name, tenant, providers=item.providers) + items.extend(child_items) + recitems.extend(child_items) + + return items
+ + + async def _list(self, path, tenant, providers): + + # Execute the list query in all providers in-parallel + result = await asyncio.gather(*[ + library.list(path) + for library in providers + ], return_exceptions=True) + + items = [] + uniq = dict() + for ress in result: + + if isinstance(ress, KeyError): + # The path doesn't exists in the provider + continue + + if isinstance(ress, Exception): + L.exception("Error when listing items from provider", exc_info=ress) + continue + + for item in ress: + + item.disabled = self.check_disabled(item.name, tenant=tenant) + + # If the item already exists, merge it + pitem = uniq.get(item.name) + if pitem is not None: + if pitem.type == 'dir' and item.type == 'dir': + # Directories are joined + pitem.providers.extend(item.providers) + + # Other item types are skipped + continue + + uniq[item.name] = item + items.append(item) + + items.sort(key=lambda x: x.name) + + return items + + + async def _read_disabled(self): + # `.disabled.yaml` is read from the first configured library + # It is applied on all libraries in the configuration. + disabled = await self.Libraries[0].read('/.disabled.yaml') + if disabled is None: + self.Disabled = {} + else: + try: + self.Disabled = yaml.safe_load(disabled) + if self.Disabled is None: + self.Disabled = {} + else: + # Disabled must be a dictionary object + assert (isinstance(self.Disabled, dict)), "The 'Disabled' attribute must be a dictionary instance." + except Exception: + self.Disabled = {} + L.exception("Failed to parse '/.disabled.yaml'") + + + def check_disabled(self, path, tenant=None): + """ + If the item is disabled for everybody, or if the item is disabled for the specified tenant, then + return True. Otherwise, return False + + :param path: The path to the item + :param tenant: The tenant name + :return: Boolean + """ + + disabled = self.Disabled.get(path) + if disabled is None: + return False + + if disabled == '*': + # Item is disabled for everybody + return True + + if tenant is not None and tenant in disabled: + # Item is disabled for a specified tenant + return True + + return False + + +
[docs] async def export(self, path="/", tenant=None, remove_path=False): + """ + It takes a path, and returns a file-like object containing a gzipped tar archive of the library contents of + that path + + :param path: The path to export, defaults to / (optional) + :param tenant: The tenant to use for the operation + :param remove_path: If True, the path will be removed from the tar file, defaults to False + (optional) + :return: A file object. + """ + + # Directory path must start with '/' + assert path[:1] == '/', "Directory path must start with a forward slash (/). For example: /library/Templates/" + # Directory path must end with '/' + assert path[-1:] == '/', "Directory path must end with a forward slash (/). For example: /library/Templates/" + # Directory path cannot contain '//' + assert '//' not in path + + fileobj = tempfile.TemporaryFile() + tarobj = tarfile.open(name=None, mode='w:gz', fileobj=fileobj) + + items = await self._list(path, tenant, providers=self.Libraries[:1]) + recitems = list(items[:]) + + while len(recitems) > 0: + + item = recitems.pop(0) + if item.type != 'dir': + continue + + child_items = await self._list(item.name, tenant, providers=item.providers) + items.extend(child_items) + recitems.extend(child_items) + + for item in items: + if item.type != 'item': + continue + my_data = await self.Libraries[0].read(item.name) + if remove_path: + assert item.name.startswith(path) + tar_name = item.name[len(path):] + else: + tar_name = item.name + info = tarfile.TarInfo(tar_name) + my_data.seek(0, io.SEEK_END) + info.size = my_data.tell() + my_data.seek(0, io.SEEK_SET) + info.mtime = time.time() + tarobj.addfile(tarinfo=info, fileobj=my_data) + + tarobj.close() + fileobj.seek(0) + return fileobj
+ + +
[docs] async def subscribe(self, paths): + """ + It subscribes to the changes in the library + :param paths: A list of absolute paths to subscribe to + """ + for path in paths: + assert path[:1] == '/', "Absolute path must be used when subscribing to the library changes" + + for provider in self.Libraries: + await provider.subscribe(path)
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/log.html b/old_docs/_build/html/_modules/asab/log.html new file mode 100644 index 000000000..87e61e6a5 --- /dev/null +++ b/old_docs/_build/html/_modules/asab/log.html @@ -0,0 +1,603 @@ + + + + + + + + asab.log — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.log

+import asyncio
+import datetime
+import logging
+import logging.handlers
+import os
+import pprint
+import queue
+import re
+import socket
+import sys
+import time
+import traceback
+import urllib.parse
+
+from .config import Config
+from .timer import Timer
+from .utils import running_in_container
+
+# Non-error/warning type of message that is visible without -v flag
+LOG_NOTICE = 25
+logging.addLevelName(LOG_NOTICE, "NOTICE")
+
+
+
[docs]class Logging(object): + + + def __init__(self, app): + self.RootLogger = logging.getLogger() + + self.ConsoleHandler = None + self.FileHandler = None + self.SyslogHandler = None + + if not self.RootLogger.hasHandlers(): + + # Add console logger if needed + if os.isatty(sys.stdout.fileno()) or os.environ.get('ASABFORCECONSOLE', '0') != '0': + self._configure_console_logging() + + # Initialize file handler + file_path = Config["logging:file"]["path"] + + if len(file_path) > 0: + + # Ensure file path + directory = os.path.dirname(file_path) + if not os.path.exists(directory): + os.makedirs(directory) + + self.FileHandler = logging.handlers.RotatingFileHandler( + file_path, + backupCount=Config.getint("logging:file", "backup_count"), + maxBytes=Config.getint("logging:file", "backup_max_bytes"), + ) + self.FileHandler.setLevel(logging.DEBUG) + self.FileHandler.setFormatter(StructuredDataFormatter( + fmt=Config["logging:file"]["format"], + datefmt=Config["logging:file"]["datefmt"], + sd_id=Config["logging"]["sd_id"], + )) + self.RootLogger.addHandler(self.FileHandler) + + rotate_every = Config.get("logging:file", "rotate_every") + if rotate_every != '': + rotate_every = re.match(r"^([0-9]+)([dMHs])$", rotate_every) + if rotate_every is not None: + i, u = rotate_every.groups() + i = int(i) + if i <= 0: + self.RootLogger.error("Invalid 'rotate_every' configuration value.") + else: + if u == 'H': + i = i * 60 * 60 + elif u == 'M': + i = i * 60 + elif u == 'd': + i = i * 60 * 60 * 24 + elif u == 's': + pass + + # PubSub is not ready at this moment, we need to create timer in a future + async def schedule(app, interval): + self.LogRotatingTime = Timer(app, self._on_tick_rotate_check, autorestart=True) + self.LogRotatingTime.start(i) + asyncio.ensure_future(schedule(app, i)) + + else: + self.RootLogger.error("Invalid 'rotate_every' configuration value.") + + # Initialize syslog + if Config["logging:syslog"].getboolean("enabled"): + + address = Config["logging:syslog"]["address"] + + if address[:1] == '/': + self.SyslogHandler = AsyncIOHandler(app.Loop, socket.AF_UNIX, socket.SOCK_DGRAM, address) + + else: + url = urllib.parse.urlparse(address) + + if url.scheme == 'tcp': + self.SyslogHandler = AsyncIOHandler(app.Loop, socket.AF_INET, socket.SOCK_STREAM, ( + url.hostname if url.hostname is not None else 'localhost', + url.port if url.port is not None else logging.handlers.SYSLOG_UDP_PORT + )) + + elif url.scheme == 'udp': + self.SyslogHandler = AsyncIOHandler(app.Loop, socket.AF_INET, socket.SOCK_DGRAM, ( + url.hostname if url.hostname is not None else 'localhost', + url.port if url.port is not None else logging.handlers.SYSLOG_UDP_PORT + )) + + elif url.scheme == 'unix-connect': + self.SyslogHandler = AsyncIOHandler(app.Loop, socket.AF_UNIX, socket.SOCK_STREAM, url.path) + + elif url.scheme == 'unix-sendto': + self.SyslogHandler = AsyncIOHandler(app.Loop, socket.AF_UNIX, socket.SOCK_DGRAM, url.path) + + else: + self.RootLogger.warning("Invalid logging:syslog address '{}'".format(address)) + address = None + + if self.SyslogHandler is not None: + self.SyslogHandler.setLevel(logging.DEBUG) + format = Config["logging:syslog"]["format"] + if format == 'm': + self.SyslogHandler.setFormatter(MacOSXSyslogFormatter(sd_id=Config["logging"]["sd_id"])) + elif format == '5': + self.SyslogHandler.setFormatter(SyslogRFC5424Formatter(sd_id=Config["logging"]["sd_id"])) + else: + self.SyslogHandler.setFormatter(SyslogRFC3164Formatter(sd_id=Config["logging"]["sd_id"])) + self.RootLogger.addHandler(self.SyslogHandler) + + # No logging is configured + if self.ConsoleHandler is None and self.FileHandler is None and self.SyslogHandler is None: + # Let's check if we run in Docker and if so, then log on stderr + if running_in_container(): + self._configure_console_logging() + + else: + self.RootLogger.warning("Logging seems to be already configured. Proceed with caution.") + + if Config["logging"].getboolean("verbose"): + self.RootLogger.setLevel(logging.DEBUG) + else: + self.RootLogger.setLevel(Config["logging"]["level"]) + + # Fine-grained log level configurations + levels = Config["logging"].get('levels') + for levelconf in levels.split('\n'): + levelconf = levelconf.strip() + if len(levelconf) == 0 or levelconf.startswith('#') or levelconf.startswith(';'): + continue + loggername, levelname = levelconf.split(' ', 1) + level = logging.getLevelName(levelname.upper()) + logging.getLogger(loggername).setLevel(level) + + +
[docs] def rotate(self): + if self.FileHandler is not None: + self.RootLogger.log(LOG_NOTICE, "Rotating logs") + self.FileHandler.doRollover()
+ + + async def _on_tick_rotate_check(self): + if self.FileHandler is not None: + if self.FileHandler.stream.tell() > 1000: + self.rotate() + + + def _configure_console_logging(self): + self.ConsoleHandler = logging.StreamHandler(stream=sys.stderr) + + # Disable colors when running in container + if running_in_container(): + self.ConsoleHandler.setFormatter(StructuredDataFormatter( + fmt=Config["logging:console"]["format"], + datefmt=Config["logging:console"]["datefmt"], + sd_id=Config["logging"]["sd_id"], + use_color=False + )) + else: + self.ConsoleHandler.setFormatter(StructuredDataFormatter( + fmt=Config["logging:console"]["format"], + datefmt=Config["logging:console"]["datefmt"], + sd_id=Config["logging"]["sd_id"], + use_color=True + )) + + self.ConsoleHandler.setLevel(logging.DEBUG) + self.RootLogger.addHandler(self.ConsoleHandler)
+ + +class _StructuredDataLogger(logging.Logger): + ''' +This class extends a default python logger class, specifically by adding ``struct_data`` parameter to logging functions. +It means that you can use expressions such as ``logger.info("Hello world!", struct_data={'key':'value'})``. + ''' + + def _log(self, level, msg, args, exc_info=None, struct_data=None, extra=None, stack_info=False): + if struct_data is not None: + if extra is None: + extra = dict() + extra['_struct_data'] = struct_data + + super()._log(level, msg, args, exc_info=exc_info, extra=extra, stack_info=stack_info) + + +logging.setLoggerClass(_StructuredDataLogger) + + +
[docs]class StructuredDataFormatter(logging.Formatter): + ''' + The logging formatter that renders log messages that includes structured data. + ''' + + empty_sd = "" + BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) + + + def __init__(self, facility=16, fmt=None, datefmt=None, style='%', sd_id='sd', use_color: bool = False): + super().__init__(fmt, datefmt, style) + self.SD_id = sd_id + self.Facility = facility + self.UseColor = use_color + + +
[docs] def format(self, record): + ''' + Format the specified record as text. + ''' + + record.struct_data = self.render_struct_data(record.__dict__.get("_struct_data")) + + # The Priority value is calculated by first multiplying the Facility number by 8 and then adding the numerical value of the Severity. + if record.levelno <= logging.DEBUG: + severity = 7 # Debug + color = self.BLUE + elif record.levelno <= logging.INFO: + severity = 6 # Informational + color = self.GREEN + elif record.levelno <= LOG_NOTICE: + severity = 5 # Notice + color = self.CYAN + elif record.levelno <= logging.WARNING: + severity = 4 # Warning + color = self.YELLOW + elif record.levelno <= logging.ERROR: + severity = 3 # Error + color = self.RED + elif record.levelno <= logging.CRITICAL: + severity = 2 # Critical + color = self.MAGENTA + else: + severity = 1 # Alert + color = self.WHITE + + if self.UseColor: + levelname = record.levelname + levelname_color = _COLOR_SEQ % (30 + color) + levelname + _RESET_SEQ + record.levelname = levelname_color + + record.priority = (self.Facility << 3) + severity + return super().format(record)
+ + +
[docs] def formatTime(self, record, datefmt=None): + ''' + Return the creation time of the specified LogRecord as formatted text. + ''' + + try: + ct = datetime.datetime.fromtimestamp(record.created) + if datefmt is not None: + s = ct.strftime(datefmt) + else: + t = ct.strftime("%Y-%m-%d %H:%M:%S") + s = "%s.%03d" % (t, record.msecs) + return s + except BaseException as e: + print("ERROR when logging: {}".format(e), file=sys.stderr) + return str(ct)
+ + +
[docs] def render_struct_data(self, struct_data): + ''' + Return the string with structured data. + ''' + + if struct_data is None: + return self.empty_sd + + else: + return "[{sd_id} {sd_params}] ".format( + sd_id=self.SD_id, + sd_params=" ".join(['{}="{}"'.format(key, val) for key, val in struct_data.items()]))
+ + + +def _loop_exception_handler(loop, context): + ''' + This is an logging exception handler for asyncio. + It's purpose is to nicely log any unhandled excpetion that arises in the asyncio tasks. + ''' + + exception = context.pop('exception', None) + + message = context.pop('message', '') + if len(message) > 0: + message += '\n' + + if len(context) > 0: + message += pprint.pformat(context) + + if exception is not None: + ex_traceback = exception.__traceback__ + tb_lines = [line.rstrip('\n') for line in traceback.format_exception(exception.__class__, exception, ex_traceback)] + message += '\n' + '\n'.join(tb_lines) + + logging.getLogger().error(message) + + +
[docs]class MacOSXSyslogFormatter(StructuredDataFormatter): + """ + It implements Syslog formatting for Mac OSX syslog (aka format ``m``). + """ + + def __init__(self, fmt=None, datefmt=None, style='%', sd_id='sd'): + fmt = '<%(priority)s>%(asctime)s {app_name}[{proc_id}]: %(levelname)s %(name)s %(struct_data)s%(message)s\000'.format( + app_name=Config["logging"]["app_name"], + proc_id=os.getpid(), + ) + + # Initialize formatter + super().__init__(fmt=fmt, datefmt='%b %d %H:%M:%S', style=style, sd_id=sd_id)
+ + +
[docs]class SyslogRFC3164Formatter(StructuredDataFormatter): + """ + Implementation of a legacy or BSD Syslog (RFC 3164) formatting (aka format ``3``). + """ + + def __init__(self, fmt=None, datefmt=None, style='%', sd_id='sd'): + fmt = '<%(priority)s>%(asctime)s {hostname} {app_name}[{proc_id}]:%(levelname)s %(name)s %(struct_data)s%(message)s\000'.format( + app_name=Config["logging"]["app_name"], + hostname=socket.gethostname(), + proc_id=os.getpid(), + ) + + # Initialize formatter + super().__init__(fmt=fmt, datefmt='%b %d %H:%M:%S', style=style, sd_id=sd_id)
+ + +
[docs]class SyslogRFC5424Formatter(StructuredDataFormatter): + """ + It implements Syslog formatting for Mac OSX syslog (aka format ``5``). + """ + + empty_sd = " " + + def __init__(self, fmt=None, datefmt=None, style='%', sd_id='sd'): + fmt = '<%(priority)s>1 %(asctime)s.%(msecs)dZ {hostname} {app_name} {proc_id} %(name)s [log l="%(levelname)s"]%(struct_data)s%(message)s'.format( + app_name=Config["logging"]["app_name"], + hostname=socket.gethostname(), + proc_id=os.getpid(), + ) + + # Initialize formatter + super().__init__(fmt=fmt, datefmt='%Y-%m-%dT%H:%M:%S', style=style, sd_id=sd_id) + + # Convert time to GMT + self.converter = time.gmtime
+ + +
[docs]class AsyncIOHandler(logging.Handler): + + ''' +A logging handler similar to a standard ``logging.handlers.SocketHandler`` that utilizes ``asyncio``. +It implements a queue for decoupling logging from a networking. The networking is fully event-driven via ``asyncio`` mechanisms. + ''' + + def __init__(self, loop, family, sock_type, address, facility=logging.handlers.SysLogHandler.LOG_LOCAL1): + logging.Handler.__init__(self) + + self._family = family + self._type = sock_type + self._address = address + self._loop = loop + + self._socket = None + self._reset() + + self._queue = queue.Queue() + + self._loop.call_soon(self._connect, self._loop) + + + def _reset(self): + self._write_ready = False + if self._socket is not None: + self._loop.remove_writer(self._socket) + self._loop.remove_reader(self._socket) + self._socket.close() + self._socket = None + + + def _connect(self, loop): + self._reset() + + try: + self._socket = socket.socket(self._family, self._type) + self._socket.setblocking(0) + self._socket.connect(self._address) + except Exception as e: + print("Error when opening syslog connection to '{}'".format(self._address), e, file=sys.stderr) + return + + self._loop.add_writer(self._socket, self._on_write) + self._loop.add_reader(self._socket, self._on_read) + + + def _on_write(self): + self._write_ready = True + self._loop.remove_writer(self._socket) + + while not self._queue.empty(): + # TODO: Handle eventual error in writing -> break the cycle and restart on write handler + msg = self._queue.get_nowait() + self._socket.sendall(msg) + + + def _on_read(self): + try: + _ = self._socket.recvfrom(1024) + # We receive "something" ... let's ignore that! + return + except Exception as e: + print("Error on the syslog socket '{}'".format(self._address), e, file=sys.stderr) + + # Close a socket - there is no reason for reading or socket is actually closed + self._reset() + + +
[docs] def emit(self, record): + ''' + This is the entry point for log entries. + ''' + try: + msg = self.format(record).encode('utf-8') + + if self._write_ready: + try: + self._socket.sendall(msg) + except Exception as e: + print("Error when writing to syslog '{}'".format(self._address), e, file=sys.stderr) + self._enqueue(msg) + + else: + self._enqueue(record) + + + except Exception as e: + print("Error when emit to syslog '{}'".format(self._address), e, file=sys.stderr) + self.handleError(record)
+ + + def _enqueue(self, record): + self._queue.put(record)
+ + +_RESET_SEQ = "\033[0m" +_COLOR_SEQ = "\033[1;%dm" +_BOLD_SEQ = "\033[1m" +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/metrics/metrics.html b/old_docs/_build/html/_modules/asab/metrics/metrics.html new file mode 100644 index 000000000..2bf3c0a0b --- /dev/null +++ b/old_docs/_build/html/_modules/asab/metrics/metrics.html @@ -0,0 +1,688 @@ + + + + + + + + asab.metrics.metrics — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.metrics.metrics

+import abc
+import copy
+import time
+from .. import Config
+
+
+class Metric(abc.ABC):
+
+	def __init__(self, init_values=None):
+		self.Init = init_values
+		self.Storage = None
+		self.StaticTags = dict()
+
+		# Expiration is relevant only to WithDynamicTagsMixIn metrics
+		self.Expiration = float(Config.get("asab:metrics", "expiration"))
+
+	def _initialize_storage(self, storage: dict):
+		assert storage['type'] is None
+		storage['type'] = self.__class__.__name__
+
+		self.Storage = storage
+		self.add_field(self.StaticTags)
+
+	def add_field(self, tags):
+		raise NotImplementedError(":-(")
+
+	def flush(self, now):
+		pass
+
+
+
[docs]class Gauge(Metric): + + def add_field(self, tags): + field = { + "tags": tags, + "values": self.Init.copy() if self.Init is not None else dict(), + "measured_at": self.App.time() + } + self.Storage['fieldset'].append(field) + self._field = field + return field + +
[docs] def set(self, name: str, value): + self._field['values'][name] = value + self._field['measured_at'] = self.App.time()
+ + +
[docs]class Counter(Metric): + + def add_field(self, tags): + field = { + "tags": tags, + "values": self.Init.copy() if self.Init is not None else dict(), + "actuals": self.Init.copy() if self.Init is not None else dict(), + "measured_at": self.App.time() + } + self.Storage['fieldset'].append(field) + self._actuals = field['actuals'] + self._field = field + return field + +
[docs] def add(self, name, value, init_value=None): + """ + :param name: name of the counter + :param value: value to be added to the counter + + Adds the `value` to the counter Values specified by `name`. + If `name` is not in Counter Values, it will be added. + + """ + try: + self._actuals[name] += value + except KeyError: + if init_value is not None: + self._actuals[name] = init_value + value + else: + self._actuals[name] = value + if not self.Storage.get("reset"): + self._field['measured_at'] = self.App.time()
+ +
[docs] def sub(self, name, value, init_value=None): + """ + :param name: name of the counter + :param value: value to be subtracted from the counter + + Subtracts the `value` from the counter Values specified by `name`. + If `name` is not in Counter Values, it will be added. + + """ + try: + self._actuals[name] -= value + except KeyError: + if init_value is not None: + self._actuals[name] = init_value - value + else: + self._actuals[name] = -value + if not self.Storage.get("reset"): + self._field['measured_at'] = self.App.time()
+ + def flush(self, now): + if self.Storage.get("reset") is True: + self._field['measured_at'] = now + for field in self.Storage['fieldset']: + field['values'] = field['actuals'] + if self.Init is not None: + field['actuals'] = self.Init.copy() + else: + field['actuals'] = dict() + self._actuals = field['actuals'] + else: + for field in self.Storage['fieldset']: + field['values'] = field['actuals'].copy()
+ + +
[docs]class EPSCounter(Counter): + """ + Event per Second Counter + Divides the count of event by a time difference between measurements. + It effectively produces the EPS metric. + The type of the metric is an integer (int). + """ + + def __init__(self, init_values=None): + if init_values is not None: + init_values = {k: int(v) for k, v in init_values.items()} + super().__init__(init_values=init_values) + self.LastTime = time.time() + + def flush(self, now): + self._field['measured_at'] = now + + delta = now - self.LastTime + if delta <= 0.0: + return + + reset = self.Storage.get("reset") + + for field in self.Storage['fieldset']: + field['values'] = { + k: int(v / delta) + for k, v in self._actuals.items() + } + + if reset is True: + if self.Init is not None: + field['actuals'] = self.Init.copy() + else: + field['actuals'] = dict() + self._actuals = field["actuals"] + + self.LastTime = now
+ + +
[docs]class DutyCycle(Metric): + ''' + https://en.wikipedia.org/wiki/Duty_cycle + + now = self.App.time() + d = now - self.LastReadyStateSwitch + self.LastReadyStateSwitch = now + ''' + + + def __init__(self, app, init_values=None): + super().__init__() + self.App = app + now = self.App.time() + self.EmptyValue = { + "on_off": None, + "timestamp": now, + "off_cycle": 0.0, + "on_cycle": 0.0 + } + + self.Init = dict() + + if init_values is not None: + for k, v in init_values.items(): + value = self.EmptyValue.copy() + value["on_off"] = v + self.Init[k] = value + + def add_field(self, tags): + field = { + "tags": tags, + "actuals": self.Init.copy(), + "values": dict(), + "measured_at": self.App.time() + } + self.Storage['fieldset'].append(field) + self._field = field + return field + + + def set(self, name, on_off: bool): + now = self.App.time() + values = self._field["actuals"].get(name) + if values is None: + value = self.EmptyValue.copy() + value["on_off"] = on_off + value["timestamp"] = now + self._field["actuals"][name] = value + return + + if values.get("on_off") == on_off: + return # No change + + d = now - values.get("timestamp") + off_cycle = values.get("off_cycle") + on_cycle = values.get("on_cycle") + if on_off: + # From off to on + off_cycle += d + else: + # From on to off + on_cycle += d + + values["on_off"] = on_off + values["timestamp"] = now + values["off_cycle"] = off_cycle + values["on_cycle"] = on_cycle + + + def flush(self, now): + self._field['measured_at'] = now + for field in self.Storage["fieldset"]: + actuals = field.get("actuals") + for v_name, values in actuals.items(): + d = now - values.get("timestamp") + off_cycle = values.get("off_cycle") + on_cycle = values.get("on_cycle") + if values.get("on_off"): + on_cycle += d + else: + off_cycle += d + + full_cycle = on_cycle + off_cycle + if full_cycle > 0.0: + field["values"][v_name] = on_cycle / full_cycle + + new_value = self.EmptyValue.copy() + new_value["on_off"] = values.get("on_off") + new_value["timestamp"] = now + + field["actuals"][v_name] = new_value
+ + +
[docs]class AggregationCounter(Counter): + ''' + Sets value aggregated with the last one. + Takes a function object as the `aggregator` argument. + The aggregation function can take two arguments only. + Maximum is used as a default aggregation function. + ''' + def __init__(self, init_values=None, aggregator=max): + super().__init__(init_values=init_values) + self.Aggregator = aggregator + +
[docs] def set(self, name, value): + if not self.Storage.get("reset"): + self._field['measured_at'] = self.App.time() + try: + self._actuals[name] = self.Aggregator(value, self._actuals[name]) + except KeyError: + self._actuals[name] = value
+ + def add(self, name, value): + raise NotImplementedError("Do not use add() method with AggregationCounter. Use set() instead.") + + def sub(self, name, value): + raise NotImplementedError("Do not use sub() method with AggregationCounter. Use set() instead.")
+ + +
[docs]class Histogram(Metric): + """ + Creates cumulative histograms. + """ + def __init__(self, buckets: list, init_values=None): + super().__init__(init_values) + _buckets = [float(b) for b in buckets] + + if _buckets != sorted(buckets): + raise ValueError("Buckets not in sorted order") + + if _buckets and _buckets[-1] != float("inf"): + _buckets.append(float("inf")) + + if len(_buckets) < 2: + raise ValueError("Must have at least two buckets") + + self.InitBuckets = {b: dict() for b in _buckets} + self.Count = 0 + self.Sum = 0.0 + self.InitHistogram = { + "buckets": self.InitBuckets, + "sum": 0.0, + "count": 0 + } + + if self.Init: + for value_name, value in self.Init.items(): + for upper_bound in self.InitHistogram["buckets"]: + if value <= upper_bound: + self.InitHistogram["buckets"][upper_bound][value_name] = 1 + self.InitHistogram["sum"] += value + self.InitHistogram["count"] += 1 + + def add_field(self, tags): + field = { + "tags": tags, + "values": copy.deepcopy(self.InitHistogram), + "actuals": copy.deepcopy(self.InitHistogram), + "measured_at": self.App.time() + } + self.Storage['fieldset'].append(field) + self._actuals = field['actuals'] + self._field = field + return field + + def flush(self, now): + if self.Storage.get("reset") is True: + self._field['measured_at'] = now + for field in self.Storage['fieldset']: + field['values'] = field['actuals'] + field['actuals'] = copy.deepcopy(self.InitHistogram) + self._actuals = field['actuals'] + else: + for field in self.Storage['fieldset']: + field['values'] = copy.deepcopy(field['actuals']) + +
[docs] def set(self, value_name, value): + if not self.Storage.get("reset"): + self._field['measured_at'] = self.App.time() + buckets = self._actuals["buckets"] + summary = self._actuals["sum"] + count = self._actuals["count"] + for upper_bound in buckets: + if value <= upper_bound: + if buckets[upper_bound].get(value_name) is None: + buckets[upper_bound][value_name] = 1 + else: + buckets[upper_bound][value_name] += 1 + self._actuals["sum"] = summary + value + self._actuals["count"] = count + 1
+ +### + + +class MetricWithDynamicTags(Metric): + + + def _initialize_storage(self, storage: dict): + storage.update({ + 'type': self.__class__.__name__, + }) + self.Storage = storage + if self.Init is not None: + self.add_field(self.StaticTags.copy()) + + + def locate_field(self, tags): + fieldset = self.Storage['fieldset'] + + tags = tags.copy() + tags.update(self.StaticTags) + + # Seek for field in the fieldset using tags + for field in fieldset: + if field['tags'] == tags: + return field + + # Field not found, create a new one + field = self.add_field(tags) + return field + + + +
[docs]class CounterWithDynamicTags(MetricWithDynamicTags): + + + def add_field(self, tags): + field = { + "tags": tags, + "values": self.Init.copy() if self.Init is not None else dict(), + "actuals": self.Init.copy() if self.Init is not None else dict(), + "expires_at": self.App.time() + self.Expiration, + "measured_at": self.App.time() + } + self.Storage['fieldset'].append(field) + return field + +
[docs] def add(self, name, value, tags): + """ + :param name: name of the counter + :param value: value to be added to the counter + + Adds the `value` to the counter Values specified by `name`. + If name is not in Counter Values, it will be added there. + """ + + field = self.locate_field(tags) + actuals = field['actuals'] + try: + actuals[name] += value + except KeyError: + actuals[name] = value + + if self.Storage.get("reset") is False: + field['measured_at'] = self.App.time() + + field["expires_at"] = self.App.time() + self.Expiration
+ +
[docs] def sub(self, name, value, tags): + """ + :param name: name of the counter + :param value: value to be subtracted from the counter + + Subtracts the `value` from the counter Values specified by `name`. + If name is not in Counter Values, it will be added there. + """ + + field = self.locate_field(tags) + actuals = field['actuals'] + try: + actuals[name] -= value + except KeyError: + actuals[name] = -value + + if self.Storage.get("reset") is False: + field['measured_at'] = self.App.time() + + field["expires_at"] = self.App.time() + self.Expiration
+ + def flush(self, now): + # Filter expired fields + for field in self.Storage["fieldset"][::-1]: + if field["expires_at"] < now: + self.Storage["fieldset"].remove(field) + + if self.Storage.get("reset") is True: + for field in self.Storage['fieldset']: + field['values'] = field['actuals'] + if self.Init is not None: + field['actuals'] = self.Init.copy() + else: + field['actuals'] = dict() + field['measured_at'] = self.App.time() + else: + for field in self.Storage['fieldset']: + field['values'] = field['actuals'].copy()
+ + +
[docs]class AggregationCounterWithDynamicTags(CounterWithDynamicTags): + + + def __init__(self, init_values=None, aggregator=max): + super().__init__(init_values=init_values) + self.Aggregator = aggregator + +
[docs] def set(self, name, value, tags): + field = self.locate_field(tags) + actuals = field['actuals'] + try: + actuals[name] = self.Aggregator(value, actuals[name]) + except KeyError: + actuals[name] = value + + if self.Storage.get("reset") is False: + field['measured_at'] = self.App.time() + + field["expires_at"] = self.App.time() + self.Expiration
+ + def add(self, name, value, tags): + raise NotImplementedError("Do not use add() method with AggregationCounter. Use set() instead.") + + def sub(self, name, value, tags): + raise NotImplementedError("Do not use sub() method with AggregationCounter. Use set() instead.")
+ + +
[docs]class HistogramWithDynamicTags(MetricWithDynamicTags): + """ + Creates cumulative histograms with dynamic tags + """ + + def __init__(self, buckets: list, init_values=None): + super().__init__(init_values) + _buckets = [float(b) for b in buckets] + + if _buckets != sorted(buckets): + raise ValueError("Buckets not in sorted order") + + if _buckets and _buckets[-1] != float("inf"): + _buckets.append(float("inf")) + + if len(_buckets) < 2: + raise ValueError("Must have at least two buckets") + + self.InitBuckets = {b: dict() for b in _buckets} + self.Count = 0 + self.Sum = 0.0 + self.InitHistogram = { + "buckets": self.InitBuckets, + "sum": 0.0, + "count": 0 + } + + if self.Init: + for value_name, value in self.Init.items(): + for upper_bound in self.InitHistogram["buckets"]: + if value <= upper_bound: + self.InitHistogram["buckets"][upper_bound][value_name] = 1 + self.InitHistogram["sum"] += value + self.InitHistogram["count"] += 1 + + def add_field(self, tags): + field = { + "tags": tags, + "values": copy.deepcopy(self.InitHistogram), + "actuals": copy.deepcopy(self.InitHistogram), + "expires_at": self.App.time() + self.Expiration, + "measured_at": self.App.time() + } + self.Storage['fieldset'].append(field) + return field + + def flush(self, now): + # Filter expired fields + for field in self.Storage["fieldset"][::-1]: + if field["expires_at"] < now: + self.Storage["fieldset"].remove(field) + + if self.Storage.get("reset") is True: + for field in self.Storage['fieldset']: + field['values'] = field['actuals'] + field['actuals'] = copy.deepcopy(self.InitHistogram) + field['measured_at'] = self.App.time() + else: + for field in self.Storage['fieldset']: + field['values'] = copy.deepcopy(field['actuals']) + +
[docs] def set(self, value_name, value, tags): + field = self.locate_field(tags) + buckets = field.get("actuals").get("buckets") + summary = field.get("actuals").get("sum") + count = field.get("actuals").get("count") + for upper_bound in buckets: + if value <= upper_bound: + if buckets[upper_bound].get(value_name) is None: + buckets[upper_bound][value_name] = 1 + else: + buckets[upper_bound][value_name] += 1 + field.get("actuals")["sum"] = summary + value + field.get("actuals")["count"] = count + 1 + + if self.Storage.get("reset") is False: + field['measured_at'] = self.App.time() + + field["expires_at"] = self.App.time() + self.Expiration
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/metrics/service.html b/old_docs/_build/html/_modules/asab/metrics/service.html new file mode 100644 index 000000000..6e28fe63e --- /dev/null +++ b/old_docs/_build/html/_modules/asab/metrics/service.html @@ -0,0 +1,299 @@ + + + + + + + + asab.metrics.service — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.metrics.service

+import configparser
+import logging
+import asyncio
+import os
+
+from ..config import Config
+from ..abc import Service
+from .metrics import (
+	Metric, Counter, EPSCounter, Gauge, DutyCycle, AggregationCounter, Histogram,
+	CounterWithDynamicTags, AggregationCounterWithDynamicTags, HistogramWithDynamicTags
+)
+from .storage import Storage
+
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+
[docs]class MetricsService(Service): + + def __init__(self, app, service_name): + + super().__init__(app, service_name) + + self.Metrics = [] + self.Targets = [] + self.Tags = { + "host": app.HostName, + "appclass": app.__class__.__name__, + } + + # A identified of the host machine (node); added if available at environment variables + node_id = os.getenv('NODE_ID', None) + if node_id is not None: + self.Tags["node_id"] = node_id + + service_id = os.getenv('SERVICE_ID', None) + if service_id is not None: + self.Tags["service_id"] = service_id + + # A unique identifier of a microservice; added as an environment variable. + instance_id = os.getenv('INSTANCE_ID', None) + if instance_id is not None: + self.Tags["instance_id"] = instance_id + + self.Storage = Storage() + + app.PubSub.subscribe("Application.tick/60!", self._on_flushing_event) + + if Config.has_option('asab:metrics', 'target'): + for target in Config.get('asab:metrics', 'target').split(): + target = target.strip() + try: + target_type = Config.get('asab:metrics:{}'.format(target), 'type') + except configparser.NoOptionError: + # This allows to specify the type of the target by its name + target_type = target + + if target_type == 'influxdb': + from .influxdb import InfluxDBTarget + target = InfluxDBTarget(self, 'asab:metrics:{}'.format(target)) + + elif target_type == 'http': + from .http import HTTPTarget + target = HTTPTarget(self, 'asab:metrics:{}'.format(target)) + + else: + raise RuntimeError("Unknown target type {}".format(target_type)) + + self.Targets.append(target) + + if Config.getboolean('asab:metrics', 'native_metrics'): + from .native import NativeMetrics + self._native_svc = NativeMetrics(self.App, self) + + + async def finalize(self, app): + await self._on_flushing_event("finalize!") + + + def clear(self): + self.Metrics.clear() + self.Storage.clear() + + def _flush_metrics(self): + now = self.App.time() + + self.App.PubSub.publish("Metrics.flush!") + for metric in self.Metrics: + try: + metric.flush(now) + except Exception: + L.exception("Exception during metric.flush()") + + return now + + async def _on_flushing_event(self, event_type): + if len(self.Metrics) == 0: + return + + now = self._flush_metrics() + + pending = set() + for target in self.Targets: + pending.add( + asyncio.ensure_future(target.process(self.Storage.Metrics, now)) + ) + + while len(pending) > 0: + done, pending = await asyncio.wait(pending, timeout=180.0, return_when=asyncio.ALL_COMPLETED) + + + def _add_metric(self, metric: Metric, metric_name: str, tags=None, reset=None, help=None, unit=None): + # Add global tags + metric.StaticTags.update(self.Tags) + metric.App = self.App + + # Add local static tags + if tags is not None: + metric.StaticTags.update(tags) + + + metric._initialize_storage( + self.Storage.add(metric_name, tags=metric.StaticTags.copy(), reset=reset, help=help, unit=unit) + ) + + self.Metrics.append(metric) + +
[docs] def create_gauge(self, metric_name, tags=None, init_values=None, help=None, unit=None): + m = Gauge(init_values=init_values) + self._add_metric(m, metric_name, tags=tags, help=help, unit=unit) + return m
+ +
[docs] def create_counter(self, metric_name, tags=None, init_values=None, reset: bool = True, help=None, unit=None, dynamic_tags=False): + if dynamic_tags: + m = CounterWithDynamicTags(init_values=init_values) + else: + m = Counter(init_values=init_values) + self._add_metric(m, metric_name, tags=tags, reset=reset, help=help, unit=unit) + return m
+ +
[docs] def create_eps_counter(self, metric_name, tags=None, init_values=None, reset: bool = True, help=None, unit=None): + m = EPSCounter(init_values=init_values) + self._add_metric(m, metric_name, tags=tags, reset=reset, help=help, unit=unit) + return m
+ +
[docs] def create_duty_cycle(self, metric_name, tags=None, init_values=None, help=None, unit=None): + m = DutyCycle(self.App, init_values=init_values) + self._add_metric(m, metric_name, tags=tags, help=help, unit=unit) + return m
+ +
[docs] def create_aggregation_counter(self, metric_name, tags=None, init_values=None, reset: bool = True, aggregator=max, help=None, unit=None, dynamic_tags=False): + if dynamic_tags: + m = AggregationCounterWithDynamicTags(init_values=init_values, aggregator=aggregator) + else: + m = AggregationCounter(init_values=init_values, aggregator=aggregator) + self._add_metric(m, metric_name, tags=tags, reset=reset, help=help, unit=unit) + return m
+ +
[docs] def create_histogram(self, metric_name, buckets: list, tags=None, init_values=None, reset: bool = True, help=None, unit=None, dynamic_tags=False): + if dynamic_tags: + m = HistogramWithDynamicTags(buckets=buckets, init_values=init_values) + else: + m = Histogram(buckets=buckets, init_values=init_values) + self._add_metric(m, metric_name, tags=tags, reset=reset, help=help, unit=unit) + return m
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/pdict.html b/old_docs/_build/html/_modules/asab/pdict.html new file mode 100644 index 000000000..b462ba710 --- /dev/null +++ b/old_docs/_build/html/_modules/asab/pdict.html @@ -0,0 +1,199 @@ + + + + + + + + asab.pdict — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.pdict

+import collections
+import os
+import shelve
+
+
+
[docs]class PersistentDict(dict): + + """ + The persistent dictionary works as the regular Python dictionary but the content of the dictionary is stored in the file. + You cat think of a ``PersistentDict`` as a simple `key-value store <https://en.wikipedia.org/wiki/Key-value_database>`_. + It is not optimized for a frequent access. This class provides common ``dict`` interface. + + *Warning*: You must explicitly `load()` and `store()` content of the dictionary + *Warning*: You can only store objects in the persistent dictionary that are serializable. + """ + + def __init__(self, path): + super().__init__() + # Create directory, if needed + dirname = os.path.dirname(path) + if not os.path.isdir(dirname): + os.makedirs(dirname) + + self._path = path + + def __delitem__(self, key): + super().__delitem__(key) + with shelve.open(self._path) as d: + del d[key] + +
[docs] def load(self) -> None: + """ + Load content of file as dictionary. + """ + with shelve.open(self._path) as d: + for key, value in d.items(): + self[key] = value
+ +
[docs] def store(self) -> None: + """ + Explicitly store content of persistent dictionary to file + """ + + with shelve.open(self._path) as d: + for key, value in self.items(): + d[key] = value
+ +
[docs] def update(self, other=(), **kwds) -> None: + """ + Update D from mapping/iterable E and F. + * If E present and has a .keys() method, does: for k in E: D[k] = E[k] + * If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v + * In either case, this is followed by: for k, v in F.items(): D[k] = v + + Inspired by a https://github.com/python/cpython/blob/3.8/Lib/_collections_abc.py + """ + + if isinstance(other, collections.Mapping): + for key in other: + self[key] = other[key] + elif hasattr(other, "keys"): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + + for key, value in kwds.items(): + self[key] = value
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/pubsub.html b/old_docs/_build/html/_modules/asab/pubsub.html new file mode 100644 index 000000000..785ad671b --- /dev/null +++ b/old_docs/_build/html/_modules/asab/pubsub.html @@ -0,0 +1,386 @@ + + + + + + + + asab.pubsub — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.pubsub

+import logging
+import asyncio
+import weakref
+import functools
+
+
+L = logging.getLogger(__name__)
+
+
+
[docs]class PubSub(object): + + + def __init__(self, app): + self.Subscribers = {} + self.Loop = app.Loop + + +
[docs] def subscribe(self, message_type, callback): + """ + Subscribe a subscriber to the an message type. + It could be even plain function, method or its coroutine variant (then it will be delivered in a dedicated future) + """ + + # If subscribe is a bound method, do special treatment + # https://stackoverflow.com/questions/53225/how-do-you-check-whether-a-python-method-is-bound-or-not + if hasattr(callback, '__self__'): + callback = weakref.WeakMethod(callback) + else: + callback = weakref.ref(callback) + + if message_type not in self.Subscribers: + self.Subscribers[message_type] = [callback] + else: + self.Subscribers[message_type].append(callback)
+ + +
[docs] def subscribe_all(self, obj): + """ + Find all @asab.subscribe decorated methods on the obj and do subscription + """ + for member_name in dir(obj): + member = getattr(obj, member_name) + message_types = getattr(member, 'asab_pubsub_subscribe_to_message_types', None) + if message_types is not None: + for message_type in message_types: + self.subscribe(message_type, member)
+ + +
[docs] def unsubscribe(self, message_type, callback): + """ Remove a subscriber of an message type from the set. """ + + callback_list = self.Subscribers.get(message_type) + if callback_list is None: + L.warning("Message type subscription '{}'' not found.".format(message_type)) + return + + remove_list = None + + for i in range(len(callback_list)): + # Take an weakref entry in the callback list and references it + c = callback_list[i]() + + # Check if a weak reference is working + if c is None: # a reference is lost, remove this entry + if remove_list is None: + remove_list = list() + remove_list.append(callback_list[i]) + continue + + if c == callback: + callback_list.pop(i) + break + + else: + L.warning("Subscriber '{}'' not found for the message type '{}'.".format(message_type, callback)) + + if remove_list is not None: + for callback_ref in remove_list: + callback_list.remove(callback_ref) + + if len(callback_list) == 0: + del self.Subscribers[message_type]
+ + + def _callback_iter(self, message_type): + + def _deliver_async(loop, callback, message_type, *args, **kwargs): + asyncio.ensure_future(callback(message_type, *args, **kwargs)) + + callback_list = self.Subscribers.get(message_type) + if callback_list is None: + return + + remove_list = None + + for callback_ref in callback_list: + callback = callback_ref() + + # Check if a weak reference is working + if callback is None: # a reference is lost + if remove_list is None: + remove_list = list() + remove_list.append(callback_ref) + continue + + if asyncio.iscoroutinefunction(callback): + callback = functools.partial(_deliver_async, self.Loop, callback) + + yield callback + + if remove_list is not None: + for callback_ref in remove_list: + callback_list.remove(callback_ref) + + +
[docs] def publish(self, message_type, *args, **kwargs): + """ + Notify subscribers of an `message type`. Including arguments. + """ + + asynchronously = kwargs.pop('asynchronously', False) + + if asynchronously: + for callback in self._callback_iter(message_type): + self.Loop.call_soon(functools.partial(callback, message_type, *args, **kwargs)) + + else: + for callback in self._callback_iter(message_type): + try: + callback(message_type, *args, **kwargs) + except Exception: + L.exception("Error in a PubSub callback", struct_data={'message_type': message_type})
+ + + def publish_threadsafe(self, message_type, *args, **kwargs): + """ + Notify subscribers of an `message type` safely form a different that main thread. + """ + def in_main_thread(): + self.publish(message_type, *args, **kwargs) + self.Loop.call_soon_threadsafe(in_main_thread) + + + async def message(self, message_type): + ''' + This method allows to await a specific message from a coroutine. + It is a convenience method for `Subscriber` object. + + Usage: + ``` + message_type, args, kwargs = await self.PubSub.message("Library.ready!") + ``` + + `message_type`, `args` and `kwargs` are the same as in PubSub callback. + + ''' + subscriber = Subscriber(self, message_type) + message_type, args, kwargs = await subscriber.message() + return message_type, args, kwargs
+ + +class subscribe(object): + + ''' + Decorator + + Usage: + + @asab.subscribe("tick") + def on_tick(self, message_type): + print("Service tick") + ''' + + def __init__(self, message_type): + self.message_type = message_type + + + def __call__(self, f): + if getattr(f, 'asab_pubsub_subscribe_to_message_types', None) is None: + f.asab_pubsub_subscribe_to_message_types = [self.message_type] + else: + f.asab_pubsub_subscribe_to_message_types.append(self.message_type) + return f + + +
[docs]class Subscriber(object): + + ''' +:any:`Subscriber` object allows to consume PubSub messages in coroutines. +It subscribes for various message types and consumes them. +It works on FIFO basis (First message In, first message Out). +If ``pubsub`` argument is None, the initial subscription is skipped. + +.. code:: python + + subscriber = asab.Subscriber( + app.PubSub, + "Application.tick!", + "Application.stop!" + ) + ''' + + def __init__(self, pubsub=None, *message_types): + + self._q = asyncio.Queue() + self._subscriptions = [] + + if pubsub is not None: + for message_type in message_types: + self.subscribe(pubsub, message_type) + + +
[docs] def subscribe(self, pubsub, message_type): + ''' +Subscribe for more message types. This method can be called many times with various ``pubsub`` objects. + ''' + pubsub.subscribe(message_type, self) + self._subscriptions.append((pubsub, message_type))
+ + + def __call__(self, message_type, *args, **kwargs): + self._q.put_nowait((message_type, args, kwargs)) + + +
[docs] def message(self): + ''' +Wait for a message asynchronously. +Returns a three-members tuple ``(message_type, args, kwargs)``. + +Example of the `await message()` use: + +.. code:: python + + async def my_coroutine(app): + # Subscribe for a two application events + subscriber = asab.Subscriber( + app.PubSub, + "Application.tick!", + "Application.exit!" + ) + while True: + message_type, args, kwargs = await subscriber.message() + if message_type == "Application.exit!": + break + print("Tick.") + + ''' + return self._q.get()
+ + + def __aiter__(self): + return self + + + async def __anext__(self): + return await self._q.get()
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/socket.html b/old_docs/_build/html/_modules/asab/socket.html new file mode 100644 index 000000000..2d84ff020 --- /dev/null +++ b/old_docs/_build/html/_modules/asab/socket.html @@ -0,0 +1,171 @@ + + + + + + + + asab.socket — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.socket

+from .abc.service import Service
+
+
+
[docs]class StreamSocketServerService(Service): + + ''' + Example of use: + + class ServiceMyProtocolServer(asab.StreamSocketServerService): + + async def initialize(self, app): + host = asab.Config.get('http', 'host') + port = asab.Config.getint('http', 'port') + + L.debug("Starting server on {} {} ...".format(host, port)) + await self.create_server(app, MyProtocol, [(host, port)]) + ''' + + def __init__(self, app, service_name): + super().__init__(app, service_name) + self._servers = [] + app.PubSub.subscribe("Application.exit!", self._on_exit) + + +
[docs] async def create_server(self, app, protocol, addrs): + # TODO: Parallelize this ... + for addr in addrs: + host, port = addr + server = await app.Loop.create_server(protocol, host, port) + self._servers.append(server)
+ + + def _on_exit(self, message_type): + for server in self._servers: + server.close() + + +
[docs] async def finalize(self, app): + # TODO: Parallelize this ... + for server in self._servers: + await server.wait_closed()
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/storage/elasticsearch.html b/old_docs/_build/html/_modules/asab/storage/elasticsearch.html new file mode 100644 index 000000000..be0fab82d --- /dev/null +++ b/old_docs/_build/html/_modules/asab/storage/elasticsearch.html @@ -0,0 +1,649 @@ + + + + + + + + asab.storage.elasticsearch — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.storage.elasticsearch

+import time
+import json
+import aiohttp
+import logging
+import datetime
+import urllib.parse
+import typing
+
+from .service import StorageServiceABC
+from .upsertor import UpsertorABC
+from ..config import Config
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+Config.add_defaults(
+	{
+		'asab:storage': {
+			# You may specify multiple ElasticSearch nodes by e.g. http://es01:9200,es02:9200,es03:9200/
+			'elasticsearch_url': 'http://localhost:9200/',
+
+			'elasticsearch_username': '',
+			'elasticsearch_password': '',
+
+			# make the operation visible to search directly, options: true, false, wait_for
+			# see: https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html
+			'refresh': 'true',
+			'scroll_timeout': '1m',
+		}
+	}
+)
+
+
+
[docs]class StorageService(StorageServiceABC): + """ + StorageService for Elastic Search. Depends on `aiohttp` library. + """ + + def __init__(self, app, service_name, config_section_name='asab:storage'): + super().__init__(app, service_name) + self.Loop = app.Loop + + self.URL = Config.get(config_section_name, 'elasticsearch_url') + parsed_url = urllib.parse.urlparse(self.URL) + self.ServerUrls = [ + urllib.parse.urlunparse((parsed_url.scheme, netloc, parsed_url.path, None, None, None)) + for netloc in parsed_url.netloc.split(',') + ] + + self.Refresh = Config.get(config_section_name, 'refresh') + self.ScrollTimeout = Config.get(config_section_name, 'scroll_timeout') + + username = Config.get(config_section_name, 'elasticsearch_username') + if username == '': + self._auth = None + else: + password = Config.get(config_section_name, 'elasticsearch_password') + self._auth = aiohttp.BasicAuth(login=username, password=password) + + self._ClientSession = None + + +
[docs] async def finalize(self, app): + """ + Close the current client session. + """ + if self._ClientSession is not None and not self._ClientSession.closed: + await self._ClientSession.close() + self._ClientSession = None
+ + +
[docs] def session(self): + """ + Get the current client session. + """ + if self._ClientSession is None: + self._ClientSession = aiohttp.ClientSession(auth=self._auth) + elif self._ClientSession.closed: + self._ClientSession = aiohttp.ClientSession(auth=self._auth) + return self._ClientSession
+ + + async def get(self, index: str, obj_id: str, decrypt=None) -> dict: + """Get object by its index and object ID. + + Args: + index (str): Index for the query. + obj_id (str): ID of the object. + decrypt (None): Not implemented yet. Defaults to None. + + Raises: + NotImplementedError: Encryption and decryption has not yet been implemented for ECS. + Exception: Connection failed. + + Returns: + dict: The query result. + """ + if decrypt is not None: + raise NotImplementedError("AES encryption for ElasticSearch not implemented") + + for url in self.ServerUrls: + url = "{}{}/_doc/{}".format(url, index, obj_id) + try: + async with self.session().request(method="GET", url=url) as resp: + obj = await resp.json() + ret = obj['_source'] + ret['_v'] = obj['_version'] + ret['_id'] = obj['_id'] + return ret + except aiohttp.client_exceptions.ClientConnectorError: + if url == self.Storage.ServerUrls[-1]: + raise Exception("Failed to connect to '{}'".format(url)) + else: + L.warning("Failed to connect to '{}', iterating to another cluster node".format(url)) + + async def get_by(self, collection: str, key: str, value, decrypt=None): + raise NotImplementedError("get_by") + + async def delete(self, index, _id=None): + for url in self.ServerUrls: + try: + if _id: + url = "{}{}/_doc/{}?refresh={}".format(url, index, _id, self.Refresh) + else: + url = "{}{}".format(url, index) + async with self.session().request(method="DELETE", url=url) as resp: + assert resp.status == 200, "Unexpected response code: {}".format(resp.status) + resp = await resp.json() + + if resp.get("acknowledged", False): + return resp + assert resp["result"] == "deleted", "Document was not deleted" + return resp + except aiohttp.client_exceptions.ClientConnectorError: + if url == self.Storage.ServerUrls[-1]: + raise Exception("Failed to connect to '{}'".format(url)) + else: + L.warning("Failed to connect to '{}', iterating to another cluster node".format(url)) + + +
[docs] async def mapping(self, index: str) -> dict: + """Retrieve mapping definitions for one index. + + :param index: Specified index. + :type index: str + :raise Exception: Connection failed. + + Returns: + dict: Mapping definitions for the index. + """ + for url in self.ServerUrls: + url = "{}{}/_mapping".format(url, index) + try: + async with self.session().request(method="GET", url=url) as resp: + obj = await resp.json() + return obj + except aiohttp.client_exceptions.ClientConnectorError: + if url == self.Storage.ServerUrls[-1]: + raise Exception("Failed to connect to '{}'".format(url)) + else: + L.warning("Failed to connect to '{}', iterating to another cluster node".format(url))
+ +
[docs] async def get_index_template(self, template_name: str) -> dict: + """Retrieve ECS Index template for the given template name. + + :param template_name: The name of the ECS template to retrieve. + :type template_name: str + :raise Exception: Raised if connection to all server URLs fails. + :return: ElasticSearch Index template. + """ + for url in self.ServerUrls: + url = "{}_template/{}?format=json".format(url, template_name) + try: + async with self.session().request(method="GET", url=url, headers={ + 'Content-Type': 'application/json' + }) as resp: + assert resp.status == 200, "Unexpected response code: {}".format(resp.status) + content = await resp.json() + return content + except aiohttp.client_exceptions.ClientConnectorError: + if url == self.Storage.ServerUrls[-1]: + raise Exception("Failed to connect to '{}'".format(url)) + else: + L.warning("Failed to connect to '{}', iterating to another cluster node".format(url))
+ +
[docs] async def put_index_template(self, template_name: str, template: dict) -> dict: + """Create a new ECS index template. + + :param template_name: The name of ECS template. + :param template: Body for the request. + :return: JSON response. + :raise Exception: Raised if connection to all server URLs fails. + """ + for url in self.ServerUrls: + url = "{}_template/{}?include_type_name".format(url, template_name) + L.warning("sending into url: {}".format(url)) + try: + async with self.session().request(method="POST", url=url, data=json.dumps(template), headers={ + 'Content-Type': 'application/json' + }) as resp: + assert resp.status == 200, "Unexpected response code: {}".format(resp.status) + resp = await resp.json() + return resp + except aiohttp.client_exceptions.ClientConnectorError: + if url == self.Storage.ServerUrls[-1]: + raise Exception("Failed to connect to '{}'".format(url)) + else: + L.warning("Failed to connect to '{}', iterating to another cluster node".format(url))
+ + +
[docs] async def reindex(self, previous_index, new_index): + for url in self.ServerUrls: + try: + if url.endswith('/'): + url = "{}_reindex".format(url) + else: + url = "{}/_reindex".format(url) + + async with self.session().request( + method="POST", + url=url, + headers={"Content-Type": "application/json"}, + data=json.dumps({ + "source": { + "index": previous_index, + }, + "dest": { + "index": new_index, + } + }) + ) as resp: + + if resp.status != 200: + raise AssertionError( + "Unexpected response code when reindexing: {}, {}".format( + resp.status, await resp.text() + ) + ) + resp = await resp.json() + return resp + except aiohttp.client_exceptions.ClientConnectorError: + if url == self.Storage.ServerUrls[-1]: + raise Exception("Failed to connect to '{}'".format(url)) + else: + L.warning("Failed to connect to '{}', iterating to another cluster node".format(url))
+ + +
[docs] async def scroll(self, index: str, body: typing.Optional[dict] = None) -> dict: + """Retrieve the next batch of results for a scrolling search. + + :param index: The index name. + :type index: str + :param body: Custom body for the request. Defaults to None. + :type body: dict + :return: JSON response. + :raise Exception: Raised if connection to all server URLs fails. + """ + if body is None: + body = { + "query": {"bool": {"must": {"match_all": {}}}} + } + + scroll_id = None + while True: + for url in self.ServerUrls: + if scroll_id is None: + path = "{}/_search?scroll={}".format( + index, self.ScrollTimeout + ) + request_body = body + else: + path = "_search/scroll" + request_body = { + "scroll": self.ScrollTimeout, + "scroll_id": scroll_id, + } + url = "{}{}".format(url, path) + try: + async with self.session().request( + method="POST", + url=url, + json=request_body, + headers={ + "Content-Type": "application/json" + }, + ) as resp: + if resp.status != 200: + data = await resp.text() + L.error( + "Failed to fetch data from ElasticSearch: {} from {}\n{}".format( + resp.status, url, data + ) + ) + break + response_json = await resp.json() + except aiohttp.client_exceptions.ClientConnectorError: + if url == self.Storage.ServerUrls[-1]: + raise Exception( + "Failed to connect to '{}'".format( + url + ) + ) + else: + L.warning( + "Failed to connect to '{}', iterating to another cluster node".format( + url + ) + ) + + scroll_id = response_json.get("_scroll_id") + if scroll_id is None: + break + return response_json
+ + def upsertor(self, index: str, obj_id=None, version: int = 0): + return ElasicSearchUpsertor(self, index, obj_id, version) + + +
[docs] async def list(self, index: str, _from: int = 0, size: int = 10000, body: dict = None) -> dict: + """List data matching the index. + + :param index: Specified index. + :param _from: Starting document offset. Defaults to 0. + :type _from: int + :param size: The number of hits to return. Defaults to 10000. + :type size: int + :param body: An optional request body. Defaults to None. + :type body: dict + + :return: The query search result. + :raise Exception: Raised if connection to all server URLs fails. + + """ + if body is None: + body = { + 'query': { + 'bool': { + 'must': { + 'match_all': {} + } + } + } + } + for url in self.ServerUrls: + try: + url = "{}{}/_search?size={}&from={}&version=true".format(url, index, size, _from) + async with self.session().request( + method="GET", + url=url, + json=body, + headers={'Content-Type': 'application/json'} + ) as resp: + assert resp.status == 200, "Unexpected response code: {}".format(resp.status) + content = await resp.json() + return content + except aiohttp.client_exceptions.ClientConnectorError: + if url == self.Storage.ServerUrls[-1]: + raise Exception("Failed to connect to '{}'".format(url)) + else: + L.warning("Failed to connect to '{}', iterating to another cluster node".format(url))
+ +
[docs] async def count(self, index) -> int: + """ + Get the number of matches for a given index. + + :param index: The specified index. + :return: The number of matches for a given index. + :raise Exception: Connection failed. + """ + for url in self.ServerUrls: + try: + count_url = "{}{}/_count".format(url, index) + async with self.session().request(method="GET", url=count_url) as resp: + assert resp.status == 200, "Unexpected response code: {}".format(resp.status) + total_count = await resp.json() + return total_count + except aiohttp.client_exceptions.ClientConnectorError: + if url == self.Storage.ServerUrls[-1]: + raise Exception("Failed to connect to '{}'".format(url)) + else: + L.warning("Failed to connect to '{}', iterating to another cluster node".format(url))
+ +
[docs] async def indices(self, search_string=None): + """ + Return high-level information about indices in a cluster, including backing indices for data streams. + + :param search_string: A search string. Default to None. + """ + for url in self.ServerUrls: + try: + url = "{}_cat/indices/{}?format=json".format(url, search_string if search_string is not None else "*") + async with self.session().request(method="GET", url=url) as resp: + assert resp.status == 200, "Unexpected response code: {}".format(resp.status) + return await resp.json() + + except aiohttp.client_exceptions.ClientConnectorError: + if url == self.Storage.ServerUrls[-1]: + raise Exception("Failed to connect to '{}'".format(url)) + else: + L.warning("Failed to connect to '{}', iterating to another cluster node".format(url))
+ + +
[docs] async def empty_index(self, index): + ''' + Create an empty ECS index. + ''' + # TODO: There is an option here to specify settings (e.g. shard number, replica number etc) and mappings here + for url in self.ServerUrls: + try: + url = "{}{}".format(url, index) + async with self.session().request(method="PUT", url=url) as resp: + assert resp.status == 200, "Unexpected response code: {}".format(resp.status) + return await resp.json() + except aiohttp.client_exceptions.ClientConnectorError: + if url == self.Storage.ServerUrls[-1]: + raise Exception("Failed to connect to '{}'".format(url)) + else: + L.warning("Failed to connect to '{}', iterating to another cluster node".format(url))
+ + +class ElasicSearchUpsertor(UpsertorABC): + + def __init__(self, storage, collection, obj_id, version=None): + super().__init__(storage, collection, obj_id, version) + + now = int(time.time()) + + self.ModSet['_m'] = now + + if version == 0: + self.ModSet['_c'] = now # Set the creation timestamp + + + @classmethod + def generate_id(cls): + raise NotImplementedError("generate_id") + + + async def execute(self, custom_data: typing.Optional[dict] = None, event_type: typing.Optional[str] = None): + # TODO: Implement webhook call + if self.ObjId is None: + return await self._insert_noobjid() + else: + return await self._upsert() + + + async def _insert_noobjid(self): + setobj = {} + + if self.Version is None: + self.Version = 0 + + if len(self.ModSet) > 0: + for k, v in self.ModSet.items(): + setobj[k] = serialize(self.ModSet[k]) + + if len(self.ModInc) > 0: + # addobj['$inc'] = self.ModInc + # raise NotImplementedError("yet") + pass + + if len(self.ModPush) > 0: + # addobj['$push'] = {k: {'$each': v} for k, v in self.ModPush.items()} + raise NotImplementedError("yet") + + # This is insert of the new document, the ObjId is to be generated by the ElasicSearch + for url in self.Storage.ServerUrls: + url = "{}{}/_doc?refresh={}".format( + url, self.Collection, self.Storage.Refresh + ) + + try: + async with self.Storage.session().request(method="POST", url=url, json=setobj) as resp: + if resp.status != 201: + raise RuntimeError("Unexpected response code: {}".format(resp.status)) + + resp_json = await resp.json() + self.ObjId = resp_json['_id'] + return self.ObjId + + except aiohttp.client_exceptions.ClientConnectorError: + if url == self.Storage.ServerUrls[-1]: + raise Exception("Failed to connect to '{}'".format(url)) + else: + L.warning("Failed to connect to '{}', iterating to another cluster node".format(url)) + + + async def _upsert(self): + upsertobj = {"doc": {}, "doc_as_upsert": True} + + if len(self.ModSet) > 0: + for k, v in self.ModSet.items(): + upsertobj["doc"][k] = serialize(self.ModSet[k]) + + for url in self.Storage.ServerUrls: + try: + url = "{}{}/_update/{}?refresh={}".format(url, self.Collection, self.ObjId, self.Storage.Refresh) + async with self.Storage.session().request(method="POST", url=url, data=json.dumps(upsertobj), + headers={'Content-Type': 'application/json'}) as resp: + assert resp.status == 200 or resp.status == 201, "Unexpected response code: {}".format(resp.status) + resp_json = await resp.json() + assert resp_json["result"] == "updated" or resp_json[ + "result"] == "created", "Creating/updating was unsuccessful" + return self.ObjId + except aiohttp.client_exceptions.ClientConnectorError: + if url == self.Storage.ServerUrls[-1]: + raise Exception("Failed to connect to '{}'".format(url)) + else: + L.warning("Failed to connect to '{}', iterating to another cluster node".format(url)) + + +def serialize(v): + if isinstance(v, datetime.datetime): + return v.timestamp() + else: + return v +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/storage/inmemory.html b/old_docs/_build/html/_modules/asab/storage/inmemory.html new file mode 100644 index 000000000..3f0101633 --- /dev/null +++ b/old_docs/_build/html/_modules/asab/storage/inmemory.html @@ -0,0 +1,285 @@ + + + + + + + + asab.storage.inmemory — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.storage.inmemory

+import typing
+from .service import StorageServiceABC
+from .upsertor import UpsertorABC
+from .exceptions import DuplicateError
+
+
+class InMemoryUpsertor(UpsertorABC):
+
+	def __init__(self, storage, collection, obj_id, version=None):
+		super().__init__(storage, collection, obj_id, version)
+		if self.ObjId is None:
+			# generate a random unique binary ID
+			self.ObjId = self.generate_id()
+
+	async def execute(self, custom_data: typing.Optional[dict] = None, event_type: typing.Optional[str] = None) -> typing.Union[str, bytes]:
+		"""Commit the changes prepared in upsertor.
+
+		:custom_data (dict, optional): Not implemented yet. Defaults to None.
+		:event_type (str, optional): Not implemented yet. Defaults to None.
+
+		Raises: :RuntimeError: Raised if the object ID was not found in the previous version.
+
+		Returns:
+			:str | bytes: ID of the created or updated document.
+		"""
+
+		# TODO: Implement webhook call
+		id_name = self.get_id_name()
+
+		# Get the object
+		if self.Version == 0:
+			obj = {
+				id_name: self.ObjId
+			}
+			self.Storage._set(self.Collection, self.ObjId, obj)
+
+		else:
+			obj = await self.Storage.get(self.Collection, self.ObjId)
+			if obj is None:
+				if self.Version is None:
+					obj = {
+						id_name: self.ObjId
+					}
+					self.Storage._set(self.Collection, self.ObjId, obj)
+				else:
+					raise RuntimeError("Previous version of '{}' not found".format(self.ObjId))
+
+
+		for k, v in self.ModSet.items():
+			obj[k] = v
+
+		for k, v in self.ModUnset.items():
+			obj.pop(k, None)
+
+		for k, v in self.ModInc.items():
+			o = obj.pop(k, 0)
+			obj[k] = o + v
+
+		for k, v in self.ModPush.items():
+			o = obj.pop(k, None)
+			if o is None:
+				o = list()
+			o.extend(v)
+			obj[k] = o
+
+		for k, v in self.ModPull.items():
+			o = obj.pop(k, None)
+			if o is None:
+				o = list()
+			for x in v:
+				try:
+					o.remove(x)
+				except ValueError:
+					pass
+			obj[k] = o
+
+		return self.ObjId
+
+
+
[docs]class StorageService(StorageServiceABC): + + + def __init__(self, app, service_name): + super().__init__(app, service_name) + self.InMemoryCollections = {} + + + def upsertor(self, collection: str, obj_id=None, version=0) -> InMemoryUpsertor: + """Obtain an in-memory upsertor for given collection and possibly for the specified object. + + :collection (str): The name of the collection. + :obj_id (_type_, optional): The ID of the document to retrieve. Defaults to None. + :version (int, optional): The version of the collection. Defaults to 0. + + Returns: + :InMemoryUpsertor: Upsertor for given collection. + + """ + return InMemoryUpsertor(self, collection, obj_id, version) + + + async def get(self, collection: str, obj_id: typing.Union[str, bytes], decrypt=None) -> dict: + """Retrieve a document from an in-memory collection by its ID. + + :collection (str): The name of the collection to retrieve the document from. + :obj_id (str | bytes): The ID of the document to retrieve. + :decrypt (_type_, optional): A list of field names to decrypt. Defaults to None. + + Returns: + :dict: A dictionary representing the retrieved document.bIf `decrypt` is not None, the specified fields in the document are decrypted using AES decryption algorithm. + + """ + coll = self.InMemoryCollections[collection] + data = coll[obj_id] + if decrypt is not None: + for field in decrypt: + if field in data: + data[field] = self.aes_decrypt(data[field]) + return data + + + async def get_by(self, collection: str, key: str, value, decrypt=None) -> dict: + """ + Retrieve a document from an in-memory collection by key and value. Not implemented yet. + + Raises: + :NotImplementedError: Not implemented on InMemoryStorage + """ + raise NotImplementedError() + + + async def delete(self, collection: str, obj_id): + """ + Delete a document from an in-memory collection. + + :param collection: Collection to delete from + :param obj_id: Object identification + + Raises: + :KeyError: If `obj_id` not found in `collection` + """ + coll = self.InMemoryCollections[collection] + del coll[obj_id] + + + def _set(self, collection: str, obj_id, obj): + try: + coll = self.InMemoryCollections[collection] + except KeyError: + coll = {} + self.InMemoryCollections[collection] = coll + + nobj = coll.setdefault(obj_id, obj) + if nobj != obj: + raise DuplicateError("Already exists", obj_id)
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/storage/mongodb.html b/old_docs/_build/html/_modules/asab/storage/mongodb.html new file mode 100644 index 000000000..669ea1e60 --- /dev/null +++ b/old_docs/_build/html/_modules/asab/storage/mongodb.html @@ -0,0 +1,340 @@ + + + + + + + + asab.storage.mongodb — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.storage.mongodb

+import datetime
+import typing
+import motor.motor_asyncio
+import pymongo
+import bson
+
+import asab
+from .exceptions import DuplicateError
+from .service import StorageServiceABC
+from .upsertor import UpsertorABC
+
+asab.Config.add_defaults(
+	{
+		'asab:storage': {
+			'mongodb_uri': 'mongodb://localhost:27017',
+			'mongodb_database': 'asabdb',
+		}
+	}
+)
+
+
+
[docs]class StorageService(StorageServiceABC): + ''' + StorageService for MongoDB. Depends on `pymongo` and `motor`. + ''' + + + def __init__(self, app, service_name, config_section_name='asab:storage'): + super().__init__(app, service_name) + self.Client = motor.motor_asyncio.AsyncIOMotorClient(asab.Config.get(config_section_name, 'mongodb_uri')) + + self.Database = self.Client.get_database( + asab.Config.get(config_section_name, 'mongodb_database'), + codec_options=bson.codec_options.CodecOptions(tz_aware=True, tzinfo=datetime.timezone.utc), + ) + assert self.Database is not None + + + def upsertor(self, collection: str, obj_id=None, version=0): + return MongoDBUpsertor(self, collection, obj_id, version) + + + async def get(self, collection: str, obj_id, decrypt=None) -> dict: + coll = self.Database[collection] + ret = await coll.find_one({'_id': obj_id}) + if ret is None: + raise KeyError("NOT-FOUND") + if decrypt is not None: + for field in decrypt: + if field in ret: + ret[field] = self.aes_decrypt(ret[field]) + return ret + + +
[docs] async def get_by(self, collection: str, key: str, value, decrypt=None) -> dict: + """ + Get object from collection by its key and value. + + :param collection: Collection to get from. + :param key: Key to filter on. + :param value: Value to filter on. + :param decrypt: Set of fields to decrypt. + :return: The object retrieved from a storage + :raise KeyError: Raised if object{key: value} cannot be found in `collection`. + """ + coll = self.Database[collection] + ret = await coll.find_one({key: value}) + if ret is None: + raise KeyError("NOT-FOUND") + if decrypt is not None: + for field in decrypt: + if field in ret: + ret[field] = self.aes_decrypt(ret[field]) + return ret
+ + +
[docs] async def collection(self, collection: str) -> motor.motor_asyncio.AsyncIOMotorCollection: + """ + Get collection. Useful for custom operations. + + :param collection: Collection to get. + :return: AsyncIOMotorCollection object connected to the queried database. + + Examples: + + >>> coll = await storage.collection("test-collection") + >>> cursor = coll.find({}) + >>> while await cursor.fetch_next: + ... obj = cursor.next_object() + ... pprint.pprint(obj) + + """ + + return self.Database[collection]
+ + + async def delete(self, collection: str, obj_id): + """ + Delete object from `collection` by its `obj_id` + + :param collection: Collection to delete from + :param obj_id: Object identification + :return: `obj_id` -- Object identification + + :raise KeyError: Raised if `obj_id` cannot be found in `collection`. + """ + coll = self.Database[collection] + ret = await coll.find_one_and_delete({'_id': obj_id}) + if ret is None: + raise KeyError("NOT-FOUND") + return ret['_id']
+ + +class MongoDBUpsertor(UpsertorABC): + + + @classmethod + def generate_id(cls): + return bson.objectid.ObjectId() + + + async def execute(self, custom_data: typing.Optional[dict] = None, event_type: typing.Optional[str] = None): + id_name = self.get_id_name() + addobj = {} + + if len(self.ModSet) > 0: + addobj['$set'] = self.ModSet + + if len(self.ModInc) > 0: + addobj['$inc'] = self.ModInc + + if len(self.ModPush) > 0: + addobj['$push'] = {k: {'$each': v} for k, v in self.ModPush.items()} + + if len(self.ModUnset) > 0: + addobj['$unset'] = {k: "" for k in self.ModUnset} + + filtr = {} + + if self.ObjId is not None: + filtr[id_name] = self.ObjId + else: + # We are going to insert a new object without explicit Id + assert (self.Version == 0) or (self.Version is None) + + if self.Version is not None: + filtr['_v'] = int(self.Version) + + # First wave (adding stuff) + if len(addobj) > 0: + coll = self.Storage.Database[self.Collection] + try: + ret = await coll.find_one_and_update( + filtr, + update=addobj, + upsert=True if (self.Version == 0) or (self.Version is None) else False, + return_document=pymongo.collection.ReturnDocument.AFTER + ) + except pymongo.errors.DuplicateKeyError as e: + if hasattr(e, "details"): + raise DuplicateError("Duplicate key error: {}".format(e), self.ObjId, key_value=e.details.get("keyValue")) + else: + raise DuplicateError("Duplicate key error: {}".format(e), self.ObjId) + + if ret is None: + # Object might have been changed in the meantime + raise KeyError("NOT-FOUND") + + self.ObjId = ret[id_name] + + # for k, v in self.ModPull.items(): + # o = obj.pop(k, None) + # if o is None: o = list() + # for x in v: + # try: + # o.remove(x) + # except ValueError: + # pass + # obj[k] = o + + if self.Storage.WebhookURIs is not None: + webhook_data = { + "collection": self.Collection, + } + + if custom_data is not None: + webhook_data["custom"] = custom_data + + if event_type is not None: + webhook_data["event_type"] = event_type + + # Add upsetor data; do not include fields that start with "__" + upsertor_data = { + "id_field_name": id_name, + "id": self.ObjId, + "_v": int(self.Version), + } + if len(self.ModSet) > 0: + upsertor_data["set"] = {k: v for k, v in self.ModSet.items() if not k.startswith("__")} + if len(self.ModInc) > 0: + upsertor_data["inc"] = {k: v for k, v in self.ModInc.items() if not k.startswith("__")} + if len(self.ModPush) > 0: + upsertor_data["push"] = {k: v for k, v in self.ModPush.items() if not k.startswith("__")} + if len(self.ModUnset) > 0: + upsertor_data["unset"] = {k: v for k, v in self.ModUnset.items() if not k.startswith("__")} + webhook_data["upsertor"] = upsertor_data + + await self.webhook(webhook_data) + + return self.ObjId +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/storage/service.html b/old_docs/_build/html/_modules/asab/storage/service.html new file mode 100644 index 000000000..ba2514496 --- /dev/null +++ b/old_docs/_build/html/_modules/asab/storage/service.html @@ -0,0 +1,335 @@ + + + + + + + + asab.storage.service — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.storage.service

+import abc
+import secrets
+import hashlib
+import logging
+import asab
+import re
+
+try:
+	import cryptography.hazmat.primitives.ciphers
+	import cryptography.hazmat.primitives.ciphers.algorithms
+	import cryptography.hazmat.primitives.ciphers.modes
+except ModuleNotFoundError:
+	cryptography = None
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+ENCRYPTED_PREFIX = b"$aes-cbc$"
+
+
+
[docs]class StorageServiceABC(asab.Service): + + def __init__(self, app, service_name): + super().__init__(app, service_name) + self.WebhookURIs = asab.Config.get("asab:storage:changestream", "webhook_uri", fallback="") or None + if self.WebhookURIs is not None: + self.WebhookURIs = [uri for uri in re.split(r"\s+", self.WebhookURIs) if len(uri) > 0] + try: + self.ProactorService = app.get_service("asab.ProactorService") + except KeyError as e: + raise Exception("Storage webhooks require ProactorService") from e + self.WebhookAuth = asab.Config.get("asab:storage:changestream", "webhook_auth", fallback="") or None + + # Specify a non-empty AES key to enable AES encryption of selected fields + self._AESKey = asab.Config.get("asab:storage", "aes_key", fallback="") + if len(self._AESKey) > 0: + if cryptography is None: + raise ModuleNotFoundError( + "You are using storage encryption without 'cryptography' installed. " + "Please run 'pip install cryptography' " + "or install asab with 'storage_encryption' optional dependency.") + self._AESKey = hashlib.sha256(self._AESKey.encode("utf-8")).digest() + else: + self._AESKey = None + + +
[docs] @abc.abstractmethod + def upsertor(self, collection: str, obj_id=None, version: int = 0): + """ + Create an upsertor object for the specified collection. + + If updating an existing object, please specify its `obj_id` and also `version` that you need to read from a storage upfront. + If `obj_id` is None, we assume that you want to insert a new object and generate its new `obj_id`, `version` should be set to 0 (default) in that case. + If you want to insert a new object with a specific `obj_id`, specify `obj_id` and set a version to 0. + - If there will be a colliding object already stored in a storage, `execute()` method will fail on `DuplicateError`. + + :param collection: Name of collection to work with + :param obj_id: Primary identification of an object in the storage (e.g. primary key) + :param version: Specify a current version of the object and hence prevent byzantine faults. \ + You should always read the version from the storage upfront, prior using an upsertor. \ + That creates a soft lock on the record. It means that if the object is updated by other \ + component in meanwhile, your upsertor will fail and you should retry the whole operation. \ + The new objects should have a `version` set to 0. + """ + pass
+ + +
[docs] @abc.abstractmethod + async def get(self, collection: str, obj_id, decrypt=None) -> dict: + """ + Get object from collection by its ID. + + :param collection: Collection to get from. + :type collection: str + :param obj_id: Object identification. + :param decrypt: Set of fields to decrypt. + :return: The object retrieved from a storage. + :raise KeyError: Raised if `obj_id` is not found in `collection`. + """ + pass
+ + + @abc.abstractmethod + async def get_by(self, collection: str, key: str, value, decrypt=None): + """ + Get object from collection by its key and value. + + :param collection: Collection to get from + :param key: Key to filter on + :param value: Value to filter on + :param decrypt: Set of fields to decrypt + :return: The object retrieved from a storage + + Raises: + KeyError: If object {key: value} not found in `collection` + """ + pass + + +
[docs] @abc.abstractmethod + async def delete(self, collection: str, obj_id): + """ + Delete object from collection. + + :param collection: Collection to get from + :type collection: str + :param obj_id: Object identification + + :return: ID of the deleted object. + + :raise KeyError: Raised when obj_id cannot be found in collection. + """ + pass
+ + +
[docs] def aes_encrypt(self, raw: bytes, iv: bytes = None) -> bytes: + """ + Take an array of bytes and encrypt it using AES-CBC. + + :param raw: The data to be encrypted. + :type raw: bytes + :param iv: AES-CBC initialization vector, 16 bytes long. If left empty, a random 16-byte array will be used. + :type iv: bytes + :return: The encrypted data. + + :raise TypeError: The data are not in binary format. + """ + block_size = cryptography.hazmat.primitives.ciphers.algorithms.AES.block_size // 8 + + if self._AESKey is None: + raise RuntimeError( + "No aes_key specified in asab:storage configuration. " + "If you want to use encryption, specify a non-empty aes_key." + ) + + if not isinstance(raw, bytes): + if isinstance(raw, str): + raise TypeError("String objects must be encoded before encryption") + else: + raise TypeError("Only 'bytes' objects can be encrypted") + + # Pad the text to fit the blocks + pad_length = -len(raw) % block_size + if pad_length != 0: + raw = raw + b"\00" * pad_length + + if iv is None: + iv = secrets.token_bytes(block_size) + + algorithm = cryptography.hazmat.primitives.ciphers.algorithms.AES(self._AESKey) + mode = cryptography.hazmat.primitives.ciphers.modes.CBC(iv) + cipher = cryptography.hazmat.primitives.ciphers.Cipher(algorithm, mode) + encryptor = cipher.encryptor() + encrypted = ENCRYPTED_PREFIX + iv + (encryptor.update(raw) + encryptor.finalize()) + return encrypted
+ + +
[docs] def aes_decrypt(self, encrypted: bytes) -> bytes: + """ + Decrypt encrypted data using AES-CBC. + + :param encrypted: The encrypted data to decrypt. + It must start with b"$aes-cbc$" prefix, followed by one-block-long initialization vector. + :type encrypted: bytes + :return: The decrypted data. + """ + block_size = cryptography.hazmat.primitives.ciphers.algorithms.AES.block_size // 8 + + if self._AESKey is None: + raise RuntimeError( + "No aes_key specified in asab:storage configuration. " + "If you want to use encryption, specify a non-empty aes_key." + ) + + if not isinstance(encrypted, bytes): + raise TypeError("Only values of type 'bytes' can be decrypted") + + # Strip the prefix + if not encrypted.startswith(ENCRYPTED_PREFIX): + raise ValueError("Encrypted data must start with {!r} prefix".format(ENCRYPTED_PREFIX)) + encrypted = encrypted[len(ENCRYPTED_PREFIX):] + + # Separate the initialization vector + iv, encrypted = encrypted[:block_size], encrypted[block_size:] + + algorithm = cryptography.hazmat.primitives.ciphers.algorithms.AES(self._AESKey) + mode = cryptography.hazmat.primitives.ciphers.modes.CBC(iv) + cipher = cryptography.hazmat.primitives.ciphers.Cipher(algorithm, mode) + decryptor = cipher.decryptor() + raw = decryptor.update(encrypted) + decryptor.finalize() + + # Strip padding + raw = raw.rstrip(b"\x00") + return raw
+ + + def encryption_enabled(self) -> bool: + """ + Check if AESKey is not empty. + """ + return self._AESKey is not None
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/storage/upsertor.html b/old_docs/_build/html/_modules/asab/storage/upsertor.html new file mode 100644 index 000000000..8b08aca55 --- /dev/null +++ b/old_docs/_build/html/_modules/asab/storage/upsertor.html @@ -0,0 +1,301 @@ + + + + + + + + asab.storage.upsertor — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.storage.upsertor

+import abc
+import json
+import urllib.parse
+import uuid
+import hashlib
+import datetime
+import logging
+import asab.web.rest.json
+import http.client
+import typing
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+
[docs]class UpsertorABC(abc.ABC): + + def __init__(self, storage, collection, obj_id, version=None): + + self.Storage = storage + self.Collection = collection + self.ObjId = obj_id + + self.Version = version + + now = datetime.datetime.now(datetime.timezone.utc) + self.ModSet = { + '_m': now, # Set the modification datetime + } + if version == 0: + self.ModSet['_c'] = now # Set the creation datetime + + self.ModUnset = {} + + self.ModInc = { + '_v': 1, # Increment '_v' at every change + } + + self.ModPush = {} + self.ModPull = {} + + self.WebhookResponseData = {} + + + def get_id_name(self): + return "_id" + + +
[docs] @classmethod + def generate_id(cls) -> bytes: + """ + Generate a unique ID string using a combination of a random UUID and a SHA-256 hash. + + :return: A string representation of the generated ID. + """ + m = hashlib.sha256() + m.update(uuid.uuid4().bytes) + return m.digest()
+ + +
[docs] def set(self, objField, value, encrypt=False, encrypt_iv=None): + """ + Add key and value to the upsertor. + + :param objField: Key of the object. + :param value: Value of the object. + :param encrypt: Allow encryption. Defaults to False. + :type encrypt: bool + :param encrypt_iv: Custom initialization vector. Defaults to None. + :type encrypt_iv: bool + """ + + if encrypt: + value = self.Storage.aes_encrypt(value, iv=encrypt_iv) + self.ModSet[objField] = value
+ + +
[docs] def unset(self, obj_field): + ''' + Scalar unset + ''' + self.ModUnset[obj_field] = ""
+ + + def increment(self, field_name, amount=1): + ''' + Scalar increment + ''' + self.ModInc[field_name] = amount + + + def decrement(self, field_name, amount=1): + ''' + Scalar decrement + ''' + return self.increment(field_name, -amount) + + + def push(self, field_name, value): + ''' + Push an item into a list + ''' + if self.ModPush.get(field_name) is None: + self.ModPush[field_name] = [] + self.ModPush[field_name].append(value) + + + def pull(self, field_name, value): + ''' + Pull an item from a list + ''' + if self.ModPull.get(field_name) is None: + self.ModPull[field_name] = [] + self.ModPull[field_name].append(value) + + +
[docs] @abc.abstractmethod + async def execute(self, custom_data: typing.Optional[dict] = None, event_type: typing.Optional[str] = None): + """ + Commit upsertor data to the storage. Afterwards, send a webhook request with upsertion details. + + :param custom_data: Custom execution data. Included in webhook payload. + :param event_type: Event type included in webhook payload. + :raise DuplicateError: Raised if thre is a colliding object already stored in a storage. + """ + + pass
+ + + async def webhook(self, data: dict): + assert self.Storage.WebhookURIs is not None + json_dump = asab.web.rest.json.JSONDumper(pretty=False)(data) + for uri in self.Storage.WebhookURIs: + self.WebhookResponseData[uri] = await self.Storage.ProactorService.execute( + self._webhook, json_dump, uri, self.Storage.WebhookAuth) + + + + def _webhook(self, data, uri, auth=None): + u = urllib.parse.urlparse(uri) + if u.scheme == "https": + conn = http.client.HTTPSConnection(u.netloc) + else: + conn = http.client.HTTPConnection(u.netloc) + + headers = {"Content-Type": "application/json"} + if auth is not None: + headers["Authorization"] = auth + + try: + conn.request("PUT", uri, data, headers) + response = conn.getresponse() + if response.status // 100 != 2: + text = response.read() + L.error( + "Webhook endpoint responded with {}: {}".format(response.status, text), + struct_data={"uri": uri}) + return + self.WebhookResponseData = json.load(response) + except ConnectionRefusedError: + L.error("Webhook call failed: Connection refused.", struct_data={"uri": uri}) + return + except json.decoder.JSONDecodeError as e: + L.error("Failed to decode JSON response from webhook: {}".format(str(e)), struct_data={"uri": uri}) + except Exception as e: + L.error("Webhook call failed with {}: {}".format(type(e).__name__, str(e)), struct_data={"uri": uri}) + finally: + conn.close()
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/timer.html b/old_docs/_build/html/_modules/asab/timer.html new file mode 100644 index 000000000..469cec0be --- /dev/null +++ b/old_docs/_build/html/_modules/asab/timer.html @@ -0,0 +1,215 @@ + + + + + + + + asab.timer — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.timer

+import asyncio
+
+
+
[docs]class Timer(object): + ''' + T.__init__(app, handler, autorestart=False) -> Timer. + + The relative and optionally repeating timer for asyncio. + + This class is simple relative timer that generate an event after a given time, and optionally repeating in regular intervals after that. + + :param app: An ASAB application. + :param handler: A coro or future that will be called when a timer triggers. + :param boolean autorestart: If `True` then a timer will be automatically restarted after triggering. + + :ivar Handler: A coro or future that will be called when a timer triggers. + :ivar Task: A future that represent the timer task. + :ivar App: An ASAB app. + :ivar boolean AutoRestart: If `True` then a timer will be automatically restarted after triggering. + + The timer object is initialized as stopped. + + *Note*: The implementation idea is borrowed from "`Python - Timer with asyncio/coroutine <https://stackoverflow.com/questions/45419723/python-timer-with-asyncio-coroutine>`_" question on StackOverflow. + ''' + + def __init__(self, app, handler, autorestart=False): + self.App = app + self.Handler = handler + self.Task = None + self.AutoRestart = autorestart + + app.PubSub.subscribe("Application.stop!", self._on_stop) + + +
[docs] def start(self, timeout): + ''' + Start the timer. + + :param float/int timeout: A timer delay in seconds. + ''' + if self.is_started(): + raise RuntimeError("Timer is already started") + self.Task = asyncio.ensure_future(self._job(timeout))
+ + +
[docs] def stop(self): + ''' + Stop the timer. + ''' + if self.Task is not None: + self.Task.cancel() + self.Task = None
+ + +
[docs] def restart(self, timeout): + ''' + Restart the timer. + + :param float/int timeout: A timer delay in seconds. + ''' + + if self.is_started(): + self.stop() + self.start(timeout)
+ + +
[docs] def is_started(self): + ''' + T.is_started() -> boolean + Return `True` is the timer is started otherwise returns `False`. + ''' + return self.Task is not None
+ + + async def _job(self, timeout): + await asyncio.sleep(timeout) + self.Task = None + if self.AutoRestart: + self.start(timeout) + await self.Handler() + + + def _on_stop(self, message_type, n): + # This is to ensure timer stop on application exit + self.stop()
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/web/service.html b/old_docs/_build/html/_modules/asab/web/service.html new file mode 100644 index 000000000..dc0499153 --- /dev/null +++ b/old_docs/_build/html/_modules/asab/web/service.html @@ -0,0 +1,196 @@ + + + + + + + + asab.web.service — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.web.service

+import logging
+
+from ..abc.service import Service
+from .. import Config
+from .. import metrics
+
+from .metrics import WebRequestsMetrics
+
+
+L = logging.getLogger(__name__)
+
+
+
[docs]class WebService(Service): + + ConfigSectionAliases = ["asab:web"] + + def __init__(self, app, service_name): + super().__init__(app, service_name) + + # Web service is dependent on Metrics service + if Config.getboolean("asab:metrics", "web_requests_metrics", fallback=False): + app.add_module(metrics.Module) + self.MetricsService = app.get_service("asab.MetricsService") + self.WebRequestsMetrics = WebRequestsMetrics(self.MetricsService) + self.Containers = {} + + async def finalize(self, app): + for containers in self.Containers.values(): + await containers._stop(app) + + def _register_container(self, container, config_section_name): + self.Containers[config_section_name] = container + self.App.TaskService.schedule(container._start(self.App)) + + + @property + def WebApp(self): + ''' + This is here to maintain backward compatibility. + ''' + return self.WebContainer.WebApp + + + @property + def WebContainer(self): + ''' + This is here to maintain backward compatibility. + ''' + config_section = "web" + + # The WebContainer should be configured in the config section [web] + if config_section not in Config.sections(): + # If there is no [web] section, try other aliases for backwards compatibility + for alias in self.ConfigSectionAliases: + if alias in Config.sections(): + config_section = alias + L.warning("Using obsolete config section [{}]. Preferred section name is [web]. ".format(alias)) + break + else: + raise RuntimeError("No [web] section configured.") + + try: + return self.Containers[config_section] + except KeyError: + from .container import WebContainer + return WebContainer(self, config_section)
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/asab/zookeeper/container.html b/old_docs/_build/html/_modules/asab/zookeeper/container.html new file mode 100644 index 000000000..5cc45b4d6 --- /dev/null +++ b/old_docs/_build/html/_modules/asab/zookeeper/container.html @@ -0,0 +1,361 @@ + + + + + + + + asab.zookeeper.container — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.zookeeper.container

+import os
+import time
+import json
+import asyncio
+import logging
+import urllib.parse
+import configparser
+
+import kazoo.exceptions
+import kazoo.recipe.watchers
+import kazoo.protocol.states
+
+from .wrapper import KazooWrapper
+from ..config import ConfigObject
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+
[docs]class ZooKeeperContainer(ConfigObject): + """ + Create a Zookeeper container with a specifications of the connectivity. + """ + + ConfigDefaults = { + # Server list to which ZooKeeper Client tries connecting. + # Specify a comma (,) separated server list. + # A server is defined as `address:port` format. + # Example: + # "servers": "zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181" + # If servers are empty, default from [zookeeper]/servers will be taken + # If [zookeeper]/servers value is not provided, ASAB_ZOOKEEPER_SERVERS environment variable is used + "servers": "", + + # If not provided, "/asab" path will be used + "path": "", + } + + + def __init__(self, zookeeper_service, config_section_name="zookeeper", config=None, z_path=None): + super().__init__(config_section_name=config_section_name, config=config) + + self.App = zookeeper_service.App + self.ConfigSectionName = config_section_name + self.ProactorService = zookeeper_service.ProactorService + + # Parse URL from z_path + if z_path is not None: + url_pieces = urllib.parse.urlparse(z_path) + url_netloc = url_pieces.netloc + url_path = url_pieces.path + else: + url_netloc = "" + url_path = "" + + # If there is no location, use the value of 'servers' from the configuration + if url_netloc == "": + url_netloc = self.Config.get("servers", "") + + if url_netloc == "": + from ..config import Config + try: + url_netloc = Config.get("zookeeper", "servers") + except (configparser.NoOptionError, configparser.NoSectionError): + pass + + if url_netloc == "": + url_netloc = os.environ.get("ASAB_ZOOKEEPER_SERVERS", "") + + if url_netloc == "": + # if server entry is missing exit + L.critical("Cannot connect to Zookeeper, the configuration of the server address is not available.") + raise SystemExit("Exit due to a critical configuration error.") + + assert url_netloc is not None + + # If path has not been provided, use the value of 'path' from the configuration + if url_path == "": + url_path = self.Config.get("path", "") + + if url_path == "": + from ..config import Config + try: + url_path = Config.get("zookeeper", "path") + except (configparser.NoOptionError, configparser.NoSectionError): + pass + + if url_path == "": + url_path = 'asab' + + # Remove all heading '/' from path + while url_path.startswith('/'): + url_path = url_path[1:] + + self.Path = url_path + + self.Advertisments = dict() + self.DataWatchers = set() + self.App.PubSub.subscribe("Application.tick/300!", self._readvertise) + + self.ZooKeeper = KazooWrapper(self, url_netloc) + + zookeeper_service.Containers.append(self) + self.ProactorService.schedule(self._start) + + + def _start(self): + # This method is called on proactor thread + while True: + try: + self.ZooKeeper.Client.start(timeout=600) # 600 seconds + return + except Exception as e: + L.error( + "Failed to connect to ZooKeeper: {} (retrying in 2 seconds)".format(e), + struct_data={ + 'hosts': str(self.ZooKeeper.Client.hosts), + } + ) + time.sleep(2) + continue + + + async def _stop(self): + await self.ZooKeeper._stop() + + + def _listener(self, state): + ''' + Generate PubSub events: + + * ZooKeeperContainer.state/CONNECTED! + * ZooKeeperContainer.state/LOST! + * ZooKeeperContainer.state/SUSPENDED! + ''' + if state == kazoo.protocol.states.KazooState.CONNECTED: + self.App.Loop.call_soon_threadsafe(self.ZooKeeper.Client.ensure_path, self.Path) + + self.App.PubSub.publish_threadsafe("ZooKeeperContainer.state/{}!".format(state), self) + + + +
[docs] def is_connected(self): + """ + Check, if the Zookeeper is connected + """ + return self.ZooKeeper.Client.connected
+ + + # Advertisement into Zookeeper + +
[docs] def advertise(self, data, path): + adv = self.Advertisments.get(self.Path + path) + if adv is None: + adv = ZooKeeperAdvertisement(self.Path + path) + self.Advertisments[self.Path + path] = adv + self.App.TaskService.schedule(adv._set_data(self, data))
+ + + async def _readvertise(self, *args): + for adv in self.Advertisments.values(): + await adv._readvertise(self) + + + # Reading + +
[docs] async def get_children(self, path=""): + return await self.ZooKeeper.get_children("{}/{}".format(self.Path, path))
+ +
[docs] async def get_data(self, path, encoding="utf-8"): + raw_data = await self.get_raw_data(path) + if raw_data is None: + return {} + return json.loads(raw_data.decode(encoding))
+ +
[docs] async def get_raw_data(self, path): + return await self.ZooKeeper.get_data("{}/{}".format(self.Path, path))
+ + +class ZooKeeperAdvertisement(object): + + def __init__(self, path): + self.Data = None + + self.Path = path + self.RealPath = None + + self.Lock = asyncio.Lock() + + + async def _set_data(self, zoocontainer, data): + async with self.Lock: + if isinstance(data, dict): + self.Data = json.dumps(data).encode("utf-8") + elif isinstance(data, str): + self.Data = data.encode("utf-8") + else: + self.Data = data + + def write_to_zk(): + if self.RealPath is None: + self.RealPath = zoocontainer.ZooKeeper.Client.create(self.Path, self.Data, sequence=True, ephemeral=True, makepath=True) + else: + try: + zoocontainer.ZooKeeper.Client.set(self.RealPath, self.Data) + except kazoo.exceptions.NoNodeError: + self.RealPath = zoocontainer.ZooKeeper.Client.create(self.Path, self.Data, sequence=True, ephemeral=True, makepath=True) + + await zoocontainer.ZooKeeper.ProactorService.execute(write_to_zk) + + + async def _readvertise(self, zoocontainer): + if self.Data is None: + return + + if self.RealPath is None: + return + + async with self.Lock: + + def check_at_zk(): + if zoocontainer.ZooKeeper.Client.exists(self.RealPath): + return + + # If the advertisement node is not present in the Zookeeper, force the recreation + self.RealPath = zoocontainer.ZooKeeper.Client.create(self.Path, self.Data, sequence=True, ephemeral=True) + + await zoocontainer.ZooKeeper.ProactorService.execute(check_at_zk) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/_modules/index.html b/old_docs/_build/html/_modules/index.html new file mode 100644 index 000000000..dd5649847 --- /dev/null +++ b/old_docs/_build/html/_modules/index.html @@ -0,0 +1,152 @@ + + + + + + + + Overview: module code — ASAB documentation + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/admin/command-line.rst b/old_docs/_build/html/_sources/admin/command-line.rst.txt similarity index 100% rename from doc/admin/command-line.rst rename to old_docs/_build/html/_sources/admin/command-line.rst.txt diff --git a/doc/admin/containers.rst b/old_docs/_build/html/_sources/admin/containers.rst.txt similarity index 100% rename from doc/admin/containers.rst rename to old_docs/_build/html/_sources/admin/containers.rst.txt diff --git a/doc/admin/install.rst b/old_docs/_build/html/_sources/admin/install.rst.txt similarity index 100% rename from doc/admin/install.rst rename to old_docs/_build/html/_sources/admin/install.rst.txt diff --git a/doc/admin/systemd.rst b/old_docs/_build/html/_sources/admin/systemd.rst.txt similarity index 100% rename from doc/admin/systemd.rst rename to old_docs/_build/html/_sources/admin/systemd.rst.txt diff --git a/doc/asab/alert.rst b/old_docs/_build/html/_sources/asab/alert.rst.txt similarity index 100% rename from doc/asab/alert.rst rename to old_docs/_build/html/_sources/asab/alert.rst.txt diff --git a/doc/asab/application.rst b/old_docs/_build/html/_sources/asab/application.rst.txt similarity index 100% rename from doc/asab/application.rst rename to old_docs/_build/html/_sources/asab/application.rst.txt diff --git a/doc/asab/config.rst b/old_docs/_build/html/_sources/asab/config.rst.txt similarity index 100% rename from doc/asab/config.rst rename to old_docs/_build/html/_sources/asab/config.rst.txt diff --git a/doc/asab/index.rst b/old_docs/_build/html/_sources/asab/index.rst.txt similarity index 100% rename from doc/asab/index.rst rename to old_docs/_build/html/_sources/asab/index.rst.txt diff --git a/old_docs/_build/html/_sources/asab/library.rst.txt b/old_docs/_build/html/_sources/asab/library.rst.txt new file mode 100644 index 000000000..3c61f59ac --- /dev/null +++ b/old_docs/_build/html/_sources/asab/library.rst.txt @@ -0,0 +1,206 @@ +.. _library-ref: + +Library +======= + +.. py:currentmodule:: asab.library + +The ASAB Library (`asab.library`) is a concept of the shared data content across microservices in the cluster. +The `asab.library` provides a read-only interface for listing and reading this content. +The library can also notify the ASAB microservice about changes, eg. for automated update/reload. + +There is a companion microservice `asab-library` that can be used for management and editation of the library content. +The `asab.library` can however operate without `asab-library` microservice. + + +Library structure +----------------- + +The library content is organized in simplified filesystem manner, with directories and files. + +Example of the library structure: + +.. code:: + + + /folder1/ + - /folder1/item1.yaml + - /folder1/item2.json + + /folder2/ + - /folder2/item3.yaml + + /folder2folder2.3/ + - /folder2/folder2.3/item4.json + + +Library path rules +------------------- + +* Any path must start with `/`, including the root path (`/`). +* The folder path must end with `/`. +* The item path must end with extension (eg. `.json`). + + +Library service +--------------- + +.. autoclass:: LibraryService + + +Example of the use: + +.. code:: python + + import asab + + class MyApplication(asab.Application): + + def __init__(self): + super().__init__() + + # Initialize the library service + self.LibraryService = asab.library.LibraryService(self, "LibraryService") + self.PubSub.subscribe("Library.ready!", self.on_library_ready) + + async def on_library_ready(self, event_name, library): + print("# Library\n") + + for item in await self.LibraryService.list("", recursive=True): + print(" *", item) + if item.type == 'item': + itemio = await self.LibraryService.read(item.name) + if itemio is not None: + with itemio: + content = itemio.read() + print(" - content: {} bytes".format(len(content))) + else: + print(" - (DISABLED)") + + +.. automethod:: LibraryService.read + +.. automethod:: LibraryService.list + +.. automethod:: LibraryService.export + + + +Notification of changes +----------------------- + + +.. automethod:: LibraryService.subscribe + + + +Providers +--------- + +.. py:currentmodule:: asab.library.providers + +The library can be configured to work with following "backends" (aka providers): + + +Filesystem +^^^^^^^^^^ + +.. py:currentmodule:: asab.library.providers.filesystem + +.. autoclass:: FileSystemLibraryProvider + :no-undoc-members: + + +Apache Zookeeper +^^^^^^^^^^^^^^^^ + +.. py:currentmodule:: asab.library.providers.zookeeper + +.. autoclass:: ZooKeeperLibraryProvider + :no-undoc-members: + + +Microsoft Azure Storage +^^^^^^^^^^^^^^^^^^^^^^^ + +.. py:currentmodule:: asab.library.providers.azurestorage + +.. autoclass:: AzureStorageLibraryProvider + :no-undoc-members: + + +Git repository +^^^^^^^^^^^^^^ + +Connection to git repositories requires `pygit2 `_ library to be installed. + +Example of configuration: + +.. code:: ini + + [library] + providers: git+https://github.com/john/awesome_project.git + +Functionality +~~~~~~~~~~~~~ + +The git provider clones the repository into a temporary directory and then uses the File System Provider to read the files from it. The default path for the cloned repository is `/tmp/asab.library.git/` and it can be changed manually: + +.. code:: ini + + [library:git] + repodir=path/to/repository/cache + + +Deploy tokens in GitLab +~~~~~~~~~~~~~~~~~~~~~~~ +GitLab uses deploy tokens to enable authentication of deployment tasks, independent of a user account. A `deploy token` is an SSH key that grants access to a single repository. The public part of the key is attached directly to the repository instead of a personal account, and the private part of the key remains on the server. It is the preferred preferred way over changing local SSH settings. + +If you want to create a deploy token for your GitLab repository, follow these steps from the `manual `_: + +1. Go to **Settings > Repository > Deploy tokens** section in your repository. (Note that you have to possess "Maintainer" or "Owner" role for the repository.) +2. Expand the "Deploy tokens" section. The list of current Active Deploy Tokens will be displayed. +3. Complete the fields and scopes. We recommend to specify custom "username", as you will need it later for the url in configuration. +4. Record the deploy token's values *before leaving or refreshing the page*! After that, you cannot access it again. + +After the deploy token is created, use the URL for repository in the following format: + +.. code:: + + https://:@gitlab.example.com/john/awesome_project.git + +Reference +~~~~~~~~~ + +.. py:currentmodule:: asab.library.providers.git + +.. autoclass:: GitLibraryProvider + :no-undoc-members: + + + +Layers +------ + +The library content can be organized into unlimmited number of layers. +Each layer is represented by a `provider` with a specific configuration. + + +Library configuration +--------------------- + + +Example: + +.. code:: ini + + [library] + providers: + provider+1://... + provider+2://... + provider+3://... + + +PubSub messages +--------------- + +.. option:: Library.ready! + +.. option:: Library.change! diff --git a/doc/asab/log.rst b/old_docs/_build/html/_sources/asab/log.rst.txt similarity index 100% rename from doc/asab/log.rst rename to old_docs/_build/html/_sources/asab/log.rst.txt diff --git a/old_docs/_build/html/_sources/asab/metrics.rst.txt b/old_docs/_build/html/_sources/asab/metrics.rst.txt new file mode 100644 index 000000000..3ad21d167 --- /dev/null +++ b/old_docs/_build/html/_sources/asab/metrics.rst.txt @@ -0,0 +1,425 @@ +.. currentmodule:: asab.metrics + +Metrics +======= +Metrics document the state of the application in a timescale manner. +For further analysis, connect your ASAB application to a time-series database. `Influx `_ and `Prometheus `_ are supported. + + +Metrics Service +------------------------ + +Create new metrics using :class:`MetricsService`. + +*example of counter initialization:* + +.. code:: python + + class MyApplication(asab.Application): + async def initialize(self): + from asab.metrics import Module + self.add_module(Module) + self.MetricsService = self.get_service('asab.MetricsService') + self.MyCounter = self.MetricsService.create_counter("mycounter", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0}) + + if __name__ == '__main__': + app = MyApplication() + app.run() + +See the full example here: https://github.com/TeskaLabs/asab/blob/master/examples/metrics.py + + + +Types of Metrics +---------------- + +- :class:`Gauge` stores single numerical values which can go up and down. Implements :func:`set` method to set the metric values. +- :class:`Counter` is a cumulative metric whose values can increase or decrease. Implements :func:`add` and :func:`sub` methods. +- Event per Second Counter (:class:`EPSCounter`) divides all values by delta time. +- :class:`DutyCycle` https://en.wikipedia.org/wiki/Duty_cycle +- :class:`AggregationCounter` allows to :func:`set` values based on an aggregation function. :func:`max` function is default. +- :class:`Histogram` represents cumulative histogram with :func:`set` method. + +:class:`Counter`, :class:`AggregationCounter` and :class:`Histogram` come also in variants respecting dynamic tags. (See section :ref:`Dynamic Tags`.) + +All methods that create new metrics objects can be found in the Metrics Service reference. You should never initiate a new metrics object on its own, but always through Metrics Service. Metris initialization is meant to be done in the init time of your application and **should not be done during runtime**. + + +ASAB Metrics Interpretation +---------------------------- + +Metrics Service not only creates new metrics but also periodically collects their values and sends them to selected databases. +Every 60 seconds in the application lifetime, Metrics Service gathers values of all ASAB metrics. +All Counters (and metric types that inherit from :class:`Counter`) reset at this event to their initial values by default. +Interpretation of ASAB Counters is affected by their resetable nature. Even though they monotonously increase, resetting every minute gives them a different meaning. +In a long-term observation (that's how you most probably monitor the metrics in time-series databases), these metrics count **events per minute**. +Thus, resettable Counters are presented to Prometheus database as gauge-type metrics. Set the `reset` argument to `False` when creating a new Counter to disable Counter resetting. +This periodic "flush" cycle also causes 60s delay of metric propagation into supported time-series databases. + + +Initial Values +-------------- +You can initiate your metric instance with or without initial values. When providing initial values, these values are always present and presented to databases even when these values were untouched during the last 60 seconds. You will always see these values in the data, with initial state or changed by occasion. +However, the lifetime of values (name and value pairs) added during runtime is only 60 s. Thus, if this value is not set during 60s period, you won't see it in your database anymore. + + +.. _dynamic_tags: + +Dynamic Tags +------------ +Some metric types (Counter, AggregationCounter, Histogram) allow you to use dynamic tags. All metrics in ASAB carry some tags - Hostname by default and others added by custom. +Using dynamic tags allows you to create values with a specific tag-set during runtime. Specific tag-sets expire after defined period. This might be spotted in your time-series database like a mysterious disappearance of unused tags. +Specify expiration period in confiuration. Default is 60 s. + +*example configuration* + +.. code:: + + [asab:metrics] + expiration=60 + + +Timestamp +--------- + +**Timestamp** contains the record of the precise moment the metric's value was created or committed to the database. There are two types of metrics: resettable (`is_reset` = True) and non-resettable (`is_reset` = False). To reset a metric means to set it back to its initial value (for example, back to 0). The metric's type is determined by the ``reset: bool = True`` parameter of the metric's constructor at the moment it is created. We measure non-resettable metrics at the time of their creation (`there are several possible methods depending on the metric's general logic`), while the resettable ones are measured when we send data to the database (`which is also the moment of them being reset`). + ++---+--------------+---------------------------------+-----------------------+-----------------------+---------+ +| |Metric's Type |Description / Methods |Time is Measured |Timestamp Value Appears|is_reset | ++===+==============+=================================+=======================+=======================+=========+ +|1F |**Gauge** |Stores single numerical values |when metric is created |**set()** |**False**| +| | |which can go up and down. |`(actual time)` |for actual time | | +| | | | | | | +| | |**add_field() /** | | | | +| | |**set()** | | | | ++---+--------------+---------------------------------+-----------------------+-----------------------+---------+ +|2F |**Counter** |A cumulative metric; |when metric is created |**add()** or **sub()** |**False**| +| | |values can increase or decrease |`(actual time)` |for actual time | | +| | |Never stops. | | | | +| | | | | | | +| |`Allows |**add_field() /** | | | | +| |dynamic tags` |**add() / sub() / flush()** | | | | ++---+--------------+---------------------------------+-----------------------+-----------------------+---------+ +|2T |**Counter** |A cumulative metric; |every 60 seconds |**flush()** |**True** | +| | |values can increase or decrease | |- time of the test | | +| | |Set to 0 every 60 seconds. | |flush | | +| | | | | | | +| |`Allows |`AgregationCounter behavior is | | | | +| |dynamic tags` |based on the resettable Counter.`| | | | ++---+--------------+---------------------------------+-----------------------+-----------------------+---------+ +|3F |**EPSCounter**|There is an adjustable |`*****` |`*****` |**False**| +| | |reset parameter | | | | +| | |in the metric’s constructor. | | | | +| | | | | | | +| | |`reset: bool = True` | | | | +| | |`reset: bool = False` | | | | ++---+--------------+---------------------------------+-----------------------+-----------------------+---------+ +|3T |**EPSCounter**|Divides the count of events |every 60 seconds |**flush()** |**True** | +| | |by the time difference between | | | | +| | |measurements. | | | | +| | | | | | | +| | |**flush()** | | | | ++---+--------------+---------------------------------+-----------------------+-----------------------+---------+ +|4T |**DutyCycle** |The fraction of one period in |every 60 seconds |**flush()** |**True** | +| | |which a signal/system is active. | | | | +| | |A 60% DC means the signal is on | | | | +| | |60% and off 40% of the time. | | | | +| | | | | | | +| | |**add_field() /** | | | | +| | |**set() / flush()** | | | | ++---+--------------+---------------------------------+-----------------------+-----------------------+---------+ +|5F |**Aggregation |Keeps track of max or min value |when metric is created |**set()** |**False**| +| |Counter** |of the Counter. |`(actual time)` | | | +| | |Maximum value is a default. | | | | +| | | | | | | +| | | | | | | +| | |**set() /** | | | | +| |`Allows |`+inherits from the Counter` | | | | +| |dynamic tags` |**add()/sub()** `are overwritten`| | | | ++---+--------------+---------------------------------+-----------------------+-----------------------+---------+ +|5T |**Aggregation |`*****` |every 60 seconds |**flush()** |**True** | +| |Counter** | | | | | +| | | | | | | +| |`Allows | | | | | +| |dynamic tags` | | | | | ++---+--------------+---------------------------------+-----------------------+-----------------------+---------+ +|6F |**Histogram** |Represents cumulative histogram |when metric is created |**set()** |**False**| +| | |with a set() method. |`(actual time)` | | | +| | | | | | | +| | | | | | | +| | | | | | | +| | | | | | | +| |`Allows |**add_field() /** | | | | +| |dynamic tags` |**set() / flush()** | | | | ++---+--------------+---------------------------------+-----------------------+-----------------------+---------+ +|6T |**Histogram** |`*****` |every 60 seconds |**flush()** |**True** | +| | | | | | | +| |`Allows | | | | | +| |dynamic tags` | | | | | ++---+--------------+---------------------------------+-----------------------+-----------------------+---------+ + + +InfluxDB +-------- +Metrics can be collected in the Influx time-series database. + +*configuration example:* + +.. code:: + + [asab:metrics] + target=influxdb + + [asab:metrics:influxdb] + url=http://localhost:8086/ + bucket=my_bucket + org=my_org + token=my_token + +**InfluxDB 2.0 API parameters**: + +- **url** - [required] url string of your influxDB +- **bucket** - [required] the destination bucket for writes +- **org** - [required] specifies the destination organization for writes +- **orgid** - [optional] specifies the ID of the destination organization for writes + (NOTE: If both orgID and org are specified, org takes precedence) +- **token** - [required] API token to authenticate to the InfluxDB + +**InfluxDB <1.8 API parameters**: + +- **url** - [required] url string of your influxDB +- **username** - [required] name of influxDB user +- **password** - [required] password of influxDB user + + +Prometheus +---------- +Prometheus is a "pull model" time-series database. +Prometheus accesses ``asab/v1/metrics`` endpoint of ASAB ApiService. Thus, connecting ASAB to Prometheus requires APIService initialization. However, no more configuration is needed. +ASAB metrics are presented to Prometheus in `OpenMetrics `_ standard format. + + +*prometheus.yaml configuration file example:* + +.. code:: yaml + + global: + scrape_interval: 15s + scrape_timeout: 10s + evaluation_interval: 15s + + scrape_configs: + - job_name: 'metrics_example' + metrics_path: '/asab/v1/metrics' + scrape_interval: 10s + static_configs: + - targets: ['127.0.0.1:8080'] + + +.. note:: + + To satisfy the OpenMetrics format required by Prometheus, you should follow the instructions below: + + - Metrics names must fit regex ``[a-zA-Z:][a-zA-Z0-9_:]*``. (Any other characters are replaced by an underscore. Leading underscores and numbers are stripped. These changes proceed without warning.) + - Metrics names MUST NOT end with “total” or “created”. + - Tags SHOULD contain items “unit” and “help” providing metadata to Prometheus. + - Values MUST be float or integer. + + +Metrics Endpoints +----------------- +The **API Service** in ASAB offers several endpoints that monitor internal ASAB functionality. Some of them present the current state of metrics. + +``/asab/v1/metrics`` + +- This endpoint returns metrics in OpenMetrics format and its primary purpose is to satisfy Prometheus database needs. + +``/asab/v1/metrics.json`` + +- This endpoint presents metrics data in JSON format. + +``/asab/v1/watch_metrics`` + +- Use this endpoint for developing or monitoring your app from the terminal. It returns a simple table of ASAB metrics. You can filter metrics by name using the ``filter`` parameter and ``tags`` parameter to show or hide tags. + + +*example commands:* + +.. code:: + + watch curl localhost:8080/asab/v1/watch_metrics + +.. code:: + + watch curl localhost:8080/asab/v1/watch_metrics?name=web_requests_duration_max,tags=True + + +HTTP Target +----------- +For use cases requiring a push model of metrics digestion, there is an HTTP Target. HTTP Target creates a POST request to configured URL with current metrics state sent as JSON body. +Configuration is required. + +*configuration example:* + +.. code:: + + [asab:metrics] + target=http + + [asab:metrics:http] + url=http://consumer_example:8080/consume + + + +Web Requests Metrics +-------------------- + +ASAB :class:`WebService` class automatically provides metrics counting web requests. +There are 5 metrics quantifying requests to all ASAB endpoints. + +- `web_requests` - Counts requests to asab endpoints as events per minute. +- `web_requests_duration` - Counts total requests duration to asab endpoints per minute. +- `web_requests_duration_min` - Counts minimal request duration to asab endpoints per minute. +- `web_requests_duration_max` - Counts maximum request duration to asab endpoints per minute. +- `web_requests_duration_hist` - Cumulative histogram counting requests in buckets defined by the request duration. + + +Native Metrics +-------------- + +You can opt out of Native Metrics through configuration by setting `native_metrics` to `false`. Default is `true`. + +*example configuration* + +.. code:: + + [asab:metrics] + native_metrics=true + +**Memory Metrics** + +A gauge with the name ``os.stat`` gathers information about memory usage by your application. + +You can find several metric values there: + +- VmPeak - Peak virtual memory size +- VmLck - Locked memory size +- VmPin - Pinned memory size +- VmHWM - Peak resident set size ("high water mark") +- VmRSS - Resident set size +- VmData, VmStk, VmExe - Size of data, stack, and text segments +- VmLib - Shared library code size +- VmPTE - Page table entries size +- VmPMD - Size of second-level page tables +- VmSwap - Swapped-out virtual memory size by anonymous private pages; shmem swap usage is not included + +**Logs Counter** + +There is a default Counter named ``logs`` with values ``warnings``, ``errors``, and ``critical``, counting logs with respective levels. +It is a humble tool for application health monitoring. + + + +Reference +--------- + +.. autoclass:: MetricsService + :show-inheritance: + + .. automethod:: create_gauge + + Creates :class:`Gauge` object. + + .. automethod:: create_counter + + Creates :class:`Counter` or :class:`CounterWithDynamicTags` object. + + .. automethod:: create_eps_counter + + Creates :class:`EPSCounter` object. + + .. automethod:: create_duty_cycle + + Creates :class:`DutyCycle` object. + + .. automethod:: create_aggregation_counter + + Creates :class:`AggregationCounter` or :class:`AggregationCounterWithDynamicTags` object. + + .. automethod:: create_histogram + + Creates :class:`Histogram` or :class:`HistogramWithDynamicTags` object. + + + +.. autoclass:: Gauge + :show-inheritance: + + Argument `init_values` is a dictionary with initial values and value names as keys. + + .. automethod:: set + + :param name: name of the value + :param value: value itself + + + +.. autoclass:: Counter + :show-inheritance: + + Argument `init_values` is a dictionary with initial values and value names as keys. + If reset is True, Counter resets every 60 seconds. + + .. automethod:: add + + .. automethod:: sub + + +.. autoclass:: EPSCounter + :show-inheritance: + + +.. autoclass:: DutyCycle + :show-inheritance: + + +.. autoclass:: AggregationCounter + :show-inheritance: + + Values (their names and init_values) can be provided when initializing the metrics or added with :func:`set` method. + :func:`add` and :func:`sub` methods are not implemented. + + .. automethod:: set + + Applies aggregation function on recent Counter value and value in argument and sets the result as new value of the Counter. + + + +.. autoclass:: Histogram + :show-inheritance: + + .. automethod:: set + + + +.. autoclass:: CounterWithDynamicTags + :show-inheritance: + + .. automethod:: add + + .. automethod:: sub + + + +.. autoclass:: AggregationCounterWithDynamicTags + :show-inheritance: + + .. automethod:: set + + + +.. autoclass:: HistogramWithDynamicTags + :show-inheritance: + + .. automethod:: set + diff --git a/doc/asab/module.rst b/old_docs/_build/html/_sources/asab/module.rst.txt similarity index 100% rename from doc/asab/module.rst rename to old_docs/_build/html/_sources/asab/module.rst.txt diff --git a/old_docs/_build/html/_sources/asab/pubsub.rst.txt b/old_docs/_build/html/_sources/asab/pubsub.rst.txt new file mode 100644 index 000000000..7d399becc --- /dev/null +++ b/old_docs/_build/html/_sources/asab/pubsub.rst.txt @@ -0,0 +1,225 @@ +Publish-Subscribe +================= + +.. py:currentmodule:: asab + +Publish–subscribe is a messaging pattern where senders of messages, called publishers, send the messages to receivers, called subscribers, via PubSub message bus. Publishers don't directly interact with subscribers in any way. Similarly, subscribers express interest in one or more message types and only receive messages that are of interest, without knowledge of which publishers, if any, there are. + +.. py:class:: PubSub(app) + +ASAB ``PubSub`` operates with a simple messages, defined by their *message type*, which is a string. +We recommend to add ``!`` (explamation mark) at the end of the message type in order to distinguish this object from other types such as Python class names or functions. +Example of the message type is e.g. :any:`Application.run!` or :any:`Application.tick/600!`. + +The message can carry an optional positional and keyword arguments. +The delivery of a message is implemented as a the standard Python function. + + +*Note:* There is an default, application-wide Publish-Subscribe message bus at :any:`Application.PubSub` that can be used to send messages. +Alternatively, you can create your own instance of :py:class:`PubSub` and enjoy isolated PubSub delivery space. + + +Subscription +------------ + +.. py:method:: PubSub.subscribe(message_type, callback) + +Subscribe to a message type. Messages will be delivered to a ``callback`` callable (function or method). +The ``callback`` can be a standard callable or an ``async`` coroutine. +Asynchronous ``callback`` means that the delivery of the message will happen in a ``Future``, asynchronously. + +``Callback`` callable will be called with the first argument + +Example of a subscription to an :any:`Application.tick!` messages. + +.. code:: python + + class MyClass(object): + def __init__(self, app): + app.PubSub.subscribe("Application.tick!", self.on_tick) + + def on_tick(self, message_type): + print(message_type) + + +Asynchronous version of the above: + +.. code:: python + + class MyClass(object): + def __init__(self, app): + app.PubSub.subscribe("Application.tick!", self.on_tick) + + async def on_tick(self, message_type): + await asyncio.sleep(5) + print(message_type) + + +.. py:method:: PubSub.subscribe_all(obj) + +To simplify the process of subscription to :any:`PubSub`, ASAB offers the decorator-based *"subscribe all"* functionality. + + +In the followin example, both ``on_tick()`` and ``on_exit()`` methods are subscribed to :any:`Application.PubSub` message bus. + +.. code:: python + + class MyClass(object): + def __init__(self, app): + app.PubSub.subscribe_all(self) + + @asab.subscribe("Application.tick!") + async def on_tick(self, message_type): + print(message_type) + + @asab.subscribe("Application.exit!") + def on_exit(self, message_type): + print(message_type) + + +.. py:method:: PubSub.unsubscribe(message_type, callback) + +Unsubscribe from a message delivery. + + +.. autoclass:: asab.Subscriber + :members: + :undoc-members: + +The subscriber object can be also used as `an asynchonous generator`. +The example of the subscriber object usage in `async for` statement: + +.. code:: python + + async def my_coroutine(self): + # Subscribe for a two application events + subscriber = asab.Subscriber( + self.PubSub, + "Application.tick!", + "Application.exit!" + ) + async for message_type, args, kwargs in subscriber: + if message_type == "Application.exit!": + break; + print("Tick.") + + +Publishing +---------- + +.. py:method:: PubSub.publish(message_type, \*args, \**kwargs) + +Publish a message to the PubSub message bus. +It will be delivered to each subscriber synchronously. +It means that the method returns after each subscribed ``callback`` is called. + +The example of a message publish to the :any:`Application.PubSub` message bus: + +.. code:: python + + def my_function(app): + app.PubSub.publish("mymessage!") + + +Asynchronous publishing of a message is requested by ``asynchronously=True`` argument. +The ``publish()`` method returns immediatelly and the delivery of the message to subscribers happens, when control returns to the event loop. + +The example of a **asynchronous version** of a message publish to the :any:`Application.PubSub` message bus: + +.. code:: python + + def my_function(app): + app.PubSub.publish("mymessage!", asynchronously=True) + + +Synchronous vs. asynchronous messaging +-------------------------------------- + +ASAB PubSub supports both modes of a message delivery: synchronous and asynchronous. +Moreover, PubSub also deals with modes, when asynchronous code (coroutine) does publish to synchronous code and vice versa. + ++-----------------+------------------------+---------------------------------------------+ +| | Sync publish | Async publish | ++-----------------+------------------------+---------------------------------------------+ +| Sync subscribe | Called immediately | ``call_soon(...)`` | ++-----------------+------------------------+---------------------------------------------+ +| Async subscribe | ``ensure_future(...)`` | ``call_soon(...)`` & ``ensure_future(...)`` | ++-----------------+------------------------+---------------------------------------------+ + + +Application-wide PubSub +------------------------ + +.. py:attribute:: Application.PubSub + +The ASAB provides the application-wide Publish-Subscribe message bus. + + +Well-Known Messages +^^^^^^^^^^^^^^^^^^^ + +This is a list of well-known messages, that are published on a ``Application.PubSub`` by ASAB itself. + + +.. option:: Application.init! + +This message is published when application is in the init-time. +It is actually one of the last things done in init-time, so the application environment is almost ready for use. +It means that configuration is loaded, logging is setup, the event loop is constructed etc. + + +.. option:: Application.run! + +This message is emitted when application enters the run-time. + + +.. option:: Application.stop! + +This message is emitted when application wants to stop the run-time. +It can be sent multiple times because of a process of graceful run-time termination. +The first argument of the message is a counter that increases with every ``Application.stop!`` event. + + +.. option:: Application.exit! + +This message is emitted when application enter the exit-time. + + +.. option:: Application.tick! +.. option:: Application.tick/10! +.. option:: Application.tick/60! +.. option:: Application.tick/300! +.. option:: Application.tick/600! +.. option:: Application.tick/1800! +.. option:: Application.tick/3600! +.. option:: Application.tick/43200! +.. option:: Application.tick/86400! + +The application publish periodically "tick" messages. +The default tick frequency is 1 second but you can change it by configuration ``[general] tick_period``. +:any:`Application.tick!` is published every tick. :any:`Application.tick/10!` is published every 10th tick and so on. + + +.. option:: Application.hup! + +This message is emitted when application receives UNIX signal ``SIGHUP`` or equivalent. + +.. option:: Application.housekeeping! + +This message is published when application is on the time for housekeeping. The time for housekeeping is set to 03:00 AM UTC by default. + +The app listens every ten minutes to see if it's time for housekeeping. If the UTC time reaches the value for housekeeping, the app will publish it and set the time for the next housekeeping for the next day at the same time. +There is also a time limit, which is set to 05:00 AM UTC by default. If the computer is in a sleep state, housekeeping will not be performed. Then, when the computer is reawakened again, it will check if it has exceeded the time limit. If not, then housekeeping will be published. If it has exceeded it, it simply informs the user and sets the housekeeping time for the next day. +Note that this only limits the time when the housekeeping can start. If the housekeeping event triggers a procedure that takes a long time to finish, it will not be terminated when the time limit is reached. + +Both housekeeping time and time limit can be changed in the configuration file: + +.. code:: ini + + [housekeeping] + at=19:30 + limit=21:00 + +This sets the housekeeping time to 7:30 PM UTC and the time limit to 9:00 PM UTC. +The time must be written in the format 'HH:MM'. +Remind yourself that the time is set to UTC, so you should be careful when operating in a different timezone. diff --git a/doc/asab/service.rst b/old_docs/_build/html/_sources/asab/service.rst.txt similarity index 100% rename from doc/asab/service.rst rename to old_docs/_build/html/_sources/asab/service.rst.txt diff --git a/doc/asab/storage.rst b/old_docs/_build/html/_sources/asab/storage.rst.txt similarity index 100% rename from doc/asab/storage.rst rename to old_docs/_build/html/_sources/asab/storage.rst.txt diff --git a/doc/asab/various.rst b/old_docs/_build/html/_sources/asab/various.rst.txt similarity index 100% rename from doc/asab/various.rst rename to old_docs/_build/html/_sources/asab/various.rst.txt diff --git a/old_docs/_build/html/_sources/asab/web/authn.rst.txt b/old_docs/_build/html/_sources/asab/web/authn.rst.txt new file mode 100644 index 000000000..0926ac926 --- /dev/null +++ b/old_docs/_build/html/_sources/asab/web/authn.rst.txt @@ -0,0 +1,75 @@ +Authn module +================= + +.. py:currentmodule:: asab.web.authn + +Module :py:mod:`asab.web.authn` provides middlewares and classes to allow only authorized users access specified web server endpoints. +It also allows to forward requests to the authorization server via instance of OAuthForwarder. + +Currently available authorization technologies include OAuth 2.0, public/private key and HTTP basic auth. + +Middleware +------------ + +.. py:method:: authn_middleware_factory(app, implementation, *args, **kwargs): + +First step is to define the authorization implementation, which can be the OAuth 2.0, public/private key or +HTTP basic auth. Depending on the implementation, there are arguments which further specify the authorization +servers that are going to be used. + +When it comes to OAuth 2.0, there are :any:`methods` for every OAuth 2.0 server, that is going to be used for authorization +and obtainment of the user identity. The relevant method is selected based on access token prefix, that is received +from the client in the HTTP request (:any:`Authorization` header): + +`Authorization: Bearer -` + +The following example illustrates how to register a middleware inside the web server container with OAuth 2.0 +implementation and GitHub method. + +.. code:: python + + container.WebApp.middlewares.append( + asab.web.authn.authn_middleware_factory(self, + "oauth2client", # other implementations include: "basicauth" and "pubkeyauth" + methods=[ + # Use GitHub OAuth provider + asab.web.authn.oauth.GitHubOAuthMethod(), + ], + ) + ) + + +Decorators +------------ + +In order to require authorization for a specific endpoint and thus utilize the output of the registered middleware, +it is necessary to decorate its handler method with :any:`authn_required_handler` decorator. + +The decorator provide the handler method with an :any:`identity` argument, which contains the user identity received +from the authorization server. Thus the user information can be further evaluated or included as part of the response. +To receive just the identity information but not force the authorization for the endpoint, the :any:`authn_optional_handler` +can be used instead. + +The following example illustrates how to use the :any:`authn_required_handler` decorator in order to enforce the +authorization and receive user identity in the :any:`identity` argument: + +.. code:: python + + @asab.web.authn.authn_required_handler + async def user(self, request, *, identity): + return asab.web.rest.json_response(request=request, data={ + 'message': '"{}", you have accessed our secured "user" endpoint.'.format(identity), + }) + + +Example +------------ + +To see & try the full example which utilizes OAuth 2.0 middleware and decorators, please see the code +in the following link: + +`https://github.com/TeskaLabs/asab/blob/master/examples/web-authn-oauth.py `_ + +Another example serves to demonstrate the public/private key authorization via ASAB web client ssl cert authorization: + +`https://github.com/TeskaLabs/asab/blob/master/examples/web-authn-pubkey.py `_ diff --git a/doc/asab/web/cors.rst b/old_docs/_build/html/_sources/asab/web/cors.rst.txt similarity index 100% rename from doc/asab/web/cors.rst rename to old_docs/_build/html/_sources/asab/web/cors.rst.txt diff --git a/doc/asab/web/index.rst b/old_docs/_build/html/_sources/asab/web/index.rst.txt similarity index 100% rename from doc/asab/web/index.rst rename to old_docs/_build/html/_sources/asab/web/index.rst.txt diff --git a/doc/asab/web/restapidocs.rst b/old_docs/_build/html/_sources/asab/web/restapidocs.rst.txt similarity index 100% rename from doc/asab/web/restapidocs.rst rename to old_docs/_build/html/_sources/asab/web/restapidocs.rst.txt diff --git a/doc/asab/zookeeper.rst b/old_docs/_build/html/_sources/asab/zookeeper.rst.txt similarity index 100% rename from doc/asab/zookeeper.rst rename to old_docs/_build/html/_sources/asab/zookeeper.rst.txt diff --git a/doc/get-started.rst b/old_docs/_build/html/_sources/get-started.rst.txt similarity index 100% rename from doc/get-started.rst rename to old_docs/_build/html/_sources/get-started.rst.txt diff --git a/old_docs/_build/html/_sources/index.rst.txt b/old_docs/_build/html/_sources/index.rst.txt new file mode 100644 index 000000000..9a9a7147a --- /dev/null +++ b/old_docs/_build/html/_sources/index.rst.txt @@ -0,0 +1,54 @@ +.. ASAB documentation master file, created by + +.. include:: asab/index.rst + +.. toctree:: + :maxdepth: 1 + :caption: Introduction + + get-started + tutorial/web/chapter1 + tutorial/web/chapter2 + +.. toctree:: + :maxdepth: 2 + :caption: Services + + asab/web/index + asab/web/restapidocs + asab/web/authn + asab/web/cors + asab/metrics + asab/storage + asab/alert + +.. toctree:: + :maxdepth: 2 + :caption: Reference + + asab/application + asab/config + asab/log + asab/pubsub + asab/service + asab/module + asab/various + asab/zookeeper + asab/library + +.. toctree:: + :maxdepth: 2 + :caption: Administration + + admin/install + admin/command-line + admin/containers + admin/systemd + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/doc/tutorial/web/chapter1.rst b/old_docs/_build/html/_sources/tutorial/web/chapter1.rst.txt similarity index 100% rename from doc/tutorial/web/chapter1.rst rename to old_docs/_build/html/_sources/tutorial/web/chapter1.rst.txt diff --git a/doc/tutorial/web/chapter2.rst b/old_docs/_build/html/_sources/tutorial/web/chapter2.rst.txt similarity index 100% rename from doc/tutorial/web/chapter2.rst rename to old_docs/_build/html/_sources/tutorial/web/chapter2.rst.txt diff --git a/old_docs/_build/html/_static/alabaster.css b/old_docs/_build/html/_static/alabaster.css new file mode 100644 index 000000000..517d0b29c --- /dev/null +++ b/old_docs/_build/html/_static/alabaster.css @@ -0,0 +1,703 @@ +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: Georgia, serif; + font-size: 17px; + background-color: #fff; + color: #000; + margin: 0; + padding: 0; +} + + +div.document { + width: 940px; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 220px; +} + +div.sphinxsidebar { + width: 220px; + font-size: 14px; + line-height: 1.5; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #fff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +div.body > .section { + text-align: left; +} + +div.footer { + width: 940px; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +p.caption { + font-family: inherit; + font-size: inherit; +} + + +div.relations { + display: none; +} + + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0; + margin: -10px 0 0 0px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo { + margin-top: -10px; + text-align: center; + margin-bottom: 5px; + text-align: left; +} + +div.sphinxsidebarwrapper h1.logo-name { + margin-top: 0px; +} + +div.sphinxsidebarwrapper p.blurb { + margin-top: 0; + font-style: normal; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: Georgia, serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar ul li.toctree-l1 > a { + font-size: 120%; +} + +div.sphinxsidebar ul li.toctree-l2 > a { + font-size: 110%; +} + +div.sphinxsidebar input { + border: 1px solid #CCC; + font-family: Georgia, serif; + font-size: 1em; +} + +div.sphinxsidebar hr { + border: none; + height: 1px; + color: #AAA; + background: #AAA; + + text-align: left; + margin-left: 0; + width: 50%; +} + +div.sphinxsidebar .badge { + border-bottom: none; +} + +div.sphinxsidebar .badge:hover { + border-bottom: none; +} + +/* To address an issue with donation coming after search */ +div.sphinxsidebar h3.donation { + margin-top: 10px; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: Georgia, serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #DDD; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #EAEAEA; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + margin: 20px 0px; + padding: 10px 30px; + background-color: #EEE; + border: 1px solid #CCC; +} + +div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fafafa; +} + +div.admonition p.admonition-title { + font-family: Georgia, serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: #fff; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.warning { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.danger { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.error { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.caution { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.attention { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.important { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.note { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.tip { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.hint { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.seealso { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.topic { + background-color: #EEE; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt, code { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +.hll { + background-color: #FFC; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +img.screenshot { +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.95em; +} + +tt.descname, code.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #EEE; + background: #FDFDFD; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.field-list p { + margin-bottom: 0.8em; +} + +/* Cloned from + * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 + */ +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +table.footnote td.label { + width: .1px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + /* Matches the 30px from the narrow-screen "li > ul" selector below */ + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #EEE; + padding: 7px 30px; + margin: 15px 0px; + line-height: 1.3em; +} + +div.viewcode-block:target { + background: #ffd; +} + +dl pre, blockquote pre, li pre { + margin-left: 0; + padding-left: 30px; +} + +tt, code { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, code.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fff; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +/* Don't put an underline on images */ +a.image-reference, a.image-reference:hover { + border-bottom: none; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt, a:hover code { + background: #EEE; +} + + +@media screen and (max-width: 870px) { + + div.sphinxsidebar { + display: none; + } + + div.document { + width: 100%; + + } + + div.documentwrapper { + margin-left: 0; + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + } + + div.bodywrapper { + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + margin-left: 0; + } + + ul { + margin-left: 0; + } + + li > ul { + /* Matches the 30px from the "ul, ol" selector above */ + margin-left: 30px; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .bodywrapper { + margin: 0; + } + + .footer { + width: auto; + } + + .github { + display: none; + } + + + +} + + + +@media screen and (max-width: 875px) { + + body { + margin: 0; + padding: 20px 30px; + } + + div.documentwrapper { + float: none; + background: #fff; + } + + div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: #FFF; + } + + div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + div.sphinxsidebar h3 a { + color: #fff; + } + + div.sphinxsidebar a { + color: #AAA; + } + + div.sphinxsidebar p.logo { + display: none; + } + + div.document { + width: 100%; + margin: 0; + } + + div.footer { + display: none; + } + + div.bodywrapper { + margin: 0; + } + + div.body { + min-height: 0; + padding: 0; + } + + .rtd_doc_footer { + display: none; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .footer { + width: auto; + } + + .github { + display: none; + } +} + + +/* misc. */ + +.revsys-inline { + display: none!important; +} + +/* Make nested-list/multi-paragraph items look better in Releases changelog + * pages. Without this, docutils' magical list fuckery causes inconsistent + * formatting between different release sub-lists. + */ +div#changelog > div.section > ul > li > p:only-child { + margin-bottom: 0; +} + +/* Hide fugly table cell borders in ..bibliography:: directive output */ +table.docutils.citation, table.docutils.citation td, table.docutils.citation th { + border: none; + /* Below needed in some edge cases; if not applied, bottom shadows appear */ + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + + +/* relbar */ + +.related { + line-height: 30px; + width: 100%; + font-size: 0.9rem; +} + +.related.top { + border-bottom: 1px solid #EEE; + margin-bottom: 20px; +} + +.related.bottom { + border-top: 1px solid #EEE; +} + +.related ul { + padding: 0; + margin: 0; + list-style: none; +} + +.related li { + display: inline; +} + +nav#rellinks { + float: right; +} + +nav#rellinks li+li:before { + content: "|"; +} + +nav#breadcrumbs li+li:before { + content: "\00BB"; +} + +/* Hide certain items when printing */ +@media print { + div.related { + display: none; + } +} \ No newline at end of file diff --git a/doc/_static/asab-architecture.png b/old_docs/_build/html/_static/asab-architecture.png similarity index 100% rename from doc/_static/asab-architecture.png rename to old_docs/_build/html/_static/asab-architecture.png diff --git a/old_docs/_build/html/_static/basic.css b/old_docs/_build/html/_static/basic.css new file mode 100644 index 000000000..7577acb1a --- /dev/null +++ b/old_docs/_build/html/_static/basic.css @@ -0,0 +1,903 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/old_docs/_build/html/_static/custom.css b/old_docs/_build/html/_static/custom.css new file mode 100644 index 000000000..2a924f1d6 --- /dev/null +++ b/old_docs/_build/html/_static/custom.css @@ -0,0 +1 @@ +/* This file intentionally left blank. */ diff --git a/old_docs/_build/html/_static/doctools.js b/old_docs/_build/html/_static/doctools.js new file mode 100644 index 000000000..d06a71d75 --- /dev/null +++ b/old_docs/_build/html/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/old_docs/_build/html/_static/documentation_options.js b/old_docs/_build/html/_static/documentation_options.js new file mode 100644 index 000000000..b57ae3b83 --- /dev/null +++ b/old_docs/_build/html/_static/documentation_options.js @@ -0,0 +1,14 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/old_docs/_build/html/_static/file.png b/old_docs/_build/html/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/_static/language_data.js b/old_docs/_build/html/_static/language_data.js new file mode 100644 index 000000000..250f5665f --- /dev/null +++ b/old_docs/_build/html/_static/language_data.js @@ -0,0 +1,199 @@ +/* + * language_data.js + * ~~~~~~~~~~~~~~~~ + * + * This script contains the language-specific data used by searchtools.js, + * namely the list of stopwords, stemmer, scorer and splitter. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; + + +/* Non-minified version is copied as a separate JS file, is available */ + +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/old_docs/_build/html/_static/minus.png b/old_docs/_build/html/_static/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..d96755fdaf8bb2214971e0db9c1fd3077d7c419d GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^+#t*WBp7;*Yy1LIik>cxAr*|t7R?Mi>2?kWtu=nj kDsEF_5m^0CR;1wuP-*O&G^0G}KYk!hp00i_>zopr08q^qX#fBK literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/_static/plus.png b/old_docs/_build/html/_static/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..7107cec93a979b9a5f64843235a16651d563ce2d GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^+#t*WBp7;*Yy1LIik>cxAr*|t7R?Mi>2?kWtu>-2 m3q%Vub%g%s<8sJhVPMczOq}xhg9DJoz~JfX=d#Wzp$Pyb1r*Kz literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/_static/pygments.css b/old_docs/_build/html/_static/pygments.css new file mode 100644 index 000000000..691aeb82d --- /dev/null +++ b/old_docs/_build/html/_static/pygments.css @@ -0,0 +1,74 @@ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #eeffcc; } +.highlight .c { color: #408090; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #007020; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #007020 } /* Comment.Preproc */ +.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #333333 } /* Generic.Output */ +.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0044DD } /* Generic.Traceback */ +.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #007020 } /* Keyword.Pseudo */ +.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #902000 } /* Keyword.Type */ +.highlight .m { color: #208050 } /* Literal.Number */ +.highlight .s { color: #4070a0 } /* Literal.String */ +.highlight .na { color: #4070a0 } /* Name.Attribute */ +.highlight .nb { color: #007020 } /* Name.Builtin */ +.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ +.highlight .no { color: #60add5 } /* Name.Constant */ +.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #007020 } /* Name.Exception */ +.highlight .nf { color: #06287e } /* Name.Function */ +.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ +.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #bb60d5 } /* Name.Variable */ +.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mb { color: #208050 } /* Literal.Number.Bin */ +.highlight .mf { color: #208050 } /* Literal.Number.Float */ +.highlight .mh { color: #208050 } /* Literal.Number.Hex */ +.highlight .mi { color: #208050 } /* Literal.Number.Integer */ +.highlight .mo { color: #208050 } /* Literal.Number.Oct */ +.highlight .sa { color: #4070a0 } /* Literal.String.Affix */ +.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ +.highlight .sc { color: #4070a0 } /* Literal.String.Char */ +.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ +.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4070a0 } /* Literal.String.Double */ +.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ +.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ +.highlight .sx { color: #c65d09 } /* Literal.String.Other */ +.highlight .sr { color: #235388 } /* Literal.String.Regex */ +.highlight .s1 { color: #4070a0 } /* Literal.String.Single */ +.highlight .ss { color: #517918 } /* Literal.String.Symbol */ +.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #06287e } /* Name.Function.Magic */ +.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ +.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ +.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ +.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ +.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/old_docs/_build/html/_static/searchtools.js b/old_docs/_build/html/_static/searchtools.js new file mode 100644 index 000000000..97d56a74d --- /dev/null +++ b/old_docs/_build/html/_static/searchtools.js @@ -0,0 +1,566 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = docUrlRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = docUrlRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms) + ); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = _( + `Search finished, found ${resultCount} page(s) matching the search query.` + ); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent !== undefined) return docContent.textContent; + console.warn( + "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + /** + * execute search (requires search index to be loaded) + */ + query: (query) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + // array of [docname, title, anchor, descr, score, filename] + let results = []; + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + let score = Math.round(100 * queryLower.length / title.length) + results.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id] of foundEntries) { + let score = Math.round(100 * queryLower.length / entry.length) + results.push([ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // lookup as object + objectTerms.forEach((term) => + results.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); + + // now sort the results by score (in opposite order of appearance, since the + // display function below uses pop() to retrieve items) and then + // alphabetically + results.sort((a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; + }); + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + results = results.reverse(); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord) && !terms[word]) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord) && !titleTerms[word]) + arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); + }); + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) + fileMap.get(file).push(word); + else fileMap.set(file, [word]); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords) => { + const text = Search.htmlToText(htmlText); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/old_docs/_build/html/_static/sphinx_highlight.js b/old_docs/_build/html/_static/sphinx_highlight.js new file mode 100644 index 000000000..aae669d7e --- /dev/null +++ b/old_docs/_build/html/_static/sphinx_highlight.js @@ -0,0 +1,144 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + parent.insertBefore( + span, + parent.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(SphinxHighlight.highlightSearchWords); +_ready(SphinxHighlight.initEscapeListener); diff --git a/old_docs/_build/html/admin/command-line.html b/old_docs/_build/html/admin/command-line.html new file mode 100644 index 000000000..35a314bf9 --- /dev/null +++ b/old_docs/_build/html/admin/command-line.html @@ -0,0 +1,209 @@ + + + + + + + + + ASAB Command-line interface — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

ASAB Command-line interface

+

ASAB-based application provides the command-line interface by default. +Here is an overview of the common command-line arguments.

+
+
+-h, --help
+
+ +

Show a help.

+
+

Configuration

+
+
+-c <CONFIG>,--config <CONFIG>
+
+ +

Load configuration file from a file CONFIG.

+
+
+

Logging

+
+
+-v, --verbose
+
+ +

Increase the logging level to DEBUG aka be more verbose about what is happening.

+
+
+-l <LOG_FILE>,--log-file <LOG_FILE>
+
+ +

Log to a file LOG_FILE.

+
+
+-s, --syslog
+
+ +

Log to a syslog.

+
+
+

Daemon

+

Python module python-daemon has to be installed in order to support daemonosation functions.

+
$ pip3 install asab python-daemon
+
+
+
+
+-d, --daemonize
+
+ +

Launch the application in the background aka daemonized.

+

Daemon-related section of Config file:

+
[daemon]
+pidfile=/var/run/myapp.pid
+uid=nobody
+gid=nobody
+working_dir=/tmp
+
+
+

Configuration options pidfile, uid , gid and working_dir are supported.

+
+
+-k, --kill
+
+ +

Shutdown the application running in the background (started previously with -d argument).

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/admin/containers.html b/old_docs/_build/html/admin/containers.html new file mode 100644 index 000000000..761e00219 --- /dev/null +++ b/old_docs/_build/html/admin/containers.html @@ -0,0 +1,234 @@ + + + + + + + + + Containerisation — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Containerisation

+

ASAB is designed for deployment into containers such as LXC/LXD or Docker. +It allows to build e.g. microservices that provides REST interface or consume MQ messages while being deployed into a container for a sake of the infrastructure flexibility.

+
+

ASAB in a LXC/LXD container

+
    +
  1. Prepare LXC/LXD container based on Alpine Linux

  2. +
+
$ lxc launch images:alpine/3.10 asab
+
+
+
    +
  1. Swich into a container

  2. +
+
$ lxc exec asab -- /bin/ash
+
+
+
    +
  1. Prepare Python3 environment

  2. +
+
$ apk update
+$ apk upgrade
+$ apk add --no-cache python3
+
+$ python3 -m ensurepip
+
+
+
    +
  1. Deploy ASAB

  2. +
+
$ apk add --virtual .buildenv python3-dev gcc musl-dev git
+$ pip3 install git+https://github.com/TeskaLabs/asab
+$ apk del .buildenv
+
+
+
    +
  1. Deploy dependencies

  2. +
+
$ pip3 install python-daemon
+
+
+
    +
  1. Use OpenRC to automatically start/stop ASAB application

  2. +
+
$ vi /etc/init.d/asab-app
+
+
+

Adjust the example of OpenRC init file.

+
$ chmod a+x /etc/init.d/asab-app
+$ rc-update add asab-app
+
+
+

Note: If you need to install python packages that require compilation using C compiler, you have to add following dependencies:

+
$ apk add --virtual .buildenv python3-dev
+$ apk add --virtual .buildenv gcc
+$ apk add --virtual .buildenv musl-dev
+
+
+

And removal of the build tools after pip install:

+
$ apk del .buildenv
+
+
+
+
+

Docker Remote API

+

In order for ASAB applications to read the Docker container name +as well as other information related to the container to be used in logs, metrics and other analysis, +the Docker Remote API must be enabled.

+

To do so:

+
    +
  1. Open the docker service file

  2. +
+
vi /lib/systemd/system/docker.service
+
+
+
    +
  1. Find the line which starts with ExecStart and add -H=tcp://0.0.0.0:2375

  2. +
  3. Save the file

  4. +
  5. Reload the docker daemon and restart the Docker service

  6. +
+
sudo systemctl daemon-reload && sudo service docker restart
+
+
+

Then in the ASAB application’s configuration, provide +the Docker Socket path in docker_socket configuration option:

+
[general]
+docker_socket=<YOUR_DOCKER_SOCKET_FILE>
+
+
+

Thus, the metric service as well as log manager can use the container +name as hostname instead of container ID, which provides better readability +when analyzing the logs and metrics, typically using InfluxDB and Grafana.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/admin/install.html b/old_docs/_build/html/admin/install.html new file mode 100644 index 000000000..14f3c581e --- /dev/null +++ b/old_docs/_build/html/admin/install.html @@ -0,0 +1,165 @@ + + + + + + + + + Installation — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Installation

+

ASAB is distributed via pypi.

+
+

Install ASAB using pip

+

This is the recommended installation method.

+
$ pip install asab
+
+
+
+
+

Install ASAB using easy_install

+
$ easy_install asab
+
+
+
+
+

Install ASAB for a GitHub

+

To install ASAB from a master branch of the GIT repository, use following command.

+

Note: Git has to be installed in order to successfuly complete the installation.

+
$ pip install git+https://github.com/TeskaLabs/asab.git
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/admin/systemd.html b/old_docs/_build/html/admin/systemd.html new file mode 100644 index 000000000..f937dabc5 --- /dev/null +++ b/old_docs/_build/html/admin/systemd.html @@ -0,0 +1,172 @@ + + + + + + + + + systemd — ASAB documentation + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

systemd

+
    +
  1. Create a new Systemd unit file in /etc/systemd/system/:

  2. +
+
$ sudo vi /etc/systemd/system/asab.service
+
+
+

Adjust the example of SystemD unit file.

+
    +
  1. Let systemd know that there is a new service:

  2. +
+
$ sudo systemctl enable asab
+
+
+

To reload existing unit file after changing, use this:

+
$ sudo systemctl daemon-reload
+
+
+
    +
  1. ASAB Application Server service for systemd is now ready.

  2. +
+
+

Start of ASAB Server

+
$ sudo service asab start
+
+
+
+
+

Stop of ASAB Server

+
$ sudo service asab stop
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/alert.html b/old_docs/_build/html/asab/alert.html new file mode 100644 index 000000000..d6e41234a --- /dev/null +++ b/old_docs/_build/html/asab/alert.html @@ -0,0 +1,211 @@ + + + + + + + + + Alert Service — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Alert Service

+

Integrate ASAB Application with alert managers.

+

There are currently two possible target systems for the alerts available:

+ +

Everything you need to do is to import the service, trigger the alert and specify the target in the configuration.

+
class MyApplication(asab.Application):
+    async def initialize(self):
+        from asab.alert import AlertService
+        self.AlertService = AlertService(self)
+        self.AlertService.trigger(
+            source="my-tenant",
+            alert_cls="my-class",
+            alert_id="deduplication-id01",
+            title="Something went wrong.",
+            detail={
+                "example1": "additional-info",
+                "example2": "additional-info",
+            },
+        )
+
+if __name__ == '__main__':
+    app = MyApplication()
+    app.run()
+
+
+
+

Opsgenie

+
    +
  • Create an account at Opsgenie.

  • +
  • In your Opsgenie account, create a new Team.

  • +
  • Add integration to your Team - choose API.

  • +
  • API Key will be generated for you.

  • +
+

myapplication.conf

+
[asab:alert:opsgenie]
+api_key=my-api-key
+tags=my-tag, my-application
+url=https://api.eu.opsgenie.com  # this is default value
+
+
+
+
+

PagerDuty

+
    +
  • Create an account at PagerDuty.

  • +
  • In your PagerDuty account, generate Api Key (Integrations > Developer Tools > Api Access Keys).

  • +
  • Create a new Service in Service Directory and add integration in the Integrations folder.

  • +
  • Choose Events API V2. An Integration Key will be generated for you.

  • +
+

myapplication.conf

+
[asab:alert:pagerduty]
+api_key=my-api-key
+integration_key=my-integration-key
+url=https://events.pagerduty.com  # this is default value
+
+
+
+
+

De-duplication

+

alert_id argument serves as a de-duplication ID for the third-party services. It enables the grouping of alerts and prevents noise. +More about alert grouping:

+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/application.html b/old_docs/_build/html/asab/application.html new file mode 100644 index 000000000..506303f1a --- /dev/null +++ b/old_docs/_build/html/asab/application.html @@ -0,0 +1,372 @@ + + + + + + + + + Application — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Application

+
+
+class asab.Application[source]
+
+ +

The Application class maintains the global application state. +You can provide your own implementation by creating a subclass. +There should be only one Application object in the process.

+

Subclassing:

+
import asab
+
+class MyApplication(asab.Application):
+    pass
+
+if __name__ == '__main__':
+    app = MyApplication()
+    app.run()
+
+
+

Direct use of Application object:

+
import asab
+
+if __name__ == '__main__':
+    app = asab.Application()
+    app.run()
+
+
+
+

Event Loop

+
+
+Application.Loop
+
+ +

The asyncio event loop that is used by this application.

+
asyncio.ensure_future(my_coro())
+
+
+
+
+

Application Lifecycle

+

The ASAB is designed around the Inversion of control principle. +It means that the ASAB is in control of the application lifecycle. +The custom-written code receives the flow from ASAB via callbacks or handlers. +Inversion of control is used to increase modularity of the code and make it extensible.

+

The application lifecycle is divided into 3 phases: init-time, run-time and exit-time.

+
+

Init-time

+
+
+Application.__init__()[source]
+
+ +

The init-time happens during Application constructor call. +The Publish-Subscribe message Application.init! is published during init-time. +The Config is loaded during init-time.

+
+
+Application.initialize()[source]
+
+ +

The application object executes asynchronous callback Application.initialize(), which can be overriden by an user.

+
class MyApplication(asab.Application):
+    async def initialize(self):
+        # Custom initialization
+        from module_sample import Module
+        self.add_module(Module)
+
+
+
+
+

Run-time

+
+
+Application.run()[source]
+
+ +

Enter a run-time. This is where the application spends the most time typically. +The Publish-Subscribe message Application.run! is published when run-time begins.

+

The method returns the value of Application.ExitCode.

+
+
+Application.main()[source]
+
+ +

The application object executes asynchronous callback Application.main(), which can be overriden. +If main() method is completed without calling stop(), then the application server will run forever (this is the default behaviour).

+
class MyApplication(asab.Application):
+    async def main(self):
+        print("Hello world!")
+        self.stop()
+
+
+
+
+Application.stop(exit_code: int = None)[source]
+
+ +

The method Application.stop() gracefully terminates the run-time and commence the exit-time. +This method is automatically called by SIGINT and SIGTERM. It also includes a response to Ctrl-C on UNIX-like system. +When this method is called 3x, it abruptly exits the application (aka emergency abort).

+

The parameter exit_code allows you to specify the application exit code (see Exit-Time chapter).

+

Note: You need to install win32api module to use Ctrl-C or an emergency abord properly with ASAB on Windows. It is an optional dependency of ASAB.

+
+
+

Exit-time

+
+
+Application.finalize()[source]
+
+ +

The application object executes asynchronous callback Application.finalize(), which can be overriden by an user.

+
class MyApplication(asab.Application):
+    async def finalize(self):
+        # Custom finalization
+        ...
+
+
+

The Publish-Subscribe message Application.exit! is published when exit-time begins.

+
+
+Application.set_exit_code(exit_code: int, force: bool = False)[source]
+
+ +

Set the exit code of the application, see os.exit() in the Python documentation. +If force is False, the exit code will be set only if the previous value is lower than the new one. +If force is True, the exit code value is set to a exit_code disregarding the previous value.

+
+
+Application.ExitCode
+
+ +

The actual value of the exit code.

+

The example of the exit code handling in the main() function of the application.

+
if __name__ == '__main__':
+    app = asab.Application()
+    exit_code = app.run()
+    sys.exit(exit_code)
+
+
+
+
+
+

Module registry

+

For more details see Module class.

+
+
+Application.add_module(module_class)[source]
+
+ +

Initialize and add a new module. +The module_class class will be instantiated during the method call.

+
class MyApplication(asab.Application):
+    async def initialize(self):
+        from my_module import MyModule
+        self.add_module(MyModule)
+
+
+
+
+Application.Modules
+
+ +

A list of modules that has been added to the application.

+
+
+

Service registry

+

Each service is identified by its unique service name. +For more details see Service class.

+
+
+Application.get_service(service_name)[source]
+
+ +

Locate a service by its service name in a registry and return the Service object.

+
svc = app.get_service("service_sample")
+svc.hello()
+
+
+
+
+Application.Services
+
+ +

A dictionary of registered services.

+
+
+

Command-line parser

+
+
+Application.create_argument_parser(prog=None, usage=None, description=None, epilog=None, prefix_chars='-', fromfile_prefix_chars=None, argument_default=None, conflict_handler='error', add_help=True) argparse.ArgumentParser[source]
+
+ +

Creates an argparse.ArgumentParser. +This method can be overloaded to adjust command-line argument parser.

+

Please refer to Python standard library argparse for more details about function arguments.

+
+
+Application.parse_args()
+
+ +

The application object calls this method during init-time to process a command-line arguments. +argparse is used to process arguments. +You can overload this method to provide your own implementation of command-line argument parser.

+
+
+Application.Description
+
+ +

The Description attribute is a text that will be displayed in a help text (--help). +It is expected that own value will be provided. +The default value is "" (empty string).

+
+
+

UTC Time

+
+
+Application.time() float[source]
+
+ +

Return the current “event loop time” in seconds since the epoch as a floating point number. +The specific date of the epoch and the handling of leap seconds is platform dependent. On Windows and most Unix systems, the epoch is January 1, 1970, 00:00:00 (UTC) and leap seconds are not counted towards the time in seconds since the epoch. This is commonly referred to as Unix time.

+

A call of the time.time() function could be expensive. +This method provides a cheaper version of the call that returns a current wall time in UTC.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/config.html b/old_docs/_build/html/asab/config.html new file mode 100644 index 000000000..df9d1f228 --- /dev/null +++ b/old_docs/_build/html/asab/config.html @@ -0,0 +1,353 @@ + + + + + + + + + Configuration — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Configuration

+
+
+asab.Config
+
+ +

The configuration is provided by Config object which is a singleton. It means that you can access Config from any place of your code, without need of explicit initialisation.

+
import asab
+
+# Initialize application object and hence the configuration
+app = asab.Application()
+
+# Access configuration values anywhere
+my_conf_value = asab.Config['section_name']['key1']
+
+
+
+

Based on ConfigParser

+

The Config is inherited from Python Standard Library configparser.ConfigParser class. which implements a basic configuration language which provides a structure similar to what’s found in Microsoft Windows INI files.

+
+
+class asab.config.ConfigParser[source]
+
+ +

Example of the configuration file:

+
[bitbucket.org]
+User = hg
+
+[topsecret.server.com]
+Port = 50022
+ForwardX11 = no
+
+
+

And this is how you access configuration values:

+
>>> asab.Config['topsecret.server.com']['ForwardX11']
+'no'
+
+
+
+
+

Multiline configuration entry

+

A multiline configuration entries are supported. +An example:

+
[section]
+key=
+  line1
+  line2
+  line3
+another_key=foo
+
+
+
+
+

Automatic load of configuration

+

If a configuration file name is specified, the configuration is automatically loaded from a configuration file during initialiation time of Application. +The configuration file name can be specified by one of -c command-line argument (1), ASAB_CONFIG environment variable (2) or config [general] config_file default value (3).

+
./sample_app.py -c ./etc/sample.conf
+
+
+
+
+

Including other configuration files

+

You can specify one or more additional configuration files that are loaded and merged from an main configuration file. +It is done by [general] include configuration value. Multiple paths are separated by os.pathsep (: on Unix). +The path can be specified as a glob (e.g. use of * and ? wildcard characters), it will be expanded by glob module from Python Standard Library. +Included configuration files may not exists, this situation is silently ignored.

+
[general]
+include=./etc/site.conf:./etc/site.d/*.conf
+
+
+

You can also use a multiline configuration entry:

+
[general]
+include=
+        ./etc/site.conf
+        ./etc/site.d/*.conf
+
+
+
+
+

Configuration default values

+
+
+Config.add_defaults(dictionary)
+
+ +

This is how you can extend configuration default values:

+
asab.Config.add_defaults(
+    {
+        'section_name': {
+            'key1': 'value',
+            'key2': 'another value'
+        },
+        'other_section': {
+            'key3': 'value',
+        },
+    }
+)
+
+
+

Only simple types (string, int and float) are allowed in the configuration values. +Don’t use complex types such as lists, dictionaries or objects because these are impossible to provide via configuration files etc.

+
+
+

Environment variables in configration

+

Environment variables found in values are automatically expanded.

+
[section_name]
+persistent_dir=${HOME}/.myapp/
+
+
+
>>> asab.Config['section_name']['persistent_dir']
+'/home/user/.myapp/'
+
+
+

There is a special environment variable ${THIS_DIR} that is expanded to a directory that contains a current configuration file. +It is useful in complex configurations that utilizes included configuration files etc.

+
[section_name]
+my_file=${THIS_DIR}/my_file.txt
+
+
+

Another environment variable ${HOSTNAME} contains the application hostname to be used f. e. in logging file path.

+
[section_name]
+my_file=${THIS_DIR}/${HOSTNAME}/my_file.txt
+
+
+
+
+

Passwords in configration

+

[passwords] section in the configuration serves to securely store passwords, +which are then not shown publicly in the default API config endpoint’s output.

+

It is convenient for the user to store passwords at one place, +so that they are not repeated in many sections of the config file(s).

+

Usage is as follows:

+
[connection:KafkaConnection]
+password=${passwords:kafka_password}
+
+[passwords]
+kafka_password=<MY_SECRET_PASSWORD>
+
+
+
+
+

Obtaining seconds

+
+
+Config.getseconds()
+
+ +

The seconds can be obtained using getseconds() method for values with different time +units specified in the configuration:

+
[sleep]
+sleep_time=5.2s
+another_sleep_time=10d
+
+
+

The available units are:

+
+
    +
  • y … years

  • +
  • M … months

  • +
  • w … weeks

  • +
  • d … days

  • +
  • h … hours

  • +
  • m … minutes

  • +
  • s … seconds

  • +
  • ms .. miliseconds

  • +
+
+

If no unit is specified, float of seconds is expected.

+

The obtainment of the second value in the code can be achieved in two ways:

+
self.SleepTime = asab.Config["sleep"].getseconds("sleep_time")
+self.AnotherSleepTime = asab.Config.getseconds("sleep", "another_sleep_time")
+
+
+
+
+

Obtaining URLs

+
+
+Config.geturl(section, option, scheme=None:str, tuple)
+
+ +

A URL can be obtained using a geturl() method that takes the URL from the config and +removes leading and trailing whitespaces and trailing backslashes.

+

There is an optional parameter called scheme that can have any URL scheme like +http, https, mongodb etc. Setting it to None, scheme validation gets bypassed.

+

Setting the scheme parameter to the same scheme as in the config, it will return the URL. +If it’s not the same it will raise an error.

+

There are two ways of obtaining the URL:

+
asab.Config["urls"].geturl("teskalabs", scheme="https")
+asab.Config.geturl("urls", "github", scheme=None)
+
+
+

Example:

+
>>> asab.Config["urls"].geturl("teskalabs", scheme="https")
+    'https://www.teskalabs.com'
+
+
+

For reference this would be the configuration file:

+
[urls]
+teskalabs=https://www.teskalabs.com/
+github=github.com
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/index.html b/old_docs/_build/html/asab/index.html new file mode 100644 index 000000000..24aa35545 --- /dev/null +++ b/old_docs/_build/html/asab/index.html @@ -0,0 +1,170 @@ + + + + + + + + + Asynchronous Server Application Boilerplate’s documentation — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Asynchronous Server Application Boilerplate’s documentation

+

Asynchronous Server App Boilerplate (or ASAB for short) is a microservice platform for Python 3.7+ and asyncio. +ASAB aims to minimize the amount of code that needs to be written when building a microservice or an application server. +ASAB is fully asynchronous using async/await syntax from Python 3, making your code modern, non-blocking, speedy and hence scalable. +We make every effort to build ASAB container-friendly so that you can deploy ASAB-based microservice via Docker or Kubernetes in a breeze.

+

ASAB is free and open-source software, available under BSD licence. +It means that anyone is freely licenced to use, copy, study, and change the software in any way, and the source code is openly shared so that people could voluntarily improve the design of the software. +Anyone can (and is encouraged to) use ASAB in his or her projects, for free. +A current maintainer is a TeskaLabs Ltd company.

+

ASAB is developed on GitHub. +Contributions are welcome!

+
+

ASAB is designed to be powerful yet simple

+

Here is a complete example of a fully working microservice:

+
import asab
+
+class MyApplication(asab.Application):
+    async def main(self):
+        print("Hello world!")
+        self.stop()
+
+if __name__ == "__main__":
+    app = MyApplication()
+    app.run()
+
+
+
+
+

ASAB is the right choice when

+
+
    +
  • using Python 3.7+.

  • +
  • building the microservice or the application server.

  • +
  • utilizing asynchronous I/O (aka asyncio).

  • +
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/library.html b/old_docs/_build/html/asab/library.html new file mode 100644 index 000000000..bdc6e1bbb --- /dev/null +++ b/old_docs/_build/html/asab/library.html @@ -0,0 +1,501 @@ + + + + + + + + + Library — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Library

+

The ASAB Library (asab.library) is a concept of the shared data content across microservices in the cluster. +The asab.library provides a read-only interface for listing and reading this content. +The library can also notify the ASAB microservice about changes, eg. for automated update/reload.

+

There is a companion microservice asab-library that can be used for management and editation of the library content. +The asab.library can however operate without asab-library microservice.

+
+

Library structure

+

The library content is organized in simplified filesystem manner, with directories and files.

+

Example of the library structure:

+
+ /folder1/
+  - /folder1/item1.yaml
+  - /folder1/item2.json
++ /folder2/
+  - /folder2/item3.yaml
+  + /folder2folder2.3/
+    - /folder2/folder2.3/item4.json
+
+
+
+
+

Library path rules

+
    +
  • Any path must start with /, including the root path (/).

  • +
  • The folder path must end with /.

  • +
  • The item path must end with extension (eg. .json).

  • +
+
+
+

Library service

+
+
+class asab.library.LibraryService(app, service_name, paths=None)[source]
+

ASAB library (aka LibraryService) is an abstration for unified filesystem-like access to resources. +In the cluster/cloud microservice architectures, it is imperative that all microservices have access to unified resources. +There are technologies such as Apache Zookeeper that provides means for it.

+

ASAB library builts on top of this concept and brings that into the ASAB microservice.

+

ASAB library is designed to be read-only. +It also allows to “stack” various libraries into one view (overlayed) that merges content of each library into one united space.

+

Configuration:

+

``` +[library] +providers:

+
+

provider+1:// +provider+2:// +provider+3://

+
+

```

+

The order of providers IS important, the priority (or layering) is top-down.

+

Each library provider is specified by URL/URI schema:

+
    +
  • zk:// or zookeeper:// for ZooKeeper provider

  • +
  • file:// or local path for FileSystem provider

  • +
  • azure+https:// for Microsoft Azure Storage provider.

  • +
+

The first provider is also responsible for providing /.disabled.yaml that controls a visibility of items. +If /.disabled.yaml is not present, then is considered empty.

+

A library is created in “not ready” state, each provider then inform library when it is ready (eg. Zookeeper provider needs to connect to Zookeeper servers). +Only after all providers are ready, the library itself become ready. +The library indicates that by the PubSub event Library.ready!.

+
+ +

Example of the use:

+
import asab
+
+class MyApplication(asab.Application):
+
+    def __init__(self):
+        super().__init__()
+
+        # Initialize the library service
+        self.LibraryService = asab.library.LibraryService(self, "LibraryService")
+        self.PubSub.subscribe("Library.ready!", self.on_library_ready)
+
+    async def on_library_ready(self, event_name, library):
+        print("# Library\n")
+
+        for item in await self.LibraryService.list("", recursive=True):
+            print(" *", item)
+            if item.type == 'item':
+                itemio = await self.LibraryService.read(item.name)
+                if itemio is not None:
+                    with itemio:
+                        content = itemio.read()
+                        print("  - content: {} bytes".format(len(content)))
+                else:
+                    print("  - (DISABLED)")
+
+
+
+
+async LibraryService.read(path: str, tenant: str | None = None) IO[source]
+

Read the content of the library item specified by path. +None is returned if the item is not found in the library.

+

If the item is disabled (globally or for specified tenant) then None is returned.

+

Example of use:

+

``` +itemio = await library.read(‘/path’, ‘tenant’) +if itemio is not None:

+
+
+
with itemio:

return itemio.read()

+
+
+
+

```

+
+
Parameters:
+
    +
  • path – The path to the file, LibraryItem.name can be used directly

  • +
  • tenant – The tenant to apply. If not specified, the global access is assumed

  • +
+
+
Returns:
+

I/O stream (read) with the content of the libary item.

+
+
+
+ +
+
+async LibraryService.list(path='/', tenant=None, recursive=False)[source]
+

List the directory of the library specified by the path. +It returns a list of LibraryItem entris.

+
+
Tenant is an optional parameter to list method for “disable” evaluation.

and default recursive is False.

+
+
When tenant=None

The method returns list of items that are enabled (not disabled).

+
+
When tenant=’xxxxx’

The method returns list of items that are enabled (not disabled) for tenant ‘xxxxx’.

+
+
When recursive=True

The method returns list of items that are located at path and in subdirectories of that location.

+
+
When recursive=False

The method returns list of items that are located at path

+
+
+
+ +
+
+async LibraryService.export(path='/', tenant=None, remove_path=False)[source]
+

It takes a path, and returns a file-like object containing a gzipped tar archive of the library contents of +that path

+
+
Parameters:
+
    +
  • path – The path to export, defaults to / (optional)

  • +
  • tenant – The tenant to use for the operation

  • +
  • remove_path – If True, the path will be removed from the tar file, defaults to False

  • +
+
+
+

(optional) +:return: A file object.

+
+ +
+
+

Notification of changes

+
+
+async LibraryService.subscribe(paths)[source]
+

It subscribes to the changes in the library +:param paths: A list of absolute paths to subscribe to

+
+ +
+
+

Providers

+

The library can be configured to work with following “backends” (aka providers):

+
+

Filesystem

+
+
+class asab.library.providers.filesystem.FileSystemLibraryProvider(library, path, *, set_ready=True)[source]
+
+ +
+
+

Apache Zookeeper

+
+
+class asab.library.providers.zookeeper.ZooKeeperLibraryProvider(library, path)[source]
+

Configuration variant:

+
    +
  1. ZooKeeper provider is fully configured from [zookeeper] section

  2. +
+

``` +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/library

+

[library] +providers:

+
+

zk://

+
+

```

+
    +
  1. ZooKeeper provider is configured by servers from [zookeeper] section and path from URL

  2. +
+

Path will be `/library’.

+

``` +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/else

+

[library] +providers:

+
+

zk:///library

+
+

```

+

2.1) ZooKeeper provider is configured by servers from [zookeeper] section and path from URL

+

Path will be `/’, this is a special case to 2)

+

``` +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/else

+

[library] +providers:

+
+

zk:///

+
+

```

+
    +
  1. ZooKeeper provider is fully configured from URL

  2. +
+

``` +[library] +providers:

+
+

zk://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/library

+
+

```

+

4) ZooKeeper provider is configured by servers from [zookeeper] section and joined path from [zookeeper] and +path from URL

+

Path will be `/else/library’

+

``` +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/else

+

[library] +providers:

+
+

zk://./library

+
+

```

+

If path from [zookeeper] section is missing, an application class name will be used +Ex. `/BSQueryApp/library’

+
+ +
+
+

Microsoft Azure Storage

+
+
+class asab.library.providers.azurestorage.AzureStorageLibraryProvider(library, path)[source]
+

AzureStorageLibraryProvider is a library provider that reads +from an Microsoft Azure Storage container.

+

Configure by:

+

azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER

+

If Container Public Access Level is not set to “Public access”, +then “Access Policy” must be created with “Read” and “List” permissions +and “Shared Access Signature” (SAS) query string must be added to a URL in a configuration:

+

azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER?sv=2020-10-02&si=XXXX&sr=c&sig=XXXXXXXXXXXXXX

+
+ +
+
+

Git repository

+

Connection to git repositories requires pygit2 library to be installed.

+

Example of configuration:

+
[library]
+providers: git+https://github.com/john/awesome_project.git
+
+
+
+

Functionality

+

The git provider clones the repository into a temporary directory and then uses the File System Provider to read the files from it. The default path for the cloned repository is /tmp/asab.library.git/ and it can be changed manually:

+
[library:git]
+repodir=path/to/repository/cache
+
+
+
+
+

Deploy tokens in GitLab

+

GitLab uses deploy tokens to enable authentication of deployment tasks, independent of a user account. A deploy token is an SSH key that grants access to a single repository. The public part of the key is attached directly to the repository instead of a personal account, and the private part of the key remains on the server. It is the preferred preferred way over changing local SSH settings.

+

If you want to create a deploy token for your GitLab repository, follow these steps from the manual:

+
    +
  1. Go to Settings > Repository > Deploy tokens section in your repository. (Note that you have to possess “Maintainer” or “Owner” role for the repository.)

  2. +
  3. Expand the “Deploy tokens” section. The list of current Active Deploy Tokens will be displayed.

  4. +
  5. Complete the fields and scopes. We recommend to specify custom “username”, as you will need it later for the url in configuration.

  6. +
  7. Record the deploy token’s values before leaving or refreshing the page! After that, you cannot access it again.

  8. +
+

After the deploy token is created, use the URL for repository in the following format:

+
https://<username>:<deploy_token>@gitlab.example.com/john/awesome_project.git
+
+
+
+
+

Reference

+
+
+class asab.library.providers.git.GitLibraryProvider(library, path)[source]
+

Read-only git provider to read from remote repository. +It clones a remote git repository to a temporary directory and then uses the +FileSystemLibraryProvider to read the files. +To read from local git repository, please use FileSystemProvider.

+

Configuration: +(Use either deploytoken, publickey+privatekey for SSH option, or username and password and HTTP access.)

+

``` +[library] +providers=git+<URL or deploy token>#<branch name>

+

[library:git] +publickey=<absolute path to file> +privatekey=<absolute path to file> +username=johnsmith +password=secretpassword +repodir=<optional location of the repository cache> +```

+
+ +
+
+
+
+

Layers

+

The library content can be organized into unlimmited number of layers. +Each layer is represented by a provider with a specific configuration.

+
+
+

Library configuration

+

Example:

+
[library]
+providers:
+    provider+1://...
+    provider+2://...
+    provider+3://...
+
+
+
+
+

PubSub messages

+
+
+Library.ready!
+
+ +
+
+Library.change!
+
+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/log.html b/old_docs/_build/html/asab/log.html new file mode 100644 index 000000000..d48d2caf6 --- /dev/null +++ b/old_docs/_build/html/asab/log.html @@ -0,0 +1,454 @@ + + + + + + + + + Logging — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Logging

+

ASAB logging is built on top of a standard Python logging module. +It means that it logs to stderr when running on a console and ASAB also provides file and syslog output (both RFC5424 and RFC3164) for background mode of operations.

+

Log timestamps are captured with sub-second precision (depending on the system capabilities) and displayed including microsecond part.

+ +
+

Logging Levels

+

ASAB uses Python logging levels with the addition of LOG_NOTICE level. +LOG_NOTICE level is similar to logging.INFO level but it is visible in even in non-verbose mode.

+
L.log(asab.LOG_NOTICE, "This message will be visible regardless verbose configuration.")
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Level

Numeric value

Syslog Severity level

CRITICAL

50

Critical / crit / 2

ERROR

40

Error / err / 3

WARNING

30

Warning / warning / 4

LOG_NOTICE

25

Notice / notice / 5

INFO

20

Informational / info / 6

DEBUG

10

Debug / debug / 7

NOTSET

0

+

Example of a custom level configuration:

+
[logging]
+levels=
+    myApp.module1 DEBUG
+    myApp.module2 WARNING
+    customLogger ERROR
+
+
+

The logger name and the corresponding logging level are separated by a space, each logger is on a separate line.

+
+
+

Verbose mode

+

The command-line argument -v enables verbose logging. +It means that log entries with levels DEBUG and INFO will be visible. +It also enables asyncio debug logging.

+

The actual verbose mode is avaiable at asab.Config["logging"]["verbose"] boolean option.

+
L.debug("This message will be visible only in verbose mode.")
+
+
+
+
+

Structured data

+

ASAB supports a structured data to be added to a log entry. +It follows the RFC 5424, section STRUCTURED-DATA. +Structured data are a dictionary, that has to be seriazable to JSON.

+
L.warning("Hello world!", struct_data={'key1':'value1', 'key2':2})
+
+
+

Example of the output to the console:

+

25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule [sd key1="value1" key2="2"] Hello world!

+
+
+

Logging to file

+

The command-line argument -l on command-line enables logging to file. +Also non-empty path option in the section [logging:file] of configuration file enables logging to file as well.

+

Example of the configuration file section:

+
[logging:file]
+path=/var/log/asab.log
+format="%%(asctime)s %%(levelname)s %%(name)s %%(struct_data)s%%(message)s",
+datefmt="%%d-%%b-%%Y %%H:%%M:%%S.%%f"
+backup_count=3
+rotate_every=1d
+
+
+

When the deployment expects more instances of the same application to be logging into the same file, +it is recommended, that the variable hostname is used in the file path:

+
[logging:file]
+path=/var/log/${HOSTNAME}/asab.log
+
+
+

In this way, the applications will log to seperate log files in different folders, +which is an intended behavior, since race conditions may occur when different application instances +log into the same file.

+
+
+

Logging to console

+

ASAB will log to the console only if it detects that it runs in the foreground respectively on the terminal using os.isatty +or if the environment variable ASABFORCECONSOLE is set to 1. +This is useful setup for eg. PyCharm.

+
+

Log rotation

+

ASAB supports a log rotation. +The log rotation is triggered by a UNIX signal SIGHUP, which can be used e.g. to integrate with logrotate utility. +It is implemented using logging.handlers.RotatingFileHandler from a Python standard library. +Also, a time-based log rotation can be configured using rotate_every option.

+

backup_count specifies a number of old files to be kept prior their removal. +The system will save old log files by appending the extensions ‘.1’, ‘.2’ etc., to the filename.

+

rotate_every specifies an time interval of a log rotation. +Default value is empty string, which means that the time-based log rotation is disabled. +The interval is specified by an integer value and an unit, e.g. 1d (for 1 day) or 30M (30 minutes). +Known units are H for hours, M for minutes, d for days and s for seconds.

+
+
+
+

Logging to syslog

+

The command-line argument -s enables logging to syslog.

+

A configuration section [logging:syslog] can be used to specify details about desired syslog logging.

+

Example of the configuration file section:

+
[logging:syslog]
+enabled=true
+format=5
+address=tcp://syslog.server.lan:1554/
+
+
+

enabled is equivalent to command-line switch -s and it enables syslog logging target.

+

format speficies which logging format will be used. +Possible values are:

+
    +
  • 5 for (new) syslog format (RFC 5424 ) ,

  • +
  • 3 for old BSD syslog format (RFC 3164 ), typically used by /dev/log and

  • +
  • m for Mac OSX syslog flavour that is based on BSD syslog format but it is not fully compatible.

  • +
+

The default value is 3 on Linux and m on Mac OSX.

+

address specifies the location of the Syslog server. It could be a UNIX path such as /dev/log or URL. +Possible URL values:

+
    +
  • tcp://syslog.server.lan:1554/ for Syslog over TCP

  • +
  • udp://syslog.server.lan:1554/ for Syslog over UDP

  • +
  • unix-connect:///path/to/syslog.socket for Syslog over UNIX socket (stream)

  • +
  • unix-sendto:///path/to/syslog.socket for Syslog over UNIX socket (datagram), equivalent to /path/to/syslog.socket, used by a /dev/log.

  • +
+

The default value is a /dev/log on Linux or /var/run/syslog on Mac OSX.

+
+
+

Logging of obsolete features

+

It proved to be essential to inform operators about features that are going to be obsoleted. +ASAB offers the unified “obsolete” logger. +This logger can indicate that a particular feature is marked as “obsolete” thru logs. +Such a log message can then be “grepped” from logs uniformly.

+

It is recommended to include eol attribute in the struct_data of the log with a YYYY-MM-DD date/time of the planned obsoletion of the feature.

+

Hint: We suggest automating the detection of obsolete warnings in logs so that the operations are informed well ahead of the actual removal of the feature. The string to seek in logs is “ OBSOLETE “.

+

Example of the use:

+
asab.LogObsolete.warning("Use of the obsolete function", struct_data={'eol':'2022-31-12'})
+
+
+

Log example:

+

21-Jul-2022 14:32:40.983884 WARNING OBSOLETE [eol="2022-31-12"] Use of the obsolete function

+
+
+

Reference

+
+
+class asab.log.AsyncIOHandler(loop, family, sock_type, address, facility=17)[source]
+

Bases: Handler

+

A logging handler similar to a standard logging.handlers.SocketHandler that utilizes asyncio. +It implements a queue for decoupling logging from a networking. The networking is fully event-driven via asyncio mechanisms.

+
+
+emit(record)[source]
+

This is the entry point for log entries.

+
+ +
+ +
+
+class asab.log.Logging(app)[source]
+

Bases: object

+
+
+rotate()[source]
+
+ +
+ +
+
+class asab.log.MacOSXSyslogFormatter(fmt=None, datefmt=None, style='%', sd_id='sd')[source]
+

Bases: StructuredDataFormatter

+

It implements Syslog formatting for Mac OSX syslog (aka format m).

+
+ +
+
+class asab.log.StructuredDataFormatter(facility=16, fmt=None, datefmt=None, style='%', sd_id='sd', use_color: bool = False)[source]
+

Bases: Formatter

+

The logging formatter that renders log messages that includes structured data.

+
+
+BLACK = 0
+
+ +
+
+BLUE = 4
+
+ +
+
+CYAN = 6
+
+ +
+
+GREEN = 2
+
+ +
+
+MAGENTA = 5
+
+ +
+
+RED = 1
+
+ +
+
+WHITE = 7
+
+ +
+
+YELLOW = 3
+
+ +
+
+empty_sd = ''
+
+ +
+
+format(record)[source]
+

Format the specified record as text.

+
+ +
+
+formatTime(record, datefmt=None)[source]
+

Return the creation time of the specified LogRecord as formatted text.

+
+ +
+
+render_struct_data(struct_data)[source]
+

Return the string with structured data.

+
+ +
+ +
+
+class asab.log.SyslogRFC3164Formatter(fmt=None, datefmt=None, style='%', sd_id='sd')[source]
+

Bases: StructuredDataFormatter

+

Implementation of a legacy or BSD Syslog (RFC 3164) formatting (aka format 3).

+
+ +
+
+class asab.log.SyslogRFC5424Formatter(fmt=None, datefmt=None, style='%', sd_id='sd')[source]
+

Bases: StructuredDataFormatter

+

It implements Syslog formatting for Mac OSX syslog (aka format 5).

+
+
+empty_sd = ' '
+
+ +
+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/metrics.html b/old_docs/_build/html/asab/metrics.html new file mode 100644 index 000000000..cfbe0250e --- /dev/null +++ b/old_docs/_build/html/asab/metrics.html @@ -0,0 +1,718 @@ + + + + + + + + + Metrics — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Metrics

+

Metrics document the state of the application in a timescale manner. +For further analysis, connect your ASAB application to a time-series database. Influx and Prometheus are supported.

+
+

Metrics Service

+

Create new metrics using MetricsService.

+

example of counter initialization:

+
class MyApplication(asab.Application):
+    async def initialize(self):
+        from asab.metrics import Module
+        self.add_module(Module)
+        self.MetricsService = self.get_service('asab.MetricsService')
+        self.MyCounter = self.MetricsService.create_counter("mycounter", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0})
+
+if __name__ == '__main__':
+    app = MyApplication()
+    app.run()
+
+
+

See the full example here: https://github.com/TeskaLabs/asab/blob/master/examples/metrics.py

+
+
+

Types of Metrics

+
    +
  • Gauge stores single numerical values which can go up and down. Implements set() method to set the metric values.

  • +
  • Counter is a cumulative metric whose values can increase or decrease. Implements add() and sub() methods.

  • +
  • Event per Second Counter (EPSCounter) divides all values by delta time.

  • +
  • DutyCycle https://en.wikipedia.org/wiki/Duty_cycle

  • +
  • AggregationCounter allows to set() values based on an aggregation function. max() function is default.

  • +
  • Histogram represents cumulative histogram with set() method.

  • +
+

Counter, AggregationCounter and Histogram come also in variants respecting dynamic tags. (See section Dynamic Tags.)

+

All methods that create new metrics objects can be found in the Metrics Service reference. You should never initiate a new metrics object on its own, but always through Metrics Service. Metris initialization is meant to be done in the init time of your application and should not be done during runtime.

+
+
+

ASAB Metrics Interpretation

+

Metrics Service not only creates new metrics but also periodically collects their values and sends them to selected databases. +Every 60 seconds in the application lifetime, Metrics Service gathers values of all ASAB metrics. +All Counters (and metric types that inherit from Counter) reset at this event to their initial values by default. +Interpretation of ASAB Counters is affected by their resetable nature. Even though they monotonously increase, resetting every minute gives them a different meaning. +In a long-term observation (that’s how you most probably monitor the metrics in time-series databases), these metrics count events per minute. +Thus, resettable Counters are presented to Prometheus database as gauge-type metrics. Set the reset argument to False when creating a new Counter to disable Counter resetting. +This periodic “flush” cycle also causes 60s delay of metric propagation into supported time-series databases.

+
+
+

Initial Values

+

You can initiate your metric instance with or without initial values. When providing initial values, these values are always present and presented to databases even when these values were untouched during the last 60 seconds. You will always see these values in the data, with initial state or changed by occasion. +However, the lifetime of values (name and value pairs) added during runtime is only 60 s. Thus, if this value is not set during 60s period, you won’t see it in your database anymore.

+
+
+

Dynamic Tags

+

Some metric types (Counter, AggregationCounter, Histogram) allow you to use dynamic tags. All metrics in ASAB carry some tags - Hostname by default and others added by custom. +Using dynamic tags allows you to create values with a specific tag-set during runtime. Specific tag-sets expire after defined period. This might be spotted in your time-series database like a mysterious disappearance of unused tags. +Specify expiration period in confiuration. Default is 60 s.

+

example configuration

+
[asab:metrics]
+expiration=60
+
+
+
+
+

Timestamp

+

Timestamp contains the record of the precise moment the metric’s value was created or committed to the database. There are two types of metrics: resettable (is_reset = True) and non-resettable (is_reset = False). To reset a metric means to set it back to its initial value (for example, back to 0). The metric’s type is determined by the reset: bool = True parameter of the metric’s constructor at the moment it is created. We measure non-resettable metrics at the time of their creation (there are several possible methods depending on the metric’s general logic), while the resettable ones are measured when we send data to the database (which is also the moment of them being reset).

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Metric’s Type

Description / Methods

Time is Measured

Timestamp Value Appears

is_reset

1F

Gauge

Stores single numerical values +which can go up and down.

+

add_field() / +set()

+

when metric is created +(actual time)

set() +for actual time

False

2F

Counter

+

Allows +dynamic tags

+

A cumulative metric; +values can increase or decrease +Never stops.

+

add_field() / +add() / sub() / flush()

+

when metric is created +(actual time)

add() or sub() +for actual time

False

2T

Counter

+

Allows +dynamic tags

+

A cumulative metric; +values can increase or decrease +Set to 0 every 60 seconds.

+

AgregationCounter behavior is +based on the resettable Counter.

+

every 60 seconds

flush() +- time of the test +flush

True

3F

EPSCounter

There is an adjustable +reset parameter +in the metric’s constructor.

+

reset: bool = True +reset: bool = False

+

*****

*****

False

3T

EPSCounter

Divides the count of events +by the time difference between +measurements.

+

flush()

+

every 60 seconds

flush()

True

4T

DutyCycle

The fraction of one period in +which a signal/system is active. +A 60% DC means the signal is on +60% and off 40% of the time.

+

add_field() / +set() / flush()

+

every 60 seconds

flush()

True

5F

Aggregation +Counter

+

Allows +dynamic tags

+

Keeps track of max or min value +of the Counter. +Maximum value is a default.

+

set() / ++inherits from the Counter +add()/sub() are overwritten

+

when metric is created +(actual time)

set()

False

5T

Aggregation +Counter

+

Allows +dynamic tags

+

*****

every 60 seconds

flush()

True

6F

Histogram

+

Allows +dynamic tags

+

Represents cumulative histogram +with a set() method.

+

add_field() / +set() / flush()

+

when metric is created +(actual time)

set()

False

6T

Histogram

+

Allows +dynamic tags

+

*****

every 60 seconds

flush()

True

+
+
+

InfluxDB

+

Metrics can be collected in the Influx time-series database.

+

configuration example:

+
[asab:metrics]
+target=influxdb
+
+[asab:metrics:influxdb]
+url=http://localhost:8086/
+bucket=my_bucket
+org=my_org
+token=my_token
+
+
+

InfluxDB 2.0 API parameters:

+
    +
  • url - [required] url string of your influxDB

  • +
  • bucket - [required] the destination bucket for writes

  • +
  • org - [required] specifies the destination organization for writes

  • +
  • +
    orgid - [optional] specifies the ID of the destination organization for writes

    (NOTE: If both orgID and org are specified, org takes precedence)

    +
    +
    +
  • +
  • token - [required] API token to authenticate to the InfluxDB

  • +
+

InfluxDB <1.8 API parameters:

+
    +
  • url - [required] url string of your influxDB

  • +
  • username - [required] name of influxDB user

  • +
  • password - [required] password of influxDB user

  • +
+
+
+

Prometheus

+

Prometheus is a “pull model” time-series database. +Prometheus accesses asab/v1/metrics endpoint of ASAB ApiService. Thus, connecting ASAB to Prometheus requires APIService initialization. However, no more configuration is needed. +ASAB metrics are presented to Prometheus in OpenMetrics standard format.

+

prometheus.yaml configuration file example:

+
global:
+  scrape_interval: 15s
+  scrape_timeout: 10s
+  evaluation_interval: 15s
+
+scrape_configs:
+- job_name: 'metrics_example'
+  metrics_path: '/asab/v1/metrics'
+  scrape_interval: 10s
+  static_configs:
+  - targets: ['127.0.0.1:8080']
+
+
+
+

Note

+

To satisfy the OpenMetrics format required by Prometheus, you should follow the instructions below:

+
    +
  • Metrics names must fit regex [a-zA-Z:][a-zA-Z0-9_:]*. (Any other characters are replaced by an underscore. Leading underscores and numbers are stripped. These changes proceed without warning.)

  • +
  • Metrics names MUST NOT end with “total” or “created”.

  • +
  • Tags SHOULD contain items “unit” and “help” providing metadata to Prometheus.

  • +
  • Values MUST be float or integer.

  • +
+
+
+
+

Metrics Endpoints

+

The API Service in ASAB offers several endpoints that monitor internal ASAB functionality. Some of them present the current state of metrics.

+

/asab/v1/metrics

+
    +
  • This endpoint returns metrics in OpenMetrics format and its primary purpose is to satisfy Prometheus database needs.

  • +
+

/asab/v1/metrics.json

+
    +
  • This endpoint presents metrics data in JSON format.

  • +
+

/asab/v1/watch_metrics

+
    +
  • Use this endpoint for developing or monitoring your app from the terminal. It returns a simple table of ASAB metrics. You can filter metrics by name using the filter parameter and tags parameter to show or hide tags.

  • +
+

example commands:

+
watch curl localhost:8080/asab/v1/watch_metrics
+
+
+
watch curl localhost:8080/asab/v1/watch_metrics?name=web_requests_duration_max,tags=True
+
+
+
+
+

HTTP Target

+

For use cases requiring a push model of metrics digestion, there is an HTTP Target. HTTP Target creates a POST request to configured URL with current metrics state sent as JSON body. +Configuration is required.

+

configuration example:

+
[asab:metrics]
+target=http
+
+[asab:metrics:http]
+url=http://consumer_example:8080/consume
+
+
+
+
+

Web Requests Metrics

+

ASAB WebService class automatically provides metrics counting web requests. +There are 5 metrics quantifying requests to all ASAB endpoints.

+
    +
  • web_requests - Counts requests to asab endpoints as events per minute.

  • +
  • web_requests_duration - Counts total requests duration to asab endpoints per minute.

  • +
  • web_requests_duration_min - Counts minimal request duration to asab endpoints per minute.

  • +
  • web_requests_duration_max - Counts maximum request duration to asab endpoints per minute.

  • +
  • web_requests_duration_hist - Cumulative histogram counting requests in buckets defined by the request duration.

  • +
+
+
+

Native Metrics

+

You can opt out of Native Metrics through configuration by setting native_metrics to false. Default is true.

+

example configuration

+
[asab:metrics]
+native_metrics=true
+
+
+

Memory Metrics

+

A gauge with the name os.stat gathers information about memory usage by your application.

+

You can find several metric values there:

+
    +
  • VmPeak - Peak virtual memory size

  • +
  • VmLck - Locked memory size

  • +
  • VmPin - Pinned memory size

  • +
  • VmHWM - Peak resident set size (“high water mark”)

  • +
  • VmRSS - Resident set size

  • +
  • VmData, VmStk, VmExe - Size of data, stack, and text segments

  • +
  • VmLib - Shared library code size

  • +
  • VmPTE - Page table entries size

  • +
  • VmPMD - Size of second-level page tables

  • +
  • VmSwap - Swapped-out virtual memory size by anonymous private pages; shmem swap usage is not included

  • +
+

Logs Counter

+

There is a default Counter named logs with values warnings, errors, and critical, counting logs with respective levels. +It is a humble tool for application health monitoring.

+
+
+

Reference

+
+
+class asab.metrics.MetricsService(app, service_name)[source]
+

Bases: Service

+
+
+create_gauge(metric_name, tags=None, init_values=None, help=None, unit=None)[source]
+

Creates Gauge object.

+
+ +
+
+create_counter(metric_name, tags=None, init_values=None, reset: bool = True, help=None, unit=None, dynamic_tags=False)[source]
+

Creates Counter or CounterWithDynamicTags object.

+
+ +
+
+create_eps_counter(metric_name, tags=None, init_values=None, reset: bool = True, help=None, unit=None)[source]
+

Creates EPSCounter object.

+
+ +
+
+create_duty_cycle(metric_name, tags=None, init_values=None, help=None, unit=None)[source]
+

Creates DutyCycle object.

+
+ +
+
+create_aggregation_counter(metric_name, tags=None, init_values=None, reset: bool = True, aggregator=<built-in function max>, help=None, unit=None, dynamic_tags=False)[source]
+

Creates AggregationCounter or AggregationCounterWithDynamicTags object.

+
+ +
+
+create_histogram(metric_name, buckets: list, tags=None, init_values=None, reset: bool = True, help=None, unit=None, dynamic_tags=False)[source]
+

Creates Histogram or HistogramWithDynamicTags object.

+
+ +
+ +
+
+class asab.metrics.Gauge(init_values=None)[source]
+

Bases: Metric

+

Argument init_values is a dictionary with initial values and value names as keys.

+
+
+set(name: str, value)[source]
+
+ +
+
Parameters:
+
    +
  • name – name of the value

  • +
  • value – value itself

  • +
+
+
+
+ +
+
+class asab.metrics.Counter(init_values=None)[source]
+

Bases: Metric

+

Argument init_values is a dictionary with initial values and value names as keys. +If reset is True, Counter resets every 60 seconds.

+
+
+add(name, value, init_value=None)[source]
+
+
Parameters:
+
    +
  • name – name of the counter

  • +
  • value – value to be added to the counter

  • +
+
+
+

Adds the value to the counter Values specified by name. +If name is not in Counter Values, it will be added.

+
+ +
+
+sub(name, value, init_value=None)[source]
+
+
Parameters:
+
    +
  • name – name of the counter

  • +
  • value – value to be subtracted from the counter

  • +
+
+
+

Subtracts the value from the counter Values specified by name. +If name is not in Counter Values, it will be added.

+
+ +
+ +
+
+class asab.metrics.EPSCounter(init_values=None)[source]
+

Bases: Counter

+

Event per Second Counter +Divides the count of event by a time difference between measurements. +It effectively produces the EPS metric. +The type of the metric is an integer (int).

+
+ +
+
+class asab.metrics.DutyCycle(app, init_values=None)[source]
+

Bases: Metric

+

https://en.wikipedia.org/wiki/Duty_cycle

+
+

now = self.App.time() +d = now - self.LastReadyStateSwitch +self.LastReadyStateSwitch = now

+
+
+ +
+
+class asab.metrics.AggregationCounter(init_values=None, aggregator=<built-in function max>)[source]
+

Bases: Counter

+

Sets value aggregated with the last one. +Takes a function object as the aggregator argument. +The aggregation function can take two arguments only. +Maximum is used as a default aggregation function.

+

Values (their names and init_values) can be provided when initializing the metrics or added with set() method. +add() and sub() methods are not implemented.

+
+
+set(name, value)[source]
+
+ +

Applies aggregation function on recent Counter value and value in argument and sets the result as new value of the Counter.

+
+ +
+
+class asab.metrics.Histogram(buckets: list, init_values=None)[source]
+

Bases: Metric

+

Creates cumulative histograms.

+
+
+set(value_name, value)[source]
+
+ +
+ +
+
+class asab.metrics.CounterWithDynamicTags(init_values=None)[source]
+

Bases: MetricWithDynamicTags

+
+
+add(name, value, tags)[source]
+
+
Parameters:
+
    +
  • name – name of the counter

  • +
  • value – value to be added to the counter

  • +
+
+
+

Adds the value to the counter Values specified by name. +If name is not in Counter Values, it will be added there.

+
+ +
+
+sub(name, value, tags)[source]
+
+
Parameters:
+
    +
  • name – name of the counter

  • +
  • value – value to be subtracted from the counter

  • +
+
+
+

Subtracts the value from the counter Values specified by name. +If name is not in Counter Values, it will be added there.

+
+ +
+ +
+
+class asab.metrics.AggregationCounterWithDynamicTags(init_values=None, aggregator=<built-in function max>)[source]
+

Bases: CounterWithDynamicTags

+
+
+set(name, value, tags)[source]
+
+ +
+ +
+
+class asab.metrics.HistogramWithDynamicTags(buckets: list, init_values=None)[source]
+

Bases: MetricWithDynamicTags

+

Creates cumulative histograms with dynamic tags

+
+
+set(value_name, value, tags)[source]
+
+ +
+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/module.html b/old_docs/_build/html/asab/module.html new file mode 100644 index 000000000..30360e8d7 --- /dev/null +++ b/old_docs/_build/html/asab/module.html @@ -0,0 +1,200 @@ + + + + + + + + + Module — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Module

+
+
+class asab.Module[source]
+
+ +

Modules are registered at the module registry, managed by an application object. +See Application.Modules for more details. +Module can be loaded by ASAB and typically provides one or more Service objects.

+
+

Structure

+

Recommended structure of the ASAB module:

+
mymodule/
+    __init__.py
+    myservice.py
+
+
+

Content of the __init__.py:

+
import asab
+from .myservice import MyService
+
+# Extend ASAB configuration defaults
+asab.Config.add_defaults({
+    'mymodule': {
+        'foo': 'bar'
+    }
+})
+
+class MyModule(asab.Module):
+    def __init__(self, app):
+        super().__init__(app)
+        self.service = MyService(app, "MyService")
+
+
+

And this is how the module is loaded:

+
from mymodule import MyModule
+app.add_module(MyModule)
+
+
+

For more details see Application.add_module.

+
+
+

Lifecycle

+
+
+Module.initialize(app)[source]
+
+ +

Called when the module is initialized. +It can be overriden by an user.

+
+
+Module.finalize(app)[source]
+
+ +

Called when the module is finalized e.g. during application exit-time. +It can be overriden by an user.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/pubsub.html b/old_docs/_build/html/asab/pubsub.html new file mode 100644 index 000000000..96c8f0215 --- /dev/null +++ b/old_docs/_build/html/asab/pubsub.html @@ -0,0 +1,431 @@ + + + + + + + + + Publish-Subscribe — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Publish-Subscribe

+

Publish–subscribe is a messaging pattern where senders of messages, called publishers, send the messages to receivers, called subscribers, via PubSub message bus. Publishers don’t directly interact with subscribers in any way. Similarly, subscribers express interest in one or more message types and only receive messages that are of interest, without knowledge of which publishers, if any, there are.

+
+
+class asab.PubSub(app)[source]
+
+ +

ASAB PubSub operates with a simple messages, defined by their message type, which is a string. +We recommend to add ! (explamation mark) at the end of the message type in order to distinguish this object from other types such as Python class names or functions. +Example of the message type is e.g. Application.run! or Application.tick/600!.

+

The message can carry an optional positional and keyword arguments. +The delivery of a message is implemented as a the standard Python function.

+

Note: There is an default, application-wide Publish-Subscribe message bus at Application.PubSub that can be used to send messages. +Alternatively, you can create your own instance of PubSub and enjoy isolated PubSub delivery space.

+
+

Subscription

+
+
+PubSub.subscribe(message_type, callback)[source]
+
+ +

Subscribe to a message type. Messages will be delivered to a callback callable (function or method). +The callback can be a standard callable or an async coroutine. +Asynchronous callback means that the delivery of the message will happen in a Future, asynchronously.

+

Callback callable will be called with the first argument

+

Example of a subscription to an Application.tick! messages.

+
class MyClass(object):
+        def __init__(self, app):
+                app.PubSub.subscribe("Application.tick!", self.on_tick)
+
+        def on_tick(self, message_type):
+                print(message_type)
+
+
+

Asynchronous version of the above:

+
class MyClass(object):
+        def __init__(self, app):
+                app.PubSub.subscribe("Application.tick!", self.on_tick)
+
+        async def on_tick(self, message_type):
+                await asyncio.sleep(5)
+                print(message_type)
+
+
+
+
+PubSub.subscribe_all(obj)[source]
+
+ +

To simplify the process of subscription to PubSub, ASAB offers the decorator-based “subscribe all” functionality.

+

In the followin example, both on_tick() and on_exit() methods are subscribed to Application.PubSub message bus.

+
class MyClass(object):
+        def __init__(self, app):
+                app.PubSub.subscribe_all(self)
+
+        @asab.subscribe("Application.tick!")
+        async def on_tick(self, message_type):
+                print(message_type)
+
+        @asab.subscribe("Application.exit!")
+        def on_exit(self, message_type):
+                print(message_type)
+
+
+
+
+PubSub.unsubscribe(message_type, callback)[source]
+
+ +

Unsubscribe from a message delivery.

+
+
+class asab.Subscriber(pubsub=None, *message_types)[source]
+

Subscriber object allows to consume PubSub messages in coroutines. +It subscribes for various message types and consumes them. +It works on FIFO basis (First message In, first message Out). +If pubsub argument is None, the initial subscription is skipped.

+
subscriber = asab.Subscriber(
+        app.PubSub,
+        "Application.tick!",
+        "Application.stop!"
+)
+
+
+
+
+message()[source]
+

Wait for a message asynchronously. +Returns a three-members tuple (message_type, args, kwargs).

+

Example of the await message() use:

+
async def my_coroutine(app):
+        # Subscribe for a two application events
+        subscriber = asab.Subscriber(
+                app.PubSub,
+                "Application.tick!",
+                "Application.exit!"
+        )
+        while True:
+                message_type, args, kwargs = await subscriber.message()
+                if message_type == "Application.exit!":
+                        break
+                print("Tick.")
+
+
+
+ +
+
+subscribe(pubsub, message_type)[source]
+

Subscribe for more message types. This method can be called many times with various pubsub objects.

+
+ +
+ +

The subscriber object can be also used as an asynchonous generator. +The example of the subscriber object usage in async for statement:

+
async def my_coroutine(self):
+        # Subscribe for a two application events
+        subscriber = asab.Subscriber(
+                self.PubSub,
+                "Application.tick!",
+                "Application.exit!"
+        )
+        async for message_type, args, kwargs in subscriber:
+                if message_type == "Application.exit!":
+                        break;
+                print("Tick.")
+
+
+
+
+

Publishing

+
+
+PubSub.publish(message_type, \*args, \**kwargs)[source]
+
+ +

Publish a message to the PubSub message bus. +It will be delivered to each subscriber synchronously. +It means that the method returns after each subscribed callback is called.

+

The example of a message publish to the Application.PubSub message bus:

+
def my_function(app):
+        app.PubSub.publish("mymessage!")
+
+
+

Asynchronous publishing of a message is requested by asynchronously=True argument. +The publish() method returns immediatelly and the delivery of the message to subscribers happens, when control returns to the event loop.

+

The example of a asynchronous version of a message publish to the Application.PubSub message bus:

+
def my_function(app):
+        app.PubSub.publish("mymessage!", asynchronously=True)
+
+
+
+
+

Synchronous vs. asynchronous messaging

+

ASAB PubSub supports both modes of a message delivery: synchronous and asynchronous. +Moreover, PubSub also deals with modes, when asynchronous code (coroutine) does publish to synchronous code and vice versa.

+ + + + + + + + + + + + + + + +

Sync publish

Async publish

Sync subscribe

Called immediately

call_soon(...)

Async subscribe

ensure_future(...)

call_soon(...) & ensure_future(...)

+
+
+

Application-wide PubSub

+
+
+Application.PubSub
+
+ +

The ASAB provides the application-wide Publish-Subscribe message bus.

+
+

Well-Known Messages

+

This is a list of well-known messages, that are published on a Application.PubSub by ASAB itself.

+
+
+Application.init!
+
+ +

This message is published when application is in the init-time. +It is actually one of the last things done in init-time, so the application environment is almost ready for use. +It means that configuration is loaded, logging is setup, the event loop is constructed etc.

+
+
+Application.run!
+
+ +

This message is emitted when application enters the run-time.

+
+
+Application.stop!
+
+ +

This message is emitted when application wants to stop the run-time. +It can be sent multiple times because of a process of graceful run-time termination. +The first argument of the message is a counter that increases with every Application.stop! event.

+
+
+Application.exit!
+
+ +

This message is emitted when application enter the exit-time.

+
+
+Application.tick!
+
+ +
+
+Application.tick/10!
+
+ +
+
+Application.tick/60!
+
+ +
+
+Application.tick/300!
+
+ +
+
+Application.tick/600!
+
+ +
+
+Application.tick/1800!
+
+ +
+
+Application.tick/3600!
+
+ +
+
+Application.tick/43200!
+
+ +
+
+Application.tick/86400!
+
+ +

The application publish periodically “tick” messages. +The default tick frequency is 1 second but you can change it by configuration [general] tick_period. +Application.tick! is published every tick. Application.tick/10! is published every 10th tick and so on.

+
+
+Application.hup!
+
+ +

This message is emitted when application receives UNIX signal SIGHUP or equivalent.

+
+
+Application.housekeeping!
+
+ +

This message is published when application is on the time for housekeeping. The time for housekeeping is set to 03:00 AM UTC by default.

+

The app listens every ten minutes to see if it’s time for housekeeping. If the UTC time reaches the value for housekeeping, the app will publish it and set the time for the next housekeeping for the next day at the same time. +There is also a time limit, which is set to 05:00 AM UTC by default. If the computer is in a sleep state, housekeeping will not be performed. Then, when the computer is reawakened again, it will check if it has exceeded the time limit. If not, then housekeeping will be published. If it has exceeded it, it simply informs the user and sets the housekeeping time for the next day. +Note that this only limits the time when the housekeeping can start. If the housekeeping event triggers a procedure that takes a long time to finish, it will not be terminated when the time limit is reached.

+

Both housekeeping time and time limit can be changed in the configuration file:

+
[housekeeping]
+at=19:30
+limit=21:00
+
+
+

This sets the housekeeping time to 7:30 PM UTC and the time limit to 9:00 PM UTC. +The time must be written in the format ‘HH:MM’. +Remind yourself that the time is set to UTC, so you should be careful when operating in a different timezone.

+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/service.html b/old_docs/_build/html/asab/service.html new file mode 100644 index 000000000..b0052d7b8 --- /dev/null +++ b/old_docs/_build/html/asab/service.html @@ -0,0 +1,206 @@ + + + + + + + + + Service — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Service

+
+
+class asab.Service(app)[source]
+
+ +

Service objects are registered at the service registry, managed by an application object. +See Application.Services for more details.

+

An example of a typical service class skeleton:

+
class MyService(asab.Service):
+
+    def __init__(self, app, service_name):
+        super().__init__(app, service_name)
+        ...
+
+    async def initialize(self, app):
+        ...
+
+
+    async def finalize(self, app):
+        ...
+
+
+    def service_method(self):
+        ....
+
+
+

This is how a service is created and registered:

+
mysvc = MyService(app, "my_service")
+
+
+

This is how a service is located and used:

+
mysvc = app.get_service("my_service")
+mysvc.service_method()
+
+
+
+
+Service.Name
+
+ +

Each service is identified by its name.

+
+
+Service.App
+
+ +

A reference to an Application object instance.

+
+

Lifecycle

+
+
+Service.initialize(app)[source]
+
+ +

Called when the service is initialized. +It can be overriden by an user.

+
+
+Service.finalize(app)[source]
+
+ +

Called when the service is finalized e.g. during application exit-time. +It can be overriden by an user.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/storage.html b/old_docs/_build/html/asab/storage.html new file mode 100644 index 000000000..41d9abfdc --- /dev/null +++ b/old_docs/_build/html/asab/storage.html @@ -0,0 +1,741 @@ + + + + + + + + + Storage — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Storage

+

The ASAB’s Storage Service supports data storage in-memory or in dedicated document databases, including MongoDB and ElasticSearch.

+
+

Configuration

+

First, specify the storage type in the configuration. The options for the storage type are:

+
    +
  • inmemory: Collects data directly in memory

  • +
  • mongodb: Collects data using MongoDB database. Depends on pymongo and motor libraries.

  • +
  • elasticsearch: Collects data using ElasticSearch database. Depends on aiohttp library.

  • +
+

Storage Service provides a unified interface for accessing and manipulating collections across multiple database technologies.

+
[asab:storage]
+type=mongodb
+
+
+

For accessing the storage, simply add asab.storage.Module` when initializing and register the service.

+
class MyApplication(asab.Application):
+
+    async def initialize(self):
+
+        self.add_module(asab.storage.Module)
+
+    async def main(self):
+        storage = self.get_service("asab.StorageService")
+
+
+
+
+

Manipulation with databases

+
+

Upsertor

+

Upsertor is an object that works like a pointer to the specified database and optionally to object id. It is used for inserting new objects, updating existing objects and deleting them.

+
u = storage.upsertor("test-collection")
+
+
+

The StorageService.upsertor() method creates an upsertor object associated with the specified collection. It takes collection as an argument and can have two parameters obj_id and version, which are used for getting an existing object by its ID and version.

+
+
+

Inserting an object

+

For inserting an object to the collection, use the Upsertor.set() method.

+
u.set("key", "value")
+
+
+

To execute these procedures, simply run the Upsertor.execute() coroutine method, which commits the upsertor data to the storage and returns the ID of the object. Since it is a coroutine, it must be awaited.

+
object_id = await u.execute()
+
+
+

The Upsertor.execute() method has optional parameters custom_data and event_type, which are used for webhook requests.

+
object_id = await u.execute(
+    custom_data= {"foo": "bar"},
+    event_type="object_created"
+    )
+
+
+
+
+

Getting a single object

+

For getting a single object, use StorageService.get() coroutine method that takes two arguments collection and obj_id and finds an object by its ID in collection.

+
obj = await storage.get(collection="test-collection", obj_id=object_id)
+print(obj)
+
+
+

When the requested object is not found in the collection, the method raises KeyError. Remember to handle this exception properly when using databases in your services and prevent them from crashing!

+
+

Note

+

MongoDB storage service in addition provides a coroutine method get_by() which is used for accessing an object by finding its key-value pair.

+
+
+
+

Updating an object

+

For updating an object, first obtain the upsertor specifying its obj_id and version.

+
u = storage.upsertor(
+    collection="test-collection",
+    obj_id=object_id,
+    version=obj['_v']
+)
+
+
+

We strongly recommend to read the version from the object such as above. That creates a soft lock on the record. It means that if the object is updated by other component in meanwhile, your upsertor will fail and you should retry the whole operation. The new objects should have a version set to 0, which is done by default.

+

After obtaining an upsertor, you can update the object via the Upsertor.set() coroutine.

+
+
+

Deleting an object

+

For deleting an object from database, use the StorageService.delete() coroutine method which takes arguments collection and obj_id, deletes the object and returns its ID.

+
deleted_id = await u.delete("test-collection", object_id)
+
+
+
+
+
+

Storing data in memory

+

If the option inmemory is set, ASAB will store data in its own memory. In particular, asab.StorageService is initialized with an attribute InMemoryCollections which is a dictionary where all the collections are stored in.

+
+

Note

+

You can go through all the databases directly by accessing InMemoryCollections attribute, although we do not recommend that.

+
import pprint
+
+storage = self.get_service("asab.StorageService")
+pprint.pprint(storage.InMemoryCollections, indent=2)
+
+
+
+
+
+

Storing data in MongoDB

+

If the option mongodb is set, ASAB will store data in MongoDB database.

+

ASAB uses motor library which provides non-blocking MongoDB driver for asyncio.

+

You can specify the database name and URL for MongoDB in config file (the following example is the default configuration):

+
[asab:storage]
+type=mongodb
+mongodb_uri=mongodb://localhost:27017
+mongodb_database=asabdb
+
+
+

You can use all the methods from the abstract class. MongoDB Storage class provides in addition two methods, StorageService.get_by() and StorageService.collection().

+

The method StorageService.get_by() is used in the same way as StorageService.get() except that it takes the arguments key and value instead of obj_id.

+
obj = await storage.get_by(database="test-collection", key="key", value="value")
+
+
+

The method collection() is used for accessing the database directly. It takes collection as the argument and returns motor.motor_asyncio.AsyncIOMotorCollection object, which can be used for calling MongoDB directives.

+
collection = await storage.collection("test-collection")
+cursor = collection.find({})
+while await cursor.fetch_next:
+    data = cursor.next_object()
+    pprint.pprint(data)
+
+
+

The full list of methods suitable for this object is described in the official documentation.

+
+
+

Storing data in ElasticSearch

+

When using ElasticSearch, add configurations for URL, username and password.

+
[asab:storage]
+type=elasticsearch
+elasticsearch_url=http://localhost:9200/
+elasticsearch_username=JohnDoe
+elasticsearch_password=lorem_ipsum_dolor?sit_amet!2023
+
+
+

You can also specify the refreshing parameter and scroll timeout for ElasticSearch Scroll API.

+
[asab:storage]
+refresh=true
+scroll_timeout=1m
+
+
+

ElasticSearch Storage provides in addition other methods for creating index templates, mappings etc (see the Reference section).

+
+
+

Encryption and decryption

+

Data stored in the database can be encrypted using an algorithm that adheres to the Advanced Encryption Standard (AES).

+
+

AES Key settings

+

In order to use encryption, first make sure you have the cryptography package installed. Then specify the AES Key in the config file.

+
[asab:storage]
+aes_key=random_key_string
+
+
+
+

Note

+

The AES Key is used as both an encryption and decryption key. It is recommended to keep it in a separate configuration file that is not exposed anywhere publicly.

+

The actual binary AES Key is obtained from the aes_key specified in the config file by encoding and hashing it using the standard hashlib algorithms, so do not worry about the length and type of the key.

+
+
+
+

Encrypting data

+

The Upsertor.set() method has an optional boolean parameter encrypt for encrypting the data before they are stored. Only values of the type bytes can be encrypted. If you want to encrypt other values, encode them first.

+
message = "This is a super secret message!"
+number = 2023
+message_binary = message.encode("ascii")
+number_binary = number.encode("ascii")
+
+u.set("message", message_binary, encrypt=True)
+u.set("number", number_binary, encrypt=True)
+object_id = await u.execute()
+
+
+
+
+

Decrypting data

+

The StorageService.get() coroutine method has an optional parameter decrypt which takes an iterable object (i.e. a list, tuple, set, …) with the names of keys whose values are to be decrypted.

+
data = await storage.get(
+    collection="test-collection",
+    obj_id=object_id,
+    decrypt=["message", "number"]
+    )
+
+
+

If some of the keys to be decrypted are missing in the required document, the method will ignore them and continue.

+
+

Note

+

Data that has been encrypted can be identified by the prefix “$aes-cbc$” and are stored in a binary format.

+
+
+
+

Under the hood

+

For encrypting data, we use the certified symmetric AES-CBC algorithm. In fact, the abstract base class StorageServiceABC provides two methods aes_encrypt() and aes_decrypt() that are called automatically in Upsertor.set() and StorageService.get() methods when the parameter encrypt or decrypt is specified.

+

AES-CBC is a mode of operation for the Advanced Encryption Standard (AES) algorithm that provides confidentiality and integrity for data. In AES-CBC, the plaintext is divided into blocks of fixed size (usually 128 bits), and each block is encrypted using the AES algorithm with a secret key.

+

CBC stands for “Cipher Block Chaining” and it is a technique that adds an extra step to the encryption process to ensure that each ciphertext block depends on the previous one. This means that any modification to the ciphertext will produce a completely different plaintext after decryption.

+

The algorithm is a symmetric cipher, which is suitable for encrypting large amounts of data. It requires much less computation power than asymmetric ciphers and is much more useful for bulk encrypting large amounts of data.

+
+
+
+

Reference

+
+

StorageService

+

Here is a list of methods of the abstract StorageService class which can be used for all types of storages.

+
+
+class asab.storage.service.StorageServiceABC(app, service_name)[source]
+
+
+abstract upsertor(collection: str, obj_id=None, version: int = 0)[source]
+

Create an upsertor object for the specified collection.

+

If updating an existing object, please specify its obj_id and also version that you need to read from a storage upfront. +If obj_id is None, we assume that you want to insert a new object and generate its new obj_id, version should be set to 0 (default) in that case. +If you want to insert a new object with a specific obj_id, specify obj_id and set a version to 0.

+
+
    +
  • If there will be a colliding object already stored in a storage, execute() method will fail on DuplicateError.

  • +
+
+
+
Parameters:
+
    +
  • collection – Name of collection to work with

  • +
  • obj_id – Primary identification of an object in the storage (e.g. primary key)

  • +
  • version – Specify a current version of the object and hence prevent byzantine faults. You should always read the version from the storage upfront, prior using an upsertor. That creates a soft lock on the record. It means that if the object is updated by other component in meanwhile, your upsertor will fail and you should retry the whole operation. The new objects should have a version set to 0.

  • +
+
+
+
+ +
+
+abstract async get(collection: str, obj_id, decrypt=None) dict[source]
+

Get object from collection by its ID.

+
+
Parameters:
+
    +
  • collection (str) – Collection to get from.

  • +
  • obj_id – Object identification.

  • +
  • decrypt – Set of fields to decrypt.

  • +
+
+
Returns:
+

The object retrieved from a storage.

+
+
Raises:
+

KeyError – Raised if obj_id is not found in collection.

+
+
+
+ +
+
+abstract async delete(collection: str, obj_id)[source]
+

Delete object from collection.

+
+
Parameters:
+
    +
  • collection (str) – Collection to get from

  • +
  • obj_id – Object identification

  • +
+
+
Returns:
+

ID of the deleted object.

+
+
Raises:
+

KeyError – Raised when obj_id cannot be found in collection.

+
+
+
+ +
+
+aes_encrypt(raw: bytes, iv: bytes | None = None) bytes[source]
+

Take an array of bytes and encrypt it using AES-CBC.

+
+
Parameters:
+
    +
  • raw (bytes) – The data to be encrypted.

  • +
  • iv (bytes) – AES-CBC initialization vector, 16 bytes long. If left empty, a random 16-byte array will be used.

  • +
+
+
Returns:
+

The encrypted data.

+
+
Raises:
+

TypeError – The data are not in binary format.

+
+
+
+ +
+
+aes_decrypt(encrypted: bytes) bytes[source]
+

Decrypt encrypted data using AES-CBC.

+
+
Parameters:
+

encrypted (bytes) – The encrypted data to decrypt. +It must start with b”$aes-cbc$” prefix, followed by one-block-long initialization vector.

+
+
Returns:
+

The decrypted data.

+
+
+
+ +
+ +
+
+

Upsertor

+

Here is a list of methods of the abstract Upsertor class which can be used for all types of storages.

+
+
+class asab.storage.upsertor.UpsertorABC(storage, collection, obj_id, version=None)[source]
+
+
+set(objField, value, encrypt=False, encrypt_iv=None)[source]
+

Add key and value to the upsertor.

+
+
Parameters:
+
    +
  • objField – Key of the object.

  • +
  • value – Value of the object.

  • +
  • encrypt (bool) – Allow encryption. Defaults to False.

  • +
  • encrypt_iv (bool) – Custom initialization vector. Defaults to None.

  • +
+
+
+
+ +
+
+unset(obj_field)[source]
+

Scalar unset

+
+ +
+
+classmethod generate_id() bytes[source]
+

Generate a unique ID string using a combination of a random UUID and a SHA-256 hash.

+
+
Returns:
+

A string representation of the generated ID.

+
+
+
+ +
+
+abstract async execute(custom_data: dict | None = None, event_type: str | None = None)[source]
+

Commit upsertor data to the storage. Afterwards, send a webhook request with upsertion details.

+
+
Parameters:
+
    +
  • custom_data – Custom execution data. Included in webhook payload.

  • +
  • event_type – Event type included in webhook payload.

  • +
+
+
Raises:
+

DuplicateError – Raised if thre is a colliding object already stored in a storage.

+
+
+
+ +
+ +
+
+

In-memory storage

+

Here is a list of methods that are specific for the in-memory storage.

+
+
+class asab.storage.inmemory.StorageService(app, service_name)[source]
+

Bases: StorageServiceABC

+
+ +
+
+

MongoDB Storage

+

Here is a list of methods that are specific for the MongoDB storage.

+
+
+class asab.storage.mongodb.StorageService(app, service_name, config_section_name='asab:storage')[source]
+

Bases: StorageServiceABC

+

StorageService for MongoDB. Depends on pymongo and motor.

+
+
+async get_by(collection: str, key: str, value, decrypt=None) dict[source]
+

Get object from collection by its key and value.

+
+
Parameters:
+
    +
  • collection – Collection to get from.

  • +
  • key – Key to filter on.

  • +
  • value – Value to filter on.

  • +
  • decrypt – Set of fields to decrypt.

  • +
+
+
Returns:
+

The object retrieved from a storage

+
+
Raises:
+

KeyError – Raised if object{key: value} cannot be found in collection.

+
+
+
+ +
+
+async collection(collection: str) AsyncIOMotorCollection[source]
+

Get collection. Useful for custom operations.

+
+
Parameters:
+

collection – Collection to get.

+
+
Returns:
+

AsyncIOMotorCollection object connected to the queried database.

+
+
+

Examples:

+
>>> coll = await storage.collection("test-collection")
+>>> cursor = coll.find({})
+>>> while await cursor.fetch_next:
+...     obj = cursor.next_object()
+...     pprint.pprint(obj)
+
+
+
+ +
+ +
+
+

ElasticSearch Storage

+

Here is a list of methods that are specific for the ElasticSearch storage.

+
+
+class asab.storage.elasticsearch.StorageService(app, service_name, config_section_name='asab:storage')[source]
+

Bases: StorageServiceABC

+

StorageService for Elastic Search. Depends on aiohttp library.

+
+
+session()[source]
+

Get the current client session.

+
+ +
+
+async finalize(app)[source]
+

Close the current client session.

+
+ +
+
+async mapping(index: str) dict[source]
+

Retrieve mapping definitions for one index.

+
+
Parameters:
+

index (str) – Specified index.

+
+
Raises:
+

Exception – Connection failed.

+
+
+
+
Returns:

dict: Mapping definitions for the index.

+
+
+
+ +
+
+async get_index_template(template_name: str) dict[source]
+

Retrieve ECS Index template for the given template name.

+
+
Parameters:
+

template_name (str) – The name of the ECS template to retrieve.

+
+
Raises:
+

Exception – Raised if connection to all server URLs fails.

+
+
Returns:
+

ElasticSearch Index template.

+
+
+
+ +
+
+async put_index_template(template_name: str, template: dict) dict[source]
+

Create a new ECS index template.

+
+
Parameters:
+
    +
  • template_name – The name of ECS template.

  • +
  • template – Body for the request.

  • +
+
+
Returns:
+

JSON response.

+
+
Raises:
+

Exception – Raised if connection to all server URLs fails.

+
+
+
+ +
+
+async reindex(previous_index, new_index)[source]
+
+ +
+
+async scroll(index: str, body: dict | None = None) dict[source]
+

Retrieve the next batch of results for a scrolling search.

+
+
Parameters:
+
    +
  • index (str) – The index name.

  • +
  • body (dict) – Custom body for the request. Defaults to None.

  • +
+
+
Returns:
+

JSON response.

+
+
Raises:
+

Exception – Raised if connection to all server URLs fails.

+
+
+
+ +
+
+async list(index: str, _from: int = 0, size: int = 10000, body: dict | None = None) dict[source]
+

List data matching the index.

+
+
Parameters:
+
    +
  • index – Specified index.

  • +
  • _from (int) – Starting document offset. Defaults to 0.

  • +
  • size (int) – The number of hits to return. Defaults to 10000.

  • +
  • body (dict) – An optional request body. Defaults to None.

  • +
+
+
Returns:
+

The query search result.

+
+
Raises:
+

Exception – Raised if connection to all server URLs fails.

+
+
+
+ +
+
+async count(index) int[source]
+

Get the number of matches for a given index.

+
+
Parameters:
+

index – The specified index.

+
+
Returns:
+

The number of matches for a given index.

+
+
Raises:
+

Exception – Connection failed.

+
+
+
+ +
+
+async indices(search_string=None)[source]
+

Return high-level information about indices in a cluster, including backing indices for data streams.

+
+
Parameters:
+

search_string – A search string. Default to None.

+
+
+
+ +
+
+async empty_index(index)[source]
+

Create an empty ECS index.

+
+ +
+ +
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/various.html b/old_docs/_build/html/asab/various.html new file mode 100644 index 000000000..49316258a --- /dev/null +++ b/old_docs/_build/html/asab/various.html @@ -0,0 +1,358 @@ + + + + + + + + + Various utility classes — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Various utility classes

+
+
+class asab.abc.Module(app)[source]
+

Bases: ABC

+

Abstract module class

+
+
+async finalize(app)[source]
+
+ +
+
+async initialize(app)[source]
+
+ +
+ +
+
+class asab.abc.Service(app, service_name)[source]
+

Bases: ABC

+

Abstract service class

+
+
+async finalize(app)[source]
+
+ +
+
+async initialize(app)[source]
+
+ +
+ +
+
+class asab.abc.Singleton[source]
+

Bases: type

+

The singleton pattern is a software design pattern that restricts the instantiation of a class to one object.

+

Note: The implementation idea is borrowed from “Creating a singleton in Python” question on StackOverflow.

+
+
+classmethod delete(singleton_cls)[source]
+

The method for an intentional removal of the singleton object. +It shouldn’t be used unless you really know what you are doing.

+

One use case is a unit test, which removes an Application object after each iteration.

+
+ +
+ +
+

Singleton

+
+
+class asab.abc.singleton.Singleton[source]
+

The singleton pattern is a software design pattern that restricts the instantiation of a class to one object.

+

Note: The implementation idea is borrowed from “Creating a singleton in Python” question on StackOverflow.

+
+
+classmethod delete(singleton_cls)[source]
+

The method for an intentional removal of the singleton object. +It shouldn’t be used unless you really know what you are doing.

+

One use case is a unit test, which removes an Application object after each iteration.

+
+ +
+ +

Usage:

+
import asab
+
+class MyClass(metaclass=asab.Singleton):
+    ...
+
+
+
+
+

Persistent dictionary

+
+
+class asab.pdict.PersistentDict(path)[source]
+

Bases: dict

+

The persistent dictionary works as the regular Python dictionary but the content of the dictionary is stored in the file. +You cat think of a PersistentDict as a simple key-value store. +It is not optimized for a frequent access. This class provides common dict interface.

+

Warning: You must explicitly load() and store() content of the dictionary +Warning: You can only store objects in the persistent dictionary that are serializable.

+
+
+load() None[source]
+

Load content of file as dictionary.

+
+ +
+
+store() None[source]
+

Explicitly store content of persistent dictionary to file

+
+ +
+
+update(other=(), **kwds) None[source]
+

Update D from mapping/iterable E and F. +* If E present and has a .keys() method, does: for k in E: D[k] = E[k] +* If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v +* In either case, this is followed by: for k, v in F.items(): D[k] = v

+

Inspired by a https://github.com/python/cpython/blob/3.8/Lib/_collections_abc.py

+
+ +
+ +

Note: A recommended way of initializing the persistent dictionary:

+
PersistentState = asab.PersistentDict("some.file")
+PersistentState.setdefault('foo', 0)
+PersistentState.setdefault('bar', 2)
+
+
+
+
+

Timer

+
+
+class asab.timer.Timer(app, handler, autorestart=False)[source]
+

Bases: object

+

The relative and optionally repeating timer for asyncio.

+

This class is simple relative timer that generate an event after a given time, and optionally repeating in regular intervals after that.

+
+
Parameters:
+
    +
  • app – An ASAB application.

  • +
  • handler – A coro or future that will be called when a timer triggers.

  • +
  • autorestart (boolean) – If True then a timer will be automatically restarted after triggering.

  • +
+
+
Variables:
+
    +
  • Handler – A coro or future that will be called when a timer triggers.

  • +
  • Task – A future that represent the timer task.

  • +
  • App – An ASAB app.

  • +
  • AutoRestart (boolean) – If True then a timer will be automatically restarted after triggering.

  • +
+
+
+

The timer object is initialized as stopped.

+

Note: The implementation idea is borrowed from “Python - Timer with asyncio/coroutine” question on StackOverflow.

+
+
+is_started() boolean[source]
+

Return True is the timer is started otherwise returns False.

+
+ +
+
+restart(timeout)[source]
+

Restart the timer.

+
+
Parameters:
+

timeout (float/int) – A timer delay in seconds.

+
+
+
+ +
+
+start(timeout)[source]
+

Start the timer.

+
+
Parameters:
+

timeout (float/int) – A timer delay in seconds.

+
+
+
+ +
+
+stop()[source]
+

Stop the timer.

+
+ +
+ +
+
+

Sockets

+
+
+class asab.socket.StreamSocketServerService(app, service_name)[source]
+

Bases: Service

+

Example of use:

+

class ServiceMyProtocolServer(asab.StreamSocketServerService):

+
+
+
async def initialize(self, app):

host = asab.Config.get(‘http’, ‘host’) +port = asab.Config.getint(‘http’, ‘port’)

+

L.debug(“Starting server on {} {} …”.format(host, port)) +await self.create_server(app, MyProtocol, [(host, port)])

+
+
+
+
+
+async create_server(app, protocol, addrs)[source]
+
+ +
+
+async finalize(app)[source]
+
+ +
+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/web/authn.html b/old_docs/_build/html/asab/web/authn.html new file mode 100644 index 000000000..67941b716 --- /dev/null +++ b/old_docs/_build/html/asab/web/authn.html @@ -0,0 +1,200 @@ + + + + + + + + + Authn module — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Authn module

+

Module asab.web.authn provides middlewares and classes to allow only authorized users access specified web server endpoints. +It also allows to forward requests to the authorization server via instance of OAuthForwarder.

+

Currently available authorization technologies include OAuth 2.0, public/private key and HTTP basic auth.

+
+

Middleware

+
+
+authn_middleware_factory(app, implementation, *args, **kwargs):
+
+ +

First step is to define the authorization implementation, which can be the OAuth 2.0, public/private key or +HTTP basic auth. Depending on the implementation, there are arguments which further specify the authorization +servers that are going to be used.

+

When it comes to OAuth 2.0, there are methods for every OAuth 2.0 server, that is going to be used for authorization +and obtainment of the user identity. The relevant method is selected based on access token prefix, that is received +from the client in the HTTP request (Authorization header):

+

Authorization: Bearer <OAUTH-SERVER-ID>-<ACCESS_TOKEN>

+

The following example illustrates how to register a middleware inside the web server container with OAuth 2.0 +implementation and GitHub method.

+
container.WebApp.middlewares.append(
+    asab.web.authn.authn_middleware_factory(self,
+        "oauth2client",  # other implementations include: "basicauth" and "pubkeyauth"
+        methods=[
+        # Use GitHub OAuth provider
+        asab.web.authn.oauth.GitHubOAuthMethod(),
+        ],
+    )
+)
+
+
+
+
+

Decorators

+

In order to require authorization for a specific endpoint and thus utilize the output of the registered middleware, +it is necessary to decorate its handler method with authn_required_handler decorator.

+

The decorator provide the handler method with an identity argument, which contains the user identity received +from the authorization server. Thus the user information can be further evaluated or included as part of the response. +To receive just the identity information but not force the authorization for the endpoint, the authn_optional_handler +can be used instead.

+

The following example illustrates how to use the authn_required_handler decorator in order to enforce the +authorization and receive user identity in the identity argument:

+
@asab.web.authn.authn_required_handler
+async def user(self, request, *, identity):
+    return asab.web.rest.json_response(request=request, data={
+        'message': '"{}", you have accessed our secured "user" endpoint.'.format(identity),
+    })
+
+
+
+
+

Example

+

To see & try the full example which utilizes OAuth 2.0 middleware and decorators, please see the code +in the following link:

+

https://github.com/TeskaLabs/asab/blob/master/examples/web-authn-oauth.py

+

Another example serves to demonstrate the public/private key authorization via ASAB web client ssl cert authorization:

+

https://github.com/TeskaLabs/asab/blob/master/examples/web-authn-pubkey.py

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/web/cors.html b/old_docs/_build/html/asab/web/cors.html new file mode 100644 index 000000000..305d2ad7c --- /dev/null +++ b/old_docs/_build/html/asab/web/cors.html @@ -0,0 +1,152 @@ + + + + + + + + + Cross-Origin Resource Sharing (CORS) — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Cross-Origin Resource Sharing (CORS)

+

When you create a web container, you specify a config section name. In the example below it’s myapp:web:

+
asab.web.WebContainer(self.WebService, "myapp:web")
+
+
+

You can then configure CORS by running your app with a config file with this contents:

+
[myapp:web]
+cors=*
+cors_preflight_paths=/*
+
+
+
    +
  • cors: contents of the Access-Control-Allow-Origin header

  • +
  • cors_preflight_paths: a pattern for endpoints that shall return responses to pre-flight requests (OPTIONS). Value must start with “/”.

  • +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/web/index.html b/old_docs/_build/html/asab/web/index.html new file mode 100644 index 000000000..81e80c4a6 --- /dev/null +++ b/old_docs/_build/html/asab/web/index.html @@ -0,0 +1,288 @@ + + + + + + + + + The web server — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

The web server

+

ASAB provides a web server in a asab.web module. +This module offers an integration of a aiohttp web server.

+
    +
  1. Before you start, make sure that you have aiohttp module installed.

  2. +
+
$ pip3 install aiohttp
+
+
+
    +
  1. The following code creates a simple web server application

  2. +
+
#!/usr/bin/env python3
+import asab
+import asab.web
+import aiohttp
+
+class MyApplication(asab.Application):
+
+    def __init__(self):
+        super().__init__()
+
+        # Load the ASAB Web module
+        self.add_module(asab.web.Module)
+
+        # Locate the ASAB Web service
+        websvc = self.get_service("asab.WebService")
+
+        # Create the Web container
+        container = asab.web.WebContainer(websvc, 'my:web', config={"listen": "0.0.0.0:8080"})
+
+        # Add a route to the handler
+        container.WebApp.router.add_get('/hello', self.hello)
+
+    # This is the web request handler
+    async def hello(self, request):
+        return aiohttp.web.Response(text='Hello!\n')
+
+if __name__ == '__main__':
+    app = MyApplication()
+    app.run()
+
+
+
    +
  1. Test it with curl

  2. +
+
$ curl http://localhost:8080/hello
+Hello!
+
+
+
+

Web Service

+
+
+class asab.web.service.WebService[source]
+
+ +

Service location example:

+
from asab.web import Module
+self.add_module(Module)
+svc = self.get_service("asab.WebService")
+
+
+
+
+

Configuration

+

The default configuration of the web container in ASAB is following:

+
[web]
+listen=0.0.0.0:8080
+
+
+

Multiple listening interfaces can be specified:

+
[web]
+listen:
+        0.0.0.0:8080
+        :: 8080
+
+
+

Multiple listening interfaces, one with HTTPS (TLS/SSL) can be specified:

+
[web]
+listen:
+        0.0.0.0 8080
+        :: 8080
+        0.0.0.0 8443 ssl:web
+
+[ssl:web]
+cert=...
+key=...
+...
+
+
+

Multiple interfaces, one with HTTPS (inline):

+
[web]
+listen:
+        0.0.0.0 8080
+        :: 8080
+        0.0.0.0 8443 ssl
+
+# The SSL parameters are inside of the WebContainer section
+cert=...
+key=...
+...
+
+
+

Other available options are:

+
+
    +
  • backlog

  • +
  • rootdir

  • +
  • servertokens (default value full)

  • +
  • cors

  • +
  • cors_preflight_paths

  • +
+
+

TLS/SSL paramereters:

+
+
    +
  • cert

  • +
  • key

  • +
  • password

  • +
  • cafile

  • +
  • capath

  • +
  • ciphers

  • +
  • dh_params

  • +
  • verify_mode: one of CERT_NONE, CERT_OPTIONAL or CERT_REQUIRED

  • +
  • check_hostname

  • +
  • options

  • +
+
+
+
+

Sessions

+

ASAB Web Service provides an implementation of the web sessions.

+
+
+class asab.web.session.ServiceWebSession
+
+ +

TODO: …

+
+
+asab.web.session.session_middleware(storage)
+
+ +

TODO: …

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/web/restapidocs.html b/old_docs/_build/html/asab/web/restapidocs.html new file mode 100644 index 000000000..7d26d9540 --- /dev/null +++ b/old_docs/_build/html/asab/web/restapidocs.html @@ -0,0 +1,240 @@ + + + + + + + + + REST API Docs — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

REST API Docs

+

ASAB’s API service generates a Swagger documentation which automatically shows all +of your endpoints and you can add summaries, descriptions, tags and more.

+

If you want Authorization in Swagger docs, you will need an OpenIDConnect endpoint.

+
+

In your microservice

+

First you need to initialize the API Service:

+
# Initialize API service
+self.ApiService = asab.api.ApiService(self)
+
+# Introduce Web to API Service
+self.ApiService.initialize_web()
+
+
+

After initializing the API Service a /doc endpoint will become available. You will notice +that some or none of your endpoints have summaries, tags or descriptions.

+

That’s because you need to add a docstring to your endpoint method:

+
async def endpoint(self, request):
+    """
+    Summary looks like this and takes the first line from docstring.
+
+    Description of what this endpoint does.
+
+    ---
+    tags: [asab.mymicroservice]
+    """
+
+
+

Also by adding a docstring to your ASAB Application, a description will be automatically added to the top of the Swagger docs:

+
class TutorialApp(asab.Application):
+    """
+    TutorialApp is the best microservice in the world!
+
+    <marquee>The description supports HTML tags</marquee>
+    """
+
+
+
+
+

Authorization in Swagger

+

Authorization requires making an OpenIDConnect endpoint with an Authorization and Token endpoint (like with using SeaCat Auth).

+

After your endpoint has authorization, here’s an example, +add the Authorization and Token endpoints into your config.

+

For the authorization bearer token to be added to the request, a scope is needed to be put into the security parameter in a docstring. +It does not matter what it is called or if it exists, but it’s needed to be there. But “- oAuth:” always needs to be there.

+
@asab.web.authz.required("resource:topsecret")
+async def top_secret_endpoint(self, request):
+    """
+    Top secret!
+
+    ---
+    tags: [asab.coolestmicroservice]
+    security:
+        - oAuth:
+            - read
+    """
+
+
+

After setting up Authorization, a green Authorize button should appear in the Swagger docs.

+
+
+

Configuration

+

For authorization you will need to add a authorizationUrl and tokenUrl:

+
[asab:doc]
+authorizationUrl=http://localhost:8080/openidconnect/authorize
+tokenUrl=http://localhost:8080/openidconnect/token
+
+
+

If you have an endpoint that requires a scope, you can add it with the configuration file:

+
[asab:doc]
+scopes=read,write
+
+
+
+
+

Tags

+

You can label your handler methods with custom tags. +These tags are used for grouping and sorting your endpoints on the documentation page.

+
async def my_method(self, request):
+"""<function description>
+---
+tags: ['custom tag 1', 'custom tag 2', 'custom tag 3']
+"""
+
+
+

(Remember to use exactly three dashes on the separate line and put tags in array with [] even if you want to have a single tag).

+

If there is no custom tag defined, the tag name is automatically set to be module_name. If you do not want to use custom tags but still would like to sort the routes, you can configure the options in the config file:

+
[asab:doc]
+default_route_tag=class_name
+
+
+

There are two options for default_route_tag:

+
    +
  • module_name: All tags without custom name are displayed with the name of the module where the handler is defined.

  • +
  • class_name: All tags without custom name are displayed with the name of the class where the handler is defined.

  • +
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/asab/zookeeper.html b/old_docs/_build/html/asab/zookeeper.html new file mode 100644 index 000000000..5a07b6729 --- /dev/null +++ b/old_docs/_build/html/asab/zookeeper.html @@ -0,0 +1,308 @@ + + + + + + + + + Zookeeper — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Zookeeper

+

The asab.zookeeper is a Apache Zookeeper asynchronous client based on Kazoo library.

+

Apache ZooKeeper is a distributed coordination service that provides a hierarchical key-value data store, called a znode tree, to store and manage configuration, coordination, and synchronization data. The znode tree is similar to a file system tree, where each znode is like a file or a directory.

+

Apache ZooKeeper can be used to design microservices in a stateless manner by managing and coordinating the state information between microservices. In this design, each microservice does not store any state information, but instead relies on ZooKeeper for state management.

+
+

Zookeeper container

+

A Zookeeper container represents a connectivity to Apache Zookeeper server(s). +The application can operate multiple instances of Zookeeper container.

+

This code illustrates the typical way how to create Zookeeper container:

+
import asab.zookeeper
+
+class MyApplication(asab.Application):
+
+    def __init__(self):
+        ...
+
+        # Load the ASAB Zookeeper module
+        self.add_module(asab.zookeeper.Module)
+
+        # Initialize ZooKeeper Service
+        self.ZooKeeperService = self.get_service("asab.ZooKeeperService")
+
+        # Create the Zookeeper container
+        self.ZooKeeperContainer = asab.zookeeper.ZooKeeperContainer(self.ZooKeeperService)
+
+        # Subscribe to Zookeeper container ready event
+        self.PubSub.subscribe("ZooKeeperContainer.state/CONNECTED!", self._on_zk_connected)
+
+
+    async def _on_zk_connected(self, event_name, zookeeper):
+        if zookeeper != self.ZooKeeperContainer:
+            return
+
+        print("Connected to Zookeeper!")
+
+
+
+
+class asab.zookeeper.ZooKeeperContainer(zookeeper_service, config_section_name='zookeeper', config=None, z_path=None)[source]
+

Create a Zookeeper container with a specifications of the connectivity.

+
+ +

Specifications are obtained from:

+
    +
  1. z_path argument, which is Zookeeper URL (see below)

  2. +
  3. the configuration section specified by config_section_name argument

  4. +
  5. ASAB_ZOOKEEPER_SERVERS environment variable

  6. +
+

The z_path argument has precedence over config but the implementation will look +at configuration if z_path URL is missing completely or partially. +Also, if configuration section doesn’t provide information about servers, ASAB_ZOOKEEPER_SERVERS environment variable is used.

+
+

Example of configuration section

+
[zookeeper]
+servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181
+path=myfolder
+
+
+
+
+

Example of ASAB_ZOOKEEPER_SERVERS environment variable

+
ASAB_ZOOKEEPER_SERVERS=zookeeper-1:2181,zookeeper-2:2181
+
+
+
+
+

Supported types of z_path URLs

+
    +
  1. Absolute URL

    +
    +

    zookeeper://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/etc/configs/file1

    +

    The URL contains all information for a connectivity.

    +
    +
  2. +
  3. URL without servers with absolute path

    +
    +

    zookeepers:///etc/configs/file1

    +

    In this case the relative url is expanded as follows: +zookeeper://{zookeeper_servers}/etc/configs/file1

    +

    Where {zookeeper_servers} is substituted with the servers entry of the [zookeeper] configuration file section.

    +
    +
  4. +
  5. URL without servers with relative path

    +
    +

    zookeeper:./etc/configs/file1

    +

    In this case, the relative URL is expanded as follows: +zookeper://{zookeeper_servers}/{zookeeper_path}/etc/configs/file1

    +

    Where {zookeeper_servers} is substituted with the servers entry of the [zookeeper] configuration file section and +{zookeeper_path} is substituted with the “path” entry of the [zookeeper] configuration file section.

    +
    +
  6. +
+
+
+ZooKeeperContainer.is_connected()[source]
+

Check, if the Zookeeper is connected

+
+ +
+
+
+

Reading from Zookeeeper

+
+
+async ZooKeeperContainer.get_children(path='')[source]
+
+ +
+
+async ZooKeeperContainer.get_data(path, encoding='utf-8')[source]
+
+ +
+
+async ZooKeeperContainer.get_raw_data(path)[source]
+
+ +
+ +
+

PubSub messages

+
+
+ZooKeeperContainer.state/CONNECTED!
+
+ +
+
+ZooKeeperContainer.state/LOST!
+
+ +
+
+ZooKeeperContainer.state/SUSPENDED!
+
+ +

When a Zookeeper connection is first created, it is in the LOST state. +After a connection is established it transitions to the CONNECTED state. +If any connection issues come up or if it needs to connect to a different Zookeeper cluster node, it will transition to SUSPENDED to let you know that commands cannot currently be run. +The connection will also be lost if the Zookeeper node is no longer part of the quorum, resulting in a SUSPENDED state.

+

Upon re-establishing a connection the client could transition to LOST if the session has expired, or CONNECTED if the session is still valid.

+

For mor info, visit: https://kazoo.readthedocs.io/en/latest/basic_usage.html#understanding-kazoo-states

+
+
+

Kazoo

+

Kazoo is the synchronous Python library for Apache Zookeeper.

+

It can be used directly for a more complicated tasks. +Kazoo client is accessible at ZooKeeperContainer.ZooKeeper.Client. +Synchronous methods of Kazoo client must be executed using ProactorService.

+

Here is the example:

+
 def write_to_zk():
+    self.ZooKeeperContainer.ZooKeeper.Client.create(path, data, sequence=True, ephemeral=True, makepath=True)
+
+await self.ZooKeeperContainer.ZooKeeper.ProactorService.execute(write_to_zk)
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/genindex.html b/old_docs/_build/html/genindex.html new file mode 100644 index 000000000..5da237ccd --- /dev/null +++ b/old_docs/_build/html/genindex.html @@ -0,0 +1,1006 @@ + + + + + + + + Index — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + +

Index

+ +
+ Symbols + | _ + | A + | B + | C + | D + | E + | F + | G + | H + | I + | L + | M + | P + | R + | S + | T + | U + | W + | Y + | Z + +
+

Symbols

+ + + +
+ +

_

+ + +
+ +

A

+ + + +
+ +

B

+ + + +
+ +

C

+ + + +
+ +

D

+ + + +
+ +

E

+ + + +
+ +

F

+ + + +
+ +

G

+ + + +
+ +

H

+ + + +
+ +

I

+ + + +
+ +

L

+ + + +
+ +

M

+ + + +
+ +

P

+ + + +
+ +

R

+ + + +
+ +

S

+ + + +
+ +

T

+ + + +
+ +

U

+ + + +
+ +

W

+ + + +
+ +

Y

+ + +
+ +

Z

+ + + +
+ + + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/get-started.html b/old_docs/_build/html/get-started.html new file mode 100644 index 000000000..6c5c36408 --- /dev/null +++ b/old_docs/_build/html/get-started.html @@ -0,0 +1,215 @@ + + + + + + + + + Getting started — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Getting started

+

Make sure you have both pip and at +least version 3.7 of Python before starting. ASAB uses the new async/await +syntax, so earlier versions of python won’t work.

+
    +
  1. Install ASAB:

  2. +
+
$ pip3 install asab
+
+
+
    +
  1. Create a file called main.py with the following code:

  2. +
+
#!/usr/bin/env python3
+import asab
+
+class MyApplication(asab.Application):
+    async def main(self):
+        print("Hello world")
+
+if __name__ == '__main__':
+    app = MyApplication()
+    app.run()
+
+
+
    +
  1. Run the server:

  2. +
+
$ python3 main.py
+Hello world
+
+
+

You are now successfully runinng an ASAB application server.

+
    +
  1. Stop the application by Control-C.

  2. +
+

Note: The ASAB is designed around a so-called event loop. +It is meant primarily for server architectures. +For that reason, it doesn’t terminate and continue running and serving eventual requests.

+
+

Going into details

+
#!/usr/bin/env python3
+
+
+

ASAB application uses a Python 3.7+. +This is specified a by hashbang line at the very begginig of the file, on the line number 1.

+
import asab
+
+
+

ASAB is included from as asab module via an import statement.

+
class MyApplication(asab.Application):
+
+
+

Every ASAB Application needs to have an application object. +It is a singleton; it means that the application must create and operate precisely one instance of the application. +ASAB provides the base Application class that you need to inherit from to implement your custom application class.

+
async def main(self):
+    print("Hello world")
+
+
+

The Application.main() method is one of the application lifecycle methods, that you can override to implement desired application functionality. +The main method is a coroutine, so that you can await any tasks etc. in fully asynchronous way. +This method is called when ASAB application is executed and initialized. +The lifecycle stage is called “runtime”.

+

In this example, we just print a message to a screen.

+
if __name__ == '__main__':
+    app = MyApplication()
+    app.run()
+
+
+

This part of the code is executed when the Python program is launched. +It creates the application object and executes the Application.run() method. +This is a standard way of how ASAB application is started.

+
+
+

Next steps

+

Check out tutorials about how to build ASAB based web server.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/index.html b/old_docs/_build/html/index.html new file mode 100644 index 000000000..792802bd3 --- /dev/null +++ b/old_docs/_build/html/index.html @@ -0,0 +1,354 @@ + + + + + + + + + Asynchronous Server Application Boilerplate’s documentation — ASAB documentation + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Asynchronous Server Application Boilerplate’s documentation

+

Asynchronous Server App Boilerplate (or ASAB for short) is a microservice platform for Python 3.7+ and asyncio. +ASAB aims to minimize the amount of code that needs to be written when building a microservice or an application server. +ASAB is fully asynchronous using async/await syntax from Python 3, making your code modern, non-blocking, speedy and hence scalable. +We make every effort to build ASAB container-friendly so that you can deploy ASAB-based microservice via Docker or Kubernetes in a breeze.

+

ASAB is free and open-source software, available under BSD licence. +It means that anyone is freely licenced to use, copy, study, and change the software in any way, and the source code is openly shared so that people could voluntarily improve the design of the software. +Anyone can (and is encouraged to) use ASAB in his or her projects, for free. +A current maintainer is a TeskaLabs Ltd company.

+

ASAB is developed on GitHub. +Contributions are welcome!

+
+

ASAB is designed to be powerful yet simple

+

Here is a complete example of a fully working microservice:

+
import asab
+
+class MyApplication(asab.Application):
+    async def main(self):
+        print("Hello world!")
+        self.stop()
+
+if __name__ == "__main__":
+    app = MyApplication()
+    app.run()
+
+
+
+
+

ASAB is the right choice when

+
+
    +
  • using Python 3.7+.

  • +
  • building the microservice or the application server.

  • +
  • utilizing asynchronous I/O (aka asyncio).

  • +
+
+ + + + +
+
+
+

Indices and tables

+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/objects.inv b/old_docs/_build/html/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..fc355d3f5d23e6ce8d0e8e59cdb61bc2625f8da9 GIT binary patch literal 2477 zcmV;e2~zeWAX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkGQ$a!s zBOq2~a&u{KZaN?eBOp|0Wgv28ZDDC{WMy(7Z)PBLXlZjGW@&6?AZc?TV{dJ6a%FRK zWn>_Ab7^j8AbMlH0f$$M1RyrjkQ)Alq#_T~l+DCAsaIUQ{hPotX;@ zBGDA8xfKAmEuZoldA&SIu#w^dQUu63X(9eU03W^&I{^U)Z<*&Y3IIh}>g1;WHE4$xBOgE%&m7O82T zyK@iIFox=R^r^X{w>@=O@Bm~qj92vg!mw`08+w$b$?!OrIH&g#NC=2V+xjdtZ6x#Y*Z0IzC0oz}c4w=7S+~V)lIN|M$VzKvMvdCgplYO&F-!<~r zj%G1BV1Q5Fo&4-`*fQA|u?K(T8K&K$8$sBxG!?<7z2QW}Kz}yO$#M3ELWqe6eij(A z85d?9s<-4ncJhbHYO7Kj+Wefs3u5b|6QMBiKC`bo@pUeEgs69m=v=s;S@sHH&PIwq zvg|kUZ5p}^|33e9b(A5`FZo&2?FQJN`YwP!Sdvp3e0}@^(lFLlBkP1-N94f->6~6G zz00DA^%f&DQmH+hQK0Kq^s0LhJnsI@Jc|AJoZ*Bmfk#(uM{yCbc{L2zY;rV{+WU03 zT>Yk9jhk}5ZDzo%eqTP!fVq9zZ06wHFK;&w`{fLzr_Fi>%JY}6`#H?~`{wTM@p%Ri zOmceiNjL-QMSL3@NyC)Ac2R9c!Z2msr%%LVUo1$*5=DGJeO`UIzWHbzsHOOyAK%X; zHf<$VM~njEEu#p-NNhr^vLe+Lqf9y$!1r4;t8YWfGor`!DFq1%_CRhMO)6E3XH!T! z1C>?*VQ85lpHW##r&+PbboMprG=h1>)&)JSPJwPWX;8P>?(Ev{78DV*(b%}y7dC^> zA`BA43@hEFOs9EEAI7Fg_wuuEX=Ng=w(`$if*+hc!M;=_cve`*+}jUI|DMi+IhnVB zQ5g=?QOCNoo8ZO_UapRGY3LiBPj95yWZQ=Il)|El7wR>=GG;Z<^xc=UIE#9yx}N0SZj`} z?1^$^h}cT^$E@6eQ#pGmzv&=~>Qh$kSQ`-&@C;pEO_`0U-*uk=OhBHiUCP;*dGV*( z6~p=ci}h8R?$CP*5)z{Bb(t_xn!qH(r)goIWNDOzhd%?tdW|@S0kx=G50J;<;baP{ z4i+1*<)@WlEqgg0fW!}BfKNG{t#ASg)0v@thmp3t2+mlzB4^Lozox`e=Y3OO%-dFn z@Zb*^6z0~_vLcv5%x4ZLoP|fs4X@=CsR4;!8N-GXGokVJrEi&CUR}SNjCHTyY01C5n}f|L zI{Jq>;2(O}H?zQR^z@G(-p_#-7#;s+2KY@6c^0&m{maeAIp_kz`06g77aTzv!5(ho zDqs`b)YpLgD(T6dC*%yLnN|^gAMa}Q`0%h;|S?-pfoK;tNR2w+82c@iD3d?smC z`4AC~st_n;#Z}Y9hF(38;;-^YT_|t(hFzh0AcgA3LcWw0vsF(+Q2ncFEE1?S;G+E^ zS6A73$;+w5;i7iMyd$jLJa^<3^#a#aa=W!HIxiI+aZC1yvy{y`9C-v%&)fNwAyyNy z6a2sb{FgWkBi?kZ<)MPKlS@5#9Tl#N@}5~YwYq!esOz+g`XON_b^Y+rQRjt=+Ur|g z!TGH&N51K>sP%-M@vsGGGq*X`d4nHejL@+%YuOgKH zmOT{v%2HCd+-R#+vi7%3eG4h&ZKVEOblPUNU{~?nW4qS71ZBLlxYJZPKe^?DdPu6O z*PdRGZBO*b%H2@QBb}yD9rLJ=6wkLj$Y{Z$4S`rj!x7|cP`a)gPn$q;o|$he8}3yq rE${s$-up5H`8l@3T!qD=>RY}edaV3^QTcXH6LdC;&ffojE@3z_gx|(> literal 0 HcmV?d00001 diff --git a/old_docs/_build/html/py-modindex.html b/old_docs/_build/html/py-modindex.html new file mode 100644 index 000000000..d68d92e06 --- /dev/null +++ b/old_docs/_build/html/py-modindex.html @@ -0,0 +1,178 @@ + + + + + + + + Python Module Index — ASAB documentation + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + +

Python Module Index

+ +
+ a +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
 
+ a
+ asab +
    + asab.abc +
    + asab.abc.singleton +
    + asab.log +
    + asab.pdict +
    + asab.socket +
    + asab.timer +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/search.html b/old_docs/_build/html/search.html new file mode 100644 index 000000000..a5c519bd0 --- /dev/null +++ b/old_docs/_build/html/search.html @@ -0,0 +1,152 @@ + + + + + + + + Search — ASAB documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + + +
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/searchindex.js b/old_docs/_build/html/searchindex.js new file mode 100644 index 000000000..793c1a516 --- /dev/null +++ b/old_docs/_build/html/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["admin/command-line", "admin/containers", "admin/install", "admin/systemd", "asab/alert", "asab/application", "asab/config", "asab/index", "asab/library", "asab/log", "asab/metrics", "asab/module", "asab/pubsub", "asab/service", "asab/storage", "asab/various", "asab/web/cors", "asab/web/index", "asab/web/restapidocs", "asab/zookeeper", "get-started", "index", "tutorial/web/chapter1", "tutorial/web/chapter2"], "filenames": ["admin/command-line.rst", "admin/containers.rst", "admin/install.rst", "admin/systemd.rst", "asab/alert.rst", "asab/application.rst", "asab/config.rst", "asab/index.rst", "asab/library.rst", "asab/log.rst", "asab/metrics.rst", "asab/module.rst", "asab/pubsub.rst", "asab/service.rst", "asab/storage.rst", "asab/various.rst", "asab/web/cors.rst", "asab/web/index.rst", "asab/web/restapidocs.rst", "asab/zookeeper.rst", "get-started.rst", "index.rst", "tutorial/web/chapter1.rst", "tutorial/web/chapter2.rst"], "titles": ["ASAB Command-line interface", "Containerisation", "Installation", "systemd", "Alert Service", "Application", "Configuration", "Asynchronous Server Application Boilerplate\u2019s documentation", "Library", "Logging", "Metrics", "Module", "Publish-Subscribe", "Service", "Storage", "Various utility classes", "Cross-Origin Resource Sharing (CORS)", "The web server", "REST API Docs", "Zookeeper", "Getting started", "Asynchronous Server Application Boilerplate\u2019s documentation", "Web Server Tutorial", "Create microservice with REST API"], "terms": {"base": [0, 1, 7, 9, 10, 12, 14, 15, 19, 20, 21], "applic": [0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 14, 15, 17, 18, 19, 20, 22, 23], "provid": [0, 1, 5, 6, 9, 10, 11, 12, 14, 15, 17, 19, 20, 21, 22, 23], "default": [0, 4, 5, 8, 9, 10, 11, 12, 14, 17, 21, 23], "here": [0, 7, 10, 14, 18, 19, 21, 23], "i": [0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 22, 23], "an": [0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 18, 20, 21, 23], "overview": 0, "common": [0, 15], "argument": [0, 4, 5, 6, 9, 10, 12, 14, 19], "h": [0, 1, 6, 9], "help": [0, 5, 10, 23], "show": [0, 10, 18], "c": [0, 1, 5, 6, 8, 20, 23], "config": [0, 5, 6, 9, 11, 14, 15, 16, 17, 18, 19, 21, 23], "load": [0, 5, 11, 12, 15, 17, 19, 21], "file": [0, 1, 3, 8, 10, 12, 14, 15, 16, 18, 19, 20, 21, 22, 23], "from": [0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 17, 18, 20, 21, 23], "v": [0, 9, 15, 21], "verbos": [0, 21], "increas": [0, 5, 10, 12], "level": [0, 8, 10, 14, 21], "debug": [0, 9, 15], "aka": [0, 5, 7, 8, 9, 21, 23], "more": [0, 4, 5, 6, 9, 10, 11, 12, 13, 14, 18, 19, 23], "about": [0, 4, 5, 8, 9, 10, 14, 19, 20, 23], "what": [0, 4, 6, 15, 18, 23], "happen": [0, 5, 12], "l": [0, 9, 15, 23], "log_fil": 0, "": [0, 1, 6, 8, 9, 10, 12, 14, 16, 18, 19, 23], "syslog": [0, 21], "python": [0, 1, 5, 6, 7, 9, 12, 15, 19, 20, 21, 23], "modul": [0, 6, 9, 10, 14, 15, 17, 18, 19, 20, 21, 22, 23], "ha": [0, 2, 5, 9, 12, 14, 15, 18, 19], "instal": [0, 1, 5, 8, 14, 17, 20, 21, 22, 23], "order": [0, 1, 2, 8, 12, 14], "support": [0, 4, 6, 9, 10, 12, 14, 18], "daemonos": 0, "function": [0, 5, 9, 10, 12, 18, 20, 22, 23], "pip3": [0, 1, 17, 20], "d": [0, 1, 6, 9, 10, 15, 23], "launch": [0, 1, 20], "background": [0, 9], "relat": [0, 1, 23], "section": [0, 6, 8, 9, 10, 14, 16, 17, 23], "pidfil": 0, "var": [0, 9], "run": [0, 4, 7, 9, 10, 12, 14, 16, 17, 19, 20, 21, 22, 23], "myapp": [0, 6, 9, 16], "pid": 0, "uid": 0, "nobodi": 0, "gid": 0, "working_dir": 0, "tmp": [0, 8], "option": [0, 1, 5, 6, 8, 9, 10, 12, 14, 15, 16, 17, 18, 23], "ar": [0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 23], "k": [0, 15], "kill": [0, 23], "shutdown": 0, "start": [0, 1, 8, 12, 14, 15, 16, 17, 21, 22, 23], "previous": 0, "design": [1, 5, 8, 15, 19, 20], "deploy": [1, 8, 9], "It": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18, 19, 20, 21, 22, 23], "allow": [1, 5, 6, 8, 10, 12, 14, 16, 23], "build": [1, 7, 20, 21, 23], "e": [1, 6, 9, 11, 12, 13, 14, 15, 23], "g": [1, 6, 9, 11, 12, 13, 14], "microservic": [1, 7, 8, 19, 21], "rest": [1, 21, 22], "interfac": [1, 8, 14, 15, 17, 21, 23], "consum": [1, 10, 12], "mq": 1, "messag": [1, 5, 9, 14, 20, 21], "while": [1, 10, 12, 14, 23], "being": [1, 10], "deploi": [1, 7, 21], "sake": 1, "infrastructur": 1, "flexibl": 1, "prepar": 1, "alpin": 1, "linux": [1, 9], "imag": [1, 23], "3": [1, 5, 6, 7, 8, 9, 15, 18, 19, 20, 21, 23], "10": [1, 8, 9, 10, 12], "swich": 1, "exec": 1, "bin": [1, 17, 20, 22, 23], "ash": 1, "python3": [1, 17, 20, 22, 23], "environ": [1, 9, 12, 21], "apk": 1, "updat": [1, 8, 15], "upgrad": 1, "add": [1, 4, 5, 10, 12, 14, 17, 18, 22, 23], "cach": [1, 8], "m": [1, 6, 9], "ensurepip": 1, "virtual": [1, 10], "buildenv": 1, "dev": [1, 9], "gcc": 1, "musl": 1, "git": [1, 2], "http": [1, 2, 4, 6, 8, 14, 15, 17, 18, 19, 21, 22, 23], "github": [1, 6, 7, 8, 10, 15, 21], "com": [1, 2, 4, 6, 8, 10, 15, 23], "teskalab": [1, 2, 6, 7, 10, 21], "del": 1, "depend": [1, 5, 9, 10, 14], "daemon": [1, 3, 21], "us": [1, 3, 5, 6, 7, 8, 10, 12, 13, 14, 15, 18, 19, 20, 21, 23], "openrc": 1, "automat": [1, 5, 10, 14, 15, 18, 21, 23], "stop": [1, 5, 7, 10, 12, 15, 20, 21], "vi": [1, 3], "etc": [1, 3, 6, 9, 12, 14, 19, 20], "init": [1, 10, 12, 23], "app": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22], "adjust": [1, 3, 5, 10, 23], "exampl": [1, 3, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 20, 21, 23], "chmod": 1, "x": 1, "rc": 1, "note": [1, 2, 5, 8, 10, 12, 15, 20], "If": [1, 5, 6, 8, 10, 12, 14, 15, 18, 19, 23], "you": [1, 4, 5, 6, 7, 8, 10, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23], "need": [1, 4, 5, 6, 7, 8, 10, 14, 18, 19, 20, 21, 23], "packag": [1, 14], "requir": [1, 8, 10, 14, 18], "compil": 1, "have": [1, 6, 8, 14, 17, 18, 20], "follow": [1, 2, 6, 8, 9, 10, 14, 15, 17, 19, 20, 23], "And": [1, 6, 11], "remov": [1, 6, 8, 9, 15], "tool": [1, 4, 10], "after": [1, 3, 8, 10, 12, 14, 15, 18, 19], "pip": [1, 20, 21, 23], "In": [1, 4, 8, 9, 10, 12, 15, 16, 19, 20, 21], "read": [1, 8, 14, 18, 21, 23], "name": [1, 5, 6, 8, 9, 10, 12, 13, 14, 16, 18, 23], "well": [1, 9], "other": [1, 10, 12, 14, 15, 17, 21, 23], "inform": [1, 8, 9, 10, 12, 14, 19], "log": [1, 6, 10, 12, 21, 23], "metric": [1, 21], "analysi": [1, 10], "must": [1, 8, 10, 12, 14, 15, 16, 19, 20, 22], "enabl": [1, 3, 4, 8, 9, 23], "To": [1, 2, 3, 8, 10, 12, 14, 22, 23], "do": [1, 4, 14, 15, 18, 23], "so": [1, 6, 7, 9, 12, 14, 20, 21, 23], "open": [1, 7, 21, 23], "servic": [1, 3, 11, 14, 15, 18, 19], "lib": [1, 15], "systemd": [1, 21], "system": [1, 3, 4, 5, 8, 9, 10, 19, 23], "find": [1, 10, 14], "line": [1, 6, 9, 18, 20, 21, 23], "which": [1, 5, 6, 9, 10, 12, 14, 15, 18, 19, 23], "execstart": 1, "tcp": [1, 9], "0": [1, 9, 10, 14, 15, 17, 23], "2375": 1, "save": [1, 9, 23], "reload": [1, 3, 8], "restart": [1, 15], "sudo": [1, 3], "systemctl": [1, 3], "Then": [1, 12, 14], "configur": [1, 4, 9, 10, 11, 12, 16, 21, 23], "socket": [1, 9, 21], "path": [1, 6, 9, 15, 19, 21, 22], "docker_socket": 1, "gener": [1, 4, 6, 10, 12, 14, 15, 18, 23], "your_docker_socket_fil": 1, "thu": [1, 10], "manag": [1, 4, 8, 11, 13, 19], "can": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23], "hostnam": [1, 6, 9, 10], "instead": [1, 8, 14, 19], "id": [1, 4, 10, 14, 23], "better": 1, "readabl": 1, "when": [1, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19, 20, 23], "analyz": 1, "typic": [1, 5, 9, 11, 13, 19, 23], "influxdb": [1, 21], "grafana": 1, "distribut": [2, 19], "via": [2, 5, 6, 7, 9, 12, 14, 20, 21], "pypi": 2, "thi": [2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23], "recommend": [2, 8, 11, 12, 14, 15, 21], "method": [2, 5, 6, 8, 10, 12, 14, 15, 18, 19, 20, 22, 23], "master": [2, 10], "branch": [2, 8], "repositori": 2, "command": [2, 6, 9, 10, 19, 21, 23], "successfuli": 2, "complet": [2, 5, 7, 8, 14, 19, 21], "creat": [3, 4, 5, 8, 9, 10, 12, 13, 14, 15, 16, 17, 19, 20, 21, 22], "new": [3, 4, 5, 9, 10, 14, 20, 23], "unit": [3, 6, 8, 9, 10, 15], "let": [3, 19, 23], "know": [3, 15, 19, 23], "exist": [3, 6, 14, 18, 23], "chang": [3, 7, 10, 12, 21], "now": [3, 10, 20, 22], "readi": [3, 8, 12, 19], "integr": [4, 9, 14, 17], "asab": [4, 5, 6, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23], "There": [4, 5, 6, 8, 10, 12, 18], "current": [4, 5, 6, 7, 8, 10, 14, 19, 21], "two": [4, 6, 10, 12, 14, 18, 23], "possibl": [4, 9, 10], "target": [4, 9, 21], "avail": [4, 6, 7, 17, 18, 21, 22], "www": [4, 6, 23], "atlassian": 4, "softwar": [4, 7, 15, 21], "event": [4, 8, 9, 10, 12, 14, 15, 19, 20, 21], "everyth": [4, 23], "import": [4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 17, 19, 20, 21, 22, 23], "trigger": [4, 9, 12, 15], "specifi": [4, 5, 6, 8, 9, 10, 14, 16, 17, 19, 20], "class": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 19, 20, 21, 22, 23], "myapplic": [4, 5, 7, 8, 10, 14, 17, 19, 20, 21], "async": [4, 5, 7, 8, 10, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23], "def": [4, 5, 7, 8, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23], "initi": [4, 5, 6, 8, 11, 12, 13, 14, 15, 18, 19, 20, 21, 23], "self": [4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23], "alertservic": 4, "sourc": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 21], "my": [4, 17], "tenant": [4, 8], "alert_cl": 4, "alert_id": 4, "dedupl": 4, "id01": 4, "titl": 4, "someth": [4, 23], "went": 4, "wrong": 4, "detail": [4, 5, 9, 11, 13, 14, 23], "example1": 4, "addit": [4, 6, 9, 14, 23], "info": [4, 9, 19], "example2": 4, "__name__": [4, 5, 7, 9, 10, 17, 20, 21, 22, 23], "__main__": [4, 5, 7, 10, 17, 20, 21, 22, 23], "account": [4, 8], "your": [4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 21, 23], "team": 4, "choos": [4, 23], "api": [4, 6, 10, 14, 21], "kei": [4, 6, 8, 10, 15, 17, 19, 23], "conf": [4, 6], "api_kei": 4, "tag": [4, 21], "url": [4, 8, 9, 10, 14, 21], "eu": 4, "valu": [4, 5, 8, 9, 12, 14, 15, 16, 17, 19, 21, 23], "develop": [4, 7, 10, 21], "access": [4, 6, 8, 10, 14, 15, 16, 19, 22], "directori": [4, 6, 8, 19], "folder": [4, 8, 9], "v2": [4, 10], "integration_kei": 4, "serv": [4, 6, 20], "third": 4, "parti": 4, "group": [4, 18], "prevent": [4, 14], "nois": 4, "doc": [4, 21, 23], "intellig": 4, "The": [5, 6, 8, 9, 10, 12, 14, 15, 18, 19, 20, 21, 23], "maintain": [5, 7, 8, 21], "global": [5, 8, 10], "state": [5, 8, 10, 12, 19], "own": [5, 10, 12, 14], "implement": [5, 6, 9, 10, 12, 15, 17, 19, 20, 23], "subclass": 5, "should": [5, 10, 12, 14, 18, 23], "onli": [5, 6, 8, 9, 10, 12, 14, 15, 23], "one": [5, 6, 8, 10, 11, 12, 14, 15, 17, 20, 23], "object": [5, 6, 8, 9, 10, 11, 12, 13, 15, 20, 23], "process": [5, 12, 14, 23], "pass": 5, "direct": [5, 14], "asyncio": [5, 7, 9, 12, 14, 15, 21], "ensure_futur": [5, 12], "my_coro": 5, "around": [5, 20], "invers": 5, "control": [5, 8, 12, 16, 20], "principl": 5, "mean": [5, 6, 7, 8, 9, 10, 12, 14, 20, 21, 22], "custom": [5, 8, 9, 10, 14, 18, 20], "written": [5, 7, 12, 21], "code": [5, 6, 7, 10, 12, 17, 19, 20, 21, 23], "receiv": [5, 12], "flow": 5, "callback": [5, 12], "handler": [5, 9, 15, 17, 18, 22], "modular": 5, "make": [5, 7, 14, 17, 18, 20, 21, 23], "extens": [5, 8, 9], "divid": [5, 10, 14], "phase": 5, "__init__": [5, 8, 11, 12, 13, 17, 19, 22], "dure": [5, 6, 10, 11, 13], "constructor": [5, 10], "call": [5, 6, 11, 12, 13, 14, 15, 18, 19, 20, 23], "publish": [5, 21], "subscrib": [5, 8, 19, 21], "execut": [5, 14, 19, 20, 22, 23], "asynchron": [5, 19, 20, 23], "overriden": [5, 11, 13], "user": [5, 6, 8, 10, 11, 12, 13, 23], "module_sampl": 5, "add_modul": [5, 10, 11, 14, 17, 19, 23], "enter": [5, 12, 23], "where": [5, 12, 14, 18, 19, 23], "spend": 5, "most": [5, 10], "begin": [5, 23], "return": [5, 6, 8, 9, 10, 12, 14, 15, 16, 17, 19, 22, 23], "exitcod": 5, "main": [5, 6, 7, 14, 20, 21], "without": [5, 6, 8, 10, 12, 18, 19, 23], "server": [5, 6, 8, 9, 14, 15, 19, 20, 23], "forev": 5, "behaviour": 5, "print": [5, 7, 8, 12, 14, 19, 20, 21], "hello": [5, 7, 9, 17, 20, 21, 22], "world": [5, 7, 9, 18, 20, 21, 22], "exit_cod": 5, "int": [5, 6, 10, 14, 15], "none": [5, 6, 8, 9, 10, 12, 14, 15, 18, 19, 23], "gracefulli": 5, "termin": [5, 9, 10, 12, 20], "commenc": 5, "sigint": 5, "sigterm": 5, "also": [5, 6, 8, 9, 10, 12, 14, 18, 19, 23], "includ": [5, 8, 9, 10, 14, 20, 21], "respons": [5, 8, 14, 16, 17, 23], "ctrl": 5, "unix": [5, 6, 9, 12], "like": [5, 6, 8, 10, 14, 18, 19], "3x": 5, "abruptli": 5, "emerg": 5, "abort": 5, "paramet": [5, 6, 8, 10, 14, 15, 17, 18], "see": [5, 10, 11, 12, 13, 14, 19], "chapter": 5, "win32api": 5, "abord": 5, "properli": [5, 14], "window": [5, 6, 8], "final": [5, 11, 13, 14, 15, 23], "set_exit_cod": 5, "forc": 5, "bool": [5, 9, 10, 14], "fals": [5, 8, 9, 10, 14, 15, 23], "set": [5, 6, 8, 9, 10, 12, 18, 23], "o": [5, 6, 7, 8, 9, 10, 21], "document": [5, 10, 14, 18, 23], "previou": [5, 14], "lower": 5, "than": [5, 14], "true": [5, 8, 9, 10, 12, 14, 15, 19, 23], "disregard": 5, "actual": [5, 9, 10, 12, 14, 23], "handl": [5, 14, 22, 23], "sy": 5, "For": [5, 6, 10, 11, 14, 18, 19, 20, 23], "module_class": 5, "instanti": [5, 15, 23], "my_modul": 5, "mymodul": [5, 9, 11], "A": [5, 6, 7, 8, 9, 10, 13, 14, 15, 19, 21, 22], "list": [5, 6, 8, 10, 12, 14], "been": [5, 14], "ad": [5, 8, 9, 10, 18], "each": [5, 8, 9, 12, 13, 14, 15, 19], "identifi": [5, 13, 14], "its": [5, 10, 13, 14], "uniqu": [5, 14], "get_servic": [5, 10, 13, 14, 17, 19, 23], "service_nam": [5, 8, 10, 13, 14, 15, 23], "locat": [5, 8, 9, 13, 17, 23], "svc": [5, 17], "service_sampl": 5, "dictionari": [5, 6, 9, 10, 14, 21], "regist": [5, 11, 13, 14, 23], "create_argument_pars": 5, "prog": 5, "usag": [5, 6, 10, 12, 15], "descript": [5, 10, 18], "epilog": 5, "prefix_char": 5, "fromfile_prefix_char": 5, "argument_default": 5, "conflict_handl": 5, "error": [5, 6, 9, 10, 23], "add_help": 5, "argpars": 5, "argumentpars": 5, "overload": 5, "pleas": [5, 8, 14, 23], "refer": [5, 6, 13], "standard": [5, 6, 9, 10, 12, 14, 20], "librari": [5, 6, 9, 10, 14, 19, 21, 23], "parse_arg": 5, "attribut": [5, 9, 14], "text": [5, 9, 10, 17], "displai": [5, 8, 9, 18], "expect": [5, 6, 9], "empti": [5, 8, 9, 14], "string": [5, 6, 8, 9, 10, 12, 14, 23], "float": [5, 6, 10, 15], "second": [5, 9, 10, 12, 15, 21], "sinc": [5, 9, 14], "epoch": 5, "point": [5, 9], "number": [5, 8, 9, 10, 14, 20, 23], "specif": [5, 8, 10, 14, 19, 23], "date": [5, 9], "leap": 5, "platform": [5, 7, 21], "On": 5, "januari": 5, "1": [5, 6, 8, 9, 10, 12, 18, 19, 20, 23], "1970": 5, "00": [5, 12], "count": [5, 10, 14], "toward": 5, "commonli": 5, "could": [5, 7, 9, 19, 21], "expens": 5, "cheaper": 5, "version": [5, 12, 14, 20, 23], "wall": 5, "singleton": [6, 20, 21], "ani": [6, 7, 8, 10, 12, 14, 19, 20, 21, 23], "place": [6, 23], "explicit": 6, "initialis": 6, "henc": [6, 7, 14, 21], "anywher": [6, 14, 23], "my_conf_valu": 6, "section_nam": 6, "key1": [6, 9], "inherit": [6, 10, 20, 23], "basic": [6, 23], "languag": 6, "structur": [6, 21, 23], "similar": [6, 9, 19], "found": [6, 8, 10, 14], "microsoft": 6, "ini": 6, "bitbucket": 6, "org": [6, 10, 23], "hg": 6, "topsecret": [6, 18], "port": [6, 15, 23], "50022": 6, "forwardx11": 6, "how": [6, 10, 11, 13, 19, 20], "line1": 6, "line2": 6, "line3": 6, "another_kei": 6, "foo": [6, 10, 11, 14, 15], "initiali": 6, "time": [6, 9, 10, 11, 12, 13, 15, 21, 23], "asab_config": 6, "2": [6, 8, 9, 10, 14, 15, 18, 19], "config_fil": 6, "sample_app": 6, "py": [6, 10, 11, 15, 20, 22], "sampl": 6, "merg": [6, 8], "done": [6, 10, 12, 14], "multipl": [6, 12, 14, 17, 19], "separ": [6, 9, 14, 18], "pathsep": 6, "glob": 6, "wildcard": 6, "charact": [6, 10], "expand": [6, 8, 19, 23], "mai": [6, 9], "situat": 6, "silent": 6, "ignor": [6, 14], "site": 6, "add_default": [6, 11, 23], "extend": [6, 11], "key2": [6, 9], "anoth": [6, 23], "other_sect": 6, "key3": 6, "simpl": [6, 10, 12, 15, 17, 22, 23], "type": [6, 8, 12, 14, 15, 21, 23], "don": [6, 12, 23], "t": [6, 10, 12, 15, 19, 20, 23], "complex": 6, "becaus": [6, 12, 18], "imposs": 6, "persistent_dir": 6, "home": 6, "special": [6, 8], "this_dir": 6, "contain": [6, 7, 8, 10, 16, 17, 21, 23], "util": [6, 7, 9, 21], "my_fil": 6, "txt": 6, "f": [6, 9, 15], "secur": [6, 18], "store": [6, 10, 15, 19, 21, 22, 23], "shown": 6, "publicli": [6, 14], "endpoint": [6, 16, 18, 21, 22], "output": [6, 9], "conveni": 6, "thei": [6, 10, 14], "repeat": [6, 15], "mani": [6, 12], "connect": [6, 8, 9, 10, 14, 19, 23], "kafkaconnect": 6, "kafka_password": 6, "my_secret_password": 6, "getsecond": 6, "differ": [6, 9, 10, 12, 14, 19], "sleep": [6, 12], "sleep_tim": 6, "5": [6, 9, 10, 12], "another_sleep_tim": 6, "10d": 6, "y": [6, 9], "year": 6, "month": 6, "w": 6, "week": 6, "dai": [6, 9, 12], "hour": [6, 9], "minut": [6, 9, 10, 12], "milisecond": 6, "achiev": 6, "wai": [6, 7, 8, 9, 12, 14, 15, 19, 20, 21], "sleeptim": 6, "anothersleeptim": 6, "geturl": 6, "scheme": 6, "str": [6, 8, 10, 14], "tupl": [6, 12, 14], "take": [6, 8, 10, 12, 14, 18, 23], "lead": [6, 10], "trail": 6, "whitespac": 6, "backslash": 6, "mongodb": [6, 21], "valid": [6, 19, 23], "get": [6, 15, 21, 22, 23], "bypass": 6, "same": [6, 9, 12, 14], "rais": [6, 14], "would": [6, 18], "short": [7, 21], "7": [7, 9, 12, 20, 21], "aim": [7, 21], "minim": [7, 10, 21], "amount": [7, 14, 21], "fulli": [7, 8, 9, 20, 21], "await": [7, 8, 12, 14, 15, 19, 20, 21, 23], "syntax": [7, 20, 21], "modern": [7, 21], "non": [7, 9, 10, 14, 21], "block": [7, 14, 21], "speedi": [7, 21], "scalabl": [7, 21], "we": [7, 8, 9, 10, 12, 14, 20, 21, 23], "everi": [7, 9, 10, 12, 20, 21], "effort": [7, 21], "friendli": [7, 21], "docker": [7, 21, 23], "kubernet": [7, 21], "breez": [7, 21], "free": [7, 21], "under": [7, 21], "bsd": [7, 9, 21], "licenc": [7, 21], "anyon": [7, 21], "freeli": [7, 21], "copi": [7, 21], "studi": [7, 21], "openli": [7, 21], "share": [7, 8, 10, 21], "peopl": [7, 21], "voluntarili": [7, 21], "improv": [7, 21], "encourag": [7, 21], "hi": [7, 21], "her": [7, 21], "project": [7, 21], "ltd": [7, 21], "compani": [7, 21], "contribut": [7, 21], "welcom": [7, 21], "work": [7, 8, 12, 14, 15, 20, 21, 23], "concept": 8, "data": [8, 10, 19, 21, 22, 23], "content": [8, 11, 15, 16], "across": [8, 14], "cluster": [8, 14, 19], "notifi": 8, "eg": [8, 9], "autom": [8, 9], "companion": 8, "edit": 8, "howev": [8, 10], "oper": [8, 9, 12, 14, 19, 20, 23], "organ": [8, 10], "simplifi": [8, 12, 22], "manner": [8, 10, 19], "folder1": 8, "item1": 8, "yaml": [8, 10], "item2": 8, "json": [8, 9, 10, 14, 23], "folder2": 8, "item3": 8, "folder2folder2": 8, "item4": 8, "root": 8, "end": [8, 10, 12], "item": [8, 10, 15], "libraryservic": 8, "abstrat": 8, "unifi": [8, 9, 14], "resourc": [8, 18, 21], "cloud": 8, "architectur": [8, 20], "imper": 8, "all": [8, 9, 10, 12, 14, 18, 19, 23], "technologi": [8, 14], "built": [8, 9, 10, 23], "top": [8, 9, 18, 23], "bring": 8, "stack": [8, 10], "variou": [8, 12, 21], "view": 8, "overlai": 8, "space": [8, 9, 12], "prioriti": 8, "down": [8, 10], "uri": 8, "schema": [8, 23], "zk": 8, "local": 8, "first": [8, 12, 14, 18, 19, 23], "disabl": [8, 9, 10], "visibl": [8, 9], "present": [8, 10, 15], "consid": 8, "itself": [8, 10, 12], "becom": [8, 18], "indic": [8, 9, 14, 23], "pubsub": 21, "asablibrari": [], "super": [8, 11, 13, 14, 17, 22, 23], "on_library_readi": 8, "event_nam": [8, 19], "n": [8, 17, 22], "recurs": 8, "itemio": 8, "byte": [8, 14], "format": [8, 9, 10, 12, 14, 15], "len": 8, "els": [8, 23], "io": [8, 19], "libraryitem": 8, "directli": [8, 12, 14, 19], "appli": [8, 10], "assum": [8, 14], "stream": [8, 9, 14], "libari": 8, "entri": [8, 9, 10, 19, 21], "evalu": 8, "xxxxx": 8, "subdirectori": 8, "export": 8, "remove_path": 8, "gzip": 8, "tar": 8, "archiv": 8, "param": 8, "absolut": [8, 19], "backend": 8, "filesystemlibraryprovid": 8, "set_readi": 8, "zookeeperlibraryprovid": 8, "variant": [8, 10], "2181": [8, 19], "case": [8, 10, 14, 15, 19], "4": [8, 9], "join": 8, "miss": [8, 14, 19], "ex": 8, "bsqueryapp": 8, "azurestorag": 8, "azurestoragelibraryprovid": 8, "blob": [8, 10, 15], "core": 8, "net": 8, "public": 8, "polici": 8, "permiss": 8, "signatur": 8, "sa": 8, "queri": [8, 14], "sv": 8, "2020": 8, "02": 8, "si": 8, "xxxx": 8, "sr": 8, "sig": 8, "xxxxxxxxxxxxxx": 8, "unlimmit": 8, "repres": [8, 10, 15, 19], "stderr": 9, "both": [9, 10, 12, 14, 20], "rfc5424": 9, "rfc3164": 9, "timestamp": [9, 21], "captur": 9, "sub": [9, 10], "precis": [9, 10, 20], "capabl": 9, "microsecond": 9, "part": [8, 9, 19, 20, 23], "logger": 9, "necessari": 9, "altern": [9, 12], "strategi": 9, "getlogg": [9, 23], "warn": [9, 10, 15, 23], "25": 9, "mar": 9, "2018": 9, "23": 9, "33": 9, "58": 9, "044595": 9, "log_notic": 9, "even": [9, 10, 18], "regardless": 9, "numer": [9, 10], "sever": [9, 10, 23], "critic": [9, 10], "50": 9, "crit": 9, "40": [9, 10], "err": 9, "30": [9, 12], "notic": [9, 18], "20": [9, 23], "6": [9, 23], "notset": 9, "module1": 9, "module2": 9, "customlogg": 9, "correspond": 9, "avaiabl": 9, "boolean": [9, 14, 15], "rfc": 9, "5424": 9, "seriaz": 9, "struct_data": 9, "value1": 9, "sd": 9, "asctim": 9, "levelnam": 9, "datefmt": 9, "b": [9, 14], "backup_count": 9, "rotate_everi": 9, "1d": 9, "instanc": [9, 10, 12, 13, 19, 20, 23], "variabl": [9, 15, 21], "seper": 9, "intend": 9, "behavior": [9, 10], "race": 9, "condit": 9, "occur": 9, "detect": 9, "foreground": 9, "respect": [9, 10, 23], "isatti": 9, "asabforceconsol": 9, "setup": [9, 12], "pycharm": 9, "signal": [9, 10, 12], "sighup": [9, 12], "logrot": 9, "rotatingfilehandl": 9, "old": 9, "kept": 9, "prior": [9, 14], "append": [9, 23], "filenam": 9, "interv": [9, 15], "integ": [9, 10], "30m": 9, "known": 9, "desir": [9, 20, 23], "address": [9, 23], "lan": 9, "1554": 9, "equival": [9, 12], "switch": 9, "spefici": 9, "3164": 9, "mac": 9, "osx": 9, "flavour": 9, "compat": 9, "over": [8, 9, 19], "udp": 9, "sendto": 9, "datagram": 9, "prove": 9, "essenti": 9, "go": [8, 9, 10, 14, 23], "offer": [9, 10, 12, 17], "particular": [9, 14], "mark": [9, 10, 12], "thru": 9, "Such": 9, "grep": 9, "uniformli": 9, "eol": 9, "yyyi": 9, "mm": [9, 12], "dd": 9, "plan": 9, "hint": 9, "suggest": [9, 23], "ahead": 9, "seek": 9, "logobsolet": 9, "2022": 9, "31": 9, "12": 9, "21": [9, 12], "jul": 9, "14": 9, "32": 9, "983884": 9, "asynciohandl": 9, "loop": [9, 12, 20, 21], "famili": 9, "sock_typ": 9, "facil": 9, "17": 9, "sockethandl": 9, "queue": 9, "decoupl": 9, "network": 9, "driven": 9, "mechan": 9, "emit": [9, 12], "record": [8, 9, 10, 14, 23], "macosxsyslogformatt": 9, "fmt": 9, "style": 9, "sd_id": 9, "structureddataformatt": 9, "16": [9, 14], "use_color": 9, "formatt": 9, "render": 9, "black": 9, "blue": 9, "cyan": 9, "green": [9, 18], "magenta": 9, "red": 9, "white": 9, "yellow": 9, "empty_sd": 9, "formattim": 9, "creation": [9, 10, 22], "logrecord": 9, "render_struct_data": 9, "syslogrfc3164formatt": 9, "legaci": 9, "syslogrfc5424formatt": 9, "timescal": 10, "further": [10, 23], "seri": 10, "databas": [10, 21, 23], "influx": 10, "metricsservic": 10, "counter": [10, 12], "mycount": 10, "create_count": 10, "bar": [10, 11, 14, 15], "init_valu": 10, "v1": 10, "full": [10, 14, 17], "gaug": 10, "singl": [8, 10, 18], "up": [10, 18, 19, 23], "cumul": 10, "whose": [10, 14], "decreas": 10, "per": 10, "epscount": 10, "delta": 10, "dutycycl": 10, "en": [10, 19, 23], "wikipedia": 10, "wiki": 10, "duty_cycl": 10, "aggregationcount": 10, "aggreg": 10, "max": 10, "histogram": 10, "come": [10, 19, 23], "never": 10, "alwai": [10, 14, 18], "through": [10, 14], "metri": 10, "meant": [10, 20], "runtim": [10, 20], "period": [10, 12], "collect": [10, 14, 23], "send": [10, 12, 14], "them": [10, 12, 14, 23], "select": 10, "60": [10, 12], "lifetim": 10, "gather": 10, "reset": 10, "affect": 10, "natur": 10, "though": 10, "monoton": 10, "give": 10, "long": [10, 12, 14], "term": 10, "observ": 10, "probabl": 10, "monitor": 10, "resett": 10, "flush": 10, "cycl": 10, "caus": 10, "delai": [10, 15], "propag": 10, "were": 10, "untouch": 10, "last": [10, 12], "occas": 10, "pair": [10, 14], "won": [10, 20], "anymor": 10, "some": [10, 14, 15, 18, 23], "carri": [10, 12], "expir": [10, 19], "defin": [10, 12, 18, 23], "might": 10, "spot": 10, "mysteri": 10, "disappear": 10, "unus": 10, "confiur": 10, "localhost": [10, 14, 17, 18, 22], "8086": 10, "bucket": 10, "my_bucket": 10, "my_org": 10, "token": [10, 18], "my_token": 10, "destin": 10, "write": [10, 18, 23], "orgid": 10, "preced": [10, 19], "authent": [8, 10], "8": [10, 15, 19], "usernam": [8, 10, 14], "password": [8, 10, 14, 17, 21, 23], "pull": [10, 23], "model": 10, "apiservic": [10, 18], "openmetr": 10, "scrape_interv": 10, "15": 10, "scrape_timeout": 10, "evaluation_interv": 10, "scrape_config": 10, "job_nam": 10, "metrics_exampl": 10, "metrics_path": 10, "static_config": 10, "127": [10, 23], "8080": [10, 17, 18, 22, 23], "satisfi": 10, "instruct": 10, "below": [10, 16, 19, 23], "fit": [10, 23], "regex": 10, "za": 10, "z": 10, "z0": 10, "9_": 10, "replac": 10, "underscor": 10, "strip": 10, "These": [10, 18, 23], "proce": 10, "NOT": 10, "total": 10, "metadata": 10, "intern": [10, 23], "primari": [10, 14], "purpos": 10, "watch_metr": 10, "tabl": 10, "filter": [10, 14], "hide": 10, "watch": 10, "curl": [10, 17], "web_requests_duration_max": 10, "push": 10, "digest": 10, "post": [10, 23], "sent": [10, 12], "bodi": [10, 14, 23], "consumer_exampl": 10, "webservic": [10, 16, 17, 23], "quantifi": 10, "web_request": 10, "web_requests_dur": 10, "durat": 10, "web_requests_duration_min": 10, "maximum": 10, "web_requests_duration_hist": 10, "opt": 10, "out": [10, 12, 20, 23], "native_metr": 10, "memori": [10, 21], "stat": 10, "vmpeak": 10, "peak": 10, "size": [10, 14], "vmlck": 10, "lock": [10, 14], "vmpin": 10, "pin": 10, "vmhwm": 10, "resid": 10, "high": [10, 14], "water": 10, "vmrss": 10, "vmdata": 10, "vmstk": 10, "vmex": 10, "segment": 10, "vmlib": 10, "vmpte": 10, "page": [8, 10, 18, 21], "vmpmd": 10, "vmswap": 10, "swap": 10, "anonym": 10, "privat": [8, 10], "shmem": 10, "humbl": 10, "health": 10, "create_gaug": 10, "metric_nam": 10, "dynamic_tag": 10, "counterwithdynamictag": 10, "create_eps_count": 10, "create_duty_cycl": 10, "create_aggregation_count": 10, "aggregationcounterwithdynamictag": 10, "create_histogram": 10, "histogramwithdynamictag": 10, "subtract": 10, "between": [10, 19, 23], "measur": 10, "effect": 10, "produc": [10, 14], "ep": 10, "lastreadystateswitch": 10, "track": 10, "recent": 10, "result": [10, 14, 19, 23], "value_nam": 10, "metricwithdynamictag": 10, "registri": [11, 13, 21], "myservic": [11, 13], "exit": [11, 12, 13, 23], "pattern": [12, 15, 16], "sender": 12, "bu": 12, "interact": 12, "similarli": 12, "express": 12, "interest": 12, "knowledg": 12, "explam": 12, "distinguish": 12, "tick": 12, "600": 12, "posit": 12, "keyword": 12, "deliveri": 12, "enjoi": 12, "isol": 12, "message_typ": 12, "deliv": 12, "callabl": 12, "coroutin": [12, 14, 15, 20, 22, 23], "futur": [12, 15], "myclass": [12, 15], "on_tick": 12, "abov": [12, 14, 22, 23], "subscribe_al": 12, "obj": [12, 14], "decor": [12, 23], "followin": 12, "on_exit": 12, "unsubscrib": 12, "fifo": 12, "basi": 12, "skip": 12, "wait": [12, 23], "three": [12, 18], "member": 12, "arg": 12, "kwarg": 12, "my_coroutin": 12, "break": 12, "asynchon": 12, "statement": [12, 20], "my_funct": 12, "mymessag": 12, "request": [12, 14, 16, 17, 18, 20, 21, 22, 23], "immediatelli": 12, "mode": [12, 14, 21], "moreov": 12, "deal": 12, "doe": [12, 15, 18, 19, 23], "vice": 12, "versa": 12, "sync": 12, "immedi": 12, "call_soon": 12, "thing": [12, 23], "almost": 12, "construct": 12, "want": [8, 12, 14, 18, 23], "grace": 12, "300": 12, "1800": 12, "3600": 12, "43200": 12, "86400": 12, "frequenc": 12, "tick_period": 12, "10th": 12, "hup": 12, "housekeep": 12, "03": 12, "am": 12, "utc": [12, 21], "housekeeping_tim": [], "19": 12, "pm": 12, "hh": 12, "remind": 12, "yourself": [12, 23], "care": 12, "timezon": 12, "skeleton": 13, "service_method": 13, "mysvc": 13, "my_servic": 13, "manual": [8, 23], "inmemori": 14, "elasticsearch": 21, "although": 14, "simpli": [12, 14, 23], "storageservic": 23, "inmemorycollect": 14, "todo": 17, "upsertor": 23, "associ": 14, "test": [10, 14, 15, 17], "u": [14, 23], "procedur": [12, 14], "commit": [10, 14], "object_id": 14, "custom_data": 14, "webhook": 14, "upsert": 14, "event_typ": 14, "user_cr": [], "obj_id": [14, 23], "keyerror": [14, 23], "get_bi": 14, "obtain": [14, 19, 21], "_v": [14, 23], "strongli": [14, 23], "That": [14, 18], "soft": 14, "compon": 14, "meanwhil": 14, "fail": [14, 23], "retri": 14, "whole": 14, "just": [20, 23], "modifi": [], "new_valu": [], "delet": 15, "deleted_id": 14, "abc": 15, "abstract": [14, 15, 23], "restrict": 15, "idea": 15, "borrow": 15, "question": 15, "stackoverflow": 15, "classmethod": [14, 15], "singleton_cl": 15, "intent": 15, "shouldn": 15, "unless": 15, "realli": 15, "One": 15, "iter": [14, 15], "metaclass": 15, "pdict": 15, "persistentdict": 15, "dict": [14, 15], "regular": 15, "cat": 15, "think": 15, "optim": 15, "frequent": 15, "explicitli": 15, "serializ": 15, "kwd": 15, "map": [14, 15], "lack": 15, "either": [8, 15, 23], "inspir": 15, "cpython": 15, "_collections_abc": 15, "persistentst": 15, "setdefault": 15, "autorestart": 15, "rel": [15, 19], "given": [14, 15], "coro": 15, "task": [8, 15, 19, 20], "is_start": 15, "otherwis": [15, 23], "timeout": [14, 15], "streamsocketserverservic": 15, "servicemyprotocolserv": 15, "host": 15, "getint": 15, "create_serv": 15, "myprotocol": 15, "protocol": 15, "addr": 15, "web": [16, 18, 20, 21, 23], "author": 21, "forward": [], "oauthforward": [], "oauth": 18, "auth": 18, "authn_middleware_factori": [], "step": [8, 14], "ident": [], "relev": [], "prefix": 14, "client": [14, 19], "header": 16, "bearer": 18, "access_token": [], "illustr": 19, "insid": 17, "webapp": [17, 23], "oauth2client": [], "basicauth": [], "pubkeyauth": [], "githuboauthmethod": [], "authn_required_handl": [], "authn_optional_handl": [], "enforc": [], "json_respons": [22, 23], "our": [], "try": 23, "link": [], "demonstr": [], "ssl": 17, "cert": 17, "pubkei": [], "webcontain": [16, 17, 23], "cors_preflight_path": [16, 17], "shall": 16, "pre": 16, "flight": 16, "aiohttp": [14, 17, 23], "befor": [8, 14, 17, 20], "sure": [14, 17, 20], "usr": [17, 20, 22, 23], "env": [17, 20, 22, 23], "websvc": 17, "listen": [12, 17, 23], "rout": [17, 18, 22], "router": [17, 23], "add_get": [17, 22, 23], "tl": 17, "8443": 17, "inlin": 17, "backlog": 17, "rootdir": 17, "servertoken": 17, "cor": [17, 21], "parameret": 17, "cafil": 17, "capath": 17, "cipher": [14, 17], "dh_param": 17, "verify_mod": 17, "cert_non": 17, "cert_opt": 17, "cert_requir": 17, "check_hostnam": 17, "servicewebsess": 17, "session_middlewar": 17, "storag": [17, 21, 23], "summari": 18, "openidconnect": 18, "introduc": 18, "initialize_web": 18, "docstr": 18, "look": [18, 19], "mymicroservic": 18, "tutorialapp": [18, 23], "best": 18, "marque": 18, "html": [18, 19, 23], "seacat": 18, "scope": [8, 18], "put": [18, 23], "matter": 18, "But": 18, "authz": 18, "top_secret_endpoint": 18, "secret": [14, 18, 23], "coolestmicroservic": 18, "button": 18, "appear": [10, 18], "authorizationurl": 18, "tokenurl": 18, "apach": 19, "coordin": 19, "hierarch": 19, "znode": 19, "tree": 19, "synchron": [19, 21], "stateless": 19, "reli": 19, "zookeeperservic": 19, "zookeepercontain": 19, "_on_zk_readi": [], "zookeeper_servic": 19, "config_section_nam": [14, 19], "partial": 19, "doesn": [19, 20], "myfold": 19, "file1": 19, "substitut": 19, "zookep": 19, "zookeeper_path": 19, "is_connect": 19, "check": [12, 19, 20, 23], "get_children": 19, "get_data": 19, "encod": [14, 19], "utf": 19, "get_raw_data": 19, "complic": 19, "proactorservic": 19, "write_to_zk": 19, "sequenc": 19, "ephemer": 19, "makepath": 19, "least": 20, "earlier": 20, "successfulli": 20, "runinng": 20, "primarili": 20, "reason": 20, "continu": [14, 20], "eventu": 20, "hashbang": 20, "veri": 20, "begginig": 20, "lifecycl": [20, 21], "overrid": 20, "stage": 20, "screen": 20, "program": [20, 23], "tutori": [20, 21, 23], "session": [14, 19, 21], "swagger": 21, "authn": [], "middlewar": 23, "cross": 21, "origin": [21, 23], "interpret": 21, "dynam": 21, "prometheu": 21, "nativ": 21, "alert": 21, "opsgeni": 21, "pagerduti": 21, "de": 21, "duplic": 21, "parser": 21, "configpars": 21, "multilin": 21, "configr": 21, "consol": 21, "obsolet": 21, "featur": 21, "subscript": 21, "wide": 21, "persist": 21, "timer": 21, "zookeep": 21, "zookeeep": 21, "advertis": 21, "kazoo": 21, "rule": 21, "notif": 21, "layer": 21, "easy_instal": 21, "containeris": 21, "lxc": 21, "lxd": 21, "remot": [8, 21], "index": [14, 21, 23], "search": [14, 21], "mywebappl": 22, "create_web_serv": 22, "declar": 22, "With": 23, "word": 23, "crud": 23, "later": [8, 23], "boilerpl": 23, "cover": 23, "score": 23, "good": 23, "ones": [10, 23], "onlin": 23, "troubl": 23, "re": [19, 23], "familiar": 23, "yet": 23, "great": 23, "opportun": 23, "consist": 23, "discuss": 23, "bottom": 23, "hub": 23, "_": 23, "mongo": 23, "forget": 23, "p": 23, "27017": [14, 23], "mongo_initdb_root_usernam": 23, "mongo_initdb_root_password": 23, "download": 23, "fairli": 23, "straightforward": 23, "shebang": 23, "tell": 23, "next": [12, 14, 23], "mongodb_uri": [14, 23], "mongous": 23, "mongopassword": 23, "mongoipaddress": 23, "mongodb_databas": [14, 23], "mongodatabas": 23, "credenti": 23, "usual": [14, 23], "commandlin": 23, "learn": 23, "describ": [14, 23], "littl": 23, "jsonexceptionmiddlewar": 23, "crudwebhandl": 23, "crudservic": 23, "__all__": 23, "transform": 23, "perspect": 23, "translat": 23, "No": 23, "busi": 23, "logic": [10, 23], "straight": 23, "awai": 23, "haven": 23, "As": 23, "mongo_svc": 23, "web_app": 23, "add_put": 23, "json_schema_handl": 23, "properti": 23, "_id": 23, "field1": 23, "field2": 23, "field3": 23, "json_data": 23, "match_info": 23, "ok": 23, "accept": 23, "incom": 23, "appropri": 23, "input": 23, "webserv": 23, "visit": [19, 23], "stabl": 23, "mention": 23, "inner": 23, "except": [14, 23], "lightweight": 23, "power": [14, 23], "mongodbstorageservic": 23, "pop": 23, "cre": 23, "zip": 23, "duplicateerror": [14, 23], "alreadi": [14, 23], "implicitli": 23, "movi": 23, "insert": 23, "5555": 23, "44424": 23, "200": 23, "statu": 23, "troubleshoot": 23, "modulenotfounderror": 23, "pymongo": [14, 23], "mongo_replica_set_cli": 23, "motor": [14, 23], "oserror": 23, "errno": 23, "98": 23, "attempt": 23, "bind": 23, "8081": 23, "congratul": 23, "oh": 23, "r": 23, "ask": 23, "challeng": 23, "Or": 23, "add_delet": 23, "elast": 14, "manipul": 21, "pointer": 14, "_updating_an_object": [], "updating_an_object": [], "dedic": 14, "object_cr": 14, "rememb": [14, 18], "crash": 14, "al": [], "pprint": 14, "indent": 14, "driver": 14, "motor_asyncio": 14, "asynciomotorcollect": 14, "suitabl": 14, "offici": 14, "generateid": [], "coll": 14, "cursor": 14, "fetch_next": 14, "next_object": 14, "encrypt": 21, "decrypt": 21, "gitlibraryprovid": 8, "clone": 8, "temporari": 8, "filesystemprovid": 8, "deploytoken": 8, "publickei": 8, "privatekei": 8, "ssh": 8, "johnsmith": 8, "secretpassword": 8, "repodir": 8, "asabdb": 14, "elasticsearch_url": 14, "9200": 14, "elasticsearch_usernam": 14, "johndo": 14, "elasticsearch_password": 14, "lorem_ipsum_dolor": 14, "sit_amet": 14, "2023": 14, "refresh": [8, 14], "co": [], "guid": [], "scroll": 14, "scroll_timeout": 14, "1m": 14, "storageserviceabc": 14, "inmemoryupsertor": [], "possibli": [], "_type_": [], "retriev": 14, "field": [8, 14], "ae": [], "algorithm": 14, "Not": [], "notimplementederror": [], "inmemorystorag": [], "identif": 14, "runtimeerror": [], "wa": 10, "bif": [], "upfront": 14, "collid": 14, "byzantin": 14, "fault": 14, "mongodbupsertor": [], "generate_id": 14, "close": 14, "ec": 14, "definit": 14, "get_index_templ": 14, "template_nam": 14, "templat": 14, "put_index_templ": 14, "reindex": 14, "previous_index": 14, "new_index": 14, "batch": 14, "_from": 14, "10000": 14, "match": 14, "offset": 14, "hit": 14, "search_str": 14, "back": [10, 14], "empty_index": 14, "certifi": 14, "symmetr": 14, "cbc": 14, "fact": 14, "aes_encrypt": 14, "aes_decrypt": 14, "advanc": 14, "confidenti": 14, "plaintext": 14, "fix": 14, "128": 14, "bit": 14, "stand": 14, "chain": 14, "techniqu": 14, "extra": 14, "ensur": 14, "ciphertext": 14, "modif": 14, "larg": 14, "much": 14, "less": 14, "comput": [12, 14], "asymmetr": 14, "bulk": 14, "adher": 14, "cryptographi": 14, "aes_kei": 14, "random_key_str": 14, "keep": [10, 14], "expos": 14, "message_binari": 14, "ascii": 14, "number_binari": 14, "gcollect": [], "binari": 14, "hash": 14, "hashlib": 14, "worri": 14, "length": 14, "raw": 14, "iv": 14, "arrai": [14, 18], "vector": 14, "left": 14, "random": 14, "xxx": [], "upsertorabc": 14, "objfield": 14, "encrypt_iv": 14, "unset": 14, "obj_field": 14, "scalar": 14, "afterward": 14, "payload": 14, "storage_servic": [], "raccoon": [], "custom_kei": [], "custom_valu": [], "create_us": [], "2o": [], "h3ulpo": [], "zwdrksbqlyb3pys0jjxcjj3nr6uqau8au": [], "id_field_nam": [], "inc": [], "_c": [], "07": [], "11t16": [], "06": [], "04": [], "380445": [], "_m": [], "c\u00e9o\u017ee": [], "typeerror": 14, "thre": 14, "cannot": [8, 14, 19], "pygit2": 8, "repo": [], "authentif": [], "independ": 8, "grant": 8, "attach": 8, "person": 8, "remain": 8, "prefer": 8, "ee": [], "deploy_token": 8, "possess": 8, "owner": 8, "role": 8, "activ": [8, 10], "leav": 8, "again": [8, 12], "tanuki": [], "awesome_project": 8, "moment": 10, "is_reset": 10, "determin": 10, "1f": 10, "add_field": 10, "2f": 10, "2t": 10, "agregationcount": 10, "3f": 10, "3t": 10, "4t": 10, "fraction": 10, "dc": 10, "off": 10, "5f": 10, "min": 10, "overwritten": 10, "5t": 10, "6f": 10, "6t": 10, "ten": 12, "reach": 12, "limit": 12, "05": 12, "perform": 12, "reawaken": 12, "exceed": 12, "finish": 12, "9": 12, "combin": 14, "uuid": 14, "sha": 14, "256": 14, "represent": 14, "label": 18, "sort": 18, "my_method": 18, "exactli": 18, "dash": 18, "module_nam": 18, "still": [18, 19], "default_route_tag": 18, "class_nam": 18, "_on_zk_connect": 19, "zookeeper_serv": 19, "lost": 19, "suspend": 19, "establish": 19, "transit": 19, "issu": 19, "node": 19, "longer": 19, "quorum": 19, "upon": 19, "mor": 19, "readthedoc": 19, "latest": 19, "basic_usag": 19, "understand": 19, "john": 8}, "objects": {"asab": [[5, 0, 1, "", "Application"], [6, 1, 1, "", "Config"], [11, 0, 1, "", "Module"], [12, 0, 1, "", "PubSub"], [13, 0, 1, "", "Service"], [12, 0, 1, "", "Subscriber"], [15, 4, 0, "-", "abc"], [9, 4, 0, "-", "log"], [15, 4, 0, "-", "pdict"], [15, 4, 0, "-", "socket"], [15, 4, 0, "-", "timer"]], "asab.Application": [[5, 1, 1, "", "Description"], [5, 2, 1, "", "ExitCode"], [5, 2, 1, "", "Loop"], [5, 2, 1, "", "Modules"], [12, 2, 1, "", "PubSub"], [5, 2, 1, "", "Services"], [5, 3, 1, "", "__init__"], [5, 3, 1, "", "add_module"], [5, 3, 1, "", "create_argument_parser"], [5, 3, 1, "", "finalize"], [5, 3, 1, "", "get_service"], [5, 3, 1, "", "initialize"], [5, 3, 1, "", "main"], [5, 3, 1, "", "parse_args"], [5, 3, 1, "", "run"], [5, 3, 1, "", "set_exit_code"], [5, 3, 1, "", "stop"], [5, 3, 1, "", "time"]], "asab.Config": [[6, 3, 1, "", "add_defaults"], [6, 3, 1, "", "getseconds"], [6, 3, 1, "", "geturl"]], "asab.Module": [[11, 3, 1, "", "finalize"], [11, 3, 1, "", "initialize"]], "asab.PubSub": [[12, 3, 1, "", "publish"], [12, 3, 1, "", "subscribe"], [12, 3, 1, "", "subscribe_all"], [12, 3, 1, "", "unsubscribe"]], "asab.Service": [[13, 1, 1, "", "App"], [13, 1, 1, "", "Name"], [13, 3, 1, "", "finalize"], [13, 3, 1, "", "initialize"]], "asab.Subscriber": [[12, 3, 1, "", "message"], [12, 3, 1, "", "subscribe"]], "asab.abc": [[15, 0, 1, "", "Module"], [15, 0, 1, "", "Service"], [15, 0, 1, "", "Singleton"], [15, 4, 0, "-", "singleton"]], "asab.abc.Module": [[15, 3, 1, "", "finalize"], [15, 3, 1, "", "initialize"]], "asab.abc.Service": [[15, 3, 1, "", "finalize"], [15, 3, 1, "", "initialize"]], "asab.abc.Singleton": [[15, 3, 1, "", "delete"]], "asab.abc.singleton": [[15, 0, 1, "", "Singleton"]], "asab.abc.singleton.Singleton": [[15, 3, 1, "", "delete"]], "asab.config": [[6, 0, 1, "", "ConfigParser"]], "asab.library": [[8, 0, 1, "", "LibraryService"]], "asab.library.LibraryService": [[8, 3, 1, "", "export"], [8, 3, 1, "", "list"], [8, 3, 1, "", "read"], [8, 3, 1, "", "subscribe"]], "asab.library.providers.azurestorage": [[8, 0, 1, "", "AzureStorageLibraryProvider"]], "asab.library.providers.filesystem": [[8, 0, 1, "", "FileSystemLibraryProvider"]], "asab.library.providers.git": [[8, 0, 1, "", "GitLibraryProvider"]], "asab.library.providers.zookeeper": [[8, 0, 1, "", "ZooKeeperLibraryProvider"]], "asab.log": [[9, 0, 1, "", "AsyncIOHandler"], [9, 0, 1, "", "Logging"], [9, 0, 1, "", "MacOSXSyslogFormatter"], [9, 0, 1, "", "StructuredDataFormatter"], [9, 0, 1, "", "SyslogRFC3164Formatter"], [9, 0, 1, "", "SyslogRFC5424Formatter"]], "asab.log.AsyncIOHandler": [[9, 3, 1, "", "emit"]], "asab.log.Logging": [[9, 3, 1, "", "rotate"]], "asab.log.StructuredDataFormatter": [[9, 2, 1, "", "BLACK"], [9, 2, 1, "", "BLUE"], [9, 2, 1, "", "CYAN"], [9, 2, 1, "", "GREEN"], [9, 2, 1, "", "MAGENTA"], [9, 2, 1, "", "RED"], [9, 2, 1, "", "WHITE"], [9, 2, 1, "", "YELLOW"], [9, 2, 1, "", "empty_sd"], [9, 3, 1, "", "format"], [9, 3, 1, "", "formatTime"], [9, 3, 1, "", "render_struct_data"]], "asab.log.SyslogRFC5424Formatter": [[9, 2, 1, "", "empty_sd"]], "asab.metrics": [[10, 0, 1, "", "AggregationCounter"], [10, 0, 1, "", "AggregationCounterWithDynamicTags"], [10, 0, 1, "", "Counter"], [10, 0, 1, "", "CounterWithDynamicTags"], [10, 0, 1, "", "DutyCycle"], [10, 0, 1, "", "EPSCounter"], [10, 0, 1, "", "Gauge"], [10, 0, 1, "", "Histogram"], [10, 0, 1, "", "HistogramWithDynamicTags"], [10, 0, 1, "", "MetricsService"]], "asab.metrics.AggregationCounter": [[10, 3, 1, "", "set"]], "asab.metrics.AggregationCounterWithDynamicTags": [[10, 3, 1, "", "set"]], "asab.metrics.Counter": [[10, 3, 1, "", "add"], [10, 3, 1, "", "sub"]], "asab.metrics.CounterWithDynamicTags": [[10, 3, 1, "", "add"], [10, 3, 1, "", "sub"]], "asab.metrics.Gauge": [[10, 3, 1, "", "set"]], "asab.metrics.Histogram": [[10, 3, 1, "", "set"]], "asab.metrics.HistogramWithDynamicTags": [[10, 3, 1, "", "set"]], "asab.metrics.MetricsService": [[10, 3, 1, "", "create_aggregation_counter"], [10, 3, 1, "", "create_counter"], [10, 3, 1, "", "create_duty_cycle"], [10, 3, 1, "", "create_eps_counter"], [10, 3, 1, "", "create_gauge"], [10, 3, 1, "", "create_histogram"]], "asab.pdict": [[15, 0, 1, "", "PersistentDict"]], "asab.pdict.PersistentDict": [[15, 3, 1, "", "load"], [15, 3, 1, "", "store"], [15, 3, 1, "", "update"]], "asab.socket": [[15, 0, 1, "", "StreamSocketServerService"]], "asab.socket.StreamSocketServerService": [[15, 3, 1, "", "create_server"], [15, 3, 1, "", "finalize"]], "asab.storage.elasticsearch": [[14, 0, 1, "", "StorageService"]], "asab.storage.elasticsearch.StorageService": [[14, 3, 1, "", "count"], [14, 3, 1, "", "empty_index"], [14, 3, 1, "", "finalize"], [14, 3, 1, "", "get_index_template"], [14, 3, 1, "", "indices"], [14, 3, 1, "", "list"], [14, 3, 1, "", "mapping"], [14, 3, 1, "", "put_index_template"], [14, 3, 1, "", "reindex"], [14, 3, 1, "", "scroll"], [14, 3, 1, "", "session"]], "asab.storage.inmemory": [[14, 0, 1, "", "StorageService"]], "asab.storage.mongodb": [[14, 0, 1, "", "StorageService"]], "asab.storage.mongodb.StorageService": [[14, 3, 1, "", "collection"], [14, 3, 1, "", "get_by"]], "asab.storage.service": [[14, 0, 1, "", "StorageServiceABC"]], "asab.storage.service.StorageServiceABC": [[14, 3, 1, "", "aes_decrypt"], [14, 3, 1, "", "aes_encrypt"], [14, 3, 1, "", "delete"], [14, 3, 1, "", "get"], [14, 3, 1, "", "upsertor"]], "asab.storage.upsertor": [[14, 0, 1, "", "UpsertorABC"]], "asab.storage.upsertor.UpsertorABC": [[14, 3, 1, "", "execute"], [14, 3, 1, "", "generate_id"], [14, 3, 1, "", "set"], [14, 3, 1, "", "unset"]], "asab.timer": [[15, 0, 1, "", "Timer"]], "asab.timer.Timer": [[15, 3, 1, "", "is_started"], [15, 3, 1, "", "restart"], [15, 3, 1, "", "start"], [15, 3, 1, "", "stop"]], "asab.web.service": [[17, 0, 1, "", "WebService"]], "asab.web.session": [[17, 0, 1, "", "ServiceWebSession"], [17, 5, 1, "", "session_middleware"]], "asab.zookeeper": [[19, 0, 1, "", "ZooKeeperContainer"]], "asab.zookeeper.ZooKeeperContainer": [[19, 3, 1, "", "advertise"], [19, 3, 1, "", "get_children"], [19, 3, 1, "", "get_data"], [19, 3, 1, "", "get_raw_data"], [19, 3, 1, "", "is_connected"]], "": [[0, 6, 1, "cmdoption-d", "--daemonize"], [0, 6, 1, "cmdoption-h", "--help"], [0, 6, 1, "cmdoption-k", "--kill"], [0, 6, 1, "cmdoption-s", "--syslog"], [0, 6, 1, "cmdoption-v", "--verbose"], [0, 6, 1, "cmdoption-c", "-c"], [0, 6, 1, "cmdoption-d", "-d"], [0, 6, 1, "cmdoption-h", "-h"], [0, 6, 1, "cmdoption-k", "-k"], [0, 6, 1, "cmdoption-l", "-l"], [0, 6, 1, "cmdoption-s", "-s"], [0, 6, 1, "cmdoption-v", "-v"]], "Application": [[12, 6, 1, "cmdoption-arg-Application.exit", "exit!"], [12, 6, 1, "cmdoption-arg-Application.housekeeping", "housekeeping!"], [12, 6, 1, "cmdoption-arg-Application.hup", "hup!"], [12, 6, 1, "cmdoption-arg-Application.init", "init!"], [12, 6, 1, "cmdoption-arg-Application.run", "run!"], [12, 6, 1, "cmdoption-arg-Application.stop", "stop!"], [12, 6, 1, "cmdoption-arg-Application.tick", "tick!"], [12, 6, 1, "cmdoption-arg-Application.tick-10", "tick/10!"], [12, 6, 1, "cmdoption-arg-Application.tick-1800", "tick/1800!"], [12, 6, 1, "cmdoption-arg-Application.tick-300", "tick/300!"], [12, 6, 1, "cmdoption-arg-Application.tick-3600", "tick/3600!"], [12, 6, 1, "cmdoption-arg-Application.tick-43200", "tick/43200!"], [12, 6, 1, "cmdoption-arg-Application.tick-60", "tick/60!"], [12, 6, 1, "cmdoption-arg-Application.tick-600", "tick/600!"], [12, 6, 1, "cmdoption-arg-Application.tick-86400", "tick/86400!"]], "Library": [[8, 6, 1, "cmdoption-arg-Library.change", "change!"], [8, 6, 1, "cmdoption-arg-Library.ready", "ready!"]], "ZooKeeperContainer": [[19, 6, 1, "cmdoption-arg-ZooKeeperContainer.state-CONNECTED", "state/CONNECTED!"], [19, 6, 1, "cmdoption-arg-ZooKeeperContainer.state-LOST", "state/LOST!"], [19, 6, 1, "cmdoption-arg-ZooKeeperContainer.state-SUSPENDED", "state/SUSPENDED!"]]}, "objtypes": {"0": "py:class", "1": "py:data", "2": "py:attribute", "3": "py:method", "4": "py:module", "5": "py:function", "6": "std:cmdoption"}, "objnames": {"0": ["py", "class", "Python class"], "1": ["py", "data", "Python data"], "2": ["py", "attribute", "Python attribute"], "3": ["py", "method", "Python method"], "4": ["py", "module", "Python module"], "5": ["py", "function", "Python function"], "6": ["std", "cmdoption", "program option"]}, "titleterms": {"asab": [0, 1, 2, 3, 7, 10, 21], "command": [0, 5], "line": [0, 5], "interfac": 0, "configur": [0, 6, 8, 14, 17, 18, 19], "log": [0, 9], "daemon": 0, "containeris": 1, "lxc": 1, "lxd": 1, "contain": [1, 19], "docker": 1, "remot": 1, "api": [1, 18, 23], "instal": 2, "us": [2, 9], "pip": 2, "easy_instal": 2, "github": 2, "systemd": 3, "start": [3, 20], "server": [3, 7, 17, 21, 22], "stop": 3, "alert": 4, "servic": [4, 5, 8, 10, 13, 17, 21, 23], "opsgeni": 4, "pagerduti": 4, "de": 4, "duplic": 4, "applic": [5, 7, 12, 21], "event": 5, "loop": 5, "lifecycl": [5, 11, 13], "init": 5, "time": 5, "run": 5, "exit": 5, "modul": [5, 11], "registri": 5, "parser": 5, "utc": 5, "base": 6, "configpars": 6, "multilin": 6, "entri": 6, "automat": 6, "load": 6, "includ": 6, "other": 6, "file": [6, 9], "default": 6, "valu": [6, 10], "environ": [6, 19], "variabl": [6, 19], "configr": 6, "password": 6, "obtain": 6, "second": 6, "url": [6, 19], "asynchron": [7, 12, 21], "boilerpl": [7, 21], "": [7, 21], "document": [7, 21], "i": [7, 21], "design": [7, 21], "power": [7, 21], "yet": [7, 21], "simpl": [7, 21], "right": [7, 21], "choic": [7, 21], "when": [7, 21], "librari": 8, "structur": [8, 9, 11], "path": 8, "rule": 8, "notif": 8, "chang": 8, "provid": 8, "filesystem": 8, "apach": 8, "zookeep": [8, 19], "microsoft": 8, "azur": 8, "storag": [8, 14], "git": 8, "repositori": 8, "layer": 8, "recommend": 9, "level": 9, "verbos": 9, "mode": 9, "data": [9, 14], "consol": 9, "rotat": 9, "syslog": 9, "obsolet": 9, "featur": 9, "refer": [8, 9, 10, 14, 21], "metric": 10, "type": [10, 19], "interpret": 10, "initi": 10, "dynam": 10, "tag": [10, 18], "influxdb": 10, "prometheu": 10, "endpoint": 10, "http": 10, "target": 10, "web": [10, 17, 22], "request": 10, "nativ": 10, "publish": 12, "subscrib": 12, "subscript": 12, "synchron": 12, "v": 12, "messag": [8, 12, 19], "wide": 12, "pubsub": [8, 12, 19], "well": 12, "known": 12, "specifi": [], "store": 14, "memori": 14, "mongodb": [14, 23], "elast": [], "search": [], "manipul": 14, "databas": 14, "variou": 15, "util": 15, "class": 15, "singleton": 15, "persist": 15, "dictionari": 15, "timer": 15, "socket": 15, "authn": [], "middlewar": [], "decor": [], "exampl": 19, "cross": 16, "origin": 16, "resourc": 16, "share": 16, "cor": 16, "The": [17, 22], "session": 17, "rest": [18, 23], "doc": 18, "In": [14, 18], "your": 18, "microservic": [18, 23], "author": 18, "swagger": 18, "section": 19, "zookeeper_serv": [], "support": 19, "z_path": 19, "read": 19, "from": 19, "zookeeep": 19, "advertis": 19, "kazoo": 19, "get": [14, 20], "go": 20, "detail": 20, "next": 20, "step": 20, "introduct": 21, "administr": 21, "indic": 21, "tabl": 21, "tutori": 22, "code": 22, "deeper": 22, "look": 22, "creat": 23, "prerequisit": 23, "compon": 23, "postman": 23, "myrestapi": 23, "py": 23, "app": 23, "__init__": 23, "handler": 23, "now": 23, "test": 23, "updat": [14, 23], "delet": [14, 23], "upsertor": 14, "insert": 14, "an": 14, "object": 14, "singl": 14, "specif": [], "encrypt": 14, "decrypt": 14, "id": [], "elasticsearch": 14, "algorithm": [], "ae": 14, "kei": 14, "set": 14, "more": [], "cbc": [], "under": 14, "hood": 14, "storageservic": 14, "deploi": 8, "token": 8, "gitlab": 8, "timestamp": 10, "asab_zookeeper_serv": 19, "function": 8}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2, "sphinx.ext.viewcode": 1, "sphinx.ext.intersphinx": 1, "sphinx": 57}, "alltitles": {"ASAB Command-line interface": [[0, "asab-command-line-interface"]], "Configuration": [[0, "configuration"], [6, "configuration"], [14, "configuration"], [17, "configuration"], [18, "configuration"]], "Logging": [[0, "logging"], [9, "logging"]], "Daemon": [[0, "daemon"]], "Containerisation": [[1, "containerisation"]], "ASAB in a LXC/LXD container": [[1, "asab-in-a-lxc-lxd-container"]], "Docker Remote API": [[1, "docker-remote-api"]], "Installation": [[2, "installation"]], "Install ASAB using pip": [[2, "install-asab-using-pip"]], "Install ASAB using easy_install": [[2, "install-asab-using-easy-install"]], "Install ASAB for a GitHub": [[2, "install-asab-for-a-github"]], "systemd": [[3, "systemd"]], "Start of ASAB Server": [[3, "start-of-asab-server"]], "Stop of ASAB Server": [[3, "stop-of-asab-server"]], "Alert Service": [[4, "alert-service"]], "Opsgenie": [[4, "opsgenie"]], "PagerDuty": [[4, "pagerduty"]], "De-duplication": [[4, "de-duplication"]], "Application": [[5, "application"]], "Event Loop": [[5, "event-loop"]], "Application Lifecycle": [[5, "application-lifecycle"]], "Init-time": [[5, "init-time"]], "Run-time": [[5, "run-time"]], "Exit-time": [[5, "exit-time"]], "Module registry": [[5, "module-registry"]], "Service registry": [[5, "service-registry"]], "Command-line parser": [[5, "command-line-parser"]], "UTC Time": [[5, "utc-time"]], "Based on ConfigParser": [[6, "based-on-configparser"]], "Multiline configuration entry": [[6, "multiline-configuration-entry"]], "Automatic load of configuration": [[6, "automatic-load-of-configuration"]], "Including other configuration files": [[6, "including-other-configuration-files"]], "Configuration default values": [[6, "configuration-default-values"]], "Environment variables in configration": [[6, "environment-variables-in-configration"]], "Passwords in configration": [[6, "passwords-in-configration"]], "Obtaining seconds": [[6, "obtaining-seconds"]], "Obtaining URLs": [[6, "obtaining-urls"]], "Asynchronous Server Application Boilerplate\u2019s documentation": [[7, "asynchronous-server-application-boilerplate-s-documentation"], [21, "asynchronous-server-application-boilerplate-s-documentation"]], "ASAB is designed to be powerful yet simple": [[7, "asab-is-designed-to-be-powerful-yet-simple"], [21, "asab-is-designed-to-be-powerful-yet-simple"]], "ASAB is the right choice when": [[7, "asab-is-the-right-choice-when"], [21, "asab-is-the-right-choice-when"]], "Recommended use": [[9, "recommended-use"]], "Logging Levels": [[9, "logging-levels"]], "Verbose mode": [[9, "verbose-mode"]], "Structured data": [[9, "structured-data"]], "Logging to file": [[9, "logging-to-file"]], "Logging to console": [[9, "logging-to-console"]], "Log rotation": [[9, "log-rotation"]], "Logging to syslog": [[9, "logging-to-syslog"]], "Logging of obsolete features": [[9, "logging-of-obsolete-features"]], "Reference": [[9, "module-asab.log"], [10, "reference"], [14, "reference"], [8, "reference"], [21, null]], "Metrics": [[10, "metrics"]], "Metrics Service": [[10, "metrics-service"]], "Types of Metrics": [[10, "types-of-metrics"]], "ASAB Metrics Interpretation": [[10, "asab-metrics-interpretation"]], "Initial Values": [[10, "initial-values"]], "Dynamic Tags": [[10, "dynamic-tags"]], "Timestamp": [[10, "timestamp"]], "InfluxDB": [[10, "influxdb"]], "Prometheus": [[10, "id2"]], "Metrics Endpoints": [[10, "metrics-endpoints"]], "HTTP Target": [[10, "http-target"]], "Web Requests Metrics": [[10, "web-requests-metrics"]], "Native Metrics": [[10, "native-metrics"]], "Module": [[11, "module"]], "Structure": [[11, "structure"]], "Lifecycle": [[11, "lifecycle"], [13, "lifecycle"]], "Publish-Subscribe": [[12, "publish-subscribe"]], "Subscription": [[12, "subscription"]], "Publishing": [[12, "publishing"]], "Synchronous vs. asynchronous messaging": [[12, "synchronous-vs-asynchronous-messaging"]], "Application-wide PubSub": [[12, "application-wide-pubsub"]], "Well-Known Messages": [[12, "well-known-messages"]], "Service": [[13, "service"]], "Storage": [[14, "storage"]], "Manipulation with databases": [[14, "manipulation-with-databases"]], "Upsertor": [[14, "upsertor"], [14, "id1"]], "Inserting an object": [[14, "inserting-an-object"]], "Getting a single object": [[14, "getting-a-single-object"]], "Updating an object": [[14, "updating-an-object"]], "Deleting an object": [[14, "deleting-an-object"]], "Storing data in memory": [[14, "storing-data-in-memory"]], "Storing data in MongoDB": [[14, "storing-data-in-mongodb"]], "Storing data in ElasticSearch": [[14, "storing-data-in-elasticsearch"]], "Encryption and decryption": [[14, "encryption-and-decryption"]], "AES Key settings": [[14, "aes-key-settings"]], "Encrypting data": [[14, "encrypting-data"]], "Decrypting data": [[14, "decrypting-data"]], "Under the hood": [[14, "under-the-hood"]], "StorageService": [[14, "storageservice"]], "In-memory storage": [[14, "in-memory-storage"]], "MongoDB Storage": [[14, "mongodb-storage"]], "ElasticSearch Storage": [[14, "elasticsearch-storage"]], "Various utility classes": [[15, "module-asab.abc"]], "Singleton": [[15, "module-asab.abc.singleton"]], "Persistent dictionary": [[15, "module-asab.pdict"]], "Timer": [[15, "module-asab.timer"]], "Sockets": [[15, "module-asab.socket"]], "Cross-Origin Resource Sharing (CORS)": [[16, "cross-origin-resource-sharing-cors"]], "The web server": [[17, "the-web-server"]], "Web Service": [[17, "web-service"]], "Sessions": [[17, "sessions"]], "REST API Docs": [[18, "rest-api-docs"]], "In your microservice": [[18, "in-your-microservice"]], "Authorization in Swagger": [[18, "authorization-in-swagger"]], "Tags": [[18, "tags"]], "PubSub messages": [[19, "pubsub-messages"], [8, "pubsub-messages"]], "Zookeeper": [[19, "zookeeper"]], "Zookeeper container": [[19, "zookeeper-container"]], "Example of configuration section": [[19, "example-of-configuration-section"]], "Example of ASAB_ZOOKEEPER_SERVERS environment variable": [[19, "example-of-asab-zookeeper-servers-environment-variable"]], "Supported types of z_path URLs": [[19, "supported-types-of-z-path-urls"]], "Reading from Zookeeeper": [[19, "reading-from-zookeeeper"]], "Advertisement into Zookeeper": [[19, "advertisement-into-zookeeper"]], "Kazoo": [[19, "id1"]], "Getting started": [[20, "getting-started"]], "Going into details": [[20, "going-into-details"]], "Next steps": [[20, "next-steps"]], "Web Server Tutorial": [[22, "web-server-tutorial"]], "The code": [[22, "the-code"]], "Deeper look": [[22, "deeper-look"]], "Create microservice with REST API": [[23, "create-microservice-with-rest-api"]], "Prerequisites": [[23, "prerequisites"]], "Components": [[23, "components"]], "MongoDB": [[23, "mongodb"]], "Postman": [[23, "postman"]], "myrestapi.py": [[23, "myrestapi-py"]], "app.py": [[23, "app-py"]], "__init__.py": [[23, "init-py"]], "handler.py": [[23, "handler-py"]], "service.py": [[23, "service-py"]], "Now test it!": [[23, "now-test-it"]], "Update and Delete": [[23, "update-and-delete"]], "Library": [[8, "library"]], "Library structure": [[8, "library-structure"]], "Library path rules": [[8, "library-path-rules"]], "Library service": [[8, "library-service"]], "Notification of changes": [[8, "notification-of-changes"]], "Providers": [[8, "providers"]], "Filesystem": [[8, "filesystem"]], "Apache Zookeeper": [[8, "apache-zookeeper"]], "Microsoft Azure Storage": [[8, "microsoft-azure-storage"]], "Git repository": [[8, "git-repository"]], "Functionality": [[8, "functionality"]], "Deploy tokens in GitLab": [[8, "deploy-tokens-in-gitlab"]], "Layers": [[8, "layers"]], "Library configuration": [[8, "library-configuration"]], "Introduction": [[21, null]], "Services": [[21, null]], "Administration": [[21, null]], "Indices and tables": [[21, "indices-and-tables"]]}, "indexentries": {"azurestoragelibraryprovider (class in asab.library.providers.azurestorage)": [[8, "asab.library.providers.azurestorage.AzureStorageLibraryProvider"]], "filesystemlibraryprovider (class in asab.library.providers.filesystem)": [[8, "asab.library.providers.filesystem.FileSystemLibraryProvider"]], "gitlibraryprovider (class in asab.library.providers.git)": [[8, "asab.library.providers.git.GitLibraryProvider"]], "library.change!": [[8, "cmdoption-arg-Library.change"]], "library.ready!": [[8, "cmdoption-arg-Library.ready"]], "libraryservice (class in asab.library)": [[8, "asab.library.LibraryService"]], "zookeeperlibraryprovider (class in asab.library.providers.zookeeper)": [[8, "asab.library.providers.zookeeper.ZooKeeperLibraryProvider"]], "command line option": [[8, "cmdoption-arg-Library.change"], [8, "cmdoption-arg-Library.ready"]], "export() (asab.library.libraryservice method)": [[8, "asab.library.LibraryService.export"]], "list() (asab.library.libraryservice method)": [[8, "asab.library.LibraryService.list"]], "read() (asab.library.libraryservice method)": [[8, "asab.library.LibraryService.read"]], "subscribe() (asab.library.libraryservice method)": [[8, "asab.library.LibraryService.subscribe"]]}}) \ No newline at end of file diff --git a/old_docs/_build/html/tutorial/web/chapter1.html b/old_docs/_build/html/tutorial/web/chapter1.html new file mode 100644 index 000000000..a1aa4f82c --- /dev/null +++ b/old_docs/_build/html/tutorial/web/chapter1.html @@ -0,0 +1,213 @@ + + + + + + + + + Web Server Tutorial — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Web Server Tutorial

+

Create a simple web server with ASAB.

+
+

The code

+
#!/usr/bin/env python3
+import asab.web.rest
+
+
+class MyWebApplication(asab.Application):
+
+    def __init__(self):
+        super().__init__()
+
+        # Create the Web server
+        web = asab.web.create_web_server(self)
+
+        # Add a route to the handler method
+        web.add_get('/hello', self.hello)
+
+    # This is the web request handler
+    async def hello(self, request):
+        return asab.web.rest.json_response(
+            request,
+            data="Hello, world!\n"
+        )
+
+
+if __name__ == '__main__':
+    app = MyWebApplication()
+    app.run()
+
+
+
+
To start the application, store above code in a file app.py.
+
Execute $ python3 ./app.py to run it.
+
+

The ASAB web server is now available at http://localhost:8080/.

+
+
+

Deeper look

+

ASAB Application

+
#!/usr/bin/env python3
+import asab.web.rest
+
+class MyWebApplication(asab.Application):
+
+    def __init__(self):
+        super().__init__()
+
+if __name__ == '__main__':
+    app = MyWebApplication()
+    app.run()
+
+
+

This is a ASAB code that declares the application class and runs it.

+

Create a Web server

+

The asab.web module provides a create_web_server() function that simplifies creation of the Web server in the ASAB application.

+
web = asab.web.create_web_server(self)
+
+
+

Install the handler

+
web.add_get('/hello', self.hello)
+
+...
+
+async def hello(self, request):
+    return asab.web.rest.json_response(
+        request,
+        data="Hello, world!\n"
+    )
+
+
+

The handler method hello() is installed at the web server at /hello endpoint. +HTTP method is GET.

+

It means that if you access the web server with a path /hello, it will be handled by a hello(...) method. A handler method must be a coroutine.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/html/tutorial/web/chapter2.html b/old_docs/_build/html/tutorial/web/chapter2.html new file mode 100644 index 000000000..dbf2c69f2 --- /dev/null +++ b/old_docs/_build/html/tutorial/web/chapter2.html @@ -0,0 +1,673 @@ + + + + + + + + + Create microservice with REST API — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Create microservice with REST API

+

With this tutorial, you will create a basic ASAB microservice that provides a REST HTTP API. +This microservice will implement Create, Read, Update and Delete functionality, in another words CRUD. +MongoDB will be used as the database.

+
+

Prerequisites

+
    +
  1. Python version 3.6 or later

  2. +
  3. Asynchronous Server App Boilerplate (ASAB) version 20.3 or later

  4. +
  5. MongoDB instance

  6. +
  7. Postman

  8. +
+
+

Note

+

We will use Docker to run MongoDB. Docker installation is not covered in this tutorial, but there are scores of good ones online should you run into any trouble. If you’re not familiar with Docker yet, it is a great opportunity to start (https://www.docker.com/get-started/).

+

Otherwise, you can install MongoDB following one of these tutorials: https://www.mongodb.com/docs/manual/installation/

+
+
+
+

Components

+

The microservice consists of several modules (aka Python files). +These modules are as follows (and also indicate the file structure) and will be discussed in more detail in the respective sections below, going from top to bottom:

+
.
+└── myrestapi.py
+─── myrestapi
+        └── __init__.py
+        ─── app.py
+        ─── tutorial
+                └── handler.py
+                └── service.py
+
+
+
+
+

MongoDB

+

To make things simple, let’s use a Docker image.

+

Pull this image: +https://hub.docker.com/_/mongo

+

You can simply use the command below to run it. +If you choose to run the instance without a password, +don’t forget to adjust the related asab.Config in ./myrestapi/app.py.

+
docker run -d -p 27017:27017 \
+        -e MONGO_INITDB_ROOT_USERNAME=user \
+        -e MONGO_INITDB_ROOT_PASSWORD=secret \
+        mongo
+
+
+
+
+

Postman

+

We use Postman to test the webservice REST API.

+

You can download it here: +https://www.postman.com/downloads/

+

The Postman is fairly straightforward to use. +You can create your collection of HTTP requests, save them, or automatically generate documentation.

+
+
+

myrestapi.py

+

This is where everything starts. +Begin with the shebang line, which tells the executing operating system python should execute this program.

+
#!/usr/bin/env python3
+
+
+

Imports follow. All you need here is the application. It is called TutorialApp:

+
from myrestapi import TutorialApp
+
+
+

Next, instantiate an application class TutorialApp in the __main__ of the application, and run it:

+
if __name__ == '__main__':
+        app = TutorialApp()
+        app.run()
+
+
+
+
+

app.py

+

./myrestapi/app.py

+

Define the application class TutorialApp.

+

Imports first:

+
import asab
+import asab.web
+import asab.web.rest
+import asab.storage
+
+
+

Add some default configuration:

+
asab.Config.add_defaults(
+{
+        'asab:storage': {
+                'type': 'mongodb',
+                'mongodb_uri': 'mongodb://mongouser:mongopassword@mongoipaddress:27017',
+                'mongodb_database': 'mongodatabase'
+        },
+})
+
+
+
+

Note

+

To make things more simple, Mongo credentials are stored here as a default configuration. +Usually, you provide your app with a configuration file using -c commandline option. +Learn more in section Configuration.

+
+

Next, describe the class, it inherits from the basic ASAB Application class, +but you need to expand it a little:

+
class TutorialApp(asab.Application):
+
+        def __init__(self):
+                super().__init__()
+                # Register modules
+                self.add_module(asab.web.Module)
+                self.add_module(asab.storage.Module)
+
+                # Locate the web service
+                self.WebService = self.get_service("asab.WebService")
+                self.WebContainer = asab.web.WebContainer(
+                        self.WebService, "web"
+                )
+                self.WebContainer.WebApp.middlewares.append(
+                        asab.web.rest.JsonExceptionMiddleware
+                )
+
+                # Initialize services
+                from .tutorial.handler import CRUDWebHandler
+                from .tutorial.service import CRUDService
+                self.CRUDService = CRUDService(self)
+                self.CRUDWebHandler = CRUDWebHandler(
+                        self, self.CRUDService
+                )
+
+
+
+
+

__init__.py

+

./myrestapi/__init__.py

+

Init file is needed so myrestapi will work as a module. +Just import the TutorialApp.

+
from .app import TutorialApp
+
+__all__ = [
+        "TutorialApp",
+]
+
+
+
+
+

handler.py

+

./myrestapi/tutorial/handler.py

+

The handler is where HTTP Rest calls are handled and transformed into the actual (internal) service calls. +From another perspective, the handler should contain only translation between REST calls and the service interface. +No actual ‘business logic’ should be here. +It is strongly suggested to build these CRUD methods one by one and test them straight away. +If you haven’t set up your database test instance yet, now is the time to do it.

+

As usual, we start by importing modules:

+
import asab
+import asab.web.rest
+
+
+

Let’s start with two methods - create and read which allow us to write into database and check the record.

+
class CRUDWebHandler(object):
+        def __init__(self, app, mongo_svc):
+                self.CRUDService = mongo_svc
+                web_app = app.WebContainer.WebApp
+                web_app.router.add_put(
+                        '/crud-myrestapi/{collection}',
+                        self.create
+                )
+                web_app.router.add_get(
+                        '/crud-myrestapi/{collection}/{id}',
+                        self.read
+                )
+
+
+        @asab.web.rest.json_schema_handler({
+                'type': 'object',
+                'properties': {
+                        '_id': {'type': 'string'},
+                        'field1': {'type': 'string'},
+                        'field2': {'type': 'number'},
+                        'field3': {'type': 'number'}
+                }})
+        async def create(self, request, *, json_data):
+                collection = request.match_info['collection']
+
+                result = await self.CRUDService.create(
+                        collection, json_data
+                )
+                if result:
+                        return asab.web.rest.json_response(
+                                request, {"result": "OK"}
+                        )
+                else:
+                        asab.web.rest.json_response(
+                                request, {"result": "FAILED"}
+                        )
+
+
+        async def read(self, request):
+                collection = request.match_info['collection']
+                key = request.match_info['id']
+                response = await self.CRUDService.read(
+                        collection, key
+                )
+                return asab.web.rest.json_response(
+                        request, response
+                )
+
+
+

The handler only accepts the incoming requests and returns appropriate responses. +All of the “logic”, be it the specifics of the database connection, additional validations and other +operations take place in the CRUDService.

+

POST and PUT requests typically come with data in their body. +Providing your WebContainer with JsonExceptionMiddleware enables you to validate a JSON input using @asab.web.rest.json_schema_handler decorator and JSON schema (https://json-schema.org/).

+
+

Note

+

ASAB WebServer is built on top of the aiohttp library. +For further details please visit https://docs.aiohttp.org/en/stable/index.html.

+
+
+
+

service.py

+

./myrestapi/tutorial/service.py

+

As mentioned above, this is where the inner workings of the microservice request processing are. +Let’s start as usual, by importing the desired modules:

+
import asab
+import asab.storage.exceptions
+
+
+

We want to start logging in here:

+
import logging
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+

Now define the CRUDService class which inherits from the asab.Service class.

+
+

Note

+

asab.Service is a lightweight yet powerful abstract class providing your object with 3 functionalities:

+
    +
  • Name of the asab.Service is registered in the app and can be called from the app object anywhere in your code.

  • +
  • asab.Service class implements initialize() and finalize() coroutines which help you to handle asynchronous operations in init and exit time of your application.

  • +
  • asab.Service registers application object as self.App for you.

  • +
+
+
class CRUDService(asab.Service):
+
+        def __init__(self, app, service_name='crud.CRUDService'):
+                super().__init__(app, service_name)
+                self.MongoDBStorageService = app.get_service(
+                        "asab.StorageService"
+                )
+
+        async def create(self, collection, json_data):
+                obj_id = json_data.pop("_id")
+
+                cre = self.MongoDBStorageService.upsertor(
+                        collection, obj_id
+                )
+
+                for key, value in zip(
+                        json_data.keys(), json_data.values()
+                ):
+                        cre.set(key, value)
+
+                try:
+                        await cre.execute()
+                        return "OK"
+                except asab.storage.exceptions.DuplicateError:
+                        L.warning(
+                                "Document you are trying to create already exists."
+                        )
+                        return None
+
+        async def read(self, collection, obj_id):
+                response = await self.MongoDBStorageService.get(
+                        collection, obj_id
+                )
+                return response
+
+
+

asab.StorageService initialized in app.py as part of the asab.storage.Module enables connection to MongoDB. +Further on, two methods provide the handler with the desired functionalities.

+
+
+

Now test it!

+

The application is implicitly running on an 8080 port. +Open the Postman and set a new request.

+

Try the PUT method:

+
127.0.0.1:8080/crud-myrestapi/movie
+
+
+

Insert into the request body:

+
{
+"_id": "1",
+"field1": "something new",
+"field2": 5555,
+"field3": 44424
+}
+
+
+

When there’s a record in your database, try to read it! +For example with this GET request:

+
127.0.0.1:8080/crud-myrestapi/movie/1
+
+
+

Is your response with a 200 status code? Does it return desired data?

+
+

Note

+

TROUBLESHOOTING

+

ERROR

+
ModuleNotFoundError: No module named 'pymongo.mongo_replica_set_client'
+
+
+

Try:

+
pip install motor
+
+
+

ERROR

+
OSError: [Errno 98] error while attempting to bind on address ('0.0.0.0', 8080): address already in use
+
+
+

Try to kill process listening on 8080 or add [web] section into configuration:

+
asab.Config.add_defaults(
+{
+        'asab:storage': {
+                'type': 'mongodb',
+                'mongodb_uri': 'mongodb://mongouser:mongopassword@mongoipaddress:27017',
+                'mongodb_database': 'mongodatabase'
+        },
+        'web': {
+                'listen': '0.0.0.0 8081'
+        }
+})
+
+
+

ERROR

+

No error at all, no response either.

+

Try to check the Mongo database credentials. Do your credentials in the configuration in app.py fit the ones you entered when running the Mongo Docker image?

+
+

Up and running! Congratulation on your first ASAB microservice!

+

Oh, wait…

+

C, R… What about Update and Delete you ask?

+

You already know everything to add the next functionality! Accept the challenge and try it yourself! Or check out the code below.

+
+
+

Update and Delete

+

handler.py

+

./myrestapi/tutorial/handler.py

+
import asab
+import asab.web.rest
+
+
+class CRUDWebHandler(object):
+        def __init__(self, app, mongo_svc):
+                self.CRUDService = mongo_svc
+                web_app = app.WebContainer.WebApp
+                web_app.router.add_put(
+                        '/crud-myrestapi/{collection}',
+                        self.create
+                )
+                web_app.router.add_get(
+                        '/crud-myrestapi/{collection}/{id}',
+                        self.read
+                )
+                web_app.router.add_put(
+                        '/crud-myrestapi/{collection}/{id}',
+                        self.update
+                )
+                web_app.router.add_delete(
+                        '/crud-myrestapi/{collection}/{id}',
+                        self.delete
+                )
+
+
+        @asab.web.rest.json_schema_handler({
+                'type': 'object',
+                'properties': {
+                        '_id': {'type': 'string'},
+                        'field1': {'type': 'string'},
+                        'field2': {'type': 'number'},
+                        'field3': {'type': 'number'}
+                }})
+        async def create(self, request, *, json_data):
+                collection = request.match_info['collection']
+
+                result = await self.CRUDService.create(
+                        collection, json_data
+                )
+                if result:
+                        return asab.web.rest.json_response(
+                                request, {"result": "OK"}
+                        )
+                else:
+                        asab.web.rest.json_response(
+                                request, {"result": "FAILED"}
+                        )
+
+
+        async def read(self, request):
+                collection = request.match_info['collection']
+                key = request.match_info['id']
+                response = await self.CRUDService.read(
+                        collection, key
+                )
+                return asab.web.rest.json_response(
+                        request, response
+                )
+
+
+        @asab.web.rest.json_schema_handler({
+                'type': 'object',
+                'properties': {
+                        '_id': {'type': 'string'},
+                        'field1': {'type': 'string'},
+                        'field2': {'type': 'number'},
+                        'field3': {'type': 'number'}
+                }})
+        async def update(self, request, *, json_data):
+                collection = request.match_info['collection']
+                obj_id = request.match_info["id"]
+
+                result = await self.CRUDService.update(
+                        collection, obj_id, json_data
+                )
+                if result:
+                        return asab.web.rest.json_response(
+                                request, {"result": "OK"}
+                        )
+                else:
+                        asab.web.rest.json_response(
+                                request, {"result": "FAILED"}
+                        )
+
+
+        async def delete(self, request):
+                collection = request.match_info['collection']
+                obj_id = request.match_info["id"]
+                result = await self.CRUDService.delete(
+                        collection, obj_id
+                )
+
+                if result:
+                        return asab.web.rest.json_response(
+                                request, {"result": "OK"}
+                        )
+                else:
+                        asab.web.rest.json_response(
+                                request, {"result": "FAILED"}
+                        )
+
+
+

service.py

+

./myrestapi/tutorial/service.py

+
import asab
+import asab.storage.exceptions
+
+import logging
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+class CRUDService(asab.Service):
+
+        def __init__(self, app, service_name='crud.CRUDService'):
+                super().__init__(app, service_name)
+                self.MongoDBStorageService = app.get_service(
+                        "asab.StorageService"
+                )
+
+        async def create(self, collection, json_data):
+                obj_id = json_data.pop("_id")
+
+                cre = self.MongoDBStorageService.upsertor(
+                        collection, obj_id
+                )
+
+                for key, value in zip(
+                        json_data.keys(), json_data.values()
+                ):
+                        cre.set(key, value)
+
+                try:
+                        await cre.execute()
+                        return "OK"
+                except asab.storage.exceptions.DuplicateError:
+                        L.warning(
+                                "Document you are trying to create already exists."
+                        )
+                        return None
+
+
+        async def read(self, collection, obj_id):
+                response = await self.MongoDBStorageService.get(
+                        collection, obj_id
+                )
+                return response
+
+
+        async def update(self, collection, obj_id, document):
+                original = await self.read(
+                        collection, obj_id
+                )
+
+                cre = self.MongoDBStorageService.upsertor(
+                        collection, original["_id"], original["_v"]
+                )
+
+                for key, value in zip(
+                        document.keys(), document.values()
+                ):
+                        cre.set(key, value)
+
+                try:
+                        await cre.execute()
+                        return "OK"
+
+                except KeyError:
+                        return None
+
+
+        async def delete(self, collection, obj_id):
+                try:
+                        await self.MongoDBStorageService.delete(
+                                collection, obj_id
+                        )
+                        return True
+                except KeyError:
+                        return False
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/.buildinfo b/old_docs/_build/htmln/.buildinfo new file mode 100644 index 000000000..fbfc401fc --- /dev/null +++ b/old_docs/_build/htmln/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 9a30dca9cdd3d0e644d245b4b3efe7c4 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/old_docs/_build/htmln/.doctrees/admin/command-line.doctree b/old_docs/_build/htmln/.doctrees/admin/command-line.doctree new file mode 100644 index 0000000000000000000000000000000000000000..f9f0b7f32a3ab0df47b8380ef7bd273f0e6dfc66 GIT binary patch literal 14162 zcmc&*U5q4Gbzbl6^!)$q+Fq|%k6jBG_u}d45E3907O>aG7*B?cZSVuEYO1@c=T=R1 zRi}RDhd^YcAbFC@19C-qPJl$RfGBS~fQWYi=NW`V6h+BHlsx3k0r7y4@|}CD>fY+< zuKC%OGSYNa-Ku;3&$*}0J@wk;Up@cfbK;LL#RKLB`)ihM2chl68K1VpZrXQ(Bzq&f z{*~;@S(DF1)?OT@QP;`%IXuy2u5U+9kloJsB0ZkCe!P~?pNgGs;)X#volUX^o4TDf z*$kgd+{AaZTm0(NFF*Z^aWm}qt-x;iZr~VhkT_A#0ydh4Sr=Y$_KBSOhrgOhY8wL! zv?Uq4$Y;!w88*QiIS-rs0^!Lv(~iYwtt5%uPMUys;&sBcW8!P7>sxV*L7YzpR$rb? z+vz}Ebgb@9kD61&Rg*`sWNt?-*|7WSQX-;LV0qR@kA;`XhBgoQ!- z6(`=YHmpwEwqmQ(2BmGw?z=&|s|jN*iowZaFP=|35X1~vv$i8^z;qG5Mj~u=tk|&) zYcTNLu0;wk22r@{LZ?Q;976}HBy4mJ4BP2hsh_OPe#(g;{MfJpBiwbOUDw$&!d^KW z5Gz2eXj|Axye9Q@ng9P2lG^|j(3T3=WRH=W+2hbHy9R4|5B{IP|C9K?4!yCbSc|Q& zRmk{4p*P6-9G`Rp+u7ITEUkDfBt8YBi(FwR%_hGvu-qu)kK`gVgk^^VQp_J3Etc`Q zZr_&IxMGdX1O$GXUmg8?i#h%vV;kZ*hlsvW5X)91k0AL1l-)f-aT9kI>5dt@u+Sup zDh@c;V#cb`$}tE(J;!In^TM2qD8MH9d7_kD^0GKp!oEFT*iAkSv@HP&u?1v^Q%6?< zpV{yG>+yhGo=*=VCx-PoLN}iWo3BdfLPyg=H}ir#idp1vioy{pYVtY451^8S1)3^+ z`zRf(&jONdI0ETF#zK<9s!>V-r%DQ6s*wWQWBV1J>u`Oc#MRLB0;w053g=(c;bhDm ziF1@tOa4a5@HEsrrH3@x24B>yoJ`mu2Sk*GPBK1Anh84;6>&rJNYy^4x5t}}t_Q+dM8{dkL#%2L>|BAh zSlO400lsiE40`T%8i_TiaFn4@MaVBsP6#clKbMb-P_PI>K33ozVYNCVmEeppJ0>i5 zD`B}S!?HzEpm3Wb&%^B>S5Y_F=ZXQo(&`!?z4@8VPrmT{$5vY{C=wDWM}$n8OgZ`a z7BCfIwW|e`-;5Vdlhrx*uQf3(LrkS}^Q$EpV+cc(sePtYoj3EqxpQ>{)G{1GF07L!pCX?15BD4ld^94h}(SbmU=b ztb?<+y!Vp;?s!kp;jTRV=#c&Rkp1LPch;YeaMq_bLd!-vrMZgHbA89?MPVOKEY76` zmA-tcIZ93KS~clTqI>(L!rpbE@P!J+nNSr$IC?`%ugbuY%bEPPCV)(BgxlM0uwA%B zd97Ib)TvlP-0+?&XNb^o`K+OXQnWF#W497Jc2!FE*qD?KDRw7}oy_YHag+cSiJeC7 z@xf-XwJY+s0-Su+(xVG#DWc1+iY{Kil*y`@%cW;PQ|dMuq=L2rCO0;K=x|paMuc4H zKSxufTQ3CN$iaKEc&GJcoH2Z7*YS-cG@gC#na@6NSUZ-{ag2V5m*HGqhSdqv#Mon2 zLhr{6FWF9j5LJfe`wv)|+FQA_i&f-g@3QaGg5Ft!-S}ANS7M!C&67?Qz24LEjgM}8 z=6UmzFKj$V$r7~E604sY9g#2rWf9VREu{Ttt*q)p+JBUDMMzuGLmIz!G9nQ!PVl7C z?K>sT(}%I6^eR{K{uO|05-IP$#QmeW)C$bz-*TeP;NHd5+`S<~Mbk;#`@!?Vy&s~( zT~8cN;ogrRb09y?)2G6!N-rIIUn%4YVHTCUQ3@HCEIoc7oUJCaKv7mJ7R4&FSQ(R9 z#0N3lDD!@oxH)rTvCxV|Vv$2Tnpc35!UJH^ZJ`ru$4r|Vk-v18J*1vOhpz_6zgQkLchae`7IHa=Wz zT12)J(TzAA48kZeaIuO{3u50Z$&`TrHS~ETeKxW_b02#? zTG5$5GKNkmwi#&0#fFyUYjeCG5qudv7b@IoH2m`r4b{vKTMU8_etvL(BIMwp1yNOt zka(f@enLR5dUtTB+XvwdFoi9sj9)ss36)_7knW0truQ>|;!_w9WlTOnX!#tjoqgJS zaubv<>Gqx#1vs6NN`yYMO%(SJ)p82)+8UuIm!NO1t+Uhf^%;sir zf+r>2K>jNTBd*!iqRj<9*$ZjM_K;8eRw$-EUcVN)J*jD0<5^ySU^n> z+fkSXXg)ycq;xF1OoYx3Kp9V*ORw

RLE1P=Bx*##ExQ_N>rqD{_1*LH3aMtWdkd zx)mI(Z^>P(Em4SHU(bWYW&W=5^R!6ul_6riw-8y2oe92B!5~0;Z)*>De@WA21Zqe+ zG}vDof?X9v)B7nP@d@xSHWfGogcGF#-oFzpZRuwXweEX=4KQPu{nx$!rnv?AL+knP zLoFmDv7R@ij5QXA#aA`Of8vKwo6zMKu7S=`08Y+s^6Eu~JqabDi!qF!G z%RLb?0U>L^j-^DXqof2^+T{PaCrT!Tk~MJkv@8voLqXG=W+WQ0-`*2#OT)%CUUw&p z3fQ;TqQcqw1!@x6ok}9RqY~M1eOx=P?`Ph%3vi4x=dg3F9g)KdSQL(`=_{xx($^hL zF{_00jOlB$oGa4TPux@bS_^D+`g*g(fBN)w1Ui+zqM@pkB0^emsjTkSF_`O;))AP` zp0pkXrW~Lt3`*~{5=_C!}66!nN zm*{X;9!`<3-hP>-i5>3A^iqApdv{Vv4u~g0>_R5Z4aH%|C zn4YRCht}V+TkM%i+*NaULuO)H?}!?CQuX8xH;tf9r~$c3Wfb&PsiyIkY8qEHQ1Mt% zQW)+nxAYcZLN_6!qlj>5w;nINvXPvvA{k>3!1279)30^Ou+ALN&MVVDGA;%GNte1I>|n@^DT&3#mh`WZ$RV{|bOOcE}p z#sGO$jyS#}Moe-HvuKY8#(YBFFTcs>BZtbbrr21|UOdldndO(4ll-Ey??P4yT9M=8 zp-DbzJDqeJ=oYDPNGUhqI#wSeGf9NjU}7qJoiDn-jSAg)d{)69jGQj2*{1DK%^7H@t$dR=x}sr>B;wj8LRHV* zN6Nt$tuzTuHN?*&UE~XP+8>yu;X$xsKsZWZ`2=uDj6k|UOzKxdgV;&!&_r7{o?1p> z7mZ4$K2umpH!*kJ*p()_gjXbZrSE_dYHP#9slp-HDxU{4FqdQuR8C(Xp^Lp_P;Mt26SCw}MmAkW39 z*Bt^+BMSWc3h;1Ni%fRMiPl^v=?NV4eFsbWK9J2MRtH{WCoFq$nyPg3}G3_(38uH~hPQnZzecBRYk;Yb&|5Ypcu zWg$Y$-bn{25z|*Z;?tZw4jjUI!mbK>p@KHQR2h}cE{_VLwFyjpKqd|;QbB#e2Z@UEq+oyL$hcfM0`9X<{gSThvNA|@hrMQ zuYEad3V>*#-oOV9-(ar_sOTwvhy7ZDr5;7mu_Zdhyf^8R`s_qAhez!mV&~PP%~|h@ z^druQ5b=s5DwiHrO1&@8k2s?@4Uck1&n?bUzMvbM;C=zyHo`N>z~uA@;m4FEFxYPg-4h*y@rL@ z2b3Fp(B{p2{0->#tJzENUVJ%#IDk(IV%V!hSO&hz@LV}8Om5B%x_)YtiEq=#V6!&G N<~)p1%8+)}{tvO!c!2-_ literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/admin/containers.doctree b/old_docs/_build/htmln/.doctrees/admin/containers.doctree new file mode 100644 index 0000000000000000000000000000000000000000..57f0f75956b553f8ea430f03e2a04dcbc887e73b GIT binary patch literal 14810 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/admin/install.doctree b/old_docs/_build/htmln/.doctrees/admin/install.doctree new file mode 100644 index 0000000000000000000000000000000000000000..658073e0312553b0d9800f4db10ce3bf62c5f3c7 GIT binary patch literal 5195 zcmcIo+io1k5hX<~$>p7tMA(ohjpCbZle>8c;6wC@({p)fqX%}!GHk+`GS0bAAwnBY$?uzP%ATk=OFf>O8E|+) z27bz;{G;5g6T6my>Xq*=D(-0+NA>HXBNoKsNBMoxH61N=z*}2p_1#Em76i<`LwsPH zKjLR}{?zW%ywGPMVK`mqV#{>hT3s<`7D_D-&3qsuo*!ldW|o=OsT^b)){!-H(pRMU zq8BiwK*Vz=Vqx*Lq&KX!Y0;rt!*!t+Gs zrDI`Lzp(01+=1^%DOk_pY=pjogXoz1S3TUGEq2U2sn=zD3hf!H+L?#I?u$L;w`eq+OVKmI^qqUVZgobbX=i%rC6x}s}!u) zm7{tO#bO zOe)7lJX10nIf+cFXgqJbfq}SMd`LCQ1zxaQ6_=n|uhwMmNC3O|uLXBf?!_TWi_d+h zOaYtrPRNljet}e=<@>$VXnlHhtt*EvSK3>otOZi@lm+e}h`p0G;XBWN_ea`)--rBJEgDpN$Y)!hJ8XqgXW6E+T}EOVO1j1A>^vE=+%L~1cP@k zz#wPp+%2`K-1nV)O?>}x_4pDhzi6Ry8}WTwqw@O8PFt0Ua9+4q$Mc_;#Z%y>P9@^6K&bvn_ zFG;MVj??o!V3<3@I0)h=RQssxu&608{}0iP2mXC^4^(An7s#-lnDoFKhq2~wJfJW* zf}x1U&VW}=u|?F0Qycl5bFw!HxaQV1C5&vPt(t+ZS>j;=ky5p*+(L0+ zm74Q(eCvbt->Vz;9~krvjM*`depK}vFMrckrb(yj3*AnH%FB0KUT%uPTa%@IB=wtB zdx2+>4SI0rR4>=VPUWTl`TeS>9Cv4DW`0Or`AK6};|TNOL|s8X@3Z~FpjPFtn2L&0 zBz?_vNi9LDwvJkDW2_~8nm#3Pu9f@ffiL+`R*k*bqrx_8*1asH5x}h*{?&?7H2!8u zajlX2m}s`@5d{?_(&#^Ov+$S&89M&Dsogj<-4T!Q^+y58vG5rN2F=0*ixEglpN-Ts*-}N zdWjv2?Ub6Eo5X1q0H>?*Il>))?Spx;|H@B)27j)nLvKnvQ5x~DR^pMYj39f$)1Ksd zXwRT|Tj((81F@P7kVU>0`N5Le1tvqcPS4r^w`j%3W>cLtg9*XkevlcRhh=-b46`e1n&*3-R_zmY}t#dlP#ZQr3Yn&=Y$y8Uh1V zVc4cpp|ZggpA0b(;4oHXBVBczeO zGh5{)4Zs=B002MOwsnbWD80GS{fHWfQ?TVB%h$* zO;C$V6p$fpSTAT!ru!Gr7l~Lr-#>m8Nq+ni{)oroL-D!zyZB0cd3=Ycx9}%3UEh1d|^e1uQRjOj=5E0&67Y5Spmfg z3Z-_%S6JJo6nwav07k+=9MmwftT(2JHFtMHVz)ZgzO+3dA5}Wl^jWw$Evwv_G0P}C zUYt>J$jyp}HW%@M4fyyh{-&gV3O7B?KR^=US_$ch>n#P?6bIJzXM(&^lWpWzWaI^z VPe>cl9oe!^C947Rs>Xez zyV`3bMOq#rtwo8KG|CISBJsfQfS6IiBGT7@e*9}6KCz+miLnrllpt29M8^6ik&o*^CW{;CFjUArp3z*>u z>A5ivvUfAxq3KF`Nv~KxmvBePFsPP`mY5ZD?`E5#ty@Yek2i+&T(X}i?z9$=RQcUaF;%wV`#*+chw$lOA3rwk44pN0X(H*9xo6vdZ z9FHXlI`Q2Kn4f>myJ=K62F%%s`H<$MdQPzs4P|0QyeO8$hL{%D^xeJ)ectzF+zBr5>2sRKd0DS>bgGn`a;hDc`FBbTf9W76rYFw#LHmE7x426eqP1T4d_OES=|Mx_@bIH-7LUlbNDV(P)G%A3 zfZM;3dk@jl-aU7mCdyKRTYQiC5!e|Ht@m=yez(EdZwjTNWUJpFNhQ)j&k6m*_5>sc zeV@T;#JO!Xkh=Sx-7{!yigmqy^sZUWv#7~4vNLFx!^hz2wH4~O|1ak(mAdvR5E=*k zb@PD78-kuO4oV*(OV8p?X)H5+_t~H|YTko-BSY+21?}^ux6=2lXVqSgNonqSt#FuK z@@ZZ2X&EbhKs8vC2ZM!Us4gvjOXSpgp;D}yJ(wyku}-FY3>o;ToX%o{?Y)xi`C}(; zmu=m9lPjyZinSAjk6{PQ7()yvofQ7Nu=UbA*T&O5)AEv5XIxdo@R!q3uIYO_fZ@-l z@x6aKrSBDw#M|N>0Qpn#Gu=u+HI?DHgenhv*$&9~iwfzD!l&k7JIb?ozy@$OQU`{aoXS z$6Mhy?mfKs9qV2cdD3ANpIQ&;t&6R~@GLxem6gIO$xabpx%<6^B4DZ&`Np|rmB>7U zgj${dJ-a$LfYrZGW2&E=!&JpzA50%*q#H2O#nMR2Twt~A&{rOkfm1+WV9nK10(JCY zg~9lRsS6iQ4+A3j@pIJ*6Q@}d9^`W+vGd5wI1Vd!Kt&LC!isi|prmm_Z8P2om={WGDIzwy{|U;u{7{9_F}gW&tX9qa z3h2`W@}!z?S1XKaHYZf`{L!ijqmnAePpB00<7ZUNYmGxrDCTkkn2y(r89tL*aQBAZ zt0cLOe;Qqfv^!m!F6EdfgpFn5EN+t7PU()5#*|{)RYJW~_T-7Ro=>=MD9(+1Bk54=BG4;|vWK87oNaM`$eO+aT=?cFhTS{eMB;m6a?s{+9L6?c z1J{E=Bl*PL9F^&nFjbRMT1HByuN@jWBx0Pw6m%z-Tc4p^y)ij(Xt7?UJ0t)~03y$1 zkIQAI2*h2aix*KI(wAfIgt2S8JOV$kjRZNi^{f*HLtGPxNY}1&>JCd)XxCl(q6Ddy z-PDilig*ClbVzV64wy#*S4<*86lB=QFgX&pA`5rcF zD>i@?xk_XY=Jhpj(zh$~tS(^Z^@Rhyn(POP?b%fY0YwEbBm1P4mTaEV++k`4~d zlRnBE*o@`YNTtM`44m-?sLUm5A4d=z8SjC<>R{H6&3z_48--JpO{k#w6gep*lgbnB z4Rg14pr?7TOC?D?pSu&-FQ_O3SHd`yo#)YpIBPf*sHIR&g$$Ppknh9cP4wnPN_0co zuxe0}PxVdo&rxUoy*UnGN4qF+P$<=|JU+cclbT&7HFRvd_ro|?%A zX5v9AUPc8jm$M`?@w;3I1yV+cdAC!&+*G|e%d#UuAi50Bm-mo`m-F&VH+%AVsLX;Y z{vh-!Hkqkc4s}+u+Y=Jo<*sJYr3v|YC}~q7vRHjct9eD*swk<;{alYnR?p zqZ&(+&zPckDvVE*2ho&I3cEv*!}~Jo<5kqgJ9@i z#G#Wyj8^e@PU)GvmOAr;?eG7HUaRHRLAI${P&vi}2o|F($$ literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/asab/alert.doctree b/old_docs/_build/htmln/.doctrees/asab/alert.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4b1c43bfa24a375ec6523855331bc97b5b0b1c02 GIT binary patch literal 12257 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 HT(ABIzeV;m literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/asab/application.doctree b/old_docs/_build/htmln/.doctrees/asab/application.doctree new file mode 100644 index 0000000000000000000000000000000000000000..90779e3a76b364d961899723b26b1614ef34933b GIT binary patch literal 54173 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 V8tM27+3A@YO-{m&^D|E7|1a~u>x}>a literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/asab/config.doctree b/old_docs/_build/htmln/.doctrees/asab/config.doctree new file mode 100644 index 0000000000000000000000000000000000000000..f589b3fba2415231246ce25dd031b26a4fd2d314 GIT binary patch literal 32587 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/asab/index.doctree b/old_docs/_build/htmln/.doctrees/asab/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..de8f584db20fabef260741fada61ae070c901e8a GIT binary patch literal 8814 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ξ3Ot3|*@0giTrS6C*bjnE5JH}($IVjxnn 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 M(9szy&B@&V2M&d*XaE2J literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/asab/log.doctree b/old_docs/_build/htmln/.doctrees/asab/log.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e1ef00a64501d177bd0d1196e82b496cccfcdc41 GIT binary patch literal 86139 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/asab/metrics.doctree b/old_docs/_build/htmln/.doctrees/asab/metrics.doctree new file mode 100644 index 0000000000000000000000000000000000000000..33b18a67e45e4eeb9c17336928115e17bd15098a GIT binary patch literal 137737 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 Hn$G=SbXe$B literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/asab/module.doctree b/old_docs/_build/htmln/.doctrees/asab/module.doctree new file mode 100644 index 0000000000000000000000000000000000000000..b96f99197bb878609a4a6b5670efe01ace05c4a6 GIT binary patch literal 10705 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/asab/pubsub.doctree b/old_docs/_build/htmln/.doctrees/asab/pubsub.doctree new file mode 100644 index 0000000000000000000000000000000000000000..9033bfad60d398785d86a1e163c602028a81af53 GIT binary patch literal 56316 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/asab/service.doctree b/old_docs/_build/htmln/.doctrees/asab/service.doctree new file mode 100644 index 0000000000000000000000000000000000000000..ac255d985bfc11fae052c27699a89a9fd0a49604 GIT binary patch literal 11799 zcmeHNUyL198E?DYKX-S#+ZMWD+Tu{a-i7uqAsAp&3Jo@d6c!XTCI*MOGw1G^*|{^9 z`P1$tQILqTa!f=<@c|_9!Ndn2O!P&cec(YKM2%qLt3KHJ4-++F{C(%lnLl^$-tM;G zlTF(@bLKnW`Tn2pJLh|D{2Q~aUGk5Zk9*t=)?1e21fj#?OiVeUopxD}WUpk4U&ua} zHAN$`F2rFP*(?*g0AX|2cOn*KPiA6{z!TSxTlxISnAwRN2E}wf&L{ZflUb8D#CYN+ zKC65ZlaI6LybH_(0*Jj&uytCx{P04isF>(kSTo7^0nsoEBKeq@$Z1;KGDly`*o7pLG^#0Z zHpktxdc8%dMVc@#Cs;ucCf0y8h&w)W>ZSx*UN(+PYLA~jVVu$nm~qdt*|Jf97{^ba z2Jg~<7R0!mk>xf49?mI+6g(7^Dnu1-#BM_w*#bS47(Q9WVAUiqc3;S>s`yEAkJGAY zo7EtzK%%kU^_L|daF$-gNb@YCxesCPS+yQN0V9}@a-UVgf(w$JX}9C!Vq7XuQ=Pw+ zlm}Z=-V`&?)=4Zbaf*Gkgp{3pXH|N+$JdBBe<*PcN!%c1b+=vE%WA_63qu*i4eR29LE!5Ed;wCxt4TY*Ulk%^mwyq3rognTYF@a?U6 z6uX1Xw(}a8`4+;{mbRmH@l61JeLH|(+bkY&O&-+YW3BTpyI>=-XJTGInpR-*FscaR zazUqoXqZ^hDoZl)A+sAgsn7E8X0`1lvTq9EVjOU;lkw-p1fCH2^7vCgkeU6sq*!@v z#gk516z~wOp@&RNlaYjNimqABV#S1_ArpJaL$I(43w%OMbyDA#8Uz*7W)j*aRG-8d ze~Ul=r3_mK4dnnt&IA0Yaz&7JKdH0gl6Dv*)tyjpWm~F`5WcMuX~cuEqAB+D`UTAc zj5%S~a)XTjUQB}Xq~F8F^9O9o@Dcqo8H8%r*buY%BW()(Y(vZkVNP?L4-rMDrIpg= zbu^EY4bdQnSdFY6uh@ZjDG%m`l6q`l%QYgl3io0Wa||mn63&cV;rW-Sf5PZmfwc;N zcHgkD_w;(cYs5!3ovJ$g&Qu2 zgG0=sjJ`E>Riem1&P1sHT0t#yIH3QVN^h~xE}aPswr+KMJ~P6OVHw~a_UjjhF4;2T zHRiJ<43_ndyyJNV?Oto7daK)WmHb&qMw8zV`*I62+kR-TRqX832Z3GD{766do@O-> zTwI=>Ht@$`9m6!;z)eiE88g3gf_(Rc=3B-|z!E6^iPIj7nv1Ps%4XmKw$*B>HLSQF z*m5OW$F+R-8CI@U!7gXW`Q?<38*FC+@sS556A1wi9l1gsxr!)!;s4SZE*)i@{IGW# z))S9NQp7ldHTL@rF~{9i?&Du#B0Zo=ixL zOFz8*3GT)Q{_^kwyijj57_cK|CA0wrPGvtT9C7CpOHcgx6?x*Zk^%2tU?^hA&E0-{ z-Zt(vDxOC!b*$SrbB2zoItlS@d%%Ta%&Sz4_b3o-rIMRVjw+$?)-6?nm{X`EjhRy@ zV<%HeH9UPqYFI3ZuB+jcRs%v*3yG_ieY2*AX$jRD2pxrbt`13|wr4*`wcS=qfVZ?2 zUM``po+9vNarE*0Y+?oFl+ncLf!fveA;N*`-q9kUjE^`;xUWt|lYdMP2z^?RBau~o zxA;1x>ChW&IZztPcSjmZllS>EwVYa)R48w~?-X-o&VL88fM<)<_bSHd9BM(RmvYq~ z7Bh#YWBes9hOUb8b;zn^vf{lC#H#AyKjS~IIUE_9KRcg3NY)~nucXqLD_)@XI z%cY`gqk5jbRU&rh``~p)w6&uW7~*vMYfcB4EA_dV$~t*bwL_QNy$7n>x)vGfa_<%L zl`eNz&E>`XnydE@5VU=Vs|&C0Z<1o^Za0J2s=M6JqO)A+oR#RS=73He!=P$CsjAjm?1eV-D%v{(Tvt#?dyisXSxf6Psx8au4etiBn76zS<7dS? zMikb#BLmYV@;xvxk|m65K^)kujna<>C0@6rt>PQ-7lr1Gmb=<4ntZ<=5RHf34zv3< z?jUk~R7Oe~f|1%7qyhIV-dZt3MvZ&H=anWm$0}v#qERb@4OJ`Rn&i4#uq|iQV{V14 z{2*;as-y2@S|zsX9mx(u@XLijhUXunvYxLNbEPovtA*g{l02=$>QJe~HwrAnDHs)y zhfwfxVMOKm`m006ULP_xcnJ_l7Y0 z6V1eB@-2A~w}X>*aZvB=6)jc{_9$fFyuCt_(p?z@ycfaQwzos?wa$3_5C5DX+w2dRh^DK%ebIp&(Q7uPB%KE1*blAO$aBCDtc3TG9L$zS5;jbdp9?}-4aa~2AJu;^3a=7qDmzUQU zb7i1CTMM*Pnm8S1%YjmLw-y+79%P5C{=Np;`$y8YMUXv(N!tywcW)Dxg6t4xKd>OX zf6%;etcg6C?l<|HI>eR)Z3?m1fUoU`*ba%g9%4&NkpZ>{`r4uf!s}Vc=MZ7Jvhb>> z=HV4qyrb~?EUkRedyalCsh=H$*VPf>RkQ0DthL%QoHWASTvQEIv96#(@0PmB zFA-IS2GESD69F0N(9Be?u&P|3O-VJ6@e@SCZZT)45w&ueMdQ}29#IWkVk%}y0_CC~ z?EtlU$p*7dB(LKgc;BZiKgG>r(eW|AA{whKz;$ba#s<9LAc~X~-f zrKY(UC=aU<+!e|Z^MadjQ72a# zr0lRbQvYZoPYENF|gWQUkKrciGjUzL?;>bUF3GQ^yfCZSmli9KjqL5oz{?ctgrH#`Vd4!CFmiEs%?2?#wTHyszfD?S4wIhB*zA@~U~3ua=tfa;!u z)#PAi$3^cAbuTW^6BdEbQimNhOxPT#d6c`feB3_>b&AF6Mfy zXBOu@#0>f!da!rUPR=2&=Sk9wmzS0>9Jka(UMq}NmojmPASD5SG!urab9fxJyRqKM zTW-G-@|=r0_5gYsDbasKqo-42GTAkx#V$)aat-R6;T!-_Fs%ep6=s90bGo+`2Wz8rsxF6tty8>E)JANo_IyO7nX5pr}5r+BZ9C^)zhET-EI{lcgu=(Pib z1$3i^v7uL$lMdGKBW6blZ4!qDaphljiD`r(J4`85WMak+QCrIPX>3K459H&oK!7h~ wpMXoDX$#H?)x5(3DfzNFkXPsf4BoDJE^pRpiCP?gQR? zT_(F(WZ+&la7B^I$qI0`Ulcc3EN_NupTtL&SHDnO()zWX$8ye1Y@Ex90+PL!8=y1 zyK#(*_&(Bb*TlC&wRY3|Saz$|Tiyyi(@w_{ca?5+{A2zJ|A_y9f51PPF3kDSnm4x= zwC0{`MInY9&po%5_)%l-nipSppK+JtIX8Bf=K!hr5{rSBTQSD);N^quWej&5gK}3} zZqv7s^40TK&%euQwxaa_G;v%f_FC&f)pJ&&mP73Xja8@SCT`iefKR9DHk@UT?|3yQ zXgF)$TGZNd@HBqZyjoCo6Wmc)<9ClWay43;dt#~LxQ&{#bP*^_f~s@Xb6ZtE`+_I#;RSx4fTWHvh!y~BH=9ul zkd&F+)BaQ%zYas~NR|RU=L9_${RhD{L=Vv21Dk=>75n=m=_3OnN3ifzIwmn`b@L9p z8`pmeIMROz{QfZhKZ5_K@qY#!d5}5Hw2+Pho^~tfq;Kj+l}_6~<3CPA;Q@>$Zfn&u z!VBn6WGR#(seoC*la9%o9an*7Us6yip!|1J-wH80rSv`<*A_!(Q2mSs|IJzaS}#12L+_-#SBhD3EG(-# zkaUtM-04Dg#K`vlnuX!}wIFxNS05Jl`tlyNUh+@+v(QbWO4EU*4y$o0Eqjp)74g!nvl2iVJ6loP@!fSm962$MXp09z1E4`E#qE3m50a|IWa(6+ z#!9f-Zt>7#QnNI6aTV>>y?LfRskl4yU|7uh345&2KgW22tZ0F_J&g z|AO6gf1N{U{1njm37~E&t=w*;7&2#uJ{VsfR^(7*a5`gQzIDp0>5|cOsM+#p3a77ix3StLg9j!_BVd*Cc`0^Bt>GCiK7$#WSd=&~_7W#ZoHe)6cI)*m z#dbW0y3MBGIgoLvcMM7X_24X{RK;-%=6|3i?_ZWN%`Enf56bA~HTJ zHE+dj*OPd9!ok0n`IEk#wkdgf-nzqgiL$tQS`zoPe(wf4N#N>?xl4h@ezgzb5 zzvBP4|F6=~Cfl4DF1p8}h~c6~u0cITO;Xe`n~`}{O$M6gp8=mXob%s@=bVQuILFh& z%k6sIODgpM=CLuo)T9H;jP6t*@oU!Ybap9d2xE6?-gzoQ6R^a2R&;7X3qORAh(`n~ zXq<$H_V3##Rwh5MId{S|s5s}4>cS}3@F=~?O95dz_E!>8zlIZdgH`OQ0RYvA<=5da&GbTY(pgrHHW_!V)0^i_vM{aK*UBfMN=5DH~Fq z(^wpoC+6@5^TcC$o)`eJ7B^BmHk0_qw*D)-!@nM;B$n0Lgm&_(X`e&jxED-0v@dBGb@ zJAVgM?iuQ-z_tX_4XB+zvLsiPV(HjNM_dx>cSKT&QQ(^uw<|Obn8(!;j@)Qj&8tgFZ`wes*99Qgi$#n5eM7=X>k(L5N@h zK+W}0DQB04q?H=&n0(Lb=F_=u22kj#5$KACm98k@6)pY}K}MB7IvB4B=#867^>1Wa zkE`2r68=LXi>1UhnZ~75ZxK_vtEy z&QYt~(>+n{lM_9QNa=c*bz-c3u?ATppAoNll{e{1RBPA0r6p&>_ZnEp2T9=8gO>=C zxx`z!u@Z&=BIY<(c(@*x{p002` zF%dsbpi3D`)Q;-{Py2~0UAkDQ>R8EX;WI{V=72-ns3;ayIM~Bk{RV^jc8F~OsE6L$ z1c!nv6QjV4;OeijkISCHVljnjw3Qw8l7p!X zzSU@%!nn}4ZsKf2t?Mz2gX zjIwhHT5;YCa9HePNVRw4Q>iY+CeP?ysbb62hNbhKF zArYjxRU-0rJUaqUCi-8eR!)SQ_*1k(=h!?JJ)M*zaByCVL>A5=s6{lJcfxHnl8#~6 zJYS>-xySS{#rHPJ)CdwpkLdn}+iKwJcynuBm<+O66)~Y8($+lNDV;^`LI(QNLkbnN zI0)AXcoD^Y3WFeOu$i@ZYdOBR`2~t3h3W>7b{@m^X&L>7NmF&S=2Ku-bUj@pTltc@bFYO+dr*Dx~Ff&LVt;VEM zIVCE$!8Xi^S=AihUN-Mo>}{+q!}58fDsQZiolsz`+7RBQ&#|%0Sna5DuQkoFirc|LS`mhG=e{rpd*!UjplXYAT@P}h^b^XIg#_7>0mM z@ezVjcCH3Ul%s?MvY<_evz(*QMrsX`65S0KL0c>1Z+4hrS*&#?$6DbAI7i1Q@9IJT z^JsX(dMNxZYC;$g;~G;|7mw$<$k`9!O*A&3_3#*)8pwJGKTeHO-l4J?&g0b~Y=-bv zG!XtQef%6g7Q;_cgJW`hd81$v+(wvWk^4zQvo{En7}3v@doa9SpZZaebHKl zR;Y3n;H@KhxppDg;bl+0`+Cl2vl9C96?_;eTwqR6qL{CZE z$hDD`w46oG4nyjdnbwi4+IR4SfqHbw#*qT{uyxUDXM6YHb{TsG=sU7xQAvR`VXj#a zy}Emd9#u0zW+B*3e$3%ojNIgij@bt3)|b@*WoQmSC*fb+Qsr5|c(O#k!0n?ggu@Q&U6_u{mE^iD35(>l{19fV&Y(SF3cjj*F2`-?wS}1AR53Q@xbmO zDY2;;hTgcXC5sWG_`dvp3J%laOPXbfI*4)7lB*FV2y?WdweH}l46&|-UuIlVyOAVN2A_m)nkj2R+~+)h2S+us6~)p zg*i&UuLEL@Jmyg_m^@aq+=o4wV64pkx4%#szREQq ziB5cn>;R-LAVb93u9$Z{s6Yv1xw5=PGqi|AfZcQ;!sJh6=3CNA7jByp`)sh( z30mceiEmVy_Lm4Uw%V4$vdji(+nr@HFhwt)o_!L}Y1|azGF%alDnrIUDU5jYQhFa4f*#)Nk;@tpUJ{{qj7mhuU4R zs7;2^a)Kx+n=0B9Eq7olou65c=~$Rqah>0D50*52MUSN`@-ct~{`P^ams1iP z^~ZXlYb{U!$v_do|FnBp_S?y@c{mJv7g_jCi!U%fW8q&OEFGlVrk{0W)RWBo7fx5! zPa_RLOe?pvO|3D$1q2ppjH11t1)K9)S;|HdqjAx1!D`_IvbcP$nc{#VaC8X0D8P^n?-eK;2C;dy6X5LtLZbjrn9rg zP!{lMG_^}t-FM;DJzKyBFt)t;y9x3W_IR2*Y+QBrB$LPPV3Q2Btc(xrSbYr&TStR0 zX6@H(*dKbPB18WZf~R(f3f`jD^xX1&z(>*ClCwtDAZ1$D4`tG0jw|b`XLvy0wd}y1 zQfA14D>5xFc-W`i+qCR)%czeKqaMz*T-9%|Y5BtdOi!5UFO%U{>w-m0jcTE9a%H5p z;1|4}F#_R|5J7?g0tB<7bNJP0LX)~l?A#D36CzSz)KPgjfGriVsqxS&P@q=fdT2cq z(1)o7xe8a$SsnaHu7f@3pbw#`UFx78$E$nRL8D@Lc{TJAC<{U(tD$M5hEy!MH}NeL z+#($*MbUjq6)&2>4 zzeI_W)JsZ{##YQZ^H^?IMVI3uv&&_Nts_%ckwQ%~3-v0N7*xhiE%f@`HeB{+LoqdZ zFaAWo!Bb3{nPR?vNv?=QJY-4L0a>Ep3v8WPhYRoUdWSsYV*exoPP#wZP<8mQ(1Ls1 zMV@ID+bLV9wbx_o7B{N50bKm|H%6P7Y?EKP8?NOhstKYd- zTn{#odwY^Zao*iM=w-EgV)w&4MZ+tmy46tuCGPFX9C`pfILB(YwEF=(X*}Ay<3A(4 z`Oz88ROD;=aZ8G^3|O_60ngtJr^*Lp>8w@Cqeez7HbyI{(8|r!3WBS{1fqJP)W{?D z9jL9=8xZ}7ti}iuR%7Mi*rs4G zgGt3tK`Jha&W+X7&T-xF9Jgz3194xc-nF$B03El%TI*;`7g9#Wi;Th16)&11dXRNT zdZ`pNO0sI1+4rKJ$QwxcC4I)|BAcdQJ%8WToY5u2$7<^6d*3MTbSSwXvuj(w!DiRb zWz4QiSxZEh-rCU;P=Rly*9S3f{+5QME95g!(XU^~y}z?gpdMK#oZH2K4AS#}7jmC2 zVDXxT{0!39*_1^#2J(bNwJKTM#}sI3ZZ!ig0)$Kt+A2NA&v79jv3%AUAdRR|;-Z{n z%xkK&0)#JkUp9;_F4MMTC^TXEx0K)KbJ(>Co1GgTOvTbiGXu1``^UNN`V&)?Hp?}I zdN^-U^>F&2i#!uluQ{Z#fdr-&&Z(VIEk>a0;E3K!l2XOiT-ZUF0%bLB}=C6&1!L6IkzmV_^I%_lO2N6Sd64F_>)pd_UQENtq>f zbzr4r94gt(k*@c?=Naa1#qd}MTJ?aPY4Q`UVC5EVkXU$|E-J%d_mprT%J`LhL)I0Z z(FHkQPY{gG`HP|Gqar|mJBwFik9?q@Oz*^+s61am^>bCa7d7b-#dPa_6esiN9zXlm z$MsW+8Vj^it1T-YyNx|)yJBK&&vr#uCE#DmqHJF}LdN^1wHaO%M(tb88~eW+IRAi8 zH<-o=3E()KyO5St3YL?tNJBONY7$=+xt!7|I@3u-jTvbtma|WlWxkU?x|noa2xRyG zFku0%Qesd6;2@4MsCGd=jXRTcrxFJ^V*zgSOxEGEJ^Qngf#)e)K1*qV@*78W$U9kW zZ8a055-%cJJ>!&~V9y9M1@(D^`$Xa*SKBwmX47N29u*sPT{j{zPh;+zFf*MV#?VSg zixq|ak5bRPiJyOGN)M>0&)WqS-=-U86Y0~KDzHtEA;=sE<=&4v6k*{V8XQyZy*Wq1$t`u!}Pj`Q9@8OQEDP-bGCyG|9-9E@y&Go z@(x`$ySv`Xb*%-fB8re(Y`))7jE!%m({zVUH@Z9hnB8d@;Fk`;9)N6eH5KrYmA8c7@6`I+!0sYQ1zU$Wj1){tX*7#=*U$xPK2)ls(dgj zY~x}v;rp8#O2(IIxF^C7a{FNwe>C0>DRm}TIfqo-RJ1!l-wg)8NKN)tM1@fQBLT)s zHW+;v^Y@B-`BB{N!j0ri*~^b*dg;xHUoGzCZ}#d%vZCx|53KlSg`M|f#qd}0nu%V9 zf0usJu5MMPWiNdA-_Y1ld?>K6Cq5kE$y7*i2AkFmcy;72!-w}B+BF~EjaT!-wDCQF z^k8b|xqpFX{$3I^CLd5zq<@UnIGq9Gb0w7gYEA7c3EevasWH zf7Gpj7w8r2=okHtr=vlG&%m-eJE&0sa)}>itj`s9iCL77Wf1u?+3wT3<#A4xcnz_w zA82FKNZi>b^|@$6H6$1A{P_2ifSw3@8c4#llT|BhlpmznnBZo+ZiJqX#C?O9Rv}_+ zuCynl9kqbyW|z}ZgQ=V~-fT#eeAET{yAfn?8=e6Y*|CVD(O{o+(h0HwMH)-CBvv{q z3sQ+16Rg-KvxYK?Q?20m24O+oo4u!&3F$;7iP$_$;*OYfyIN6}>nk`ug`XBJvJ28I zPh^Xz{6)NWj<`V-y!te_Vvc@d8f5cJa03?MNp^q34vQyh_LBmKsyWqz9WSS-)U+@` zM#WCMJmOSEk6%G!=@^j9RlveurJrnQTffH|C^JZFyzTUe{7Or>E&M*#h~yYzd5It_ z$&q5v>`s*%5W$4k#%p_2Sh=|H-iE8byu*0t=D%Z0A% zMs55{Vw=8J*mQUi?T1g}qiE^(CEW-w{XT=R=4Bf$d%04$g88?)p`Po$@cjhM^ZlTa zYrP)Oyl6wya|xEUX?s30oi%L-9@L){4yw@5{V#YG$Q;Db{XfOM6dAg*mq85OBjZKv z5*8V{vX_i$#x^E##6WAV2Mas5Czhe6xV;# zs5CKpu>KlaP}(*9&LQ6Gb&3O%%))20uHQDB)*la4&%%;oqZgFVnZr>Tkb> zZ`Atgjc^tN$VrQpg8ZEHryKJgVKd7FeB z<>lA;It8_IDcYjaxH&wdO4*6HAx^f%{J(=yuq5-k)qW$Yw~LZ?de1sy5m;?mAx=JW z3}H^Ide*t&F<~tUe<&yA84Z%&(+g)}k&~%=w@s~x^zS1!eyxsvEZ0$1M-H_OR^RTB5J5I909RtGpFaR~0RFqJ2Xm0dJM;h4Wu zh;JKR7y@q=)o`D5u+y(Edk+Tb>@ZTGoE5{&4Q8VHt=*4weh>0z0LT+8s~+>HR#8i0 z6_us}b}<`I?!G7^x3U-}w1IZw_q=By`Te0#p&m=`YT43yUOO6TRp0+PgL8j z7@Bnf;bv7arc9MKreD4>Gr^lWWsOAfV0pz$s(z(`quJ*<>yQ*Nz0J*(>3T)D4yI>% zWF^wmx+u^8TR;oifdF3z>25>z*l%QMYq;#Q*C<;6P8FO&fI_O^HQ{1F;(0sZV-i_= zamgOJ`G|JIA_9j~?>V)bRm4)Xg7cYivW!0aT^#454|x|BY~Q08hdEQxB=bCdYk;>@ z+5gN*j+F>h|8|a1slut=c(ow@-#Li06RNFsR4!4!HgD^Je1ur2HKc@j(yPEBa!Lo1O{LwGRXl=rJ0PNJpT+f2YewTo#vhNz8J}^*4fQ5Y z%D@3E=IE4L+^QM<6M8JY{A2mitNHk!Sy;g6&3yc+UinO!(*-9ozmVHhU!ZisOk&eJ z&Ye9wmwynY6$n2I?~eS&g~-d@Rv25TV_VN!C1}QN)c%d|>&ZC4k>r><9y)jS++&JA z-uQs(dG{HRXpi%5S9aBxvINwV?(_Fp`$gP(962iCZwY~1R9&Y+cBag-N!Q%i*eFZN zmaEa+YCEWTbW~=B+H+_Fd$Le5eGYaLz9e&WWMWA+%_kE-Y+rdoRBpzM4kOJ;f;A8I z+GdLkl-6Io$NO2-K2~un7$_mA;7;V-HTSn(sorIRrZTHZzPu`Tc$Q)Pj3+V6-Sh zsi0ZgRvJtyca{L1u`S8b(^k4wo#hWNzF+E)k~rPBWTexwHPl1clLcA zYr~{|-z2WGEGErm8H*{;PR9CCCXQ;E+ER1l?_^c0nHx*Fxlsz^Legq`69V3fRB;P$ zT~iD+{qij&Gv$UGPPRLCrN!k9$AHLx@ijARggUcbQx;U8oS!h_eIz3{98K>RR${R{o( zFy_}ET7BBS?(}}lt(5nRA!CDltz==qnB~?(c{FKJ>4kk7Rsr_MpB1MEUb>(LYh5uT z{>D%vChUGyzroo3Y6iQH6Ly_xKia_IET_fR?p3crRkh#(ph8JY>Ss`+q9?+Kpf-R` zr4QQ;eCDJ&eZ`?p&9^IS_i&xO=C20xXmbAo29=JJ3U z=`2!KU$^j^;iPflQ7HvAOL*l)hc6Z^;XoqOeL6k#q@}}!ueo}$nh4{DB}*2)3EGLf_hv=iDt@;sdduP_t9ZU zu}PUahEwJw@sPZRA6RnYTo7zp!H>hDn+n>#j-M0qC)P9gb(Hdamfh-gx{K~cMAAxn z9A`NsR9e`&d3k?&G{#=C1{N%vSPrgraAgvy!$Gqm>ypN3@`Sj8YClw|G_Fu>gbD|h z05W=%FTg6s1~yzc((;;7E2-2`j=J8td`CLrW3RUQIg;Lmvkq~RZh}1rvAH@@^OoDI zczu#isxcPH0Gc=0fTB$J|D1A}_|f$WXk%jumoh8T## zvEa=*#?(oV*4@Tx8$1e(*YNueuhB{Grj6{aTBYXE;f?5q_L3~7qhbY57zt_>>}yyF zHj&qpPP*+RLVXo=DZK+?k{+$K*P1x6n9HEj>yvzek5g@634tre_zJMwh>85>5~>Nd zYf)u$jaceVoR%2HUd4WsxdcUB)&s0@nMIFPY5}(Y)M+4%6%b=F9a93~&!$H(7&_om zIGeyV^0CSaiWtTn_-v-=8#zef$x9`~iL3N3h?6k9ImvW1=ia z8lf1~w*S7H{?<(%&o+i~0`;oN2zw;8^h4BJhH zYnx%Z$?$A5EJ#~;h$PJCiFVHteB%OdQ5J^W=3PjQ= zV*-&>0$L!FD)k9OQq?MfNZRl(5J}NQfym#ZZ?9gW56AWu#A(g^cA?9n#QC({SzIadWqJDZj z)8e@5m0voZX&)19E1{YF-h5l~&c1X4b4L|tSwKN_(!(Y!3HxE}DS7>;!9ySIya##^ xd%>VlAx|+RUv#Lakj&-7`Z5deVH{XkZ`Vj!tdhc?z#0MO86m5)D6(+M{}+d})${-W literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/asab/various.doctree b/old_docs/_build/htmln/.doctrees/asab/various.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4375a3626f0f3a59cc281ad433f10fb086beba0f GIT binary patch literal 65371 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/asab/web/cors.doctree b/old_docs/_build/htmln/.doctrees/asab/web/cors.doctree new file mode 100644 index 0000000000000000000000000000000000000000..fdf55106be21d00d634457a934b12b4b308e77aa GIT binary patch literal 4708 zcmcgwZEGFJ6}Bv2NmnmdmST%QtaPI$jil<{TWFxIXbQofj9b~YOhPDTJ-a*i&P4l` znOVJj2)G{tc9^ylZ{MK(8>IyLXAFV-j6P@f?%tKaMlqyHOu> z^(*eruIgOK^mM?YD9s|SOS=$dVUh6El+VkZ-(-@fcY8YHpdu~kUJd~p|3}Rp;$KE7q z9@#ta?xda(+~cP#$z$#XJkCx$X-%geUdu#dm*UCT)>5y)W` z$OG{<(uFvzI!yTpJ4cp*(Hgg+W0zXiRv_B2-Nu2I(qFWdGVuc>Uc3X${Sd$R@OvM> z9VAu!Sp1A^z|I?XX1}H3oLT&p8v0^W>>-cWYFIcwR$^(mVzD2@S$Nd;;->_M0U|#5 zga^0lOm1r)k4SRJ)v*lup10L_wlyi44f|Sat6;;rLmj+47`8LYs3$zLJt4;;#?San zjj3#G_cV$3b|t%wY&?t?6T{3*eiIZ&n( z#1@Ks)Em6u%u_|0QnLW+l?QNoC(?*1wnq{eb|NFBcBO!Bpeytujo+90DP+av(N$w( zu@#92O(b@I*QEH-BDI7Mcilf95gt_u$e9uP!{KfX_wTZ#$@}r^=3PXBi;A1boLcLKP#A~!~tJwd3`Go!zo~^^XnWzN$iT5nz-9<^gMHS*eFU;PEud zGl{xFKA7>eU~%jzZVHT}{PQfu+3A_g162DJRw4hq;2KM|@7;fR=ib5L&cOSa#Rd10 zLPLjP%2buRHQX9p%;0~j4F0XL_05;rTBq>_rSYOGt+f8P9pP68jnewHOY8CfHxe(N z{B!u?$-f3Iv%hYeeK}yYo6zKD6UHi%NYi&p);^`Ff6h)pO`PfF32lg=*rOAE z#`eNO5oPong1B5uDxzo?G&csOf-$c(6nKP2Vo(S;+#HPcw5hBf*zTBvfH9M)5-$Aa%qwH zr>M%LgrtWCCv!i{5~B4QD&MLkJmyZ~)8XjX^cFi#7EJi=fn8QS&lLJKKjv|H_o`h) zbvLgayT(r?Vr7^qbUmqKI}s0xF}CZSFhvJ6W`L6>kaUd#Ga#qRr?w~4yf8kvTNYs! zxI#PhB5gFaU(Q@&tn6r-mjaqulPrCrSmb6!iwX({dIg^>#?KI_d~xng^j z-l+}s>RaarE-bd!$p?)<34|ziY-gpWIEZ)zo^ur!CHscr0BPh$JO@6ojl}igz|K|l zn<643*O=sKDdudC6(;kiB70Q=R4Y-D1kp`3rGF~QH7}yf z2P?y@>-;p&H22#p9ZEvuA4@GOh_3pP1o4bH9HC1B7S7iNA@=MtoY5!&=5BjH&19NS ze9PUEHs}ePfcw!LWSF!?Ncj?Ol+7z3x<*w6;2&nVm+t`R>ea`+fK5WX8KU>G5Q(qq4N-O>#Ok9WCrS?M zs*6$82c7{vSt!#HFi9DuxlaPD@u+HR&+IHukLikS7piuG`UMna8c7s~@p0IXIocDh z*K05e&@%Y20N6xyp~jVB{hYMAbVCenqvmA}FLYmre4d2Wv-nngqivT2<}8PWUzFn8 zXIi|2|KEsZZCBdKa;sNDiImg!&{#>RChK{XnQcim55^<8Nsz@&{@v6Y7lh61?m3O! zdRMn-{hWTshNz$4yr^q3a>Xv9V}w~j{h+iTQ!YKu2y74E_gT(hHLS literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/asab/web/index.doctree b/old_docs/_build/htmln/.doctrees/asab/web/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..fa6ef2626ccce3be93e47185588d37985a74ae17 GIT binary patch literal 21509 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 TxkNWx=E^kh$5W(OS`_{VnhkUV literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/asab/web/restapidocs.doctree b/old_docs/_build/htmln/.doctrees/asab/web/restapidocs.doctree new file mode 100644 index 0000000000000000000000000000000000000000..2fb6d165dd49a9d00b4b2e53dfb3596f67636e8b GIT binary patch literal 12295 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/asab/zookeeper.doctree b/old_docs/_build/htmln/.doctrees/asab/zookeeper.doctree new file mode 100644 index 0000000000000000000000000000000000000000..89a748c2947e05a8d5efc219570627d4c950f5cf GIT binary patch literal 35104 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 Ra=b>+K-|uFLIfPk{}0=I3)lbv literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/environment.pickle b/old_docs/_build/htmln/.doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..8286dd1bbf946777eaf2d8b2f56034f378bfb69d GIT binary patch literal 1333481 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

VW3my?VM*!_)J^LrUYpK=U zN*{|CROA(T(WlRjqd0Zf#5Au2236FSZc0r8Cws61K&t~j_^9X9$)3}N=}kRY5qP=& z2@Z>55v6_>-FRM(L~!|Mg&K#Cf8wuhF1r(1hL}jp8AZdxqOP#gtRc?`VR;fzkx*>~ zsuwLR?rLX^zhRHzdGfZehr%#I;HZcol<#Fr&Q8x&Icdw z7*evJ!gR7;4B4ml*#?iDazTdAaIS{UEcL2hFK0@*^4Js#OzY=8es;t#PUW$|hT{W^ z6U9=FvpvruzVfl>|9lO(iBphfY_8o~%vUS5%4pr$*xG++e}-yK`;s{qF#_bA*6T;3 zGp)2>&kRtrUg@^yZowQ|B03M5d%WlUQI16dduAhgYnwf@3ysaeoc1Io$V4UEo>@;; zbWDzIfz~(1;&w-cn+EOuL|QKcTp21da*!wJ#q@U0Qt$-JXk07z7^60X+X7XQ8zUBLjWG9^9KEsLd>_0(!JgXRk#`y^yrZ*)7LHl?P&^GZ22S2~ zJ;m|w$n-D(J-aq!ZX2P>JGJ82U~Ll1?j0HDkxb97U5*i_w{kVh3tB%CA=1`4IRxwF zFYxv3LPvcIfTXo-adt2|caKajyp^9Ii}AcDR0x z$V7kI4p;iFM;hdCy++AbgI;sycSt}d9Imnx)8Pua^C3wD+G!~mhx7*m=73T#ZZr>9Gkuyw)?g+$- zCVh}QBcn(!=Q5DqbY~noIb5s{PvuV+>e)(l>{QoroGApi#Q0cO*U5Ti5^e+p7iH>nl`C(@;x_rWYwZlzXy6vDIB{H@Rsb~L&`?%rL zv>$Ip*ooic3;VUZr|OjnZ1CohdXVG&Um^5T+?zfv__@|zes%?Z(%-O0;P?3j{=_K+ z`tKiwCs_c;&fbhV0vt&eDrurHqEZ>;leGVCV+t|Z(~K?K?H$;xrcUlT$oM=VV5?aQfk?{a;)hrV(kuZS2( zh`RUs@DuxMXV72Uy!elzvBdsbI}XVcnIO=k7eYbd2~Sa)n1~1Q=JnbwD%VNMX)I}x zbckdKgT9T$O41zq^GN3RCc z?XR&BJ&34@?BsN&FQ3Ww7wUQaGdvUJQHkhyuXs(ye*oG$wlhS$WP0^gMy2uS%dc@?2(i_g9`5argfi@=_=e;4`^)*#)ClFD@)AH>2wwkM zO;R$}8-jC}^t9FS;Tn(&{SA8%aV)@q{2C0%r|T$7Wq@hhOP7bn;U7f`)X9~C5TVlh zXi2H-lXD7f0crO-Z~~UyL=Jmi{>jX)@-#x09t=LOenM6-NI(Xee2<+_*$l7aQMeNI zPU_=&MO%R10Xf0QSfr*ZwJhH&Orj0cmfC?2xE?647v*p$=z(r?XsIwfIsbU9R2fE< znCw`V$`&dsbR8NX*oKB~$2U}<8p%^>Z93OGhZkvoTJPLds79noQkff~<>AxLa1Zks{Dn7k`T zng}(kB;QM%bh#oSyXc<_WX#X>%3c!zwul8-!ZUA&Y;gBnfN@(ZN<@w~DFUE?3FT#hgi$V-QY)C3@*UPwR6X3x$A;AhU$ zJR}UDCjU3#+EsV#Sef3n@a!}Iq@|GEHMK4lwTcK7dF}EL#|Y-uyvG++;EsSHWgC5FZkvc+AASJJJY!kRG2%4cl-GU zy9er@hhfN!3;I2nk=oU$m$Tk`UO6itj80R?8`mr0!?LT7mtAtn*vIy-Z{g^^6tPxo zZShEJrud7;tM&-1UAU8tRb%v{g6luuUaohSi=Xv3>{%{O0Q3$;M$(az8aeLyF$#D3 z>?1*A3t^cpJ!%7yP=-V$K_$lp(Mu+oR>H3!SAqS)n9(jn8o zqZ))a=r!n>|BmqtJI%c>3)EcFo80S@;Aqsr^!4)A8*>lzY)T|^ zHn9E{Tx4%9_gaf7ylx3DA>nslr0CjTC8so(ezX%yI3K)mNq{uZsswR*rC~p9@Vi|* z@Uno{gUScGu~!v^!M_uN0Qu@fRHN*~43B|S`!Fk_8sn4?+)G@`VU2gwHx6s$Z%M)$ zSu;n6HEy?S-PvJiv@49jbJXcGJSlQkH7v~Z%?Me23c>2cq;@1U?b(V?W@s%L}qntgMi2RC)xi^}Efah`eDeY{5n z#^^8_yyNd?Gqq%PqnmiR%b7pb?D*3Mo?;|L-4o!W&MoU=gz?ovxXfJHJ$7FiUSs4H zl3%?(Jqd3!{O0P^grOk{vp_9Q#|h45fN@jlBnlRSNJ6X5KDiI6`=%tbq2d!Y&muX+XIUg5@plXh^9lVzj!Wa8Z(rL z+P>dlB+4WLXo)7dga)33x&-A#a{)?_<1rC5%Z7$D(@J=Pid4UTE+BeeGT}jr@A(!V zF+oNlKg8&WV&EW8%nO25m)Uybs=Rm6-KWiiKBaklJ_Gr*3^J(U=~hA%X~i7hS#aat zfKW9`o9on80A2mB3t)|4*+GR#?KcQD9K>bjztnpH$pqP?N& zC~>9X+R&ar)u;UsHCw$V-5Tad?CuVZ6stRLcxc~! z_wIeTKRYpvkduDNB?;g48Z2J|20CZ3H1k8hEGBa9_N8l>^+Y7PC{;t%0fZ4zwUK6| zZnUdWFFL=|QFO+z|6Ub>QByMi5OZU-Afg>rJ%RT6mUCdkC)+OhYF(^fQ z8oO;0zVnGdF`<&9FmIXyDYpt|LuABUiDwO!i~>i*XVArtMD*+5vh@d?b9U5JmGot= z7P%6vasHI@qao-qRY+~ON}37P8~g4%dhF0{%vv1RrBni~7%_pNFrSKH8prtyoVb8R z9YV994G>9|%@nev5lWS@F$&BhtaAjHV-D!>rmG`|Amwd+guDfcv^#vCNISP=7n>ux zNU_RuMViKLi}Zdn7u$nOA$U>vX_Mf+IfS!J!P^l-@W>$2>=iDAtu*8n$OGq9Am18{ zHj^lg8$A;^mP0BRrq)-qQ#JJh!*;Z5OIEz*q|o@+C9N%$Xmt>OsdVMxT&;GtLg%JL zE{`If6TCg%Ucq#iLJY2}n|m!t%jQB)P->snBDn z0!IEi7+ItVHF7p|sfw25AH(})4i>G!pXTD-N4u&S>@APGk#gNLd#r-MXZ&<%_d@QMl@v;f2N3v0>NH!>5(gm_DJ>00 z5HWdaEyCoKRK(e(oc_i&Z8vlw(1xvO5OkVX#&nuc6$cn`xHHH(LB%XJ=YVwTP$b1V zJX7}8+%z^t$;Zc#1i@a^d4jzwCc!Q}UZe7Rv=pMMdgR?U3m*hOA^>`A=K=cl5P;0- zvw9NTP*$pC$AR4F>D(UYZ#WjT_JA2{f358}O-~Kle?N?38}|1aGN;AOowwcl^ueQh z_Z-=KZ1C{zqeq{1-;uj^Nek(G3_uY>Vd(9k#rd!w0zNh!(@1pNe=x(C%Q?x2izAj^6~b{h&v5`#NV)I8vYP~>`Y+ObvSQQW1@F$ zrq{D`>xMO5?)f$AJ|7m;6ab1dlO;F}!489PJ46(N4(e$wkm;L#Tss2{S>&`5$n-UT zcOKGy1f(?snYvt%nuC-+h^aY9W)RbSmw485P%kdtkt)7;A2&p& z=@3k9W&H(kWUm}r4AHp=(-90%uP_7!=y=Ixhvx*cbwtUrk0@RIWkF!@%teSU@a1J=thttHtIoGU1XB?b!Eq&wQ9R8LhIEOV%ba2jdj$t*T z6`P$kS7F@`_skR>-;fz{r3?oNYIVn^uHMw4;~3x>9vy|B8AdQ2yw^2_lNdY&D(uAx zrV{r6At%5``*^yWk41W6t|!!l#PawYJ*y-fQemv{!YDggAJIvO7L3|Ca$P+%dN3$& z=pSq=T7}AsLQ)8yMvXscKlfuwEaZd+&`fg`p3+jGFnOwrKL&|Wc5clM)SRL`p5HfZ z9FZhS`m)zd+yhjfKQr+YA?Pt323HXO=g#C%0Gxtfln7zP@5qVbmGH*|-H*4IZ-eOm z2O)rsVd82mA1+n$rw5-sRjC(dADQ*&;Km!*A?j!vF-KV(DmGm}x%n>o@4#Y+F zFaLB_|8%xcIIVse(Z7u3rqvJQ`Uji{quZIV+bNc(>IL;wP5-7<9XCFqe$1fadeQ#f z;kmKZ!ShD1^`)iaPGhwJi_?TbU#mNcUddUo0h7m)?SjjMLH(Y zu&s)^GLJp~mlaiH@AOcZwr!Il`LtrF5)UVZa{Vqyqnaoxh)h~tXmXi@aFbY%5VR4* z0<${rDq`I$(e;K1bfo~zCD!W{Xx!;?CYBNy**!hgVQPIwq53sEo)jQ8r4}ShC;$iH zCb2$5z(x=YtvK&0Vx5)P`gjDkQb6Vs>m!UDy((d1u_}|j(?cDm)n^s0KET6C0Z~(0 zAxGV-njLhTr20C+8bK;F;=HR!H6oGqSOl_C0OpeFuNXIqRLhuDG{?x!>6s2w>T`-x zU**xH0H`UYAXQ?{bkJ>*YX16YQlS;+T}7&KiLE8nK!|;w0y39W3(>HguXy&Cz0*Ts zy|-z;`XfcF3wSswAZkjhi-v{_YsSI2Nv$3NH$t$`j`Oaf)`Y~@h6sG6fX$`WT1Jl& ztQBg)QkI$QpC0Qly*{t#bt4Zb1x#`1WmuXH&P{q9Byc0>g?5~G6}=2y^wbD^rGU+) z*C9ramtNXBmh_^>I!v!WR`hxb4=4ppP3d(x_5%v1 z^Ct{So{hj{3aDL5);yG4jn$TSsUwL=Pj;A?f1-$4X%{h*=y2;3Sk5)(t+T73{V)7! z`t9`MqmXjql?&dG#(gdllfky33~3n!7~npmeM+Zt>V^y_InXAs?X6S6nb`dE6oXO> zmbMY$KX_*ZN2FlNApgM^6h|~g$^mkWD6b?}f7LtT3K1%!&2=!2Ai6@8oz3OPi-j{f zf9Y%`a~9^D;Y(?2%L0AB*?IJRF$8_4+pSS6lt!~h$@O*&E;pQ);Mu4;+09P3?o%Eo zeXshB9dzAmyZCh-e;3k<|K;utnQonPIOw|dx}B{l#i@_4p?O_~p8)+j=Q4~D-~DI7 z)HStU<02&(RA0lMrtRGuJMPPU#8w_Hro+%aYy8dRRqkf;@goO~on-T-5TdWOSBTtg zkjN8~JMNGfY)Wp z7i$t|J6-84`$xg4D>sDOPobcE8h&!?Gq{A5KlnV||6^SA4&J#;u)2#?5npjMavw2*pb1gNz>EU4f^goyF6AbAYEsEM=kCF>W(X^lt(ar#p*@ zvG!xav|OTcdLjZ^nyNluKmQ56Z<|Cd2DGdcvt?kl8GCxL16fv!SE4J-d`)Th|0^ac z%uAgJVv(Jg>s8E#K0GE4VtEVkC%`7b?!6;-D7D3GtD$6$7V354P`HqgQbLyd2K!A!Y!ydTJ|6f2)mNq|G}+@o(xF&4#T%~V zsZU1ml#gMT+Mr5yU93Qq4Sz18;g*<{M(i@HN@<=$oC{`+!d{!0^;^+BcC-ArhP1lKD8pbE>Kmlfb}81s?@lA`gjDU7S|z`ub3!bUfvASG2f0!Hk|>_Ibzz~N&aHTKV;8!h7UCUYXb1^cOLNX zgaB?jIEx;y$;ocaf;HvNr1`KLll18vBI;`JNGe|5+09xLo=wkt+S}5rUWfB?3{kC9 z!|qF@M;*V1n&0NIUxj*wj~@f`opVjjpPaULNrDcb{reD_m=oSoeVDPqZ0^s3nJ(;u zeb~N8fgmaRZpgq*W;$tBAW6bdTyl@OYe#?o*|TS}4)>wB_=HiGq@z7~8Ri;bw{r{= z!Yx$yzI2AqwLhIlF$!=k!PAnjaAOP*GE|N zl?!w4XY~D63WQJz4Bt)n-Pt5+?f^+Ln&o`A1yNS;uh&%=hEt-V1xIr{VLEbpluG+tkt1>Dx2ta+2>n zlfHh3?wrE6153wWGh;oAejB9A5H9De9DV&hJu{4NGgh9jBevW@b!>&8rM^^)&xGlG!^ynZ1qu7AH+#`gjgTsmto5P8l=ky>GFQM{5iSP{tsP_ zQ=><4nX=A$x;eNMd<+mDZo&X@6=ABHZE>+}28~P1F=$+)fI;IR z3QFCxIOC6iwAd>_-cO61rc>5KJW%Ul_3=D>fDA8CA1_oNFIFEfRUb3zrjBEP z3-wI5PY-sJ`$W}9&=vwtLGw;bF9p!a>>RC**k0s~wHFa{3@33aG!~T*WKx0MOlh^0c-P-N}i8lWm67u2#X zVQBplu_%N4Hu@%9yh#Y4aq4dFzr){f<5pE9aH3f4KU}SF>EZsv)AjL6x&Ig~5D#L3 z*iXyBevDXsDdL>J2eQ=~%6&Zq8XTDKck7+_Zyd51f)X!MGrh2D=@?p0n?&7~YJDyH z0uhjxuU4r3OA+=i5dbAbCip2ey3FS6&Fk5}Jd`6M7ArV%n_J2iC%9zH1k&^;P%)2J z_qmD66jCs;>d#jY2*n<)a-o3gI;!f{*=n(lN|SJ2<1##jgR;m`h@*bI!@yYKgYnkx z;sP~Q-7$m^b^K6ph6iMGmC6<6pZarWb8zWkxb@rv%CT+(15ah{G<7)*n?Q{bhbI=Q z2skKL%6*(NhTB-FPh!;Q0*-YI6}YLvLrQ6J*{-J*sF6YjQinQ(g;8LP9i0r0!ZK6` zl`kk%`$nrM%rZg+b#$>6bj%wCBZbLQWtt!F8_rQNGJyjsH+>iK*B~fB#{rl;)iNBl z?B~j5hO33bg9XPyrJbf@bHoYKIr@G-w>v=;KCkOChl`|KFVV~;oBmit(-6Wtf zYrpG>mqCPn#?p@)mKG{Hinq+=PShH}JI#`ww|<*Ai?!-PwVabWJ3!O^3Tax>prn2v zeykcQlZA4hT3$fFN9$+d``jQ>XrWs&cOJb9TPAr@BV3DgqL4$$Qr3;wSfNvDb(>HV z`Z?_L@hNB^*WfBZV3ceI=#t?G!Sj2A_wr?xm5T z7r+R`iXuk@z*?@#uaJg~BpO5&+O(QM(>wzrs2INxHqn?Sx*KCjmrYL({^ZIjYpKeA!IzxOhpThsw*OWv-A3MIA-k zHYw_5@f3Aq(ALr;v@C+!!>%?8AKp`}@0%KS(d+stO#>XNB-^zI7F@MBjB3yoDld(# z^RtB#6inedn-bdSy4c^HWV?k~;4@^I;bZ$viHB+rN9_nLb0C$2SP?OZG`#QWNAbPd z(!!=gI9~liK&S~2f*WH|$pPGu2n?-H4Z5&37mF4CUF8!mFlKX!zZFn@o_NEh)D9HK+DZ-;z{57dyBte zkHL3|-?(esy3Y=dVf|LZN(+VOb9`hG%$}THaH38uFCM)sHDmv$rIrMG_WGf4)>TPF zHp2G3OmU6G7tmww1N}Z7iG)Qi`6s%%@`x>~W$vB!IB--wI?oSlckl^cysD#OW8)?KuMfiYS)dT-vDuz9 zxCOIaeXb9WK=#iwkr@6YQR-rs*8mXfCtGOPVTt|b7sXf3PQFk7jP z^>6Mk6^E-hH5blO_Dg2R>k}o|Zfmn$4#wjbQMy?9553Sitr$B8)=LR{Dsx_0T|qAk zLeBW{-ELjptK{#+=qcI$fu0}SRP~?ZCVXY4wm9zE1f&kd;ag1{rfXhc`R$#@@>+%E zH+Kxn&zd92FnGFgs-ykdY@pXnO~qd>UOpH>SKkWi))rKUJxnFl!9M9vL<}a0S!R0? zoL^c?*SeAl zY@N+VS$QGZQ5;}e7%Bb0>y%{wHlr^IAw%?Ml3{Um2>JJeEh_u)D$B2h&q*Fy~%3{{py(@lUdjY!&Mf-nRC%n(?&i+qP~7B=0#( zw~)sK!(ML^9&~s6iC;7m{Vc`_u?>+iPAptMoiR>!RMX;qu=N7E{3p4;|BWs;L4{b? z)5W687+ro$mmkvQ%XIm3T-+EXYGj5RIL9xa;}>W6r5S$VoEwG2o$>05JNswqkvqGZ z8s^T};lQ1-=Aq84FK~}@5g`;7^gUZD_+TK5O7X8@j_PPVn~O~ zAh;u6nB*WAn&0$}Dze)6fN(lTHIt*DnwnS-yBSKQDIB(nU>535c0e1WXNqucWO9f? z&yDm|Xv-E(GI(H-=gGUJbeuV_o3Y_a&(L>{Q>T~{^sU;}L*_`6TnW3q2wN+T(y5sm zM6p!Q4dbXIy|G-|kSUC1xvQKyC>O5asY!rW=*P)Wl^kN;oU(CD+l&2plh)fIKQ$aO z`yxbENtD=qDU+OK)24^)I<)o50;>1-yOM`TjUnMm@3AxfKyL#8Pi2W-exGXDuwtj+iy}ZFMq#8_R|&W}p2JZUUi~43klVyzZxr!Hfh0KI53Wt*r;*w) z#^4>FsVV4yg(eV5X?T7FqlRb>2O9yJ!@egwITz7MOPYg5Z)=VNZ6uByehM7f8q_H8 z8KGU@I2Sm&I+D*?hT5in5Y+ZP*~zcZ1=OpANE?oiDB`wB9jypaNAb5mE;^`8K18Wi zr}D_RMhv>wJsxmh=-f}Y7tO92_$hzG9y9Qw0G)e^Y#Bo%k|P5<4!JUdoDt+!R=eQE z(IWoh)4-=;&rOh?MZoU{){D+LE@)c2MDdZt zc>s#9(}}ruJfV$khk4v}6Wd%do)@70b>~6V`{q7S&3*GXuFv%2m`B8bZtBOrcAxtf zO1DgG%1-AdO8(ymvR189?sDE85bqB3)4QAPcipE{M+4c-^th+90X+n|L$7Y(=B0!_ zo(HOktC;IwKwIxFcXK-|YL~mQ?172W4lbcH+gLhTEwGDkcKpimNA-&G>Dc@>%{RT# zZ4%$q#*K?KWA{0Xjd&!nh;<(ED9)S}u(BOL5u~HdfssCoue2|=mG)!~r)O2CO7KDm ztsV4$5VX}BfgI^+Xho;EYI}vhVUOCr9$?1b*S!rv%6y=EW&+D@AUcOQ7Cta+sDB7$ zLdyBllwL!_Rb4?<5XMI@?t0F)HM|8@H;qtDae7PZ%FuqKNpXW8HV0`wi*^A{>x{<&8?7GmPXE zbow(m5>*pd`%&b|3T4H936FZx_Zoc2oti5=a)BHrM=D%1#bofu}0wm_!n#B zgXkp>;Sk#q(2`wlyp6#yjV)=~vo)U9tm_lBA^GiG1cUf=?Gg=--MdnKi=Dk-( zG@F84F5l63ZNBqqr6^$9#CSc5@m|z<#!E8b#^PaQdlrxd`zGvQYr|}GH8hdoSJO&W zS`XgMVr4BhF18Ibn(6zL}OJ&W@NL(H_cYtrWx6zh$56M>ANeK^Y_}z zoUT#!aeu?^L~~$00DLoiot~M-O%#{gUr|$LV+nRJkTFZ!UcK1V#^y!|nKn0RgdEj* z%DpNCnX=wI`!j228&CHBot1BiI_Be9#p?l3HJ%-Nx6Hd!*sqC&7{whFy8|$=Geg1S zo*`!Khm4`|z7);Y?+d|Uuk}0fPNPpY(TlhQqzNhnaisJH=G_`sPIu~t^;*xpSWu}k zaPqe6>rm}GGChpdo?RO3@!BEKK3fqK{nEX5mZmfZ_oft6xn-v8gqmMznz5Q_)NhJB@wI zKi2ccP$>5>Y<z23%h@K7HX);eL1*ov8j|1JcQ$A{ZL z1ptar0l2m1(XiD1H-P=90qiO%BobQlrU3WiG~g~Ja22de3DzWFek1{yW^MheBZc3F zy4P1fegWRI?^vCh+l$&f?>K zMd7DiA!oRGJLSmmw;0uUic#g!N96Q!KORt8OOI;G7}Y|m=P3uKeiCCllYDHAmB_cs zO_l0{D7HLRfYUKZ)*6@8rY0$=Yp^x}ml&UtU7JNQsdJ=hqLz{)tu~h~-joTGpi?8mCsn4xF_< zi6TlGtsjdr6CC@S|~))p+v7Q4r`rVtU+T}r31-nTm|94_#cLqtzsFdjs(uEGxp@LtBX24xjahb za{(fF__-8d4P`h~O=x(3DHy9iU#d(Q6?k%09N$(4ezBj4peS`79ugrb`k}~`F%WEl zs_A0;wx;W)J6+m?@^lS<27(~CN^&7TUapiXW3)|Jo63)4v4FZ*I5)14c}Asj8V9B! z;DVz%oX9X$JcQsa)?H5>%|s`DhPy<#6N>hI$rWv&)M?>xoxWcuS?~sE{)XrY!eKhi z?&lapoBt{63Wf6Fbwetw+B3y|v>k&;5k14S($w{25G$yvqjMX9u{dga?o=lNslO{g zWo6-Lxv+&>kSdEn>LR6anj-bx0;&EKQYYM!EA(*4BxJjCmi0zAwvF}9shudGlps@!!$RQ=C_uQK00ZZ3I&Kru1iado zLfv>zD+7P*`ETZ-Klc2$%+=rp1AM;o46r071FS+tkI~|ou7zvF7??K&5MSv$5M42W zxMFB%sOzLw4X3*Fq)>HF745agFcUPE;|^-oO<<pAF>;FW3aH#g*;Tx17FQqOI0Zt5$UI=qU_)I6U-!8`$p;UB8 zluxOcNzrR<0<7PJj6H`O>j%VNoAH-p=$pzuMH7sw1n&v#tsDr)UYk_%YDL&(=qcIa zT~j2F)N^H6x^t&)(?<~#oeLl!Hm-ZEe+H{0xaP|B4VYz7 zp$3yO%8E{NkyDy|$sXc00xTxv`kgI1Q>xxlTocl|)Pwg%pxHWvyc;iTEu@jzoTtb( zfB#Y0;PHqCQ^?-El={Oultyan(9LPkBUD5b+-+imOJlOZ*1cYH$z}rz$aD@S#}QI= zG*$ocBm33yDmi0rPuYe*$wYf87qmLKJOm~2L!CAbJ$M>Z%@9@I7<$lNKJqWLT*QL% zfLc)6cy!p+(4yA!30!-RX9Y50yqvy7cjLUx^U)&iTk`vh+lw`Kqx|PQ{JxODmHpD~ zFbl!A@4rf-NYWqY<5?5awXu)^HwH0ObUCM#0-AfxSX;=W`kHDZq1MQXcZ- z&2r}Xpn#?RAwFhBGj^$hI?QTUo|yV>)D1tX;;)->^#`fvFs@$a^ddQ6iSAqy|6_h2 zT3Oh-#Q!iOSj`_d5ogDMSMUNg5XSp$;)N>}FZ>P1upp|3O#mT$L>>MqkqQAqM zWXiC!3I5?pR2nT})y_Pvv>Anv4E1M6iijb>@thp=Z=cOc1xhO=N)sBYer_7ziNI8|mJ_u0W6d7%GiVNXi^_6Sk*X}?Q@FfSD#mz|chksaO<(P2wE zkRY*jpcx$>1!bE=`r2TTPSN^>*pya{$^B~Irgms>U~hvCD{bfi$lz`G@mEnCldAOC@Yn^kJYJKmm@CXnEo!Fp;K4 zF=t9rdE&uAoMKcT95hQ5BS@xD?OmI7?xPklWmnR_>ofcDP7x=X>%)(1-KzsaoCmp* zv6j`NI)r(rj0=``c@#JTSpI6(Mpn8yTbmlL(A(|T*WDBoTpG<*%64TU9KwkC zNQ2?lXEq4k8uOGRha;X!KCEfY<5Q5~9o%#u7&dFUSct4EcFru+6k`ngy^ zrRebC5O#XGF$#E*-B2^SE3~4m9tz{~_e76!mZ9o0_yKxIOE$)&p5%EJ6|d=D&_5dy zNG8^=?#Mj!Fr1*6$-A>;gXHSHr9!z^-(9=b-&UanX%Fnd(|Ye+`)T&yd)L}-CwiRM zus;*Fp9$N~gsp?ZrY2c6^G#!pZC}E>8=5(OrCHNGDAj!+WcqD)rjPYySS^k9tb5lY z;?J8gBd3eZL;+QYMv&?gHGi@ajhpY|IBpXp-`pcdrIa=WJnx`Xeyqfh@lZxe4gSbH zCqq*N6g+*b&GhZcJQwp6JUiL__t`dmWLgeS(kaq%_&vEOczcA&W+hF_`PGQV!d4gw z(sF35p_X@G?48Tr+CX;Ga^CD8YvatE=XoiJW(C~R`?zTrX=Z=2y2MCvC2#vi2t z<7xuqn)qP2xi-zgFmr8gh$H4UnEsTTWzOsFGiK(^LVCu&tue(v2~2$}Ii`~2-h3U+ zgNiGRw1s)b?mGS!qxxQoQC-n2nPRzb#i$afDm^Nbjtijv9Wvg8QZgQK za6;e}efd#=$kkiG)6SYVee7(5G8jfGbX?Bt_7=3u~*WzXbcT>O=YLj?(d`inr0sFGz z>3>H~n1>XND?_Jin|l6~r^V_W`vFBo`$s{@Ehz|@06`lW(~0Hu&J?3cAg6j%N#*o# zicuwyQ#~qEPP<$)&8BCsl~i7bQw%*Q*1di5YIS2sky83BJOCY^luBn(fSQ0xdQ`rd z=Q%cUl(5Zvj+}X3lwwo~I65V+UYlZ6$#E6UtO0q2Z%;9-B;49q0CzW1$7r^}nPRBk z(NLp^m|x=ZYuIFvTxlj{{Ew!fD$*0*44kUD%sIh~AoYfYw4V7{f0L@z*Z7zG7?{z03no-xIKQd-_7>?=4Ru* z487U<@xEy2AA9~A82-ne|MMF%_(S0Ue}!T}5Sn@l^KZ7IZY-By^+78>(f6hC21aVA znN@~m*o0JB)~gXYL}5cHiHhi&T3u#ZyB=On$-dNhc#!x+zR|c&3?ym*I?sC{;z7+u zR(Kn62Fx>_yd}u-kqC06m~lTu&2bo-OOEAA?%uChjFHmiB1NLYMV_grFO5QrQnkU4 z2yp+nz2F9EOPxgiIR-Zc3O_?bWM{g|}DDgyYRAB|%T zyf=hOSeF3hQN=;E0o6;*vH0Fd-&hLW)gw)^UUUpsMy5kRjepodxYFE1hDxTdFLMk_ zMEF2xyQBSl1J)=Sg&RMKk=VrRdx3i(DTg;g5F=1HYICI{b$ zw}rjGy(quOLHQnhv(1=AFisvZGKA@Vm=;h1d3i9V88dJC;vwy0aL{a&dAQKL zFFPBI7;}p0#a$CeLcw;!Wx)&~#3!niw0ecb=MJW23JBet(N*y1b%RqBmeC)(xaVE^Z8wW*1M6Z6t*?ZY^{8_)KBv6u?%9|d+_ z)L!DdlJb0o8kNHzASrY|T2l6qq_m160c=#CEwR$W3~U=%Da9zbVm&kTj^==F$&Q!vS;Y zEpo697(O@8w*CG0QCManH<9V3h_tmTP9H8DJD^?_*<&|su8QM#X;!o+KQ%d|ZA9Sc z^X9jZb302cW zhOP6x7ONoSkh-f#`1%h5VU%_T{*%6qIp4Vp-Ptn8-7GCa|WNa+75+3~G6qrg7>GlEzMN-asB*mx_aF!mG$yxEv zMEHdiV{4ta)Q~&NTdUn1Xtr6x`3r%SI$PR)MoFUQcOj1-NrAHjT=s!KtEfTm@c+Tf~S} zb9|vxkCmJ$WO;EdeYIapb;@X{^q$udK9r%FCdHcLVbO7EhuYhvbfvEXoOj6_qR}G9B z;^StrU3BgSVi)L`CAV-1waashTX3@1`miyEeeD{9uX)n}{5LrH`?_#J^VA72c zQHV<++irx2Z&>|`7^VyzeHsNjdKN)lwEv?8#@6+=rYGOIE-**u9YOl2jAf>mcF*hp zOBA=W>ExG|3(el_N0r&;zb$B3XfF+eI9JD*Qe%B)Lb4pz(xIrN7@^!Us)4tCVH@iG;$HkI(t3k!xd1FYCCFbUb6h)1{Q8 zKZ`(U>WrhWMKqd1l-%_ijn-bT^~Pn%_yDJn(IC~KIp}}$U{k>BnxcvcQw%G}6xG9O zsyYrEs)JWyt>_MyZO!%Dr9oZUk1MM*_z|HL7T)4DFFG>gUZ|A91?UO<7kkFNwFRYM zqoIw$epv*fQVaXl5sju`eplFOw8{3-wSOl_CNEM1yqMceF)UXm6%VvYCN*D~GMS=v zH@(-_Mq|W$?TR<5L^KwriW0;d(O5&}F3=Ai5pR_DkM(?W+5yB6TJ4NDdXXPSXSXVZ z9<4+i1)$V=Aq^ok;%KogXx^A3`$u8=yfzIe>7$OCgJMP<^~M!(*W59KMA{a2^sC8{ zl_c)y7tuU8HEDFn2U3hG!M?p7mAP*pC+_G|DMr@%p1m4y5+lW@&fK`8w=0^MEY%66g+*#hbs9G?r7gx2J@sg+y z>O5;drIx+oj!^j*?+7v%#};j1U#h*~oWr?_r9xk+cpArs4_kDQ z8Wq(-(PKJ7F_#&8usAu1%>fjn%;c*1aU3&aMlk6jT(m*ZRUgL&0hxhP!=0xw2wggw zLN5fBr1LqR28lMxzE{M`i=IHNYmv+p6ljwmiO`#UFS1^}Hw3&7icz%eDRtBG&r-vj zO6WpP(@1D4VeFH*!vj{f5Kq}@#rz!+M@nC8u;YmkFHy<#<1l+2p5$>PnEAu;au;6L zUJSaq!>>WZKv-z*Fx?OJNbp-5$k`kl4}veE8u#hXm_crwb@)n#D$Fd25G6O?{N)NU zvGdLQ^p?La(4hYU8=!iY+Q0^yDmaOZqt9%e)Ji`2??#X&1?VnMd_;jB$`f=ynkTL& zo@j;w!3t4rw!{h_WMER@BRwk|_n6nDC{SvEjzd!w23S(g7IFUPFrDd1cKAqUv|5?q zh+CT5R6P$JnaG+%1iSlLMi}ivBa1r%-`|O#VG3lq%=6bxn1}91Gtb>^!k2(Is@sznQ3uN0$j>k*twI|?^noaWMG{#GM-LR8#sLf2+l5^SxdU#k{4Ld%ndKlOV5_jPx}?hK_UU6e&3azW12`$OdZw5!;DK%Z7hG^^*4oY= zidDx?C_L}PZ-x%C+yhJ3!yXz(d88mSx!0PIcN%LBRqDl2I))i>NVFcwkLSu`1*619 z=u?8z_O+MON*JmFc(1=<55P|Yz@0e`Zlim!Y23Za8>99ro#q0!D+8cxJT&*)mF^%@ z>{woFEX6YF}~c-maa&pD2ZBXI?UdPHMknl!KXa(R-59S_`aocp=8@JUOO|>Y{@Egg|ki=d8E;OI4K2gMO*)O%; znCoM1PLT8EW4(*N#c5G|FDA8m%7e+^5`d ztx}q*EB_WZ;xq{lpHxV5(V-CWZwuVC>{WHwB_q_Z*Nglu(Ni+H*Na4VT_Q=U)+HXg zhfd&e*Cjus!ScG~|Is&Im+-eF>k>94*|F>(BWPW+21#&^@!wY&?X!)4TLQJ!(GU-M zR|zewQ^;(OzfM_pxLP?=9P!oC_53clYx!+n$!nRr+_lJ3f5V=&$RL0+>qQ?XZ=zlS z+Eq-k(=%Eeo2t@&P$hG=Qa!C|0FG8lrOH{_FzO!8pv+re7Xq1A`eAl7c!-r1Xs`MJVDN zUHAH#zy&$!v46)S8Vi%a1WQjEYv{}sD9S#2*e$-d-#^yI>(lu$9QN#Y*)xkXe@7~L z6i_8K36E7Pyy`C8%urbwbnXnqBPXU~w)r?@PL<`ylfxh(G;L+=8bB7SNJ9u+yIvV8 zZBoHTJSQaLfiwW8U)weZ*j(G%vvjBuvElZY`CFp(kNt#Yu6%tD@Y>h;RUqn>$q|)g z_4_h3pUevONxK^>`Vwx;GW`HDF2F>FyvvwSKM6Gaa%a)-jyXWXymbyk_~KCATZ{la zDxm+}6woJ#4gAO)K)*^(!8R)VwF;Lx58BVzUNU=!6u3zcIs8S&P2!mJZ>Jbl z0*dKTnbDjJX>(qpP5mUe>0eWft@T(=HDsTYCn6T6sitYEG1t%5d~#^FpKaaXL}g?O zMs`0L3jKP%=yxm&kBKweScFrni#WF7L6EIU6lVY=jv3)Y)?H}NUflP_JMZ+mrgqJ& zRi1yr1qeCgQ%`Bg%E^}5iEs4hOVkmk{9UgB-SbR6Hi%jS-c1d}a+*B{JA@C<_FB_R zd9O5rt$c1A*@<%Fct#Rx3~M*eB4zLw0&QcIU(XWg?8WJ)Z|ue4Z%Mp3yl5gXPAEMa zIDN=ow)r-d<-LggWVz^8xNukIv|Nqvr@3(VWG)YX$1^IG(}e=!#iVBP-xgYG7a_|b zeH*f%bH@^M zf#$vtI(S~2B+HrY32RJx2+jR## z%Rkn~F|!5kP=`%{E(c337vp)M_MYcQk;5Ay&T-2qn$;=2iuPZpOGD5 zhx+uSyCP}MrtMyltZlX;arB$JAbAz=*JMEw0EnZ_e7HJ+_7W~g!W_QtXvKPjMy%E& ze@EZwPkTK=-+k*5k0w;>k(2bAW0b;F4BN!-^={e1e;?XHOx!$wm$>{CA=u8`Mn5q$G}Ptcnl6f!Mm)eyhmra=?HJg!ebWZ_hXM14&HO_bMV#%l zT`)Ft^qOZRH|7r+=cCdOg7`NkAU>bvyv1Cm%Rq12@x#w<_8;ba9r^=q*kOEshtMGa zqz+x>C%N0F%p)c~&51#JXK@fm1Tes*C$(92s>^Yj8LBk+5dqL05dbCO{s@3{wNc69 z0BB^LP^67T51!u9-*2;@$?(=;8mYIIjecH$bENa&=(DsBp{HaDLZiq%Yu(W_2Xvc0 z6q!Qb>RIc>1n6Oz+m=8+xBBI?z(_I`N%OSv1$K6wgT_eTqirEQh2;kX-S7KB6^~JfxrpHYQMfxA+wwjoxO|6*l~+MsJi# zj{>qyoOnr0v*&o*?cM^;qP4X}8l(3glG1D-KFtO;`DymI9-19(v(d}A5Ed2n7RKLg zBK>7CNgr&^3Y#$a5dqMm+rt4eMJ&ci=s_m@lR^M8E#8%E@!Dc%^Ptc2y^KcewS0~D z1bAyY58hP@yi3qi+bm$+rq5_+; zG27F6diyg9@-}fwrYWbqZovifE}(zb2tq#^Sz(F|@fq{u@T$@Qav47I5XZ;mbEwjT zM3Mo|wl@2Sq71pI2x26c--jbwGfB&OCcz4JAYcVcqqiyE-46?n>eEEvMa&sdptp(8 z-AxIt===CH@7|P^}bf&l0jm|8fTld_l6LTkL}Xj7;NMP?}bKsD*F?*hf1 zQ;ekKGh{X4IJYD)v^NJB+G?C_njyD@$e8K!c;1$_Iy^E~rC3JQgdy7J3)l+8ftwuN zq4uCKvD(w2c8c`G9FBB}oQt4Ti!PB@M>L&6?p&7$joDrx-xR$iXCt)*pcgBG*w|L{ zK|oIDJLUr1>;2&R`9f&aC<3=hV7A2+n5ztj5A9Ic6Hbqf-x&LJABn(pa$WVwh}KLt zC7rq@!K!0Rz^a2rZ*%X3{azgSj*gB3v`w_TB_{12f6kn5CZ$_~RoIq*RoK@&bnCn` zhkEOiFDlxjs8WV-4$J8rt(kN`cbW)rO5wgjx+GK{3;)4|rH<4j;; zZwWB5)i~Rv&G&>zfN8o`P{}>a&eS36v<)*+tkqD8hE9XY*h z!k_B5$Xdi;0?hpLCJ}erJQ}l*03{@aTN5nIwgfE9yqLN?fHQn1PZT4xNl5kv3rULB z-P(yVlST#od(v$}Q%++h-Jc_}ank(^edDBi{+1-^{#MG6;L?fSU_KM<#)Ub~bMJGU zM`nnV{Y1w5MCv4b%21D=gumwAV!m3bRYvQX-4CM3VCHDOQq7GyL0@Wh7W$N!u-}kC z7GhW=CG2S{&U&4{VNXi_Gyv{Qk-VocN;F0es>1w-b#cY!W%6=_&zeFf67z2lNzC^? zmW}8zFg-s2GmSU5nw~F46f;9#yb}dQiah;w5$&DlRQ-?nIn!~WCr;J>R77K8(`$lM zeHv@1-V99J@};1Umrs`%c^2DXqCl(CovfPX=m}%cfA|$Ru%JTMP+XO4mIHLC9KQ% zS^Q%WI#k7B>P>Gqo|jK=rQ*Z2F3v@RYaqlXw-1ReRGlOoWuDJjuR^!qlR|tW4y1IG z1>R5i_tqJ>OY{VSnC_RAcJYKlW_a32^fm4Y5RQw6Wr9-3oE&Hts< z!1d$x`eY5MzPtDAx$pR)V||Bq-@7+ET&fIb^Ob5Li+b-Pm9w>Mxlr%F^Wc4V_U*av z(6Qb75A8i7XXut&6KKkJ9!)y4yD6If8lEl?o6bruR5ORChT%iY?9S&4wOZz2;Y^`K zQiih%km!jMm@AoX{YZ`<>E3|Dk_+Wbw|?Vr1+PzcXC|g_!3%lK>&xo_P^ zAe7ylDcXIoSgUtuP@|4Lc$IRk3%i7w?xW*5s>`oiJ6aqo=jvGWp$`Ai-AC7Eo=tAM zj4nTI_mLYJQKkHI8SFW8nRTb)1=s#C`1c11Ax61=0W)g$Yp8KYz)jWs?NJHH@gTuY z_X$k=N$}I3CI)aT1PAnVYgiC0`0UQJ;8Laio3h|Ui;{YK?aa=BjRPC|Hf`+NIB-*~ zxbp=5-BhdY%;S$S{)>K5|D;^cao>Uj&+9x1Rs@s4XGb)z9^rZtmT1l~Uyt6!xgTEM#Azd!Vk^>M>gfiAu$M+lPCO_5IuMfDv&5*+G>5Udr4 zUI5Omzoj9BI`l5~3yg#{=m7!Zf2091z5A{?h>r{R-SR!ay5k>+w`xq_w_1Yc+vc}g zz>RgpeRq9l(Qs}1(O?=>iL{^VzH82=?RMW?-^_i7S=RO1{Qy$i#A_D-f}^{9So%G* zm(XkXq;P#Jopm%;<*YkQ>_mUs&N}+;bJlq@o?0vXJ~iM7V<6~hg=4y%T2=Sh6iAzSVh@N zn8Cc9W)B3ydvMC;c!5ux3qFSpjqot=REBH!XSujkjxYo6J9g}FMmfZ?P89&w%DQieXwF=Sv797GT-X|rxIn{)oFtAFeOJzb9en{v&147^ZxMNHT1X9(Zyn*A(&W7jNyOX8Yk{~5bx z9c>fjnq38b(&q}V&m&9sJ;IIqsRKOWsWh?PSmu;D_Vp}oMRdBe->0QL?om3eI==UJ z@xk1*@BD51M=>{iGl5J*E!Xry!S(ij-QTbWoJN2J_Nrsv!?&@=SSZ8L$96n61}oLE zT)FrlHtvdL%neiJQgH&B9)F{*`7lg0sP7WPobB2Ry{-PBy-4r`qCn9Uo<(We9MS}I z1nH34X4IvbMzN1+*Y)BV!LikK0^jJ|3{Pt6@A|RmtP_1{1YIs@_Kc;BiKRBkvhn|n zXx!A>F=+3m6VRw_L+09MSQhLU1+OV|F^1%tD()d^uT-XrPz=Nkek3t+1P4#e-;Dp z@weZ~z=N3L^@=GZBpCQJ7K?n8#!=h!^A@)6%HW?ZV(T{{dL*08${z=Ue%!2nl$7j9 z4+@V z(Ac#&=i`u-;p=sD=En`V=rd$U#1C0Le6N?UYx%m4uj_GbEW*r6+sl3USHV4+Q!$LaXn{k$94R9)((7N$T&AXU&oN?uSHY!(Z21o z)-L>EjSymP_x`+_{li-HS;uh&3hu|py%+XaPs8US z>jbXWx2cz><6C3tWMQ)J#*JHWUhGM}|4h379lC!C-wrGtf6a{bEP8SwJe*^*))2m* zvvTy*_vxu&e4DZId>z3R9TxbHQCzKW(j#O1_c*TStRj6MABM$jS@?R$I*ltvJb@1| zSVet2TYc2j2k{slA->DitSSDnSMegV-!Ve|Q|Yp7BQA^S@)5dxkS=%Lip%YESwx4! z&Zo;)$k6x;x@@PEt*vxosgLI&>R^zEy3`4(M%jJ!qbE6W|pp?aX;FOj1Q|Dw|7{sd}bR9??HJmZ-Ak62C1b)3b!nHoIIO0DM-RXyl()2s8HPMPTfv z^?&J!#-b8M52AK{W1%{yXvx!dA33!D&^@yd1t4qoz!F!9eH}R0O6Wj zv*8%0J<=(9y*ij)gqdi1_0tnRdRebPdp4<7wnVB+Kq~6Q zx{)q-(B!LA1|yifDfrOfQ(eI+me!8$t&ZQOTz*mcph}}vD ztvn$l{YiTcryH#J=~0A=S#eG3HJz^}En;z*3(u6HThWZ%(S-mPpkHQc))s zpDgv0M5KCR&X2vFBJz#FL?)a@6Zya9g2>c~#m92pN@d2M5ccYxPLb-4U{VogqDi%t zo`|+rH?$;=1CU4R#Nwlzp8bR&)w4Q9s*}N_BFsdS>U48bZET5DTR|%7#LCg-1$2om zRZmRSIo&BDp9v;1;WV1a5786R^4L0&sS~S8m;X(dpK>D4c8bWa2_`b(G@8hNL{CH$ zd236OyaSRzj1h zLeYLt2vU8nQ>6NIFsTSL(WJ`K6Var)y(LoJ1yWHb7N2W!S0Yk9G3Up>=@gM43nnt* zG@8h}=7Px7iM5q3b-Kis$0sI{FSrLVcEU;UqhKNvPNRujrYE8$d3Q^ad^aSSINv}Y|0e&CCOf*TKM^8kP zbdgI^%479~c*wk772@F}ydGE%l2RuYmn8VrCk&~!b&6D*gGoi0i6+%Mnv-f-OQfRU zW$MJ@toRQlBGnU9#XhxDL_QQuWWs4Qk$-D0h)kVW@1hImsc=3i<*8VdL^x$V#K|hw z!|LOC_&`q03)II8)yIp~$4k}6jQV&vK9JPYppOfzSKz~X6)s5DpLx(Fk`fRvVKmv8XLb;bHs$`$*RWH^{1ynaexuZIzpim)<%9%oylT>mw z#LkZt%T!2-Bk6|=`5cuuD%N{ynOY@N8?RLBMvlsGC%VJgTHX#tT*CvMV#29lCX6VP z;!Fhd>{OP8`w!iHUmNpSVpDz1@p9pTNz}gL#Q72A>dDl0l~5G=l)&(8r!f4Q^cY@X zV|dZtBS-E#GV5w?O8l|2QC9nA+vcf4l+6@hx^BG_b!1MX-Z+&iL*iD=$>PdohD*8f zX{36U3%8vM=m1x73&DQf#&Wkeq+fL#4uhZk#R)*HQ3BOLlH)ZeG*k10_gw6AP zC>trhV6~*bL>xy;EeTCHZyzA&gb(1y>4_Dn2~%YJILQqbr6O6BsuG`AJMJzPN+Xz? zaQa3|vsNn&2~u6vDN~M*R(d)GD!`T!p~z~dEG>(&c;XAhj=iY%hKd=qoaIT2 z3uk1`{I6cXv z{&H+VuW0Q{C|VbRW|WT;pIkrf6W2RCMfkV3i}1Q~N^AKuYe0C)?uk$M&?!kM&CsWW zbp39pko?i~NRBaaU6oL}p8Q0gxW3#eI{kTiIt5N#EoCUt#6{^-7Nyr%lztIkDt_A4 z;lFo^1O6pF2grF)tHajPC2j%>P%=k+!iOrl6zXvGe)QZ4U&abFoN|F2LmjS9s1DaX z(beI)PSL3+J)Hv8VM_@qqz)-t#-ePB_yUp0j^FID<2Scv$8Q#PJQ@?0#@I8X#KR$Swo$o`Kfl%T+dmp=c&Z@H@0)SdZ<(QeIPx4V@y|@6HZr@2Siy) z@l{|;9wT8lwA7MNfUoZqu^vfJtiU;|r6duWvnWl;qBItZ(j4Mb?WbKG{${5*;63R% zKu&>L9k!O1uoEmmNfYr2-%g$Q`A#AEv+0o>Lnq#uP$%wAVrR6Z#5$x7ztbr?eLFp! z0@Yzli65j6DJ#XItObjr+T%;bPrEvt{}f=O6N~Mir00M@b=Z1zImNzP6jg0e)NR3f z-BJ!%jcYWzwa&S)?xuaylN>&JI)l>YV}*LA+jBNTH=WBj!?hJ`xXU#>&SlHW=^E|qcdU+JsI%K^;;p~n4hr>3Iub&`t z*UBvrMc`eG#XkvV$-&Cl7y@+Vi6PFf!kD|w;oWWYjZV;VVny83UY?7e5tsaY_3?A+ z<3;M@CH$cwoxvZ9IJfv4Zrl?4K>LwOzMsyf?Jrfvveg<+ci>Yx=L1V-mHhARKDzr( z9MH!g6Uz)w6-y}OUB>BvlXTz{PHw8>aLpW!)jT|1AIFWMA^rH!P-dbsGDT6%I4yRf zkSo(^uemycmZ?SjQNhEt`beQ##j|I}3*}68s*IS-G3p>kM~c)ch?b_qJ9!+r5<;Ez zAulyPoRII;rfX;~gM$5&sM+5;T&a&|j@-Rx>z08nd>`L8Z`!tHEuRod$5V_|D^q9_ zqeG1KC=Lvz{Y)G{SaSkF^?6eR$-$TYj01i`IUHbZSS+})vD||?gS|9LW#dO98c)Gq zJ24!^UNmYj1FMnl=0udEN(3@acC;BlLX3k)h%aQ*g}DIuC65zM6q+OosqSexu{Ft? zNRyB{vYtXHW%1Xi!AjK z@jDa6e6?aXijz7VNmX3>co~!++QaQ-*C3+lGhcl~i$9;OJ_1TjOn@}NH&RNZ82auC z0AJZ&0NwfR<^F~}oVqfAD`%fZhe~KjXlB8gvxrf_EJCUihZ7DB9mFJ4EN5`U39@L^ z%%tWc&AnjdQYlj|48>7^AZ}uZ0eC}Ap@JZs$J186c#fS!5nlEUi_Iy#9Ya9!XjKW!) z^yF$aM@kk2^yV>jhl&%#1~#j79n9>szh_~MLyLkfdj|*Ui0r|^wOw6wU|rY2?ActE zOrYNGeT7n~lEI1PrIG8pjZK$!H?EMVAp01o>9zcu&nk_m!|6Ux)65^!#e#v+SUkyQ zqJ2bNnT!r&Cb~ET!=`b1qdviqY&cGrQwAV}pZ?O;qj9`p%y$G+{YiV}CP_2WVmE1Y~ zhyI2=b9#5coc`Oq`T}li_S({(cKMt#mEgy+o*Nl~{Rk@)ngA2wefJC=y6@QjJ$o_Z z^P^d;GyK2OdbU=aD3)?nwHDRQXDL`#kaDx)062tQ8GbKQF_E*A%~i%TQAXvs35vD=oxQkxdC?>PYP zrnvy`G6kN&R4u@Iq2mtF3@M4Z!pp6)o9%M}?^X?OLirHNCW`i^#+B+dP?rYj^Ba_M zmD(r3Tsv_v3xxKPUo7j2$%ah#v2ln#R=c&_SOM!>ED>-Px~&STg)z9kO1PV`)qprJ zH)|Sho$JPH!W{+!oL3XBHw5crumi`R`N*v2Bu>`}OE(*f>*SrAoDF`a*W!nkLwQ@G(0YwcfkA%lya{2tpi`X8KicJ3|6vG<{D&rSBadEX9SWyGiONpgLWY)`ApYfp;X-W%9O)sXxSIaM=OQl z%E)x6%)b^L2Jv}sdc)epu+c;goY|Z0v_vKOjwLkdhplm zfj%kbamIH)7KeHKfwf(KX28aY_RcQ%JSMTTAp$$T1=v!%3%hx>L9vkfmCbI6Xg0-s zOz;LH1|E#nK50cmcg}#$%+jJ%N1UHdDVQn!L7Jd*Id~SO&7yeWyGFg9y1r>8ekqZPV3N z|BIVQpsO~Ux(YuCUG<&zVlV>yZ_hpWS3XT`SF*O!TbFEJZL!sg)>vKcgAzSIjzEu3 zXMwYwPV5ep-ddu6myIvJx2=Y)Yh%%^BOi6iOn3=09u~%~K4k6S^yG1H)V# z4iII%>ML|}V@s!aU?Un%wU!AY=QgFm`qH-PYOrphO`fHiK z(^~67^I553z7T;YpYj58tA6Z0v}cQcl+FHSM6)d^E*h^_acz_RMuC$;Lqw4MkK0A| z6vOI-;(}-EuDy32zb9h7xbTpnxfbyok^+nAp-#Bs=cD1a*;+f4>iS9RMErk>A!Bd- z&EI6IF8m;re|LK^7{tRG{A<&q)YaTc!N2UT!tm4>n_46Ejdj+|wmz|aTlPZ|F}Fk@ z#;2>m&$^BOa6lx)Y(%afa=@i52gtmeijrhK! zdyhq^s|lj2*U(z5UXe7Ybc*(;)1o|xjJGL$HJ-LjS6~a=M0`_go}sSrx6oEEZ!i8L zfIruH;Nu7K=$IN4uWb;IZzyclpWCviW_VV0bay5ui zx}6B_^$~r{#56=_>Le%0B|#F z%;gIkGKE}z+-?rhqnyobKgq|?IC0|2ESdZ61^<7$^ZfsmU_zLR zsu9UX~a(~obB){SyRKz;K$E+v|gpWM^5=w)IuwI z70L2rJHyPVX>N^ECGGBphH|y(a=u7T47Sj1Nps{xuMM6Q4uLdGmfsh?5cRDV7Axo_ zN$2;SkxgC_(PZ)o(sK8bXsq@+;f_{GAjg~t4FOI74i^hr=-)UO$XLW|)B;3)e=GwO z;B&osF5u~IE(t9Fi@i}tiXa_s<2$t4(Nc8@knJEU~xW^ zG)pdDpMp!(PUYYNA(+2&XL3c-iy0IzAtWP3WKX3$S{ysstrcYVsgvFMt?pA$V#5^_ zF3BMuZIaT`OfA+EvoA@nTm-#*D(%Kt;3!TlAdqUz!l&}k^#B*3B+SY);#l@@T~J6FzND{q<&w$Td85uBwGPKC@6N-AZz zzS3>u_4;IOM}L1E8n2cu7V4wfN_DJ%ygpItua4&Fp2+9E|He zRd7URAw%nautJ`);}Jz%Bc>ZyVgU^}yClCf%c8nAg&9^2HoVPpHK)0KJ0joq%(2 zIh0k{Ba*#`$z*tN)Be4CR2jQ7!QoP|_lG*_{kj}IJ!Er4W1}&uD0?lDn5HoNNem1o zqPMXCSG%(fzZ-WAjG*!S7RV~s-RHp%_!LLX0Owtx;NW7XB`)y>PW^C=CBR05$VZw? zz&DHyg*r8w*U1;XY&0#DsR1UL;BIOCaRhzq!x zZP??pDn)rL*_AMVV|56dd*fsMtW>4}?d&TF(N~PvUuy)1x+9^9M_K@fL?XVpVD7&T8I4ZW><8 znQ1NlwP_d*LObNNScPR3;vg8fy3?WxORI2DsdHMg==Y`03TQa7=zTGqf~s(7tn>|> zL1wpU65N5?aNkNaI%mf>i*eT?7)CYX z|L``fu#NKsO7WJ;Gc4{`I0j{OYEa;)48iQ;6c+P_`lqs@VwHu$r>9G>eV%Du?tPJ} zyEp}ZGo_5*p&B0Of#TlaF%J~S6TTb#449Mq(I?8)8Vj?-r%>N5FO@qs;UFU`^Yy+>YQ8_4yy8-B17w_#e$y$mn1PVY9!Hb*sq7`QjKmQK1Iq=1Wk+ygJZx zbfO6PAkZd6gka9_TFaw_iR_VLxdP6JBFs6b0+}PI!FVM@n335Tr<}{xE4&`L-)sOL zf5!G8O!|EEtXppT{i+R)%(Or6{7ic|oQYJkr?FB<$iZ595E(=BT*?pR>Zi?s2CmFn zUwWRl%U^l|!{HeVbfSlSKv4blWKr!eK)}-`V#7XPZp;jFkFYJIu0w-GDJG6 z*;;KTlj(s<4MkpmxG;63SSe32z3QpDOa=kmv3K8f+ppWZXaC+^+hL^&qM!-~vVaW9 zWHw>|gcTX&%5bb+!k6`Fc3eeaJPpN9ubaqLCcU{Va$zdnA30sLd|xM4^a}VCf;Gx- zOFewj4t^ZdL0ju#gj}wNon{oIFc}T{^f2nvv9D6ugLXInMTvSueV0HG1!@RkePN4fr>QqD+rF9+G}uoV?VMk%W4D>AeV z$zt7?*MoY)0eSseU0xr&2O@M#a0MdK88lwxp!{HAVJdyJc(^!S$QQFLsEmKD2Lz1B zZy~abq-LqReghy!AvFu*(^ zsg@-$0@M3&6%0>yfH`mje+Vs&RUofDE6ZDZM=6Pey0}kt06xHV``~C6mr4Xz0(9y4 z2mru=<*RP=jfN&7G2sK}wXg##FeiXc)-5`9eF3jVy031BiV7zO$4Eii5d)HmN|1qX ztfK63&MXgp_sigSa|YC7;D|F|do>0=XvEeYI+RfO{9=BiW=ql`C@~B_0Ddb177+j! zKr{dFM&lVpDHO{z1Im$CJ^pO;#>}8t#3w0jdLkj>Yf3h94;$1ct_h1{?3gEKsy;ai z+l27oz*3%hJ!Mwf;lgwcjywaW4thn46>x)2mLU;pNFYPmGHR=NKbTR?wmV2P+oT3`w~ zCWR@2FDX-el%R`k-t(*g6P2q;-N&I}z&?}r@A>b8V#2jJhNyxE332V4TI1S-yTP(n zXMPZ?;L89jl3BJDU`k|Qp5w{n0j8<u|m&OJ2c6ArHkvNC+%fsTTt$c_N!e znWpe-ILHrEH1nMQ(WGV_!y7rDxP8vOqPX{tcZ>&qf=ynZD%M~x9a`iY^G*t!G|omy z)R^gW;BNDV-A-!r1_vB7^%|TUnC{s*RX)mp1ePpBGcq@TeGOkulgUW9tIjRnSw%84eZBA*ssL!OIwra>A+{NIm zTB7EsyL=f<)}0S5L&f6U8)$Rii)qe+d}{yzKD&eDTOMRv+P~p&cB{kLO`H2gH-@u< z4ab{y6avEm<<$Y@X>-f>MUy)*`tSjHVuM0pIH0OJpek+d{B8{B6h=6YQH=cwP z+*`vHoZ5N=7rKK|S*golxequ4ES(kE-@@YXk65FQH>D22&ew{h@cO9M^=V@LfdL&E zGEvhBtIDmW8}0l)fQZR`Z>N+x3P6PQrJF7~n5J zpB~8?gcIz&jmlLp$V0OF_?QDGFf%M$&gZ*Thte~1we5A7&j(;o1kW2(ChuJ_O=P)=h8i1K)u6&}#CU%tFqrG7xW zdmyH}wipG+AsJ=3Jvyo8bSQ6mxM+{y~>Di_7 zRSy@8`C-`LQjp1im-WD|J_u}AhikcM*sCWbC2XRDoV;`?J2kZNvdb=APgyqEra1!n zsNMR6ygS(kVO2G7C9Hr)Z$sc+;KTp%&|HxEY>O1A{zWqLDs8Bfw9kY z&&}m3KjD_SVVD=iOT^R}6=FBC8_K7P_+!cp-|H0Rz8zrGYtc4nbG(GA*mx8RCq&i9 zBd9vQk~k;4V=`0jm*M2WzyWNHTQZr;fYg9>$4N~Uj`m3#NDw(?ya(Coa|S$`DuU5n zxF2v*n2+0Qb*6wE5P-$|Ei=LAD)q&Cuz^k#iCqj0OKWFM3_d7l;;*8>an&eyhxT)y z8v}!hT$5q#WcG6le5$eRHurNw5PMU^>YeTNmOHv1W-R6hum_O35drKV0tMHOirAt-|Me_lA3 zQ>@2QUNvHu2WN;kHpbyg=B3uLVO;qUs%=goI1$!)}^L@uss~k;y_w9NJ8*Q z!uF&h1U1t=9(@(**T{9DciDNU1qNf6@42L#J4w0j4?4wlzsrctJH3mE*N)+zjtD!B z63_|p^Ant(f2Z^OYyz!GwxK!|Fn5*;S5$j)7sy+l24Y?N+B)iNX;pNCmWwAXK zQd%%2Wj~ko!oTUj2O9QT+)-ZMDupbSJ%X=7^1E&Fx_d?D}`PfMxB z_(H&G=K)7W?_%+sGRndO(c-EtR-FqCOIF>JESl&Du%jq}tIb|>yXefA<`YBEdGXXH zGa+ug3C)C0M9hTNJwf1liS_Ucn@G%$GI;-;1J~W`F|0D>+)I%NQOmdsoA%|k%M9T2 zVj-ipTPr^o5cK2dQ&h>o8}F?m8n|8q|CO$;y#&i4HV>vdp#6CliQ0Nhf~ z$Hap|xaF2@(cE%7_8-G7P5M%}CH8B|EqCbyPsUkrCnE~CW_4~sTo7)-&pXU5pXS_h z8w0Gn+_DF_WvX}#(_f}wgDiv**P|AN!k=C|v79?xsD*J2+kVB~Iw?pdEo3MC%6h8M zc>u8(#YTNC13}qoT}z--a=tW%oEE6}&B+HD^*CFt(}WP;tEM1}@EQKT!+iD^oX_rK zkXj734XN~6LEx8w&B z#%5DL(B4q@4V8+%9|V@nFfXw37}V4d#sF9WL8pSJ(AiSp%!uYGDSsTpKibSRXV0I< zG;cvwUq&I^a*c5c!BQLJTOER7DsomT6ri0gyCqu8B{td^M^YRyP1rofk@Q(UFIDDN zTW_2ya$qo*n@0uIXtehUW_o#_kZ6;D!%r>0>Lv}r{_1NdCONmB$$joFk;#pF3`en$ z4b&kRD`fEuf-0qY{HMfhOef0%et!2Qdc%RCKM6xuZ2W_3V5=H<<)$m(f?$UYfM*WU z6Ct;*2piJ?>3F7eWfC@uVu7u4MdtWQ9PscBZt@y0V?`eL1+*Yh1({5&!bBMhad8hJ zm@u$=Gw-aG->hW`!jS#QOYa~{fHMRWjf+r$3*3pYu?<5+Stv(WsTFheQnn&VfN`VA zY~?Vt2j0U#leLLT9owx!VRhzPWZOGM0Y%n0cqdt{iM8XE0&MooujTuP@i(~L4F_GC z@to<*{yNxuqLB6MgKv@OdiKG$CWbJj+18N;KNM&~a9HUK6>)^&uh#jp9lt=B^ZE;1 z=Fl0SGkjwfxE;7AP!^GMd9GB?7o1F?T!Ms(8f>$Kpd)V4WNz$CpcE&oZj8Qd7%?wN z0^0a?_-}Cc?!j%_;Mg=^+4XFvpKyXtLtgI`u&5v*?C+FS9mOp2*i59xpBD=wRVO#a zpjO*fw~&pG%B}e@WZLAum?kYWl)tqOVU_y$G#$$n3ZsFYLMTKBxGX?C+C{z_16?hN z9pD!VhS5lu2YHPSw8!T{+QE@-jPp_}#wTJT4iT#HV7V>k=@!MrXK#Q_(nHQ|Q0BZ2 z3aJYErw%9Ivcf@3B=913VlGSJ45cb7Q=kS}IXfm1p^!S$UMMiQ4rOHoP+@Y-3UUF9 zpF7!!LKZ{>51Wb8&qUDz`BX{^2aR^V6P%evg~DMJRIEP`ZEKyq*J5?M1KXXoo@C(; zgeU*|jtW$cKQ8z~S#7>DSr!k|FweBeI;)jh*pRd5#Va`(Lcbt0;VqpX&Q~Iaqi$@u zgPldUt319}*uQDP=GsF}h+^c7*9k9D4PzR}_UGH`Os z#=)EFr9mXSv+>fQ&6|cU-H^WO%FS0^d8s@k+n?5V0*}B6Egp-&Q7v&S7Raqq(*NA2 z5D7eV!Kd7>brKM&ZNHc-0epAH=b>S%{Jk(~_N{Ols%o}zE~pjUzByPP8u_ zS>Zu>FZ_x#MF_~=axHmiE2japYq#RD(>LxF1sR=Gu9U4ZGfD#6H`_Q<-lyr;vo_;+ ze+1T3?uY1`#xU(IRVtUK2b{6&WU&N=$*T|`9DxjdIBZ@d7~#7dt4le&@d_`znsOh2 zfd=T@*mURB&#ysksUfGAjkb5ofO9o$p3aRxfy@zhfc=o;ed6?P*#f8O$#^Vt-!5do zqvGehTQ&EWPrOGc2<|K3Zz3n>DupN4#k3Z+7Mz7fv+hHHMSwTVSN8_&m7Vv8!0JUF z;yB%X3fc4va1m_#cCWFsbyyp>ub(JS7S>M|E9-BrlwGVlz5eEz+C+J3{eeRDaCTRA zw91O?^9xLq^z_V7zMK>GHOR3jrgQHFAa>4$3H(=Z6C~_X?4!B3M z2qdT6uOc442A4u8sx>_Q9e&S{9)c(LN(8|h&=bmlR?rzhN2R_bL%ZH)XrDz;KiB%u zzGyJCZ=OzRHE1-O<;YX+PtK(6EWmc;YxftiZ`s`CKOo3DWR5I%(OFF3%yj zZ)QJeO!TPN*e$Fv4GoL9Sd2u3`ktXeJ|xJfcNQ6UcL5noJ>3wAkC0CoN&?RbRvzsv zR*rW8D_$P1R6Ocr(LP`p@tzWVysNYL_^mGBV_CpjkbIKTB*+r^mHdRO6#p?n%f~y5 zmX9#BxVM2c2bnR^O0u;@1N=fkt^3VeXC1jSe4 z-)tXHz{=u?ejYa9ZNLXp@>KXX46i9Qa@%sWLzxG}T0Jex+Do<< zaizuLCzSb@A?O|qw5qIou~H`d+*Z0%b3)uRu#2EzSS%oiDFr!vhstW`&&(jAY}h~!&O=n7I5q2D2#qxsBTK_taJC_qW{qX=1deut zbK8ow+2ia3^qZtD1?`&m(a?DB)1T}?vTkd>LQx6hg7<_Pf@adi#@kJV2h;r;w+0S+2UCHT0 z1y~LW)04P)t98fm8aim!P6{)RDll?k52aky*|vaxH}HZi-#|@G79| z$1gmR2Npuiz2M;k)Kmm;an^`Gbn2GiLl5{aB3lkdVy*X$D807Apkt2`4%d=_Q4#KzTIH!Cpt2U9Xqa7t0Yj_6K!c`cI5=Rk^m zi7SU7 z$Q?!yJd;5+br*YMCeA_mlxUG%HiNM@c$*JKHA?5hbd0n}$xGE7B`=vR%ASznkD3qP zBsP2(G;gLawVC3_BJOCvG2akvPKYiVqV66TS`)i71YmF0XPsVL~SGj73=3fw2t> zJ4oCJPVu4*?q=1@MtYg4Rng{~!B%7B?WE%5-27@nRN&^$IJ(yI)8~k*OQ!miAR*6qYqv^Q8&M*5r<34rKi5f6zT`WnG2g)MTj*sI}Z^zIUkFi{lA zU>LBAs@>=L=rhR6)s&>K*Fr|-eg{YESxa5iYmF5OBB;a>)7ST{ga99{8 zZN@|H|A8oCzLkZyqvR8CqcaH4buY|Hw~EgFnhFe{n+uJz*y@_ynXImv6e8=p2*5%YQrfVodBKMrut6gAN$Wm^i@Z^< z^G40?Oh(-`pF-d6Y!1pH^Qw0{*dZWrDrtkAr(5tS2Cj^0woMLX6w^dVJz9-}bI;`E|t3>kc@6_SK8d9bUsM)jb|`Kd_#=2qRl|@d?4#i_P(6;$*oOng^r8IBoV(3$P5*W(8Pk+Ux=py%b~o5kc9TEMRLtb(Vu{ zVvlIz%y(BEJ;{!3~uTNQkWx!to zEIa=Cq6KX2^A`uXv;4KxGh-y{=*+c{eIws<))LPMV|~{GO9qVfoF!xZ)B-F6#u8wu zj5QxDLy9u?gdl9*9nr>HgbCob&sH4Z&azdHZxTx+gz**H&GNnEEB1__X^jP%4EX9y zXx>I4_E~^sz*hn+m9G}yGK1obKO!i*+yb`tIg5jwC}*|RnD6ImZWMOW&*dHliPXfm z6#}rgI?!-(8MN1)Z%f8+5HjxA$|DEipE7=f_nPx6u!7*ut1GbqZ#^30ywc-0m+JAG z2RxU>`+j{Yf4PG@AfzMbL+cLiPa!#2y5OJV9dqlmJ1Ymbj}CO!b|yS} zNrVgucXKxvJ)JG|Qi^~!CHGzrZ@e6eyO?;TS*HXc4SM{Lf75Z zUyqr~=I-j}Vp@xm3w?62UcrU~;>OeE+78z%xlB zu-%TsIs{?vzaj{c4(mt@%fb#@cqjDa*|AiMMGn^9Y2AFVs?&OZ2gHF~R_d`m5x-PeX zD}g0F1J}eP(PW_S<6h0juKKtWiks}UK#+l(XeS5Wn4b<=fMvi>0xXrET8o>w7O=I? zQyk>Z@>B=nCNH%>mH~gg*pk0qZ2^`6e+jVc`0H&Ju(i)$9OTaOSCVm)KefP;0b_m8 zlCeHx0hR${39wYgY9(&+v;}1CvlR!pvuu@U+~l7u&}6_@-?ikcpId-sz*hn+m9JWh zn=JY@W3xYjh#UvGvz&D%RDch20YqE#OTAynZ@6U|cuow|3oLMFz;0`xd9de~pG9g@ zxhvssvf7wCMD6B53$V_DMq|spor}G)4Y~p><5asL3$P4)7XmDGg|+~_KOQ-ix>|ny zH0BcJ-x3np=^!%(12FiG|ED z>P-Q_WG()tIK>X&tKzv)iaH62)S2k+ zrfYX?y>4fq$Xi4t%s=W63cg(|Eyi@j*J;*j)Sf2Ff0RfDrPA&cKkkzFm%E^aM$a z&DqYDWZDT&T?#-FX`_hLrKR41xv|yGCUGb%eQ65sSo#vXGf7`!@}KNV?ojH|#%p)o zvfWU(t!qKI-Lk#Is_oop)dqb>YPJP9Uiq3^Tl^8xYcD74NY!tINN%U>=u7qP8slBj zYlsUeTC|h9=3XihWuevHq>m{{t@b)--bSnat_4^IT1|jutkwR+0xScqCcxra?NX}M z@SQJuDX(kV#!jn+@VEOIb}Ly=>*oP@o0wK>A}W|t`)lYhMyYWbA$8i*@Uf=T0t4bY z?Li!2r*#_bgzK~bBnj!XXK^S@r#**vOsBEClT)W%cl*{oiR(0M^hD`2)_1f{3%(XQ zjXfed?cWJI(s|wio%S=myRPUojtePRbe-m9!CC0Em3IYabW12SS*b09=52J^xfWm< z=rjSAu}U zwh#t)UyR*K*3Qa;|P_)}&{dPgK?jtqa zVhN!5g6lZ%DbaG@A>7$$%IQp2K&(Fs2yM^pBmM3t@5hC)llIJ*}T_z}v+1 zTywF(G~EWEL5!yJgoV^~8{vCR*9C^fb=|iJdOM`+XeV6P1t3XC*KI{6WxDQKykokK z-JO)WZo|Iq+YI&GMNPwP&}N5q+?psIhh0bNxA}p$T(_|&M6cb6MDwgJI?+3@db>^U zt})gHy~Z#h1&gZF+$-UzcB$Q)(gn?G~|H$$MHq``~S2N-bVaFopI`=r2a0F$p1+*}LFdO_>FT z!eF%rbl-c8W$CMenJ1LdfrrU0~@qlUeNOPwoYqi4) zEz--tJNJa~6L6MG-%DoipG~=WxNR&X?}by6KO<`GON1vouGXH^yX%TmQeZ<07gez} z=3e1j2gZ{6S$$AR>a}k|^EP_zpDn;L&}#xLV{HAq1y}}pO@PJq+7(o<;X7XdQ)bun zjh$W#VQ}{w*sWwet)IVyw~6VsCgS3;`E%yZ!TtGJFtLzq267i*o6h0#D|nOx~kjUhN`T@70hY0lRdx6-irY06WT)yvINaTb-AdNe`gsAo zO-$7_6&Y+5_e$t8W)&wTh17Acg3mP_7Z?=Ral<%DPn2{>$I(u>jtfANkdAvh4uvh` z-hp>a$FaMUQpa6Zn4GT7j8yZ6TCT6DmXi&4SkF08dd}-VQqwI_KjFI0e@wL9M+l2{ zT-$v}@2+vU3);@di4;1TzMI$E+lIn>N*`E~3h#5!yp6*98w;=u6rKRfSmAxg0xScC zC%|F~56Mb69$)%GnR2|QiR?692$#E`#cn0@Y5lw(-X^B;S`Z#g=grT?>O5a!NUgU3 zexPZ+z`(fH`(uLO4rx8w3DX%))b~uX%ZCKxJ9HE@)x!og)vkr+ z&FYwFo1^{ezFXRF%r7StLVI@@ks)=C+r@H1jmSlpm^w{L4TTKGqoSre*TE>0(w%Mz zQO2}m4esJrgkmH@H#Q=bu8=Byva*a{sVG1mt~pcKxhF2-G^bj=<)R(@ypkGJaS=7& z3VDamIyj%fsTGdZl%g!H{e(=e`v`n3iL;hUt+>6|FlSVbi5b$9*^CnwihslhMJu-z z0=RExD=eBU)F#UL*iG`UMR?ircoy%Np}_8}3>a?Y0rijxI1gW-~iAv8K2Ry;_0UdyUwIs=BJ=}Gnp4-Wqh19rkPwFsQ3Pj z&SK?n_&|)Sb^enDSO(QP1z2iX%+}5m_?ZQ4?H9%5AZvz{iL=AEVmW`c)tGO^hKL*Y zV~C>@V#Tg)F7RiYSh67l@+5_ZvvW4Lal-I z8)EY&)hN-(>k-kO)!vduZp|uwx6k+-n**dLGYz3x#gsJMDh|*u39EPq!pp4U>+z0R z#q7?`D)#WvIjeXJuXQ<6W%Vpau$HBnb-cN$b*%SbVkOtRU?qn@Xkjg15hX(O=2HQ5 z#~90}>A#f59*=Q_eL$vamQ0|QrfNIJ^C7*v#)%|gs1dy^fP4>~s)H`{Bh`Km{fN2h z$QweDV>*gF{g{9yU4!P$7m|zNHhw8*UkqaY8Je{?;dJGm9r=U>-#^i{~~N zabgzF+Yo)s;(0gR#aKLHaza`@1Fd5s%mNCKkn8L_5Gc<&FtLDo0~Qd>Q9P~qXt6fY zq}FoFzarD{y#&gZ1Y>J9%jmPm}01AeSvSK%~YYRx%#Upi;RuNo6Kxnjck$@ zSvWKn*4OrMbfk=qK@QkrN{Q&kraP~GJ}$6^oL+|D-Yo;p)%ij-H&QK*k5s3#xx$d+ zed6?P*>Xr47vd20h3t1UH{(ahXcWJm?l3Pz{jV{tMcEbxStbZ<pPo>n_RkBS5t1wU3L@$wqAbs{8LItJ z$IXYThT8{?X1T0_;H$s1OpR+i~iE>t3jrs1w=0;%`)BW6YfI3YAp&|)*2&5twT;2xVS+99ubnNp7W*vBpECy*@(i@d zBXh`N>7p1=BiDsjECPO-H$B6Sryb;ufycww0U1!zKxttnj5bDG1Q4?49-8ea2 zDohrpYCOUZ!TqdLDvW1yGfuhUT)Tgp!`JOj3Y>Hf`u6%{j2}JXsqEpb_}j^3HfJ(@ zUYe`$Gwn>U2RaL{CxcVGoCCm-q|ge3PR?#VgXSumareeF7%^8`n-mBsAfHX!d4M4@ zL*s^_N#^D*YLD66@1W?s7kDp<8!TG)vwEpuX4t15porF6cYseLIhgDJZoFfze|Bf( z0Qb?+x%36!34Yn7n=G8*0FZW#t0+)y&j-LS07*r9y z^I1Vb(CUi%h=}w*u^Fnphr0PtPjV0S=gskD;-UUaXddWo>_PmR1z08vat@ZZAm3A- zDo{g(Co>Zk`$r4d5?GKkkRvpEs4b*PG~Yx0=Y0HK@KFD!1+okrKEL1tG3Kx31rSFO z%g6|c=o;{s0LzZQ&bEN9eg5Jgcb31B^iXfIz>)!DrJ;En!SzB5unZVWfTc24D<10I z7Lc{iRvh5YvQ?rU>M;v68SvGpC12Gnz%t+~0hY>Ft$CntugSb9*0a;goE1WMNy6K_*lbG4ycF05hXV_V z$DqH&Jk+0u#>_p`jMJEhnsHxZ9%`hznZuzw9%^Mh9rQ_lfKVT1kLsb`abwLXN+)$y zdZWcQGju`2t+P9ubN22(=u}w(r{a~qEW|5)O`EM!7w&Up5Y0W&01;i_%~g)8`KOo$ zBj!Zt>PwK<56>W^faGvbblfmB32fkr?xLTHi)4+d-a=hHo=A4@gBMtg{Q>wF0&6jY zYAl8zNu^k*&K`pAE1A%6V^bT=alGFwa1Wz@y1=(J5#iM8op4i1p&$0e=%J&mE@1?m9RX%^=(4R@+Oj0^Pc(ffDkr!d$C*T-`4tB1#jE4 znVEIW5<6ND9&9IA4*G0F`OF)>z!2NN+&p}*ncRV4aru54j= z34*!y5CP7mp2&}_TvWrMtb-MUTgN*V z>!IC;yivc@8#TK#8MVH*NgZ{{U34q(-_lB9tN@#ra|Iv;K}7IX)_oZ_0v=}n2&}vZ zNyFBsSKS169@BBG+=S2AgnLfMN@Fo>Z5js?bym(gVWS0K#P@l5Y@hQ?moe3Hy#h#Z z5o|HO^OwK~E`ZA(*J0NS@xeuK5uvdXU}KNl%ig8fwU1r<+4T~*x&wF_gbO4Zr1?MV z;h#P326o-ZuAA`1Ja;qxv(UYi|8p68bve6U0oO;|E8*&1g_j|`yZ|p(<7F5xTfAr2 z;N1)HvK24a;^jKLY{ScTxa@Ivu= ziMS3g_wR?xJ$U&J{`nkU8rb=9xYXUF0icdEfQ~a@jx#`xGa!yL03KnTA7>pOci#=a zeuQ;%oOSUCYyLQE`gq-)5zVq;vboHL`3f8>8|E+Zjt%n{IBGV`H+#eU4BoL}4&qpG znC{o`?n=BH#1XP#-iCKoI#qs9TdOpKwNaxdudW*r_56}d{m zj}?(ZWmjWiu{sGQ^BxhCd=MID0;_RTa=RsEY5fn4KA<2%h?Cv zaz0+ZgqLUVa@p;0c>!LYz5^~_#Y@j2xU9s>19*8UUj79yKf?V4FACVdI|sMrTm{?=l{H%|8t!G^9uL}W^V)knd3eR|G2M$ z3(QKCM?2?Le|>h}tovGcgiFi6T^7Lws%K>Vw)%9bn9J4*%t2Dj6>Cl{TNy9ZoT=<2 z?EhRFoQ7+?#5}(G-`woi&p!B;;P0P(@U2SX+NTjSR3SE9k37V5E9F+fq;G~-oR>a{ z*dC2q(u6g^=3ch3uv9owD9!Gi+gMPWnFdAo6ToF-QBdtQ7Lt8!6!~VSDDri4ilF3c zlOpq>2{fx7V>82jJ^ZuBeFOjFP3#YkTtJ;U$Uj-Q1af+O5jqj^BIQofH;u)+3*f8C zRpm;ZPZ#egS?B$yhwz`_9WlX8_*XFFaU23OHh-x%+!$_IcIV5v^_XeC9!jU;P|}rZ zO^E9SfGJgw{8WtCf#20J7nm3L0`=`x`^rvpQG->$a4$bA1y;>vO9f{#J2h3Pq2ZLa3bfa&RM-M{r(C)iZ2ESegu7SOlmV8y4=Y_*Vf zGB-|*mFmZwt0!u;>FUt>^+%5$O&8fS{3x9(Pp;pR8G)|yPUhxH8LPw=>Q(>yY42IO zSmvKrpgM1Tdb(VJ`edFs6nVEO4VZ~HxobS^;j8D8lQh#q_5oaiE zf#yFa>oXR?tXGP&?m7g+eFWz#Gp^DAAgK5th|D##kntx)rx6)1ZjHCS0kU3u{P{q; zz9L~t20P-^e4eBxoqjD7@@$`ww1q9+5EUBs_}^)Cr0*hVd3}qtT5P1lX+4F?9@ z6QZy-UWXMa3(i#GD4wK&D$c1_F&H?+HY*Kf#5lz;GpevZJF)>fU#4}?JQG(7qn{bk zxrbzBPl|gFwjLzF3JNxb<-QnLBBXFzaq?r(pP3czCwQPOMs{*N42>Db$s5brb~!=e zS$F3mGyqw&T*Z`NDu4HuKWmorS%ahmR$}sTuCkJeBXdG?S3p5|J%qI{>MtD2Vz?XY ztmew~sT!D5#i?Sgm@O6WVVksu`aO=?LzTY!F65CQN3Ct%8s)Oz#TFuLj0i4^i##9l z6!-5i{981^)`f~BT)}CoVe<~)kbwDr@O5+N%wZD2**&w>H(_}MHt?WtsK+c#q$Vfmz9S6H3Vg*$H4#I=jpHda1zL!SC>A>1;kf0*)AXp5m|j z=zBWfonihfSiz5gJ&Xc6#m@(#-}S1k%v>iJMKnM^PqX^Hg%QC`skM_c;&$x-I1I+C z!}s=%mCLAin|jeg`vwp1_RyCWOn)rJA5_sAx^xxcTcr#R+}jG!?$GU5ym zJG~<#liA|b$VjiiMVG_o+?? z5%XSM(f->0LV+z}$Lgh$BV{10Ou;KA4b*Wc=2#zP>&OFz>f!9J>}Zv*nnz1zSUP8` zAbQt}-&Vb)H0+8NtSc6dYhwDMvh}GL*{ZGIwk8HA*LexFN6f)zVg_R(<^46)S5QOn zHI={KL!9ZMHA@5fym0nWReWQm5bfxdU}m!7ZTCI^c`ZL6iwiLfKX@48&rxjL){Xd8 z2f(*kMf*U=dC8ER(E4jax1S_LH_eRyvEFcCh-<;t8DB}Xv*(;kxnBlvUO;a*UMx-N z>$COoLI!HCmMbu1H1WYQngS;k*!aB|rxXT0pxr`ei2Up_jOcD&8! zRcC0dK9w8FR139?IDXFo_Y?fd1O=zKXwX|OsID@1@dOAZZeXRf1;7dlwMQ1!?qA_I z!b!G}4U-CsRrryaA=Z|;za08Y%-lZ*8Z$Qc-Pa=r1&n-wmKfXqB0iy)GT1pTwGG>k>?}wPXt>1+|UgS zixCZn8u>8`zAeyLfCCmVKpM+16GKEqz$RD>e;&~N z`U-~1h=xri>Kmc403%pRR6t6cL=EAAun>k7`KllqBFXmwjePLAO1=+vmwfL_l6)Ue zgnWP$L-H*Z3K66+QG9VEOi1wwX37|&v33%qy3Sz`UGdL-!UAEu6 zUuwlZCto~Lg!1W57Tg75Q879Limz1Tq3&o^_7BLDQk609@;T9cQxZIfKaDW)H6ge< z1n$V$^g|ygF35ZQ(NY+G6azzq;A%@Z{s8(*OgH`v8ViU-OWhd6O^kZHn5#!5nv5en zzZJ$Ivo4P03C%hI=eLXz-Tth5f#lI`_1esJGr1Bh-K86=FqJ-9JY1YEU z|AKU<+RR7}zw~%n@#VSa76TJZ-MV_3-lNx$y6k?w-w>Y^OFb~@oLGk+M$F4j%!v!3 zzr^OmdT6ZuIT1ij%#`TmQ{sFEKga1@hvE|7Md4EOd8Uk+g$dl&e@5ow_88D2$Q*66 zv8<5m5fQ2flVc~L$t^H`4#T(!knK33Xymsq*S1&H_J!iobxhqvq?<~ z>&UzVnPaf7%=$luY_X{vwvv`Vn#>-{cu#TZ0in2Ty%ab)T@?)_ zYRUQbD7HwJiXqOoSH*N2G4X&XxrpAjygiDr$PvI!|d z0a?ZvrR^)iT~e*wP=vVDcqKcTaVmvr2vEV2vl?`+PRI}V$$`>E>PMi`Jstxqnys-j z!Cqu1ddSMNpZ&4OkF^Tq-^bY!6q`%EAJN(TPxxUM72C+-FPGG6ccEps5tIDAqx|Ps2tQOft^TKx~s+4BbaHoC6o3t-*jQzdf@ANb$WX79ioSCY;S@Z z2fnr^IYal;8EPqrJ;cO_;Y+v}-pZioVtC$w;>W<3QL;`Gu~rMu!`MSmy@oBS2ze)C zV2W5t1eYkrG!EDagtV{jGHD-8 zlC*D5gtP(Fm{D}NEeTF7D)srx~dF_s5)2!-iG*1R#lTFcKi7Q=NA z^i+Ia(8FheIAU2RA4rlnK0$e7KEgqh86II$fu#jK!Z&*?5310(U$ZVY?Fq7|qO;gPUP@!d3`4LJrPEIS<~`iEPc`$@*k#Q+d<{^8!|u;6EKLK*7U0 z#52J*feo)R1r(y3ED;sV6jACX?c83jJJpGDy_AR6j(FQhVBb_Wq_H1 zMRl+|Hpp}Ds@kqq{sqnw|BH6g%Q5%5_4M*JY?uCSv90n(+<*qYEm_MaXrRV^NrdjA z!_n5W1@emQ;y;V)U)pqlQ1{E*6wbNL2bH9~3%%1|cD zgW|AM94nx_8&CzW1Cck_$WoPE0+(RY3L~0emvj$m6|n}cLUB@niobFg?{P&_oPuUR zBC`!`>cY7X*SnA!4+^OUUQ7q{2bbx5xI*Yl7+9(dkJR;0hCwD~pn1?>0_xZp#|iw7 zx5qlmj$&?qwpOn|`3KCQftO76z&A6_WErRg|F2g8`!YLqfP=|a<*4G|v*Hv~S#`!C zw-t345Frc6J~R#|ouhZnS3&w+_L z)XQL)fEpNp3J+zt?OeE*fssJ5-t3jO@Yo8rBm!r^W{E*0vFtGob^+htkYNpj&!aLf zN_>=^%ntB!K#IoE3BWb8J5bSb<3Mzdz2%EgO2mi9M>)a_fY zT|7po*|zR}Iv<-2Y68#8LZrSE(|d%}Z_7V%F7%g}gSa0WYu`WNAtq)CyO|pfNGoB! z9J~v7`+vF!e)hpPc2Ec#%oEi}J|k3sQ=|A)O~lgL@`nT49CTlsxmJ2kT#p|#<>14G35@0 z=a_njs&gGv@I-sWpKHXO2C`!Q%jbY$^8Y3OPK z>z+A}#EPakRjp;Av@=h!0L%O+?CURs|B9|r(#~yY<$}=(iT-Hj($~^b7a5CaaSQ*K zFud6wH)4c)3p%zq;`5A~`=XJfu;y^U;4jy66Sx56ek@!#l%TdiVExBkbw`V^XcL`Q zdHDi=OP*LEVxI$iq!NA@JzxaJotwx`jYB`Ms4C}j*(xSh_S{fDit8daJV&l6(FhkX zrm%|u$*R;czD^Li8tq=LH;R{?!6(Rgb zk|n&aiyqe-4(OuoA-d=p5JdYiIfOXVQo>a-;OIFf1CEzh0zwsY96SWCJ(_x!{I(xjN(~PNsWqVP)|I zxAI09990R3h&Ks+fXWj*K$z-M9OEf2;E3_Wxlje*R#H9y58<)tB5KVsuy-(TAF3?p zh3H3R0jgmVi~nF)r#fA(p-WWCfAn*z?jBH9hcQq!IfG?*is1HReyHi`Lbk%xJ?OCd z6krh?Vt|=+4~J-m!@)gyT=8Hx;AR~w)+_9B+S$f;6`(?6y3Cut7|%HPzf}Ger7{sK zpVeo7()wfvm)=y)=whXDrdRThvFW(r)95OHUq#r1?zb~!g)7nkU2gtOvIF)D`+XT2 zHuJj0gwAh@z?o9muW|03xFj1A^72p*lRj*E4`054%;zSba;D(D{t!mevGQi_M^^!! z_~x*%(q_BDN3O1PQ|=!Dl#Tht{6_UKo0MlxFp)Ux{mD`f;p=u({dPAy$c`+SUjpX) z9mJHI<4+JE{=~=}Si-A7Z@ZR~%YRJf>oV-tEY~>B{`1X%C3?dFGhlzne7$ePT z3=s$$^)+VJGe2*2xrjo0`W{L@n_A1+McAMA!s!V?TjP$+K! zTAVPUd@zD`>Si5?=}KwlY)Wr%w%&XrxKdzePyvkBYJb1CLQH8XHy1SdDJ9IBm~QCg z*q`j=@Y8JevdO{Iq~{LNPVrrolvXua-0C>SLdZpsr1j#08~XcU%JlccYU<8P;qE#t zTk?k-cm$Q>SgIK;EtrRqPqBc4QpoO3<8Zmy(h0j*bVCU^ANrvN5ivj!P(GKgt`l>vvJla+L{ah}p%)lINg(~Eg@RcP0iXAn5 z6mn+Z5MZgTRF-%QVTfXh9=|`Y0hU9zh<894<4yW-+R^AfW4xZBn$O_%lrfqQoUjMB z)M54*@a2kDlxeh7mfY%{@U z>$mxM{tqRr&!CE~ZEQ`9n>g_jXphLbC6m#(vmks}%&N#Sw-9==S+F*Gn5Q1X>QHw- zNCb0Zy>YtV)JO>mAB=#V6iMoTV5BxjLSv=Ui-7tYmhHK*g5EQ?w8FYu`}^6lSv3xD z;m2NJ;%v4K@*Q@qup>I*ZS|xOlg~qp{=?2aD6sB6ktQuje+kv%uprHP#RTEgd5`l9B#}y zgn3IS1$8&ZOJi`>7NH&t5X#n#fo*h{pi`Wn_c3TK2J9=M868+6Av9&Q9z0F3e+AP5 zRDHx!1z@2eU0IlSQ1M8q7*y`>V9!yEusqm{*93E4ERo&Qx%+$iKs=3VfgykHzKbE5 ztB~hY6%syRqS^4*9cG3yXNKQma9Rwt4Q9BkzkfPgtsX5`#0u1Ramweo@+1t=6K#!b zwrEZ=hi-rX4@n^U{rEQLA^C#x&=+HfWr0|qhdv+RpE5)uth6f|t1!+bQ&`RFe@ z&qs-y9YP+e3Qp~(v4nGCepJg<3%+S5bd53G*0a>ek+xhGazPV(LFCDQ#PERyi~6DI zU+4|{ieP6=kGvk-3mIyG&4G~Mly%ll;~8jh3SptNHasRB7@3pJur2 z6b;Bj!ZDjXpRMH4fjgP?OV5ha-gX9?MfAeH2p_??IU+2ZEggztDo&P7MT--)7GGm^ z2zjK~e1_|R+)`bY*~OsY47V2 zqLw^>o%F=d?LJeM-d3iBOiK1oQuW`YSJq0`SiaybReb z;vDuME1n9mU1eSq86HPpRb^QQuIpTvQ=zWQ@Wx>Ow70!GJ(Ha*DFSe;2z#+b!e2~E z&0gf0p#HkVpjpa(FG`601fl#qo83q~qw_>#5(Dmuz^|HT^Mi3X-ZNXmlWMEEN_M(1 z!uDuE0`!ox@v^G_7zH_OB!Z_K@M!^4q**vv`9Y6phU=;7P|u*_mPgs~xNxMdP%k5b zV!hCkd^8P}9N-In=%}w~@e>^~1_N&PDdylLUr1*jhn^fTTzQ^Qb;!B1cjKlj(i`A^ z8!`Q7L+>FfU;ZZzoKJ4f5qaRUj%5%v7T^?>QZg*D^S%ha9EW6c5Xj|PVfMANfx|Bk zeg}-W15geDNL?Lc6*8QFW)OA>RAJzmE4bgww@LUeD^ZbW3~H3XjstW%<1V>Moz&<@C|Cuxs^Coyw{x1u=0~@VY zu4PMTp21Ez_>=E?$iss){Qdy$t=NCV-dlEULt$Hkv#eo%T4Az^pVq-X#UCP|@aIIK zG>v}(JYpvyOy?}_%A%Dyu-#kP#!H6*goV3GWhmDG0HDAbFI2o_(3E=4Xd~AJ2B6ZR zD?JjOdtb6@CCqLAD4%=Bn4U2>fA%ka6()v9U)9a`Dnz_=^D#^Pyx8$lYv9!}WYg9u zYhr|m2Ok6B%m`saJAXq==WVT9a8z>L(m0vK8y$Zf@)NRCU&ZIlqYNPyIQ4y(zrk^; z9!fe)naxmKdt9S(^@ou)f(CD!{SaC8QEWW9?FV79>Nh#wAMY66Z|R7di=@YwRC;u% ze?q6f?mV4d&FS=oj?t-Qvq7~Q-0!F;Z{8Ha-uF6>z1MK;eLE@anFzg>!sSBzag)KM zb-pwe7Cj#&UF)-~Coce|HjP`lHmP0^v1O~#MDNx@XRuopV9SweAc*Rf_8E!t?7VJ~O2q@}4l%>aqrshX4!J;=9II=?w?Q`nnLe z%Bx{H0ci@DVj?`x5Gw^cpE;4sSRk+pbt#}$Mz-X+Ek#LQC_Tt({xLrRw}Qwf%)K%E#u-f%PE# z7o~o*9VIK3QF;=Zk!)E21GKk39jEOO%MZ2TFr;nuzzN1VVNV1s3a#q=wDkJDp3hCn zuOaMtdM2a#filsjTV02M2W_2I>W?XDx5o_BVjlYL{;iC(7EOd%KyQq|Ra8!lmIzU2 zbq2gB6;!RQSEjHaHTV>Atg1qYBL&y>SonInQk={}wT0<=Wx5QG2M9Dl@Jf1Nd>4yf zauefFPpj$Y0HfMlI5TdtglyK3y}$@ zw`6Vz(3{GKvvv89cB|#77$I>ljwL80&QOH}Yk^9N`*j4gqXc|OF=I=dFoM6eT}g2% zoti>l`=WyR^T0Z|Y5(3mG7=m;(KlPPM(3$j3uKzTK3T$rVg2nK>#wz?q(9AmQwO%Q z(@cQgbef$Lm}W<_wcNyrP#!V!?1MO%;5>VtH_u2DbfSGoM?o?Z?E|*t2_yM$wL8(C zy#-Whjg=6W$s>?h0o&$|KoDXY(?sAeVPNB5Y~w8yLg!`4A->??juF_0SxP%MVq}7= z^sG}YPEJE0l$Xku`6z-|yr3SIXMkWS{NA$wASA&O1naCS61JYn@J}GS#oMsWT>Y60 z))gX;(Hy|4-~jPNG0#gfrDJmE{{B~e>{5n_70laD^6}CM_@$T$sQIybd_Iwb<~c5l zIQ!71zZ%oDi3K5|-M$h#CLh}>z!1&kP&f~CM1mo>k zGDEW(RlnCFehwPq=NeSX!$%9FBbe0yJL;<=P(POE+Q13b11N`v4^-*}DxW&nO%UUk zok)!TVK~NBvDP?MSU!W&`JtaGBtP-Jo8U?&X?0>|wCYhtFKg?r3tMD4G8Z$uGC;+r=|l zq*Gb;#+}Q|=L`qIuvP15IX{!`xsIiZiOGa8$h;vh`Gngszk=f ze6CX73SlMl@@QoQo~$q>PcRwjWrI?kdv~%!_I2(gG@O{ueLMnds?I$~%AXzT5#`Y^ zZCNdihR;Y@G{9CBPCcr~Buthbxn4Y_!l-lI1a->G0D~t?i+?yAJ0}p%cn!c!7PhF z$^+P7bRs+n2a&@$0iZPMP{9yX$Z;XK`!>zZUw1#Wi8U<}aobWk56`o_@M@Wgd+QGgv=kIl3 zePJI~aPU?_LvN8A;3bx)?n`I63=Ux}sBSM#yNqV2p1Wfh>dXjWC}*7!?A zn@+IUa%fnJE382$CY&9T2%llgQ6MM8Xa9%u*%CH}?(*54;iMgbKuUnu;4esdC`oR^ zGkf@Y0v4UPdo&=&T4A>Jh|(zOwI&84%5Z0gG8}?VneNgU3R+;>munjt!MKimq0e-d z*dknqO?Q~U461%0=agi08v{w z6lWaDa)VDzteU)a5F~r>BD{D~F+aTqqQw{@7N2;-g5iBf z(I4my`)h}te+9!+(@87x984(l>fi~N5N)920&!I-*T*NkkO4R6K#su~Ud&09!Gh*T z3SL$dt}8NQ>=<}*E>;G13l}op!a}%#u1f#{It@RjW5IVKsVm@BD)b5+>DXvTe-YD> z1s#3Cg(Hwllm&=R+ON?77YkC*aV=!@q0N4!8^bw;umlCbXk3dpJJDe+Ko+BoeyhO64(O#QF5zwKQ1%}8aDHe#^ho= z6M-`|F0@vO3sE63%$STglUw-#R{e8_aU=YH0vZJVPCpm`e)hsjsN>%2nmaxJze5R_)=Y@Ah@q0}Sezi2jWdT5` zG+itPKpVe4rg00c=O-c})KcqR-4@D-wH1eqgkOX+z4Z{tg||-LT*w}V^%?u;NU>6@g9A}ajB4>7KSN8A zP;Lds7YypP&=x^Zt@8-_2acd=#@rV3!}nrL>cINeeOP4RoLeV%`z9p0% zS5X?*2*Kqmbnra0+hW{d%=RqD<;zbDE^h{R4lrpEicz+P%Xfs}GO`hZ%ir!iE}!GL zeA@}Y<)&LFZ@6u@oba%%88$w^#%4Sd8mGIHS~~&9Iy;c?iQ%YhbQ?|9{=Cw`2Wxe!2j8|PVU>kAMn3VMZKs0RWyH5MRQCWgp>cO z^O*ccj>)G^049fTo!kahx(1wEC->J5<3HPv6#%jOk&VHXf?NIuuuNnQUgDaiPL@$N>*mijX!IYoo2MDmGfv zmIzkQz@I1QSO~K!zQ?h8D)eOKX=uYjO957QZwm;FY5_7x^MfVa$_P7_B&wrDMZb#P z)|(`F9_T!tzt8cUIsted1NnS3JB^5jf1ncNAg;YbmKwakWO-_4vRr578;*bx!U$1) z0c_NSMTt|zhWL6NQs1H0Camgnr8-m(kKW8(=t}>dXk+PHUFwr?(RH2Yq91TBx~B77 zWa1oXDFP;zf=ykvtNQzQm7#hl%S(mcF2|#VZ!)_ zoV-nO^k)ZHGBR#}!Pt7XUaCoaG51>@c43zQiQs%YT7<(bvCuN8s!T@Ic!d`O@K>Qy zDOcD%T4$L|4o>35tZ01e#q+Tp-U_T$;7Cjs_h%v+lA>V)IRjz>>doTb@p8Gu&S?cP zBYk+zL?K%O82l~is#ovArlX;>ti{k$bMV1VT#gAU9~R(4+U$KX%~~wseb*ksD_wi1 z5Q0zujK;M*NK87mC6dat`B!#heDemBaGlYhU{ko{NjjuO{4pKSJGwETMSST(do~&r zP|BZJbXZH|3)=i2cVl38b$E^w)fk5`6HOBn-uh9v>{MHCtl;si$lMC?UheT|GphpA z4qDHuSh}wOW%KZKVag|g=LD@^PL@&pT#BdlhJA1A&Y!@b-U6F10yWnCGiC3C7x&Mm z+y~%asF(jB|K}n857`~tSS;31vxngO%4x89<6@CdB9F33@f|zhd&KnFwAiB4H``bf z{5ws5H9N6(Pi;0Uc;&s&GiQyEL3ut}_xrGxdJ<* z!1LDu5@1k)RvVk{y!!d*1%X2f*vNXf3^-TAiRZbIYH@s|It^vshaB${r+3R1@5lkU zaftnn%8Q@r)ba=R2nE4?1^i8{rn!p5o>Mblbk0Jf*|-${H(;-A9>^M^%GDza{XknvL0&8xnQwW*WWx-nFJpv*j*T`8l1{$~!W%Pd6t* z%Ka+h>1%K)gpxwT>YUq|DTN4>^2u*NhTEDs95NMwY6#rIl~1_*j??kswCC6AuAB-{5- zmxOCRBR>vOFfb#nG%)U-6#J1I=Z(OTcJ)$02uDRO&Nddpx5fOddlBG_Zo(8|`N=r3 z>?tG-KmQCeTyBO=xr?y+@?y9|O!TLrlg9F(RGoF7foCxMFJu1*oqGy4azEbTpAXNv zEARo{3s6_$-}j)52uL|TV}49j3W)Sm;oC4g>t~D%T#KbFhMXbLAxupVWgcLVW=C^r zsXBzf^ma=Ky}nrdmTLBga10R+U~NnAI-`Eom9pEwzJl(Q#R60c(ko*?idZJMwL|zf zkZML{LMd~S9l~#b#>{sJGfvuxdw>~t?Si|;Sy6m~< zPWTXBOqi}?%a6_c6r&NA(U$6SQb9SRtTJ$cI8n~SS|skPbg;#!g$W&M2OH= zM7MvI5S145kCY_#hTy05?ivqteXT$!5?DB>M(CFIh$YQ1-C|u9Xjp!wS+1cUF{m~j$cpdN08IRlKop~-b@d~Sh8PXjcJzbQg2d7%%n8b@EVSU$3x0G{%dEE@&9r7 zZv)djV4Aphps5~I;d6(n@?KDnwkM)!l!HcN*Y@My0zrUPr(iV}pqP;u3V5#gUx zEns^|By5e<)%x^wxl$XcLK0Q&?m8R`Se-pCG~2@p$eK|aJm?@}Uc1r)ECXH>VA=87b_>|r=QR#;XL)U@r@AHk=uEZ% zzmc!Sd}NOZTis=WBLlX&!;-B^7GN2$l>p0*t!6A>YoDz+$Q@=Y&kU4&6T(*bjeITG ziajE1^%@Ht8L-tWE!pZF7GN2$l>p0*t^UXYw)WYIgPbT^wbhvK8w;`I-7llT<$0@5 zkZ-K9CT96HOZ^g>(=23Ep8c#L?$2Pj?K{o5KZE(roK5{K1uB47;l@ldHek9Dg{VSt2)xvc0F!G%Q)px4Ed-z zCQIbk)E@qJ%*@jKYb$6^o}^Q&?fnQF4O-y~8ECZU{}vMX_; z{Q?>@ccUR=xr!T2phipv-)DA`EX+BRB9{Pbvi0v0kHLsmi(@2h^2RJKRL@%=>i$a( z%s(I&J(sW&Gv=0dhE*hm85_myg3+l=J8p>r4{DWx|`qQs4@emi>VJ zG2TKc8AY32@C5#PxGIu^3V4B<_yY0dMMzi}#oWGO2aCoJKu(|T9~^MXeU zlpR!OG8MLH##5#GeZxEq=`lczDRpc`3Z9rQ33JBy40hu_%ibJPMXgLRYu%WfU@ zG7H$+Uq^9}O^g6@w(78l@vRn!Ggz~~(URBxzyd4-UK3#1@!E$iU~8Y(ILMvlwbOKi zz}E$83KS%bfb}5Xa}!!TBRc)BEzo7aVPD`Jwwwkg+?5yx2(HxT4$)QGw=BRqD>5b_ z4BT_Q;DZ3mI7Rb^7GN2qXbP}YS}s5n&?Du=w8p%je#8to{w*Q#e^>w=nl>CP`F=Iv z(qDa;`UBb;P#j#>;_IP6{BVV(8|;VXZ6cZl3$P5hU4W&rRZG$HiUn-#vlR!q!)%pU=;;*} zI5J?Xms_&c8!f;xU@HNZ9b3KI0=D+qii6x)wmMDsR!P~dhc=f7KbD_yYnHwuqW%*W z$TQ%#CoK8x3l?A*@S6Zj<+p{*AxLp2o)M(|tp#-La~uacQI2b?F+bQD;(l~*KvVjJ z2RkEzf6_xq<43}z_V);cjLUQ8X{g%>15PyDIrkV~kcB&!!kr%OR2|SV;CVs3S3M-; z8K4!9Wo#zvAd`^ibux%41CiHZ(fvXNf}RyG3@V=82K)ZEaew>)Ja*j+TZ#3q*me*R z7d;ix6X9al;-afmaJ)&bMn>0Qv%&TDVgW5(b)Og0d&C;7t=Q<<(4U#(m-04=jrKxg z{))7*knh)IE6~C*tcn0RGRN5mxJ`fdxO)?BEI=+)W1}8&g3D2icAPxn2hP#REiyj3 z0C|y;(}ea2baf=hwNK0O@pKFE@j$y>h>_RBwRr#tgFQ34TRc2Y9upHk zO~;qywzkKUw%g{*7O=Iy%;q4Q zD1CFb>ToRlM;3@Pn0P<1=51o(k6VCc z!0iGojjdXWg@4)tw)WYIgWO@ZN-P%scNRD@V5_fLvegePz%pPf0hS$G{hI}B?XwjJ zIZ?K1t1&+^8RGnL--yeQ6CRmVN_5K2H$ndpb*pR9$&j&m?iCGv55b@ljZU6_4`7i+ zCohIOJvtfY29y!X=QsChhD0d?bmOk{myz|PNtE*WYLs&O&HF_t#xM$*Ml?hOXS68f zY8f~RbSM3CTCKAyvE^W}sK@^m4G;~*zz|^rw-t-L9QreJyirajvB+)En0bH*c}|T* z2Jxc?g-$MyFK1t59T}302usCrmo~+%!cx2E&*jiuf*AD}*^IneT#C+29+wJC-z4Hv zF2c*=Qit)5#iiKYNgJ2CQbbPj_1erxZYEbMv>cWiY#}V=H`|4%)L6I#_hCqt%4MiI z-Fh4&Y`bPm80u6FnVukJQK*pjBnb5~!tNapLOrN=*Ldj(3qtv1iitsOOM-%uD0$W#b>e+;`PwHnIMdb1iY3trUjTttvadhRcwTQ z#E?SX5ZrvQv$%O*7jTnYskB04R}p}WyfphSisgkuW^t&%WKK`ST|eX$bhZZ zL-RI1)~yy`8L*WA%Z{z~SisgkTXB#(%vOo{SjR1JWWZKAOSY<8fMvi|0xUbWddLE{ z_SuSqoG4qh)tK*N4O!c`uR$ev!hNhxvsG%ddUqj1^A;Ey_U?r-C+cE-4>B5av3>yV zbQf#L8drK)*ESn@SmnC_(YR0Oeqzd)I9S)J4%Thp^tcXv9)|wakHkzi&A)n@^soB8 z$pxt9Ui~yS9CWWP^?pRXtDlL1AYzf(mUs12(4X0=Gse66C1}jtyNc|ldRGJJ(VVL% zlP807F0xG%-)bCZX>;4ox4KyPRv$-vCgoeDlal*Z12Z=X-|9~hUglfxaUnc?d9V?gfx7mMgs5PvscTP05JbBIBTX7!}Z`aEEf-|h8)osePueY~M@2=4} zVeVW>wE)w{_;nj6Cy%J7))CL9RMbg0MlaTB=h<`-`rO26ycU`_Q{OQjtn*o8n$uW! zjA}=KgnYtgRNy(8KwCPCm7y+RCDN~_At(Avh9mtoLDj9DMb*A8peiOOTtimew+vlj z9}t91brxZ67ZA2q%GhYl=xHuhNSXYWA+(hr5ClKmSp+}S1qADkQjHNqKH(zGvqeP=OHpqxL>cY<@HcA2Vck-J!4Qq<02S*q7J^FAU2tU@8980 zcksn6f261Hl9q81=JE^BlRHk9AV>jMMdZ=4+F=*Bt1iE-{#xA6t@Mk)=&#i}8fNui z7Th0%oGt-1PvIKrDb%6xPQBG!hAXg#pv&+y{nu0lt%`vuVy)4Z?{GQvXSVo=@g1H6 zjhXunk&{*5VHln?C*n!De&&+`Sxb5oLyE^3abABk=c)YfS(IvxqRq%wK}Nh#XGEnj z%9od61KupBbEOk}xsf3-qGi*PGS@(3$?#ftJQgl>v7(2Q)?!uI4<#%UsO`yko9rc6ZXcny(Pf%ZXyORvxcpCtJ?q z9caP9?6ukjxAN=4O$QGI>L?to=MEQYaCCeL27Y4BV_Bu5-jk5bl-FMqL;e9WHChyU z_CDf!^zIrDoiHDy|XM} zYd=GegWOrR(nC{`+(iy!C#yyBhKPra7Kk(8wLxg!Cdv333$P5bK?PWLytc~%w)T0A zgWOqO3ybSTa$Bp1C>1QwWx!!s&SAzjM%4l=0~f5}QF^rn z(Cyn84Cc0Nj7J&&Bw%CMQv44rkY`SD+5)!r z6$8g)XBC4Uh!3%CF(~h?QECX&AU}Hz>xu4t%2rk*lN%MECaR@VA-+NkOge* zvlR!qvuqWU0iug7dQuWuHPKgu-}YM|&w$_dTJl@g0xSc56JV+Q*6JZjQx?#*&v6{+ zL^-al#{6`fka&UHK;O>^Pq&FUP{cRqGpFw*v-i)Y+&mnV;~z@ffWHDS z8rQ1{H8;qJBRNdTd#XhI4L91oD`q-s=`-F&JFoNTteN*=!@*>QrQVNdQo;vfAc$Cz zwUsRMN6?>Hn1=E>DP#5oG-jTZfE=kN%LLG)CLf$k@k7qt$Th&z+`iY3RWf3#3uR`E z#~&(3dxoEy5c3S;G00t&bO+6gw%;flZOY zRGz-s#%aO7)9mA@1Re%+gv@c@9|3*J{SbZAIFogfD#ChrejN=*2TKklSnqVxQ>Md?4REozBF_D6W>~ z6Zxg?x*$@cH9<^ojPak z9Q=>Z8V)_+HB*zk;!ttUMf`A zqr_V;3FU~DYK<9mJLBR=E!j_=?1kvRV!-v`Ea630Kj;vu z3K;%_s7nw!5uf-F-r+y*pAU{f8wu|vsH^ecXzA!OQn181_?gncDG`R8wP$DR<@uTq zDZL}0c*rIg8G9zv9-+?JMVX<>$(Q!PGWj`osy@cxG0Za~W38EU?b_Ov^HLjFDm+Rh`X1R}frJ9%biY2PElCREr2jFOQa5GBvQhwSK=Dn9M7saiI3EJ>M&D-bC z)rLb0Pfp4estY~?e$HSsrsb-Y+(J2;ffx25Y{+DD;@2r%Buuhcqg#^mQ~*kF1i~JM znYMR^EN1_t;lvXADITNAf5ECr038k4T_?)OgvA=Yaa7mW{JOOvh3sam#XeOjg0p%e z69V*b7(PpKSUKbdrp>Bi?38;iCX~I@GWe&ld(yqoq-04 z3*hZX=tBb$ono5iyc043IOQ$W32QDV+`Fa1Hkyxj?!@uhx|CAnBk#U?Spcj3{lHOevOnb6}$6 zPZw$9=)54vm$3sQUV&QtVh(yV+R4@NXvhT*E{}g=Iaep6Y2pnHk$;5Y^ZJx849pNK zx!@Y!e{*qL7S2C)7hT6pmw;CJ=}}P1mGY!S*-xPpz>pB@-oy92)Z-2uK9436r$ZJK^RCeV|#Y@AAvGx(Q4Tfs0t5TkFK*e8&#L~4thQoZI+ zPb3q%UFCVwvy!o#VSv9yq7jachlbP0i_g=^yNZpJQ8w-4jwpL9L7idXCS@}~@fi>a z0(alf$X}sg8m|=RG{KZ5xYS%iGETPgg$@A{yLgE&(%kC|NQ>6+&#|L1dhj?A2~sDv zv4(#evMi~@KgK&!iFD_p68pA>f2OQLmAs0-mIX%S>q%jeF0JFAEW26wmHY!pLuIHL z`o-DJy*s6~Byr;4<|43(92~2(EGHyd$*7sM{(uSo$aVFGlNuzfW2 z*R^H*Q=u{UWqe{MTE-_9%dm{U0H%y!X=EWcBTY^diY(AV{(`}N6yr3Qj^xOKFWkv?*&<|A9%J7AGh9Jw2L&Y|3NKEF2jatnZAH1AWlSE zyO+!Kr^YSQ7b=Z1tci!xIO{_F+1*7{w0gT98V-GsB{7Th_&nkuP9dRMj@K9G!{IU= zlh%ecwc2zpXo>L*0zLzyM2onmit)F-Jip0Up08KDao+>W*e`l;kC_=E4y37Ule}Hi zWp@hhGYmQ+`gLN^i5VIAJe}w=IU!~Aj04gd?1%%drjcYohRFdLpoo_7*JXv`N{o#X zE2F^56jHigHL*A=6nj(?M?w<@;R7W=(c?6OMYr!L7Hh=yV>B_wj7i`PoO3JZzvz&)+Qo{{NkHOcHLx$>uNV&5Y z!{u9eN9j0p=aP;?fje#yqCo3W@Uhky&l-G$PY>7NBZAgR@DZ_+786U|FNJ;U>u8G* z8a9J|j{Q{|!V0F<_q3 zZkXs#Y^jtvbaZl^HG6Pr+!AA*Jw&3H98DQ%?_$WYju|ir- zxsDo(f{!smIQSh3=EEoWh;q6`eoxFOl*F_U^ z8V0;1#-Z@J5spyPqTS$QS{v5XatS`ZiGWYCXHpm?3O)U)7=PQr$88jmi1r4F@Egp> zdNp6DLvUrHTAAr?4DuT(B*-xKi1uF*V^5?#K2N9pMuCmiNMKGvTDu+b!xw2l8E|6q zLk1|KP~>Z~LJ@@`QG6x3?P-}!Q7H0IRw$xS#B44|s zxws#r=^!wfHs}npDhf=h=^O?o`JB%rgQCDBH$R0vrrD^8tvduJpNf>Dz~rrXM}bMY z%NCea_yF;i0kP50dCI*Qx|Wxp*n0arB&XEKOKRkF=Q8rX?T{S2@`gP!bs~9_&~djmXTIJZlp<#W0Xo^78H2;%bqInA{d{Z@tFX}=h?t+R zCFl>BxA3kkL(0BIv-Ob79OJ}|msUtS@l898lvP4xi!SU5!_?>8G3ByF^Hb0~7^2RJ zq+iPbmP0I8f|V_n`@IaXbsozVAiLNXmK=+=Xnu^yk}$d36N*tRw>9@KP$FsY9vEhe z5N-_cO88mGo`d!}58;MeG!Z%xzg_iQxWj*jTQu=r#wVjKnwpRlk=kcq14<9WG)s=u znh8ML+O4!K?XUJqEw90GD1Z#Zz}%y`sb#5Uvu~@`@~POLzPPLsaG8udJq4_UIndEA z&6A-&x0O!Lq^#KTMrh1^mnL!4&ZUyA0@|f{8ncvPFIBZvs0~Xb+trpA!YJM;H=7|N zxfyM8wkR)kfy^>7F^^#k2NTnre($?-KNek{^{d_<+Bg{|&<#AXw7&$0phVGNEF1>A zEa7cP!OMH~(u@z4nI|Uvs$VYnkYHCo;QM8$rkk%dsy^0ou0d*6-SgoUsNcNbpPut( zt5BG}AX^1v3Ty8I@rMWYLf&hAZq^U0lZoGHPh%O<`s)59KnM;;eUnPy69N23;{cdU z*uhA|MOA`Kh}DZG-vxJ~P!^_aJTq8YrSz~-D&s{NBm`*tmiPxA`A2W7M$qM^E0tM&=jH+( zkyK4#{lM9Me|k!5NfXJzeMevuxjJ@6T4rzLzL#xS`%)@9;F*}3tgYa=+CZ#QA zPibLQ{KT;GK6k9R`04M4=G{zIYnnyg<=d&Ten&F?rneaSycm>oB;(r|z;cLWNU*X+ zGJcc+w$39N0%R96s3os;)L0bBXe|pCDw6R!pcHo!rQsPBn~DKmDFO>WC1|gEkqm@R zL^6&)2zU6;Fp`1yRwP4H7{W&0hYhH}fm0--Cuc^j!(k|RxOZTkKHd45QG?i>t{Y>E zO>Ia4DpAvSaAuST{kiD`&Y>)fF$|5lhcSqqD2zcYmZ8{GKTbl?3>@9@Lnd-FT}@|l zVT@BTB~M`778AqBP1WnOwUMn`{qpdE(!SEHUo7Q^E7i%Z_^+*ql+gluWy zIpA%FLSEAo!`FksI*g&F+@^sd{D_Z+;4`%8LTihAU=wDBEB6^ zEMNx0p4z)kRi9*1_p&3#jDDAx(d3zl-vPke_J}W=I@my$$5}mC!Th98s_g1L( z6dVLsdb;l^(YFPIj2OCvbK$)F?Cf-@kgu02We>d@FGr#09nsIkVVm&GxcU@qy{wD} z5UlhtA9kOJeNvoL9vz@HXM`aa92!RYxn7YzI=<~Z86Y?5WEpraK}BwT3C_?=v_u`& zeo*m6h#3khz8LQ)s7QC&f{F?sy$dRC-Z42@^(TpkTjn60$yQeEFZ&Q?yvFX;N)+1S z<>jC%)$NyzH%im>A=tY=(J0eFkKRoFj!U(@oc%el{p~4}#yuMOzLeIIG`B-E5`j&e z4zV_c<+?`E$hX?CHXD7&M6)?X><;c~Qqkw_!6|Pvfe@X9C1Y?I{1t+b7?wOP4h_07 z8utPd_utGi#O#5})4Me3qNmw_PQ70L+C_=Z!5A6{xgj5;k^Vk%2m>2uW(l0 zgbgT;bBgfwCRgb(DO11-@pU0r=~C=Z*Dvw8N>4}uD`94Kl&f?J^yelEIg_#=-*wQK zdytPfih_K^Wm$5S7S?PM9F7d-W*eF={sLQnVi@N!28@aO{q-KdUXz97LL~=#Sm}s( ztfMy#VIZ$k_943{zYouaj~oo?=9Aa&dt>3(mFk$6mj}^{oTTsx1`w2cQh>-p9h&s& z2P*1)h#i!t=Y|J%(VJ6|1bI&VHQgE(-$++v z=;X0UtDxB`9VN;9^Kvl3N>w^g6i8AoYGvSSn>?H#P}Ncf;$TWnL1G}5mZo4` zsXR$pg);Het5jwEOPaYOIL$`J;H-x+%nqEY6o&`oZ%`!@<|lL(zS9^F-$B0cMGe52 z*=fo?^o!=q%J&?2J|mu!G9xU_zA_vX3|!5)Es!|7>E8Lf=5s+28Rdo8qOQA_0G^b?8&RV#jUkCb*|I|M8^>oRG9s@g zlJWfr1|uW9Zj$kX_>wYIxxh}qb|+-~3&KP~!>(lf6g1WyG6G_(jPM|pj7vyFbb*9W z7bBU34_PFH*G&?Br@th8u$v_OLDxtKh;bz0>2f9}NOdOd(q?BT`Z!9n-F1;%>#!`+ z-V}cvCYdgms-%(}-eIo-2<^COzIj%Qs6RHC6#3_4;!?&Tx%ey_J{pErtx*f;e++b) zrq-GyteHThUl^U&{z(RLm_5jOtleF6Zb4$=M7=0{Y{phsYA6mBPE6(}z7;;Uf~4)8 z33INE5*77H(i;wC88<@nZUF!*ycPvR&!WbxU}%@hGG5VJOkCD|Ot?rw3$0PqGG*7ZlS58kOi?Gv=#?F*InG*O6o&n++U5;nM-`nPc)=q4+Er@p_jBX8*#ITe@(UfQ5 zIA{s~KD?tPe7bX4!Y8$dE`g%9wKeWe$`Zl2QKWjK7!bsRs(t}?!-b3TqM8`Gr{WG4 zw8K~hS)`zZMMeo6WJs|fDD>?gkT1&w6WNw>Tt(1hK_OvE__>USxV4a^0#Yj3so;lZ zY+aIIY+19>g)Mo|U$CXNGSG@GmlPnDSW9q-gAI#;4PU3Y^7V=<>CS~KRY98wAH7Q~ zS$|EbRMKI zs(xkY`i(ofT(S=yf#$)^TD6XOyTNMsH*|5mR$#p=40oy41%79 zy;8tdg5|uy_V^57IY=uBmPyaWDESpJjoKYh!9<@H;$24K4Hj@+E-FD7+bb z^EmkDimE?R2ZIknElmLjg{|emMFj|3ub7=1nSuHTxDnwMlkmxM_(50}yY)yl5y=C% zlf7XFw_2dp#d@-oK;%~cN^o@B=~&$<4RuWh8aiO;iG*tR(oj#%0G7jsN(olB4V8rq zuywwnQh?l5UhAl_C~)xsThbe5tfER z=tP9##mG_k&oJEz?g;CWf^p+xdpdKgI5J z6&1Uo@{K7#CEB4KY^Z!4^p~t$V%6VLP;bRbVLmtlf+kEEz7raYlwni)%B|LHiJd6d zidgJ0-B78S-@-;0OpQ$B=2*#zq5>WZ<2niGU&^=*rlh$S?u;v{K5VJ0d4W(tX4cr}S=a4ZwsGuuSfjHytAc08tqLmslnbV?73{)?qtpRd| z;8bx~1N2yDIf{agYO7NnE&%?_op(Apo$beVcg@*8EC4bjYB3MflU`%tH*}J0-+3T< zH+;!j1B`n|B>ZU~v&np9Q&;VrZ4$JWi}(D0fdFnwD#da6Pim}J>wzct7855x^IgV- zWj3Zn(=D_{W_8RY34VhUM@6(2$gFN2&F4`I3p-{U$rkqih5>eNVUsN_mH{tA_Mv6K ztKqJx1^4*s-)c6dxJ5q=_d?hI0Ey9#`Q6E)AMb<&0q24QZgW`ly9H4siUH!CCJbmY) zfnUx5mP3qNf|V`C{kIul>paFSKz1=4ELj(=r+kFSk}&Dp6P%GT-kSRt$QTda3Bzn* zfyV%^grbG)1JGXQ7I+xrM(Bk3z2f^9)GZl z3Z)yyk=mXhw+=3ot?}jLV{lXoJj0YQ7F3%TwLA4{X(?Nhq|qLx6QMsh51X?y3y5!k#@qwq#CsGFCw`=W_+}Q%gM5EFC?Oty za!hKk(_vsUiP?ed=VlyQ(cOL|-Y3~S!b%cDS;^QECVFo|z303O)@0h%Yb<1k*tDb5eD{f!|AQ@sAB$uz z@d2a7J{vj8d`O^$i}^eW&AaJ`6r-;|jrA%PeP3@ead#guu^1<(BDuv7>?ti#hz}S; zJkVP-yrTPPu&mr{A^8|F5sV`;l)Jw`UO@AdWZB$mn@-H2)bzISb{&kibMJus01==6 z45E+X^ZyI(nn{t5CaH*UtIlc3qm7H)Ya|l-co%l6toBr=;>-(K{3c3@+>r1f7i{8B zngciFVIzQF_p8yw6RUsP12(}PV(_)4{bC(jX^8y8y`drUO>CHU>tBy|#I_i_xR`?+ zjdF5z{P1(ZgUjQeSQ!teqLT53hNz%Lcm`FW(tv}fs-Ymt1=ny0np|-SNkrO;A?jbd zi>Ti!MEw#P2E0(eOT35gd8x;pD107q5T}s%>UbKq+{Z$ z$qaUwByjHE7)p#WIM;7Nh)Sq(Rj$;bwvXBdDZYZOT6L(zH9f6Ou_-tyP$iGah}8-O z1fM@QrLpm85y3)8yBNVjjH2+}BJ_9b2p09P2i_OqFKo)a z!(Bpjl2Z9+c6SRI!BPY|EFxH+wUMJ-+$7cHu*vC@(0tb-SRbXvdKJO?Zf`O1tv+C) z8xgF3?JXL9*?ly)XlW}x8m(i;h>75TATkcy2o_2bz91<5-DnS2%%Iftw(#}_7;RT0 zSnFO0=%Wah2X`qEEF4Lz2o}5(7s1j^lQ3UH;Y?w@~Hz~G7@8HoI!Me7)h>C(4S3<*~*Ay4Q!skg8YBz$F)`m6l zTq0PP6Yv=rC5m5MCdS`(1Zx|)v}Obg<|Ce0RR<4!qFR~hZXm0gLV^rqk7!>OV^54; z;`4OcZxq-NVZ1aXFq=26-H!NS9}Or2PE3Bt07Vqfx+E(UQ9KL9SEAdR7Q>I?S-GrG zMDeV%p$UWjffA>2@vLX;k@J8Dwah8em$23`92V|%z0)3DgpZr#EWn_B{4?f*F}Pb^&hB1=U^ip06R(@80< zCFu``Jwga<;+%=KDy$Gev`1*A4Qun+eMnYp$v8dOE_ALvRz>9mx^%K#CR?!za08)+K9lCp6!+nDf=tm=$ww z=fuGB3g63|f$xAi1ipe)4T@qn`yvDz5mmBh91 zvlQCvJXRa-MMCIApmrYb@SovcB)pel<*444CYeRhbvb^ff|{v8S2H2xvUc|(#b-9Q zw;AbG3_c!owd!v@uH|N=7NA(Wk=}&e>&hr8nUhW9x1<1_sDeAF&-DiA&rNW0j%M4D z-UE%fZ$~2bqwPqf6Tjo}@kNlsgG0QkMvXxEy z*La+m%zX5Vb(^9s26e&23TVF9nCM1A#@W3^!}{){!7^4;);BHgij4Ufi4pt)XNL+2 zERZqZJi9H4-6}UDW_)UMf$m%a>ts}*jhD;|Dbq6$9aL|Ued1oJN-6YoN z!ScY{>>(!5jHfI3K zq57W$D_ixyi!#90dG$X5a#wk+qsAg9y|t!VASXTe2uvxyK4I;Shyh+1F&2LAgZ4W2 zz{3?cgig5MK5`WPGhA`Qduzo_Gj@d2{2XjRS=UZ0ZvCkK7o^M+Yr(DS)&J_)yKd&S zQ~hs$3djl4u%qgKRp`$x0Lj^zY0i6~G56&*;yqe!BYy0>`rqN;<%s!#4Cv<2S&M9k z&tN7QYr}o3+iy z#I0>6`LWTG=BBm+RB0=joWD2;9ggC8Y!a;4w|z2C8=J{nFJpevo%=f3O#V^3yXM^s z7}{yEdU+CUR??3{5=al{zg-qF?m!;Xb&Pw5mhtolOh!CtqfJ>_NixD=oB7wEc{f#R ztvf}&*q5j=%NH}2Elr#lj}uol|Eaf__-P+7(T!EjB`?*@S1xh7zz|15^Ic{L%OOZv zhOxLSa+qQSNbp7E2^Gm)Acv`WTAK83wU`+*EH%L`%zY5X+qo-6PLo*7JQul%7Beq^ zyJm7wm#<--kv8JErAv)a!pi(Go6RX+SSL%Dyc3!$oMkKoJ1<>65fMmBmsjE)EnU)` z%OW0G5#3w5f_%?J0>A88K%IaDtYy!P7(xKkd#z{e^$&|653M{ImFm&s&Ft5@wodY`{Z?Q^l4 zh;1&dRT@=5LV#e)@tuK%70-mr?!cq#di-GnTx89LX<7^4NY8R~-9*>TbUhcY!4|v> z!DZ)>!LazV75?lFw$b%Gx}J{@jtVZoKTCqgh(C{|M;FrdBDfw59tYRpV!VvtAH)qyXpEQy50a+LRRoc^zR$--+S<~7cK{bo8Ss#elq;ob?nCAX85~1xCO4k53!@C z;N4U4aw|P~8s7c{pWFs_JC{$r_)zf2_}eI6#^7==$m8v=@SSnEI}{Y?T7)ZfzIP{RAEaoi&v!0ql}A6$W(XW-9W^Fc-Yxn2CJi9he!N3XmI{^V;x zgMQ2fMVyRzylh4G-h!7u!pm;F{1Pue$IB7$S@3@YxZI0(&&137@$z20ESiQ3b`Tte zcmIud|1krXNAPl487`OLW#=qhuEEQz@$w41yzO?lyag{`slnxoczGHE^c1)>f&&_$ zhX}}n1mHme?hpZXh=4jo039M=4iX@T2#7-jz(MN#5OsWrIz2=k9-__;HG(FC?+6)mN61)?2pXus<-ZU&gq8~tH-wgB z@d2S_H{yoS@>;wjw7dhcglGv!5dJfw>JhwrvJRKe;pM#jaJdjK&$2}Ps2<3S#YW0C4V1WCh_v)XT#+ec$vE&E_dUl z^jx@<@$!a)aCs|UR^oBs$KnOgDG%smb39Kmpc5GJT$g}Og25Wj0abm*S~vk!&%vD* z0qxDe9ISw{wlEePQ1lp0nE;KSMsOz)E4WMixf}if_uni2+$a7#NBnuN_;X17c^>?M zxz)r!M+DD@Kfw#(0&@nX#m=K@&zZk*K6oko1nqryr4o!q5R9srjTI3ZdSYXCx>SGz zmA%po-a%!|dcHd8*Qtc&h&MP3RXcnrKijAcs`{9syvcd3zJ2(f*F;}Ge9vo#`Of=; z$PQdnDPu6nxQ|;K)FVPvzV|uMu$#^yw$3+~O#A!&>G_>UHW%0DW8?t#F>M^<5dO&G6Q5Na`*FNuMr;PW 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

MT36^Su$ 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

;5=` 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/get-started.doctree b/old_docs/_build/htmln/.doctrees/get-started.doctree new file mode 100644 index 0000000000000000000000000000000000000000..9a3c38868b8a86855f107710233f969a277c03f9 GIT binary patch literal 14516 zcmds8ON<=Hc_z8yVmYZ#HAu>^#~+_QW#nr#Z(Bzu+Y;pT{G3Q zJ>Bho?8C@|KG-1Ra*)Jh0|64}6d<|fsUY_RPJ#qE7%>n82m)Q40KVjyQ}X>)UEMXa zyW}iI!ifcQJzZV(*Z=?Zzw7TiQ{Vcdmrtnw3eESHNZF)e03 z9IS{rIhFZYz^zwu=^dVBe%NJc<|Y~U1~e5jC*S9Lgu=lIUma+yreha4WCL+l&N(I0 zVnR+AxNgbGzz_LgD{r~7=4M&qxAF`$5=|4nmlFOn?Z8b_4C41x==SxmSuc;PhnCyk zPI!mro+yYy-xmc#{dT0AW##6|g9LqvVv==(|Iy(H>^1!?2G{Y*q*<9(iPyPtDg zX~Rw3Rs)zex;$Gi=&dIyNchyvQ+W$i&w(blo4B#CdG!5v-EGd&JmG9V%9(I?IBP|j zV9nT%*=r)p;&ijoz(YOWkKMW-HF(&-2CaZM{186^FrwRdqvlvZkR0kPe%swd0(yrp92a(Q*ya=F#A8&=o&NNZgdQlBeF_ z=E(x5^YWcXBs3OxM^AGm@H3vcflc>ZDP-n|rj*cGVBGNziKuf*a!xiZ2*ZdpwZVfR z(dJsNtIg@zTADu0=2yp8laKHGj!~2&)PNr;mPGNoxG2_OStdcbGE+*xmUsy3p13fz zPT<4#RNAA>H0c(-aBw1h>#bb8p)H9r2b(p`mwL&ug`wAmYa^o-A>SUKdxnr%5c1ow z<@crfH!-Yg@Z8#O~!4vddKZM_DHrcKZpF}RA69qxEOJ2Q=pklLjKv-URXjqDW zbOI|W4?4vg zdK)Kxn5|s;Sq^ccm?7{kt=4LOhdBZ%LT|dX0MOzzN$Bi<9d>Z zE34+%e@v(`W}|oFdgrim429_}mpeSrUD!G!{^#bzVcNomwB;fkfMVx{5^q?^ znkCDI{s+t|Pj};!pYB21f5|%A%9+3ROUN^jUa>IRMdHzJ^EB<`L9oxDKYj?q?uI%o za4Q{W`rvh34`cYrfK)B)VkNaUA+3G*wQEtBB~h?` zt=X&}aA41kw@w|gN^y>wU-^aJ7e?r`eAdDcI!18jN)#<9tq~~q=N7_ZwXgDC2y-f~ zk76^Pqxvl1-3A8ZsNSs-)8ne%9@i+cLRX=QqI#XtJP^QMnk;7OYtoc;0Z^)B?|#0lEB6 zL;{USFM^6@E^3KJW)6E*Vf9yI%MNiHA$0Gfa)ru_H-?<``NKn7gUeB`H9i3TT>yU! z!Pkox-a{7dE6T3fZcCNuTvNtFQSbSB?R^33g#V>6Z~GmetRI7W6UYHuNC_ELNKp_} zE)eCweN_LtT|e}@RI^jL9Fn~?h9V(7sM*MwTPW_mP&)em1DI4&@h{~WA17LPWthuV z!ZUAWHbxYN#>(^m!Q(mq*M~8yJlxM1zvhSSAop;xoh0fbqhd`;wwkOTc{vjG9p9yB zt)K&`9_l*qV3ogk>PSGAq5kg?wxUe5q>A}YSv0guAJZBK!?8(K`lt?R;?yzX`rb*J zeW6DvKm*Q8_CV6AoksB<&vd;t%=Aheo*OT>HFS?Vy%eGgAoVdAk?X_sltT2uDtL;3 z270fAz)H|j=jR?O{*k_KfCSm5CTh_ghw)d4q+r4Wo<-rS6wgpJM3)7HU9lJTbKE<$ zi%JsWnJ8ApNQ6$XPe}jwVQRRpn4z|BjF1JPUQ?LHNwni5qEluG6)ny--Ee=iX;IK* z`mhupba6ry5kY<^cmgz)zR+_&4wO#N^-99pK#>&5%4`&%N@KqJW5O~^zt=}JQk;;d zV;*`qS7#3@ZY%flK~`&lFN03uOE z3W)d%m#U>1qpj5C6x{kg%iMH3Wjt%wVb_>0(x{^pNfbtT%646~gGy2jfkoE4EBGO0 z9L(f<9Jl&}G)y$2!ORDyU*?`hwc-P!i7u>lYHkBAAyv)%KEG7i%1I*5())~5MO~Wf z_^kKS7$}p0r;a?HQ48~{1V>w#Wy``8r)h0?XJo?>L({vC_xCX~zl_&onVH@%5TK*1 z%dgYRBdtsCHoZQKjuGo}3*t>2RMzF!e#9bcG5Nr$o&u8PsZML*Ha25Y8Q;p1eFt-G zkr+Oq5!-K~!IBIAXmR2Hqt1MM=XVRO`S{N7*%i1^o{neWNkS|GUm8I9;tk5-lybXd zoYvSbXFUqXlzm5Dh~}4+^cf)$B02gHem(UE6ax9^Y0?y%2#@+d}(x~zXEFxq9EwOy8Co3-7?Bijwz!<7eltbfDu zN8qu32rv)wSci}?;;>o}Tw?^E`yZK1&t0?*^J+-VP0RGytUhIdqD&c$+t zDsu`TQW=adUK6~%%@A0!EYG3@kzLB%7Cn@CoJRIu!qO^9l@mIlwX@W_R+g&c$a9At z4_$!RiE0ms5u=r64qg3?vcJ+1(@AJ9HAwEwg)6}`l9#utHL?~$($Viql3wYP8ZG3% zyd*hHk08DluqEX3NQt_pf7XI%UKuZfS0m~2ec1|53gHXdumW1a+fTF9cdLp{m#7TZk$uVjB9mpf6Eg}C;#Ufw(@7pNf{ zHG5|dmy&%ncFM&Rt2D6pRvJQJ~uJ7EJFQIPReV?-V-cN362h(n%#s=b zcf*v9zZ!~Do_mplc0tTKgPK>Aa>rh&q@Lf&z@3ysK54FlF`S~`hC1-o)%`%8qnQc;%ye)Gg5$|lmn4tZ zKl4*p!Oz8{(;fj&BNh1P40tH3OCr0?le*8dj@koi-w;_pXh34od=D-1GBLP0D=$JO z`%bBzWW81Ex}zI4@5wW|dEP1eInkyWL?rsBQ*;z$&X;oNbqYp3p`P_4nh;RP(X71) zFARKe@LJ!%WyM0Q-p*s{6$N(s!baPHdyt-}?S~!6fH4fqWGd3UH8KxP4P6{Ydg-|~W^Fqh34Y+fbB9CX~GQA^wQl;#ThuQ5@|30sWb$@mc!w0sZ+!{K@4Ut)wck`gTOEy(ezp zRm<+GCHK_yd%1W99|~x=r^PMtt_J%11X%&4z*7NLt}>SkwooW67f^Xt8bpGqM@aY0 zJk1V!M9;&g2oR!vD+)?EQ&WFpWU!n)Hw1Cc?5Y+m55ZSS8TpNKqp*rMCu9wlsg0%@ zh#$)BZM6U50C80CPBYhv@o(Y`zB>3kv<%rQ^tGrq(1!GB&|@`U{)v(v?eWrFdpn%FfR>jsXG%nky*H41uY_ z^B+PnVSh~>rPm-zo1s_v|TRkZ!b#waUjjgwTo_w4B2n)7Wf7zruc6&b{49ZWD zRLGB}-QIs-*i_((X6`BrI2H>xEEaA&EDJY=SO_o`3uh;f%fczFI2H?gr?BD}3}la# zfmbaCUVT^wUL9f}z*G!;_Sg($kDGz$#^Z9ij5~~4EAuj64l9d4UoFb%U znd;u2?xwqXcgGUMK?=Gh6-AInC{854{DK6E5Q!jh5)>gzM2VE2f)E0P5d4Jl51v>By5@$P&vZT*)IfEH}?gehb!u&1L=K5^^i zTemF(*%4k8S|cYFEU^Y&z^+;SggJt_R&Sj1g}XU#$TJ^iJA}iD)_yW4jOBdn06mfO zvuV$fO-G2t>tzDRqvOnaZVJ@pLO*cQ6rK1z7dj*TYthZ(>Z9lMHxo8ca~eCN;CdQ6 zM25vUVJSU95lz*yrJB)T^@~CcjP7A4<(V$`XcRqXe@XX zc0bJ0P3J|Ymv)`h>2xC}c=_IMh<(a?>S$^kq)&p4)(@73#POQqCCxG#9uYGPB zisnfRq2gI8r6LGl zFKE#Ko1J0e#JqOoSAKA6X668lt=eg=Rs>3rSPt+b^j?yCoKFF&W<%mqLF0|a}AofNfXCVagE~$h$i7RD~!T+FNpdye9cN@V2v$saG(m> zqP|qb5fXt307=*j`bXnfdqpbcd{OEWKe3$17)mU!q}^1C@2vZHdx*VK$tY%FTl*R)))9<6fy%7>RHTlNs+UZoOBeAVFpCz z;t!dDK6k>QwsK}mrHtX&+IEULWC9Dcl>GzFges{&2a0ZK1!5M(0mCL);96Tz0Hf(7 z9_D$YIEl9OHV9F?VMxYQ!`0`6xNGFeinItb?1D4GpgBWqA)<9Ufi^_27MzesV8s#( zpp`4WrVKn$6Tqx~mQVlzA@T~VrCr0l(oelTk40K~()7&~PmyP9Ko{);#eqnvTgYCCGqryiy1xL;U zy)5x^d0}5UQ-M+d3*oBBa31P1WL4M>C-e4$BvfN=0x-E;%5OUmZtj?ftTtfjfg(gJ zQR5${XzexGEGg;ccTN>Jt;$BF2$db2;KK3jU}HZ!C~ac|UBn#$tO_DBBo^=Y#PeCN zI{MHPJnNBWP6yi1)K2q#2uxIZfT$YbUxJ8?1(?hpDPxJXy&KiI{Cb_sd}PeDeCou= z7=db(r>Jf7$MtQF7N!~u{u}bLk)VT#QHs;+5T{R+r+EBWgq#v6Y~I#8)r5&KDm(WG z(wCGV@y{sfArw~S!-q1b5~v9V98aKDY6A5xb5@f`J!v|M+!NkH`yJ&%G1sI<-_g@mjPO7`Hjp=-N35xx75Sh50kXw*9Qs9G z(<$E zVY8|7cT3*|tkxs2+{d&{FKNVwxn*-(ATPX_$#R!eY3EX|_^7AYRA`2u6+($02 zt93L=lRK%1;?{bz=?yH~CbMnZ*3FyNW!t7$!L~0K`^2$za|$I52{~LR$->sUq4xia zvuLh^d*4UJ<-pKZ&LJ^G9<(c0xHseh{tFvki|R7`QT~`*3=mLeh}o!yqiQ3{D*Z@7(3Rn|5F~a7EN(+?m8zDGiR;g5e199Z>^$KMaf4*Fy%*7R@T1!f$>|e_w zF_D&jv5i2PiUFoNfKo@N*{1AH|>2MLkoNj84Fs>0{m``1+V{4PHfv_Y$aM*ZB+~)^WNU>U0NN4>-TW2x0$7 zgsl_}dH4TxKgA)cV;!kORfy<+WQz8+VDyHmH@yW_)6%jk_g1L7=@FFlafitz#}vwTXiMCE}T`FOmIu=oni)IJv~Q6y-`5Db7TR z+pU>aZF%_&?na`%Kv8Aym?8Z%CHO@-r)vGUpg{=+wPLz_X>G_QB)9DpNiOb*^54og zdDaX2L52tr_Z|we|3w_m|8r{o0u7UkBWDMt zXu*-m;*tnpJ>0j*vo8Rf$j$Wii##(7q8=iddG5I`9Qm$XE+Cg3i(xiGks9dUnUPIZ z3{E3dzA(3mE4Au$>eFoGe+5_&pZ)-U!KW7LfOFu}7pQwGxI&3p)3?2iYmk^FNVg_$ zQvBBm%0v_ZfVhA0KaT<9MKr(sKit!GU?>NWe~Q`upP^Cg(YG|j3C%s?(A(6_4fWx+ zOgOPedaf8$&2}=uL)Euj&hAHvo_1DsjTpqBSg3mtg;QluEo-Vd4sNjoG1&jI#>oFW zLhtXX`3GwLk(z&|=3l7!S2WE3OSE@R`+tQ$a*=Mw5SOL7|5beN`fsTAYpVS^+B-A; zH`K>pqrIE^-^3sP-_cAlYZuC=XlB0}MVpL~j8?OX*bY4v-~N-x zN|$*4e^K*4)XbblbDEkn)XY<}h-Q+5jhD)smXok>34o?p_z+n5eQf-b#lmIB#myr0 z3%V2pii~Tz3nqAkvUgkE6cc&RoBpDFtr<}ONXNK&ACVEQsBRHSFH`dvHCNC~5_jbm zZH_QHQ5VN2Qj&E*o1*YlQ1}7r{-Knl@_OWm#p9ABLALCOJdaGQa{MozVe|`q~ zHR*p^lbOxA>nJK;zc*x|@+kK-Ze;-Of0STS(lR5@;zo(C&Fvj5sl^)AoQ9nDLZu#6 zeprpJ%0;tHEqv>jNbi@^wd5JKo19HiGsnXW;kIdaHtm5O0&~&-82(I4dwr^^sY6C` zwcUHmXo z;+MU>{d$osEgFC|F8+Rr$-Z3lM;JdY4|B|Yi#+@z+UD3i^gmA1tK&>D?`Oe`-#G%8 zI`e4$r;nb0Oy(_X#Y~x#^!XmO{2T1Emvv?D1nW#MSU0c1)fo3}0(4*{p>-n0{p}Hl zKScSyhovWFoH@)C+nxm*-aG=6I@@UeH;n&?n&^m zq_;siG2Fywv-r%C0AI_<24(d~yF(6uKX2FfOPg7R}t zuCg6Z*f@>IQZs2z&bh3Y4YAz{xe0QXfXkc_dKw7o`iu?*@3G>AaVBhfK0z)umyJve z+CPs9I(|PqIcT#ai4q&nKwRWspfjP`$D74-Q6?s#%qb|jyfig31;T%H7J|8=;Z``9 z)elb&Of8n@=?p0d#X+J#z0_PbR|=rG3+H(nxw?EHVaPFE8)-h|1KUuQVMERri4Z8_ zxi+474!oV5&*KFmDh+nkB~N=0s%1AD#daxpAgt=Z6%rn%IRODYr+Pr$FeUa^U2)1X zH?r}f6tm95jpM<3oo-4_qKLwt8D)3hf zcqpqwB8#Vh9gm5Dx+#F#cj<1R3yFn+f)=?{!daA;Ad@4zR8I<<)N?#rzvbPP=k>El zyS$U4H@6Xq{@HYddXv5;NkOOw)VI1dfo4T`{|LFk^WjUVJ^>#vUh5mEtVoE}n^}zL zj9y9W*MQm%pjw0;FC0JyjA2+KQ-MT#YMwVjr30HeS{vy#@MaE~L21c_3Xg#TXL$Fq zD=+jhYtv>38Uq_Ix>0nY=gs%!YVl|o!Ws;;S=*JfEZoWwn8`(LPN2UKMKbeH4q@v6 zQk`xUNI|qvZX>Zl>5T5{g0ZXC@2a);)w?$p*1^ov z1grPxc@Pqa*{Bxh5Y+ zm8+|I>&IgYfj|%?mM#xr3xN<)BB8tx!Ae9Z4+)BbctvPK!XrrhJn(`P3GuW-eCJl( zTh-OK+U4;q5?EtT)va6S|D5}GPW|S>?|g(J)Mj@m}Q@A-W*Ojx7u_u`@H zMakRA=5Hmxp0wCbXW3q7l~%o-s_X z8vS^b-*k=ML0}H3Pt2AgW1k)+)+OtjbB9f%_AJUosp z-|Os};eqiPqZ@XN(CBtRX(!4U?mRNPot|ZkA~X0%I|#wd^ABd@E@ZF_?u`Aw7+FQB zz4(d1G$K!N`*b}duu!O{e6c|(r=zLl5Hsb1er3pd$L8Os# z+7M?uFvFJjt>C|hpB6k zuMu3!@cJ$sZD_(G`$gCk0Q7w`YTfEsrtA8*wm^V8X!Dzl%$wS-WrrI65iBAoFyD$H zB>|TMG{R%A$HlX<7D z8cMB_l;4;nWuC{^nsm%T*Hx4(a3>ZNWOowt@0BsLB_RW2iqI?hUN2jdKs@&pHW+>fn3=$ErAGE67pY`A+wcH?De9U$FZc6!yN8B=}~}AZzS};nSh>>T?6cl z9G`F{0sj32z=n^gX<%khht`!sNERfIwMj((Jb|b-<+Gc21#G&MAb&govYx0n*kT&E zb5P@MJcm(5VC2^Vr87Ts;lc#g^ODB1(vg0FO6e@m3e+6+4w010?EcwH@4l#1{aH?(2V>KBhn*W6@&`Ni*r{h1Lm$ko|@N&y$Qq zH*adEElvKUamw#IY@l4*al&#){K;^v@+E-OL&gBVT zS3x|hCp5%%gP=Tbkfi^)0ul6`ZSi1s7GgsW3uIiJGBimwu$e7^5LXh@_Y|0F`$Y8^ zG|kw0%kHG$eyoCD*Seg~;%zbaD@3RZbBbZ8o`IdZ zpt^DDUY20BMo%e*D+-Fw7?~FM6i=FDX?nN7H`fGd*_}lHk^=oXw=$|1oGE`)Pyu6oe-Bl4$m#wNm___+{ljUrl&Yy(N z(i_Rsud2}3=IMu6--|g>VdKJ40X>twt&N|S3F6Dml8qw;M)mBw@5kL~8$<4R5-X zTz_AM@O*b1E+~efx}k3Rl4A}BpXmU*ax zSVKvlh}2aB0RQd1yUe^r7tH8;)q4)sn6Nb_XG$)bv^akZB7 zKAxw{pFX7-J|K|qNIH1d*=pQ%{sK)h?`HG_LKx!%#1|ln&&^#j6=hAY09A)NL`Df(cMl5d4h&( z`C)YT)t6s=xs$7OKF_Q8#R%pid?FK&2Ol&3k_C1&IP`>IPP23T4dPT z7{q~{I1Rjm%uQ#W-o54!v6J3WW?`y2WD@AQ&`D8$tbq`8hX+YRWRUW6}xtNmo8;nn(`PT;D$sLK|z#C3U;Dq$sNuX{F9B`35KDsWJO{>h^7JUH9_H zdi!=t0+IxABH`miBG~%6Y~Cl$XROEP~|T`_2r}b;?Ttw20o?jpRhH{-nU%*M!FH~ zQ|`O-r|^8|oA|>TE;3AGV;_q!F^wTF*vWFcpB*=vJj#AjBm^62tR*MMgacuB$wA6BthfD(?l8Lhs5PEttz;ci8pT(DC2z#lD*Jp0umPz+tkonn}(>vQhCVa_> z2y^P}R~7FR{QdAOGzxzY@KRlW->hQi%QUWG%9UliV@@*k`!UAEQQ#lis06{BaBpuS z>!P)Zo+7_5RW+|bum?6?;oXt=r}+b}_*_mj$;2>_nn__gnh&(|L{LFACneF0&wVZy zNf)8NA-E}k`DzJF^$1C0Vm4zW+k>jF3R6{vRcaB zs?2k}nZbw0?JysAUc%C+Mqz`HS>5h3LVgEQJb#3Ax&Wh$jqP#9^4N%Y@w$g4nCo)G z&q^4=ch6)K+5F&d@lxG*@ya+mxt_iOJ)Kr0(r&k#%{uiTXQ};| zsQZ{w^C2^x{*O>At@K}^qW9BEKRT|~+)9TOb;rws5cbo`9SZeS?~_`wiE5&BH-S7h zt2IN*-dR(Sb^a}g+uJZST!Oh>&zWX^u~}T}Al4liKnf zv4@PxsH`-X(PI&v3y%vGyR^qLS16f9opH4x$RcWMi&lg)Y^@guRBo-y;_8c{B`vaM zjnIr>{a9nN%d$9pfDMrd;{z6$pEq0-jpmypmv-3lzUgH(Ubw*kj~otTI7)WdN{U7Y z>;v33v)eduakm=zJ)MfO=_$}HfUe*;VOIveA9;R+&2sth!3PJ`<4->Sk zQR?VO&#Em$fV`Hrn663nm!VF@)H+|Yf@EOKUdU?2ci6?iq^e=vH4jZUc`(bGmf_0V z1$NmyLM1S`iQ-UnT3`!(vm5UN-r6H0@E|MnKtb;iEz41Wf=i-1`3hUJy-^(L*f#Y0 zJjHc6js|yLy%X976&AL!Xwo~6b1qJ&*SFdB!lz@a4Udg)0Cg!45xAX`h} z<}`@6pBsNrdYP>g4%>ap`0-Vj_69VjNU?O1l^*(m;XotOrg(T## z*z>&s*n~vvzK)ZVfqj%%i)_t6&AgsBu~{2Nwc3w|BUD0Xh6lm&2Fyjwz%yI|c!{?_ zx?V`?&zsWXE*%Fo=(TPhjr`C=0eAi;w~}6@AKIZ!Wr%>K_iZekT@#FCR4xgJu(sGm zFcZQB(h5shP1a4PLl*vpfepF>68JF{%0a^ftq+y2;9Cpw7AAU`ANshaw+};f?V%kd zZ>-;9Ya?@nLg{QznV7jqEnNe&lXI|VX=^#e&NiAu94pZ$2-<$I-$~fh)RPl{o_b{B z0|M|keAfZ(cV2w?Cn3+ZV9+aprr$4%%E+X(SYNiZyQ+A&;_#P$mqh0 z`jM49Xt3+>x1lcGQ!=2ZM`R~#9o6HJaiq)LsstZzpuJRfF&yGJOMfedUxyIXReqn| z>U{e?743C=M*;LeeW|}e%3Oqa`yd|CP8g`;pP|U&zzM9!@7dnK&jZ613Ke18E%mce z&S(Oek$NM2R^lLm%?!I{A1-_h?OLW80m;)n^g7T@)SA0Gvh%SOMjw~>3cH+r9s|be z4$`o8!shTD0{T1!Yoy`CBqLkLfs+mAh;*Fep){Wx&Sek<(?Vn?vq4!X?c}j5W39Yw zo0d zyV8Dm*QZL2viI^B#ASh%zjS2`K0hd>@!;t)tnA4J)gst>^*M(xh14f;t zPh{_L3r$foH6FMK*Jluh?GCjr(L``}84_Cbm(1)II}I LvO`05+-?6462Ji_ literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/.doctrees/tutorial/web/chapter2.doctree b/old_docs/_build/htmln/.doctrees/tutorial/web/chapter2.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4855a8fdc95d814688c8bddb20fb10f7a7b0a2e2 GIT binary patch literal 58108 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 + + + + + + asab.abc.module — ASAB documentation + + + + + + + + + + + + + + + + +

+
+
+ + +
+ +

Source code for asab.abc.module

+import abc
+
+
+
[docs]class Module(abc.ABC): + """ + Abstract module class + """ + + def __init__(self, app): + pass + + # Lifecycle + +
[docs] async def initialize(self, app): + pass
+ +
[docs] async def finalize(self, app): + pass
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/abc/service.html b/old_docs/_build/htmln/_modules/asab/abc/service.html new file mode 100644 index 000000000..ddbf2c923 --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/abc/service.html @@ -0,0 +1,151 @@ + + + + + + + + asab.abc.service — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.abc.service

+import abc
+
+
+
[docs]class Service(abc.ABC): + """ + Abstract service class + """ + + def __init__(self, app, service_name): + self.Name = service_name + self.App = app + app._register_service(self) + + # Lifecycle + +
[docs] async def initialize(self, app): + pass
+ +
[docs] async def finalize(self, app): + pass
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/abc/singleton.html b/old_docs/_build/htmln/_modules/asab/abc/singleton.html new file mode 100644 index 000000000..4ff48daea --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/abc/singleton.html @@ -0,0 +1,156 @@ + + + + + + + + asab.abc.singleton — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.abc.singleton

+
+
[docs]class Singleton(type): + + """ +The `singleton pattern <https://en.wikipedia.org/wiki/Singleton_pattern>`_ is a software design pattern that restricts the instantiation of a class to one object. + +*Note*: The implementation idea is borrowed from "`Creating a singleton in Python <https://stackoverflow.com/questions/6760685/creating-a-singleton-in-python>`_" question on StackOverflow. + """ + + _instances = {} + + def __call__(cls, *args, **kwargs): + if cls not in cls._instances: + cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) + return cls._instances[cls] + +
[docs] @classmethod + def delete(cls, singleton_cls): + ''' + The method for an intentional removal of the singleton object. + It shouldn't be used unless you really know what you are doing. + + One use case is a unit test, which removes an Application object after each iteration. + ''' + del cls._instances[singleton_cls]
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/application.html b/old_docs/_build/htmln/_modules/asab/application.html new file mode 100644 index 000000000..d91f3a1fb --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/application.html @@ -0,0 +1,750 @@ + + + + + + + + asab.application — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.application

+import os
+import sys
+import time
+import signal
+import random
+import logging
+import asyncio
+import argparse
+import itertools
+import platform
+import datetime
+
+try:
+	import daemon
+	import daemon.pidfile
+	import lockfile
+except ImportError:
+	daemon = None
+
+from .config import Config
+from .abc.singleton import Singleton
+from .log import Logging, _loop_exception_handler, LOG_NOTICE
+from .task import TaskService
+from .docker import running_in_container
+
+L = logging.getLogger(__name__)
+
+
+
[docs]class Application(metaclass=Singleton): + + Description = "This app is based on ASAB." + +
[docs] def __init__(self, args=None, modules=[]): + ''' + Argument `modules` allows to specify a list of ASAB modules that will be added by `app.add_module()` call. + + Example: + + class MyApplication(asab.Application): + def __init__(self): + super().__init__(modules=[asab.web.Module, asab.zookeeper.Module]) + ''' + + try: + # EX_OK code is not available on Windows + self.ExitCode = os.EX_OK + except AttributeError: + self.ExitCode = 0 + + # Queue of Services to be initialized + self.InitServicesQueue = [] + # Queue of Modules to be initialized + self.InitModulesQueue = [] + + # Parse command line + self.Args = self.parse_arguments(args=args) + + # Load configuration + + # Obtain HostName + self.HostName = platform.node() + os.environ['HOSTNAME'] = self.HostName + Config._load() + + if hasattr(self.Args, "daemonize") and self.Args.daemonize: + self.daemonize() + + elif hasattr(self.Args, "kill") and self.Args.kill: + self.daemon_kill() + + # Seed the random generator + random.seed() + + # Obtain the event loop + self.Loop = asyncio.get_event_loop() + if self.Loop.is_closed(): + self.Loop = asyncio.new_event_loop() + asyncio.set_event_loop(self.Loop) + + self.LaunchTime = time.time() + self.BaseTime = self.LaunchTime - self.Loop.time() + + self.Modules = [] + self.Services = {} + + # Check if the application is running in Docker, + # if so, add Docker service + if running_in_container(): + from .docker import Module + self.add_module(Module) + self.DockerService = self.get_service("asab.DockerService") + + self.HostName = self.DockerService.load_hostname() + self.ServerName = self.DockerService.load_servername() + os.environ['HOSTNAME'] = self.HostName + Config._load() + else: + self.ServerName = self.HostName + + # Setup logging + self.Logging = Logging(self) + + # Configure the event loop + self.Loop.set_exception_handler(_loop_exception_handler) + if Config["logging"].getboolean("verbose"): + self.Loop.set_debug(True) + + # Adding a handler to listen to the interrupt event + if platform.system() == "Windows": + + try: + + # Windows win32api import + import win32api + + def handler(type): + self.stop() + return True + + win32api.SetConsoleCtrlHandler(handler, True) + + except ImportError as e: + L.warning("win32api module could not be loaded, because '{}'".format( + e + )) + + else: + + # POSIX and other reasonable systems + self.Loop.add_signal_handler(signal.SIGINT, self.stop) + self.Loop.add_signal_handler(signal.SIGTERM, self.stop) + self.Loop.add_signal_handler(signal.SIGHUP, self._hup) + + self._stop_event = asyncio.Event() + self._stop_event.clear() + self._stop_counter = 0 + + from .pubsub import PubSub + self.PubSub = PubSub(self) + + L.info("Initializing ...") + + self.TaskService = TaskService(self) + + for module in modules: + self.add_module(module) + + # Every 10 minutes listen for housekeeping + self.NextHousekeeping = self._set_housekeeping_time_from_config() + self.PubSub.subscribe("Application.tick/600!", self._on_housekeeping_tick)
+ + +
[docs] def create_argument_parser( + self, + prog=None, + usage=None, + description=None, + epilog=None, + prefix_chars='-', + fromfile_prefix_chars=None, + argument_default=None, + conflict_handler='error', + add_help=True + ): + ''' + This method can be overriden to adjust argparse configuration. + Refer to the Python standard library to `argparse.ArgumentParser` for details of arguments. + ''' + + parser = argparse.ArgumentParser( + prog=prog, + usage=usage, + description=description if description is not None else self.Description, + epilog=epilog, + formatter_class=argparse.RawDescriptionHelpFormatter, + prefix_chars=prefix_chars, + fromfile_prefix_chars=fromfile_prefix_chars, + argument_default=argument_default, + conflict_handler=conflict_handler, + add_help=add_help + ) + parser.add_argument('-c', '--config', help='specify a path to a configuration file') + parser.add_argument('-v', '--verbose', action='store_true', help='print more information (enable debug output)') + parser.add_argument('-s', '--syslog', action='store_true', help='enable logging to a syslog') + parser.add_argument('-l', '--log-file', help='specify a path to a log file') + parser.add_argument('-w', '--web-api', help='activate Asab web API (default listening port is 0.0.0.0:8080)', const="0.0.0.0:8080", nargs="?") + + + if daemon is not None: + parser.add_argument('-d', '--daemonize', action='store_true', help='run daemonized (in the background)') + parser.add_argument('-k', '--kill', action='store_true', help='kill a running daemon and quit') + + return parser
+ + + def parse_arguments(self, args=None): + """ + It parses the command line arguments and sets the default values for the configuration accordingly. + + :param args: The arguments to parse. If not set, sys.argv[1:] will be used + :return: The arguments that were parsed. + """ + + parser = self.create_argument_parser() + args = parser.parse_args(args=args) + + if args.config is not None: + Config._default_values['general']['config_file'] = args.config + + if args.verbose: + Config._default_values['logging']['verbose'] = True + + if args.syslog: + Config._default_values['logging:syslog']['enabled'] = True + + if args.log_file: + Config._default_values['logging:file']['path'] = args.log_file + + if args.web_api: + if 'web' not in Config._default_values: + Config._default_values['web'] = {} + Config._default_values['web']['listen'] = args.web_api + + return args + + + def get_pidfile_path(self): + """ + Return the `pidfile` path from the configuration. + + Example from the configuration: + + ``` + [general] + pidfile=/tmp/my.pid + ``` + + `pidfile` is a file that contains process id of the ASAB process. + It is used for interaction with OS respective it's control of running services. + + If the `pidfile` is set to "", then return None. + + If it's set to "!", then return the default pidfile path (in `/var/run/` folder). + This is the default value. + + :return: The path to the `pidfile`. + """ + + pidfilepath = Config['general']['pidfile'] + if pidfilepath == "": + return None + elif pidfilepath == "!": + return os.path.join('/var/run', os.path.basename(sys.argv[0]) + '.pid') + else: + return pidfilepath + + + def daemonize(self): + if daemon is None: + print("Install 'python-daemon' module to support daemonizing.", file=sys.stderr) + sys.exit(1) + + pidfilepath = self.get_pidfile_path() + if pidfilepath is not None: + pidfile = daemon.pidfile.TimeoutPIDLockFile(pidfilepath) + + working_dir = Config['general']['working_dir'] + + uid = Config['general']['uid'] + if uid == "": + uid = None + + gid = Config['general']['gid'] + if gid == "": + gid = None + + signal_map = { + signal.SIGTTIN: None, + signal.SIGTTOU: None, + signal.SIGTSTP: None, + } + + self.DaemonContext = daemon.DaemonContext( + working_directory=working_dir, + signal_map=signal_map, + pidfile=pidfile, + uid=uid, + gid=gid, + ) + + try: + self.DaemonContext.open() + except lockfile.AlreadyLocked as e: + print("Cannot create a PID file '{}':".format(pidfilepath), e, file=sys.stderr) + sys.exit(1) + + + def daemon_kill(self): + if daemon is None: + print("Install 'python-daemon' module to support daemonising.", file=sys.stderr) + sys.exit(1) + + pidfilepath = self.get_pidfile_path() + if pidfilepath is None: + sys.exit(0) + + try: + pid = open(pidfilepath, "r").read() + except FileNotFoundError: + print("Pid file '{}' not found.".format(pidfilepath), file=sys.stderr) + sys.exit(0) + + pid = int(pid) + + for sno in [signal.SIGINT, signal.SIGINT, signal.SIGINT, signal.SIGINT, signal.SIGTERM]: + try: + os.kill(pid, sno) + except ProcessLookupError: + print("Process with pid '{}' not found.".format(pid), file=sys.stderr) + sys.exit(0) + for i in range(10): + if not os.path.exists(pidfilepath): + sys.exit(0) + time.sleep(0.1) + print("Daemon process (pid: {}) still running ...".format(pid), file=sys.stderr) + + print("Pid file '{}' not found.".format(pidfilepath), file=sys.stderr) + sys.exit(1) + + + +
[docs] def run(self): + # Comence init-time + self.PubSub.publish("Application.init!") + self.Loop.run_until_complete(asyncio.gather( + self._init_time_governor(), + self.initialize(), + + )) + + # Comence run-time and application main() function + L.log(LOG_NOTICE, "is ready.") + self._stop_event.clear() + self.Loop.run_until_complete(asyncio.gather( + self._run_time_governor(), + self.main(), + )) + + # Comence exit-time + L.log(LOG_NOTICE, "is exiting ...") + self.Loop.run_until_complete(asyncio.gather( + self.finalize(), + self._exit_time_governor(), + )) + + # Python 3.5 lacks support for shutdown_asyncgens() + if hasattr(self.Loop, "shutdown_asyncgens"): + self.Loop.run_until_complete(self.Loop.shutdown_asyncgens()) + self.Loop.close() + + return self.ExitCode
+ + +
[docs] def stop(self, exit_code: int = None): + if exit_code is not None: + self.set_exit_code(exit_code) + + self._stop_event.set() + self._stop_counter += 1 + self.PubSub.publish("Application.stop!", self._stop_counter) + + if self._stop_counter >= 3: + L.fatal("Emergency exit") + for task in asyncio.all_tasks(): + L.warning("Pending task during emergency exit: {}".format(task)) + try: + # EX_SOFTWARE code is not available on Windows + return os._exit(os.EX_SOFTWARE) + except AttributeError: + return os._exit(0) + + elif self._stop_counter > 1: + L.warning("{} tasks still active".format(len(asyncio.all_tasks())))
+ + + def _hup(self): + self.Logging.rotate() + self.PubSub.publish("Application.hup!") + + + # Modules + +
[docs] def add_module(self, module_class): + """ + Load a new module. + """ + + for module in self.Modules: + if isinstance(module, module_class): + # Already loaded and registered + return + + module = module_class(self) + self.Modules.append(module) + + # Enqueue module for initialization (happens in run phase) + self.InitModulesQueue.append(module)
+ + + # Services + +
[docs] def get_service(self, service_name): + """ + Get a new service by its name. + + Returns `None` if the service is not registered. + """ + return self.Services.get(service_name)
+ + + def _register_service(self, service): + """ + Register a new service using its name. + """ + + if service.Name in self.Services: + L.error("Service '{}' already registered (existing:{} new:{})".format( + service.Name, self.Services[service.Name], service)) + raise RuntimeError("Service {} already registered".format(service.Name)) + + self.Services[service.Name] = service + + # Enqueue service for initialization (happens in run phase) + self.InitServicesQueue.append(service) + + + # Lifecycle callback + +
[docs] async def initialize(self): + pass
+ +
[docs] async def main(self): + pass
+ +
[docs] async def finalize(self): + pass
+ + + # Governors + + async def _init_time_governor(self): + # Initialize all services that has been created during application construction + await self._ensure_initialization() + + + async def _run_time_governor(self): + timeout = Config.getint('general', 'tick_period') + self.PubSub.publish("Application.run!") + + # Wait for stop event & tick in meanwhile + for cycle_no in itertools.count(1): + + await self._ensure_initialization() + + try: + await asyncio.wait_for(self._stop_event.wait(), timeout=timeout) + break + except asyncio.TimeoutError: + self.PubSub.publish("Application.tick!") + if (cycle_no % 10) == 0: + self.PubSub.publish("Application.tick/10!") + if (cycle_no % 60) == 0: + # Rebase a Loop time + self.BaseTime = time.time() - self.Loop.time() + self.PubSub.publish("Application.tick/60!") + if (cycle_no % 300) == 0: + self.PubSub.publish("Application.tick/300!") + if (cycle_no % 600) == 0: + self.PubSub.publish("Application.tick/600!") + if (cycle_no % 1800) == 0: + self.PubSub.publish("Application.tick/1800!") + if (cycle_no % 3600) == 0: + self.PubSub.publish("Application.tick/3600!") + if (cycle_no % 43200) == 0: + self.PubSub.publish("Application.tick/43200!") + if (cycle_no % 86400) == 0: + self.PubSub.publish("Application.tick/86400!") + continue + + + async def _exit_time_governor(self): + self.PubSub.publish("Application.exit!") + + # Finalize services + futures = set() + for service in self.Services.values(): + futures.add( + asyncio.ensure_future(service.finalize(self)) + ) + + while len(futures) > 0: + done, futures = await asyncio.wait(futures, return_when=asyncio.FIRST_EXCEPTION) + for fut in done: + try: + fut.result() + except Exception: + L.exception("Error during finalize call") + + + # Finalize modules + futures = set() + for module in self.Modules: + futures.add( + asyncio.ensure_future(module.finalize(self)) + ) + + while len(futures) > 0: + done, futures = await asyncio.wait(futures, return_when=asyncio.FIRST_EXCEPTION) + for fut in done: + try: + fut.result() + except Exception: + L.exception("Error during finalize call") + + + # Wait for non-finalized tasks + tasks_awaiting = 0 + for i in range(3): + try: + ts = asyncio.all_tasks(self.Loop) + except AttributeError: + # Compatibility for Python 3.6- + ts = asyncio.Task.all_tasks(self.Loop) + tasks_awaiting = 0 + for t in ts: + if t.done(): + continue + tasks_awaiting += 1 + if tasks_awaiting <= 1: + # 2 is for _exit_time_governor and wait() + break + + await asyncio.sleep(1) + + else: + L.warning("Exiting but {} async task(s) are still waiting".format(tasks_awaiting)) + + + async def _ensure_initialization(self): + ''' + This method ensures that any newly add module or registered service is initialized. + It is called from: + (1) init-time for modules&services added during application construction. + (2) run-time for modules&services added during aplication lifecycle. + ''' + + # Initialize modules + while len(self.InitModulesQueue) > 0: + module = self.InitModulesQueue.pop() + try: + await module.initialize(self) + except Exception: + L.exception("Error during module initialization") + + # Initialize services + while len(self.InitServicesQueue) > 0: + service = self.InitServicesQueue.pop() + try: + await service.initialize(self) + except Exception: + L.exception("Error during service initialization") + + +
[docs] def set_exit_code(self, exit_code: int, force: bool = False): + if (self.ExitCode < exit_code) or force: + L.debug("Exit code set to {}".format(exit_code)) + self.ExitCode = exit_code
+ + + # Time + +
[docs] def time(self): + ''' + Return UTC unix timestamp using a loop time (a fast way how to get a wall clock time). + ''' + return self.BaseTime + self.Loop.time()
+ + + # Housekeeping + + def _set_housekeeping_time_from_config(self): + """Set the housekeeping time from `Config['general']['housekeeping_time']`. + """ + config_house_time = datetime.datetime.strptime(Config['general']['housekeeping_time'], "%H:%M") # default: 03:00 + now = datetime.datetime.now(datetime.timezone.utc) + next_housekeeping_time = now.replace( + hour=config_house_time.hour, + minute=config_house_time.minute, + second=0, + microsecond=0) + + # if the app started after the housekeeping time, set it to the next day + if now > next_housekeeping_time: + next_housekeeping_time += datetime.timedelta(days=1) + return next_housekeeping_time + + def _on_housekeeping_tick(self, message_type): + """Check if it's time for 'Application.housekeeping!'. + If so, publish the message and set housekeeping time for the next day. + """ + if datetime.datetime.now(datetime.timezone.utc) > self.NextHousekeeping: + self.PubSub.publish("Application.housekeeping!") + self.NextHousekeeping += datetime.timedelta(days=1) + L.log( + LOG_NOTICE, + "Setting time for the next housekeeping: {} UTC".format( + self.NextHousekeeping.strftime("%Y-%m-%d %H:%M:%S") + ) + )
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/config.html b/old_docs/_build/htmln/_modules/asab/config.html new file mode 100644 index 000000000..667a1b86c --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/config.html @@ -0,0 +1,519 @@ + + + + + + + + asab.config — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.config

+import os
+import sys
+import glob
+import logging
+import inspect
+import platform
+import configparser
+import urllib.parse
+import collections.abc
+
+from . import utils
+
+
+L = logging.getLogger(__name__)
+
+
+
[docs]class ConfigParser(configparser.ConfigParser): + _syslog_sockets = { + 'Darwin': '/var/run/syslog' + } + + _syslog_format = { + 'Darwin': 'm' + } + + _default_values = { + + 'general': { + 'config_file': os.environ.get('ASAB_CONFIG', ''), + 'tick_period': 1, # In seconds + 'var_dir': os.path.expanduser('~/.' + os.path.splitext(os.path.basename(sys.argv[0]))[0]), + + 'changelog': '', + 'manifest': '', + + # Daemonization + 'pidfile': '!', # '!' has a special meaning => it transforms into platform specific location of pid file + 'working_dir': '.', + 'uid': '', + 'gid': '', + + 'housekeeping_time': '03:00', + }, + + "asab:metrics": { + "native_metrics": "true", + "web_requests_metrics": False, # False is a default, web_requests_metrics won't be generated. + "expiration": 60, + }, + + "logging": { + 'verbose': os.environ.get('ASAB_VERBOSE', False), + "app_name": os.path.basename(sys.argv[0]), + "sd_id": "sd", # Structured data id, see RFC5424 + "level": "NOTICE", + "levels": "", + }, + + "logging:console": { + "format": "%(asctime)s %(levelname)s %(name)s %(struct_data)s%(message)s", + "datefmt": "%d-%b-%Y %H:%M:%S.%f", + }, + + "logging:syslog": { + "enabled": "false", + # TODO: "facility": 'local1', + "address": _syslog_sockets.get(platform.system(), "/dev/log"), + "format": _syslog_format.get(platform.system(), "3"), + }, + + "logging:file": { + "path": "", + "format": "%(asctime)s %(levelname)s %(name)s %(struct_data)s%(message)s", + "datefmt": "%d-%b-%Y %H:%M:%S.%f", + "backup_count": 3, + "backup_max_bytes": 0, + "rotate_every": "", + }, + + "authz": { + # RBAC URL + # If !DISABLED! is specified, all authorization checks will be skipped + "rbac_url": "http://localhost:8081/rbac", + }, + + "library": { + "azure_cache": "false", # true or the actual path of where the cache should be located + }, + + # "passwords" section serves to securely store passwords + # in the configuration file; the passwords are not + # shown in the default API + # + # Usage in the configuration file: + # + # [connection:KafkaConnection] + # password=${passwords:kafka_password} + # + # [passwords] + # kafka_password=<MY_SECRET_PASSWORD> + "passwords": { + } + } + + + def add_defaults(self, dictionary): + """ Add defaults to a current configuration """ + + for section, keys in dictionary.items(): + section = str(section) + + if section not in self._sections: + try: + self.add_section(section) + except ValueError: + if self._strict: + raise + + for key, value in keys.items(): + + key = self.optionxform(str(key)) + if key in self._sections[section]: + # Value exists, no default needed + continue + + if value is not None: + value = str(value) + + if value is not None and "$" in value: + self.set(section, key, os.path.expandvars(value)) + else: + self.set(section, key, value) + + + def _traverse_includes(self, includes, this_dir): + """ Reads included config files. Supports nested including. """ + if '\n' in includes: + sep = '\n' + else: + sep = os.pathsep + + for include_glob in includes.split(sep): + include_glob = include_glob.strip() + + if len(include_glob) == 0: + continue + + if include_glob.startswith("zookeeper"): + self._include_from_zookeeper(include_glob) + + include_glob = os.path.expandvars(include_glob.strip()) + + for include in glob.glob(include_glob): + include = os.path.abspath(include) + + if include in self._included: + # Preventing infinite dependency looping + L.warn("Config file '{}' can be included only once.".format(include)) + continue + + self._included.add(include) + self.set('general', 'include', '') + + self._load_dir_stack.append(os.path.dirname(include)) + try: + self.read(include) + finally: + self._load_dir_stack.pop() + + includes = self.get('general', 'include', fallback='') + self._traverse_includes(includes, os.path.dirname(include_glob)) + + + def _load(self): + """ This method should be called only once, any subsequent call will lead to undefined behaviour """ + self._load_dir_stack = [] + self.config_contents_list = [] + self.config_name_list = [] + + config_fname = ConfigParser._default_values['general']['config_file'] + if config_fname != '': + if not os.path.isfile(config_fname): + print("Config file '{}' not found".format(config_fname), file=sys.stderr) + sys.exit(1) + + self._load_dir_stack.append(os.path.dirname(config_fname)) + try: + self.read(config_fname) + finally: + self._load_dir_stack.pop() + + includes = self.get('general', 'include', fallback='') + + self._included = set() + self._traverse_includes(includes, this_dir=os.path.dirname(config_fname)) + + self.add_defaults(ConfigParser._default_values) + + del self._load_dir_stack + + + def _include_from_zookeeper(self, zkurl): + # parse include value into hostname and path + url_pieces = urllib.parse.urlparse(zkurl) + url_path = url_pieces.path + url_netloc = url_pieces.netloc + + if not url_netloc: + if "asab:zookeeper" in self: + # Backward compatibility + url_netloc = self["asab:zookeeper"]["servers"] + else: + url_netloc = self["zookeeper"]["servers"] + + if url_path.startswith("./"): + if "asab:zookeeper" in self: + # Backward compatibility + url_path = self["asab:zookeeper"]["path"] + url_path[1:] + else: + url_path = self["zookeeper"]["path"] + url_path[1:] + + head, tail = os.path.split(url_path) + self.config_name_list.append(tail) + + try: + # Delayed import to minimize a hard dependecy footprint + import kazoo.client + zk = kazoo.client(url_netloc) + zk.start() + data = zk.get(url_path) + # convert bytes to string + encode_config = str(data, 'utf-8') + self.read_string(encode_config) + # Include in the list of config file contents + self.config_contents_list.append(encode_config) + zk.close() + except Exception as e: + L.error("Failed to obtain configuration from Zookeeper server(s): '{}'.".format(e)) + sys.exit(1) + + + def get_config_contents_list(self): + return self.config_contents_list, self.config_name_list + + + def getseconds(self, section, option, *, raw=False, vars=None, fallback=None, **kwargs): + if fallback is None: + fallback = configparser._UNSET + + return self._get_conv(section, option, utils.convert_to_seconds, raw=raw, vars=vars, fallback=fallback, **kwargs) + + + def geturl(self, section, option, raw=False, vars=None, fallback=None, scheme=None, **kwargs): + """Gets URL from config and removes all leading and trailing + whitespaces and trailing slashes. + + :param scheme: URL scheme(s) awaited. If None, scheme validation is bypassed. + :type scheme: str, tuple + :return: validated URL, raises ValueError when scheme requirements are not met if set. + """ + return utils.validate_url(self.get(section, option, raw=False, vars=None, fallback=fallback), scheme)
+ + +class _Interpolation(configparser.ExtendedInterpolation): + """Interpolation which expands environment variables in values.""" + + + def before_read(self, parser, section, option, value): + # Expand environment variables + if '$' in value: + os.environ['THIS_DIR'] = os.path.abspath(parser._load_dir_stack[-1]) + + value = os.path.expandvars(value) + + return super().before_read(parser, section, option, value) + + +Config = ConfigParser(interpolation=_Interpolation()) + + +class Configurable(object): + ''' + Usage: + class ConfigurableObject(asab.Configurable): + + ConfigDefaults = { + 'foo': 'bar', + } + + def __init__(self, config_section_name, config=None): + super().__init__(config_section_name=config_section_name, config=config) + + config_foo = self.Config.get('foo') + + ''' + + ConfigDefaults = {} + + + def __init__(self, config_section_name, config=None): + self.Config = ConfigObjectDict() + + for base_class in inspect.getmro(self.__class__): + if not hasattr(base_class, 'ConfigDefaults'): + continue + if len(base_class.ConfigDefaults) == 0: + continue + + # Merge config defaults of each base class in the 'inheritance' way + for key, value in base_class.ConfigDefaults.items(): + + if value is None: + raise ValueError("None value not allowed in ConfigDefaults. Found in %s:%s " % ( + config_section_name, key)) + + if key not in self.Config: + self.Config[key] = value + + if Config.has_section(config_section_name): + for key, value in Config.items(config_section_name): + self.Config[key] = value + + if config is not None: + self.Config.update(config) + + +# This is for backward compatibility +ConfigObject = Configurable + + +class ConfigObjectDict(collections.abc.MutableMapping): + + + def __init__(self): + self._data = {} + + + def __getitem__(self, key): + return self._data[key] + + + def __setitem__(self, key, value): + self._data[key] = value + + + def __delitem__(self, key): + del self._data[key] + + + def __iter__(self): + return iter(self._data) + + + def __len__(self): + return len(self._data) + + + def getboolean(self, key): + value = self._data[key] + if isinstance(value, bool): + return value + if value.lower() not in configparser.ConfigParser.BOOLEAN_STATES: + raise ValueError("Not a boolean: {}".format(value)) + return configparser.ConfigParser.BOOLEAN_STATES[value.lower()] + + + def getseconds(self, key): + value = self._data[key] + return utils.convert_to_seconds(value) + + + def getint(self, key): + value = self._data[key] + return int(value) + + + def getfloat(self, key): + value = self._data[key] + return float(value) + + + def geturl(self, key, scheme): + value = self._data[key] + return utils.validate_url(value, scheme) + + + def __repr__(self): + return "<%s %r>" % (self.__class__.__name__, self._data) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/library/providers/azurestorage.html b/old_docs/_build/htmln/_modules/asab/library/providers/azurestorage.html new file mode 100644 index 000000000..2715f2fb8 --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/library/providers/azurestorage.html @@ -0,0 +1,369 @@ + + + + + + + + asab.library.providers.azurestorage — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.library.providers.azurestorage

+import os
+import io
+import typing
+import hashlib
+import logging
+import tempfile
+import dataclasses
+import urllib.parse
+import xml.dom.minidom
+
+import aiohttp
+
+from ...config import Config
+from ..item import LibraryItem
+from .abc import LibraryProviderABC
+
+#
+
+L = logging.getLogger(__name__)
+
+
+#
+
+
+
[docs]class AzureStorageLibraryProvider(LibraryProviderABC): + ''' + AzureStorageLibraryProvider is a library provider that reads + from an Microsoft Azure Storage container. + + Configure by: + + azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER + + If Container Public Access Level is not set to "Public access", + then "Access Policy" must be created with "Read" and "List" permissions + and "Shared Access Signature" (SAS) query string must be added to a URL in a configuration: + + azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER?sv=2020-10-02&si=XXXX&sr=c&sig=XXXXXXXXXXXXXX + + ''' + + def __init__(self, library, path): + super().__init__(library) + assert path[:6] == "azure+" + + self.URL = urllib.parse.urlparse(path[6:]) + self.Model = None # Will be set by `_load_model` method + self.Path = path + + self.CacheDir = Config.get("library", "azure_cache") + if self.CacheDir == 'false': + self.CacheDir = None + elif self.CacheDir == 'true': + self.CacheDir = os.path.join(tempfile.gettempdir(), "asab.library.azure.{}".format(hashlib.sha256(path.encode('utf-8')).hexdigest())) + + # Ensure that the case directory exists + if self.CacheDir is not None: + try: + os.makedirs(self.CacheDir) + except FileExistsError: + pass # Cache directory already exists + + self.App.TaskService.schedule(self._start()) + + + async def _start(self): + await self._load_model() + if self.Model is not None: + await self._set_ready() + + + # TODO: Call this periodically + async def _load_model(self): + url = urllib.parse.urlunparse(urllib.parse.ParseResult( + scheme=self.URL.scheme, + netloc=self.URL.netloc, + path=self.URL.path, + params='', + query=self.URL.query + "&restype=container&comp=list", + fragment='' + )) + + async with aiohttp.ClientSession() as session: + async with session.get(url) as resp: + if resp.status == 200: + content = await resp.text() + else: + err = await resp.text() + L.warning("Failed to list blobs from `{}`:\n{}".format(url, err)) + return + + model = AzureDirectory("/", sub=dict()) + + dom = xml.dom.minidom.parseString(content) + for blob in dom.getElementsByTagName("Blob"): + path = get_xml_text(blob.getElementsByTagName("Name")) + + path = path.split('/') + curmodel = model + for i in range(len(path) - 1): + newmodel = curmodel.sub.get(path[i]) + if newmodel is None: + curmodel.sub[path[i]] = newmodel = AzureDirectory( + name='/' + '/'.join(path[:i + 1]), + sub=dict() + ) + + curmodel = newmodel + + curmodel.sub[path[-1]] = AzureItem( + name='/' + '/'.join(path) + ) + + self.Model = model + + # TODO: If the cache is active, remove items from the cache that: + # 1) are not in the list + # 2) their etag differs + + L.info("is connected.", struct_data={'path': self.Path}) + + + async def list(self, path: str) -> list: + if self.Model is None: + L.warning("Azure Storage library provider is not ready. Cannot list {}".format(path)) + raise RuntimeError("Not ready") + + assert path[:1] == '/' + assert '//' not in path + assert len(path) == 1 or path[-1:] != '/' + + if path == '/': + pathparts = [] + else: + pathparts = path.split("/")[1:] + + curmodel = self.Model + for p in pathparts: + curmodel = curmodel.sub.get(p) + if curmodel is None: + raise KeyError("Not '{}' found".format(path)) + if curmodel.type != 'dir': + raise KeyError("Not '{}' found".format(path)) + + items = [] + for i in curmodel.sub.values(): + items.append(LibraryItem( + name=i.name, + type=i.type, + providers=[self], + )) + + return items + + + async def read(self, path: str) -> typing.IO: + + assert path[:1] == '/' + assert '//' not in path + assert len(path) == 1 or path[-1:] != '/' + + headers = {} + + pathhash = hashlib.sha256(path.encode('utf-8')).hexdigest() + cachefname = os.path.join(self.CacheDir, pathhash) + if self.CacheDir is not None: + try: + with open(cachefname + '.etag', "r") as etagf: + etag = etagf.read() + # We found a local cached file with the etag, we will use that in the request + # if the request returns "304 Not Modified" then we will ship the local version of the file + headers['If-None-Match'] = etag + except FileNotFoundError: + pass + + + url = urllib.parse.urlunparse(urllib.parse.ParseResult( + scheme=self.URL.scheme, + netloc=self.URL.netloc, + path=self.URL.path + path, + params='', + query=self.URL.query, + fragment='' + )) + + async with aiohttp.ClientSession() as session: + async with session.get(url, headers=headers) as resp: + if resp.status == 200: + + etag = resp.headers.get('ETag') + + if self.CacheDir is not None and etag is not None: + output = open(cachefname, "w+b") + + with open(cachefname + '.etag', "w") as etagf: + etagf.write(etag) + + else: + # Store the response into the temporary file + # ... that's to avoid storing the whole (and possibly large) file in the memory + output = tempfile.TemporaryFile() + + async for chunk in resp.content.iter_chunked(16 * io.DEFAULT_BUFFER_SIZE): + output.write(chunk) + + elif resp.status == 304 and self.CacheDir is not None: # 304 is Not Modified + # The file should be read from cache + output = open(cachefname, "r+b") + + else: + L.warning("Failed to get blob:\n{}".format(await resp.text()), struct_data={'status': resp.status}) + return None + + # Rewind the file so the reader can start consuming from the beginning + output.seek(0) + return output
+ + +@dataclasses.dataclass +class AzureDirectory: + name: str + sub: dict + type: str = "dir" + + +@dataclasses.dataclass +class AzureItem: + name: str + type: str = "item" + + +def get_xml_text(nodelist): + rc = [] + for node in nodelist: + for textnode in node.childNodes: + if textnode.nodeType == textnode.TEXT_NODE: + rc.append(textnode.data) + return ''.join(rc) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/library/providers/filesystem.html b/old_docs/_build/htmln/_modules/asab/library/providers/filesystem.html new file mode 100644 index 000000000..c16ad2520 --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/library/providers/filesystem.html @@ -0,0 +1,326 @@ + + + + + + + + asab.library.providers.filesystem — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.library.providers.filesystem

+import io
+import os
+import os.path
+import stat
+import glob
+import struct
+import typing
+import logging
+
+from .abc import LibraryProviderABC
+from ..item import LibraryItem
+from ...timer import Timer
+
+try:
+	from .filesystem_inotify import inotify_init, inotify_add_watch, IN_CREATE, IN_ISDIR, IN_ALL_EVENTS, EVENT_FMT, EVENT_SIZE, IN_MOVED_TO, IN_IGNORED
+except OSError:
+	inotify_init = None
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+
[docs]class FileSystemLibraryProvider(LibraryProviderABC): + + def __init__(self, library, path, *, set_ready=True): + ''' + `set_ready` can be used to disable/defer `self._set_ready` call. + ''' + + super().__init__(library) + self.BasePath = os.path.abspath(path) + while self.BasePath.endswith("/"): + self.BasePath = self.BasePath[:-1] + + L.info("is connected.", struct_data={'path': path}) + # Filesystem is always ready (or you have a serious problem) + if set_ready: + self.App.TaskService.schedule(self._set_ready()) + + # Open inotify file descriptor + if inotify_init is not None: + self.FD = inotify_init() + + self.App.Loop.add_reader(self.FD, self._on_inotify_read) + self.AggrTimer = Timer(self.App, self._on_aggr_timer) + else: + self.FD = None + + self.AggrEvents = [] + self.WDs = {} + + + async def read(self, path: str) -> typing.IO: + + node_path = self.BasePath + path + + # File path must start with '/' + assert node_path[:1] == '/', "File path must start with a forward slash (/). For example: /library/Templates/file.json" + # File path must end with the extension + assert len(os.path.splitext(node_path)[1]) > 0, "File path must end with an extension. For example: /library/Templates/item.json" + # File cannot contain '//' + assert '//' not in node_path + + try: + return io.FileIO(node_path, 'rb') + + except FileNotFoundError: + return None + + except IsADirectoryError: + return None + + + async def list(self, path: str) -> list: + # This list method is completely synchronous, but it should look like asynchronous to make all list methods unified among providers. + return self._list(path) + + + def _list(self, path: str): + + node_path = self.BasePath + path + + # Directory path must start with '/' + assert node_path[:1] == '/', "Directory path must start with a forward slash (/). For example: /library/Templates/" + # Directory path must end with '/' + assert node_path[-1:] == '/', "Directory path must end with a forward slash (/). For example: /library/Templates/" + # Directory cannot contain '//' + assert '//' not in node_path + + exists = os.access(node_path, os.R_OK) and os.path.isdir(node_path) + if not exists: + raise KeyError(" '{}' not found".format(path)) + + items = [] + for fname in glob.iglob(os.path.join(node_path, "*")): + + fstat = os.stat(fname) + + assert fname.startswith(self.BasePath) + fname = fname[len(self.BasePath):] + + if stat.S_ISREG(fstat.st_mode): + ftype = "item" + elif stat.S_ISDIR(fstat.st_mode): + ftype = "dir" + fname += '/' + else: + ftype = "?" + + # Remove any component that starts with '.' + if any(x.startswith('.') for x in fname.split('/')): + continue + + items.append(LibraryItem( + name=fname, + type=ftype, + providers=[self], + )) + + return items + + + def _on_inotify_read(self): + data = os.read(self.FD, 64 * 1024) + + pos = 0 + while pos < len(data): + wd, mask, cookie, namesize = struct.unpack_from(EVENT_FMT, data, pos) + pos += EVENT_SIZE + namesize + name = (data[pos - namesize: pos].split(b'\x00', 1)[0]).decode() + + if mask & IN_ISDIR == IN_ISDIR and ((mask & IN_CREATE == IN_CREATE) or (mask & IN_MOVED_TO == IN_MOVED_TO)): + subscribed_path, child_path = self.WDs[wd] + self._subscribe_recursive(subscribed_path, "/".join([child_path, name])) + + if mask & IN_IGNORED == IN_IGNORED: + # cleanup + del self.WDs[wd] + continue + + self.AggrEvents.append((wd, mask, cookie, os.fsdecode(name))) + + self.AggrTimer.restart(0.2) + + + async def _on_aggr_timer(self): + to_advertise = set() + for wd, mask, cookie, name in self.AggrEvents: + # When wathed directory is being removed, more than one inotify events are being produced. + # When IN_IGNORED event occurs, respective wd is removed from self.WDs, + # but some other events (like IN_DELETE_SELF) get to this point, without having its reference in self.WDs. + subscribed_path, _ = self.WDs.get(wd, (None, None)) + to_advertise.add(subscribed_path) + self.AggrEvents.clear() + + for path in to_advertise: + if path is None: + continue + self.App.PubSub.publish("ASABLibrary.change!", self, path) + + + async def subscribe(self, path): + if not os.path.isdir(self.BasePath + path): + return + if self.FD is None: + return + self._subscribe_recursive(path, path) + + + def _subscribe_recursive(self, subscribed_path, path_to_be_listed): + binary = (self.BasePath + path_to_be_listed).encode() + wd = inotify_add_watch(self.FD, binary, IN_ALL_EVENTS) + if wd == -1: + L.error("Error in inotify_add_watch") + return + self.WDs[wd] = (subscribed_path, path_to_be_listed) + + try: + items = self._list(path_to_be_listed) + except KeyError: + # subscribing to non-existing directory is silent + return + + for item in items: + if item.type == "dir": + self._subscribe_recursive(subscribed_path, item.name) + + + async def finalize(self, app): + if self.FD is not None: + self.App.Loop.remove_reader(self.FD) + os.close(self.FD)
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/library/providers/git.html b/old_docs/_build/htmln/_modules/asab/library/providers/git.html new file mode 100644 index 000000000..aed0c694c --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/library/providers/git.html @@ -0,0 +1,330 @@ + + + + + + + + asab.library.providers.git — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.library.providers.git

+import os
+import tempfile
+import logging
+import hashlib
+
+from .filesystem import FileSystemLibraryProvider
+from ...config import Config
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+try:
+	import pygit2
+except ImportError:
+	L.critical("Please install pygit2 package to enable Git Library Provider. >>> pip install pygit2")
+	raise SystemExit("Application exiting... .")
+
+
+
[docs]class GitLibraryProvider(FileSystemLibraryProvider): + """ + Read-only git provider to read from remote repository. + It clones a remote git repository to a temporary directory and then uses the + FileSystemLibraryProvider to read the files. + To read from local git repository, please use FileSystemProvider. + + Configuration: + (Use either deploytoken, publickey+privatekey for SSH option, or username and password and HTTP access.) + + ``` + [library] + providers=git+<URL or deploy token>#<branch name> + + [library:git] + publickey=<absolute path to file> + privatekey=<absolute path to file> + username=johnsmith + password=secretpassword + repodir=<optional location of the repository cache> + ``` + """ + def __init__(self, library, path): + + # The branch can be optionally specified in the URL fragment (after '#') + split_path = path.split("#", 1) + if len(split_path) > 1: + self.Branch = split_path[-1] + self.URL = split_path[0][4:] + else: + self.Branch = None + self.URL = path[4:] + + self.Callbacks = pygit2.RemoteCallbacks(get_git_credentials(self.URL)) + + repodir = Config.get("library:git", "repodir", fallback=None) + if repodir is not None: + self.RepoPath = os.path.abspath(repodir) + else: + tempdir = tempfile.gettempdir() + self.RepoPath = os.path.join( + tempdir, + "asab.library.git", + hashlib.sha256(path.encode('utf-8')).hexdigest() + ) + + super().__init__(library, self.RepoPath, set_ready=False) + + self.GitRepository = None + + from ...proactor import Module + self.App.add_module(Module) + self.ProactorService = self.App.get_service("asab.ProactorService") + self.PullLock = False + + self.SubscribedPaths = set() + + self.App.TaskService.schedule(self.intialize_git_repo()) + self.App.PubSub.subscribe("Application.tick/60!", self._periodic_pull) + + + async def _periodic_pull(self, event_name): + """ + Changes in remote repository are being pulled every minute. `PullLock` flag ensures that only if previous "pull" has finished, new one can start. + """ + if self.GitRepository is None: + return + + if self.PullLock: + return + + self.PullLock = True + + try: + await self.ProactorService.execute(self.pull) + finally: + self.PullLock = False + + + async def intialize_git_repo(self): + + def init_task(): + if pygit2.discover_repository(self.RepoPath) is None: + # For a new repository, clone the remote bit + try: + os.makedirs(self.RepoPath, mode=0o700) + except FileExistsError: + pass + self.GitRepository = pygit2.clone_repository(self.URL, self.RepoPath, callbacks=self.Callbacks, checkout_branch=self.Branch) + else: + # For existing repository, pull the latest changes + self.GitRepository = pygit2.Repository(self.RepoPath) + self.pull() + + try: + await self.ProactorService.execute(init_task) + except Exception: + L.exception("Initialize git repo failed.") + + try: + assert self.GitRepository.remotes["origin"] is not None + except (KeyError, AssertionError): + L.error("Connection to remote git repository failed.") + # The library will not get ready ... maybe we can retry init_test() in a while + return + + await self._set_ready() + + + def fetch(self): + """ + It fetches the remote repository and returns the commit ID of the remote branch + + :return: The commit id of the latest commit on the remote repository. + """ + if self.GitRepository is None: + return None + + self.GitRepository.remotes["origin"].fetch(callbacks=self.Callbacks) + if self.Branch is None: + reference = self.GitRepository.lookup_reference("refs/remotes/origin/HEAD") + else: + reference = self.GitRepository.lookup_reference("refs/remotes/origin/{}".format(self.Branch)) + commit_id = reference.peel().id + return commit_id + + + def pull(self): + new_commit_id = self.fetch() + + # Before new head is set, check the diffs. If changes in subscribed directory occured, set `publish` flag. + + to_publish = [] + for path in self.SubscribedPaths: + for i in self.GitRepository.diff(self.GitRepository.head.target, new_commit_id).deltas: + if path == "/": + to_publish.append(path) + elif ("/" + i.old_file.path).startswith(path): + to_publish.append(path) + + if new_commit_id == self.GitRepository.head.target: + return + + # Reset HEAD + self.GitRepository.head.set_target(new_commit_id) + self.GitRepository.reset(new_commit_id, pygit2.GIT_RESET_HARD) + + # Once reset of the head is finished, PubSub message about the change in the subsrcibed directory gets published. + for path in to_publish: + self.App.PubSub.publish("ASABLibrary.change!", self, path) + + async def subscribe(self, path): + if not os.path.isdir(self.BasePath + path): + return + self.SubscribedPaths.add(path)
+ + +def get_git_credentials(url): + """ + Returns a pygit2.Credentials object that can be used to authenticate with the git repository + + :param url: The URL of the repository you want to clone + :return: A pygit2.Keypair object or a pygit2.UserPass object + """ + username = Config.get("library:git", "username", fallback=None) + password = Config.get("library:git", "password", fallback=None) + publickey = Config.get("library:git", "publickey", fallback=None) + privatekey = Config.get("library:git", "privatekey", fallback=None) + + if publickey is not None and privatekey is not None: + return pygit2.Keypair(username_from_url(url), publickey, privatekey, "") + + elif username is not None and password is not None: + return pygit2.UserPass(username, password) + + +def username_from_url(url): + return url.split("@")[0] +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/library/providers/zookeeper.html b/old_docs/_build/htmln/_modules/asab/library/providers/zookeeper.html new file mode 100644 index 000000000..f8f05b9ee --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/library/providers/zookeeper.html @@ -0,0 +1,416 @@ + + + + + + + + asab.library.providers.zookeeper — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.library.providers.zookeeper

+import io
+import typing
+import logging
+import functools
+import os.path
+import urllib.parse
+
+import kazoo.exceptions
+
+from .abc import LibraryProviderABC
+from ..item import LibraryItem
+from ...zookeeper import ZooKeeperContainer
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+
[docs]class ZooKeeperLibraryProvider(LibraryProviderABC): + + """ + + Configuration variant: + + + 1) ZooKeeper provider is fully configured from [zookeeper] section + + ``` + [zookeeper] + servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 + path=/library + + [library] + providers: + zk:// + ``` + + + 2) ZooKeeper provider is configured by `servers` from [zookeeper] section and path from URL + + Path will be `/library'. + + ``` + [zookeeper] + servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 + path=/else + + [library] + providers: + zk:///library + ``` + + + 2.1) ZooKeeper provider is configured by `servers` from [zookeeper] section and path from URL + + Path will be `/', this is a special case to 2) + + ``` + [zookeeper] + servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 + path=/else + + [library] + providers: + zk:/// + ``` + + 3) ZooKeeper provider is fully configured from URL + + ``` + [library] + providers: + zk://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/library + ``` + + 4) ZooKeeper provider is configured by `servers` from [zookeeper] section and joined `path` from [zookeeper] and + path from URL + + Path will be `/else/library' + + ``` + [zookeeper] + servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 + path=/else + + [library] + providers: + zk://./library + ``` + + If `path` from [zookeeper] section is missing, an application class name will be used + Ex. `/BSQueryApp/library' + + """ + + def __init__(self, library, path): + super().__init__(library) + + url_pieces = urllib.parse.urlparse(path) + + self.FullPath = url_pieces.scheme + '://' + self.BasePath = url_pieces.path.lstrip("/") + while self.BasePath.endswith("/"): + self.BasePath = self.BasePath[:-1] + + self.BasePath = '/' + self.BasePath + if self.BasePath == '/': + self.BasePath = '' + + if url_pieces.netloc in ["", "."]: + # if netloc is not provided `zk:///path`, then use `zookeeper` section from config + config_section_name = 'zookeeper' + z_url = None + else: + config_section_name = '' + z_url = path + + # Initialize ZooKeeper client + zksvc = self.App.get_service("asab.ZooKeeperService") + self.ZookeeperContainer = ZooKeeperContainer( + zksvc, + config_section_name=config_section_name, + z_path=z_url + ) + self.Zookeeper = self.ZookeeperContainer.ZooKeeper + + if config_section_name == 'zookeeper': + self.FullPath += self.ZookeeperContainer.Config['servers'] + else: + self.FullPath += url_pieces.netloc + + # Handle `zk://` configuration + if z_url is None and url_pieces.netloc == "" and url_pieces.path == "" and self.ZookeeperContainer.Path != '': + self.BasePath = '/' + self.ZookeeperContainer.Path + + # Handle `zk://./path` configuration + if z_url is None and url_pieces.netloc == "." and self.ZookeeperContainer.Path != '': + self.BasePath = '/' + self.ZookeeperContainer.Path + self.BasePath + + self.FullPath += self.BasePath + + self.VersionNodePath = self.build_path('/.version.yaml') + self.Version = None # Will be read when a library become ready + self.VersionWatch = None + + self.App.PubSub.subscribe("ZooKeeperContainer.started!", self._on_zk_ready) + self.App.PubSub.subscribe("Application.tick/60!", self._get_version_counter) + + + async def finalize(self, app): + """ + The `finalize` function is called when the application is shutting down + """ + await self.Zookeeper._stop() + + + async def _on_zk_ready(self, event_name, zkcontainer): + """ + When the Zookeeper container is ready, set the self.Zookeeper property to the Zookeeper object. + """ + if zkcontainer != self.ZookeeperContainer: + return + + L.info("is connected.", struct_data={'path': self.FullPath}) + + def on_version_changed(version, event): + self.App.Loop.call_soon_threadsafe(self._check_version_counter, version) + + def install_watcher(): + return kazoo.recipe.watchers.DataWatch(self.Zookeeper.Client, self.VersionNodePath, on_version_changed) + + self.VersionWatch = await self.Zookeeper.ProactorService.execute(install_watcher) + + await self._set_ready() + + + async def _get_version_counter(self, event_name=None): + if self.Zookeeper is None: + return + + version = await self.Zookeeper.get_data(self.VersionNodePath) + await self.Zookeeper.ProactorService.execute(self._check_version_counter, version) + + + def _check_version_counter(self, version): + # If version is `None` aka `/.version.yaml` doesn't exists, then assume version -1 + if version is not None: + try: + version = int(version) + except ValueError: + version = 1 + else: + version = 1 + + if self.Version is None: + # Initial grab of the version + self.Version = int(version) + return + + if self.Version == int(version): + # The version has not changed + return + + L.info("Version changed", struct_data={'version': version, 'name': self.Library.Name}) + self.App.PubSub.publish("Library.changed!", self.Library, self) + + + async def read(self, path: str) -> typing.IO: + if self.Zookeeper is None: + L.warning("Zookeeper Client has not been established (yet). Cannot read {}".format(path)) + return None + + node_path = self.build_path(path) + + try: + node_data = await self.Zookeeper.get_data(node_path) + except kazoo.exceptions.NoNodeError: + return None + + # Consider adding other exceptions from Kazoo to indicate common non-critical errors + + if node_data is not None: + return io.BytesIO(initial_bytes=node_data) + else: + return None + + + async def list(self, path: str) -> list: + if self.Zookeeper is None: + L.warning("Zookeeper Client has not been established (yet). Cannot list {}".format(path)) + raise RuntimeError("Not ready") + + node_path = self.build_path(path) + + nodes = await self.Zookeeper.get_children(node_path) + if nodes is None: + raise KeyError("Not '{}' found".format(node_path)) + + items = [] + for node in nodes: + + # Remove any component that starts with '.' + startswithdot = functools.reduce(lambda x, y: x or y.startswith('.'), node.split(os.path.sep), False) + if startswithdot: + continue + + if '.' in node: # We detect files in zookeeper by presence of the dot in the filename, + fname = path + node + ftype = "item" + else: + fname = path + node + '/' + ftype = "dir" + + items.append(LibraryItem( + name=fname, + type=ftype, + providers=[self], + )) + + return items + + + def build_path(self, path): + """ + It takes a path in the library and transforms in into a path within Zookeeper. + It does also series of sanity checks (asserts). + + IMPORTANT: If you encounter asserting failure, don't remove assert. + It means that your code is incorrect. + """ + assert path[:1] == '/' + if path != '/': + node_path = self.BasePath + path + else: + node_path = self.BasePath + + # Zookeeper path should not have forward slash at the end of path + node_path = node_path.rstrip("/") + + assert '//' not in node_path + assert node_path[0] == '/' + + return node_path
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/library/service.html b/old_docs/_build/htmln/_modules/asab/library/service.html new file mode 100644 index 000000000..79ef11b46 --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/library/service.html @@ -0,0 +1,527 @@ + + + + + + + + asab.library.service — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.library.service

+import re
+import io
+import time
+import os.path
+import typing
+import tarfile
+import asyncio
+import logging
+import tempfile
+import functools
+import configparser
+
+import yaml
+
+from ..abc import Service
+from ..config import Config
+from ..log import LOG_NOTICE
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+
[docs]class LibraryService(Service): + ''' + ASAB library (aka LibraryService) is an abstration for unified filesystem-like access to resources. + In the cluster/cloud microservice architectures, it is imperative that all microservices have access to unified resources. + There are technologies such as Apache Zookeeper that provides means for it. + + ASAB library builts on top of this concept and brings that into the ASAB microservice. + + ASAB library is designed to be read-only. + It also allows to "stack" various libraries into one view (overlayed) that merges content of each library into one united space. + + Configuration: + + ``` + [library] + providers: + provider+1:// + provider+2:// + provider+3:// + ``` + + The order of providers *IS* important, the priority (or layering) is top-down. + + Each library provider is specified by URL/URI schema: + + * `zk://` or `zookeeper://` for ZooKeeper provider + * `file://` or local path for FileSystem provider + * `azure+https://` for Microsoft Azure Storage provider. + + The first provider is also responsible for providing `/.disabled.yaml` that controls a visibility of items. + If `/.disabled.yaml` is not present, then is considered empty. + + A library is created in "not ready" state, each provider then inform library when it is ready (eg. Zookeeper provider needs to connect to Zookeeper servers). + Only after all providers are ready, the library itself become ready. + The library indicates that by the PubSub event `ASABLibrary.ready!`. + + ''' + + def __init__(self, app, service_name, paths=None): + ''' + The library service is designed to "exists" in multiple instances, + with different `paths` setup. + For that reason, you have to provide unique `service_name` + and there is no _default_ value for that. + + If `paths` are not provided, they are fetched from `[library]providers` configuration. + ''' + + super().__init__(app, service_name) + self.Libraries = list() + self.Disabled = {} + + if paths is None: + try: + paths = Config.get("library", "providers") + except configparser.NoOptionError: + L.critical("'providers' option is not present in configuration section 'library'.") + raise SystemExit("Exit due to a critical configuration error.") + + if isinstance(paths, str): + paths = re.split(r"\s+", paths) + + for path in paths: + self._create_library(path) + app.PubSub.subscribe("Application.tick/60!", self.on_tick) + + + async def finalize(self, app): + while len(self.Libraries) > 0: + lib = self.Libraries.pop(-1) + await lib.finalize(self.App) + + + async def on_tick(self, message_type): + await self._read_disabled() + + + def _create_library(self, path): + library_provider = None + if path.startswith('zk://') or path.startswith('zookeeeper://'): + from .providers.zookeeper import ZooKeeperLibraryProvider + library_provider = ZooKeeperLibraryProvider(self, path) + + elif path.startswith('./') or path.startswith('/') or path.startswith('file://'): + from .providers.filesystem import FileSystemLibraryProvider + library_provider = FileSystemLibraryProvider(self, path) + + elif path.startswith('azure+https://'): + from .providers.azurestorage import AzureStorageLibraryProvider + library_provider = AzureStorageLibraryProvider(self, path) + + elif path.startswith('git+'): + from .providers.git import GitLibraryProvider + library_provider = GitLibraryProvider(self, path) + + elif path == '' or path.startswith("#") or path.startswith(";"): + # This is empty or commented line + return + + else: + L.error("Incorrect/unknown provider for '{}'".format(path)) + raise SystemExit("Exit due to a critical configuration error.") + + self.Libraries.append(library_provider) + + + def is_ready(self): + """ + It checks if all the libraries are ready. + + :return: A boolean value. + """ + return functools.reduce( + lambda x, provider: provider.IsReady and x, + self.Libraries, + True + ) + + + async def _set_ready(self, provider): + if provider == self.Libraries[0]: + await self._read_disabled() + + if self.is_ready(): + L.log(LOG_NOTICE, "is ready.", struct_data={'name': self.Name}) + self.App.PubSub.publish("ASABLibrary.ready!", self) + + +
[docs] async def read(self, path: str, tenant: str = None) -> typing.IO: + """ + Read the content of the library item specified by `path`. + `None` is returned if the item is not found in the library. + + If the item is disabled (globally or for specified tenant) then None is returned. + + Example of use: + + ``` + itemio = await library.read('/path', 'tenant') + if itemio is not None: + with itemio: + return itemio.read() + ``` + + :param path: The path to the file, `LibraryItem.name` can be used directly + :param tenant: The tenant to apply. If not specified, the global access is assumed + :return: I/O stream (read) with the content of the libary item. + """ + # item path must start with '/' + assert path[:1] == '/', "Item path must start with a forward slash (/). For example: /library/Templates/item.json" + # Item path must end with the extension + assert len(os.path.splitext(path)[1]) > 0, "Item path must end with an extension. For example: /library/Templates/item.json" + + if self.check_disabled(path, tenant=tenant): + return None + + for library in self.Libraries: + itemio = await library.read(path) + if itemio is None: + continue + return itemio + + return None
+ + +
[docs] async def list(self, path="/", tenant=None, recursive=False): + """ + List the directory of the library specified by the path. + It returns a list of `LibraryItem` entris. + + Tenant is an optional parameter to list method for "disable" evaluation. + and default recursive is False. + + When tenant=None + The method returns list of items that are enabled (not disabled). + + When tenant='xxxxx' + The method returns list of items that are enabled (not disabled) for tenant 'xxxxx'. + + When recursive=True + The method returns list of items that are located at `path` and in subdirectories of that location. + + When recursive=False + The method returns list of items that are located at `path` + """ + + # Directory path must start with '/' + assert path[:1] == '/', "Directory path must start with a forward slash (/). For example: /library/Templates/" + # Directory path must end with '/' + assert path[-1:] == '/', "Directory path must end with a forward slash (/). For example: /library/Templates/" + # Directory path cannot contain '//' + assert '//' not in path + + # List requested level using all available providers + items = await self._list(path, tenant, providers=self.Libraries) + + if recursive: + # If recursive scan is requested, then iterate thru list of items + # find 'dir' types there and list them. + # Output of this list is attached to the list for recursive scan + # and also to the final output + recitems = list(items[:]) + + while len(recitems) > 0: + + item = recitems.pop(0) + if item.type != 'dir': + continue + + child_items = await self._list(item.name, tenant, providers=item.providers) + items.extend(child_items) + recitems.extend(child_items) + + return items
+ + + async def _list(self, path, tenant, providers): + + # Execute the list query in all providers in-parallel + result = await asyncio.gather(*[ + library.list(path) + for library in providers + ], return_exceptions=True) + + items = [] + uniq = dict() + for ress in result: + + if isinstance(ress, KeyError): + # The path doesn't exists in the provider + continue + + if isinstance(ress, Exception): + L.exception("Error when listing items from provider", exc_info=ress) + continue + + for item in ress: + + item.disabled = self.check_disabled(item.name, tenant=tenant) + + # If the item already exists, merge it + pitem = uniq.get(item.name) + if pitem is not None: + if pitem.type == 'dir' and item.type == 'dir': + # Directories are joined + pitem.providers.extend(item.providers) + + # Other item types are skipped + continue + + uniq[item.name] = item + items.append(item) + + items.sort(key=lambda x: x.name) + + return items + + + async def _read_disabled(self): + # `.disabled.yaml` is read from the first configured library + # It is applied on all libraries in the configuration. + disabled = await self.Libraries[0].read('/.disabled.yaml') + if disabled is None: + self.Disabled = {} + else: + try: + self.Disabled = yaml.safe_load(disabled) + if self.Disabled is None: + self.Disabled = {} + else: + # Disabled must be a dictionary object + assert (isinstance(self.Disabled, dict)), "The 'Disabled' attribute must be a dictionary instance." + except Exception: + self.Disabled = {} + L.exception("Failed to parse '/.disabled.yaml'") + + + def check_disabled(self, path, tenant=None): + """ + If the item is disabled for everybody, or if the item is disabled for the specified tenant, then + return True. Otherwise, return False + + :param path: The path to the item + :param tenant: The tenant name + :return: Boolean + """ + + disabled = self.Disabled.get(path) + if disabled is None: + return False + + if disabled == '*': + # Item is disabled for everybody + return True + + if tenant is not None and tenant in disabled: + # Item is disabled for a specified tenant + return True + + return False + + +
[docs] async def export(self, path="/", tenant=None, remove_path=False): + """ + It takes a path, and returns a file-like object containing a gzipped tar archive of the library contents of + that path + + :param path: The path to export, defaults to / (optional) + :param tenant: The tenant to use for the operation + :param remove_path: If True, the path will be removed from the tar file, defaults to False + (optional) + :return: A file object. + """ + + # Directory path must start with '/' + assert path[:1] == '/', "Directory path must start with a forward slash (/). For example: /library/Templates/" + # Directory path must end with '/' + assert path[-1:] == '/', "Directory path must end with a forward slash (/). For example: /library/Templates/" + # Directory path cannot contain '//' + assert '//' not in path + + fileobj = tempfile.TemporaryFile() + tarobj = tarfile.open(name=None, mode='w:gz', fileobj=fileobj) + + # List requested level using all available providers + only_first = [self.Libraries[0]] + items = await self._list(path, tenant, providers=only_first) + + recitems = list(items[:]) + + while len(recitems) > 0: + + item = recitems.pop(0) + if item.type != 'dir': + continue + + child_items = await self._list(item.name, tenant, providers=item.providers) + items.extend(child_items) + recitems.extend(child_items) + + for item in items: + if item.type != 'item': + continue + my_data = await self.Libraries[0].read(item.name) + if remove_path: + assert item.name.startswith(path) + tar_name = item.name[len(path):] + else: + tar_name = item.name + info = tarfile.TarInfo(tar_name) + my_data.seek(0, io.SEEK_END) + info.size = my_data.tell() + my_data.seek(0, io.SEEK_SET) + info.mtime = time.time() + tarobj.addfile(tarinfo=info, fileobj=my_data) + + tarobj.close() + fileobj.seek(0) + return fileobj
+ + +
[docs] async def subscribe(self, paths): + """ + It subscribes to the changes in the library + :param paths: A list of absolute paths to subscribe to + """ + for path in paths: + assert path[:1] == '/', "Absolute path must be used when subscribing to the library changes" + + for provider in self.Libraries: + await provider.subscribe(path)
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/log.html b/old_docs/_build/htmln/_modules/asab/log.html new file mode 100644 index 000000000..53871fae3 --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/log.html @@ -0,0 +1,605 @@ + + + + + + + + asab.log — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.log

+import asyncio
+import datetime
+import logging
+import logging.handlers
+import os
+import pprint
+import queue
+import re
+import socket
+import sys
+import time
+import traceback
+import urllib.parse
+
+from .config import Config
+from .timer import Timer
+
+# Non-error/warning type of message that is visible without -v flag
+LOG_NOTICE = 25
+logging.addLevelName(LOG_NOTICE, "NOTICE")
+
+
+
[docs]class Logging(object): + + + def __init__(self, app): + self.RootLogger = logging.getLogger() + + self.ConsoleHandler = None + self.FileHandler = None + self.SyslogHandler = None + + if not self.RootLogger.hasHandlers(): + + # Add console logger if needed + if os.isatty(sys.stdout.fileno()) or os.environ.get('ASABFORCECONSOLE', '0') != '0': + self._configure_console_logging() + + # Initialize file handler + file_path = Config["logging:file"]["path"] + + if len(file_path) > 0: + + # Ensure file path + directory = os.path.dirname(file_path) + if not os.path.exists(directory): + os.makedirs(directory) + + self.FileHandler = logging.handlers.RotatingFileHandler( + file_path, + backupCount=Config.getint("logging:file", "backup_count"), + maxBytes=Config.getint("logging:file", "backup_max_bytes"), + ) + self.FileHandler.setLevel(logging.DEBUG) + self.FileHandler.setFormatter(StructuredDataFormatter( + fmt=Config["logging:file"]["format"], + datefmt=Config["logging:file"]["datefmt"], + sd_id=Config["logging"]["sd_id"], + )) + self.RootLogger.addHandler(self.FileHandler) + + rotate_every = Config.get("logging:file", "rotate_every") + if rotate_every != '': + rotate_every = re.match(r"^([0-9]+)([dMHs])$", rotate_every) + if rotate_every is not None: + i, u = rotate_every.groups() + i = int(i) + if i <= 0: + self.RootLogger.error("Invalid 'rotate_every' configuration value.") + else: + if u == 'H': + i = i * 60 * 60 + elif u == 'M': + i = i * 60 + elif u == 'd': + i = i * 60 * 60 * 24 + elif u == 's': + pass + + # PubSub is not ready at this moment, we need to create timer in a future + async def schedule(app, interval): + self.LogRotatingTime = Timer(app, self._on_tick_rotate_check, autorestart=True) + self.LogRotatingTime.start(i) + asyncio.ensure_future(schedule(app, i)) + + else: + self.RootLogger.error("Invalid 'rotate_every' configuration value.") + + # Initialize syslog + if Config["logging:syslog"].getboolean("enabled"): + + address = Config["logging:syslog"]["address"] + + if address[:1] == '/': + self.SyslogHandler = AsyncIOHandler(app.Loop, socket.AF_UNIX, socket.SOCK_DGRAM, address) + + else: + url = urllib.parse.urlparse(address) + + if url.scheme == 'tcp': + self.SyslogHandler = AsyncIOHandler(app.Loop, socket.AF_INET, socket.SOCK_STREAM, ( + url.hostname if url.hostname is not None else 'localhost', + url.port if url.port is not None else logging.handlers.SYSLOG_UDP_PORT + )) + + elif url.scheme == 'udp': + self.SyslogHandler = AsyncIOHandler(app.Loop, socket.AF_INET, socket.SOCK_DGRAM, ( + url.hostname if url.hostname is not None else 'localhost', + url.port if url.port is not None else logging.handlers.SYSLOG_UDP_PORT + )) + + elif url.scheme == 'unix-connect': + self.SyslogHandler = AsyncIOHandler(app.Loop, socket.AF_UNIX, socket.SOCK_STREAM, url.path) + + elif url.scheme == 'unix-sendto': + self.SyslogHandler = AsyncIOHandler(app.Loop, socket.AF_UNIX, socket.SOCK_DGRAM, url.path) + + else: + self.RootLogger.warning("Invalid logging:syslog address '{}'".format(address)) + address = None + + if self.SyslogHandler is not None: + self.SyslogHandler.setLevel(logging.DEBUG) + format = Config["logging:syslog"]["format"] + if format == 'm': + self.SyslogHandler.setFormatter(MacOSXSyslogFormatter(sd_id=Config["logging"]["sd_id"])) + elif format == '5': + self.SyslogHandler.setFormatter(SyslogRFC5424Formatter(sd_id=Config["logging"]["sd_id"])) + else: + self.SyslogHandler.setFormatter(SyslogRFC3164Formatter(sd_id=Config["logging"]["sd_id"])) + self.RootLogger.addHandler(self.SyslogHandler) + + # No logging is configured + if self.ConsoleHandler is None and self.FileHandler is None and self.SyslogHandler is None: + # Let's check if we run in Docker and if so, then log on stderr + from .docker import running_in_docker + if running_in_docker(): + self._configure_console_logging() + + else: + self.RootLogger.warning("Logging seems to be already configured. Proceed with caution.") + + if Config["logging"].getboolean("verbose"): + self.RootLogger.setLevel(logging.DEBUG) + else: + self.RootLogger.setLevel(Config["logging"]["level"]) + + # Fine-grained log level configurations + levels = Config["logging"].get('levels') + for levelconf in levels.split('\n'): + levelconf = levelconf.strip() + if len(levelconf) == 0 or levelconf.startswith('#') or levelconf.startswith(';'): + continue + loggername, levelname = levelconf.split(' ', 1) + level = logging.getLevelName(levelname.upper()) + logging.getLogger(loggername).setLevel(level) + + +
[docs] def rotate(self): + if self.FileHandler is not None: + self.RootLogger.log(LOG_NOTICE, "Rotating logs") + self.FileHandler.doRollover()
+ + + async def _on_tick_rotate_check(self): + if self.FileHandler is not None: + if self.FileHandler.stream.tell() > 1000: + self.rotate() + + + def _configure_console_logging(self): + self.ConsoleHandler = logging.StreamHandler(stream=sys.stderr) + + # Disable colors when running in container + from .docker import running_in_container + if running_in_container(): + self.ConsoleHandler.setFormatter(StructuredDataFormatter( + fmt=Config["logging:console"]["format"], + datefmt=Config["logging:console"]["datefmt"], + sd_id=Config["logging"]["sd_id"], + use_color=False + )) + else: + self.ConsoleHandler.setFormatter(StructuredDataFormatter( + fmt=Config["logging:console"]["format"], + datefmt=Config["logging:console"]["datefmt"], + sd_id=Config["logging"]["sd_id"], + use_color=True + )) + + self.ConsoleHandler.setLevel(logging.DEBUG) + self.RootLogger.addHandler(self.ConsoleHandler)
+ + +class _StructuredDataLogger(logging.Logger): + ''' +This class extends a default python logger class, specifically by adding ``struct_data`` parameter to logging functions. +It means that you can use expressions such as ``logger.info("Hello world!", struct_data={'key':'value'})``. + ''' + + def _log(self, level, msg, args, exc_info=None, struct_data=None, extra=None, stack_info=False): + if struct_data is not None: + if extra is None: + extra = dict() + extra['_struct_data'] = struct_data + + super()._log(level, msg, args, exc_info=exc_info, extra=extra, stack_info=stack_info) + + +logging.setLoggerClass(_StructuredDataLogger) + + +
[docs]class StructuredDataFormatter(logging.Formatter): + ''' + The logging formatter that renders log messages that includes structured data. + ''' + + empty_sd = "" + BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) + + + def __init__(self, facility=16, fmt=None, datefmt=None, style='%', sd_id='sd', use_color: bool = False): + super().__init__(fmt, datefmt, style) + self.SD_id = sd_id + self.Facility = facility + self.UseColor = use_color + + +
[docs] def format(self, record): + ''' + Format the specified record as text. + ''' + + record.struct_data = self.render_struct_data(record.__dict__.get("_struct_data")) + + # The Priority value is calculated by first multiplying the Facility number by 8 and then adding the numerical value of the Severity. + if record.levelno <= logging.DEBUG: + severity = 7 # Debug + color = self.BLUE + elif record.levelno <= logging.INFO: + severity = 6 # Informational + color = self.GREEN + elif record.levelno <= LOG_NOTICE: + severity = 5 # Notice + color = self.CYAN + elif record.levelno <= logging.WARNING: + severity = 4 # Warning + color = self.YELLOW + elif record.levelno <= logging.ERROR: + severity = 3 # Error + color = self.RED + elif record.levelno <= logging.CRITICAL: + severity = 2 # Critical + color = self.MAGENTA + else: + severity = 1 # Alert + color = self.WHITE + + if self.UseColor: + levelname = record.levelname + levelname_color = _COLOR_SEQ % (30 + color) + levelname + _RESET_SEQ + record.levelname = levelname_color + + record.priority = (self.Facility << 3) + severity + return super().format(record)
+ + +
[docs] def formatTime(self, record, datefmt=None): + ''' + Return the creation time of the specified LogRecord as formatted text. + ''' + + try: + ct = datetime.datetime.fromtimestamp(record.created) + if datefmt is not None: + s = ct.strftime(datefmt) + else: + t = ct.strftime("%Y-%m-%d %H:%M:%S") + s = "%s.%03d" % (t, record.msecs) + return s + except BaseException as e: + print("ERROR when logging: {}".format(e), file=sys.stderr) + return str(ct)
+ + +
[docs] def render_struct_data(self, struct_data): + ''' + Return the string with structured data. + ''' + + if struct_data is None: + return self.empty_sd + + else: + return "[{sd_id} {sd_params}] ".format( + sd_id=self.SD_id, + sd_params=" ".join(['{}="{}"'.format(key, val) for key, val in struct_data.items()]))
+ + + +def _loop_exception_handler(loop, context): + ''' + This is an logging exception handler for asyncio. + It's purpose is to nicely log any unhandled excpetion that arises in the asyncio tasks. + ''' + + exception = context.pop('exception', None) + + message = context.pop('message', '') + if len(message) > 0: + message += '\n' + + if len(context) > 0: + message += pprint.pformat(context) + + if exception is not None: + ex_traceback = exception.__traceback__ + tb_lines = [line.rstrip('\n') for line in traceback.format_exception(exception.__class__, exception, ex_traceback)] + message += '\n' + '\n'.join(tb_lines) + + logging.getLogger().error(message) + + +
[docs]class MacOSXSyslogFormatter(StructuredDataFormatter): + """ + It implements Syslog formatting for Mac OSX syslog (aka format ``m``). + """ + + def __init__(self, fmt=None, datefmt=None, style='%', sd_id='sd'): + fmt = '<%(priority)s>%(asctime)s {app_name}[{proc_id}]: %(levelname)s %(name)s %(struct_data)s%(message)s\000'.format( + app_name=Config["logging"]["app_name"], + proc_id=os.getpid(), + ) + + # Initialize formatter + super().__init__(fmt=fmt, datefmt='%b %d %H:%M:%S', style=style, sd_id=sd_id)
+ + +
[docs]class SyslogRFC3164Formatter(StructuredDataFormatter): + """ + Implementation of a legacy or BSD Syslog (RFC 3164) formatting (aka format ``3``). + """ + + def __init__(self, fmt=None, datefmt=None, style='%', sd_id='sd'): + fmt = '<%(priority)s>%(asctime)s {hostname} {app_name}[{proc_id}]:%(levelname)s %(name)s %(struct_data)s%(message)s\000'.format( + app_name=Config["logging"]["app_name"], + hostname=socket.gethostname(), + proc_id=os.getpid(), + ) + + # Initialize formatter + super().__init__(fmt=fmt, datefmt='%b %d %H:%M:%S', style=style, sd_id=sd_id)
+ + +
[docs]class SyslogRFC5424Formatter(StructuredDataFormatter): + """ + It implements Syslog formatting for Mac OSX syslog (aka format ``5``). + """ + + empty_sd = " " + + def __init__(self, fmt=None, datefmt=None, style='%', sd_id='sd'): + fmt = '<%(priority)s>1 %(asctime)s.%(msecs)dZ {hostname} {app_name} {proc_id} %(name)s [log l="%(levelname)s"]%(struct_data)s%(message)s'.format( + app_name=Config["logging"]["app_name"], + hostname=socket.gethostname(), + proc_id=os.getpid(), + ) + + # Initialize formatter + super().__init__(fmt=fmt, datefmt='%Y-%m-%dT%H:%M:%S', style=style, sd_id=sd_id) + + # Convert time to GMT + self.converter = time.gmtime
+ + +
[docs]class AsyncIOHandler(logging.Handler): + + ''' +A logging handler similar to a standard ``logging.handlers.SocketHandler`` that utilizes ``asyncio``. +It implements a queue for decoupling logging from a networking. The networking is fully event-driven via ``asyncio`` mechanisms. + ''' + + def __init__(self, loop, family, sock_type, address, facility=logging.handlers.SysLogHandler.LOG_LOCAL1): + logging.Handler.__init__(self) + + self._family = family + self._type = sock_type + self._address = address + self._loop = loop + + self._socket = None + self._reset() + + self._queue = queue.Queue() + + self._loop.call_soon(self._connect, self._loop) + + + def _reset(self): + self._write_ready = False + if self._socket is not None: + self._loop.remove_writer(self._socket) + self._loop.remove_reader(self._socket) + self._socket.close() + self._socket = None + + + def _connect(self, loop): + self._reset() + + try: + self._socket = socket.socket(self._family, self._type) + self._socket.setblocking(0) + self._socket.connect(self._address) + except Exception as e: + print("Error when opening syslog connection to '{}'".format(self._address), e, file=sys.stderr) + return + + self._loop.add_writer(self._socket, self._on_write) + self._loop.add_reader(self._socket, self._on_read) + + + def _on_write(self): + self._write_ready = True + self._loop.remove_writer(self._socket) + + while not self._queue.empty(): + # TODO: Handle eventual error in writing -> break the cycle and restart on write handler + msg = self._queue.get_nowait() + self._socket.sendall(msg) + + + def _on_read(self): + try: + _ = self._socket.recvfrom(1024) + # We receive "something" ... let's ignore that! + return + except Exception as e: + print("Error on the syslog socket '{}'".format(self._address), e, file=sys.stderr) + + # Close a socket - there is no reason for reading or socket is actually closed + self._reset() + + +
[docs] def emit(self, record): + ''' + This is the entry point for log entries. + ''' + try: + msg = self.format(record).encode('utf-8') + + if self._write_ready: + try: + self._socket.sendall(msg) + except Exception as e: + print("Error when writing to syslog '{}'".format(self._address), e, file=sys.stderr) + self._enqueue(msg) + + else: + self._enqueue(record) + + + except Exception as e: + print("Error when emit to syslog '{}'".format(self._address), e, file=sys.stderr) + self.handleError(record)
+ + + def _enqueue(self, record): + self._queue.put(record)
+ + +_RESET_SEQ = "\033[0m" +_COLOR_SEQ = "\033[1;%dm" +_BOLD_SEQ = "\033[1m" +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/metrics/metrics.html b/old_docs/_build/htmln/_modules/asab/metrics/metrics.html new file mode 100644 index 000000000..1697eb1a3 --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/metrics/metrics.html @@ -0,0 +1,656 @@ + + + + + + + + asab.metrics.metrics — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.metrics.metrics

+import abc
+import copy
+import time
+from .. import Config
+
+
+class Metric(abc.ABC):
+
+	def __init__(self, init_values=None):
+		self.Init = init_values
+		self.Storage = None
+		self.StaticTags = dict()
+
+		# Expiration is relevant only to WithDynamicTagsMixIn metrics
+		self.Expiration = float(Config.get("asab:metrics", "expiration"))
+
+	def _initialize_storage(self, storage: dict):
+		assert storage['type'] is None
+		storage['type'] = self.__class__.__name__
+
+		self.Storage = storage
+		self.add_field(self.StaticTags)
+
+	def add_field(self, tags):
+		raise NotImplementedError(":-(")
+
+	def flush(self, now):
+		pass
+
+
+
[docs]class Gauge(Metric): + + def add_field(self, tags): + field = { + "tags": tags, + "values": self.Init.copy() if self.Init is not None else dict(), + } + self.Storage['fieldset'].append(field) + self._field = field + return field + +
[docs] def set(self, name: str, value): + self._field['values'][name] = value
+ + +
[docs]class Counter(Metric): + + def add_field(self, tags): + field = { + "tags": tags, + "values": self.Init.copy() if self.Init is not None else dict(), + "actuals": self.Init.copy() if self.Init is not None else dict(), + } + self.Storage['fieldset'].append(field) + self._actuals = field['actuals'] + return field + +
[docs] def add(self, name, value, init_value=None): + """ + :param name: name of the counter + :param value: value to be added to the counter + + Adds the `value` to the counter Values specified by `name`. + If `name` is not in Counter Values, it will be added. + + """ + try: + self._actuals[name] += value + except KeyError: + if init_value is not None: + self._actuals[name] = init_value + value + else: + self._actuals[name] = value
+ +
[docs] def sub(self, name, value, init_value=None): + """ + :param name: name of the counter + :param value: value to be subtracted from the counter + + Subtracts the `value` from the counter Values specified by `name`. + If `name` is not in Counter Values, it will be added. + + """ + try: + self._actuals[name] -= value + except KeyError: + if init_value is not None: + self._actuals[name] = init_value - value + else: + self._actuals[name] = -value
+ + def flush(self, now): + if self.Storage.get("reset") is True: + for field in self.Storage['fieldset']: + field['values'] = field['actuals'] + if self.Init is not None: + field['actuals'] = self.Init.copy() + else: + field['actuals'] = dict() + self._actuals = field['actuals'] + else: + for field in self.Storage['fieldset']: + field['values'] = field['actuals'].copy()
+ + +
[docs]class EPSCounter(Counter): + """ + Event per Second Counter + Divides the count of event by a time difference between measurements. + It effectively produces the EPS metric. + The type of the metric is an integer (int). + """ + + def __init__(self, init_values=None): + if init_values is not None: + init_values = {k: int(v) for k, v in init_values.items()} + + super().__init__(init_values=init_values) + self.LastTime = time.time() + + + def flush(self, now): + + delta = now - self.LastTime + if delta <= 0.0: + return + + reset = self.Storage.get("reset") + + for field in self.Storage['fieldset']: + field['values'] = { + k: int(v / delta) + for k, v in self._actuals.items() + } + + if reset is True: + if self.Init is not None: + field['actuals'] = self.Init.copy() + else: + field['actuals'] = dict() + self._actuals = field["actuals"] + + self.LastTime = now
+ + +
[docs]class DutyCycle(Metric): + ''' + https://en.wikipedia.org/wiki/Duty_cycle + + now = self.Loop.time() + d = now - self.LastReadyStateSwitch + self.LastReadyStateSwitch = now + ''' + + + def __init__(self, loop, init_values=None): + super().__init__() + self.Loop = loop + now = self.Loop.time() + self.EmptyValue = { + "on_off": None, + "timestamp": now, + "off_cycle": 0.0, + "on_cycle": 0.0 + } + + self.Init = dict() + + if init_values is not None: + for k, v in init_values.items(): + value = self.EmptyValue.copy() + value["on_off"] = v + self.Init[k] = value + + def add_field(self, tags): + field = { + "tags": tags, + "actuals": self.Init.copy(), + "values": dict(), + } + self.Storage['fieldset'].append(field) + self._field = field + return field + + + def set(self, name, on_off: bool): + now = self.Loop.time() + values = self._field["actuals"].get(name) + if values is None: + value = self.EmptyValue.copy() + value["on_off"] = on_off + value["timestamp"] = now + self._field["actuals"][name] = value + return + + if values.get("on_off") == on_off: + return # No change + + d = now - values.get("timestamp") + off_cycle = values.get("off_cycle") + on_cycle = values.get("on_cycle") + if on_off: + # From off to on + off_cycle += d + else: + # From on to off + on_cycle += d + + values["on_off"] = on_off + values["timestamp"] = now + values["off_cycle"] = off_cycle + values["on_cycle"] = on_cycle + + + def flush(self, now): + for field in self.Storage["fieldset"]: + actuals = field.get("actuals") + for v_name, values in actuals.items(): + d = now - values.get("timestamp") + off_cycle = values.get("off_cycle") + on_cycle = values.get("on_cycle") + if values.get("on_off"): + on_cycle += d + else: + off_cycle += d + + full_cycle = on_cycle + off_cycle + if full_cycle > 0.0: + field["values"][v_name] = on_cycle / full_cycle + + new_value = self.EmptyValue.copy() + new_value["on_off"] = values.get("on_off") + new_value["timestamp"] = now + + field["actuals"][v_name] = new_value
+ + +
[docs]class AggregationCounter(Counter): + ''' + Sets value aggregated with the last one. + Takes a function object as the `aggregator` argument. + The aggregation function can take two arguments only. + Maximum is used as a default aggregation function. + ''' + def __init__(self, init_values=None, aggregator=max): + super().__init__(init_values=init_values) + self.Aggregator = aggregator + +
[docs] def set(self, name, value): + try: + self._actuals[name] = self.Aggregator(value, self._actuals[name]) + except KeyError: + self._actuals[name] = value
+ + def add(self, name, value): + raise NotImplementedError("Do not use add() method with AggregationCounter. Use set() instead.") + + def sub(self, name, value): + raise NotImplementedError("Do not use sub() method with AggregationCounter. Use set() instead.")
+ + +
[docs]class Histogram(Metric): + """ + Creates cumulative histograms. + """ + def __init__(self, buckets: list, init_values=None): + super().__init__(init_values) + _buckets = [float(b) for b in buckets] + + if _buckets != sorted(buckets): + raise ValueError("Buckets not in sorted order") + + if _buckets and _buckets[-1] != float("inf"): + _buckets.append(float("inf")) + + if len(_buckets) < 2: + raise ValueError("Must have at least two buckets") + + self.InitBuckets = {b: dict() for b in _buckets} + self.Count = 0 + self.Sum = 0.0 + self.InitHistogram = { + "buckets": self.InitBuckets, + "sum": 0.0, + "count": 0 + } + + if self.Init: + for value_name, value in self.Init.items(): + for upper_bound in self.InitHistogram["buckets"]: + if value <= upper_bound: + self.InitHistogram["buckets"][upper_bound][value_name] = 1 + self.InitHistogram["sum"] += value + self.InitHistogram["count"] += 1 + + def add_field(self, tags): + field = { + "tags": tags, + "values": copy.deepcopy(self.InitHistogram), + "actuals": copy.deepcopy(self.InitHistogram), + } + self.Storage['fieldset'].append(field) + self._actuals = field['actuals'] + return field + + def flush(self, now): + if self.Storage.get("reset") is True: + for field in self.Storage['fieldset']: + field['values'] = field['actuals'] + field['actuals'] = copy.deepcopy(self.InitHistogram) + self._actuals = field['actuals'] + else: + for field in self.Storage['fieldset']: + field['values'] = copy.deepcopy(field['actuals']) + +
[docs] def set(self, value_name, value): + buckets = self._actuals["buckets"] + summary = self._actuals["sum"] + count = self._actuals["count"] + for upper_bound in buckets: + if value <= upper_bound: + if buckets[upper_bound].get(value_name) is None: + buckets[upper_bound][value_name] = 1 + else: + buckets[upper_bound][value_name] += 1 + self._actuals["sum"] = summary + value + self._actuals["count"] = count + 1
+ +### + + +class MetricWithDynamicTags(Metric): + + + def _initialize_storage(self, storage: dict): + storage.update({ + 'type': self.__class__.__name__, + }) + self.Storage = storage + if self.Init is not None: + self.add_field(self.StaticTags.copy()) + + + def locate_field(self, tags): + fieldset = self.Storage['fieldset'] + + tags = tags.copy() + tags.update(self.StaticTags) + + # Seek for field in the fieldset using tags + for field in fieldset: + if field['tags'] == tags: + return field + + # Field not found, create a new one + field = self.add_field(tags) + return field + + + +
[docs]class CounterWithDynamicTags(MetricWithDynamicTags): + + + def add_field(self, tags): + field = { + "tags": tags, + "values": self.Init.copy() if self.Init is not None else dict(), + "actuals": self.Init.copy() if self.Init is not None else dict(), + "expires_at": self.App.time() + self.Expiration, + } + self.Storage['fieldset'].append(field) + return field + +
[docs] def add(self, name, value, tags): + """ + :param name: name of the counter + :param value: value to be added to the counter + + Adds the `value` to the counter Values specified by `name`. + If name is not in Counter Values, it will be added there. + """ + + field = self.locate_field(tags) + actuals = field['actuals'] + try: + actuals[name] += value + except KeyError: + actuals[name] = value + + field["expires_at"] = self.App.time() + self.Expiration
+ +
[docs] def sub(self, name, value, tags): + """ + :param name: name of the counter + :param value: value to be subtracted from the counter + + Subtracts the `value` from the counter Values specified by `name`. + If name is not in Counter Values, it will be added there. + """ + + field = self.locate_field(tags) + actuals = field['actuals'] + try: + actuals[name] -= value + except KeyError: + actuals[name] = -value + + field["expires_at"] = self.App.time() + self.Expiration
+ + def flush(self, now): + # Filter expired fields + for field in self.Storage["fieldset"][::-1]: + if field["expires_at"] < now: + self.Storage["fieldset"].remove(field) + + if self.Storage.get("reset") is True: + for field in self.Storage['fieldset']: + field['values'] = field['actuals'] + if self.Init is not None: + field['actuals'] = self.Init.copy() + else: + field['actuals'] = dict() + else: + for field in self.Storage['fieldset']: + field['values'] = field['actuals'].copy()
+ + +
[docs]class AggregationCounterWithDynamicTags(CounterWithDynamicTags): + + + def __init__(self, init_values=None, aggregator=max): + super().__init__(init_values=init_values) + self.Aggregator = aggregator + +
[docs] def set(self, name, value, tags): + field = self.locate_field(tags) + actuals = field['actuals'] + try: + actuals[name] = self.Aggregator(value, actuals[name]) + except KeyError: + actuals[name] = value + + field["expires_at"] = self.App.time() + self.Expiration
+ + def add(self, name, value, tags): + raise NotImplementedError("Do not use add() method with AggregationCounter. Use set() instead.") + + def sub(self, name, value, tags): + raise NotImplementedError("Do not use sub() method with AggregationCounter. Use set() instead.")
+ + +
[docs]class HistogramWithDynamicTags(MetricWithDynamicTags): + """ + Creates cumulative histograms with dynamic tags + """ + + def __init__(self, buckets: list, init_values=None): + super().__init__(init_values) + _buckets = [float(b) for b in buckets] + + if _buckets != sorted(buckets): + raise ValueError("Buckets not in sorted order") + + if _buckets and _buckets[-1] != float("inf"): + _buckets.append(float("inf")) + + if len(_buckets) < 2: + raise ValueError("Must have at least two buckets") + + self.InitBuckets = {b: dict() for b in _buckets} + self.Count = 0 + self.Sum = 0.0 + self.InitHistogram = { + "buckets": self.InitBuckets, + "sum": 0.0, + "count": 0 + } + + if self.Init: + for value_name, value in self.Init.items(): + for upper_bound in self.InitHistogram["buckets"]: + if value <= upper_bound: + self.InitHistogram["buckets"][upper_bound][value_name] = 1 + self.InitHistogram["sum"] += value + self.InitHistogram["count"] += 1 + + def add_field(self, tags): + field = { + "tags": tags, + "values": copy.deepcopy(self.InitHistogram), + "actuals": copy.deepcopy(self.InitHistogram), + "expires_at": self.App.time() + self.Expiration, + } + self.Storage['fieldset'].append(field) + return field + + def flush(self, now): + # Filter expired fields + for field in self.Storage["fieldset"][::-1]: + if field["expires_at"] < now: + self.Storage["fieldset"].remove(field) + + if self.Storage.get("reset") is True: + for field in self.Storage['fieldset']: + field['values'] = field['actuals'] + field['actuals'] = copy.deepcopy(self.InitHistogram) + else: + for field in self.Storage['fieldset']: + field['values'] = copy.deepcopy(field['actuals']) + +
[docs] def set(self, value_name, value, tags): + field = self.locate_field(tags) + buckets = field.get("actuals").get("buckets") + summary = field.get("actuals").get("sum") + count = field.get("actuals").get("count") + for upper_bound in buckets: + if value <= upper_bound: + if buckets[upper_bound].get(value_name) is None: + buckets[upper_bound][value_name] = 1 + else: + buckets[upper_bound][value_name] += 1 + field.get("actuals")["sum"] = summary + value + field.get("actuals")["count"] = count + 1 + + field["expires_at"] = self.App.time() + self.Expiration
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/metrics/service.html b/old_docs/_build/htmln/_modules/asab/metrics/service.html new file mode 100644 index 000000000..d20c6dd8d --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/metrics/service.html @@ -0,0 +1,290 @@ + + + + + + + + asab.metrics.service — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.metrics.service

+import configparser
+import logging
+import asyncio
+import os
+
+from ..config import Config
+from ..abc import Service
+from .metrics import (
+	Metric, Counter, EPSCounter, Gauge, DutyCycle, AggregationCounter, Histogram,
+	CounterWithDynamicTags, AggregationCounterWithDynamicTags, HistogramWithDynamicTags
+)
+from .storage import Storage
+
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+
[docs]class MetricsService(Service): + + def __init__(self, app, service_name): + + super().__init__(app, service_name) + + self.Metrics = [] + self.Targets = [] + self.Tags = { + "host": app.HostName, + "appclass": app.__class__.__name__, + } + # A unique identifier of a microservice; added as an environment variable. + instance_id = os.getenv('INSTANCE_ID', None) + if instance_id is not None: + self.Tags["instance_id"] = instance_id + + self.Storage = Storage() + + app.PubSub.subscribe("Application.tick/60!", self._on_flushing_event) + + if Config.has_option('asab:metrics', 'target'): + for target in Config.get('asab:metrics', 'target').split(): + target = target.strip() + try: + target_type = Config.get('asab:metrics:{}'.format(target), 'type') + except configparser.NoOptionError: + # This allows to specify the type of the target by its name + target_type = target + + if target_type == 'influxdb': + from .influxdb import InfluxDBTarget + target = InfluxDBTarget(self, 'asab:metrics:{}'.format(target)) + + elif target_type == 'http': + from .http import HTTPTarget + target = HTTPTarget(self, 'asab:metrics:{}'.format(target)) + + else: + raise RuntimeError("Unknown target type {}".format(target_type)) + + self.Targets.append(target) + + if Config.getboolean('asab:metrics', 'native_metrics'): + from .native import NativeMetrics + self._native_svc = NativeMetrics(self.App, self) + + + async def finalize(self, app): + await self._on_flushing_event("finalize!") + + + def clear(self): + self.Metrics.clear() + self.Storage.clear() + + def _flush_metrics(self): + now = self.App.time() + + self.App.PubSub.publish("Metrics.flush!") + for metric in self.Metrics: + try: + metric.flush(now) + except Exception: + L.exception("Exception during metric.flush()") + + return now + + async def _on_flushing_event(self, event_type): + if len(self.Metrics) == 0: + return + + now = self._flush_metrics() + + pending = set() + for target in self.Targets: + pending.add( + asyncio.ensure_future(target.process(self.Storage.Metrics, now)) + ) + + while len(pending) > 0: + done, pending = await asyncio.wait(pending, timeout=180.0, return_when=asyncio.ALL_COMPLETED) + + + def _add_metric(self, metric: Metric, metric_name: str, tags=None, reset=None, help=None, unit=None): + # Add global tags + metric.StaticTags.update(self.Tags) + metric.App = self.App + + # Add local static tags + if tags is not None: + metric.StaticTags.update(tags) + + + metric._initialize_storage( + self.Storage.add(metric_name, tags=metric.StaticTags.copy(), reset=reset, help=help, unit=unit) + ) + + self.Metrics.append(metric) + +
[docs] def create_gauge(self, metric_name, tags=None, init_values=None, help=None, unit=None): + m = Gauge(init_values=init_values) + self._add_metric(m, metric_name, tags=tags, help=help, unit=unit) + return m
+ +
[docs] def create_counter(self, metric_name, tags=None, init_values=None, reset: bool = True, help=None, unit=None, dynamic_tags=False): + if dynamic_tags: + m = CounterWithDynamicTags(init_values=init_values) + else: + m = Counter(init_values=init_values) + self._add_metric(m, metric_name, tags=tags, reset=reset, help=help, unit=unit) + return m
+ +
[docs] def create_eps_counter(self, metric_name, tags=None, init_values=None, reset: bool = True, help=None, unit=None): + m = EPSCounter(init_values=init_values) + self._add_metric(m, metric_name, tags=tags, reset=reset, help=help, unit=unit) + return m
+ +
[docs] def create_duty_cycle(self, loop, metric_name, tags=None, init_values=None, help=None, unit=None): + m = DutyCycle(loop, init_values=init_values) + self._add_metric(m, metric_name, tags=tags, help=help, unit=unit) + return m
+ +
[docs] def create_aggregation_counter(self, metric_name, tags=None, init_values=None, reset: bool = True, aggregator=max, help=None, unit=None, dynamic_tags=False): + if dynamic_tags: + m = AggregationCounterWithDynamicTags(init_values=init_values, aggregator=aggregator) + else: + m = AggregationCounter(init_values=init_values, aggregator=aggregator) + self._add_metric(m, metric_name, tags=tags, reset=reset, help=help, unit=unit) + return m
+ +
[docs] def create_histogram(self, metric_name, buckets: list, tags=None, init_values=None, reset: bool = True, help=None, unit=None, dynamic_tags=False): + if dynamic_tags: + m = HistogramWithDynamicTags(buckets=buckets, init_values=init_values) + else: + m = Histogram(buckets=buckets, init_values=init_values) + self._add_metric(m, metric_name, tags=tags, reset=reset, help=help, unit=unit) + return m
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/pdict.html b/old_docs/_build/htmln/_modules/asab/pdict.html new file mode 100644 index 000000000..7025ee9af --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/pdict.html @@ -0,0 +1,200 @@ + + + + + + + + asab.pdict — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.pdict

+import collections
+import os
+import shelve
+
+
+
[docs]class PersistentDict(dict): + + """ + The persistent dictionary works as the regular Python dictionary but the content of the dictionary is stored in the file. + You cat think of a ``PersistentDict`` as a simple `key-value store <https://en.wikipedia.org/wiki/Key-value_database>`_. + It is not optimized for a frequent access. This class provides common ``dict`` interface. + + *Warning*: You must explicitly `load()` and `store()` content of the dictionary + *Warning*: You can only store objects in the persistent dictionary that are serializable. + """ + + def __init__(self, path): + super().__init__() + # Create directory, if needed + dirname = os.path.dirname(path) + if not os.path.isdir(dirname): + os.makedirs(dirname) + + self._path = path + + def __delitem__(self, key): + super().__delitem__(key) + with shelve.open(self._path) as d: + del d[key] + +
[docs] def load(self) -> None: + """ + Load content of file as dictionary. + """ + with shelve.open(self._path) as d: + for key, value in d.items(): + self[key] = value
+ +
[docs] def store(self) -> None: + """ + Explicitly store content of persistent dictionary to file + """ + + with shelve.open(self._path) as d: + for key, value in self.items(): + d[key] = value
+ +
[docs] def update(self, other=(), **kwds) -> None: + """ + Update D from mapping/iterable E and F. + * If E present and has a .keys() method, does: for k in E: D[k] = E[k] + * If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v + * In either case, this is followed by: for k, v in F.items(): D[k] = v + + Inspired by a https://github.com/python/cpython/blob/3.8/Lib/_collections_abc.py + """ + + if isinstance(other, collections.Mapping): + for key in other: + self[key] = other[key] + elif hasattr(other, "keys"): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + + for key, value in kwds.items(): + self[key] = value
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/pubsub.html b/old_docs/_build/htmln/_modules/asab/pubsub.html new file mode 100644 index 000000000..0e9c02142 --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/pubsub.html @@ -0,0 +1,359 @@ + + + + + + + + asab.pubsub — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.pubsub

+import logging
+import asyncio
+import weakref
+import functools
+
+
+L = logging.getLogger(__name__)
+
+
+
[docs]class PubSub(object): + + + def __init__(self, app): + self.Subscribers = {} + self.Loop = app.Loop + + +
[docs] def subscribe(self, message_type, callback): + """ + Subscribe a subscriber to the an message type. + It could be even plain function, method or its coroutine variant (then it will be delivered in a dedicated future) + """ + + # If subscribe is a bound method, do special treatment + # https://stackoverflow.com/questions/53225/how-do-you-check-whether-a-python-method-is-bound-or-not + if hasattr(callback, '__self__'): + callback = weakref.WeakMethod(callback) + + else: + callback = weakref.ref(callback) + + if message_type not in self.Subscribers: + self.Subscribers[message_type] = [callback] + else: + self.Subscribers[message_type].append(callback)
+ + +
[docs] def subscribe_all(self, obj): + """ + Find all @asab.subscribe decorated methods on the obj and do subscription + """ + for member_name in dir(obj): + member = getattr(obj, member_name) + message_types = getattr(member, 'asab_pubsub_subscribe_to_message_types', None) + if message_types is not None: + for message_type in message_types: + self.subscribe(message_type, member)
+ + +
[docs] def unsubscribe(self, message_type, callback): + """ Remove a subscriber of an message type from the set. """ + + callback_list = self.Subscribers.get(message_type) + if callback_list is None: + L.warning("Message type subscription '{}'' not found.".format(message_type)) + return + + remove_list = None + + for i in range(len(callback_list)): + # Take an weakref entry in the callback list and references it + c = callback_list[i]() + + # Check if a weak reference is working + if c is None: # a reference is lost, remove this entry + if remove_list is None: + remove_list = list() + remove_list.append(callback_list[i]) + continue + + if c == callback: + callback_list.pop(i) + break + + else: + L.warning("Subscriber '{}'' not found for the message type '{}'.".format(message_type, callback)) + + if remove_list is not None: + for callback_ref in remove_list: + callback_list.remove(callback_ref) + + if len(callback_list) == 0: + del self.Subscribers[message_type]
+ + + def _callback_iter(self, message_type): + + def _deliver_async(loop, callback, message_type, *args, **kwargs): + asyncio.ensure_future(callback(message_type, *args, **kwargs)) + + callback_list = self.Subscribers.get(message_type) + if callback_list is None: + return + + remove_list = None + + for callback_ref in callback_list: + callback = callback_ref() + + # Check if a weak reference is working + if callback is None: # a reference is lost + if remove_list is None: + remove_list = list() + remove_list.append(callback_ref) + continue + + if asyncio.iscoroutinefunction(callback): + callback = functools.partial(_deliver_async, self.Loop, callback) + + yield callback + + if remove_list is not None: + for callback_ref in remove_list: + callback_list.remove(callback_ref) + + +
[docs] def publish(self, message_type, *args, **kwargs): + """ Notify subscribers of an message type. Including arguments. """ + + asynchronously = kwargs.pop('asynchronously', False) + + if asynchronously: + for callback in self._callback_iter(message_type): + self.Loop.call_soon(functools.partial(callback, message_type, *args, **kwargs)) + + else: + for callback in self._callback_iter(message_type): + callback(message_type, *args, **kwargs)
+ + +### + +class subscribe(object): + + ''' + Decorator + + Usage: + + @asab.subscribe("tick") + def on_tick(self, message_type): + print("Service tick") + ''' + + def __init__(self, message_type): + self.message_type = message_type + + def __call__(self, f): + if getattr(f, 'asab_pubsub_subscribe_to_message_types', None) is None: + f.asab_pubsub_subscribe_to_message_types = [self.message_type] + else: + f.asab_pubsub_subscribe_to_message_types.append(self.message_type) + return f + + +### + +
[docs]class Subscriber(object): + + ''' +:any:`Subscriber` object allows to consume PubSub messages in coroutines. +It subscribes for various message types and consumes them. +It works on FIFO basis (First message In, first message Out). +If ``pubsub`` argument is None, the initial subscription is skipped. + +.. code:: python + + subscriber = asab.Subscriber( + app.PubSub, + "Application.tick!", + "Application.stop!" + ) + ''' + + def __init__(self, pubsub=None, *message_types): + + self._q = asyncio.Queue() + self._subscriptions = [] + + if pubsub is not None: + for message_type in message_types: + self.subscribe(pubsub, message_type) + + +
[docs] def subscribe(self, pubsub, message_type): + ''' +Subscribe for more message types. This method can be called many times with various ``pubsub`` objects. + ''' + pubsub.subscribe(message_type, self) + self._subscriptions.append((pubsub, message_type))
+ + + def __call__(self, message_type, *args, **kwargs): + self._q.put_nowait((message_type, args, kwargs)) + + +
[docs] def message(self): + ''' +Wait for a message asynchronously. +Returns a three-members tuple ``(message_type, args, kwargs)``. + +Example of the `await message()` use: + +.. code:: python + + async def my_coroutine(app): + # Subscribe for a two application events + subscriber = asab.Subscriber( + app.PubSub, + "Application.tick!", + "Application.exit!" + ) + while True: + message_type, args, kwargs = await subscriber.message() + if message_type == "Application.exit!": + break + print("Tick.") + + ''' + return self._q.get()
+ + + def __aiter__(self): + return self + + + async def __anext__(self): + return await self._q.get()
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/socket.html b/old_docs/_build/htmln/_modules/asab/socket.html new file mode 100644 index 000000000..916abd86c --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/socket.html @@ -0,0 +1,172 @@ + + + + + + + + asab.socket — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.socket

+from .abc.service import Service
+
+
+
[docs]class StreamSocketServerService(Service): + + ''' + Example of use: + + class ServiceMyProtocolServer(asab.StreamSocketServerService): + + async def initialize(self, app): + host = asab.Config.get('http', 'host') + port = asab.Config.getint('http', 'port') + + L.debug("Starting server on {} {} ...".format(host, port)) + await self.create_server(app, MyProtocol, [(host, port)]) + ''' + + def __init__(self, app, service_name): + super().__init__(app, service_name) + self._servers = [] + app.PubSub.subscribe("Application.exit!", self._on_exit) + + +
[docs] async def create_server(self, app, protocol, addrs): + # TODO: Parallelize this ... + for addr in addrs: + host, port = addr + server = await app.Loop.create_server(protocol, host, port) + self._servers.append(server)
+ + + def _on_exit(self, message_type): + for server in self._servers: + server.close() + + +
[docs] async def finalize(self, app): + # TODO: Parallelize this ... + for server in self._servers: + await server.wait_closed()
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/timer.html b/old_docs/_build/htmln/_modules/asab/timer.html new file mode 100644 index 000000000..fe5132160 --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/timer.html @@ -0,0 +1,216 @@ + + + + + + + + asab.timer — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.timer

+import asyncio
+
+
+
[docs]class Timer(object): + ''' + T.__init__(app, handler, autorestart=False) -> Timer. + + The relative and optionally repeating timer for asyncio. + + This class is simple relative timer that generate an event after a given time, and optionally repeating in regular intervals after that. + + :param app: An ASAB application. + :param handler: A coro or future that will be called when a timer triggers. + :param boolean autorestart: If `True` then a timer will be automatically restarted after triggering. + + :ivar Handler: A coro or future that will be called when a timer triggers. + :ivar Task: A future that represent the timer task. + :ivar App: An ASAB app. + :ivar boolean AutoRestart: If `True` then a timer will be automatically restarted after triggering. + + The timer object is initialized as stopped. + + *Note*: The implementation idea is borrowed from "`Python - Timer with asyncio/coroutine <https://stackoverflow.com/questions/45419723/python-timer-with-asyncio-coroutine>`_" question on StackOverflow. + ''' + + def __init__(self, app, handler, autorestart=False): + self.App = app + self.Handler = handler + self.Task = None + self.AutoRestart = autorestart + + app.PubSub.subscribe("Application.stop!", self._on_stop) + + +
[docs] def start(self, timeout): + ''' + Start the timer. + + :param float/int timeout: A timer delay in seconds. + ''' + if self.is_started(): + raise RuntimeError("Timer is already started") + self.Task = asyncio.ensure_future(self._job(timeout))
+ + +
[docs] def stop(self): + ''' + Stop the timer. + ''' + if self.Task is not None: + self.Task.cancel() + self.Task = None
+ + +
[docs] def restart(self, timeout): + ''' + Restart the timer. + + :param float/int timeout: A timer delay in seconds. + ''' + + if self.is_started(): + self.stop() + self.start(timeout)
+ + +
[docs] def is_started(self): + ''' + T.is_started() -> boolean + Return `True` is the timer is started otherwise returns `False`. + ''' + return self.Task is not None
+ + + async def _job(self, timeout): + await asyncio.sleep(timeout) + self.Task = None + if self.AutoRestart: + self.start(timeout) + await self.Handler() + + + def _on_stop(self, message_type, n): + # This is to ensure timer stop on application exit + self.stop()
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/web/service.html b/old_docs/_build/htmln/_modules/asab/web/service.html new file mode 100644 index 000000000..ebc1ea2bb --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/web/service.html @@ -0,0 +1,197 @@ + + + + + + + + asab.web.service — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.web.service

+import logging
+
+from ..abc.service import Service
+from .. import Config
+from .. import metrics
+
+from .metrics import WebRequestsMetrics
+
+
+L = logging.getLogger(__name__)
+
+
+
[docs]class WebService(Service): + + ConfigSectionAliases = ["asab:web"] + + def __init__(self, app, service_name): + super().__init__(app, service_name) + + # Web service is dependent on Metrics service + if Config.getboolean("asab:metrics", "web_requests_metrics", fallback=False): + app.add_module(metrics.Module) + self.MetricsService = app.get_service("asab.MetricsService") + self.WebRequestsMetrics = WebRequestsMetrics(self.MetricsService) + self.Containers = {} + + async def finalize(self, app): + for containers in self.Containers.values(): + await containers._stop(app) + + def _register_container(self, container, config_section_name): + self.Containers[config_section_name] = container + self.App.TaskService.schedule(container._start(self.App)) + + + @property + def WebApp(self): + ''' + This is here to maintain backward compatibility. + ''' + return self.WebContainer.WebApp + + + @property + def WebContainer(self): + ''' + This is here to maintain backward compatibility. + ''' + config_section = "web" + + # The WebContainer should be configured in the config section [web] + if config_section not in Config.sections(): + # If there is no [web] section, try other aliases for backwards compatibility + for alias in self.ConfigSectionAliases: + if alias in Config.sections(): + config_section = alias + L.warning("Using obsolete config section [{}]. Preferred section name is [web]. ".format(alias)) + break + else: + raise RuntimeError("No [web] section configured.") + + try: + return self.Containers[config_section] + except KeyError: + from .container import WebContainer + return WebContainer(self, config_section)
+
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/asab/zookeeper/container.html b/old_docs/_build/htmln/_modules/asab/zookeeper/container.html new file mode 100644 index 000000000..0987a401e --- /dev/null +++ b/old_docs/_build/htmln/_modules/asab/zookeeper/container.html @@ -0,0 +1,346 @@ + + + + + + + + asab.zookeeper.container — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Source code for asab.zookeeper.container

+import os
+import json
+import asyncio
+import logging
+import urllib.parse
+import configparser
+
+import kazoo.exceptions
+import kazoo.recipe.watchers
+
+from .wrapper import KazooWrapper
+from ..config import ConfigObject
+
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+
[docs]class ZooKeeperContainer(ConfigObject): + """ + Create a Zookeeper container with a specifications of the connectivity. + """ + + ConfigDefaults = { + # Server list to which ZooKeeper Client tries connecting. + # Specify a comma (,) separated server list. + # A server is defined as `address:port` format. + # Example: + # "servers": "zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181" + # If servers are empty, default from [zookeeper]/servers will be taken + # If [zookeeper]/servers value is not provided, ZOOKEEPER_SERVERS environment variable is used + "servers": "", + + # If not provided, "/asab" path will be used + "path": "", + } + + + def __init__(self, zookeeper_service, config_section_name="zookeeper", config=None, z_path=None): + super().__init__(config_section_name=config_section_name, config=config) + + self.App = zookeeper_service.App + self.ConfigSectionName = config_section_name + + # Parse URL from z_path + if z_path is not None: + url_pieces = urllib.parse.urlparse(z_path) + url_netloc = url_pieces.netloc + url_path = url_pieces.path + else: + url_netloc = "" + url_path = "" + + # If there is no location, use the value of 'servers' from the configuration + if url_netloc == "": + url_netloc = self.Config.get("servers", "") + + if url_netloc == "": + from ..config import Config + try: + url_netloc = Config.get("zookeeper", "servers") + except (configparser.NoOptionError, configparser.NoSectionError): + pass + + if url_netloc == "": + url_netloc = os.environ.get("ZOOKEEPER_SERVERS", "") + + if url_netloc == "": + # if server entry is missing exit + L.critical("Cannot connect to Zookeeper, the configuration of the server address is not available.") + raise SystemExit("Exit due to a critical configuration error.") + + assert url_netloc is not None + + # If path has not been provided, use the value of 'path' from the configuration + if url_path == "": + url_path = self.Config.get("path", "") + + if url_path == "": + from ..config import Config + try: + url_path = Config.get("zookeeper", "path") + except (configparser.NoOptionError, configparser.NoSectionError): + pass + + if url_path == "": + url_path = 'asab' + + # Remove all heading '/' from path + while url_path.startswith('/'): + url_path = url_path[1:] + + self.ZooKeeper = KazooWrapper(zookeeper_service, url_netloc) + self.Path = url_path + + self.Advertisments = dict() + self.DataWatchers = set() + self.App.PubSub.subscribe("Application.tick/300!", self._readvertise) + + zookeeper_service.Containers.append(self) + zookeeper_service.ProactorService.schedule(self._start, self.App) + + + def _start(self, app): + # This method is called on proactor thread + try: + self.ZooKeeper._start() + except Exception as e: + L.error( + "Failed to connect to ZooKeeper: {}".format(e), + struct_data={ + 'hosts': str(self.ZooKeeper.Client.hosts), + } + ) + return + + self.ZooKeeper.Client.ensure_path(self.Path) + + def in_main_thread(): + self.App.PubSub.publish("ZooKeeperContainer.started!", self) + self.App.Loop.call_soon_threadsafe(in_main_thread) + + + async def _stop(self, app): + await self.ZooKeeper._stop() + + +
[docs] def is_connected(self): + """ + Check, if the Zookeeper is connected + """ + return self.ZooKeeper.Client.connected
+ + + # Advertisement into Zookeeper + +
[docs] def advertise(self, data, path): + adv = self.Advertisments.get(self.Path + path) + if adv is None: + adv = ZooKeeperAdvertisement(self.Path + path) + self.Advertisments[self.Path + path] = adv + self.App.TaskService.schedule(adv._set_data(self, data))
+ + + async def _readvertise(self, *args): + for adv in self.Advertisments.values(): + await adv._readvertise(self) + + + # Reading + +
[docs] async def get_children(self, path=""): + return await self.ZooKeeper.get_children("{}/{}".format(self.Path, path))
+ +
[docs] async def get_data(self, path, encoding="utf-8"): + raw_data = await self.get_raw_data(path) + if raw_data is None: + return {} + return json.loads(raw_data.decode(encoding))
+ +
[docs] async def get_raw_data(self, path): + return await self.ZooKeeper.get_data("{}/{}".format(self.Path, path))
+ + +class ZooKeeperAdvertisement(object): + + def __init__(self, path): + self.Data = None + + self.Path = path + self.RealPath = None + + self.Lock = asyncio.Lock() + + + async def _set_data(self, zoocontainer, data): + async with self.Lock: + if isinstance(data, dict): + self.Data = json.dumps(data).encode("utf-8") + elif isinstance(data, str): + self.Data = data.encode("utf-8") + else: + self.Data = data + + def write_to_zk(): + if self.RealPath is None: + self.RealPath = zoocontainer.ZooKeeper.Client.create(self.Path, self.Data, sequence=True, ephemeral=True, makepath=True) + else: + try: + zoocontainer.ZooKeeper.Client.set(self.RealPath, self.Data) + except kazoo.exceptions.NoNodeError: + self.RealPath = zoocontainer.ZooKeeper.Client.create(self.Path, self.Data, sequence=True, ephemeral=True, makepath=True) + + await zoocontainer.ZooKeeper.ProactorService.execute(write_to_zk) + + + async def _readvertise(self, zoocontainer): + if self.Data is None: + return + + if self.RealPath is None: + return + + async with self.Lock: + + def check_at_zk(): + if zoocontainer.ZooKeeper.Client.exists(self.RealPath): + return + + # If the advertisement node is not present in the Zookeeper, force the recreation + self.RealPath = zoocontainer.ZooKeeper.Client.create(self.Path, self.Data, sequence=True, ephemeral=True) + + await zoocontainer.ZooKeeper.ProactorService.execute(check_at_zk) +
+ +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_modules/index.html b/old_docs/_build/htmln/_modules/index.html new file mode 100644 index 000000000..06cd672f0 --- /dev/null +++ b/old_docs/_build/htmln/_modules/index.html @@ -0,0 +1,148 @@ + + + + + + + + Overview: module code — ASAB documentation + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/_sources/admin/command-line.rst.txt b/old_docs/_build/htmln/_sources/admin/command-line.rst.txt new file mode 100644 index 000000000..51903d336 --- /dev/null +++ b/old_docs/_build/htmln/_sources/admin/command-line.rst.txt @@ -0,0 +1,66 @@ +ASAB Command-line interface +=========================== + +ASAB-based application provides the command-line interface by default. +Here is an overview of the common command-line arguments. + + +.. option:: -h , --help + +Show a help. + + +Configuration +------------- + +.. option:: -c ,--config + +Load configuration file from a file CONFIG. + + +Logging +------- + +.. option:: -v , --verbose + +Increase the logging level to DEBUG aka be more verbose about what is happening. + + +.. option:: -l ,--log-file + +Log to a file LOG_FILE. + + +.. option:: -s , --syslog + +Log to a syslog. + + +Daemon +------ + +Python module :py:mod:`python-daemon` has to be installed in order to support daemonosation functions. + +.. code-block:: bash + + $ pip3 install asab python-daemon + + +.. option:: -d , --daemonize + +Launch the application in the background aka daemonized. + +Daemon-related section of :any:`Config` file:: + + [daemon] + pidfile=/var/run/myapp.pid + uid=nobody + gid=nobody + working_dir=/tmp + +Configuration options ``pidfile``, ``uid`` , ``gid`` and ``working_dir`` are supported. + + +.. option:: -k , --kill + +Shutdown the application running in the background (started previously with ``-d`` argument). diff --git a/old_docs/_build/htmln/_sources/admin/containers.rst.txt b/old_docs/_build/htmln/_sources/admin/containers.rst.txt new file mode 100644 index 000000000..f9a69ce24 --- /dev/null +++ b/old_docs/_build/htmln/_sources/admin/containers.rst.txt @@ -0,0 +1,121 @@ +Containerisation +================ + +ASAB is designed for deployment into containers such as LXC/LXD or Docker. +It allows to build e.g. microservices that provides REST interface or consume MQ messages while being deployed into a container for a sake of the infrastructure flexibility. + + +ASAB in a LXC/LXD container +--------------------------- + +1. Prepare LXC/LXD container based on Alpine Linux + +.. code-block:: bash + + $ lxc launch images:alpine/3.10 asab + + +2. Swich into a container + +.. code-block:: bash + + $ lxc exec asab -- /bin/ash + + +3. Prepare Python3 environment + +.. code-block:: bash + + $ apk update + $ apk upgrade + $ apk add --no-cache python3 + + $ python3 -m ensurepip + + +4. Deploy ASAB + +.. code-block:: bash + + $ apk add --virtual .buildenv python3-dev gcc musl-dev git + $ pip3 install git+https://github.com/TeskaLabs/asab + $ apk del .buildenv + + +5. Deploy dependencies + +.. code-block:: bash + + $ pip3 install python-daemon + + +7. Use OpenRC to automatically start/stop ASAB application + +.. code-block:: bash + + $ vi /etc/init.d/asab-app + + +Adjust the example of `OpenRC init file `_. + +.. code-block:: bash + + $ chmod a+x /etc/init.d/asab-app + $ rc-update add asab-app + + +*Note*: If you need to install python packages that require compilation using C compiler, you have to add following dependencies: + +.. code-block:: bash + + $ apk add --virtual .buildenv python3-dev + $ apk add --virtual .buildenv gcc + $ apk add --virtual .buildenv musl-dev + + +And removal of the build tools after pip install: + +.. code-block:: bash + + $ apk del .buildenv + +Docker Remote API +--------------------------- + +In order for ASAB applications to read the Docker container name +as well as other information related to the container to be used in logs, metrics and other analysis, +the Docker Remote API must be enabled. + +To do so: + +1. Open the docker service file + +.. code-block:: bash + + vi /lib/systemd/system/docker.service + + +2. Find the line which starts with ExecStart and add `-H=tcp://0.0.0.0:2375` + + +3. Save the file + + +4. Reload the docker daemon and restart the Docker service + +.. code-block:: bash + + sudo systemctl daemon-reload && sudo service docker restart + + +Then in the ASAB application's configuration, provide +the Docker Socket path in `docker_socket` configuration option: + +.. code-block:: bash + + [general] + docker_socket= + +Thus, the metric service as well as log manager can use the container +name as hostname instead of container ID, which provides better readability +when analyzing the logs and metrics, typically using InfluxDB and Grafana. diff --git a/old_docs/_build/htmln/_sources/admin/install.rst.txt b/old_docs/_build/htmln/_sources/admin/install.rst.txt new file mode 100644 index 000000000..bfc1453fc --- /dev/null +++ b/old_docs/_build/htmln/_sources/admin/install.rst.txt @@ -0,0 +1,37 @@ +Installation +============ + +ASAB is distributed via `pypi `_. + + +Install ASAB using pip +---------------------- + +This is the recommended installation method. + +.. code-block:: bash + + $ pip install asab + + +Install ASAB using easy_install +------------------------------- + +.. code-block:: bash + + $ easy_install asab + + + +Install ASAB for a GitHub +------------------------- + +To install ASAB from a master branch of the GIT repository, use following command. + +*Note*: Git has to be installed in order to successfuly complete the installation. + + +.. code-block:: bash + + $ pip install git+https://github.com/TeskaLabs/asab.git + diff --git a/old_docs/_build/htmln/_sources/admin/systemd.rst.txt b/old_docs/_build/htmln/_sources/admin/systemd.rst.txt new file mode 100644 index 000000000..c22dc0ba0 --- /dev/null +++ b/old_docs/_build/htmln/_sources/admin/systemd.rst.txt @@ -0,0 +1,45 @@ +systemd +======= + +1. Create a new Systemd unit file in /etc/systemd/system/: + +.. code-block:: bash + + $ sudo vi /etc/systemd/system/asab.service + + +Adjust the example of `SystemD unit file `_. + + +2. Let systemd know that there is a new service: + +.. code-block:: bash + + $ sudo systemctl enable asab + + +To reload existing unit file after changing, use this: + +.. code-block:: bash + + $ sudo systemctl daemon-reload + + +3. ASAB Application Server service for systemd is now ready. + + +Start of ASAB Server +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + $ sudo service asab start + + +Stop of ASAB Server +^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + $ sudo service asab stop + diff --git a/old_docs/_build/htmln/_sources/asab/alert.rst.txt b/old_docs/_build/htmln/_sources/asab/alert.rst.txt new file mode 100644 index 000000000..147a47872 --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/alert.rst.txt @@ -0,0 +1,81 @@ +Alert Service +============= + +Integrate ASAB Application with alert managers. + +There are currently two possible target systems for the alerts available: + +- Opsgenie - https://www.atlassian.com/software/opsgenie + +- PagerDuty - https://events.pagerduty.com + +Everything you need to do is to import the service, trigger the alert and specify the target in the **configuration**. + +.. code:: python + + class MyApplication(asab.Application): + async def initialize(self): + from asab.alert import AlertService + self.AlertService = AlertService(self) + self.AlertService.trigger( + source="my-tenant", + alert_cls="my-class", + alert_id="deduplication-id01", + title="Something went wrong.", + detail={ + "example1": "additional-info", + "example2": "additional-info", + }, + ) + + if __name__ == '__main__': + app = MyApplication() + app.run() + + +Opsgenie +-------- + +- Create an account at Opsgenie. +- In your Opsgenie account, create a new **Team**. +- Add integration to your Team - choose **API**. +- API Key will be generated for you. + +*myapplication.conf* + +.. code:: + + [asab:alert:opsgenie] + api_key=my-api-key + tags=my-tag, my-application + url=https://api.eu.opsgenie.com # this is default value + + +PagerDuty +--------- + +- Create an account at PagerDuty. +- In your PagerDuty account, generate **Api Key** (Integrations > Developer Tools > Api Access Keys). +- Create a new Service in Service Directory and add integration in the Integrations folder. +- Choose **Events API V2**. An **Integration Key** will be generated for you. + +*myapplication.conf* + +.. code:: + + [asab:alert:pagerduty] + api_key=my-api-key + integration_key=my-integration-key + url=https://events.pagerduty.com # this is default value + + + +De-duplication +-------------- + +`alert_id` argument serves as a de-duplication ID for the third-party services. It enables the grouping of alerts and prevents noise. +More about alert grouping: + +- Opsgenie: https://support.atlassian.com/opsgenie/docs/what-is-alert-de-duplication/ + +- PagerDuty: https://support.pagerduty.com/docs/intelligent-alert-grouping \ No newline at end of file diff --git a/old_docs/_build/htmln/_sources/asab/application.rst.txt b/old_docs/_build/htmln/_sources/asab/application.rst.txt new file mode 100644 index 000000000..127203f27 --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/application.rst.txt @@ -0,0 +1,239 @@ +Application +=========== + +.. py:currentmodule:: asab + +.. py:class:: Application() + +The :py:class:`Application` class maintains the global application state. +You can provide your own implementation by creating a subclass. +There should be only one :py:class:`Application` object in the process. + +Subclassing: + +.. code:: python + + import asab + + class MyApplication(asab.Application): + pass + + if __name__ == '__main__': + app = MyApplication() + app.run() + + +Direct use of :py:class:`Application` object: + +.. code:: python + + import asab + + if __name__ == '__main__': + app = asab.Application() + app.run() + + + +Event Loop +---------- + +.. py:attribute:: Application.Loop + +The :py:mod:`asyncio` event loop that is used by this application. + +.. code:: python + + asyncio.ensure_future(my_coro()) + + +Application Lifecycle +--------------------- + +The ASAB is designed around the `Inversion of control `_ principle. +It means that the ASAB is in control of the application lifecycle. +The custom-written code receives the flow from ASAB via callbacks or handlers. +Inversion of control is used to increase modularity of the code and make it extensible. + +The application lifecycle is divided into 3 phases: init-time, run-time and exit-time. + +Init-time +^^^^^^^^^ + +.. py:method:: Application.__init__() + +The init-time happens during :py:class:`Application` constructor call. +The Publish-Subscribe message :any:`Application.init!` is published during init-time. +The :class:`Config` is loaded during init-time. + + +.. py:method:: Application.initialize() + +The application object executes asynchronous callback ``Application.initialize()``, which can be overriden by an user. + +.. code:: python + + class MyApplication(asab.Application): + async def initialize(self): + # Custom initialization + from module_sample import Module + self.add_module(Module) + + +Run-time +^^^^^^^^ + +.. py:method:: Application.run() + +Enter a run-time. This is where the application spends the most time typically. +The Publish-Subscribe message :any:`Application.run!` is published when run-time begins. + +The method returns the value of :any:`Application.ExitCode`. + + +.. py:method:: Application.main() + +The application object executes asynchronous callback ``Application.main()``, which can be overriden. +If ``main()`` method is completed without calling ``stop()``, then the application server will run forever (this is the default behaviour). + +.. code:: python + + class MyApplication(asab.Application): + async def main(self): + print("Hello world!") + self.stop() + + +.. py:method:: Application.stop(exit_code:int=None) + +The method ``Application.stop()`` gracefully terminates the run-time and commence the exit-time. +This method is automatically called by ``SIGINT`` and ``SIGTERM``. It also includes a response to ``Ctrl-C`` on UNIX-like system. +When this method is called 3x, it abruptly exits the application (aka emergency abort). + +The parameter ``exit_code`` allows you to specify the application exit code (see *Exit-Time* chapter). + +*Note:* You need to install :py:mod:`win32api` module to use ``Ctrl-C`` or an emergency abord properly with ASAB on Windows. It is an optional dependency of ASAB. + + +Exit-time +^^^^^^^^^ + +.. py:method:: Application.finalize() + +The application object executes asynchronous callback ``Application.finalize()``, which can be overriden by an user. + +.. code:: python + + class MyApplication(asab.Application): + async def finalize(self): + # Custom finalization + ... + + +The Publish-Subscribe message :any:`Application.exit!` is published when exit-time begins. + + +.. py:method:: Application.set_exit_code(exit_code:int, force:bool=False) + +Set the exit code of the application, see ``os.exit()`` in the Python documentation. +If ``force`` is ``False``, the exit code will be set only if the previous value is lower than the new one. +If ``force`` is ``True``, the exit code value is set to a ``exit_code`` disregarding the previous value. + + +.. py:attribute:: Application.ExitCode + +The actual value of the exit code. + + +The example of the exit code handling in the ``main()`` function of the application. + +.. code:: python + + if __name__ == '__main__': + app = asab.Application() + exit_code = app.run() + sys.exit(exit_code) + + + +Module registry +--------------- + +For more details see :py:class:`Module` class. + +.. py:method:: Application.add_module(module_class) + +Initialize and add a new module. +The ``module_class`` class will be instantiated during the method call. + + +.. code:: python + + class MyApplication(asab.Application): + async def initialize(self): + from my_module import MyModule + self.add_module(MyModule) + +.. py:attribute:: Application.Modules + +A list of modules that has been added to the application. + + +Service registry +---------------- + +Each service is identified by its unique service name. +For more details see :py:class:`Service` class. + +.. py:method:: Application.get_service(service_name) + +Locate a service by its service name in a registry and return the ``Service`` object. + +.. code:: python + + svc = app.get_service("service_sample") + svc.hello() + + +.. py:attribute:: Application.Services + +A dictionary of registered services. + + +Command-line parser +------------------- + +.. py:method:: Application.create_argument_parser(prog=None, usage=None, description=None, epilog=None, prefix_chars='-', fromfile_prefix_chars=None, argument_default=None, conflict_handler='error', add_help=True ) -> argparse.ArgumentParser + +Creates an ``argparse.ArgumentParser``. +This method can be overloaded to adjust command-line argument parser. + +Please refer to Python standard library ``argparse`` for more details about function arguments. + + +.. py:method:: Application.parse_args() + +The application object calls this method during init-time to process a command-line arguments. +:py:mod:`argparse` is used to process arguments. +You can overload this method to provide your own implementation of command-line argument parser. + + +.. py:data:: Application.Description + +The :py:data:`Description` attribute is a text that will be displayed in a help text (``--help``). +It is expected that own value will be provided. +The default value is ``""`` (empty string). + + + +UTC Time +-------- + +.. py:method:: Application.time() -> float + +Return the current "event loop time" in seconds since the epoch as a floating point number. +The specific date of the epoch and the handling of leap seconds is platform dependent. On Windows and most Unix systems, the epoch is January 1, 1970, 00:00:00 (UTC) and leap seconds are not counted towards the time in seconds since the epoch. This is commonly referred to as Unix time. + +A call of the ``time.time()`` function could be expensive. +This method provides a cheaper version of the call that returns a current wall time in UTC. + diff --git a/old_docs/_build/htmln/_sources/asab/config.rst.txt b/old_docs/_build/htmln/_sources/asab/config.rst.txt new file mode 100644 index 000000000..1ce9621c1 --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/config.rst.txt @@ -0,0 +1,251 @@ +.. _configuration-ref: + +Configuration +============= + +.. py:currentmodule:: asab + +.. py:data:: Config + +The configuration is provided by :py:obj:`Config` object which is a singleton. It means that you can access :py:obj:`Config` from any place of your code, without need of explicit initialisation. + +.. code:: python + + import asab + + # Initialize application object and hence the configuration + app = asab.Application() + + # Access configuration values anywhere + my_conf_value = asab.Config['section_name']['key1'] + + +Based on ConfigParser +--------------------- + +The :py:obj:`Config` is inherited from Python Standard Library :py:class:`configparser.ConfigParser` class. which implements a basic configuration language which provides a structure similar to what’s found in Microsoft Windows INI files. + +.. py:currentmodule:: asab.config + +.. py:class:: ConfigParser + +Example of the configuration file: + +.. code:: ini + + [bitbucket.org] + User = hg + + [topsecret.server.com] + Port = 50022 + ForwardX11 = no + + +And this is how you access configuration values: + +.. code:: python + + >>> asab.Config['topsecret.server.com']['ForwardX11'] + 'no' + + +.. py:currentmodule:: asab + + +Multiline configuration entry +----------------------------- + +A multiline configuration entries are supported. +An example: + +.. code:: ini + + [section] + key= + line1 + line2 + line3 + another_key=foo + + +Automatic load of configuration +------------------------------- + +If a configuration file name is specified, the configuration is automatically loaded from a configuration file during initialiation time of :py:class:`Application`. +The configuration file name can be specified by one of ``-c`` command-line argument (1), ``ASAB_CONFIG`` environment variable (2) or config ``[general] config_file`` default value (3). + +.. code:: shell + + ./sample_app.py -c ./etc/sample.conf + + + +Including other configuration files +----------------------------------- + +You can specify one or more additional configuration files that are loaded and merged from an main configuration file. +It is done by ``[general] include`` configuration value. Multiple paths are separated by ``os.pathsep`` (``:`` on Unix). +The path can be specified as a glob (e.g. use of ``*`` and ``?`` wildcard characters), it will be expanded by ``glob`` module from Python Standard Library. +Included configuration files may not exists, this situation is silently ignored. + +.. code:: ini + + [general] + include=./etc/site.conf:./etc/site.d/*.conf + + +You can also use a multiline configuration entry: + +.. code:: ini + + [general] + include= + ./etc/site.conf + ./etc/site.d/*.conf + + + +Configuration default values +---------------------------- + +.. py:method:: Config.add_defaults(dictionary) + +This is how you can extend configuration default values: + +.. code:: python + + asab.Config.add_defaults( + { + 'section_name': { + 'key1': 'value', + 'key2': 'another value' + }, + 'other_section': { + 'key3': 'value', + }, + } + ) + +Only simple types (``string``, ``int`` and ``float``) are allowed in the configuration values. +Don't use complex types such as lists, dictionaries or objects because these are impossible to provide via configuration files etc. + + +Environment variables in configration +------------------------------------- + +Environment variables found in values are automatically expanded. + +.. code:: ini + + [section_name] + persistent_dir=${HOME}/.myapp/ + +.. code:: python + + >>> asab.Config['section_name']['persistent_dir'] + '/home/user/.myapp/' + +There is a special environment variable `${THIS_DIR}` that is expanded to a directory that contains a current configuration file. +It is useful in complex configurations that utilizes included configuration files etc. + +.. code:: ini + + [section_name] + my_file=${THIS_DIR}/my_file.txt + +Another environment variable `${HOSTNAME}` contains the application hostname to be used f. e. in logging file path. + +.. code:: ini + + [section_name] + my_file=${THIS_DIR}/${HOSTNAME}/my_file.txt + +Passwords in configration +------------------------------------- + +[passwords] section in the configuration serves to securely store passwords, +which are then not shown publicly in the default API config endpoint's output. + +It is convenient for the user to store passwords at one place, +so that they are not repeated in many sections of the config file(s). + +Usage is as follows: + +.. code:: ini + + [connection:KafkaConnection] + password=${passwords:kafka_password} + + [passwords] + kafka_password= + + +Obtaining seconds +------------------------------------- + +.. py:method:: Config.getseconds() + +The seconds can be obtained using `getseconds()` method for values with different time +units specified in the configuration: + +.. code:: ini + + [sleep] + sleep_time=5.2s + another_sleep_time=10d + +The available units are: + + * ``y`` ... years + * ``M`` ... months + * ``w`` ... weeks + * ``d`` ... days + * ``h`` ... hours + * ``m`` ... minutes + * ``s`` ... seconds + * ``ms`` .. miliseconds + +If no unit is specified, float of seconds is expected. + +The obtainment of the second value in the code can be achieved in two ways: + +.. code:: python + + self.SleepTime = asab.Config["sleep"].getseconds("sleep_time") + self.AnotherSleepTime = asab.Config.getseconds("sleep", "another_sleep_time") + +Obtaining URLs +------------------------------------- + +.. py:method:: Config.geturl(section, option, scheme=None:str,tuple) + +A URL can be obtained using a `geturl()` method that takes the URL from the config and +removes leading and trailing whitespaces and trailing backslashes. + +There is an optional parameter called `scheme` that can have any URL scheme like +http, https, mongodb etc. Setting it to None, scheme validation gets bypassed. + +Setting the scheme parameter to the same scheme as in the config, it will return the URL. +If it's not the same it will raise an error. + +There are two ways of obtaining the URL: + +.. code:: py + + asab.Config["urls"].geturl("teskalabs", scheme="https") + asab.Config.geturl("urls", "github", scheme=None) + +Example: + +.. code:: python + + >>> asab.Config["urls"].geturl("teskalabs", scheme="https") + 'https://www.teskalabs.com' + +For reference this would be the configuration file: + +.. code:: ini + + [urls] + teskalabs=https://www.teskalabs.com/ + github=github.com \ No newline at end of file diff --git a/old_docs/_build/htmln/_sources/asab/index.rst.txt b/old_docs/_build/htmln/_sources/asab/index.rst.txt new file mode 100644 index 000000000..17ee066a0 --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/index.rst.txt @@ -0,0 +1,43 @@ +Asynchronous Server Application Boilerplate's documentation +=========================================================== + +Asynchronous Server App Boilerplate (or ASAB for short) is a microservice platform for Python 3.7+ and `asyncio`. +ASAB aims to minimize the amount of code that needs to be written when building a microservice or an application server. +ASAB is fully asynchronous using async/await syntax from Python 3, making your code modern, non-blocking, speedy and hence scalable. +We make every effort to build ASAB container-friendly so that you can deploy ASAB-based microservice via Docker or Kubernetes in a breeze. + +ASAB is free and open-source software, available under BSD licence. +It means that anyone is freely licenced to use, copy, study, and change the software in any way, and the source code is openly shared so that people could voluntarily improve the design of the software. +Anyone can (and is encouraged to) use ASAB in his or her projects, for free. +A current maintainer is a `TeskaLabs Ltd `_ company. + +ASAB is developed `on GitHub `_. +Contributions are welcome! + + +ASAB is designed to be powerful yet simple +------------------------------------------ + +Here is a complete example of a fully working microservice: + +.. code:: python + + import asab + + class MyApplication(asab.Application): + async def main(self): + print("Hello world!") + self.stop() + + if __name__ == "__main__": + app = MyApplication() + app.run() + + +ASAB is the right choice when +----------------------------- + + - using Python 3.7+. + - building the microservice or the application server. + - utilizing asynchronous I/O (aka `asyncio `_). + diff --git a/old_docs/_build/htmln/_sources/asab/library.rst.txt b/old_docs/_build/htmln/_sources/asab/library.rst.txt new file mode 100644 index 000000000..30faafa1c --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/library.rst.txt @@ -0,0 +1,159 @@ +.. _library-ref: + +Library +======= + +.. py:currentmodule:: asab.library + +The ASAB Library (`asab.library`) is a concept of the shared data content across microservices in the cluster. +The `asab.library` provides a read-only interface for listing and reading this content. +The library can also notify the ASAB microservice about changes, eg. for automated update/reload. + +There is a companion microservice `asab-library` that can be used for management and editation of the library content. +The `asab.library` can however operate without `asab-library` microservice. + + +Library structure +----------------- + +The library content is organized in simplified filesystem manner, with directories and files. + +Example of the library structure: + +.. code:: + + + /folder1/ + - /folder1/item1.yaml + - /folder1/item2.json + + /folder2/ + - /folder2/item3.yaml + + /folder2folder2.3/ + - /folder2/folder2.3/item4.json + + +Library path rules +------------------- + +* Any path must start with `/`, including the root path (`/`). +* The folder path must end with `/`. +* The item path must end with extension (eg. `.json`). + + +Library service +--------------- + +.. autoclass:: LibraryService + + +Example of the use: + +.. code:: python + + import asab + + class MyApplication(asab.Application): + + def __init__(self): + super().__init__() + + # Initialize the library service + self.LibraryService = asab.library.LibraryService(self, "LibraryService") + self.PubSub.subscribe("ASABLibrary.ready!", self.on_library_ready) + + async def on_library_ready(self, event_name, library): + print("# Library\n") + + for item in await self.LibraryService.list("", recursive=True): + print(" *", item) + if item.type == 'item': + itemio = await self.LibraryService.read(item.name) + if itemio is not None: + with itemio: + content = itemio.read() + print(" - content: {} bytes".format(len(content))) + else: + print(" - (DISABLED)") + + +.. automethod:: LibraryService.read + +.. automethod:: LibraryService.list + +.. automethod:: LibraryService.export + + + +Notification of changes +----------------------- + + +.. automethod:: LibraryService.subscribe + + + +Providers +--------- + +.. py:currentmodule:: asab.library.providers + +The library can be configured to work with following "backends" (aka providers): + + +Filesystem +^^^^^^^^^^ + +.. py:currentmodule:: asab.library.providers.filesystem + +.. autoclass:: FileSystemLibraryProvider + :no-undoc-members: + + +Apache Zookeeper +^^^^^^^^^^^^^^^^ + +.. py:currentmodule:: asab.library.providers.zookeeper + +.. autoclass:: ZooKeeperLibraryProvider + :no-undoc-members: + + +Microsoft Azure Storage +^^^^^^^^^^^^^^^^^^^^^^^ + +.. py:currentmodule:: asab.library.providers.azurestorage + +.. autoclass:: AzureStorageLibraryProvider + :no-undoc-members: + + +Git repository +^^^^^^^^^^^^^^ + +.. py:currentmodule:: asab.library.providers.git + +.. autoclass:: GitLibraryProvider + :no-undoc-members: + + + +Layers +------ + +The library content can be organized into unlimmited number of layers. +Each layer is represented by a `provider` with a specific configuration. + + +Library configuration +--------------------- + + +Example: + +.. code:: ini + + [library] + providers: + provider+1://... + provider+2://... + provider+3://... + diff --git a/old_docs/_build/htmln/_sources/asab/log.rst.txt b/old_docs/_build/htmln/_sources/asab/log.rst.txt new file mode 100644 index 000000000..7d3e4278d --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/log.rst.txt @@ -0,0 +1,232 @@ +Logging +======= + +.. py:currentmodule:: asab + +ASAB logging is built on top of a standard Python ``logging`` module. +It means that it logs to ``stderr`` when running on a console and ASAB also provides file and syslog output (both RFC5424 and RFC3164) for background mode of operations. + +Log timestamps are captured with sub-second precision (depending on the system capabilities) and displayed including microsecond part. + + +Recommended use +--------------- + +We recommend to create a logger ``L`` in every module that captures all necessary logging output. +Alternative logging strategies are also supported. + +.. code:: python + + import logging + L = logging.getLogger(__name__) + + ... + + L.warning("Hello world!") + + +Example of the output to the console: + +``25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule Hello world!`` + + +Logging Levels +-------------- + +ASAB uses Python logging levels with the addition of ``LOG_NOTICE`` level. +``LOG_NOTICE`` level is similar to ``logging.INFO`` level but it is visible in even in non-verbose mode. + + +.. code:: python + + L.log(asab.LOG_NOTICE, "This message will be visible regardless verbose configuration.") + + ++----------------+---------------+------------------------------+ +| Level | Numeric value | Syslog Severity level | ++================+===============+==============================+ +| ``CRITICAL`` | 50 | Critical / ``crit`` / 2 | ++----------------+---------------+------------------------------+ +| ``ERROR`` | 40 | Error / ``err`` / 3 | ++----------------+---------------+------------------------------+ +| ``WARNING`` | 30 | Warning / ``warning`` / 4 | ++----------------+---------------+------------------------------+ +| ``LOG_NOTICE`` | 25 | Notice / ``notice`` / 5 | ++----------------+---------------+------------------------------+ +| ``INFO`` | 20 | Informational / ``info`` / 6 | ++----------------+---------------+------------------------------+ +| ``DEBUG`` | 10 | Debug / ``debug`` / 7 | ++----------------+---------------+------------------------------+ +| ``NOTSET`` | 0 | | ++----------------+---------------+------------------------------+ + + +Example of a custom level configuration: + +.. code:: ini + + [logging] + levels= + myApp.module1 DEBUG + myApp.module2 WARNING + customLogger ERROR + +The logger name and the corresponding logging level are separated by a space, each logger is on a separate line. + + +Verbose mode +------------ + +The command-line argument ``-v`` enables verbose logging. +It means that log entries with levels ``DEBUG`` and ``INFO`` will be visible. +It also enables ``asyncio`` debug logging. + +The actual verbose mode is avaiable at ``asab.Config["logging"]["verbose"]`` boolean option. + +.. code:: python + + L.debug("This message will be visible only in verbose mode.") + + +Structured data +--------------- + +ASAB supports a structured data to be added to a log entry. +It follows the `RFC 5424 `_, section ``STRUCTURED-DATA``. +Structured data are a dictionary, that has to be seriazable to JSON. + +.. code:: python + + L.warning("Hello world!", struct_data={'key1':'value1', 'key2':2}) + + +Example of the output to the console: + +``25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule [sd key1="value1" key2="2"] Hello world!`` + + +Logging to file +--------------- + +The command-line argument ``-l`` on command-line enables logging to file. +Also non-empty ``path`` option in the section ``[logging:file]`` of configuration file enables logging to file as well. + +Example of the configuration file section: + +.. code:: ini + + [logging:file] + path=/var/log/asab.log + format="%%(asctime)s %%(levelname)s %%(name)s %%(struct_data)s%%(message)s", + datefmt="%%d-%%b-%%Y %%H:%%M:%%S.%%f" + backup_count=3 + rotate_every=1d + + +When the deployment expects more instances of the same application to be logging into the same file, +it is recommended, that the variable hostname is used in the file path: + +.. code:: ini + + [logging:file] + path=/var/log/${HOSTNAME}/asab.log + +In this way, the applications will log to seperate log files in different folders, +which is an intended behavior, since race conditions may occur when different application instances +log into the same file. + +Logging to console +------------------ + +ASAB will log to the console only if it detects that it runs in the foreground respectively on the terminal using ``os.isatty`` +or if the environment variable ``ASABFORCECONSOLE`` is set to ``1``. +This is useful setup for eg. PyCharm. + + +Log rotation +^^^^^^^^^^^^ + +ASAB supports a `log rotation `_. +The log rotation is triggered by a UNIX signal ``SIGHUP``, which can be used e.g. to integrate with ``logrotate`` utility. +It is implemented using ``logging.handlers.RotatingFileHandler`` from a Python standard library. +Also, a time-based log rotation can be configured using ``rotate_every`` option. + +``backup_count`` specifies a number of old files to be kept prior their removal. +The system will save old log files by appending the extensions ‘.1’, ‘.2’ etc., to the filename. + +``rotate_every`` specifies an time interval of a log rotation. +Default value is empty string, which means that the time-based log rotation is disabled. +The interval is specified by an integer value and an unit, e.g. 1d (for 1 day) or 30M (30 minutes). +Known units are `H` for hours, `M` for minutes, `d` for days and `s` for seconds. + + +Logging to syslog +----------------- + +The command-line argument ``-s`` enables logging to syslog. + +A configuration section ``[logging:syslog]`` can be used to specify details about desired syslog logging. + +Example of the configuration file section: + +.. code:: ini + + [logging:syslog] + enabled=true + format=5 + address=tcp://syslog.server.lan:1554/ + + +``enabled`` is equivalent to command-line switch ``-s`` and it enables syslog logging target. + +``format`` speficies which logging format will be used. +Possible values are: + +- ``5`` for (new) syslog format (`RFC 5424 `_ ) , +- ``3`` for old BSD syslog format (`RFC 3164 `_ ), typically used by ``/dev/log`` and +- ``m`` for Mac OSX syslog flavour that is based on BSD syslog format but it is not fully compatible. + +The default value is ``3`` on Linux and ``m`` on Mac OSX. + +``address`` specifies the location of the Syslog server. It could be a UNIX path such as ``/dev/log`` or URL. +Possible URL values: + +- ``tcp://syslog.server.lan:1554/`` for Syslog over TCP +- ``udp://syslog.server.lan:1554/`` for Syslog over UDP +- ``unix-connect:///path/to/syslog.socket`` for Syslog over UNIX socket (stream) +- ``unix-sendto:///path/to/syslog.socket`` for Syslog over UNIX socket (datagram), equivalent to ``/path/to/syslog.socket``, used by a ``/dev/log``. + +The default value is a ``/dev/log`` on Linux or ``/var/run/syslog`` on Mac OSX. + + +Logging of obsolete features +---------------------------- + +It proved to be essential to inform operators about features that are going to be obsoleted. +ASAB offers the unified "obsolete" logger. +This logger can indicate that a particular feature is marked as "obsolete" thru logs. +Such a log message can then be "grepped" from logs uniformly. + +It is recommended to include `eol` attribute in the `struct_data` of the log with a `YYYY-MM-DD` date/time of the planned obsoletion of the feature. + +Hint: We suggest automating the detection of obsolete warnings in logs so that the operations are informed well ahead of the actual removal of the feature. The string to seek in logs is " OBSOLETE ". + +Example of the use: + +.. code:: python + + asab.LogObsolete.warning("Use of the obsolete function", struct_data={'eol':'2022-31-12'}) + + +Log example: + +``21-Jul-2022 14:32:40.983884 WARNING OBSOLETE [eol="2022-31-12"] Use of the obsolete function`` + + +Reference +--------- + +.. automodule:: asab.log + :members: + :undoc-members: + :show-inheritance: diff --git a/old_docs/_build/htmln/_sources/asab/metrics.rst.txt b/old_docs/_build/htmln/_sources/asab/metrics.rst.txt new file mode 100644 index 000000000..892cd4aaa --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/metrics.rst.txt @@ -0,0 +1,347 @@ +.. currentmodule:: asab.metrics + +Metrics +======= +Metrics document the state of the application in a timescale manner. +For further analysis, connect your ASAB application to a time-series database. `Influx `_ and `Prometheus `_ are supported. + + +Metrics Service +------------------------ + +Create new metrics using :class:`MetricsService`. + +*example of counter initialization:* + +.. code:: python + + class MyApplication(asab.Application): + async def initialize(self): + from asab.metrics import Module + self.add_module(Module) + self.MetricsService = self.get_service('asab.MetricsService') + self.MyCounter = self.MetricsService.create_counter("mycounter", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0}) + + if __name__ == '__main__': + app = MyApplication() + app.run() + +See the full example here: https://github.com/TeskaLabs/asab/blob/master/examples/metrics.py + + + +Types of Metrics +---------------- + +- :class:`Gauge` stores single numerical values which can go up and down. Implements :func:`set` method to set the metric values. +- :class:`Counter` is a cumulative metric whose values can increase or decrease. Implements :func:`add` and :func:`sub` methods. +- Event per Second Counter (:class:`EPSCounter`) divides all values by delta time. +- :class:`DutyCycle` https://en.wikipedia.org/wiki/Duty_cycle +- :class:`AggregationCounter` allows to :func:`set` values based on an aggregation function. :func:`max` function is default. +- :class:`Histogram` represents cumulative histogram with :func:`set` method. + +:class:`Counter`, :class:`AggregationCounter` and :class:`Histogram` come also in variants respecting dynamic tags. (See section :ref:`Dynamic Tags`.) + +All methods that create new metrics objects can be found in the Metrics Service reference. You should never initiate a new metrics object on its own, but always through Metrics Service. Metris initialization is meant to be done in the init time of your application and **should not be done during runtime**. + + +ASAB Metrics Interpretation +---------------------------- + +Metrics Service not only creates new metrics but also periodically collects their values and sends them to selected databases. +Every 60 seconds in the application lifetime, Metrics Service gathers values of all ASAB metrics. +All Counters (and metric types that inherit from :class:`Counter`) reset at this event to their initial values by default. +Interpretation of ASAB Counters is affected by their resetable nature. Even though they monotonously increase, resetting every minute gives them a different meaning. +In a long-term observation (that's how you most probably monitor the metrics in time-series databases), these metrics count **events per minute**. +Thus, resettable Counters are presented to Prometheus database as gauge-type metrics. Set the `reset` argument to `False` when creating a new Counter to disable Counter resetting. +This periodic "flush" cycle also causes 60s delay of metric propagation into supported time-series databases. + + +Initial Values +-------------- +You can initiate your metric instance with or without initial values. When providing initial values, these values are always present and presented to databases even when these values were untouched during the last 60 seconds. You will always see these values in the data, with initial state or changed by occasion. +However, the lifetime of values (name and value pairs) added during runtime is only 60 s. Thus, if this value is not set during 60s period, you won't see it in your database anymore. + + +.. _dynamic_tags: + +Dynamic Tags +------------ +Some metric types (Counter, AggregationCounter, Histogram) allow you to use dynamic tags. All metrics in ASAB carry some tags - Hostname by default and others added by custom. +Using dynamic tags allows you to create values with a specific tag-set during runtime. Specific tag-sets expire after defined period. This might be spotted in your time-series database like a mysterious disappearance of unused tags. +Specify expiration period in confiuration. Default is 60 s. + +*example configuration* + +.. code:: + + [asab:metrics] + expiration=60 + + +InfluxDB +-------- +Metrics can be collected in the Influx time-series database. + +*configuration example:* + +.. code:: + + [asab:metrics] + target=influxdb + + [asab:metrics:influxdb] + url=http://localhost:8086/ + bucket=my_bucket + org=my_org + token=my_token + +**InfluxDB 2.0 API parameters**: + +- **url** - [required] url string of your influxDB +- **bucket** - [required] the destination bucket for writes +- **org** - [required] specifies the destination organization for writes +- **orgid** - [optional] specifies the ID of the destination organization for writes + (NOTE: If both orgID and org are specified, org takes precedence) +- **token** - [required] API token to authenticate to the InfluxDB + +**InfluxDB <1.8 API parameters**: + +- **url** - [required] url string of your influxDB +- **username** - [required] name of influxDB user +- **password** - [required] password of influxDB user + + +Prometheus +---------- +Prometheus is a "pull model" time-series database. +Prometheus accesses ``asab/v1/metrics`` endpoint of ASAB ApiService. Thus, connecting ASAB to Prometheus requires APIService initialization. However, no more configuration is needed. +ASAB metrics are presented to Prometheus in `OpenMetrics `_ standard format. + + +*prometheus.yaml configuration file example:* + +.. code:: yaml + + global: + scrape_interval: 15s + scrape_timeout: 10s + evaluation_interval: 15s + + scrape_configs: + - job_name: 'metrics_example' + metrics_path: '/asab/v1/metrics' + scrape_interval: 10s + static_configs: + - targets: ['127.0.0.1:8080'] + + +.. note:: + + To satisfy the OpenMetrics format required by Prometheus, you should follow the instructions below: + + - Metrics names must fit regex ``[a-zA-Z:][a-zA-Z0-9_:]*``. (Any other characters are replaced by an underscore. Leading underscores and numbers are stripped. These changes proceed without warning.) + - Metrics names MUST NOT end with “total” or “created”. + - Tags SHOULD contain items “unit” and “help” providing metadata to Prometheus. + - Values MUST be float or integer. + + +Metrics Endpoints +----------------- +The **API Service** in ASAB offers several endpoints that monitor internal ASAB functionality. Some of them present the current state of metrics. + +``/asab/v1/metrics`` + +- This endpoint returns metrics in OpenMetrics format and its primary purpose is to satisfy Prometheus database needs. + +``/asab/v1/metrics.json`` + +- This endpoint presents metrics data in JSON format. + +``/asab/v1/watch_metrics`` + +- Use this endpoint for developing or monitoring your app from the terminal. It returns a simple table of ASAB metrics. You can filter metrics by name using the ``filter`` parameter and ``tags`` parameter to show or hide tags. + + +*example commands:* + +.. code:: + + watch curl localhost:8080/asab/v1/watch_metrics + +.. code:: + + watch curl localhost:8080/asab/v1/watch_metrics?name=web_requests_duration_max,tags=True + + +HTTP Target +----------- +For use cases requiring a push model of metrics digestion, there is an HTTP Target. HTTP Target creates a POST request to configured URL with current metrics state sent as JSON body. +Configuration is required. + +*configuration example:* + +.. code:: + + [asab:metrics] + target=http + + [asab:metrics:http] + url=http://consumer_example:8080/consume + + + +Web Requests Metrics +-------------------- + +ASAB :class:`WebService` class automatically provides metrics counting web requests. +There are 5 metrics quantifying requests to all ASAB endpoints. + +- `web_requests` - Counts requests to asab endpoints as events per minute. +- `web_requests_duration` - Counts total requests duration to asab endpoints per minute. +- `web_requests_duration_min` - Counts minimal request duration to asab endpoints per minute. +- `web_requests_duration_max` - Counts maximum request duration to asab endpoints per minute. +- `web_requests_duration_hist` - Cumulative histogram counting requests in buckets defined by the request duration. + + +Native Metrics +-------------- + +You can opt out of Native Metrics through configuration by setting `native_metrics` to `false`. Default is `true`. + +*example configuration* + +.. code:: + + [asab:metrics] + native_metrics=true + +**Memory Metrics** + +A gauge with the name ``os.stat`` gathers information about memory usage by your application. + +You can find several metric values there: + +- VmPeak - Peak virtual memory size +- VmLck - Locked memory size +- VmPin - Pinned memory size +- VmHWM - Peak resident set size ("high water mark") +- VmRSS - Resident set size +- VmData, VmStk, VmExe - Size of data, stack, and text segments +- VmLib - Shared library code size +- VmPTE - Page table entries size +- VmPMD - Size of second-level page tables +- VmSwap - Swapped-out virtual memory size by anonymous private pages; shmem swap usage is not included + +**Logs Counter** + +There is a default Counter named ``logs`` with values ``warnings``, ``errors``, and ``critical``, counting logs with respective levels. +It is a humble tool for application health monitoring. + + + +Reference +--------- + +.. autoclass:: MetricsService + :show-inheritance: + + .. automethod:: create_gauge + + Creates :class:`Gauge` object. + + .. automethod:: create_counter + + Creates :class:`Counter` or :class:`CounterWithDynamicTags` object. + + .. automethod:: create_eps_counter + + Creates :class:`EPSCounter` object. + + .. automethod:: create_duty_cycle + + Creates :class:`DutyCycle` object. + + .. automethod:: create_aggregation_counter + + Creates :class:`AggregationCounter` or :class:`AggregationCounterWithDynamicTags` object. + + .. automethod:: create_histogram + + Creates :class:`Histogram` or :class:`HistogramWithDynamicTags` object. + + + +.. autoclass:: Gauge + :show-inheritance: + + Argument `init_values` is a dictionary with initial values and value names as keys. + + .. automethod:: set + + :param name: name of the value + :param value: value itself + + + +.. autoclass:: Counter + :show-inheritance: + + Argument `init_values` is a dictionary with initial values and value names as keys. + If reset is True, Counter resets every 60 seconds. + + .. automethod:: add + + .. automethod:: sub + + +.. autoclass:: EPSCounter + :show-inheritance: + + +.. autoclass:: DutyCycle + :show-inheritance: + + To initialize DutyCycle, provide an application loop (asab.Application.Loop) as this object tracks the time of the application. + + +.. autoclass:: AggregationCounter + :show-inheritance: + + Values (their names and init_values) can be provided when initializing the metrics or added with :func:`set` method. + :func:`add` and :func:`sub` methods are not implemented. + + .. automethod:: set + + Applies aggregation function on recent Counter value and value in argument and sets the result as new value of the Counter. + + + +.. autoclass:: Histogram + :show-inheritance: + + .. automethod:: set + + + +.. autoclass:: CounterWithDynamicTags + :show-inheritance: + + .. automethod:: add + + .. automethod:: sub + + + +.. autoclass:: AggregationCounterWithDynamicTags + :show-inheritance: + + .. automethod:: set + + + +.. autoclass:: HistogramWithDynamicTags + :show-inheritance: + + .. automethod:: set + diff --git a/old_docs/_build/htmln/_sources/asab/module.rst.txt b/old_docs/_build/htmln/_sources/asab/module.rst.txt new file mode 100644 index 000000000..0e47b5b49 --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/module.rst.txt @@ -0,0 +1,65 @@ +Module +====== + +.. py:currentmodule:: asab + +.. py:class:: Module + +Modules are registered at the module registry, managed by an application object. +See :any:`Application.Modules` for more details. +Module can be loaded by ASAB and typically provides one or more :any:`Service` objects. + + +Structure +--------- + +Recommended structure of the ASAB module:: + + mymodule/ + __init__.py + myservice.py + + +Content of the `__init__.py`: + +.. code:: python + + import asab + from .myservice import MyService + + # Extend ASAB configuration defaults + asab.Config.add_defaults({ + 'mymodule': { + 'foo': 'bar' + } + }) + + class MyModule(asab.Module): + def __init__(self, app): + super().__init__(app) + self.service = MyService(app, "MyService") + + +And this is how the module is loaded: + +.. code:: python + + from mymodule import MyModule + app.add_module(MyModule) + +For more details see :any:`Application.add_module`. + + +Lifecycle +--------- + +.. py:method:: Module.initialize(app) + +Called when the module is initialized. +It can be overriden by an user. + + +.. py:method:: Module.finalize(app) + +Called when the module is finalized e.g. during application exit-time. +It can be overriden by an user. diff --git a/old_docs/_build/htmln/_sources/asab/pubsub.rst.txt b/old_docs/_build/htmln/_sources/asab/pubsub.rst.txt new file mode 100644 index 000000000..850db71d8 --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/pubsub.rst.txt @@ -0,0 +1,218 @@ +Publish-Subscribe +================= + +.. py:currentmodule:: asab + +Publish–subscribe is a messaging pattern where senders of messages, called publishers, send the messages to receivers, called subscribers, via PubSub message bus. Publishers don't directly interact with subscribers in any way. Similarly, subscribers express interest in one or more message types and only receive messages that are of interest, without knowledge of which publishers, if any, there are. + +.. py:class:: PubSub(app) + +ASAB ``PubSub`` operates with a simple messages, defined by their *message type*, which is a string. +We recommend to add ``!`` (explamation mark) at the end of the message type in order to distinguish this object from other types such as Python class names or functions. +Example of the message type is e.g. :any:`Application.run!` or :any:`Application.tick/600!`. + +The message can carry an optional positional and keyword arguments. +The delivery of a message is implemented as a the standard Python function. + + +*Note:* There is an default, application-wide Publish-Subscribe message bus at :any:`Application.PubSub` that can be used to send messages. +Alternatively, you can create your own instance of :py:class:`PubSub` and enjoy isolated PubSub delivery space. + + +Subscription +------------ + +.. py:method:: PubSub.subscribe(message_type, callback) + +Subscribe to a message type. Messages will be delivered to a ``callback`` callable (function or method). +The ``callback`` can be a standard callable or an ``async`` coroutine. +Asynchronous ``callback`` means that the delivery of the message will happen in a ``Future``, asynchronously. + +``Callback`` callable will be called with the first argument + +Example of a subscription to an :any:`Application.tick!` messages. + +.. code:: python + + class MyClass(object): + def __init__(self, app): + app.PubSub.subscribe("Application.tick!", self.on_tick) + + def on_tick(self, message_type): + print(message_type) + + +Asynchronous version of the above: + +.. code:: python + + class MyClass(object): + def __init__(self, app): + app.PubSub.subscribe("Application.tick!", self.on_tick) + + async def on_tick(self, message_type): + await asyncio.sleep(5) + print(message_type) + + +.. py:method:: PubSub.subscribe_all(obj) + +To simplify the process of subscription to :any:`PubSub`, ASAB offers the decorator-based *"subscribe all"* functionality. + + +In the followin example, both ``on_tick()`` and ``on_exit()`` methods are subscribed to :any:`Application.PubSub` message bus. + +.. code:: python + + class MyClass(object): + def __init__(self, app): + app.PubSub.subscribe_all(self) + + @asab.subscribe("Application.tick!") + async def on_tick(self, message_type): + print(message_type) + + @asab.subscribe("Application.exit!") + def on_exit(self, message_type): + print(message_type) + + +.. py:method:: PubSub.unsubscribe(message_type, callback) + +Unsubscribe from a message delivery. + + +.. autoclass:: asab.Subscriber + :members: + :undoc-members: + +The subscriber object can be also used as `an asynchonous generator`. +The example of the subscriber object usage in `async for` statement: + +.. code:: python + + async def my_coroutine(self): + # Subscribe for a two application events + subscriber = asab.Subscriber( + self.PubSub, + "Application.tick!", + "Application.exit!" + ) + async for message_type, args, kwargs in subscriber: + if message_type == "Application.exit!": + break; + print("Tick.") + + +Publishing +---------- + +.. py:method:: PubSub.publish(message_type, \*args, \**kwargs) + +Publish a message to the PubSub message bus. +It will be delivered to each subscriber synchronously. +It means that the method returns after each subscribed ``callback`` is called. + +The example of a message publish to the :any:`Application.PubSub` message bus: + +.. code:: python + + def my_function(app): + app.PubSub.publish("mymessage!") + + +Asynchronous publishing of a message is requested by ``asynchronously=True`` argument. +The ``publish()`` method returns immediatelly and the delivery of the message to subscribers happens, when control returns to the event loop. + +The example of a **asynchronous version** of a message publish to the :any:`Application.PubSub` message bus: + +.. code:: python + + def my_function(app): + app.PubSub.publish("mymessage!", asynchronously=True) + + +Synchronous vs. asynchronous messaging +-------------------------------------- + +ASAB PubSub supports both modes of a message delivery: synchronous and asynchronous. +Moreover, PubSub also deals with modes, when asynchronous code (coroutine) does publish to synchronous code and vice versa. + ++-----------------+------------------------+---------------------------------------------+ +| | Sync publish | Async publish | ++-----------------+------------------------+---------------------------------------------+ +| Sync subscribe | Called immediately | ``call_soon(...)`` | ++-----------------+------------------------+---------------------------------------------+ +| Async subscribe | ``ensure_future(...)`` | ``call_soon(...)`` & ``ensure_future(...)`` | ++-----------------+------------------------+---------------------------------------------+ + + +Application-wide PubSub +------------------------ + +.. py:attribute:: Application.PubSub + +The ASAB provides the application-wide Publish-Subscribe message bus. + + +Well-Known Messages +^^^^^^^^^^^^^^^^^^^ + +This is a list of well-known messages, that are published on a ``Application.PubSub`` by ASAB itself. + + +.. option:: Application.init! + +This message is published when application is in the init-time. +It is actually one of the last things done in init-time, so the application environment is almost ready for use. +It means that configuration is loaded, logging is setup, the event loop is constructed etc. + + +.. option:: Application.run! + +This message is emitted when application enters the run-time. + + +.. option:: Application.stop! + +This message is emitted when application wants to stop the run-time. +It can be sent multiple times because of a process of graceful run-time termination. +The first argument of the message is a counter that increases with every ``Application.stop!`` event. + + +.. option:: Application.exit! + +This message is emitted when application enter the exit-time. + + +.. option:: Application.tick! +.. option:: Application.tick/10! +.. option:: Application.tick/60! +.. option:: Application.tick/300! +.. option:: Application.tick/600! +.. option:: Application.tick/1800! +.. option:: Application.tick/3600! +.. option:: Application.tick/43200! +.. option:: Application.tick/86400! + +The application publish periodically "tick" messages. +The default tick frequency is 1 second but you can change it by configuration ``[general] tick_period``. +:any:`Application.tick!` is published every tick. :any:`Application.tick/10!` is published every 10th tick and so on. + + +.. option:: Application.hup! + +This message is emitted when application receives UNIX signal ``SIGHUP`` or equivalent. + +.. option:: Application.housekeeping! + +This message is published when application is on the time for housekeeping. The time for housekeeping is set to 03:00 AM UTC. It can be changed in the configuration file: + +.. code:: ini + + [general] + housekeeping_time=19:30 + +This sets the housekeeping time to 7:30 PM UTC. +The time must be written in the format 'HH:MM'. +Remind yourself that the time is set to UTC, so you should be careful when operating in a different timezone. diff --git a/old_docs/_build/htmln/_sources/asab/service.rst.txt b/old_docs/_build/htmln/_sources/asab/service.rst.txt new file mode 100644 index 000000000..4fe35ba01 --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/service.rst.txt @@ -0,0 +1,72 @@ +Service +======= + +.. py:currentmodule:: asab + +.. py:class:: Service(app) + +Service objects are registered at the service registry, managed by an application object. +See :any:`Application.Services` for more details. + + +An example of a typical service class skeleton: + +.. code:: python + + class MyService(asab.Service): + + def __init__(self, app, service_name): + super().__init__(app, service_name) + ... + + async def initialize(self, app): + ... + + + async def finalize(self, app): + ... + + + def service_method(self): + .... + + +This is how a service is created and registered: + +.. code:: python + + mysvc = MyService(app, "my_service") + + +This is how a service is located and used: + +.. code:: python + + mysvc = app.get_service("my_service") + mysvc.service_method() + + + +.. py:data:: Service.Name + +Each service is identified by its name. + + +.. py:data:: Service.App + +A reference to an :py:class:`Application` object instance. + + +Lifecycle +--------- + +.. py:method:: Service.initialize(app) + +Called when the service is initialized. +It can be overriden by an user. + + +.. py:method:: Service.finalize(app) + +Called when the service is finalized e.g. during application exit-time. +It can be overriden by an user. diff --git a/old_docs/_build/htmln/_sources/asab/storage.rst.txt b/old_docs/_build/htmln/_sources/asab/storage.rst.txt new file mode 100644 index 000000000..44f7ecf89 --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/storage.rst.txt @@ -0,0 +1,227 @@ +.. currentmodule:: asab.storage + +Storage +======= + +ASAB provides a service for storing data. Data can be stored in memory or in dedicated document database. For now, `MongoDB `_ and `Elastic Search `_ databases are supported. + +Specification of the storage type +--------------------------------- + +In order to use `asab.storage`, first you have to specify the type of storage. You can add configurations in the config file: + +.. code:: ini + + [asab:storage] + type=mongodb + +or you can set it manually in the ASAB app: + +.. code:: python + + import asab + import asab.storage + + asab.Config.add_defaults( + { + 'asab:storage': { + 'type': 'mongodb' + } + } + ) + +The options for the storage type are: + +- `inmemory`: Collects data directly in memory +- `mongodb`: Collects data using MongoDB database. Depends on `pymongo `_ and `motor `_ libraries. +- `elasticsearch`: Collects data using Elastic Search database. Depends on `aiohttp `_ library. + +Although these three databases are different, accessing the database and manipulation with collections is done by using the same methods. + +For accessing the storage, simply `add asab.storage.Module`` when initializing and register the service. + +.. code:: python + + class MyApplication(asab.Application): + + async def initialize(self): + + self.add_module(asab.storage.Module) + + async def main(self): + storage = self.get_service("asab.StorageService") + + +Manipulation with databases +--------------------------- + +Upsertor +~~~~~~~~ + +Upsertors are used for manipulations with databases. Upsertor is an object that works like a pointer to the specified database and optionally to object id. + +.. code:: python + + u = storage.upsertor("test-collection") + +The method :func:`upsertor()` create an upsertor object associated with the specified collection. It takes `collection` as an argument and can have two parameters `obj_id` and `version`, which are used for getting an existing object by its ID and version. + +Inserting an object +~~~~~~~~~~~~~~~~~~~ + +For inserting an object to the collection, use the `set()` method. + +.. code:: python + + u.set("key", "value") + +To execute these procedures, simply run the :func:`execute()` coroutine method, which commits the upsertor data to the storage and returns the ID of the object. Since it is a coroutine, it must be awaited. + +.. code:: python + + object_id = await u.execute() + +The `execute()` method has optional parameters `custom_data` and `event_type`, which are used for webhook requests. + +.. code:: python + + object_id = await u.execute(custom_data= {"foo": "bar"},event_type="object_created") + +Getting a single object +~~~~~~~~~~~~~~~~~~~~~~~ + +For getting a single object, use :func:`get()` coroutine method that takes two arguments `collection` and `obj_id` and finds an object by its ID in collection. + +.. code:: python + + obj = await storage.get(collection="test-collection", obj_id=object_id) + +When the requested object is not found in the collection, the method raises ``KeyError``. Remember to handle this exception properly when using databases in your services and prevent them from crashing! + +.. note:: + + MongoDB storage service in addition provides a coroutine method :func:`get_by()` which is used for accessing an object by finding its key-value pair. + + .. code::python + + obj = await storage.get_by(database="test-collection", key="key", value="value") + +Updating an object +~~~~~~~~~~~~~~~~~~ + +For updating an object, first obtain the upsertor specifying its `obj_id` and `version`. + +.. code:: python + + u = storage.upsertor("test-collection", obj_id=object_id, version=obj['_v'] + +We strongly recommend to read the version from the object such as above. That creates a soft lock on the record. It means that if the object is updated by other component in meanwhile, your upsertor will fail and you should retry the whole operation. The new objects should have a version set to 0, which is done by default. + +After obtaining an upsertor, you can update the object via the :func:`set()` coroutine. + +.. code::python + + u.set("key", "new_value") + object_id = await u.execute() + + +Deleting an object +~~~~~~~~~~~~~~~~~~ + +For deleting an object from database, use the :func:`delete()` coroutine method which takes arguments `collection` and `obj_id`, deletes the object and returns its ID. + +.. code:: python + + deleted_id = await u.delete("test-collection", object_id) + + + +Storing data in memory +---------------------- + +If the option `inmemory` is set, ASAB will store data in its own memory. In particular, `asab.StorageService` is initialized with an attribute `InMemoryCollections` which is a dictionary where all the collections are stored in. + +.. note:: + + You can go through all the databases directly by accessing `InMemoryCollections` attribute, although we do not recommend that. + + .. code:: python + + import pprint + + storage = self.get_service("asab.StorageService") + pprint.pprint(storage.InMemoryCollections, indent=2) + + +Storing data in MongoDB +----------------------- + +If the option `mongodb` is set, ASAB will store data in MongoDB database. + +ASAB uses `motor library `_ which provides non-blocking MongoDB driver for `asyncio`. + +You can specify the database name and URL for MongoDB in config file (the following example is the default configuration): + +.. code:: ini + + [asab:storage] + type=mongodb + mongodb_uri=mongodb://localhost:27017 + mongodb_database=asabdb + + + +.. py:method:: StorageService.get_by(collection: str, key: str, value, decrypt = None) -> dict + + +.. py:method:: StorageService.collection(collection: str) -> motor.motor_asyncio.AsyncIOMotorCollection + +Mongo Storage class provides in addition a method :func:`collection()` for accessing database directly. It takes `collection` as the argument and returns `motor.motor_asyncio.AsyncIOMotorCollection` object, which can be used for calling MongoDB directives. + +Example of the use: + +.. code:: python + + collection = await storage.collection("test-collection") + cursor = collection.find({}) + while await cursor.fetch_next: + data = cursor.next_object() + pprint.pprint(data) + +The full list of methods suitable for this object is described in the `official documentation `_. + + + +Storing data in Elastic Search +------------------------------ + +When using Elastic Search, add configurations for URL, username and password. + +.. code:: ini + + [asab:storage] + type=elasticsearch + elasticsearch_url=http://localhost:9200/ + elasticsearch_username=JohnDoe + elasticsearch_password=lorem_ipsum_dolor?sit_amet!2023 + +You can also specify `refreshing parameter ` and scroll timeout for `Elastic Search Scroll API `_. + +.. code:: ini + + [asab:storage] + refresh=true + scroll_timeout=1m + + + +Encryption and decryption +------------------------- + +TODO + + +Object ID +--------- + +TODO (how ID's are generated via `generateid()` method) \ No newline at end of file diff --git a/old_docs/_build/htmln/_sources/asab/various.rst.txt b/old_docs/_build/htmln/_sources/asab/various.rst.txt new file mode 100644 index 000000000..180658c98 --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/various.rst.txt @@ -0,0 +1,60 @@ +Various utility classes +======================= + +.. automodule:: asab.abc + :members: + :undoc-members: + :show-inheritance: + + +Singleton +--------- + +.. automodule:: asab.abc.singleton + :members: + :undoc-members: + +Usage: + +.. code:: python + + import asab + + class MyClass(metaclass=asab.Singleton): + ... + + +Persistent dictionary +--------------------- + +.. automodule:: asab.pdict + :members: + :undoc-members: + :show-inheritance: + + +*Note*: A recommended way of initializing the persistent dictionary: + +.. code:: python + + PersistentState = asab.PersistentDict("some.file") + PersistentState.setdefault('foo', 0) + PersistentState.setdefault('bar', 2) + + +Timer +----- + +.. automodule:: asab.timer + :members: + :undoc-members: + :show-inheritance: + + +Sockets +------- + +.. automodule:: asab.socket + :members: + :undoc-members: + :show-inheritance: diff --git a/old_docs/_build/htmln/_sources/asab/web/authn.rst.txt b/old_docs/_build/htmln/_sources/asab/web/authn.rst.txt new file mode 100644 index 000000000..0926ac926 --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/web/authn.rst.txt @@ -0,0 +1,75 @@ +Authn module +================= + +.. py:currentmodule:: asab.web.authn + +Module :py:mod:`asab.web.authn` provides middlewares and classes to allow only authorized users access specified web server endpoints. +It also allows to forward requests to the authorization server via instance of OAuthForwarder. + +Currently available authorization technologies include OAuth 2.0, public/private key and HTTP basic auth. + +Middleware +------------ + +.. py:method:: authn_middleware_factory(app, implementation, *args, **kwargs): + +First step is to define the authorization implementation, which can be the OAuth 2.0, public/private key or +HTTP basic auth. Depending on the implementation, there are arguments which further specify the authorization +servers that are going to be used. + +When it comes to OAuth 2.0, there are :any:`methods` for every OAuth 2.0 server, that is going to be used for authorization +and obtainment of the user identity. The relevant method is selected based on access token prefix, that is received +from the client in the HTTP request (:any:`Authorization` header): + +`Authorization: Bearer -` + +The following example illustrates how to register a middleware inside the web server container with OAuth 2.0 +implementation and GitHub method. + +.. code:: python + + container.WebApp.middlewares.append( + asab.web.authn.authn_middleware_factory(self, + "oauth2client", # other implementations include: "basicauth" and "pubkeyauth" + methods=[ + # Use GitHub OAuth provider + asab.web.authn.oauth.GitHubOAuthMethod(), + ], + ) + ) + + +Decorators +------------ + +In order to require authorization for a specific endpoint and thus utilize the output of the registered middleware, +it is necessary to decorate its handler method with :any:`authn_required_handler` decorator. + +The decorator provide the handler method with an :any:`identity` argument, which contains the user identity received +from the authorization server. Thus the user information can be further evaluated or included as part of the response. +To receive just the identity information but not force the authorization for the endpoint, the :any:`authn_optional_handler` +can be used instead. + +The following example illustrates how to use the :any:`authn_required_handler` decorator in order to enforce the +authorization and receive user identity in the :any:`identity` argument: + +.. code:: python + + @asab.web.authn.authn_required_handler + async def user(self, request, *, identity): + return asab.web.rest.json_response(request=request, data={ + 'message': '"{}", you have accessed our secured "user" endpoint.'.format(identity), + }) + + +Example +------------ + +To see & try the full example which utilizes OAuth 2.0 middleware and decorators, please see the code +in the following link: + +`https://github.com/TeskaLabs/asab/blob/master/examples/web-authn-oauth.py `_ + +Another example serves to demonstrate the public/private key authorization via ASAB web client ssl cert authorization: + +`https://github.com/TeskaLabs/asab/blob/master/examples/web-authn-pubkey.py `_ diff --git a/old_docs/_build/htmln/_sources/asab/web/cors.rst.txt b/old_docs/_build/htmln/_sources/asab/web/cors.rst.txt new file mode 100644 index 000000000..a5aaad072 --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/web/cors.rst.txt @@ -0,0 +1,21 @@ +Cross-Origin Resource Sharing (CORS) +==================================== + +When you create a web container, you specify a config section name. In the example below it’s `myapp:web`: + +.. code:: python + + asab.web.WebContainer(self.WebService, "myapp:web") + +You can then configure CORS by running your app with a config file with this contents: + +.. code:: INI + + [myapp:web] + cors=* + cors_preflight_paths=/* + + + +- **cors**: contents of the Access-Control-Allow-Origin header +- **cors_preflight_paths**: a pattern for endpoints that shall return responses to pre-flight requests (OPTIONS). Value must start with "/". diff --git a/old_docs/_build/htmln/_sources/asab/web/index.rst.txt b/old_docs/_build/htmln/_sources/asab/web/index.rst.txt new file mode 100644 index 000000000..42c2ee0c2 --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/web/index.rst.txt @@ -0,0 +1,163 @@ +The web server +============== + +ASAB provides a web server in a :py:mod:`asab.web` module. +This module offers an integration of a :py:mod:`aiohttp` `web server `_. + +1. Before you start, make sure that you have :py:mod:`aiohttp` module installed. + +.. code-block:: bash + + $ pip3 install aiohttp + +2. The following code creates a simple web server application + +.. code:: python + + #!/usr/bin/env python3 + import asab + import asab.web + import aiohttp + + class MyApplication(asab.Application): + + def __init__(self): + super().__init__() + + # Load the ASAB Web module + self.add_module(asab.web.Module) + + # Locate the ASAB Web service + websvc = self.get_service("asab.WebService") + + # Create the Web container + container = asab.web.WebContainer(websvc, 'my:web', config={"listen": "0.0.0.0:8080"}) + + # Add a route to the handler + container.WebApp.router.add_get('/hello', self.hello) + + # This is the web request handler + async def hello(self, request): + return aiohttp.web.Response(text='Hello!\n') + + if __name__ == '__main__': + app = MyApplication() + app.run() + +3. Test it with `curl` + +.. code-block:: bash + + $ curl http://localhost:8080/hello + Hello! + + +Web Service +----------- + +.. py:currentmodule:: asab.web.service + +.. py:class:: WebService + +Service location example: + +.. code:: python + + from asab.web import Module + self.add_module(Module) + svc = self.get_service("asab.WebService") + + +Configuration +------------- + +The default configuration of the `web` container in ASAB is following: + +.. code:: ini + + [web] + listen=0.0.0.0:8080 + + +Multiple listening interfaces can be specified: + +.. code:: ini + + [web] + listen: + 0.0.0.0:8080 + :: 8080 + + +Multiple listening interfaces, one with HTTPS (TLS/SSL) can be specified: + +.. code:: ini + + [web] + listen: + 0.0.0.0 8080 + :: 8080 + 0.0.0.0 8443 ssl:web + + [ssl:web] + cert=... + key=... + ... + + +Multiple interfaces, one with HTTPS (inline): + + +.. code:: ini + + [web] + listen: + 0.0.0.0 8080 + :: 8080 + 0.0.0.0 8443 ssl + + # The SSL parameters are inside of the WebContainer section + cert=... + key=... + ... + + +Other available options are: + + * `backlog` + * `rootdir` + * `servertokens` (default value `full`) + * `cors` + * `cors_preflight_paths` + + +TLS/SSL paramereters: + + * `cert` + * `key` + * `password` + * `cafile` + * `capath` + * `ciphers` + * `dh_params` + * `verify_mode`: one of `CERT_NONE`, `CERT_OPTIONAL` or `CERT_REQUIRED` + * `check_hostname` + * `options` + +Sessions +-------- + +ASAB Web Service provides an implementation of the web sessions. + + +.. py:currentmodule:: asab.web.session + +.. py:class:: ServiceWebSession + +TODO: ... + + +.. py:function:: session_middleware(storage) + +TODO: ... + diff --git a/old_docs/_build/htmln/_sources/asab/web/restapidocs.rst.txt b/old_docs/_build/htmln/_sources/asab/web/restapidocs.rst.txt new file mode 100644 index 000000000..1e062ee1f --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/web/restapidocs.rst.txt @@ -0,0 +1,93 @@ +REST API Docs +============== + +ASAB's API service generates a `Swagger documentation `_ which automatically shows all +of your endpoints and you can add summaries, descriptions, tags and more. + +If you want Authorization in Swagger docs, you will need an OpenIDConnect endpoint. + +In your microservice +-------------------- + +First you need to initialize the API Service: + +.. code-block:: python + + # Initialize API service + self.ApiService = asab.api.ApiService(self) + + # Introduce Web to API Service + self.ApiService.initialize_web() + +After initializing the API Service a **/doc** endpoint will become available. You will notice +that some or none of your endpoints have summaries, tags or descriptions. + +That's because you need to add a docstring to your endpoint method: + +.. code-block:: python + + async def endpoint(self, request): + """ + Summary looks like this and takes the first line from docstring. + + Description of what this endpoint does. + + --- + tags: [asab.mymicroservice] + """ + +Also by adding a docstring to your ASAB Application, a description will be automatically added to the top of the Swagger docs: + +.. code-block:: python + + class TutorialApp(asab.Application): + """ + TutorialApp is the best microservice in the world! + + The description supports HTML tags + """ + +Authorization in Swagger +------------------------ + +Authorization requires making an OpenIDConnect endpoint with an Authorization and Token endpoint (like with using `SeaCat Auth `_). + +After your endpoint has authorization, `here's an example `_, +add the Authorization and Token endpoints into your `config <#configuration>`_. + +For the authorization bearer token to be added to the request, a scope is needed to be put into the security parameter in a docstring. +It does not matter what it is called or if it exists, but it's needed to be there. But "`- oAuth:`" always needs to be there. + +.. code-block:: python + + @asab.web.authz.required("resource:topsecret") + async def top_secret_endpoint(self, request): + """ + Top secret! + + --- + tags: [asab.coolestmicroservice] + security: + - oAuth: + - read + """ + +After setting up Authorization, a green `Authorize` button should appear in the Swagger docs. + +Configuration +------------- + +For authorization you will need to add a `authorizationUrl` and `tokenUrl`: + +.. code-block:: ini + + [asab:doc] + authorizationUrl=http://localhost:8080/openidconnect/authorize + tokenUrl=http://localhost:8080/openidconnect/token + +If you have an endpoint that requires a scope, you can add it with the configuration file: + +.. code-block:: ini + + [asab:doc] + scopes=read,write diff --git a/old_docs/_build/htmln/_sources/asab/zookeeper.rst.txt b/old_docs/_build/htmln/_sources/asab/zookeeper.rst.txt new file mode 100644 index 000000000..714a169ca --- /dev/null +++ b/old_docs/_build/htmln/_sources/asab/zookeeper.rst.txt @@ -0,0 +1,154 @@ +.. _zookeeper-ref: + +Zookeeper +========= + +.. py:currentmodule:: asab.zookeeper + +The `asab.zookeeper` is a `Apache Zookeeper `_ asynchronous client based on `Kazoo `_ library. + +Apache ZooKeeper is a distributed coordination service that provides a hierarchical key-value data store, called a znode tree, to store and manage configuration, coordination, and synchronization data. The znode tree is similar to a file system tree, where each znode is like a file or a directory. + +Apache ZooKeeper can be used to design microservices in a stateless manner by managing and coordinating the state information between microservices. In this design, each microservice does not store any state information, but instead relies on ZooKeeper for state management. + + +Zookeeper container +------------------- + +A Zookeeper container represents a connectivity to Apache Zookeeper server(s). +The application can operate multiple instances of Zookeeper container. + + +This code illustrates the typical way how to create Zookeeper container: + +.. code:: python + + import asab.zookeeper + + class MyApplication(asab.Application): + + def __init__(self): + ... + + # Load the ASAB Zookeeper module + self.add_module(asab.zookeeper.Module) + + # Initialize ZooKeeper Service + self.ZooKeeperService = self.get_service("asab.ZooKeeperService") + + # Create the Zookeeper container + self.ZooKeeperContainer = asab.zookeeper.ZooKeeperContainer(self.ZooKeeperService) + + # Subscribe to Zookeeper container ready event + self.PubSub.subscribe("ZooKeeperContainer.started!", self._on_zk_ready) + + + async def _on_zk_ready(self, event_name, zookeeper): + if zookeeper != self.ZooKeeperContainer: + return + + print("Connected to Zookeeper!") + + + +.. autoclass:: ZooKeeperContainer + +Specifications are obtained from: + +1. `z_path` argument, which is Zookeeper URL (see below) +2. the configuration section specified by `config_section_name` argument +3. `ZOOKEEPER_SERVERS` environment variable + +The `z_path` argument has precedence over config but the implementation will look +at configuration if `z_path` URL is missing completely or partially. +Also, if configuration section doesn't provide information about servers, `ZOOKEEPER_SERVERS` environment variable is used. + + +Example of configuration section +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code:: ini + + [zookeeper] + servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 + path=myfolder + + +Example of `ZOOKEEPER_SERVER` environment variable +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code:: ini + + ZOOKEEPER_SERVERS=zookeeper-1:2181,zookeeper-2:2181 + + +Supported types of `z_path` URLs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +1. Absolute URL + + `zookeeper://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/etc/configs/file1` + + + The URL contains all information for a connectivity. + + +2. URL without servers with absolute path + + `zookeepers:///etc/configs/file1` + + In this case the relative url is expanded as follows: + `zookeeper://{zookeeper_servers}/etc/configs/file1` + + Where `{zookeeper_servers}` is substituted with the `servers` entry of the [zookeeper] configuration file section. + + +3. URL without servers with relative path + + `zookeeper:./etc/configs/file1` + + In this case, the relative URL is expanded as follows: + `zookeper://{zookeeper_servers}/{zookeeper_path}/etc/configs/file1` + + Where {zookeeper_servers} is substituted with the `servers` entry of the [zookeeper] configuration file section and + {zookeeper_path} is substituted with the "path" entry of the [zookeeper] configuration file section. + + + +.. automethod:: ZooKeeperContainer.is_connected + + +Reading from Zookeeeper +----------------------- + +.. automethod:: ZooKeeperContainer.get_children + +.. automethod:: ZooKeeperContainer.get_data + +.. automethod:: ZooKeeperContainer.get_raw_data + + +Advertisement into Zookeeper +---------------------------- + +.. automethod:: ZooKeeperContainer.advertise + + +Kazoo +----- + +Kazoo is the synchronous Python library for Apache Zookeeper. + +It can be used directly for a more complicated tasks. +Kazoo `client` is accessible at `ZooKeeperContainer.ZooKeeper.Client`. +Synchronous methods of Kazoo client must be executed using `ProactorService`. + +Here is the example: + +.. code:: python + + def write_to_zk(): + self.ZooKeeperContainer.ZooKeeper.Client.create(path, data, sequence=True, ephemeral=True, makepath=True) + + await self.ZooKeeperContainer.ZooKeeper.ProactorService.execute(write_to_zk) + diff --git a/old_docs/_build/htmln/_sources/get-started.rst.txt b/old_docs/_build/htmln/_sources/get-started.rst.txt new file mode 100644 index 000000000..1b47c6110 --- /dev/null +++ b/old_docs/_build/htmln/_sources/get-started.rst.txt @@ -0,0 +1,107 @@ +Getting started +=============== + +Make sure you have both `pip `_ and at +least version 3.7 of Python before starting. ASAB uses the new ``async``/``await`` +syntax, so earlier versions of python won't work. + +1. Install ASAB: + +.. code:: bash + + $ pip3 install asab + + +2. Create a file called ``main.py`` with the following code: + + +.. code:: python + + #!/usr/bin/env python3 + import asab + + class MyApplication(asab.Application): + async def main(self): + print("Hello world") + + if __name__ == '__main__': + app = MyApplication() + app.run() + + +3. Run the server: + +.. code:: bash + + $ python3 main.py + Hello world + +You are now successfully runinng an ASAB application server. + + +4. Stop the application by ``Control-C``. + +Note: The ASAB is designed around a so-called `event loop `_. +It is meant primarily for server architectures. +For that reason, it doesn't terminate and continue running and serving eventual requests. + + + +Going into details +------------------ + +.. code:: python + + #!/usr/bin/env python3 + +ASAB application uses a Python 3.7+. +This is specified a by hashbang line at the very begginig of the file, on the line number 1. + + +.. code:: python + + import asab + + +ASAB is included from as `asab` module via an import statement. + + +.. code:: python + + class MyApplication(asab.Application): + +Every ASAB Application needs to have an application object. +It is a singleton; it means that the application must create and operate precisely one instance of the application. +ASAB provides the base :any:`Application` class that you need to inherit from to implement your custom application class. + + +.. code:: python + + async def main(self): + print("Hello world") + +The :any:`Application.main()` method is one of the application lifecycle methods, that you can override to implement desired application functionality. +The `main` method is a coroutine, so that you can await any tasks etc. in fully asynchronous way. +This method is called when ASAB application is executed and initialized. +The lifecycle stage is called "runtime". + +In this example, we just print a message to a screen. + + + +.. code:: python + + if __name__ == '__main__': + app = MyApplication() + app.run() + +This part of the code is executed when the Python program is launched. +It creates the application object and executes the :any:`Application.run()` method. +This is a standard way of how ASAB application is started. + + +Next steps +---------- + +Check out tutorials about how to build ASAB based :doc:`web server `. + diff --git a/old_docs/_build/htmln/_sources/index.rst.txt b/old_docs/_build/htmln/_sources/index.rst.txt new file mode 100644 index 000000000..9a9a7147a --- /dev/null +++ b/old_docs/_build/htmln/_sources/index.rst.txt @@ -0,0 +1,54 @@ +.. ASAB documentation master file, created by + +.. include:: asab/index.rst + +.. toctree:: + :maxdepth: 1 + :caption: Introduction + + get-started + tutorial/web/chapter1 + tutorial/web/chapter2 + +.. toctree:: + :maxdepth: 2 + :caption: Services + + asab/web/index + asab/web/restapidocs + asab/web/authn + asab/web/cors + asab/metrics + asab/storage + asab/alert + +.. toctree:: + :maxdepth: 2 + :caption: Reference + + asab/application + asab/config + asab/log + asab/pubsub + asab/service + asab/module + asab/various + asab/zookeeper + asab/library + +.. toctree:: + :maxdepth: 2 + :caption: Administration + + admin/install + admin/command-line + admin/containers + admin/systemd + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/old_docs/_build/htmln/_sources/tutorial/web/chapter1.rst.txt b/old_docs/_build/htmln/_sources/tutorial/web/chapter1.rst.txt new file mode 100644 index 000000000..bb8bb0c47 --- /dev/null +++ b/old_docs/_build/htmln/_sources/tutorial/web/chapter1.rst.txt @@ -0,0 +1,69 @@ +Web Server Tutorial +=================== + +Create a simple web server with ASAB. + + +The code +-------- + +.. include:: web1/app.py + :code: python + +| To start the application, store above code in a file ``app.py``. +| Execute ``$ python3 ./app.py`` to run it. + +The ASAB web server is now available at http://localhost:8080/. + + +Deeper look +----------- + +**ASAB Application** + +.. code:: python + + #!/usr/bin/env python3 + import asab.web.rest + + class MyWebApplication(asab.Application): + + def __init__(self): + super().__init__() + + if __name__ == '__main__': + app = MyWebApplication() + app.run() + +This is a ASAB code that declares the application class and runs it. + + +**Create a Web server** + +The ``asab.web`` module provides a ``create_web_server()`` function that simplifies creation of the Web server in the ASAB application. + + +.. code:: python + + web = asab.web.create_web_server(self) + + +**Install the handler** + +.. code:: python + + web.add_get('/hello', self.hello) + + ... + + async def hello(self, request): + return asab.web.rest.json_response( + request, + data="Hello, world!\n" + ) + + +The handler method ``hello()`` is installed at the web server at ``/hello`` endpoint. +HTTP method is ``GET``. + +It means that if you access the web server with a path ``/hello``, it will be handled by a ``hello(...)`` method. A handler method must be a coroutine. diff --git a/old_docs/_build/htmln/_sources/tutorial/web/chapter2.rst.txt b/old_docs/_build/htmln/_sources/tutorial/web/chapter2.rst.txt new file mode 100644 index 000000000..7817a5154 --- /dev/null +++ b/old_docs/_build/htmln/_sources/tutorial/web/chapter2.rst.txt @@ -0,0 +1,629 @@ +Create microservice with REST API +================================= + +With this tutorial, you will create a basic ASAB microservice that provides a REST HTTP API. +This microservice will implement Create, Read, Update and Delete functionality, in another words CRUD. +MongoDB will be used as the database. + + +Prerequisites +------------- + +1. Python version 3.6 or later +2. Asynchronous Server App Boilerplate (ASAB) version 20.3 or later +3. MongoDB instance +4. Postman + +.. note:: + We will use Docker to run MongoDB. Docker installation is not covered in this tutorial, but there are scores of good ones online should you run into any trouble. If you're not familiar with Docker yet, it is a great opportunity to start (https://www.docker.com/get-started/). + + Otherwise, you can install MongoDB following one of these tutorials: https://www.mongodb.com/docs/manual/installation/ + + +Components +---------- + +The microservice consists of several modules (aka Python files). +These modules are as follows (and also indicate the file structure) and will be discussed in more detail in the respective sections below, going from top to bottom: + +.. code:: + + . + └── myrestapi.py + ─── myrestapi + └── __init__.py + ─── app.py + ─── tutorial + └── handler.py + └── service.py + + + +MongoDB +------- + +To make things simple, let's use a Docker image. + +Pull this image: +https://hub.docker.com/_/mongo + +You can simply use the command below to run it. +If you choose to run the instance without a password, +don't forget to adjust the related **asab.Config** in `./myrestapi/app.py`. + +.. code:: bash + + docker run -d -p 27017:27017 \ + -e MONGO_INITDB_ROOT_USERNAME=user \ + -e MONGO_INITDB_ROOT_PASSWORD=secret \ + mongo + + +Postman +------- + +We use Postman to test the webservice REST API. + +You can download it here: +https://www.postman.com/downloads/ + +The Postman is fairly straightforward to use. +You can create your collection of HTTP requests, save them, or automatically generate documentation. + + +myrestapi.py +------------ + +This is where everything starts. +Begin with the shebang line, which tells the executing operating system **python** should execute this program. + +.. code:: python + + #!/usr/bin/env python3 + +Imports follow. All you need here is the application. It is called **TutorialApp**: + +.. code:: python + + from myrestapi import TutorialApp + +Next, instantiate an application class `TutorialApp` in the __main__ of the application, and run it: + +.. code:: python + + if __name__ == '__main__': + app = TutorialApp() + app.run() + + + +app.py +------ + +`./myrestapi/app.py` + +Define the application class `TutorialApp`. + +Imports first: + +.. code:: python + + import asab + import asab.web + import asab.web.rest + import asab.storage + + +Add some default configuration: + +.. code:: python + + asab.Config.add_defaults( + { + 'asab:storage': { + 'type': 'mongodb', + 'mongodb_uri': 'mongodb://mongouser:mongopassword@mongoipaddress:27017', + 'mongodb_database': 'mongodatabase' + }, + }) + +.. note:: + To make things more simple, Mongo credentials are stored here as a default configuration. + Usually, you provide your app with a configuration file using `-c` commandline option. + Learn more in section :ref:`configuration-ref`. + +Next, describe the class, it inherits from the basic ASAB Application class, +but you need to expand it a little: + +.. code:: python + + class TutorialApp(asab.Application): + + def __init__(self): + super().__init__() + # Register modules + self.add_module(asab.web.Module) + self.add_module(asab.storage.Module) + + # Locate the web service + self.WebService = self.get_service("asab.WebService") + self.WebContainer = asab.web.WebContainer( + self.WebService, "web" + ) + self.WebContainer.WebApp.middlewares.append( + asab.web.rest.JsonExceptionMiddleware + ) + + # Initialize services + from .tutorial.handler import CRUDWebHandler + from .tutorial.service import CRUDService + self.CRUDService = CRUDService(self) + self.CRUDWebHandler = CRUDWebHandler( + self, self.CRUDService + ) + + +\_\_init\_\_.py +---------------- + +`./myrestapi/__init__.py` + +Init file is needed so myrestapi will work as a module. +Just import the TutorialApp. + +.. code:: python + + from .app import TutorialApp + + __all__ = [ + "TutorialApp", + ] + + +handler.py +---------- + +`./myrestapi/tutorial/handler.py` + +The handler is where HTTP Rest calls are handled and transformed into the actual (internal) service calls. +From another perspective, the handler should contain only translation between REST calls and the service interface. +No actual 'business logic' should be here. +It is strongly suggested to build these CRUD methods one by one and test them straight away. +If you haven't set up your database test instance yet, now is the time to do it. + +As usual, we start by importing modules: + +.. code:: python + + import asab + import asab.web.rest + + +Let's start with two methods - `create` and `read` which allow us to write into database and check the record. + +.. code:: python + + class CRUDWebHandler(object): + def __init__(self, app, mongo_svc): + self.CRUDService = mongo_svc + web_app = app.WebContainer.WebApp + web_app.router.add_put( + '/crud-myrestapi/{collection}', + self.create + ) + web_app.router.add_get( + '/crud-myrestapi/{collection}/{id}', + self.read + ) + + + @asab.web.rest.json_schema_handler({ + 'type': 'object', + 'properties': { + '_id': {'type': 'string'}, + 'field1': {'type': 'string'}, + 'field2': {'type': 'number'}, + 'field3': {'type': 'number'} + }}) + async def create(self, request, *, json_data): + collection = request.match_info['collection'] + + result = await self.CRUDService.create( + collection, json_data + ) + if result: + return asab.web.rest.json_response( + request, {"result": "OK"} + ) + else: + asab.web.rest.json_response( + request, {"result": "FAILED"} + ) + + + async def read(self, request): + collection = request.match_info['collection'] + key = request.match_info['id'] + response = await self.CRUDService.read( + collection, key + ) + return asab.web.rest.json_response( + request, response + ) + +The handler only accepts the incoming requests and returns appropriate responses. +All of the "logic", be it the specifics of the database connection, additional validations and other +operations take place in the CRUDService. + +POST and PUT requests typically come with data in their body. +Providing your `WebContainer` with `JsonExceptionMiddleware` enables you to validate a JSON input using `@asab.web.rest.json_schema_handler` decorator and JSON schema (https://json-schema.org/). + +.. note:: + ASAB WebServer is built on top of the aiohttp library. + For further details please visit https://docs.aiohttp.org/en/stable/index.html. + + +service.py +---------- + +`./myrestapi/tutorial/service.py` + +As mentioned above, this is where the inner workings of the microservice request processing are. +Let's start as usual, by importing the desired modules: + +.. code:: python + + import asab + import asab.storage.exceptions + + +We want to start logging in here: + +.. code:: python + + import logging + # + + L = logging.getLogger(__name__) + + # + + +Now define the CRUDService class which inherits from the `asab.Service` class. + + +.. note:: + `asab.Service` is a lightweight yet powerful abstract class providing your object with 3 functionalities: + + - Name of the `asab.Service` is registered in the app and can be called from the `app` object anywhere in your code. + - `asab.Service` class implements `initialize()` and `finalize()` coroutines which help you to handle asynchronous operations in init and exit time of your application. + - `asab.Service` registers application object as `self.App` for you. + + +.. code:: python + + class CRUDService(asab.Service): + + def __init__(self, app, service_name='crud.CRUDService'): + super().__init__(app, service_name) + self.MongoDBStorageService = app.get_service( + "asab.StorageService" + ) + + async def create(self, collection, json_data): + obj_id = json_data.pop("_id") + + cre = self.MongoDBStorageService.upsertor( + collection, obj_id + ) + + for key, value in zip( + json_data.keys(), json_data.values() + ): + cre.set(key, value) + + try: + await cre.execute() + return "OK" + except asab.storage.exceptions.DuplicateError: + L.warning( + "Document you are trying to create already exists." + ) + return None + + async def read(self, collection, obj_id): + response = await self.MongoDBStorageService.get( + collection, obj_id + ) + return response + + +`asab.StorageService` initialized in `app.py` as part of the `asab.storage.Module` enables connection to MongoDB. +Further on, two methods provide the handler with the desired functionalities. + +Now test it! +------------ + +The application is implicitly running on an **8080** port. +Open the Postman and set a new request. + +Try the PUT method: + +.. code:: + + 127.0.0.1:8080/crud-myrestapi/movie + +Insert into the request body: + +.. code:: + + { + "_id": "1", + "field1": "something new", + "field2": 5555, + "field3": 44424 + } + +When there's a record in your database, try to read it! +For example with this GET request: + +.. code:: + + 127.0.0.1:8080/crud-myrestapi/movie/1 + +Is your response with a 200 status code? Does it return desired data? + + +.. note:: + + **TROUBLESHOOTING** + + **ERROR** + + .. code:: + + ModuleNotFoundError: No module named 'pymongo.mongo_replica_set_client' + + Try: + + .. code:: + + pip install motor + + + + **ERROR** + + .. code:: + + OSError: [Errno 98] error while attempting to bind on address ('0.0.0.0', 8080): address already in use + + Try to kill process listening on 8080 or add [web] section into configuration: + + .. code:: + + asab.Config.add_defaults( + { + 'asab:storage': { + 'type': 'mongodb', + 'mongodb_uri': 'mongodb://mongouser:mongopassword@mongoipaddress:27017', + 'mongodb_database': 'mongodatabase' + }, + 'web': { + 'listen': '0.0.0.0 8081' + } + }) + + + **ERROR** + + No error at all, no response either. + + Try to check the Mongo database credentials. Do your credentials in the configuration in `app.py` fit the ones you entered when running the Mongo Docker image? + + +Up and running! Congratulation on your first ASAB microservice! + +Oh, wait... + +**C**, **R**... What about **Update** and **Delete** you ask? + +You already know everything to add the next functionality! Accept the challenge and try it yourself! Or check out the code below. + + +Update and Delete +----------------- + +**handler.py** + +`./myrestapi/tutorial/handler.py` + +.. code:: python + + import asab + import asab.web.rest + + + class CRUDWebHandler(object): + def __init__(self, app, mongo_svc): + self.CRUDService = mongo_svc + web_app = app.WebContainer.WebApp + web_app.router.add_put( + '/crud-myrestapi/{collection}', + self.create + ) + web_app.router.add_get( + '/crud-myrestapi/{collection}/{id}', + self.read + ) + web_app.router.add_put( + '/crud-myrestapi/{collection}/{id}', + self.update + ) + web_app.router.add_delete( + '/crud-myrestapi/{collection}/{id}', + self.delete + ) + + + @asab.web.rest.json_schema_handler({ + 'type': 'object', + 'properties': { + '_id': {'type': 'string'}, + 'field1': {'type': 'string'}, + 'field2': {'type': 'number'}, + 'field3': {'type': 'number'} + }}) + async def create(self, request, *, json_data): + collection = request.match_info['collection'] + + result = await self.CRUDService.create( + collection, json_data + ) + if result: + return asab.web.rest.json_response( + request, {"result": "OK"} + ) + else: + asab.web.rest.json_response( + request, {"result": "FAILED"} + ) + + + async def read(self, request): + collection = request.match_info['collection'] + key = request.match_info['id'] + response = await self.CRUDService.read( + collection, key + ) + return asab.web.rest.json_response( + request, response + ) + + + @asab.web.rest.json_schema_handler({ + 'type': 'object', + 'properties': { + '_id': {'type': 'string'}, + 'field1': {'type': 'string'}, + 'field2': {'type': 'number'}, + 'field3': {'type': 'number'} + }}) + async def update(self, request, *, json_data): + collection = request.match_info['collection'] + obj_id = request.match_info["id"] + + result = await self.CRUDService.update( + collection, obj_id, json_data + ) + if result: + return asab.web.rest.json_response( + request, {"result": "OK"} + ) + else: + asab.web.rest.json_response( + request, {"result": "FAILED"} + ) + + + async def delete(self, request): + collection = request.match_info['collection'] + obj_id = request.match_info["id"] + result = await self.CRUDService.delete( + collection, obj_id + ) + + if result: + return asab.web.rest.json_response( + request, {"result": "OK"} + ) + else: + asab.web.rest.json_response( + request, {"result": "FAILED"} + ) + + +**service.py** + +`./myrestapi/tutorial/service.py` + +.. code:: python + + import asab + import asab.storage.exceptions + + import logging + # + + L = logging.getLogger(__name__) + + # + + + class CRUDService(asab.Service): + + def __init__(self, app, service_name='crud.CRUDService'): + super().__init__(app, service_name) + self.MongoDBStorageService = app.get_service( + "asab.StorageService" + ) + + async def create(self, collection, json_data): + obj_id = json_data.pop("_id") + + cre = self.MongoDBStorageService.upsertor( + collection, obj_id + ) + + for key, value in zip( + json_data.keys(), json_data.values() + ): + cre.set(key, value) + + try: + await cre.execute() + return "OK" + except asab.storage.exceptions.DuplicateError: + L.warning( + "Document you are trying to create already exists." + ) + return None + + + async def read(self, collection, obj_id): + response = await self.MongoDBStorageService.get( + collection, obj_id + ) + return response + + + async def update(self, collection, obj_id, document): + original = await self.read( + collection, obj_id + ) + + cre = self.MongoDBStorageService.upsertor( + collection, original["_id"], original["_v"] + ) + + for key, value in zip( + document.keys(), document.values() + ): + cre.set(key, value) + + try: + await cre.execute() + return "OK" + + except KeyError: + return None + + + async def delete(self, collection, obj_id): + try: + await self.MongoDBStorageService.delete( + collection, obj_id + ) + return True + except KeyError: + return False diff --git a/old_docs/_build/htmln/_static/alabaster.css b/old_docs/_build/htmln/_static/alabaster.css new file mode 100644 index 000000000..517d0b29c --- /dev/null +++ b/old_docs/_build/htmln/_static/alabaster.css @@ -0,0 +1,703 @@ +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: Georgia, serif; + font-size: 17px; + background-color: #fff; + color: #000; + margin: 0; + padding: 0; +} + + +div.document { + width: 940px; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 220px; +} + +div.sphinxsidebar { + width: 220px; + font-size: 14px; + line-height: 1.5; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #fff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +div.body > .section { + text-align: left; +} + +div.footer { + width: 940px; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +p.caption { + font-family: inherit; + font-size: inherit; +} + + +div.relations { + display: none; +} + + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0; + margin: -10px 0 0 0px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo { + margin-top: -10px; + text-align: center; + margin-bottom: 5px; + text-align: left; +} + +div.sphinxsidebarwrapper h1.logo-name { + margin-top: 0px; +} + +div.sphinxsidebarwrapper p.blurb { + margin-top: 0; + font-style: normal; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: Georgia, serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar ul li.toctree-l1 > a { + font-size: 120%; +} + +div.sphinxsidebar ul li.toctree-l2 > a { + font-size: 110%; +} + +div.sphinxsidebar input { + border: 1px solid #CCC; + font-family: Georgia, serif; + font-size: 1em; +} + +div.sphinxsidebar hr { + border: none; + height: 1px; + color: #AAA; + background: #AAA; + + text-align: left; + margin-left: 0; + width: 50%; +} + +div.sphinxsidebar .badge { + border-bottom: none; +} + +div.sphinxsidebar .badge:hover { + border-bottom: none; +} + +/* To address an issue with donation coming after search */ +div.sphinxsidebar h3.donation { + margin-top: 10px; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: Georgia, serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #DDD; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #EAEAEA; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + margin: 20px 0px; + padding: 10px 30px; + background-color: #EEE; + border: 1px solid #CCC; +} + +div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fafafa; +} + +div.admonition p.admonition-title { + font-family: Georgia, serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: #fff; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.warning { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.danger { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.error { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.caution { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.attention { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.important { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.note { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.tip { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.hint { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.seealso { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.topic { + background-color: #EEE; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt, code { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +.hll { + background-color: #FFC; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +img.screenshot { +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.95em; +} + +tt.descname, code.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #EEE; + background: #FDFDFD; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.field-list p { + margin-bottom: 0.8em; +} + +/* Cloned from + * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 + */ +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +table.footnote td.label { + width: .1px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + /* Matches the 30px from the narrow-screen "li > ul" selector below */ + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #EEE; + padding: 7px 30px; + margin: 15px 0px; + line-height: 1.3em; +} + +div.viewcode-block:target { + background: #ffd; +} + +dl pre, blockquote pre, li pre { + margin-left: 0; + padding-left: 30px; +} + +tt, code { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, code.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fff; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +/* Don't put an underline on images */ +a.image-reference, a.image-reference:hover { + border-bottom: none; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt, a:hover code { + background: #EEE; +} + + +@media screen and (max-width: 870px) { + + div.sphinxsidebar { + display: none; + } + + div.document { + width: 100%; + + } + + div.documentwrapper { + margin-left: 0; + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + } + + div.bodywrapper { + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + margin-left: 0; + } + + ul { + margin-left: 0; + } + + li > ul { + /* Matches the 30px from the "ul, ol" selector above */ + margin-left: 30px; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .bodywrapper { + margin: 0; + } + + .footer { + width: auto; + } + + .github { + display: none; + } + + + +} + + + +@media screen and (max-width: 875px) { + + body { + margin: 0; + padding: 20px 30px; + } + + div.documentwrapper { + float: none; + background: #fff; + } + + div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: #FFF; + } + + div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + div.sphinxsidebar h3 a { + color: #fff; + } + + div.sphinxsidebar a { + color: #AAA; + } + + div.sphinxsidebar p.logo { + display: none; + } + + div.document { + width: 100%; + margin: 0; + } + + div.footer { + display: none; + } + + div.bodywrapper { + margin: 0; + } + + div.body { + min-height: 0; + padding: 0; + } + + .rtd_doc_footer { + display: none; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .footer { + width: auto; + } + + .github { + display: none; + } +} + + +/* misc. */ + +.revsys-inline { + display: none!important; +} + +/* Make nested-list/multi-paragraph items look better in Releases changelog + * pages. Without this, docutils' magical list fuckery causes inconsistent + * formatting between different release sub-lists. + */ +div#changelog > div.section > ul > li > p:only-child { + margin-bottom: 0; +} + +/* Hide fugly table cell borders in ..bibliography:: directive output */ +table.docutils.citation, table.docutils.citation td, table.docutils.citation th { + border: none; + /* Below needed in some edge cases; if not applied, bottom shadows appear */ + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + + +/* relbar */ + +.related { + line-height: 30px; + width: 100%; + font-size: 0.9rem; +} + +.related.top { + border-bottom: 1px solid #EEE; + margin-bottom: 20px; +} + +.related.bottom { + border-top: 1px solid #EEE; +} + +.related ul { + padding: 0; + margin: 0; + list-style: none; +} + +.related li { + display: inline; +} + +nav#rellinks { + float: right; +} + +nav#rellinks li+li:before { + content: "|"; +} + +nav#breadcrumbs li+li:before { + content: "\00BB"; +} + +/* Hide certain items when printing */ +@media print { + div.related { + display: none; + } +} \ No newline at end of file diff --git a/old_docs/_build/htmln/_static/asab-architecture.png b/old_docs/_build/htmln/_static/asab-architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..c92b65d2ec53365984c055ac99c37a233eb20592 GIT binary patch literal 39024 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 literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/_static/basic.css b/old_docs/_build/htmln/_static/basic.css new file mode 100644 index 000000000..7577acb1a --- /dev/null +++ b/old_docs/_build/htmln/_static/basic.css @@ -0,0 +1,903 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/old_docs/_build/htmln/_static/custom.css b/old_docs/_build/htmln/_static/custom.css new file mode 100644 index 000000000..2a924f1d6 --- /dev/null +++ b/old_docs/_build/htmln/_static/custom.css @@ -0,0 +1 @@ +/* This file intentionally left blank. */ diff --git a/old_docs/_build/htmln/_static/doctools.js b/old_docs/_build/htmln/_static/doctools.js new file mode 100644 index 000000000..d06a71d75 --- /dev/null +++ b/old_docs/_build/htmln/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/old_docs/_build/htmln/_static/documentation_options.js b/old_docs/_build/htmln/_static/documentation_options.js new file mode 100644 index 000000000..b57ae3b83 --- /dev/null +++ b/old_docs/_build/htmln/_static/documentation_options.js @@ -0,0 +1,14 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/old_docs/_build/htmln/_static/file.png b/old_docs/_build/htmln/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/_static/language_data.js b/old_docs/_build/htmln/_static/language_data.js new file mode 100644 index 000000000..250f5665f --- /dev/null +++ b/old_docs/_build/htmln/_static/language_data.js @@ -0,0 +1,199 @@ +/* + * language_data.js + * ~~~~~~~~~~~~~~~~ + * + * This script contains the language-specific data used by searchtools.js, + * namely the list of stopwords, stemmer, scorer and splitter. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; + + +/* Non-minified version is copied as a separate JS file, is available */ + +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/old_docs/_build/htmln/_static/minus.png b/old_docs/_build/htmln/_static/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..d96755fdaf8bb2214971e0db9c1fd3077d7c419d GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^+#t*WBp7;*Yy1LIik>cxAr*|t7R?Mi>2?kWtu=nj kDsEF_5m^0CR;1wuP-*O&G^0G}KYk!hp00i_>zopr08q^qX#fBK literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/_static/plus.png b/old_docs/_build/htmln/_static/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..7107cec93a979b9a5f64843235a16651d563ce2d GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^+#t*WBp7;*Yy1LIik>cxAr*|t7R?Mi>2?kWtu>-2 m3q%Vub%g%s<8sJhVPMczOq}xhg9DJoz~JfX=d#Wzp$Pyb1r*Kz literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/_static/pygments.css b/old_docs/_build/htmln/_static/pygments.css new file mode 100644 index 000000000..691aeb82d --- /dev/null +++ b/old_docs/_build/htmln/_static/pygments.css @@ -0,0 +1,74 @@ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #eeffcc; } +.highlight .c { color: #408090; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #007020; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #007020 } /* Comment.Preproc */ +.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #333333 } /* Generic.Output */ +.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0044DD } /* Generic.Traceback */ +.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #007020 } /* Keyword.Pseudo */ +.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #902000 } /* Keyword.Type */ +.highlight .m { color: #208050 } /* Literal.Number */ +.highlight .s { color: #4070a0 } /* Literal.String */ +.highlight .na { color: #4070a0 } /* Name.Attribute */ +.highlight .nb { color: #007020 } /* Name.Builtin */ +.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ +.highlight .no { color: #60add5 } /* Name.Constant */ +.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #007020 } /* Name.Exception */ +.highlight .nf { color: #06287e } /* Name.Function */ +.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ +.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #bb60d5 } /* Name.Variable */ +.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mb { color: #208050 } /* Literal.Number.Bin */ +.highlight .mf { color: #208050 } /* Literal.Number.Float */ +.highlight .mh { color: #208050 } /* Literal.Number.Hex */ +.highlight .mi { color: #208050 } /* Literal.Number.Integer */ +.highlight .mo { color: #208050 } /* Literal.Number.Oct */ +.highlight .sa { color: #4070a0 } /* Literal.String.Affix */ +.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ +.highlight .sc { color: #4070a0 } /* Literal.String.Char */ +.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ +.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4070a0 } /* Literal.String.Double */ +.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ +.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ +.highlight .sx { color: #c65d09 } /* Literal.String.Other */ +.highlight .sr { color: #235388 } /* Literal.String.Regex */ +.highlight .s1 { color: #4070a0 } /* Literal.String.Single */ +.highlight .ss { color: #517918 } /* Literal.String.Symbol */ +.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #06287e } /* Name.Function.Magic */ +.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ +.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ +.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ +.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ +.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/old_docs/_build/htmln/_static/searchtools.js b/old_docs/_build/htmln/_static/searchtools.js new file mode 100644 index 000000000..97d56a74d --- /dev/null +++ b/old_docs/_build/htmln/_static/searchtools.js @@ -0,0 +1,566 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = docUrlRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = docUrlRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms) + ); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = _( + `Search finished, found ${resultCount} page(s) matching the search query.` + ); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent !== undefined) return docContent.textContent; + console.warn( + "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + /** + * execute search (requires search index to be loaded) + */ + query: (query) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + // array of [docname, title, anchor, descr, score, filename] + let results = []; + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + let score = Math.round(100 * queryLower.length / title.length) + results.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id] of foundEntries) { + let score = Math.round(100 * queryLower.length / entry.length) + results.push([ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // lookup as object + objectTerms.forEach((term) => + results.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); + + // now sort the results by score (in opposite order of appearance, since the + // display function below uses pop() to retrieve items) and then + // alphabetically + results.sort((a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; + }); + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + results = results.reverse(); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord) && !terms[word]) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord) && !titleTerms[word]) + arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); + }); + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) + fileMap.get(file).push(word); + else fileMap.set(file, [word]); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords) => { + const text = Search.htmlToText(htmlText); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/old_docs/_build/htmln/_static/sphinx_highlight.js b/old_docs/_build/htmln/_static/sphinx_highlight.js new file mode 100644 index 000000000..aae669d7e --- /dev/null +++ b/old_docs/_build/htmln/_static/sphinx_highlight.js @@ -0,0 +1,144 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + parent.insertBefore( + span, + parent.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(SphinxHighlight.highlightSearchWords); +_ready(SphinxHighlight.initEscapeListener); diff --git a/old_docs/_build/htmln/admin/command-line.html b/old_docs/_build/htmln/admin/command-line.html new file mode 100644 index 000000000..a719aa05d --- /dev/null +++ b/old_docs/_build/htmln/admin/command-line.html @@ -0,0 +1,210 @@ + + + + + + + + + ASAB Command-line interface — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

ASAB Command-line interface

+

ASAB-based application provides the command-line interface by default. +Here is an overview of the common command-line arguments.

+
+
+-h, --help
+
+ +

Show a help.

+
+

Configuration

+
+
+-c <CONFIG>,--config <CONFIG>
+
+ +

Load configuration file from a file CONFIG.

+
+
+

Logging

+
+
+-v, --verbose
+
+ +

Increase the logging level to DEBUG aka be more verbose about what is happening.

+
+
+-l <LOG_FILE>,--log-file <LOG_FILE>
+
+ +

Log to a file LOG_FILE.

+
+
+-s, --syslog
+
+ +

Log to a syslog.

+
+
+

Daemon

+

Python module python-daemon has to be installed in order to support daemonosation functions.

+
$ pip3 install asab python-daemon
+
+
+
+
+-d, --daemonize
+
+ +

Launch the application in the background aka daemonized.

+

Daemon-related section of Config file:

+
[daemon]
+pidfile=/var/run/myapp.pid
+uid=nobody
+gid=nobody
+working_dir=/tmp
+
+
+

Configuration options pidfile, uid , gid and working_dir are supported.

+
+
+-k, --kill
+
+ +

Shutdown the application running in the background (started previously with -d argument).

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/admin/containers.html b/old_docs/_build/htmln/admin/containers.html new file mode 100644 index 000000000..9a80fc1dc --- /dev/null +++ b/old_docs/_build/htmln/admin/containers.html @@ -0,0 +1,235 @@ + + + + + + + + + Containerisation — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Containerisation

+

ASAB is designed for deployment into containers such as LXC/LXD or Docker. +It allows to build e.g. microservices that provides REST interface or consume MQ messages while being deployed into a container for a sake of the infrastructure flexibility.

+
+

ASAB in a LXC/LXD container

+
    +
  1. Prepare LXC/LXD container based on Alpine Linux

  2. +
+
$ lxc launch images:alpine/3.10 asab
+
+
+
    +
  1. Swich into a container

  2. +
+
$ lxc exec asab -- /bin/ash
+
+
+
    +
  1. Prepare Python3 environment

  2. +
+
$ apk update
+$ apk upgrade
+$ apk add --no-cache python3
+
+$ python3 -m ensurepip
+
+
+
    +
  1. Deploy ASAB

  2. +
+
$ apk add --virtual .buildenv python3-dev gcc musl-dev git
+$ pip3 install git+https://github.com/TeskaLabs/asab
+$ apk del .buildenv
+
+
+
    +
  1. Deploy dependencies

  2. +
+
$ pip3 install python-daemon
+
+
+
    +
  1. Use OpenRC to automatically start/stop ASAB application

  2. +
+
$ vi /etc/init.d/asab-app
+
+
+

Adjust the example of OpenRC init file.

+
$ chmod a+x /etc/init.d/asab-app
+$ rc-update add asab-app
+
+
+

Note: If you need to install python packages that require compilation using C compiler, you have to add following dependencies:

+
$ apk add --virtual .buildenv python3-dev
+$ apk add --virtual .buildenv gcc
+$ apk add --virtual .buildenv musl-dev
+
+
+

And removal of the build tools after pip install:

+
$ apk del .buildenv
+
+
+
+
+

Docker Remote API

+

In order for ASAB applications to read the Docker container name +as well as other information related to the container to be used in logs, metrics and other analysis, +the Docker Remote API must be enabled.

+

To do so:

+
    +
  1. Open the docker service file

  2. +
+
vi /lib/systemd/system/docker.service
+
+
+
    +
  1. Find the line which starts with ExecStart and add -H=tcp://0.0.0.0:2375

  2. +
  3. Save the file

  4. +
  5. Reload the docker daemon and restart the Docker service

  6. +
+
sudo systemctl daemon-reload && sudo service docker restart
+
+
+

Then in the ASAB application’s configuration, provide +the Docker Socket path in docker_socket configuration option:

+
[general]
+docker_socket=<YOUR_DOCKER_SOCKET_FILE>
+
+
+

Thus, the metric service as well as log manager can use the container +name as hostname instead of container ID, which provides better readability +when analyzing the logs and metrics, typically using InfluxDB and Grafana.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/admin/install.html b/old_docs/_build/htmln/admin/install.html new file mode 100644 index 000000000..d613608a1 --- /dev/null +++ b/old_docs/_build/htmln/admin/install.html @@ -0,0 +1,166 @@ + + + + + + + + + Installation — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Installation

+

ASAB is distributed via pypi.

+
+

Install ASAB using pip

+

This is the recommended installation method.

+
$ pip install asab
+
+
+
+
+

Install ASAB using easy_install

+
$ easy_install asab
+
+
+
+
+

Install ASAB for a GitHub

+

To install ASAB from a master branch of the GIT repository, use following command.

+

Note: Git has to be installed in order to successfuly complete the installation.

+
$ pip install git+https://github.com/TeskaLabs/asab.git
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/admin/systemd.html b/old_docs/_build/htmln/admin/systemd.html new file mode 100644 index 000000000..5f4a74180 --- /dev/null +++ b/old_docs/_build/htmln/admin/systemd.html @@ -0,0 +1,173 @@ + + + + + + + + + systemd — ASAB documentation + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

systemd

+
    +
  1. Create a new Systemd unit file in /etc/systemd/system/:

  2. +
+
$ sudo vi /etc/systemd/system/asab.service
+
+
+

Adjust the example of SystemD unit file.

+
    +
  1. Let systemd know that there is a new service:

  2. +
+
$ sudo systemctl enable asab
+
+
+

To reload existing unit file after changing, use this:

+
$ sudo systemctl daemon-reload
+
+
+
    +
  1. ASAB Application Server service for systemd is now ready.

  2. +
+
+

Start of ASAB Server

+
$ sudo service asab start
+
+
+
+
+

Stop of ASAB Server

+
$ sudo service asab stop
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/alert.html b/old_docs/_build/htmln/asab/alert.html new file mode 100644 index 000000000..5c829486d --- /dev/null +++ b/old_docs/_build/htmln/asab/alert.html @@ -0,0 +1,212 @@ + + + + + + + + + Alert Service — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Alert Service

+

Integrate ASAB Application with alert managers.

+

There are currently two possible target systems for the alerts available:

+ +

Everything you need to do is to import the service, trigger the alert and specify the target in the configuration.

+
class MyApplication(asab.Application):
+    async def initialize(self):
+        from asab.alert import AlertService
+        self.AlertService = AlertService(self)
+        self.AlertService.trigger(
+            source="my-tenant",
+            alert_cls="my-class",
+            alert_id="deduplication-id01",
+            title="Something went wrong.",
+            detail={
+                "example1": "additional-info",
+                "example2": "additional-info",
+            },
+        )
+
+if __name__ == '__main__':
+    app = MyApplication()
+    app.run()
+
+
+
+

Opsgenie

+
    +
  • Create an account at Opsgenie.

  • +
  • In your Opsgenie account, create a new Team.

  • +
  • Add integration to your Team - choose API.

  • +
  • API Key will be generated for you.

  • +
+

myapplication.conf

+
[asab:alert:opsgenie]
+api_key=my-api-key
+tags=my-tag, my-application
+url=https://api.eu.opsgenie.com  # this is default value
+
+
+
+
+

PagerDuty

+
    +
  • Create an account at PagerDuty.

  • +
  • In your PagerDuty account, generate Api Key (Integrations > Developer Tools > Api Access Keys).

  • +
  • Create a new Service in Service Directory and add integration in the Integrations folder.

  • +
  • Choose Events API V2. An Integration Key will be generated for you.

  • +
+

myapplication.conf

+
[asab:alert:pagerduty]
+api_key=my-api-key
+integration_key=my-integration-key
+url=https://events.pagerduty.com  # this is default value
+
+
+
+
+

De-duplication

+

alert_id argument serves as a de-duplication ID for the third-party services. It enables the grouping of alerts and prevents noise. +More about alert grouping:

+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/application.html b/old_docs/_build/htmln/asab/application.html new file mode 100644 index 000000000..dbd05ee43 --- /dev/null +++ b/old_docs/_build/htmln/asab/application.html @@ -0,0 +1,373 @@ + + + + + + + + + Application — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Application

+
+
+class asab.Application[source]
+
+ +

The Application class maintains the global application state. +You can provide your own implementation by creating a subclass. +There should be only one Application object in the process.

+

Subclassing:

+
import asab
+
+class MyApplication(asab.Application):
+    pass
+
+if __name__ == '__main__':
+    app = MyApplication()
+    app.run()
+
+
+

Direct use of Application object:

+
import asab
+
+if __name__ == '__main__':
+    app = asab.Application()
+    app.run()
+
+
+
+

Event Loop

+
+
+Application.Loop
+
+ +

The asyncio event loop that is used by this application.

+
asyncio.ensure_future(my_coro())
+
+
+
+
+

Application Lifecycle

+

The ASAB is designed around the Inversion of control principle. +It means that the ASAB is in control of the application lifecycle. +The custom-written code receives the flow from ASAB via callbacks or handlers. +Inversion of control is used to increase modularity of the code and make it extensible.

+

The application lifecycle is divided into 3 phases: init-time, run-time and exit-time.

+
+

Init-time

+
+
+Application.__init__()[source]
+
+ +

The init-time happens during Application constructor call. +The Publish-Subscribe message Application.init! is published during init-time. +The Config is loaded during init-time.

+
+
+Application.initialize()[source]
+
+ +

The application object executes asynchronous callback Application.initialize(), which can be overriden by an user.

+
class MyApplication(asab.Application):
+    async def initialize(self):
+        # Custom initialization
+        from module_sample import Module
+        self.add_module(Module)
+
+
+
+
+

Run-time

+
+
+Application.run()[source]
+
+ +

Enter a run-time. This is where the application spends the most time typically. +The Publish-Subscribe message Application.run! is published when run-time begins.

+

The method returns the value of Application.ExitCode.

+
+
+Application.main()[source]
+
+ +

The application object executes asynchronous callback Application.main(), which can be overriden. +If main() method is completed without calling stop(), then the application server will run forever (this is the default behaviour).

+
class MyApplication(asab.Application):
+    async def main(self):
+        print("Hello world!")
+        self.stop()
+
+
+
+
+Application.stop(exit_code: int = None)[source]
+
+ +

The method Application.stop() gracefully terminates the run-time and commence the exit-time. +This method is automatically called by SIGINT and SIGTERM. It also includes a response to Ctrl-C on UNIX-like system. +When this method is called 3x, it abruptly exits the application (aka emergency abort).

+

The parameter exit_code allows you to specify the application exit code (see Exit-Time chapter).

+

Note: You need to install win32api module to use Ctrl-C or an emergency abord properly with ASAB on Windows. It is an optional dependency of ASAB.

+
+
+

Exit-time

+
+
+Application.finalize()[source]
+
+ +

The application object executes asynchronous callback Application.finalize(), which can be overriden by an user.

+
class MyApplication(asab.Application):
+    async def finalize(self):
+        # Custom finalization
+        ...
+
+
+

The Publish-Subscribe message Application.exit! is published when exit-time begins.

+
+
+Application.set_exit_code(exit_code: int, force: bool = False)[source]
+
+ +

Set the exit code of the application, see os.exit() in the Python documentation. +If force is False, the exit code will be set only if the previous value is lower than the new one. +If force is True, the exit code value is set to a exit_code disregarding the previous value.

+
+
+Application.ExitCode
+
+ +

The actual value of the exit code.

+

The example of the exit code handling in the main() function of the application.

+
if __name__ == '__main__':
+    app = asab.Application()
+    exit_code = app.run()
+    sys.exit(exit_code)
+
+
+
+
+
+

Module registry

+

For more details see Module class.

+
+
+Application.add_module(module_class)[source]
+
+ +

Initialize and add a new module. +The module_class class will be instantiated during the method call.

+
class MyApplication(asab.Application):
+    async def initialize(self):
+        from my_module import MyModule
+        self.add_module(MyModule)
+
+
+
+
+Application.Modules
+
+ +

A list of modules that has been added to the application.

+
+
+

Service registry

+

Each service is identified by its unique service name. +For more details see Service class.

+
+
+Application.get_service(service_name)[source]
+
+ +

Locate a service by its service name in a registry and return the Service object.

+
svc = app.get_service("service_sample")
+svc.hello()
+
+
+
+
+Application.Services
+
+ +

A dictionary of registered services.

+
+
+

Command-line parser

+
+
+Application.create_argument_parser(prog=None, usage=None, description=None, epilog=None, prefix_chars='-', fromfile_prefix_chars=None, argument_default=None, conflict_handler='error', add_help=True) argparse.ArgumentParser[source]
+
+ +

Creates an argparse.ArgumentParser. +This method can be overloaded to adjust command-line argument parser.

+

Please refer to Python standard library argparse for more details about function arguments.

+
+
+Application.parse_args()
+
+ +

The application object calls this method during init-time to process a command-line arguments. +argparse is used to process arguments. +You can overload this method to provide your own implementation of command-line argument parser.

+
+
+Application.Description
+
+ +

The Description attribute is a text that will be displayed in a help text (--help). +It is expected that own value will be provided. +The default value is "" (empty string).

+
+
+

UTC Time

+
+
+Application.time() float[source]
+
+ +

Return the current “event loop time” in seconds since the epoch as a floating point number. +The specific date of the epoch and the handling of leap seconds is platform dependent. On Windows and most Unix systems, the epoch is January 1, 1970, 00:00:00 (UTC) and leap seconds are not counted towards the time in seconds since the epoch. This is commonly referred to as Unix time.

+

A call of the time.time() function could be expensive. +This method provides a cheaper version of the call that returns a current wall time in UTC.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/config.html b/old_docs/_build/htmln/asab/config.html new file mode 100644 index 000000000..e52e11587 --- /dev/null +++ b/old_docs/_build/htmln/asab/config.html @@ -0,0 +1,354 @@ + + + + + + + + + Configuration — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Configuration

+
+
+asab.Config
+
+ +

The configuration is provided by Config object which is a singleton. It means that you can access Config from any place of your code, without need of explicit initialisation.

+
import asab
+
+# Initialize application object and hence the configuration
+app = asab.Application()
+
+# Access configuration values anywhere
+my_conf_value = asab.Config['section_name']['key1']
+
+
+
+

Based on ConfigParser

+

The Config is inherited from Python Standard Library configparser.ConfigParser class. which implements a basic configuration language which provides a structure similar to what’s found in Microsoft Windows INI files.

+
+
+class asab.config.ConfigParser[source]
+
+ +

Example of the configuration file:

+
[bitbucket.org]
+User = hg
+
+[topsecret.server.com]
+Port = 50022
+ForwardX11 = no
+
+
+

And this is how you access configuration values:

+
>>> asab.Config['topsecret.server.com']['ForwardX11']
+'no'
+
+
+
+
+

Multiline configuration entry

+

A multiline configuration entries are supported. +An example:

+
[section]
+key=
+  line1
+  line2
+  line3
+another_key=foo
+
+
+
+
+

Automatic load of configuration

+

If a configuration file name is specified, the configuration is automatically loaded from a configuration file during initialiation time of Application. +The configuration file name can be specified by one of -c command-line argument (1), ASAB_CONFIG environment variable (2) or config [general] config_file default value (3).

+
./sample_app.py -c ./etc/sample.conf
+
+
+
+
+

Including other configuration files

+

You can specify one or more additional configuration files that are loaded and merged from an main configuration file. +It is done by [general] include configuration value. Multiple paths are separated by os.pathsep (: on Unix). +The path can be specified as a glob (e.g. use of * and ? wildcard characters), it will be expanded by glob module from Python Standard Library. +Included configuration files may not exists, this situation is silently ignored.

+
[general]
+include=./etc/site.conf:./etc/site.d/*.conf
+
+
+

You can also use a multiline configuration entry:

+
[general]
+include=
+        ./etc/site.conf
+        ./etc/site.d/*.conf
+
+
+
+
+

Configuration default values

+
+
+Config.add_defaults(dictionary)
+
+ +

This is how you can extend configuration default values:

+
asab.Config.add_defaults(
+    {
+        'section_name': {
+            'key1': 'value',
+            'key2': 'another value'
+        },
+        'other_section': {
+            'key3': 'value',
+        },
+    }
+)
+
+
+

Only simple types (string, int and float) are allowed in the configuration values. +Don’t use complex types such as lists, dictionaries or objects because these are impossible to provide via configuration files etc.

+
+
+

Environment variables in configration

+

Environment variables found in values are automatically expanded.

+
[section_name]
+persistent_dir=${HOME}/.myapp/
+
+
+
>>> asab.Config['section_name']['persistent_dir']
+'/home/user/.myapp/'
+
+
+

There is a special environment variable ${THIS_DIR} that is expanded to a directory that contains a current configuration file. +It is useful in complex configurations that utilizes included configuration files etc.

+
[section_name]
+my_file=${THIS_DIR}/my_file.txt
+
+
+

Another environment variable ${HOSTNAME} contains the application hostname to be used f. e. in logging file path.

+
[section_name]
+my_file=${THIS_DIR}/${HOSTNAME}/my_file.txt
+
+
+
+
+

Passwords in configration

+

[passwords] section in the configuration serves to securely store passwords, +which are then not shown publicly in the default API config endpoint’s output.

+

It is convenient for the user to store passwords at one place, +so that they are not repeated in many sections of the config file(s).

+

Usage is as follows:

+
[connection:KafkaConnection]
+password=${passwords:kafka_password}
+
+[passwords]
+kafka_password=<MY_SECRET_PASSWORD>
+
+
+
+
+

Obtaining seconds

+
+
+Config.getseconds()
+
+ +

The seconds can be obtained using getseconds() method for values with different time +units specified in the configuration:

+
[sleep]
+sleep_time=5.2s
+another_sleep_time=10d
+
+
+

The available units are:

+
+
    +
  • y … years

  • +
  • M … months

  • +
  • w … weeks

  • +
  • d … days

  • +
  • h … hours

  • +
  • m … minutes

  • +
  • s … seconds

  • +
  • ms .. miliseconds

  • +
+
+

If no unit is specified, float of seconds is expected.

+

The obtainment of the second value in the code can be achieved in two ways:

+
self.SleepTime = asab.Config["sleep"].getseconds("sleep_time")
+self.AnotherSleepTime = asab.Config.getseconds("sleep", "another_sleep_time")
+
+
+
+
+

Obtaining URLs

+
+
+Config.geturl(section, option, scheme=None:str, tuple)
+
+ +

A URL can be obtained using a geturl() method that takes the URL from the config and +removes leading and trailing whitespaces and trailing backslashes.

+

There is an optional parameter called scheme that can have any URL scheme like +http, https, mongodb etc. Setting it to None, scheme validation gets bypassed.

+

Setting the scheme parameter to the same scheme as in the config, it will return the URL. +If it’s not the same it will raise an error.

+

There are two ways of obtaining the URL:

+
asab.Config["urls"].geturl("teskalabs", scheme="https")
+asab.Config.geturl("urls", "github", scheme=None)
+
+
+

Example:

+
>>> asab.Config["urls"].geturl("teskalabs", scheme="https")
+    'https://www.teskalabs.com'
+
+
+

For reference this would be the configuration file:

+
[urls]
+teskalabs=https://www.teskalabs.com/
+github=github.com
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/index.html b/old_docs/_build/htmln/asab/index.html new file mode 100644 index 000000000..84691e469 --- /dev/null +++ b/old_docs/_build/htmln/asab/index.html @@ -0,0 +1,171 @@ + + + + + + + + + Asynchronous Server Application Boilerplate’s documentation — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Asynchronous Server Application Boilerplate’s documentation

+

Asynchronous Server App Boilerplate (or ASAB for short) is a microservice platform for Python 3.7+ and asyncio. +ASAB aims to minimize the amount of code that needs to be written when building a microservice or an application server. +ASAB is fully asynchronous using async/await syntax from Python 3, making your code modern, non-blocking, speedy and hence scalable. +We make every effort to build ASAB container-friendly so that you can deploy ASAB-based microservice via Docker or Kubernetes in a breeze.

+

ASAB is free and open-source software, available under BSD licence. +It means that anyone is freely licenced to use, copy, study, and change the software in any way, and the source code is openly shared so that people could voluntarily improve the design of the software. +Anyone can (and is encouraged to) use ASAB in his or her projects, for free. +A current maintainer is a TeskaLabs Ltd company.

+

ASAB is developed on GitHub. +Contributions are welcome!

+
+

ASAB is designed to be powerful yet simple

+

Here is a complete example of a fully working microservice:

+
import asab
+
+class MyApplication(asab.Application):
+    async def main(self):
+        print("Hello world!")
+        self.stop()
+
+if __name__ == "__main__":
+    app = MyApplication()
+    app.run()
+
+
+
+
+

ASAB is the right choice when

+
+
    +
  • using Python 3.7+.

  • +
  • building the microservice or the application server.

  • +
  • utilizing asynchronous I/O (aka asyncio).

  • +
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/library.html b/old_docs/_build/htmln/asab/library.html new file mode 100644 index 000000000..9a9e7d228 --- /dev/null +++ b/old_docs/_build/htmln/asab/library.html @@ -0,0 +1,456 @@ + + + + + + + + + Library — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Library

+

The ASAB Library (asab.library) is a concept of the shared data content across microservices in the cluster. +The asab.library provides a read-only interface for listing and reading this content. +The library can also notify the ASAB microservice about changes, eg. for automated update/reload.

+

There is a companion microservice asab-library that can be used for management and editation of the library content. +The asab.library can however operate without asab-library microservice.

+
+

Library structure

+

The library content is organized in simplified filesystem manner, with directories and files.

+

Example of the library structure:

+
+ /folder1/
+  - /folder1/item1.yaml
+  - /folder1/item2.json
++ /folder2/
+  - /folder2/item3.yaml
+  + /folder2folder2.3/
+    - /folder2/folder2.3/item4.json
+
+
+
+
+

Library path rules

+
    +
  • Any path must start with /, including the root path (/).

  • +
  • The folder path must end with /.

  • +
  • The item path must end with extension (eg. .json).

  • +
+
+
+

Library service

+
+
+class asab.library.LibraryService(app, service_name, paths=None)[source]
+

ASAB library (aka LibraryService) is an abstration for unified filesystem-like access to resources. +In the cluster/cloud microservice architectures, it is imperative that all microservices have access to unified resources. +There are technologies such as Apache Zookeeper that provides means for it.

+

ASAB library builts on top of this concept and brings that into the ASAB microservice.

+

ASAB library is designed to be read-only. +It also allows to “stack” various libraries into one view (overlayed) that merges content of each library into one united space.

+

Configuration:

+

``` +[library] +providers:

+
+

provider+1:// +provider+2:// +provider+3://

+
+

```

+

The order of providers IS important, the priority (or layering) is top-down.

+

Each library provider is specified by URL/URI schema:

+
    +
  • zk:// or zookeeper:// for ZooKeeper provider

  • +
  • file:// or local path for FileSystem provider

  • +
  • azure+https:// for Microsoft Azure Storage provider.

  • +
+

The first provider is also responsible for providing /.disabled.yaml that controls a visibility of items. +If /.disabled.yaml is not present, then is considered empty.

+

A library is created in “not ready” state, each provider then inform library when it is ready (eg. Zookeeper provider needs to connect to Zookeeper servers). +Only after all providers are ready, the library itself become ready. +The library indicates that by the PubSub event ASABLibrary.ready!.

+
+ +

Example of the use:

+
import asab
+
+class MyApplication(asab.Application):
+
+    def __init__(self):
+        super().__init__()
+
+        # Initialize the library service
+        self.LibraryService = asab.library.LibraryService(self, "LibraryService")
+        self.PubSub.subscribe("ASABLibrary.ready!", self.on_library_ready)
+
+    async def on_library_ready(self, event_name, library):
+        print("# Library\n")
+
+        for item in await self.LibraryService.list("", recursive=True):
+            print(" *", item)
+            if item.type == 'item':
+                itemio = await self.LibraryService.read(item.name)
+                if itemio is not None:
+                    with itemio:
+                        content = itemio.read()
+                        print("  - content: {} bytes".format(len(content)))
+                else:
+                    print("  - (DISABLED)")
+
+
+
+
+async LibraryService.read(path: str, tenant: str | None = None) IO[source]
+

Read the content of the library item specified by path. +None is returned if the item is not found in the library.

+

If the item is disabled (globally or for specified tenant) then None is returned.

+

Example of use:

+

``` +itemio = await library.read(‘/path’, ‘tenant’) +if itemio is not None:

+
+
+
with itemio:

return itemio.read()

+
+
+
+

```

+
+
Parameters:
+
    +
  • path – The path to the file, LibraryItem.name can be used directly

  • +
  • tenant – The tenant to apply. If not specified, the global access is assumed

  • +
+
+
Returns:
+

I/O stream (read) with the content of the libary item.

+
+
+
+ +
+
+async LibraryService.list(path='/', tenant=None, recursive=False)[source]
+

List the directory of the library specified by the path. +It returns a list of LibraryItem entris.

+
+
Tenant is an optional parameter to list method for “disable” evaluation.

and default recursive is False.

+
+
When tenant=None

The method returns list of items that are enabled (not disabled).

+
+
When tenant=’xxxxx’

The method returns list of items that are enabled (not disabled) for tenant ‘xxxxx’.

+
+
When recursive=True

The method returns list of items that are located at path and in subdirectories of that location.

+
+
When recursive=False

The method returns list of items that are located at path

+
+
+
+ +
+
+async LibraryService.export(path='/', tenant=None, remove_path=False)[source]
+

It takes a path, and returns a file-like object containing a gzipped tar archive of the library contents of +that path

+
+
Parameters:
+
    +
  • path – The path to export, defaults to / (optional)

  • +
  • tenant – The tenant to use for the operation

  • +
  • remove_path – If True, the path will be removed from the tar file, defaults to False

  • +
+
+
+

(optional) +:return: A file object.

+
+ +
+
+

Notification of changes

+
+
+async LibraryService.subscribe(paths)[source]
+

It subscribes to the changes in the library +:param paths: A list of absolute paths to subscribe to

+
+ +
+
+

Providers

+

The library can be configured to work with following “backends” (aka providers):

+
+

Filesystem

+
+
+class asab.library.providers.filesystem.FileSystemLibraryProvider(library, path, *, set_ready=True)[source]
+
+ +
+
+

Apache Zookeeper

+
+
+class asab.library.providers.zookeeper.ZooKeeperLibraryProvider(library, path)[source]
+

Configuration variant:

+
    +
  1. ZooKeeper provider is fully configured from [zookeeper] section

  2. +
+

``` +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/library

+

[library] +providers:

+
+

zk://

+
+

```

+
    +
  1. ZooKeeper provider is configured by servers from [zookeeper] section and path from URL

  2. +
+

Path will be `/library’.

+

``` +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/else

+

[library] +providers:

+
+

zk:///library

+
+

```

+

2.1) ZooKeeper provider is configured by servers from [zookeeper] section and path from URL

+

Path will be `/’, this is a special case to 2)

+

``` +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/else

+

[library] +providers:

+
+

zk:///

+
+

```

+
    +
  1. ZooKeeper provider is fully configured from URL

  2. +
+

``` +[library] +providers:

+
+

zk://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/library

+
+

```

+

4) ZooKeeper provider is configured by servers from [zookeeper] section and joined path from [zookeeper] and +path from URL

+

Path will be `/else/library’

+

``` +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/else

+

[library] +providers:

+
+

zk://./library

+
+

```

+

If path from [zookeeper] section is missing, an application class name will be used +Ex. `/BSQueryApp/library’

+
+ +
+
+

Microsoft Azure Storage

+
+
+class asab.library.providers.azurestorage.AzureStorageLibraryProvider(library, path)[source]
+

AzureStorageLibraryProvider is a library provider that reads +from an Microsoft Azure Storage container.

+

Configure by:

+

azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER

+

If Container Public Access Level is not set to “Public access”, +then “Access Policy” must be created with “Read” and “List” permissions +and “Shared Access Signature” (SAS) query string must be added to a URL in a configuration:

+

azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER?sv=2020-10-02&si=XXXX&sr=c&sig=XXXXXXXXXXXXXX

+
+ +
+
+

Git repository

+
+
+class asab.library.providers.git.GitLibraryProvider(library, path)[source]
+

Read-only git provider to read from remote repository. +It clones a remote git repository to a temporary directory and then uses the +FileSystemLibraryProvider to read the files. +To read from local git repository, please use FileSystemProvider.

+

Configuration: +(Use either deploytoken, publickey+privatekey for SSH option, or username and password and HTTP access.)

+

``` +[library] +providers=git+<URL or deploy token>#<branch name>

+

[library:git] +publickey=<absolute path to file> +privatekey=<absolute path to file> +username=johnsmith +password=secretpassword +repodir=<optional location of the repository cache> +```

+
+ +
+
+
+

Layers

+

The library content can be organized into unlimmited number of layers. +Each layer is represented by a provider with a specific configuration.

+
+
+

Library configuration

+

Example:

+
[library]
+providers:
+    provider+1://...
+    provider+2://...
+    provider+3://...
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/log.html b/old_docs/_build/htmln/asab/log.html new file mode 100644 index 000000000..1c781dd39 --- /dev/null +++ b/old_docs/_build/htmln/asab/log.html @@ -0,0 +1,455 @@ + + + + + + + + + Logging — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Logging

+

ASAB logging is built on top of a standard Python logging module. +It means that it logs to stderr when running on a console and ASAB also provides file and syslog output (both RFC5424 and RFC3164) for background mode of operations.

+

Log timestamps are captured with sub-second precision (depending on the system capabilities) and displayed including microsecond part.

+ +
+

Logging Levels

+

ASAB uses Python logging levels with the addition of LOG_NOTICE level. +LOG_NOTICE level is similar to logging.INFO level but it is visible in even in non-verbose mode.

+
L.log(asab.LOG_NOTICE, "This message will be visible regardless verbose configuration.")
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Level

Numeric value

Syslog Severity level

CRITICAL

50

Critical / crit / 2

ERROR

40

Error / err / 3

WARNING

30

Warning / warning / 4

LOG_NOTICE

25

Notice / notice / 5

INFO

20

Informational / info / 6

DEBUG

10

Debug / debug / 7

NOTSET

0

+

Example of a custom level configuration:

+
[logging]
+levels=
+    myApp.module1 DEBUG
+    myApp.module2 WARNING
+    customLogger ERROR
+
+
+

The logger name and the corresponding logging level are separated by a space, each logger is on a separate line.

+
+
+

Verbose mode

+

The command-line argument -v enables verbose logging. +It means that log entries with levels DEBUG and INFO will be visible. +It also enables asyncio debug logging.

+

The actual verbose mode is avaiable at asab.Config["logging"]["verbose"] boolean option.

+
L.debug("This message will be visible only in verbose mode.")
+
+
+
+
+

Structured data

+

ASAB supports a structured data to be added to a log entry. +It follows the RFC 5424, section STRUCTURED-DATA. +Structured data are a dictionary, that has to be seriazable to JSON.

+
L.warning("Hello world!", struct_data={'key1':'value1', 'key2':2})
+
+
+

Example of the output to the console:

+

25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule [sd key1="value1" key2="2"] Hello world!

+
+
+

Logging to file

+

The command-line argument -l on command-line enables logging to file. +Also non-empty path option in the section [logging:file] of configuration file enables logging to file as well.

+

Example of the configuration file section:

+
[logging:file]
+path=/var/log/asab.log
+format="%%(asctime)s %%(levelname)s %%(name)s %%(struct_data)s%%(message)s",
+datefmt="%%d-%%b-%%Y %%H:%%M:%%S.%%f"
+backup_count=3
+rotate_every=1d
+
+
+

When the deployment expects more instances of the same application to be logging into the same file, +it is recommended, that the variable hostname is used in the file path:

+
[logging:file]
+path=/var/log/${HOSTNAME}/asab.log
+
+
+

In this way, the applications will log to seperate log files in different folders, +which is an intended behavior, since race conditions may occur when different application instances +log into the same file.

+
+
+

Logging to console

+

ASAB will log to the console only if it detects that it runs in the foreground respectively on the terminal using os.isatty +or if the environment variable ASABFORCECONSOLE is set to 1. +This is useful setup for eg. PyCharm.

+
+

Log rotation

+

ASAB supports a log rotation. +The log rotation is triggered by a UNIX signal SIGHUP, which can be used e.g. to integrate with logrotate utility. +It is implemented using logging.handlers.RotatingFileHandler from a Python standard library. +Also, a time-based log rotation can be configured using rotate_every option.

+

backup_count specifies a number of old files to be kept prior their removal. +The system will save old log files by appending the extensions ‘.1’, ‘.2’ etc., to the filename.

+

rotate_every specifies an time interval of a log rotation. +Default value is empty string, which means that the time-based log rotation is disabled. +The interval is specified by an integer value and an unit, e.g. 1d (for 1 day) or 30M (30 minutes). +Known units are H for hours, M for minutes, d for days and s for seconds.

+
+
+
+

Logging to syslog

+

The command-line argument -s enables logging to syslog.

+

A configuration section [logging:syslog] can be used to specify details about desired syslog logging.

+

Example of the configuration file section:

+
[logging:syslog]
+enabled=true
+format=5
+address=tcp://syslog.server.lan:1554/
+
+
+

enabled is equivalent to command-line switch -s and it enables syslog logging target.

+

format speficies which logging format will be used. +Possible values are:

+
    +
  • 5 for (new) syslog format (RFC 5424 ) ,

  • +
  • 3 for old BSD syslog format (RFC 3164 ), typically used by /dev/log and

  • +
  • m for Mac OSX syslog flavour that is based on BSD syslog format but it is not fully compatible.

  • +
+

The default value is 3 on Linux and m on Mac OSX.

+

address specifies the location of the Syslog server. It could be a UNIX path such as /dev/log or URL. +Possible URL values:

+
    +
  • tcp://syslog.server.lan:1554/ for Syslog over TCP

  • +
  • udp://syslog.server.lan:1554/ for Syslog over UDP

  • +
  • unix-connect:///path/to/syslog.socket for Syslog over UNIX socket (stream)

  • +
  • unix-sendto:///path/to/syslog.socket for Syslog over UNIX socket (datagram), equivalent to /path/to/syslog.socket, used by a /dev/log.

  • +
+

The default value is a /dev/log on Linux or /var/run/syslog on Mac OSX.

+
+
+

Logging of obsolete features

+

It proved to be essential to inform operators about features that are going to be obsoleted. +ASAB offers the unified “obsolete” logger. +This logger can indicate that a particular feature is marked as “obsolete” thru logs. +Such a log message can then be “grepped” from logs uniformly.

+

It is recommended to include eol attribute in the struct_data of the log with a YYYY-MM-DD date/time of the planned obsoletion of the feature.

+

Hint: We suggest automating the detection of obsolete warnings in logs so that the operations are informed well ahead of the actual removal of the feature. The string to seek in logs is “ OBSOLETE “.

+

Example of the use:

+
asab.LogObsolete.warning("Use of the obsolete function", struct_data={'eol':'2022-31-12'})
+
+
+

Log example:

+

21-Jul-2022 14:32:40.983884 WARNING OBSOLETE [eol="2022-31-12"] Use of the obsolete function

+
+
+

Reference

+
+
+class asab.log.AsyncIOHandler(loop, family, sock_type, address, facility=17)[source]
+

Bases: Handler

+

A logging handler similar to a standard logging.handlers.SocketHandler that utilizes asyncio. +It implements a queue for decoupling logging from a networking. The networking is fully event-driven via asyncio mechanisms.

+
+
+emit(record)[source]
+

This is the entry point for log entries.

+
+ +
+ +
+
+class asab.log.Logging(app)[source]
+

Bases: object

+
+
+rotate()[source]
+
+ +
+ +
+
+class asab.log.MacOSXSyslogFormatter(fmt=None, datefmt=None, style='%', sd_id='sd')[source]
+

Bases: StructuredDataFormatter

+

It implements Syslog formatting for Mac OSX syslog (aka format m).

+
+ +
+
+class asab.log.StructuredDataFormatter(facility=16, fmt=None, datefmt=None, style='%', sd_id='sd', use_color: bool = False)[source]
+

Bases: Formatter

+

The logging formatter that renders log messages that includes structured data.

+
+
+BLACK = 0
+
+ +
+
+BLUE = 4
+
+ +
+
+CYAN = 6
+
+ +
+
+GREEN = 2
+
+ +
+
+MAGENTA = 5
+
+ +
+
+RED = 1
+
+ +
+
+WHITE = 7
+
+ +
+
+YELLOW = 3
+
+ +
+
+empty_sd = ''
+
+ +
+
+format(record)[source]
+

Format the specified record as text.

+
+ +
+
+formatTime(record, datefmt=None)[source]
+

Return the creation time of the specified LogRecord as formatted text.

+
+ +
+
+render_struct_data(struct_data)[source]
+

Return the string with structured data.

+
+ +
+ +
+
+class asab.log.SyslogRFC3164Formatter(fmt=None, datefmt=None, style='%', sd_id='sd')[source]
+

Bases: StructuredDataFormatter

+

Implementation of a legacy or BSD Syslog (RFC 3164) formatting (aka format 3).

+
+ +
+
+class asab.log.SyslogRFC5424Formatter(fmt=None, datefmt=None, style='%', sd_id='sd')[source]
+

Bases: StructuredDataFormatter

+

It implements Syslog formatting for Mac OSX syslog (aka format 5).

+
+
+empty_sd = ' '
+
+ +
+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/metrics.html b/old_docs/_build/htmln/asab/metrics.html new file mode 100644 index 000000000..a4010ba1e --- /dev/null +++ b/old_docs/_build/htmln/asab/metrics.html @@ -0,0 +1,565 @@ + + + + + + + + + Metrics — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Metrics

+

Metrics document the state of the application in a timescale manner. +For further analysis, connect your ASAB application to a time-series database. Influx and Prometheus are supported.

+
+

Metrics Service

+

Create new metrics using MetricsService.

+

example of counter initialization:

+
class MyApplication(asab.Application):
+    async def initialize(self):
+        from asab.metrics import Module
+        self.add_module(Module)
+        self.MetricsService = self.get_service('asab.MetricsService')
+        self.MyCounter = self.MetricsService.create_counter("mycounter", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0})
+
+if __name__ == '__main__':
+    app = MyApplication()
+    app.run()
+
+
+

See the full example here: https://github.com/TeskaLabs/asab/blob/master/examples/metrics.py

+
+
+

Types of Metrics

+
    +
  • Gauge stores single numerical values which can go up and down. Implements set() method to set the metric values.

  • +
  • Counter is a cumulative metric whose values can increase or decrease. Implements add() and sub() methods.

  • +
  • Event per Second Counter (EPSCounter) divides all values by delta time.

  • +
  • DutyCycle https://en.wikipedia.org/wiki/Duty_cycle

  • +
  • AggregationCounter allows to set() values based on an aggregation function. max() function is default.

  • +
  • Histogram represents cumulative histogram with set() method.

  • +
+

Counter, AggregationCounter and Histogram come also in variants respecting dynamic tags. (See section Dynamic Tags.)

+

All methods that create new metrics objects can be found in the Metrics Service reference. You should never initiate a new metrics object on its own, but always through Metrics Service. Metris initialization is meant to be done in the init time of your application and should not be done during runtime.

+
+
+

ASAB Metrics Interpretation

+

Metrics Service not only creates new metrics but also periodically collects their values and sends them to selected databases. +Every 60 seconds in the application lifetime, Metrics Service gathers values of all ASAB metrics. +All Counters (and metric types that inherit from Counter) reset at this event to their initial values by default. +Interpretation of ASAB Counters is affected by their resetable nature. Even though they monotonously increase, resetting every minute gives them a different meaning. +In a long-term observation (that’s how you most probably monitor the metrics in time-series databases), these metrics count events per minute. +Thus, resettable Counters are presented to Prometheus database as gauge-type metrics. Set the reset argument to False when creating a new Counter to disable Counter resetting. +This periodic “flush” cycle also causes 60s delay of metric propagation into supported time-series databases.

+
+
+

Initial Values

+

You can initiate your metric instance with or without initial values. When providing initial values, these values are always present and presented to databases even when these values were untouched during the last 60 seconds. You will always see these values in the data, with initial state or changed by occasion. +However, the lifetime of values (name and value pairs) added during runtime is only 60 s. Thus, if this value is not set during 60s period, you won’t see it in your database anymore.

+
+
+

Dynamic Tags

+

Some metric types (Counter, AggregationCounter, Histogram) allow you to use dynamic tags. All metrics in ASAB carry some tags - Hostname by default and others added by custom. +Using dynamic tags allows you to create values with a specific tag-set during runtime. Specific tag-sets expire after defined period. This might be spotted in your time-series database like a mysterious disappearance of unused tags. +Specify expiration period in confiuration. Default is 60 s.

+

example configuration

+
[asab:metrics]
+expiration=60
+
+
+
+
+

InfluxDB

+

Metrics can be collected in the Influx time-series database.

+

configuration example:

+
[asab:metrics]
+target=influxdb
+
+[asab:metrics:influxdb]
+url=http://localhost:8086/
+bucket=my_bucket
+org=my_org
+token=my_token
+
+
+

InfluxDB 2.0 API parameters:

+
    +
  • url - [required] url string of your influxDB

  • +
  • bucket - [required] the destination bucket for writes

  • +
  • org - [required] specifies the destination organization for writes

  • +
  • +
    orgid - [optional] specifies the ID of the destination organization for writes

    (NOTE: If both orgID and org are specified, org takes precedence)

    +
    +
    +
  • +
  • token - [required] API token to authenticate to the InfluxDB

  • +
+

InfluxDB <1.8 API parameters:

+
    +
  • url - [required] url string of your influxDB

  • +
  • username - [required] name of influxDB user

  • +
  • password - [required] password of influxDB user

  • +
+
+
+

Prometheus

+

Prometheus is a “pull model” time-series database. +Prometheus accesses asab/v1/metrics endpoint of ASAB ApiService. Thus, connecting ASAB to Prometheus requires APIService initialization. However, no more configuration is needed. +ASAB metrics are presented to Prometheus in OpenMetrics standard format.

+

prometheus.yaml configuration file example:

+
global:
+  scrape_interval: 15s
+  scrape_timeout: 10s
+  evaluation_interval: 15s
+
+scrape_configs:
+- job_name: 'metrics_example'
+  metrics_path: '/asab/v1/metrics'
+  scrape_interval: 10s
+  static_configs:
+  - targets: ['127.0.0.1:8080']
+
+
+
+

Note

+

To satisfy the OpenMetrics format required by Prometheus, you should follow the instructions below:

+
    +
  • Metrics names must fit regex [a-zA-Z:][a-zA-Z0-9_:]*. (Any other characters are replaced by an underscore. Leading underscores and numbers are stripped. These changes proceed without warning.)

  • +
  • Metrics names MUST NOT end with “total” or “created”.

  • +
  • Tags SHOULD contain items “unit” and “help” providing metadata to Prometheus.

  • +
  • Values MUST be float or integer.

  • +
+
+
+
+

Metrics Endpoints

+

The API Service in ASAB offers several endpoints that monitor internal ASAB functionality. Some of them present the current state of metrics.

+

/asab/v1/metrics

+
    +
  • This endpoint returns metrics in OpenMetrics format and its primary purpose is to satisfy Prometheus database needs.

  • +
+

/asab/v1/metrics.json

+
    +
  • This endpoint presents metrics data in JSON format.

  • +
+

/asab/v1/watch_metrics

+
    +
  • Use this endpoint for developing or monitoring your app from the terminal. It returns a simple table of ASAB metrics. You can filter metrics by name using the filter parameter and tags parameter to show or hide tags.

  • +
+

example commands:

+
watch curl localhost:8080/asab/v1/watch_metrics
+
+
+
watch curl localhost:8080/asab/v1/watch_metrics?name=web_requests_duration_max,tags=True
+
+
+
+
+

HTTP Target

+

For use cases requiring a push model of metrics digestion, there is an HTTP Target. HTTP Target creates a POST request to configured URL with current metrics state sent as JSON body. +Configuration is required.

+

configuration example:

+
[asab:metrics]
+target=http
+
+[asab:metrics:http]
+url=http://consumer_example:8080/consume
+
+
+
+
+

Web Requests Metrics

+

ASAB WebService class automatically provides metrics counting web requests. +There are 5 metrics quantifying requests to all ASAB endpoints.

+
    +
  • web_requests - Counts requests to asab endpoints as events per minute.

  • +
  • web_requests_duration - Counts total requests duration to asab endpoints per minute.

  • +
  • web_requests_duration_min - Counts minimal request duration to asab endpoints per minute.

  • +
  • web_requests_duration_max - Counts maximum request duration to asab endpoints per minute.

  • +
  • web_requests_duration_hist - Cumulative histogram counting requests in buckets defined by the request duration.

  • +
+
+
+

Native Metrics

+

You can opt out of Native Metrics through configuration by setting native_metrics to false. Default is true.

+

example configuration

+
[asab:metrics]
+native_metrics=true
+
+
+

Memory Metrics

+

A gauge with the name os.stat gathers information about memory usage by your application.

+

You can find several metric values there:

+
    +
  • VmPeak - Peak virtual memory size

  • +
  • VmLck - Locked memory size

  • +
  • VmPin - Pinned memory size

  • +
  • VmHWM - Peak resident set size (“high water mark”)

  • +
  • VmRSS - Resident set size

  • +
  • VmData, VmStk, VmExe - Size of data, stack, and text segments

  • +
  • VmLib - Shared library code size

  • +
  • VmPTE - Page table entries size

  • +
  • VmPMD - Size of second-level page tables

  • +
  • VmSwap - Swapped-out virtual memory size by anonymous private pages; shmem swap usage is not included

  • +
+

Logs Counter

+

There is a default Counter named logs with values warnings, errors, and critical, counting logs with respective levels. +It is a humble tool for application health monitoring.

+
+
+

Reference

+
+
+class asab.metrics.MetricsService(app, service_name)[source]
+

Bases: Service

+
+
+create_gauge(metric_name, tags=None, init_values=None, help=None, unit=None)[source]
+

Creates Gauge object.

+
+ +
+
+create_counter(metric_name, tags=None, init_values=None, reset: bool = True, help=None, unit=None, dynamic_tags=False)[source]
+

Creates Counter or CounterWithDynamicTags object.

+
+ +
+
+create_eps_counter(metric_name, tags=None, init_values=None, reset: bool = True, help=None, unit=None)[source]
+

Creates EPSCounter object.

+
+ +
+
+create_duty_cycle(loop, metric_name, tags=None, init_values=None, help=None, unit=None)[source]
+

Creates DutyCycle object.

+
+ +
+
+create_aggregation_counter(metric_name, tags=None, init_values=None, reset: bool = True, aggregator=<built-in function max>, help=None, unit=None, dynamic_tags=False)[source]
+

Creates AggregationCounter or AggregationCounterWithDynamicTags object.

+
+ +
+
+create_histogram(metric_name, buckets: list, tags=None, init_values=None, reset: bool = True, help=None, unit=None, dynamic_tags=False)[source]
+

Creates Histogram or HistogramWithDynamicTags object.

+
+ +
+ +
+
+class asab.metrics.Gauge(init_values=None)[source]
+

Bases: Metric

+

Argument init_values is a dictionary with initial values and value names as keys.

+
+
+set(name: str, value)[source]
+
+ +
+
Parameters:
+
    +
  • name – name of the value

  • +
  • value – value itself

  • +
+
+
+
+ +
+
+class asab.metrics.Counter(init_values=None)[source]
+

Bases: Metric

+

Argument init_values is a dictionary with initial values and value names as keys. +If reset is True, Counter resets every 60 seconds.

+
+
+add(name, value, init_value=None)[source]
+
+
Parameters:
+
    +
  • name – name of the counter

  • +
  • value – value to be added to the counter

  • +
+
+
+

Adds the value to the counter Values specified by name. +If name is not in Counter Values, it will be added.

+
+ +
+
+sub(name, value, init_value=None)[source]
+
+
Parameters:
+
    +
  • name – name of the counter

  • +
  • value – value to be subtracted from the counter

  • +
+
+
+

Subtracts the value from the counter Values specified by name. +If name is not in Counter Values, it will be added.

+
+ +
+ +
+
+class asab.metrics.EPSCounter(init_values=None)[source]
+

Bases: Counter

+

Event per Second Counter +Divides the count of event by a time difference between measurements. +It effectively produces the EPS metric. +The type of the metric is an integer (int).

+
+ +
+
+class asab.metrics.DutyCycle(loop, init_values=None)[source]
+

Bases: Metric

+

https://en.wikipedia.org/wiki/Duty_cycle

+
+

now = self.Loop.time() +d = now - self.LastReadyStateSwitch +self.LastReadyStateSwitch = now

+
+

To initialize DutyCycle, provide an application loop (asab.Application.Loop) as this object tracks the time of the application.

+
+ +
+
+class asab.metrics.AggregationCounter(init_values=None, aggregator=<built-in function max>)[source]
+

Bases: Counter

+

Sets value aggregated with the last one. +Takes a function object as the aggregator argument. +The aggregation function can take two arguments only. +Maximum is used as a default aggregation function.

+

Values (their names and init_values) can be provided when initializing the metrics or added with set() method. +add() and sub() methods are not implemented.

+
+
+set(name, value)[source]
+
+ +

Applies aggregation function on recent Counter value and value in argument and sets the result as new value of the Counter.

+
+ +
+
+class asab.metrics.Histogram(buckets: list, init_values=None)[source]
+

Bases: Metric

+

Creates cumulative histograms.

+
+
+set(value_name, value)[source]
+
+ +
+ +
+
+class asab.metrics.CounterWithDynamicTags(init_values=None)[source]
+

Bases: MetricWithDynamicTags

+
+
+add(name, value, tags)[source]
+
+
Parameters:
+
    +
  • name – name of the counter

  • +
  • value – value to be added to the counter

  • +
+
+
+

Adds the value to the counter Values specified by name. +If name is not in Counter Values, it will be added there.

+
+ +
+
+sub(name, value, tags)[source]
+
+
Parameters:
+
    +
  • name – name of the counter

  • +
  • value – value to be subtracted from the counter

  • +
+
+
+

Subtracts the value from the counter Values specified by name. +If name is not in Counter Values, it will be added there.

+
+ +
+ +
+
+class asab.metrics.AggregationCounterWithDynamicTags(init_values=None, aggregator=<built-in function max>)[source]
+

Bases: CounterWithDynamicTags

+
+
+set(name, value, tags)[source]
+
+ +
+ +
+
+class asab.metrics.HistogramWithDynamicTags(buckets: list, init_values=None)[source]
+

Bases: MetricWithDynamicTags

+

Creates cumulative histograms with dynamic tags

+
+
+set(value_name, value, tags)[source]
+
+ +
+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/module.html b/old_docs/_build/htmln/asab/module.html new file mode 100644 index 000000000..156d8205e --- /dev/null +++ b/old_docs/_build/htmln/asab/module.html @@ -0,0 +1,201 @@ + + + + + + + + + Module — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Module

+
+
+class asab.Module[source]
+
+ +

Modules are registered at the module registry, managed by an application object. +See Application.Modules for more details. +Module can be loaded by ASAB and typically provides one or more Service objects.

+
+

Structure

+

Recommended structure of the ASAB module:

+
mymodule/
+    __init__.py
+    myservice.py
+
+
+

Content of the __init__.py:

+
import asab
+from .myservice import MyService
+
+# Extend ASAB configuration defaults
+asab.Config.add_defaults({
+    'mymodule': {
+        'foo': 'bar'
+    }
+})
+
+class MyModule(asab.Module):
+    def __init__(self, app):
+        super().__init__(app)
+        self.service = MyService(app, "MyService")
+
+
+

And this is how the module is loaded:

+
from mymodule import MyModule
+app.add_module(MyModule)
+
+
+

For more details see Application.add_module.

+
+
+

Lifecycle

+
+
+Module.initialize(app)[source]
+
+ +

Called when the module is initialized. +It can be overriden by an user.

+
+
+Module.finalize(app)[source]
+
+ +

Called when the module is finalized e.g. during application exit-time. +It can be overriden by an user.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/pubsub.html b/old_docs/_build/htmln/asab/pubsub.html new file mode 100644 index 000000000..b8846ebd1 --- /dev/null +++ b/old_docs/_build/htmln/asab/pubsub.html @@ -0,0 +1,427 @@ + + + + + + + + + Publish-Subscribe — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Publish-Subscribe

+

Publish–subscribe is a messaging pattern where senders of messages, called publishers, send the messages to receivers, called subscribers, via PubSub message bus. Publishers don’t directly interact with subscribers in any way. Similarly, subscribers express interest in one or more message types and only receive messages that are of interest, without knowledge of which publishers, if any, there are.

+
+
+class asab.PubSub(app)[source]
+
+ +

ASAB PubSub operates with a simple messages, defined by their message type, which is a string. +We recommend to add ! (explamation mark) at the end of the message type in order to distinguish this object from other types such as Python class names or functions. +Example of the message type is e.g. Application.run! or Application.tick/600!.

+

The message can carry an optional positional and keyword arguments. +The delivery of a message is implemented as a the standard Python function.

+

Note: There is an default, application-wide Publish-Subscribe message bus at Application.PubSub that can be used to send messages. +Alternatively, you can create your own instance of PubSub and enjoy isolated PubSub delivery space.

+
+

Subscription

+
+
+PubSub.subscribe(message_type, callback)[source]
+
+ +

Subscribe to a message type. Messages will be delivered to a callback callable (function or method). +The callback can be a standard callable or an async coroutine. +Asynchronous callback means that the delivery of the message will happen in a Future, asynchronously.

+

Callback callable will be called with the first argument

+

Example of a subscription to an Application.tick! messages.

+
class MyClass(object):
+        def __init__(self, app):
+                app.PubSub.subscribe("Application.tick!", self.on_tick)
+
+        def on_tick(self, message_type):
+                print(message_type)
+
+
+

Asynchronous version of the above:

+
class MyClass(object):
+        def __init__(self, app):
+                app.PubSub.subscribe("Application.tick!", self.on_tick)
+
+        async def on_tick(self, message_type):
+                await asyncio.sleep(5)
+                print(message_type)
+
+
+
+
+PubSub.subscribe_all(obj)[source]
+
+ +

To simplify the process of subscription to PubSub, ASAB offers the decorator-based “subscribe all” functionality.

+

In the followin example, both on_tick() and on_exit() methods are subscribed to Application.PubSub message bus.

+
class MyClass(object):
+        def __init__(self, app):
+                app.PubSub.subscribe_all(self)
+
+        @asab.subscribe("Application.tick!")
+        async def on_tick(self, message_type):
+                print(message_type)
+
+        @asab.subscribe("Application.exit!")
+        def on_exit(self, message_type):
+                print(message_type)
+
+
+
+
+PubSub.unsubscribe(message_type, callback)[source]
+
+ +

Unsubscribe from a message delivery.

+
+
+class asab.Subscriber(pubsub=None, *message_types)[source]
+

Subscriber object allows to consume PubSub messages in coroutines. +It subscribes for various message types and consumes them. +It works on FIFO basis (First message In, first message Out). +If pubsub argument is None, the initial subscription is skipped.

+
subscriber = asab.Subscriber(
+        app.PubSub,
+        "Application.tick!",
+        "Application.stop!"
+)
+
+
+
+
+message()[source]
+

Wait for a message asynchronously. +Returns a three-members tuple (message_type, args, kwargs).

+

Example of the await message() use:

+
async def my_coroutine(app):
+        # Subscribe for a two application events
+        subscriber = asab.Subscriber(
+                app.PubSub,
+                "Application.tick!",
+                "Application.exit!"
+        )
+        while True:
+                message_type, args, kwargs = await subscriber.message()
+                if message_type == "Application.exit!":
+                        break
+                print("Tick.")
+
+
+
+ +
+
+subscribe(pubsub, message_type)[source]
+

Subscribe for more message types. This method can be called many times with various pubsub objects.

+
+ +
+ +

The subscriber object can be also used as an asynchonous generator. +The example of the subscriber object usage in async for statement:

+
async def my_coroutine(self):
+        # Subscribe for a two application events
+        subscriber = asab.Subscriber(
+                self.PubSub,
+                "Application.tick!",
+                "Application.exit!"
+        )
+        async for message_type, args, kwargs in subscriber:
+                if message_type == "Application.exit!":
+                        break;
+                print("Tick.")
+
+
+
+
+

Publishing

+
+
+PubSub.publish(message_type, \*args, \**kwargs)[source]
+
+ +

Publish a message to the PubSub message bus. +It will be delivered to each subscriber synchronously. +It means that the method returns after each subscribed callback is called.

+

The example of a message publish to the Application.PubSub message bus:

+
def my_function(app):
+        app.PubSub.publish("mymessage!")
+
+
+

Asynchronous publishing of a message is requested by asynchronously=True argument. +The publish() method returns immediatelly and the delivery of the message to subscribers happens, when control returns to the event loop.

+

The example of a asynchronous version of a message publish to the Application.PubSub message bus:

+
def my_function(app):
+        app.PubSub.publish("mymessage!", asynchronously=True)
+
+
+
+
+

Synchronous vs. asynchronous messaging

+

ASAB PubSub supports both modes of a message delivery: synchronous and asynchronous. +Moreover, PubSub also deals with modes, when asynchronous code (coroutine) does publish to synchronous code and vice versa.

+ + + + + + + + + + + + + + + +

Sync publish

Async publish

Sync subscribe

Called immediately

call_soon(...)

Async subscribe

ensure_future(...)

call_soon(...) & ensure_future(...)

+
+
+

Application-wide PubSub

+
+
+Application.PubSub
+
+ +

The ASAB provides the application-wide Publish-Subscribe message bus.

+
+

Well-Known Messages

+

This is a list of well-known messages, that are published on a Application.PubSub by ASAB itself.

+
+
+Application.init!
+
+ +

This message is published when application is in the init-time. +It is actually one of the last things done in init-time, so the application environment is almost ready for use. +It means that configuration is loaded, logging is setup, the event loop is constructed etc.

+
+
+Application.run!
+
+ +

This message is emitted when application enters the run-time.

+
+
+Application.stop!
+
+ +

This message is emitted when application wants to stop the run-time. +It can be sent multiple times because of a process of graceful run-time termination. +The first argument of the message is a counter that increases with every Application.stop! event.

+
+
+Application.exit!
+
+ +

This message is emitted when application enter the exit-time.

+
+
+Application.tick!
+
+ +
+
+Application.tick/10!
+
+ +
+
+Application.tick/60!
+
+ +
+
+Application.tick/300!
+
+ +
+
+Application.tick/600!
+
+ +
+
+Application.tick/1800!
+
+ +
+
+Application.tick/3600!
+
+ +
+
+Application.tick/43200!
+
+ +
+
+Application.tick/86400!
+
+ +

The application publish periodically “tick” messages. +The default tick frequency is 1 second but you can change it by configuration [general] tick_period. +Application.tick! is published every tick. Application.tick/10! is published every 10th tick and so on.

+
+
+Application.hup!
+
+ +

This message is emitted when application receives UNIX signal SIGHUP or equivalent.

+
+
+Application.housekeeping!
+
+ +

This message is published when application is on the time for housekeeping. The time for housekeeping is set to 03:00 AM UTC. It can be changed in the configuration file:

+
[general]
+housekeeping_time=19:30
+
+
+

This sets the housekeeping time to 7:30 PM UTC. +The time must be written in the format ‘HH:MM’. +Remind yourself that the time is set to UTC, so you should be careful when operating in a different timezone.

+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/service.html b/old_docs/_build/htmln/asab/service.html new file mode 100644 index 000000000..0b1dfc12c --- /dev/null +++ b/old_docs/_build/htmln/asab/service.html @@ -0,0 +1,207 @@ + + + + + + + + + Service — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Service

+
+
+class asab.Service(app)[source]
+
+ +

Service objects are registered at the service registry, managed by an application object. +See Application.Services for more details.

+

An example of a typical service class skeleton:

+
class MyService(asab.Service):
+
+    def __init__(self, app, service_name):
+        super().__init__(app, service_name)
+        ...
+
+    async def initialize(self, app):
+        ...
+
+
+    async def finalize(self, app):
+        ...
+
+
+    def service_method(self):
+        ....
+
+
+

This is how a service is created and registered:

+
mysvc = MyService(app, "my_service")
+
+
+

This is how a service is located and used:

+
mysvc = app.get_service("my_service")
+mysvc.service_method()
+
+
+
+
+Service.Name
+
+ +

Each service is identified by its name.

+
+
+Service.App
+
+ +

A reference to an Application object instance.

+
+

Lifecycle

+
+
+Service.initialize(app)[source]
+
+ +

Called when the service is initialized. +It can be overriden by an user.

+
+
+Service.finalize(app)[source]
+
+ +

Called when the service is finalized e.g. during application exit-time. +It can be overriden by an user.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/storage.html b/old_docs/_build/htmln/asab/storage.html new file mode 100644 index 000000000..46a1f3dc5 --- /dev/null +++ b/old_docs/_build/htmln/asab/storage.html @@ -0,0 +1,313 @@ + + + + + + + + + Storage — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Storage

+

ASAB provides a service for storing data. Data can be stored in memory or in dedicated document database. For now, MongoDB and Elastic Search databases are supported.

+
+

Specification of the storage type

+

In order to use asab.storage, first you have to specify the type of storage. You can add configurations in the config file:

+
[asab:storage]
+type=mongodb
+
+
+

or you can set it manually in the ASAB app:

+
import asab
+import asab.storage
+
+asab.Config.add_defaults(
+    {
+        'asab:storage': {
+            'type': 'mongodb'
+        }
+    }
+)
+
+
+

The options for the storage type are:

+
    +
  • inmemory: Collects data directly in memory

  • +
  • mongodb: Collects data using MongoDB database. Depends on pymongo and motor libraries.

  • +
  • elasticsearch: Collects data using Elastic Search database. Depends on aiohttp library.

  • +
+

Although these three databases are different, accessing the database and manipulation with collections is done by using the same methods.

+

For accessing the storage, simply add asab.storage.Module` when initializing and register the service.

+
class MyApplication(asab.Application):
+
+    async def initialize(self):
+
+        self.add_module(asab.storage.Module)
+
+    async def main(self):
+        storage = self.get_service("asab.StorageService")
+
+
+
+
+

Manipulation with databases

+
+

Upsertor

+

Upsertors are used for manipulations with databases. Upsertor is an object that works like a pointer to the specified database and optionally to object id.

+
u = storage.upsertor("test-collection")
+
+
+

The method upsertor() create an upsertor object associated with the specified collection. It takes collection as an argument and can have two parameters obj_id and version, which are used for getting an existing object by its ID and version.

+
+
+

Inserting an object

+

For inserting an object to the collection, use the set() method.

+
u.set("key", "value")
+
+
+

To execute these procedures, simply run the execute() coroutine method, which commits the upsertor data to the storage and returns the ID of the object. Since it is a coroutine, it must be awaited.

+
object_id = await u.execute()
+
+
+

The execute() method has optional parameters custom_data and event_type, which are used for webhook requests.

+
object_id = await u.execute(custom_data= {"foo": "bar"},event_type="object_created")
+
+
+
+
+

Getting a single object

+

For getting a single object, use get() coroutine method that takes two arguments collection and obj_id and finds an object by its ID in collection.

+
obj = await storage.get(collection="test-collection", obj_id=object_id)
+
+
+

When the requested object is not found in the collection, the method raises KeyError. Remember to handle this exception properly when using databases in your services and prevent them from crashing!

+
+

Note

+

MongoDB storage service in addition provides a coroutine method get_by() which is used for accessing an object by finding its key-value pair.

+
+
+
+

Updating an object

+

For updating an object, first obtain the upsertor specifying its obj_id and version.

+
u = storage.upsertor("test-collection", obj_id=object_id, version=obj['_v']
+
+
+

We strongly recommend to read the version from the object such as above. That creates a soft lock on the record. It means that if the object is updated by other component in meanwhile, your upsertor will fail and you should retry the whole operation. The new objects should have a version set to 0, which is done by default.

+

After obtaining an upsertor, you can update the object via the set() coroutine.

+
+
+

Deleting an object

+

For deleting an object from database, use the delete() coroutine method which takes arguments collection and obj_id, deletes the object and returns its ID.

+
deleted_id = await u.delete("test-collection", object_id)
+
+
+
+
+
+

Storing data in memory

+

If the option inmemory is set, ASAB will store data in its own memory. In particular, asab.StorageService is initialized with an attribute InMemoryCollections which is a dictionary where all the collections are stored in.

+
+

Note

+

You can go through all the databases directly by accessing InMemoryCollections attribute, although we do not recommend that.

+
import pprint
+
+storage = self.get_service("asab.StorageService")
+pprint.pprint(storage.InMemoryCollections, indent=2)
+
+
+
+
+
+

Storing data in MongoDB

+

If the option mongodb is set, ASAB will store data in MongoDB database.

+

ASAB uses motor library which provides non-blocking MongoDB driver for asyncio.

+

You can specify the database name and URL for MongoDB in config file (the following example is the default configuration):

+
[asab:storage]
+type=mongodb
+mongodb_uri=mongodb://localhost:27017
+mongodb_database=asabdb
+
+
+
+
+StorageService.get_by(collection: str, key: str, value, decrypt=None) dict
+
+ +
+
+StorageService.collection(collection: str) motor.motor_asyncio.AsyncIOMotorCollection
+
+ +

Mongo Storage class provides in addition a method collection() for accessing database directly. It takes collection as the argument and returns motor.motor_asyncio.AsyncIOMotorCollection object, which can be used for calling MongoDB directives.

+

Example of the use:

+
collection = await storage.collection("test-collection")
+cursor = collection.find({})
+while await cursor.fetch_next:
+    data = cursor.next_object()
+    pprint.pprint(data)
+
+
+

The full list of methods suitable for this object is described in the official documentation.

+
+ +
+

Encryption and decryption

+

TODO

+
+
+

Object ID

+

TODO (how ID’s are generated via generateid() method)

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/various.html b/old_docs/_build/htmln/asab/various.html new file mode 100644 index 000000000..08f6ae2f0 --- /dev/null +++ b/old_docs/_build/htmln/asab/various.html @@ -0,0 +1,359 @@ + + + + + + + + + Various utility classes — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Various utility classes

+
+
+class asab.abc.Module(app)[source]
+

Bases: ABC

+

Abstract module class

+
+
+async finalize(app)[source]
+
+ +
+
+async initialize(app)[source]
+
+ +
+ +
+
+class asab.abc.Service(app, service_name)[source]
+

Bases: ABC

+

Abstract service class

+
+
+async finalize(app)[source]
+
+ +
+
+async initialize(app)[source]
+
+ +
+ +
+
+class asab.abc.Singleton[source]
+

Bases: type

+

The singleton pattern is a software design pattern that restricts the instantiation of a class to one object.

+

Note: The implementation idea is borrowed from “Creating a singleton in Python” question on StackOverflow.

+
+
+classmethod delete(singleton_cls)[source]
+

The method for an intentional removal of the singleton object. +It shouldn’t be used unless you really know what you are doing.

+

One use case is a unit test, which removes an Application object after each iteration.

+
+ +
+ +
+

Singleton

+
+
+class asab.abc.singleton.Singleton[source]
+

The singleton pattern is a software design pattern that restricts the instantiation of a class to one object.

+

Note: The implementation idea is borrowed from “Creating a singleton in Python” question on StackOverflow.

+
+
+classmethod delete(singleton_cls)[source]
+

The method for an intentional removal of the singleton object. +It shouldn’t be used unless you really know what you are doing.

+

One use case is a unit test, which removes an Application object after each iteration.

+
+ +
+ +

Usage:

+
import asab
+
+class MyClass(metaclass=asab.Singleton):
+    ...
+
+
+
+
+

Persistent dictionary

+
+
+class asab.pdict.PersistentDict(path)[source]
+

Bases: dict

+

The persistent dictionary works as the regular Python dictionary but the content of the dictionary is stored in the file. +You cat think of a PersistentDict as a simple key-value store. +It is not optimized for a frequent access. This class provides common dict interface.

+

Warning: You must explicitly load() and store() content of the dictionary +Warning: You can only store objects in the persistent dictionary that are serializable.

+
+
+load() None[source]
+

Load content of file as dictionary.

+
+ +
+
+store() None[source]
+

Explicitly store content of persistent dictionary to file

+
+ +
+
+update(other=(), **kwds) None[source]
+

Update D from mapping/iterable E and F. +* If E present and has a .keys() method, does: for k in E: D[k] = E[k] +* If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v +* In either case, this is followed by: for k, v in F.items(): D[k] = v

+

Inspired by a https://github.com/python/cpython/blob/3.8/Lib/_collections_abc.py

+
+ +
+ +

Note: A recommended way of initializing the persistent dictionary:

+
PersistentState = asab.PersistentDict("some.file")
+PersistentState.setdefault('foo', 0)
+PersistentState.setdefault('bar', 2)
+
+
+
+
+

Timer

+
+
+class asab.timer.Timer(app, handler, autorestart=False)[source]
+

Bases: object

+

The relative and optionally repeating timer for asyncio.

+

This class is simple relative timer that generate an event after a given time, and optionally repeating in regular intervals after that.

+
+
Parameters:
+
    +
  • app – An ASAB application.

  • +
  • handler – A coro or future that will be called when a timer triggers.

  • +
  • autorestart (boolean) – If True then a timer will be automatically restarted after triggering.

  • +
+
+
Variables:
+
    +
  • Handler – A coro or future that will be called when a timer triggers.

  • +
  • Task – A future that represent the timer task.

  • +
  • App – An ASAB app.

  • +
  • AutoRestart (boolean) – If True then a timer will be automatically restarted after triggering.

  • +
+
+
+

The timer object is initialized as stopped.

+

Note: The implementation idea is borrowed from “Python - Timer with asyncio/coroutine” question on StackOverflow.

+
+
+is_started() boolean[source]
+

Return True is the timer is started otherwise returns False.

+
+ +
+
+restart(timeout)[source]
+

Restart the timer.

+
+
Parameters:
+

timeout (float/int) – A timer delay in seconds.

+
+
+
+ +
+
+start(timeout)[source]
+

Start the timer.

+
+
Parameters:
+

timeout (float/int) – A timer delay in seconds.

+
+
+
+ +
+
+stop()[source]
+

Stop the timer.

+
+ +
+ +
+
+

Sockets

+
+
+class asab.socket.StreamSocketServerService(app, service_name)[source]
+

Bases: Service

+

Example of use:

+

class ServiceMyProtocolServer(asab.StreamSocketServerService):

+
+
+
async def initialize(self, app):

host = asab.Config.get(‘http’, ‘host’) +port = asab.Config.getint(‘http’, ‘port’)

+

L.debug(“Starting server on {} {} …”.format(host, port)) +await self.create_server(app, MyProtocol, [(host, port)])

+
+
+
+
+
+async create_server(app, protocol, addrs)[source]
+
+ +
+
+async finalize(app)[source]
+
+ +
+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/web/authn.html b/old_docs/_build/htmln/asab/web/authn.html new file mode 100644 index 000000000..b21e94217 --- /dev/null +++ b/old_docs/_build/htmln/asab/web/authn.html @@ -0,0 +1,201 @@ + + + + + + + + + Authn module — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Authn module

+

Module asab.web.authn provides middlewares and classes to allow only authorized users access specified web server endpoints. +It also allows to forward requests to the authorization server via instance of OAuthForwarder.

+

Currently available authorization technologies include OAuth 2.0, public/private key and HTTP basic auth.

+
+

Middleware

+
+
+authn_middleware_factory(app, implementation, *args, **kwargs):
+
+ +

First step is to define the authorization implementation, which can be the OAuth 2.0, public/private key or +HTTP basic auth. Depending on the implementation, there are arguments which further specify the authorization +servers that are going to be used.

+

When it comes to OAuth 2.0, there are methods for every OAuth 2.0 server, that is going to be used for authorization +and obtainment of the user identity. The relevant method is selected based on access token prefix, that is received +from the client in the HTTP request (Authorization header):

+

Authorization: Bearer <OAUTH-SERVER-ID>-<ACCESS_TOKEN>

+

The following example illustrates how to register a middleware inside the web server container with OAuth 2.0 +implementation and GitHub method.

+
container.WebApp.middlewares.append(
+    asab.web.authn.authn_middleware_factory(self,
+        "oauth2client",  # other implementations include: "basicauth" and "pubkeyauth"
+        methods=[
+        # Use GitHub OAuth provider
+        asab.web.authn.oauth.GitHubOAuthMethod(),
+        ],
+    )
+)
+
+
+
+
+

Decorators

+

In order to require authorization for a specific endpoint and thus utilize the output of the registered middleware, +it is necessary to decorate its handler method with authn_required_handler decorator.

+

The decorator provide the handler method with an identity argument, which contains the user identity received +from the authorization server. Thus the user information can be further evaluated or included as part of the response. +To receive just the identity information but not force the authorization for the endpoint, the authn_optional_handler +can be used instead.

+

The following example illustrates how to use the authn_required_handler decorator in order to enforce the +authorization and receive user identity in the identity argument:

+
@asab.web.authn.authn_required_handler
+async def user(self, request, *, identity):
+    return asab.web.rest.json_response(request=request, data={
+        'message': '"{}", you have accessed our secured "user" endpoint.'.format(identity),
+    })
+
+
+
+
+

Example

+

To see & try the full example which utilizes OAuth 2.0 middleware and decorators, please see the code +in the following link:

+

https://github.com/TeskaLabs/asab/blob/master/examples/web-authn-oauth.py

+

Another example serves to demonstrate the public/private key authorization via ASAB web client ssl cert authorization:

+

https://github.com/TeskaLabs/asab/blob/master/examples/web-authn-pubkey.py

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/web/cors.html b/old_docs/_build/htmln/asab/web/cors.html new file mode 100644 index 000000000..ffdd2508e --- /dev/null +++ b/old_docs/_build/htmln/asab/web/cors.html @@ -0,0 +1,153 @@ + + + + + + + + + Cross-Origin Resource Sharing (CORS) — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Cross-Origin Resource Sharing (CORS)

+

When you create a web container, you specify a config section name. In the example below it’s myapp:web:

+
asab.web.WebContainer(self.WebService, "myapp:web")
+
+
+

You can then configure CORS by running your app with a config file with this contents:

+
[myapp:web]
+cors=*
+cors_preflight_paths=/*
+
+
+
    +
  • cors: contents of the Access-Control-Allow-Origin header

  • +
  • cors_preflight_paths: a pattern for endpoints that shall return responses to pre-flight requests (OPTIONS). Value must start with “/”.

  • +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/web/index.html b/old_docs/_build/htmln/asab/web/index.html new file mode 100644 index 000000000..d546bbfe0 --- /dev/null +++ b/old_docs/_build/htmln/asab/web/index.html @@ -0,0 +1,289 @@ + + + + + + + + + The web server — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

The web server

+

ASAB provides a web server in a asab.web module. +This module offers an integration of a aiohttp web server.

+
    +
  1. Before you start, make sure that you have aiohttp module installed.

  2. +
+
$ pip3 install aiohttp
+
+
+
    +
  1. The following code creates a simple web server application

  2. +
+
#!/usr/bin/env python3
+import asab
+import asab.web
+import aiohttp
+
+class MyApplication(asab.Application):
+
+    def __init__(self):
+        super().__init__()
+
+        # Load the ASAB Web module
+        self.add_module(asab.web.Module)
+
+        # Locate the ASAB Web service
+        websvc = self.get_service("asab.WebService")
+
+        # Create the Web container
+        container = asab.web.WebContainer(websvc, 'my:web', config={"listen": "0.0.0.0:8080"})
+
+        # Add a route to the handler
+        container.WebApp.router.add_get('/hello', self.hello)
+
+    # This is the web request handler
+    async def hello(self, request):
+        return aiohttp.web.Response(text='Hello!\n')
+
+if __name__ == '__main__':
+    app = MyApplication()
+    app.run()
+
+
+
    +
  1. Test it with curl

  2. +
+
$ curl http://localhost:8080/hello
+Hello!
+
+
+
+

Web Service

+
+
+class asab.web.service.WebService[source]
+
+ +

Service location example:

+
from asab.web import Module
+self.add_module(Module)
+svc = self.get_service("asab.WebService")
+
+
+
+
+

Configuration

+

The default configuration of the web container in ASAB is following:

+
[web]
+listen=0.0.0.0:8080
+
+
+

Multiple listening interfaces can be specified:

+
[web]
+listen:
+        0.0.0.0:8080
+        :: 8080
+
+
+

Multiple listening interfaces, one with HTTPS (TLS/SSL) can be specified:

+
[web]
+listen:
+        0.0.0.0 8080
+        :: 8080
+        0.0.0.0 8443 ssl:web
+
+[ssl:web]
+cert=...
+key=...
+...
+
+
+

Multiple interfaces, one with HTTPS (inline):

+
[web]
+listen:
+        0.0.0.0 8080
+        :: 8080
+        0.0.0.0 8443 ssl
+
+# The SSL parameters are inside of the WebContainer section
+cert=...
+key=...
+...
+
+
+

Other available options are:

+
+
    +
  • backlog

  • +
  • rootdir

  • +
  • servertokens (default value full)

  • +
  • cors

  • +
  • cors_preflight_paths

  • +
+
+

TLS/SSL paramereters:

+
+
    +
  • cert

  • +
  • key

  • +
  • password

  • +
  • cafile

  • +
  • capath

  • +
  • ciphers

  • +
  • dh_params

  • +
  • verify_mode: one of CERT_NONE, CERT_OPTIONAL or CERT_REQUIRED

  • +
  • check_hostname

  • +
  • options

  • +
+
+
+
+

Sessions

+

ASAB Web Service provides an implementation of the web sessions.

+
+
+class asab.web.session.ServiceWebSession
+
+ +

TODO: …

+
+
+asab.web.session.session_middleware(storage)
+
+ +

TODO: …

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/web/restapidocs.html b/old_docs/_build/htmln/asab/web/restapidocs.html new file mode 100644 index 000000000..fd7c0be1a --- /dev/null +++ b/old_docs/_build/htmln/asab/web/restapidocs.html @@ -0,0 +1,217 @@ + + + + + + + + + REST API Docs — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

REST API Docs

+

ASAB’s API service generates a Swagger documentation which automatically shows all +of your endpoints and you can add summaries, descriptions, tags and more.

+

If you want Authorization in Swagger docs, you will need an OpenIDConnect endpoint.

+
+

In your microservice

+

First you need to initialize the API Service:

+
# Initialize API service
+self.ApiService = asab.api.ApiService(self)
+
+# Introduce Web to API Service
+self.ApiService.initialize_web()
+
+
+

After initializing the API Service a /doc endpoint will become available. You will notice +that some or none of your endpoints have summaries, tags or descriptions.

+

That’s because you need to add a docstring to your endpoint method:

+
async def endpoint(self, request):
+    """
+    Summary looks like this and takes the first line from docstring.
+
+    Description of what this endpoint does.
+
+    ---
+    tags: [asab.mymicroservice]
+    """
+
+
+

Also by adding a docstring to your ASAB Application, a description will be automatically added to the top of the Swagger docs:

+
class TutorialApp(asab.Application):
+    """
+    TutorialApp is the best microservice in the world!
+
+    <marquee>The description supports HTML tags</marquee>
+    """
+
+
+
+
+

Authorization in Swagger

+

Authorization requires making an OpenIDConnect endpoint with an Authorization and Token endpoint (like with using SeaCat Auth).

+

After your endpoint has authorization, here’s an example, +add the Authorization and Token endpoints into your config.

+

For the authorization bearer token to be added to the request, a scope is needed to be put into the security parameter in a docstring. +It does not matter what it is called or if it exists, but it’s needed to be there. But “- oAuth:” always needs to be there.

+
@asab.web.authz.required("resource:topsecret")
+async def top_secret_endpoint(self, request):
+    """
+    Top secret!
+
+    ---
+    tags: [asab.coolestmicroservice]
+    security:
+        - oAuth:
+            - read
+    """
+
+
+

After setting up Authorization, a green Authorize button should appear in the Swagger docs.

+
+
+

Configuration

+

For authorization you will need to add a authorizationUrl and tokenUrl:

+
[asab:doc]
+authorizationUrl=http://localhost:8080/openidconnect/authorize
+tokenUrl=http://localhost:8080/openidconnect/token
+
+
+

If you have an endpoint that requires a scope, you can add it with the configuration file:

+
[asab:doc]
+scopes=read,write
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/asab/zookeeper.html b/old_docs/_build/htmln/asab/zookeeper.html new file mode 100644 index 000000000..2f14770d7 --- /dev/null +++ b/old_docs/_build/htmln/asab/zookeeper.html @@ -0,0 +1,284 @@ + + + + + + + + + Zookeeper — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Zookeeper

+

The asab.zookeeper is a Apache Zookeeper asynchronous client based on Kazoo library.

+

Apache ZooKeeper is a distributed coordination service that provides a hierarchical key-value data store, called a znode tree, to store and manage configuration, coordination, and synchronization data. The znode tree is similar to a file system tree, where each znode is like a file or a directory.

+

Apache ZooKeeper can be used to design microservices in a stateless manner by managing and coordinating the state information between microservices. In this design, each microservice does not store any state information, but instead relies on ZooKeeper for state management.

+
+

Zookeeper container

+

A Zookeeper container represents a connectivity to Apache Zookeeper server(s). +The application can operate multiple instances of Zookeeper container.

+

This code illustrates the typical way how to create Zookeeper container:

+
import asab.zookeeper
+
+class MyApplication(asab.Application):
+
+    def __init__(self):
+        ...
+
+        # Load the ASAB Zookeeper module
+        self.add_module(asab.zookeeper.Module)
+
+        # Initialize ZooKeeper Service
+        self.ZooKeeperService = self.get_service("asab.ZooKeeperService")
+
+        # Create the Zookeeper container
+        self.ZooKeeperContainer = asab.zookeeper.ZooKeeperContainer(self.ZooKeeperService)
+
+        # Subscribe to Zookeeper container ready event
+        self.PubSub.subscribe("ZooKeeperContainer.started!", self._on_zk_ready)
+
+
+    async def _on_zk_ready(self, event_name, zookeeper):
+        if zookeeper != self.ZooKeeperContainer:
+            return
+
+        print("Connected to Zookeeper!")
+
+
+
+
+class asab.zookeeper.ZooKeeperContainer(zookeeper_service, config_section_name='zookeeper', config=None, z_path=None)[source]
+

Create a Zookeeper container with a specifications of the connectivity.

+
+ +

Specifications are obtained from:

+
    +
  1. z_path argument, which is Zookeeper URL (see below)

  2. +
  3. the configuration section specified by config_section_name argument

  4. +
  5. ZOOKEEPER_SERVERS environment variable

  6. +
+

The z_path argument has precedence over config but the implementation will look +at configuration if z_path URL is missing completely or partially. +Also, if configuration section doesn’t provide information about servers, ZOOKEEPER_SERVERS environment variable is used.

+
+

Example of configuration section

+
[zookeeper]
+servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181
+path=myfolder
+
+
+
+
+

Example of ZOOKEEPER_SERVER environment variable

+
ZOOKEEPER_SERVERS=zookeeper-1:2181,zookeeper-2:2181
+
+
+
+
+

Supported types of z_path URLs

+
    +
  1. Absolute URL

    +
    +

    zookeeper://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/etc/configs/file1

    +

    The URL contains all information for a connectivity.

    +
    +
  2. +
  3. URL without servers with absolute path

    +
    +

    zookeepers:///etc/configs/file1

    +

    In this case the relative url is expanded as follows: +zookeeper://{zookeeper_servers}/etc/configs/file1

    +

    Where {zookeeper_servers} is substituted with the servers entry of the [zookeeper] configuration file section.

    +
    +
  4. +
  5. URL without servers with relative path

    +
    +

    zookeeper:./etc/configs/file1

    +

    In this case, the relative URL is expanded as follows: +zookeper://{zookeeper_servers}/{zookeeper_path}/etc/configs/file1

    +

    Where {zookeeper_servers} is substituted with the servers entry of the [zookeeper] configuration file section and +{zookeeper_path} is substituted with the “path” entry of the [zookeeper] configuration file section.

    +
    +
  6. +
+
+
+ZooKeeperContainer.is_connected()[source]
+

Check, if the Zookeeper is connected

+
+ +
+
+
+

Reading from Zookeeeper

+
+
+async ZooKeeperContainer.get_children(path='')[source]
+
+ +
+
+async ZooKeeperContainer.get_data(path, encoding='utf-8')[source]
+
+ +
+
+async ZooKeeperContainer.get_raw_data(path)[source]
+
+ +
+ +
+

Kazoo

+

Kazoo is the synchronous Python library for Apache Zookeeper.

+

It can be used directly for a more complicated tasks. +Kazoo client is accessible at ZooKeeperContainer.ZooKeeper.Client. +Synchronous methods of Kazoo client must be executed using ProactorService.

+

Here is the example:

+
 def write_to_zk():
+    self.ZooKeeperContainer.ZooKeeper.Client.create(path, data, sequence=True, ephemeral=True, makepath=True)
+
+await self.ZooKeeperContainer.ZooKeeper.ProactorService.execute(write_to_zk)
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/genindex.html b/old_docs/_build/htmln/genindex.html new file mode 100644 index 000000000..aec0ce83b --- /dev/null +++ b/old_docs/_build/htmln/genindex.html @@ -0,0 +1,908 @@ + + + + + + + + Index — ASAB documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + +

Index

+ +
+ Symbols + | _ + | A + | B + | C + | D + | E + | F + | G + | H + | I + | L + | M + | P + | R + | S + | T + | U + | W + | Y + | Z + +
+

Symbols

+ + + +
+ +

_

+ + +
+ +

A

+ + + +
+ +

B

+ + + +
+ +

C

+ + + +
+ +

D

+ + + +
+ +

E

+ + + +
+ +

F

+ + + +
+ +

G

+ + + +
+ +

H

+ + + +
+ +

I

+ + + +
+ +

L

+ + + +
+ +

M

+ + + +
+ +

P

+ + + +
+ +

R

+ + + +
+ +

S

+ + + +
+ +

T

+ + + +
+ +

U

+ + + +
+ +

W

+ + + +
+ +

Y

+ + +
+ +

Z

+ + + +
+ + + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/get-started.html b/old_docs/_build/htmln/get-started.html new file mode 100644 index 000000000..56b4c3d86 --- /dev/null +++ b/old_docs/_build/htmln/get-started.html @@ -0,0 +1,216 @@ + + + + + + + + + Getting started — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Getting started

+

Make sure you have both pip and at +least version 3.7 of Python before starting. ASAB uses the new async/await +syntax, so earlier versions of python won’t work.

+
    +
  1. Install ASAB:

  2. +
+
$ pip3 install asab
+
+
+
    +
  1. Create a file called main.py with the following code:

  2. +
+
#!/usr/bin/env python3
+import asab
+
+class MyApplication(asab.Application):
+    async def main(self):
+        print("Hello world")
+
+if __name__ == '__main__':
+    app = MyApplication()
+    app.run()
+
+
+
    +
  1. Run the server:

  2. +
+
$ python3 main.py
+Hello world
+
+
+

You are now successfully runinng an ASAB application server.

+
    +
  1. Stop the application by Control-C.

  2. +
+

Note: The ASAB is designed around a so-called event loop. +It is meant primarily for server architectures. +For that reason, it doesn’t terminate and continue running and serving eventual requests.

+
+

Going into details

+
#!/usr/bin/env python3
+
+
+

ASAB application uses a Python 3.7+. +This is specified a by hashbang line at the very begginig of the file, on the line number 1.

+
import asab
+
+
+

ASAB is included from as asab module via an import statement.

+
class MyApplication(asab.Application):
+
+
+

Every ASAB Application needs to have an application object. +It is a singleton; it means that the application must create and operate precisely one instance of the application. +ASAB provides the base Application class that you need to inherit from to implement your custom application class.

+
async def main(self):
+    print("Hello world")
+
+
+

The Application.main() method is one of the application lifecycle methods, that you can override to implement desired application functionality. +The main method is a coroutine, so that you can await any tasks etc. in fully asynchronous way. +This method is called when ASAB application is executed and initialized. +The lifecycle stage is called “runtime”.

+

In this example, we just print a message to a screen.

+
if __name__ == '__main__':
+    app = MyApplication()
+    app.run()
+
+
+

This part of the code is executed when the Python program is launched. +It creates the application object and executes the Application.run() method. +This is a standard way of how ASAB application is started.

+
+
+

Next steps

+

Check out tutorials about how to build ASAB based web server.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/index.html b/old_docs/_build/htmln/index.html new file mode 100644 index 000000000..21fbd74d6 --- /dev/null +++ b/old_docs/_build/htmln/index.html @@ -0,0 +1,357 @@ + + + + + + + + + Asynchronous Server Application Boilerplate’s documentation — ASAB documentation + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Asynchronous Server Application Boilerplate’s documentation

+

Asynchronous Server App Boilerplate (or ASAB for short) is a microservice platform for Python 3.7+ and asyncio. +ASAB aims to minimize the amount of code that needs to be written when building a microservice or an application server. +ASAB is fully asynchronous using async/await syntax from Python 3, making your code modern, non-blocking, speedy and hence scalable. +We make every effort to build ASAB container-friendly so that you can deploy ASAB-based microservice via Docker or Kubernetes in a breeze.

+

ASAB is free and open-source software, available under BSD licence. +It means that anyone is freely licenced to use, copy, study, and change the software in any way, and the source code is openly shared so that people could voluntarily improve the design of the software. +Anyone can (and is encouraged to) use ASAB in his or her projects, for free. +A current maintainer is a TeskaLabs Ltd company.

+

ASAB is developed on GitHub. +Contributions are welcome!

+
+

ASAB is designed to be powerful yet simple

+

Here is a complete example of a fully working microservice:

+
import asab
+
+class MyApplication(asab.Application):
+    async def main(self):
+        print("Hello world!")
+        self.stop()
+
+if __name__ == "__main__":
+    app = MyApplication()
+    app.run()
+
+
+
+
+

ASAB is the right choice when

+
+
    +
  • using Python 3.7+.

  • +
  • building the microservice or the application server.

  • +
  • utilizing asynchronous I/O (aka asyncio).

  • +
+
+ + + + +
+
+
+

Indices and tables

+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/objects.inv b/old_docs/_build/htmln/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..052344e628f7adef382197d4a60e49546061f58f GIT binary patch literal 2225 zcmV;i2u}ASAX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkGQ$a!s zBOq2~a&u{KZaN?eBOp|0Wgv28ZDDC{WMy(7Z)PBLXlZjGW@&6?AZc?TV{dJ6a%FRK zWn>_Ab7^j8AbM?M4HU zFoiKmZ~)MWvg&K}_4*{mjTA(JH;^ld1pW`;!8sss2tdI;Smt?xLckEty!`lUm;g$> z3lH$JSKw3@99Wus|AXf*Kur}~K^hX2mxKr~Fb=T(ir5NAP^bZ81nmn3$02So&L_xk zaa1IbP9SWG{kGU!0eP{f#lAzkh2#Z=lbYY{P=?rUClD!Q2ON#lgDBdi(g?1EkU+rT z4v@G=Va9ejAQTc;+7rq^g1$NTCWdTBm04X8!k}nUCsKeiSFJRkuqJgSkixlf%B=@^ zQ0_tFMuFiP*qhG`KF>R1kZF9L5J;orCsK47q@v~ufnOTLtLdpjj}j_%(B)T zpa~+#e@C^ar?C21`Zi&Gsgj%`suku8)H7*V0r3U-m{55gqecHzz0f1x1k10DLP5 zp&{V3P7J@Zd+=GE#(mT@9lvzBrmm9lXC; zu70!b#>aAgU(bM9{k8l&1LpdEy`F<}yS!e1ept>xx?f+-KzaQ5>0u5t|FyokxqF-e z1k;=ycQl#-^(6ldjiheMgLP9qjznO_r_UXg#XGqn8A_D#eg9$g_Tuv0=s+#SKfil3 zlX&bX@n<9`q`@+d35;bDVug#$){V02P=Ls{Sa#ndDUXO9u8tWuHS-qMC~>C&zGZQELn5m%}F)0D6aPoCi3s}ejbEaL9H3rqi=&VxCf zw}WvR4%1Nw)7i)1hP=Fd8>#QrH@KbFNO5Vl4r}R!!z1=Q*Yt-O_XL)?yT6H(sD)~q z+554Es)bvd`1_Gc&_c7!?ES=(sE;~f3|kqsHp{d@+uYpWQcbD(d4xhXGJhyF!3Gk_ zI}bB>KslI7?y`bYM++0WDrPv+TS0C zLd2J3GIG46CU_{71BS*>1c>tOF(3>Mjt^5UvbeyO*Y1~25Zb=f+jU>yzM9t_;l9m- zd9_z4i{MwQoKoZ1i=@aqP89vSOHmXh@C#6r%2SakU+W=RQpGErF@Q45*qjx&ycFLNT1Sd(WNpFeC-)sGA-Qr9s1c3!`u_zT~U z08DWv=1Iz;U&A!QdFg;rin3QBPE(LYe!>-sTh;L+NjShHcMu<>_!%XMgZNpBsmzc$ z$f=Zb2j64r^58E*AC4D_A?8+d(;Xaj&yKppQAZthFK#;X{FONT^<5KFUnHFd5|G%h z18U3zf0;lLLnw{GC}+%DgHD^r9-iscD}up;VZ2DS0ZGDWMFB#6o$ zY6Qyo-axMp&h)xKi9e|eQ>adSL`|VCP(ppNP=|CAzT7<%RCo0g%L;n&zo;MVZ7OSr zem!FV7RHgIhR`^PHN{cIL_M?oKE?A z>g3zP2!Td*BQm^=I@s%1d6I>BQnVp8PmrEFfZn?|6~><4(|Le}xjStr%w4PZhptpG zlpuEWbBHY=DA=Lta#e|T1X(FHOd~3Um{6-y6lkv_m{R|aAU;nF{< zElz`Qz9I7dE-x3M8CO1mPg0tIJxpwI$hT(akr=7u>5hr)X;XTZ7}a%sSyyLWJ&|@@ z#4tMKz6&5>`evvW0tfP{y0p}JQ_vn=0;_+$kSR0I+g4F{0(_t}MMJZlBT zdE~yWZTO&TS$S{zcyG!O6e&@Uy9$p*JuQ7f>`?jtqVnyQA!sBQPTv1Nl0CEYc8)qr literal 0 HcmV?d00001 diff --git a/old_docs/_build/htmln/py-modindex.html b/old_docs/_build/htmln/py-modindex.html new file mode 100644 index 000000000..2256a093d --- /dev/null +++ b/old_docs/_build/htmln/py-modindex.html @@ -0,0 +1,179 @@ + + + + + + + + Python Module Index — ASAB documentation + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + +

Python Module Index

+ +
+ a +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
 
+ a
+ asab +
    + asab.abc +
    + asab.abc.singleton +
    + asab.log +
    + asab.pdict +
    + asab.socket +
    + asab.timer +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/search.html b/old_docs/_build/htmln/search.html new file mode 100644 index 000000000..4c037a5e6 --- /dev/null +++ b/old_docs/_build/htmln/search.html @@ -0,0 +1,153 @@ + + + + + + + + Search — ASAB documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + + +
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/searchindex.js b/old_docs/_build/htmln/searchindex.js new file mode 100644 index 000000000..dd4c484fd --- /dev/null +++ b/old_docs/_build/htmln/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["admin/command-line", "admin/containers", "admin/install", "admin/systemd", "asab/alert", "asab/application", "asab/config", "asab/index", "asab/library", "asab/log", "asab/metrics", "asab/module", "asab/pubsub", "asab/service", "asab/storage", "asab/various", "asab/web/authn", "asab/web/cors", "asab/web/index", "asab/web/restapidocs", "asab/zookeeper", "get-started", "index", "tutorial/web/chapter1", "tutorial/web/chapter2"], "filenames": ["admin/command-line.rst", "admin/containers.rst", "admin/install.rst", "admin/systemd.rst", "asab/alert.rst", "asab/application.rst", "asab/config.rst", "asab/index.rst", "asab/library.rst", "asab/log.rst", "asab/metrics.rst", "asab/module.rst", "asab/pubsub.rst", "asab/service.rst", "asab/storage.rst", "asab/various.rst", "asab/web/authn.rst", "asab/web/cors.rst", "asab/web/index.rst", "asab/web/restapidocs.rst", "asab/zookeeper.rst", "get-started.rst", "index.rst", "tutorial/web/chapter1.rst", "tutorial/web/chapter2.rst"], "titles": ["ASAB Command-line interface", "Containerisation", "Installation", "systemd", "Alert Service", "Application", "Configuration", "Asynchronous Server Application Boilerplate\u2019s documentation", "Library", "Logging", "Metrics", "Module", "Publish-Subscribe", "Service", "Storage", "Various utility classes", "Authn module", "Cross-Origin Resource Sharing (CORS)", "The web server", "REST API Docs", "Zookeeper", "Getting started", "Asynchronous Server Application Boilerplate\u2019s documentation", "Web Server Tutorial", "Create microservice with REST API"], "terms": {"base": [0, 1, 7, 9, 10, 12, 15, 16, 20, 21, 22], "applic": [0, 1, 3, 4, 6, 8, 9, 10, 11, 13, 14, 15, 18, 19, 20, 21, 23, 24], "provid": [0, 1, 5, 6, 9, 10, 11, 12, 14, 15, 16, 18, 20, 21, 22, 23, 24], "default": [0, 4, 5, 8, 9, 10, 11, 12, 14, 18, 22, 24], "here": [0, 7, 10, 19, 20, 22, 24], "i": [0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 23, 24], "an": [0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 18, 19, 21, 22, 24], "overview": 0, "common": [0, 15], "argument": [0, 4, 5, 6, 9, 10, 12, 14, 16, 20], "h": [0, 1, 6, 9], "help": [0, 5, 10, 24], "show": [0, 10, 19], "c": [0, 1, 5, 6, 8, 21, 24], "config": [0, 5, 6, 9, 11, 14, 15, 17, 18, 19, 20, 22, 24], "load": [0, 5, 11, 12, 15, 18, 20, 22], "file": [0, 1, 3, 8, 10, 12, 14, 15, 17, 19, 20, 21, 22, 23, 24], "from": [0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 18, 19, 21, 22, 24], "v": [0, 9, 15, 22], "verbos": [0, 22], "increas": [0, 5, 10, 12], "level": [0, 8, 10, 22], "debug": [0, 9, 15], "aka": [0, 5, 7, 8, 9, 22, 24], "more": [0, 4, 5, 6, 9, 10, 11, 12, 13, 19, 20, 24], "about": [0, 4, 5, 8, 9, 10, 20, 21, 24], "what": [0, 4, 6, 15, 19, 24], "happen": [0, 5, 12], "l": [0, 9, 15, 24], "log_fil": 0, "": [0, 1, 6, 9, 10, 14, 17, 19, 20, 24], "syslog": [0, 22], "python": [0, 1, 5, 6, 7, 9, 12, 15, 20, 21, 22, 24], "modul": [0, 6, 9, 10, 14, 15, 18, 20, 21, 22, 23, 24], "ha": [0, 2, 5, 9, 14, 15, 19, 20], "instal": [0, 1, 5, 18, 21, 22, 23, 24], "order": [0, 1, 2, 8, 12, 14, 16], "support": [0, 4, 6, 9, 10, 12, 14, 19], "daemonos": 0, "function": [0, 5, 9, 10, 12, 21, 23, 24], "pip3": [0, 1, 18, 21], "d": [0, 1, 6, 9, 10, 15, 24], "launch": [0, 1, 21], "background": [0, 9], "relat": [0, 1, 24], "section": [0, 6, 8, 9, 10, 17, 18, 24], "pidfil": 0, "var": [0, 9], "run": [0, 4, 7, 9, 10, 12, 14, 17, 18, 21, 22, 23, 24], "myapp": [0, 6, 9, 17], "pid": 0, "uid": 0, "nobodi": 0, "gid": 0, "working_dir": 0, "tmp": 0, "option": [0, 1, 5, 6, 8, 9, 10, 12, 14, 15, 17, 18, 24], "ar": [0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 22, 24], "k": [0, 15], "kill": [0, 24], "shutdown": 0, "start": [0, 1, 8, 15, 17, 18, 20, 22, 23, 24], "previous": 0, "design": [1, 5, 8, 15, 20, 21], "deploy": [1, 9], "It": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24], "allow": [1, 5, 6, 8, 10, 12, 16, 17, 24], "build": [1, 7, 21, 22, 24], "e": [1, 6, 9, 11, 12, 13, 15, 24], "g": [1, 6, 9, 11, 12, 13], "microservic": [1, 7, 8, 20, 22], "rest": [1, 16, 22, 23], "interfac": [1, 8, 15, 18, 22, 24], "consum": [1, 10, 12], "mq": 1, "messag": [1, 5, 9, 16, 21, 22], "while": [1, 12, 14, 24], "being": 1, "deploi": [1, 7, 8, 22], "sake": 1, "infrastructur": 1, "flexibl": 1, "prepar": 1, "alpin": 1, "linux": [1, 9], "imag": [1, 24], "3": [1, 5, 6, 7, 8, 9, 15, 20, 21, 22, 24], "10": [1, 8, 9, 10, 12], "swich": 1, "exec": 1, "bin": [1, 18, 21, 23, 24], "ash": 1, "python3": [1, 18, 21, 23, 24], "environ": [1, 9, 12, 22], "apk": 1, "updat": [1, 8, 15], "upgrad": 1, "add": [1, 4, 5, 10, 12, 14, 18, 19, 23, 24], "cach": [1, 8], "m": [1, 6, 9], "ensurepip": 1, "virtual": [1, 10], "buildenv": 1, "dev": [1, 9], "gcc": 1, "musl": 1, "git": [1, 2], "http": [1, 2, 4, 6, 8, 14, 15, 16, 18, 19, 22, 23, 24], "github": [1, 6, 7, 10, 15, 16, 22], "com": [1, 2, 4, 6, 10, 15, 16, 24], "teskalab": [1, 2, 6, 7, 10, 16, 22], "del": 1, "depend": [1, 5, 9, 14, 16], "daemon": [1, 3, 22], "us": [1, 3, 5, 6, 7, 8, 10, 12, 13, 14, 15, 16, 19, 20, 21, 22, 24], "openrc": 1, "automat": [1, 5, 10, 15, 19, 22, 24], "stop": [1, 5, 7, 12, 15, 21, 22], "vi": [1, 3], "etc": [1, 3, 6, 9, 12, 20, 21], "init": [1, 10, 12, 24], "app": [1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 22, 23], "adjust": [1, 3, 5, 24], "exampl": [1, 3, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 17, 18, 19, 21, 22, 24], "chmod": 1, "x": 1, "rc": 1, "note": [1, 2, 5, 10, 12, 15, 21], "If": [1, 5, 6, 8, 10, 12, 14, 15, 19, 24], "you": [1, 4, 5, 6, 7, 10, 12, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24], "need": [1, 4, 5, 6, 7, 8, 10, 19, 21, 22, 24], "packag": 1, "requir": [1, 10, 16, 19], "compil": 1, "have": [1, 6, 8, 14, 16, 18, 19, 21], "follow": [1, 2, 6, 8, 9, 10, 14, 15, 16, 18, 20, 21, 24], "And": [1, 6, 11], "remov": [1, 6, 8, 9, 15], "tool": [1, 4, 10], "after": [1, 3, 8, 10, 12, 14, 15, 19], "pip": [1, 21, 22, 24], "In": [1, 4, 8, 9, 10, 12, 14, 15, 16, 17, 20, 21, 22], "read": [1, 8, 14, 19, 22, 24], "name": [1, 5, 6, 8, 9, 10, 12, 13, 14, 17, 24], "well": [1, 9], "other": [1, 10, 12, 14, 15, 16, 18, 22, 24], "inform": [1, 8, 9, 10, 16, 20], "log": [1, 6, 10, 12, 22, 24], "metric": [1, 22], "analysi": [1, 10], "must": [1, 8, 10, 12, 14, 15, 17, 20, 21, 23], "enabl": [1, 3, 4, 8, 9, 24], "To": [1, 2, 3, 8, 10, 12, 14, 16, 23, 24], "do": [1, 4, 14, 15, 24], "so": [1, 6, 7, 9, 12, 21, 22, 24], "open": [1, 7, 22, 24], "servic": [1, 3, 11, 14, 15, 19, 20], "lib": [1, 15], "systemd": [1, 22], "system": [1, 3, 4, 5, 9, 20, 24], "find": [1, 10, 14], "line": [1, 6, 9, 19, 21, 22, 24], "which": [1, 5, 6, 9, 10, 12, 14, 15, 16, 19, 20, 24], "execstart": 1, "tcp": [1, 9], "0": [1, 9, 10, 14, 15, 16, 18, 24], "2375": 1, "save": [1, 9, 24], "reload": [1, 3, 8], "restart": [1, 15], "sudo": [1, 3], "systemctl": [1, 3], "Then": 1, "configur": [1, 4, 9, 10, 11, 12, 14, 17, 22, 24], "socket": [1, 9, 22], "path": [1, 6, 9, 15, 20, 22, 23], "docker_socket": 1, "gener": [1, 4, 6, 12, 14, 15, 19, 24], "your_docker_socket_fil": 1, "thu": [1, 10, 16], "manag": [1, 4, 8, 11, 13, 20], "can": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24], "hostnam": [1, 6, 9, 10], "instead": [1, 16, 20], "id": [1, 4, 10, 16, 22, 24], "better": 1, "readabl": 1, "when": [1, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 21, 24], "analyz": 1, "typic": [1, 5, 9, 11, 13, 20, 24], "influxdb": [1, 22], "grafana": 1, "distribut": [2, 20], "via": [2, 5, 6, 7, 9, 12, 14, 16, 21, 22], "pypi": 2, "thi": [2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 23, 24], "recommend": [2, 11, 12, 14, 15, 22], "method": [2, 5, 6, 8, 10, 12, 14, 15, 16, 19, 20, 21, 23, 24], "master": [2, 10, 16], "branch": [2, 8], "repositori": 2, "command": [2, 6, 9, 10, 22, 24], "successfuli": 2, "complet": [2, 5, 7, 20, 22], "creat": [3, 4, 5, 8, 9, 10, 12, 13, 14, 15, 17, 18, 20, 21, 22, 23], "new": [3, 4, 5, 9, 10, 14, 21, 24], "unit": [3, 6, 8, 9, 10, 15], "let": [3, 24], "know": [3, 15, 24], "exist": [3, 6, 14, 19, 24], "chang": [3, 7, 10, 12, 22], "now": [3, 10, 14, 21, 23], "readi": [3, 8, 12, 20], "integr": [4, 9, 18], "asab": [4, 5, 6, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24], "There": [4, 5, 6, 8, 10, 12], "current": [4, 5, 6, 7, 10, 14, 16, 22], "two": [4, 6, 10, 12, 14, 24], "possibl": [4, 9], "target": [4, 9, 22], "avail": [4, 6, 7, 16, 18, 19, 22, 23], "www": [4, 6, 14, 24], "atlassian": 4, "softwar": [4, 7, 15, 22], "event": [4, 8, 9, 10, 12, 15, 20, 21, 22], "everyth": [4, 24], "import": [4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 18, 20, 21, 22, 23, 24], "trigger": [4, 9, 15], "specifi": [4, 5, 6, 8, 9, 10, 14, 16, 17, 18, 20, 21], "class": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 19, 20, 21, 22, 23, 24], "myapplic": [4, 5, 7, 8, 10, 14, 18, 20, 21, 22], "async": [4, 5, 7, 8, 10, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24], "def": [4, 5, 7, 8, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24], "initi": [4, 5, 6, 8, 11, 12, 13, 14, 15, 19, 20, 21, 22, 24], "self": [4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], "alertservic": 4, "sourc": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 18, 20, 22], "my": [4, 18], "tenant": [4, 8], "alert_cl": 4, "alert_id": 4, "dedupl": 4, "id01": 4, "titl": 4, "someth": [4, 24], "went": 4, "wrong": 4, "detail": [4, 5, 9, 11, 13, 24], "example1": 4, "addit": [4, 6, 9, 14, 24], "info": [4, 9], "example2": 4, "__name__": [4, 5, 7, 9, 10, 18, 21, 22, 23, 24], "__main__": [4, 5, 7, 10, 18, 21, 22, 23, 24], "account": [4, 8], "your": [4, 5, 6, 7, 10, 12, 14, 17, 21, 22, 24], "team": 4, "choos": [4, 24], "api": [4, 6, 10, 14, 22], "kei": [4, 6, 10, 14, 15, 16, 18, 20, 24], "conf": [4, 6], "api_kei": 4, "tag": [4, 19, 22], "url": [4, 8, 9, 10, 14, 22], "eu": 4, "valu": [4, 5, 9, 14, 15, 17, 18, 20, 22, 24], "develop": [4, 7, 10, 22], "access": [4, 6, 8, 10, 14, 15, 16, 17, 20, 23], "directori": [4, 6, 8, 20], "folder": [4, 8, 9], "v2": [4, 10], "integration_kei": 4, "serv": [4, 6, 16, 21], "third": 4, "parti": 4, "group": 4, "prevent": [4, 14], "nois": 4, "doc": [4, 14, 22, 24], "intellig": 4, "The": [5, 6, 8, 9, 10, 12, 14, 15, 16, 19, 20, 21, 22, 24], "maintain": [5, 7, 22], "global": [5, 8, 10], "state": [5, 8, 10, 20], "own": [5, 10, 12, 14], "implement": [5, 6, 9, 10, 12, 15, 16, 18, 20, 21, 24], "subclass": 5, "should": [5, 10, 12, 14, 19, 24], "onli": [5, 6, 8, 9, 10, 12, 15, 16, 24], "one": [5, 6, 8, 10, 11, 12, 15, 18, 21, 24], "object": [5, 6, 8, 9, 10, 11, 12, 13, 15, 21, 22, 24], "process": [5, 12, 24], "pass": 5, "direct": [5, 14], "asyncio": [5, 7, 9, 12, 14, 15, 22], "ensure_futur": [5, 12], "my_coro": 5, "around": [5, 21], "invers": 5, "control": [5, 8, 12, 17, 21], "principl": 5, "mean": [5, 6, 7, 8, 9, 10, 12, 14, 21, 22, 23], "custom": [5, 9, 10, 21], "written": [5, 7, 12, 22], "code": [5, 6, 7, 10, 12, 16, 18, 20, 21, 22, 24], "receiv": [5, 12, 16], "flow": 5, "callback": [5, 12], "handler": [5, 9, 15, 16, 18, 23], "modular": 5, "make": [5, 7, 18, 19, 21, 22, 24], "extens": [5, 8, 9], "divid": [5, 10], "phase": 5, "__init__": [5, 8, 11, 12, 13, 18, 20, 23], "dure": [5, 6, 10, 11, 13], "constructor": 5, "call": [5, 6, 11, 12, 13, 14, 15, 19, 20, 21, 24], "publish": [5, 22], "subscrib": [5, 8, 20, 22], "execut": [5, 14, 20, 21, 23, 24], "asynchron": [5, 20, 21, 24], "overriden": [5, 11, 13], "user": [5, 6, 10, 11, 13, 16, 24], "module_sampl": 5, "add_modul": [5, 10, 11, 14, 18, 20, 24], "enter": [5, 12, 24], "where": [5, 12, 14, 20, 24], "spend": 5, "most": [5, 10], "begin": [5, 24], "return": [5, 6, 8, 9, 10, 12, 14, 15, 16, 17, 18, 20, 23, 24], "exitcod": 5, "main": [5, 6, 7, 14, 21, 22], "without": [5, 6, 8, 10, 12, 20, 24], "server": [5, 6, 8, 9, 15, 16, 20, 21, 24], "forev": 5, "behaviour": 5, "print": [5, 7, 8, 12, 20, 21, 22], "hello": [5, 7, 9, 18, 21, 22, 23], "world": [5, 7, 9, 19, 21, 22, 23], "exit_cod": 5, "int": [5, 6, 10, 15], "none": [5, 6, 8, 9, 10, 12, 14, 15, 19, 20, 24], "gracefulli": 5, "termin": [5, 9, 10, 12, 21], "commenc": 5, "sigint": 5, "sigterm": 5, "also": [5, 6, 8, 9, 10, 12, 14, 16, 19, 20, 24], "includ": [5, 8, 9, 10, 16, 21, 22], "respons": [5, 8, 16, 17, 18, 24], "ctrl": 5, "unix": [5, 6, 9, 12], "like": [5, 6, 8, 10, 14, 19, 20], "3x": 5, "abruptli": 5, "emerg": 5, "abort": 5, "paramet": [5, 6, 8, 10, 14, 15, 18, 19], "see": [5, 10, 11, 13, 16, 20], "chapter": 5, "win32api": 5, "abord": 5, "properli": [5, 14], "window": [5, 6, 8], "final": [5, 11, 13, 15, 24], "set_exit_cod": 5, "forc": [5, 16], "bool": [5, 9, 10], "fals": [5, 8, 9, 10, 15, 24], "set": [5, 6, 8, 9, 10, 12, 14, 19, 24], "o": [5, 6, 7, 8, 9, 10, 22], "document": [5, 10, 14, 19, 24], "previou": 5, "lower": 5, "than": 5, "true": [5, 8, 9, 10, 12, 14, 15, 20, 24], "disregard": 5, "actual": [5, 9, 12, 24], "handl": [5, 14, 23, 24], "sy": 5, "For": [5, 6, 10, 11, 14, 19, 21, 24], "module_class": 5, "instanti": [5, 15, 24], "my_modul": 5, "mymodul": [5, 9, 11], "A": [5, 6, 7, 8, 9, 10, 13, 15, 20, 22, 23], "list": [5, 6, 8, 10, 12, 14], "been": 5, "ad": [5, 8, 9, 10, 19], "each": [5, 8, 9, 12, 13, 15, 20], "identifi": [5, 13], "its": [5, 10, 13, 14, 16], "uniqu": 5, "get_servic": [5, 10, 13, 14, 18, 20, 24], "service_nam": [5, 8, 10, 13, 15, 24], "locat": [5, 8, 9, 13, 18, 24], "svc": [5, 18], "service_sampl": 5, "dictionari": [5, 6, 9, 10, 14, 22], "regist": [5, 11, 13, 14, 16, 24], "create_argument_pars": 5, "prog": 5, "usag": [5, 6, 10, 12, 15], "descript": [5, 19], "epilog": 5, "prefix_char": 5, "fromfile_prefix_char": 5, "argument_default": 5, "conflict_handl": 5, "error": [5, 6, 9, 10, 24], "add_help": 5, "argpars": 5, "argumentpars": 5, "overload": 5, "pleas": [5, 8, 16, 24], "refer": [5, 6, 13, 14], "standard": [5, 6, 9, 10, 12, 21], "librari": [5, 6, 9, 10, 14, 20, 22, 24], "parse_arg": 5, "attribut": [5, 9, 14], "text": [5, 9, 10, 18], "displai": [5, 9], "expect": [5, 6, 9], "empti": [5, 8, 9], "string": [5, 6, 8, 9, 10, 12, 24], "float": [5, 6, 10, 15], "second": [5, 9, 10, 12, 15, 22], "sinc": [5, 9, 14], "epoch": 5, "point": [5, 9], "number": [5, 8, 9, 10, 21, 24], "specif": [5, 8, 10, 16, 20, 22, 24], "date": [5, 9], "leap": 5, "platform": [5, 7, 22], "On": 5, "januari": 5, "1": [5, 6, 8, 9, 10, 12, 20, 21, 24], "1970": 5, "00": [5, 12], "count": [5, 10], "toward": 5, "commonli": 5, "could": [5, 7, 9, 22], "expens": 5, "cheaper": 5, "version": [5, 12, 14, 21, 24], "wall": 5, "singleton": [6, 21, 22], "ani": [6, 7, 8, 10, 12, 20, 21, 22, 24], "place": [6, 24], "explicit": 6, "initialis": 6, "henc": [6, 7, 22], "anywher": [6, 24], "my_conf_valu": 6, "section_nam": 6, "key1": [6, 9], "inherit": [6, 10, 21, 24], "basic": [6, 16, 24], "languag": 6, "structur": [6, 22, 24], "similar": [6, 9, 20], "found": [6, 8, 10, 14], "microsoft": 6, "ini": 6, "bitbucket": 6, "org": [6, 10, 24], "hg": 6, "topsecret": [6, 19], "port": [6, 15, 24], "50022": 6, "forwardx11": 6, "how": [6, 10, 11, 13, 14, 16, 20, 21], "line1": 6, "line2": 6, "line3": 6, "another_kei": 6, "foo": [6, 10, 11, 14, 15], "initiali": 6, "time": [6, 9, 10, 11, 12, 13, 15, 22, 24], "asab_config": 6, "2": [6, 8, 9, 10, 14, 15, 16, 20], "config_fil": 6, "sample_app": 6, "py": [6, 10, 11, 15, 16, 21, 23], "sampl": 6, "merg": [6, 8], "done": [6, 10, 12, 14], "multipl": [6, 12, 18, 20], "separ": [6, 9], "pathsep": 6, "glob": 6, "wildcard": 6, "charact": [6, 10], "expand": [6, 20, 24], "mai": [6, 9], "situat": 6, "silent": 6, "ignor": 6, "site": 6, "add_default": [6, 11, 14, 24], "extend": [6, 11], "key2": [6, 9], "anoth": [6, 16, 24], "other_sect": 6, "key3": 6, "simpl": [6, 10, 12, 15, 18, 23, 24], "type": [6, 8, 12, 15, 22, 24], "don": [6, 12, 24], "t": [6, 10, 12, 15, 20, 21, 24], "complex": 6, "becaus": [6, 12, 19], "imposs": 6, "persistent_dir": 6, "home": 6, "special": [6, 8], "this_dir": 6, "contain": [6, 7, 8, 10, 16, 17, 18, 22, 24], "util": [6, 7, 9, 16, 22], "my_fil": 6, "txt": 6, "f": [6, 9, 15], "secur": [6, 16, 19], "store": [6, 10, 15, 20, 22, 23, 24], "shown": 6, "publicli": 6, "endpoint": [6, 16, 17, 19, 22, 23], "output": [6, 9, 16], "conveni": 6, "thei": [6, 10], "repeat": [6, 15], "mani": [6, 12], "connect": [6, 8, 9, 10, 20, 24], "kafkaconnect": 6, "kafka_password": 6, "my_secret_password": 6, "getsecond": 6, "differ": [6, 9, 10, 12, 14], "sleep": [6, 12], "sleep_tim": 6, "5": [6, 9, 10, 12], "another_sleep_tim": 6, "10d": 6, "y": [6, 9], "year": 6, "month": 6, "w": 6, "week": 6, "dai": [6, 9], "hour": [6, 9], "minut": [6, 9, 10], "milisecond": 6, "achiev": 6, "wai": [6, 7, 9, 12, 15, 20, 21, 22], "sleeptim": 6, "anothersleeptim": 6, "geturl": 6, "scheme": 6, "str": [6, 8, 10, 14], "tupl": [6, 12], "take": [6, 8, 10, 14, 19, 24], "lead": [6, 10], "trail": 6, "whitespac": 6, "backslash": 6, "mongodb": [6, 22], "valid": [6, 24], "get": [6, 15, 22, 23, 24], "bypass": 6, "same": [6, 9, 14], "rais": [6, 14], "would": 6, "short": [7, 22], "7": [7, 9, 12, 21, 22], "aim": [7, 22], "minim": [7, 10, 22], "amount": [7, 22], "fulli": [7, 8, 9, 21, 22], "await": [7, 8, 12, 14, 15, 20, 21, 22, 24], "syntax": [7, 21, 22], "modern": [7, 22], "non": [7, 9, 14, 22], "block": [7, 14, 22], "speedi": [7, 22], "scalabl": [7, 22], "we": [7, 9, 12, 14, 21, 22, 24], "everi": [7, 9, 10, 12, 16, 21, 22], "effort": [7, 22], "friendli": [7, 22], "docker": [7, 22, 24], "kubernet": [7, 22], "breez": [7, 22], "free": [7, 22], "under": [7, 22], "bsd": [7, 9, 22], "licenc": [7, 22], "anyon": [7, 22], "freeli": [7, 22], "copi": [7, 22], "studi": [7, 22], "openli": [7, 22], "share": [7, 8, 10, 22], "peopl": [7, 22], "voluntarili": [7, 22], "improv": [7, 22], "encourag": [7, 22], "hi": [7, 22], "her": [7, 22], "project": [7, 22], "ltd": [7, 22], "compani": [7, 22], "contribut": [7, 22], "welcom": [7, 22], "work": [7, 8, 12, 14, 15, 21, 22, 24], "concept": 8, "data": [8, 10, 16, 20, 22, 23, 24], "content": [8, 11, 15, 17], "across": 8, "cluster": 8, "notifi": 8, "eg": [8, 9], "autom": [8, 9], "companion": 8, "edit": 8, "howev": [8, 10], "oper": [8, 9, 12, 14, 20, 21, 24], "organ": [8, 10], "simplifi": [8, 12, 23], "manner": [8, 10, 20], "folder1": 8, "item1": 8, "yaml": [8, 10], "item2": 8, "json": [8, 9, 10, 24], "folder2": 8, "item3": 8, "folder2folder2": 8, "item4": 8, "root": 8, "end": [8, 10, 12], "item": [8, 10, 15], "libraryservic": 8, "abstrat": 8, "unifi": [8, 9], "resourc": [8, 19, 22], "cloud": 8, "architectur": [8, 21], "imper": 8, "all": [8, 9, 10, 12, 14, 19, 20, 24], "technologi": [8, 16], "built": [8, 9, 10, 24], "top": [8, 9, 19, 24], "bring": 8, "stack": [8, 10], "variou": [8, 12, 22], "view": 8, "overlai": 8, "space": [8, 9, 12], "prioriti": 8, "down": [8, 10], "uri": 8, "schema": [8, 24], "zk": 8, "local": 8, "first": [8, 12, 14, 16, 19, 24], "disabl": [8, 9, 10], "visibl": [8, 9], "present": [8, 10, 15], "consid": 8, "itself": [8, 10, 12], "becom": [8, 19], "indic": [8, 9, 24], "pubsub": [8, 20, 22], "asablibrari": 8, "super": [8, 11, 13, 18, 23, 24], "on_library_readi": 8, "event_nam": [8, 20], "n": [8, 18, 23], "recurs": 8, "itemio": 8, "byte": 8, "format": [8, 9, 10, 12, 15, 16], "len": 8, "els": [8, 24], "io": 8, "libraryitem": 8, "directli": [8, 12, 14, 20], "appli": [8, 10], "assum": 8, "stream": [8, 9], "libari": 8, "entri": [8, 9, 10, 20, 22], "evalu": [8, 16], "xxxxx": 8, "subdirectori": 8, "export": 8, "remove_path": 8, "gzip": 8, "tar": 8, "archiv": 8, "param": 8, "absolut": [8, 20], "backend": 8, "filesystemlibraryprovid": 8, "set_readi": 8, "zookeeperlibraryprovid": 8, "variant": [8, 10], "2181": [8, 20], "case": [8, 10, 15, 20], "4": [8, 9], "join": 8, "miss": [8, 20], "ex": 8, "bsqueryapp": 8, "azurestorag": 8, "azurestoragelibraryprovid": 8, "blob": [8, 10, 15, 16], "core": 8, "net": 8, "public": [8, 16], "polici": 8, "permiss": 8, "signatur": 8, "sa": 8, "queri": 8, "sv": 8, "2020": 8, "02": 8, "si": 8, "xxxx": 8, "sr": 8, "sig": 8, "xxxxxxxxxxxxxx": 8, "unlimmit": 8, "repres": [8, 10, 15, 20], "stderr": 9, "both": [9, 10, 12, 21], "rfc5424": 9, "rfc3164": 9, "timestamp": 9, "captur": 9, "sub": [9, 10], "precis": [9, 21], "capabl": 9, "microsecond": 9, "part": [9, 16, 21, 24], "logger": 9, "necessari": [9, 16], "altern": [9, 12], "strategi": 9, "getlogg": [9, 24], "warn": [9, 10, 15, 24], "25": 9, "mar": 9, "2018": 9, "23": 9, "33": 9, "58": 9, "044595": 9, "log_notic": 9, "even": [9, 10], "regardless": 9, "numer": [9, 10], "sever": [9, 10, 24], "critic": [9, 10], "50": 9, "crit": 9, "40": 9, "err": 9, "30": [9, 12], "notic": [9, 19], "20": [9, 24], "6": [9, 24], "notset": 9, "module1": 9, "module2": 9, "customlogg": 9, "correspond": 9, "avaiabl": 9, "boolean": [9, 15], "rfc": 9, "5424": 9, "seriaz": 9, "struct_data": 9, "value1": 9, "sd": 9, "asctim": 9, "levelnam": 9, "datefmt": 9, "b": 9, "backup_count": 9, "rotate_everi": 9, "1d": 9, "instanc": [9, 10, 12, 13, 16, 20, 21, 24], "variabl": [9, 15, 22], "seper": 9, "intend": 9, "behavior": 9, "race": 9, "condit": 9, "occur": 9, "detect": 9, "foreground": 9, "respect": [9, 10, 24], "isatti": 9, "asabforceconsol": 9, "setup": [9, 12], "pycharm": 9, "signal": [9, 12], "sighup": [9, 12], "logrot": 9, "rotatingfilehandl": 9, "old": 9, "kept": 9, "prior": 9, "append": [9, 16, 24], "filenam": 9, "interv": [9, 15], "integ": [9, 10], "30m": 9, "known": 9, "desir": [9, 21, 24], "address": [9, 24], "lan": 9, "1554": 9, "equival": [9, 12], "switch": 9, "spefici": 9, "3164": 9, "mac": 9, "osx": 9, "flavour": 9, "compat": 9, "over": [9, 20], "udp": 9, "sendto": 9, "datagram": 9, "prove": 9, "essenti": 9, "go": [9, 10, 14, 16, 24], "offer": [9, 10, 12, 18], "particular": [9, 14], "mark": [9, 10, 12], "thru": 9, "Such": 9, "grep": 9, "uniformli": 9, "eol": 9, "yyyi": 9, "mm": [9, 12], "dd": 9, "plan": 9, "hint": 9, "suggest": [9, 24], "ahead": 9, "seek": 9, "logobsolet": 9, "2022": 9, "31": 9, "12": 9, "21": 9, "jul": 9, "14": 9, "32": 9, "983884": 9, "asynciohandl": 9, "loop": [9, 10, 12, 21, 22], "famili": 9, "sock_typ": 9, "facil": 9, "17": 9, "sockethandl": 9, "queue": 9, "decoupl": 9, "network": 9, "driven": 9, "mechan": 9, "emit": [9, 12], "record": [9, 14, 24], "macosxsyslogformatt": 9, "fmt": 9, "style": 9, "sd_id": 9, "structureddataformatt": 9, "16": 9, "use_color": 9, "formatt": 9, "render": 9, "black": 9, "blue": 9, "cyan": 9, "green": [9, 19], "magenta": 9, "red": 9, "white": 9, "yellow": 9, "empty_sd": 9, "formattim": 9, "creation": [9, 23], "logrecord": 9, "render_struct_data": 9, "syslogrfc3164formatt": 9, "legaci": 9, "syslogrfc5424formatt": 9, "timescal": 10, "further": [10, 16, 24], "seri": 10, "databas": [10, 22, 24], "influx": 10, "metricsservic": 10, "counter": [10, 12], "mycount": 10, "create_count": 10, "bar": [10, 11, 14, 15], "init_valu": 10, "v1": 10, "full": [10, 14, 16, 18], "gaug": 10, "singl": 10, "up": [10, 19, 24], "cumul": 10, "whose": 10, "decreas": 10, "per": 10, "epscount": 10, "delta": 10, "dutycycl": 10, "en": [10, 14, 24], "wikipedia": 10, "wiki": 10, "duty_cycl": 10, "aggregationcount": 10, "aggreg": 10, "max": 10, "histogram": 10, "come": [10, 16, 24], "never": 10, "alwai": [10, 19], "through": [10, 14], "metri": 10, "meant": [10, 21], "runtim": [10, 21], "period": [10, 12], "collect": [10, 14, 24], "send": [10, 12], "them": [10, 12, 14, 24], "select": [10, 16], "60": [10, 12], "lifetim": 10, "gather": 10, "reset": 10, "affect": 10, "natur": 10, "though": 10, "monoton": 10, "give": 10, "long": 10, "term": 10, "observ": 10, "probabl": 10, "monitor": 10, "resett": 10, "flush": 10, "cycl": 10, "caus": 10, "delai": [10, 15], "propag": 10, "were": 10, "untouch": 10, "last": [10, 12], "occas": 10, "pair": [10, 14], "won": [10, 21], "anymor": 10, "some": [10, 15, 19, 24], "carri": [10, 12], "expir": 10, "defin": [10, 12, 16, 24], "might": 10, "spot": 10, "mysteri": 10, "disappear": 10, "unus": 10, "confiur": 10, "localhost": [10, 14, 18, 19, 23], "8086": 10, "bucket": 10, "my_bucket": 10, "my_org": 10, "token": [8, 10, 16, 19], "my_token": 10, "destin": 10, "write": [10, 19, 24], "orgid": 10, "preced": [10, 20], "authent": 10, "8": [10, 15, 20], "usernam": [8, 10, 14], "password": [8, 10, 14, 18, 22, 24], "pull": [10, 24], "model": 10, "apiservic": [10, 19], "openmetr": 10, "scrape_interv": 10, "15": 10, "scrape_timeout": 10, "evaluation_interv": 10, "scrape_config": 10, "job_nam": 10, "metrics_exampl": 10, "metrics_path": 10, "static_config": 10, "127": [10, 24], "8080": [10, 18, 19, 23, 24], "satisfi": 10, "instruct": 10, "below": [10, 17, 20, 24], "fit": [10, 24], "regex": 10, "za": 10, "z": 10, "z0": 10, "9_": 10, "replac": 10, "underscor": 10, "strip": 10, "These": [10, 24], "proce": 10, "NOT": 10, "total": 10, "metadata": 10, "intern": [10, 24], "primari": 10, "purpos": 10, "watch_metr": 10, "tabl": 10, "filter": 10, "hide": 10, "watch": 10, "curl": [10, 18], "web_requests_duration_max": 10, "push": 10, "digest": 10, "post": [10, 24], "sent": [10, 12], "bodi": [10, 24], "consumer_exampl": 10, "webservic": [10, 17, 18, 24], "quantifi": 10, "web_request": 10, "web_requests_dur": 10, "durat": 10, "web_requests_duration_min": 10, "maximum": 10, "web_requests_duration_hist": 10, "opt": 10, "out": [10, 12, 21, 24], "native_metr": 10, "memori": [10, 22], "stat": 10, "vmpeak": 10, "peak": 10, "size": 10, "vmlck": 10, "lock": [10, 14], "vmpin": 10, "pin": 10, "vmhwm": 10, "resid": 10, "high": 10, "water": 10, "vmrss": 10, "vmdata": 10, "vmstk": 10, "vmex": 10, "segment": 10, "vmlib": 10, "vmpte": 10, "page": [10, 22], "vmpmd": 10, "vmswap": 10, "swap": 10, "anonym": 10, "privat": [10, 16], "shmem": 10, "humbl": 10, "health": 10, "create_gaug": 10, "metric_nam": 10, "dynamic_tag": 10, "counterwithdynamictag": 10, "create_eps_count": 10, "create_duty_cycl": 10, "create_aggregation_count": 10, "aggregationcounterwithdynamictag": 10, "create_histogram": 10, "histogramwithdynamictag": 10, "subtract": 10, "between": [10, 20, 24], "measur": 10, "effect": 10, "produc": 10, "ep": 10, "lastreadystateswitch": 10, "track": 10, "recent": 10, "result": [10, 24], "value_nam": 10, "metricwithdynamictag": 10, "registri": [11, 13, 22], "myservic": [11, 13], "exit": [11, 12, 13, 24], "pattern": [12, 15, 17], "sender": 12, "bu": 12, "interact": 12, "similarli": 12, "express": 12, "interest": 12, "knowledg": 12, "explam": 12, "distinguish": 12, "tick": 12, "600": 12, "posit": 12, "keyword": 12, "deliveri": 12, "enjoi": 12, "isol": 12, "message_typ": 12, "deliv": 12, "callabl": 12, "coroutin": [12, 14, 15, 21, 23, 24], "futur": [12, 15], "myclass": [12, 15], "on_tick": 12, "abov": [12, 14, 23, 24], "subscribe_al": 12, "obj": [12, 14], "decor": [12, 22, 24], "followin": 12, "on_exit": 12, "unsubscrib": 12, "fifo": 12, "basi": 12, "skip": 12, "wait": [12, 24], "three": [12, 14], "member": 12, "arg": [12, 16], "kwarg": [12, 16], "my_coroutin": 12, "break": 12, "asynchon": 12, "statement": [12, 21], "my_funct": 12, "mymessag": 12, "request": [12, 14, 16, 17, 18, 19, 21, 22, 23, 24], "immediatelli": 12, "mode": [12, 22], "moreov": 12, "deal": 12, "doe": [12, 15, 19, 20, 24], "vice": 12, "versa": 12, "sync": 12, "immedi": 12, "call_soon": 12, "thing": [12, 24], "almost": 12, "construct": 12, "want": [12, 19, 24], "grace": 12, "300": 12, "1800": 12, "3600": 12, "43200": 12, "86400": 12, "frequenc": 12, "tick_period": 12, "10th": 12, "hup": 12, "housekeep": 12, "03": 12, "am": 12, "utc": [12, 22], "housekeeping_tim": 12, "19": 12, "pm": 12, "hh": 12, "remind": 12, "yourself": [12, 24], "care": 12, "timezon": 12, "skeleton": 13, "service_method": 13, "mysvc": 13, "my_servic": 13, "dedic": 14, "manual": [14, 24], "inmemori": 14, "pymongo": [14, 24], "motor": [14, 24], "elasticsearch": 14, "aiohttp": [14, 18, 24], "although": 14, "simpli": [14, 24], "storageservic": [14, 24], "pointer": 14, "u": [14, 24], "test": [14, 15, 18], "associ": 14, "obj_id": [14, 24], "procedur": 14, "commit": 14, "object_id": 14, "custom_data": 14, "event_typ": 14, "webhook": 14, "object_cr": 14, "keyerror": [14, 24], "rememb": 14, "except": [14, 24], "crash": 14, "get_bi": 14, "obtain": [14, 16, 20, 22], "_v": [14, 24], "strongli": [14, 24], "That": [14, 19], "soft": 14, "compon": 14, "meanwhil": 14, "fail": [14, 24], "retri": 14, "whole": 14, "deleted_id": 14, "inmemorycollect": 14, "pprint": 14, "indent": 14, "driver": 14, "mongodb_uri": [14, 24], "27017": [14, 24], "mongodb_databas": [14, 24], "asabdb": 14, "dict": [14, 15], "motor_asyncio": 14, "asynciomotorcollect": 14, "mongo": [14, 24], "coll": [], "cursor": 14, "fetch_next": 14, "next_object": 14, "suitabl": 14, "describ": [14, 24], "offici": 14, "todo": [14, 18], "elasticsearch_url": 14, "9200": 14, "elasticsearch_usernam": 14, "johndo": 14, "elasticsearch_password": 14, "lorem_ipsum_dolor": 14, "sit_amet": 14, "2023": 14, "refresh": 14, "scroll_timeout": 14, "1m": 14, "generateid": 14, "abc": 15, "abstract": [15, 24], "restrict": 15, "idea": 15, "borrow": 15, "question": 15, "stackoverflow": 15, "classmethod": 15, "delet": 15, "singleton_cl": 15, "intent": 15, "shouldn": 15, "unless": 15, "realli": 15, "One": 15, "iter": 15, "metaclass": 15, "pdict": 15, "persistentdict": 15, "regular": 15, "cat": 15, "think": 15, "optim": 15, "frequent": 15, "explicitli": 15, "serializ": 15, "kwd": 15, "map": 15, "lack": 15, "either": [8, 15, 24], "inspir": 15, "cpython": 15, "_collections_abc": 15, "persistentst": 15, "setdefault": 15, "autorestart": 15, "rel": [15, 20], "given": 15, "coro": 15, "task": [15, 20, 21], "is_start": 15, "otherwis": [15, 24], "timeout": [14, 15], "streamsocketserverservic": 15, "servicemyprotocolserv": 15, "host": 15, "getint": 15, "create_serv": 15, "myprotocol": 15, "protocol": 15, "addr": 15, "web": [16, 17, 19, 21, 22, 24], "author": [16, 22], "forward": 16, "oauthforward": 16, "oauth": [16, 19], "auth": [16, 19], "authn_middleware_factori": 16, "step": 16, "ident": 16, "relev": 16, "prefix": 16, "client": [16, 20], "header": [16, 17], "bearer": [16, 19], "access_token": 16, "illustr": [16, 20], "insid": [16, 18], "webapp": [16, 18, 24], "oauth2client": 16, "basicauth": 16, "pubkeyauth": 16, "githuboauthmethod": 16, "authn_required_handl": 16, "just": [16, 21, 24], "authn_optional_handl": 16, "enforc": 16, "json_respons": [16, 23, 24], "our": 16, "try": [16, 24], "link": 16, "demonstr": 16, "ssl": [16, 18], "cert": [16, 18], "pubkei": 16, "webcontain": [17, 18, 24], "cors_preflight_path": [17, 18], "shall": 17, "pre": 17, "flight": 17, "befor": [18, 21], "sure": [18, 21], "usr": [18, 21, 23, 24], "env": [18, 21, 23, 24], "websvc": 18, "listen": [18, 24], "rout": [18, 23], "router": [18, 24], "add_get": [18, 23, 24], "tl": 18, "8443": 18, "inlin": 18, "backlog": 18, "rootdir": 18, "servertoken": 18, "cor": [18, 22], "parameret": 18, "cafil": 18, "capath": 18, "cipher": 18, "dh_param": 18, "verify_mod": 18, "cert_non": 18, "cert_opt": 18, "cert_requir": 18, "check_hostnam": 18, "servicewebsess": 18, "session_middlewar": 18, "storag": [18, 22, 24], "summari": 19, "openidconnect": 19, "introduc": 19, "initialize_web": 19, "docstr": 19, "look": [19, 20], "mymicroservic": 19, "tutorialapp": [19, 24], "best": 19, "marque": 19, "html": [14, 19, 24], "seacat": 19, "scope": 19, "put": [19, 24], "matter": 19, "But": 19, "authz": 19, "top_secret_endpoint": 19, "secret": [19, 24], "coolestmicroservic": 19, "button": 19, "appear": 19, "authorizationurl": 19, "tokenurl": 19, "apach": 20, "coordin": 20, "hierarch": 20, "znode": 20, "tree": 20, "synchron": [20, 22], "stateless": 20, "reli": 20, "zookeeperservic": 20, "zookeepercontain": 20, "_on_zk_readi": 20, "zookeeper_servic": 20, "config_section_nam": 20, "partial": 20, "doesn": [20, 21], "myfold": 20, "file1": 20, "substitut": 20, "zookep": 20, "zookeeper_path": 20, "is_connect": 20, "check": [20, 21, 24], "get_children": 20, "get_data": 20, "encod": 20, "utf": 20, "get_raw_data": 20, "complic": 20, "proactorservic": 20, "write_to_zk": 20, "sequenc": 20, "ephemer": 20, "makepath": 20, "least": 21, "earlier": 21, "successfulli": 21, "runinng": 21, "primarili": 21, "reason": 21, "continu": 21, "eventu": 21, "hashbang": 21, "veri": 21, "begginig": 21, "lifecycl": [21, 22], "overrid": 21, "stage": 21, "screen": 21, "program": [21, 24], "tutori": [21, 22, 24], "session": 22, "swagger": 22, "authn": 22, "middlewar": [22, 24], "cross": 22, "origin": [22, 24], "interpret": 22, "dynam": 22, "prometheu": 22, "nativ": 22, "manipul": 22, "elast": 22, "search": 22, "encrypt": 22, "decrypt": 22, "alert": 22, "opsgeni": 22, "pagerduti": 22, "de": 22, "duplic": 22, "parser": 22, "configpars": 22, "multilin": 22, "configr": 22, "consol": 22, "obsolet": 22, "featur": 22, "subscript": 22, "wide": 22, "persist": 22, "timer": 22, "zookeep": 22, "zookeeep": 22, "advertis": 22, "kazoo": 22, "rule": 22, "notif": 22, "layer": 22, "easy_instal": 22, "containeris": 22, "lxc": 22, "lxd": 22, "remot": [8, 22], "index": [22, 24], "mywebappl": 23, "create_web_serv": 23, "declar": 23, "With": 24, "word": 24, "crud": 24, "later": 24, "boilerpl": 24, "cover": 24, "score": 24, "good": 24, "ones": 24, "onlin": 24, "troubl": 24, "re": 24, "familiar": 24, "yet": 24, "great": 24, "opportun": 24, "consist": 24, "discuss": 24, "bottom": 24, "hub": 24, "_": 24, "forget": 24, "p": 24, "mongo_initdb_root_usernam": 24, "mongo_initdb_root_password": 24, "download": 24, "fairli": 24, "straightforward": 24, "shebang": 24, "tell": 24, "next": 24, "mongous": 24, "mongopassword": 24, "mongoipaddress": 24, "mongodatabas": 24, "credenti": 24, "usual": 24, "commandlin": 24, "learn": 24, "littl": 24, "jsonexceptionmiddlewar": 24, "crudwebhandl": 24, "crudservic": 24, "__all__": 24, "transform": 24, "perspect": 24, "translat": 24, "No": 24, "busi": 24, "logic": 24, "straight": 24, "awai": 24, "haven": 24, "As": 24, "mongo_svc": 24, "web_app": 24, "add_put": 24, "json_schema_handl": 24, "properti": 24, "_id": 24, "field1": 24, "field2": 24, "field3": 24, "json_data": 24, "match_info": 24, "ok": 24, "accept": 24, "incom": 24, "appropri": 24, "input": 24, "webserv": 24, "visit": 24, "stabl": 24, "mention": 24, "inner": 24, "lightweight": 24, "power": 24, "mongodbstorageservic": 24, "pop": 24, "cre": 24, "upsertor": 24, "zip": 24, "duplicateerror": 24, "alreadi": 24, "implicitli": 24, "movi": 24, "insert": 24, "5555": 24, "44424": 24, "200": 24, "statu": 24, "troubleshoot": 24, "modulenotfounderror": 24, "mongo_replica_set_cli": 24, "oserror": 24, "errno": 24, "98": 24, "attempt": 24, "bind": 24, "8081": 24, "congratul": 24, "oh": 24, "r": 24, "ask": 24, "challeng": 24, "Or": 24, "add_delet": 24, "co": 14, "guid": 14, "scroll": 14, "gitlibraryprovid": 8, "clone": 8, "temporari": 8, "filesystemprovid": 8, "deploytoken": 8, "publickei": 8, "privatekei": 8, "ssh": 8, "johnsmith": 8, "secretpassword": 8, "repodir": 8}, "objects": {"asab": [[5, 0, 1, "", "Application"], [6, 1, 1, "", "Config"], [11, 0, 1, "", "Module"], [12, 0, 1, "", "PubSub"], [13, 0, 1, "", "Service"], [12, 0, 1, "", "Subscriber"], [15, 4, 0, "-", "abc"], [9, 4, 0, "-", "log"], [15, 4, 0, "-", "pdict"], [15, 4, 0, "-", "socket"], [15, 4, 0, "-", "timer"]], "asab.Application": [[5, 1, 1, "", "Description"], [5, 2, 1, "", "ExitCode"], [5, 2, 1, "", "Loop"], [5, 2, 1, "", "Modules"], [12, 2, 1, "", "PubSub"], [5, 2, 1, "", "Services"], [5, 3, 1, "", "__init__"], [5, 3, 1, "", "add_module"], [5, 3, 1, "", "create_argument_parser"], [5, 3, 1, "", "finalize"], [5, 3, 1, "", "get_service"], [5, 3, 1, "", "initialize"], [5, 3, 1, "", "main"], [5, 3, 1, "", "parse_args"], [5, 3, 1, "", "run"], [5, 3, 1, "", "set_exit_code"], [5, 3, 1, "", "stop"], [5, 3, 1, "", "time"]], "asab.Config": [[6, 3, 1, "", "add_defaults"], [6, 3, 1, "", "getseconds"], [6, 3, 1, "", "geturl"]], "asab.Module": [[11, 3, 1, "", "finalize"], [11, 3, 1, "", "initialize"]], "asab.PubSub": [[12, 3, 1, "", "publish"], [12, 3, 1, "", "subscribe"], [12, 3, 1, "", "subscribe_all"], [12, 3, 1, "", "unsubscribe"]], "asab.Service": [[13, 1, 1, "", "App"], [13, 1, 1, "", "Name"], [13, 3, 1, "", "finalize"], [13, 3, 1, "", "initialize"]], "asab.Subscriber": [[12, 3, 1, "", "message"], [12, 3, 1, "", "subscribe"]], "asab.abc": [[15, 0, 1, "", "Module"], [15, 0, 1, "", "Service"], [15, 0, 1, "", "Singleton"], [15, 4, 0, "-", "singleton"]], "asab.abc.Module": [[15, 3, 1, "", "finalize"], [15, 3, 1, "", "initialize"]], "asab.abc.Service": [[15, 3, 1, "", "finalize"], [15, 3, 1, "", "initialize"]], "asab.abc.Singleton": [[15, 3, 1, "", "delete"]], "asab.abc.singleton": [[15, 0, 1, "", "Singleton"]], "asab.abc.singleton.Singleton": [[15, 3, 1, "", "delete"]], "asab.config": [[6, 0, 1, "", "ConfigParser"]], "asab.library": [[8, 0, 1, "", "LibraryService"]], "asab.library.LibraryService": [[8, 3, 1, "", "export"], [8, 3, 1, "", "list"], [8, 3, 1, "", "read"], [8, 3, 1, "", "subscribe"]], "asab.library.providers.azurestorage": [[8, 0, 1, "", "AzureStorageLibraryProvider"]], "asab.library.providers.filesystem": [[8, 0, 1, "", "FileSystemLibraryProvider"]], "asab.library.providers.git": [[8, 0, 1, "", "GitLibraryProvider"]], "asab.library.providers.zookeeper": [[8, 0, 1, "", "ZooKeeperLibraryProvider"]], "asab.log": [[9, 0, 1, "", "AsyncIOHandler"], [9, 0, 1, "", "Logging"], [9, 0, 1, "", "MacOSXSyslogFormatter"], [9, 0, 1, "", "StructuredDataFormatter"], [9, 0, 1, "", "SyslogRFC3164Formatter"], [9, 0, 1, "", "SyslogRFC5424Formatter"]], "asab.log.AsyncIOHandler": [[9, 3, 1, "", "emit"]], "asab.log.Logging": [[9, 3, 1, "", "rotate"]], "asab.log.StructuredDataFormatter": [[9, 2, 1, "", "BLACK"], [9, 2, 1, "", "BLUE"], [9, 2, 1, "", "CYAN"], [9, 2, 1, "", "GREEN"], [9, 2, 1, "", "MAGENTA"], [9, 2, 1, "", "RED"], [9, 2, 1, "", "WHITE"], [9, 2, 1, "", "YELLOW"], [9, 2, 1, "", "empty_sd"], [9, 3, 1, "", "format"], [9, 3, 1, "", "formatTime"], [9, 3, 1, "", "render_struct_data"]], "asab.log.SyslogRFC5424Formatter": [[9, 2, 1, "", "empty_sd"]], "asab.metrics": [[10, 0, 1, "", "AggregationCounter"], [10, 0, 1, "", "AggregationCounterWithDynamicTags"], [10, 0, 1, "", "Counter"], [10, 0, 1, "", "CounterWithDynamicTags"], [10, 0, 1, "", "DutyCycle"], [10, 0, 1, "", "EPSCounter"], [10, 0, 1, "", "Gauge"], [10, 0, 1, "", "Histogram"], [10, 0, 1, "", "HistogramWithDynamicTags"], [10, 0, 1, "", "MetricsService"]], "asab.metrics.AggregationCounter": [[10, 3, 1, "", "set"]], "asab.metrics.AggregationCounterWithDynamicTags": [[10, 3, 1, "", "set"]], "asab.metrics.Counter": [[10, 3, 1, "", "add"], [10, 3, 1, "", "sub"]], "asab.metrics.CounterWithDynamicTags": [[10, 3, 1, "", "add"], [10, 3, 1, "", "sub"]], "asab.metrics.Gauge": [[10, 3, 1, "", "set"]], "asab.metrics.Histogram": [[10, 3, 1, "", "set"]], "asab.metrics.HistogramWithDynamicTags": [[10, 3, 1, "", "set"]], "asab.metrics.MetricsService": [[10, 3, 1, "", "create_aggregation_counter"], [10, 3, 1, "", "create_counter"], [10, 3, 1, "", "create_duty_cycle"], [10, 3, 1, "", "create_eps_counter"], [10, 3, 1, "", "create_gauge"], [10, 3, 1, "", "create_histogram"]], "asab.pdict": [[15, 0, 1, "", "PersistentDict"]], "asab.pdict.PersistentDict": [[15, 3, 1, "", "load"], [15, 3, 1, "", "store"], [15, 3, 1, "", "update"]], "asab.socket": [[15, 0, 1, "", "StreamSocketServerService"]], "asab.socket.StreamSocketServerService": [[15, 3, 1, "", "create_server"], [15, 3, 1, "", "finalize"]], "asab.storage.StorageService": [[14, 3, 1, "", "collection"], [14, 3, 1, "", "get_by"]], "asab.timer": [[15, 0, 1, "", "Timer"]], "asab.timer.Timer": [[15, 3, 1, "", "is_started"], [15, 3, 1, "", "restart"], [15, 3, 1, "", "start"], [15, 3, 1, "", "stop"]], "asab.web.service": [[18, 0, 1, "", "WebService"]], "asab.web.session": [[18, 0, 1, "", "ServiceWebSession"], [18, 5, 1, "", "session_middleware"]], "asab.zookeeper": [[20, 0, 1, "", "ZooKeeperContainer"]], "asab.zookeeper.ZooKeeperContainer": [[20, 3, 1, "", "advertise"], [20, 3, 1, "", "get_children"], [20, 3, 1, "", "get_data"], [20, 3, 1, "", "get_raw_data"], [20, 3, 1, "", "is_connected"]], "": [[0, 6, 1, "cmdoption-d", "--daemonize"], [0, 6, 1, "cmdoption-h", "--help"], [0, 6, 1, "cmdoption-k", "--kill"], [0, 6, 1, "cmdoption-s", "--syslog"], [0, 6, 1, "cmdoption-v", "--verbose"], [0, 6, 1, "cmdoption-c", "-c"], [0, 6, 1, "cmdoption-d", "-d"], [0, 6, 1, "cmdoption-h", "-h"], [0, 6, 1, "cmdoption-k", "-k"], [0, 6, 1, "cmdoption-l", "-l"], [0, 6, 1, "cmdoption-s", "-s"], [0, 6, 1, "cmdoption-v", "-v"]], "Application": [[12, 6, 1, "cmdoption-arg-Application.exit", "exit!"], [12, 6, 1, "cmdoption-arg-Application.housekeeping", "housekeeping!"], [12, 6, 1, "cmdoption-arg-Application.hup", "hup!"], [12, 6, 1, "cmdoption-arg-Application.init", "init!"], [12, 6, 1, "cmdoption-arg-Application.run", "run!"], [12, 6, 1, "cmdoption-arg-Application.stop", "stop!"], [12, 6, 1, "cmdoption-arg-Application.tick", "tick!"], [12, 6, 1, "cmdoption-arg-Application.tick-10", "tick/10!"], [12, 6, 1, "cmdoption-arg-Application.tick-1800", "tick/1800!"], [12, 6, 1, "cmdoption-arg-Application.tick-300", "tick/300!"], [12, 6, 1, "cmdoption-arg-Application.tick-3600", "tick/3600!"], [12, 6, 1, "cmdoption-arg-Application.tick-43200", "tick/43200!"], [12, 6, 1, "cmdoption-arg-Application.tick-60", "tick/60!"], [12, 6, 1, "cmdoption-arg-Application.tick-600", "tick/600!"], [12, 6, 1, "cmdoption-arg-Application.tick-86400", "tick/86400!"]]}, "objtypes": {"0": "py:class", "1": "py:data", "2": "py:attribute", "3": "py:method", "4": "py:module", "5": "py:function", "6": "std:cmdoption"}, "objnames": {"0": ["py", "class", "Python class"], "1": ["py", "data", "Python data"], "2": ["py", "attribute", "Python attribute"], "3": ["py", "method", "Python method"], "4": ["py", "module", "Python module"], "5": ["py", "function", "Python function"], "6": ["std", "cmdoption", "program option"]}, "titleterms": {"asab": [0, 1, 2, 3, 7, 10, 22], "command": [0, 5], "line": [0, 5], "interfac": 0, "configur": [0, 6, 8, 18, 19, 20], "log": [0, 9], "daemon": 0, "containeris": 1, "lxc": 1, "lxd": 1, "contain": [1, 20], "docker": 1, "remot": 1, "api": [1, 19, 24], "instal": 2, "us": [2, 9], "pip": 2, "easy_instal": 2, "github": 2, "systemd": 3, "start": [3, 21], "server": [3, 7, 18, 22, 23], "stop": 3, "alert": 4, "servic": [4, 5, 8, 10, 13, 18, 22, 24], "opsgeni": 4, "pagerduti": 4, "de": 4, "duplic": 4, "applic": [5, 7, 12, 22], "event": 5, "loop": 5, "lifecycl": [5, 11, 13], "init": 5, "time": 5, "run": 5, "exit": 5, "modul": [5, 11, 16], "registri": 5, "parser": 5, "utc": 5, "base": 6, "configpars": 6, "multilin": 6, "entri": 6, "automat": 6, "load": 6, "includ": 6, "other": 6, "file": [6, 9], "default": 6, "valu": [6, 10], "environ": [6, 20], "variabl": [6, 20], "configr": 6, "password": 6, "obtain": 6, "second": 6, "url": [6, 20], "asynchron": [7, 12, 22], "boilerpl": [7, 22], "": [7, 22], "document": [7, 22], "i": [7, 22], "design": [7, 22], "power": [7, 22], "yet": [7, 22], "simpl": [7, 22], "right": [7, 22], "choic": [7, 22], "when": [7, 22], "librari": 8, "structur": [8, 9, 11], "path": 8, "rule": 8, "notif": 8, "chang": 8, "provid": 8, "filesystem": 8, "apach": 8, "zookeep": [8, 20], "microsoft": 8, "azur": 8, "storag": [8, 14], "git": 8, "repositori": 8, "layer": 8, "recommend": 9, "level": 9, "verbos": 9, "mode": 9, "data": [9, 14], "consol": 9, "rotat": 9, "syslog": 9, "obsolet": 9, "featur": 9, "refer": [9, 10, 22], "metric": 10, "type": [10, 14, 20], "interpret": 10, "initi": 10, "dynam": 10, "tag": 10, "influxdb": 10, "prometheu": 10, "endpoint": 10, "http": 10, "target": 10, "web": [10, 18, 23], "request": 10, "nativ": 10, "publish": 12, "subscrib": 12, "subscript": 12, "synchron": 12, "v": 12, "messag": 12, "wide": 12, "pubsub": 12, "well": 12, "known": 12, "specif": 14, "manipul": 14, "databas": 14, "upsertor": 14, "insert": 14, "an": 14, "object": 14, "get": [14, 21], "singl": 14, "updat": [14, 24], "delet": [14, 24], "store": 14, "memori": 14, "mongodb": [14, 24], "elast": 14, "search": 14, "encrypt": 14, "decrypt": 14, "id": 14, "variou": 15, "util": 15, "class": 15, "singleton": 15, "persist": 15, "dictionari": 15, "timer": 15, "socket": 15, "authn": 16, "middlewar": 16, "decor": 16, "exampl": [16, 20], "cross": 17, "origin": 17, "resourc": 17, "share": 17, "cor": 17, "The": [18, 23], "session": 18, "rest": [19, 24], "doc": 19, "In": 19, "your": 19, "microservic": [19, 24], "author": 19, "swagger": 19, "section": 20, "zookeeper_serv": 20, "support": 20, "z_path": 20, "read": 20, "from": 20, "zookeeep": 20, "advertis": 20, "kazoo": 20, "go": 21, "detail": 21, "next": 21, "step": 21, "introduct": 22, "administr": 22, "indic": 22, "tabl": 22, "tutori": 23, "code": 23, "deeper": 23, "look": 23, "creat": 24, "prerequisit": 24, "compon": 24, "postman": 24, "myrestapi": 24, "py": 24, "app": 24, "__init__": 24, "handler": 24, "now": 24, "test": 24}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2, "sphinx.ext.viewcode": 1, "sphinx.ext.intersphinx": 1, "sphinx": 57}, "alltitles": {"ASAB Command-line interface": [[0, "asab-command-line-interface"]], "Configuration": [[0, "configuration"], [6, "configuration"], [18, "configuration"], [19, "configuration"]], "Logging": [[0, "logging"], [9, "logging"]], "Daemon": [[0, "daemon"]], "Containerisation": [[1, "containerisation"]], "ASAB in a LXC/LXD container": [[1, "asab-in-a-lxc-lxd-container"]], "Docker Remote API": [[1, "docker-remote-api"]], "Installation": [[2, "installation"]], "Install ASAB using pip": [[2, "install-asab-using-pip"]], "Install ASAB using easy_install": [[2, "install-asab-using-easy-install"]], "Install ASAB for a GitHub": [[2, "install-asab-for-a-github"]], "systemd": [[3, "systemd"]], "Start of ASAB Server": [[3, "start-of-asab-server"]], "Stop of ASAB Server": [[3, "stop-of-asab-server"]], "Alert Service": [[4, "alert-service"]], "Opsgenie": [[4, "opsgenie"]], "PagerDuty": [[4, "pagerduty"]], "De-duplication": [[4, "de-duplication"]], "Application": [[5, "application"]], "Event Loop": [[5, "event-loop"]], "Application Lifecycle": [[5, "application-lifecycle"]], "Init-time": [[5, "init-time"]], "Run-time": [[5, "run-time"]], "Exit-time": [[5, "exit-time"]], "Module registry": [[5, "module-registry"]], "Service registry": [[5, "service-registry"]], "Command-line parser": [[5, "command-line-parser"]], "UTC Time": [[5, "utc-time"]], "Based on ConfigParser": [[6, "based-on-configparser"]], "Multiline configuration entry": [[6, "multiline-configuration-entry"]], "Automatic load of configuration": [[6, "automatic-load-of-configuration"]], "Including other configuration files": [[6, "including-other-configuration-files"]], "Configuration default values": [[6, "configuration-default-values"]], "Environment variables in configration": [[6, "environment-variables-in-configration"]], "Passwords in configration": [[6, "passwords-in-configration"]], "Obtaining seconds": [[6, "obtaining-seconds"]], "Obtaining URLs": [[6, "obtaining-urls"]], "Asynchronous Server Application Boilerplate\u2019s documentation": [[7, "asynchronous-server-application-boilerplate-s-documentation"], [22, "asynchronous-server-application-boilerplate-s-documentation"]], "ASAB is designed to be powerful yet simple": [[7, "asab-is-designed-to-be-powerful-yet-simple"], [22, "asab-is-designed-to-be-powerful-yet-simple"]], "ASAB is the right choice when": [[7, "asab-is-the-right-choice-when"], [22, "asab-is-the-right-choice-when"]], "Recommended use": [[9, "recommended-use"]], "Logging Levels": [[9, "logging-levels"]], "Verbose mode": [[9, "verbose-mode"]], "Structured data": [[9, "structured-data"]], "Logging to file": [[9, "logging-to-file"]], "Logging to console": [[9, "logging-to-console"]], "Log rotation": [[9, "log-rotation"]], "Logging to syslog": [[9, "logging-to-syslog"]], "Logging of obsolete features": [[9, "logging-of-obsolete-features"]], "Reference": [[9, "module-asab.log"], [10, "reference"], [22, null]], "Metrics": [[10, "metrics"]], "Metrics Service": [[10, "metrics-service"]], "Types of Metrics": [[10, "types-of-metrics"]], "ASAB Metrics Interpretation": [[10, "asab-metrics-interpretation"]], "Initial Values": [[10, "initial-values"]], "Dynamic Tags": [[10, "dynamic-tags"]], "InfluxDB": [[10, "influxdb"]], "Prometheus": [[10, "id2"]], "Metrics Endpoints": [[10, "metrics-endpoints"]], "HTTP Target": [[10, "http-target"]], "Web Requests Metrics": [[10, "web-requests-metrics"]], "Native Metrics": [[10, "native-metrics"]], "Module": [[11, "module"]], "Structure": [[11, "structure"]], "Lifecycle": [[11, "lifecycle"], [13, "lifecycle"]], "Publish-Subscribe": [[12, "publish-subscribe"]], "Subscription": [[12, "subscription"]], "Publishing": [[12, "publishing"]], "Synchronous vs. asynchronous messaging": [[12, "synchronous-vs-asynchronous-messaging"]], "Application-wide PubSub": [[12, "application-wide-pubsub"]], "Well-Known Messages": [[12, "well-known-messages"]], "Service": [[13, "service"]], "Various utility classes": [[15, "module-asab.abc"]], "Singleton": [[15, "module-asab.abc.singleton"]], "Persistent dictionary": [[15, "module-asab.pdict"]], "Timer": [[15, "module-asab.timer"]], "Sockets": [[15, "module-asab.socket"]], "Authn module": [[16, "authn-module"]], "Middleware": [[16, "middleware"]], "Decorators": [[16, "decorators"]], "Example": [[16, "example"]], "Cross-Origin Resource Sharing (CORS)": [[17, "cross-origin-resource-sharing-cors"]], "The web server": [[18, "the-web-server"]], "Web Service": [[18, "web-service"]], "Sessions": [[18, "sessions"]], "REST API Docs": [[19, "rest-api-docs"]], "In your microservice": [[19, "in-your-microservice"]], "Authorization in Swagger": [[19, "authorization-in-swagger"]], "Zookeeper": [[20, "zookeeper"]], "Zookeeper container": [[20, "zookeeper-container"]], "Example of configuration section": [[20, "example-of-configuration-section"]], "Example of ZOOKEEPER_SERVER environment variable": [[20, "example-of-zookeeper-server-environment-variable"]], "Supported types of z_path URLs": [[20, "supported-types-of-z-path-urls"]], "Reading from Zookeeeper": [[20, "reading-from-zookeeeper"]], "Advertisement into Zookeeper": [[20, "advertisement-into-zookeeper"]], "Kazoo": [[20, "id1"]], "Getting started": [[21, "getting-started"]], "Going into details": [[21, "going-into-details"]], "Next steps": [[21, "next-steps"]], "Introduction": [[22, null]], "Services": [[22, null]], "Administration": [[22, null]], "Indices and tables": [[22, "indices-and-tables"]], "Web Server Tutorial": [[23, "web-server-tutorial"]], "The code": [[23, "the-code"]], "Deeper look": [[23, "deeper-look"]], "Create microservice with REST API": [[24, "create-microservice-with-rest-api"]], "Prerequisites": [[24, "prerequisites"]], "Components": [[24, "components"]], "MongoDB": [[24, "mongodb"]], "Postman": [[24, "postman"]], "myrestapi.py": [[24, "myrestapi-py"]], "app.py": [[24, "app-py"]], "__init__.py": [[24, "init-py"]], "handler.py": [[24, "handler-py"]], "service.py": [[24, "service-py"]], "Now test it!": [[24, "now-test-it"]], "Update and Delete": [[24, "update-and-delete"]], "Storage": [[14, "storage"]], "Specification of the storage type": [[14, "specification-of-the-storage-type"]], "Manipulation with databases": [[14, "manipulation-with-databases"]], "Upsertor": [[14, "upsertor"]], "Inserting an object": [[14, "inserting-an-object"]], "Getting a single object": [[14, "getting-a-single-object"]], "Updating an object": [[14, "updating-an-object"]], "Deleting an object": [[14, "deleting-an-object"]], "Storing data in memory": [[14, "storing-data-in-memory"]], "Storing data in MongoDB": [[14, "storing-data-in-mongodb"]], "Storing data in Elastic Search": [[14, "storing-data-in-elastic-search"]], "Encryption and decryption": [[14, "encryption-and-decryption"]], "Object ID": [[14, "object-id"]], "Library": [[8, "library"]], "Library structure": [[8, "library-structure"]], "Library path rules": [[8, "library-path-rules"]], "Library service": [[8, "library-service"]], "Notification of changes": [[8, "notification-of-changes"]], "Providers": [[8, "providers"]], "Filesystem": [[8, "filesystem"]], "Apache Zookeeper": [[8, "apache-zookeeper"]], "Microsoft Azure Storage": [[8, "microsoft-azure-storage"]], "Git repository": [[8, "git-repository"]], "Layers": [[8, "layers"]], "Library configuration": [[8, "library-configuration"]]}, "indexentries": {"azurestoragelibraryprovider (class in asab.library.providers.azurestorage)": [[8, "asab.library.providers.azurestorage.AzureStorageLibraryProvider"]], "filesystemlibraryprovider (class in asab.library.providers.filesystem)": [[8, "asab.library.providers.filesystem.FileSystemLibraryProvider"]], "gitlibraryprovider (class in asab.library.providers.git)": [[8, "asab.library.providers.git.GitLibraryProvider"]], "libraryservice (class in asab.library)": [[8, "asab.library.LibraryService"]], "zookeeperlibraryprovider (class in asab.library.providers.zookeeper)": [[8, "asab.library.providers.zookeeper.ZooKeeperLibraryProvider"]], "export() (asab.library.libraryservice method)": [[8, "asab.library.LibraryService.export"]], "list() (asab.library.libraryservice method)": [[8, "asab.library.LibraryService.list"]], "read() (asab.library.libraryservice method)": [[8, "asab.library.LibraryService.read"]], "subscribe() (asab.library.libraryservice method)": [[8, "asab.library.LibraryService.subscribe"]]}}) \ No newline at end of file diff --git a/old_docs/_build/htmln/tutorial/web/chapter1.html b/old_docs/_build/htmln/tutorial/web/chapter1.html new file mode 100644 index 000000000..e5f3be4d6 --- /dev/null +++ b/old_docs/_build/htmln/tutorial/web/chapter1.html @@ -0,0 +1,214 @@ + + + + + + + + + Web Server Tutorial — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Web Server Tutorial

+

Create a simple web server with ASAB.

+
+

The code

+
#!/usr/bin/env python3
+import asab.web.rest
+
+
+class MyWebApplication(asab.Application):
+
+    def __init__(self):
+        super().__init__()
+
+        # Create the Web server
+        web = asab.web.create_web_server(self)
+
+        # Add a route to the handler method
+        web.add_get('/hello', self.hello)
+
+    # This is the web request handler
+    async def hello(self, request):
+        return asab.web.rest.json_response(
+            request,
+            data="Hello, world!\n"
+        )
+
+
+if __name__ == '__main__':
+    app = MyWebApplication()
+    app.run()
+
+
+
+
To start the application, store above code in a file app.py.
+
Execute $ python3 ./app.py to run it.
+
+

The ASAB web server is now available at http://localhost:8080/.

+
+
+

Deeper look

+

ASAB Application

+
#!/usr/bin/env python3
+import asab.web.rest
+
+class MyWebApplication(asab.Application):
+
+    def __init__(self):
+        super().__init__()
+
+if __name__ == '__main__':
+    app = MyWebApplication()
+    app.run()
+
+
+

This is a ASAB code that declares the application class and runs it.

+

Create a Web server

+

The asab.web module provides a create_web_server() function that simplifies creation of the Web server in the ASAB application.

+
web = asab.web.create_web_server(self)
+
+
+

Install the handler

+
web.add_get('/hello', self.hello)
+
+...
+
+async def hello(self, request):
+    return asab.web.rest.json_response(
+        request,
+        data="Hello, world!\n"
+    )
+
+
+

The handler method hello() is installed at the web server at /hello endpoint. +HTTP method is GET.

+

It means that if you access the web server with a path /hello, it will be handled by a hello(...) method. A handler method must be a coroutine.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_build/htmln/tutorial/web/chapter2.html b/old_docs/_build/htmln/tutorial/web/chapter2.html new file mode 100644 index 000000000..7c8502b92 --- /dev/null +++ b/old_docs/_build/htmln/tutorial/web/chapter2.html @@ -0,0 +1,674 @@ + + + + + + + + + Create microservice with REST API — ASAB documentation + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Create microservice with REST API

+

With this tutorial, you will create a basic ASAB microservice that provides a REST HTTP API. +This microservice will implement Create, Read, Update and Delete functionality, in another words CRUD. +MongoDB will be used as the database.

+
+

Prerequisites

+
    +
  1. Python version 3.6 or later

  2. +
  3. Asynchronous Server App Boilerplate (ASAB) version 20.3 or later

  4. +
  5. MongoDB instance

  6. +
  7. Postman

  8. +
+
+

Note

+

We will use Docker to run MongoDB. Docker installation is not covered in this tutorial, but there are scores of good ones online should you run into any trouble. If you’re not familiar with Docker yet, it is a great opportunity to start (https://www.docker.com/get-started/).

+

Otherwise, you can install MongoDB following one of these tutorials: https://www.mongodb.com/docs/manual/installation/

+
+
+
+

Components

+

The microservice consists of several modules (aka Python files). +These modules are as follows (and also indicate the file structure) and will be discussed in more detail in the respective sections below, going from top to bottom:

+
.
+└── myrestapi.py
+─── myrestapi
+        └── __init__.py
+        ─── app.py
+        ─── tutorial
+                └── handler.py
+                └── service.py
+
+
+
+
+

MongoDB

+

To make things simple, let’s use a Docker image.

+

Pull this image: +https://hub.docker.com/_/mongo

+

You can simply use the command below to run it. +If you choose to run the instance without a password, +don’t forget to adjust the related asab.Config in ./myrestapi/app.py.

+
docker run -d -p 27017:27017 \
+        -e MONGO_INITDB_ROOT_USERNAME=user \
+        -e MONGO_INITDB_ROOT_PASSWORD=secret \
+        mongo
+
+
+
+
+

Postman

+

We use Postman to test the webservice REST API.

+

You can download it here: +https://www.postman.com/downloads/

+

The Postman is fairly straightforward to use. +You can create your collection of HTTP requests, save them, or automatically generate documentation.

+
+
+

myrestapi.py

+

This is where everything starts. +Begin with the shebang line, which tells the executing operating system python should execute this program.

+
#!/usr/bin/env python3
+
+
+

Imports follow. All you need here is the application. It is called TutorialApp:

+
from myrestapi import TutorialApp
+
+
+

Next, instantiate an application class TutorialApp in the __main__ of the application, and run it:

+
if __name__ == '__main__':
+        app = TutorialApp()
+        app.run()
+
+
+
+
+

app.py

+

./myrestapi/app.py

+

Define the application class TutorialApp.

+

Imports first:

+
import asab
+import asab.web
+import asab.web.rest
+import asab.storage
+
+
+

Add some default configuration:

+
asab.Config.add_defaults(
+{
+        'asab:storage': {
+                'type': 'mongodb',
+                'mongodb_uri': 'mongodb://mongouser:mongopassword@mongoipaddress:27017',
+                'mongodb_database': 'mongodatabase'
+        },
+})
+
+
+
+

Note

+

To make things more simple, Mongo credentials are stored here as a default configuration. +Usually, you provide your app with a configuration file using -c commandline option. +Learn more in section Configuration.

+
+

Next, describe the class, it inherits from the basic ASAB Application class, +but you need to expand it a little:

+
class TutorialApp(asab.Application):
+
+        def __init__(self):
+                super().__init__()
+                # Register modules
+                self.add_module(asab.web.Module)
+                self.add_module(asab.storage.Module)
+
+                # Locate the web service
+                self.WebService = self.get_service("asab.WebService")
+                self.WebContainer = asab.web.WebContainer(
+                        self.WebService, "web"
+                )
+                self.WebContainer.WebApp.middlewares.append(
+                        asab.web.rest.JsonExceptionMiddleware
+                )
+
+                # Initialize services
+                from .tutorial.handler import CRUDWebHandler
+                from .tutorial.service import CRUDService
+                self.CRUDService = CRUDService(self)
+                self.CRUDWebHandler = CRUDWebHandler(
+                        self, self.CRUDService
+                )
+
+
+
+
+

__init__.py

+

./myrestapi/__init__.py

+

Init file is needed so myrestapi will work as a module. +Just import the TutorialApp.

+
from .app import TutorialApp
+
+__all__ = [
+        "TutorialApp",
+]
+
+
+
+
+

handler.py

+

./myrestapi/tutorial/handler.py

+

The handler is where HTTP Rest calls are handled and transformed into the actual (internal) service calls. +From another perspective, the handler should contain only translation between REST calls and the service interface. +No actual ‘business logic’ should be here. +It is strongly suggested to build these CRUD methods one by one and test them straight away. +If you haven’t set up your database test instance yet, now is the time to do it.

+

As usual, we start by importing modules:

+
import asab
+import asab.web.rest
+
+
+

Let’s start with two methods - create and read which allow us to write into database and check the record.

+
class CRUDWebHandler(object):
+        def __init__(self, app, mongo_svc):
+                self.CRUDService = mongo_svc
+                web_app = app.WebContainer.WebApp
+                web_app.router.add_put(
+                        '/crud-myrestapi/{collection}',
+                        self.create
+                )
+                web_app.router.add_get(
+                        '/crud-myrestapi/{collection}/{id}',
+                        self.read
+                )
+
+
+        @asab.web.rest.json_schema_handler({
+                'type': 'object',
+                'properties': {
+                        '_id': {'type': 'string'},
+                        'field1': {'type': 'string'},
+                        'field2': {'type': 'number'},
+                        'field3': {'type': 'number'}
+                }})
+        async def create(self, request, *, json_data):
+                collection = request.match_info['collection']
+
+                result = await self.CRUDService.create(
+                        collection, json_data
+                )
+                if result:
+                        return asab.web.rest.json_response(
+                                request, {"result": "OK"}
+                        )
+                else:
+                        asab.web.rest.json_response(
+                                request, {"result": "FAILED"}
+                        )
+
+
+        async def read(self, request):
+                collection = request.match_info['collection']
+                key = request.match_info['id']
+                response = await self.CRUDService.read(
+                        collection, key
+                )
+                return asab.web.rest.json_response(
+                        request, response
+                )
+
+
+

The handler only accepts the incoming requests and returns appropriate responses. +All of the “logic”, be it the specifics of the database connection, additional validations and other +operations take place in the CRUDService.

+

POST and PUT requests typically come with data in their body. +Providing your WebContainer with JsonExceptionMiddleware enables you to validate a JSON input using @asab.web.rest.json_schema_handler decorator and JSON schema (https://json-schema.org/).

+
+

Note

+

ASAB WebServer is built on top of the aiohttp library. +For further details please visit https://docs.aiohttp.org/en/stable/index.html.

+
+
+
+

service.py

+

./myrestapi/tutorial/service.py

+

As mentioned above, this is where the inner workings of the microservice request processing are. +Let’s start as usual, by importing the desired modules:

+
import asab
+import asab.storage.exceptions
+
+
+

We want to start logging in here:

+
import logging
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+

Now define the CRUDService class which inherits from the asab.Service class.

+
+

Note

+

asab.Service is a lightweight yet powerful abstract class providing your object with 3 functionalities:

+
    +
  • Name of the asab.Service is registered in the app and can be called from the app object anywhere in your code.

  • +
  • asab.Service class implements initialize() and finalize() coroutines which help you to handle asynchronous operations in init and exit time of your application.

  • +
  • asab.Service registers application object as self.App for you.

  • +
+
+
class CRUDService(asab.Service):
+
+        def __init__(self, app, service_name='crud.CRUDService'):
+                super().__init__(app, service_name)
+                self.MongoDBStorageService = app.get_service(
+                        "asab.StorageService"
+                )
+
+        async def create(self, collection, json_data):
+                obj_id = json_data.pop("_id")
+
+                cre = self.MongoDBStorageService.upsertor(
+                        collection, obj_id
+                )
+
+                for key, value in zip(
+                        json_data.keys(), json_data.values()
+                ):
+                        cre.set(key, value)
+
+                try:
+                        await cre.execute()
+                        return "OK"
+                except asab.storage.exceptions.DuplicateError:
+                        L.warning(
+                                "Document you are trying to create already exists."
+                        )
+                        return None
+
+        async def read(self, collection, obj_id):
+                response = await self.MongoDBStorageService.get(
+                        collection, obj_id
+                )
+                return response
+
+
+

asab.StorageService initialized in app.py as part of the asab.storage.Module enables connection to MongoDB. +Further on, two methods provide the handler with the desired functionalities.

+
+
+

Now test it!

+

The application is implicitly running on an 8080 port. +Open the Postman and set a new request.

+

Try the PUT method:

+
127.0.0.1:8080/crud-myrestapi/movie
+
+
+

Insert into the request body:

+
{
+"_id": "1",
+"field1": "something new",
+"field2": 5555,
+"field3": 44424
+}
+
+
+

When there’s a record in your database, try to read it! +For example with this GET request:

+
127.0.0.1:8080/crud-myrestapi/movie/1
+
+
+

Is your response with a 200 status code? Does it return desired data?

+
+

Note

+

TROUBLESHOOTING

+

ERROR

+
ModuleNotFoundError: No module named 'pymongo.mongo_replica_set_client'
+
+
+

Try:

+
pip install motor
+
+
+

ERROR

+
OSError: [Errno 98] error while attempting to bind on address ('0.0.0.0', 8080): address already in use
+
+
+

Try to kill process listening on 8080 or add [web] section into configuration:

+
asab.Config.add_defaults(
+{
+        'asab:storage': {
+                'type': 'mongodb',
+                'mongodb_uri': 'mongodb://mongouser:mongopassword@mongoipaddress:27017',
+                'mongodb_database': 'mongodatabase'
+        },
+        'web': {
+                'listen': '0.0.0.0 8081'
+        }
+})
+
+
+

ERROR

+

No error at all, no response either.

+

Try to check the Mongo database credentials. Do your credentials in the configuration in app.py fit the ones you entered when running the Mongo Docker image?

+
+

Up and running! Congratulation on your first ASAB microservice!

+

Oh, wait…

+

C, R… What about Update and Delete you ask?

+

You already know everything to add the next functionality! Accept the challenge and try it yourself! Or check out the code below.

+
+
+

Update and Delete

+

handler.py

+

./myrestapi/tutorial/handler.py

+
import asab
+import asab.web.rest
+
+
+class CRUDWebHandler(object):
+        def __init__(self, app, mongo_svc):
+                self.CRUDService = mongo_svc
+                web_app = app.WebContainer.WebApp
+                web_app.router.add_put(
+                        '/crud-myrestapi/{collection}',
+                        self.create
+                )
+                web_app.router.add_get(
+                        '/crud-myrestapi/{collection}/{id}',
+                        self.read
+                )
+                web_app.router.add_put(
+                        '/crud-myrestapi/{collection}/{id}',
+                        self.update
+                )
+                web_app.router.add_delete(
+                        '/crud-myrestapi/{collection}/{id}',
+                        self.delete
+                )
+
+
+        @asab.web.rest.json_schema_handler({
+                'type': 'object',
+                'properties': {
+                        '_id': {'type': 'string'},
+                        'field1': {'type': 'string'},
+                        'field2': {'type': 'number'},
+                        'field3': {'type': 'number'}
+                }})
+        async def create(self, request, *, json_data):
+                collection = request.match_info['collection']
+
+                result = await self.CRUDService.create(
+                        collection, json_data
+                )
+                if result:
+                        return asab.web.rest.json_response(
+                                request, {"result": "OK"}
+                        )
+                else:
+                        asab.web.rest.json_response(
+                                request, {"result": "FAILED"}
+                        )
+
+
+        async def read(self, request):
+                collection = request.match_info['collection']
+                key = request.match_info['id']
+                response = await self.CRUDService.read(
+                        collection, key
+                )
+                return asab.web.rest.json_response(
+                        request, response
+                )
+
+
+        @asab.web.rest.json_schema_handler({
+                'type': 'object',
+                'properties': {
+                        '_id': {'type': 'string'},
+                        'field1': {'type': 'string'},
+                        'field2': {'type': 'number'},
+                        'field3': {'type': 'number'}
+                }})
+        async def update(self, request, *, json_data):
+                collection = request.match_info['collection']
+                obj_id = request.match_info["id"]
+
+                result = await self.CRUDService.update(
+                        collection, obj_id, json_data
+                )
+                if result:
+                        return asab.web.rest.json_response(
+                                request, {"result": "OK"}
+                        )
+                else:
+                        asab.web.rest.json_response(
+                                request, {"result": "FAILED"}
+                        )
+
+
+        async def delete(self, request):
+                collection = request.match_info['collection']
+                obj_id = request.match_info["id"]
+                result = await self.CRUDService.delete(
+                        collection, obj_id
+                )
+
+                if result:
+                        return asab.web.rest.json_response(
+                                request, {"result": "OK"}
+                        )
+                else:
+                        asab.web.rest.json_response(
+                                request, {"result": "FAILED"}
+                        )
+
+
+

service.py

+

./myrestapi/tutorial/service.py

+
import asab
+import asab.storage.exceptions
+
+import logging
+#
+
+L = logging.getLogger(__name__)
+
+#
+
+
+class CRUDService(asab.Service):
+
+        def __init__(self, app, service_name='crud.CRUDService'):
+                super().__init__(app, service_name)
+                self.MongoDBStorageService = app.get_service(
+                        "asab.StorageService"
+                )
+
+        async def create(self, collection, json_data):
+                obj_id = json_data.pop("_id")
+
+                cre = self.MongoDBStorageService.upsertor(
+                        collection, obj_id
+                )
+
+                for key, value in zip(
+                        json_data.keys(), json_data.values()
+                ):
+                        cre.set(key, value)
+
+                try:
+                        await cre.execute()
+                        return "OK"
+                except asab.storage.exceptions.DuplicateError:
+                        L.warning(
+                                "Document you are trying to create already exists."
+                        )
+                        return None
+
+
+        async def read(self, collection, obj_id):
+                response = await self.MongoDBStorageService.get(
+                        collection, obj_id
+                )
+                return response
+
+
+        async def update(self, collection, obj_id, document):
+                original = await self.read(
+                        collection, obj_id
+                )
+
+                cre = self.MongoDBStorageService.upsertor(
+                        collection, original["_id"], original["_v"]
+                )
+
+                for key, value in zip(
+                        document.keys(), document.values()
+                ):
+                        cre.set(key, value)
+
+                try:
+                        await cre.execute()
+                        return "OK"
+
+                except KeyError:
+                        return None
+
+
+        async def delete(self, collection, obj_id):
+                try:
+                        await self.MongoDBStorageService.delete(
+                                collection, obj_id
+                        )
+                        return True
+                except KeyError:
+                        return False
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/old_docs/_static/asab-architecture.png b/old_docs/_static/asab-architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..c92b65d2ec53365984c055ac99c37a233eb20592 GIT binary patch literal 39024 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 literal 0 HcmV?d00001 diff --git a/old_docs/admin/command-line.rst b/old_docs/admin/command-line.rst new file mode 100644 index 000000000..51903d336 --- /dev/null +++ b/old_docs/admin/command-line.rst @@ -0,0 +1,66 @@ +ASAB Command-line interface +=========================== + +ASAB-based application provides the command-line interface by default. +Here is an overview of the common command-line arguments. + + +.. option:: -h , --help + +Show a help. + + +Configuration +------------- + +.. option:: -c ,--config + +Load configuration file from a file CONFIG. + + +Logging +------- + +.. option:: -v , --verbose + +Increase the logging level to DEBUG aka be more verbose about what is happening. + + +.. option:: -l ,--log-file + +Log to a file LOG_FILE. + + +.. option:: -s , --syslog + +Log to a syslog. + + +Daemon +------ + +Python module :py:mod:`python-daemon` has to be installed in order to support daemonosation functions. + +.. code-block:: bash + + $ pip3 install asab python-daemon + + +.. option:: -d , --daemonize + +Launch the application in the background aka daemonized. + +Daemon-related section of :any:`Config` file:: + + [daemon] + pidfile=/var/run/myapp.pid + uid=nobody + gid=nobody + working_dir=/tmp + +Configuration options ``pidfile``, ``uid`` , ``gid`` and ``working_dir`` are supported. + + +.. option:: -k , --kill + +Shutdown the application running in the background (started previously with ``-d`` argument). diff --git a/old_docs/admin/containers.rst b/old_docs/admin/containers.rst new file mode 100644 index 000000000..f9a69ce24 --- /dev/null +++ b/old_docs/admin/containers.rst @@ -0,0 +1,121 @@ +Containerisation +================ + +ASAB is designed for deployment into containers such as LXC/LXD or Docker. +It allows to build e.g. microservices that provides REST interface or consume MQ messages while being deployed into a container for a sake of the infrastructure flexibility. + + +ASAB in a LXC/LXD container +--------------------------- + +1. Prepare LXC/LXD container based on Alpine Linux + +.. code-block:: bash + + $ lxc launch images:alpine/3.10 asab + + +2. Swich into a container + +.. code-block:: bash + + $ lxc exec asab -- /bin/ash + + +3. Prepare Python3 environment + +.. code-block:: bash + + $ apk update + $ apk upgrade + $ apk add --no-cache python3 + + $ python3 -m ensurepip + + +4. Deploy ASAB + +.. code-block:: bash + + $ apk add --virtual .buildenv python3-dev gcc musl-dev git + $ pip3 install git+https://github.com/TeskaLabs/asab + $ apk del .buildenv + + +5. Deploy dependencies + +.. code-block:: bash + + $ pip3 install python-daemon + + +7. Use OpenRC to automatically start/stop ASAB application + +.. code-block:: bash + + $ vi /etc/init.d/asab-app + + +Adjust the example of `OpenRC init file `_. + +.. code-block:: bash + + $ chmod a+x /etc/init.d/asab-app + $ rc-update add asab-app + + +*Note*: If you need to install python packages that require compilation using C compiler, you have to add following dependencies: + +.. code-block:: bash + + $ apk add --virtual .buildenv python3-dev + $ apk add --virtual .buildenv gcc + $ apk add --virtual .buildenv musl-dev + + +And removal of the build tools after pip install: + +.. code-block:: bash + + $ apk del .buildenv + +Docker Remote API +--------------------------- + +In order for ASAB applications to read the Docker container name +as well as other information related to the container to be used in logs, metrics and other analysis, +the Docker Remote API must be enabled. + +To do so: + +1. Open the docker service file + +.. code-block:: bash + + vi /lib/systemd/system/docker.service + + +2. Find the line which starts with ExecStart and add `-H=tcp://0.0.0.0:2375` + + +3. Save the file + + +4. Reload the docker daemon and restart the Docker service + +.. code-block:: bash + + sudo systemctl daemon-reload && sudo service docker restart + + +Then in the ASAB application's configuration, provide +the Docker Socket path in `docker_socket` configuration option: + +.. code-block:: bash + + [general] + docker_socket= + +Thus, the metric service as well as log manager can use the container +name as hostname instead of container ID, which provides better readability +when analyzing the logs and metrics, typically using InfluxDB and Grafana. diff --git a/old_docs/admin/install.rst b/old_docs/admin/install.rst new file mode 100644 index 000000000..bfc1453fc --- /dev/null +++ b/old_docs/admin/install.rst @@ -0,0 +1,37 @@ +Installation +============ + +ASAB is distributed via `pypi `_. + + +Install ASAB using pip +---------------------- + +This is the recommended installation method. + +.. code-block:: bash + + $ pip install asab + + +Install ASAB using easy_install +------------------------------- + +.. code-block:: bash + + $ easy_install asab + + + +Install ASAB for a GitHub +------------------------- + +To install ASAB from a master branch of the GIT repository, use following command. + +*Note*: Git has to be installed in order to successfuly complete the installation. + + +.. code-block:: bash + + $ pip install git+https://github.com/TeskaLabs/asab.git + diff --git a/old_docs/admin/systemd.rst b/old_docs/admin/systemd.rst new file mode 100644 index 000000000..c22dc0ba0 --- /dev/null +++ b/old_docs/admin/systemd.rst @@ -0,0 +1,45 @@ +systemd +======= + +1. Create a new Systemd unit file in /etc/systemd/system/: + +.. code-block:: bash + + $ sudo vi /etc/systemd/system/asab.service + + +Adjust the example of `SystemD unit file `_. + + +2. Let systemd know that there is a new service: + +.. code-block:: bash + + $ sudo systemctl enable asab + + +To reload existing unit file after changing, use this: + +.. code-block:: bash + + $ sudo systemctl daemon-reload + + +3. ASAB Application Server service for systemd is now ready. + + +Start of ASAB Server +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + $ sudo service asab start + + +Stop of ASAB Server +^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + $ sudo service asab stop + diff --git a/doc/asab-openrc b/old_docs/asab-openrc similarity index 100% rename from doc/asab-openrc rename to old_docs/asab-openrc diff --git a/doc/asab.service b/old_docs/asab.service similarity index 100% rename from doc/asab.service rename to old_docs/asab.service diff --git a/old_docs/asab/alert.rst b/old_docs/asab/alert.rst new file mode 100644 index 000000000..147a47872 --- /dev/null +++ b/old_docs/asab/alert.rst @@ -0,0 +1,81 @@ +Alert Service +============= + +Integrate ASAB Application with alert managers. + +There are currently two possible target systems for the alerts available: + +- Opsgenie - https://www.atlassian.com/software/opsgenie + +- PagerDuty - https://events.pagerduty.com + +Everything you need to do is to import the service, trigger the alert and specify the target in the **configuration**. + +.. code:: python + + class MyApplication(asab.Application): + async def initialize(self): + from asab.alert import AlertService + self.AlertService = AlertService(self) + self.AlertService.trigger( + source="my-tenant", + alert_cls="my-class", + alert_id="deduplication-id01", + title="Something went wrong.", + detail={ + "example1": "additional-info", + "example2": "additional-info", + }, + ) + + if __name__ == '__main__': + app = MyApplication() + app.run() + + +Opsgenie +-------- + +- Create an account at Opsgenie. +- In your Opsgenie account, create a new **Team**. +- Add integration to your Team - choose **API**. +- API Key will be generated for you. + +*myapplication.conf* + +.. code:: + + [asab:alert:opsgenie] + api_key=my-api-key + tags=my-tag, my-application + url=https://api.eu.opsgenie.com # this is default value + + +PagerDuty +--------- + +- Create an account at PagerDuty. +- In your PagerDuty account, generate **Api Key** (Integrations > Developer Tools > Api Access Keys). +- Create a new Service in Service Directory and add integration in the Integrations folder. +- Choose **Events API V2**. An **Integration Key** will be generated for you. + +*myapplication.conf* + +.. code:: + + [asab:alert:pagerduty] + api_key=my-api-key + integration_key=my-integration-key + url=https://events.pagerduty.com # this is default value + + + +De-duplication +-------------- + +`alert_id` argument serves as a de-duplication ID for the third-party services. It enables the grouping of alerts and prevents noise. +More about alert grouping: + +- Opsgenie: https://support.atlassian.com/opsgenie/docs/what-is-alert-de-duplication/ + +- PagerDuty: https://support.pagerduty.com/docs/intelligent-alert-grouping \ No newline at end of file diff --git a/old_docs/asab/application.rst b/old_docs/asab/application.rst new file mode 100644 index 000000000..127203f27 --- /dev/null +++ b/old_docs/asab/application.rst @@ -0,0 +1,239 @@ +Application +=========== + +.. py:currentmodule:: asab + +.. py:class:: Application() + +The :py:class:`Application` class maintains the global application state. +You can provide your own implementation by creating a subclass. +There should be only one :py:class:`Application` object in the process. + +Subclassing: + +.. code:: python + + import asab + + class MyApplication(asab.Application): + pass + + if __name__ == '__main__': + app = MyApplication() + app.run() + + +Direct use of :py:class:`Application` object: + +.. code:: python + + import asab + + if __name__ == '__main__': + app = asab.Application() + app.run() + + + +Event Loop +---------- + +.. py:attribute:: Application.Loop + +The :py:mod:`asyncio` event loop that is used by this application. + +.. code:: python + + asyncio.ensure_future(my_coro()) + + +Application Lifecycle +--------------------- + +The ASAB is designed around the `Inversion of control `_ principle. +It means that the ASAB is in control of the application lifecycle. +The custom-written code receives the flow from ASAB via callbacks or handlers. +Inversion of control is used to increase modularity of the code and make it extensible. + +The application lifecycle is divided into 3 phases: init-time, run-time and exit-time. + +Init-time +^^^^^^^^^ + +.. py:method:: Application.__init__() + +The init-time happens during :py:class:`Application` constructor call. +The Publish-Subscribe message :any:`Application.init!` is published during init-time. +The :class:`Config` is loaded during init-time. + + +.. py:method:: Application.initialize() + +The application object executes asynchronous callback ``Application.initialize()``, which can be overriden by an user. + +.. code:: python + + class MyApplication(asab.Application): + async def initialize(self): + # Custom initialization + from module_sample import Module + self.add_module(Module) + + +Run-time +^^^^^^^^ + +.. py:method:: Application.run() + +Enter a run-time. This is where the application spends the most time typically. +The Publish-Subscribe message :any:`Application.run!` is published when run-time begins. + +The method returns the value of :any:`Application.ExitCode`. + + +.. py:method:: Application.main() + +The application object executes asynchronous callback ``Application.main()``, which can be overriden. +If ``main()`` method is completed without calling ``stop()``, then the application server will run forever (this is the default behaviour). + +.. code:: python + + class MyApplication(asab.Application): + async def main(self): + print("Hello world!") + self.stop() + + +.. py:method:: Application.stop(exit_code:int=None) + +The method ``Application.stop()`` gracefully terminates the run-time and commence the exit-time. +This method is automatically called by ``SIGINT`` and ``SIGTERM``. It also includes a response to ``Ctrl-C`` on UNIX-like system. +When this method is called 3x, it abruptly exits the application (aka emergency abort). + +The parameter ``exit_code`` allows you to specify the application exit code (see *Exit-Time* chapter). + +*Note:* You need to install :py:mod:`win32api` module to use ``Ctrl-C`` or an emergency abord properly with ASAB on Windows. It is an optional dependency of ASAB. + + +Exit-time +^^^^^^^^^ + +.. py:method:: Application.finalize() + +The application object executes asynchronous callback ``Application.finalize()``, which can be overriden by an user. + +.. code:: python + + class MyApplication(asab.Application): + async def finalize(self): + # Custom finalization + ... + + +The Publish-Subscribe message :any:`Application.exit!` is published when exit-time begins. + + +.. py:method:: Application.set_exit_code(exit_code:int, force:bool=False) + +Set the exit code of the application, see ``os.exit()`` in the Python documentation. +If ``force`` is ``False``, the exit code will be set only if the previous value is lower than the new one. +If ``force`` is ``True``, the exit code value is set to a ``exit_code`` disregarding the previous value. + + +.. py:attribute:: Application.ExitCode + +The actual value of the exit code. + + +The example of the exit code handling in the ``main()`` function of the application. + +.. code:: python + + if __name__ == '__main__': + app = asab.Application() + exit_code = app.run() + sys.exit(exit_code) + + + +Module registry +--------------- + +For more details see :py:class:`Module` class. + +.. py:method:: Application.add_module(module_class) + +Initialize and add a new module. +The ``module_class`` class will be instantiated during the method call. + + +.. code:: python + + class MyApplication(asab.Application): + async def initialize(self): + from my_module import MyModule + self.add_module(MyModule) + +.. py:attribute:: Application.Modules + +A list of modules that has been added to the application. + + +Service registry +---------------- + +Each service is identified by its unique service name. +For more details see :py:class:`Service` class. + +.. py:method:: Application.get_service(service_name) + +Locate a service by its service name in a registry and return the ``Service`` object. + +.. code:: python + + svc = app.get_service("service_sample") + svc.hello() + + +.. py:attribute:: Application.Services + +A dictionary of registered services. + + +Command-line parser +------------------- + +.. py:method:: Application.create_argument_parser(prog=None, usage=None, description=None, epilog=None, prefix_chars='-', fromfile_prefix_chars=None, argument_default=None, conflict_handler='error', add_help=True ) -> argparse.ArgumentParser + +Creates an ``argparse.ArgumentParser``. +This method can be overloaded to adjust command-line argument parser. + +Please refer to Python standard library ``argparse`` for more details about function arguments. + + +.. py:method:: Application.parse_args() + +The application object calls this method during init-time to process a command-line arguments. +:py:mod:`argparse` is used to process arguments. +You can overload this method to provide your own implementation of command-line argument parser. + + +.. py:data:: Application.Description + +The :py:data:`Description` attribute is a text that will be displayed in a help text (``--help``). +It is expected that own value will be provided. +The default value is ``""`` (empty string). + + + +UTC Time +-------- + +.. py:method:: Application.time() -> float + +Return the current "event loop time" in seconds since the epoch as a floating point number. +The specific date of the epoch and the handling of leap seconds is platform dependent. On Windows and most Unix systems, the epoch is January 1, 1970, 00:00:00 (UTC) and leap seconds are not counted towards the time in seconds since the epoch. This is commonly referred to as Unix time. + +A call of the ``time.time()`` function could be expensive. +This method provides a cheaper version of the call that returns a current wall time in UTC. + diff --git a/old_docs/asab/config.rst b/old_docs/asab/config.rst new file mode 100644 index 000000000..1ce9621c1 --- /dev/null +++ b/old_docs/asab/config.rst @@ -0,0 +1,251 @@ +.. _configuration-ref: + +Configuration +============= + +.. py:currentmodule:: asab + +.. py:data:: Config + +The configuration is provided by :py:obj:`Config` object which is a singleton. It means that you can access :py:obj:`Config` from any place of your code, without need of explicit initialisation. + +.. code:: python + + import asab + + # Initialize application object and hence the configuration + app = asab.Application() + + # Access configuration values anywhere + my_conf_value = asab.Config['section_name']['key1'] + + +Based on ConfigParser +--------------------- + +The :py:obj:`Config` is inherited from Python Standard Library :py:class:`configparser.ConfigParser` class. which implements a basic configuration language which provides a structure similar to what’s found in Microsoft Windows INI files. + +.. py:currentmodule:: asab.config + +.. py:class:: ConfigParser + +Example of the configuration file: + +.. code:: ini + + [bitbucket.org] + User = hg + + [topsecret.server.com] + Port = 50022 + ForwardX11 = no + + +And this is how you access configuration values: + +.. code:: python + + >>> asab.Config['topsecret.server.com']['ForwardX11'] + 'no' + + +.. py:currentmodule:: asab + + +Multiline configuration entry +----------------------------- + +A multiline configuration entries are supported. +An example: + +.. code:: ini + + [section] + key= + line1 + line2 + line3 + another_key=foo + + +Automatic load of configuration +------------------------------- + +If a configuration file name is specified, the configuration is automatically loaded from a configuration file during initialiation time of :py:class:`Application`. +The configuration file name can be specified by one of ``-c`` command-line argument (1), ``ASAB_CONFIG`` environment variable (2) or config ``[general] config_file`` default value (3). + +.. code:: shell + + ./sample_app.py -c ./etc/sample.conf + + + +Including other configuration files +----------------------------------- + +You can specify one or more additional configuration files that are loaded and merged from an main configuration file. +It is done by ``[general] include`` configuration value. Multiple paths are separated by ``os.pathsep`` (``:`` on Unix). +The path can be specified as a glob (e.g. use of ``*`` and ``?`` wildcard characters), it will be expanded by ``glob`` module from Python Standard Library. +Included configuration files may not exists, this situation is silently ignored. + +.. code:: ini + + [general] + include=./etc/site.conf:./etc/site.d/*.conf + + +You can also use a multiline configuration entry: + +.. code:: ini + + [general] + include= + ./etc/site.conf + ./etc/site.d/*.conf + + + +Configuration default values +---------------------------- + +.. py:method:: Config.add_defaults(dictionary) + +This is how you can extend configuration default values: + +.. code:: python + + asab.Config.add_defaults( + { + 'section_name': { + 'key1': 'value', + 'key2': 'another value' + }, + 'other_section': { + 'key3': 'value', + }, + } + ) + +Only simple types (``string``, ``int`` and ``float``) are allowed in the configuration values. +Don't use complex types such as lists, dictionaries or objects because these are impossible to provide via configuration files etc. + + +Environment variables in configration +------------------------------------- + +Environment variables found in values are automatically expanded. + +.. code:: ini + + [section_name] + persistent_dir=${HOME}/.myapp/ + +.. code:: python + + >>> asab.Config['section_name']['persistent_dir'] + '/home/user/.myapp/' + +There is a special environment variable `${THIS_DIR}` that is expanded to a directory that contains a current configuration file. +It is useful in complex configurations that utilizes included configuration files etc. + +.. code:: ini + + [section_name] + my_file=${THIS_DIR}/my_file.txt + +Another environment variable `${HOSTNAME}` contains the application hostname to be used f. e. in logging file path. + +.. code:: ini + + [section_name] + my_file=${THIS_DIR}/${HOSTNAME}/my_file.txt + +Passwords in configration +------------------------------------- + +[passwords] section in the configuration serves to securely store passwords, +which are then not shown publicly in the default API config endpoint's output. + +It is convenient for the user to store passwords at one place, +so that they are not repeated in many sections of the config file(s). + +Usage is as follows: + +.. code:: ini + + [connection:KafkaConnection] + password=${passwords:kafka_password} + + [passwords] + kafka_password= + + +Obtaining seconds +------------------------------------- + +.. py:method:: Config.getseconds() + +The seconds can be obtained using `getseconds()` method for values with different time +units specified in the configuration: + +.. code:: ini + + [sleep] + sleep_time=5.2s + another_sleep_time=10d + +The available units are: + + * ``y`` ... years + * ``M`` ... months + * ``w`` ... weeks + * ``d`` ... days + * ``h`` ... hours + * ``m`` ... minutes + * ``s`` ... seconds + * ``ms`` .. miliseconds + +If no unit is specified, float of seconds is expected. + +The obtainment of the second value in the code can be achieved in two ways: + +.. code:: python + + self.SleepTime = asab.Config["sleep"].getseconds("sleep_time") + self.AnotherSleepTime = asab.Config.getseconds("sleep", "another_sleep_time") + +Obtaining URLs +------------------------------------- + +.. py:method:: Config.geturl(section, option, scheme=None:str,tuple) + +A URL can be obtained using a `geturl()` method that takes the URL from the config and +removes leading and trailing whitespaces and trailing backslashes. + +There is an optional parameter called `scheme` that can have any URL scheme like +http, https, mongodb etc. Setting it to None, scheme validation gets bypassed. + +Setting the scheme parameter to the same scheme as in the config, it will return the URL. +If it's not the same it will raise an error. + +There are two ways of obtaining the URL: + +.. code:: py + + asab.Config["urls"].geturl("teskalabs", scheme="https") + asab.Config.geturl("urls", "github", scheme=None) + +Example: + +.. code:: python + + >>> asab.Config["urls"].geturl("teskalabs", scheme="https") + 'https://www.teskalabs.com' + +For reference this would be the configuration file: + +.. code:: ini + + [urls] + teskalabs=https://www.teskalabs.com/ + github=github.com \ No newline at end of file diff --git a/old_docs/asab/index.rst b/old_docs/asab/index.rst new file mode 100644 index 000000000..17ee066a0 --- /dev/null +++ b/old_docs/asab/index.rst @@ -0,0 +1,43 @@ +Asynchronous Server Application Boilerplate's documentation +=========================================================== + +Asynchronous Server App Boilerplate (or ASAB for short) is a microservice platform for Python 3.7+ and `asyncio`. +ASAB aims to minimize the amount of code that needs to be written when building a microservice or an application server. +ASAB is fully asynchronous using async/await syntax from Python 3, making your code modern, non-blocking, speedy and hence scalable. +We make every effort to build ASAB container-friendly so that you can deploy ASAB-based microservice via Docker or Kubernetes in a breeze. + +ASAB is free and open-source software, available under BSD licence. +It means that anyone is freely licenced to use, copy, study, and change the software in any way, and the source code is openly shared so that people could voluntarily improve the design of the software. +Anyone can (and is encouraged to) use ASAB in his or her projects, for free. +A current maintainer is a `TeskaLabs Ltd `_ company. + +ASAB is developed `on GitHub `_. +Contributions are welcome! + + +ASAB is designed to be powerful yet simple +------------------------------------------ + +Here is a complete example of a fully working microservice: + +.. code:: python + + import asab + + class MyApplication(asab.Application): + async def main(self): + print("Hello world!") + self.stop() + + if __name__ == "__main__": + app = MyApplication() + app.run() + + +ASAB is the right choice when +----------------------------- + + - using Python 3.7+. + - building the microservice or the application server. + - utilizing asynchronous I/O (aka `asyncio `_). + diff --git a/doc/asab/library.rst b/old_docs/asab/library.rst similarity index 100% rename from doc/asab/library.rst rename to old_docs/asab/library.rst diff --git a/old_docs/asab/log.rst b/old_docs/asab/log.rst new file mode 100644 index 000000000..7d3e4278d --- /dev/null +++ b/old_docs/asab/log.rst @@ -0,0 +1,232 @@ +Logging +======= + +.. py:currentmodule:: asab + +ASAB logging is built on top of a standard Python ``logging`` module. +It means that it logs to ``stderr`` when running on a console and ASAB also provides file and syslog output (both RFC5424 and RFC3164) for background mode of operations. + +Log timestamps are captured with sub-second precision (depending on the system capabilities) and displayed including microsecond part. + + +Recommended use +--------------- + +We recommend to create a logger ``L`` in every module that captures all necessary logging output. +Alternative logging strategies are also supported. + +.. code:: python + + import logging + L = logging.getLogger(__name__) + + ... + + L.warning("Hello world!") + + +Example of the output to the console: + +``25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule Hello world!`` + + +Logging Levels +-------------- + +ASAB uses Python logging levels with the addition of ``LOG_NOTICE`` level. +``LOG_NOTICE`` level is similar to ``logging.INFO`` level but it is visible in even in non-verbose mode. + + +.. code:: python + + L.log(asab.LOG_NOTICE, "This message will be visible regardless verbose configuration.") + + ++----------------+---------------+------------------------------+ +| Level | Numeric value | Syslog Severity level | ++================+===============+==============================+ +| ``CRITICAL`` | 50 | Critical / ``crit`` / 2 | ++----------------+---------------+------------------------------+ +| ``ERROR`` | 40 | Error / ``err`` / 3 | ++----------------+---------------+------------------------------+ +| ``WARNING`` | 30 | Warning / ``warning`` / 4 | ++----------------+---------------+------------------------------+ +| ``LOG_NOTICE`` | 25 | Notice / ``notice`` / 5 | ++----------------+---------------+------------------------------+ +| ``INFO`` | 20 | Informational / ``info`` / 6 | ++----------------+---------------+------------------------------+ +| ``DEBUG`` | 10 | Debug / ``debug`` / 7 | ++----------------+---------------+------------------------------+ +| ``NOTSET`` | 0 | | ++----------------+---------------+------------------------------+ + + +Example of a custom level configuration: + +.. code:: ini + + [logging] + levels= + myApp.module1 DEBUG + myApp.module2 WARNING + customLogger ERROR + +The logger name and the corresponding logging level are separated by a space, each logger is on a separate line. + + +Verbose mode +------------ + +The command-line argument ``-v`` enables verbose logging. +It means that log entries with levels ``DEBUG`` and ``INFO`` will be visible. +It also enables ``asyncio`` debug logging. + +The actual verbose mode is avaiable at ``asab.Config["logging"]["verbose"]`` boolean option. + +.. code:: python + + L.debug("This message will be visible only in verbose mode.") + + +Structured data +--------------- + +ASAB supports a structured data to be added to a log entry. +It follows the `RFC 5424 `_, section ``STRUCTURED-DATA``. +Structured data are a dictionary, that has to be seriazable to JSON. + +.. code:: python + + L.warning("Hello world!", struct_data={'key1':'value1', 'key2':2}) + + +Example of the output to the console: + +``25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule [sd key1="value1" key2="2"] Hello world!`` + + +Logging to file +--------------- + +The command-line argument ``-l`` on command-line enables logging to file. +Also non-empty ``path`` option in the section ``[logging:file]`` of configuration file enables logging to file as well. + +Example of the configuration file section: + +.. code:: ini + + [logging:file] + path=/var/log/asab.log + format="%%(asctime)s %%(levelname)s %%(name)s %%(struct_data)s%%(message)s", + datefmt="%%d-%%b-%%Y %%H:%%M:%%S.%%f" + backup_count=3 + rotate_every=1d + + +When the deployment expects more instances of the same application to be logging into the same file, +it is recommended, that the variable hostname is used in the file path: + +.. code:: ini + + [logging:file] + path=/var/log/${HOSTNAME}/asab.log + +In this way, the applications will log to seperate log files in different folders, +which is an intended behavior, since race conditions may occur when different application instances +log into the same file. + +Logging to console +------------------ + +ASAB will log to the console only if it detects that it runs in the foreground respectively on the terminal using ``os.isatty`` +or if the environment variable ``ASABFORCECONSOLE`` is set to ``1``. +This is useful setup for eg. PyCharm. + + +Log rotation +^^^^^^^^^^^^ + +ASAB supports a `log rotation `_. +The log rotation is triggered by a UNIX signal ``SIGHUP``, which can be used e.g. to integrate with ``logrotate`` utility. +It is implemented using ``logging.handlers.RotatingFileHandler`` from a Python standard library. +Also, a time-based log rotation can be configured using ``rotate_every`` option. + +``backup_count`` specifies a number of old files to be kept prior their removal. +The system will save old log files by appending the extensions ‘.1’, ‘.2’ etc., to the filename. + +``rotate_every`` specifies an time interval of a log rotation. +Default value is empty string, which means that the time-based log rotation is disabled. +The interval is specified by an integer value and an unit, e.g. 1d (for 1 day) or 30M (30 minutes). +Known units are `H` for hours, `M` for minutes, `d` for days and `s` for seconds. + + +Logging to syslog +----------------- + +The command-line argument ``-s`` enables logging to syslog. + +A configuration section ``[logging:syslog]`` can be used to specify details about desired syslog logging. + +Example of the configuration file section: + +.. code:: ini + + [logging:syslog] + enabled=true + format=5 + address=tcp://syslog.server.lan:1554/ + + +``enabled`` is equivalent to command-line switch ``-s`` and it enables syslog logging target. + +``format`` speficies which logging format will be used. +Possible values are: + +- ``5`` for (new) syslog format (`RFC 5424 `_ ) , +- ``3`` for old BSD syslog format (`RFC 3164 `_ ), typically used by ``/dev/log`` and +- ``m`` for Mac OSX syslog flavour that is based on BSD syslog format but it is not fully compatible. + +The default value is ``3`` on Linux and ``m`` on Mac OSX. + +``address`` specifies the location of the Syslog server. It could be a UNIX path such as ``/dev/log`` or URL. +Possible URL values: + +- ``tcp://syslog.server.lan:1554/`` for Syslog over TCP +- ``udp://syslog.server.lan:1554/`` for Syslog over UDP +- ``unix-connect:///path/to/syslog.socket`` for Syslog over UNIX socket (stream) +- ``unix-sendto:///path/to/syslog.socket`` for Syslog over UNIX socket (datagram), equivalent to ``/path/to/syslog.socket``, used by a ``/dev/log``. + +The default value is a ``/dev/log`` on Linux or ``/var/run/syslog`` on Mac OSX. + + +Logging of obsolete features +---------------------------- + +It proved to be essential to inform operators about features that are going to be obsoleted. +ASAB offers the unified "obsolete" logger. +This logger can indicate that a particular feature is marked as "obsolete" thru logs. +Such a log message can then be "grepped" from logs uniformly. + +It is recommended to include `eol` attribute in the `struct_data` of the log with a `YYYY-MM-DD` date/time of the planned obsoletion of the feature. + +Hint: We suggest automating the detection of obsolete warnings in logs so that the operations are informed well ahead of the actual removal of the feature. The string to seek in logs is " OBSOLETE ". + +Example of the use: + +.. code:: python + + asab.LogObsolete.warning("Use of the obsolete function", struct_data={'eol':'2022-31-12'}) + + +Log example: + +``21-Jul-2022 14:32:40.983884 WARNING OBSOLETE [eol="2022-31-12"] Use of the obsolete function`` + + +Reference +--------- + +.. automodule:: asab.log + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/asab/metrics.rst b/old_docs/asab/metrics.rst similarity index 100% rename from doc/asab/metrics.rst rename to old_docs/asab/metrics.rst diff --git a/old_docs/asab/module.rst b/old_docs/asab/module.rst new file mode 100644 index 000000000..0e47b5b49 --- /dev/null +++ b/old_docs/asab/module.rst @@ -0,0 +1,65 @@ +Module +====== + +.. py:currentmodule:: asab + +.. py:class:: Module + +Modules are registered at the module registry, managed by an application object. +See :any:`Application.Modules` for more details. +Module can be loaded by ASAB and typically provides one or more :any:`Service` objects. + + +Structure +--------- + +Recommended structure of the ASAB module:: + + mymodule/ + __init__.py + myservice.py + + +Content of the `__init__.py`: + +.. code:: python + + import asab + from .myservice import MyService + + # Extend ASAB configuration defaults + asab.Config.add_defaults({ + 'mymodule': { + 'foo': 'bar' + } + }) + + class MyModule(asab.Module): + def __init__(self, app): + super().__init__(app) + self.service = MyService(app, "MyService") + + +And this is how the module is loaded: + +.. code:: python + + from mymodule import MyModule + app.add_module(MyModule) + +For more details see :any:`Application.add_module`. + + +Lifecycle +--------- + +.. py:method:: Module.initialize(app) + +Called when the module is initialized. +It can be overriden by an user. + + +.. py:method:: Module.finalize(app) + +Called when the module is finalized e.g. during application exit-time. +It can be overriden by an user. diff --git a/doc/asab/pubsub.rst b/old_docs/asab/pubsub.rst similarity index 100% rename from doc/asab/pubsub.rst rename to old_docs/asab/pubsub.rst diff --git a/old_docs/asab/service.rst b/old_docs/asab/service.rst new file mode 100644 index 000000000..4fe35ba01 --- /dev/null +++ b/old_docs/asab/service.rst @@ -0,0 +1,72 @@ +Service +======= + +.. py:currentmodule:: asab + +.. py:class:: Service(app) + +Service objects are registered at the service registry, managed by an application object. +See :any:`Application.Services` for more details. + + +An example of a typical service class skeleton: + +.. code:: python + + class MyService(asab.Service): + + def __init__(self, app, service_name): + super().__init__(app, service_name) + ... + + async def initialize(self, app): + ... + + + async def finalize(self, app): + ... + + + def service_method(self): + .... + + +This is how a service is created and registered: + +.. code:: python + + mysvc = MyService(app, "my_service") + + +This is how a service is located and used: + +.. code:: python + + mysvc = app.get_service("my_service") + mysvc.service_method() + + + +.. py:data:: Service.Name + +Each service is identified by its name. + + +.. py:data:: Service.App + +A reference to an :py:class:`Application` object instance. + + +Lifecycle +--------- + +.. py:method:: Service.initialize(app) + +Called when the service is initialized. +It can be overriden by an user. + + +.. py:method:: Service.finalize(app) + +Called when the service is finalized e.g. during application exit-time. +It can be overriden by an user. diff --git a/old_docs/asab/storage.rst b/old_docs/asab/storage.rst new file mode 100644 index 000000000..83c1a2e5f --- /dev/null +++ b/old_docs/asab/storage.rst @@ -0,0 +1,381 @@ +.. currentmodule:: asab.storage + +Storage +======= + +The ASAB's Storage Service supports data storage in-memory or in dedicated document databases, including `MongoDB `_ and `ElasticSearch `_. + +Configuration +------------- + +First, specify the storage type in the configuration. The options for the storage type are: + +- `inmemory`: Collects data directly in memory +- `mongodb`: Collects data using MongoDB database. Depends on `pymongo `_ and `motor `_ libraries. +- `elasticsearch`: Collects data using ElasticSearch database. Depends on `aiohttp `_ library. + +Storage Service provides a unified interface for accessing and manipulating collections across multiple database technologies. + +.. code:: ini + + [asab:storage] + type=mongodb + +For accessing the storage, simply add `asab.storage.Module`` when initializing and register the service. + +.. code:: python + + class MyApplication(asab.Application): + + async def initialize(self): + + self.add_module(asab.storage.Module) + + async def main(self): + storage = self.get_service("asab.StorageService") + + +Manipulation with databases +--------------------------- + +Upsertor +~~~~~~~~ + +Upsertor is an object that works like a pointer to the specified database and optionally to object id. It is used for inserting new objects, updating existing objects and deleting them. + +.. code:: python + + u = storage.upsertor("test-collection") + +The :func:`StorageService.upsertor()` method creates an upsertor object associated with the specified collection. It takes `collection` as an argument and can have two parameters `obj_id` and `version`, which are used for getting an existing object by its ID and version. + +Inserting an object +~~~~~~~~~~~~~~~~~~~ + +For inserting an object to the collection, use the :func:`Upsertor.set()` method. + +.. code:: python + + u.set("key", "value") + +To execute these procedures, simply run the :func:`Upsertor.execute()` coroutine method, which commits the upsertor data to the storage and returns the ID of the object. Since it is a coroutine, it must be awaited. + +.. code:: python + + object_id = await u.execute() + +The `Upsertor.execute()` method has optional parameters `custom_data` and `event_type`, which are used for webhook requests. + +.. code:: python + + object_id = await u.execute( + custom_data= {"foo": "bar"}, + event_type="object_created" + ) + +Getting a single object +~~~~~~~~~~~~~~~~~~~~~~~ + +For getting a single object, use :func:`StorageService.get()` coroutine method that takes two arguments `collection` and `obj_id` and finds an object by its ID in collection. + +.. code:: python + + obj = await storage.get(collection="test-collection", obj_id=object_id) + print(obj) + +When the requested object is not found in the collection, the method raises ``KeyError``. Remember to handle this exception properly when using databases in your services and prevent them from crashing! + +.. note:: + + MongoDB storage service in addition provides a coroutine method :func:`get_by()` which is used for accessing an object by finding its key-value pair. + + .. code::python + + obj = await storage.get_by(database="test-collection", key="key", value="value") + +Updating an object +~~~~~~~~~~~~~~~~~~ + +For updating an object, first obtain the upsertor specifying its `obj_id` and `version`. + +.. code:: python + + u = storage.upsertor( + collection="test-collection", + obj_id=object_id, + version=obj['_v'] + ) + +We strongly recommend to read the version from the object such as above. That creates a soft lock on the record. It means that if the object is updated by other component in meanwhile, your upsertor will fail and you should retry the whole operation. The new objects should have a version set to 0, which is done by default. + +After obtaining an upsertor, you can update the object via the :func:`Upsertor.set()` coroutine. + +.. code::python + + u.set("key", "new_value") + object_id = await u.execute() + + +Deleting an object +~~~~~~~~~~~~~~~~~~ + +For deleting an object from database, use the :func:`StorageService.delete()` coroutine method which takes arguments `collection` and `obj_id`, deletes the object and returns its ID. + +.. code:: python + + deleted_id = await u.delete("test-collection", object_id) + + + +Storing data in memory +---------------------- + +If the option `inmemory` is set, ASAB will store data in its own memory. In particular, `asab.StorageService` is initialized with an attribute `InMemoryCollections` which is a dictionary where all the collections are stored in. + +.. note:: + + You can go through all the databases directly by accessing `InMemoryCollections` attribute, although we do not recommend that. + + .. code:: python + + import pprint + + storage = self.get_service("asab.StorageService") + pprint.pprint(storage.InMemoryCollections, indent=2) + + +Storing data in MongoDB +----------------------- + +If the option `mongodb` is set, ASAB will store data in MongoDB database. + +ASAB uses `motor library `_ which provides non-blocking MongoDB driver for `asyncio`. + +You can specify the database name and URL for MongoDB in config file (the following example is the default configuration): + +.. code:: ini + + [asab:storage] + type=mongodb + mongodb_uri=mongodb://localhost:27017 + mongodb_database=asabdb + +You can use all the methods from the abstract class. MongoDB Storage class provides in addition two methods, :func:`StorageService.get_by()` and :func:`StorageService.collection()`. + +The method :func:`StorageService.get_by()` is used in the same way as :func:`StorageService.get()` except that it takes the arguments `key` and `value` instead of `obj_id`. + +.. code:: python + + obj = await storage.get_by(database="test-collection", key="key", value="value") + +The method :func:`collection()` is used for accessing the database directly. It takes `collection` as the argument and returns `motor.motor_asyncio.AsyncIOMotorCollection` object, which can be used for calling MongoDB directives. + +.. code:: python + + collection = await storage.collection("test-collection") + cursor = collection.find({}) + while await cursor.fetch_next: + data = cursor.next_object() + pprint.pprint(data) + +The full list of methods suitable for this object is described in the `official documentation `_. + + + +Storing data in ElasticSearch +------------------------------ + +When using ElasticSearch, add configurations for URL, username and password. + +.. code:: ini + + [asab:storage] + type=elasticsearch + elasticsearch_url=http://localhost:9200/ + elasticsearch_username=JohnDoe + elasticsearch_password=lorem_ipsum_dolor?sit_amet!2023 + +You can also specify the `refreshing parameter `_ and scroll timeout for `ElasticSearch Scroll API `_. + +.. code:: ini + + [asab:storage] + refresh=true + scroll_timeout=1m + +ElasticSearch Storage provides in addition other methods for creating index templates, mappings etc (see the Reference section). + + +Encryption and decryption +------------------------- + +Data stored in the database can be encrypted using an algorithm that adheres to the Advanced Encryption Standard (AES). + +AES Key settings +~~~~~~~~~~~~~~~~ + +In order to use encryption, first make sure you have the `cryptography package `_ installed. Then specify the AES Key in the config file. + +.. code:: ini + + [asab:storage] + aes_key=random_key_string + +.. note:: + + The AES Key is used as both an encryption and decryption key. It is recommended to keep it in `a separate configuration file `_ that is not exposed anywhere publicly. + + The actual binary AES Key is obtained from the `aes_key` specified in the config file by encoding and hashing it using the standard `hashlib `_ algorithms, so do not worry about the length and type of the key. + + + +Encrypting data +~~~~~~~~~~~~~~~ + +The :func:`Upsertor.set()` method has an optional boolean parameter `encrypt` for encrypting the data before they are stored. Only values of the type ``bytes`` can be encrypted. If you want to encrypt other values, encode them first. + +.. code:: python + + message = "This is a super secret message!" + number = 2023 + message_binary = message.encode("ascii") + number_binary = number.encode("ascii") + + u.set("message", message_binary, encrypt=True) + u.set("number", number_binary, encrypt=True) + object_id = await u.execute() + + +Decrypting data +~~~~~~~~~~~~~~~ + +The :func:`StorageService.get()` coroutine method has an optional parameter `decrypt` which takes an ``iterable`` object (i.e. a list, tuple, set, ...) with the names of keys whose values are to be decrypted. + +.. code:: python + + data = await storage.get( + collection="test-collection", + obj_id=object_id, + decrypt=["message", "number"] + ) + +If some of the keys to be decrypted are missing in the required document, the method will ignore them and continue. + +.. note:: + + Data that has been encrypted can be identified by the prefix "$aes-cbc$" and are stored in a binary format. + + +Under the hood +~~~~~~~~~~~~~~ + +For encrypting data, we use the certified symmetric AES-CBC algorithm. In fact, the abstract base class :class:`StorageServiceABC` provides two methods :func:`aes_encrypt()` and :func:`aes_decrypt()` that are called automatically in :func:`Upsertor.set()` and :func:`StorageService.get()` methods when the parameter `encrypt` or `decrypt` is specified. + + +AES-CBC is a mode of operation for the Advanced Encryption Standard (AES) algorithm that provides confidentiality and integrity for data. In AES-CBC, the plaintext is divided into blocks of fixed size (usually 128 bits), and each block is encrypted using the AES algorithm with a secret key. + +CBC stands for "Cipher Block Chaining" and it is a technique that adds an extra step to the encryption process to ensure that each ciphertext block depends on the previous one. This means that any modification to the ciphertext will produce a completely different plaintext after decryption. + +The algorithm is a symmetric cipher, which is suitable for encrypting large amounts of data. It requires much less computation power than asymmetric ciphers and is much more useful for bulk encrypting large amounts of data. + + + +Reference +--------- + +StorageService +~~~~~~~~~~~~~~ + +Here is a list of methods of the abstract StorageService class which can be used for all types of storages. + + +.. currentmodule:: asab.storage.service + +.. autoclass:: StorageServiceABC + + .. automethod:: upsertor + + .. automethod:: get + + .. automethod:: delete + + .. automethod:: aes_encrypt + + .. automethod:: aes_decrypt + + +Upsertor +~~~~~~~~ + +Here is a list of methods of the abstract Upsertor class which can be used for all types of storages. + +.. currentmodule:: asab.storage.upsertor + +.. autoclass:: UpsertorABC + + .. automethod:: set + + .. automethod:: unset + + .. automethod:: generate_id + + .. automethod:: execute + + +In-memory storage +~~~~~~~~~~~~~~~~~ + +Here is a list of methods that are specific for the in-memory storage. + +.. currentmodule:: asab.storage.inmemory + +.. autoclass:: StorageService + :show-inheritance: + + +MongoDB Storage +~~~~~~~~~~~~~~~ + +Here is a list of methods that are specific for the MongoDB storage. + +.. currentmodule:: asab.storage.mongodb + +.. autoclass:: StorageService + :show-inheritance: + + .. automethod:: get_by + + .. automethod:: collection + + +ElasticSearch Storage +~~~~~~~~~~~~~~~~~~~~~~ + +Here is a list of methods that are specific for the ElasticSearch storage. + +.. currentmodule:: asab.storage.elasticsearch + +.. autoclass:: StorageService + :show-inheritance: + + .. automethod:: session + + .. automethod:: finalize + + .. automethod:: mapping + + .. automethod:: get_index_template + + .. automethod:: put_index_template + + .. automethod:: reindex + + .. automethod:: scroll + + .. automethod:: list + + .. automethod:: count + + .. automethod:: indices + + .. automethod:: empty_index \ No newline at end of file diff --git a/old_docs/asab/various.rst b/old_docs/asab/various.rst new file mode 100644 index 000000000..180658c98 --- /dev/null +++ b/old_docs/asab/various.rst @@ -0,0 +1,60 @@ +Various utility classes +======================= + +.. automodule:: asab.abc + :members: + :undoc-members: + :show-inheritance: + + +Singleton +--------- + +.. automodule:: asab.abc.singleton + :members: + :undoc-members: + +Usage: + +.. code:: python + + import asab + + class MyClass(metaclass=asab.Singleton): + ... + + +Persistent dictionary +--------------------- + +.. automodule:: asab.pdict + :members: + :undoc-members: + :show-inheritance: + + +*Note*: A recommended way of initializing the persistent dictionary: + +.. code:: python + + PersistentState = asab.PersistentDict("some.file") + PersistentState.setdefault('foo', 0) + PersistentState.setdefault('bar', 2) + + +Timer +----- + +.. automodule:: asab.timer + :members: + :undoc-members: + :show-inheritance: + + +Sockets +------- + +.. automodule:: asab.socket + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/asab/web/auth.rst b/old_docs/asab/web/auth.rst similarity index 100% rename from doc/asab/web/auth.rst rename to old_docs/asab/web/auth.rst diff --git a/old_docs/asab/web/cors.rst b/old_docs/asab/web/cors.rst new file mode 100644 index 000000000..a5aaad072 --- /dev/null +++ b/old_docs/asab/web/cors.rst @@ -0,0 +1,21 @@ +Cross-Origin Resource Sharing (CORS) +==================================== + +When you create a web container, you specify a config section name. In the example below it’s `myapp:web`: + +.. code:: python + + asab.web.WebContainer(self.WebService, "myapp:web") + +You can then configure CORS by running your app with a config file with this contents: + +.. code:: INI + + [myapp:web] + cors=* + cors_preflight_paths=/* + + + +- **cors**: contents of the Access-Control-Allow-Origin header +- **cors_preflight_paths**: a pattern for endpoints that shall return responses to pre-flight requests (OPTIONS). Value must start with "/". diff --git a/old_docs/asab/web/index.rst b/old_docs/asab/web/index.rst new file mode 100644 index 000000000..42c2ee0c2 --- /dev/null +++ b/old_docs/asab/web/index.rst @@ -0,0 +1,163 @@ +The web server +============== + +ASAB provides a web server in a :py:mod:`asab.web` module. +This module offers an integration of a :py:mod:`aiohttp` `web server `_. + +1. Before you start, make sure that you have :py:mod:`aiohttp` module installed. + +.. code-block:: bash + + $ pip3 install aiohttp + +2. The following code creates a simple web server application + +.. code:: python + + #!/usr/bin/env python3 + import asab + import asab.web + import aiohttp + + class MyApplication(asab.Application): + + def __init__(self): + super().__init__() + + # Load the ASAB Web module + self.add_module(asab.web.Module) + + # Locate the ASAB Web service + websvc = self.get_service("asab.WebService") + + # Create the Web container + container = asab.web.WebContainer(websvc, 'my:web', config={"listen": "0.0.0.0:8080"}) + + # Add a route to the handler + container.WebApp.router.add_get('/hello', self.hello) + + # This is the web request handler + async def hello(self, request): + return aiohttp.web.Response(text='Hello!\n') + + if __name__ == '__main__': + app = MyApplication() + app.run() + +3. Test it with `curl` + +.. code-block:: bash + + $ curl http://localhost:8080/hello + Hello! + + +Web Service +----------- + +.. py:currentmodule:: asab.web.service + +.. py:class:: WebService + +Service location example: + +.. code:: python + + from asab.web import Module + self.add_module(Module) + svc = self.get_service("asab.WebService") + + +Configuration +------------- + +The default configuration of the `web` container in ASAB is following: + +.. code:: ini + + [web] + listen=0.0.0.0:8080 + + +Multiple listening interfaces can be specified: + +.. code:: ini + + [web] + listen: + 0.0.0.0:8080 + :: 8080 + + +Multiple listening interfaces, one with HTTPS (TLS/SSL) can be specified: + +.. code:: ini + + [web] + listen: + 0.0.0.0 8080 + :: 8080 + 0.0.0.0 8443 ssl:web + + [ssl:web] + cert=... + key=... + ... + + +Multiple interfaces, one with HTTPS (inline): + + +.. code:: ini + + [web] + listen: + 0.0.0.0 8080 + :: 8080 + 0.0.0.0 8443 ssl + + # The SSL parameters are inside of the WebContainer section + cert=... + key=... + ... + + +Other available options are: + + * `backlog` + * `rootdir` + * `servertokens` (default value `full`) + * `cors` + * `cors_preflight_paths` + + +TLS/SSL paramereters: + + * `cert` + * `key` + * `password` + * `cafile` + * `capath` + * `ciphers` + * `dh_params` + * `verify_mode`: one of `CERT_NONE`, `CERT_OPTIONAL` or `CERT_REQUIRED` + * `check_hostname` + * `options` + +Sessions +-------- + +ASAB Web Service provides an implementation of the web sessions. + + +.. py:currentmodule:: asab.web.session + +.. py:class:: ServiceWebSession + +TODO: ... + + +.. py:function:: session_middleware(storage) + +TODO: ... + diff --git a/old_docs/asab/web/restapidocs.rst b/old_docs/asab/web/restapidocs.rst new file mode 100644 index 000000000..cb7625522 --- /dev/null +++ b/old_docs/asab/web/restapidocs.rst @@ -0,0 +1,122 @@ +REST API Docs +============== + +ASAB's API service generates a `Swagger documentation `_ which automatically shows all +of your endpoints and you can add summaries, descriptions, tags and more. + +If you want Authorization in Swagger docs, you will need an OpenIDConnect endpoint. + +In your microservice +-------------------- + +First you need to initialize the API Service: + +.. code-block:: python + + # Initialize API service + self.ApiService = asab.api.ApiService(self) + + # Introduce Web to API Service + self.ApiService.initialize_web() + +After initializing the API Service a **/doc** endpoint will become available. You will notice +that some or none of your endpoints have summaries, tags or descriptions. + +That's because you need to add a docstring to your endpoint method: + +.. code-block:: python + + async def endpoint(self, request): + """ + Summary looks like this and takes the first line from docstring. + + Description of what this endpoint does. + + --- + tags: [asab.mymicroservice] + """ + +Also by adding a docstring to your ASAB Application, a description will be automatically added to the top of the Swagger docs: + +.. code-block:: python + + class TutorialApp(asab.Application): + """ + TutorialApp is the best microservice in the world! + + The description supports HTML tags + """ + +Authorization in Swagger +------------------------ + +Authorization requires making an OpenIDConnect endpoint with an Authorization and Token endpoint (like with using `SeaCat Auth `_). + +After your endpoint has authorization, `here's an example `_, +add the Authorization and Token endpoints into your `config <#configuration>`_. + +For the authorization bearer token to be added to the request, a scope is needed to be put into the security parameter in a docstring. +It does not matter what it is called or if it exists, but it's needed to be there. But "`- oAuth:`" always needs to be there. + +.. code-block:: python + + @asab.web.authz.required("resource:topsecret") + async def top_secret_endpoint(self, request): + """ + Top secret! + + --- + tags: [asab.coolestmicroservice] + security: + - oAuth: + - read + """ + +After setting up Authorization, a green `Authorize` button should appear in the Swagger docs. + +Configuration +------------- + +For authorization you will need to add a `authorizationUrl` and `tokenUrl`: + +.. code-block:: ini + + [asab:doc] + authorizationUrl=http://localhost:8080/openidconnect/authorize + tokenUrl=http://localhost:8080/openidconnect/token + +If you have an endpoint that requires a scope, you can add it with the configuration file: + +.. code-block:: ini + + [asab:doc] + scopes=read,write + + +Tags +---- + +You can label your handler methods with custom tags. +These tags are used for grouping and sorting your endpoints on the documentation page. + +.. code:: python + + async def my_method(self, request): + """ + --- + tags: ['custom tag 1', 'custom tag 2', 'custom tag 3'] + """ + +(Remember to use exactly three dashes on the separate line and put tags in array with `[]` even if you want to have a single tag). + +If there is no custom tag defined, the tag name is automatically set to be `module_name`. If you do not want to use custom tags but still would like to sort the routes, you can configure the options in the config file: + +.. code-block:: ini + + [asab:doc] + default_route_tag=class_name + +There are two options for `default_route_tag`: + +- `module_name`: All tags without custom name are displayed with the name of the **module** where the handler is defined. +- `class_name`: All tags without custom name are displayed with the name of the **class** where the handler is defined. diff --git a/old_docs/asab/zookeeper.rst b/old_docs/asab/zookeeper.rst new file mode 100644 index 000000000..33e0d310e --- /dev/null +++ b/old_docs/asab/zookeeper.rst @@ -0,0 +1,173 @@ +.. _zookeeper-ref: + +Zookeeper +========= + +.. py:currentmodule:: asab.zookeeper + +The `asab.zookeeper` is a `Apache Zookeeper `_ asynchronous client based on `Kazoo `_ library. + +Apache ZooKeeper is a distributed coordination service that provides a hierarchical key-value data store, called a znode tree, to store and manage configuration, coordination, and synchronization data. The znode tree is similar to a file system tree, where each znode is like a file or a directory. + +Apache ZooKeeper can be used to design microservices in a stateless manner by managing and coordinating the state information between microservices. In this design, each microservice does not store any state information, but instead relies on ZooKeeper for state management. + + +Zookeeper container +------------------- + +A Zookeeper container represents a connectivity to Apache Zookeeper server(s). +The application can operate multiple instances of Zookeeper container. + + +This code illustrates the typical way how to create Zookeeper container: + +.. code:: python + + import asab.zookeeper + + class MyApplication(asab.Application): + + def __init__(self): + ... + + # Load the ASAB Zookeeper module + self.add_module(asab.zookeeper.Module) + + # Initialize ZooKeeper Service + self.ZooKeeperService = self.get_service("asab.ZooKeeperService") + + # Create the Zookeeper container + self.ZooKeeperContainer = asab.zookeeper.ZooKeeperContainer(self.ZooKeeperService) + + # Subscribe to Zookeeper container ready event + self.PubSub.subscribe("ZooKeeperContainer.state/CONNECTED!", self._on_zk_connected) + + + async def _on_zk_connected(self, event_name, zookeeper): + if zookeeper != self.ZooKeeperContainer: + return + + print("Connected to Zookeeper!") + + + +.. autoclass:: ZooKeeperContainer + +Specifications are obtained from: + +1. `z_path` argument, which is Zookeeper URL (see below) +2. the configuration section specified by `config_section_name` argument +3. `ASAB_ZOOKEEPER_SERVERS` environment variable + +The `z_path` argument has precedence over config but the implementation will look +at configuration if `z_path` URL is missing completely or partially. +Also, if configuration section doesn't provide information about servers, `ASAB_ZOOKEEPER_SERVERS` environment variable is used. + + +Example of configuration section +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code:: ini + + [zookeeper] + servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 + path=myfolder + + +Example of `ASAB_ZOOKEEPER_SERVERS` environment variable +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code:: ini + + ASAB_ZOOKEEPER_SERVERS=zookeeper-1:2181,zookeeper-2:2181 + + +Supported types of `z_path` URLs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +1. Absolute URL + + `zookeeper://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/etc/configs/file1` + + + The URL contains all information for a connectivity. + + +2. URL without servers with absolute path + + `zookeepers:///etc/configs/file1` + + In this case the relative url is expanded as follows: + `zookeeper://{zookeeper_servers}/etc/configs/file1` + + Where `{zookeeper_servers}` is substituted with the `servers` entry of the [zookeeper] configuration file section. + + +3. URL without servers with relative path + + `zookeeper:./etc/configs/file1` + + In this case, the relative URL is expanded as follows: + `zookeper://{zookeeper_servers}/{zookeeper_path}/etc/configs/file1` + + Where {zookeeper_servers} is substituted with the `servers` entry of the [zookeeper] configuration file section and + {zookeeper_path} is substituted with the "path" entry of the [zookeeper] configuration file section. + + + +.. automethod:: ZooKeeperContainer.is_connected + + +Reading from Zookeeeper +----------------------- + +.. automethod:: ZooKeeperContainer.get_children + +.. automethod:: ZooKeeperContainer.get_data + +.. automethod:: ZooKeeperContainer.get_raw_data + + +Advertisement into Zookeeper +---------------------------- + +.. automethod:: ZooKeeperContainer.advertise + + +PubSub messages +--------------- + +.. option:: ZooKeeperContainer.state/CONNECTED! + +.. option:: ZooKeeperContainer.state/LOST! + +.. option:: ZooKeeperContainer.state/SUSPENDED! + +When a Zookeeper connection is first created, it is in the LOST state. +After a connection is established it transitions to the CONNECTED state. +If any connection issues come up or if it needs to connect to a different Zookeeper cluster node, it will transition to SUSPENDED to let you know that commands cannot currently be run. +The connection will also be lost if the Zookeeper node is no longer part of the quorum, resulting in a SUSPENDED state. + +Upon re-establishing a connection the client could transition to LOST if the session has expired, or CONNECTED if the session is still valid. + +For mor info, visit: https://kazoo.readthedocs.io/en/latest/basic_usage.html#understanding-kazoo-states + + +Kazoo +----- + +Kazoo is the synchronous Python library for Apache Zookeeper. + +It can be used directly for a more complicated tasks. +Kazoo `client` is accessible at `ZooKeeperContainer.ZooKeeper.Client`. +Synchronous methods of Kazoo client must be executed using `ProactorService`. + +Here is the example: + +.. code:: python + + def write_to_zk(): + self.ZooKeeperContainer.ZooKeeper.Client.create(path, data, sequence=True, ephemeral=True, makepath=True) + + await self.ZooKeeperContainer.ZooKeeper.ProactorService.execute(write_to_zk) + diff --git a/doc/conf.py b/old_docs/conf.py similarity index 100% rename from doc/conf.py rename to old_docs/conf.py diff --git a/old_docs/get-started.rst b/old_docs/get-started.rst new file mode 100644 index 000000000..1b47c6110 --- /dev/null +++ b/old_docs/get-started.rst @@ -0,0 +1,107 @@ +Getting started +=============== + +Make sure you have both `pip `_ and at +least version 3.7 of Python before starting. ASAB uses the new ``async``/``await`` +syntax, so earlier versions of python won't work. + +1. Install ASAB: + +.. code:: bash + + $ pip3 install asab + + +2. Create a file called ``main.py`` with the following code: + + +.. code:: python + + #!/usr/bin/env python3 + import asab + + class MyApplication(asab.Application): + async def main(self): + print("Hello world") + + if __name__ == '__main__': + app = MyApplication() + app.run() + + +3. Run the server: + +.. code:: bash + + $ python3 main.py + Hello world + +You are now successfully runinng an ASAB application server. + + +4. Stop the application by ``Control-C``. + +Note: The ASAB is designed around a so-called `event loop `_. +It is meant primarily for server architectures. +For that reason, it doesn't terminate and continue running and serving eventual requests. + + + +Going into details +------------------ + +.. code:: python + + #!/usr/bin/env python3 + +ASAB application uses a Python 3.7+. +This is specified a by hashbang line at the very begginig of the file, on the line number 1. + + +.. code:: python + + import asab + + +ASAB is included from as `asab` module via an import statement. + + +.. code:: python + + class MyApplication(asab.Application): + +Every ASAB Application needs to have an application object. +It is a singleton; it means that the application must create and operate precisely one instance of the application. +ASAB provides the base :any:`Application` class that you need to inherit from to implement your custom application class. + + +.. code:: python + + async def main(self): + print("Hello world") + +The :any:`Application.main()` method is one of the application lifecycle methods, that you can override to implement desired application functionality. +The `main` method is a coroutine, so that you can await any tasks etc. in fully asynchronous way. +This method is called when ASAB application is executed and initialized. +The lifecycle stage is called "runtime". + +In this example, we just print a message to a screen. + + + +.. code:: python + + if __name__ == '__main__': + app = MyApplication() + app.run() + +This part of the code is executed when the Python program is launched. +It creates the application object and executes the :any:`Application.run()` method. +This is a standard way of how ASAB application is started. + + +Next steps +---------- + +Check out tutorials about how to build ASAB based :doc:`web server `. + diff --git a/doc/index.rst b/old_docs/index.rst similarity index 100% rename from doc/index.rst rename to old_docs/index.rst diff --git a/doc/make.bat b/old_docs/make.bat similarity index 100% rename from doc/make.bat rename to old_docs/make.bat diff --git a/doc/openapi3-swagger.jpg b/old_docs/openapi3-swagger.jpg similarity index 100% rename from doc/openapi3-swagger.jpg rename to old_docs/openapi3-swagger.jpg diff --git a/old_docs/web/chapter1.rst b/old_docs/web/chapter1.rst new file mode 100644 index 000000000..bb8bb0c47 --- /dev/null +++ b/old_docs/web/chapter1.rst @@ -0,0 +1,69 @@ +Web Server Tutorial +=================== + +Create a simple web server with ASAB. + + +The code +-------- + +.. include:: web1/app.py + :code: python + +| To start the application, store above code in a file ``app.py``. +| Execute ``$ python3 ./app.py`` to run it. + +The ASAB web server is now available at http://localhost:8080/. + + +Deeper look +----------- + +**ASAB Application** + +.. code:: python + + #!/usr/bin/env python3 + import asab.web.rest + + class MyWebApplication(asab.Application): + + def __init__(self): + super().__init__() + + if __name__ == '__main__': + app = MyWebApplication() + app.run() + +This is a ASAB code that declares the application class and runs it. + + +**Create a Web server** + +The ``asab.web`` module provides a ``create_web_server()`` function that simplifies creation of the Web server in the ASAB application. + + +.. code:: python + + web = asab.web.create_web_server(self) + + +**Install the handler** + +.. code:: python + + web.add_get('/hello', self.hello) + + ... + + async def hello(self, request): + return asab.web.rest.json_response( + request, + data="Hello, world!\n" + ) + + +The handler method ``hello()`` is installed at the web server at ``/hello`` endpoint. +HTTP method is ``GET``. + +It means that if you access the web server with a path ``/hello``, it will be handled by a ``hello(...)`` method. A handler method must be a coroutine. diff --git a/old_docs/web/chapter2.rst b/old_docs/web/chapter2.rst new file mode 100644 index 000000000..7817a5154 --- /dev/null +++ b/old_docs/web/chapter2.rst @@ -0,0 +1,629 @@ +Create microservice with REST API +================================= + +With this tutorial, you will create a basic ASAB microservice that provides a REST HTTP API. +This microservice will implement Create, Read, Update and Delete functionality, in another words CRUD. +MongoDB will be used as the database. + + +Prerequisites +------------- + +1. Python version 3.6 or later +2. Asynchronous Server App Boilerplate (ASAB) version 20.3 or later +3. MongoDB instance +4. Postman + +.. note:: + We will use Docker to run MongoDB. Docker installation is not covered in this tutorial, but there are scores of good ones online should you run into any trouble. If you're not familiar with Docker yet, it is a great opportunity to start (https://www.docker.com/get-started/). + + Otherwise, you can install MongoDB following one of these tutorials: https://www.mongodb.com/docs/manual/installation/ + + +Components +---------- + +The microservice consists of several modules (aka Python files). +These modules are as follows (and also indicate the file structure) and will be discussed in more detail in the respective sections below, going from top to bottom: + +.. code:: + + . + └── myrestapi.py + ─── myrestapi + └── __init__.py + ─── app.py + ─── tutorial + └── handler.py + └── service.py + + + +MongoDB +------- + +To make things simple, let's use a Docker image. + +Pull this image: +https://hub.docker.com/_/mongo + +You can simply use the command below to run it. +If you choose to run the instance without a password, +don't forget to adjust the related **asab.Config** in `./myrestapi/app.py`. + +.. code:: bash + + docker run -d -p 27017:27017 \ + -e MONGO_INITDB_ROOT_USERNAME=user \ + -e MONGO_INITDB_ROOT_PASSWORD=secret \ + mongo + + +Postman +------- + +We use Postman to test the webservice REST API. + +You can download it here: +https://www.postman.com/downloads/ + +The Postman is fairly straightforward to use. +You can create your collection of HTTP requests, save them, or automatically generate documentation. + + +myrestapi.py +------------ + +This is where everything starts. +Begin with the shebang line, which tells the executing operating system **python** should execute this program. + +.. code:: python + + #!/usr/bin/env python3 + +Imports follow. All you need here is the application. It is called **TutorialApp**: + +.. code:: python + + from myrestapi import TutorialApp + +Next, instantiate an application class `TutorialApp` in the __main__ of the application, and run it: + +.. code:: python + + if __name__ == '__main__': + app = TutorialApp() + app.run() + + + +app.py +------ + +`./myrestapi/app.py` + +Define the application class `TutorialApp`. + +Imports first: + +.. code:: python + + import asab + import asab.web + import asab.web.rest + import asab.storage + + +Add some default configuration: + +.. code:: python + + asab.Config.add_defaults( + { + 'asab:storage': { + 'type': 'mongodb', + 'mongodb_uri': 'mongodb://mongouser:mongopassword@mongoipaddress:27017', + 'mongodb_database': 'mongodatabase' + }, + }) + +.. note:: + To make things more simple, Mongo credentials are stored here as a default configuration. + Usually, you provide your app with a configuration file using `-c` commandline option. + Learn more in section :ref:`configuration-ref`. + +Next, describe the class, it inherits from the basic ASAB Application class, +but you need to expand it a little: + +.. code:: python + + class TutorialApp(asab.Application): + + def __init__(self): + super().__init__() + # Register modules + self.add_module(asab.web.Module) + self.add_module(asab.storage.Module) + + # Locate the web service + self.WebService = self.get_service("asab.WebService") + self.WebContainer = asab.web.WebContainer( + self.WebService, "web" + ) + self.WebContainer.WebApp.middlewares.append( + asab.web.rest.JsonExceptionMiddleware + ) + + # Initialize services + from .tutorial.handler import CRUDWebHandler + from .tutorial.service import CRUDService + self.CRUDService = CRUDService(self) + self.CRUDWebHandler = CRUDWebHandler( + self, self.CRUDService + ) + + +\_\_init\_\_.py +---------------- + +`./myrestapi/__init__.py` + +Init file is needed so myrestapi will work as a module. +Just import the TutorialApp. + +.. code:: python + + from .app import TutorialApp + + __all__ = [ + "TutorialApp", + ] + + +handler.py +---------- + +`./myrestapi/tutorial/handler.py` + +The handler is where HTTP Rest calls are handled and transformed into the actual (internal) service calls. +From another perspective, the handler should contain only translation between REST calls and the service interface. +No actual 'business logic' should be here. +It is strongly suggested to build these CRUD methods one by one and test them straight away. +If you haven't set up your database test instance yet, now is the time to do it. + +As usual, we start by importing modules: + +.. code:: python + + import asab + import asab.web.rest + + +Let's start with two methods - `create` and `read` which allow us to write into database and check the record. + +.. code:: python + + class CRUDWebHandler(object): + def __init__(self, app, mongo_svc): + self.CRUDService = mongo_svc + web_app = app.WebContainer.WebApp + web_app.router.add_put( + '/crud-myrestapi/{collection}', + self.create + ) + web_app.router.add_get( + '/crud-myrestapi/{collection}/{id}', + self.read + ) + + + @asab.web.rest.json_schema_handler({ + 'type': 'object', + 'properties': { + '_id': {'type': 'string'}, + 'field1': {'type': 'string'}, + 'field2': {'type': 'number'}, + 'field3': {'type': 'number'} + }}) + async def create(self, request, *, json_data): + collection = request.match_info['collection'] + + result = await self.CRUDService.create( + collection, json_data + ) + if result: + return asab.web.rest.json_response( + request, {"result": "OK"} + ) + else: + asab.web.rest.json_response( + request, {"result": "FAILED"} + ) + + + async def read(self, request): + collection = request.match_info['collection'] + key = request.match_info['id'] + response = await self.CRUDService.read( + collection, key + ) + return asab.web.rest.json_response( + request, response + ) + +The handler only accepts the incoming requests and returns appropriate responses. +All of the "logic", be it the specifics of the database connection, additional validations and other +operations take place in the CRUDService. + +POST and PUT requests typically come with data in their body. +Providing your `WebContainer` with `JsonExceptionMiddleware` enables you to validate a JSON input using `@asab.web.rest.json_schema_handler` decorator and JSON schema (https://json-schema.org/). + +.. note:: + ASAB WebServer is built on top of the aiohttp library. + For further details please visit https://docs.aiohttp.org/en/stable/index.html. + + +service.py +---------- + +`./myrestapi/tutorial/service.py` + +As mentioned above, this is where the inner workings of the microservice request processing are. +Let's start as usual, by importing the desired modules: + +.. code:: python + + import asab + import asab.storage.exceptions + + +We want to start logging in here: + +.. code:: python + + import logging + # + + L = logging.getLogger(__name__) + + # + + +Now define the CRUDService class which inherits from the `asab.Service` class. + + +.. note:: + `asab.Service` is a lightweight yet powerful abstract class providing your object with 3 functionalities: + + - Name of the `asab.Service` is registered in the app and can be called from the `app` object anywhere in your code. + - `asab.Service` class implements `initialize()` and `finalize()` coroutines which help you to handle asynchronous operations in init and exit time of your application. + - `asab.Service` registers application object as `self.App` for you. + + +.. code:: python + + class CRUDService(asab.Service): + + def __init__(self, app, service_name='crud.CRUDService'): + super().__init__(app, service_name) + self.MongoDBStorageService = app.get_service( + "asab.StorageService" + ) + + async def create(self, collection, json_data): + obj_id = json_data.pop("_id") + + cre = self.MongoDBStorageService.upsertor( + collection, obj_id + ) + + for key, value in zip( + json_data.keys(), json_data.values() + ): + cre.set(key, value) + + try: + await cre.execute() + return "OK" + except asab.storage.exceptions.DuplicateError: + L.warning( + "Document you are trying to create already exists." + ) + return None + + async def read(self, collection, obj_id): + response = await self.MongoDBStorageService.get( + collection, obj_id + ) + return response + + +`asab.StorageService` initialized in `app.py` as part of the `asab.storage.Module` enables connection to MongoDB. +Further on, two methods provide the handler with the desired functionalities. + +Now test it! +------------ + +The application is implicitly running on an **8080** port. +Open the Postman and set a new request. + +Try the PUT method: + +.. code:: + + 127.0.0.1:8080/crud-myrestapi/movie + +Insert into the request body: + +.. code:: + + { + "_id": "1", + "field1": "something new", + "field2": 5555, + "field3": 44424 + } + +When there's a record in your database, try to read it! +For example with this GET request: + +.. code:: + + 127.0.0.1:8080/crud-myrestapi/movie/1 + +Is your response with a 200 status code? Does it return desired data? + + +.. note:: + + **TROUBLESHOOTING** + + **ERROR** + + .. code:: + + ModuleNotFoundError: No module named 'pymongo.mongo_replica_set_client' + + Try: + + .. code:: + + pip install motor + + + + **ERROR** + + .. code:: + + OSError: [Errno 98] error while attempting to bind on address ('0.0.0.0', 8080): address already in use + + Try to kill process listening on 8080 or add [web] section into configuration: + + .. code:: + + asab.Config.add_defaults( + { + 'asab:storage': { + 'type': 'mongodb', + 'mongodb_uri': 'mongodb://mongouser:mongopassword@mongoipaddress:27017', + 'mongodb_database': 'mongodatabase' + }, + 'web': { + 'listen': '0.0.0.0 8081' + } + }) + + + **ERROR** + + No error at all, no response either. + + Try to check the Mongo database credentials. Do your credentials in the configuration in `app.py` fit the ones you entered when running the Mongo Docker image? + + +Up and running! Congratulation on your first ASAB microservice! + +Oh, wait... + +**C**, **R**... What about **Update** and **Delete** you ask? + +You already know everything to add the next functionality! Accept the challenge and try it yourself! Or check out the code below. + + +Update and Delete +----------------- + +**handler.py** + +`./myrestapi/tutorial/handler.py` + +.. code:: python + + import asab + import asab.web.rest + + + class CRUDWebHandler(object): + def __init__(self, app, mongo_svc): + self.CRUDService = mongo_svc + web_app = app.WebContainer.WebApp + web_app.router.add_put( + '/crud-myrestapi/{collection}', + self.create + ) + web_app.router.add_get( + '/crud-myrestapi/{collection}/{id}', + self.read + ) + web_app.router.add_put( + '/crud-myrestapi/{collection}/{id}', + self.update + ) + web_app.router.add_delete( + '/crud-myrestapi/{collection}/{id}', + self.delete + ) + + + @asab.web.rest.json_schema_handler({ + 'type': 'object', + 'properties': { + '_id': {'type': 'string'}, + 'field1': {'type': 'string'}, + 'field2': {'type': 'number'}, + 'field3': {'type': 'number'} + }}) + async def create(self, request, *, json_data): + collection = request.match_info['collection'] + + result = await self.CRUDService.create( + collection, json_data + ) + if result: + return asab.web.rest.json_response( + request, {"result": "OK"} + ) + else: + asab.web.rest.json_response( + request, {"result": "FAILED"} + ) + + + async def read(self, request): + collection = request.match_info['collection'] + key = request.match_info['id'] + response = await self.CRUDService.read( + collection, key + ) + return asab.web.rest.json_response( + request, response + ) + + + @asab.web.rest.json_schema_handler({ + 'type': 'object', + 'properties': { + '_id': {'type': 'string'}, + 'field1': {'type': 'string'}, + 'field2': {'type': 'number'}, + 'field3': {'type': 'number'} + }}) + async def update(self, request, *, json_data): + collection = request.match_info['collection'] + obj_id = request.match_info["id"] + + result = await self.CRUDService.update( + collection, obj_id, json_data + ) + if result: + return asab.web.rest.json_response( + request, {"result": "OK"} + ) + else: + asab.web.rest.json_response( + request, {"result": "FAILED"} + ) + + + async def delete(self, request): + collection = request.match_info['collection'] + obj_id = request.match_info["id"] + result = await self.CRUDService.delete( + collection, obj_id + ) + + if result: + return asab.web.rest.json_response( + request, {"result": "OK"} + ) + else: + asab.web.rest.json_response( + request, {"result": "FAILED"} + ) + + +**service.py** + +`./myrestapi/tutorial/service.py` + +.. code:: python + + import asab + import asab.storage.exceptions + + import logging + # + + L = logging.getLogger(__name__) + + # + + + class CRUDService(asab.Service): + + def __init__(self, app, service_name='crud.CRUDService'): + super().__init__(app, service_name) + self.MongoDBStorageService = app.get_service( + "asab.StorageService" + ) + + async def create(self, collection, json_data): + obj_id = json_data.pop("_id") + + cre = self.MongoDBStorageService.upsertor( + collection, obj_id + ) + + for key, value in zip( + json_data.keys(), json_data.values() + ): + cre.set(key, value) + + try: + await cre.execute() + return "OK" + except asab.storage.exceptions.DuplicateError: + L.warning( + "Document you are trying to create already exists." + ) + return None + + + async def read(self, collection, obj_id): + response = await self.MongoDBStorageService.get( + collection, obj_id + ) + return response + + + async def update(self, collection, obj_id, document): + original = await self.read( + collection, obj_id + ) + + cre = self.MongoDBStorageService.upsertor( + collection, original["_id"], original["_v"] + ) + + for key, value in zip( + document.keys(), document.values() + ): + cre.set(key, value) + + try: + await cre.execute() + return "OK" + + except KeyError: + return None + + + async def delete(self, collection, obj_id): + try: + await self.MongoDBStorageService.delete( + collection, obj_id + ) + return True + except KeyError: + return False diff --git a/doc/tutorial/web/web1/app.py b/old_docs/web/web1/app.py similarity index 100% rename from doc/tutorial/web/web1/app.py rename to old_docs/web/web1/app.py diff --git a/doc/tutorial/web/web2/asab.webservice.md b/old_docs/web/web2/asab.webservice.md similarity index 100% rename from doc/tutorial/web/web2/asab.webservice.md rename to old_docs/web/web2/asab.webservice.md diff --git a/transfer_docs.py b/transfer_docs.py new file mode 100644 index 000000000..286f8313f --- /dev/null +++ b/transfer_docs.py @@ -0,0 +1,13 @@ +import pathlib +import os + +old_files = pathlib.Path.cwd() / "old_docs" / "web" + +for old_file_rst in old_files.iterdir(): + print(old_file_rst.stem) + new_file_md = pathlib.Path.cwd() / "docs" / "tutorial" / f"{old_file_rst.stem}.md" + print(new_file_md) + + command = f"pandoc -f rst -t markdown {old_file_rst} -o {new_file_md}" + + os.system(command) From 68818868fafe3f7b266dadbb2a79af210ad168b6 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 22 Jun 2023 16:54:09 +0200 Subject: [PATCH 002/154] Add plugin for python syntax highlighting --- docs/index.md | 25 ++++++------------------- mkdocs.yml | 9 +++++++++ 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/docs/index.md b/docs/index.md index ec4a7b6f8..57419f4fd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,31 +1,18 @@ -# Asynchronous Server Application Boilerplate\'s documentation +# Asynchronous Server Application Boilerplate's documentation - -Asynchronous Server App Boilerplate (or ASAB for short) is a -microservice platform for Python 3.7+ and [asyncio]{.title-ref}. ASAB -aims to minimize the amount of code that needs to be written when -building a microservice or an application server. ASAB is fully -asynchronous using async/await syntax from Python 3, making your code -modern, non-blocking, speedy and hence scalable. We make every effort to -build ASAB container-friendly so that you can deploy ASAB-based +Asynchronous Server App Boilerplate (or ASAB for short) is a microservice platform for Python 3.7+ and [asyncio](https://docs.python.org/3/library/asyncio.html). ASAB aims to minimize the amount of code that needs to be written when building a microservice or an application server. ASAB is fully asynchronous using async/await syntax from Python 3, making your code modern, non-blocking, speedy and hence scalable. We make every effort to build ASAB container-friendly so that you can deploy ASAB-based microservice via Docker or Kubernetes in a breeze. -ASAB is free and open-source software, available under BSD licence. It -means that anyone is freely licenced to use, copy, study, and change the -software in any way, and the source code is openly shared so that people -could voluntarily improve the design of the software. Anyone can (and is -encouraged to) use ASAB in his or her projects, for free. A current -maintainer is a [TeskaLabs Ltd](https://teskalabs.com) company. +ASAB is free and open-source software, available under BSD licence. It means that anyone is freely licenced to use, copy, study, and change the software in any way, and the source code is openly shared so that people could voluntarily improve the design of the software. Anyone can (and is encouraged to) use ASAB in his or her projects, for free. A current maintainer is a [TeskaLabs Ltd](https://teskalabs.com) company. -ASAB is developed [on GitHub](https://github.com/TeskaLabs/asab/). -Contributions are welcome! +ASAB is developed [on GitHub](https://github.com/TeskaLabs/asab/). Contributions are welcome! # ASAB is designed to be powerful yet simple - Here is a complete example of a fully working microservice: -``` python +```python + import asab class MyApplication(asab.Application): diff --git a/mkdocs.yml b/mkdocs.yml index 982cdf07f..5146a9e45 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -6,6 +6,15 @@ theme: plugins: - mkdocstrings +markdown_extensions: + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences + nav: - Introduction: index.md From 90a82315cdb801e6aeb58d4cccb1272fc0268452 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 22 Jun 2023 22:03:31 +0200 Subject: [PATCH 003/154] Add settings for tabs indentation --- asab/storage/service.py | 30 +++-- docs/TODO.md | 23 ++++ docs/asab/index.md | 47 ------- docs/{ => explanation}/admin/command-line.md | 0 docs/{ => explanation}/admin/containers.md | 0 docs/{ => explanation}/admin/install.md | 0 docs/{ => explanation}/admin/systemd.md | 0 docs/{ => explanation}/asab/alert.md | 0 docs/{ => explanation}/asab/application.md | 0 docs/{ => explanation}/asab/config.md | 0 docs/{ => explanation}/asab/library.md | 0 docs/{ => explanation}/asab/log.md | 0 docs/{ => explanation}/asab/metrics.md | 4 + docs/{ => explanation}/asab/module.md | 0 docs/{ => explanation}/asab/pubsub.md | 16 ++- docs/{ => explanation}/asab/service.md | 0 docs/{ => explanation}/asab/storage.md | 0 docs/{ => explanation}/asab/various.md | 0 docs/{ => explanation}/asab/web/auth.md | 0 docs/{ => explanation}/asab/web/cors.md | 0 docs/{ => explanation}/asab/web/index.md | 0 .../{ => explanation}/asab/web/restapidocs.md | 0 docs/{ => explanation}/asab/zookeeper.md | 0 docs/index.md | 56 ++++++-- docs/reference/application.md | 1 + docs/reference/config.md | 1 + docs/reference/library.md | 1 + docs/reference/log.md | 1 + docs/reference/metrics.md | 1 + docs/reference/module.md | 0 docs/reference/storage/abc.md | 5 + docs/reference/storage/elasticsearch.md | 1 + docs/reference/storage/inmemory.md | 1 + docs/reference/storage/mongodb.md | 1 + docs/{tutorial => tutorials}/chapter1.md | 0 docs/{tutorial => tutorials}/chapter2.md | 0 docs/{ => tutorials}/get-started.md | 69 +++++----- mkdocs.yml | 121 ++++++++++++++---- 38 files changed, 245 insertions(+), 134 deletions(-) create mode 100644 docs/TODO.md delete mode 100644 docs/asab/index.md rename docs/{ => explanation}/admin/command-line.md (100%) rename docs/{ => explanation}/admin/containers.md (100%) rename docs/{ => explanation}/admin/install.md (100%) rename docs/{ => explanation}/admin/systemd.md (100%) rename docs/{ => explanation}/asab/alert.md (100%) rename docs/{ => explanation}/asab/application.md (100%) rename docs/{ => explanation}/asab/config.md (100%) rename docs/{ => explanation}/asab/library.md (100%) rename docs/{ => explanation}/asab/log.md (100%) rename docs/{ => explanation}/asab/metrics.md (99%) rename docs/{ => explanation}/asab/module.md (100%) rename docs/{ => explanation}/asab/pubsub.md (97%) rename docs/{ => explanation}/asab/service.md (100%) rename docs/{ => explanation}/asab/storage.md (100%) rename docs/{ => explanation}/asab/various.md (100%) rename docs/{ => explanation}/asab/web/auth.md (100%) rename docs/{ => explanation}/asab/web/cors.md (100%) rename docs/{ => explanation}/asab/web/index.md (100%) rename docs/{ => explanation}/asab/web/restapidocs.md (100%) rename docs/{ => explanation}/asab/zookeeper.md (100%) create mode 100644 docs/reference/application.md create mode 100644 docs/reference/config.md create mode 100644 docs/reference/library.md create mode 100644 docs/reference/log.md create mode 100644 docs/reference/metrics.md create mode 100644 docs/reference/module.md create mode 100644 docs/reference/storage/abc.md create mode 100644 docs/reference/storage/elasticsearch.md create mode 100644 docs/reference/storage/inmemory.md create mode 100644 docs/reference/storage/mongodb.md rename docs/{tutorial => tutorials}/chapter1.md (100%) rename docs/{tutorial => tutorials}/chapter2.md (100%) rename docs/{ => tutorials}/get-started.md (59%) diff --git a/asab/storage/service.py b/asab/storage/service.py index 96a9e956f..8d88e33a0 100644 --- a/asab/storage/service.py +++ b/asab/storage/service.py @@ -23,6 +23,10 @@ class StorageServiceABC(asab.Service): + """ + An abstract class for the Storage Service. + + """ def __init__(self, app, service_name): super().__init__(app, service_name) @@ -49,7 +53,7 @@ def __init__(self, app, service_name): @abc.abstractmethod - def upsertor(self, collection: str, obj_id=None, version: int = 0): + def upsertor(self, collection: str, obj_id=None, version: int = 0) -> None: """ Create an upsertor object for the specified collection. @@ -58,9 +62,11 @@ def upsertor(self, collection: str, obj_id=None, version: int = 0): If you want to insert a new object with a specific `obj_id`, specify `obj_id` and set a version to 0. - If there will be a colliding object already stored in a storage, `execute()` method will fail on `DuplicateError`. - :param collection: Name of collection to work with - :param obj_id: Primary identification of an object in the storage (e.g. primary key) - :param version: Specify a current version of the object and hence prevent byzantine faults. \ + Args: + + collection (str): Name of collection to work with + obj_id: Primary identification of an object in the storage (e.g. primary key) + version (int): Specify a current version of the object and hence prevent byzantine faults. \ You should always read the version from the storage upfront, prior using an upsertor. \ That creates a soft lock on the record. It means that if the object is updated by other \ component in meanwhile, your upsertor will fail and you should retry the whole operation. \ @@ -74,12 +80,16 @@ async def get(self, collection: str, obj_id, decrypt=None) -> dict: """ Get object from collection by its ID. - :param collection: Collection to get from. - :type collection: str - :param obj_id: Object identification. - :param decrypt: Set of fields to decrypt. - :return: The object retrieved from a storage. - :raise KeyError: Raised if `obj_id` is not found in `collection`. + Args: + collection (str): Collection to get from. + obj_id: Object identification. + decrypt (bool): Set of fields to decrypt. + + Returns: + (dict) The object retrieved from a storage. + + Raises: + KeyError: Raised if `obj_id` is not found in `collection`. """ pass diff --git a/docs/TODO.md b/docs/TODO.md new file mode 100644 index 000000000..3cc6069c2 --- /dev/null +++ b/docs/TODO.md @@ -0,0 +1,23 @@ +# TODOs + +https://squidfunk.github.io/mkdocs-material/reference/code-blocks/ + +https://realpython.com/python-project-documentation-with-mkdocs/#step-1-set-up-your-environment-for-building-documentation + +https://diataxis.fr/ + +https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings + +- plán: začni indexem a zkus prvních několik souborů převést do čitelné podoby +- pozor na # vs ---- kazí strukturu vyhledávání +- reference na moduly? + +# Tutorials + +# How to guides + +# Explanation + +# Reference + +copy-paste sections \ No newline at end of file diff --git a/docs/asab/index.md b/docs/asab/index.md deleted file mode 100644 index 9f63ae730..000000000 --- a/docs/asab/index.md +++ /dev/null @@ -1,47 +0,0 @@ -Asynchronous Server Application Boilerplate\'s documentation -============================================================ - -Asynchronous Server App Boilerplate (or ASAB for short) is a -microservice platform for Python 3.7+ and [asyncio]{.title-ref}. ASAB -aims to minimize the amount of code that needs to be written when -building a microservice or an application server. ASAB is fully -asynchronous using async/await syntax from Python 3, making your code -modern, non-blocking, speedy and hence scalable. We make every effort to -build ASAB container-friendly so that you can deploy ASAB-based -microservice via Docker or Kubernetes in a breeze. - -ASAB is free and open-source software, available under BSD licence. It -means that anyone is freely licenced to use, copy, study, and change the -software in any way, and the source code is openly shared so that people -could voluntarily improve the design of the software. Anyone can (and is -encouraged to) use ASAB in his or her projects, for free. A current -maintainer is a [TeskaLabs Ltd](https://teskalabs.com) company. - -ASAB is developed [on GitHub](https://github.com/TeskaLabs/asab/). -Contributions are welcome! - -ASAB is designed to be powerful yet simple ------------------------------------------- - -Here is a complete example of a fully working microservice: - -``` {.python} -import asab - -class MyApplication(asab.Application): - async def main(self): - print("Hello world!") - self.stop() - -if __name__ == "__main__": - app = MyApplication() - app.run() -``` - -ASAB is the right choice when ------------------------------ - -> - using Python 3.7+. -> - building the microservice or the application server. -> - utilizing asynchronous I/O (aka -> [asyncio](https://docs.python.org/3/library/asyncio.html)). diff --git a/docs/admin/command-line.md b/docs/explanation/admin/command-line.md similarity index 100% rename from docs/admin/command-line.md rename to docs/explanation/admin/command-line.md diff --git a/docs/admin/containers.md b/docs/explanation/admin/containers.md similarity index 100% rename from docs/admin/containers.md rename to docs/explanation/admin/containers.md diff --git a/docs/admin/install.md b/docs/explanation/admin/install.md similarity index 100% rename from docs/admin/install.md rename to docs/explanation/admin/install.md diff --git a/docs/admin/systemd.md b/docs/explanation/admin/systemd.md similarity index 100% rename from docs/admin/systemd.md rename to docs/explanation/admin/systemd.md diff --git a/docs/asab/alert.md b/docs/explanation/asab/alert.md similarity index 100% rename from docs/asab/alert.md rename to docs/explanation/asab/alert.md diff --git a/docs/asab/application.md b/docs/explanation/asab/application.md similarity index 100% rename from docs/asab/application.md rename to docs/explanation/asab/application.md diff --git a/docs/asab/config.md b/docs/explanation/asab/config.md similarity index 100% rename from docs/asab/config.md rename to docs/explanation/asab/config.md diff --git a/docs/asab/library.md b/docs/explanation/asab/library.md similarity index 100% rename from docs/asab/library.md rename to docs/explanation/asab/library.md diff --git a/docs/asab/log.md b/docs/explanation/asab/log.md similarity index 100% rename from docs/asab/log.md rename to docs/explanation/asab/log.md diff --git a/docs/asab/metrics.md b/docs/explanation/asab/metrics.md similarity index 99% rename from docs/asab/metrics.md rename to docs/explanation/asab/metrics.md index e48a0c169..0493ea69d 100644 --- a/docs/asab/metrics.md +++ b/docs/explanation/asab/metrics.md @@ -630,3 +630,7 @@ HistogramWithDynamicTags set xxx xxx + +# Reference + +::: asab.metrics diff --git a/docs/asab/module.md b/docs/explanation/asab/module.md similarity index 100% rename from docs/asab/module.md rename to docs/explanation/asab/module.md diff --git a/docs/asab/pubsub.md b/docs/explanation/asab/pubsub.md similarity index 97% rename from docs/asab/pubsub.md rename to docs/explanation/asab/pubsub.md index d46f657ed..a8bd534ff 100644 --- a/docs/asab/pubsub.md +++ b/docs/explanation/asab/pubsub.md @@ -1,4 +1,4 @@ -Publish-Subscribe {#pubsub_page} +Publish-Subscribe {Xpubsub_page} ================= Publish--subscribe is a messaging pattern where senders of messages, @@ -75,14 +75,14 @@ class MyClass(object): async def on_tick(self, message_type): print(message_type) - @asab.subscribe("Application.exit!") + @asab.subscribe("Application.exit!")python def on_exit(self, message_type): print(message_type) ``` Unsubscribe from a message delivery. -# TODO: autoclass members="" undoc-members=""} +X TODO: autoclass members="" undoc-members=""} asab.Subscriber xxx @@ -92,7 +92,7 @@ generator]{.title-ref}. The example of the subscriber object usage in ``` {.python} async def my_coroutine(self): - # Subscribe for a two application events + X Subscribe for a two application events subscriber = asab.Subscriber( self.PubSub, "Application.tick!", @@ -153,7 +153,7 @@ Application-wide PubSub The ASAB provides the application-wide Publish-Subscribe message bus. -### Well-Known Messages +XXX Well-Known Messages This is a list of well-known messages, that are published on a `Application.PubSub` by ASAB itself. @@ -272,3 +272,9 @@ This sets the housekeeping time to 7:30 PM UTC and the time limit to 9:00 PM UTC. The time must be written in the format \'HH:MM\'. Remind yourself that the time is set to UTC, so you should be careful when operating in a different timezone. + + +Reference +--------- + +::: asab.pubsub \ No newline at end of file diff --git a/docs/asab/service.md b/docs/explanation/asab/service.md similarity index 100% rename from docs/asab/service.md rename to docs/explanation/asab/service.md diff --git a/docs/asab/storage.md b/docs/explanation/asab/storage.md similarity index 100% rename from docs/asab/storage.md rename to docs/explanation/asab/storage.md diff --git a/docs/asab/various.md b/docs/explanation/asab/various.md similarity index 100% rename from docs/asab/various.md rename to docs/explanation/asab/various.md diff --git a/docs/asab/web/auth.md b/docs/explanation/asab/web/auth.md similarity index 100% rename from docs/asab/web/auth.md rename to docs/explanation/asab/web/auth.md diff --git a/docs/asab/web/cors.md b/docs/explanation/asab/web/cors.md similarity index 100% rename from docs/asab/web/cors.md rename to docs/explanation/asab/web/cors.md diff --git a/docs/asab/web/index.md b/docs/explanation/asab/web/index.md similarity index 100% rename from docs/asab/web/index.md rename to docs/explanation/asab/web/index.md diff --git a/docs/asab/web/restapidocs.md b/docs/explanation/asab/web/restapidocs.md similarity index 100% rename from docs/asab/web/restapidocs.md rename to docs/explanation/asab/web/restapidocs.md diff --git a/docs/asab/zookeeper.md b/docs/explanation/asab/zookeeper.md similarity index 100% rename from docs/asab/zookeeper.md rename to docs/explanation/asab/zookeeper.md diff --git a/docs/index.md b/docs/index.md index 57419f4fd..0b6331f91 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,18 +1,41 @@ -# Asynchronous Server Application Boilerplate's documentation +--- +title: My Document +summary: A brief description of my document. +authors: + - Waylan Limberg + - Tom Christie +date: 2018-07-10 +some_url: https://example.com +--- -Asynchronous Server App Boilerplate (or ASAB for short) is a microservice platform for Python 3.7+ and [asyncio](https://docs.python.org/3/library/asyncio.html). ASAB aims to minimize the amount of code that needs to be written when building a microservice or an application server. ASAB is fully asynchronous using async/await syntax from Python 3, making your code modern, non-blocking, speedy and hence scalable. We make every effort to build ASAB container-friendly so that you can deploy ASAB-based +Asynchronous Server Application Boilerplate +=========================================== + +Asynchronous Server App Boilerplate (or ASAB for short) is a +microservice platform for Python 3.7+ and [asyncio](https://docs.python.org/3/library/asyncio.html). ASAB +aims to minimize the amount of code that needs to be written when +building a microservice or an application server. ASAB is fully +asynchronous using async/await syntax from Python 3, making your code +modern, non-blocking, speedy and hence scalable. We make every effort to +build ASAB container-friendly so that you can deploy ASAB-based microservice via Docker or Kubernetes in a breeze. -ASAB is free and open-source software, available under BSD licence. It means that anyone is freely licenced to use, copy, study, and change the software in any way, and the source code is openly shared so that people could voluntarily improve the design of the software. Anyone can (and is encouraged to) use ASAB in his or her projects, for free. A current maintainer is a [TeskaLabs Ltd](https://teskalabs.com) company. +ASAB is free and open-source software, available under BSD licence. It +means that anyone is freely licenced to use, copy, study, and change the +software in any way, and the source code is openly shared so that people +could voluntarily improve the design of the software. Anyone can (and is +encouraged to) use ASAB in his or her projects, for free. A current +maintainer is a [TeskaLabs Ltd](https://teskalabs.com) company. -ASAB is developed [on GitHub](https://github.com/TeskaLabs/asab/). Contributions are welcome! +ASAB is developed [on GitHub](https://github.com/TeskaLabs/asab/). +Contributions are welcome! -# ASAB is designed to be powerful yet simple +ASAB is designed to be powerful yet simple +------------------------------------------ Here is a complete example of a fully working microservice: -```python - +``` python title="hello_world.py" import asab class MyApplication(asab.Application): @@ -25,8 +48,19 @@ if __name__ == "__main__": app.run() ``` -# ASAB is the right choice when +ASAB is the right choice when +----------------------------- + +> - using Python 3.7+. +> - building the microservice or the application server. +> - utilizing asynchronous I/O (aka +> [asyncio](https://docs.python.org/3/library/asyncio.html)). + +``` yaml +theme: + features: + - content.code.annotate # (1) +``` -- using Python 3.7+. -- building the microservice or the application server. -- utilizing asynchronous I/O (aka [asyncio](https://docs.python.org/3/library/asyncio.html)). +1. :man_raising_hand: I'm a code annotation! I can contain `code`, __formatted + text__, images, ... basically anything that can be written in Markdown. \ No newline at end of file diff --git a/docs/reference/application.md b/docs/reference/application.md new file mode 100644 index 000000000..7459c7636 --- /dev/null +++ b/docs/reference/application.md @@ -0,0 +1 @@ +::: asab.application \ No newline at end of file diff --git a/docs/reference/config.md b/docs/reference/config.md new file mode 100644 index 000000000..37b64b1dd --- /dev/null +++ b/docs/reference/config.md @@ -0,0 +1 @@ +::: asab.config \ No newline at end of file diff --git a/docs/reference/library.md b/docs/reference/library.md new file mode 100644 index 000000000..469b4b808 --- /dev/null +++ b/docs/reference/library.md @@ -0,0 +1 @@ +::: asab.library \ No newline at end of file diff --git a/docs/reference/log.md b/docs/reference/log.md new file mode 100644 index 000000000..3a5afed73 --- /dev/null +++ b/docs/reference/log.md @@ -0,0 +1 @@ +::: asab.log \ No newline at end of file diff --git a/docs/reference/metrics.md b/docs/reference/metrics.md new file mode 100644 index 000000000..bcae9445f --- /dev/null +++ b/docs/reference/metrics.md @@ -0,0 +1 @@ +::: asab.metrics.service \ No newline at end of file diff --git a/docs/reference/module.md b/docs/reference/module.md new file mode 100644 index 000000000..e69de29bb diff --git a/docs/reference/storage/abc.md b/docs/reference/storage/abc.md new file mode 100644 index 000000000..027b958fa --- /dev/null +++ b/docs/reference/storage/abc.md @@ -0,0 +1,5 @@ +::: asab.storage.service + +::: asab.storage.upsertor + +::: asab.storage.exceptions \ No newline at end of file diff --git a/docs/reference/storage/elasticsearch.md b/docs/reference/storage/elasticsearch.md new file mode 100644 index 000000000..4ce51fabf --- /dev/null +++ b/docs/reference/storage/elasticsearch.md @@ -0,0 +1 @@ +::: asab.storage.elasticsearch \ No newline at end of file diff --git a/docs/reference/storage/inmemory.md b/docs/reference/storage/inmemory.md new file mode 100644 index 000000000..f09abae0a --- /dev/null +++ b/docs/reference/storage/inmemory.md @@ -0,0 +1 @@ +::: asab.storage.inmemory \ No newline at end of file diff --git a/docs/reference/storage/mongodb.md b/docs/reference/storage/mongodb.md new file mode 100644 index 000000000..dcbfe5302 --- /dev/null +++ b/docs/reference/storage/mongodb.md @@ -0,0 +1 @@ +::: asab.storage.mongodb \ No newline at end of file diff --git a/docs/tutorial/chapter1.md b/docs/tutorials/chapter1.md similarity index 100% rename from docs/tutorial/chapter1.md rename to docs/tutorials/chapter1.md diff --git a/docs/tutorial/chapter2.md b/docs/tutorials/chapter2.md similarity index 100% rename from docs/tutorial/chapter2.md rename to docs/tutorials/chapter2.md diff --git a/docs/get-started.md b/docs/tutorials/get-started.md similarity index 59% rename from docs/get-started.md rename to docs/tutorials/get-started.md index 4fa1f908e..ac661d525 100644 --- a/docs/get-started.md +++ b/docs/tutorials/get-started.md @@ -3,73 +3,77 @@ Getting started Make sure you have both [pip](https://pip.pypa.io/en/stable/installing/) and at least version 3.7 of Python before starting. ASAB uses the new -`async`/`await` syntax, so earlier versions of python won\'t work. +`async`/`await` syntax, so earlier versions of python won't work. 1. Install ASAB: -``` {.bash} -$ pip3 install asab -``` + ``` console + pip3 install asab + ``` 2. Create a file called `main.py` with the following code: -``` {.python} -#!/usr/bin/env python3 -import asab + ``` python + #!/usr/bin/env python3 + import asab -class MyApplication(asab.Application): - async def main(self): - print("Hello world") + class MyApplication(asab.Application): + async def main(self): + print("Hello world") -if __name__ == '__main__': - app = MyApplication() - app.run() -``` + if __name__ == '__main__': + app = MyApplication() + app.run() + ``` 3. Run the server: -``` {.bash} -$ python3 main.py -Hello world -``` + ``` console + python3 main.py + ``` + + and you should've seen the output: + ``` + Hello world! + ``` -You are now successfully runinng an ASAB application server. + You are now successfully runinng an ASAB application server. 4. Stop the application by `Control-C`. -Note: The ASAB is designed around a so-called [event -loop](https://en.wikipedia.org/wiki/Event_loop). It is meant primarily -for server architectures. For that reason, it doesn\'t terminate and -continue running and serving eventual requests. + Note: The ASAB is designed around a so-called [event + loop](https://en.wikipedia.org/wiki/Event_loop). It is meant primarily + for server architectures. For that reason, it doesn't terminate and + continue running and serving eventual requests. Going into details ------------------ -``` {.python} +``` python #!/usr/bin/env python3 ``` ASAB application uses a Python 3.7+. This is specified a by hashbang line at the very begginig of the file, on the line number 1. -``` {.python} +``` python import asab ``` -ASAB is included from as [asab]{.title-ref} module via an import +ASAB is included from as [asab][asab] module via an import statement. -``` {.python} +``` python class MyApplication(asab.Application): ``` Every ASAB Application needs to have an application object. It is a singleton; it means that the application must create and operate precisely one instance of the application. ASAB provides the base -`Application`{.interpreted-text role="any"} class that you need to +[asab.Application] class that you need to inherit from to implement your custom application class. -``` {.python} +``` python async def main(self): print("Hello world") ``` @@ -79,11 +83,11 @@ the application lifecycle methods, that you can override to implement desired application functionality. The [main]{.title-ref} method is a coroutine, so that you can await any tasks etc. in fully asynchronous way. This method is called when ASAB application is executed and -initialized. The lifecycle stage is called \"runtime\". +initialized. The lifecycle stage is called "runtime". In this example, we just print a message to a screen. -``` {.python} +``` python if __name__ == '__main__': app = MyApplication() app.run() @@ -97,5 +101,4 @@ standard way of how ASAB application is started. Next steps ---------- -Check out tutorials about how to build ASAB based -`web server `{.interpreted-text role="doc"}. +Check out tutorials about how to build ASAB based [web server][tutorial/chapter1.md]. diff --git a/mkdocs.yml b/mkdocs.yml index 5146a9e45..59e153cb8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,10 +1,61 @@ -site_name: My Docs +site_name: ASAB theme: name: "material" + features: + - content.code.copy + - content.code.select + - content.code.annotate # + - navigation.tabs + - navigation.footer + - navigation.indexes + - attr_list + - admonition + - pymdownx.details + - pymdownx.superfences + - pymdownx.critic + - pymdownx.caret + - pymdownx.keys + - pymdownx.mark + - pymdownx.tilde + - def_list + # - pymdownx.tasklist: + # custom_checkbox: true + # - pymdownx.emoji: + # emoji_index: !!python/name:materialx.emoji.twemoji + # emoji_generator: !!python/name:materialx.emoji.to_svg + + + font: + text: Verdana + + palette: + - scheme: default + primary: blue + accent: blue + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - scheme: slate + primary: blue + accent: yellow + toggle: + icon: material/brightness-4 + name: Switch to light mode + + plugins: - - mkdocstrings + - mkdocstrings: + markdown_extensions: + - pymdownx.superfences: + custom_fences: + - name: code + class: code + config: + default_handler: python + python: + use_indentation: '\t' markdown_extensions: - pymdownx.highlight: @@ -18,35 +69,49 @@ markdown_extensions: nav: - Introduction: index.md - - Get Started: - - get-started.md - - tutorial/chapter1.md - - tutorial/chapter2.md + - Installation: explanation/admin/install.md + + + - Tutorials: + - tutorials/get-started.md + - tutorials/chapter1.md + - tutorials/chapter2.md + + - Explanation: + + - Services: + - explanation/asab/web/index.md + - explanation/asab/web/auth.md + - explanation/asab/web/cors.md + - explanation/asab/web/restapidocs.md + - explanation/asab/library.md - - Services: - - asab/web/index.md - - asab/web/auth.md - - asab/web/cors.md - - asab/web/restapidocs.md - - asab/library.md + - Reference: + - explanation/asab/application.md + - explanation/asab/config.md + - explanation/asab/log.md + - explanation/asab/metrics.md + - explanation/asab/module.md + - explanation/asab/pubsub.md + - explanation/asab/service.md + - explanation/asab/storage.md + - explanation/asab/various.md + - explanation/asab/zookeeper.md - Reference: - - asab/application.md - - asab/config.md - - asab/log.md - - asab/metrics.md - - asab/module.md - - asab/pubsub.md - - asab/service.md - - asab/storage.md - - asab/various.md - - asab/zookeeper.md + # - reference/application.md + # - reference/config.md + # - reference/library.md + # - reference/log.md + # - reference/metrics.md + # - reference/module.md + - Storage: + - Abstract class: reference/storage/abc.md + - ElasticSearch: reference/storage/elasticsearch.md - Administration: - - admin/command-line.md - - admin/containers.md - - admin/install.md - - admin/systemd.md + - explanation/admin/command-line.md + - explanation/admin/containers.md + - explanation/admin/systemd.md - - asab/index.md - - asab/alert.md \ No newline at end of file + - explanation/asab/alert.md \ No newline at end of file From 6dc654b3be5f077184c13585e1d2150749a9a263 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 22 Jun 2023 22:39:02 +0200 Subject: [PATCH 004/154] Create reference section for the Storage Service --- asab/storage/exceptions.py | 3 ++ asab/storage/mongodb.py | 26 +++---------- asab/storage/service.py | 55 +++++++++++++++++----------- asab/storage/upsertor.py | 24 +++++++----- docs/reference/storage/abc.md | 5 --- docs/reference/storage/exceptions.md | 1 + docs/reference/storage/service.md | 1 + docs/reference/storage/upsertor.md | 1 + mkdocs.yml | 6 ++- 9 files changed, 63 insertions(+), 59 deletions(-) delete mode 100644 docs/reference/storage/abc.md create mode 100644 docs/reference/storage/exceptions.md create mode 100644 docs/reference/storage/service.md create mode 100644 docs/reference/storage/upsertor.md diff --git a/asab/storage/exceptions.py b/asab/storage/exceptions.py index c303e3f45..ae0bec9f6 100644 --- a/asab/storage/exceptions.py +++ b/asab/storage/exceptions.py @@ -1,5 +1,8 @@ class DuplicateError(RuntimeError): + """ + Raised when the key already exists in the same document. + """ def __init__(self, message, obj_id, key_value=None): super().__init__(message) diff --git a/asab/storage/mongodb.py b/asab/storage/mongodb.py index ff9340047..d0e7b57a4 100644 --- a/asab/storage/mongodb.py +++ b/asab/storage/mongodb.py @@ -53,16 +53,6 @@ async def get(self, collection: str, obj_id, decrypt=None) -> dict: async def get_by(self, collection: str, key: str, value, decrypt=None) -> dict: - """ - Get object from collection by its key and value. - - :param collection: Collection to get from. - :param key: Key to filter on. - :param value: Value to filter on. - :param decrypt: Set of fields to decrypt. - :return: The object retrieved from a storage - :raise KeyError: Raised if object{key: value} cannot be found in `collection`. - """ coll = self.Database[collection] ret = await coll.find_one({key: value}) if ret is None: @@ -78,8 +68,11 @@ async def collection(self, collection: str) -> motor.motor_asyncio.AsyncIOMotorC """ Get collection. Useful for custom operations. - :param collection: Collection to get. - :return: AsyncIOMotorCollection object connected to the queried database. + Args: + collection: Collection to get. + + Returns: + `AsyncIOMotorCollection` object connected to the queried database. Examples: @@ -95,15 +88,6 @@ async def collection(self, collection: str) -> motor.motor_asyncio.AsyncIOMotorC async def delete(self, collection: str, obj_id): - """ - Delete object from `collection` by its `obj_id` - - :param collection: Collection to delete from - :param obj_id: Object identification - :return: `obj_id` -- Object identification - - :raise KeyError: Raised if `obj_id` cannot be found in `collection`. - """ coll = self.Database[collection] ret = await coll.find_one_and_delete({'_id': obj_id}) if ret is None: diff --git a/asab/storage/service.py b/asab/storage/service.py index 8d88e33a0..0ffc6fd89 100644 --- a/asab/storage/service.py +++ b/asab/storage/service.py @@ -86,7 +86,7 @@ async def get(self, collection: str, obj_id, decrypt=None) -> dict: decrypt (bool): Set of fields to decrypt. Returns: - (dict) The object retrieved from a storage. + The object retrieved from a storage. Raises: KeyError: Raised if `obj_id` is not found in `collection`. @@ -95,15 +95,18 @@ async def get(self, collection: str, obj_id, decrypt=None) -> dict: @abc.abstractmethod - async def get_by(self, collection: str, key: str, value, decrypt=None): + async def get_by(self, collection: str, key: str, value, decrypt=None) -> dict: """ Get object from collection by its key and value. - :param collection: Collection to get from - :param key: Key to filter on - :param value: Value to filter on - :param decrypt: Set of fields to decrypt - :return: The object retrieved from a storage + Args: + collection: Collection to get from + key: Key to filter on + value: Value to filter on + decrypt: Set of fields to decrypt + + Returns: + The object retrieved from a storage. Raises: KeyError: If object {key: value} not found in `collection` @@ -116,13 +119,15 @@ async def delete(self, collection: str, obj_id): """ Delete object from collection. - :param collection: Collection to get from - :type collection: str - :param obj_id: Object identification + Args: + collection: Collection to get from + obj_id: Object identification - :return: ID of the deleted object. + Returns: + ID of the deleted object. - :raise KeyError: Raised when obj_id cannot be found in collection. + Raises: + KeyError: Raised when obj_id cannot be found in collection. """ pass @@ -131,13 +136,15 @@ def aes_encrypt(self, raw: bytes, iv: bytes = None) -> bytes: """ Take an array of bytes and encrypt it using AES-CBC. - :param raw: The data to be encrypted. - :type raw: bytes - :param iv: AES-CBC initialization vector, 16 bytes long. If left empty, a random 16-byte array will be used. - :type iv: bytes - :return: The encrypted data. + Args: + raw: The data to be encrypted. + iv: AES-CBC initialization vector, 16 bytes long. If left empty, a random 16-byte array will be used. - :raise TypeError: The data are not in binary format. + Returns: + The encrypted data. + + Raises: + TypeError: The data are not in binary format. """ block_size = cryptography.hazmat.primitives.ciphers.algorithms.AES.block_size // 8 @@ -173,10 +180,11 @@ def aes_decrypt(self, encrypted: bytes) -> bytes: """ Decrypt encrypted data using AES-CBC. - :param encrypted: The encrypted data to decrypt. - It must start with b"$aes-cbc$" prefix, followed by one-block-long initialization vector. - :type encrypted: bytes - :return: The decrypted data. + Args: + encrypted: The encrypted data to decrypt. It must start with b"$aes-cbc$" prefix, followed by one-block-long initialization vector. + + Returns: + The decrypted data. """ block_size = cryptography.hazmat.primitives.ciphers.algorithms.AES.block_size // 8 @@ -211,5 +219,8 @@ def aes_decrypt(self, encrypted: bytes) -> bytes: def encryption_enabled(self) -> bool: """ Check if AESKey is not empty. + + Returns: + True if AESKey is not empty. """ return self._AESKey is not None diff --git a/asab/storage/upsertor.py b/asab/storage/upsertor.py index af5d695bb..e1c4ea1b3 100644 --- a/asab/storage/upsertor.py +++ b/asab/storage/upsertor.py @@ -54,7 +54,8 @@ def generate_id(cls) -> bytes: """ Generate a unique ID string using a combination of a random UUID and a SHA-256 hash. - :return: A string representation of the generated ID. + Returns: + A string representation of the generated ID. """ m = hashlib.sha256() m.update(uuid.uuid4().bytes) @@ -65,12 +66,11 @@ def set(self, objField, value, encrypt=False, encrypt_iv=None): """ Add key and value to the upsertor. - :param objField: Key of the object. - :param value: Value of the object. - :param encrypt: Allow encryption. Defaults to False. - :type encrypt: bool - :param encrypt_iv: Custom initialization vector. Defaults to None. - :type encrypt_iv: bool + Args: + objField: Key of the object. + value: Value of the object. + encrypt: Allow encryption. + encrypt_iv: Custom initialization vector. """ if encrypt: @@ -122,15 +122,19 @@ async def execute(self, custom_data: typing.Optional[dict] = None, event_type: t """ Commit upsertor data to the storage. Afterwards, send a webhook request with upsertion details. - :param custom_data: Custom execution data. Included in webhook payload. - :param event_type: Event type included in webhook payload. - :raise DuplicateError: Raised if thre is a colliding object already stored in a storage. + Args: + custom_data: Custom execution data. Included in webhook payload. + event_type: Event type included in webhook payload. + + Raises: + DuplicateError: Raised if there is a colliding object already stored in a storage. """ pass async def webhook(self, data: dict): + # TODO: add docstring assert self.Storage.WebhookURIs is not None json_dump = asab.web.rest.json.JSONDumper(pretty=False)(data) for uri in self.Storage.WebhookURIs: diff --git a/docs/reference/storage/abc.md b/docs/reference/storage/abc.md deleted file mode 100644 index 027b958fa..000000000 --- a/docs/reference/storage/abc.md +++ /dev/null @@ -1,5 +0,0 @@ -::: asab.storage.service - -::: asab.storage.upsertor - -::: asab.storage.exceptions \ No newline at end of file diff --git a/docs/reference/storage/exceptions.md b/docs/reference/storage/exceptions.md new file mode 100644 index 000000000..3ceeb8c23 --- /dev/null +++ b/docs/reference/storage/exceptions.md @@ -0,0 +1 @@ +::: asab.storage.exceptions \ No newline at end of file diff --git a/docs/reference/storage/service.md b/docs/reference/storage/service.md new file mode 100644 index 000000000..1fcf2966b --- /dev/null +++ b/docs/reference/storage/service.md @@ -0,0 +1 @@ +::: asab.storage.service \ No newline at end of file diff --git a/docs/reference/storage/upsertor.md b/docs/reference/storage/upsertor.md new file mode 100644 index 000000000..adf0a2071 --- /dev/null +++ b/docs/reference/storage/upsertor.md @@ -0,0 +1 @@ +::: asab.storage.upsertor diff --git a/mkdocs.yml b/mkdocs.yml index 59e153cb8..c84317ca5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -106,8 +106,12 @@ nav: # - reference/metrics.md # - reference/module.md - Storage: - - Abstract class: reference/storage/abc.md + - StorageService: reference/storage/service.md + - Upsertor: reference/storage/upsertor.md + - Exceptions: reference/storage/exceptions.md - ElasticSearch: reference/storage/elasticsearch.md + - MongoDB: reference/storage/mongodb.md + - In-Memory: reference/storage/inmemory.md - Administration: - explanation/admin/command-line.md From 1f8f395f7a1449d2de96727db6104a14eeacd527 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 22 Jun 2023 22:51:17 +0200 Subject: [PATCH 005/154] Rename Explanation -> Topics --- .../admin/command-line.md | 0 .../admin/containers.md | 0 docs/{explanation => topics}/admin/install.md | 0 docs/{explanation => topics}/admin/systemd.md | 0 docs/{explanation => topics}/asab/alert.md | 0 .../asab/application.md | 0 docs/{explanation => topics}/asab/config.md | 0 docs/{explanation => topics}/asab/library.md | 0 docs/{explanation => topics}/asab/log.md | 0 docs/{explanation => topics}/asab/metrics.md | 0 docs/{explanation => topics}/asab/module.md | 0 docs/{explanation => topics}/asab/pubsub.md | 0 docs/{explanation => topics}/asab/service.md | 0 docs/{explanation => topics}/asab/storage.md | 190 ++---------------- docs/{explanation => topics}/asab/various.md | 0 docs/{explanation => topics}/asab/web/auth.md | 0 docs/{explanation => topics}/asab/web/cors.md | 0 .../{explanation => topics}/asab/web/index.md | 0 .../asab/web/restapidocs.md | 0 .../{explanation => topics}/asab/zookeeper.md | 0 mkdocs.yml | 48 +++-- 21 files changed, 39 insertions(+), 199 deletions(-) rename docs/{explanation => topics}/admin/command-line.md (100%) rename docs/{explanation => topics}/admin/containers.md (100%) rename docs/{explanation => topics}/admin/install.md (100%) rename docs/{explanation => topics}/admin/systemd.md (100%) rename docs/{explanation => topics}/asab/alert.md (100%) rename docs/{explanation => topics}/asab/application.md (100%) rename docs/{explanation => topics}/asab/config.md (100%) rename docs/{explanation => topics}/asab/library.md (100%) rename docs/{explanation => topics}/asab/log.md (100%) rename docs/{explanation => topics}/asab/metrics.md (100%) rename docs/{explanation => topics}/asab/module.md (100%) rename docs/{explanation => topics}/asab/pubsub.md (100%) rename docs/{explanation => topics}/asab/service.md (100%) rename docs/{explanation => topics}/asab/storage.md (78%) rename docs/{explanation => topics}/asab/various.md (100%) rename docs/{explanation => topics}/asab/web/auth.md (100%) rename docs/{explanation => topics}/asab/web/cors.md (100%) rename docs/{explanation => topics}/asab/web/index.md (100%) rename docs/{explanation => topics}/asab/web/restapidocs.md (100%) rename docs/{explanation => topics}/asab/zookeeper.md (100%) diff --git a/docs/explanation/admin/command-line.md b/docs/topics/admin/command-line.md similarity index 100% rename from docs/explanation/admin/command-line.md rename to docs/topics/admin/command-line.md diff --git a/docs/explanation/admin/containers.md b/docs/topics/admin/containers.md similarity index 100% rename from docs/explanation/admin/containers.md rename to docs/topics/admin/containers.md diff --git a/docs/explanation/admin/install.md b/docs/topics/admin/install.md similarity index 100% rename from docs/explanation/admin/install.md rename to docs/topics/admin/install.md diff --git a/docs/explanation/admin/systemd.md b/docs/topics/admin/systemd.md similarity index 100% rename from docs/explanation/admin/systemd.md rename to docs/topics/admin/systemd.md diff --git a/docs/explanation/asab/alert.md b/docs/topics/asab/alert.md similarity index 100% rename from docs/explanation/asab/alert.md rename to docs/topics/asab/alert.md diff --git a/docs/explanation/asab/application.md b/docs/topics/asab/application.md similarity index 100% rename from docs/explanation/asab/application.md rename to docs/topics/asab/application.md diff --git a/docs/explanation/asab/config.md b/docs/topics/asab/config.md similarity index 100% rename from docs/explanation/asab/config.md rename to docs/topics/asab/config.md diff --git a/docs/explanation/asab/library.md b/docs/topics/asab/library.md similarity index 100% rename from docs/explanation/asab/library.md rename to docs/topics/asab/library.md diff --git a/docs/explanation/asab/log.md b/docs/topics/asab/log.md similarity index 100% rename from docs/explanation/asab/log.md rename to docs/topics/asab/log.md diff --git a/docs/explanation/asab/metrics.md b/docs/topics/asab/metrics.md similarity index 100% rename from docs/explanation/asab/metrics.md rename to docs/topics/asab/metrics.md diff --git a/docs/explanation/asab/module.md b/docs/topics/asab/module.md similarity index 100% rename from docs/explanation/asab/module.md rename to docs/topics/asab/module.md diff --git a/docs/explanation/asab/pubsub.md b/docs/topics/asab/pubsub.md similarity index 100% rename from docs/explanation/asab/pubsub.md rename to docs/topics/asab/pubsub.md diff --git a/docs/explanation/asab/service.md b/docs/topics/asab/service.md similarity index 100% rename from docs/explanation/asab/service.md rename to docs/topics/asab/service.md diff --git a/docs/explanation/asab/storage.md b/docs/topics/asab/storage.md similarity index 78% rename from docs/explanation/asab/storage.md rename to docs/topics/asab/storage.md index 9cde30414..0d20cef9e 100644 --- a/docs/explanation/asab/storage.md +++ b/docs/topics/asab/storage.md @@ -1,11 +1,7 @@ -xxx {.currentmodule} -asab.storage -xxx - Storage ======= -The ASAB\'s Storage Service supports data storage in-memory or in +The ASAB's Storage Service supports data storage in-memory or in dedicated document databases, including [MongoDB](https://www.mongodb.com/) and [ElasticSearch](https://www.elastic.co/). @@ -16,12 +12,12 @@ Configuration First, specify the storage type in the configuration. The options for the storage type are: -- \`inmemory\`: Collects data directly in memory -- \`mongodb\`: Collects data using MongoDB database. Depends on +- `inmemory`: Collects data directly in memory +- `mongodb`: Collects data using MongoDB database. Depends on [pymongo](https://pymongo.readthedocs.io/en/stable/) and [motor](https://motor.readthedocs.io/en/stable/api-asyncio/asyncio_motor_collection.html) libraries. -- \`elasticsearch\`: Collects data using ElasticSearch database. +- `elasticsearch`: Collects data using ElasticSearch database. Depends on [aiohttp](https://docs.aiohttp.org/en/latest/) library. Storage Service provides a unified interface for accessing and @@ -33,7 +29,7 @@ type=mongodb ``` For accessing the storage, simply add -[asab.storage.Module]{.title-ref}\` when initializing and register the +[asab.storage.Module]{.title-ref}` when initializing and register the service. ``` {.python} @@ -63,7 +59,7 @@ u = storage.upsertor("test-collection") The `StorageService.upsertor()`{.interpreted-text role="func"} method creates an upsertor object associated with the specified collection. It takes [collection]{.title-ref} as an argument and can have two -parameters [obj\_id]{.title-ref} and [version]{.title-ref}, which are +parameters [obj_id]{.title-ref} and [version]{.title-ref}, which are used for getting an existing object by its ID and version. ### Inserting an object @@ -85,7 +81,7 @@ object_id = await u.execute() ``` The [Upsertor.execute()]{.title-ref} method has optional parameters -[custom\_data]{.title-ref} and [event\_type]{.title-ref}, which are used +[custom_data]{.title-ref} and [event_type]{.title-ref}, which are used for webhook requests. ``` {.python} @@ -100,7 +96,7 @@ object_id = await u.execute( For getting a single object, use `StorageService.get()`{.interpreted-text role="func"} coroutine method that takes two arguments [collection]{.title-ref} and -[obj\_id]{.title-ref} and finds an object by its ID in collection. +[obj_id]{.title-ref} and finds an object by its ID in collection. ``` {.python} obj = await storage.get(collection="test-collection", obj_id=object_id) @@ -128,7 +124,7 @@ xxx ### Updating an object For updating an object, first obtain the upsertor specifying its -[obj\_id]{.title-ref} and [version]{.title-ref}. +[obj_id]{.title-ref} and [version]{.title-ref}. ``` {.python} u = storage.upsertor( @@ -157,7 +153,7 @@ object_id = await u.execute() For deleting an object from database, use the `StorageService.delete()`{.interpreted-text role="func"} coroutine method which takes arguments [collection]{.title-ref} and -[obj\_id]{.title-ref}, deletes the object and returns its ID. +[obj_id]{.title-ref}, deletes the object and returns its ID. ``` {.python} deleted_id = await u.delete("test-collection", object_id) @@ -215,7 +211,7 @@ class provides in addition two methods, The method `StorageService.get_by()`{.interpreted-text role="func"} is used in the same way as `StorageService.get()`{.interpreted-text role="func"} except that it takes the arguments [key]{.title-ref} and -[value]{.title-ref} instead of [obj\_id]{.title-ref}. +[value]{.title-ref} instead of [obj_id]{.title-ref}. ``` {.python} obj = await storage.get_by(database="test-collection", key="key", value="value") @@ -224,7 +220,7 @@ obj = await storage.get_by(database="test-collection", key="key", value="value") The method `collection()`{.interpreted-text role="func"} is used for accessing the database directly. It takes [collection]{.title-ref} as the argument and returns -[motor.motor\_asyncio.AsyncIOMotorCollection]{.title-ref} object, which +[motor.motor_asyncio.AsyncIOMotorCollection]{.title-ref} object, which can be used for calling MongoDB directives. ``` {.python} @@ -294,7 +290,7 @@ recommended to keep it in [a separate configuration file](https://asab.readthedocs.io/en/latest/asab/config.html#including-other-configuration-files) that is not exposed anywhere publicly. -The actual binary AES Key is obtained from the [aes\_key]{.title-ref} +The actual binary AES Key is obtained from the [aes_key]{.title-ref} specified in the config file by encoding and hashing it using the standard [hashlib](https://docs.python.org/3/library/hashlib.html) algorithms, so do not worry about the length and type of the key. @@ -322,7 +318,7 @@ object_id = await u.execute() The `StorageService.get()`{.interpreted-text role="func"} coroutine method has an optional parameter [decrypt]{.title-ref} which takes an -`iterable` object (i.e. a list, tuple, set, \...) with the names of keys +`iterable` object (i.e. a list, tuple, set, ...) with the names of keys whose values are to be decrypted. ``` {.python} @@ -342,7 +338,7 @@ Note xxx Data that has been encrypted can be identified by the prefix -\"\$aes-cbc\$\" and are stored in a binary format. +"$aes-cbc$" and are stored in a binary format. xxx ### Under the hood @@ -362,7 +358,7 @@ AES-CBC, the plaintext is divided into blocks of fixed size (usually 128 bits), and each block is encrypted using the AES algorithm with a secret key. -CBC stands for \"Cipher Block Chaining\" and it is a technique that adds +CBC stands for "Cipher Block Chaining" and it is a technique that adds an extra step to the encryption process to ensure that each ciphertext block depends on the previous one. This means that any modification to the ciphertext will produce a completely different plaintext after @@ -372,157 +368,3 @@ The algorithm is a symmetric cipher, which is suitable for encrypting large amounts of data. It requires much less computation power than asymmetric ciphers and is much more useful for bulk encrypting large amounts of data. - -Reference ---------- - -### StorageService - -Here is a list of methods of the abstract StorageService class which can -be used for all types of storages. - -xxx {.currentmodule} -asab.storage.service -xxx - -# TODO: autoclass% -StorageServiceABC - -# TODO: automethod% -upsertor -xxx - -# TODO: automethod% -get -xxx - -# TODO: automethod% -delete -xxx - -# TODO: automethod% -aes\_encrypt -xxx - -# TODO: automethod% -aes\_decrypt -xxx -xxx - -### Upsertor - -Here is a list of methods of the abstract Upsertor class which can be -used for all types of storages. - -xxx {.currentmodule} -asab.storage.upsertor -xxx - -# TODO: autoclass% -UpsertorABC - -# TODO: automethod% -set -xxx - -# TODO: automethod% -unset -xxx - -# TODO: automethod% -generate\_id -xxx - -# TODO: automethod% -execute -xxx -xxx - -### In-memory storage - -Here is a list of methods that are specific for the in-memory storage. - -xxx {.currentmodule} -asab.storage.inmemory -xxx - -# TODO: autoclass show-inheritance=""} -StorageService -xxx - -### MongoDB Storage - -Here is a list of methods that are specific for the MongoDB storage. - -xxx {.currentmodule} -asab.storage.mongodb -xxx - -# TODO: autoclass show-inheritance=""} -StorageService - -# TODO: automethod% -get\_by -xxx - -# TODO: automethod% -collection -xxx -xxx - -### ElasticSearch Storage - -Here is a list of methods that are specific for the ElasticSearch -storage. - -xxx {.currentmodule} -asab.storage.elasticsearch -xxx - -# TODO: autoclass show-inheritance=""} -StorageService - -# TODO: automethod% -session -xxx - -# TODO: automethod% -finalize -xxx - -# TODO: automethod% -mapping -xxx - -# TODO: automethod% -get\_index\_template -xxx - -# TODO: automethod% -put\_index\_template -xxx - -# TODO: automethod% -reindex -xxx - -# TODO: automethod% -scroll -xxx - -# TODO: automethod% -list -xxx - -# TODO: automethod% -count -xxx - -# TODO: automethod% -indices -xxx - -# TODO: automethod% -empty\_index -xxx -xxx diff --git a/docs/explanation/asab/various.md b/docs/topics/asab/various.md similarity index 100% rename from docs/explanation/asab/various.md rename to docs/topics/asab/various.md diff --git a/docs/explanation/asab/web/auth.md b/docs/topics/asab/web/auth.md similarity index 100% rename from docs/explanation/asab/web/auth.md rename to docs/topics/asab/web/auth.md diff --git a/docs/explanation/asab/web/cors.md b/docs/topics/asab/web/cors.md similarity index 100% rename from docs/explanation/asab/web/cors.md rename to docs/topics/asab/web/cors.md diff --git a/docs/explanation/asab/web/index.md b/docs/topics/asab/web/index.md similarity index 100% rename from docs/explanation/asab/web/index.md rename to docs/topics/asab/web/index.md diff --git a/docs/explanation/asab/web/restapidocs.md b/docs/topics/asab/web/restapidocs.md similarity index 100% rename from docs/explanation/asab/web/restapidocs.md rename to docs/topics/asab/web/restapidocs.md diff --git a/docs/explanation/asab/zookeeper.md b/docs/topics/asab/zookeeper.md similarity index 100% rename from docs/explanation/asab/zookeeper.md rename to docs/topics/asab/zookeeper.md diff --git a/mkdocs.yml b/mkdocs.yml index c84317ca5..30bd542e1 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -69,7 +69,7 @@ markdown_extensions: nav: - Introduction: index.md - - Installation: explanation/admin/install.md + - Installation: topics/admin/install.md - Tutorials: @@ -77,26 +77,24 @@ nav: - tutorials/chapter1.md - tutorials/chapter2.md - - Explanation: - - - Services: - - explanation/asab/web/index.md - - explanation/asab/web/auth.md - - explanation/asab/web/cors.md - - explanation/asab/web/restapidocs.md - - explanation/asab/library.md - - - Reference: - - explanation/asab/application.md - - explanation/asab/config.md - - explanation/asab/log.md - - explanation/asab/metrics.md - - explanation/asab/module.md - - explanation/asab/pubsub.md - - explanation/asab/service.md - - explanation/asab/storage.md - - explanation/asab/various.md - - explanation/asab/zookeeper.md + # - Services: + # # - topics/asab/web/index.md + # # - topics/asab/web/auth.md + # # - topics/asab/web/cors.md + # # - topics/asab/web/restapidocs.md + # # - topics/asab/library.md + + - Topics: + # - topics/asab/application.md + # - topics/asab/config.md + # - topics/asab/log.md + # - topics/asab/metrics.md + # - topics/asab/module.md + # - topics/asab/pubsub.md + # - topics/asab/service.md + - topics/asab/storage.md + # - topics/asab/various.md + # - topics/asab/zookeeper.md - Reference: # - reference/application.md @@ -114,8 +112,8 @@ nav: - In-Memory: reference/storage/inmemory.md - Administration: - - explanation/admin/command-line.md - - explanation/admin/containers.md - - explanation/admin/systemd.md + - topics/admin/command-line.md + - topics/admin/containers.md + - topics/admin/systemd.md - - explanation/asab/alert.md \ No newline at end of file + - topics/asab/alert.md \ No newline at end of file From 69b82201b2ef3555645f47b3371ccf01810b8591 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 22 Jun 2023 23:59:12 +0200 Subject: [PATCH 006/154] Add various plugins; Improve Storage Topic --- docs/topics/asab/storage.md | 370 ------------------ docs/topics/asab/storage/elasticsearch.md | 28 ++ docs/topics/asab/storage/encryption.md | 105 +++++ docs/topics/asab/storage/inmemory.md | 24 ++ docs/topics/asab/storage/intro.md | 44 +++ .../storage/manipulation_with_databases.md | 109 ++++++ docs/topics/asab/storage/mongodb.md | 50 +++ mkdocs.yml | 14 +- 8 files changed, 373 insertions(+), 371 deletions(-) delete mode 100644 docs/topics/asab/storage.md create mode 100644 docs/topics/asab/storage/elasticsearch.md create mode 100644 docs/topics/asab/storage/encryption.md create mode 100644 docs/topics/asab/storage/inmemory.md create mode 100644 docs/topics/asab/storage/intro.md create mode 100644 docs/topics/asab/storage/manipulation_with_databases.md create mode 100644 docs/topics/asab/storage/mongodb.md diff --git a/docs/topics/asab/storage.md b/docs/topics/asab/storage.md deleted file mode 100644 index 0d20cef9e..000000000 --- a/docs/topics/asab/storage.md +++ /dev/null @@ -1,370 +0,0 @@ -Storage -======= - -The ASAB's Storage Service supports data storage in-memory or in -dedicated document databases, including -[MongoDB](https://www.mongodb.com/) and -[ElasticSearch](https://www.elastic.co/). - -Configuration -------------- - -First, specify the storage type in the configuration. The options for -the storage type are: - -- `inmemory`: Collects data directly in memory -- `mongodb`: Collects data using MongoDB database. Depends on - [pymongo](https://pymongo.readthedocs.io/en/stable/) and - [motor](https://motor.readthedocs.io/en/stable/api-asyncio/asyncio_motor_collection.html) - libraries. -- `elasticsearch`: Collects data using ElasticSearch database. - Depends on [aiohttp](https://docs.aiohttp.org/en/latest/) library. - -Storage Service provides a unified interface for accessing and -manipulating collections across multiple database technologies. - -``` {.ini} -[asab:storage] -type=mongodb -``` - -For accessing the storage, simply add -[asab.storage.Module]{.title-ref}` when initializing and register the -service. - -``` {.python} -class MyApplication(asab.Application): - - async def initialize(self): - - self.add_module(asab.storage.Module) - - async def main(self): - storage = self.get_service("asab.StorageService") -``` - -Manipulation with databases ---------------------------- - -### Upsertor - -Upsertor is an object that works like a pointer to the specified -database and optionally to object id. It is used for inserting new -objects, updating existing objects and deleting them. - -``` {.python} -u = storage.upsertor("test-collection") -``` - -The `StorageService.upsertor()`{.interpreted-text role="func"} method -creates an upsertor object associated with the specified collection. It -takes [collection]{.title-ref} as an argument and can have two -parameters [obj_id]{.title-ref} and [version]{.title-ref}, which are -used for getting an existing object by its ID and version. - -### Inserting an object - -For inserting an object to the collection, use the -`Upsertor.set()`{.interpreted-text role="func"} method. - -``` {.python} -u.set("key", "value") -``` - -To execute these procedures, simply run the -`Upsertor.execute()`{.interpreted-text role="func"} coroutine method, -which commits the upsertor data to the storage and returns the ID of the -object. Since it is a coroutine, it must be awaited. - -``` {.python} -object_id = await u.execute() -``` - -The [Upsertor.execute()]{.title-ref} method has optional parameters -[custom_data]{.title-ref} and [event_type]{.title-ref}, which are used -for webhook requests. - -``` {.python} -object_id = await u.execute( - custom_data= {"foo": "bar"}, - event_type="object_created" - ) -``` - -### Getting a single object - -For getting a single object, use -`StorageService.get()`{.interpreted-text role="func"} coroutine method -that takes two arguments [collection]{.title-ref} and -[obj_id]{.title-ref} and finds an object by its ID in collection. - -``` {.python} -obj = await storage.get(collection="test-collection", obj_id=object_id) -print(obj) -``` - -When the requested object is not found in the collection, the method -raises `KeyError`. Remember to handle this exception properly when using -databases in your services and prevent them from crashing! - -xxx {.note} -xxx {.title} -Note -xxx - -MongoDB storage service in addition provides a coroutine method -`get_by()`{.interpreted-text role="func"} which is used for accessing an -object by finding its key-value pair. - -``` {.python} -obj = await storage.get_by(database="test-collection", key="key", value="value") -``` -xxx - -### Updating an object - -For updating an object, first obtain the upsertor specifying its -[obj_id]{.title-ref} and [version]{.title-ref}. - -``` {.python} -u = storage.upsertor( - collection="test-collection", - obj_id=object_id, - version=obj['_v'] -) -``` - -We strongly recommend to read the version from the object such as above. -That creates a soft lock on the record. It means that if the object is -updated by other component in meanwhile, your upsertor will fail and you -should retry the whole operation. The new objects should have a version -set to 0, which is done by default. - -After obtaining an upsertor, you can update the object via the -`Upsertor.set()`{.interpreted-text role="func"} coroutine. - -``` {.python} -u.set("key", "new_value") -object_id = await u.execute() -``` - -### Deleting an object - -For deleting an object from database, use the -`StorageService.delete()`{.interpreted-text role="func"} coroutine -method which takes arguments [collection]{.title-ref} and -[obj_id]{.title-ref}, deletes the object and returns its ID. - -``` {.python} -deleted_id = await u.delete("test-collection", object_id) -``` - -Storing data in memory ----------------------- - -If the option [inmemory]{.title-ref} is set, ASAB will store data in its -own memory. In particular, [asab.StorageService]{.title-ref} is -initialized with an attribute [InMemoryCollections]{.title-ref} which is -a dictionary where all the collections are stored in. - -xxx {.note} -xxx {.title} -Note -xxx - -You can go through all the databases directly by accessing -[InMemoryCollections]{.title-ref} attribute, although we do not -recommend that. - -``` {.python} -import pprint - -storage = self.get_service("asab.StorageService") -pprint.pprint(storage.InMemoryCollections, indent=2) -``` -xxx - -Storing data in MongoDB ------------------------ - -If the option [mongodb]{.title-ref} is set, ASAB will store data in -MongoDB database. - -ASAB uses [motor library](https://pypi.org/project/motor/) which -provides non-blocking MongoDB driver for [asyncio]{.title-ref}. - -You can specify the database name and URL for MongoDB in config file -(the following example is the default configuration): - -``` {.ini} -[asab:storage] -type=mongodb -mongodb_uri=mongodb://localhost:27017 -mongodb_database=asabdb -``` - -You can use all the methods from the abstract class. MongoDB Storage -class provides in addition two methods, -`StorageService.get_by()`{.interpreted-text role="func"} and -`StorageService.collection()`{.interpreted-text role="func"}. - -The method `StorageService.get_by()`{.interpreted-text role="func"} is -used in the same way as `StorageService.get()`{.interpreted-text -role="func"} except that it takes the arguments [key]{.title-ref} and -[value]{.title-ref} instead of [obj_id]{.title-ref}. - -``` {.python} -obj = await storage.get_by(database="test-collection", key="key", value="value") -``` - -The method `collection()`{.interpreted-text role="func"} is used for -accessing the database directly. It takes [collection]{.title-ref} as -the argument and returns -[motor.motor_asyncio.AsyncIOMotorCollection]{.title-ref} object, which -can be used for calling MongoDB directives. - -``` {.python} -collection = await storage.collection("test-collection") -cursor = collection.find({}) -while await cursor.fetch_next: - data = cursor.next_object() - pprint.pprint(data) -``` - -The full list of methods suitable for this object is described in the -[official -documentation](https://motor.readthedocs.io/en/stable/api-asyncio/asyncio_motor_collection.html). - -Storing data in ElasticSearch ------------------------------ - -When using ElasticSearch, add configurations for URL, username and -password. - -``` {.ini} -[asab:storage] -type=elasticsearch -elasticsearch_url=http://localhost:9200/ -elasticsearch_username=JohnDoe -elasticsearch_password=lorem_ipsum_dolor?sit_amet!2023 -``` - -You can also specify the [refreshing -parameter](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-refresh.html#docs-refresh) -and scroll timeout for [ElasticSearch Scroll -API](https://www.elastic.co/guide/en/elasticsearch//reference/current/scroll-api.html). - -``` {.ini} -[asab:storage] -refresh=true -scroll_timeout=1m -``` - -ElasticSearch Storage provides in addition other methods for creating -index templates, mappings etc (see the Reference section). - -Encryption and decryption -------------------------- - -Data stored in the database can be encrypted using an algorithm that -adheres to the Advanced Encryption Standard (AES). - -### AES Key settings - -In order to use encryption, first make sure you have the [cryptography -package](https://pypi.org/project/cryptography/) installed. Then specify -the AES Key in the config file. - -``` {.ini} -[asab:storage] -aes_key=random_key_string -``` - -xxx {.note} -xxx {.title} -Note -xxx - -The AES Key is used as both an encryption and decryption key. It is -recommended to keep it in [a separate configuration -file](https://asab.readthedocs.io/en/latest/asab/config.html#including-other-configuration-files) -that is not exposed anywhere publicly. - -The actual binary AES Key is obtained from the [aes_key]{.title-ref} -specified in the config file by encoding and hashing it using the -standard [hashlib](https://docs.python.org/3/library/hashlib.html) -algorithms, so do not worry about the length and type of the key. -xxx - -### Encrypting data - -The `Upsertor.set()`{.interpreted-text role="func"} method has an -optional boolean parameter [encrypt]{.title-ref} for encrypting the data -before they are stored. Only values of the type `bytes` can be -encrypted. If you want to encrypt other values, encode them first. - -``` {.python} -message = "This is a super secret message!" -number = 2023 -message_binary = message.encode("ascii") -number_binary = number.encode("ascii") - -u.set("message", message_binary, encrypt=True) -u.set("number", number_binary, encrypt=True) -object_id = await u.execute() -``` - -### Decrypting data - -The `StorageService.get()`{.interpreted-text role="func"} coroutine -method has an optional parameter [decrypt]{.title-ref} which takes an -`iterable` object (i.e. a list, tuple, set, ...) with the names of keys -whose values are to be decrypted. - -``` {.python} -data = await storage.get( - collection="test-collection", - obj_id=object_id, - decrypt=["message", "number"] - ) -``` - -If some of the keys to be decrypted are missing in the required -document, the method will ignore them and continue. - -xxx {.note} -xxx {.title} -Note -xxx - -Data that has been encrypted can be identified by the prefix -"$aes-cbc$" and are stored in a binary format. -xxx - -### Under the hood - -For encrypting data, we use the certified symmetric AES-CBC algorithm. -In fact, the abstract base class `StorageServiceABC`{.interpreted-text -role="class"} provides two methods `aes_encrypt()`{.interpreted-text -role="func"} and `aes_decrypt()`{.interpreted-text role="func"} that are -called automatically in `Upsertor.set()`{.interpreted-text role="func"} -and `StorageService.get()`{.interpreted-text role="func"} methods when -the parameter [encrypt]{.title-ref} or [decrypt]{.title-ref} is -specified. - -AES-CBC is a mode of operation for the Advanced Encryption Standard -(AES) algorithm that provides confidentiality and integrity for data. In -AES-CBC, the plaintext is divided into blocks of fixed size (usually 128 -bits), and each block is encrypted using the AES algorithm with a secret -key. - -CBC stands for "Cipher Block Chaining" and it is a technique that adds -an extra step to the encryption process to ensure that each ciphertext -block depends on the previous one. This means that any modification to -the ciphertext will produce a completely different plaintext after -decryption. - -The algorithm is a symmetric cipher, which is suitable for encrypting -large amounts of data. It requires much less computation power than -asymmetric ciphers and is much more useful for bulk encrypting large -amounts of data. diff --git a/docs/topics/asab/storage/elasticsearch.md b/docs/topics/asab/storage/elasticsearch.md new file mode 100644 index 000000000..c903ec368 --- /dev/null +++ b/docs/topics/asab/storage/elasticsearch.md @@ -0,0 +1,28 @@ + +Storing data in ElasticSearch +----------------------------- + +When using ElasticSearch, add configurations for URL, username and +password. + +``` {.ini} +[asab:storage] +type=elasticsearch +elasticsearch_url=http://localhost:9200/ +elasticsearch_username=JohnDoe +elasticsearch_password=lorem_ipsum_dolor?sit_amet!2023 +``` + +You can also specify the [refreshing +parameter](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-refresh.html#docs-refresh) +and scroll timeout for [ElasticSearch Scroll +API](https://www.elastic.co/guide/en/elasticsearch//reference/current/scroll-api.html). + +``` {.ini} +[asab:storage] +refresh=true +scroll_timeout=1m +``` + +ElasticSearch Storage provides in addition other methods for creating +index templates, mappings etc (see the Reference section). \ No newline at end of file diff --git a/docs/topics/asab/storage/encryption.md b/docs/topics/asab/storage/encryption.md new file mode 100644 index 000000000..43f91ca83 --- /dev/null +++ b/docs/topics/asab/storage/encryption.md @@ -0,0 +1,105 @@ +Encryption and decryption +------------------------- + +Data stored in the database can be encrypted using an algorithm that +adheres to the Advanced Encryption Standard (AES). + +### AES Key settings + +In order to use encryption, first make sure you have the [cryptography +package](https://pypi.org/project/cryptography/) installed. Then specify +the AES Key in the config file. + +``` {.ini} +[asab:storage] +aes_key=random_key_string +``` + +xxx {.note} +xxx {.title} +Note +xxx + +The AES Key is used as both an encryption and decryption key. It is +recommended to keep it in [a separate configuration +file](https://asab.readthedocs.io/en/latest/asab/config.html#including-other-configuration-files) +that is not exposed anywhere publicly. + +The actual binary AES Key is obtained from the [aes_key]{.title-ref} +specified in the config file by encoding and hashing it using the +standard [hashlib](https://docs.python.org/3/library/hashlib.html) +algorithms, so do not worry about the length and type of the key. +xxx + +### Encrypting data + +The `Upsertor.set()`{.interpreted-text role="func"} method has an +optional boolean parameter [encrypt]{.title-ref} for encrypting the data +before they are stored. Only values of the type `bytes` can be +encrypted. If you want to encrypt other values, encode them first. + +``` {.python} +message = "This is a super secret message!" +number = 2023 +message_binary = message.encode("ascii") +number_binary = number.encode("ascii") + +u.set("message", message_binary, encrypt=True) +u.set("number", number_binary, encrypt=True) +object_id = await u.execute() +``` + +### Decrypting data + +The `StorageService.get()`{.interpreted-text role="func"} coroutine +method has an optional parameter [decrypt]{.title-ref} which takes an +`iterable` object (i.e. a list, tuple, set, ...) with the names of keys +whose values are to be decrypted. + +``` {.python} +data = await storage.get( + collection="test-collection", + obj_id=object_id, + decrypt=["message", "number"] + ) +``` + +If some of the keys to be decrypted are missing in the required +document, the method will ignore them and continue. + +xxx {.note} +xxx {.title} +Note +xxx + +Data that has been encrypted can be identified by the prefix +"$aes-cbc$" and are stored in a binary format. +xxx + +### Under the hood + +For encrypting data, we use the certified symmetric AES-CBC algorithm. +In fact, the abstract base class `StorageServiceABC`{.interpreted-text +role="class"} provides two methods `aes_encrypt()`{.interpreted-text +role="func"} and `aes_decrypt()`{.interpreted-text role="func"} that are +called automatically in `Upsertor.set()`{.interpreted-text role="func"} +and `StorageService.get()`{.interpreted-text role="func"} methods when +the parameter [encrypt]{.title-ref} or [decrypt]{.title-ref} is +specified. + +AES-CBC is a mode of operation for the Advanced Encryption Standard +(AES) algorithm that provides confidentiality and integrity for data. In +AES-CBC, the plaintext is divided into blocks of fixed size (usually 128 +bits), and each block is encrypted using the AES algorithm with a secret +key. + +CBC stands for "Cipher Block Chaining" and it is a technique that adds +an extra step to the encryption process to ensure that each ciphertext +block depends on the previous one. This means that any modification to +the ciphertext will produce a completely different plaintext after +decryption. + +The algorithm is a symmetric cipher, which is suitable for encrypting +large amounts of data. It requires much less computation power than +asymmetric ciphers and is much more useful for bulk encrypting large +amounts of data. diff --git a/docs/topics/asab/storage/inmemory.md b/docs/topics/asab/storage/inmemory.md new file mode 100644 index 000000000..c06df6c62 --- /dev/null +++ b/docs/topics/asab/storage/inmemory.md @@ -0,0 +1,24 @@ +Storing data in memory +---------------------- + +If the option [inmemory]{.title-ref} is set, ASAB will store data in its +own memory. In particular, [asab.StorageService]{.title-ref} is +initialized with an attribute [InMemoryCollections]{.title-ref} which is +a dictionary where all the collections are stored in. + +xxx {.note} +xxx {.title} +Note +xxx + +You can go through all the databases directly by accessing +[InMemoryCollections]{.title-ref} attribute, although we do not +recommend that. + +``` {.python} +import pprint + +storage = self.get_service("asab.StorageService") +pprint.pprint(storage.InMemoryCollections, indent=2) +``` +xxx \ No newline at end of file diff --git a/docs/topics/asab/storage/intro.md b/docs/topics/asab/storage/intro.md new file mode 100644 index 000000000..4d2bca088 --- /dev/null +++ b/docs/topics/asab/storage/intro.md @@ -0,0 +1,44 @@ +Storage +======= + +The ASAB's Storage Service supports data storage in-memory or in +dedicated document databases, including +[MongoDB](https://www.mongodb.com/) and +[ElasticSearch](https://www.elastic.co/). + +Configuration +------------- + +First, specify the storage type in the configuration. The options for +the storage type are: + +- `inmemory`: Collects data directly in memory +- `mongodb`: Collects data using MongoDB database. Depends on + [pymongo](https://pymongo.readthedocs.io/en/stable/) and + [motor](https://motor.readthedocs.io/en/stable/api-asyncio/asyncio_motor_collection.html) + libraries. +- `elasticsearch`: Collects data using ElasticSearch database. + Depends on [aiohttp](https://docs.aiohttp.org/en/latest/) library. + +Storage Service provides a unified interface for accessing and +manipulating collections across multiple database technologies. + +``` {.ini} +[asab:storage] +type=mongodb +``` + +For accessing the storage, simply add +[asab.storage.Module]{.title-ref}` when initializing and register the +service. + +``` {.python} +class MyApplication(asab.Application): + + async def initialize(self): + + self.add_module(asab.storage.Module) + + async def main(self): + storage = self.get_service("asab.StorageService") +``` diff --git a/docs/topics/asab/storage/manipulation_with_databases.md b/docs/topics/asab/storage/manipulation_with_databases.md new file mode 100644 index 000000000..871b1769d --- /dev/null +++ b/docs/topics/asab/storage/manipulation_with_databases.md @@ -0,0 +1,109 @@ + +Manipulation with databases +--------------------------- + +### Upsertor + +Upsertor is an object that works like a pointer to the specified +database and optionally to object id. It is used for inserting new +objects, updating existing objects and deleting them. + +``` python +u = storage.upsertor("test-collection") +``` + +The `StorageService.upsertor()` method +creates an upsertor object associated with the specified collection. It +takes [collection]{.title-ref} as an argument and can have two +parameters [obj_id]{.title-ref} and [version]{.title-ref}, which are +used for getting an existing object by its ID and version. + +### Inserting an object + +For inserting an object to the collection, use the `Upsertor.set()` method. + +``` python +u.set("key", "value") +``` + +To execute these procedures, simply run the `Upsertor.execute()` coroutine method, which commits the upsertor data to the storage and returns the ID of the object. Since it is a coroutine, it must be awaited. + +``` python +object_id = await u.execute() +``` + +The `Upsertor.execute()` method has optional parameters `custom_data` and `event_type`, which are used for webhook requests. + +``` python +object_id = await u.execute( + custom_data= {"foo": "bar"}, + event_type="object_created" + ) +``` + +### Getting a single object + +For getting a single object, use +`StorageService.get()`coroutine method +that takes two arguments `collection` and +`obj_id` and finds an object by its ID in collection. + +``` python +obj = await storage.get(collection="test-collection", obj_id=object_id) +print(obj) +``` + +When the requested object is not found in the collection, the method +raises `KeyError`. Remember to handle this exception properly when using +databases in your services and prevent them from crashing! + +!!! quote "Made with ❤️ by TeskaLabs" + +!!! note +``` + MongoDB storage service in addition provides a coroutine method + `get_by()`{.interpreted-text role="func"} which is used for accessing an + object by finding its key-value pair. + + ``` python + obj = await storage.get_by(database="test-collection", key="key", value="value") + ``` +``` + +### Updating an object + +For updating an object, first obtain the upsertor specifying its +[obj_id]{.title-ref} and [version]{.title-ref}. + +``` python +u = storage.upsertor( + collection="test-collection", + obj_id=object_id, + version=obj['_v'] +) +``` + +We strongly recommend to read the version from the object such as above. +That creates a soft lock on the record. It means that if the object is +updated by other component in meanwhile, your upsertor will fail and you +should retry the whole operation. The new objects should have a version +set to 0, which is done by default. + +After obtaining an upsertor, you can update the object via the +(Upsertor.set)(reference/storage/upsertor/#asab.storage.upsertor.UpsertorABC.set) coroutine. + +``` python +u.set("key", "new_value") +object_id = await u.execute() +``` + +### Deleting an object + +For deleting an object from database, use the +`StorageService.delete()`{.interpreted-text role="func"} coroutine +method which takes arguments [collection]{.title-ref} and +[obj_id]{.title-ref}, deletes the object and returns its ID. + +``` python +deleted_id = await u.delete("test-collection", object_id) +``` diff --git a/docs/topics/asab/storage/mongodb.md b/docs/topics/asab/storage/mongodb.md new file mode 100644 index 000000000..27bffabab --- /dev/null +++ b/docs/topics/asab/storage/mongodb.md @@ -0,0 +1,50 @@ +Storing data in MongoDB +----------------------- + +If the option [mongodb]{.title-ref} is set, ASAB will store data in +MongoDB database. + +ASAB uses [motor library](https://pypi.org/project/motor/) which +provides non-blocking MongoDB driver for [asyncio]{.title-ref}. + +You can specify the database name and URL for MongoDB in config file +(the following example is the default configuration): + +``` {.ini} +[asab:storage] +type=mongodb +mongodb_uri=mongodb://localhost:27017 +mongodb_database=asabdb +``` + +You can use all the methods from the abstract class. MongoDB Storage +class provides in addition two methods, +`StorageService.get_by()`{.interpreted-text role="func"} and +`StorageService.collection()`{.interpreted-text role="func"}. + +The method `StorageService.get_by()`{.interpreted-text role="func"} is +used in the same way as `StorageService.get()`{.interpreted-text +role="func"} except that it takes the arguments [key]{.title-ref} and +[value]{.title-ref} instead of [obj_id]{.title-ref}. + +``` {.python} +obj = await storage.get_by(database="test-collection", key="key", value="value") +``` + +The method `collection()`{.interpreted-text role="func"} is used for +accessing the database directly. It takes [collection]{.title-ref} as +the argument and returns +[motor.motor_asyncio.AsyncIOMotorCollection]{.title-ref} object, which +can be used for calling MongoDB directives. + +``` {.python} +collection = await storage.collection("test-collection") +cursor = collection.find({}) +while await cursor.fetch_next: + data = cursor.next_object() + pprint.pprint(data) +``` + +The full list of methods suitable for this object is described in the +[official +documentation](https://motor.readthedocs.io/en/stable/api-asyncio/asyncio_motor_collection.html). diff --git a/mkdocs.yml b/mkdocs.yml index 30bd542e1..21a2fb9bb 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -56,6 +56,12 @@ plugins: default_handler: python python: use_indentation: '\t' + - glightbox + - search + - awesome-pages + # - print-site: + # add_to_navigation: true + markdown_extensions: - pymdownx.highlight: @@ -92,7 +98,13 @@ nav: # - topics/asab/module.md # - topics/asab/pubsub.md # - topics/asab/service.md - - topics/asab/storage.md + - Storage: + - Intro: topics/asab/storage/intro.md + - Manipulation with Databases: topics/asab/storage/manipulation_with_databases.md + - Encryption and Decryption: topics/asab/storage/encryption.md + - In-Memory Storage: topics/asab/storage/inmemory.md + - MongoDB Storage: topics/asab/storage/mongodb.md + - ElasticSearch Storage: topics/asab/storage/elasticsearch.md # - topics/asab/various.md # - topics/asab/zookeeper.md From 16563e9ac0c5ac5a4a296476531efb5355b80dba Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 23 Jun 2023 00:12:10 +0200 Subject: [PATCH 007/154] Add plugin for icons --- .../storage/manipulation_with_databases.md | 8 +++--- mkdocs.yml | 26 +++++++++++++++---- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/docs/topics/asab/storage/manipulation_with_databases.md b/docs/topics/asab/storage/manipulation_with_databases.md index 871b1769d..ef5327226 100644 --- a/docs/topics/asab/storage/manipulation_with_databases.md +++ b/docs/topics/asab/storage/manipulation_with_databases.md @@ -57,23 +57,21 @@ When the requested object is not found in the collection, the method raises `KeyError`. Remember to handle this exception properly when using databases in your services and prevent them from crashing! -!!! quote "Made with ❤️ by TeskaLabs" !!! note -``` + MongoDB storage service in addition provides a coroutine method - `get_by()`{.interpreted-text role="func"} which is used for accessing an + `get_by()` which is used for accessing an object by finding its key-value pair. ``` python obj = await storage.get_by(database="test-collection", key="key", value="value") ``` -``` ### Updating an object For updating an object, first obtain the upsertor specifying its -[obj_id]{.title-ref} and [version]{.title-ref}. +`obj_id` and `version`. ``` python u = storage.upsertor( diff --git a/mkdocs.yml b/mkdocs.yml index 21a2fb9bb..2170596ed 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -19,12 +19,22 @@ theme: - pymdownx.mark - pymdownx.tilde - def_list - # - pymdownx.tasklist: - # custom_checkbox: true - # - pymdownx.emoji: - # emoji_index: !!python/name:materialx.emoji.twemoji - # emoji_generator: !!python/name:materialx.emoji.to_svg + icon: + admonition: + # https://squidfunk.github.io/mkdocs-material/reference/admonitions/#fontawesome + note: fontawesome/solid/note-sticky + abstract: fontawesome/solid/book + info: fontawesome/solid/circle-info + tip: fontawesome/solid/bullhorn + success: fontawesome/solid/check + question: fontawesome/solid/circle-question + warning: fontawesome/solid/triangle-exclamation + failure: fontawesome/solid/bomb + danger: fontawesome/solid/skull + bug: fontawesome/solid/robot + example: fontawesome/solid/flask + quote: fontawesome/solid/quote-left font: text: Verdana @@ -72,6 +82,12 @@ markdown_extensions: - pymdownx.snippets - pymdownx.superfences + # Extensions for notes, warnings, ... + # https://squidfunk.github.io/mkdocs-material/reference/admonitions/#fontawesome + - admonition + - pymdownx.details + - pymdownx.superfences + nav: - Introduction: index.md From 611d29c1c41424590994e9092d0880bdba129f87 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 23 Jun 2023 02:29:51 +0200 Subject: [PATCH 008/154] Improve Tutorial section dramatically --- docs/index.md | 4 +- .../{get-started.md => 01_hello_world.md} | 58 +++++------ docs/tutorials/02_web_server.md | 99 +++++++++++++++++++ .../tutorials/{chapter2.md => 03_rest_api.md} | 0 docs/tutorials/chapter1.md | 66 ------------- mkdocs.yml | 10 +- 6 files changed, 134 insertions(+), 103 deletions(-) rename docs/tutorials/{get-started.md => 01_hello_world.md} (65%) create mode 100644 docs/tutorials/02_web_server.md rename docs/tutorials/{chapter2.md => 03_rest_api.md} (100%) delete mode 100644 docs/tutorials/chapter1.md diff --git a/docs/index.md b/docs/index.md index 0b6331f91..df7213e3f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ ---- + Asynchronous Server Application Boilerplate =========================================== diff --git a/docs/tutorials/get-started.md b/docs/tutorials/01_hello_world.md similarity index 65% rename from docs/tutorials/get-started.md rename to docs/tutorials/01_hello_world.md index ac661d525..30aaa37f9 100644 --- a/docs/tutorials/get-started.md +++ b/docs/tutorials/01_hello_world.md @@ -1,5 +1,5 @@ -Getting started -=============== +Creating your first asab application +==================================== Make sure you have both [pip](https://pip.pypa.io/en/stable/installing/) and at least version 3.7 of Python before starting. ASAB uses the new @@ -13,7 +13,7 @@ and at least version 3.7 of Python before starting. ASAB uses the new 2. Create a file called `main.py` with the following code: - ``` python + ``` python title="main.py" #!/usr/bin/env python3 import asab @@ -49,51 +49,45 @@ and at least version 3.7 of Python before starting. ASAB uses the new Going into details ------------------ -``` python -#!/usr/bin/env python3 -``` +Let's look on the application one more time. -ASAB application uses a Python 3.7+. This is specified a by hashbang -line at the very begginig of the file, on the line number 1. -``` python -import asab -``` +``` python title="main.py" linenums="1" -ASAB is included from as [asab][asab] module via an import -statement. + #!/usr/bin/env python3 # (1) + import asab # (2) + + class MyApplication(asab.Application): # (3) + async def main(self): # (4) + print("Hello world") # (5) -``` python -class MyApplication(asab.Application): + if __name__ == '__main__': # (6) + app = MyApplication() + app.run() ``` -Every ASAB Application needs to have an application object. It is a +1. ASAB application uses a Python 3.7+. This is specified a by hashbang +line at the very beginning of the file. + +2. ASAB is included from as `asab` module via an import +statement. + +3. Every ASAB Application needs to have an application object. It is a singleton; it means that the application must create and operate precisely one instance of the application. ASAB provides the base -[asab.Application] class that you need to +[asab.Application][#TODO] class that you need to inherit from to implement your custom application class. -``` python -async def main(self): - print("Hello world") -``` - -The `Application.main()`{.interpreted-text role="any"} method is one of +4. The `Application.main()` method is one of the application lifecycle methods, that you can override to implement -desired application functionality. The [main]{.title-ref} method is a +desired application functionality. The `main` method is a coroutine, so that you can await any tasks etc. in fully asynchronous way. This method is called when ASAB application is executed and initialized. The lifecycle stage is called "runtime". -In this example, we just print a message to a screen. - -``` python -if __name__ == '__main__': - app = MyApplication() - app.run() -``` +5. In this example, we just print a message to a screen. -This part of the code is executed when the Python program is launched. +6. This part of the code is executed when the Python program is launched. It creates the application object and executes the `Application.run()`{.interpreted-text role="any"} method. This is a standard way of how ASAB application is started. diff --git a/docs/tutorials/02_web_server.md b/docs/tutorials/02_web_server.md new file mode 100644 index 000000000..ecf9598e3 --- /dev/null +++ b/docs/tutorials/02_web_server.md @@ -0,0 +1,99 @@ +Creating a Web Server +===================== + +Now, when you know how to create and run a basic asab application, let's create the very first web server! + +Set up a new project and create a new file `app.py` with the following code: + +``` python title="app.py" + +#!/usr/bin/env python3 +import asab.web.rest + +class MyWebApplication(asab.Application): + + def __init__(self): + super().__init__() + + # Create the Web server + web = asab.web.create_web_server(self) + + # Add a route to the handler method + web.add_get('/hello', self.hello) + + # This is the web request handler + async def hello(self, request): + return asab.web.rest.json_response( + request, + data="Hello, world!" + ) + +if __name__ == '__main__': + app = MyWebApplication() + app.run() + +``` + +Run it with the command: + +``` console +python3 app.py +``` + + +The ASAB web server is now available at [http://localhost:8080/](http://localhost:8080/). + +!!! note + + In case you don't know, **localhost** refers to the loopback network interface address of a device, usually represented as the IP address 127.0.0.1. It is used to refer to the device itself, allowing software to communicate with services running on the same device. In simpler terms, it's like talking to yourself within a computer to access and test applications or websites without going online. + + The part `:8080` refers to a port. A **port** is a communication endpoint in a computer network. It is represented by a numerical value, such as 8080, and it allows applications and services to establish connections and exchange data. Ports enable the proper routing and delivery of network traffic, ensuring that information reaches the intended destination within a device or across different devices on a network. + +## TODO: send a request to /hello endpoint + +Deeper look +----------- + +``` python title="app.py" linenums="1" + +#!/usr/bin/env python3 +import asab.web.rest # (1) + +class MyWebApplication(asab.Application): + + def __init__(self): + super().__init__() # (2) + + # Create the Web server + web = asab.web.create_web_server(self) # (3) + + # Add a route to the handler method + web.add_get('/hello', self.hello) # (4) + + # This is the web request handler + async def hello(self, request): # (5) + return asab.web.rest.json_response( # (6) + request, + data="Hello, world!" + ) + +if __name__ == '__main__': + app = MyWebApplication() + app.run() + +``` + +1. Let's start by importing the `asab.web.rest` module. + +2. As you will see later, `asab.Application` has a lifecycle with three phases. This time, we modify the initialization of the application. In order not to completely override the whole application initialization, call the `super.__init__()` method. + +3. The `asab.web` module provides a `create_web_server()` method that +simplifies creation of the Web server in the ASAB application. It returns an object, which is used as a router in which you can add new routes. + +4. With the `add_get()` method, you can define a new route that requests can be send to. If you now access the web server with a path `/hello`, it will +be handled by a `hello()` method. In other words, the `hello()` method is installed at the web server at `/hello` endpoint with the `GET` HTTP method. Similar methods for `PUT`, `POST` and `DELETE` methods exist, as we will see in the next tutorial. + +5. This is a handler method, which is called by the router when `GET` request is send to a `/hello` endpoint. Every handler method must be a coroutine! That means, it has to be defined with `async def` keyword. Also, there has to be the `request` argument, even if you (for some peculiar reason) don't want to use it in the function body. Otherwise it won't work together with the `add_get()` method. + +6. The `asab.web.rest` module provides a `json_response()` method that simply sends back any data you want to the client in JSON format. + diff --git a/docs/tutorials/chapter2.md b/docs/tutorials/03_rest_api.md similarity index 100% rename from docs/tutorials/chapter2.md rename to docs/tutorials/03_rest_api.md diff --git a/docs/tutorials/chapter1.md b/docs/tutorials/chapter1.md deleted file mode 100644 index ef26144b6..000000000 --- a/docs/tutorials/chapter1.md +++ /dev/null @@ -1,66 +0,0 @@ -Web Server Tutorial -=================== - -Create a simple web server with ASAB. - -The code --------- - -``` {.python} -``` - -| To start the application, store above code in a file `app.py`. -| Execute `$ python3 ./app.py` to run it. - -The ASAB web server is now available at . - -Deeper look ------------ - -**ASAB Application** - -``` {.python} -#!/usr/bin/env python3 -import asab.web.rest - -class MyWebApplication(asab.Application): - - def __init__(self): - super().__init__() - -if __name__ == '__main__': - app = MyWebApplication() - app.run() -``` - -This is a ASAB code that declares the application class and runs it. - -**Create a Web server** - -The `asab.web` module provides a `create_web_server()` function that -simplifies creation of the Web server in the ASAB application. - -``` {.python} -web = asab.web.create_web_server(self) -``` - -**Install the handler** - -``` {.python} -web.add_get('/hello', self.hello) - -... - -async def hello(self, request): - return asab.web.rest.json_response( - request, - data="Hello, world!\n" - ) -``` - -The handler method `hello()` is installed at the web server at `/hello` -endpoint. HTTP method is `GET`. - -It means that if you access the web server with a path `/hello`, it will -be handled by a `hello(...)` method. A handler method must be a -coroutine. diff --git a/mkdocs.yml b/mkdocs.yml index 2170596ed..ff136c47d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -19,6 +19,7 @@ theme: - pymdownx.mark - pymdownx.tilde - def_list + - navigation.tracking icon: admonition: @@ -69,6 +70,7 @@ plugins: - glightbox - search - awesome-pages + - git-revision-date-localized # - print-site: # add_to_navigation: true @@ -87,6 +89,8 @@ markdown_extensions: - admonition - pymdownx.details - pymdownx.superfences + - attr_list + - md_in_html nav: - Introduction: index.md @@ -95,9 +99,9 @@ nav: - Tutorials: - - tutorials/get-started.md - - tutorials/chapter1.md - - tutorials/chapter2.md + - Hello World: tutorials/01_hello_world.md + - Creating a web server: tutorials/02_web_server.md + - Creating a microservice with REST API: tutorials/03_rest_api.md # - Services: # # - topics/asab/web/index.md From ed926e5c263eba8eb7c3f71cc79933c458783b0d Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 23 Jun 2023 09:49:25 +0200 Subject: [PATCH 009/154] Add section about logging to web server tutorial --- docs/tutorials/01_hello_world.md | 2 +- docs/tutorials/02_web_server.md | 70 ++++++++++++++++++++++++++++---- docs/tutorials/03_rest_api.md | 6 ++- mkdocs.yml | 8 ++++ 4 files changed, 75 insertions(+), 11 deletions(-) diff --git a/docs/tutorials/01_hello_world.md b/docs/tutorials/01_hello_world.md index 30aaa37f9..a6dfc8cdd 100644 --- a/docs/tutorials/01_hello_world.md +++ b/docs/tutorials/01_hello_world.md @@ -95,4 +95,4 @@ standard way of how ASAB application is started. Next steps ---------- -Check out tutorials about how to build ASAB based [web server][tutorial/chapter1.md]. +Check out tutorials about how to build ASAB based [web server](./02_web_server.md). diff --git a/docs/tutorials/02_web_server.md b/docs/tutorials/02_web_server.md index ecf9598e3..cf9d3ae73 100644 --- a/docs/tutorials/02_web_server.md +++ b/docs/tutorials/02_web_server.md @@ -1,7 +1,7 @@ -Creating a Web Server +Creating a web server ===================== -Now, when you know how to create and run a basic asab application, let's create the very first web server! +Now, when you know how to create and run [a basic asab application](./01_hello_world.md), let's create the first web server! Set up a new project and create a new file `app.py` with the following code: @@ -49,11 +49,31 @@ The ASAB web server is now available at [http://localhost:8080/](http://localhos The part `:8080` refers to a port. A **port** is a communication endpoint in a computer network. It is represented by a numerical value, such as 8080, and it allows applications and services to establish connections and exchange data. Ports enable the proper routing and delivery of network traffic, ensuring that information reaches the intended destination within a device or across different devices on a network. -## TODO: send a request to /hello endpoint +Now open your web browser and open [http://localhost:8080/](http://localhost:8080/). You shouldn't see anything but an error: + +``` +404: Not Found +``` + +That is correct, because the endpoint "/" is not handled by the router. But now, if you open [http://localhost:8080/hello](http://localhost:8080/hello), you should see the response: + +``` + "Hello world!" +``` + +You should get the same result from a terminal using cURL command: + +``` console +curl --location 'localhost:8080/hello' +``` + + Deeper look ----------- +Let's go line by line in the code to understand how the asab server is constructed. + ``` python title="app.py" linenums="1" #!/usr/bin/env python3 @@ -83,17 +103,51 @@ if __name__ == '__main__': ``` -1. Let's start by importing the `asab.web.rest` module. +1. Let's start by importing the `asab.web.rest` module. Note that this enables calling functions from `asab` and `asab.web` modules. -2. As you will see later, `asab.Application` has a lifecycle with three phases. This time, we modify the initialization of the application. In order not to completely override the whole application initialization, call the `super.__init__()` method. +2. As you will see later, `asab.Application` has a lifecycle with three phases. This time, we have modified the initialization of the application. In order not to completely override the whole application initialization, call the `super.__init__()` method. 3. The `asab.web` module provides a `create_web_server()` method that -simplifies creation of the Web server in the ASAB application. It returns an object, which is used as a router in which you can add new routes. +simplifies creation of the Web server in the ASAB application. It returns an object, which is used as a router to which you can add new routes. 4. With the `add_get()` method, you can define a new route that requests can be send to. If you now access the web server with a path `/hello`, it will -be handled by a `hello()` method. In other words, the `hello()` method is installed at the web server at `/hello` endpoint with the `GET` HTTP method. Similar methods for `PUT`, `POST` and `DELETE` methods exist, as we will see in the next tutorial. +be handled by a `hello()` method. In other words, the `hello()` method is installed at the web server at `/hello` endpoint with the `GET` HTTP method. Similar methods for `PUT`, `POST` and `DELETE` methods exist, as we will see in the next tutorial. 5. This is a handler method, which is called by the router when `GET` request is send to a `/hello` endpoint. Every handler method must be a coroutine! That means, it has to be defined with `async def` keyword. Also, there has to be the `request` argument, even if you (for some peculiar reason) don't want to use it in the function body. Otherwise it won't work together with the `add_get()` method. -6. The `asab.web.rest` module provides a `json_response()` method that simply sends back any data you want to the client in JSON format. +6. The `asab.web.rest` module provides a `json_response()` method that simply sends back any data you want to the client in JSON format. In this case, the output is just a single string, but it could be any JSON-serializable document. + + +As you can see, it is easy to create a fully functioning web server using asab, so that you can concentrate more on the application logic. +`asab` is built on the top of the [asyncio](https://docs.python.org/3/library/asyncio.html) and [aiohttp](https://docs.aiohttp.org/en/stable/) libraries which are designed to make the most out of [non-blocking network operations](https://docs.aiohttp.org/en/stable/http_request_lifecycle.html#aiohttp-request-lifecycle). + + +Logging basics +-------------- + +At this point, let us also mention the basics of asab logging. + +ASAB Application provides a structured logging which is used to trace back useful information about various events during the application run-time. +The default configuration sends logs to the standard output, so you can see the logs directly in the terminal. + +If you now check the terminal where the asab application is running, you should see messages similar to these: + +``` python +23-Jun-2023 08:08:44.683943 NOTICE asab.application is ready. # (1) +23-Jun-2023 08:18:04.116786 NOTICE asab.web.al [sd I="127.0.0.1" ...] # (2) +``` + +1. This log informs that the initialization of the application is finished. It means that configuration is loaded, logging is setup, the event loop is constructed etc. + +2. This log is displayed every time a valid HTTP request is processed. +If you deconstruct the message, you learn what request method was used, what application sent the request, the response status code etc. + + +Finally, let's stop the application using `Control+C`, see the last log displayed and go to the [next tutorial](./03_rest_api.md) where we create a microservice with REST API. + +``` python +23-Jun-2023 08:32:23.292862 NOTICE asab.application is exiting ... #(1) +``` +1. This log informs that the application is in exit-time. +Note that there may be processes that take a long time to terminate, so terminating an application may take a noticeably long time. \ No newline at end of file diff --git a/docs/tutorials/03_rest_api.md b/docs/tutorials/03_rest_api.md index f87362046..0ae8273c2 100644 --- a/docs/tutorials/03_rest_api.md +++ b/docs/tutorials/03_rest_api.md @@ -1,5 +1,7 @@ -Create microservice with REST API -================================= +Creating a microservice with REST API +===================================== + +In the [previous tutorial](./02_web_server.md), you have learned how to create a web server. With this tutorial, you will create a basic ASAB microservice that provides a REST HTTP API. This microservice will implement Create, Read, diff --git a/mkdocs.yml b/mkdocs.yml index ff136c47d..1b1bae012 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -20,6 +20,9 @@ theme: - pymdownx.tilde - def_list - navigation.tracking + + repo_name: TeskaLabs/asab + repo_url: https://github.com/TeskaLabs/asab icon: admonition: @@ -92,6 +95,11 @@ markdown_extensions: - attr_list - md_in_html +extra: + social: + - icon: fontawesome/brands/github-alt + link: https://github.com/TeskaLabs/asab + nav: - Introduction: index.md From 35839bafdae06281c4c8c03bffe111b40f686ada Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 23 Jun 2023 14:38:13 +0200 Subject: [PATCH 010/154] Improve REST API tutorial --- docs/tutorials/03_rest_api.md | 402 ++++++++++++++++------------------ 1 file changed, 183 insertions(+), 219 deletions(-) diff --git a/docs/tutorials/03_rest_api.md b/docs/tutorials/03_rest_api.md index 0ae8273c2..8814d9b50 100644 --- a/docs/tutorials/03_rest_api.md +++ b/docs/tutorials/03_rest_api.md @@ -4,169 +4,103 @@ Creating a microservice with REST API In the [previous tutorial](./02_web_server.md), you have learned how to create a web server. With this tutorial, you will create a basic ASAB microservice that -provides a REST HTTP API. This microservice will implement Create, Read, -Update and Delete functionality, in another words CRUD. MongoDB will be -used as the database. - -Prerequisites -------------- - -1. Python version 3.6 or later -2. Asynchronous Server App Boilerplate (ASAB) version 20.3 or later -3. MongoDB instance -4. Postman - -xxx {.note} -xxx {.title} -Note -xxx - -We will use Docker to run MongoDB. Docker installation is not covered in -this tutorial, but there are scores of good ones online should you run -into any trouble. If you\'re not familiar with Docker yet, it is a great -opportunity to start (). - -Otherwise, you can install MongoDB following one of these tutorials: - -xxx - -Components ----------- - -The microservice consists of several modules (aka Python files). These -modules are as follows (and also indicate the file structure) and will -be discussed in more detail in the respective sections below, going from -top to bottom: - -``` {.} -. -└── myrestapi.py -─── myrestapi - └── __init__.py - ─── app.py - ─── tutorial - └── handler.py - └── service.py +provides a REST HTTP API. This microservice will implement **CREATE**, **READ**, **UPDATE** and **DELETE** functionality, in another words: **CRUD**. +We will also use [MongoDB](https://www.mongodb.com/) as a database running on [Docker](https://docs.docker.com/), and . In case you are not familiar with these technologies, take the opportunity to learn their basics concepts, as they are alpha-omega of the backend programming. + +Set up the project with Docker and MongoDB +------------------------------------------ + +Here are the steps: + +1. **Install Docker** if you don't have it already. Go to [the official website](https://docs.docker.com/get-docker/), choose your operating system and follow the guide. + + !!! tip + Take it as a recommendation from the experience of the authors of this tutorial that in most cases there is no need to install a Docker desktop, but the Docker engine will suffice. In some cases, installing Docker desktop may cause problems when interacting with Docker in the terminal. + + You can always check if you have Docker installed successfully: + ``` bash + docker --version + ``` + +2. **Pull the MongoDB image** from Docker Hub. +``` bash +docker pull mongo ``` - -MongoDB -------- - -To make things simple, let\'s use a Docker image. - -Pull this image: - -You can simply use the command below to run it. If you choose to run the -instance without a password, don\'t forget to adjust the related -**asab.Config** in [./myrestapi/app.py]{.title-ref}. - -``` {.bash} +Start the container: +``` bash docker run -d -p 27017:27017 \ -e MONGO_INITDB_ROOT_USERNAME=user \ -e MONGO_INITDB_ROOT_PASSWORD=secret \ mongo ``` -Postman -------- - -We use Postman to test the webservice REST API. - -You can download it here: - +3. **Install Postman** in case you do not have it. We will use it to test the webservice REST API. +You can download it from [the official website](https://www.postman.com/downloads/). The Postman is fairly straightforward to use. You can create your collection of HTTP requests, save them, or automatically generate documentation. -myrestapi.py ------------- +4. **Prepare the structure of the project.** Every asab microservice consists of several Python modules. +Create the following file structure in your repository: -This is where everything starts. Begin with the shebang line, which -tells the executing operating system **python** should execute this -program. + ``` + . + └── my_rest_api.py + ─── my_rest_api + └── __init__.py + ─── app.py + ─── tutorial + └── handler.py + └── service.py + ─── conf + └── config.ini + ``` -``` {.python} -#!/usr/bin/env python3 -``` +Build a microservice +-------------------- -Imports follow. All you need here is the application. It is called -**TutorialApp**: +With the prepared modules, we move on to actual coding. Here is the code for every module with explanations. -``` {.python} -from myrestapi import TutorialApp -``` -Next, instantiate an application class [TutorialApp]{.title-ref} in the -\_\_[main](#init__.py) of the application, and run it: +``` python title="my_rest_api.py" +#!/usr/bin/env python3 # (1) +from my_rest_api import TutorialApp # (2) -``` {.python} -if __name__ == '__main__': +if __name__ == '__main__': # (3) app = TutorialApp() app.run() ``` -app.py ------- - -[./myrestapi/app.py]{.title-ref} +1. This is the executable file used to run the application via `python my_rest_api.py` command. +2. The asab application will be stored in `my_rest_api` module. +3. As always, we start the application by creating it's singleton and executing the `run()` method. -Define the application class [TutorialApp]{.title-ref}. +```python title="my_rest_api/app.py" -Imports first: - -``` {.python} -import asab +import asab # (1) import asab.web import asab.web.rest -import asab.storage -``` - -Add some default configuration: - -``` {.python} -asab.Config.add_defaults( -{ - 'asab:storage': { - 'type': 'mongodb', - 'mongodb_uri': 'mongodb://mongouser:mongopassword@mongoipaddress:27017', - 'mongodb_database': 'mongodatabase' - }, -}) -``` +import asab.storage # (2) -xxx {.note} -xxx {.title} -Note -xxx - -To make things more simple, Mongo credentials are stored here as a -default configuration. Usually, you provide your app with a -configuration file using [-c]{.title-ref} commandline option. Learn more -in section `configuration-ref`{.interpreted-text role="ref"}. -xxx - -Next, describe the class, it inherits from the basic ASAB Application -class, but you need to expand it a little: - -``` {.python} class TutorialApp(asab.Application): def __init__(self): - super().__init__() - # Register modules + super().__init__() # (3) + + # Register modules # (4) self.add_module(asab.web.Module) self.add_module(asab.storage.Module) - # Locate the web service - self.WebService = self.get_service("asab.WebService") + # Locate the web service + self.WebService = self.get_service("asab.WebService") # (5) self.WebContainer = asab.web.WebContainer( - self.WebService, "web" + self.WebService, "web" # (6) ) self.WebContainer.WebApp.middlewares.append( - asab.web.rest.JsonExceptionMiddleware + asab.web.rest.JsonExceptionMiddleware # (7) ) - # Initialize services + # Initialize services # (8) from .tutorial.handler import CRUDWebHandler from .tutorial.service import CRUDService self.CRUDService = CRUDService(self) @@ -175,53 +109,65 @@ class TutorialApp(asab.Application): ) ``` -\_\_init\_\_.py ---------------- +1. As always, let's start with importing the `asab` modules. -[./myrestapi/\_\_init\_\_.py]{.title-ref} +2. This module is a built-in asab service which is used for manipulation with databases. -Init file is needed so myrestapi will work as a module. Just import the -TutorialApp. +3. Remember, if you override a `__init__()` method, don't forget to add this super-initialization line of code. -``` {.python} +4. `asab` modules are registered with the `add_module()` method on the `asab.Application` object. + +5. To access the web service, use the `get_service()` method. It is common to have all the services stored as attributes on the `asab.Application` object. + +6. TODO +7. TODO + +8. `asab` microservices consist of two parts: **services** and **handlers**. +When HTTP request is sent to the web server, **handler** will identify its type and calls the corresponding **service**. The service performs some operations and returns some data back to the handler, which sends it back to the client. + +``` ini title="conf/config.ini" +[asab:storage] +type=mongodb +mongodb_uri='mongodb://mongouser:mongopassword@mongoipaddress:27017' +mongodb_database=mongodatabase +``` + +Continue with the init file, so that the directory `my_rest_api` will work as a module. + +``` python title="my_rest_api/__init__.py" from .app import TutorialApp __all__ = [ - "TutorialApp", + "TutorialApp", # (1) ] ``` -handler.py ----------- +1. The list of strings that define what variables have to be imported to another file. If you don't know, what is going on, [this explanation](https://www.geeksforgeeks.org/python-__all__/) could help. In this case, we only want to import `TutorialApp` class. -[./myrestapi/tutorial/handler.py]{.title-ref} +Create a handler +---------------- The handler is where HTTP Rest calls are handled and transformed into the actual (internal) service calls. From another perspective, the handler should contain only translation between REST calls and the -service interface. No actual \'business logic\' should be here. It is +service interface. No actual 'business logic' should be here. It is strongly suggested to build these CRUD methods one by one and test them -straight away. If you haven\'t set up your database test instance yet, -now is the time to do it. +straight away. -As usual, we start by importing modules: +``` python title="my_rest_api/tutorial/handler.py" linenums="1" -``` {.python} import asab import asab.web.rest -``` -Let\'s start with two methods - [create]{.title-ref} and -[read]{.title-ref} which allow us to write into database and check the -record. -``` {.python} class CRUDWebHandler(object): def __init__(self, app, mongo_svc): - self.CRUDService = mongo_svc + self.CRUDService = mongo_svc # (1) web_app = app.WebContainer.WebApp + + # Handle PUT and GET requests web_app.router.add_put( - '/crud-myrestapi/{collection}', + '/crud-myrestapi/{collection}', # (2) self.create ) web_app.router.add_get( @@ -229,110 +175,98 @@ class CRUDWebHandler(object): self.read ) - - @asab.web.rest.json_schema_handler({ + self.JSONSchema = { # (3) 'type': 'object', - 'properties': { - '_id': {'type': 'string'}, - 'field1': {'type': 'string'}, - 'field2': {'type': 'number'}, - 'field3': {'type': 'number'} - }}) + 'properties': { + '_id': {'type': 'string'}, + 'name': {'type': 'string'}, + 'age': {'type': 'number'} + } + } + + + @asab.web.rest.json_schema_handler(self.JSONSchema) # (4) async def create(self, request, *, json_data): - collection = request.match_info['collection'] + collection = request.match_info['collection'] # (5) result = await self.CRUDService.create( - collection, json_data + collection, json_data # (6) ) - if result: + if result: return asab.web.rest.json_response( - request, {"result": "OK"} + request, {"result": "OK"} # (7) ) else: asab.web.rest.json_response( - request, {"result": "FAILED"} + request, {"result": "FAILED"} # (8) ) - async def read(self, request): - collection = request.match_info['collection'] + collection = request.match_info['collection'] # (9) key = request.match_info['id'] + response = await self.CRUDService.read( - collection, key + collection, key # (10) ) return asab.web.rest.json_response( - request, response + request, response # (11) ) ``` +1. This is a reference on the microservice. In this app, we will create a service which uses the MongoDB Storage. + +2. Methods `add_put`, `add_get` take arguments `path`, which specifies the endpoint, and `handler`, which is a coroutine that is called after the request is received from the client. In fact, these methods are performed on [aiohttp web handler](https://docs.aiohttp.org/en/stable/web_reference.html#aiohttp.web.UrlDispatcher) and are special cases of the `add_route` method. In this case, the the path is `/crud-myrestapi/{collection}`, where collection is a variable name. + +3. In order to prevent storing arbitrary data, we define a [JSON schema](https://json-schema.org/). Now if the request data do not satisfy the format, they cannot be posted to the database. + +4. The JSON schema handler is used as a decorator and validates JSON documents by [JSON schema](https://json-schema.org/). It takes either a dictionary with the schema itself (as in this example), or a string with the path for the JSON file to look at. + +5. This method is used for matching data from the URI. They must be listed in the brackets such as `{collection}` on line 12. + +6. After the request is sent and the handler calls the `create` method, it calls a method with the same name on the service, expecting from it to perform some logic ("save `json_data` into `database`") and then return some data back. + +7. Now if the service has returned some data back, the handler will send a positive response to the client... + +8. ...or negative if the service didn't return anything. + +9. Once again, obtain the data from the path. + +10. After the `GET` request is sent, the handler calls the service to perform a method `read()`, expecting some data back. + +11. Simply respond with the data found in the collection. If they do not exist, the response will be empty. + +Let's start with two methods - `PUT` and `GET` which allow us to write into database and check the +record. + The handler only accepts the incoming requests and returns appropriate -responses. All of the \"logic\", be it the specifics of the database +responses. All of the "logic", be it the specifics of the database connection, additional validations and other operations take place in the CRUDService. -POST and PUT requests typically come with data in their body. Providing +`POST` and `PUT` requests typically come with data in their body. Providing your [WebContainer]{.title-ref} with [JsonExceptionMiddleware]{.title-ref} enables you to validate a JSON input using [\@asab.web.rest.json\_schema\_handler]{.title-ref} decorator and JSON schema (). -xxx {.note} -xxx {.title} -Note -xxx + ASAB WebServer is built on top of the aiohttp library. For further details please visit . -xxx -service.py ----------- -[./myrestapi/tutorial/service.py]{.title-ref} +Create a service +---------------- -As mentioned above, this is where the inner workings of the microservice -request processing are. Let\'s start as usual, by importing the desired -modules: +``` python title="my_rest_api/tutorial/service.py" -``` {.python} import asab import asab.storage.exceptions -``` - -We want to start logging in here: - -``` {.python} import logging -# L = logging.getLogger(__name__) -# -``` - -Now define the CRUDService class which inherits from the -[asab.Service]{.title-ref} class. -xxx {.note} -xxx {.title} -Note -xxx - -[asab.Service]{.title-ref} is a lightweight yet powerful abstract class -providing your object with 3 functionalities: - -- Name of the [asab.Service]{.title-ref} is registered in the app and - can be called from the [app]{.title-ref} object anywhere in your - code. -- [asab.Service]{.title-ref} class implements - [initialize()]{.title-ref} and [finalize()]{.title-ref} coroutines - which help you to handle asynchronous operations in init and exit - time of your application. -- [asab.Service]{.title-ref} registers application object as - [self.App]{.title-ref} for you. -xxx - -``` {.python} class CRUDService(asab.Service): def __init__(self, app, service_name='crud.CRUDService'): @@ -367,17 +301,43 @@ class CRUDService(asab.Service): collection, obj_id ) return response + ``` +As mentioned above, this is where the inner workings of the microservice +request processing are. Let\'s start as usual, by importing the desired +modules: + + +Now define the CRUDService class which inherits from the +[asab.Service]{.title-ref} class. + + + +[asab.Service]{.title-ref} is a lightweight yet powerful abstract class +providing your object with 3 functionalities: + +- Name of the [asab.Service]{.title-ref} is registered in the app and + can be called from the [app]{.title-ref} object anywhere in your + code. +- [asab.Service]{.title-ref} class implements + [initialize()]{.title-ref} and [finalize()]{.title-ref} coroutines + which help you to handle asynchronous operations in init and exit + time of your application. +- [asab.Service]{.title-ref} registers application object as + [self.App]{.title-ref} for you. +xxx + + [asab.StorageService]{.title-ref} initialized in [app.py]{.title-ref} as part of the [asab.storage.Module]{.title-ref} enables connection to MongoDB. Further on, two methods provide the handler with the desired functionalities. -Now test it! ------------- +Testing the app +--------------- -The application is implicitly running on an **8080** port. Open the +The application is implicitly running on an [http://localhost:8080/](http://localhost:8080/) port. Open the Postman and set a new request. Try the PUT method: @@ -459,15 +419,19 @@ xxx Up and running! Congratulation on your first ASAB microservice! -Oh, wait\... +Exercise 0: Store JSON schema in the file +----------------------------------------- + +In order to get used to the `asab.web.rest.json_schema_handler()` decorator, store the JSON schema in a separate file. Then pass its path as an argument to the decorator. + + +Exercise 1: Implement `POST` and `DELETE` methods +------------------------------------------------- -**C**, **R**\... What about **Update** and **Delete** you ask? +For updating and deleting data from the database, we should implement the methods `POST` and `DELETE`. -You already know everything to add the next functionality! Accept the -challenge and try it yourself! Or check out the code below. +1. Implement `update()` and `delete()` methods to the `CRUDService` class. Use -Update and Delete ------------------ **handler.py** From ff09219520679491e795f8636722f272c44f8807 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 23 Jun 2023 18:08:12 +0200 Subject: [PATCH 011/154] Progress on testing REST API section --- docs/topics/admin/install.md | 21 +-- docs/tutorials/01_hello_world.md | 12 +- docs/tutorials/02_web_server.md | 63 +++++++-- docs/tutorials/03_rest_api.md | 231 +++++++++++++++++-------------- docs/tutorials/04_storage.md | 5 + docs/tutorials/05_pubsub.md | 5 + docs/tutorials/06_library.md | 1 + docs/tutorials/07_swagger.md | 0 mkdocs.yml | 5 + 9 files changed, 209 insertions(+), 134 deletions(-) create mode 100644 docs/tutorials/04_storage.md create mode 100644 docs/tutorials/05_pubsub.md create mode 100644 docs/tutorials/06_library.md create mode 100644 docs/tutorials/07_swagger.md diff --git a/docs/topics/admin/install.md b/docs/topics/admin/install.md index 1b2ee91a4..c2b4e528b 100644 --- a/docs/topics/admin/install.md +++ b/docs/topics/admin/install.md @@ -8,15 +8,15 @@ Install ASAB using pip This is the recommended installation method. -``` {.bash} -$ pip install asab +``` bash +pip install asab ``` -Install ASAB using easy\_install --------------------------------- +Install ASAB using easy install +------------------------------- -``` {.bash} -$ easy_install asab +``` bash +easy_install asab ``` Install ASAB for a GitHub @@ -25,9 +25,10 @@ Install ASAB for a GitHub To install ASAB from a master branch of the GIT repository, use following command. -*Note*: Git has to be installed in order to successfuly complete the -installation. +!!! note + Git has to be installed in order to successfuly complete the + installation. -``` {.bash} -$ pip install git+https://github.com/TeskaLabs/asab.git +``` bash +pip install git+https://github.com/TeskaLabs/asab.git ``` diff --git a/docs/tutorials/01_hello_world.md b/docs/tutorials/01_hello_world.md index a6dfc8cdd..28f2e8d7d 100644 --- a/docs/tutorials/01_hello_world.md +++ b/docs/tutorials/01_hello_world.md @@ -54,14 +54,14 @@ Let's look on the application one more time. ``` python title="main.py" linenums="1" - #!/usr/bin/env python3 # (1) - import asab # (2) + #!/usr/bin/env python3 # (1)! + import asab # (2)! - class MyApplication(asab.Application): # (3) - async def main(self): # (4) - print("Hello world") # (5) + class MyApplication(asab.Application): # (3)! + async def main(self): # (4)! + print("Hello world") # (5)! - if __name__ == '__main__': # (6) + if __name__ == '__main__': # (6)! app = MyApplication() app.run() ``` diff --git a/docs/tutorials/02_web_server.md b/docs/tutorials/02_web_server.md index cf9d3ae73..76a6e7934 100644 --- a/docs/tutorials/02_web_server.md +++ b/docs/tutorials/02_web_server.md @@ -1,6 +1,9 @@ Creating a web server ===================== +Build and run +------------- + Now, when you know how to create and run [a basic asab application](./01_hello_world.md), let's create the first web server! Set up a new project and create a new file `app.py` with the following code: @@ -67,8 +70,6 @@ You should get the same result from a terminal using cURL command: curl --location 'localhost:8080/hello' ``` - - Deeper look ----------- @@ -77,22 +78,22 @@ Let's go line by line in the code to understand how the asab server is construct ``` python title="app.py" linenums="1" #!/usr/bin/env python3 -import asab.web.rest # (1) +import asab.web.rest # (1) class MyWebApplication(asab.Application): def __init__(self): - super().__init__() # (2) + super().__init__() # (2) # Create the Web server - web = asab.web.create_web_server(self) # (3) + web = asab.web.create_web_server(self) # (3) # Add a route to the handler method - web.add_get('/hello', self.hello) # (4) + web.add_get('/hello', self.hello) # (4) # This is the web request handler - async def hello(self, request): # (5) - return asab.web.rest.json_response( # (6) + async def hello(self, request): # (5) + return asab.web.rest.json_response( # (6) request, data="Hello, world!" ) @@ -122,8 +123,8 @@ As you can see, it is easy to create a fully functioning web server using asab, `asab` is built on the top of the [asyncio](https://docs.python.org/3/library/asyncio.html) and [aiohttp](https://docs.aiohttp.org/en/stable/) libraries which are designed to make the most out of [non-blocking network operations](https://docs.aiohttp.org/en/stable/http_request_lifecycle.html#aiohttp-request-lifecycle). -Logging basics --------------- +Logging +------- At this point, let us also mention the basics of asab logging. @@ -133,8 +134,8 @@ The default configuration sends logs to the standard output, so you can see the If you now check the terminal where the asab application is running, you should see messages similar to these: ``` python -23-Jun-2023 08:08:44.683943 NOTICE asab.application is ready. # (1) -23-Jun-2023 08:18:04.116786 NOTICE asab.web.al [sd I="127.0.0.1" ...] # (2) +23-Jun-2023 08:08:44.683943 NOTICE asab.application is ready. # (1) +23-Jun-2023 08:18:04.116786 NOTICE asab.web.al [sd I="127.0.0.1" ...] # (2) ``` 1. This log informs that the initialization of the application is finished. It means that configuration is loaded, logging is setup, the event loop is constructed etc. @@ -143,11 +144,43 @@ If you now check the terminal where the asab application is running, you should If you deconstruct the message, you learn what request method was used, what application sent the request, the response status code etc. -Finally, let's stop the application using `Control+C`, see the last log displayed and go to the [next tutorial](./03_rest_api.md) where we create a microservice with REST API. +If you stop the application using `Control+C`, another log shows up: ``` python -23-Jun-2023 08:32:23.292862 NOTICE asab.application is exiting ... #(1) +23-Jun-2023 08:32:23.292862 NOTICE asab.application is exiting ... #(1)! ``` 1. This log informs that the application is in exit-time. -Note that there may be processes that take a long time to terminate, so terminating an application may take a noticeably long time. \ No newline at end of file +Note that there may be processes that take a long time to terminate, so terminating an application may take a noticeably long time. + +`asab` uses a formatted logger on top of [the standard logging library](https://docs.python.org/3/library/logging.html) provided with utilities such as + +- colors indicating the log level +- structured data formatting +- log rotation +- logging to syslog + +Configuration +------------- + +In order to start your `asab` application with certain configuration, create a config file in `ini` format. There are specific options + +``` ini title="config.ini" +[web] +listen=0.0.0.0:7000 + +[logging] +level=DEBUG + +[logging:file] +path=./log.txt +``` + +Now if you run the application with this configuration file, +``` bash +python app.py -c config.ini +``` +you should see some differences: now your web server is running on [http://localhost:8000](http://localhost:8000), logging is set to another level and it is stored in a file `log.txt`. + + +Finally, go to the [next tutorial](./03_rest_api.md) where we create a microservice with REST API. \ No newline at end of file diff --git a/docs/tutorials/03_rest_api.md b/docs/tutorials/03_rest_api.md index 8814d9b50..d8a431f4e 100644 --- a/docs/tutorials/03_rest_api.md +++ b/docs/tutorials/03_rest_api.md @@ -56,6 +56,7 @@ Create the following file structure in your repository: └── config.ini ``` + Build a microservice -------------------- @@ -63,10 +64,10 @@ With the prepared modules, we move on to actual coding. Here is the code for eve ``` python title="my_rest_api.py" -#!/usr/bin/env python3 # (1) -from my_rest_api import TutorialApp # (2) +#!/usr/bin/env python3 # (1)! +from my_rest_api import TutorialApp # (2)! -if __name__ == '__main__': # (3) +if __name__ == '__main__': # (3)! app = TutorialApp() app.run() ``` @@ -77,30 +78,30 @@ if __name__ == '__main__': # (3) ```python title="my_rest_api/app.py" -import asab # (1) +import asab # (1)! import asab.web import asab.web.rest -import asab.storage # (2) +import asab.storage # (2)! class TutorialApp(asab.Application): def __init__(self): - super().__init__() # (3) + super().__init__() # (3)! - # Register modules # (4) - self.add_module(asab.web.Module) + # Register modules + self.add_module(asab.web.Module) # (4)! self.add_module(asab.storage.Module) # Locate the web service - self.WebService = self.get_service("asab.WebService") # (5) + self.WebService = self.get_service("asab.WebService") # (5)! self.WebContainer = asab.web.WebContainer( - self.WebService, "web" # (6) + self.WebService, "web" # (6)! ) self.WebContainer.WebApp.middlewares.append( - asab.web.rest.JsonExceptionMiddleware # (7) + asab.web.rest.JsonExceptionMiddleware # (7)! ) - # Initialize services # (8) + # Initialize services # (8)! from .tutorial.handler import CRUDWebHandler from .tutorial.service import CRUDService self.CRUDService = CRUDService(self) @@ -125,12 +126,6 @@ class TutorialApp(asab.Application): 8. `asab` microservices consist of two parts: **services** and **handlers**. When HTTP request is sent to the web server, **handler** will identify its type and calls the corresponding **service**. The service performs some operations and returns some data back to the handler, which sends it back to the client. -``` ini title="conf/config.ini" -[asab:storage] -type=mongodb -mongodb_uri='mongodb://mongouser:mongopassword@mongoipaddress:27017' -mongodb_database=mongodatabase -``` Continue with the init file, so that the directory `my_rest_api` will work as a module. @@ -138,7 +133,7 @@ Continue with the init file, so that the directory `my_rest_api` will work as a from .app import TutorialApp __all__ = [ - "TutorialApp", # (1) + "TutorialApp", # (1)! ] ``` @@ -162,12 +157,12 @@ import asab.web.rest class CRUDWebHandler(object): def __init__(self, app, mongo_svc): - self.CRUDService = mongo_svc # (1) + self.CRUDService = mongo_svc # (1)! web_app = app.WebContainer.WebApp # Handle PUT and GET requests web_app.router.add_put( - '/crud-myrestapi/{collection}', # (2) + '/crud-myrestapi/{collection}', # (2)! self.create ) web_app.router.add_get( @@ -175,41 +170,42 @@ class CRUDWebHandler(object): self.read ) - self.JSONSchema = { # (3) + self.JSONSchema = { # (3)! 'type': 'object', 'properties': { '_id': {'type': 'string'}, 'name': {'type': 'string'}, - 'age': {'type': 'number'} + 'age': {'type': 'number'}, + 'job': {'type': 'string'} } } - @asab.web.rest.json_schema_handler(self.JSONSchema) # (4) + @asab.web.rest.json_schema_handler(self.JSONSchema) # (4)! async def create(self, request, *, json_data): - collection = request.match_info['collection'] # (5) + collection = request.match_info['collection'] # (5)! result = await self.CRUDService.create( - collection, json_data # (6) + collection, json_data # (6)! ) if result: return asab.web.rest.json_response( - request, {"result": "OK"} # (7) + request, {"result": "OK"} # (7)! ) else: asab.web.rest.json_response( - request, {"result": "FAILED"} # (8) + request, {"result": "FAILED"} # (8)! ) async def read(self, request): - collection = request.match_info['collection'] # (9) + collection = request.match_info['collection'] # (9)! key = request.match_info['id'] response = await self.CRUDService.read( - collection, key # (10) + collection, key # (10)! ) return asab.web.rest.json_response( - request, response # (11) + request, response # (11)! ) ``` @@ -243,17 +239,6 @@ responses. All of the "logic", be it the specifics of the database connection, additional validations and other operations take place in the CRUDService. -`POST` and `PUT` requests typically come with data in their body. Providing -your [WebContainer]{.title-ref} with -[JsonExceptionMiddleware]{.title-ref} enables you to validate a JSON -input using [\@asab.web.rest.json\_schema\_handler]{.title-ref} -decorator and JSON schema (). - - - -ASAB WebServer is built on top of the aiohttp library. For further -details please visit . - Create a service ---------------- @@ -334,90 +319,130 @@ part of the [asab.storage.Module]{.title-ref} enables connection to MongoDB. Further on, two methods provide the handler with the desired functionalities. +Create a configuration file +--------------------------- + + +``` ini title="conf/config.ini" +[asab:storage] +type=mongodb +mongodb_uri='mongodb://mongouser:mongopassword@mongoipaddress:27017' +mongodb_database=mongodatabase +``` + + Testing the app --------------- -The application is implicitly running on an [http://localhost:8080/](http://localhost:8080/) port. Open the -Postman and set a new request. +Now everything is prepared and we can test our application using Postman. Let's create a new collection named `celebrities` provided with some information. -Try the PUT method: +1. Start the application + ``` + python my_rest_api.py -c conf/config.ini + ``` -``` {.} -127.0.0.1:8080/crud-myrestapi/movie -``` + The application is implicitly running on an [http://localhost:8080/](http://localhost:8080/) port. -Insert into the request body: +2. Open the Postman and set a new request. + First try to add some data using `PUT` method to `localhost:8080/crud-myrestapi/celebrities` endpoint. Insert this JSON document into the request body: -``` {.} -{ -"_id": "1", -"field1": "something new", -"field2": 5555, -"field3": 44424 -} -``` + ``` json + { + "_id": "1", + "name": "Johnny Depp", + "age": 60, + "job": "actor" + } + ``` -When there\'s a record in your database, try to read it! For example -with this GET request: + Hopefully you received a status 200! Let's add one more. -``` {.} -127.0.0.1:8080/crud-myrestapi/movie/1 -``` + ``` json + { + "_id": "2", + "name": "Lady Gaga", + "age": 37, + "job": "singer" + } + ``` -Is your response with a 200 status code? Does it return desired data? + Now let's test if we can request for some data. Use the `GET` method to `localhost:8080/crud-myrestapi/celebrities/1` endpoint, this time with no request body. -xxx {.note} -xxx {.title} -Note -xxx + Now, what is the response? -**TROUBLESHOOTING** + !!! success -**ERROR** + Up and running! Congratulation on your first ASAB microservice! -``` {.} -ModuleNotFoundError: No module named 'pymongo.mongo_replica_set_client' -``` + !!! failure + If you see the following message: -Try: + ``` bash + ModuleNotFoundError: No module named 'pymongo.mongo_replica_set_client' + ``` -``` {.} -pip install motor -``` + that means there is a missing module, probably the [motor](https://motor.readthedocs.io/en/stable/) library, which provides an asynchronous driver for MongoDB. Try to fix it: -**ERROR** + ``` bash + pip install motor + ``` -``` {.} -OSError: [Errno 98] error while attempting to bind on address ('0.0.0.0', 8080): address already in use -``` + !!! failure + If you see the following message: -Try to kill process listening on 8080 or add \[web\] section into -configuration: - -``` {.} -asab.Config.add_defaults( -{ - 'asab:storage': { - 'type': 'mongodb', - 'mongodb_uri': 'mongodb://mongouser:mongopassword@mongoipaddress:27017', - 'mongodb_database': 'mongodatabase' - }, - 'web': { - 'listen': '0.0.0.0 8081' - } -}) -``` + ``` bash + OSError: [Errno 98] error while attempting to bind on address ('0.0.0.0', 8080): address already in use + ``` -**ERROR** + that means that the port is already used by some other application (have you exit the application from the previous tutorial?) + To check, what is running on your port, try: -No error at all, no response either. + ``` bash + lsof | grep LISTEN + ``` -Try to check the Mongo database credentials. Do your credentials in the -configuration in [app.py]{.title-ref} fit the ones you entered when -running the Mongo Docker image? -xxx + or + + ``` bash + lsof | grep localhost:8000 + ``` + + If you something similar to the following output: + + ``` + python3 103203 user 7u IPv4 1059624 0t0 TCP *:bbs (LISTEN) + ``` + + that means there is a running process using the port with ID 103203. + + The first option is simply to stop the process: + + ``` + kill -9 103203 + ``` + (replace the ID with the corresponding ID from the previous output). + + The second option is to add these lines into the configuration file: + + ``` ini title="conf/config.ini" + [web] + listen=0.0.0.0:8081 + ``` + + If you run the app again, it should be running on an [http://localhost:8081/](http://localhost:8081/) port. + + !!! question + + You see no error at all, no response either. + + Try to check the Mongo database credentials. Do your credentials in the config file fit the ones you entered when running the Mongo Docker image? + + +Conclusion +---------- + +TODO TODO TODO -Up and running! Congratulation on your first ASAB microservice! Exercise 0: Store JSON schema in the file ----------------------------------------- diff --git a/docs/tutorials/04_storage.md b/docs/tutorials/04_storage.md new file mode 100644 index 000000000..f54b3aabc --- /dev/null +++ b/docs/tutorials/04_storage.md @@ -0,0 +1,5 @@ +# TODO: Add tutorial on how to use storage + +Concentrate more on StorageServic + +# Build a NOTE-taking app \ No newline at end of file diff --git a/docs/tutorials/05_pubsub.md b/docs/tutorials/05_pubsub.md new file mode 100644 index 000000000..14d67f9b3 --- /dev/null +++ b/docs/tutorials/05_pubsub.md @@ -0,0 +1,5 @@ +# TODO: add tutorial on PubSub + +Create a very basic App that should use PubSub messages + +Concepts: \ No newline at end of file diff --git a/docs/tutorials/06_library.md b/docs/tutorials/06_library.md new file mode 100644 index 000000000..8806d881e --- /dev/null +++ b/docs/tutorials/06_library.md @@ -0,0 +1 @@ +Create a \ No newline at end of file diff --git a/docs/tutorials/07_swagger.md b/docs/tutorials/07_swagger.md new file mode 100644 index 000000000..e69de29bb diff --git a/mkdocs.yml b/mkdocs.yml index 1b1bae012..cc8f25890 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -66,6 +66,11 @@ plugins: custom_fences: - name: code class: code + # TODO: Diagrams for some reason do not work https://squidfunk.github.io/mkdocs-material/reference/diagrams/ + # - name: mermaid + # class: mermaid + # format: !!python/name:pymdownx.superfences.fence_code_format + config: default_handler: python python: From c3d576b4d190635ce0bafacf7a0386c29f5852ab Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 3 Jul 2023 13:55:23 +0200 Subject: [PATCH 012/154] Tutorial progress --- docs/index.md | 9 --------- docs/tutorials/01_hello_world.md | 7 +++++-- docs/tutorials/02_web_server.md | 19 +++++++++---------- docs/tutorials/03_rest_api.md | 9 ++++----- docs/tutorials/04_storage.md | 6 ++---- mkdocs.yml | 3 ++- 6 files changed, 22 insertions(+), 31 deletions(-) diff --git a/docs/index.md b/docs/index.md index df7213e3f..cd373f82a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -55,12 +55,3 @@ ASAB is the right choice when > - building the microservice or the application server. > - utilizing asynchronous I/O (aka > [asyncio](https://docs.python.org/3/library/asyncio.html)). - -``` yaml -theme: - features: - - content.code.annotate # (1) -``` - -1. :man_raising_hand: I'm a code annotation! I can contain `code`, __formatted - text__, images, ... basically anything that can be written in Markdown. \ No newline at end of file diff --git a/docs/tutorials/01_hello_world.md b/docs/tutorials/01_hello_world.md index 28f2e8d7d..e7a321c8c 100644 --- a/docs/tutorials/01_hello_world.md +++ b/docs/tutorials/01_hello_world.md @@ -92,7 +92,10 @@ It creates the application object and executes the `Application.run()`{.interpreted-text role="any"} method. This is a standard way of how ASAB application is started. -Next steps ----------- + +Summary +------- + +In this tutorial, you learned how to install `asab` and create a basic application. Check out tutorials about how to build ASAB based [web server](./02_web_server.md). diff --git a/docs/tutorials/02_web_server.md b/docs/tutorials/02_web_server.md index 76a6e7934..b7e6c47b0 100644 --- a/docs/tutorials/02_web_server.md +++ b/docs/tutorials/02_web_server.md @@ -1,10 +1,9 @@ Creating a web server ===================== +Now, when you know how to create and run [a basic asab application](./01_hello_world.md), let's create your first web server. -Build and run -------------- - -Now, when you know how to create and run [a basic asab application](./01_hello_world.md), let's create the first web server! +Create and run the app +---------------------- Set up a new project and create a new file `app.py` with the following code: @@ -37,9 +36,9 @@ if __name__ == '__main__': ``` -Run it with the command: +Now you can run the application with the command: -``` console +``` bash python3 app.py ``` @@ -54,19 +53,19 @@ The ASAB web server is now available at [http://localhost:8080/](http://localhos Now open your web browser and open [http://localhost:8080/](http://localhost:8080/). You shouldn't see anything but an error: -``` +``` bash 404: Not Found ``` That is correct, because the endpoint "/" is not handled by the router. But now, if you open [http://localhost:8080/hello](http://localhost:8080/hello), you should see the response: -``` - "Hello world!" +``` json +"Hello world!" ``` You should get the same result from a terminal using cURL command: -``` console +``` bash curl --location 'localhost:8080/hello' ``` diff --git a/docs/tutorials/03_rest_api.md b/docs/tutorials/03_rest_api.md index d8a431f4e..01efd788a 100644 --- a/docs/tutorials/03_rest_api.md +++ b/docs/tutorials/03_rest_api.md @@ -3,8 +3,7 @@ Creating a microservice with REST API In the [previous tutorial](./02_web_server.md), you have learned how to create a web server. -With this tutorial, you will create a basic ASAB microservice that -provides a REST HTTP API. This microservice will implement **CREATE**, **READ**, **UPDATE** and **DELETE** functionality, in another words: **CRUD**. +With this tutorial, you will create a basic ASAB microservice that provides a REST HTTP API. This microservice will implement **CREATE**, **READ**, **UPDATE** and **DELETE** functionality, in another words: **CRUD**. We will also use [MongoDB](https://www.mongodb.com/) as a database running on [Docker](https://docs.docker.com/), and . In case you are not familiar with these technologies, take the opportunity to learn their basics concepts, as they are alpha-omega of the backend programming. Set up the project with Docker and MongoDB @@ -438,10 +437,10 @@ Now everything is prepared and we can test our application using Postman. Let's Try to check the Mongo database credentials. Do your credentials in the config file fit the ones you entered when running the Mongo Docker image? -Conclusion ----------- +Summary +------- -TODO TODO TODO +In this tutorial, you learned how to create a simple **microservice** provided with **REST API**. Exercise 0: Store JSON schema in the file diff --git a/docs/tutorials/04_storage.md b/docs/tutorials/04_storage.md index f54b3aabc..7aeb5af92 100644 --- a/docs/tutorials/04_storage.md +++ b/docs/tutorials/04_storage.md @@ -1,5 +1,3 @@ -# TODO: Add tutorial on how to use storage +ASAB Storage +------------ -Concentrate more on StorageServic - -# Build a NOTE-taking app \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index cc8f25890..225faf1e5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -32,9 +32,10 @@ theme: info: fontawesome/solid/circle-info tip: fontawesome/solid/bullhorn success: fontawesome/solid/check + # failure: fontawesome/solid/bomb + failure: fontawesome/solid/xmark question: fontawesome/solid/circle-question warning: fontawesome/solid/triangle-exclamation - failure: fontawesome/solid/bomb danger: fontawesome/solid/skull bug: fontawesome/solid/robot example: fontawesome/solid/flask From ce64f363b9534aeaf4c1e396d90d338abc9898f0 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 4 Jul 2023 14:19:50 +0200 Subject: [PATCH 013/154] Refactor mkdocs settings --- mkdocs.yml | 48 ++++++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 225faf1e5..6345f7767 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,4 +1,8 @@ site_name: ASAB +repo_url: https://github.com/TeskaLabs/asab +repo_name: TeskaLabs/asab + +# THEME, COLORS, FONTS, ICONS theme: name: "material" @@ -20,13 +24,9 @@ theme: - pymdownx.tilde - def_list - navigation.tracking - - repo_name: TeskaLabs/asab - repo_url: https://github.com/TeskaLabs/asab icon: admonition: - # https://squidfunk.github.io/mkdocs-material/reference/admonitions/#fontawesome note: fontawesome/solid/note-sticky abstract: fontawesome/solid/book info: fontawesome/solid/circle-info @@ -40,48 +40,35 @@ theme: bug: fontawesome/solid/robot example: fontawesome/solid/flask quote: fontawesome/solid/quote-left + + repo: fontawesome/brands/github font: text: Verdana palette: - scheme: default - primary: blue - accent: blue + primary: teal + accent: teal toggle: icon: material/brightness-7 name: Switch to dark mode - scheme: slate - primary: blue + primary: teal accent: yellow toggle: icon: material/brightness-4 name: Switch to light mode +# PLUGINS plugins: - - mkdocstrings: - markdown_extensions: - - pymdownx.superfences: - custom_fences: - - name: code - class: code - # TODO: Diagrams for some reason do not work https://squidfunk.github.io/mkdocs-material/reference/diagrams/ - # - name: mermaid - # class: mermaid - # format: !!python/name:pymdownx.superfences.fence_code_format - - config: - default_handler: python - python: - use_indentation: '\t' + - mkdocstrings - glightbox - search - awesome-pages - git-revision-date-localized - # - print-site: - # add_to_navigation: true markdown_extensions: @@ -89,15 +76,16 @@ markdown_extensions: anchor_linenums: true line_spans: __span pygments_lang_class: true + - pymdownx.inlinehilite - pymdownx.snippets - - pymdownx.superfences - # Extensions for notes, warnings, ... - # https://squidfunk.github.io/mkdocs-material/reference/admonitions/#fontawesome + # Admonitions (call-outs) https://squidfunk.github.io/mkdocs-material/reference/admonitions/ - admonition - pymdownx.details - - pymdownx.superfences + - pymdownx.superfences # arbitrary nesting of code and tabs + + # Annotations https://squidfunk.github.io/mkdocs-material/reference/annotations/ - attr_list - md_in_html @@ -106,12 +94,12 @@ extra: - icon: fontawesome/brands/github-alt link: https://github.com/TeskaLabs/asab +# NAVIGATION TREE + nav: - Introduction: index.md - - Installation: topics/admin/install.md - - Tutorials: - Hello World: tutorials/01_hello_world.md - Creating a web server: tutorials/02_web_server.md From 40e2685ceae74efa36fc9ec6e447640fc5a96593 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 4 Jul 2023 14:51:48 +0200 Subject: [PATCH 014/154] Modify tree-structure of tutorials --- .../01_hello_world.md | 13 ++++++----- .../02_web_server.md | 12 +++++----- .../admin => getting-started}/containers.md | 0 .../admin => getting-started}/install.md | 0 docs/{tutorials => how-tos}/03_rest_api.md | 0 docs/{tutorials => how-tos}/04_storage.md | 0 docs/{tutorials => how-tos}/05_pubsub.md | 0 docs/{tutorials => how-tos}/06_library.md | 0 docs/{tutorials => how-tos}/07_swagger.md | 0 mkdocs.yml | 23 ++++++++----------- 10 files changed, 23 insertions(+), 25 deletions(-) rename docs/{tutorials => getting-started}/01_hello_world.md (90%) rename docs/{tutorials => getting-started}/02_web_server.md (96%) rename docs/{topics/admin => getting-started}/containers.md (100%) rename docs/{topics/admin => getting-started}/install.md (100%) rename docs/{tutorials => how-tos}/03_rest_api.md (100%) rename docs/{tutorials => how-tos}/04_storage.md (100%) rename docs/{tutorials => how-tos}/05_pubsub.md (100%) rename docs/{tutorials => how-tos}/06_library.md (100%) rename docs/{tutorials => how-tos}/07_swagger.md (100%) diff --git a/docs/tutorials/01_hello_world.md b/docs/getting-started/01_hello_world.md similarity index 90% rename from docs/tutorials/01_hello_world.md rename to docs/getting-started/01_hello_world.md index e7a321c8c..a93db853a 100644 --- a/docs/tutorials/01_hello_world.md +++ b/docs/getting-started/01_hello_world.md @@ -28,7 +28,7 @@ and at least version 3.7 of Python before starting. ASAB uses the new 3. Run the server: - ``` console + ``` shell python3 main.py ``` @@ -54,7 +54,8 @@ Let's look on the application one more time. ``` python title="main.py" linenums="1" - #!/usr/bin/env python3 # (1)! + #!/usr/bin/env python3 + # (1)! import asab # (2)! class MyApplication(asab.Application): # (3)! @@ -73,21 +74,21 @@ line at the very beginning of the file. statement. 3. Every ASAB Application needs to have an application object. It is a -singleton; it means that the application must create and operate +**singleton**: the application must create and operate precisely one instance of the application. ASAB provides the base [asab.Application][#TODO] class that you need to inherit from to implement your custom application class. -4. The `Application.main()` method is one of +1. The `#!python Application.main()` method is one of the application lifecycle methods, that you can override to implement desired application functionality. The `main` method is a coroutine, so that you can await any tasks etc. in fully asynchronous way. This method is called when ASAB application is executed and initialized. The lifecycle stage is called "runtime". -5. In this example, we just print a message to a screen. +1. In this example, we just print a message to a screen. -6. This part of the code is executed when the Python program is launched. +2. This part of the code is executed when the Python program is launched. It creates the application object and executes the `Application.run()`{.interpreted-text role="any"} method. This is a standard way of how ASAB application is started. diff --git a/docs/tutorials/02_web_server.md b/docs/getting-started/02_web_server.md similarity index 96% rename from docs/tutorials/02_web_server.md rename to docs/getting-started/02_web_server.md index b7e6c47b0..1853b1cef 100644 --- a/docs/tutorials/02_web_server.md +++ b/docs/getting-started/02_web_server.md @@ -77,22 +77,22 @@ Let's go line by line in the code to understand how the asab server is construct ``` python title="app.py" linenums="1" #!/usr/bin/env python3 -import asab.web.rest # (1) +import asab.web.rest # (1)! class MyWebApplication(asab.Application): def __init__(self): - super().__init__() # (2) + super().__init__() # (2)! # Create the Web server - web = asab.web.create_web_server(self) # (3) + web = asab.web.create_web_server(self) # (3)! # Add a route to the handler method - web.add_get('/hello', self.hello) # (4) + web.add_get('/hello', self.hello) # (4)! # This is the web request handler - async def hello(self, request): # (5) - return asab.web.rest.json_response( # (6) + async def hello(self, request): # (5)! + return asab.web.rest.json_response( # (6)! request, data="Hello, world!" ) diff --git a/docs/topics/admin/containers.md b/docs/getting-started/containers.md similarity index 100% rename from docs/topics/admin/containers.md rename to docs/getting-started/containers.md diff --git a/docs/topics/admin/install.md b/docs/getting-started/install.md similarity index 100% rename from docs/topics/admin/install.md rename to docs/getting-started/install.md diff --git a/docs/tutorials/03_rest_api.md b/docs/how-tos/03_rest_api.md similarity index 100% rename from docs/tutorials/03_rest_api.md rename to docs/how-tos/03_rest_api.md diff --git a/docs/tutorials/04_storage.md b/docs/how-tos/04_storage.md similarity index 100% rename from docs/tutorials/04_storage.md rename to docs/how-tos/04_storage.md diff --git a/docs/tutorials/05_pubsub.md b/docs/how-tos/05_pubsub.md similarity index 100% rename from docs/tutorials/05_pubsub.md rename to docs/how-tos/05_pubsub.md diff --git a/docs/tutorials/06_library.md b/docs/how-tos/06_library.md similarity index 100% rename from docs/tutorials/06_library.md rename to docs/how-tos/06_library.md diff --git a/docs/tutorials/07_swagger.md b/docs/how-tos/07_swagger.md similarity index 100% rename from docs/tutorials/07_swagger.md rename to docs/how-tos/07_swagger.md diff --git a/mkdocs.yml b/mkdocs.yml index 6345f7767..419f7612e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -72,11 +72,11 @@ plugins: markdown_extensions: + # Syntax highlighting - pymdownx.highlight: anchor_linenums: true line_spans: __span pygments_lang_class: true - - pymdownx.inlinehilite - pymdownx.snippets @@ -98,19 +98,16 @@ extra: nav: - Introduction: index.md - - Installation: topics/admin/install.md - - Tutorials: - - Hello World: tutorials/01_hello_world.md - - Creating a web server: tutorials/02_web_server.md - - Creating a microservice with REST API: tutorials/03_rest_api.md - # - Services: - # # - topics/asab/web/index.md - # # - topics/asab/web/auth.md - # # - topics/asab/web/cors.md - # # - topics/asab/web/restapidocs.md - # # - topics/asab/library.md + - Getting started: + - Installation: getting-started/install.md + - Hello World: getting-started/01_hello_world.md + - Creating a web server: getting-started/02_web_server.md + - Containerization: getting-started/containers.md + + - How-To Guides: + - Creating a microservice with REST API: how-tos/03_rest_api.md - Topics: # - topics/asab/application.md @@ -147,7 +144,7 @@ nav: - Administration: - topics/admin/command-line.md - - topics/admin/containers.md + - topics/admin/systemd.md - topics/asab/alert.md \ No newline at end of file From 7ef460999ef33d198202c1cd62180ba9cfb1381d Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 4 Jul 2023 16:39:54 +0200 Subject: [PATCH 015/154] Improve Installation and Containerization --- docs/getting-started/containers.md | 129 ++++++++++++++--------------- docs/getting-started/install.md | 43 +++++----- mkdocs.yml | 6 +- 3 files changed, 86 insertions(+), 92 deletions(-) diff --git a/docs/getting-started/containers.md b/docs/getting-started/containers.md index 40039a755..dcd9a8bb2 100644 --- a/docs/getting-started/containers.md +++ b/docs/getting-started/containers.md @@ -1,110 +1,105 @@ -Containerisation -================ +# Containerisation ASAB is designed for deployment into containers such as LXC/LXD or Docker. It allows to build e.g. microservices that provides REST interface or consume MQ messages while being deployed into a container for a sake of the infrastructure flexibility. -ASAB in a LXC/LXD container ---------------------------- +## Running ASAB in a LXC/LXD container 1. Prepare LXC/LXD container based on Alpine Linux -``` {.bash} -$ lxc launch images:alpine/3.10 asab -``` + ``` bash + lxc launch images:alpine/3.10 asab + ``` 2. Swich into a container -``` {.bash} -$ lxc exec asab -- /bin/ash -``` + ``` bash + lxc exec asab -- /bin/ash + ``` 3. Prepare Python3 environment -``` {.bash} -$ apk update -$ apk upgrade -$ apk add --no-cache python3 + ``` bash + apk update + apk upgrade + apk add --no-cache python3 -$ python3 -m ensurepip -``` + python3 -m ensurepip + ``` 4. Deploy ASAB -``` {.bash} -$ apk add --virtual .buildenv python3-dev gcc musl-dev git -$ pip3 install git+https://github.com/TeskaLabs/asab -$ apk del .buildenv -``` + ``` bash + apk add --virtual .buildenv python3-dev gcc musl-dev git + pip3 install git+https://github.com/TeskaLabs/asab + apk del .buildenv + ``` 5. Deploy dependencies -``` {.bash} -$ pip3 install python-daemon -``` + ``` bash + pip3 install python-daemon + ``` -7. Use OpenRC to automatically start/stop ASAB application +6. Use OpenRC to automatically start/stop ASAB application -``` {.bash} -$ vi /etc/init.d/asab-app -``` + ``` bash + vi /etc/init.d/asab-app + ``` -Adjust the example of [OpenRC init -file](https://github.com/TeskaLabs/asab/blob/master/doc/asab-openrc). + Adjust the example of [OpenRC init + file](https://github.com/TeskaLabs/asab/blob/master/doc/asab-openrc). -``` {.bash} -$ chmod a+x /etc/init.d/asab-app -$ rc-update add asab-app -``` + ``` bash + chmod a+x /etc/init.d/asab-app + rc-update add asab-app + ``` -*Note*: If you need to install python packages that require compilation -using C compiler, you have to add following dependencies: + !!! note + If you need to install python packages that require compilation + using C compiler, you have to add following dependencies: -``` {.bash} -$ apk add --virtual .buildenv python3-dev -$ apk add --virtual .buildenv gcc -$ apk add --virtual .buildenv musl-dev -``` + ``` bash + apk add --virtual .buildenv python3-dev + apk add --virtual .buildenv gcc + apk add --virtual .buildenv musl-dev + ``` -And removal of the build tools after pip install: + And removal of the build tools after pip install: -``` {.bash} -$ apk del .buildenv -``` + ``` bash + apk del .buildenv + ``` -Docker Remote API ------------------ +## Docker Remote API In order for ASAB applications to read the Docker container name as well as other information related to the container to be used in logs, -metrics and other analysis, the Docker Remote API must be enabled. +metrics and other analysis, the Docker Remote API must be enabled. To do so: -To do so: +1. Open the docker service file: -1. Open the docker service file + ``` bash + vi /lib/systemd/system/docker.service + ``` -``` {.bash} -vi /lib/systemd/system/docker.service -``` +2. Find the line which starts with `ExecStart` and add `-H=tcp://0.0.0.0:2375`. +3. Save the file. +4. Reload the docker daemon and restart the Docker service: -2. Find the line which starts with ExecStart and add - [-H=tcp://0.0.0.0:2375]{.title-ref} -3. Save the file -4. Reload the docker daemon and restart the Docker service + ``` bash + sudo systemctl daemon-reload && sudo service docker restart + ``` -``` {.bash} -sudo systemctl daemon-reload && sudo service docker restart -``` + Then in the ASAB application's configuration, provide the Docker Socket + path in `docker_socket` configuration option: -Then in the ASAB application\'s configuration, provide the Docker Socket -path in [docker\_socket]{.title-ref} configuration option: - -``` {.bash} -[general] -docker_socket= -``` + ``` bash + [general] + docker_socket= + ``` Thus, the metric service as well as log manager can use the container name as hostname instead of container ID, which provides better diff --git a/docs/getting-started/install.md b/docs/getting-started/install.md index c2b4e528b..ea8c47baa 100644 --- a/docs/getting-started/install.md +++ b/docs/getting-started/install.md @@ -1,34 +1,29 @@ -Installation -============ +# Installation -ASAB is distributed via [pypi](https://pypi.org/project/asab/). +ASAB is distributed via [pypi](https://pypi.org/project/asab/). For installing ASAB, there are three options you can choose from: -Install ASAB using pip ----------------------- +=== "Using pip" -This is the recommended installation method. + This is the simplest and recommended installation method. -``` bash -pip install asab -``` + ``` bash + pip install asab + ``` -Install ASAB using easy install -------------------------------- +=== "Cloning from git repository" -``` bash -easy_install asab -``` + To install ASAB from a master branch of the GIT repository, you can use the following command. -Install ASAB for a GitHub -------------------------- + ``` bash + pip install git+https://github.com/TeskaLabs/asab.git + ``` -To install ASAB from a master branch of the GIT repository, use -following command. -!!! note - Git has to be installed in order to successfuly complete the - installation. +=== "Using easy_install" + + You can install asab using [EasyInstall](http://peak.telecommunity.com/DevCenter/EasyInstall) package manager. + + ``` bash + easy_install asab + ``` -``` bash -pip install git+https://github.com/TeskaLabs/asab.git -``` diff --git a/mkdocs.yml b/mkdocs.yml index 419f7612e..5b19e34b4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -89,6 +89,10 @@ markdown_extensions: - attr_list - md_in_html + # Content tabs and anchor links https://squidfunk.github.io/mkdocs-material/reference/content-tabs/ + - pymdownx.tabbed: + alternate_style: true + extra: social: - icon: fontawesome/brands/github-alt @@ -102,7 +106,7 @@ nav: - Getting started: - Installation: getting-started/install.md - - Hello World: getting-started/01_hello_world.md + - Hello World! application: getting-started/01_hello_world.md - Creating a web server: getting-started/02_web_server.md - Containerization: getting-started/containers.md From 79db9612a30bbbcdd9d37eaa554445e88c7add17 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 5 Jul 2023 00:49:59 +0200 Subject: [PATCH 016/154] Add icons and tags --- docs/getting-started/01_hello_world.md | 8 ++- docs/getting-started/install.md | 11 +++- docs/index.md | 75 ++++++++++++-------------- mkdocs.yml | 15 +++--- 4 files changed, 57 insertions(+), 52 deletions(-) diff --git a/docs/getting-started/01_hello_world.md b/docs/getting-started/01_hello_world.md index a93db853a..d3824a208 100644 --- a/docs/getting-started/01_hello_world.md +++ b/docs/getting-started/01_hello_world.md @@ -1,3 +1,9 @@ +--- +tags: + - application + +--- + Creating your first asab application ==================================== @@ -7,7 +13,7 @@ and at least version 3.7 of Python before starting. ASAB uses the new 1. Install ASAB: - ``` console + ``` bash pip3 install asab ``` diff --git a/docs/getting-started/install.md b/docs/getting-started/install.md index ea8c47baa..e69de2884 100644 --- a/docs/getting-started/install.md +++ b/docs/getting-started/install.md @@ -12,14 +12,21 @@ ASAB is distributed via [pypi](https://pypi.org/project/asab/). For installing A === "Cloning from git repository" - To install ASAB from a master branch of the GIT repository, you can use the following command. + To install ASAB from a master branch of the git repository, you can use the following command: ``` bash pip install git+https://github.com/TeskaLabs/asab.git ``` + Or you can clone the repository manually: -=== "Using easy_install" + ``` bash + git clone https://github.com/TeskaLabs/asab.git + pip install -e . + ``` + + +=== "Using EasyInstall" You can install asab using [EasyInstall](http://peak.telecommunity.com/DevCenter/EasyInstall) package manager. diff --git a/docs/index.md b/docs/index.md index cd373f82a..f84a19471 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,37 +1,27 @@ - - -Asynchronous Server Application Boilerplate -=========================================== - -Asynchronous Server App Boilerplate (or ASAB for short) is a -microservice platform for Python 3.7+ and [asyncio](https://docs.python.org/3/library/asyncio.html). ASAB -aims to minimize the amount of code that needs to be written when -building a microservice or an application server. ASAB is fully -asynchronous using async/await syntax from Python 3, making your code -modern, non-blocking, speedy and hence scalable. We make every effort to -build ASAB container-friendly so that you can deploy ASAB-based -microservice via Docker or Kubernetes in a breeze. - -ASAB is free and open-source software, available under BSD licence. It -means that anyone is freely licenced to use, copy, study, and change the -software in any way, and the source code is openly shared so that people -could voluntarily improve the design of the software. Anyone can (and is -encouraged to) use ASAB in his or her projects, for free. A current -maintainer is a [TeskaLabs Ltd](https://teskalabs.com) company. - -ASAB is developed [on GitHub](https://github.com/TeskaLabs/asab/). -Contributions are welcome! - -ASAB is designed to be powerful yet simple ------------------------------------------- +# Asynchronous Server Application Boilerplate + +Asynchronous Server App Boilerplate (or ASAB for short) is a microservice platform for Python 3.7+ and [asyncio](https://docs.python.org/3/library/asyncio.html). +ASAB aims to minimize the amount of code that needs to be written +when building a microservice or an application server. +ASAB is fully asynchronous using async/await syntax from Python 3, making your code modern, +non-blocking, speedy and hence scalable. +We make every effort to build ASAB container-friendly so that you can deploy +ASAB-based microservice via Docker or Kubernetes in a breeze. + +Anyone can (and is encouraged to) use ASAB in his or her projects, for free. +A current maintainer is a [TeskaLabs Ltd](https://teskalabs.com) company. + +!!! info "" + + - :simple-opensourceinitiative: ASAB is free and open-source software, available under BSD licence. + Anyone is freely licensed to use, copy, study, and change the + software in any way, and the source code is openly shared so that people + could voluntarily improve the design of the software. + + - :simple-github: ASAB is developed [on GitHub](https://github.com/TeskaLabs/asab/). + Contributions are welcome! + +## ASAB is designed to be powerful yet simple Here is a complete example of a fully working microservice: @@ -48,10 +38,15 @@ if __name__ == "__main__": app.run() ``` -ASAB is the right choice when ------------------------------ +## ASAB is the right choice when + +
+ +- :material-language-python: using Python 3.7+ +- :material-server: building the microservice or the application server +- :material-clock-fast: utilizing asynchronous I/O + +
+ +[Get started with ASAB](./getting-started/install.md){ .md-button .md-button--primary } -> - using Python 3.7+. -> - building the microservice or the application server. -> - utilizing asynchronous I/O (aka -> [asyncio](https://docs.python.org/3/library/asyncio.html)). diff --git a/mkdocs.yml b/mkdocs.yml index 5b19e34b4..08fe4357e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -69,6 +69,7 @@ plugins: - search - awesome-pages - git-revision-date-localized + - tags markdown_extensions: @@ -89,6 +90,10 @@ markdown_extensions: - attr_list - md_in_html + - pymdownx.emoji: + emoji_index: !!python/name:materialx.emoji.twemoji + emoji_generator: !!python/name:materialx.emoji.to_svg + # Content tabs and anchor links https://squidfunk.github.io/mkdocs-material/reference/content-tabs/ - pymdownx.tabbed: alternate_style: true @@ -101,8 +106,7 @@ extra: # NAVIGATION TREE nav: - - Introduction: index.md - + - Home: index.md - Getting started: - Installation: getting-started/install.md @@ -145,10 +149,3 @@ nav: - ElasticSearch: reference/storage/elasticsearch.md - MongoDB: reference/storage/mongodb.md - In-Memory: reference/storage/inmemory.md - - - Administration: - - topics/admin/command-line.md - - - topics/admin/systemd.md - - - topics/asab/alert.md \ No newline at end of file From 78fce31053df66902cf733f3e039ce482280186f Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 5 Jul 2023 02:50:37 +0200 Subject: [PATCH 017/154] Simplify tutorials and installation, add Contributing --- docs/contributing.md | 58 ++++++++ docs/getting-started/01_hello_world.md | 108 --------------- docs/getting-started/install.md | 36 ----- .../getting-started/installation_first_app.md | 126 ++++++++++++++++++ .../{02_web_server.md => web_server.md} | 23 ++-- docs/index.md | 2 +- mkdocs.yml | 7 +- 7 files changed, 200 insertions(+), 160 deletions(-) create mode 100644 docs/contributing.md delete mode 100644 docs/getting-started/01_hello_world.md delete mode 100644 docs/getting-started/install.md create mode 100644 docs/getting-started/installation_first_app.md rename docs/getting-started/{02_web_server.md => web_server.md} (96%) diff --git a/docs/contributing.md b/docs/contributing.md new file mode 100644 index 000000000..4102da247 --- /dev/null +++ b/docs/contributing.md @@ -0,0 +1,58 @@ +# Contributing + +We appreciate your effort to help us improve ASAB. In case you are interested in contributing, please follow the rules and conventions that we describe below. + + +## Coding conventions + +In TeskaLabs, we are following [PEP8 Style Guide](https://www.python.org/dev/peps/pep-0008/) that provides guidelines and +best practices on how to write Python code to improve its readability and consistency. + +To check if changes in your code are compliant with PEP8, you can use [flake8](https://flake8.pycqa.org/en/latest/): + +```bash +flake8 . +``` + +!!! tip "Pre-commit hooks" + + It is highly recommended to create a pre-commit hook: + + ```shell title=".git/hooks/pre-commit" + #!/bin/sh + echo "Running flake8 ..." + flake8 . + ``` + + Do not forget to make the hook executable: + + ``` bash + chmod u+x .git/hooks/pre-commit + ``` + +We shall provide some parts of the PEP8 Style Guide that we are focused on. + +### Imports + +Imports shall be written one-per-line style as per the example below + +```python +import os +import sys +import logging +``` + +Following additional rules apply for imports: + +1. Use **relative imports** when you import locally from a package. +2. Use **absolute imports** when you import from external package. +3. Never use `from ... import ...` because it unnecessarily increases complexity for readers +(unless you have very good reason for that). The only exception is `__init__.py` where it is +used for importing symbols that you want to expose as a given module public API. + +## Documentation conventions + +As a documentation engine, we use [mkdocs-material](https://squidfunk.github.io/mkdocs-material/). If you want to learn about various features provided by the engine, you can [read more](https://squidfunk.github.io/mkdocs-material/reference/). + +MkDocs uses markdown for writing documentation. + diff --git a/docs/getting-started/01_hello_world.md b/docs/getting-started/01_hello_world.md deleted file mode 100644 index d3824a208..000000000 --- a/docs/getting-started/01_hello_world.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -tags: - - application - ---- - -Creating your first asab application -==================================== - -Make sure you have both [pip](https://pip.pypa.io/en/stable/installing/) -and at least version 3.7 of Python before starting. ASAB uses the new -`async`/`await` syntax, so earlier versions of python won't work. - -1. Install ASAB: - - ``` bash - pip3 install asab - ``` - -2. Create a file called `main.py` with the following code: - - ``` python title="main.py" - #!/usr/bin/env python3 - import asab - - class MyApplication(asab.Application): - async def main(self): - print("Hello world") - - if __name__ == '__main__': - app = MyApplication() - app.run() - ``` - -3. Run the server: - - ``` shell - python3 main.py - ``` - - and you should've seen the output: - ``` - Hello world! - ``` - - You are now successfully runinng an ASAB application server. - -4. Stop the application by `Control-C`. - - Note: The ASAB is designed around a so-called [event - loop](https://en.wikipedia.org/wiki/Event_loop). It is meant primarily - for server architectures. For that reason, it doesn't terminate and - continue running and serving eventual requests. - -Going into details ------------------- - -Let's look on the application one more time. - - -``` python title="main.py" linenums="1" - - #!/usr/bin/env python3 - # (1)! - import asab # (2)! - - class MyApplication(asab.Application): # (3)! - async def main(self): # (4)! - print("Hello world") # (5)! - - if __name__ == '__main__': # (6)! - app = MyApplication() - app.run() -``` - -1. ASAB application uses a Python 3.7+. This is specified a by hashbang -line at the very beginning of the file. - -2. ASAB is included from as `asab` module via an import -statement. - -3. Every ASAB Application needs to have an application object. It is a -**singleton**: the application must create and operate -precisely one instance of the application. ASAB provides the base -[asab.Application][#TODO] class that you need to -inherit from to implement your custom application class. - -1. The `#!python Application.main()` method is one of -the application lifecycle methods, that you can override to implement -desired application functionality. The `main` method is a -coroutine, so that you can await any tasks etc. in fully asynchronous -way. This method is called when ASAB application is executed and -initialized. The lifecycle stage is called "runtime". - -1. In this example, we just print a message to a screen. - -2. This part of the code is executed when the Python program is launched. -It creates the application object and executes the -`Application.run()`{.interpreted-text role="any"} method. This is a -standard way of how ASAB application is started. - - -Summary -------- - -In this tutorial, you learned how to install `asab` and create a basic application. - -Check out tutorials about how to build ASAB based [web server](./02_web_server.md). diff --git a/docs/getting-started/install.md b/docs/getting-started/install.md deleted file mode 100644 index e69de2884..000000000 --- a/docs/getting-started/install.md +++ /dev/null @@ -1,36 +0,0 @@ -# Installation - -ASAB is distributed via [pypi](https://pypi.org/project/asab/). For installing ASAB, there are three options you can choose from: - -=== "Using pip" - - This is the simplest and recommended installation method. - - ``` bash - pip install asab - ``` - -=== "Cloning from git repository" - - To install ASAB from a master branch of the git repository, you can use the following command: - - ``` bash - pip install git+https://github.com/TeskaLabs/asab.git - ``` - - Or you can clone the repository manually: - - ``` bash - git clone https://github.com/TeskaLabs/asab.git - pip install -e . - ``` - - -=== "Using EasyInstall" - - You can install asab using [EasyInstall](http://peak.telecommunity.com/DevCenter/EasyInstall) package manager. - - ``` bash - easy_install asab - ``` - diff --git a/docs/getting-started/installation_first_app.md b/docs/getting-started/installation_first_app.md new file mode 100644 index 000000000..e2752f64b --- /dev/null +++ b/docs/getting-started/installation_first_app.md @@ -0,0 +1,126 @@ +# Installation and first application + +## Installation + +ASAB is distributed via [pypi](https://pypi.org/project/asab/). For installing ASAB, there are three options you can choose from: + +=== "Using pip" + + This is the simplest and recommended installation method. + + ``` bash + pip install asab + ``` + +=== "Cloning from git repository" + + To install ASAB from a master branch of the git repository, you can use the following command: + + ``` bash + pip install git+https://github.com/TeskaLabs/asab.git + ``` + + Or you can clone the repository manually: + + ``` bash + git clone https://github.com/TeskaLabs/asab.git + pip install -e . + ``` + + +=== "Using EasyInstall" + + You can install asab using [EasyInstall](http://peak.telecommunity.com/DevCenter/EasyInstall) package manager. + + ``` bash + easy_install asab + ``` + +## Creating your first application + +1. Create a file called `main.py` with the following code: + + ``` python title="main.py" + #!/usr/bin/env python3 + import asab + + class MyApplication(asab.Application): + async def main(self): + print("Hello world") + + if __name__ == '__main__': + app = MyApplication() + app.run() + ``` + +2. Run the server: + + ``` shell + python3 main.py + ``` + + If you see the following output, you have successfully created and run an ASAB application server. + + ``` + Hello world! + ``` + + +3. Stop the application by `Ctrl+C`. + + !!! info + The ASAB is designed around a so-called [event + loop](https://en.wikipedia.org/wiki/Event_loop). It is meant primarily + for server architectures. For that reason, it doesn't terminate and + continue running and serving eventual requests. + +## Taking a closer look + +Let's look on the application one more time. + + +``` python title="main.py" linenums="1" + + #!/usr/bin/env python3 + # (1)! + import asab # (2)! + + class MyApplication(asab.Application): # (3)! + async def main(self): # (4)! + print("Hello world") # (5)! + + if __name__ == '__main__': # (6)! + app = MyApplication() + app.run() +``` + +1. ASAB application uses a Python 3.7+. This is specified a by hashbang +line at the very beginning of the file. + +1. ASAB is included from as `asab` module via an import +statement. + +1. Every ASAB Application needs to have an application object. It is a +**singleton**: the application must create and operate +precisely one instance of the application. ASAB provides the base +[asab.Application][#TODO] class that you need to +inherit from to implement your custom application class. + +1. The `#!python Application.main()` method is one of +the application lifecycle methods, that you can override to implement +desired application functionality. The `main` method is a +coroutine, so that you can await any tasks etc. in fully asynchronous +way. This method is called when ASAB application is executed and +initialized. The lifecycle stage is called "runtime". + +1. In this example, we just print a message to a screen. + +2. This part of the code is executed when the Python program is launched. +It creates the application object and executes the `#!python run()` method which creates and runs an event loop. +This is a standard way of how ASAB application is started. + +## Summary + +In this tutorial, you learned how to install ASAB and how to create a basic application. + +You can continue with a step-by-step tutorial on how to build ASAB based [web server](./web_server.md). diff --git a/docs/getting-started/02_web_server.md b/docs/getting-started/web_server.md similarity index 96% rename from docs/getting-started/02_web_server.md rename to docs/getting-started/web_server.md index 1853b1cef..7b4b5935c 100644 --- a/docs/getting-started/02_web_server.md +++ b/docs/getting-started/web_server.md @@ -1,9 +1,9 @@ -Creating a web server -===================== -Now, when you know how to create and run [a basic asab application](./01_hello_world.md), let's create your first web server. +# Creating a web server -Create and run the app ----------------------- + +Now, when you know how to create and run [a basic asab application](./installation_first_app.md), let's create your first web server. + +## Creating and running a web server Set up a new project and create a new file `app.py` with the following code: @@ -69,8 +69,8 @@ You should get the same result from a terminal using cURL command: curl --location 'localhost:8080/hello' ``` -Deeper look ------------ +## Taking a closer look + Let's go line by line in the code to understand how the asab server is constructed. @@ -122,8 +122,8 @@ As you can see, it is easy to create a fully functioning web server using asab, `asab` is built on the top of the [asyncio](https://docs.python.org/3/library/asyncio.html) and [aiohttp](https://docs.aiohttp.org/en/stable/) libraries which are designed to make the most out of [non-blocking network operations](https://docs.aiohttp.org/en/stable/http_request_lifecycle.html#aiohttp-request-lifecycle). -Logging -------- +## Logging + At this point, let us also mention the basics of asab logging. @@ -159,10 +159,9 @@ Note that there may be processes that take a long time to terminate, so terminat - log rotation - logging to syslog -Configuration -------------- +## Configuration -In order to start your `asab` application with certain configuration, create a config file in `ini` format. There are specific options +In order to start your `asab` application with certain configuration, create a config file in `ini` format. ``` ini title="config.ini" [web] diff --git a/docs/index.md b/docs/index.md index f84a19471..fd07e9142 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,7 +19,7 @@ A current maintainer is a [TeskaLabs Ltd](https://teskalabs.com) company. could voluntarily improve the design of the software. - :simple-github: ASAB is developed [on GitHub](https://github.com/TeskaLabs/asab/). - Contributions are welcome! + Contributions are most welcome! If you want to help us improve asab, check our [contribution rules](./contributing.md). ## ASAB is designed to be powerful yet simple diff --git a/mkdocs.yml b/mkdocs.yml index 08fe4357e..6e5a1660e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -109,9 +109,8 @@ nav: - Home: index.md - Getting started: - - Installation: getting-started/install.md - - Hello World! application: getting-started/01_hello_world.md - - Creating a web server: getting-started/02_web_server.md + - Installation and first application: getting-started/installation_first_app.md + - Creating a web server: getting-started/web_server.md - Containerization: getting-started/containers.md - How-To Guides: @@ -149,3 +148,5 @@ nav: - ElasticSearch: reference/storage/elasticsearch.md - MongoDB: reference/storage/mongodb.md - In-Memory: reference/storage/inmemory.md + + - Contributing: contributing.md From 0b79314840362758875aa9653d096acfbf27fae2 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 5 Jul 2023 03:15:00 +0200 Subject: [PATCH 018/154] Add some tabs, docstring formatting rules --- docs/contributing.md | 77 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/docs/contributing.md b/docs/contributing.md index 4102da247..4f841a332 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -32,6 +32,20 @@ flake8 . We shall provide some parts of the PEP8 Style Guide that we are focused on. +### Tabs + +We use tabs as an indentation method. Do not mix them with spaces! + +### Blank lines + +Surround top-level function and class definitions with two blank lines. + +Method definitions inside a class are surrounded by a single blank line. + +Extra blank lines may be used (sparingly) to separate groups of related functions. Blank lines may be omitted between a bunch of related one-liners (e.g. a set of dummy implementations). + +Use blank lines in functions, sparingly, to indicate logical sections. + ### Imports Imports shall be written one-per-line style as per the example below @@ -56,3 +70,66 @@ As a documentation engine, we use [mkdocs-material](https://squidfunk.github.io/ MkDocs uses markdown for writing documentation. +### Docstrings formatting + +In order for the automatic documentation to be generated without errors, [Google style docstring guide](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings) must be followed. Here is an example of the properly documented function: + +```python +def fetch_smalltable_rows( + table_handle: smalltable.Table, + keys: Sequence[bytes | str], + require_all_keys: bool = False, +) -> Mapping[bytes, tuple[str, ...]]: + """Fetches rows from a Smalltable. + + Retrieves rows pertaining to the given keys from the Table instance + represented by table_handle. String keys will be UTF-8 encoded. + + Args: + table_handle: + An open smalltable.Table instance. + keys: + A sequence of strings representing the key of each table row to + fetch. String keys will be UTF-8 encoded. + require_all_keys: + If True only rows with values set for all keys will be returned. + + Returns: + A dict mapping keys to the corresponding table row data + fetched. Each row is represented as a tuple of strings. For + example: + + {b'Serak': ('Rigel VII', 'Preparer'), + b'Zim': ('Irk', 'Invader'), + b'Lrrr': ('Omicron Persei 8', 'Emperor')} + + Returned keys are always bytes. If a key from the keys argument is + missing from the dictionary, then that row was not found in the + table (and require_all_keys must have been False). + + Raises: + IOError: An error occurred accessing the smalltable. + """ +``` + + +!!! tip + If you use code annotations, it will be automatically incorporated into the documentation. In case you for some reason do not want to use them and still would like to have type hints in documentation, you can manually add them like this: + + ```python + def sum_of_squares(a, b): + """ + Return sum of squares a^2 + b^2. + + Args: + a (float | int): first number + b (float | int): second number + + Returns: + float or int representing the sum of squares. + """ + + ``` + + +## Creating examples From 7f5bfc0780e969945b1d5b04494867c451dfaae5 Mon Sep 17 00:00:00 2001 From: eliska-n Date: Mon, 10 Jul 2023 09:56:33 +0200 Subject: [PATCH 019/154] metrics docs revised --- asab/metrics/metrics.py | 120 +++- asab/metrics/service.py | 146 +++- docs/reference/metrics.md | 1 - docs/reference/metrics/aggregation_counter.md | 8 + .../aggregation_counter_with_dynamic_tags.md | 8 + docs/reference/metrics/counter.md | 9 + .../metrics/counter_with_dynamic_tags.md | 9 + docs/reference/metrics/duty_cycle.md | 8 + docs/reference/metrics/eps_counter.md | 9 + docs/reference/metrics/gauge.md | 8 + docs/reference/metrics/histogram.md | 8 + .../metrics/histogram_with_dynamic_tags.md | 8 + docs/reference/metrics/service.md | 13 + docs/topics/asab/metrics.md | 636 ------------------ docs/topics/asab/metrics/built-ins.md | 63 ++ docs/topics/asab/metrics/intro.md | 111 +++ docs/topics/asab/metrics/tags.md | 66 ++ docs/topics/asab/metrics/targets.md | 137 ++++ mkdocs.yml | 22 +- 19 files changed, 716 insertions(+), 674 deletions(-) delete mode 100644 docs/reference/metrics.md create mode 100644 docs/reference/metrics/aggregation_counter.md create mode 100644 docs/reference/metrics/aggregation_counter_with_dynamic_tags.md create mode 100644 docs/reference/metrics/counter.md create mode 100644 docs/reference/metrics/counter_with_dynamic_tags.md create mode 100644 docs/reference/metrics/duty_cycle.md create mode 100644 docs/reference/metrics/eps_counter.md create mode 100644 docs/reference/metrics/gauge.md create mode 100644 docs/reference/metrics/histogram.md create mode 100644 docs/reference/metrics/histogram_with_dynamic_tags.md create mode 100644 docs/reference/metrics/service.md delete mode 100644 docs/topics/asab/metrics.md create mode 100644 docs/topics/asab/metrics/built-ins.md create mode 100644 docs/topics/asab/metrics/intro.md create mode 100644 docs/topics/asab/metrics/tags.md create mode 100644 docs/topics/asab/metrics/targets.md diff --git a/asab/metrics/metrics.py b/asab/metrics/metrics.py index 246e79735..7636c4bab 100644 --- a/asab/metrics/metrics.py +++ b/asab/metrics/metrics.py @@ -41,6 +41,14 @@ def add_field(self, tags): return field def set(self, name: str, value): + """ + The function sets a value for a given value name and updates the 'measured_at' field with + the current time. + + Args: + name (str): The name of the value to be set. + value: The value that you want to set for the given name in the field. + """ self._field['values'][name] = value self._field['measured_at'] = self.App.time() @@ -59,14 +67,17 @@ def add_field(self, tags): self._field = field return field - def add(self, name, value, init_value=None): + def add(self, name: str, value, init_value: dict = None): """ - :param name: name of the counter - :param value: value to be added to the counter - - Adds the `value` to the counter Values specified by `name`. - If `name` is not in Counter Values, it will be added. - + The `add` function adds a specified value to a counter, and if the counter does not exist, it + creates it and initializes it with an optional initial value. + + Args: + name (str): Value name to which the `value` will be added. + value: Value that needs to be added to the counter. It is the amount by which the counter will be incremented. + init_value (dict): The `init_value` parameter is an optional parameter that specifies the initial value + of the counter if it doesn't already exist in the counter values. If `init_value` is provided, it + will be added to the `value` parameter and the result will be assigned as the value of the counter. """ try: self._actuals[name] += value @@ -78,15 +89,18 @@ def add(self, name, value, init_value=None): if not self.Storage.get("reset"): self._field['measured_at'] = self.App.time() - def sub(self, name, value, init_value=None): + def sub(self, name: str, value, init_value: dict = None): """ - :param name: name of the counter - :param value: value to be subtracted from the counter - - Subtracts the `value` from the counter Values specified by `name`. - If `name` is not in Counter Values, it will be added. - + The function subtracts a value from a variable and updates the 'measured_at' field. + + Args: + name (str): The name of the variable or field that you want to subtract the value from. + value: Value that needs to be added to the counter. It is the amount by which the counter will be incremented. + init_value (dict): The `init_value` parameter is an optional parameter that specifies the initial value + of the counter if it doesn't already exist in the counter values. If `init_value` is provided, it + will be added to the `value` parameter and the result will be assigned as the value of the counter. """ + try: self._actuals[name] -= value except KeyError: @@ -154,10 +168,6 @@ def flush(self, now): class DutyCycle(Metric): ''' https://en.wikipedia.org/wiki/Duty_cycle - - now = self.App.time() - d = now - self.LastReadyStateSwitch - self.LastReadyStateSwitch = now ''' @@ -192,7 +202,16 @@ def add_field(self, tags): return field - def set(self, name, on_off: bool): + def set(self, name: str, on_off: bool): + """ + The function `set` updates the state of a variable, tracking the duration of on and off cycles. + + Args: + name (str): Name of the value that you want to set. + on_off (bool): The `on_off` parameter is a boolean value that represents whether something is + turned on. It is used to set the state of a particular item or feature. + + """ now = self.App.time() values = self._field["actuals"].get(name) if values is None: @@ -257,6 +276,14 @@ def __init__(self, init_values=None, aggregator=max): self.Aggregator = aggregator def set(self, name, value): + """ + The function sets a value in a dictionary, updating it if the key already exists, and also updates a + 'measured_at' field if a certain condition is met. + + Args: + name: Name of the value being set. + value: Value that you want to set for the given name. + """ if not self.Storage.get("reset"): self._field['measured_at'] = self.App.time() try: @@ -329,6 +356,13 @@ def flush(self, now): field['values'] = copy.deepcopy(field['actuals']) def set(self, value_name, value): + """ + The function updates the values of the histogram based on the input value and value name. + + Args: + value_name: String that represents the name of the value being set. + value: Value that needs to be set. + """ if not self.Storage.get("reset"): self._field['measured_at'] = self.App.time() buckets = self._actuals["buckets"] @@ -391,11 +425,16 @@ def add_field(self, tags): def add(self, name, value, tags): """ - :param name: name of the counter - :param value: value to be added to the counter - - Adds the `value` to the counter Values specified by `name`. - If name is not in Counter Values, it will be added there. + The `add` function adds a specified value to a counter, and if the counter does not exist, it + creates it and initializes it with an optional initial value. + + Args: + name (str): Value name to which the `value` will be added. + value: Value that needs to be added to the counter. It is the amount by which the counter will be incremented. + init_value (dict): The `init_value` parameter is an optional parameter that specifies the initial value + of the counter if it doesn't already exist in the counter values. If `init_value` is provided, it + will be added to the `value` parameter and the result will be assigned as the value of the counter. + tags (dict): Dynamic tags appliying to this value. """ field = self.locate_field(tags) @@ -412,11 +451,15 @@ def add(self, name, value, tags): def sub(self, name, value, tags): """ - :param name: name of the counter - :param value: value to be subtracted from the counter - - Subtracts the `value` from the counter Values specified by `name`. - If name is not in Counter Values, it will be added there. + The function subtracts a value from a variable and updates the 'measured_at' field. + + Args: + name (str): The name of the variable or field that you want to subtract the value from. + value: Value that needs to be added to the counter. It is the amount by which the counter will be incremented. + init_value (dict): The `init_value` parameter is an optional parameter that specifies the initial value + of the counter if it doesn't already exist in the counter values. If `init_value` is provided, it + will be added to the `value` parameter and the result will be assigned as the value of the counter. + tags (dict): Dynamic tags appliying to this value. """ field = self.locate_field(tags) @@ -458,6 +501,15 @@ def __init__(self, init_values=None, aggregator=max): self.Aggregator = aggregator def set(self, name, value, tags): + """ + The function sets a value for a given name and tags in a field, updates the measured_at and + expires_at timestamps, and handles resetting the field if necessary. + + Args: + name (str): String that represents the name of the value being set. + value: Value that you want to set for a specific field. + tags (dict): Dictionary of tags that are used to locate a specific field. + """ field = self.locate_field(tags) actuals = field['actuals'] try: @@ -538,7 +590,15 @@ def flush(self, now): for field in self.Storage['fieldset']: field['values'] = copy.deepcopy(field['actuals']) - def set(self, value_name, value, tags): + def set(self, value_name, value, tags: dict): + """ + The function updates the values of the histogram based on the input value and value name. + + Args: + value_name (str): String that represents the name of the value being set. + value: Value that needs to be set. + tags (dict): Dynamic tags appliying to this value. + """ field = self.locate_field(tags) buckets = field.get("actuals").get("buckets") summary = field.get("actuals").get("sum") diff --git a/asab/metrics/service.py b/asab/metrics/service.py index f4ec5b7da..fbacfd65c 100644 --- a/asab/metrics/service.py +++ b/asab/metrics/service.py @@ -129,12 +129,57 @@ def _add_metric(self, metric: Metric, metric_name: str, tags=None, reset=None, h self.Metrics.append(metric) - def create_gauge(self, metric_name, tags=None, init_values=None, help=None, unit=None): + def create_gauge(self, metric_name: str, tags: dict = None, init_values: dict = None, help: str = None, unit: str = None): + """ + The `create_gauge` function creates and returns a Gauge metric with specified parameters. + + Args: + metric_name (str): The name of the metric you want to create. + tags (dict): Dictionary where the keys represent the tag names and the values represent the tag values. It allows you + to categorize and filter metrics based on different dimensions or attributes. + init_values (dict): The `init_values` parameter is used to set the initial value of the gauge + metric. Provide pairs of value names and their initial values. If not provided, the gauge + metric will be initialized with a value of 0. + help (str): The "help" parameter is used to provide a description or explanation of the metric. It + can be used to provide additional information about what the metric measures or how it should be + interpreted. + unit (str): The "unit" parameter is used to specify the unit of measurement for the metric. It + helps provide context and understanding for the metric being measured. For example, if the metric is + measuring the temperature, the unit could be "degrees Celsius". + + Returns: + an instance of the Gauge class. + """ + m = Gauge(init_values=init_values) self._add_metric(m, metric_name, tags=tags, help=help, unit=unit) return m - def create_counter(self, metric_name, tags=None, init_values=None, reset: bool = True, help=None, unit=None, dynamic_tags=False): + def create_counter(self, metric_name: str, tags: dict = None, init_values: dict = None, reset: bool = True, help: str = None, unit: str = None, dynamic_tags: bool = False): + """ + The function creates a counter metric with optional dynamic tags and adds it to a metric collection. + + Args: + metric_name (str): The name of the metric you want to create. + tags (dict): Dictionary where the keys represent the tag names and the values represent the tag values. It allows you + to categorize and filter metrics based on different dimensions or attributes. + init_values (dict): The `init_values` parameter is used to set the initial value of the + metric. Provide pairs of value names and their initial values. If not provided, the + metric will be initialized with a value of 0. + reset (bool): The "reset" parameter is a boolean value that determines whether the counter should + be reset to initial values every 60 seconds. Defaults to True + help (str): The "help" parameter is used to provide a description or explanation of the metric. It + can be used to provide additional information about what the metric measures or how it should be + interpreted. + unit (str): The "unit" parameter is used to specify the unit of measurement for the metric. It + helps provide context and understanding for the metric being measured. For example, if the metric is + measuring the temperature, the unit could be "degrees Celsius". + dynamic_tags: Boolean flag. If set to True, the counter will be an instance of the + "CounterWithDynamicTags" class, which allows tags to be added or removed dynamically. Defaults to False + + Returns: + the created counter object. + """ if dynamic_tags: m = CounterWithDynamicTags(init_values=init_values) else: @@ -142,17 +187,83 @@ def create_counter(self, metric_name, tags=None, init_values=None, reset: bool = self._add_metric(m, metric_name, tags=tags, reset=reset, help=help, unit=unit) return m - def create_eps_counter(self, metric_name, tags=None, init_values=None, reset: bool = True, help=None, unit=None): + def create_eps_counter(self, metric_name: str, tags: dict = None, init_values: dict = None, reset: bool = True, help: str = None, unit: str = None): + """ + The function creates an EPSCounter object, and returns the object. + + Args: + metric_name (str): The name of the metric you want to create. + tags (dict): Dictionary where the keys represent the tag names and the values represent the tag values. It allows you + to categorize and filter metrics based on different dimensions or attributes. + init_values (dict): The `init_values` parameter is used to set the initial value of the + metric. Provide pairs of value names and their initial values. If not provided, the + metric will be initialized with a value of 0. + reset (bool): The "reset" parameter is a boolean value that determines whether the counter should + be reset to initial values every 60 seconds. Defaults to True + help (str): The "help" parameter is used to provide a description or explanation of the metric. It + can be used to provide additional information about what the metric measures or how it should be + interpreted. + unit (str): The "unit" parameter is used to specify the unit of measurement for the metric. It + helps provide context and understanding for the metric being measured. For example, if the metric is + measuring the temperature, the unit could be "degrees Celsius". + + Returns: + an instance of the `EPSCounter` class. + """ m = EPSCounter(init_values=init_values) self._add_metric(m, metric_name, tags=tags, reset=reset, help=help, unit=unit) return m - def create_duty_cycle(self, metric_name, tags=None, init_values=None, help=None, unit=None): + def create_duty_cycle(self, metric_name: str, tags: dict = None, init_values: dict = None, help: str = None, unit: str = None): + """ + The function creates a duty cycle metric and returns the object. + + Args: + metric_name (str): The name of the metric you want to create. + tags (dict): Dictionary where the keys represent the tag names and the values represent the tag values. It allows you + to categorize and filter metrics based on different dimensions or attributes. + init_values (dict): The `init_values` parameter is used to set the initial value of the + metric. Provide pairs of value names and their initial values. If not provided, the + metric will be initialized with a value of 0. + help (str): The "help" parameter is used to provide a description or explanation of the metric. It + can be used to provide additional information about what the metric measures or how it should be + interpreted. + unit (str): The "unit" parameter is used to specify the unit of measurement for the metric. It + helps provide context and understanding for the metric being measured. For example, if the metric is + measuring the temperature, the unit could be "degrees Celsius". + + Returns: + an instance of the DutyCycle class. + """ m = DutyCycle(self.App, init_values=init_values) self._add_metric(m, metric_name, tags=tags, help=help, unit=unit) return m def create_aggregation_counter(self, metric_name, tags=None, init_values=None, reset: bool = True, aggregator=max, help=None, unit=None, dynamic_tags=False): + """ + The function creates a counter metric with optional dynamic tags and adds it to a metric collection. + + Args: + metric_name (str): The name of the metric you want to create. + tags (dict): Dictionary where the keys represent the tag names and the values represent the tag values. It allows you + to categorize and filter metrics based on different dimensions or attributes. + init_values (dict): The `init_values` parameter is used to set the initial value of the + metric. Provide pairs of value names and their initial values. If not provided, the + metric will be initialized with a value of 0. + reset (bool): The "reset" parameter is a boolean value that determines whether the counter should + be reset to initial values every 60 seconds. Defaults to True + help (str): The "help" parameter is used to provide a description or explanation of the metric. It + can be used to provide additional information about what the metric measures or how it should be + interpreted. + unit (str): The "unit" parameter is used to specify the unit of measurement for the metric. It + helps provide context and understanding for the metric being measured. For example, if the metric is + measuring the temperature, the unit could be "degrees Celsius". + dynamic_tags: Boolean flag. If set to True, the counter will be an instance of the + "AggregationCounterWithDynamicTags" class, which allows tags to be added or removed dynamically. Defaults to False + + Returns: + the created counter object. + """ if dynamic_tags: m = AggregationCounterWithDynamicTags(init_values=init_values, aggregator=aggregator) else: @@ -161,6 +272,33 @@ def create_aggregation_counter(self, metric_name, tags=None, init_values=None, r return m def create_histogram(self, metric_name, buckets: list, tags=None, init_values=None, reset: bool = True, help=None, unit=None, dynamic_tags=False): + """ + The function creates a histogram metric. + + Args: + metric_name (str): The name of the metric you want to create. + buckets (list): The "buckets" parameter is a list that specifies the boundaries for the histogram + buckets. Each element in the list represents the upper bound of a bucket. For example, if the list + is [10, 20, 30], it means that the histogram will have three buckets: one for values less than 10, second for values less than 20, third for values less than 30 + tags (dict): Dictionary where the keys represent the tag names and the values represent the tag values. It allows you + to categorize and filter metrics based on different dimensions or attributes. + init_values (dict): The `init_values` parameter is used to set the initial value of the + metric. Provide pairs of value names and their initial values. If not provided, the + metric will be initialized with a value of 0. + reset (bool): The "reset" parameter is a boolean value that determines whether the histogram should + be reset to initial values every 60 seconds. Defaults to True + help (str): The "help" parameter is used to provide a description or explanation of the metric. It + can be used to provide additional information about what the metric measures or how it should be + interpreted. + unit (str): The "unit" parameter is used to specify the unit of measurement for the metric. It + helps provide context and understanding for the metric being measured. For example, if the metric is + measuring the temperature, the unit could be "degrees Celsius". + dynamic_tags: Boolean flag. If set to True, the counter will be an instance of the + "AggregationCounterWithDynamicTags" class, which allows tags to be added or removed dynamically. Defaults to False + + Returns: + a histogram object + """ if dynamic_tags: m = HistogramWithDynamicTags(buckets=buckets, init_values=init_values) else: diff --git a/docs/reference/metrics.md b/docs/reference/metrics.md deleted file mode 100644 index bcae9445f..000000000 --- a/docs/reference/metrics.md +++ /dev/null @@ -1 +0,0 @@ -::: asab.metrics.service \ No newline at end of file diff --git a/docs/reference/metrics/aggregation_counter.md b/docs/reference/metrics/aggregation_counter.md new file mode 100644 index 000000000..16e748057 --- /dev/null +++ b/docs/reference/metrics/aggregation_counter.md @@ -0,0 +1,8 @@ +::: asab.metrics.metrics.AggregationCounter + handler: python + options: + members: + - set + show_root_heading: true + show_source: true + heading_level: 3 \ No newline at end of file diff --git a/docs/reference/metrics/aggregation_counter_with_dynamic_tags.md b/docs/reference/metrics/aggregation_counter_with_dynamic_tags.md new file mode 100644 index 000000000..c09b00135 --- /dev/null +++ b/docs/reference/metrics/aggregation_counter_with_dynamic_tags.md @@ -0,0 +1,8 @@ +::: asab.metrics.metrics.AggregationCounterWithDynamicTags + handler: python + options: + members: + - set + show_root_heading: true + show_source: true + heading_level: 3 \ No newline at end of file diff --git a/docs/reference/metrics/counter.md b/docs/reference/metrics/counter.md new file mode 100644 index 000000000..1f2c1ca7a --- /dev/null +++ b/docs/reference/metrics/counter.md @@ -0,0 +1,9 @@ +::: asab.metrics.metrics.Counter + handler: python + options: + members: + - add + - sub + show_root_heading: true + show_source: true + heading_level: 3 \ No newline at end of file diff --git a/docs/reference/metrics/counter_with_dynamic_tags.md b/docs/reference/metrics/counter_with_dynamic_tags.md new file mode 100644 index 000000000..e84577d94 --- /dev/null +++ b/docs/reference/metrics/counter_with_dynamic_tags.md @@ -0,0 +1,9 @@ +::: asab.metrics.metrics.CounterWithDynamicTags + handler: python + options: + members: + - add + - sub + show_root_heading: true + show_source: true + heading_level: 3 \ No newline at end of file diff --git a/docs/reference/metrics/duty_cycle.md b/docs/reference/metrics/duty_cycle.md new file mode 100644 index 000000000..6e2cd5cc4 --- /dev/null +++ b/docs/reference/metrics/duty_cycle.md @@ -0,0 +1,8 @@ +::: asab.metrics.metrics.DutyCycle + handler: python + options: + members: + - set + show_root_heading: true + show_source: true + heading_level: 3 \ No newline at end of file diff --git a/docs/reference/metrics/eps_counter.md b/docs/reference/metrics/eps_counter.md new file mode 100644 index 000000000..12eff9e21 --- /dev/null +++ b/docs/reference/metrics/eps_counter.md @@ -0,0 +1,9 @@ +::: asab.metrics.metrics.EPSCounter + handler: python + options: + members: + - add + - sub + show_root_heading: true + show_source: true + heading_level: 3 diff --git a/docs/reference/metrics/gauge.md b/docs/reference/metrics/gauge.md new file mode 100644 index 000000000..a50bb1f5e --- /dev/null +++ b/docs/reference/metrics/gauge.md @@ -0,0 +1,8 @@ +::: asab.metrics.metrics.Gauge + handler: python + options: + members: + - set + show_root_heading: true + show_source: true + heading_level: 3 \ No newline at end of file diff --git a/docs/reference/metrics/histogram.md b/docs/reference/metrics/histogram.md new file mode 100644 index 000000000..254800a0d --- /dev/null +++ b/docs/reference/metrics/histogram.md @@ -0,0 +1,8 @@ +::: asab.metrics.metrics.Histogram + handler: python + options: + members: + - set + show_root_heading: true + show_source: true + heading_level: 3 \ No newline at end of file diff --git a/docs/reference/metrics/histogram_with_dynamic_tags.md b/docs/reference/metrics/histogram_with_dynamic_tags.md new file mode 100644 index 000000000..193faaa91 --- /dev/null +++ b/docs/reference/metrics/histogram_with_dynamic_tags.md @@ -0,0 +1,8 @@ +::: asab.metrics.metrics.HistogramWithDynamicTags + handler: python + options: + members: + - set + show_root_heading: true + show_source: true + heading_level: 3 \ No newline at end of file diff --git a/docs/reference/metrics/service.md b/docs/reference/metrics/service.md new file mode 100644 index 000000000..7965e6f64 --- /dev/null +++ b/docs/reference/metrics/service.md @@ -0,0 +1,13 @@ +::: asab.metrics.service.MetricsService + handler: python + options: + members: + - create_gauge + - create_counter + - create_eps_counter + - create_duty_cycle + - create_aggregation_counter + - create_histogram + show_root_heading: true + show_source: false + heading_level: 3 \ No newline at end of file diff --git a/docs/topics/asab/metrics.md b/docs/topics/asab/metrics.md deleted file mode 100644 index 0493ea69d..000000000 --- a/docs/topics/asab/metrics.md +++ /dev/null @@ -1,636 +0,0 @@ -xxx {.currentmodule} -asab.metrics -xxx - -Metrics -======= - -Metrics document the state of the application in a timescale manner. For -further analysis, connect your ASAB application to a time-series -database. [Influx](https://www.influxdata.com/) and -[Prometheus](https://prometheus.io/) are supported. - -Metrics Service ---------------- - -Create new metrics using `MetricsService`{.interpreted-text -role="class"}. - -*example of counter initialization:* - -``` {.python} -class MyApplication(asab.Application): - async def initialize(self): - from asab.metrics import Module - self.add_module(Module) - self.MetricsService = self.get_service('asab.MetricsService') - self.MyCounter = self.MetricsService.create_counter("mycounter", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0}) - -if __name__ == '__main__': - app = MyApplication() - app.run() -``` - -See the full example here: - - -Types of Metrics ----------------- - -- `Gauge`{.interpreted-text role="class"} stores single numerical - values which can go up and down. Implements `set`{.interpreted-text - role="func"} method to set the metric values. -- `Counter`{.interpreted-text role="class"} is a cumulative metric - whose values can increase or decrease. Implements - `add`{.interpreted-text role="func"} and `sub`{.interpreted-text - role="func"} methods. -- Event per Second Counter (`EPSCounter`{.interpreted-text - role="class"}) divides all values by delta time. -- `DutyCycle`{.interpreted-text role="class"} - -- `AggregationCounter`{.interpreted-text role="class"} allows to - `set`{.interpreted-text role="func"} values based on an aggregation - function. `max`{.interpreted-text role="func"} function is default. -- `Histogram`{.interpreted-text role="class"} represents cumulative - histogram with `set`{.interpreted-text role="func"} method. - -`Counter`{.interpreted-text role="class"}, -`AggregationCounter`{.interpreted-text role="class"} and -`Histogram`{.interpreted-text role="class"} come also in variants -respecting dynamic tags. (See section -`Dynamic Tags`{.interpreted-text role="ref"}.) - -All methods that create new metrics objects can be found in the Metrics -Service reference. You should never initiate a new metrics object on its -own, but always through Metrics Service. Metris initialization is meant -to be done in the init time of your application and **should not be done -during runtime**. - -ASAB Metrics Interpretation ---------------------------- - -Metrics Service not only creates new metrics but also periodically -collects their values and sends them to selected databases. Every 60 -seconds in the application lifetime, Metrics Service gathers values of -all ASAB metrics. All Counters (and metric types that inherit from -`Counter`{.interpreted-text role="class"}) reset at this event to their -initial values by default. Interpretation of ASAB Counters is affected -by their resetable nature. Even though they monotonously increase, -resetting every minute gives them a different meaning. In a long-term -observation (that\'s how you most probably monitor the metrics in -time-series databases), these metrics count **events per minute**. Thus, -resettable Counters are presented to Prometheus database as gauge-type -metrics. Set the [reset]{.title-ref} argument to [False]{.title-ref} -when creating a new Counter to disable Counter resetting. This periodic -\"flush\" cycle also causes 60s delay of metric propagation into -supported time-series databases. - -Initial Values --------------- - -You can initiate your metric instance with or without initial values. -When providing initial values, these values are always present and -presented to databases even when these values were untouched during the -last 60 seconds. You will always see these values in the data, with -initial state or changed by occasion. However, the lifetime of values -(name and value pairs) added during runtime is only 60 s. Thus, if this -value is not set during 60s period, you won\'t see it in your database -anymore. - -Built-in Tags {#dynamic_tags} -------------- - -Tags help you to sort and group metrics in a selected target database, -and analyze the data easily. Several \"static\" tags are provided -directly by ASAB. - -%TODO: option% -host -xxx - -This is a hostname of the server or machine where the application is -running - -%TODO: option% -appclass -xxx - -This is the name of the application. It is literally the name of the -class that inherits from the ASAB Application object. - -%TODO: option% -node\_id -xxx - -Present if NODE\_ID environmental variable is specified. Meant to -specify a node in the cluster. Automatically set by the Remote Control. - -%TODO: option% -service\_id -xxx - -Present if SERVICE\_ID environmental variable is specified. Meant to -specify a service in the cluster. Automatically set by the Remote -Control. - -%TODO: option% -instance\_id -xxx - -Present if INSTANCE\_ID environmental variable is specified. Meant to -specify an instance in the cluster. Automatically set by the Remote -Control. - -You can use with convenience the three last tags even without Remote -Control by adding the respective environmental variables to Docker -containers (or any other technology you use to run ASAB microservices). - -Dynamic Tags ------------- - -Some metric types (Counter, AggregationCounter, Histogram) allow you to -use dynamic tags. All metrics in ASAB carry some tags - Hostname by -default and others added by custom. Using dynamic tags allows you to -create values with a specific tag-set during runtime. Specific tag-sets -expire after defined period. This might be spotted in your time-series -database like a mysterious disappearance of unused tags. Specify -expiration period in confiuration. Default is 60 s. - -*example configuration* - -``` {.} -[asab:metrics] -expiration=60 -``` - -Timestamp ---------- - -**Timestamp** contains the record of the precise moment the metric\'s -value was created or committed to the database. There are two types of -metrics: resettable ([is\_reset]{.title-ref} = True) and non-resettable -([is\_reset]{.title-ref} = False). To reset a metric means to set it -back to its initial value (for example, back to 0). The metric\'s type -is determined by the `reset: bool = True` parameter of the metric\'s -constructor at the moment it is created. We measure non-resettable -metrics at the time of their creation ([there are several possible -methods depending on the metric\'s general logic]{.title-ref}), while -the resettable ones are measured when we send data to the database -([which is also the moment of them being reset]{.title-ref}). - -+---+--------+---------------------+--------------+--------------+-----+ -| | Met | Description / | Time is | Timestamp | is\ | -| | ric\'s | Methods | Measured | Value | _re | -| | Type | | | Appears | set | -+===+========+=====================+==============+==============+=====+ -| 1 | **G | Stores single | when metric | **set()** | **F | -| F | auge** | numerical values | is created | for actual | als | -| | | which can go up and | [(actual | time | e** | -| | | down. | time)] | | | -| | | | {.title-ref} | | | -| | | **add\_field() /** | | | | -| | | **set()** | | | | -+---+--------+---------------------+--------------+--------------+-----+ -| 2 | **Cou | A cumulative | when metric | **add()** or | **F | -| F | nter** | metric; values can | is created | **sub()** | als | -| | | increase or | [(actual | for actual | e** | -| | [ | decrease Never | time)] | time | | -| | Allows | stops. | {.title-ref} | | | -| | d | | | | | -| | ynamic | **add\_field() /** | | | | -| | tags] | **add() / sub() / | | | | -| | {.titl | flush()** | | | | -| | e-ref} | | | | | -+---+--------+---------------------+--------------+--------------+-----+ -| 2 | **Cou | A cumulative | every 60 | **flush()** | ** | -| T | nter** | metric; values can | seconds | - time of | Tru | -| | | increase or | | the test | e** | -| | [ | decrease Set to 0 | | flush | | -| | Allows | every 60 seconds. | | | | -| | d | | | | | -| | ynamic | [AgregationCounter | | | | -| | tags] | behavior is based | | | | -| | {.titl | on the resettable | | | | -| | e-ref} | Co | | | | -| | | unter.]{.title-ref} | | | | -+---+--------+---------------------+--------------+--------------+-----+ -| 3 | ** | There is an | [\*\*\*\*\*] | [\*\*\*\*\*] | **F | -| F | EPSCou | adjustable reset | {.title-ref} | {.title-ref} | als | -| | nter** | parameter in the | | | e** | -| | | metric's | | | | -| | | constructor. | | | | -| | | | | | | -| | | [reset: bool = | | | | -| | | True]{.title-ref} | | | | -| | | [reset: bool = | | | | -| | | False]{.title-ref} | | | | -+---+--------+---------------------+--------------+--------------+-----+ -| 3 | ** | Divides the count | every 60 | **flush()** | ** | -| T | EPSCou | of events by the | seconds | | Tru | -| | nter** | time difference | | | e** | -| | | between | | | | -| | | measurements. | | | | -| | | | | | | -| | | **flush()** | | | | -+---+--------+---------------------+--------------+--------------+-----+ -| 4 | * | The fraction of one | every 60 | **flush()** | ** | -| T | *DutyC | period in which a | seconds | | Tru | -| | ycle** | signal/system is | | | e** | -| | | active. A 60% DC | | | | -| | | means the signal is | | | | -| | | on 60% and off 40% | | | | -| | | of the time. | | | | -| | | | | | | -| | | **add\_field() /** | | | | -| | | **set() / flush()** | | | | -+---+--------+---------------------+--------------+--------------+-----+ -| 5 | * | Keeps track of max | when metric | **set()** | **F | -| F | *Aggre | or min value of the | is created | | als | -| | gation | Counter. Maximum | [(actual | | e** | -| | Cou | value is a default. | time)] | | | -| | nter** | | {.title-ref} | | | -| | | **set() /** | | | | -| | [ | [+inherits from the | | | | -| | Allows | C | | | | -| | d | ounter]{.title-ref} | | | | -| | ynamic | **add()/sub()** | | | | -| | tags] | [are | | | | -| | {.titl | overw | | | | -| | e-ref} | ritten]{.title-ref} | | | | -+---+--------+---------------------+--------------+--------------+-----+ -| 5 | * | [\*\* | every 60 | **flush()** | ** | -| T | *Aggre | \*\*\*]{.title-ref} | seconds | | Tru | -| | gation | | | | e** | -| | Cou | | | | | -| | nter** | | | | | -| | | | | | | -| | [ | | | | | -| | Allows | | | | | -| | d | | | | | -| | ynamic | | | | | -| | tags] | | | | | -| | {.titl | | | | | -| | e-ref} | | | | | -+---+--------+---------------------+--------------+--------------+-----+ -| 6 | * | Represents | when metric | **set()** | **F | -| F | *Histo | cumulative | is created | | als | -| | gram** | histogram with a | [(actual | | e** | -| | | set() method. | time)] | | | -| | [ | | {.title-ref} | | | -| | Allows | **add\_field() /** | | | | -| | d | **set() / flush()** | | | | -| | ynamic | | | | | -| | tags] | | | | | -| | {.titl | | | | | -| | e-ref} | | | | | -+---+--------+---------------------+--------------+--------------+-----+ -| 6 | * | [\*\* | every 60 | **flush()** | ** | -| T | *Histo | \*\*\*]{.title-ref} | seconds | | Tru | -| | gram** | | | | e** | -| | | | | | | -| | [ | | | | | -| | Allows | | | | | -| | d | | | | | -| | ynamic | | | | | -| | tags] | | | | | -| | {.titl | | | | | -| | e-ref} | | | | | -+---+--------+---------------------+--------------+--------------+-----+ - -InfluxDB --------- - -Metrics can be collected in the Influx time-series database. - -*configuration example:* - -``` {.} -[asab:metrics] -target=influxdb - -[asab:metrics:influxdb] -url=http://localhost:8086/ -bucket=my_bucket -org=my_org -token=my_token -``` - -**InfluxDB 2.0 API parameters**: - -- **url** - \[required\] url string of your influxDB - -- **bucket** - \[required\] the destination bucket for writes - -- **org** - \[required\] specifies the destination organization for - writes - -- - - **orgid** - \[optional\] specifies the ID of the destination organization for writes - - : (NOTE: If both orgID and org are specified, org takes - precedence) - -- **token** - \[required\] API token to authenticate to the InfluxDB - -**InfluxDB \<1.8 API parameters**: - -- **url** - \[required\] url string of your influxDB -- **username** - \[required\] name of influxDB user -- **password** - \[required\] password of influxDB user - -Prometheus ----------- - -Prometheus is a \"pull model\" time-series database. Prometheus accesses -`asab/v1/metrics` endpoint of ASAB ApiService. Thus, connecting ASAB to -Prometheus requires APIService initialization. However, no more -configuration is needed. ASAB metrics are presented to Prometheus in -[OpenMetrics](https://openmetrics.io/) standard format. - -*prometheus.yaml configuration file example:* - -``` {.yaml} -global: - scrape_interval: 15s - scrape_timeout: 10s - evaluation_interval: 15s - -scrape_configs: -- job_name: 'metrics_example' - metrics_path: '/asab/v1/metrics' - scrape_interval: 10s - static_configs: - - targets: ['127.0.0.1:8080'] -``` - -xxx {.note} -xxx {.title} -Note -xxx - -To satisfy the OpenMetrics format required by Prometheus, you should -follow the instructions below: - -- Metrics names must fit regex `[a-zA-Z:][a-zA-Z0-9_:]*`. (Any other - characters are replaced by an underscore. Leading underscores and - numbers are stripped. These changes proceed without warning.) -- Metrics names MUST NOT end with "total" or "created". -- Tags SHOULD contain items "unit" and "help" providing metadata to - Prometheus. -- Values MUST be float or integer. -xxx - -Metrics Endpoints ------------------ - -The **API Service** in ASAB offers several endpoints that monitor -internal ASAB functionality. Some of them present the current state of -metrics. Check for Swagger documentation of your ASAB Application REST -API by visiting the [/doc]{.title-ref} endpoint. - -`/asab/v1/metrics` - -- This endpoint returns metrics in OpenMetrics format and its primary - purpose is to satisfy Prometheus database needs. - -`/asab/v1/metrics.json` - -- This endpoint presents metrics data in JSON format. - -`/asab/v1/watch_metrics` - -- Use this endpoint for developing or monitoring your app from the - terminal. It returns a simple table of ASAB metrics. You can filter - metrics by name using the `filter` parameter and `tags` parameter to - show or hide tags. - -*example commands:* - -``` {.} -watch curl localhost:8080/asab/v1/watch_metrics -``` - -``` {.} -watch curl localhost:8080/asab/v1/watch_metrics?name=web_requests_duration_max,tags=True -``` - -HTTP Target ------------ - -For use cases requiring a push model of metrics digestion, there is an -HTTP Target. HTTP Target creates a POST request to configured URL with -current metrics state sent as JSON body. Configuration is required. - -*configuration example:* - -``` {.} -[asab:metrics] -target=http - -[asab:metrics:http] -url=http://consumer_example:8080/consume -``` - -Web Requests Metrics --------------------- - -ASAB `WebService`{.interpreted-text role="class"} class automatically -provides metrics counting web requests. There are 5 metrics quantifying -requests to all ASAB endpoints. - -- [web\_requests]{.title-ref} - Counts requests to asab endpoints as - events per minute. -- [web\_requests\_duration]{.title-ref} - Counts total requests - duration to asab endpoints per minute. -- [web\_requests\_duration\_min]{.title-ref} - Counts minimal request - duration to asab endpoints per minute. -- [web\_requests\_duration\_max]{.title-ref} - Counts maximum request - duration to asab endpoints per minute. -- [web\_requests\_duration\_hist]{.title-ref} - Cumulative histogram - counting requests in buckets defined by the request duration. - -Native Metrics --------------- - -You can opt out of Native Metrics through configuration by setting -[native\_metrics]{.title-ref} to [false]{.title-ref}. Default is -[true]{.title-ref}. - -*example configuration* - -``` {.} -[asab:metrics] -native_metrics=true -``` - -**Memory Metrics** - -A gauge with the name `os.stat` gathers information about memory usage -by your application. - -You can find several metric values there: - -- VmPeak - Peak virtual memory size -- VmLck - Locked memory size -- VmPin - Pinned memory size -- VmHWM - Peak resident set size (\"high water mark\") -- VmRSS - Resident set size -- VmData, VmStk, VmExe - Size of data, stack, and text segments -- VmLib - Shared library code size -- VmPTE - Page table entries size -- VmPMD - Size of second-level page tables -- VmSwap - Swapped-out virtual memory size by anonymous private pages; - shmem swap usage is not included - -**Logs Counter** - -There is a default Counter named `logs` with values `warnings`, -`errors`, and `critical`, counting logs with respective levels. It is a -humble tool for application health monitoring. - -Reference ---------- - -# TODO: autoclass show-inheritance=""} -MetricsService - -{.automethod} -create\_gauge - -Creates `Gauge`{.interpreted-text role="class"} object. -xxx - -{.automethod} -create\_counter - -Creates `Counter`{.interpreted-text role="class"} or -`CounterWithDynamicTags`{.interpreted-text role="class"} object. -xxx - -{.automethod} -create\_eps\_counter - -Creates `EPSCounter`{.interpreted-text role="class"} object. -xxx - -{.automethod} -create\_duty\_cycle - -Creates `DutyCycle`{.interpreted-text role="class"} object. -xxx - -{.automethod} -create\_aggregation\_counter - -Creates `AggregationCounter`{.interpreted-text role="class"} or -`AggregationCounterWithDynamicTags`{.interpreted-text role="class"} -object. -xxx - -{.automethod} -create\_histogram - -Creates `Histogram`{.interpreted-text role="class"} or -`HistogramWithDynamicTags`{.interpreted-text role="class"} object. -xxx -xxx - -# TODO: autoclass show-inheritance=""} -Gauge - -Argument [init\_values]{.title-ref} is a dictionary with initial values -and value names as keys. - -{.automethod} -set -xxx - -param name - -: name of the value - -param value - -: value itself -xxx - -# TODO: autoclass show-inheritance=""} -Counter - -Argument [init\_values]{.title-ref} is a dictionary with initial values -and value names as keys. If reset is True, Counter resets every 60 -seconds. - -{.automethod} -add -xxx - -{.automethod} -sub -xxx -xxx - -# TODO: autoclass show-inheritance=""} -EPSCounter -xxx - -# TODO: autoclass show-inheritance=""} -DutyCycle -xxx - -# TODO: autoclass show-inheritance=""} -AggregationCounter - -Values (their names and init\_values) can be provided when initializing -the metrics or added with `set`{.interpreted-text role="func"} method. -`add`{.interpreted-text role="func"} and `sub`{.interpreted-text -role="func"} methods are not implemented. - -{.automethod} -set -xxx - -Applies aggregation function on recent Counter value and value in -argument and sets the result as new value of the Counter. -xxx - -# TODO: autoclass show-inheritance=""} -Histogram - -{.automethod} -set -xxx -xxx - -# TODO: autoclass show-inheritance=""} -CounterWithDynamicTags - -{.automethod} -add -xxx - -{.automethod} -sub -xxx -xxx - -# TODO: autoclass show-inheritance=""} -AggregationCounterWithDynamicTags - -{.automethod} -set -xxx -xxx - -# TODO: autoclass show-inheritance=""} -HistogramWithDynamicTags - -{.automethod} -set -xxx -xxx - -# Reference - -::: asab.metrics diff --git a/docs/topics/asab/metrics/built-ins.md b/docs/topics/asab/metrics/built-ins.md new file mode 100644 index 000000000..b680124ec --- /dev/null +++ b/docs/topics/asab/metrics/built-ins.md @@ -0,0 +1,63 @@ +# Built-in Metrics + +## Web Requests Metrics + +ASAB `WebService` class automatically +provides metrics counting web requests. There are 5 metrics quantifying +requests to all ASAB endpoints. They use dynamic tags to provide infromation about method, path and status of the response. + +- `web_requests` - Counts requests to asab endpoints as + events per minute. +- `web_requests_duration` - Counts total requests + duration to asab endpoints per minute. +- `web_requests_duration_min` - Counts minimal request + duration to asab endpoints per minute. +- `web_requests_duration_max` - Counts maximum request + duration to asab endpoints per minute. +- `web_requests_duration_hist` - Cumulative histogram + counting requests in buckets defined by the request duration. + +Web Requests Metrics are switched off by default. Use configuration to allow them. +Be aware that both Web module and Metrics module must be initialized for these metrics. + +!!! example "Configuration example" + ``` {.} + [asab:metrics] + web_requests_metrics=true + ``` + +## Native Metrics + +You can opt out of Native Metrics through configuration by setting +`native_metrics` to `false`. Default is `true`. + +!!! example "Configuration example" + ``` {.} + [asab:metrics] + native_metrics=true + ``` + +### Memory Metrics + +A gauge with the name `os.stat` gathers information about memory usage +by your application. + +You can find several metric values there: + +- VmPeak - Peak virtual memory size +- VmLck - Locked memory size +- VmPin - Pinned memory size +- VmHWM - Peak resident set size (\"high water mark\") +- VmRSS - Resident set size +- VmData, VmStk, VmExe - Size of data, stack, and text segments +- VmLib - Shared library code size +- VmPTE - Page table entries size +- VmPMD - Size of second-level page tables +- VmSwap - Swapped-out virtual memory size by anonymous private pages; + shmem swap usage is not included + +### Logs Counter + +There is a default Counter named `logs` with values `warnings`, +`errors`, and `critical`, counting logs with respective levels. It is a +humble tool for application health monitoring. \ No newline at end of file diff --git a/docs/topics/asab/metrics/intro.md b/docs/topics/asab/metrics/intro.md new file mode 100644 index 000000000..62668479f --- /dev/null +++ b/docs/topics/asab/metrics/intro.md @@ -0,0 +1,111 @@ +# Metrics + +Metrics document the state of the application in a timescale manner. +For further analysis, connect your ASAB application to a time-series +database. [Influx](https://www.influxdata.com/) and +[Prometheus](https://prometheus.io/) are supported. + + +!!! example + + ``` python + class MyApplication(asab.Application): + async def initialize(self): + from asab.metrics import Module # (1)! + self.add_module(Module) + self.MetricsService = self.get_service('asab.MetricsService') # (2)! + self.MyCounter = self.MetricsService.create_counter("mycounter", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0}) # (3)! + + if __name__ == '__main__': + app = MyApplication() + app.run() + ``` + + 1. Import asab.metrics Module and add it to the application. + 2. Then, you can localize MetricsService. + 3. Use MetricsService to intialize the counter. + + +See the full example here: + + +See reference here (TODO link) + +## Types of Metrics + +- `Gauge` stores single numerical values which can go up and down. + Implements `set` method to set the metric values. +- `Counter` is a cumulative metric whose values can increase or decrease. + Implements `add` and `sub` methods. +- Event per Second Counter (`EPSCounter`) divides all values by delta time. +- `DutyCycle` measures the fraction of a period in which a signal/system is active +- `AggregationCounter` allows to `set` values based on an aggregation function. + `max` function is default. +- `Histogram` represents cumulative histogram with `set` method. + +`Counter`, `AggregationCounter` and `Histogram` come also in variants +respecting dynamic tags. (See section [Dynamic Tags](./tags.md)) + +All methods that create new metrics objects can be found in the Metrics +Service reference. You should never initiate a new metrics object on its +own, but always through Metrics Service. Metris initialization is meant +to be done in the init time of your application and **should not be done +during runtime**. + +## ASAB Metrics Interpretation + +Metrics Service not only creates new metrics but also periodically +collects their values and sends them to selected databases. Every 60 +seconds in the application lifetime, Metrics Service gathers values of +all ASAB metrics. All Counters (and metric types that inherit from +`Counter`) reset at this event to their +initial values by default. Interpretation of ASAB Counters is affected +by their resetable nature. Even though they monotonously increase, +resetting every minute gives them a different meaning. In a long-term +observation (that's how you most probably monitor the metrics in +time-series databases), these metrics count **events per minute**. Thus, +resettable Counters are presented to Prometheus database as gauge-type +metrics. Set the `reset` argument to `False` +when creating a new Counter to disable Counter resetting. This periodic +"flush" cycle also causes 60s delay of metric propagation into +supported time-series databases. +Please, see the Timestamp section explaining the origin of a timestamp in each metric record. + +## Initial Values + +You can initiate your metric instance **with or without initial values**. +Initial values are always present and presented to databases even without a single event changing the metric values. +You will always find a pair of value name and its value in resulting dataset. +Values (name and value pairs) added during runtime last only 60 s. +You might spot this feature as missing values in the resulting time-series dataset. + + +## Timestamp + +**Timestamp** contains the record of the precise moment the metric's +value was created or committed to the database. There are two types of +metrics: resettable (`is_reset` = True) and non-resettable +(`is_reset` = False). To reset a metric means to set it +back to its initial value (for example, back to 0). The metric's type +is determined by the `reset: bool = True` parameter of the metric's +constructor at the moment of creation. We measure values of non-resettable +metrics at the time of their creation (there are several possible +methods depending on the metric's general logic), while +the resettable ones are measured when we reset the data +(which is also the moment of them being sent into the database). + +| Metric Type | Description / Methods | Origin of the timestamp | is_reset | +| :-------------------------------- | :------------------------------------------- | :--------------------- | :-------- | +| `Gauge` | Stores single numerical values which can go up and down. `set()` | When value is set. `set()` | **False** | +| `Counter` (*Allows dynamic tags*) | A cumulative metric; values can increase or decrease. Never stops. `add()`, `sub()` | When value is set. `add()` or `sub()` | **False** | +| `Counter` (*Allows dynamic tags*) | A cumulative metric; values can increase or decrease. Set to 0 every 60 seconds. | On `flush()`, every 60 seconds | **True** | +| `EPSCounter` | Divides the count of events by the time of the application run. | On `flush()`, every 60 seconds | **False** | +| `EPSCounter` | Divides the count of events by the time difference between measurements. | On `flush()`, every 60 seconds | **True** | +| `DutyCycle` | The fraction of one period in which a signal/system is active. A 60% DC means the signal is on 60% and off 40% of the time. | On `flush()`, every 60 seconds | **True** | +| `Aggregation Counter` (*Allows dynamic tags*) | Keeps track of max or min value of the Counter. Keeps maximum value by default. | When value is set. `set()` | **False** | +| `Aggregation Counter` (*Allows dynamic tags*)| Keeps track of max or min value of the Counter in each 60s window. Keeps maximum value by default. | On `flush()`, every 60 seconds | **True** | +| `Histogram` (*Allows dynamic tags*) | Cumulative histogram with a `set()` method. | When value is set. `set()` | **False** | +| `Histogram` (*Allows dynamic tags*) | Cumulative histogram with a `set()` method. | On `flush()`, every 60 seconds | **True** | + + + diff --git a/docs/topics/asab/metrics/tags.md b/docs/topics/asab/metrics/tags.md new file mode 100644 index 000000000..4607af994 --- /dev/null +++ b/docs/topics/asab/metrics/tags.md @@ -0,0 +1,66 @@ +# Tags +Tags allow filtering and aggregating collected metrics. +They provide dimensions for further analysis of the collected data. +There are two means of assigning a tag to a metric. Static tags are given to the metric when it is initialized. +Dynamic tags are assigned whenever a value is set. + +## Static Tags +!!! example + + ``` python + MyCounter = MetricsService.create_counter( + "mycounter", + tags={'origin': 'MyApplication'}, + init_values={'v1': 0, 'v2': 0} + ) + ``` + +You can see the new tag `origin` in the initialization of `MyCounter`. You can locate the origin of each record in the time-series database by this tag. +To make tracking of each metric record easier, there are several built-in static tags. + +### Built-in Tags + +- `host`: +Hostname of the server or machine where the application is running. + +- `appclass`: +Name of the application. It is the name of the class that inherits from the ASAB Application object. + +- `node_id`: +Present if NODE_ID environmental variable is specified. It names a node in the cluster. + +- `service_id`: +Present if SERVICE_ID environmental variable is specified. It names a service in the cluster. + +- `instance_id`: +Present if INSTANCE_ID environmental variable is specified. It names an instance in the cluster. + + +## Dynamic Tags +!!! example + + ``` python + MyCounter = MetricsService.create_counter( + "mycounter", + tags={'origin': 'MyApplication'}, + init_values={'v1': 0, 'v2': 0}, + dynamic_tags=True + ) + + MyCounter.add("v1", 1, {"method": "GET"}): + ``` +Some metric types (Counter, AggregationCounter, Histogram) allow you to +use dynamic tags. +You can create values with a specific tag-set during runtime. +Specific tag-sets expire after a defined period. +This might be spotted in your time-series database like a mysterious disappearance of unused tags. +Specify the expiration period in the configuration, default is 60 s. + +!!! example "Configuration example" + + ``` {.} + [asab:metrics] + expiration=60 + ``` + +See [webrequests metrics](./built-ins.md#web-requests-metrics) as an example of metrics with dynamic tags. \ No newline at end of file diff --git a/docs/topics/asab/metrics/targets.md b/docs/topics/asab/metrics/targets.md new file mode 100644 index 000000000..3f8cb52fe --- /dev/null +++ b/docs/topics/asab/metrics/targets.md @@ -0,0 +1,137 @@ +# Monitoring +The Metrics module in ASAB serves to produce data - metrics. It does not store them, nor analyse. To get some overview, you must collect the metrics in a time-series database, or choose some custom way of monitoring. +InfluxDB and Prometheus databases are supported by ASAB and several endpoints can be used for data monitoring or collecting as well. + +## InfluxDB + +Metrics can be collected in the Influx time-series database. Metrics are being sent in 60s intervals to configured Influx instance. + +!!! example "Configuration example" + ``` {.} + [asab:metrics] + target=influxdb + + [asab:metrics:influxdb] + url=http://localhost:8086/ + bucket=my_bucket + org=my_org + token=my_token + ``` + +**InfluxDB 2.0 API parameters**: + +- **url** - (required) URL string of your InfluxDB. +- **bucket** - (required) Destination bucket for writing. +- **org** - (required) Destination organization for writing. +- **orgid** - (optional) ID of the destination organization for writing. + : (NOTE: If both orgID and org are specified, org takes + precedence) +- **token** - (required) API token to authenticate to the InfluxDB + +**InfluxDB \<1.8 API parameters**: +- **url** - (required) URL string of your InfluxDB. +- **username** - (required) name of InfluxDB user. +- **password** - (required) password of InfluxDB user. + +## Prometheus +Prometheus is a "pull model" time-series database. +Prometheus accesses `asab/v1/metrics` endpoint of ASAB ApiService. Thus, connecting ASAB to +Prometheus requires APIService initialization. All other configuration is required on the Prometheus side. +ASAB metrics are presented to Prometheus in [OpenMetrics](https://openmetrics.io/) standard format. + +!!! example "ApiService initialization" + + ``` python + class MyApplication(asab.Application): + async def initialize(self): + from asab.metrics import Module + self.add_module(Module) + self.MetricsService = self.get_service('asab.MetricsService') + self.MyCounter = self.MetricsService.create_counter("mycounter", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0}) + + # Initialize API service + self.ApiService = asab.api.ApiService(self) + self.ApiService.initialize_web() + + if __name__ == '__main__': + app = MyApplication() + app.run() + ``` + +!!! example "prometheus.yaml configuration file example" + + ``` {.yaml} + global: + scrape_interval: 15s + scrape_timeout: 10s + evaluation_interval: 15s + + scrape_configs: + - job_name: 'metrics_example' + metrics_path: '/asab/v1/metrics' + scrape_interval: 10s + static_configs: + - targets: ['127.0.0.1:8080'] + ``` + +!!! note + + To satisfy the OpenMetrics format required by Prometheus, you should + follow the instructions below: + + - Metrics names must fit regex `[a-zA-Z:][a-zA-Z0-9_:]*`. (Any other + characters are replaced by an underscore. Leading underscores and + numbers are stripped. These changes proceed without warning.) + - Metrics names MUST NOT end with "total" or "created". + - Tags SHOULD contain items "unit" and "help" providing metadata to + Prometheus. + - Values MUST be float or integer. + + +## Metrics Endpoints + +The **API Service** in ASAB offers several endpoints that monitor +internal ASAB functionality. Some of them present the current state of +metrics. Check for Swagger documentation of your ASAB Application REST +API by visiting the `/doc` endpoint. + +`/asab/v1/metrics` + +- This endpoint returns metrics in OpenMetrics format and its primary + purpose is to satisfy Prometheus database needs. + +`/asab/v1/metrics.json` + +- This endpoint presents metrics data in JSON format. + +`/asab/v1/watch_metrics` + +- Use this endpoint for developing or monitoring your app from the + terminal. It returns a simple table of ASAB metrics. You can filter + metrics by name using the `filter` parameter and `tags` parameter to + show or hide tags. + +!!! example + + ``` {.} + watch curl localhost:8080/asab/v1/watch_metrics + ``` + + ``` {.} + watch curl localhost:8080/asab/v1/watch_metrics?name=web_requests_duration_max,tags=True + ``` + +## HTTP Target + +For use cases requiring a push model of metrics digestion, there is an +HTTP Target. HTTP Target creates a POST request every 60 seconds to configured URL with +the current metrics state sent as JSON body. Configuration is required. + +!!! example "Configuration example" + ``` {.} + [asab:metrics] + target=http + + [asab:metrics:http] + url=http://consumer_example:8080/consume + ``` \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 6e5a1660e..6f39c7606 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -80,6 +80,7 @@ markdown_extensions: pygments_lang_class: true - pymdownx.inlinehilite - pymdownx.snippets + - tables # Admonitions (call-outs) https://squidfunk.github.io/mkdocs-material/reference/admonitions/ - admonition @@ -96,7 +97,7 @@ markdown_extensions: # Content tabs and anchor links https://squidfunk.github.io/mkdocs-material/reference/content-tabs/ - pymdownx.tabbed: - alternate_style: true + alternate_style: true extra: social: @@ -125,12 +126,17 @@ nav: # - topics/asab/pubsub.md # - topics/asab/service.md - Storage: - - Intro: topics/asab/storage/intro.md + - Introduction: topics/asab/storage/intro.md - Manipulation with Databases: topics/asab/storage/manipulation_with_databases.md - Encryption and Decryption: topics/asab/storage/encryption.md - In-Memory Storage: topics/asab/storage/inmemory.md - MongoDB Storage: topics/asab/storage/mongodb.md - ElasticSearch Storage: topics/asab/storage/elasticsearch.md + - Metrics: + - Introduction: topics/asab/metrics/intro.md + - Tags: topics/asab/metrics/tags.md + - Built-in metrics: topics/asab/metrics/built-ins.md + - Monitoring: topics/asab/metrics/targets.md # - topics/asab/various.md # - topics/asab/zookeeper.md @@ -139,7 +145,17 @@ nav: # - reference/config.md # - reference/library.md # - reference/log.md - # - reference/metrics.md + - Metrics: + - MetricsService: reference/metrics/service.md + - Gauge: reference/metrics/gauge.md + - Counter: reference/metrics/counter.md + - EPSCounter: reference/metrics/eps_counter.md + - DutyCycle: reference/metrics/duty_cycle.md + - AggregationCounter: reference/metrics/aggregation_counter.md + - Histogram: reference/metrics/histogram.md + - CounterWithDynamicTags: reference/metrics/counter_with_dynamic_tags.md + - AggregationCounterWithDynamicTags: reference/metrics/aggregation_counter_with_dynamic_tags.md + - HistogramWithDynamicTags: reference/metrics/histogram_with_dynamic_tags.md # - reference/module.md - Storage: - StorageService: reference/storage/service.md From 8d9fa5048d21a41e68fda4b3f160f2306d53a057 Mon Sep 17 00:00:00 2001 From: eliska-n Date: Mon, 10 Jul 2023 10:14:06 +0200 Subject: [PATCH 020/154] fixies --- docs/topics/asab/metrics/intro.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/topics/asab/metrics/intro.md b/docs/topics/asab/metrics/intro.md index 62668479f..6af9859c6 100644 --- a/docs/topics/asab/metrics/intro.md +++ b/docs/topics/asab/metrics/intro.md @@ -26,10 +26,9 @@ database. [Influx](https://www.influxdata.com/) and 3. Use MetricsService to intialize the counter. -See the full example here: - +See the full example [here](https://github.com/TeskaLabs/asab/blob/master/examples/metrics.py). -See reference here (TODO link) +See reference [here](./../../../reference/metrics/service.md). ## Types of Metrics From c3077e7f8f6b3504d595a590890fd4582fc58760 Mon Sep 17 00:00:00 2001 From: eliska-n Date: Mon, 10 Jul 2023 10:21:42 +0200 Subject: [PATCH 021/154] flake8 --- asab/metrics/metrics.py | 2 +- asab/metrics/service.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/asab/metrics/metrics.py b/asab/metrics/metrics.py index 7636c4bab..9d654fccf 100644 --- a/asab/metrics/metrics.py +++ b/asab/metrics/metrics.py @@ -71,7 +71,7 @@ def add(self, name: str, value, init_value: dict = None): """ The `add` function adds a specified value to a counter, and if the counter does not exist, it creates it and initializes it with an optional initial value. - + Args: name (str): Value name to which the `value` will be added. value: Value that needs to be added to the counter. It is the amount by which the counter will be incremented. diff --git a/asab/metrics/service.py b/asab/metrics/service.py index fbacfd65c..64996c7c0 100644 --- a/asab/metrics/service.py +++ b/asab/metrics/service.py @@ -146,7 +146,7 @@ def create_gauge(self, metric_name: str, tags: dict = None, init_values: dict = unit (str): The "unit" parameter is used to specify the unit of measurement for the metric. It helps provide context and understanding for the metric being measured. For example, if the metric is measuring the temperature, the unit could be "degrees Celsius". - + Returns: an instance of the Gauge class. """ @@ -217,7 +217,7 @@ def create_eps_counter(self, metric_name: str, tags: dict = None, init_values: d def create_duty_cycle(self, metric_name: str, tags: dict = None, init_values: dict = None, help: str = None, unit: str = None): """ The function creates a duty cycle metric and returns the object. - + Args: metric_name (str): The name of the metric you want to create. tags (dict): Dictionary where the keys represent the tag names and the values represent the tag values. It allows you @@ -277,7 +277,7 @@ def create_histogram(self, metric_name, buckets: list, tags=None, init_values=No Args: metric_name (str): The name of the metric you want to create. - buckets (list): The "buckets" parameter is a list that specifies the boundaries for the histogram + buckets (list): The "buckets" parameter is a list that specifies the boundaries for the histogram buckets. Each element in the list represents the upper bound of a bucket. For example, if the list is [10, 20, 30], it means that the histogram will have three buckets: one for values less than 10, second for values less than 20, third for values less than 30 tags (dict): Dictionary where the keys represent the tag names and the values represent the tag values. It allows you From 052f3205b102733f47a9868d3f893fc340e16ec0 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 10 Jul 2023 11:54:52 +0200 Subject: [PATCH 022/154] Add python handler options --- docs/TODO.md | 4 +--- mkdocs.yml | 12 +++++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/TODO.md b/docs/TODO.md index 3cc6069c2..e3a5b9d74 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -8,9 +8,7 @@ https://diataxis.fr/ https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings -- plán: začni indexem a zkus prvních několik souborů převést do čitelné podoby -- pozor na # vs ---- kazí strukturu vyhledávání -- reference na moduly? +Create application that consists of two microservices. One of them pulls periodically the data from RSS channel and parses them into json file # Tutorials diff --git a/mkdocs.yml b/mkdocs.yml index 6e5a1660e..cd386fdc8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -64,12 +64,22 @@ theme: # PLUGINS plugins: - - mkdocstrings + - mkdocstrings: + default_handler: python + handlers: + python: + options: + # https://mkdocstrings.github.io/python/usage/configuration/docstrings/ + docstring_style: google # | google | numpy | sphinx + docstring_section_style: table # table | list | spacy + show_if_no_docstring: true + show_docstring_description: false - glightbox - search - awesome-pages - git-revision-date-localized - tags + - autorefs # https://mkdocstrings.github.io/usage/#cross-references-to-any-markdown-heading markdown_extensions: From ec4a8735997136656d062744d5799a0274d88c36 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 10 Jul 2023 11:55:08 +0200 Subject: [PATCH 023/154] Further simplification --- .../getting-started/installation_first_app.md | 92 ++++++++----------- docs/how-tos/rss-reader.md | 10 ++ 2 files changed, 48 insertions(+), 54 deletions(-) create mode 100644 docs/how-tos/rss-reader.md diff --git a/docs/getting-started/installation_first_app.md b/docs/getting-started/installation_first_app.md index e2752f64b..e3845f261 100644 --- a/docs/getting-started/installation_first_app.md +++ b/docs/getting-started/installation_first_app.md @@ -40,19 +40,48 @@ ASAB is distributed via [pypi](https://pypi.org/project/asab/). For installing A 1. Create a file called `main.py` with the following code: - ``` python title="main.py" - #!/usr/bin/env python3 - import asab + + ``` python title="main.py" linenums="1" - class MyApplication(asab.Application): - async def main(self): - print("Hello world") + #!/usr/bin/env python3 + # (1)! + import asab # (2)! - if __name__ == '__main__': - app = MyApplication() - app.run() + class MyApplication(asab.Application): # (3)! + async def main(self): # (4)! + print("Hello world") # (5)! + + if __name__ == '__main__': # (6)! + app = MyApplication() + app.run() ``` + 1. ASAB application uses a Python 3.7+. This is specified a by hashbang + line at the very beginning of the file. + + 1. ASAB is included from as `asab` module via an import + statement. + + 1. Every ASAB Application needs to have an application object. It is a + **singleton**: the application must create and operate + precisely one instance of the application. ASAB provides the base + [asab.Application][#TODO] class that you need to + inherit from to implement your custom application class. + + 1. The `#!python Application.main()` method is one of + the application lifecycle methods, that you can override to implement + desired application functionality. The `main` method is a + coroutine, so that you can await any tasks etc. in fully asynchronous + way. This method is called when ASAB application is executed and + initialized. The lifecycle stage is called "runtime". + + 1. In this example, we just print a message to a screen. + + 2. This part of the code is executed when the Python program is launched. + It creates the application object and executes the `#!python run()` method which creates and runs an event loop. + This is a standard way of how ASAB application is started. + + 2. Run the server: ``` shell @@ -74,51 +103,6 @@ ASAB is distributed via [pypi](https://pypi.org/project/asab/). For installing A for server architectures. For that reason, it doesn't terminate and continue running and serving eventual requests. -## Taking a closer look - -Let's look on the application one more time. - - -``` python title="main.py" linenums="1" - - #!/usr/bin/env python3 - # (1)! - import asab # (2)! - - class MyApplication(asab.Application): # (3)! - async def main(self): # (4)! - print("Hello world") # (5)! - - if __name__ == '__main__': # (6)! - app = MyApplication() - app.run() -``` - -1. ASAB application uses a Python 3.7+. This is specified a by hashbang -line at the very beginning of the file. - -1. ASAB is included from as `asab` module via an import -statement. - -1. Every ASAB Application needs to have an application object. It is a -**singleton**: the application must create and operate -precisely one instance of the application. ASAB provides the base -[asab.Application][#TODO] class that you need to -inherit from to implement your custom application class. - -1. The `#!python Application.main()` method is one of -the application lifecycle methods, that you can override to implement -desired application functionality. The `main` method is a -coroutine, so that you can await any tasks etc. in fully asynchronous -way. This method is called when ASAB application is executed and -initialized. The lifecycle stage is called "runtime". - -1. In this example, we just print a message to a screen. - -2. This part of the code is executed when the Python program is launched. -It creates the application object and executes the `#!python run()` method which creates and runs an event loop. -This is a standard way of how ASAB application is started. - ## Summary In this tutorial, you learned how to install ASAB and how to create a basic application. diff --git a/docs/how-tos/rss-reader.md b/docs/how-tos/rss-reader.md new file mode 100644 index 000000000..5aeb17d05 --- /dev/null +++ b/docs/how-tos/rss-reader.md @@ -0,0 +1,10 @@ +# How to create a RSS reader + +## Contents: + +1. Create a `ParserService` that sends requests to a certain RSS feed: + 1. **Config**: make source configurable and explain Config syntax + 2. **PubSub**: schedule the request every 1 minute +2. Create a web server that renders the RSS on a webpage. + 1. **LibraryService** - uses filesystem provider. + 2. \ No newline at end of file From ffe2e621febff61eb989d796e6194e97ac0b5f2f Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 11 Jul 2023 10:18:12 +0200 Subject: [PATCH 024/154] Add navigation and search features --- mkdocs.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index cd386fdc8..7fe443008 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -13,6 +13,8 @@ theme: - navigation.tabs - navigation.footer - navigation.indexes + - navigation.top # back-to-the-top button when scrolling up + - navigation.tracking - attr_list - admonition - pymdownx.details @@ -23,7 +25,8 @@ theme: - pymdownx.mark - pymdownx.tilde - def_list - - navigation.tracking + - search.suggest # autocomplete the search query + - search.share # share the queried endpoint icon: admonition: @@ -32,7 +35,6 @@ theme: info: fontawesome/solid/circle-info tip: fontawesome/solid/bullhorn success: fontawesome/solid/check - # failure: fontawesome/solid/bomb failure: fontawesome/solid/xmark question: fontawesome/solid/circle-question warning: fontawesome/solid/triangle-exclamation @@ -160,3 +162,6 @@ nav: - In-Memory: reference/storage/inmemory.md - Contributing: contributing.md + + # Examples are rendered automatically with create_examples.py script + - Examples: From 5a978304e7bc8353e5c43616e7a946f417ddd3f1 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 11 Jul 2023 11:36:57 +0200 Subject: [PATCH 025/154] Add script for creating examples md automatically --- docs/TODO.md | 12 +- docs/create_examples.py | 80 +++++++++ docs/examples/application_states.md | 75 ++++++++ docs/examples/argparser.md | 68 +++++++ docs/examples/config_getseconds.md | 57 ++++++ docs/examples/config_geturl.md | 71 ++++++++ docs/examples/executor.md | 70 ++++++++ docs/examples/hello_world.md | 29 +++ docs/examples/json_schema.md | 69 +++++++ docs/examples/library-git-provider.md | 78 ++++++++ docs/examples/library-subscribe.md | 56 ++++++ docs/examples/library.md | 76 ++++++++ docs/examples/logging-file.md | 38 ++++ docs/examples/metrics-web-requests.md | 116 ++++++++++++ docs/examples/metrics.md | 66 +++++++ docs/examples/pdict.md | 37 ++++ docs/examples/pubsub.md | 49 +++++ docs/examples/service-discovery.md | 96 ++++++++++ docs/examples/storage_elasticsearch.md | 91 ++++++++++ docs/examples/storage_inmemory.md | 62 +++++++ docs/examples/storage_mongodb.md | 89 +++++++++ docs/examples/task.md | 44 +++++ docs/examples/timer.md | 33 ++++ docs/examples/web-auth.md | 239 +++++++++++++++++++++++++ docs/examples/web-authz-rbac.md | 71 ++++++++ docs/examples/web-authz-userinfo.md | 104 +++++++++++ docs/examples/webserver.md | 45 +++++ docs/examples/websocket-chat.md | 52 ++++++ docs/examples/zookeeper-advertise.md | 54 ++++++ docs/examples/zookeeper.md | 59 ++++++ mkdocs.yml | 29 +++ 31 files changed, 2104 insertions(+), 11 deletions(-) create mode 100644 docs/create_examples.py create mode 100644 docs/examples/application_states.md create mode 100644 docs/examples/argparser.md create mode 100644 docs/examples/config_getseconds.md create mode 100644 docs/examples/config_geturl.md create mode 100644 docs/examples/executor.md create mode 100644 docs/examples/hello_world.md create mode 100644 docs/examples/json_schema.md create mode 100644 docs/examples/library-git-provider.md create mode 100644 docs/examples/library-subscribe.md create mode 100644 docs/examples/library.md create mode 100644 docs/examples/logging-file.md create mode 100644 docs/examples/metrics-web-requests.md create mode 100644 docs/examples/metrics.md create mode 100644 docs/examples/pdict.md create mode 100644 docs/examples/pubsub.md create mode 100644 docs/examples/service-discovery.md create mode 100644 docs/examples/storage_elasticsearch.md create mode 100644 docs/examples/storage_inmemory.md create mode 100644 docs/examples/storage_mongodb.md create mode 100644 docs/examples/task.md create mode 100644 docs/examples/timer.md create mode 100644 docs/examples/web-auth.md create mode 100644 docs/examples/web-authz-rbac.md create mode 100644 docs/examples/web-authz-userinfo.md create mode 100644 docs/examples/webserver.md create mode 100644 docs/examples/websocket-chat.md create mode 100644 docs/examples/zookeeper-advertise.md create mode 100644 docs/examples/zookeeper.md diff --git a/docs/TODO.md b/docs/TODO.md index e3a5b9d74..d6030a34a 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -8,14 +8,4 @@ https://diataxis.fr/ https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings -Create application that consists of two microservices. One of them pulls periodically the data from RSS channel and parses them into json file - -# Tutorials - -# How to guides - -# Explanation - -# Reference - -copy-paste sections \ No newline at end of file +- Experiment with search boosting: https://squidfunk.github.io/mkdocs-material/setup/setting-up-site-search/#search-boosting \ No newline at end of file diff --git a/docs/create_examples.py b/docs/create_examples.py new file mode 100644 index 000000000..2cb838d22 --- /dev/null +++ b/docs/create_examples.py @@ -0,0 +1,80 @@ +"""This script iterates over .py files in examples directory and converts them into .md files into docs/examples.""" + +import pathlib +import yaml +import datetime +import re +import subprocess + +EXAMPLE_DIR = pathlib.Path.cwd() / "examples" +DOCS_DIR = pathlib.Path.cwd() / "docs" / "examples" +MKDOCS_FILE = pathlib.Path.cwd() / "mkdocs.yml" + + +def process_examples(path_from, path_to): + """Find all the python files in 'path_from'. + For each file, check if the corresponding .md file exist in 'path_to' + or if it was modified (has a different commit hash). + If so, create a new md file and append its reference to the 'nav' section in 'mkdocs.yml' file. +""" + for py_file in EXAMPLE_DIR.glob("*.py"): + # Check if the example is referenced in docs + md_file = DOCS_DIR / py_file.with_suffix(".md").name + if not md_file.exists() or git_metadata(py_file) != load_headers(md_file): + create_markdown(py_file, md_file) + add_to_navbar(md_file, MKDOCS_FILE) + + +def load_headers(md_file: pathlib.Path): + _, headers, *content = md_file.read_text().split("---") + assert content, "{} does not have 'headers' section defined.".format(md_file) + return yaml.safe_load(headers) + + +def git_metadata(py_file: pathlib.Path) -> dict: + git_format = "%aN|%ad|%H" + last_git_commit = subprocess.check_output(["git", "log", "-n", "1", "--format={}".format(git_format), "--", py_file]).decode('utf-8').strip("\n").split("|") + date_format = '%a %b %d %H:%M:%S %Y %z' + metadata = { + "author": last_git_commit[0], + "date": datetime.datetime.strptime(last_git_commit[1], date_format), + "commit": last_git_commit[2], + "title": py_file.stem.replace("_", " ").replace("-", " ").capitalize() + } + return metadata + + +def create_markdown(py_file: pathlib.Path, md_file: pathlib.Path): + text = """--- +{headers} +--- + +!!! example + + ```python title={py_file_name} linenums="1" + {py_file_content} + ``` +""".format( + headers=yaml.safe_dump(git_metadata(py_file)), + py_file_name=py_file.name, + py_file_content=py_file.read_text().replace("\n", "\n\t") + ) + md_file.write_text(text) + + +def add_to_navbar(md_file: pathlib.Path, mkdocs_file: pathlib.Path): + + with open(mkdocs_file, "+at", encoding="utf-8") as f: + content = f.read() + if md_file.name not in content: + print(md_file.name, "not in", mkdocs_file.name) + nav_reference = " - examples/{}\n".format(md_file.name) + f.write(nav_reference) + + +def main(): + process_examples(EXAMPLE_DIR, DOCS_DIR) + + +if __name__ == '__main__': + main() diff --git a/docs/examples/application_states.md b/docs/examples/application_states.md new file mode 100644 index 000000000..592232650 --- /dev/null +++ b/docs/examples/application_states.md @@ -0,0 +1,75 @@ +--- +author: Adam Wichera +commit: 87d06294757f217f36a410543f9def11e64d3110 +date: 2020-02-05 16:53:57+01:00 +title: Application states + +--- + +!!! example + + ```python title=application_states.py linenums="1" + #!/usr/bin/env python3 + import asab + import asyncio + + + class StatesDemonstrationApplication(asab.Application): + + def __init__(self, args=None): + super().__init__(args) + asyncio.ensure_future(self.async_init_task()) + # asyncio.create_task(self.async_init_task()) + + print("*****\n1. Synchronous init takes place.") + print(" Async tasks are being added to the loop, but are never awaited") + + async def initialize(self): + self.PubSub.subscribe("Application.tick!", self.when_done) + asyncio.ensure_future(self.async_initialize_task()) + + print("*****\n3-5. Asynchronous initializatin takes place.") + print(" app.initialize is run concurrently") + print(" \"Application.init!\" is published") + await asyncio.sleep(1) + print("*****\n6-8. app.initialize awaited") + + async def async_init_task(self): + print("*****\n3-5. Scheduled async tasks are run concurrently") + await asyncio.sleep(2) + print("*****\n6-8. All scheduled async tasks awaited") + + async def async_initialize_task(self): + print("*****\n3-5. Even the ones scheuled in futures themselves.") + await asyncio.sleep(3) + print("*****\n6-8. Even the ones scheuled in futures themselves.") + + async def main(self): + asyncio.ensure_future(self.async_main_task()) + + print("*****\n7. Run time starts. app.main() is called") + print(" then async tasks are being handled, until the application is stopped.") + print(" \"Application.init!\" is published, application also starts ticking") + + + async def async_main_task(self): + print("*****\n8. Scheduled async tasks run concurrenlty") + await asyncio.sleep(10) + + async def when_done(self, event_type): + print("*****\n9. app.stop() is called by user code, or application is interupted in terminal") + print(" Asab waits 3 seconds to let all scheduled async tasks finish and then exits.") + print(" If some tasks are still pending throws warning.") + self.stop() + + async def finalize(self): + print("*****\n10. app.finilize is called, all modules and services are finalized. ") + + + + if __name__ == '__main__': + app = StatesDemonstrationApplication() + print("*****\n2. Now application waits for run method to be called") + app.run() + + ``` diff --git a/docs/examples/argparser.md b/docs/examples/argparser.md new file mode 100644 index 000000000..1dbd1acf2 --- /dev/null +++ b/docs/examples/argparser.md @@ -0,0 +1,68 @@ +--- +author: Jakub Boukal +commit: c9edd8964b82e5962b9d4eda0ad499ef8845ea83 +date: 2020-02-10 14:35:53+01:00 +title: Argparser + +--- + +!!! example + + ```python title=argparser.py linenums="1" + #!/usr/bin/env python3 + import asab + + + class Application(asab.Application): + + def __init__(self): + self.command = None + self.command_args = None + super().__init__() + + + def create_argument_parser(self, *args, **kwargs): + parser = super().create_argument_parser() + + subparsers = parser.add_subparsers(dest="command") + command1_subparser = subparsers.add_parser('command1') + command1_subparser.add_argument('-i', '--input-file') + + command2_subparser = subparsers.add_parser('command2') + command2_subparser.add_argument('-o', '--output-file') + + return parser + + + def parse_arguments(self, args=None): + args = super().parse_arguments() + self.command = args.command or "" + + if args.command == "command1": + self.command_args = { + "input_file": args.input_file or "" + } + + elif args.command == "command2": + self.command_args = { + "output_file": args.output_file or "" + } + + return args + + + async def main(self): + + if self.command == "": + exit("Please specify command (run with --help to see your options)") + + print("Command: {}; Args: {}".format(self.command, self.command_args)) + + self.stop() + + + if __name__ == '__main__': + app = Application() + app.run() + + ``` diff --git a/docs/examples/config_getseconds.md b/docs/examples/config_getseconds.md new file mode 100644 index 000000000..9b3ac2867 --- /dev/null +++ b/docs/examples/config_getseconds.md @@ -0,0 +1,57 @@ +--- +author: "P\u0159emysl \u010Cern\xFD" +commit: 2355687718e4be5936cbf48f92049f88eac12e5b +date: 2021-02-15 09:31:42+01:00 +title: Config getseconds + +--- + +!!! example + + ```python title=config_getseconds.py linenums="1" + #!/usr/bin/env python3 + import logging + import asyncio + + import asab + + # + + L = logging.getLogger(__name__) + + # + + asab.Config.add_defaults({ + "sleep": { + "for": "5.2s", + "joke": "10d", + } + }) + + + class MyApplication(asab.Application): + + def __init__(self): + super().__init__() + + # Two ways of obtaining seconds + self.SleepFor = asab.Config["sleep"].getseconds("for") + self.SleepJoke = asab.Config.getseconds("sleep", "joke") + + + async def main(self): + L.warning("Sleeping for '{}' seconds".format(self.SleepFor)) + + await asyncio.sleep(self.SleepFor) + + L.warning("Sleeping done. You really do not want to sleep for another '{}' seconds.".format(self.SleepJoke)) + + L.warning("Stopping the application.") + self.stop() + + + if __name__ == "__main__": + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/config_geturl.md b/docs/examples/config_geturl.md new file mode 100644 index 000000000..e311c0364 --- /dev/null +++ b/docs/examples/config_geturl.md @@ -0,0 +1,71 @@ +--- +author: "Anton\xEDn" +commit: abb1e5ad150a5f5be46f333bfeabd2b8a82cc971 +date: 2022-07-28 12:45:35+02:00 +title: Config geturl + +--- + +!!! example + + ```python title=config_geturl.py linenums="1" + #!/usr/bin/env python3 + import logging + + import asab + import asab.utils + + # + + L = logging.getLogger(__name__) + + # + + asab.Config.add_defaults({ + "urls": { + "teskalabs": "https://www.teskalabs.com/", # Has a trailing slash + "google": " https://www.google.com/ ", # Has leading and trailing whitespace and a trailing slash + "mongodb": "mongodb://LOCALHOST:27017/coolDB/", # Has a trailing slash + "github": "github.com", # Has no scheme + } + }) + + + class MyApplication(asab.Application): + + def __init__(self): + super().__init__() + + # Two ways of obtaining the URL + self.UrlsTeskalabs = asab.Config["urls"].geturl("teskalabs", scheme="https") + self.UrlsGoogle = asab.Config.geturl("urls", "google", scheme=None) + + self.UrlsMongo = asab.Config["urls"].geturl("mongodb", scheme="mongodb") + self.UrlsGithub = asab.Config.geturl("urls", "github", scheme=None) + + # You can also use a tuple in the scheme parameter + self.UrlsMongoTuple = asab.Config["urls"].geturl("mongodb", scheme=("https", "mongodb")) + self.UrlsTeskalabsTuple = asab.Config["urls"].geturl("teskalabs", scheme=("https", "mongodb")) + + + # This would throw a Error, because the URL in config has no scheme + # self.UrlsGithub = asab.Config.geturl("urls", "github", scheme="https") + + + async def main(self): + L.warning("Did you know the url for TeskaLabs is {}".format(self.UrlsTeskalabs)) + L.warning("Did you know the url for Google is {}".format(self.UrlsGoogle)) + L.warning("Checkout my MongoDB {} Oh wait you can't :(️".format(self.UrlsMongo)) + L.warning("Github: {}".format(self.UrlsGithub)) + L.warning("MongoDB using a tuple scheme: {}".format(self.UrlsMongoTuple)) + L.warning("TeskaLabs using a tuple scheme: {}".format(self.UrlsTeskalabsTuple)) + + L.warning("Stopping the application.") + self.stop() + + + if __name__ == "__main__": + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/executor.md b/docs/examples/executor.md new file mode 100644 index 000000000..67d3dc5cb --- /dev/null +++ b/docs/examples/executor.md @@ -0,0 +1,70 @@ +--- +author: Premysl Cerny +commit: fba5de43c4b5f0e95bd015ee52d4d255f7ce2228 +date: 2022-11-23 14:04:05+01:00 +title: Executor + +--- + +!!! example + + ```python title=executor.py linenums="1" + #!/usr/bin/env python3 + import concurrent.futures + import threading + import asyncio + import asab + + ''' + This example demonstrates the integration of ASAB event loop with ThreadPoolExecutor. + + It is useful to offload long-running or blocking tasks from the main event loop into a dedicated thread. + It provides the seamless integration with the async world so that the caller can await the result of the worker thread. + Thanks to ThreadPoolExecutor, the worker threads are pre-created and managed in the pool. + ''' + + + def task(n): + print("Executing our Task") + result = n + i = 0 + for i in range(10): + result = result + i + print("I: {}".format(result)) + print("Task Executed {}".format(threading.current_thread())) + return result + + + class MyApplication(asab.Application): + + asab.Config.add_defaults({ + 'asab': { + 'workers': 3 + } + }) + + def __init__(self): + super().__init__() + + self.Executor = concurrent.futures.ThreadPoolExecutor( + max_workers=asab.Config.getint('asab', 'workers') + ) + + + async def main(self): + tasks = [] + for i in range(100): + t = self.Loop.run_in_executor(self.Executor, task, i) + tasks.append(t) + + results = await asyncio.gather(*tasks) + print("Result:", sum(results)) + + self.stop() + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/hello_world.md b/docs/examples/hello_world.md new file mode 100644 index 000000000..b21999e35 --- /dev/null +++ b/docs/examples/hello_world.md @@ -0,0 +1,29 @@ +--- +author: awichera +commit: ac71f28056ae26c0163f246d9b2b174a15d983fa +date: 2020-08-12 11:58:12+02:00 +title: Hello world + +--- + +!!! example + + ```python title=hello_world.py linenums="1" + #!/usr/bin/env python3 + import logging + import asab + + L = logging.getLogger(__name__) + + + class MyApplication(asab.Application): + async def main(self): + L.warning("Hello world!") + self.stop() + + + if __name__ == "__main__": + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/json_schema.md b/docs/examples/json_schema.md new file mode 100644 index 000000000..3a13bc1ba --- /dev/null +++ b/docs/examples/json_schema.md @@ -0,0 +1,69 @@ +--- +author: Jakub Boukal +commit: 3244e16952cf9398e3cb02329bebea6f0c88b451 +date: 2019-12-10 12:34:35+01:00 +title: Json schema + +--- + +!!! example + + ```python title=json_schema.py linenums="1" + import aiohttp + import aiohttp.web + + import asab + import asab.web + import asab.web.rest + import asab.web.session + + + class MyApplication(asab.Application): + + async def initialize(self): + # Loading the web service module + self.add_module(asab.web.Module) + + # Locate web service + websvc = self.get_service("asab.WebService") + + # Create a dedicated web container + container = asab.web.WebContainer(websvc, 'example:web') + + # Enable exception to JSON exception middleware + container.WebApp.middlewares.append(asab.web.rest.JsonExceptionMiddleware) + + # Add routes + container.WebApp.router.add_post('/api/jsonfile', self.jsonfile) + print(""" + Test file schema example with curl: + $ curl http://localhost:8080/api/jsonfile -X POST -H "Content-Type: application/json" -d '{"key2":666}' + """) + + container.WebApp.router.add_post('/api/jsondict', self.jsondict) + print(""" + Test dict schema example with curl: + $ curl http://localhost:8080/api/jsondict -X POST -H "Content-Type: application/json" -d '{"key1":"sample text"}' + or as form + $ curl http://localhost:8080/api/jsondict -X POST -d "key1=sample%20text" + """) + + @asab.web.rest.json_schema_handler('./data/sample_json_schema.json') + async def jsonfile(self, request, *, json_data): + return aiohttp.web.Response(text='Valid data {}\n'.format(json_data)) + + @asab.web.rest.json_schema_handler({ + 'type': 'object', + 'properties': { + 'key1': {'type': 'string'}, + 'key2': {'type': 'number'}, + }}) + async def jsondict(self, request, *, json_data): + return aiohttp.web.Response(text='Valid data {}\n'.format(json_data)) + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/library-git-provider.md b/docs/examples/library-git-provider.md new file mode 100644 index 000000000..7ff16b917 --- /dev/null +++ b/docs/examples/library-git-provider.md @@ -0,0 +1,78 @@ +--- +author: mejroslav +commit: 815aa23bdd210217f437227e3bbd3d1c6780c454 +date: 2023-06-12 14:42:13+02:00 +title: Library git provider + +--- + +!!! example + + ```python title=library-git-provider.py linenums="1" + #!/usr/bin/env python3 + import asab + import asab.library + + + class MyApplication(asab.Application): + + def __init__(self): + super().__init__() + + # Specify the location of the library + # The branch can be optionally specified in the URL fragment (after '#') + # If the branch does not exist, KeyError is raised with the message: "reference 'refs/remotes/origin/...' not found" + asab.Config["library"]["providers"] = "git+https://github.com/TeskaLabs/asab.git" + + # NOTE: If cloning from GitLab, use Deploy Tokens and specify the provider in format: + # git+https://:@gitlab.com/john/awesome_project.git + + # The repository will be cloned to a temporary directory. You can optionally specify the path like this: + # asab.Config["library:git"]["repodir"] = "/tmp/asab.provider.git/awesome_project" + + self.LibraryService = asab.library.LibraryService(self, "LibraryService") + + # Specify the directory path. It must start and end with "/"! + self.Path = "/examples/data/" + + # Continue only if the library is ready + self.PubSub.subscribe("Library.ready!", self.on_library_ready) + + + async def on_library_ready(self, event_name, library): + + items = await self.LibraryService.list(self.Path, recursive=True) + + print("=" * 10) + print("# Testing Git provider with ASAB Library\n") + print("The repository is cloned to a temporary directory: {}\n".format(self.LibraryService.Libraries[0].RepoPath)) + + if self.LibraryService.Libraries[0].Branch is not None: + print("On branch: {}\n".format(self.LibraryService.Libraries[0].Branch)) + else: + print("On branch: master/main\n") + + if len(items) == 0: + print("There are no items in directory {}!".format(self.Path)) + else: + print("Items:") + + for item in items: + print("*", item.name) + if item.type == 'item': + itemio = await self.LibraryService.read(item.name) + if itemio is not None: + with itemio: + content = itemio.read() + print(" - content: {} bytes".format(len(content))) + else: + print(" - N/A") # Item is likely disabled + print("\n", "=" * 10, sep="") + self.stop() + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/library-subscribe.md b/docs/examples/library-subscribe.md new file mode 100644 index 000000000..c9853656e --- /dev/null +++ b/docs/examples/library-subscribe.md @@ -0,0 +1,56 @@ +--- +author: "Miroslav Bur\xFD\u0161ek" +commit: 0148e678ecf8f8fb81f6c0ef2b23deb2e306fdcb +date: 2023-06-13 14:56:00+02:00 +title: Library subscribe + +--- + +!!! example + + ```python title=library-subscribe.py linenums="1" + #!/usr/bin/env python3 + + import asab + import asab.library + import asab.zookeeper + + + class MyApplication(asab.Application): + + def __init__(self): + + super().__init__() + asab.Config["library"]["providers"] = "git+https://github.com/TeskaLabs/asab.git" + + self.LibraryService = asab.library.LibraryService( + self, + "LibraryService", + ) + + # Continue only if the library is ready + self.PubSub.subscribe("Library.ready!", self.on_library_ready) + self.PubSub.subscribe("Library.change!", self.on_library_change) + + # NOTE: Git Provider periodically pulls changes once per minute + + + async def on_library_ready(self, event_name, library=None): + items = await self.LibraryService.list("/", recursive=True) + print("# Library\n") + for item in items: + print(" *", item) + print("\n===") + + # Add subscription for changes in paths + await self.LibraryService.subscribe(["/asab"]) + + def on_library_change(self, msg, provider, path): + print("\N{rabbit} New changes in the library found by provider: '{}'".format(provider)) + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/library.md b/docs/examples/library.md new file mode 100644 index 000000000..70749c1de --- /dev/null +++ b/docs/examples/library.md @@ -0,0 +1,76 @@ +--- +author: mejroslav +commit: e371f8ceb39b8d768c3951d0af69677e886d0b3e +date: 2023-05-10 10:44:53+02:00 +title: Library + +--- + +!!! example + + ```python title=library.py linenums="1" + #!/usr/bin/env python3 + import os.path + + import asab + import asab.library + import asab.zookeeper + + asab.Config.add_defaults({ + "zookeeper": { + # "servers": "zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181", + "servers": "zookeeper-1:2181" + }, + + "library": { + "azure_cache": "true", + } + + }) + + + class MyApplication(asab.Application): + + def __init__(self): + super().__init__(modules=[asab.zookeeper.Module]) + + # Specify a locations of the default library + asab.Config["library"]["providers"] = '\n'.join([ + os.path.join(os.path.dirname(__file__), "library"), + # "zk:///library", + # "git+https://github.com/TeskaLabs/asab.git" + "azure+https://lmio.blob.core.windows.net/library" + ]) + + self.LibraryService = asab.library.LibraryService( + self, + "LibraryService", + ) + + # Continue only if the library is ready + # We need to wait till eg. Zookeeper is connected + self.PubSub.subscribe("Library.ready!", self.on_library_ready) + + + async def on_library_ready(self, event_name, library): + items = await self.LibraryService.list("", recursive=True) + print("# Library\n") + for item in items: + print(" *", item) + if item.type == 'item': + itemio = await self.LibraryService.read(item.name) + if itemio is not None: + with itemio: + content = itemio.read() + print(" - content: {} bytes".format(len(content))) + else: + print(" - N/A") # Item is likely disabled + print("\n===") + self.stop() + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/logging-file.md b/docs/examples/logging-file.md new file mode 100644 index 000000000..f7d265340 --- /dev/null +++ b/docs/examples/logging-file.md @@ -0,0 +1,38 @@ +--- +author: "P\u0159emysl \u010Cern\xFD" +commit: cbb41483295e35fa3ab1b0169a249a30b51f8270 +date: 2021-05-24 11:31:24+02:00 +title: Logging file + +--- + +!!! example + + ```python title=logging-file.py linenums="1" + #!/usr/bin/env python3 + import logging + import asab + + # + + L = logging.getLogger(__name__) + + # + + + class MyApplication(asab.Application): + """ + python3 logging-file.py -c ./data/logging-file.conf + """ + + async def main(self): + L.warning("Sample log WARNING!") + L.error("Sample log ERROR!") + self.stop() + + + if __name__ == "__main__": + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/metrics-web-requests.md b/docs/examples/metrics-web-requests.md new file mode 100644 index 000000000..b0ce6eea0 --- /dev/null +++ b/docs/examples/metrics-web-requests.md @@ -0,0 +1,116 @@ +--- +author: eliska +commit: 19baa8a7fc7bc1f62251098c03b19aecf5aef0ec +date: 2022-06-22 12:14:06+02:00 +title: Metrics web requests + +--- + +!!! example + + ```python title=metrics-web-requests.py linenums="1" + import logging + import time + + import asab + import asab.web + import asab.web.rest + + # + + L = logging.getLogger(__name__) + + # + + + class MyApplication(asab.Application): + """ + Use Prometheus to track and visualize ASAB metrics. + + Accepts requests on port 8089. + To see data in Prometheus, add these lines into scrape_configs section in your prometheus.yml config file: + scrape_configs: + - job_name: 'metrics_animal_example' + metrics_path: '/asab/v1/metrics' + scrape_interval: 10s + static_configs: + - targets: ['127.0.0.1:8089'] + + There is 60s lag in ASAB-Prometheus data transfer. + Call the unicorn and see what happens! + """ + + async def initialize(self): + asab.Config.read_string( + """ + [web] + listen=0.0.0.0 8089 + + [asab:metrics] + target=influxdb + + [asab:metrics:influxdb] + url=http://localhost:8086 + username=test + password=testtest + db=test + + """ + ) + # Loading the web service module + self.add_module(asab.web.Module) + # Locate web service + websvc = self.get_service("asab.WebService") + + # Create a dedicated web container + container = asab.web.WebContainer(websvc, "web") + + # Create ApiService to enable asab/v1/metrics endpoint + from asab.api import ApiService + + self.ApiService = ApiService(self) + self.ApiService.initialize_web(container) + + container.WebApp.middlewares.append(asab.web.rest.JsonExceptionMiddleware) + + # Add a route + container.WebApp.router.add_get("/racoon", self.get_racoon) + container.WebApp.router.add_get("/unicorn", self.get_unicorn) + container.WebApp.router.add_get("/jellyfish", self.get_jellyfish) + container.WebApp.router.add_put("/dolphin", self.get_dolphin) + + async def get_racoon(self, request): + message = "Hi, I am racoon." + return asab.web.rest.json_response(request=request, data={"message": message}) + + async def get_unicorn(self, request): + message = "Hi, I am unicorn." + return asab.web.rest.json_response( + request=request, data={"message": message}, status=401 + ) + + async def get_jellyfish(self, request): + raise RuntimeError() + + + @asab.web.rest.json_schema_handler( + { + "type": "object", + "properties": { + "name": {"type": "string"}, + "favourite_food": {"type": "string"}, + }, + "required": ["name", "favourite_food"] + } + ) + async def get_dolphin(self, request, *, json_data): + message = "Hi, I am dolphin {} and I like {}!".format(json_data.get("name"), json_data.get("favourite_food")) + time.sleep(0.05) + return asab.web.rest.json_response(request=request, data={"message": message}) + + + if __name__ == "__main__": + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/metrics.md b/docs/examples/metrics.md new file mode 100644 index 000000000..f072ca16e --- /dev/null +++ b/docs/examples/metrics.md @@ -0,0 +1,66 @@ +--- +author: eliska +commit: 3c9b1d9774c791af8f47a7a5b06bd427c081eab8 +date: 2022-06-27 12:27:14+02:00 +title: Metrics + +--- + +!!! example + + ```python title=metrics.py linenums="1" + #!/usr/bin/env python3 + import asab + import asab.web + import asab.metrics + import asab.api + + # Advertisement through ApiService requires two configuration sections - `web` and `zookeeper` + asab.Config.add_defaults( + { + "web": { + "listen": "0.0.0.0 8089", + }, + "asab:metrics": { + "target": "influxdb" + }, + "asab:metrics:influxdb": { + "url": "http://localhost:8086/", + "db": "test", + "username": "test", + "password": "testtest", + } + } + ) + + + class MyApplication(asab.Application): + + def __init__(self): + super().__init__(modules=[asab.web.Module, asab.metrics.Module]) + + metrics_service = self.get_service('asab.MetricsService') + self.MyCounter = metrics_service.create_counter("mycounter", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0}) + self.MyGauge = metrics_service.create_gauge("mygauge", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0}) + self.MyEPSCounter = metrics_service.create_eps_counter("myepscounter", tags={'foo': 'bar'}, init_values={'event.in': 0}) + + # The timer will trigger a message publishing at every second + self.PubSub.subscribe("Application.tick!", self.on_tick) + + # Initialize API service + self.ApiService = asab.api.ApiService(self) + self.ApiService.initialize_web() + + + async def on_tick(self, event_type): + print("Tick!") + self.MyCounter.add('v1', 1) + self.MyGauge.set('v1', 1) + self.MyEPSCounter.add('event.in', 1) + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/pdict.md b/docs/examples/pdict.md new file mode 100644 index 000000000..a241884f8 --- /dev/null +++ b/docs/examples/pdict.md @@ -0,0 +1,37 @@ +--- +author: Jakub Boukal +commit: b535454e6c89cf14ed8d21daeb4c45b6f8ec2945 +date: 2019-12-20 16:46:01+01:00 +title: Pdict + +--- + +!!! example + + ```python title=pdict.py linenums="1" + #!/usr/bin/env python3 + import os.path + import asab + + + class MyApplication(asab.Application): + + async def main(self): + var_dir = asab.Config['general']['var_dir'] + pdict = asab.PersistentDict(os.path.join(var_dir, 'pdict.bin')) + + # Explicit load + pdict.load() + counter = pdict['counter'] = pdict.setdefault('counter', 0) + 1 + print("Executed for {} times".format(counter)) + + # Explicit store + pdict.store() + self.stop() + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/pubsub.md b/docs/examples/pubsub.md new file mode 100644 index 000000000..d4e310657 --- /dev/null +++ b/docs/examples/pubsub.md @@ -0,0 +1,49 @@ +--- +author: Jakub Boukal +commit: 4db78e814d48f1911e1ce8df476f25be725764f0 +date: 2019-12-10 17:55:51+01:00 +title: Pubsub + +--- + +!!! example + + ```python title=pubsub.py linenums="1" + #!/usr/bin/env python3 + import asab + + + class MyApplication(asab.Application): + + async def initialize(self): + self.PubSub.subscribe("Application.tick!", self.on_tick) + self.d = DisapearingSubscriber() + self.d_cnt = 3 + self.PubSub.subscribe("Application.tick!", self.d.on_non_ref) + self.PubSub.subscribe("Application.tick!", FunctionalSubscriber) + + + def on_tick(self, message_name): + print(message_name) + self.d_cnt -= 1 + if self.d_cnt == 0: + self.d = None + + + + class DisapearingSubscriber(object): + + async def on_non_ref(self, message_name): + print("DisapearingSubscriber: ", message_name) + + + def FunctionalSubscriber(message_name): + print("FunctionalSubscriber: ", message_name) + + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/service-discovery.md b/docs/examples/service-discovery.md new file mode 100644 index 000000000..0650d98ca --- /dev/null +++ b/docs/examples/service-discovery.md @@ -0,0 +1,96 @@ +--- +author: eliska-n +commit: 856001dcd37f84e89c09832429eefeaaa9a1e1fe +date: 2023-05-29 17:19:46+02:00 +title: Service discovery + +--- + +!!! example + + ```python title=service-discovery.py linenums="1" + import logging + import aiohttp + import aiohttp.web + + import asab + import asab.web + import asab.api + import asab.api.discovery + import asab.zookeeper + + import os + + # `instance_id`` and `service_id` are identificators set as environemnt variables. + # ASAB miroservices are meant to run in separate (Docker) containers. + os.environ["INSTANCE_ID"] = "my_application_1" + + # + + L = logging.getLogger(__name__) + + # + + asab.Config.add_defaults( + { + "web": { + "listen": "0.0.0.0 8089", + }, + + "zookeeper": { + "path": "example", + "servers": "localhost:2181" + }, + } + ) + + + class MyApplication(asab.Application): + + async def initialize(self): + # Initialize web server + self.add_module(asab.web.Module) + websvc = self.get_service("asab.WebService") + self.WebContainer = asab.web.WebContainer(websvc, "web") + + # Initialize zookeeper + self.add_module(asab.zookeeper.Module) + self.ZooKeeperService = self.get_service("asab.ZooKeeperService") + self.ZooKeeperContainer = asab.zookeeper.ZooKeeperContainer(self.ZooKeeperService, "zookeeper") + + # The DiscoverySession is functional only with ApiService initialized. + self.ASABApiService = asab.api.ApiService(self) + self.ASABApiService.initialize_web(self.WebContainer) + self.ASABApiService.initialize_zookeeper(self.ZooKeeperContainer) + + self.DiscoveryService = self.get_service("asab.DiscoveryService") + + self.WebContainer.WebApp.router.add_get('/locate', self.locate_self) + + async def locate_self(self, request): + # This method seeks for this application in the ZooKeeper. Thus, it calls itself, being a tiny Oroboros. + # Try to run more than one ASAB Application with the same ZooKeeper configuration. + # You will get a tool to locate any service in the "cluster". + + # Get config of the application: + config = None + async with self.DiscoveryService.session() as session: + try: + # use URL in format: ://..asab/ where key is "service_id" or "instance_id" and value the respective serivce identificator + async with session.get("http://my_application_1.instance_id.asab/asab/v1/config") as resp: + if resp.status == 200: + config = await resp.json() + except asab.api.discovery.NotDiscoveredError as e: + L.error(e) + + if config is None: + return aiohttp.web.json_response({"result": "FAILED"}) + + return aiohttp.web.json_response(config) + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/storage_elasticsearch.md b/docs/examples/storage_elasticsearch.md new file mode 100644 index 000000000..9e2c3551c --- /dev/null +++ b/docs/examples/storage_elasticsearch.md @@ -0,0 +1,91 @@ +--- +author: mejroslav +commit: 04a232b899de3bbe8c634361f5547865dea1a4c7 +date: 2023-03-20 17:49:20+01:00 +title: Storage elasticsearch + +--- + +!!! example + + ```python title=storage_elasticsearch.py linenums="1" + import pprint + + import asab + import asab.storage + + + asab.Config.add_defaults( + { + 'asab:storage': { + 'type': 'elasticsearch', + 'elasticsearch_url': 'http://localhost:9200/', + } + } + ) + + + class MyApplication(asab.Application): + + async def initialize(self): + + # Loading the web service module + self.add_module(asab.storage.Module) + + + async def main(self): + storage = self.get_service("asab.StorageService") + + # Obtain upsertor object which is associated with given "test-collection" + # To create new object we keep default `version` to zero + print("Creating default id and version") + u = storage.upsertor("test-collection") + u.set("bar", {"data": "test"}) + objid = await u.execute() + + obj = await storage.get("test-collection", objid) + print("Result of get by id '{}'".format(objid)) + pprint.pprint(obj) + + obj = await storage.get("test-collection", objid) + # Obtain upsertor object for update - specify existing `version` number + print("Specify version when updating") + u = storage.upsertor("test-collection", obj_id=objid, version=obj['_v']) + u.set("foo", "buzz") + objid = await u.execute() + + obj = await storage.get("test-collection", objid) + print("Result of get by id '{}'".format(objid)) + pprint.pprint(obj) + + # Reindex the collection + await storage.reindex("test-collection", "test-collection-reindex") + await storage.reindex("test-collection-reindex", "test-collection") + + # Remove the reindexed collection + await storage.delete("test-collection-reindex") + + # Delete the item + await storage.delete("test-collection", objid) + + + # Insert the document with provided ObjId + print("Insert the document with provided ObjId") + u = storage.upsertor("test-collection", "test") + u.set("foo", "bar") + objid = await u.execute() + + obj = await storage.get("test-collection", objid) + print("Result of get by id '{}'".format(objid)) + pprint.pprint(obj) + print("Delete the document with provided ObjId") + await storage.delete("test-collection", objid) + + self.stop() + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/storage_inmemory.md b/docs/examples/storage_inmemory.md new file mode 100644 index 000000000..2e6cf2974 --- /dev/null +++ b/docs/examples/storage_inmemory.md @@ -0,0 +1,62 @@ +--- +author: mejroslav +commit: 04a232b899de3bbe8c634361f5547865dea1a4c7 +date: 2023-03-20 17:49:20+01:00 +title: Storage inmemory + +--- + +!!! example + + ```python title=storage_inmemory.py linenums="1" + import pprint + + import asab + import asab.storage + + + asab.Config.add_defaults( + { + 'asab:storage': { + 'type': 'inmemory', + } + } + ) + + + class MyApplication(asab.Application): + + async def initialize(self): + # Loading the web service module + self.add_module(asab.storage.Module) + + + async def main(self): + storage = self.get_service("asab.StorageService") + + # Obtain upsertor object which is associated with given "test-collection" + # To create new object we keep default `version` to zero + u = storage.upsertor("test-collection") + u.set("foo", "bar") + objid = await u.execute() + + obj = await storage.get("test-collection", objid) + # Obtain upsertor object for update - specify existing `version` number + u = storage.upsertor("test-collection", obj_id=objid, version=obj['_v']) + u.set("foo", "buzz") + objid = await u.execute() + + obj = await storage.get("test-collection", objid) + print(f"Result of get by id: {objid}") + pprint.pprint(obj) + + await storage.delete("test-collection", objid) + + self.stop() + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/storage_mongodb.md b/docs/examples/storage_mongodb.md new file mode 100644 index 000000000..cde02ad7f --- /dev/null +++ b/docs/examples/storage_mongodb.md @@ -0,0 +1,89 @@ +--- +author: mejroslav +commit: 712444ba07d0be0d15c5c83bbd2aee9855fc0c9b +date: 2023-03-23 19:55:26+01:00 +title: Storage mongodb + +--- + +!!! example + + ```python title=storage_mongodb.py linenums="1" + import pprint + import os + import asab + import asab.storage + + + asab.Config.add_defaults( + { + 'asab:storage': { + 'type': 'mongodb', + 'aes_key': os.urandom(24) + } + } + ) + + + class MyApplication(asab.Application): + + async def initialize(self): + + # Loading the web service module + self.add_module(asab.storage.Module) + + + async def main(self): + storage = self.get_service("asab.StorageService") + # Obtain upsertor object which is associated with given "test-collection" + # To create new object we keep default `version` to zero + u = storage.upsertor("test-collection") + u.set("foo", "bar") + object_id = await u.execute() + + # Get the object by its id + obj = await storage.get("test-collection", object_id) + + # Obtain upsertor object for update - specify existing `version` number + u = storage.upsertor("test-collection", obj_id=object_id, version=obj['_v']) + u.set("foo", "buzz") + object_id = await u.execute() + + # See the results + obj = await storage.get("test-collection", object_id) + print(f"Result of get by id: {object_id}") + pprint.pprint(obj) + + # Encrypt some data + u = storage.upsertor("test-collection", obj_id=object_id, version=obj['_v']) + secret_message = "This is a super secret message!" + # Convert the message to binary format before encrypting + u.set("super_secret", secret_message.encode("ascii"), encrypt=True) + object_id = await u.execute() + + # See the encrypted data + obj = await storage.get("test-collection", object_id) + print("Encrypted data: {}".format(obj.get("super_secret"))) + + # See the decrypted data + obj = await storage.get("test-collection", object_id, decrypt=["super_secret"]) + print("Decrypted data: {}".format(obj.get("super_secret"))) + + # Test the StorageService.collection() method + coll = await storage.collection("test-collection") + cursor = coll.find({}) + print("Result of list") + while await cursor.fetch_next: + obj = cursor.next_object() + pprint.pprint(obj) + + await storage.delete("test-collection", object_id) + + self.stop() + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/task.md b/docs/examples/task.md new file mode 100644 index 000000000..5eb16a758 --- /dev/null +++ b/docs/examples/task.md @@ -0,0 +1,44 @@ +--- +author: eliska +commit: d83dcedb619098678100883d1faa15ad2b08e878 +date: 2022-02-09 10:16:42+01:00 +title: Task + +--- + +!!! example + + ```python title=task.py linenums="1" + #!/usr/bin/env python3 + import asab + + + class MyApplication(asab.Application): + + async def main(self): + task_service = app.get_service("asab.TaskService") + + # Schedule tasks to be executed + # They will be executed in ~ 5 seconds + task_service.schedule( + self.task1(), + self.task2(), + self.task3(), + ) + + + async def task1(self): + print("Task1") + + async def task2(self): + print("Task2") + + async def task3(self): + print("Task3") + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/timer.md b/docs/examples/timer.md new file mode 100644 index 000000000..fa09394e8 --- /dev/null +++ b/docs/examples/timer.md @@ -0,0 +1,33 @@ +--- +author: Jakub Boukal +commit: 4db78e814d48f1911e1ce8df476f25be725764f0 +date: 2019-12-10 17:55:51+01:00 +title: Timer + +--- + +!!! example + + ```python title=timer.py linenums="1" + #!/usr/bin/env python3 + import asab + + + class TimerApplication(asab.Application): + + + async def initialize(self): + # The timer will trigger a message publishing at every second + self.Timer = asab.Timer(self, self.on_tick, autorestart=True) + self.Timer.start(1) + + + async def on_tick(self): + print("Think!") + + + if __name__ == '__main__': + app = TimerApplication() + app.run() + + ``` diff --git a/docs/examples/web-auth.md b/docs/examples/web-auth.md new file mode 100644 index 000000000..d94598780 --- /dev/null +++ b/docs/examples/web-auth.md @@ -0,0 +1,239 @@ +--- +author: robin.hruska@teskalabs.com +commit: 1e4b1e42a8ad586fe46396e92371307466ad8d37 +date: 2023-06-21 14:40:45+02:00 +title: Web auth + +--- + +!!! example + + ```python title=web-auth.py linenums="1" + #!/usr/bin/env python3 + import asab.web.rest + import asab.web.auth + import typing + + # Set up a web container listening at port 8080 + asab.Config["web"] = {"listen": "0.0.0.0 8089"} + + # Changes the behavior of endpoints with configurable tenant parameter. + # With multitenancy enabled, the tenant paramerter in query is required. + # With multitenancy disabled, the tenant paramerter in query is ignored. + asab.Config["auth"]["multitenancy"] = "yes" + + # Activating the dev mode disables communication with the authorization server. + # The requests' Authorization headers are ignored and AuthService provides mock authorization with mock user info. + # You can provide custom user info by specifying `dev_user_info_path` pointing to your JSON file. + asab.Config["auth"]["dev_mode"] = "yes" + asab.Config["auth"]["dev_user_info_path"] = "./dev-userinfo.json" + + # URL of the authorization server's JWK public keys, used for ID token verification. + # This option is ignored in dev mode. + asab.Config["auth"]["public_keys_url"] = "http://localhost:8081/openidconnect/public_keys" + + # URL of the authorization server's tenant list, used for tenant verification. + # This option is ignored in dev mode. + asab.Config["auth"]["tenant_url"] = "http://localhost:8081/tenant" + + + class MyApplication(asab.Application): + + def __init__(self): + super().__init__() + + # Initialize web container + self.add_module(asab.web.Module) + self.WebService = self.get_service("asab.WebService") + self.WebContainer = asab.web.WebContainer(self.WebService, "web") + + self.WebContainer.WebApp.middlewares.append(asab.web.rest.JsonExceptionMiddleware) + + from asab.api import ApiService + self.ApiService = ApiService(self) + self.ApiService.initialize_web(self.WebContainer) + + # Initialize authorization + self.AuthService = asab.web.auth.AuthService(self) + self.AuthService.install(self.WebContainer) + + # Add routes + self.WebContainer.WebApp.router.add_get("/no_auth", self.no_auth) + self.WebContainer.WebApp.router.add_get("/auth", self.auth) + self.WebContainer.WebApp.router.add_get("/auth/resource_check", self.auth_resource) + self.WebContainer.WebApp.router.add_put("/auth/resource_check", self.auth_resource_put) + self.WebContainer.WebApp.router.add_get("/{tenant}/required_tenant", self.tenant_in_path) + self.WebContainer.WebApp.router.add_get("/{tenant}/required_tenant/resource_check", self.tenant_in_path_resources) + self.WebContainer.WebApp.router.add_get("/configurable_tenant", self.tenant_in_query) + self.WebContainer.WebApp.router.add_get("/configurable_tenant/resource_check", self.tenant_in_query_resources) + + + @asab.web.auth.noauth + async def no_auth(self, request): + """ + NO AUTH + - authentication skipped + + - `tenant`, `user_info`, `resources` params not allowed + """ + data = { + "tenant": "NOT AVAILABLE", + "resources": "NOT AVAILABLE", + "user_info": "NOT AVAILABLE", + } + return asab.web.rest.json_response(request, data) + + + async def auth(self, request, *, user_info: dict, resources: frozenset): + """ + TENANT-AGNOSTIC + - returns 401 if authentication not successful + + - `user_info`, `resources` params allowed + - `tenant` param not allowed + - `resources` contain only globally granted resources + """ + data = { + "tenant": "NOT AVAILABLE", + "resources": list(resources), + "user_info": user_info, + } + return asab.web.rest.json_response(request, data) + + + @asab.web.auth.require("something:access", "something:edit") + async def auth_resource(self, request, *, user_info: dict, resources: frozenset): + """ + TENANT-AGNOSTIC + RESOURCE CHECK + - returns 401 if authentication not successful + - globally granted resources checked + - returns 403 if resource access not granted + + - `user_info`, `resources` params allowed + - `tenant` param not allowed + - `resources` contain only globally granted resources + """ + data = { + "tenant": "NOT AVAILABLE", + "resources": list(resources), + "user_info": user_info, + } + return asab.web.rest.json_response(request, data) + + + @asab.web.rest.json_schema_handler({ + "type": "object" + }) + @asab.web.auth.require("something:access", "something:edit") + async def auth_resource_put(self, request, *, user_info: dict, resources: frozenset, json_data: dict): + """ + Decorator asab.web.auth.require can be used together with other decorators. + """ + data = { + "tenant": "NOT AVAILABLE", + "resources": list(resources), + "user_info": user_info, + "json_data": json_data, + } + return asab.web.rest.json_response(request, data) + + + async def tenant_in_path(self, request, *, tenant: str, user_info: dict, resources: frozenset): + """ + TENANT-AWARE + - returns 401 if authentication not successful + - `tenant` access checked + - returns 403 if tenant not accessible + + - `user_info`, `resources` params allowed + - `tenant` param required in path, cannot be None + - `resources` contain tenant-granted resources + """ + data = { + "tenant": tenant, + "resources": list(resources), + "user_info": user_info, + } + return asab.web.rest.json_response(request, data) + + + async def tenant_in_query(self, request, *, tenant: typing.Union[str|None], user_info: dict, resources: frozenset): + """ + CONFIGURABLY TENANT-AWARE + - returns 401 if authentication not successful + - if multitenancy is enabled + - `tenant` required in query string + - tenant access checked + - returns 400 if `tenant` not in query + - returns 403 if tenant not accessible + - if multitenancy is disabled + - `tenant` is set to `None` + + - `user_info`, `resources` params allowed + - `tenant` param required in query only if multitenancy is enabled + - `resources` contain tenant-granted resources if multitenancy is enabled, + otherwise only globally-granted resources + """ + data = { + "tenant": tenant, + "resources": list(resources), + "user_info": user_info, + } + return asab.web.rest.json_response(request, data) + + + @asab.web.auth.require("something:access", "something:edit") + async def tenant_in_path_resources(self, request, *, tenant: typing.Union[str|None], user_info: dict, resources: frozenset): + """ + TENANT-AWARE + RESOURCE CHECK + - returns 401 if authentication not successful + - `tenant` access checked + - returns 403 if tenant not accessible + - tenant-accessible resources checked + - returns 403 if resource access not granted + + - `user_info`, `resources` params allowed + - `tenant` param required, cannot be None + - `resources` contain only resources granted within tenant + """ + data = { + "tenant": tenant, + "resources": list(resources), + "user_info": user_info, + } + return asab.web.rest.json_response(request, data) + + + @asab.web.auth.require("something:access", "something:edit") + async def tenant_in_query_resources(self, request, *, tenant: typing.Union[str|None], user_info: dict, resources: frozenset): + """ + CONFIGURABLY TENANT-AWARE + RESOURCE CHECK + - returns 401 if authentication not successful + - if multitenancy is enabled + - `tenant` required in query string + - tenant access checked + - returns 400 if `tenant` not in query + - returns 403 if tenant not accessible + - returns 403 if resource access not granted within tenant + - if multitenancy is disabled + - `tenant` is set to `None` + - returns 403 if resources not granted globally + + - `user_info`, `resources` params allowed + - `tenant` param required only if multitenancy is enabled + - `resources` contain tenant-granted resources if multitenancy is enabled, + otherwise only globally-granted resources + """ + data = { + "tenant": tenant, + "resources": list(resources), + "user_info": user_info, + } + return asab.web.rest.json_response(request, data) + + + if __name__ == "__main__": + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/web-authz-rbac.md b/docs/examples/web-authz-rbac.md new file mode 100644 index 000000000..08a9aef75 --- /dev/null +++ b/docs/examples/web-authz-rbac.md @@ -0,0 +1,71 @@ +--- +author: "P\u0159emysl \u010Cern\xFD" +commit: 2af375c787237402e889bb5cb7140e85445711e0 +date: 2021-04-14 14:56:38+02:00 +title: Web authz rbac + +--- + +!!! example + + ```python title=web-authz-rbac.py linenums="1" + import logging + + import asab + import asab.web + import asab.web.authz + import asab.web.rest + import asab.web.tenant + + # + + L = logging.getLogger(__name__) + + # + + + class MyRBACSecuredApplication(asab.Application): + """ + MyRBACSecuredApplication serves endpoints, which are checked for tenant authorization rights using SeaCat Auth RBAC. + + Test by: + + 1.) Run SeaCat Auth at: http://localhost:8081 + 2.) Perform OAuth authentication to obtain access token + 3.) Run: curl -H "Authorization: " http://localhost:8089/cars + """ + + async def initialize(self): + # Loading the web service module + self.add_module(asab.web.Module) + + # Locate web service + websvc = self.get_service("asab.WebService") + + # Create a dedicated web container + container = asab.web.WebContainer(websvc, 'example:rbac', config={"listen": "0.0.0.0 8089"}) + + # Add authz service + # It is required by asab.web.authz.required decorator + authz_service = asab.web.authz.AuthzService(self) + container.WebApp.middlewares.append( + asab.web.authz.authz_middleware_factory(self, authz_service) + ) + + # Enable exception to JSON exception middleware + container.WebApp.middlewares.append(asab.web.rest.JsonExceptionMiddleware) + + # Add a route + container.WebApp.router.add_get('/cars', self.get_cars) + + @asab.web.authz.required("car:list") + async def get_cars(self, request): + cars = ["Skoda", "Volvo", "Kia"] + return asab.web.rest.json_response(request=request, data=cars) + + + if __name__ == '__main__': + app = MyRBACSecuredApplication() + app.run() + + ``` diff --git a/docs/examples/web-authz-userinfo.md b/docs/examples/web-authz-userinfo.md new file mode 100644 index 000000000..a2491d702 --- /dev/null +++ b/docs/examples/web-authz-userinfo.md @@ -0,0 +1,104 @@ +--- +author: robin.hruska@teskalabs.com +commit: eae5fe4fbef9254e11e87165e1d34d2bc1db2809 +date: 2023-02-15 18:58:47+01:00 +title: Web authz userinfo + +--- + +!!! example + + ```python title=web-authz-userinfo.py linenums="1" + import logging + + import asab + import asab.web + import asab.web.authz + import asab.web.rest + import asab.web.tenant + + # + + L = logging.getLogger(__name__) + + # + + + class MyApplication(asab.Application): + """ + MyApplication serves endpoints which use user info obtained from ID tokens issued by the authorization server. + + Test by: + 1) Run NGINX server with Seacat Auth (at localhost:8081) + 2) Run this example app with config file: + ```sh + python3 examples/web-authz-userinfo.py -c examples/web-authz-userinfo.conf + ``` + 1) In Seacat Admin UI, register a public web client for this app, with client_id="example-app" + 3) Set up a NGINX location with intropection for this example app: + ```nginx + location /example { + rewrite ^/example/(.*)? /$1 break; + proxy_pass http://localhost:8089; + + auth_request /_example_cookie_introspect; + error_page 401 /auth/api/openidconnect/authorize?response_type=code&scope=openid%20cookie%20profile&client_id=example-app&redirect_uri=$request_uri; + + auth_request_set $authorization $upstream_http_authorization; + proxy_set_header Authorization $authorization; + + auth_request_set $cookie $upstream_http_cookie; + proxy_set_header Cookie $cookie; + + auth_request_set $set_cookie $upstream_http_set_cookie; + add_header Set-Cookie $set_cookie; + } + + location = /_example_cookie_introspect { + internal; + proxy_method POST; + proxy_set_body "$http_authorization"; + proxy_pass http://auth_api/cookie/nginx?client_id=example-app; + proxy_ignore_headers Cache-Control Expires Set-Cookie; + } + ``` + 4) Access "https://YOUR_DOMAIN/example/user" in your browser + """ + + async def initialize(self): + # Loading the web service module + self.add_module(asab.web.Module) + + # Locate web service + websvc = self.get_service("asab.WebService") + + # Create a dedicated web container + container = asab.web.WebContainer(websvc, "web") + + # Add authz service + # It is required by asab.web.authz.required decorator + authz_service = asab.web.authz.AuthzService(self) + container.WebApp.middlewares.append( + asab.web.authz.authz_middleware_factory(self, authz_service) + ) + + # Enable exception to JSON exception middleware + container.WebApp.middlewares.append(asab.web.rest.JsonExceptionMiddleware) + + # Add a route + container.WebApp.router.add_get('/user', self.get_userinfo) + + @asab.web.authz.userinfo_handler + async def get_userinfo(self, request, *, userinfo): + message = "Hi {}, your email is {}".format( + userinfo.get("preferred_username"), + userinfo.get("email") + ) + return asab.web.rest.json_response(request=request, data={"message": message}) + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/webserver.md b/docs/examples/webserver.md new file mode 100644 index 000000000..1d9c4f2ea --- /dev/null +++ b/docs/examples/webserver.md @@ -0,0 +1,45 @@ +--- +author: Ales Teska +commit: e5b55d992b90aed61e45975ac354e4b2a85223a9 +date: 2023-02-14 20:53:53+01:00 +title: Webserver + +--- + +!!! example + + ```python title=webserver.py linenums="1" + #!/usr/bin/env python3 + import asab.web.rest + + + class MyApplication(asab.Application): + ''' + Run by: + `$ PYTHONPATH=.. ./webserver.py` + + The application is available at http://localhost:8080/hello + ''' + + def __init__(self): + super().__init__() + + # Create the Web server + web = asab.web.create_web_server(self) + + # Add a route to the handler method + web.add_get('/hello', self.hello) + + print("Test with curl:\n\t$ curl http://localhost:8080/hello") + + + # This is the web request handler + async def hello(self, request): + return asab.web.rest.json_response(request, data="Hello, world!\n") + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/websocket-chat.md b/docs/examples/websocket-chat.md new file mode 100644 index 000000000..89f707b8a --- /dev/null +++ b/docs/examples/websocket-chat.md @@ -0,0 +1,52 @@ +--- +author: Ales Teska +commit: a074b8dbd1a1e284fd96261215a04427c5f308d6 +date: 2022-08-25 23:02:16+02:00 +title: Websocket chat + +--- + +!!! example + + ```python title=websocket-chat.py linenums="1" + import os + + import aiohttp + + import asab + import asab.web + + + class MyApplication(asab.Application): + """ + Run a simple multi-user chat on http://localhost:8080/ + """ + + def __init__(self): + super().__init__() + + # Initialize WebService + self.add_module(asab.web.Module) + self.WebService = self.get_service("asab.WebService") + self.WebContainer = asab.web.WebContainer(self.WebService, "web") + + self.WebContainer.WebApp.router.add_get('/', self.index) + + self.WebSocketFactory = asab.web.WebSocketFactory(self) + self.WebContainer.WebApp.router.add_get('/ws', self.WebSocketFactory) + self.WebSocketFactory.on_message = self.on_message + + async def index(self, request): + data = open(os.path.join(os.path.dirname(__file__), "websocket-chat.html"), 'r').read() + return aiohttp.web.Response(text=data, content_type="text/html") + + async def on_message(self, websocket, message, wsid): + if message.type == aiohttp.WSMsgType.TEXT: + await self.WebSocketFactory.send_str_all(message.data) + + + if __name__ == "__main__": + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/zookeeper-advertise.md b/docs/examples/zookeeper-advertise.md new file mode 100644 index 000000000..2f8e3d62f --- /dev/null +++ b/docs/examples/zookeeper-advertise.md @@ -0,0 +1,54 @@ +--- +author: Ales Teska +commit: 0de7db994b4725059a738cc40683df32c6f3352f +date: 2022-06-13 20:17:49+02:00 +title: Zookeeper advertise + +--- + +!!! example + + ```python title=zookeeper-advertise.py linenums="1" + import asab + import asab.api + import asab.zookeeper + + + # Advertisement through ApiService requires two configuration sections - `web` and `zookeeper` + asab.Config.add_defaults( + { + "web": { + "listen": "0.0.0.0 8088", + }, + "zookeeper": { + # specify "servers": "..." here to provide addresses of Zookeeper servers + "path": "asab" + }, + } + ) + + + class MyApplication(asab.Application): + + def __init__(self): + super().__init__(modules=[asab.web.Module, asab.zookeeper.Module]) + + # Locate a Web Service + self.WebService = self.get_service("asab.WebService") + + # Locate a ZooKeeper Service + self.ZooKeeperService = self.get_service("asab.ZooKeeperService") + + # Initialize API service + self.ApiService = asab.api.ApiService(self) + + # Introduce Web and ZooKeeper to API Service + self.ApiService.initialize_web() + self.ApiService.initialize_zookeeper() + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/docs/examples/zookeeper.md b/docs/examples/zookeeper.md new file mode 100644 index 000000000..742353f1b --- /dev/null +++ b/docs/examples/zookeeper.md @@ -0,0 +1,59 @@ +--- +author: Ales Teska +commit: 96255ea5fe472f3485a894512a0e74ba20032698 +date: 2022-06-10 15:24:33+02:00 +title: Zookeeper + +--- + +!!! example + + ```python title=zookeeper.py linenums="1" + #!/usr/bin/env python3 + import asab + import asab.zookeeper + + # Specify a default configuration + asab.Config.add_defaults( + { + "my:zk": { + # specify "servers": "..." here to provide addresses of Zookeeper servers + "path": "asab" + }, + } + ) + + + class MyApplication(asab.Application): + + + def __init__(self): + super().__init__() + + # Loading the ASAB Zookeeper module + self.add_module(asab.zookeeper.Module) + + # Locate the Zookeeper service + zksvc = self.get_service("asab.ZooKeeperService") + + # Create the Zookeeper container + self.ZkContainer = asab.zookeeper.ZooKeeperContainer(zksvc, 'my:zk') + + # Subscribe to the event that indicated the successful connection to the Zookeeper server(s) + self.PubSub.subscribe("ZooKeeperContainer.started!", self._on_zk_ready) + + + async def _on_zk_ready(self, event_name, zkcontainer): + # If there is more than one ZooKeeper Container being initialized, this method is called at every Container initialization. + # Then you need to check whether the specific ZK Container has been initialized. + if zkcontainer == self.ZkContainer: + path = self.ZkContainer.ZooKeeperPath + "/hello" + await self.ZkContainer.ZooKeeper.ensure_path(path) + print("The path in Zookeeper has been created.") + + + if __name__ == '__main__': + app = MyApplication() + app.run() + + ``` diff --git a/mkdocs.yml b/mkdocs.yml index 7fe443008..31160e6b2 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -165,3 +165,32 @@ nav: # Examples are rendered automatically with create_examples.py script - Examples: + + - examples/hello_world.md + - examples/config_geturl.md + - examples/storage_mongodb.md + - examples/websocket-chat.md + - examples/metrics-web-requests.md + - examples/argparser.md + - examples/task.md + - examples/json_schema.md + - examples/config_getseconds.md + - examples/library-subscribe.md + - examples/storage_inmemory.md + - examples/webserver.md + - examples/zookeeper.md + - examples/application_states.md + - examples/library.md + - examples/service-discovery.md + - examples/executor.md + - examples/metrics.md + - examples/timer.md + - examples/pubsub.md + - examples/zookeeper-advertise.md + - examples/storage_elasticsearch.md + - examples/logging-file.md + - examples/web-authz-rbac.md + - examples/pdict.md + - examples/library-git-provider.md + - examples/web-authz-userinfo.md + - examples/web-auth.md From ffbc78adbf0e4212566a789588cb90ef6892d003 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 11 Jul 2023 12:28:14 +0200 Subject: [PATCH 026/154] Create admonitions from headers --- docs/index.md | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/docs/index.md b/docs/index.md index fd07e9142..c3adf40a5 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,42 +11,40 @@ ASAB-based microservice via Docker or Kubernetes in a breeze. Anyone can (and is encouraged to) use ASAB in his or her projects, for free. A current maintainer is a [TeskaLabs Ltd](https://teskalabs.com) company. -!!! info "" +!!! success "ASAB is the right choice when:" - - :simple-opensourceinitiative: ASAB is free and open-source software, available under BSD licence. - Anyone is freely licensed to use, copy, study, and change the - software in any way, and the source code is openly shared so that people - could voluntarily improve the design of the software. + - :material-server: you want to build a microservice or an application server + - :material-language-python: you are using Python 3.7+ + - :material-clock-fast: you want to utilize asynchronous I/O + - :material-file-document-edit: you want to write non-blocking, speedy and scalable code - - :simple-github: ASAB is developed [on GitHub](https://github.com/TeskaLabs/asab/). - Contributions are most welcome! If you want to help us improve asab, check our [contribution rules](./contributing.md). +!!! example "Here is a complete example of a fully working microservice:" -## ASAB is designed to be powerful yet simple + ``` python title="hello_world.py" + import asab -Here is a complete example of a fully working microservice: + class MyApplication(asab.Application): + async def main(self): + print("Hello world!") + self.stop() -``` python title="hello_world.py" -import asab + if __name__ == "__main__": + app = MyApplication() + app.run() + ``` -class MyApplication(asab.Application): - async def main(self): - print("Hello world!") - self.stop() -if __name__ == "__main__": - app = MyApplication() - app.run() -``` +!!! info "Development" -## ASAB is the right choice when + - :simple-opensourceinitiative: ASAB is free and open-source software, available under BSD licence. + Anyone is freely licensed to use, copy, study, and change the + software in any way, and the source code is openly shared so that people + could voluntarily improve the design of the software. -
+ - :simple-github: ASAB is developed [on GitHub](https://github.com/TeskaLabs/asab/). + Contributions are most welcome! If you want to help us improve asab, check our [contribution rules](./contributing.md). -- :material-language-python: using Python 3.7+ -- :material-server: building the microservice or the application server -- :material-clock-fast: utilizing asynchronous I/O -
[Get started with ASAB](./getting-started/install.md){ .md-button .md-button--primary } From 83f1961cf2e7cff8abff79daeb10a95463ba6bbd Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 11 Jul 2023 12:42:27 +0200 Subject: [PATCH 027/154] Create test example --- examples/test.py | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 examples/test.py diff --git a/examples/test.py b/examples/test.py new file mode 100644 index 000000000..a79e09f9f --- /dev/null +++ b/examples/test.py @@ -0,0 +1,3 @@ +import asab + +print("Hello!") \ No newline at end of file From 5d3b9eabaabc8a44200c6eae49b9106d87c4b424 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 11 Jul 2023 12:44:03 +0200 Subject: [PATCH 028/154] Fix: title, overwriting, non-staged file --- docs/create_examples.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/create_examples.py b/docs/create_examples.py index 2cb838d22..292025aaa 100644 --- a/docs/create_examples.py +++ b/docs/create_examples.py @@ -34,6 +34,7 @@ def load_headers(md_file: pathlib.Path): def git_metadata(py_file: pathlib.Path) -> dict: git_format = "%aN|%ad|%H" last_git_commit = subprocess.check_output(["git", "log", "-n", "1", "--format={}".format(git_format), "--", py_file]).decode('utf-8').strip("\n").split("|") + assert last_git_commit != [""], "{} is not staged by git.".format(py_file) date_format = '%a %b %d %H:%M:%S %Y %z' metadata = { "author": last_git_commit[0], @@ -51,7 +52,7 @@ def create_markdown(py_file: pathlib.Path, md_file: pathlib.Path): !!! example - ```python title={py_file_name} linenums="1" + ```python title='{py_file_name}' linenums="1" {py_file_content} ``` """.format( @@ -64,8 +65,9 @@ def create_markdown(py_file: pathlib.Path, md_file: pathlib.Path): def add_to_navbar(md_file: pathlib.Path, mkdocs_file: pathlib.Path): - with open(mkdocs_file, "+at", encoding="utf-8") as f: - content = f.read() + content = mkdocs_file.read_text() + + with open(mkdocs_file, "a", encoding="utf-8") as f: if md_file.name not in content: print(md_file.name, "not in", mkdocs_file.name) nav_reference = " - examples/{}\n".format(md_file.name) From 4ba2dae87daf8b3fb3fd095b1233cfc8c0736d59 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 11 Jul 2023 13:09:35 +0200 Subject: [PATCH 029/154] Process each md file separately --- docs/create_examples.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/create_examples.py b/docs/create_examples.py index 292025aaa..cb1b61ab3 100644 --- a/docs/create_examples.py +++ b/docs/create_examples.py @@ -3,7 +3,6 @@ import pathlib import yaml import datetime -import re import subprocess EXAMPLE_DIR = pathlib.Path.cwd() / "examples" @@ -22,7 +21,9 @@ def process_examples(path_from, path_to): md_file = DOCS_DIR / py_file.with_suffix(".md").name if not md_file.exists() or git_metadata(py_file) != load_headers(md_file): create_markdown(py_file, md_file) - add_to_navbar(md_file, MKDOCS_FILE) + + for md_file in EXAMPLE_DIR.iterdir(): + add_to_navbar(md_file, MKDOCS_FILE) def load_headers(md_file: pathlib.Path): @@ -68,8 +69,8 @@ def add_to_navbar(md_file: pathlib.Path, mkdocs_file: pathlib.Path): content = mkdocs_file.read_text() with open(mkdocs_file, "a", encoding="utf-8") as f: - if md_file.name not in content: - print(md_file.name, "not in", mkdocs_file.name) + if "examples/{}".format(md_file.name) not in content: + print("Adding 'examples/{}' to navbar.".format(md_file.name)) nav_reference = " - examples/{}\n".format(md_file.name) f.write(nav_reference) From 5d9c7596714100da7d8e4ddb41ec94ce641f9f93 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 11 Jul 2023 13:10:01 +0200 Subject: [PATCH 030/154] Fix example title --- docs/examples/application_states.md | 2 +- docs/examples/argparser.md | 2 +- docs/examples/config_getseconds.md | 2 +- docs/examples/config_geturl.md | 2 +- docs/examples/executor.md | 2 +- docs/examples/hello_world.md | 2 +- docs/examples/json_schema.md | 2 +- docs/examples/library-git-provider.md | 2 +- docs/examples/library-subscribe.md | 2 +- docs/examples/library.md | 2 +- docs/examples/logging-file.md | 2 +- docs/examples/metrics-web-requests.md | 2 +- docs/examples/metrics.md | 2 +- docs/examples/pdict.md | 2 +- docs/examples/pubsub.md | 2 +- docs/examples/service-discovery.md | 2 +- docs/examples/storage_elasticsearch.md | 2 +- docs/examples/storage_inmemory.md | 2 +- docs/examples/storage_mongodb.md | 2 +- docs/examples/task.md | 2 +- docs/examples/timer.md | 2 +- docs/examples/web-auth.md | 2 +- docs/examples/web-authz-rbac.md | 2 +- docs/examples/web-authz-userinfo.md | 2 +- docs/examples/webserver.md | 2 +- docs/examples/websocket-chat.md | 2 +- docs/examples/zookeeper-advertise.md | 2 +- docs/examples/zookeeper.md | 2 +- examples/test.py | 3 -- mkdocs.yml | 63 ++++++++++++++------------ 30 files changed, 62 insertions(+), 60 deletions(-) delete mode 100644 examples/test.py diff --git a/docs/examples/application_states.md b/docs/examples/application_states.md index 592232650..cf6fba3a9 100644 --- a/docs/examples/application_states.md +++ b/docs/examples/application_states.md @@ -8,7 +8,7 @@ title: Application states !!! example - ```python title=application_states.py linenums="1" + ```python title='application_states.py' linenums="1" #!/usr/bin/env python3 import asab import asyncio diff --git a/docs/examples/argparser.md b/docs/examples/argparser.md index 1dbd1acf2..9e7492ec7 100644 --- a/docs/examples/argparser.md +++ b/docs/examples/argparser.md @@ -8,7 +8,7 @@ title: Argparser !!! example - ```python title=argparser.py linenums="1" + ```python title='argparser.py' linenums="1" #!/usr/bin/env python3 import asab diff --git a/docs/examples/config_getseconds.md b/docs/examples/config_getseconds.md index 9b3ac2867..00eb332ba 100644 --- a/docs/examples/config_getseconds.md +++ b/docs/examples/config_getseconds.md @@ -8,7 +8,7 @@ title: Config getseconds !!! example - ```python title=config_getseconds.py linenums="1" + ```python title='config_getseconds.py' linenums="1" #!/usr/bin/env python3 import logging import asyncio diff --git a/docs/examples/config_geturl.md b/docs/examples/config_geturl.md index e311c0364..7aa7e22af 100644 --- a/docs/examples/config_geturl.md +++ b/docs/examples/config_geturl.md @@ -8,7 +8,7 @@ title: Config geturl !!! example - ```python title=config_geturl.py linenums="1" + ```python title='config_geturl.py' linenums="1" #!/usr/bin/env python3 import logging diff --git a/docs/examples/executor.md b/docs/examples/executor.md index 67d3dc5cb..b35c58daa 100644 --- a/docs/examples/executor.md +++ b/docs/examples/executor.md @@ -8,7 +8,7 @@ title: Executor !!! example - ```python title=executor.py linenums="1" + ```python title='executor.py' linenums="1" #!/usr/bin/env python3 import concurrent.futures import threading diff --git a/docs/examples/hello_world.md b/docs/examples/hello_world.md index b21999e35..0222ed634 100644 --- a/docs/examples/hello_world.md +++ b/docs/examples/hello_world.md @@ -8,7 +8,7 @@ title: Hello world !!! example - ```python title=hello_world.py linenums="1" + ```python title='hello_world.py' linenums="1" #!/usr/bin/env python3 import logging import asab diff --git a/docs/examples/json_schema.md b/docs/examples/json_schema.md index 3a13bc1ba..1e4d92244 100644 --- a/docs/examples/json_schema.md +++ b/docs/examples/json_schema.md @@ -8,7 +8,7 @@ title: Json schema !!! example - ```python title=json_schema.py linenums="1" + ```python title='json_schema.py' linenums="1" import aiohttp import aiohttp.web diff --git a/docs/examples/library-git-provider.md b/docs/examples/library-git-provider.md index 7ff16b917..efb829c67 100644 --- a/docs/examples/library-git-provider.md +++ b/docs/examples/library-git-provider.md @@ -8,7 +8,7 @@ title: Library git provider !!! example - ```python title=library-git-provider.py linenums="1" + ```python title='library-git-provider.py' linenums="1" #!/usr/bin/env python3 import asab import asab.library diff --git a/docs/examples/library-subscribe.md b/docs/examples/library-subscribe.md index c9853656e..fdba623db 100644 --- a/docs/examples/library-subscribe.md +++ b/docs/examples/library-subscribe.md @@ -8,7 +8,7 @@ title: Library subscribe !!! example - ```python title=library-subscribe.py linenums="1" + ```python title='library-subscribe.py' linenums="1" #!/usr/bin/env python3 import asab diff --git a/docs/examples/library.md b/docs/examples/library.md index 70749c1de..75f1a6522 100644 --- a/docs/examples/library.md +++ b/docs/examples/library.md @@ -8,7 +8,7 @@ title: Library !!! example - ```python title=library.py linenums="1" + ```python title='library.py' linenums="1" #!/usr/bin/env python3 import os.path diff --git a/docs/examples/logging-file.md b/docs/examples/logging-file.md index f7d265340..0a3c738d7 100644 --- a/docs/examples/logging-file.md +++ b/docs/examples/logging-file.md @@ -8,7 +8,7 @@ title: Logging file !!! example - ```python title=logging-file.py linenums="1" + ```python title='logging-file.py' linenums="1" #!/usr/bin/env python3 import logging import asab diff --git a/docs/examples/metrics-web-requests.md b/docs/examples/metrics-web-requests.md index b0ce6eea0..2c12029c0 100644 --- a/docs/examples/metrics-web-requests.md +++ b/docs/examples/metrics-web-requests.md @@ -8,7 +8,7 @@ title: Metrics web requests !!! example - ```python title=metrics-web-requests.py linenums="1" + ```python title='metrics-web-requests.py' linenums="1" import logging import time diff --git a/docs/examples/metrics.md b/docs/examples/metrics.md index f072ca16e..2502a22af 100644 --- a/docs/examples/metrics.md +++ b/docs/examples/metrics.md @@ -8,7 +8,7 @@ title: Metrics !!! example - ```python title=metrics.py linenums="1" + ```python title='metrics.py' linenums="1" #!/usr/bin/env python3 import asab import asab.web diff --git a/docs/examples/pdict.md b/docs/examples/pdict.md index a241884f8..5d3e81f6c 100644 --- a/docs/examples/pdict.md +++ b/docs/examples/pdict.md @@ -8,7 +8,7 @@ title: Pdict !!! example - ```python title=pdict.py linenums="1" + ```python title='pdict.py' linenums="1" #!/usr/bin/env python3 import os.path import asab diff --git a/docs/examples/pubsub.md b/docs/examples/pubsub.md index d4e310657..834bb5cc8 100644 --- a/docs/examples/pubsub.md +++ b/docs/examples/pubsub.md @@ -8,7 +8,7 @@ title: Pubsub !!! example - ```python title=pubsub.py linenums="1" + ```python title='pubsub.py' linenums="1" #!/usr/bin/env python3 import asab diff --git a/docs/examples/service-discovery.md b/docs/examples/service-discovery.md index 0650d98ca..198f36c92 100644 --- a/docs/examples/service-discovery.md +++ b/docs/examples/service-discovery.md @@ -8,7 +8,7 @@ title: Service discovery !!! example - ```python title=service-discovery.py linenums="1" + ```python title='service-discovery.py' linenums="1" import logging import aiohttp import aiohttp.web diff --git a/docs/examples/storage_elasticsearch.md b/docs/examples/storage_elasticsearch.md index 9e2c3551c..db1de4383 100644 --- a/docs/examples/storage_elasticsearch.md +++ b/docs/examples/storage_elasticsearch.md @@ -8,7 +8,7 @@ title: Storage elasticsearch !!! example - ```python title=storage_elasticsearch.py linenums="1" + ```python title='storage_elasticsearch.py' linenums="1" import pprint import asab diff --git a/docs/examples/storage_inmemory.md b/docs/examples/storage_inmemory.md index 2e6cf2974..1f5976ef2 100644 --- a/docs/examples/storage_inmemory.md +++ b/docs/examples/storage_inmemory.md @@ -8,7 +8,7 @@ title: Storage inmemory !!! example - ```python title=storage_inmemory.py linenums="1" + ```python title='storage_inmemory.py' linenums="1" import pprint import asab diff --git a/docs/examples/storage_mongodb.md b/docs/examples/storage_mongodb.md index cde02ad7f..34c3c0c64 100644 --- a/docs/examples/storage_mongodb.md +++ b/docs/examples/storage_mongodb.md @@ -8,7 +8,7 @@ title: Storage mongodb !!! example - ```python title=storage_mongodb.py linenums="1" + ```python title='storage_mongodb.py' linenums="1" import pprint import os import asab diff --git a/docs/examples/task.md b/docs/examples/task.md index 5eb16a758..3ff099012 100644 --- a/docs/examples/task.md +++ b/docs/examples/task.md @@ -8,7 +8,7 @@ title: Task !!! example - ```python title=task.py linenums="1" + ```python title='task.py' linenums="1" #!/usr/bin/env python3 import asab diff --git a/docs/examples/timer.md b/docs/examples/timer.md index fa09394e8..cad472c46 100644 --- a/docs/examples/timer.md +++ b/docs/examples/timer.md @@ -8,7 +8,7 @@ title: Timer !!! example - ```python title=timer.py linenums="1" + ```python title='timer.py' linenums="1" #!/usr/bin/env python3 import asab diff --git a/docs/examples/web-auth.md b/docs/examples/web-auth.md index d94598780..c4cd5c04a 100644 --- a/docs/examples/web-auth.md +++ b/docs/examples/web-auth.md @@ -8,7 +8,7 @@ title: Web auth !!! example - ```python title=web-auth.py linenums="1" + ```python title='web-auth.py' linenums="1" #!/usr/bin/env python3 import asab.web.rest import asab.web.auth diff --git a/docs/examples/web-authz-rbac.md b/docs/examples/web-authz-rbac.md index 08a9aef75..54826e5ad 100644 --- a/docs/examples/web-authz-rbac.md +++ b/docs/examples/web-authz-rbac.md @@ -8,7 +8,7 @@ title: Web authz rbac !!! example - ```python title=web-authz-rbac.py linenums="1" + ```python title='web-authz-rbac.py' linenums="1" import logging import asab diff --git a/docs/examples/web-authz-userinfo.md b/docs/examples/web-authz-userinfo.md index a2491d702..cff0512fa 100644 --- a/docs/examples/web-authz-userinfo.md +++ b/docs/examples/web-authz-userinfo.md @@ -8,7 +8,7 @@ title: Web authz userinfo !!! example - ```python title=web-authz-userinfo.py linenums="1" + ```python title='web-authz-userinfo.py' linenums="1" import logging import asab diff --git a/docs/examples/webserver.md b/docs/examples/webserver.md index 1d9c4f2ea..ea6262269 100644 --- a/docs/examples/webserver.md +++ b/docs/examples/webserver.md @@ -8,7 +8,7 @@ title: Webserver !!! example - ```python title=webserver.py linenums="1" + ```python title='webserver.py' linenums="1" #!/usr/bin/env python3 import asab.web.rest diff --git a/docs/examples/websocket-chat.md b/docs/examples/websocket-chat.md index 89f707b8a..f211b3085 100644 --- a/docs/examples/websocket-chat.md +++ b/docs/examples/websocket-chat.md @@ -8,7 +8,7 @@ title: Websocket chat !!! example - ```python title=websocket-chat.py linenums="1" + ```python title='websocket-chat.py' linenums="1" import os import aiohttp diff --git a/docs/examples/zookeeper-advertise.md b/docs/examples/zookeeper-advertise.md index 2f8e3d62f..71f0263ad 100644 --- a/docs/examples/zookeeper-advertise.md +++ b/docs/examples/zookeeper-advertise.md @@ -8,7 +8,7 @@ title: Zookeeper advertise !!! example - ```python title=zookeeper-advertise.py linenums="1" + ```python title='zookeeper-advertise.py' linenums="1" import asab import asab.api import asab.zookeeper diff --git a/docs/examples/zookeeper.md b/docs/examples/zookeeper.md index 742353f1b..e0f3437a1 100644 --- a/docs/examples/zookeeper.md +++ b/docs/examples/zookeeper.md @@ -8,7 +8,7 @@ title: Zookeeper !!! example - ```python title=zookeeper.py linenums="1" + ```python title='zookeeper.py' linenums="1" #!/usr/bin/env python3 import asab import asab.zookeeper diff --git a/examples/test.py b/examples/test.py deleted file mode 100644 index a79e09f9f..000000000 --- a/examples/test.py +++ /dev/null @@ -1,3 +0,0 @@ -import asab - -print("Hello!") \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index cb0dca3be..c158d3506 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -181,32 +181,37 @@ nav: # Examples are rendered automatically with create_examples.py script - Examples: - - - examples/hello_world.md - - examples/config_geturl.md - - examples/storage_mongodb.md - - examples/websocket-chat.md - - examples/metrics-web-requests.md - - examples/argparser.md - - examples/task.md - - examples/json_schema.md - - examples/config_getseconds.md - - examples/library-subscribe.md - - examples/storage_inmemory.md - - examples/webserver.md - - examples/zookeeper.md - - examples/application_states.md - - examples/library.md - - examples/service-discovery.md - - examples/executor.md - - examples/metrics.md - - examples/timer.md - - examples/pubsub.md - - examples/zookeeper-advertise.md - - examples/storage_elasticsearch.md - - examples/logging-file.md - - examples/web-authz-rbac.md - - examples/pdict.md - - examples/library-git-provider.md - - examples/web-authz-userinfo.md - - examples/web-auth.md + - examples/hello_world.py + - examples/config_geturl.py + - examples/storage_mongodb.py + - examples/websocket-chat.py + - examples/metrics-web-requests.py + - examples/argparser.py + - examples/task.py + - examples/data + - examples/json_schema.py + - examples/config_getseconds.py + - examples/.mypy_cache + - examples/library-subscribe.py + - examples/storage_inmemory.py + - examples/webserver.py + - examples/ssl + - examples/zookeeper.py + - examples/application_states.py + - examples/webapp + - examples/library.py + - examples/service-discovery.py + - examples/executor.py + - examples/metrics.py + - examples/timer.py + - examples/pubsub.py + - examples/zookeeper-advertise.py + - examples/web-authz-userinfo.conf + - examples/storage_elasticsearch.py + - examples/logging-file.py + - examples/web-authz-rbac.py + - examples/pdict.py + - examples/websocket-chat.html + - examples/library-git-provider.py + - examples/web-authz-userinfo.py + - examples/web-auth.py From a55a143c0faba46a6de0dfcd67128ee835a9e9a3 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 11 Jul 2023 13:15:14 +0200 Subject: [PATCH 031/154] Make examples sorted by name --- docs/create_examples.py | 2 +- mkdocs.yml | 62 +++++++++++++++++++---------------------- 2 files changed, 29 insertions(+), 35 deletions(-) diff --git a/docs/create_examples.py b/docs/create_examples.py index cb1b61ab3..434864b59 100644 --- a/docs/create_examples.py +++ b/docs/create_examples.py @@ -22,7 +22,7 @@ def process_examples(path_from, path_to): if not md_file.exists() or git_metadata(py_file) != load_headers(md_file): create_markdown(py_file, md_file) - for md_file in EXAMPLE_DIR.iterdir(): + for md_file in sorted(DOCS_DIR.iterdir()): add_to_navbar(md_file, MKDOCS_FILE) diff --git a/mkdocs.yml b/mkdocs.yml index c158d3506..f2ddfe6b0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -181,37 +181,31 @@ nav: # Examples are rendered automatically with create_examples.py script - Examples: - - examples/hello_world.py - - examples/config_geturl.py - - examples/storage_mongodb.py - - examples/websocket-chat.py - - examples/metrics-web-requests.py - - examples/argparser.py - - examples/task.py - - examples/data - - examples/json_schema.py - - examples/config_getseconds.py - - examples/.mypy_cache - - examples/library-subscribe.py - - examples/storage_inmemory.py - - examples/webserver.py - - examples/ssl - - examples/zookeeper.py - - examples/application_states.py - - examples/webapp - - examples/library.py - - examples/service-discovery.py - - examples/executor.py - - examples/metrics.py - - examples/timer.py - - examples/pubsub.py - - examples/zookeeper-advertise.py - - examples/web-authz-userinfo.conf - - examples/storage_elasticsearch.py - - examples/logging-file.py - - examples/web-authz-rbac.py - - examples/pdict.py - - examples/websocket-chat.html - - examples/library-git-provider.py - - examples/web-authz-userinfo.py - - examples/web-auth.py + - examples/application_states.md + - examples/argparser.md + - examples/config_getseconds.md + - examples/config_geturl.md + - examples/executor.md + - examples/hello_world.md + - examples/json_schema.md + - examples/library-git-provider.md + - examples/library-subscribe.md + - examples/library.md + - examples/logging-file.md + - examples/metrics-web-requests.md + - examples/metrics.md + - examples/pdict.md + - examples/pubsub.md + - examples/service-discovery.md + - examples/storage_elasticsearch.md + - examples/storage_inmemory.md + - examples/storage_mongodb.md + - examples/task.md + - examples/timer.md + - examples/web-auth.md + - examples/web-authz-rbac.md + - examples/web-authz-userinfo.md + - examples/webserver.md + - examples/websocket-chat.md + - examples/zookeeper-advertise.md + - examples/zookeeper.md From e895ea7857a5e31da2da4455be009f873c6b5eb3 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 11 Jul 2023 17:43:16 +0200 Subject: [PATCH 032/154] Add TeskaLabs icons --- docs/images/icon-singlecolor_white.svg | 14 ++++++++++++++ docs/images/teskalabs-logo.svg | 14 ++++++++++++++ docs/index.md | 19 +++++++++---------- docs/overrides/.icons/teskalabs-white.svg | 14 ++++++++++++++ docs/overrides/.icons/teskalabs.svg | 14 ++++++++++++++ mkdocs.yml | 3 +++ 6 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 docs/images/icon-singlecolor_white.svg create mode 100644 docs/images/teskalabs-logo.svg create mode 100644 docs/overrides/.icons/teskalabs-white.svg create mode 100644 docs/overrides/.icons/teskalabs.svg diff --git a/docs/images/icon-singlecolor_white.svg b/docs/images/icon-singlecolor_white.svg new file mode 100644 index 000000000..a1f457b6f --- /dev/null +++ b/docs/images/icon-singlecolor_white.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/docs/images/teskalabs-logo.svg b/docs/images/teskalabs-logo.svg new file mode 100644 index 000000000..a89d69de8 --- /dev/null +++ b/docs/images/teskalabs-logo.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/docs/index.md b/docs/index.md index c3adf40a5..a9a8a2867 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,6 +1,6 @@ # Asynchronous Server Application Boilerplate -Asynchronous Server App Boilerplate (or ASAB for short) is a microservice platform for Python 3.7+ and [asyncio](https://docs.python.org/3/library/asyncio.html). +**Asynchronous Server App Boilerplate** (or ASAB for short) is an open-source microservice platform for Python 3.7+ and [asyncio](https://docs.python.org/3/library/asyncio.html). ASAB aims to minimize the amount of code that needs to be written when building a microservice or an application server. ASAB is fully asynchronous using async/await syntax from Python 3, making your code modern, @@ -9,7 +9,9 @@ We make every effort to build ASAB container-friendly so that you can deploy ASAB-based microservice via Docker or Kubernetes in a breeze. Anyone can (and is encouraged to) use ASAB in his or her projects, for free. -A current maintainer is a [TeskaLabs Ltd](https://teskalabs.com) company. + + +[Get started](getting-started/installation_first_app.md){ .md-button .md-button--primary } [Read more about TeskaLabs](https://docs.teskalabs.com/){ .md-button .md-button--primary } [Contribute](contributing.md){ .md-button .md-button--primary } !!! success "ASAB is the right choice when:" @@ -36,15 +38,12 @@ A current maintainer is a [TeskaLabs Ltd](https://teskalabs.com) company. !!! info "Development" - - :simple-opensourceinitiative: ASAB is free and open-source software, available under BSD licence. - Anyone is freely licensed to use, copy, study, and change the - software in any way, and the source code is openly shared so that people - could voluntarily improve the design of the software. + - :teskalabs: A current maintainer of ASAB is a [TeskaLabs Ltd](https://teskalabs.com) company. - :simple-github: ASAB is developed [on GitHub](https://github.com/TeskaLabs/asab/). Contributions are most welcome! If you want to help us improve asab, check our [contribution rules](./contributing.md). - - -[Get started with ASAB](./getting-started/install.md){ .md-button .md-button--primary } - + - :simple-opensourceinitiative: ASAB is free and open-source software, available under BSD licence. + Anyone is freely licensed to use, copy, study, and change the + software in any way, and the source code is openly shared so that people + could voluntarily improve the design of the software. diff --git a/docs/overrides/.icons/teskalabs-white.svg b/docs/overrides/.icons/teskalabs-white.svg new file mode 100644 index 000000000..a1f457b6f --- /dev/null +++ b/docs/overrides/.icons/teskalabs-white.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/docs/overrides/.icons/teskalabs.svg b/docs/overrides/.icons/teskalabs.svg new file mode 100644 index 000000000..a89d69de8 --- /dev/null +++ b/docs/overrides/.icons/teskalabs.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/mkdocs.yml b/mkdocs.yml index f2ddfe6b0..eff002f28 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -106,6 +106,9 @@ markdown_extensions: - pymdownx.emoji: emoji_index: !!python/name:materialx.emoji.twemoji emoji_generator: !!python/name:materialx.emoji.to_svg + options: + custom_icons: + - docs/overrides/.icons # Content tabs and anchor links https://squidfunk.github.io/mkdocs-material/reference/content-tabs/ - pymdownx.tabbed: From 9deeb5ecba4b437a3dd2a5a8facd158f782e98c4 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 11 Jul 2023 17:43:32 +0200 Subject: [PATCH 033/154] Simplify installation guide --- docs/getting-started/installation_first_app.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/getting-started/installation_first_app.md b/docs/getting-started/installation_first_app.md index e3845f261..ed1954bca 100644 --- a/docs/getting-started/installation_first_app.md +++ b/docs/getting-started/installation_first_app.md @@ -14,7 +14,7 @@ ASAB is distributed via [pypi](https://pypi.org/project/asab/). For installing A === "Cloning from git repository" - To install ASAB from a master branch of the git repository, you can use the following command: + You can clone it from master branch using pip: ``` bash pip install git+https://github.com/TeskaLabs/asab.git @@ -103,8 +103,4 @@ ASAB is distributed via [pypi](https://pypi.org/project/asab/). For installing A for server architectures. For that reason, it doesn't terminate and continue running and serving eventual requests. -## Summary - -In this tutorial, you learned how to install ASAB and how to create a basic application. - You can continue with a step-by-step tutorial on how to build ASAB based [web server](./web_server.md). From c741ecfbd6894b60a1cc44658fded2d17f06a787 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 12 Jul 2023 17:43:25 +0200 Subject: [PATCH 034/154] Add reference to the class --- docs/reference/storage/elasticsearch.md | 2 +- docs/reference/storage/inmemory.md | 2 +- docs/reference/storage/mongodb.md | 2 +- docs/reference/storage/service.md | 2 +- docs/reference/storage/upsertor.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/reference/storage/elasticsearch.md b/docs/reference/storage/elasticsearch.md index 4ce51fabf..9cfe8c5ef 100644 --- a/docs/reference/storage/elasticsearch.md +++ b/docs/reference/storage/elasticsearch.md @@ -1 +1 @@ -::: asab.storage.elasticsearch \ No newline at end of file +::: asab.storage.elasticsearch.StorageService \ No newline at end of file diff --git a/docs/reference/storage/inmemory.md b/docs/reference/storage/inmemory.md index f09abae0a..6898d373c 100644 --- a/docs/reference/storage/inmemory.md +++ b/docs/reference/storage/inmemory.md @@ -1 +1 @@ -::: asab.storage.inmemory \ No newline at end of file +::: asab.storage.inmemory.StorageService \ No newline at end of file diff --git a/docs/reference/storage/mongodb.md b/docs/reference/storage/mongodb.md index dcbfe5302..289005905 100644 --- a/docs/reference/storage/mongodb.md +++ b/docs/reference/storage/mongodb.md @@ -1 +1 @@ -::: asab.storage.mongodb \ No newline at end of file +::: asab.storage.mongodb.StorageService \ No newline at end of file diff --git a/docs/reference/storage/service.md b/docs/reference/storage/service.md index 1fcf2966b..110864d53 100644 --- a/docs/reference/storage/service.md +++ b/docs/reference/storage/service.md @@ -1 +1 @@ -::: asab.storage.service \ No newline at end of file +::: asab.storage.service.StorageServiceABC diff --git a/docs/reference/storage/upsertor.md b/docs/reference/storage/upsertor.md index adf0a2071..c3110870c 100644 --- a/docs/reference/storage/upsertor.md +++ b/docs/reference/storage/upsertor.md @@ -1 +1 @@ -::: asab.storage.upsertor +::: asab.storage.upsertor.UpsertorABC From f5891294f2d18249a3ab362395ee39c08605dd4c Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 12 Jul 2023 18:17:16 +0200 Subject: [PATCH 035/154] Add configuration and comments --- .gitignore | 5 ++++- docs/TODO.md | 4 +++- docs/plugins.txt | 5 +++++ mkdocs.yml | 10 ++++++++-- 4 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 docs/plugins.txt diff --git a/.gitignore b/.gitignore index 4c576e884..e46485cf3 100644 --- a/.gitignore +++ b/.gitignore @@ -110,5 +110,8 @@ ENV/ etc/site.conf etc/site.d/ -doc/_build examples/ssl/clients/.index.bin + +# mkdocs +doc/_build +doc/env \ No newline at end of file diff --git a/docs/TODO.md b/docs/TODO.md index d6030a34a..073129e8c 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -8,4 +8,6 @@ https://diataxis.fr/ https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings -- Experiment with search boosting: https://squidfunk.github.io/mkdocs-material/setup/setting-up-site-search/#search-boosting \ No newline at end of file +- Create a Dockerfile +- Experiment with search boosting: https://squidfunk.github.io/mkdocs-material/setup/setting-up-site-search/#search-boosting +- Override the CSS for 'h2.doc-heading' so that we can use different heading level and improve the design diff --git a/docs/plugins.txt b/docs/plugins.txt new file mode 100644 index 000000000..67d13a6c6 --- /dev/null +++ b/docs/plugins.txt @@ -0,0 +1,5 @@ +mkdocs-print-site-plugin +mkdocs-awesome-pages-plugin +mkdocs-glightbox +mkdocstrings +mkdocstrings[python] \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index eff002f28..79f09fa12 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -9,12 +9,14 @@ theme: features: - content.code.copy - content.code.select - - content.code.annotate # + - content.code.annotate + - navigation.tabs - navigation.footer - navigation.indexes - navigation.top # back-to-the-top button when scrolling up - navigation.tracking + - attr_list - admonition - pymdownx.details @@ -74,8 +76,11 @@ plugins: # https://mkdocstrings.github.io/python/usage/configuration/docstrings/ docstring_style: google # | google | numpy | sphinx docstring_section_style: table # table | list | spacy - show_if_no_docstring: true + show_if_no_docstring: false show_docstring_description: false + show_root_heading: true + show_source: false + heading_level: 1 - glightbox - search - awesome-pages @@ -183,6 +188,7 @@ nav: - Contributing: contributing.md # Examples are rendered automatically with create_examples.py script + # please do not modify this part manually and leave it at the bottom of the file - Examples: - examples/application_states.md - examples/argparser.md From 0ac8b80656ddac1378aae2fa4e503c87beac9589 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 12 Jul 2023 18:18:29 +0200 Subject: [PATCH 036/154] Add permalinks --- mkdocs.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mkdocs.yml b/mkdocs.yml index 79f09fa12..51cb1db02 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -119,6 +119,10 @@ markdown_extensions: - pymdownx.tabbed: alternate_style: true + # Permalinks + - toc: + permalink: "¤" + extra: social: - icon: fontawesome/brands/github-alt From 9f62f82e20caf101f97063ef8304df88ace089b8 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 12 Jul 2023 18:21:48 +0200 Subject: [PATCH 037/154] Move utility script for sphinx docs --- transfer_docs.py => docs/transfer_docs.py | 2 ++ 1 file changed, 2 insertions(+) rename transfer_docs.py => docs/transfer_docs.py (84%) diff --git a/transfer_docs.py b/docs/transfer_docs.py similarity index 84% rename from transfer_docs.py rename to docs/transfer_docs.py index 286f8313f..036f29f09 100644 --- a/transfer_docs.py +++ b/docs/transfer_docs.py @@ -1,3 +1,5 @@ +"""Utility script for transferring sphinx docs into yaml files.""" + import pathlib import os From 8698bea138dcc275264f5fae9f449781853591df Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 12 Jul 2023 18:38:52 +0200 Subject: [PATCH 038/154] Fix indentation --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 51cb1db02..975ef3c65 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -121,7 +121,7 @@ markdown_extensions: # Permalinks - toc: - permalink: "¤" + permalink: "¤" extra: social: From 4347d0111978177e7db9fa2db351a73b59708943 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Sun, 16 Jul 2023 12:55:55 +0200 Subject: [PATCH 039/154] Add custom CSS and logos --- docs/stylesheets/extra.css | 3 +++ mkdocs.yml | 27 ++++++++++++++++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 docs/stylesheets/extra.css diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 000000000..a2b305dd4 --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,3 @@ +.md-typeset { + font-size: 0.7rem; +} diff --git a/mkdocs.yml b/mkdocs.yml index 975ef3c65..49ab8ad40 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -6,6 +6,8 @@ repo_name: TeskaLabs/asab theme: name: "material" + logo: images/teskalabs-logo.svg + features: - content.code.copy - content.code.select @@ -64,6 +66,9 @@ theme: icon: material/brightness-4 name: Switch to light mode +extra_css: + - stylesheets/extra.css + # PLUGINS @@ -127,16 +132,26 @@ extra: social: - icon: fontawesome/brands/github-alt link: https://github.com/TeskaLabs/asab + - icon: fontawesome/brands/linkedin + link: https://www.linkedin.com/company/teskalabs + - icon: fontawesome/brands/twitter + link: https://twitter.com/teskalabs + - icon: fontawesome/solid/paper-plane + link: mailto:info@teskalabs.com + name: info@teskalabs.com + # NAVIGATION TREE nav: - - Home: index.md + - Home: + - About: index.md + - Getting started: + - Installation and first application: getting-started/installation_first_app.md + - Creating a web server: getting-started/web_server.md + - Containerization: getting-started/containers.md - - Getting started: - - Installation and first application: getting-started/installation_first_app.md - - Creating a web server: getting-started/web_server.md - - Containerization: getting-started/containers.md + - Contributing: contributing.md - How-To Guides: - Creating a microservice with REST API: how-tos/03_rest_api.md @@ -188,8 +203,6 @@ nav: - ElasticSearch: reference/storage/elasticsearch.md - MongoDB: reference/storage/mongodb.md - In-Memory: reference/storage/inmemory.md - - - Contributing: contributing.md # Examples are rendered automatically with create_examples.py script # please do not modify this part manually and leave it at the bottom of the file From b42028293911d975276d5ad7b069ef1f957062c1 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 17 Jul 2023 11:41:53 +0200 Subject: [PATCH 040/154] Make codeblocks bigger --- docs/stylesheets/extra.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index a2b305dd4..ee9521159 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -1,3 +1,3 @@ .md-typeset { - font-size: 0.7rem; + font-size: 0.75rem; } From 3ab34f9e49f877fa23b14421c17ed8e51cd5e2ab Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 17 Jul 2023 11:42:20 +0200 Subject: [PATCH 041/154] Add section about docstrings --- docs/TODO.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/TODO.md b/docs/TODO.md index 073129e8c..6d4cb2601 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -8,6 +8,26 @@ https://diataxis.fr/ https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings +## Converting docstrings + +- Script for converting docstrings from one format to another: https://github.com/dadadel/pyment + +1. Install via pip: +``` +pip install git+https://github.com/dadadel/pyment.git +``` + +2. This command creates a patch: +``` +pyment path/to/file.py -o google +``` +3. Rewrite the patches: +``` +patch path/to/file.py path/to/file.py.patch +``` + + - Create a Dockerfile - Experiment with search boosting: https://squidfunk.github.io/mkdocs-material/setup/setting-up-site-search/#search-boosting - Override the CSS for 'h2.doc-heading' so that we can use different heading level and improve the design + From 1b60fcd8b6555a56902d91bf5162fb523862220a Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 17 Jul 2023 12:01:48 +0200 Subject: [PATCH 042/154] Add module docstring --- asab/__init__.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/asab/__init__.py b/asab/__init__.py index 8bd7b2fec..5f61760ac 100644 --- a/asab/__init__.py +++ b/asab/__init__.py @@ -1,3 +1,14 @@ +"""Asynchronous Server Application Boilerplate. + +ASAB (Asynchronous Serverless Application Builder) is a lightweight Python framework for building +asynchronous and serverless applications. It provides a simple yet powerful set of tools and +conventions for developing scalable and efficient applications. + +For detailed documentation and examples, please refer to the ASAB documentation at: + - GitHub Repository: https://github.com/TeskaLabs/asab + - Documentation: https://asab.readthedocs.io +""" + import logging from .abc.module import Module From f24e54950a09ce17dc29638cba860cb7be8cf19d Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 18 Jul 2023 13:33:20 +0200 Subject: [PATCH 043/154] Specify autodocs default options --- mkdocs.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 49ab8ad40..6d3eab5c0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -81,11 +81,12 @@ plugins: # https://mkdocstrings.github.io/python/usage/configuration/docstrings/ docstring_style: google # | google | numpy | sphinx docstring_section_style: table # table | list | spacy - show_if_no_docstring: false - show_docstring_description: false - show_root_heading: true - show_source: false - heading_level: 1 + show_if_no_docstring: false # ...we are hereby compelled to write docstrings + show_docstring_description: true + show_root_heading: true # e.g. 'asab.storage.service.StorageService' + show_source: true # show source code of method (class) + heading_level: 3 # class names displayed as

+ annotations_path: brief - glightbox - search - awesome-pages @@ -184,6 +185,7 @@ nav: # - reference/config.md # - reference/library.md # - reference/log.md + - Application: reference/application/application.md - Metrics: - MetricsService: reference/metrics/service.md - Gauge: reference/metrics/gauge.md From e5cf1e0c88a97d45d7c730ab9b2bc51e2b100e3a Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 18 Jul 2023 13:36:27 +0200 Subject: [PATCH 044/154] Rename 'application' file --- docs/reference/application.md | 1 - docs/topics/asab/application.md | 204 -------------------------------- 2 files changed, 205 deletions(-) delete mode 100644 docs/reference/application.md delete mode 100644 docs/topics/asab/application.md diff --git a/docs/reference/application.md b/docs/reference/application.md deleted file mode 100644 index 7459c7636..000000000 --- a/docs/reference/application.md +++ /dev/null @@ -1 +0,0 @@ -::: asab.application \ No newline at end of file diff --git a/docs/topics/asab/application.md b/docs/topics/asab/application.md deleted file mode 100644 index f85abcffc..000000000 --- a/docs/topics/asab/application.md +++ /dev/null @@ -1,204 +0,0 @@ -Application -=========== - -The :py`Application`{.interpreted-text role="class"} class maintains the -global application state. You can provide your own implementation by -creating a subclass. There should be only one -:py`Application`{.interpreted-text role="class"} object in the process. - -Subclassing: - -``` {.python} -import asab - -class MyApplication(asab.Application): - pass - -if __name__ == '__main__': - app = MyApplication() - app.run() -``` - -Direct use of :py`Application`{.interpreted-text role="class"} object: - -``` {.python} -import asab - -if __name__ == '__main__': - app = asab.Application() - app.run() -``` - -Event Loop ----------- - -The :py`asyncio`{.interpreted-text role="mod"} event loop that is used -by this application. - -``` {.python} -asyncio.ensure_future(my_coro()) -``` - -Application Lifecycle ---------------------- - -The ASAB is designed around the [Inversion of -control](https://en.wikipedia.org/wiki/Inversion_of_control) principle. -It means that the ASAB is in control of the application lifecycle. The -custom-written code receives the flow from ASAB via callbacks or -handlers. Inversion of control is used to increase modularity of the -code and make it extensible. - -The application lifecycle is divided into 3 phases: init-time, run-time -and exit-time. - -### Init-time - -The init-time happens during :py`Application`{.interpreted-text -role="class"} constructor call. The Publish-Subscribe message -`Application.init!`{.interpreted-text role="any"} is published during -init-time. The `Config`{.interpreted-text role="class"} is loaded during -init-time. - -The application object executes asynchronous callback -`Application.initialize()`, which can be overriden by an user. - -``` {.python} -class MyApplication(asab.Application): - async def initialize(self): - # Custom initialization - from module_sample import Module - self.add_module(Module) -``` - -### Run-time - -Enter a run-time. This is where the application spends the most time -typically. The Publish-Subscribe message -`Application.run!`{.interpreted-text role="any"} is published when -run-time begins. - -The method returns the value of `Application.ExitCode`{.interpreted-text -role="any"}. - -The application object executes asynchronous callback -`Application.main()`, which can be overriden. If `main()` method is -completed without calling `stop()`, then the application server will run -forever (this is the default behaviour). - -``` {.python} -class MyApplication(asab.Application): - async def main(self): - print("Hello world!") - self.stop() -``` - -The method `Application.stop()` gracefully terminates the run-time and -commence the exit-time. This method is automatically called by `SIGINT` -and `SIGTERM`. It also includes a response to `Ctrl-C` on UNIX-like -system. When this method is called 3x, it abruptly exits the application -(aka emergency abort). - -The parameter `exit_code` allows you to specify the application exit -code (see *Exit-Time* chapter). - -*Note:* You need to install :py`win32api`{.interpreted-text role="mod"} -module to use `Ctrl-C` or an emergency abord properly with ASAB on -Windows. It is an optional dependency of ASAB. - -### Exit-time - -The application object executes asynchronous callback -`Application.finalize()`, which can be overriden by an user. - -``` {.python} -class MyApplication(asab.Application): - async def finalize(self): - # Custom finalization - ... -``` - -The Publish-Subscribe message `Application.exit!`{.interpreted-text -role="any"} is published when exit-time begins. - -Set the exit code of the application, see `os.exit()` in the Python -documentation. If `force` is `False`, the exit code will be set only if -the previous value is lower than the new one. If `force` is `True`, the -exit code value is set to a `exit_code` disregarding the previous value. - -The actual value of the exit code. - -The example of the exit code handling in the `main()` function of the -application. - -``` {.python} -if __name__ == '__main__': - app = asab.Application() - exit_code = app.run() - sys.exit(exit_code) -``` - -Module registry ---------------- - -For more details see :py`Module`{.interpreted-text role="class"} class. - -Initialize and add a new module. The `module_class` class will be -instantiated during the method call. - -``` {.python} -class MyApplication(asab.Application): - async def initialize(self): - from my_module import MyModule - self.add_module(MyModule) -``` - -A list of modules that has been added to the application. - -Service registry ----------------- - -Each service is identified by its unique service name. For more details -see :py`Service`{.interpreted-text role="class"} class. - -Locate a service by its service name in a registry and return the -`Service` object. - -``` {.python} -svc = app.get_service("service_sample") -svc.hello() -``` - -A dictionary of registered services. - -Command-line parser -------------------- - -Creates an `argparse.ArgumentParser`. This method can be overloaded to -adjust command-line argument parser. - -Please refer to Python standard library `argparse` for more details -about function arguments. - -The application object calls this method during init-time to process a -command-line arguments. :py`argparse`{.interpreted-text role="mod"} is -used to process arguments. You can overload this method to provide your -own implementation of command-line argument parser. - -The :py`Description`{.interpreted-text role="data"} attribute is a text -that will be displayed in a help text (`--help`). It is expected that -own value will be provided. The default value is `""` (empty string). - -UTC Time --------- - -Return the current \"event loop time\" in seconds since the epoch as a -floating point number. The specific date of the epoch and the handling -of leap seconds is platform dependent. On Windows and most Unix systems, -the epoch is January 1, 1970, 00:00:00 (UTC) and leap seconds are not -counted towards the time in seconds since the epoch. This is commonly -referred to as Unix time. - -A call of the `time.time()` function could be expensive. This method -provides a cheaper version of the call that returns a current wall time -in UTC. From fb3b95081732d50db1808e7086546b35275a7cbb Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 18 Jul 2023 13:43:12 +0200 Subject: [PATCH 045/154] Convert docstrings to Google style format --- asab/application.py | 217 +++++++++++++++++++++++++++++++++----------- 1 file changed, 166 insertions(+), 51 deletions(-) diff --git a/asab/application.py b/asab/application.py index 4562087c3..d012c0bfd 100644 --- a/asab/application.py +++ b/asab/application.py @@ -9,6 +9,7 @@ import itertools import platform import datetime +import typing import asab @@ -28,19 +29,56 @@ class Application(metaclass=Singleton): + """The base application object that maintains the global application state. + + You can provide your own implementation by creating a subclass. It is intended to be a Singleton. + + Examples: + ```python + class MyApplication(asab.Application): + async def main(self): + print("Hello world!") + self.stop() + + if __name__ == "__main__": + app = MyApplication() + app.run() + ``` + """ Description = "This app is based on ASAB." - def __init__(self, args=None, modules=[]): - ''' - Argument `modules` allows to specify a list of ASAB modules that will be added by `app.add_module()` call. + def __init__(self, args: typing.Optional[list] = None, modules: list = []): + """ + Initialize the Application provided with arguments and modules. + + Args: + args: sequence of arguments to be parsed by `Application.parse_arguments()` call. + modules: list of ASAB modules to be added by `Application.add_module()` call. - Example: + Examples: + ```python class MyApplication(asab.Application): def __init__(self): super().__init__(modules=[asab.web.Module, asab.zookeeper.Module]) - ''' + ``` + """ + + self.ExitCode: typing.Union[str, int] + """ + The actual value of the exit code that can be set via `set_exit_code()` method. + + Examples: + The example of the exit code handling in the `main()` function of the application: + + ```python + if __name__ == '__main__': + app = asab.Application() + exit_code = app.run() + sys.exit(exit_code) + ``` + """ try: # EX_OK code is not available on Windows @@ -81,8 +119,15 @@ def __init__(self): self.LaunchTime = time.time() self.BaseTime = self.LaunchTime - self.Loop.time() - self.Modules = [] - self.Services = {} + self.Modules: list[asab.Module] = [] + """ + A list of modules that has been added to the application. + """ + + self.Services: dict[str, asab.Service] = {} + """ + A dictionary of registered services. + """ # Setup logging self.Logging = Logging(self) @@ -150,11 +195,28 @@ def create_argument_parser( argument_default=None, conflict_handler='error', add_help=True - ): - ''' - This method can be overriden to adjust argparse configuration. - Refer to the Python standard library to `argparse.ArgumentParser` for details of arguments. - ''' + ) -> argparse.ArgumentParser: + """ + Create an `argparse.ArgumentParser` object supplemented by default ASAB arguments. + + This method can be overridden to adjust argparse configuration. + Refer to the Python standard library to [`argparse.ArgumentParser`](https://docs.python.org/3/library/argparse.html?highlight=argumentparser#argumentparser-objects) for details of arguments. + + Default ASAB arguments: + + | Argument | Type | Action | + | :----- | :----- | :----- | + | `-c`, `--config` | str | specify a path to a configuration file | + | `-d`, `--daemonize` | bool | run daemonized (in the background) | + | `-k`, `--kill` | bool | kill a running daemon and quit | + | `-l`, `--log-file` | str | specify a path to a log file | + | `-s`, `--syslog`| bool | enable logging to a syslog | + | `-v`, `--verbose` | bool | print more information (enable debug output) | + | `-w`, `--web-api` | str | activate Asab web API (default listening port is 0.0.0.0:8080) | + | `--startup-housekeeping` | | trigger housekeeping event immediately after application startup | + + + """ parser = argparse.ArgumentParser( prog=prog, @@ -185,10 +247,13 @@ def create_argument_parser( def parse_arguments(self, args=None): """ - It parses the command line arguments and sets the default values for the configuration accordingly. + Parse the command line arguments and set the default values for the configuration accordingly. - :param args: The arguments to parse. If not set, sys.argv[1:] will be used - :return: The arguments that were parsed. + Args: + args: The arguments to parse. If not set, sys.argv[1:] will be used. + + Returns: + The arguments that were parsed. """ parser = self.create_argument_parser() @@ -217,26 +282,26 @@ def parse_arguments(self, args=None): return args - def get_pidfile_path(self): + def get_pidfile_path(self) -> typing.Optional[str]: """ - Return the `pidfile` path from the configuration. + Get the path for PID file from the configuration. - Example from the configuration: + PID file is a file that contains process id of the ASAB process. + It is used for interaction with OS respective it's control of running services. - ``` + - If the `pidfile` is set to the empty string, return None. + - If `pidfile` is set to "!", return the default PID file path (in `/var/run/` folder). + This is the default value. + + Example of PID path configuration: + + ```ini [general] pidfile=/tmp/my.pid ``` - `pidfile` is a file that contains process id of the ASAB process. - It is used for interaction with OS respective it's control of running services. - - If the `pidfile` is set to "", then return None. - - If it's set to "!", then return the default pidfile path (in `/var/run/` folder). - This is the default value. - - :return: The path to the `pidfile`. + Returns: + The path to the `pidfile`. """ pidfilepath = Config['general']['pidfile'] @@ -323,7 +388,13 @@ def daemon_kill(self): def run(self): - # Comence init-time + """Run the application. + + Returns: + (int): Exit code of the finalized process. + """ + + # Commence init-time self.PubSub.publish("Application.init!") self.Loop.run_until_complete(asyncio.gather( self._init_time_governor(), @@ -332,7 +403,7 @@ def run(self): )) try: - # Comence run-time and application main() function + # Commence run-time and application main() function L.log(LOG_NOTICE, "is ready.") self._stop_event.clear() self.Loop.run_until_complete(asyncio.gather( @@ -362,7 +433,17 @@ def run(self): return self.ExitCode - def stop(self, exit_code: int = None): + def stop(self, exit_code: typing.Optional[int] = None) -> None: + """ + Gracefully terminate the _run-time_ and commence the _exit-time_. + + This method is automatically called by `SIGINT` and `SIGTERM`. + It also includes a response to `Ctrl-C` on UNIX-like system. + When this method is called 3x, it abruptly exits the application (aka emergency abort). + + Args: + exit_code (int, optional): Exit code of the finalized process. + """ if exit_code is not None: self.set_exit_code(exit_code) @@ -388,17 +469,20 @@ def _do_restart(self, event_name): self.stop("!RESTART!") def restart(self): - ''' - Schedules a hard restart of the whole application. + """ + Schedule a hard restart of the whole application. - This function works by using os.execv(), which replaces the current process with a new one (without creating a new process ID). + This function works by using `os.execv()`, which replaces the current process with a new one (without creating a new process ID). Arguments and environment variables will be retained. - IMPORTANT: Please note that this will work on Unix-based systems only, as it uses a feature specific to Unix. + !!! warning + Please note that this will work on Unix-based systems only, as it uses a feature specific to Unix. - A piece of advice: Be careful while using this function, make sure you have some control over when and how this function is being called to avoid any unexpected process restarts. - It is not common to use these types of function calls in Python applications. - ''' + !!! hint + Be careful while using this function, make sure you have some control + over when and how this function is being called to avoid any unexpected process restarts. + It is not common to use these types of function calls in Python applications. + """ self.PubSub.subscribe("Application.tick/10!", self._do_restart) @@ -409,7 +493,7 @@ def _hup(self): # Modules - def add_module(self, module_class): + def add_module(self, module_class: asab.Module) -> None: """ Load a new module. """ @@ -428,16 +512,21 @@ def add_module(self, module_class): # Services - def get_service(self, service_name): + def get_service(self, service_name: str) -> typing.Optional[asab.Service]: """ Get a new service by its name. - Returns `None` if the service is not registered. + Args: + service_name: Name of the service to retrieve. + + Returns: + The service object associated with the provided service_name, + or None if the service is not registered. """ return self.Services.get(service_name) - def _register_service(self, service): + def _register_service(self, service: asab.Service): """ Register a new service using its name. """ @@ -456,19 +545,30 @@ def _register_service(self, service): # Lifecycle callback async def initialize(self): + """ + This method is called during the application _init-time_. It is intended to be overridden by the user. + """ pass async def main(self): + """ + This method is called during the application _run-time_. It is intended to be overridden by the user. + """ pass async def finalize(self): + """ + This method is called during the application _exit-time_. It is intended to be overridden by the user. + """ pass # Governors async def _init_time_governor(self): - # Initialize all services that has been created during application construction + """ + Initialize all services that has been created during application construction + """ await self._ensure_initialization() @@ -594,7 +694,17 @@ async def _ensure_initialization(self): L.exception("Error during service initialization") - def set_exit_code(self, exit_code: int, force: bool = False): + def set_exit_code(self, exit_code: typing.Union[str, int], force: bool = False): + """ + Set the exit code of the application. + + If `force` is `False`, the exit code will be set only if the previous value is lower than the new one. + If `force` is `True`, the exit code value is set to `exit_code` value disregarding the previous value. + + Args: + exit_code (str | int): The exit code value. + force: Force the exit code reassignment. + """ if self.ExitCode == "!RESTART!": return @@ -608,9 +718,12 @@ def set_exit_code(self, exit_code: int, force: bool = False): # Time - def time(self): + def time(self) -> float: ''' - Return UTC unix timestamp using a loop time (a fast way how to get a wall clock time). + Return UTC UNIX timestamp using a loop time (a fast way how to get a wall clock time). + + Returns: + Current UTC UNIX timestamp. ''' return self.BaseTime + self.Loop.time() @@ -620,7 +733,9 @@ def time(self): def _initialize_housekeeping_schedule(self): """ Set the next housekeeping time and time limit from configuration. - Returns: (next_housekeeping_time, next_time_limit, next_housekeeping_id) + + Returns: + (next_housekeeping_time, next_time_limit, next_housekeeping_id) """ config_house_time = datetime.datetime.strptime(Config['housekeeping']['at'], "%H:%M") # default: 03:00 config_time_limit = datetime.datetime.strptime(Config['housekeeping']['limit'], "%H:%M") # default: 05:00 @@ -645,7 +760,7 @@ def _initialize_housekeeping_schedule(self): next_time_limit = next_housekeeping_time + time_delta_limit # Each time has its id that prevents from accidental executing housekeeping twice. - next_housekeeping_id = housekeeping_id(now) + next_housekeeping_id = _housekeeping_id(now) return (next_housekeeping_time, next_time_limit, next_housekeeping_id) @@ -656,7 +771,7 @@ def _on_housekeeping_tick(self, message_type): If so, publish the message and set housekeeping time, the time limit and time id for the next day. """ now = datetime.datetime.now(datetime.timezone.utc) - today_id = housekeeping_id(now) + today_id = _housekeeping_id(now) if self.HousekeepingTime < now: if now < self.HousekeepingTimeLimit and self.HousekeepingId <= today_id: @@ -674,7 +789,7 @@ def _on_housekeeping_tick(self, message_type): self.HousekeepingTime += datetime.timedelta(days=1) self.HousekeepingTimeLimit += datetime.timedelta(days=1) - self.HousekeepingId = housekeeping_id(self.HousekeepingTime) + self.HousekeepingId = _housekeeping_id(self.HousekeepingTime) L.log( LOG_NOTICE, "Setting time for the next housekeeping.", @@ -693,7 +808,7 @@ def _on_housekeeping_tick(self, message_type): }) -def housekeeping_id(dt: datetime.datetime) -> int: +def _housekeeping_id(dt: datetime.datetime) -> int: """ Create a unique ID for each date. Utility function for housekeeping. From a33c0aa14578568e34d8fd95e6f4af49f5048610 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 18 Jul 2023 16:35:32 +0200 Subject: [PATCH 046/154] Create 'Application' section --- docs/reference/application/application.md | 188 ++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 docs/reference/application/application.md diff --git a/docs/reference/application/application.md b/docs/reference/application/application.md new file mode 100644 index 000000000..20593e223 --- /dev/null +++ b/docs/reference/application/application.md @@ -0,0 +1,188 @@ +# Application + +The `asab.Application` class maintains the global application state. You can provide your own implementation by +creating a subclass. There should be only one `Application` object in the process. + +!!! example "Creating a new asab application:" + + ```python + import asab + + class MyApplication(asab.Application): + pass + + if __name__ == '__main__': + app = MyApplication() + app.run() + ``` + +!!! example "Direct use of `Application` object:" + + ``` python + import asab + + if __name__ == '__main__': + app = asab.Application() + app.run() + ``` + + +## Application Lifecycle + +Runtime of the `Application` object is driven by `asyncio` [event loop](https://docs.python.org/3/library/asyncio-eventloop.html) which runs asynchronous tasks and callbacks, performs network IO operations, and runs subprocesses. + +The ASAB is designed around the [Inversion of +control](https://en.wikipedia.org/wiki/Inversion_of_control) principle. +It means that the ASAB is in control of the application lifecycle. The +custom-written code receives the flow from ASAB via callbacks or +handlers. Inversion of control is used to increase modularity of the +code and make it extensible. + +The application lifecycle is divided into 3 phases: init-time, run-time +and exit-time. + +- **init-time:** + The init-time happens during `Application` constructor call. + The Publish-Subscribe message `Application.init!` is published during init-time. + The `Config` is loaded during init-time. + + The application object executes asynchronous callback `Application.initialize()`, which can be overridden by an user. + + ``` python + class MyApplication(asab.Application): + async def initialize(self): + # Custom initialization + from module_sample import Module + self.add_module(Module) + ``` + +- **run-time:** + + The run-time starts after all the modules and services are loaded. This is where the application spends the most time typically. + The Publish-Subscribe message `Application.run!` is published when run-time begins. + + The method returns the value of `Application.ExitCode`. + + The application object executes asynchronous callback + `Application.main()`, which can be overridden. If `main()` method is + completed without calling `stop()`, then the application server will run + forever (this is the default behaviour). + + ``` python + class MyApplication(asab.Application): + async def main(self): + print("Hello world!") + self.stop() + ``` + + The method `Application.stop()` gracefully terminates the run-time and + commence the exit-time. This method is automatically called by `SIGINT` + and `SIGTERM`. It also includes a response to `Ctrl-C` on UNIX-like + system. When this method is called 3x, it abruptly exits the application + (aka emergency abort). + + The parameter `exit_code` allows you to specify the application exit + code. + + !!! note + You need to install :py`win32api`{.interpreted-text role="mod"} + module to use `Ctrl-C` or an emergency abord properly with ASAB on + Windows. It is an optional dependency of ASAB. + +- **exit-time:** + +The application object executes asynchronous callback +`Application.finalize()`, which can be overridden by an user. + +``` python +class MyApplication(asab.Application): + async def finalize(self): + # Custom finalization + ... +``` + +The Publish-Subscribe message `Application.exit!`{.interpreted-text +role="any"} is published when exit-time begins. + +Set the exit code of the application, see `os.exit()` in the Python +documentation. If `force` is `False`, the exit code will be set only if +the previous value is lower than the new one. If `force` is `True`, the +exit code value is set to a `exit_code` disregarding the previous value. + +The actual value of the exit code. + +The example of the exit code handling in the `main()` function of the +application. + +``` {.python} +if __name__ == '__main__': + app = asab.Application() + exit_code = app.run() + sys.exit(exit_code) +``` + +## Registering modules and services + + +For more details see :py`Module`{.interpreted-text role="class"} class. + +Initialize and add a new module. The `module_class` class will be +instantiated during the method call. + +``` python +class MyApplication(asab.Application): + async def initialize(self): + from my_module import MyModule + self.add_module(MyModule) +``` + +A list of modules that has been added to the application. + + +Each service is identified by its unique service name. For more details +see :py`Service`{.interpreted-text role="class"} class. + +Locate a service by its service name in a registry and return the +`Service` object. + +``` python +svc = app.get_service("service_sample") +svc.hello() +``` + +A dictionary of registered services. + +## Command-line parser + +Creates an `argparse.ArgumentParser`. This method can be overloaded to +adjust command-line argument parser. + +Please refer to Python standard library `argparse` for more details +about function arguments. + +The application object calls this method during init-time to process a +command-line arguments. `argparse`{.interpreted-text role="mod"} is +used to process arguments. You can overload this method to provide your +own implementation of command-line argument parser. + +The :py`Description`{.interpreted-text role="data"} attribute is a text +that will be displayed in a help text (`--help`). It is expected that +own value will be provided. The default value is `""` (empty string). + +## UTC Time + +Return the current \"event loop time\" in seconds since the epoch as a +floating point number. The specific date of the epoch and the handling +of leap seconds is platform dependent. On Windows and most Unix systems, +the epoch is January 1, 1970, 00:00:00 (UTC) and leap seconds are not +counted towards the time in seconds since the epoch. This is commonly +referred to as Unix time. + +A call of the `time.time()` function could be expensive. This method +provides a cheaper version of the call that returns a current wall time +in UTC. + +--- +## Documentation + +::: asab.application.Application \ No newline at end of file From f143fa2d23a605cf9f6460aead1f27e2223b2c07 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 18 Jul 2023 16:36:24 +0200 Subject: [PATCH 047/154] Rename chapters --- mkdocs.yml | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 6d3eab5c0..d99651cd6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -154,37 +154,10 @@ nav: - Contributing: contributing.md - - How-To Guides: + - How-To: - Creating a microservice with REST API: how-tos/03_rest_api.md - - Topics: - # - topics/asab/application.md - # - topics/asab/config.md - # - topics/asab/log.md - # - topics/asab/metrics.md - # - topics/asab/module.md - # - topics/asab/pubsub.md - # - topics/asab/service.md - - Storage: - - Introduction: topics/asab/storage/intro.md - - Manipulation with Databases: topics/asab/storage/manipulation_with_databases.md - - Encryption and Decryption: topics/asab/storage/encryption.md - - In-Memory Storage: topics/asab/storage/inmemory.md - - MongoDB Storage: topics/asab/storage/mongodb.md - - ElasticSearch Storage: topics/asab/storage/elasticsearch.md - - Metrics: - - Introduction: topics/asab/metrics/intro.md - - Tags: topics/asab/metrics/tags.md - - Built-in metrics: topics/asab/metrics/built-ins.md - - Monitoring: topics/asab/metrics/targets.md - # - topics/asab/various.md - # - topics/asab/zookeeper.md - - Reference: - # - reference/application.md - # - reference/config.md - # - reference/library.md - # - reference/log.md - Application: reference/application/application.md - Metrics: - MetricsService: reference/metrics/service.md @@ -197,7 +170,6 @@ nav: - CounterWithDynamicTags: reference/metrics/counter_with_dynamic_tags.md - AggregationCounterWithDynamicTags: reference/metrics/aggregation_counter_with_dynamic_tags.md - HistogramWithDynamicTags: reference/metrics/histogram_with_dynamic_tags.md - # - reference/module.md - Storage: - StorageService: reference/storage/service.md - Upsertor: reference/storage/upsertor.md From 7f7e7599592de658df497780ec4c70769caafefe Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 18 Jul 2023 17:45:34 +0200 Subject: [PATCH 048/154] Add docstrings to ConfigParser --- asab/config.py | 29 +++++++++++++++++++-------- docs/reference/{ => config}/config.md | 0 2 files changed, 21 insertions(+), 8 deletions(-) rename docs/reference/{ => config}/config.md (100%) diff --git a/asab/config.py b/asab/config.py index aeecc820e..bde9df309 100644 --- a/asab/config.py +++ b/asab/config.py @@ -15,6 +15,9 @@ class ConfigParser(configparser.ConfigParser): + """ + ConfigParser enhanced with new features such as adding default configuration, URL validation, automatic reading from Zookeeper etc. + """ _syslog_sockets = { 'Darwin': '/var/run/syslog' } @@ -109,8 +112,12 @@ class ConfigParser(configparser.ConfigParser): # If `ASAB_ZOOKEEPER_SERVERS` are specified, use that as a default value _default_values['zookeeper'] = {'servers': os.environ['ASAB_ZOOKEEPER_SERVERS']} - def add_defaults(self, dictionary): - """ Add defaults to a current configuration """ + def add_defaults(self, dictionary: dict) -> None: + """Add defaults to a current configuration. + + Args: + dictionary: Arguments to be added to the default configuration. + """ for section, keys in dictionary.items(): section = str(section) @@ -229,7 +236,7 @@ def _include_from_zookeeper(self, zkurl): self.config_name_list.append(tail) try: - # Delayed import to minimize a hard dependecy footprint + # Delayed import to minimize a hard dependency footprint import kazoo.client import json import yaml @@ -263,7 +270,7 @@ def get_config_contents_list(self): return self.config_contents_list, self.config_name_list - def getseconds(self, section, option, *, raw=False, vars=None, fallback=None, **kwargs): + def getseconds(self, section, option, *, raw=False, vars=None, fallback=None, **kwargs) -> float: if fallback is None: fallback = configparser._UNSET @@ -271,12 +278,18 @@ def getseconds(self, section, option, *, raw=False, vars=None, fallback=None, ** def geturl(self, section, option, raw=False, vars=None, fallback=None, scheme=None, **kwargs): - """Gets URL from config and removes all leading and trailing + """ + Get URL from config and remove all leading and trailing whitespaces and trailing slashes. - :param scheme: URL scheme(s) awaited. If None, scheme validation is bypassed. - :type scheme: str, tuple - :return: validated URL, raises ValueError when scheme requirements are not met if set. + Args: + scheme (str | tuple): URL scheme(s) awaited. If `None`, scheme validation is bypassed. + + Returns: + Validated URL. + + Raises: + ValueError: Scheme requirements are not met if set. """ return utils.validate_url(self.get(section, option, raw=False, vars=None, fallback=fallback), scheme) diff --git a/docs/reference/config.md b/docs/reference/config/config.md similarity index 100% rename from docs/reference/config.md rename to docs/reference/config/config.md From e43414328e72d4603e067642cfb3b720fbb192e3 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 19 Jul 2023 10:05:41 +0200 Subject: [PATCH 049/154] Rename How-Tos section --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index d99651cd6..0437b8ea7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -154,7 +154,7 @@ nav: - Contributing: contributing.md - - How-To: + - How-Tos: - Creating a microservice with REST API: how-tos/03_rest_api.md - Reference: From ce325ed38fcfaf7ca9be49d571ff4f0e2d635e81 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 20 Jul 2023 12:32:23 +0200 Subject: [PATCH 050/154] Add table of exit codes --- asab/application.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/asab/application.py b/asab/application.py index d012c0bfd..d36dea413 100644 --- a/asab/application.py +++ b/asab/application.py @@ -78,6 +78,12 @@ def __init__(self): exit_code = app.run() sys.exit(exit_code) ``` + + | Exit code | Usage | + | --- | --- | + | 0 | success | + | 1 | abnormal termination of a program perhaps as a result a minor problem in the code | + """ try: @@ -694,7 +700,7 @@ async def _ensure_initialization(self): L.exception("Error during service initialization") - def set_exit_code(self, exit_code: typing.Union[str, int], force: bool = False): + def set_exit_code(self, exit_code: typing.Union[int, str], force: bool = False): """ Set the exit code of the application. From 5af6f51550dd2dad2a5219a8d065b352b2d89fd1 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 21 Jul 2023 12:49:07 +0200 Subject: [PATCH 051/154] Add docstrings --- asab/config.py | 87 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/asab/config.py b/asab/config.py index bde9df309..01509d918 100644 --- a/asab/config.py +++ b/asab/config.py @@ -145,8 +145,10 @@ def add_defaults(self, dictionary: dict) -> None: self.set(section, key, value) - def _traverse_includes(self, includes, this_dir): - """ Reads included config files. Supports nested including. """ + def _traverse_includes(self, includes: str, this_dir: str) -> None: + """ + Read included config files. Nested including is supported. + """ if '\n' in includes: sep = '\n' else: @@ -185,7 +187,9 @@ def _traverse_includes(self, includes, this_dir): def _load(self): - """ This method should be called only once, any subsequent call will lead to undefined behaviour """ + """ + This method should be called only once, any subsequent call will lead to undefined behaviour. + """ self._load_dir_stack = [] self.config_contents_list = [] self.config_name_list = [] @@ -213,6 +217,26 @@ def _load(self): def _include_from_zookeeper(self, zkurl): + """ + Load the configuration from a ZooKeeper server and append it to the `self.config_contents_list` attribute. + + The method establishes a connection to the ZooKeeper server specified in the configuration file mentioned above. + It retrieves the configuration by accessing the path specified in the `general` section, using the key `includes`. + The server URL is provided as a list of server names: server1, server2, server3. + The path to the configuration file follows this format: 'zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/asab/etc/zk-site.conf.' + + The loaded configuration is then appended to the `self.config_contents_list` attribute, allowing further processing or usage. + This method supports loading configuration files in various formats, such as .json, .yaml, and .conf. + + Example: + + ```ini + [asab:zookeeper] + url=server1 server2 server3 + [general] + include=zookeeper://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/asab/etc/zk-site.conf. + ``` + """ # parse include value into hostname and path url_pieces = urllib.parse.urlparse(zkurl) url_path = url_pieces.path @@ -271,6 +295,13 @@ def get_config_contents_list(self): def getseconds(self, section, option, *, raw=False, vars=None, fallback=None, **kwargs) -> float: + """ + Get time data from config and convert time string into seconds with `convert_to_seconds()` method. + + Returns: + float: Time in seconds. + """ + if fallback is None: fallback = configparser._UNSET @@ -312,20 +343,23 @@ def before_read(self, parser, section, option, value): class Configurable(object): - ''' - Usage: - class ConfigurableObject(asab.Configurable): + """ + Custom object whose attributes can be loaded from the configuration. - ConfigDefaults = { - 'foo': 'bar', - } + Example: + ``` + class ConfigurableObject(asab.Configurable): - def __init__(self, config_section_name, config=None): - super().__init__(config_section_name=config_section_name, config=config) + ConfigDefaults = { + 'foo': 'bar', + } - config_foo = self.Config.get('foo') + def __init__(self, config_section_name, config=None): + super().__init__(config_section_name=config_section_name, config=config) - ''' + config_foo = self.Config.get('foo') + ``` + """ ConfigDefaults = {} @@ -362,7 +396,9 @@ def __init__(self, config_section_name, config=None): class ConfigObjectDict(collections.abc.MutableMapping): - + """ + A dictionary supplemented with custom methods for obtaining bools, seconds, urls etc. + """ def __init__(self): self._data = {} @@ -388,27 +424,42 @@ def __len__(self): return len(self._data) - def getboolean(self, key): + def getboolean(self, key) -> bool: + """ + Obtain the corresponding value of the key and convert it into bool. + """ value = self._data[key] return utils.string_to_boolean(value) - def getseconds(self, key): + def getseconds(self, key) -> float: + """ + Obtain the corresponding value of the key and convert it into seconds via `convert_to_seconds()` method. + """ value = self._data[key] return utils.convert_to_seconds(value) - def getint(self, key): + def getint(self, key) -> int: + """ + Obtain the corresponding value of the key and convert it into integer. + """ value = self._data[key] return int(value) - def getfloat(self, key): + def getfloat(self, key) -> float: + """ + Obtain the corresponding value of the key and convert it into float. + """ value = self._data[key] return float(value) def geturl(self, key, scheme): + """ + Obtain the corresponding value of the key and parse it via `validate_url()` method. + """ value = self._data[key] return utils.validate_url(value, scheme) From 170545dcd71c4e61d89e9543371c2134aa25e118 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 21 Jul 2023 12:57:29 +0200 Subject: [PATCH 052/154] Format python example --- asab/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asab/config.py b/asab/config.py index 01509d918..adcb6a32a 100644 --- a/asab/config.py +++ b/asab/config.py @@ -347,7 +347,7 @@ class Configurable(object): Custom object whose attributes can be loaded from the configuration. Example: - ``` + ```python class ConfigurableObject(asab.Configurable): ConfigDefaults = { From 3482d881282ed97cd14ce256695546674c5bed01 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 21 Jul 2023 13:04:08 +0200 Subject: [PATCH 053/154] Add restart exit code to the table --- asab/application.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/asab/application.py b/asab/application.py index d36dea413..e788084ea 100644 --- a/asab/application.py +++ b/asab/application.py @@ -79,10 +79,11 @@ def __init__(self): sys.exit(exit_code) ``` - | Exit code | Usage | + | Exit code | Meaning | | --- | --- | | 0 | success | | 1 | abnormal termination of a program perhaps as a result a minor problem in the code | + | "!RESTART!" | hard restart of the whole application | """ From 650686f3cd31b76238d5c3773e3021dbb1be4285 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 21 Jul 2023 13:05:16 +0200 Subject: [PATCH 054/154] Reverse int-str order --- asab/application.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asab/application.py b/asab/application.py index e788084ea..6e08ef1b2 100644 --- a/asab/application.py +++ b/asab/application.py @@ -65,7 +65,7 @@ def __init__(self): ``` """ - self.ExitCode: typing.Union[str, int] + self.ExitCode: typing.Union[int, str] """ The actual value of the exit code that can be set via `set_exit_code()` method. From 5ce8941c11442dc79ae32ed0324891bc9b89df60 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 21 Jul 2023 14:43:20 +0200 Subject: [PATCH 055/154] Unify docstring format --- asab/log.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/asab/log.py b/asab/log.py index bfa4e4e47..a9359e2ec 100644 --- a/asab/log.py +++ b/asab/log.py @@ -393,11 +393,10 @@ def __init__(self, fmt=None, datefmt=None, style='%', sd_id='sd'): class AsyncIOHandler(logging.Handler): - - ''' -A logging handler similar to a standard ``logging.handlers.SocketHandler`` that utilizes ``asyncio``. -It implements a queue for decoupling logging from a networking. The networking is fully event-driven via ``asyncio`` mechanisms. - ''' + """ + A logging handler similar to a standard `logging.handlers.SocketHandler` that utilizes `asyncio`. + It implements a queue for decoupling logging from a networking. The networking is fully event-driven via `asyncio` mechanisms. + """ def __init__(self, loop, family, sock_type, address, facility=logging.handlers.SysLogHandler.LOG_LOCAL1): logging.Handler.__init__(self) @@ -463,9 +462,9 @@ def _on_read(self): def emit(self, record): - ''' + """ This is the entry point for log entries. - ''' + """ try: msg = self.format(record).encode('utf-8') From 6269bdd31abcddf9a0a3fe425a4139180d58ad8f Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 21 Jul 2023 14:44:05 +0200 Subject: [PATCH 056/154] Extend docstrings in PersistentDict --- asab/pdict.py | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/asab/pdict.py b/asab/pdict.py index 8c21f6267..91c141a53 100644 --- a/asab/pdict.py +++ b/asab/pdict.py @@ -4,17 +4,36 @@ class PersistentDict(dict): - """ The persistent dictionary works as the regular Python dictionary but the content of the dictionary is stored in the file. - You cat think of a ``PersistentDict`` as a simple `key-value store `_. - It is not optimized for a frequent access. This class provides common ``dict`` interface. + You cat think of a `PersistentDict` as a simple [key-value store](https://en.wikipedia.org/wiki/Key-value_database). + It is not optimized for a frequent access. This class provides common `dict` interface. + + Example: + ```python + class MyApplication(asab.Application): + async def main(self): + pdict = asab.PersistentDict('./pdict.bin') + pdict.load() + counter = pdict['counter'] = pdict.setdefault('counter', 0) + 1 + print("Executed for {} times".format(counter)) + pdict.store() + self.stop() + ``` + + !!! warning + You must explicitly `load()` and `store()` content of the dictionary! - *Warning*: You must explicitly `load()` and `store()` content of the dictionary - *Warning*: You can only store objects in the persistent dictionary that are serializable. + !!! warning + You can only store objects in the persistent dictionary that are serializable. """ - def __init__(self, path): + def __init__(self, path: str): + """Initialize persistent dictionary. + + Args: + path (str): Path for the dictionary file. + """ super().__init__() # Create directory, if needed dirname = os.path.dirname(path) @@ -38,7 +57,7 @@ def load(self) -> None: def store(self) -> None: """ - Explicitly store content of persistent dictionary to file + Store content of persistent dictionary to a file. """ with shelve.open(self._path) as d: @@ -47,15 +66,16 @@ def store(self) -> None: def update(self, other=(), **kwds) -> None: """ - Update D from mapping/iterable E and F. - * If E present and has a .keys() method, does: for k in E: D[k] = E[k] - * If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v - * In either case, this is followed by: for k, v in F.items(): D[k] = v + Update persistent dictionary from mapping or iterable. - Inspired by a https://github.com/python/cpython/blob/3.8/Lib/_collections_abc.py + Examples: + ```python + >>> pdict.update({'foo': 'bar'}) + >>> pdict.update(foo='bar') + ``` """ - if isinstance(other, collections.Mapping): + if isinstance(other, collections.abc.Mapping): for key in other: self[key] = other[key] elif hasattr(other, "keys"): From 4655d9058351c7b9af42c356d9c9ae16d4ce9acd Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 21 Jul 2023 15:02:15 +0200 Subject: [PATCH 057/154] Add docstrings to utils functions --- asab/utils.py | 80 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 21 deletions(-) diff --git a/asab/utils.py b/asab/utils.py index aff3a8434..f18e4018f 100644 --- a/asab/utils.py +++ b/asab/utils.py @@ -1,11 +1,21 @@ import os import urllib.parse import configparser +import typing def convert_to_seconds(value: str) -> float: """ Parse time duration string (e.g. "3h", "20m" or "1y") and convert it into seconds. + + Args: + value: Time duration string. + + Returns: + float: Number of seconds. + + Raises: + ValueError: If the string is not in a valid format. """ if isinstance(value, (int, float)): return float(value) @@ -37,27 +47,30 @@ def convert_to_seconds(value: str) -> float: return value -def convert_to_bytes(size): +def convert_to_bytes(size: str) -> int: """ Convert a size string to bytes. The size string should be a number optionally followed by a unit (B, kB, MB, GB, or TB), e.g., "10MB". - Example of the usage: - - ``` - self.RotateAtSize = asab.utils.convert_to_bytes(asab.Config.get('general', 'rotate_size')) - ``` - - Example of the config: - - ``` - [general] - rotate_size=30G - ``` - - :param size: Size string. - :return: Size in bytes. - :raise ValueError: If the size string does not have the correct format. + Examples: + Configuration: + ```ini + [general] + rotate_size=30G + ``` + Usage: + ```python + self.RotateAtSize = asab.utils.convert_to_bytes(asab.Config.get('general', 'rotate_size')) + ``` + + Args: + size: Size string. + + Returns: + Size in bytes. + + Raises: + ValueError: If the size string does not have the correct format. """ units = { "B": 1, @@ -67,7 +80,7 @@ def convert_to_bytes(size): "GB": 10**9, "TB": 10**12, - # These are typicall shortcuts that users take, we support them as well + # These are typical shortcuts that users take, we support them as well "k": 10**3, "K": 10**3, "M": 10**6, @@ -100,7 +113,16 @@ def convert_to_bytes(size): def string_to_boolean(value: str) -> bool: """ - Convert common boolean string values (e.g. "yes" or "no") into boolean. + Convert common boolean string values (e.g. 'yes' or 'no') into boolean. + + - `True`: '1', 'yes', 'true', 'on' + - `False`: '0', 'no', 'false', 'off' + + Args: + value: A value to be parsed. + + Returns: + Value converted to bool. """ if isinstance(value, bool): return value @@ -109,7 +131,20 @@ def string_to_boolean(value: str) -> bool: return configparser.ConfigParser.BOOLEAN_STATES[value.lower()] -def validate_url(input_url: str, scheme): +def validate_url(input_url: str, scheme: typing.Union[str, typing.Tuple[str], None]) -> str: + """Parse URL, remove leading and trailing whitespaces and a trailing slash. + If `scheme` is specified, check if it matches the `input_url` scheme. + + Args: + input_url (str): URL to be parsed and validated. + scheme (str | tuple[str] | None): Requested URL schema. + + Raises: + ValueError: If `scheme` is specified and is invalid. + + Returns: + str: Parsed and validated URL. + """ # Remove leading and trailing whitespaces before parsing url = urllib.parse.urlparse(input_url.strip()) @@ -133,7 +168,10 @@ def validate_url(input_url: str, scheme): return url.geturl() -def running_in_container(): +def running_in_container() -> bool: + """ + Check if the application is running in Docker or LXC container. + """ if os.path.exists('/.dockerenv') and os.path.isfile('/proc/self/cgroup'): with open('/proc/self/cgroup', "r") as f: From 3537ca3b40352a22a1da87109ad2bc413b0a94ed Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 21 Jul 2023 15:11:29 +0200 Subject: [PATCH 058/154] Modify docstrings --- asab/utils.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/asab/utils.py b/asab/utils.py index f18e4018f..f5de46734 100644 --- a/asab/utils.py +++ b/asab/utils.py @@ -115,8 +115,8 @@ def string_to_boolean(value: str) -> bool: """ Convert common boolean string values (e.g. 'yes' or 'no') into boolean. - - `True`: '1', 'yes', 'true', 'on' - - `False`: '0', 'no', 'false', 'off' + - `True`: `1`, `'yes'`, `'true'`, `'on'` + - `False`: `0`, `'no'`, `'false'`, `'off'` Args: value: A value to be parsed. @@ -171,6 +171,9 @@ def validate_url(input_url: str, scheme: typing.Union[str, typing.Tuple[str], No def running_in_container() -> bool: """ Check if the application is running in Docker or LXC container. + + Returns: + bool: `True` if the application is running in a container. """ if os.path.exists('/.dockerenv') and os.path.isfile('/proc/self/cgroup'): From d390283d8955f40a3131585b1996eab607b2bb2c Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 21 Jul 2023 15:11:49 +0200 Subject: [PATCH 059/154] Add Utils section --- docs/reference/utils/utils.md | 1 + mkdocs.yml | 1 + 2 files changed, 2 insertions(+) create mode 100644 docs/reference/utils/utils.md diff --git a/docs/reference/utils/utils.md b/docs/reference/utils/utils.md new file mode 100644 index 000000000..ae7271ada --- /dev/null +++ b/docs/reference/utils/utils.md @@ -0,0 +1 @@ +:::asab.utils \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 0437b8ea7..5560f47dd 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -177,6 +177,7 @@ nav: - ElasticSearch: reference/storage/elasticsearch.md - MongoDB: reference/storage/mongodb.md - In-Memory: reference/storage/inmemory.md + - Utils: reference/utils/utils.md # Examples are rendered automatically with create_examples.py script # please do not modify this part manually and leave it at the bottom of the file From 762442f5774e2e47946dbe0731a7ec6482a49230 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 21 Jul 2023 15:27:35 +0200 Subject: [PATCH 060/154] Add list of tuples to docstring --- mkdocs.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 5560f47dd..91746d148 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -177,7 +177,9 @@ nav: - ElasticSearch: reference/storage/elasticsearch.md - MongoDB: reference/storage/mongodb.md - In-Memory: reference/storage/inmemory.md - - Utils: reference/utils/utils.md + - Utility functions and classes: + - Utility functions: reference/utils/utils.md + - Persistent dictionary: reference/utils/persistent_dictionary.md # Examples are rendered automatically with create_examples.py script # please do not modify this part manually and leave it at the bottom of the file From 6bd13360a847be7e1fa33e43c8abafe05d85e4de Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 21 Jul 2023 15:27:48 +0200 Subject: [PATCH 061/154] Add persistent dictionary section --- asab/pdict.py | 10 +++++++--- docs/reference/utils/persistent_dictionary.md | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 docs/reference/utils/persistent_dictionary.md diff --git a/asab/pdict.py b/asab/pdict.py index 91c141a53..1cfa524ce 100644 --- a/asab/pdict.py +++ b/asab/pdict.py @@ -64,15 +64,19 @@ def store(self) -> None: for key, value in self.items(): d[key] = value - def update(self, other=(), **kwds) -> None: + def update(self, other={}, **kwds) -> None: """ Update persistent dictionary from mapping or iterable. Examples: ```python - >>> pdict.update({'foo': 'bar'}) - >>> pdict.update(foo='bar') + >>> pdict.update({'foo': 'bar', 'moo': 'buzz'}) + >>> pdict.update(foo='bar', moo='buzz') + >>> pdict.update([('foo','bar'),('moo','buzz')]) ``` + + Args: + other: Dictionary or iterable of 2-tuples of the form (key, value) to be updated. """ if isinstance(other, collections.abc.Mapping): diff --git a/docs/reference/utils/persistent_dictionary.md b/docs/reference/utils/persistent_dictionary.md new file mode 100644 index 000000000..f03b17e58 --- /dev/null +++ b/docs/reference/utils/persistent_dictionary.md @@ -0,0 +1 @@ +::: asab.pdict.PersistentDict \ No newline at end of file From aa2d03c3d8d24c73023df06fe03e022b4a5f9cb6 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 21 Jul 2023 16:03:46 +0200 Subject: [PATCH 062/154] Extend 'Timer' docstrings --- asab/timer.py | 80 +++++++++++++++++++++-------------- docs/reference/utils/timer.md | 1 + mkdocs.yml | 1 + 3 files changed, 51 insertions(+), 31 deletions(-) create mode 100644 docs/reference/utils/timer.md diff --git a/asab/timer.py b/asab/timer.py index d303d378b..5d19a4e51 100644 --- a/asab/timer.py +++ b/asab/timer.py @@ -1,27 +1,38 @@ import asyncio +import typing class Timer(object): - ''' - T.__init__(app, handler, autorestart=False) -> Timer. - + """ The relative and optionally repeating timer for asyncio. - This class is simple relative timer that generate an event after a given time, and optionally repeating in regular intervals after that. + This class is simple relative timer that generate an event after a given time, + and optionally repeating in regular intervals after that. + The timer object is initialized as stopped. - :param app: An ASAB application. - :param handler: A coro or future that will be called when a timer triggers. - :param boolean autorestart: If `True` then a timer will be automatically restarted after triggering. + Attributes: + App (asab.Application): Reference to the ASAB application. + Handler (asyncio.Coroutine | asyncio.Task): A coroutine or future that will be called when a timer triggers. + Task (asyncio.Future | asyncio.Task | None): A future that represents the timer task. + AutoRestart (bool): If `True` then a timer will be automatically restarted after triggering. - :ivar Handler: A coro or future that will be called when a timer triggers. - :ivar Task: A future that represent the timer task. - :ivar App: An ASAB app. - :ivar boolean AutoRestart: If `True` then a timer will be automatically restarted after triggering. + Examples: + ```python + class TimerApplication(asab.Application): + async def initialize(self): + self.Timer = asab.Timer(self, self.on_tick, autorestart=True) + self.Timer.start(1) #(1) - The timer object is initialized as stopped. + async def on_tick(self): #(2) + print("Think!") + ``` - *Note*: The implementation idea is borrowed from "`Python - Timer with asyncio/coroutine `_" question on StackOverflow. - ''' + 1. The timer will trigger a message publishing at every second. + 2. This function has to be a coroutine. + + !!! note + The implementation idea was borrowed from [StackOverflow discussion](https://stackoverflow.com/questions/45419723/python-timer-with-asyncio-coroutine). + """ def __init__(self, app, handler, autorestart=False): self.App = app @@ -32,43 +43,50 @@ def __init__(self, app, handler, autorestart=False): app.PubSub.subscribe("Application.stop!", self._on_stop) - def start(self, timeout): - ''' - Start the timer. + def start(self, timeout: typing.Union[int, float]): + """ + Start the `Timer` with new timeout. + + Args: + timeout (int | float): A timer delay in seconds. - :param float/int timeout: A timer delay in seconds. - ''' + Raises: + RuntimeError: If the `Timer` has already started. + """ if self.is_started(): raise RuntimeError("Timer is already started") self.Task = asyncio.ensure_future(self._job(timeout)) def stop(self): - ''' + """ Stop the timer. - ''' + """ if self.Task is not None: self.Task.cancel() self.Task = None - def restart(self, timeout): - ''' - Restart the timer. + def restart(self, timeout: typing.Union[int, float]): + """ + Restart the timer with a new timeout. - :param float/int timeout: A timer delay in seconds. - ''' + Args: + timeout (int | float): A new timeout in seconds. + """ if self.is_started(): self.stop() self.start(timeout) - def is_started(self): - ''' - T.is_started() -> boolean - Return `True` is the timer is started otherwise returns `False`. - ''' + def is_started(self) -> bool: + """ + Check if the `Timer` has started. + + Returns: + `True` if the `Timer` has started. + """ return self.Task is not None diff --git a/docs/reference/utils/timer.md b/docs/reference/utils/timer.md new file mode 100644 index 000000000..c122cdb45 --- /dev/null +++ b/docs/reference/utils/timer.md @@ -0,0 +1 @@ +::: asab.timer.Timer \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 91746d148..a6c7ec5fc 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -180,6 +180,7 @@ nav: - Utility functions and classes: - Utility functions: reference/utils/utils.md - Persistent dictionary: reference/utils/persistent_dictionary.md + - Timer: reference/utils/timer.md # Examples are rendered automatically with create_examples.py script # please do not modify this part manually and leave it at the bottom of the file From e0141b52a18d6c9038ced01bb02acad765f120d6 Mon Sep 17 00:00:00 2001 From: Ales Teska Date: Sun, 23 Jul 2023 13:58:00 +0200 Subject: [PATCH 063/154] Add a GitLab CI/CD --- .gitlab-ci.yml | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000..d1a874d57 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,44 @@ +stages: + - deploy + +deploy staging: + stage: deploy + tags: + - docker + image: + name: squidfunk/mkdocs-material + entrypoint: [""] + script: + - apk update && apk add openssh-client rsync + - pip3 install mkdocs-print-site-plugin mkdocs-awesome-pages-plugin mkdocs-glightbox + - mkdir -p ~/.ssh + - echo "$DEPLOY_PRIVATE_KEY" > ~/.ssh/id_rsa + - chmod 600 ~/.ssh/id_rsa + - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config + - mkdir /output + - mkdocs build --site-dir /output + - (cd ./cs && mkdocs build --site-dir /output/cs) + - rsync -r -a -v -e ssh --delete /output/ "$RSYNC_USER"@"$TARGET_SERVER":"$STAGING_DIR" + only: + - "docs/mkdocs-migration" + +deploy production: + stage: deploy + tags: + - docker + image: + name: squidfunk/mkdocs-material + entrypoint: [""] + script: + - apk update && apk add openssh-client rsync + - pip3 install mkdocs-print-site-plugin mkdocs-awesome-pages-plugin mkdocs-glightbox + - mkdir -p ~/.ssh + - echo "$DEPLOY_PRIVATE_KEY" > ~/.ssh/id_rsa + - chmod 600 ~/.ssh/id_rsa + - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config + - mkdir /output + - mkdocs build --site-dir /output + - (cd ./cs && mkdocs build --site-dir /output/cs) + - rsync -r -a -v -e ssh --delete /output/ "$RSYNC_USER"@"$TARGET_SERVER":"$PRODUCTION_DIR" + only: + - production From 0aafba680680f5d0d09fb85d0f60bd851fb07764 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 24 Jul 2023 08:49:20 +0200 Subject: [PATCH 064/154] Update gitlab dependencies --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d1a874d57..40e45621f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -31,7 +31,7 @@ deploy production: entrypoint: [""] script: - apk update && apk add openssh-client rsync - - pip3 install mkdocs-print-site-plugin mkdocs-awesome-pages-plugin mkdocs-glightbox + - pip3 install mkdocs-print-site-plugin mkdocs-awesome-pages-plugin mkdocs-glightbox mkdocstrings mkdocstrings[python] - mkdir -p ~/.ssh - echo "$DEPLOY_PRIVATE_KEY" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa From 5674900dcc64c8e88e5a688b3393a54d0be37fdf Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 24 Jul 2023 09:09:03 +0200 Subject: [PATCH 065/154] Add dependencies to deploy staging --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 40e45621f..44c59b569 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ deploy staging: entrypoint: [""] script: - apk update && apk add openssh-client rsync - - pip3 install mkdocs-print-site-plugin mkdocs-awesome-pages-plugin mkdocs-glightbox + - pip3 install mkdocs-print-site-plugin mkdocs-awesome-pages-plugin mkdocs-glightbox mkdocstrings mkdocstrings[python] - mkdir -p ~/.ssh - echo "$DEPLOY_PRIVATE_KEY" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa From 0d2294882eeb9230d7f03fa342e9a429e7e0b0be Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 24 Jul 2023 09:55:11 +0200 Subject: [PATCH 066/154] Add git revision plugin --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 44c59b569..9f651ce9a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ deploy staging: entrypoint: [""] script: - apk update && apk add openssh-client rsync - - pip3 install mkdocs-print-site-plugin mkdocs-awesome-pages-plugin mkdocs-glightbox mkdocstrings mkdocstrings[python] + - pip3 install mkdocs-print-site-plugin mkdocs-awesome-pages-plugin mkdocs-glightbox mkdocstrings mkdocstrings[python] mkdocs-git-revision-date-localized-plugin - mkdir -p ~/.ssh - echo "$DEPLOY_PRIVATE_KEY" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa @@ -31,7 +31,7 @@ deploy production: entrypoint: [""] script: - apk update && apk add openssh-client rsync - - pip3 install mkdocs-print-site-plugin mkdocs-awesome-pages-plugin mkdocs-glightbox mkdocstrings mkdocstrings[python] + - pip3 install mkdocs-print-site-plugin mkdocs-awesome-pages-plugin mkdocs-glightbox mkdocstrings mkdocstrings[python] mkdocs-git-revision-date-localized-plugin - mkdir -p ~/.ssh - echo "$DEPLOY_PRIVATE_KEY" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa From d149190e75488c0658f8c6b2f032f3be9661be67 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 24 Jul 2023 11:13:53 +0200 Subject: [PATCH 067/154] Disable Czech site-build --- .gitlab-ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9f651ce9a..216d184b8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,7 +17,8 @@ deploy staging: - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config - mkdir /output - mkdocs build --site-dir /output - - (cd ./cs && mkdocs build --site-dir /output/cs) + # For other languages + # - (cd ./cs && mkdocs build --site-dir /output/cs) - rsync -r -a -v -e ssh --delete /output/ "$RSYNC_USER"@"$TARGET_SERVER":"$STAGING_DIR" only: - "docs/mkdocs-migration" @@ -38,7 +39,8 @@ deploy production: - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config - mkdir /output - mkdocs build --site-dir /output - - (cd ./cs && mkdocs build --site-dir /output/cs) + # For other languages + # - (cd ./cs && mkdocs build --site-dir /output/cs) - rsync -r -a -v -e ssh --delete /output/ "$RSYNC_USER"@"$TARGET_SERVER":"$PRODUCTION_DIR" only: - production From cc4659a498765e95ff2f53239a729d0f38c845b1 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 25 Jul 2023 09:56:56 +0200 Subject: [PATCH 068/154] Edit rsync path --- .gitlab-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 216d184b8..6c87976ed 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,7 +19,8 @@ deploy staging: - mkdocs build --site-dir /output # For other languages # - (cd ./cs && mkdocs build --site-dir /output/cs) - - rsync -r -a -v -e ssh --delete /output/ "$RSYNC_USER"@"$TARGET_SERVER":"$STAGING_DIR" + # - rsync -r -a -v -e ssh --delete /output/ "$RSYNC_USER"@"$TARGET_SERVER":"$STAGING_DIR" + - rsync -r -a -v -e ssh --delete /output/ "$TARGET_SERVER":"$STAGING_DIR" only: - "docs/mkdocs-migration" From 362cd72e0c3a9b4228be15cddbb546be98b32221 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 25 Jul 2023 10:56:36 +0200 Subject: [PATCH 069/154] Edit path --- .gitlab-ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6c87976ed..216d184b8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,8 +19,7 @@ deploy staging: - mkdocs build --site-dir /output # For other languages # - (cd ./cs && mkdocs build --site-dir /output/cs) - # - rsync -r -a -v -e ssh --delete /output/ "$RSYNC_USER"@"$TARGET_SERVER":"$STAGING_DIR" - - rsync -r -a -v -e ssh --delete /output/ "$TARGET_SERVER":"$STAGING_DIR" + - rsync -r -a -v -e ssh --delete /output/ "$RSYNC_USER"@"$TARGET_SERVER":"$STAGING_DIR" only: - "docs/mkdocs-migration" From 6e5d4383b72118ee05e0dfdd0591c0d5bfaea247 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 27 Jul 2023 14:32:55 +0200 Subject: [PATCH 070/154] Add favicon --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index a6c7ec5fc..a9da9ee19 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -7,6 +7,7 @@ repo_name: TeskaLabs/asab theme: name: "material" logo: images/teskalabs-logo.svg + favicon: images/teskalabs-logo.svg features: - content.code.copy From fcbbc86d3d0bf8ebf893d98fb26a4fe065c3d6ad Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 27 Jul 2023 15:31:01 +0200 Subject: [PATCH 071/154] Remove rst relics --- .../application/{application.md => reference.md} | 15 +++++++-------- mkdocs.yml | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) rename docs/reference/application/{application.md => reference.md} (92%) diff --git a/docs/reference/application/application.md b/docs/reference/application/reference.md similarity index 92% rename from docs/reference/application/application.md rename to docs/reference/application/reference.md index 20593e223..f07fa84cc 100644 --- a/docs/reference/application/application.md +++ b/docs/reference/application/reference.md @@ -85,7 +85,7 @@ and exit-time. code. !!! note - You need to install :py`win32api`{.interpreted-text role="mod"} + You need to install :py`win32api` module to use `Ctrl-C` or an emergency abord properly with ASAB on Windows. It is an optional dependency of ASAB. @@ -101,8 +101,7 @@ class MyApplication(asab.Application): ... ``` -The Publish-Subscribe message `Application.exit!`{.interpreted-text -role="any"} is published when exit-time begins. +The Publish-Subscribe message `Application.exit!` is published when exit-time begins. Set the exit code of the application, see `os.exit()` in the Python documentation. If `force` is `False`, the exit code will be set only if @@ -114,7 +113,7 @@ The actual value of the exit code. The example of the exit code handling in the `main()` function of the application. -``` {.python} +```python if __name__ == '__main__': app = asab.Application() exit_code = app.run() @@ -124,7 +123,7 @@ if __name__ == '__main__': ## Registering modules and services -For more details see :py`Module`{.interpreted-text role="class"} class. +For more details see `Module` class. Initialize and add a new module. The `module_class` class will be instantiated during the method call. @@ -140,7 +139,7 @@ A list of modules that has been added to the application. Each service is identified by its unique service name. For more details -see :py`Service`{.interpreted-text role="class"} class. +see `Service` class. Locate a service by its service name in a registry and return the `Service` object. @@ -161,11 +160,11 @@ Please refer to Python standard library `argparse` for more details about function arguments. The application object calls this method during init-time to process a -command-line arguments. `argparse`{.interpreted-text role="mod"} is +command-line arguments. `argparse` is used to process arguments. You can overload this method to provide your own implementation of command-line argument parser. -The :py`Description`{.interpreted-text role="data"} attribute is a text +The `Description` attribute is a text that will be displayed in a help text (`--help`). It is expected that own value will be provided. The default value is `""` (empty string). diff --git a/mkdocs.yml b/mkdocs.yml index a9da9ee19..4e59332be 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -159,7 +159,7 @@ nav: - Creating a microservice with REST API: how-tos/03_rest_api.md - Reference: - - Application: reference/application/application.md + - Application: reference/application/reference.md - Metrics: - MetricsService: reference/metrics/service.md - Gauge: reference/metrics/gauge.md From 5a733d01a354e8501c645f6b4ce0b2c11e7e11e7 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 27 Jul 2023 15:55:13 +0200 Subject: [PATCH 072/154] Create subheaders --- docs/reference/application/reference.md | 77 +++++++++++++------------ 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/docs/reference/application/reference.md b/docs/reference/application/reference.md index f07fa84cc..cef02b59c 100644 --- a/docs/reference/application/reference.md +++ b/docs/reference/application/reference.md @@ -41,55 +41,56 @@ code and make it extensible. The application lifecycle is divided into 3 phases: init-time, run-time and exit-time. -- **init-time:** - The init-time happens during `Application` constructor call. - The Publish-Subscribe message `Application.init!` is published during init-time. - The `Config` is loaded during init-time. +### Init-time - The application object executes asynchronous callback `Application.initialize()`, which can be overridden by an user. +The init-time happens during `Application` constructor call. +The Publish-Subscribe message `Application.init!` is published during init-time. +The `Config` is loaded during init-time. - ``` python - class MyApplication(asab.Application): - async def initialize(self): - # Custom initialization - from module_sample import Module - self.add_module(Module) - ``` +The application object executes asynchronous callback `Application.initialize()`, which can be overridden by an user. -- **run-time:** +``` python +class MyApplication(asab.Application): + async def initialize(self): + # Custom initialization + from module_sample import Module + self.add_module(Module) +``` - The run-time starts after all the modules and services are loaded. This is where the application spends the most time typically. - The Publish-Subscribe message `Application.run!` is published when run-time begins. +### Run-time - The method returns the value of `Application.ExitCode`. +The run-time starts after all the modules and services are loaded. This is where the application spends the most time typically. +The Publish-Subscribe message `Application.run!` is published when run-time begins. - The application object executes asynchronous callback - `Application.main()`, which can be overridden. If `main()` method is - completed without calling `stop()`, then the application server will run - forever (this is the default behaviour). +The method returns the value of `Application.ExitCode`. - ``` python - class MyApplication(asab.Application): - async def main(self): - print("Hello world!") - self.stop() - ``` +The application object executes asynchronous callback +`Application.main()`, which can be overridden. If `main()` method is +completed without calling `stop()`, then the application server will run +forever (this is the default behaviour). + +``` python +class MyApplication(asab.Application): + async def main(self): + print("Hello world!") + self.stop() +``` - The method `Application.stop()` gracefully terminates the run-time and - commence the exit-time. This method is automatically called by `SIGINT` - and `SIGTERM`. It also includes a response to `Ctrl-C` on UNIX-like - system. When this method is called 3x, it abruptly exits the application - (aka emergency abort). +The method `Application.stop()` gracefully terminates the run-time and +commence the exit-time. This method is automatically called by `SIGINT` +and `SIGTERM`. It also includes a response to `Ctrl-C` on UNIX-like +system. When this method is called 3x, it abruptly exits the application +(aka emergency abort). - The parameter `exit_code` allows you to specify the application exit - code. +The parameter `exit_code` allows you to specify the application exit +code. - !!! note - You need to install :py`win32api` - module to use `Ctrl-C` or an emergency abord properly with ASAB on - Windows. It is an optional dependency of ASAB. +!!! note + You need to install :py`win32api` + module to use `Ctrl-C` or an emergency abord properly with ASAB on + Windows. It is an optional dependency of ASAB. -- **exit-time:** +### Exit-time The application object executes asynchronous callback `Application.finalize()`, which can be overridden by an user. From 88cb35c2d88548ee697b375b5d91eb6cb97f9b9b Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 27 Jul 2023 15:55:24 +0200 Subject: [PATCH 073/154] Add logging section --- docs/reference/log.md | 1 - docs/reference/logging/reference.md | 241 ++++++++++++++++++++++++++++ mkdocs.yml | 2 + 3 files changed, 243 insertions(+), 1 deletion(-) delete mode 100644 docs/reference/log.md create mode 100644 docs/reference/logging/reference.md diff --git a/docs/reference/log.md b/docs/reference/log.md deleted file mode 100644 index 3a5afed73..000000000 --- a/docs/reference/log.md +++ /dev/null @@ -1 +0,0 @@ -::: asab.log \ No newline at end of file diff --git a/docs/reference/logging/reference.md b/docs/reference/logging/reference.md new file mode 100644 index 000000000..31a88a38f --- /dev/null +++ b/docs/reference/logging/reference.md @@ -0,0 +1,241 @@ +Logging +======= + +ASAB logging is built on top of a standard Python `logging` module. It +means that it logs to `stderr` when running on a console and ASAB also +provides file and syslog output (both RFC5424 and RFC3164) for +background mode of operations. + +Log timestamps are captured with sub-second precision (depending on the +system capabilities) and displayed including microsecond part. + +Recommended use +--------------- + +We recommend to create a logger `L` in every module that captures all +necessary logging output. Alternative logging strategies are also +supported. + +``` {.python} +import logging +L = logging.getLogger(__name__) + +... + +L.warning("Hello world!") +``` + +Example of the output to the console: + +`25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule Hello world!` + +Logging Levels +-------------- + +ASAB uses Python logging levels with the addition of `LOG_NOTICE` level. +`LOG_NOTICE` level is similar to `logging.INFO` level but it is visible +in even in non-verbose mode. + +``` {.python} +L.log(asab.LOG_NOTICE, "This message will be visible regardless verbose configuration.") +``` + + --------------------------------------------------------------- + Level Numeric value Syslog Severity level + ---------------- --------------- ------------------------------ + `CRITICAL` 50 Critical / `crit` / 2 + + `ERROR` 40 Error / `err` / 3 + + `WARNING` 30 Warning / `warning` / 4 + + `LOG_NOTICE` 25 Notice / `notice` / 5 + + `INFO` 20 Informational / `info` / 6 + + `DEBUG` 10 Debug / `debug` / 7 + + `NOTSET` 0 + --------------------------------------------------------------- + +Example of a custom level configuration: + +``` {.ini} +[logging] +levels= + myApp.module1 DEBUG + myApp.module2 WARNING + customLogger ERROR +``` + +The logger name and the corresponding logging level are separated by a +space, each logger is on a separate line. + +Verbose mode +------------ + +The command-line argument `-v` enables verbose logging. It means that +log entries with levels `DEBUG` and `INFO` will be visible. It also +enables `asyncio` debug logging. + +The actual verbose mode is avaiable at +`asab.Config["logging"]["verbose"]` boolean option. + +``` {.python} +L.debug("This message will be visible only in verbose mode.") +``` + +Structured data +--------------- + +ASAB supports a structured data to be added to a log entry. It follows +the [RFC 5424](https://tools.ietf.org/html/rfc5424), section +`STRUCTURED-DATA`. Structured data are a dictionary, that has to be +seriazable to JSON. + +``` {.python} +L.warning("Hello world!", struct_data={'key1':'value1', 'key2':2}) +``` + +Example of the output to the console: + +`25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule [sd key1="value1" key2="2"] Hello world!` + +Logging to file +--------------- + +The command-line argument `-l` on command-line enables logging to file. +Also non-empty `path` option in the section `[logging:file]` of +configuration file enables logging to file as well. + +Example of the configuration file section: + +``` {.ini} +[logging:file] +path=/var/log/asab.log +format="%%(asctime)s %%(levelname)s %%(name)s %%(struct_data)s%%(message)s", +datefmt="%%d-%%b-%%Y %%H:%%M:%%S.%%f" +backup_count=3 +rotate_every=1d +``` + +When the deployment expects more instances of the same application to be +logging into the same file, it is recommended, that the variable +hostname is used in the file path: + +``` {.ini} +[logging:file] +path=/var/log/${HOSTNAME}/asab.log +``` + +In this way, the applications will log to seperate log files in +different folders, which is an intended behavior, since race conditions +may occur when different application instances log into the same file. + +Logging to console +------------------ + +ASAB will log to the console only if it detects that it runs in the +foreground respectively on the terminal using `os.isatty` or if the +environment variable `ASABFORCECONSOLE` is set to `1`. This is useful +setup for eg. PyCharm. + +### Log rotation + +ASAB supports a [log +rotation](https://en.wikipedia.org/wiki/Log_rotation). The log rotation +is triggered by a UNIX signal `SIGHUP`, which can be used e.g. to +integrate with `logrotate` utility. It is implemented using +`logging.handlers.RotatingFileHandler` from a Python standard library. +Also, a time-based log rotation can be configured using `rotate_every` +option. + +`backup_count` specifies a number of old files to be kept prior their +removal. The system will save old log files by appending the extensions +'.1', '.2' etc., to the filename. + +`rotate_every` specifies an time interval of a log rotation. Default +value is empty string, which means that the time-based log rotation is +disabled. The interval is specified by an integer value and an unit, +e.g. 1d (for 1 day) or 30M (30 minutes). Known units are [H]{.title-ref} +for hours, [M]{.title-ref} for minutes, [d]{.title-ref} for days and +[s]{.title-ref} for seconds. + +Logging to syslog +----------------- + +The command-line argument `-s` enables logging to syslog. + +A configuration section `[logging:syslog]` can be used to specify +details about desired syslog logging. + +Example of the configuration file section: + +``` {.ini} +[logging:syslog] +enabled=true +format=5 +address=tcp://syslog.server.lan:1554/ +``` + +`enabled` is equivalent to command-line switch `-s` and it enables +syslog logging target. + +`format` speficies which logging format will be used. Possible values +are: + +- `5` for (new) syslog format ([RFC + 5424](https://tools.ietf.org/html/rfc5424) ) , +- `3` for old BSD syslog format ([RFC + 3164](https://tools.ietf.org/html/rfc3164) ), typically used by + `/dev/log` and +- `m` for Mac OSX syslog flavour that is based on BSD syslog format + but it is not fully compatible. + +The default value is `3` on Linux and `m` on Mac OSX. + +`address` specifies the location of the Syslog server. It could be a +UNIX path such as `/dev/log` or URL. Possible URL values: + +- `tcp://syslog.server.lan:1554/` for Syslog over TCP +- `udp://syslog.server.lan:1554/` for Syslog over UDP +- `unix-connect:///path/to/syslog.socket` for Syslog over UNIX socket + (stream) +- `unix-sendto:///path/to/syslog.socket` for Syslog over UNIX socket + (datagram), equivalent to `/path/to/syslog.socket`, used by a + `/dev/log`. + +The default value is a `/dev/log` on Linux or `/var/run/syslog` on Mac +OSX. + +Logging of obsolete features +---------------------------- + +It proved to be essential to inform operators about features that are +going to be obsoleted. ASAB offers the unified \"obsolete\" logger. This +logger can indicate that a particular feature is marked as \"obsolete\" +thru logs. Such a log message can then be \"grepped\" from logs +uniformly. + +It is recommended to include [eol]{.title-ref} attribute in the +[struct\_data]{.title-ref} of the log with a [YYYY-MM-DD]{.title-ref} +date/time of the planned obsoletion of the feature. + +Hint: We suggest automating the detection of obsolete warnings in logs +so that the operations are informed well ahead of the actual removal of +the feature. The string to seek in logs is \" OBSOLETE \". + +Example of the use: + +``` {.python} +asab.LogObsolete.warning("Use of the obsolete function", struct_data={'eol':'2022-31-12'}) +``` + +Log example: + +`21-Jul-2022 14:32:40.983884 WARNING OBSOLETE [eol="2022-31-12"] Use of the obsolete function` + +Reference +--------- + +::: asab.log diff --git a/mkdocs.yml b/mkdocs.yml index 4e59332be..3fa298269 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -160,6 +160,8 @@ nav: - Reference: - Application: reference/application/reference.md + - Configuration: reference/config/config.md + - Logging: reference/logging/reference.md - Metrics: - MetricsService: reference/metrics/service.md - Gauge: reference/metrics/gauge.md From 4e890fccb46d6caca9d1748a61c73e05776cb713 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 27 Jul 2023 17:57:43 +0200 Subject: [PATCH 074/154] Add docstring to LOG_NOTICE --- asab/log.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/asab/log.py b/asab/log.py index a9359e2ec..5001a435f 100644 --- a/asab/log.py +++ b/asab/log.py @@ -16,8 +16,12 @@ from .timer import Timer from .utils import running_in_container -# Non-error/warning type of message that is visible without -v flag + LOG_NOTICE = 25 +""" +Info log level that is visible in non-verbose mode. It should not be used for warnings and errors. +""" + logging.addLevelName(LOG_NOTICE, "NOTICE") From a05dd753295a597839cc5401ca0ae65ba51ea8eb Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 27 Jul 2023 17:58:28 +0200 Subject: [PATCH 075/154] Convert to markdown format --- docs/reference/logging/reference.md | 269 ++++++++++++++++------------ 1 file changed, 156 insertions(+), 113 deletions(-) diff --git a/docs/reference/logging/reference.md b/docs/reference/logging/reference.md index 31a88a38f..725c997e5 100644 --- a/docs/reference/logging/reference.md +++ b/docs/reference/logging/reference.md @@ -1,150 +1,191 @@ -Logging -======= +# Logging -ASAB logging is built on top of a standard Python `logging` module. It -means that it logs to `stderr` when running on a console and ASAB also -provides file and syslog output (both RFC5424 and RFC3164) for +ASAB logging is built on top of [`logging` module](https://docs.python.org/3/library/logging.html). +It provides the standard logging to `stderr` output when running on a console and also file and syslog output (both RFC5424 and RFC3164) for background mode of operations. Log timestamps are captured with sub-second precision (depending on the system capabilities) and displayed including microsecond part. -Recommended use ---------------- +## Recommended use We recommend to create a logger `L` in every module that captures all necessary logging output. Alternative logging strategies are also supported. -``` {.python} -import logging -L = logging.getLogger(__name__) +!!! example -... + The following code -L.warning("Hello world!") -``` + ```python title="myapp/mymodule.py" + import logging + L = logging.getLogger(__name__) + ... + + L.warning("Hello world!") + ``` -Example of the output to the console: + will produce the following output to the console: -`25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule Hello world!` + ``` + 25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule Hello world! + ``` -Logging Levels --------------- + +## Logging Levels ASAB uses Python logging levels with the addition of `LOG_NOTICE` level. `LOG_NOTICE` level is similar to `logging.INFO` level but it is visible in even in non-verbose mode. -``` {.python} -L.log(asab.LOG_NOTICE, "This message will be visible regardless verbose configuration.") -``` - - --------------------------------------------------------------- - Level Numeric value Syslog Severity level - ---------------- --------------- ------------------------------ - `CRITICAL` 50 Critical / `crit` / 2 +Level | Numeric value | Syslog Severity level | +| --- | --- | --- | +| `CRITICAL` | 50 | Critical / `crit` / 2 | +| `ERROR` | 40 | Error / `err` / 3 | +| `WARNING` | 30 | Warning / `warning` / 4 | +| `LOG_NOTICE` | 25 | Notice / `notice` / 5 | +| `INFO` | 20 | Informational / `info` / 6 | +| `DEBUG` | 10 | Debug / `debug` / 7 | +| `NOTSET` | 0 | | - `ERROR` 40 Error / `err` / 3 - `WARNING` 30 Warning / `warning` / 4 +!!! example "Usage of the `LOG_NOTICE` level:" - `LOG_NOTICE` 25 Notice / `notice` / 5 + ```python + L.log(asab.LOG_NOTICE, "This message will be visible regardless verbose configuration.") + ``` - `INFO` 20 Informational / `info` / 6 +!!! example "Setting the level for the entire application:" - `DEBUG` 10 Debug / `debug` / 7 + ```ini + [logging] + level=DEBUG + ``` - `NOTSET` 0 - --------------------------------------------------------------- +!!! example "Setting levels for particular modules:" -Example of a custom level configuration: + ```ini + [logging] + levels= + myApp.module1 DEBUG + myApp.module2 WARNING + ``` -``` {.ini} -[logging] -levels= - myApp.module1 DEBUG - myApp.module2 WARNING - customLogger ERROR -``` + The logger name and the corresponding logging level are separated by a + space, each logger is on a separate line. -The logger name and the corresponding logging level are separated by a -space, each logger is on a separate line. -Verbose mode ------------- +## Verbose mode The command-line argument `-v` enables verbose logging. It means that log entries with levels `DEBUG` and `INFO` will be visible. It also enables `asyncio` debug logging. -The actual verbose mode is avaiable at -`asab.Config["logging"]["verbose"]` boolean option. +The actual verbose mode is available at `asab.Config["logging"]["verbose"]` boolean option. -``` {.python} -L.debug("This message will be visible only in verbose mode.") -``` +!!! example -Structured data ---------------- + There are three options to display `DEBUG` and `INFO` log messages. -ASAB supports a structured data to be added to a log entry. It follows -the [RFC 5424](https://tools.ietf.org/html/rfc5424), section -`STRUCTURED-DATA`. Structured data are a dictionary, that has to be -seriazable to JSON. + 1. + ```ini + [logging] + verbose=true + ``` + 2. + ```ini + [logging] + level=DEBUG + ``` + 3. + ```shell + python3 myapp.py -v + ``` + +## Structured data + +ASAB supports a structured data to be added to a log entry. Structured data are passed to the log message as a dictionary that has to be JSON-serializable. + +!!! example + + The following warning message with structured data + + ```python title="myapp/mymodule.py" + L.warning("Hello world!", struct_data={'key1':'value1', 'key2':2}) + ``` + + will produce the following output to the console: + + ``` + 25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule [sd key1="value1" key2="2"] Hello world! + ``` -``` {.python} -L.warning("Hello world!", struct_data={'key1':'value1', 'key2':2}) -``` -Example of the output to the console: +!!! info + ASAB structured data logging follows the [RFC 5424](https://datatracker.ietf.org/doc/html/rfc5424#section-6.3). -`25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule [sd key1="value1" key2="2"] Hello world!` -Logging to file ---------------- +!!! tip + + Use logging with structured data to provide better error messages: + + ```python title='myapp/mymodule.py' + try: + print(a / b) + except ZeroDivisionError: + L.error("Division by zero.", struct_data={"a": a, "b": b}) + ``` + + Output: + + ``` + 27-Jul-2023 16:54:22.311522 ERROR myapp.mymodule [sd a="24" b="0"] Division by zero. + ``` + +## Logging to a file The command-line argument `-l` on command-line enables logging to file. Also non-empty `path` option in the section `[logging:file]` of configuration file enables logging to file as well. -Example of the configuration file section: +!!! example "Example of the configuration file section:" -``` {.ini} -[logging:file] -path=/var/log/asab.log -format="%%(asctime)s %%(levelname)s %%(name)s %%(struct_data)s%%(message)s", -datefmt="%%d-%%b-%%Y %%H:%%M:%%S.%%f" -backup_count=3 -rotate_every=1d -``` + ```ini + [logging:file] + path=/var/log/asab.log + format="%(asctime)s %(levelname)s %(name)s %(struct_data)s%(message)s", + datefmt="%d-%b-%Y %H:%M:%S.%f" + backup_count=3 + rotate_every=1d #(1)! + ``` + + 1. When reading this configuration, `asab.Config.getseconds()` method is used. When the deployment expects more instances of the same application to be logging into the same file, it is recommended, that the variable hostname is used in the file path: -``` {.ini} +```ini [logging:file] path=/var/log/${HOSTNAME}/asab.log ``` -In this way, the applications will log to seperate log files in +In this way, the applications will log to separate log files in different folders, which is an intended behavior, since race conditions may occur when different application instances log into the same file. -Logging to console ------------------- +## Logging to console + ASAB will log to the console only if it detects that it runs in the foreground respectively on the terminal using `os.isatty` or if the environment variable `ASABFORCECONSOLE` is set to `1`. This is useful setup for eg. PyCharm. -### Log rotation +## Log rotation -ASAB supports a [log -rotation](https://en.wikipedia.org/wiki/Log_rotation). The log rotation -is triggered by a UNIX signal `SIGHUP`, which can be used e.g. to +ASAB supports a [log rotation](https://en.wikipedia.org/wiki/Log_rotation). +The log rotation is triggered by a UNIX signal `SIGHUP`, which can be used e.g. to integrate with `logrotate` utility. It is implemented using `logging.handlers.RotatingFileHandler` from a Python standard library. Also, a time-based log rotation can be configured using `rotate_every` @@ -161,8 +202,8 @@ e.g. 1d (for 1 day) or 30M (30 minutes). Known units are [H]{.title-ref} for hours, [M]{.title-ref} for minutes, [d]{.title-ref} for days and [s]{.title-ref} for seconds. -Logging to syslog ------------------ +## Logging to syslog + The command-line argument `-s` enables logging to syslog. @@ -171,7 +212,7 @@ details about desired syslog logging. Example of the configuration file section: -``` {.ini} +```ini [logging:syslog] enabled=true format=5 @@ -181,16 +222,14 @@ address=tcp://syslog.server.lan:1554/ `enabled` is equivalent to command-line switch `-s` and it enables syslog logging target. -`format` speficies which logging format will be used. Possible values -are: +`format` specifies which logging format will be used. -- `5` for (new) syslog format ([RFC - 5424](https://tools.ietf.org/html/rfc5424) ) , -- `3` for old BSD syslog format ([RFC - 3164](https://tools.ietf.org/html/rfc3164) ), typically used by - `/dev/log` and -- `m` for Mac OSX syslog flavour that is based on BSD syslog format - but it is not fully compatible. +| Option | Format | Note | +| --- | --- | --- | +| `5` | syslog format [RFC 5424](https://tools.ietf.org/html/rfc5424) | | +| `5micro` | syslog format RFC 5424 with microseconds | | +| `3` | the old BSD syslog format ([RFC 3164](https://tools.ietf.org/html/rfc3164) ) | It is typically used by `/dev/log`. | +| `m` | Mac OSX syslog flavour | It is based on BSD syslog format but it is not fully compatible. | The default value is `3` on Linux and `m` on Mac OSX. @@ -208,34 +247,38 @@ UNIX path such as `/dev/log` or URL. Possible URL values: The default value is a `/dev/log` on Linux or `/var/run/syslog` on Mac OSX. -Logging of obsolete features ----------------------------- +## Logging of obsolete features -It proved to be essential to inform operators about features that are -going to be obsoleted. ASAB offers the unified \"obsolete\" logger. This -logger can indicate that a particular feature is marked as \"obsolete\" -thru logs. Such a log message can then be \"grepped\" from logs -uniformly. +It proved to be essential to inform operators about features that are going to be obsoleted. +ASAB offers the unified "obsolete" logger. +This logger can indicate that a particular feature is marked as *obsolete* thru logs. +Such a log message can then be *grepped* from logs uniformly. -It is recommended to include [eol]{.title-ref} attribute in the -[struct\_data]{.title-ref} of the log with a [YYYY-MM-DD]{.title-ref} -date/time of the planned obsoletion of the feature. +!!! example -Hint: We suggest automating the detection of obsolete warnings in logs -so that the operations are informed well ahead of the actual removal of -the feature. The string to seek in logs is \" OBSOLETE \". + ```python + asab.LogObsolete.warning("Use of the obsolete function", struct_data={'eol':'2022-31-12'}) + ``` -Example of the use: + produces the output: -``` {.python} -asab.LogObsolete.warning("Use of the obsolete function", struct_data={'eol':'2022-31-12'}) -``` + ``` + 21-Jul-2022 14:32:40.983884 WARNING OBSOLETE [eol="2022-31-12"] Use of the obsolete function + + ``` + + We suggest to add the `eol` attribute in the `struct_data` of the log with a `YYYY-MM-DD` + date/time of the planned *end of life* of the feature. + +!!! tip + + We suggest automating the detection of obsolete warnings in logs + so that the operations are informed well ahead of the actual removal of + the feature. The string to seek in logs is "OBSOLETE". -Log example: +## Reference -`21-Jul-2022 14:32:40.983884 WARNING OBSOLETE [eol="2022-31-12"] Use of the obsolete function` +::: asab.log.LOG_NOTICE -Reference ---------- +::: asab.log.Logging -::: asab.log From db6d6797ff1e7b59c0254f45abca9dd2be7706a6 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 27 Jul 2023 23:23:34 +0200 Subject: [PATCH 076/154] Enhance format and tables --- docs/reference/logging/reference.md | 45 ++++++++++++++--------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/docs/reference/logging/reference.md b/docs/reference/logging/reference.md index 725c997e5..874d9d4cc 100644 --- a/docs/reference/logging/reference.md +++ b/docs/reference/logging/reference.md @@ -187,20 +187,16 @@ setup for eg. PyCharm. ASAB supports a [log rotation](https://en.wikipedia.org/wiki/Log_rotation). The log rotation is triggered by a UNIX signal `SIGHUP`, which can be used e.g. to integrate with `logrotate` utility. It is implemented using -`logging.handlers.RotatingFileHandler` from a Python standard library. -Also, a time-based log rotation can be configured using `rotate_every` -option. +[`logging.handlers.RotatingFileHandler` from a Python standard library](https://docs.python.org/3/library/logging.handlers.html#baserotatinghandler). +Also, a time-based log rotation can be configured using `rotate_every` option. -`backup_count` specifies a number of old files to be kept prior their -removal. The system will save old log files by appending the extensions -'.1', '.2' etc., to the filename. +- `backup_count` specifies a number of old files to be kept prior their removal. +The system will save old log files by appending the extensions '.1', '.2' etc., to the filename. -`rotate_every` specifies an time interval of a log rotation. Default -value is empty string, which means that the time-based log rotation is -disabled. The interval is specified by an integer value and an unit, -e.g. 1d (for 1 day) or 30M (30 minutes). Known units are [H]{.title-ref} -for hours, [M]{.title-ref} for minutes, [d]{.title-ref} for days and -[s]{.title-ref} for seconds. +- `rotate_every` specifies an time interval of a log rotation. +Default value is empty string, which means that the time-based log rotation is disabled. +The interval is specified by an integer value and an unit, e.g. 1d (for 1 day) or 30M (30 minutes). +Known units are `H` for hours, `M` for minutes, `d` for days and `s` for seconds. ## Logging to syslog @@ -219,22 +215,20 @@ format=5 address=tcp://syslog.server.lan:1554/ ``` -`enabled` is equivalent to command-line switch `-s` and it enables -syslog logging target. +- `enabled` is equivalent to command-line switch `-s` and it enables syslog logging target. -`format` specifies which logging format will be used. +- `format` specifies which logging format will be used. | Option | Format | Note | | --- | --- | --- | | `5` | syslog format [RFC 5424](https://tools.ietf.org/html/rfc5424) | | | `5micro` | syslog format RFC 5424 with microseconds | | -| `3` | the old BSD syslog format ([RFC 3164](https://tools.ietf.org/html/rfc3164) ) | It is typically used by `/dev/log`. | +| `3` | the old BSD syslog format [RFC 3164](https://tools.ietf.org/html/rfc3164) | It is typically used by `/dev/log`. | | `m` | Mac OSX syslog flavour | It is based on BSD syslog format but it is not fully compatible. | The default value is `3` on Linux and `m` on Mac OSX. -`address` specifies the location of the Syslog server. It could be a -UNIX path such as `/dev/log` or URL. Possible URL values: +- `address` specifies the location of the Syslog server. It could be a UNIX path such as `/dev/log` or URL. Possible URL values: - `tcp://syslog.server.lan:1554/` for Syslog over TCP - `udp://syslog.server.lan:1554/` for Syslog over UDP @@ -244,14 +238,12 @@ UNIX path such as `/dev/log` or URL. Possible URL values: (datagram), equivalent to `/path/to/syslog.socket`, used by a `/dev/log`. -The default value is a `/dev/log` on Linux or `/var/run/syslog` on Mac -OSX. +The default value is a `/dev/log` on Linux or `/var/run/syslog` on Mac OSX. ## Logging of obsolete features It proved to be essential to inform operators about features that are going to be obsoleted. -ASAB offers the unified "obsolete" logger. -This logger can indicate that a particular feature is marked as *obsolete* thru logs. +ASAB offers the unified `asab.LogObsolete` logger which can indicate that a particular feature is marked as *obsolete* thru logs. Such a log message can then be *grepped* from logs uniformly. !!! example @@ -264,7 +256,6 @@ Such a log message can then be *grepped* from logs uniformly. ``` 21-Jul-2022 14:32:40.983884 WARNING OBSOLETE [eol="2022-31-12"] Use of the obsolete function - ``` We suggest to add the `eol` attribute in the `struct_data` of the log with a `YYYY-MM-DD` @@ -278,6 +269,14 @@ Such a log message can then be *grepped* from logs uniformly. ## Reference +### Command-line arguments + +| Argument | Action | +| --- | --- | +| `-v` | Enables verbose logging so that `DEBUG` and `INFO` levels are visible. | +| `-s`| Enables logging to syslog. | + + ::: asab.log.LOG_NOTICE ::: asab.log.Logging From eb0d10840caec031de1214f0fca5ca225954830a Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 27 Jul 2023 23:26:15 +0200 Subject: [PATCH 077/154] Add library chapter --- docs/reference/library.md | 1 - docs/reference/library/reference.md | 378 ++++++++++++++++++++++++++++ 2 files changed, 378 insertions(+), 1 deletion(-) delete mode 100644 docs/reference/library.md create mode 100644 docs/reference/library/reference.md diff --git a/docs/reference/library.md b/docs/reference/library.md deleted file mode 100644 index 469b4b808..000000000 --- a/docs/reference/library.md +++ /dev/null @@ -1 +0,0 @@ -::: asab.library \ No newline at end of file diff --git a/docs/reference/library/reference.md b/docs/reference/library/reference.md new file mode 100644 index 000000000..6e5762b30 --- /dev/null +++ b/docs/reference/library/reference.md @@ -0,0 +1,378 @@ +Library {#library-ref} +======= + +The ASAB Library ([asab.library]{.title-ref}) is a concept of the shared +data content across microservices in the cluster. In the cluster/cloud +microservice architectures, all microservices must have access to +unified resources. The [asab.library]{.title-ref} provides a read-only +interface for listing and reading this content. + +[asab.library]{.title-ref} is designed to be read-only. It also allows +to \"stack\" various libraries into one view (overlayed) that merges the +content of each library into one united space. + +The library can also notify the ASAB microservice about changes, e.g. +for automated update/reload. + +There is a companion microservice [asab-library]{.title-ref} that can be +used for the management and editing of the library content. The +[asab.library]{.title-ref} can however operate without +[asab-library]{.title-ref} microservice. + +Library structure +----------------- + +The library content is organized in a simplified filesystem manner, with +directories and files. + +Example of the library structure: + +``` {.} ++ /folder1/ + - /folder1/item1.yaml + - /folder1/item2.json ++ /folder2/ + - /folder2/item3.yaml + + /folder2/folder2.3/ + - /folder2/folder2.3/item4.json +``` + +Library path rules +------------------ + +- Any path must start with [/]{.title-ref}, including the root path + ([/]{.title-ref}). +- The folder path must end with [/]{.title-ref}. +- The item path must end with an extension (e.g. [.json]{.title-ref}). + +Layers +------ + +The library content can be organized into an unlimited number of layers. +Each layer is represented by a [provider]{.title-ref} with a specific +configuration. + +The layers of the library are like slices of Swiss cheese layered on top +of each other. Only if there is a hole in the top layer can you see the +layer that shows through underneath. It means that files of the upper +layer overwrite files with the same path in the lower layers. + +The first provider is responsible for providing +[/.disabled.yaml]{.title-ref} that controls the visibility of items. If +[/.disabled.yaml]{.title-ref} is not present, then is considered empty. + +Library service +--------------- + +Example of the use: + +``` {.python} +import asab +import asab.library + + +# this substitutes configuration file +asab.Config.read_string( + """ +[library] +providers=git+https://github.com/TeskaLabs/asab-maestro-library.git +""" + ) + + +class MyApplication(asab.Application): + + def __init__(self): + super().__init__() + # Initialize the library service + self.LibraryService = asab.library.LibraryService(self, "LibraryService") + self.PubSub.subscribe("Library.ready!", self.on_library_ready) + + async def on_library_ready(self, event_name, library): + print("# Library\n") + + for item in await self.LibraryService.list("/", recursive=True): + print(" *", item) + if item.type == 'item': + itemio = await self.LibraryService.read(item.name) + if itemio is not None: + with itemio: + content = itemio.read() + print(" - content: {} bytes".format(len(content))) + else: + print(" - (DISABLED)") + +if __name__ == '__main__': + app = MyApplication() + app.run() +``` + +The library service may exist in multiple instances, with different +[paths]{.title-ref} setups. For that reason, you have to provide a +unique [service\_name]{.title-ref} and there is no default value for +that. + +For more examples of Library usage, please see [ASAB +examples](https://github.com/TeskaLabs/asab/tree/master/examples) + +Library configuration +--------------------- + +Example: + +``` {.ini} +[library] +providers: + provider+1://... + provider+2://... + provider+3://... +``` + +PubSub messages +--------------- + +Read more about `PubSub`{.interpreted-text role="ref"} in +ASAB. + +::: {.option} +Library.ready! +::: + +A library is created in a "not ready" state. Only after all providers +are ready, the library itself becomes ready. The library indicates that +by the PubSub event [Library.ready!]{.title-ref}. + +::: {.option} +Library.not\_ready! +::: + +The readiness of the library (connection to external technologies) can +be lost. You can also subscribe to [Library.not\_ready!]{.title-ref} +event. + +::: {.option} +Library.change! +::: + +You can get [Notification on Changes](#notification-on-changes) in the +library. Specify a path or paths that you would like to \"listen to\". +Then subscribe to [Library.change!]{.title-ref} PubSub event. Available +for Git and FileSystem providers for now. + +Notification on changes +----------------------- + +::: {.automethod} +LibraryService.subscribe +::: + +Providers +--------- + +The library can be configured to work with the following \"backends\" +(aka providers): + +### Filesystem + +The most basic provider that reads data from the local filesystem. The +notification on changes functionality is available only for Linux +systems, as it implements +[inotify](https://en.wikipedia.org/wiki/Inotify) + +Configuration examples: + +``` {.ini} +[library] +providers: /home/user/directory +``` + +``` {.ini} +[library] +providers: ./this_directory +``` + +``` {.ini} +[library] +providers: file:///home/user/directory +``` + +### Apache Zookeeper + +ZooKeeper as a consensus technology is vital for microservices in the +cluster. + +There are several configuration strategies: + +1) Configuration from \[zookeeper\] section. + +``` {.ini} +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/library + +[library] +providers: + zk:// +``` + +2) Specify a path of a ZooKeeper node where only library lives. + + > The library path will be [/library]{.title-ref}. + +``` {.ini} +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/else + +[library] +providers: + zk:///library + + +The library path will be `/`. +``` + +``` {.ini} +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/else + +[library] +providers: + zk:/// +``` + +3) Configuration from the URL in the \[library\] section. + +``` {.ini} +[library] +providers: + zk://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/library +``` + +4) Configuration from \[zookeeper\] section and joined + [path]{.title-ref} from \[zookeeper\] and \[library\] sections. + + > The resulting path will be [/else/library]{.title-ref}. + +``` {.ini} +[zookeeper] +servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 +path=/else + +[library] +providers: + zk://./library +``` + +If a [path]{.title-ref} from the \[zookeeper\] section is missing, an +application class name will be used E.g. +[/BSQueryApp/library]{.title-ref} + +### Microsoft Azure Storage + +Reads from the Microsoft Azure Storage container. + +Configuration: + +``` {.ini} +[library] +providers: azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER +``` + +If Container Public Access Level is not set to \"Public access\", then +\"Access Policy\" must be created with \"Read\" and \"List\" permissions +and \"Shared Access Signature\" (SAS) query string must be added to a +URL in a configuration: + +``` {.ini} +[library] +providers: azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER?sv=2020-10-02&si=XXXX&sr=c&sig=XXXXXXXXXXXXXX +``` + +### Git repository + +Connection to git repositories requires +[pygit2](https://www.pygit2.org/) library to be installed. + +Configuration: + +Please follow this format in the configuration: + +``` {.ini} +[library] +providers: git+http(s)://:@#]{.title-ref} to clone a repository from a +selected branch: + +``` {.ini} +[library] +providers: git+https://github.com/john/awesome_project.git#name-of-the-branch +``` + +#### Deploy tokens in GitLab + +GitLab uses deploy tokens to enable authentication of deployment tasks, +independent of a user account. Authentication through deploy tokens is +the only supported option for now. + +If you want to create a deploy token for your GitLab repository, follow +these steps from the +[manual](https://docs.gitlab.com/ee/user/project/deploy_tokens/#create-a-deploy-token): + +1. Go to **Settings \> Repository \> Deploy tokens** section in your + repository. (Note that you have to possess a \"Maintainer\" or + \"Owner\" role for the repository.) +2. Expand the \"Deploy tokens\" section. The list of current Active + Deploy Tokens will be displayed. +3. Complete the fields and scopes. We recommend a custom \"username\", + as you will need it later for the URL in the configuration. +4. Record the deploy token\'s values *before leaving or refreshing the + page*! After that, you cannot access it again. + +After the deploy token is created, use the URL for the repository in the +following format: + +``` {.ini} +[library] +providers: git+https://:@gitlab.example.com/john/awesome_project.git +``` + +#### Where does the repository clone? + +The git provider clones the repository into a temporary directory. The +default path for the cloned repository is +[/tmp/asab.library.git/]{.title-ref} and it can be changed manually: + +``` {.ini} +[library:git] +repodir=path/to/repository/cache +``` + +### Reference + +::: {.autoclass} +LibraryService + +::: {.automethod} +read +::: + +::: {.automethod} +list +::: + +::: {.automethod} +export +::: +::: From 3ff2effd00bc9decbcac66351166d43bd263f81d Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 31 Jul 2023 15:19:19 +0200 Subject: [PATCH 078/154] Format code examples --- docs/reference/logging/reference.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/reference/logging/reference.md b/docs/reference/logging/reference.md index 874d9d4cc..71e4092b5 100644 --- a/docs/reference/logging/reference.md +++ b/docs/reference/logging/reference.md @@ -59,7 +59,7 @@ Level | Numeric value | Syslog Severity level | ```ini [logging] - level=DEBUG + level = DEBUG ``` !!! example "Setting levels for particular modules:" @@ -71,8 +71,8 @@ Level | Numeric value | Syslog Severity level | myApp.module2 WARNING ``` - The logger name and the corresponding logging level are separated by a - space, each logger is on a separate line. + Each logger must be on a separate line. + The logger name and the corresponding logging level have to be separated by a space. ## Verbose mode @@ -90,13 +90,16 @@ The actual verbose mode is available at `asab.Config["logging"]["verbose"]` bool 1. ```ini [logging] - verbose=true + verbose = true ``` + The string `true` is interpreted by `ConfigParser` via [`this method`](#asab.utils.string_to_boolean). + 2. ```ini [logging] - level=DEBUG + level = DEBUG ``` + 3. ```shell python3 myapp.py -v @@ -156,11 +159,9 @@ configuration file enables logging to file as well. format="%(asctime)s %(levelname)s %(name)s %(struct_data)s%(message)s", datefmt="%d-%b-%Y %H:%M:%S.%f" backup_count=3 - rotate_every=1d #(1)! + rotate_every=1d ``` - 1. When reading this configuration, `asab.Config.getseconds()` method is used. - When the deployment expects more instances of the same application to be logging into the same file, it is recommended, that the variable hostname is used in the file path: From 1bd757b9e4230a7185e6f2726af52b803abad1c1 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 31 Jul 2023 15:19:37 +0200 Subject: [PATCH 079/154] Add Configuration and Library --- mkdocs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 3fa298269..c685e8cee 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -160,8 +160,9 @@ nav: - Reference: - Application: reference/application/reference.md - - Configuration: reference/config/config.md + - Configuration: reference/config/reference.md - Logging: reference/logging/reference.md + - Library: reference/library/reference.md - Metrics: - MetricsService: reference/metrics/service.md - Gauge: reference/metrics/gauge.md From cb0ed6586554ee3844c6ecbe783517f020aa0fcb Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 31 Jul 2023 15:20:24 +0200 Subject: [PATCH 080/154] Create Config section --- docs/reference/config/config.md | 1 - docs/reference/config/reference.md | 317 +++++++++++++++++++++++++++++ 2 files changed, 317 insertions(+), 1 deletion(-) delete mode 100644 docs/reference/config/config.md create mode 100644 docs/reference/config/reference.md diff --git a/docs/reference/config/config.md b/docs/reference/config/config.md deleted file mode 100644 index 37b64b1dd..000000000 --- a/docs/reference/config/config.md +++ /dev/null @@ -1 +0,0 @@ -::: asab.config \ No newline at end of file diff --git a/docs/reference/config/reference.md b/docs/reference/config/reference.md new file mode 100644 index 000000000..85bba6613 --- /dev/null +++ b/docs/reference/config/reference.md @@ -0,0 +1,317 @@ +# Configuration + +The configuration is provided by `asab.Config` object which is a singleton. +It means that you can access `asab.Config` from any place of your code, without need of explicit initialization. + +```python +import asab + +app = asab.Application() #(1)! + +... + +my_conf_value = asab.Config['section_name']['key1'] #(2)! +``` + +1. Initialize application object and hence the configuration. +2. Access configuration values anywhere. + + +## Based on ConfigParser object + +The `asab.Config` is inherited from [the standard `configparser.ConfigParser` class](https://docs.python.org/3/library/configparser.html#customizing-parser-behaviour) +which implements a basic configuration language that provides a structure similar to what's found in Microsoft Windows INI files. + +!!! example "Basic usage:" + + Example of the configuration file: + + ``` ini + [section name] + key=value + keys can contain spaces = values can contain spaces + + you can use = equal signs + as well as: colons + extra spaces are : removed + + [another section] + final answer = 42 + are you sure = true + + numerical values are held as: strings + booleans are also: strings + use these functions: getint(), getfloat(), getboolean() + ``` + + And this is how you access configuration values: + + ``` python + >>> asab.Config['section name']['key'] + 'value' + >>> asab.Config.get('another section', 'final answer') + '42' + >>> asab.Config.getint('another section', 'final answer') + 42 + >>> asab.Config.getboolean('another section', 'are you sure') + True + ``` + +!!! warning "Be careful with comments:" + + ```ini + [comments] + # Comments in empty lines are supported + key = value # inline comments are not supported! + + # That would prevent URL fragments from being read: + path = https://www.netlog.org/path#fragment + ``` + + +!!! example "Multiline configuration entry:" + + A multiline configuration entries are supported: + + ``` ini + multiline_values = are + handled just fine as + long as they are indented + deeper than the first line + of a value + chorus: I'm a lumberjack, and I'm okay + I sleep all night and I work all day + ``` + +## Loading configuration from a file + + +If a configuration file name is specified,the configuration is automatically +loaded from a configuration file during [initialization time of `Application`](../../application/reference/#init-time). +There are three ways how to include a configuration file: + +1. by specifying the `-c` command-line argument: + + ``` shell + python3 my_app.py -c ./etc/sample.conf + ``` + + +2. by running the application with `ASAB_CONFIG` environment variable set: + + ``` shell + export ASAB_CONFIG="./etc/sample.conf" + python3 my_app.py + ``` + +3. by setting the variable during the init-time: + + ```python + class MyApplication(asab.Application) + async def initialize(self): + asab.Config["general"]["config_file"] = "./etc/sample.conf" + ``` + + + + +### Including other configuration files + +You can specify one or more additional configuration files that are +loaded and merged from an main configuration file. +It is done by `[general] include` configuration value. + +``` ini +[general] +include=./etc/site.conf:./etc/site.d/*.conf +``` + +Multiple paths are separated by [`os.pathsep`](https://docs.python.org/3/library/os.html?highlight=os%20pathsep#os.pathsep) value, which is `:` on Unix and `;` on Windows. +The path can be specified as a glob (e.g. use of `*` and `?` wildcard characters), +it will be expanded by [`glob` module](https://docs.python.org/3/library/glob.html?highlight=glob#module-glob). +Included configuration files may not exists, this situation is silently ignored. + +You can also use a multiline configuration entry: + +``` ini +[general] +include= + ./etc/site.conf + ./etc/site.d/*.conf +``` + +## Including ZooKeeper node in the configuration + +The separator between includes is newline or space - it means that space MUST NOT be in the names of nodes in the ZooKeeper. + +The ZooKeeper node can contain a configuration file in .conf, .json or .yaml format. + +You can specify servers and path of the ZooKeeper node directly in the include option: + +```ini +[general] +include=zookeeper://localhost:2181/asab/config/config-test.yaml +``` + +It is also possible to name only the node path in this section and use zookeeper configuration section to read the location of ZooKeeper servers. Using the environment variable `ASAB_ZOOKEEPERS_SERVERS` is also a possible option. + +```ini +[general] +include=zookeeper:///asab/config/config-test.yaml +``` + + + + + +## Default values + +This is how you can extend configuration default values: + +``` python + +asab.Config.add_defaults( + { + 'section_name': { + 'key1': 'value', + 'key2': 'another value' + }, + 'other_section': { + 'key3': 'value', + }, + } +) +``` + +!!! warning + + Only simple types (`string`, `int` and `float`) are allowed in the + configuration values. Do not use complex types such as lists, + dictionaries or objects because these are impossible to provide via + configuration files etc. + + +## Environment variables + +Environment variables found in values are automatically expanded. + +```ini +[section_name] +persistent_dir=${HOME}/.myapp/ +``` + +```python +>>> asab.Config['section_name']['persistent_dir'] +'/home/user/.myapp/' +``` + +There is a special environment variable `${THIS_DIR}` that +is expanded to a directory that contains a current configuration file. +It is useful in complex configurations that utilizes included +configuration files etc. + +``` {.ini} +[section_name] +my_file=${THIS_DIR}/my_file.txt +``` + +Another environment variable [${HOSTNAME}]{.title-ref} contains the +application hostname to be used f. e. in logging file path. + +``` {.ini} +[section_name] +my_file=${THIS_DIR}/${HOSTNAME}/my_file.txt +``` + +## Passwords + + +[passwords] section in the configuration serves to securely store +passwords, which are then not shown publicly in the default API config +endpoint's output. + +It is convenient for the user to store passwords at one place, so that +they are not repeated in many sections of the config file(s). + +Usage is as follows: + +``` {.ini} +[connection:KafkaConnection] +password=${passwords:kafka_password} + +[passwords] +kafka_password= +``` + +## Obtaining seconds + +The seconds can be obtained using [getseconds()]{.title-ref} method for +values with different time units specified in the configuration: + +``` {.ini} +[sleep] +sleep_time=5.2s +another_sleep_time=10d +``` + +The available units are: + +> - `y` ... years +> - `M` ... months +> - `w` ... weeks +> - `d` ... days +> - `h` ... hours +> - `m` ... minutes +> - `s` ... seconds +> - `ms` .. miliseconds + +If no unit is specified, float of seconds is expected. + +The obtainment of the second value in the code can be achieved in two +ways: + +``` {.python} +self.SleepTime = asab.Config["sleep"].getseconds("sleep_time") +self.AnotherSleepTime = asab.Config.getseconds("sleep", "another_sleep_time") +``` + +Obtaining URLs +-------------- + +A URL can be obtained using a [geturl()]{.title-ref} method that takes +the URL from the config and removes leading and trailing whitespaces and +trailing backslashes. + +There is an optional parameter called [scheme]{.title-ref} that can have +any URL scheme like http, https, mongodb etc. Setting it to None, scheme +validation gets bypassed. + +Setting the scheme parameter to the same scheme as in the config, it +will return the URL. If it's not the same it will raise an error. + +There are two ways of obtaining the URL: + +``` {.py} +asab.Config["urls"].geturl("teskalabs", scheme="https") +asab.Config.geturl("urls", "github", scheme=None) +``` + +Example: + +``` {.python} +>>> asab.Config["urls"].geturl("teskalabs", scheme="https") + 'https://www.teskalabs.com' +``` + +For reference this would be the configuration file: + +``` {.ini} +[urls] +teskalabs=https://www.teskalabs.com/ +github=github.com +``` + +## Reference + +::: asab.config + From 48de1acbffef8b5b3f42890d89198113174f5510 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 31 Jul 2023 18:15:52 +0200 Subject: [PATCH 081/154] Extend docstrings --- asab/config.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/asab/config.py b/asab/config.py index adcb6a32a..5605ad12b 100644 --- a/asab/config.py +++ b/asab/config.py @@ -298,8 +298,26 @@ def getseconds(self, section, option, *, raw=False, vars=None, fallback=None, ** """ Get time data from config and convert time string into seconds with `convert_to_seconds()` method. + The available units are: + + - `y` - years + - `M` - months + - `w` - weeks + - `d` - days + - `h` - hours + - `m` - minutes + - `s` - seconds + - `ms` - milliseconds + Returns: float: Time in seconds. + + Examples: + + ```python + self.SleepTime = asab.Config["sleep"].getseconds("sleep_time") + self.AnotherSleepTime = asab.Config.getseconds("sleep", "another_sleep_time") + ``` """ if fallback is None: @@ -321,6 +339,20 @@ def geturl(self, section, option, raw=False, vars=None, fallback=None, scheme=No Raises: ValueError: Scheme requirements are not met if set. + + Examples: + + Configuration file: + ```ini + [urls] + teskalabs=https://www.teskalabs.com/ + github=github.com + ``` + Script: + ``` python + asab.Config["urls"].geturl("teskalabs", scheme="https") + asab.Config.geturl("urls", "github", scheme=None) + ``` """ return utils.validate_url(self.get(section, option, raw=False, vars=None, fallback=fallback), scheme) From bb50aabc36359700408afb0b101705fe885c1d2e Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 31 Jul 2023 18:19:04 +0200 Subject: [PATCH 082/154] Move function description to docstrings, modify headers --- docs/reference/config/reference.md | 105 ++++++----------------------- 1 file changed, 21 insertions(+), 84 deletions(-) diff --git a/docs/reference/config/reference.md b/docs/reference/config/reference.md index 85bba6613..6348cbdfa 100644 --- a/docs/reference/config/reference.md +++ b/docs/reference/config/reference.md @@ -140,7 +140,7 @@ include= ./etc/site.d/*.conf ``` -## Including ZooKeeper node in the configuration +### Including ZooKeeper node in the configuration The separator between includes is newline or space - it means that space MUST NOT be in the names of nodes in the ZooKeeper. @@ -161,15 +161,11 @@ include=zookeeper:///asab/config/config-test.yaml ``` - - - ## Default values This is how you can extend configuration default values: -``` python - +```python asab.Config.add_defaults( { 'section_name': { @@ -205,28 +201,26 @@ persistent_dir=${HOME}/.myapp/ '/home/user/.myapp/' ``` -There is a special environment variable `${THIS_DIR}` that -is expanded to a directory that contains a current configuration file. -It is useful in complex configurations that utilizes included -configuration files etc. +There is a special environment variable `${THIS_DIR}` that is +expanded to a directory that contains a current configuration file. +It is useful in complex configurations that utilizes included configuration files etc. -``` {.ini} +``` ini [section_name] my_file=${THIS_DIR}/my_file.txt ``` -Another environment variable [${HOSTNAME}]{.title-ref} contains the -application hostname to be used f. e. in logging file path. +Another environment variable `${HOSTNAME}` contains the +application hostname to be used, e.g. in logging file path. -``` {.ini} +``` ini [section_name] my_file=${THIS_DIR}/${HOSTNAME}/my_file.txt ``` ## Passwords - -[passwords] section in the configuration serves to securely store +`[passwords]` section in the configuration serves to securely store passwords, which are then not shown publicly in the default API config endpoint's output. @@ -235,7 +229,7 @@ they are not repeated in many sections of the config file(s). Usage is as follows: -``` {.ini} +``` ini [connection:KafkaConnection] password=${passwords:kafka_password} @@ -243,75 +237,18 @@ password=${passwords:kafka_password} kafka_password= ``` -## Obtaining seconds - -The seconds can be obtained using [getseconds()]{.title-ref} method for -values with different time units specified in the configuration: - -``` {.ini} -[sleep] -sleep_time=5.2s -another_sleep_time=10d -``` - -The available units are: - -> - `y` ... years -> - `M` ... months -> - `w` ... weeks -> - `d` ... days -> - `h` ... hours -> - `m` ... minutes -> - `s` ... seconds -> - `ms` .. miliseconds - -If no unit is specified, float of seconds is expected. - -The obtainment of the second value in the code can be achieved in two -ways: - -``` {.python} -self.SleepTime = asab.Config["sleep"].getseconds("sleep_time") -self.AnotherSleepTime = asab.Config.getseconds("sleep", "another_sleep_time") -``` - -Obtaining URLs --------------- - -A URL can be obtained using a [geturl()]{.title-ref} method that takes -the URL from the config and removes leading and trailing whitespaces and -trailing backslashes. - -There is an optional parameter called [scheme]{.title-ref} that can have -any URL scheme like http, https, mongodb etc. Setting it to None, scheme -validation gets bypassed. - -Setting the scheme parameter to the same scheme as in the config, it -will return the URL. If it's not the same it will raise an error. - -There are two ways of obtaining the URL: - -``` {.py} -asab.Config["urls"].geturl("teskalabs", scheme="https") -asab.Config.geturl("urls", "github", scheme=None) -``` - -Example: - -``` {.python} ->>> asab.Config["urls"].geturl("teskalabs", scheme="https") - 'https://www.teskalabs.com' -``` +## Reference -For reference this would be the configuration file: +### Environment variables -``` {.ini} -[urls] -teskalabs=https://www.teskalabs.com/ -github=github.com -``` +| Name | Usage | +| --- | --- | +| `ASAB_CONFIG` | Path to the custom configuration file with which ASAB app will be using. | +| `ASAB_ZOOKEEPERS_SERVERS`| URL for Zookeeper node. | +| `THIS_DIR` | Directory that contains a current configuration file. | -## Reference +::: asab.config.ConfigParser -::: asab.config +::: asab.config.ConfigObjectDict +::: asab.config.Configurable From 523ffb346bcb58067acca57ead188eb3f2e8f829 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 31 Jul 2023 18:22:31 +0200 Subject: [PATCH 083/154] Rename autodocs section --- docs/reference/application/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/application/reference.md b/docs/reference/application/reference.md index cef02b59c..77a4e55cb 100644 --- a/docs/reference/application/reference.md +++ b/docs/reference/application/reference.md @@ -183,6 +183,6 @@ provides a cheaper version of the call that returns a current wall time in UTC. --- -## Documentation +## Reference ::: asab.application.Application \ No newline at end of file From d719f0b2a93de38993d8e618828654d16fe4546c Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 31 Jul 2023 18:31:23 +0200 Subject: [PATCH 084/154] Checks --- docs/reference/config/reference.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/reference/config/reference.md b/docs/reference/config/reference.md index 6348cbdfa..37b2c0f33 100644 --- a/docs/reference/config/reference.md +++ b/docs/reference/config/reference.md @@ -1,7 +1,6 @@ # Configuration -The configuration is provided by `asab.Config` object which is a singleton. -It means that you can access `asab.Config` from any place of your code, without need of explicit initialization. +The configuration is provided by `asab.Config` object which you can access from any place of your code, without need of explicit initialization. ```python import asab @@ -13,13 +12,13 @@ app = asab.Application() #(1)! my_conf_value = asab.Config['section_name']['key1'] #(2)! ``` -1. Initialize application object and hence the configuration. -2. Access configuration values anywhere. +1. Initializes application object and hence the configuration. +2. You can access the configuration values anywhere. ## Based on ConfigParser object -The `asab.Config` is inherited from [the standard `configparser.ConfigParser` class](https://docs.python.org/3/library/configparser.html#customizing-parser-behaviour) +`asab.Config` is inherited from [`configparser.ConfigParser` class](https://docs.python.org/3/library/configparser.html#customizing-parser-behaviour) which implements a basic configuration language that provides a structure similar to what's found in Microsoft Windows INI files. !!! example "Basic usage:" @@ -40,7 +39,7 @@ which implements a basic configuration language that provides a structure simila are you sure = true numerical values are held as: strings - booleans are also: strings + booleans are held as: strings use these functions: getint(), getfloat(), getboolean() ``` @@ -227,15 +226,15 @@ endpoint's output. It is convenient for the user to store passwords at one place, so that they are not repeated in many sections of the config file(s). -Usage is as follows: +!!! example -``` ini -[connection:KafkaConnection] -password=${passwords:kafka_password} + ``` ini + [connection:KafkaConnection] + password=${passwords:kafka_password} -[passwords] -kafka_password= -``` + [passwords] + kafka_password= + ``` ## Reference @@ -246,6 +245,8 @@ kafka_password= | `ASAB_CONFIG` | Path to the custom configuration file with which ASAB app will be using. | | `ASAB_ZOOKEEPERS_SERVERS`| URL for Zookeeper node. | | `THIS_DIR` | Directory that contains a current configuration file. | +| `HOSTNAME` | The application hostname. | + ::: asab.config.ConfigParser From aa3b868c7813928f3c807b47ebaf00df0c298edd Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 31 Jul 2023 18:41:54 +0200 Subject: [PATCH 085/154] Code formatting --- docs/reference/logging/reference.md | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/reference/logging/reference.md b/docs/reference/logging/reference.md index 71e4092b5..162e46ae1 100644 --- a/docs/reference/logging/reference.md +++ b/docs/reference/logging/reference.md @@ -19,7 +19,9 @@ supported. ```python title="myapp/mymodule.py" import logging + L = logging.getLogger(__name__) + ... L.warning("Hello world!") @@ -162,18 +164,20 @@ configuration file enables logging to file as well. rotate_every=1d ``` -When the deployment expects more instances of the same application to be -logging into the same file, it is recommended, that the variable -hostname is used in the file path: +!!! tip -```ini -[logging:file] -path=/var/log/${HOSTNAME}/asab.log -``` + When the deployment expects more instances of the same application to be + logging into the same file, it is recommended to use + [`${HOSTNAME}`](../../config/reference/#environment-variables) variable in the file path: + + ```ini + [logging:file] + path=/var/log/${HOSTNAME}/asab.log + ``` -In this way, the applications will log to separate log files in -different folders, which is an intended behavior, since race conditions -may occur when different application instances log into the same file. + In this way, the applications will log to separate log files in + different folders, which is an intended behavior, since race conditions + may occur when different application instances log into the same file. ## Logging to console From 6c2c790713f80fdf75af50f4c464d2517d550324 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 31 Jul 2023 20:01:49 +0200 Subject: [PATCH 086/154] Transform the design --- docs/reference/library/reference.md | 332 +++++++++++----------------- 1 file changed, 131 insertions(+), 201 deletions(-) diff --git a/docs/reference/library/reference.md b/docs/reference/library/reference.md index 6e5762b30..c1a2d4284 100644 --- a/docs/reference/library/reference.md +++ b/docs/reference/library/reference.md @@ -1,33 +1,21 @@ -Library {#library-ref} -======= +# Library Service -The ASAB Library ([asab.library]{.title-ref}) is a concept of the shared -data content across microservices in the cluster. In the cluster/cloud -microservice architectures, all microservices must have access to -unified resources. The [asab.library]{.title-ref} provides a read-only -interface for listing and reading this content. +The ASAB Library is a concept of the shared data content across microservices in the cluster. +In the cluster/cloud microservice architectures, all microservices must have access to unified resources. +The Library provides a read-only interface for listing and reading this content. -[asab.library]{.title-ref} is designed to be read-only. It also allows -to \"stack\" various libraries into one view (overlayed) that merges the -content of each library into one united space. +It is designed to be read-only. It also allows to *"stack"* various libraries into one view (overlayed) +that merges the content of each library into one united space. -The library can also notify the ASAB microservice about changes, e.g. -for automated update/reload. +The library can also notify the ASAB microservice about changes, e.g. for automated update/reload. -There is a companion microservice [asab-library]{.title-ref} that can be -used for the management and editing of the library content. The -[asab.library]{.title-ref} can however operate without -[asab-library]{.title-ref} microservice. +## Library structure -Library structure ------------------ - -The library content is organized in a simplified filesystem manner, with -directories and files. +The library content is organized in a simplified filesystem manner, with directories and files. Example of the library structure: -``` {.} +``` + /folder1/ - /folder1/item1.yaml - /folder1/item2.json @@ -37,68 +25,48 @@ Example of the library structure: - /folder2/folder2.3/item4.json ``` -Library path rules ------------------- +## Library path rules -- Any path must start with [/]{.title-ref}, including the root path - ([/]{.title-ref}). -- The folder path must end with [/]{.title-ref}. -- The item path must end with an extension (e.g. [.json]{.title-ref}). +- Any path must start with "/", including the root path. +- The folder path must end with "/". +- The item path must end with an extension (e.g. ".json"). -Layers ------- +## Layers The library content can be organized into an unlimited number of layers. -Each layer is represented by a [provider]{.title-ref} with a specific -configuration. +Each layer is represented by a **provider** with a specific configuration. -The layers of the library are like slices of Swiss cheese layered on top -of each other. Only if there is a hole in the top layer can you see the -layer that shows through underneath. It means that files of the upper -layer overwrite files with the same path in the lower layers. +The layers of the library are like slices of Swiss cheese layered on top of each other. +Only if there is a hole in the top layer can you see the layer that shows through underneath. +It means that files of the upper layer overwrite files with the same path in the lower layers. -The first provider is responsible for providing -[/.disabled.yaml]{.title-ref} that controls the visibility of items. If -[/.disabled.yaml]{.title-ref} is not present, then is considered empty. +The first provider is responsible for providing '/.disabled.yaml' that controls the visibility of items. +If '/.disabled.yaml' is not present, then is considered empty. -Library service ---------------- +## Library service Example of the use: -``` {.python} +```python import asab import asab.library - -# this substitutes configuration file -asab.Config.read_string( - """ -[library] -providers=git+https://github.com/TeskaLabs/asab-maestro-library.git -""" - ) - - class MyApplication(asab.Application): - def __init__(self): - super().__init__() - # Initialize the library service - self.LibraryService = asab.library.LibraryService(self, "LibraryService") - self.PubSub.subscribe("Library.ready!", self.on_library_ready) + async def initialize(self): + self.LibraryService = asab.library.LibraryService(self, "LibraryService") #(1)! + self.PubSub.subscribe("Library.ready!", self.on_library_ready) #(2)! - async def on_library_ready(self, event_name, library): - print("# Library\n") + async def on_library_ready(self, event_name, library): #(3)! - for item in await self.LibraryService.list("/", recursive=True): - print(" *", item) - if item.type == 'item': - itemio = await self.LibraryService.read(item.name) + for item in await self.LibraryService.list("/", recursive=True): #(4)! + print("*", item) + if item.type == 'item': #(5)! + itemio = await self.LibraryService.read(item.name) #(6)! if itemio is not None: - with itemio: + with itemio: #(7)! content = itemio.read() - print(" - content: {} bytes".format(len(content))) + print("- content: {} bytes".format(len(content))) else: print(" - (DISABLED)") @@ -107,94 +75,72 @@ if __name__ == '__main__': app.run() ``` -The library service may exist in multiple instances, with different -[paths]{.title-ref} setups. For that reason, you have to provide a -unique [service\_name]{.title-ref} and there is no default value for -that. - -For more examples of Library usage, please see [ASAB -examples](https://github.com/TeskaLabs/asab/tree/master/examples) - -Library configuration ---------------------- - -Example: - -``` {.ini} -[library] -providers: - provider+1://... - provider+2://... - provider+3://... -``` - -PubSub messages ---------------- +1. Initializes the Library Service. +2. When the Library is initialized, `Library.ready!` PubSub message is emitted. +3. The callback has to possess two arguments. `event_name` is the message "Library.ready!", `library` is the specific provider with +which is the Library initialized. +4. `list()` method returns list of `LibraryItem`s. For more information, see the reference section. +5. `item.type` can be either 'item' or 'dir'. +6. `read()` coroutine returns item IO object or None if the file is disabled. +7. Item IO object is used as a context manager. -Read more about `PubSub`{.interpreted-text role="ref"} in -ASAB. +The library service may exist in multiple instances, with different `paths` setups. +For that reason, you have to provide a unique `service_name` and there is no default value for that. -::: {.option} -Library.ready! -::: +!!! example "Example of the library configuration:" -A library is created in a "not ready" state. Only after all providers -are ready, the library itself becomes ready. The library indicates that -by the PubSub event [Library.ready!]{.title-ref}. + ``` ini + [library] + providers: + provider+1://... + provider+2://... + provider+3://... + ``` -::: {.option} -Library.not\_ready! -::: +## PubSub messages -The readiness of the library (connection to external technologies) can -be lost. You can also subscribe to [Library.not\_ready!]{.title-ref} -event. +| Message | Published when... | +| --- | --- | +| `Library.not_ready!` | Library is created and the providers are not connected or Library is disconnected. | +| `Library.ready!` | After all of the providers are ready. | +| `Library.change!` | The content of the Library has changed. | -::: {.option} -Library.change! -::: +## Notification on changes -You can get [Notification on Changes](#notification-on-changes) in the -library. Specify a path or paths that you would like to \"listen to\". -Then subscribe to [Library.change!]{.title-ref} PubSub event. Available -for Git and FileSystem providers for now. -Notification on changes ------------------------ +## Providers -::: {.automethod} -LibraryService.subscribe -::: +The list of available providers: -Providers ---------- - -The library can be configured to work with the following \"backends\" -(aka providers): +| Provider | Read the content | Notify on changes | +| --- | :---: | :---: | +| Filesystem | :material-check: | :material-check: | +| Apache Zookeeper | :material-check: | :material-check: | +| Microsoft Azure Storage | :material-check: | :material-close: | +| Git | :material-check: | :material-check: | ### Filesystem -The most basic provider that reads data from the local filesystem. The -notification on changes functionality is available only for Linux -systems, as it implements -[inotify](https://en.wikipedia.org/wiki/Inotify) +The most basic provider that reads data from the local filesystem. +The notification on changes functionality is available only for Linux systems, +as it uses [inotify](https://en.wikipedia.org/wiki/Inotify). -Configuration examples: +!!! example "Configuration examples:" -``` {.ini} -[library] -providers: /home/user/directory -``` + ```ini + [library] + providers: /home/user/directory + ``` -``` {.ini} -[library] -providers: ./this_directory -``` + ```ini + [library] + providers: ./this_directory + ``` -``` {.ini} -[library] -providers: file:///home/user/directory -``` + ```ini + [library] + providers: file:///home/user/directory + ``` ### Apache Zookeeper @@ -203,9 +149,9 @@ cluster. There are several configuration strategies: -1) Configuration from \[zookeeper\] section. +1) Configuration from `[zookeeper]` section. -``` {.ini} +```ini [zookeeper] servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 path=/library @@ -217,9 +163,7 @@ providers: 2) Specify a path of a ZooKeeper node where only library lives. - > The library path will be [/library]{.title-ref}. - -``` {.ini} +```ini [zookeeper] servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 path=/else @@ -227,12 +171,9 @@ path=/else [library] providers: zk:///library - - -The library path will be `/`. ``` -``` {.ini} +``` ini [zookeeper] servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 path=/else @@ -242,20 +183,20 @@ providers: zk:/// ``` -3) Configuration from the URL in the \[library\] section. +3) Configuration from the URL in the `[library]` section. -``` {.ini} +``` ini [library] providers: zk://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/library ``` -4) Configuration from \[zookeeper\] section and joined - [path]{.title-ref} from \[zookeeper\] and \[library\] sections. +4) Configuration from `[zookeeper]` section and joined + [path]{.title-ref} from `[zookeeper]` and `[library]` sections. > The resulting path will be [/else/library]{.title-ref}. -``` {.ini} +``` ini [zookeeper] servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 path=/else @@ -265,9 +206,8 @@ providers: zk://./library ``` -If a [path]{.title-ref} from the \[zookeeper\] section is missing, an -application class name will be used E.g. -[/BSQueryApp/library]{.title-ref} +If a `path` from the `[zookeeper]` section is missing, an application class name will be used, e.g. +`/BSQueryApp/library`. ### Microsoft Azure Storage @@ -275,50 +215,58 @@ Reads from the Microsoft Azure Storage container. Configuration: -``` {.ini} +``` ini [library] providers: azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER ``` -If Container Public Access Level is not set to \"Public access\", then -\"Access Policy\" must be created with \"Read\" and \"List\" permissions -and \"Shared Access Signature\" (SAS) query string must be added to a +If Container Public Access Level is not set to *"Public access"*, then +*"Access Policy"* must be created with *"Read"* and *"List"* permissions +and *"Shared Access Signature" (SAS)* query string must be added to a URL in a configuration: -``` {.ini} +``` ini [library] providers: azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER?sv=2020-10-02&si=XXXX&sr=c&sig=XXXXXXXXXXXXXX ``` ### Git repository -Connection to git repositories requires -[pygit2](https://www.pygit2.org/) library to be installed. +!!! warning -Configuration: + Connection to git repositories requires + [pygit2](https://www.pygit2.org/) library to be installed. + + ```shell + pip install pygit2 + ``` Please follow this format in the configuration: -``` {.ini} +``` ini [library] -providers: git+http(s)://:@#:@# ``` -Using a public repository from github, the configuration may look like -this: +!!! example "Cloning from GitHub repository:" -``` {.ini} -[library] -providers: git+https://github.com/john/awesome_project.git -``` + Using a public repository from GitHub, the configuration may look like + this: -Use hash [\#\]{.title-ref} to clone a repository from a -selected branch: + ``` ini + [library] + providers: git+https://github.com/john/awesome_project.git + ``` -``` {.ini} -[library] -providers: git+https://github.com/john/awesome_project.git#name-of-the-branch -``` +!!! example "Using custom branch:" + + Use hash `#` to clone a repository from a + selected branch: + + ``` ini + [library] + providers: git+https://github.com/john/awesome_project.git#name-of-the-branch + ``` #### Deploy tokens in GitLab @@ -330,14 +278,14 @@ If you want to create a deploy token for your GitLab repository, follow these steps from the [manual](https://docs.gitlab.com/ee/user/project/deploy_tokens/#create-a-deploy-token): -1. Go to **Settings \> Repository \> Deploy tokens** section in your - repository. (Note that you have to possess a \"Maintainer\" or - \"Owner\" role for the repository.) -2. Expand the \"Deploy tokens\" section. The list of current Active +1. Go to **Settings > Repository > Deploy tokens** section in your + repository. (Note that you have to possess a *"Maintainer"* or + *"Owner"* role for the repository.) +2. Expand the **"Deploy tokens"** section. The list of current Active Deploy Tokens will be displayed. -3. Complete the fields and scopes. We recommend a custom \"username\", +3. Complete the fields and scopes. We recommend a custom *"username"*, as you will need it later for the URL in the configuration. -4. Record the deploy token\'s values *before leaving or refreshing the +4. Record the deploy token's values *before leaving or refreshing the page*! After that, you cannot access it again. After the deploy token is created, use the URL for the repository in the @@ -352,27 +300,9 @@ providers: git+https://:@gitlab.example.com/john/awesome The git provider clones the repository into a temporary directory. The default path for the cloned repository is -[/tmp/asab.library.git/]{.title-ref} and it can be changed manually: +`/tmp/asab.library.git/` and it can be changed manually: -``` {.ini} +``` ini [library:git] repodir=path/to/repository/cache ``` - -### Reference - -::: {.autoclass} -LibraryService - -::: {.automethod} -read -::: - -::: {.automethod} -list -::: - -::: {.automethod} -export -::: -::: From 21ad79bc500484c11f701668f1d4717f2cae1626 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 31 Jul 2023 20:43:50 +0200 Subject: [PATCH 087/154] Add example on Library.change\! --- docs/reference/library/reference.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/docs/reference/library/reference.md b/docs/reference/library/reference.md index c1a2d4284..71a1c4197 100644 --- a/docs/reference/library/reference.md +++ b/docs/reference/library/reference.md @@ -107,6 +107,24 @@ For that reason, you have to provide a unique `service_name` and there is no def ## Notification on changes +!!! example + + ```python + class MyApplication(asab.Application): + + async def initialize(self): + self.PubSub.subscribe("Library.ready!", self.on_library_ready + self.PubSub.subscribe("Library.change!", self.on_library_change) + + async def on_library_ready(self, event_name, library=None): + await self.LibraryService.subscribe(["/asab"]) #(1)! + + def on_library_change(self, message, provider, path): #(2)! + print("New changes in the library found by provider: '{}'".format(provider)) + ``` + + 1. `self.LibraryService.subscribe()` method takes either a single path as a string or multiple paths in list and watches for changes in them. + 2. This coroutine takes three arguments: `message` (`Library.change!` in this case), `provider` (name of the provider that has detected changes) and `path` (the path where changes were made). ## Providers @@ -291,7 +309,7 @@ these steps from the After the deploy token is created, use the URL for the repository in the following format: -``` {.ini} +``` ini [library] providers: git+https://:@gitlab.example.com/john/awesome_project.git ``` @@ -306,3 +324,7 @@ default path for the cloned repository is [library:git] repodir=path/to/repository/cache ``` + +## Reference + +::: asab.library.LibraryService From d3ddd83bb83325438d5c23f05ce739e2bd6f5822 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 1 Aug 2023 13:25:07 +0200 Subject: [PATCH 088/154] Modify docstrings --- asab/library/service.py | 127 ++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 63 deletions(-) diff --git a/asab/library/service.py b/asab/library/service.py index 7090dc89d..432064a18 100644 --- a/asab/library/service.py +++ b/asab/library/service.py @@ -15,6 +15,9 @@ from ..abc import Service from ..config import Config from ..log import LOG_NOTICE +from .item import LibraryItem +from ..application import Application +from .providers.abc import LibraryProviderABC # @@ -28,15 +31,15 @@ class LibraryService(Service): """ Configuration: - .. code:: + ```ini + [library] + providers: + provider+1:// + provider+2:// + provider+3:// + ``` - [library] - providers: - provider+1:// - provider+2:// - provider+3:// - - The order of providers *IS* important, the priority (or layering) is top-down. + The order of providers is important, the priority (or layering) is top-down. Each library provider is specified by URL/URI schema: @@ -52,19 +55,26 @@ class LibraryService(Service): The library indicates that by the PubSub event `Library.ready!`. """ - def __init__(self, app, service_name, paths=None): + def __init__(self, app: Application, service_name: str, paths: typing.Union[str, typing.List[str], None] = None): """ + Initialize the LibraryService. + The library service is designed to "exist" in multiple instances, with different `paths` setups. For that reason, you have to provide unique `service_name` and there is no _default_ value for that. If `paths` are not provided, they are fetched from `[library]providers` configuration. + + Args: + app: The ASAB Application. + service_name: A unique name of the service. + paths (str | list[str] | None ): Either single path or list of paths with which LibraryService is connected. """ super().__init__(app, service_name) - self.Libraries = list() - self.Disabled = {} + self.Libraries: list[LibraryProviderABC] = [] + self.Disabled: dict = {} if paths is None: try: @@ -79,14 +89,14 @@ def __init__(self, app, service_name, paths=None): for layer, path in enumerate(paths): # Create library for each layer of paths self._create_library(path, layer) - app.PubSub.subscribe("Application.tick/60!", self.on_tick) + app.PubSub.subscribe("Application.tick/60!", self._on_tick) async def finalize(self, app): while len(self.Libraries) > 0: lib = self.Libraries.pop(-1) await lib.finalize(self.App) - async def on_tick(self, message_type): + async def _on_tick(self, message_type): await self._read_disabled() def _create_library(self, path, layer): @@ -117,11 +127,12 @@ def _create_library(self, path, layer): self.Libraries.append(library_provider) - def is_ready(self): + def is_ready(self) -> bool: """ - It checks if all the libraries are ready. + Check if all the libraries are ready. - :return: A boolean value. + Returns: + True if all libraries are ready, otherwise False. """ if len(self.Libraries) == 0: return False @@ -146,26 +157,26 @@ async def _set_ready(self, provider): L.log(LOG_NOTICE, "is NOT ready.", struct_data={'name': self.Name}) self.App.PubSub.publish("Library.not_ready!", self) - async def read(self, path: str, tenant: str = None) -> typing.IO: + async def read(self, path: str, tenant: typing.Optional[str] = None) -> typing.Optional[typing.IO]: """ Read the content of the library item specified by `path`. - `None` is returned if the item is not found in the library. - - If the item is disabled (globally or for specified tenant) then None is returned. - - Example of use: - .. code:: + Args: + path (str): Path to the file, `LibraryItem.name` can be used directly. + tenant (str | None): The tenant to apply. If not specified, the global access is assumed. - itemio = await library.read('/path', 'tenant') - if itemio is not None: - with itemio: - return itemio.read() + Returns: + (IO | None) Readable stream with the content of the library item. + `None` is returned if the item is not found or if it is disabled (either globally or for the specified tenant). + Examples: - :param path: The path to the file, `LibraryItem.name` can be used directly - :param tenant: The tenant to apply. If not specified, the global access is assumed - :return: I/O stream (read) with the content of the libary item. + ```python + itemio = await library.read('/path', 'tenant') + if itemio is not None: + with itemio: + return itemio.read() + ``` """ # item path must start with '/' assert path[:1] == '/', "Item path must start with a forward slash (/). For example: /library/Templates/item.json" @@ -183,25 +194,14 @@ async def read(self, path: str, tenant: str = None) -> typing.IO: return None - async def list(self, path="/", tenant=None, recursive=False) -> list: + async def list(self, path: str = "/", tenant: typing.Optional[str] = None, recursive: bool = False) -> typing.List[LibraryItem]: """ - List the directory of the library specified by the path. - It returns a list of `LibraryItem` entris. + List the directory of the library specified by the path that are enabled for the specified tenant. - Tenant is an optional parameter to list method for "disable" evaluation. - and default recursive is False. - - When tenant=None - The method returns list of items that are enabled (not disabled). - - When tenant='xxxxx' - The method returns list of items that are enabled (not disabled) for tenant 'xxxxx'. - - When recursive=True - The method returns list of items that are located at `path` and in subdirectories of that location. - - When recursive=False - The method returns list of items that are located at `path` + Args: + path (str): Path to the directory. + tenant (str | None): If specified, items that are enabled for the tenant are filtered. + recursive (bool): If `True`, return a list of items located at `path` and its subdirectories. """ # Directory path must start with '/' @@ -292,14 +292,13 @@ async def _read_disabled(self): self.Disabled = {} L.exception("Failed to parse '/.disabled.yaml'") - def check_disabled(self, path, tenant=None): + def check_disabled(self, path: str, tenant: typing.Optional[str] = None) -> bool: """ - If the item is disabled for everybody, or if the item is disabled for the specified tenant, then - return True. Otherwise, return False + Check if the item specified in path is disabled, either globally or for the specified tenant. - :param path: The path to the item - :param tenant: The tenant name - :return: Boolean + Args: + path (str): Path to the item to be checked. + tenant (str | None): The tenant to apply. If not specified, the global access is assumed. """ disabled = self.Disabled.get(path) @@ -316,15 +315,17 @@ def check_disabled(self, path, tenant=None): return False - async def export(self, path="/", tenant=None, remove_path=False) -> typing.IO: + async def export(self, path: str = "/", tenant: typing.Optional[str] = None, remove_path: bool = False) -> typing.IO: """ - It takes a path, and returns a file-like object containing a gzipped tar archive of the library contents of - that path + Return a file-like stream containing a gzipped tar archive of the library contents of the path. + + Args: + path: The path to export. + tenant: The tenant to use for the operation. + remove_path: If `True`, the path will be removed from the tar file. - :param path: The path to export, defaults to / (optional) - :param tenant: The tenant to use for the operation - :param remove_path: If True, the path will be removed from the tar file, defaults to False - :return: A file object. + Returns: + A file object containing a gzipped tar archive. """ # Directory path must start with '/' @@ -373,10 +374,10 @@ async def export(self, path="/", tenant=None, remove_path=False) -> typing.IO: async def subscribe(self, paths: typing.Union[str, typing.List[str]]) -> None: """ - Subscribe to changes for specified paths in the library. + Subscribe to changes for specified paths of the library. - :param paths: Either single path or list of paths to be subscribed. All the paths must be absolute (start with '/'). - :type paths: list[str] | str + Args: + paths (str | list[str]): Either single path or list of paths to be subscribed. All the paths must be absolute (start with '/'). """ if isinstance(paths, str): paths = [paths] From 58ad10b41afa8a0b71de7cf8ba004220e371a581 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 1 Aug 2023 14:13:01 +0200 Subject: [PATCH 089/154] Add returning objects to docstrings --- asab/library/service.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/asab/library/service.py b/asab/library/service.py index 432064a18..53d279c88 100644 --- a/asab/library/service.py +++ b/asab/library/service.py @@ -202,6 +202,9 @@ async def list(self, path: str = "/", tenant: typing.Optional[str] = None, recur path (str): Path to the directory. tenant (str | None): If specified, items that are enabled for the tenant are filtered. recursive (bool): If `True`, return a list of items located at `path` and its subdirectories. + + Returns: + List of items that are enabled for the tenant. """ # Directory path must start with '/' @@ -299,6 +302,9 @@ def check_disabled(self, path: str, tenant: typing.Optional[str] = None) -> bool Args: path (str): Path to the item to be checked. tenant (str | None): The tenant to apply. If not specified, the global access is assumed. + + Returns: + `True` if the item is enabled for the tenant. """ disabled = self.Disabled.get(path) From 58f3650f55e759d7677346a93623bc951716a96c Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 1 Aug 2023 14:26:34 +0200 Subject: [PATCH 090/154] Add typing and examples --- asab/library/service.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/asab/library/service.py b/asab/library/service.py index 53d279c88..f2d55082f 100644 --- a/asab/library/service.py +++ b/asab/library/service.py @@ -166,8 +166,7 @@ async def read(self, path: str, tenant: typing.Optional[str] = None) -> typing.O tenant (str | None): The tenant to apply. If not specified, the global access is assumed. Returns: - (IO | None) Readable stream with the content of the library item. - `None` is returned if the item is not found or if it is disabled (either globally or for the specified tenant). + ( IO | None ): Readable stream with the content of the library item. `None` is returned if the item is not found or if it is disabled (either globally or for the specified tenant). Examples: @@ -327,7 +326,7 @@ async def export(self, path: str = "/", tenant: typing.Optional[str] = None, rem Args: path: The path to export. - tenant: The tenant to use for the operation. + tenant (str | None ): The tenant to use for the operation. remove_path: If `True`, the path will be removed from the tar file. Returns: @@ -382,8 +381,26 @@ async def subscribe(self, paths: typing.Union[str, typing.List[str]]) -> None: """ Subscribe to changes for specified paths of the library. + In order to notify on changes in the Library, this method must be used after the Library is ready. + Args: paths (str | list[str]): Either single path or list of paths to be subscribed. All the paths must be absolute (start with '/'). + + Examples: + ```python + class MyApplication(asab.Application): + + async def initialize(self): + self.PubSub.subscribe("Library.ready!", self.on_library_ready + self.PubSub.subscribe("Library.change!", self.on_library_change) + + async def on_library_ready(self, event_name, library=None): + await self.LibraryService.subscribe(["/alpha","/beta"]) + + def on_library_change(self, message, provider, path): + print("New changes in the library found by provider: '{}'".format(provider)) + + ``` """ if isinstance(paths, str): paths = [paths] From 6defe3779b3c90be91f7ab4531563f25128b1348 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 1 Aug 2023 14:53:22 +0200 Subject: [PATCH 091/154] Add typing and docstrings --- asab/abc/module.py | 65 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/asab/abc/module.py b/asab/abc/module.py index f46bb8a07..07a925c14 100644 --- a/asab/abc/module.py +++ b/asab/abc/module.py @@ -1,18 +1,75 @@ import abc +from ..application import Application + class Module(abc.ABC): """ - Abstract module class + Abstract class for ASAB modules. + + Modules are registered at the module registry `asab.Application.Modules`, managed by an application object. + Module can be loaded by ASAB and typically provides one or more Service objects. + + Every module provides asynchronous methods `initialize()` and `finalize()` that are called when the module is being initialized and finalized. + + Examples: + + Recommended structure of the ASAB module: + + ``` + my_module/ + - __init__.py + - my_service.py + ``` + + Content of `__init__.py`: + + ```python title="__init__.py" + import asab + from .my_service import MyService + + # Extend ASAB configuration defaults + asab.Config.add_defaults({ + 'mymodule': { + 'foo': 'bar' + } + }) + + class MyModule(asab.Module): + def __init__(self, app): + super().__init__(app) + self.service = MyService(app, "MyService") + ``` + + And this is how the module is loaded: + + ```python + from mymodule import MyModule + ... + app.add_module(MyModule) + ``` + """ - def __init__(self, app): + def __init__(self, app: Application): pass # Lifecycle - async def initialize(self, app): + async def initialize(self, app: Application): + """ + This method is called when the Module is initialized. It can be overridden by an user. + + Args: + app: ASAB application + """ pass - async def finalize(self, app): + async def finalize(self, app: Application): + """ + This method is called when the Module is finalized, e.g., during application `exit-time`. It can be overridden by an user. + + Args: + app: ASAB application + """ pass From 6d3c6869c07114acd56586987ad6a92787a1f825 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 1 Aug 2023 15:08:30 +0200 Subject: [PATCH 092/154] Improve docstrings --- asab/abc/module.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/asab/abc/module.py b/asab/abc/module.py index 07a925c14..90b798e73 100644 --- a/asab/abc/module.py +++ b/asab/abc/module.py @@ -61,7 +61,7 @@ async def initialize(self, app: Application): This method is called when the Module is initialized. It can be overridden by an user. Args: - app: ASAB application + app: Reference to ASAB application. """ pass @@ -70,6 +70,6 @@ async def finalize(self, app: Application): This method is called when the Module is finalized, e.g., during application `exit-time`. It can be overridden by an user. Args: - app: ASAB application + app: Reference to ASAB application. """ pass From 69a5262721beec17846e9896b3949e2174fc3338 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 1 Aug 2023 15:08:43 +0200 Subject: [PATCH 093/154] Add typing and docstrings --- asab/abc/service.py | 64 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/asab/abc/service.py b/asab/abc/service.py index a6d6479d4..2e4e99a11 100644 --- a/asab/abc/service.py +++ b/asab/abc/service.py @@ -1,20 +1,76 @@ import abc +from ..application import Application class Service(abc.ABC): """ - Abstract service class + Abstract class for ASAB services. + + Service objects are registered at the service registry `asab.Application.Services`, managed by an application object. + + Examples: + + This is how Service is created and registered: + ```python + my_service = MyService(app, "my_service") + ``` + + This is how Service is located and used: + + ```python + my_service = app.get_service("my_service") + my_service.service_method() + ``` + + Example of a typical Service class skeleton: + + ```python + class MyService(asab.Service): + def __init__(self, app, service_name): + super().__init__(app, service_name) + ... + + async def initialize(self, app): + ... + + async def finalize(self, app): + ... + + def service_method(self): + ... + ``` """ - def __init__(self, app, service_name): + def __init__(self, app: Application, service_name: str): + """ + Register the service to `asab.Application.Services` dictionary with the provided `service_name`. + + Args: + app: Reference to ASAB application. + service_name: Reference name of the Service. + """ self.Name = service_name self.App = app app._register_service(self) # Lifecycle - async def initialize(self, app): + async def initialize(self, app: Application): + """ + This method is called when the Service is initialized. + It can be overridden by an user. + + Args: + app: Reference to ASAB application. + """ pass - async def finalize(self, app): + async def finalize(self, app: Application): + """ + This method is called when the Service is finalized, e.g., during application `exit-time`. + It can be overridden by an user. + + Args: + app: Reference to ASAB application. + """ pass From 8217831ca70e4da54ea50ff2f438006c2b3e7222 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 1 Aug 2023 15:13:50 +0200 Subject: [PATCH 094/154] Add docstrings to attributes --- asab/abc/service.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/asab/abc/service.py b/asab/abc/service.py index 2e4e99a11..ed08a692c 100644 --- a/asab/abc/service.py +++ b/asab/abc/service.py @@ -50,7 +50,13 @@ def __init__(self, app: Application, service_name: str): service_name: Reference name of the Service. """ self.Name = service_name + """ + The reference name for the Service. + """ self.App = app + """ + The reference to the Application object. + """ app._register_service(self) # Lifecycle From 07c4ac064b3684c27b1bebe6407be112267ef1f5 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 1 Aug 2023 15:25:59 +0200 Subject: [PATCH 095/154] Create Modules and Services section --- asab/abc/module.py | 2 +- docs/reference/modules_services/reference.md | 3 +++ mkdocs.yml | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 docs/reference/modules_services/reference.md diff --git a/asab/abc/module.py b/asab/abc/module.py index 90b798e73..77a1c2b49 100644 --- a/asab/abc/module.py +++ b/asab/abc/module.py @@ -30,7 +30,7 @@ class Module(abc.ABC): # Extend ASAB configuration defaults asab.Config.add_defaults({ - 'mymodule': { + 'my_module': { 'foo': 'bar' } }) diff --git a/docs/reference/modules_services/reference.md b/docs/reference/modules_services/reference.md new file mode 100644 index 000000000..f1b5f3f52 --- /dev/null +++ b/docs/reference/modules_services/reference.md @@ -0,0 +1,3 @@ +::: asab.Module + +::: asab.Service diff --git a/mkdocs.yml b/mkdocs.yml index c685e8cee..110bba3c4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -160,6 +160,7 @@ nav: - Reference: - Application: reference/application/reference.md + - Modules and Services: reference/modules_services/reference.md - Configuration: reference/config/reference.md - Logging: reference/logging/reference.md - Library: reference/library/reference.md From 5717f4e7f842e956d143eb27b8ffbc9c16bd8c20 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 1 Aug 2023 16:07:31 +0200 Subject: [PATCH 096/154] Add table of built-in Services --- docs/reference/modules_services/reference.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/reference/modules_services/reference.md b/docs/reference/modules_services/reference.md index f1b5f3f52..606ea31ca 100644 --- a/docs/reference/modules_services/reference.md +++ b/docs/reference/modules_services/reference.md @@ -1,3 +1,23 @@ +# Modules and Services + +ASAB applications contain several **Services**. Each Service is located in a separate **Module**. + +## Built-in Services and Modules: + +Table of ASAB built-in Services and Modules: + +| Service | Module | Features | +| --- | --- | --- | +| `WebService` | `asab.web` | Creating a web server. | +| `StorageService` | `asab.storage` | Storing the data in various databases. | +| [`LibraryService`](/reference/library/reference) | `asab.library` | Reading the data from various sources. | +| `ZooKeeperService` | `asab.zookeeper` | Synchronizing data with Apache Zookeeper. | +| [`MetricService`](/reference/metrics/service/) | `asab.metric` | Analysis of the application state in a timescale manner.| +| `AlertService`| `asab.alert` | Integration of Alert Managers. | +| `TaskService`| `asab.task`| Execution of one-off background tasks. | +| `ProactorService` | `asab.proactor` | Running long-time activities asynchronously. | + + ::: asab.Module ::: asab.Service From 134ee79cf995c5ce823e9d5068f21c14d9369e3c Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 1 Aug 2023 16:13:48 +0200 Subject: [PATCH 097/154] Change import of Application --- asab/abc/module.py | 2 +- asab/abc/service.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/asab/abc/module.py b/asab/abc/module.py index 77a1c2b49..e910450bd 100644 --- a/asab/abc/module.py +++ b/asab/abc/module.py @@ -1,6 +1,6 @@ import abc -from ..application import Application +from asab import Application class Module(abc.ABC): diff --git a/asab/abc/service.py b/asab/abc/service.py index ed08a692c..983d49097 100644 --- a/asab/abc/service.py +++ b/asab/abc/service.py @@ -1,5 +1,5 @@ import abc -from ..application import Application +from asab import Application class Service(abc.ABC): From c314d9a1cc8ff6fd28becf7a6abbc4cff20840d4 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 1 Aug 2023 16:17:06 +0200 Subject: [PATCH 098/154] Removing Application reference --- asab/abc/module.py | 12 +++++------- asab/abc/service.py | 13 ++++++------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/asab/abc/module.py b/asab/abc/module.py index e910450bd..82c507c2c 100644 --- a/asab/abc/module.py +++ b/asab/abc/module.py @@ -1,7 +1,5 @@ import abc -from asab import Application - class Module(abc.ABC): """ @@ -51,25 +49,25 @@ def __init__(self, app): """ - def __init__(self, app: Application): + def __init__(self, app): pass # Lifecycle - async def initialize(self, app: Application): + async def initialize(self, app): """ This method is called when the Module is initialized. It can be overridden by an user. Args: - app: Reference to ASAB application. + app (asab.Application): Reference to ASAB application. """ pass - async def finalize(self, app: Application): + async def finalize(self, app): """ This method is called when the Module is finalized, e.g., during application `exit-time`. It can be overridden by an user. Args: - app: Reference to ASAB application. + app (asab.Application): Reference to ASAB application. """ pass diff --git a/asab/abc/service.py b/asab/abc/service.py index 983d49097..b8acec92e 100644 --- a/asab/abc/service.py +++ b/asab/abc/service.py @@ -1,5 +1,4 @@ import abc -from asab import Application class Service(abc.ABC): @@ -41,12 +40,12 @@ def service_method(self): ``` """ - def __init__(self, app: Application, service_name: str): + def __init__(self, app, service_name: str): """ Register the service to `asab.Application.Services` dictionary with the provided `service_name`. Args: - app: Reference to ASAB application. + app (asab.Application): Reference to ASAB application. service_name: Reference name of the Service. """ self.Name = service_name @@ -61,22 +60,22 @@ def __init__(self, app: Application, service_name: str): # Lifecycle - async def initialize(self, app: Application): + async def initialize(self, app): """ This method is called when the Service is initialized. It can be overridden by an user. Args: - app: Reference to ASAB application. + app (asab.Application): Reference to ASAB application. """ pass - async def finalize(self, app: Application): + async def finalize(self, app): """ This method is called when the Service is finalized, e.g., during application `exit-time`. It can be overridden by an user. Args: - app: Reference to ASAB application. + app (asab.Application): Reference to ASAB application. """ pass From 49595093cfeb1f65fdbb0167325187779d7f3b6c Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 1 Aug 2023 16:23:46 +0200 Subject: [PATCH 099/154] Add API Service --- docs/reference/modules_services/reference.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/reference/modules_services/reference.md b/docs/reference/modules_services/reference.md index 606ea31ca..21afd29c3 100644 --- a/docs/reference/modules_services/reference.md +++ b/docs/reference/modules_services/reference.md @@ -16,6 +16,7 @@ Table of ASAB built-in Services and Modules: | `AlertService`| `asab.alert` | Integration of Alert Managers. | | `TaskService`| `asab.task`| Execution of one-off background tasks. | | `ProactorService` | `asab.proactor` | Running long-time activities asynchronously. | +| `ApiService`| `asab.api` | Implementation of Swagger documentation. | ::: asab.Module From 2ce6060f4134fb69caff12ae0cf559cc0d833f2e Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 1 Aug 2023 17:29:07 +0200 Subject: [PATCH 100/154] Create REST API DOCS section --- docs/images/rest-api-docs-authorize.png | Bin 0 -> 33015 bytes .../rest-api-docs-default-tag-class.png | Bin 0 -> 212311 bytes .../rest-api-docs-default-tag-module-name.png | Bin 0 -> 209639 bytes docs/reference/web/rest_api_docs.md | 135 ++++++++++++++++++ mkdocs.yml | 1 + 5 files changed, 136 insertions(+) create mode 100644 docs/images/rest-api-docs-authorize.png create mode 100644 docs/images/rest-api-docs-default-tag-class.png create mode 100644 docs/images/rest-api-docs-default-tag-module-name.png create mode 100644 docs/reference/web/rest_api_docs.md diff --git a/docs/images/rest-api-docs-authorize.png b/docs/images/rest-api-docs-authorize.png new file mode 100644 index 0000000000000000000000000000000000000000..7e70b6674e4021f5b0513097ec0e3d35b80deacd GIT binary patch literal 33015 zcmeFZcUY5K_bqBKARr>5AVsQ*fFiw02c`Fp3J3`#C_R+KMiT+)9YpC6B9Md*DoXDy zk`Ry@AcWo_a9{WL{qA|r-t7PHea_*JJiG~SvNGpdbB#I1ScK{8YS7WJ(i}T>j802a z)$rJ{)0kt&j!U0A13Z&=ymSB9F|K1;s!GPbwhKfb-^(V1<`uScbtA_P9~mn@^7$FrH$(I9IndI^-S13g<77pi z>v0q;uiiIpVNZV{?3!6jSi|lIx@&prhL_uipE8Sf4?6p>$@uhytIieWzsLGjB{SDR zq?Mbg3h>Ga{^fQzS;y&lH@<~7lguH_c+sF*+a1RucS7RIR_o8Qr)K4{rty?^@%ej} zb=2KAYkY`YQh`;-RF>>Ie$`@aSE;MKQVAx;VeE9CiV;3_t7tonZW8S zGGcJwR{mvm&d^2I<|2WnpMTHu@6=;iSU274K|qX022b!bb-pi~4$WihG3C`6D_&eV zKu@=1LmU@(X&^YZo_CZcM{MuAsS>zHmDJx;{z(K#X5jrUU>Y)R zav$z`f=X#$zJ#8W_846?@3cnExNs0Y+!--wM22|B@U~8kk07THu5a*4QK&I@Ko6^) zPk&jEty70f_1KA>^I@M}V!OfTQSk*Hurhz|T4~kGk!mlVz9-WCi3xc$0XKIW3Syk@ zDeYQF`@>KRvgM`{2YaPnu7w{v3`>9cwno>-W$R|>Ku4?jNuBr_y*nRt_7r2;BvGmz z1@c%7^Z6sDL*#?6%9Jg?_1K71`1);em-*+dsRD_5DPzzPZqD`n5pt;x>rle82=cC& z9T$U)JFn_c@uBX)$WFxqb?arCB0@>nw)&1zYm8Q#@hv`&+zT;6Qbkj(u||tRzEPL! zD_&j}F*P^L)?{pHe+pHkwXX5Dfgjo@?(Y&ZR|%2n?h`+5NwfHk$}NRox*Vt7m!rc| z*ufBIPrpws$(MaD1Q`F7g;^^jy4j zgJ~R3mKC=G!^4z^czIaMybtB-8Ul6uFwK&2WvRN#K2`&faJjY5O0fpszwgtZCJ^(3 z2C0#9(OM(ecuSMqe3(GXf3?9+-ncKf<=VX^H;v}@!Uju?>QP|wJlyomc{<(L`j3kC zeCymuuYQf`1}@uZ@0kL~GoUDMzcw%gXTRi`AGkUN+Hs$i8eS$cC=g@Ulz^Yr?;d(B z8pImaJ!{=it5>uvBCVhJiX0aAr`_k*uVu36J*yw^-JB~ktT1JU{XWi?+p@kCR}F@Fi;w*oxQ< zR5`YR_iPvR%R!ZQtBE1kT6o#kz{6p$rzIdx(QjZj(EuZb``x$5NikI^k9I!sAh`l| zy7*U@<_0f$Q_;-?SXIl#*0kJE2hC)?vg})6_6lmtRg1bBn{1C&#{koL`C5tGJ82>R z*hqYmzp~R|20uLtnK7K)cxP*|OLz4~yJ>M)%%W}(KC$upRD?SFR3%7}F;yv_ovrR` zrYvaQ`kEprp+KyTx#;IP%;%ZZ2IrgrX$RMVvnf1hHkNKh#cPcq`Az_<4|7kd?@Y87 zZ$a%^KvJ|G_g;5#>~KRu)Oy;xXGJ$mIFlTyt{aP+{0PITYxvx^?;)8Q)56TG%kuBe>b z+GZofUD(LZIa`~ap)l9K_e1H3g+x2DqA!c69}x}g(_bS^X}Mz18Y^UsRm)(J+2?^; zqpZ#BTOJN+=Vj~YC^=~|Uf}aJ?rOp*o6M4Kqn@&9`m${r0nPNGx-Er>S05397r}lm zgu05icmu_z8RS^BP0eB0?gNh>kESycqWo*8`%BMne0&g$r#5JDgmp>}40W=R_IJVA z-4tbrMokQ`3%7pJffa9Z$G_7nl}Pra4710HVdUbz;ED%UyokHzOc>c&X3LTbIn0<@a-D~w#e6U z@NCuWPOgnd$zwhXF`bJ0ymlz6sjv+_lQLu}YH2L+Y>ra@@+Ncr1>$3`*8TJ6;Y_-2 zS6*GfoJAxK&L>jjYAZOeIpd=|(eyrOPLPFnqQk>L)S%wpd<5-~6RUcN+lgEJ#lrUA zDRvOI(#Hv_hDAR_$>kA;a93rr0=79`a6ibRq8!tdIOZ5RaEVW?>_Xp8@-Hf1gvb(i z^FQ#~gOPJ1%vqb0j-1iQ1N|$BD-mpx*{0MXg^G>mbeKH`)?1Gf0x1$p_x0rY0~G_i zi@so!@(n6-D0ul%@=a9zYOU8n&ZETX_=j%4y2QcGcCh7F%L*ui2s=1c1-=)UC+1h4 z+pN-V2JbIi^=4nHC#v6W*es*KJZ6OAZ}9L}2PVk+&?n!AWD~jr=faA=EzF}NTXyME zr@nsUai3X`ZvCK;J`$@KC3iRyYgq6-JVw; z4*XGRa$c4t)>XHeJIX20j8b~}T&?yBqzKo7`s$R@D!gKIwJp3`9i}xe;d3BrQNAdf zEHhqoGYWUGKyDc3Z8$i{tExv#r|tLcUET-V))**-`9(ee|>sYO*)f! zd~cI8W=R5CI@IHI4XnJ~{=}^KrIdZs`b>DjYs11Rs$rKLPCHpty((B_NzXX;{Z)C3 zXC1Z+-sWLv!&5~Ny5@Grsv@ConCRQ_3y8C6Q5(~{`z!F~L77N@T8DfH&WPakxy8$W z6l)oGxz)6Dy^X^yXpr>%AimUUF>&Nt#)n-7)Y|SZFP?`G6+jqnSs_jUH zNgTI=j-#0syKOUZUa%AQhhs`}2XQFp4( z=D{{Q>|j{n(}or58#=ftBN%QV>Ng^0QT-ID2l4UD5a1LMV#iB}EBQ=~-OzKnF6U_+ z9FgW6v|E1x89XE+xGutgu6vg^{wRqIk*5j<&*u_*3i>NfYBjIe$X3MgG%Gta6{|sw zX4eKpqCc@3*km@0E>&7Kzi2oaq9bbOmlid@SqIO!@Bal2G3cgTC1v0u8U6#!N&iMXBpGQ^S#|MA2`q@>pa?cq}Gu834BQmYI zX?+GlJvnpMyg#temY;Vkw!NsU{i2?H>ulOXM2iK z2A&kjSVvu#GYQsUp2^iq93sc0R_yaG)h>B_*-`vsy%6Z7ywso4 z3=mMMbC(pTr?|X3Ym>nWo=~#1OPQrLl=xQ#)$9bJLq3%S5sKKydRq@t}$xfaF#=b;)Ay^L3=l5W?@a!iy}}e{_pfs zrBp>7o}==IB19EuhsV&@&%1G6jE!zIPKe~(2x`V&%}}NkTZj@&Pso;hV>ERk$GkIP zOYy$GIgZ*?#3{@kunOq3$6tX|w}!>uTcQ??FD2Rq@J7Y?^=y`*>mDUS>r@GKKRjob zx_(7d)!1z`TvaF;b!S>+`rUteIrI4)c7H!~|D@F4wYpS)651>l@HrRlYC1-Sz-kl_ z^>qb{Pj7WJTJBm4!MbHmr^39cn z#xJ$eD4%*DOPR*dOuOoBIOS8!9}uu{f#|rM6WkaOpGQlzj~A8=Pqy-h*F+|JTxnl6 zh=p|DGDUwGD6!C@VY$tu}<~Z0`EI8XKvRJ&5n!$$Fcq)1aD55RXrFJ>4l1Ol%E@29ek4O4Ai% z=adwjb~P&`Zs4QpHrXJmk|;ErCG`M3Cz;v0-lqU`)b%^w<%5j`=xkGoW!RF;Qzmd` z!*hee0q3WLv(!lrw^jgwViVTTuwsQ+*i86sh`}Vt_kWVK78rR|)+lm#oo#EH@6O}h zaY=|iaWaeaeY5okGKVPfe%*0V7WN)`ad@gXQ+v?ol`QO9am3$txnn2bS1RqZur>_~ z`#bLK>sl(vh_gjF(3~l?IF$?{yqSHApT|63xqWSW@T#N?X8-Hpd^9GpGtiriYj=R?IEeLw-wpt0HdM7JngF z8wBC~B2Bjx)*s&!Jf;AfKx4F~gTh&I{03=O)6Yj@m_vy@5&T|_S_nGgO|%Nj)(3ME z4!kU~hu}@VKQ@|gP}H&qzo%`AI`7u}TP8)aKp=u`;NAM<`BW{-pwJnML*EPZ*`#Nc-GO|4u)o>yk>*0H=^m z-=uxmZP(4_J!CilWx6E&1}e3as=wkF#AH+sPpF@ySU+nx;WoJx8?J)_ce4$vJ9Spd zV4(%#(YpZlsV;u=kG#BM{*xE1V!j0mV^wq-c`)#xMLa-oP4oOUx!?AWc&f9!&3`e& zh{irHeEDmdF}z_NsrMebO9e^eMXKE+a@`LCroNh}SX1W6pf?S@lX+Im+4rvDH$Og{ zHp@<*V_7`6xG)1uavwy+8{@m*Dv8TZIav7IUB~^$=V_|h0bXT5i(Wf(JNtq{UCqqLjy3THJiWzzuY2geoeS)iz=kYcn05B0;-wWvL z+_b&EcE{!b6QJ-sn<76)oekV^S(lJ6vDxb&k63!id3}FO*c1mKRJ>n=%r7Xuz%Ira zgI&vi^7?TNox+AWRkT&Q$2%<#qQELaergqlLa={C@cotpR!W64LC1R$KdC-HGC8u6 zMYQvqb@FcB^$R@kYw(hHqd%~2W+o?&dAGeA9NWF_>hjU1!IbZouO3IHts@;aamm#W zXXfe>Dc<)ZW6y0P@Rzfq>IwgsLyD?@TpL<2M4UsL3XNinrJDEDb_j?Z6v4rRVX z)VCsCyZ7u}$KBME)%3_`gN3HeJvzs|JRab(nA7At_yb0RgFo^#X?xNB2n-ZLbNg)n z9*r47r+i_{P=?eA*D2JD17r<==5mEJ9SL4&9nI-^9aSsqN_x5xabKVJwt;8b=P`@S zP1Rxf*xVH{^zAB~(;K2fSFCJaN5%|CzCR6SBm5-9C<`J}8v&zDX#f3W62edbl8~S* zl$92sx`!8~DB~saK>a*WaNa1*8%OS1sz93Uj{O08^Wv^fvJsnEL+`xwR0LZvF(Y2i zdTTr7+=r)CwN)TQv=QOda0JjzwE$gJ*m^W{qA<0pnw}1n*p)du~N}N){F1c+l6wIuReF zSpFXF8tdPY!FZ?cpobfHq2l`1(cn$S3~@(aRn$n*Tl|e&oGWD)NtBSe(3LVwGjp9H zyx<2TV?e*G%YIM|6m*ei?5YDI=FT2OFn4MA_|kUE2jMyE$F$lS_R}ba2Ny8%n4RZ$ zMph_Ms*>EE>{~1%-1fl;j+IIE&YEBNY`sJY!*Dtr4CrvnDLEz0NGowc!$+5?$$9#O zQbq^kZuK`lbiXOVenmBk!3QP}PM6=vAv*Vc!HT(9<0eI|Dw2mJi3?U^QV2#g0NSzv z4h}-PCYqnv9KpA7$_)|p#c$_*Xs6A_ucTl+PiLZ1zmt$>jRJMz$x7`Cl;XVJz;4oM zXZ#Cdy=#lZ8Wv1E!fwq|cK0{n8q>eKy=v3&VoZGUp*6=WNhg2k~94J4CY6h8jM|$S)`tQc9>URal5ciLi2L2F8 z@uqtxMC_`%ippG0J8COKY(6@nj+ZT_>OfsUZ0|@JFl%(W3ZD^Vq54J^mNw}g%p5&- z3Rz2p-nKrx8<=wVhZ!C%$6*D~Yd`Rp)Kt8Q>s?+WbNc?hBP*ZmPWZA~szGp*(ry{n zqAv5xq5X0ud>U-O=1vjOy@MS_`AFs=OA!0u@|CMDoQu&a3gKXyOoc5|H447^r zq3oB@jhMv;-IOF5GSBNqaXmGv4=0<@>7>2e>PKAOD)g?1|*<_17;h{sYHw zefWB6(Ko-2lo{Ap`O}KS!Yj5??b&A~Qo{9nbQqugl|-~eDqS_b27y*@uoz+`5x47A z^mDh@#rdFU4pt-&Fbr-|S7xF3u-T@-l16(y2tzY@$H?i%gsIz1}RP?3TT#L9%zFRfDJeLC^SS!-`jdR*a+wojQzRujw7> zI@e3H$ck-rm`e6nc^HqdJb%_^0Cf2#0PHgc<%zee zsbl=S22%;v`yjoRSk=iKt4}b}pG~qRSk1DWESVft-fEe8VW+-d*_8^JUXHfE_hijC z68hL8|D#*hrc>Q$yi=wyxqo+~Q~mu}di)lDWZ^q}-suh{0o@Eywq(2+kB_LyG^W-# zereYwO3bal)4RY{ek{SgThTFarhu~wE&*EL>V+?6G`$}Vclb6dC; ztH1YI?`$i6gDr4+bxsOryAv5(`=sb&EHA92ghEW;(u=T7C*X61rrz` zhvR=XGDO{`><+*sz8t*g7J(CND`R$o=btDts!NXqxL1R80=m$|s_>_Ey(pqx`ac%e6FyD-J&pNKpy* zQrR~f>V}`xbjfS~+|7hG&+*6M!A*9JMmgS|$`I;=Qp3wHY}E!6yi7y>g}j>^3MDo* z!XhU5E(FeMaE{qjdWEHb8hCKtE!(Hz1~xNlyD;icpSqE}DTB)(c~AZatjd{{_=6cQ zU%t%iq9d~ApcSjG%?50f2!_I>1Vw|5!L7l*7uNJfFokZkdat)aS0m6;lBq)*6X5jO z>gRGtEWV4U7T*C~xqlH=o$dU2X~tIc!e@r|uic8C9+5ivfs;*i1qP`2X1cRBENnd$ zA#%2xjHvG2Iu2?!csg-9tSl!GE})w!EojoA?&JO0z9!eOMxC!BYGAgd_o7c!+jNdg zqA64n_tN6cvl_-&{hEoQY1KV30-al6mQB&KX5FM4v3Z>ysp^CfXEsIz9pWv%xkJ_h z^+YzRu7?w`@MJBgxkjPlMwPSj$aJn+_?hjl&yeQDKLQuDA_EY_I#R`D44*Fqe8`*M zzT6tyUYKLVBhh_#*eIX)+iT z^Y|YxfOgmq@sDF6pR%&Zp*s0U51n)cJN2kcj_J?6wmm?pDlpJq!4{VhtaG41Qj`AMV^EZ{@_Vdc2uNMw@{rH9A*&mryiF>qFee&xni-~skXF#lIhH$i>lBVTlA9Nq4^V;@y^HI|J_m2c z?}f9x*mK2qoE8Na`|Ekje}NRK8#d@pk>5e{iG@^ujqF)wm*oDt zu0?G-A(Xmzd7GKtj<_;>hmivia_1VsE74_(PN@(x( zVjV!;VEwTq`2>aSSRSCY6aW@Ek_0M>n9(5v#H>6&s4qJqaF5>71P2f}4*oXPVIQIV zvobP1RC6qKKb6qEkz4`Z46e1MnDpu>+k}|v9xhLImw6M_hoP29&L3qR^hIFV18<Q$Zca!F^aq6@t;>uRrR(zX*SSbvjeO zzHD{4i=sQ_(W1=ef&bTP7P?(Z@R=AjoztE}can>TII~D1Ee9tY zWlA}kB)a@!BRpXNlhbw;=Kbd&&a+Fq(^2G=UEB$I#aUMXeaGVJS4(Xg`)9Iy&to=F zeCsIwg{JqdDmo%mIRyhZ;%1TO+-4Z16fdkncqgT9{G?ouR)&3Q?hg<5$-nM;)IVn8 zIo?yRRN27(WJx5$W~pe7gZ^QLg1kK<2)}iuTEo*r5jSr}3h(JW@a$K#3*Iyt(qX0G zU;kOQ^9xJ$hrNk8Nc%sSIba(u5Y_DBwYA3yhZ0D`B(;uLFBrk(4d*Y^mAp5u{&pH9 zKLBIPG=E@Za_o}Zi?|hNG5PK6yLX#0L+=nZS%~zHOCN|cS@j*L=79ne3mJ6jSWiDr z-^yxeKrDU^JTJ4p^|);KWj`+K24b33NA>VTqn9&*4T6}wI$F}5x#VMwoGfB&zVXl1 zc3z9CHyFQr5mRkcBu8n==xww)a%2u?1jKvZ&*_OcZv^ z*~Rk7ub@|50$|!OTlt!{S0_V?KMr^SU)&b^Jm$i6xh8b|uglYQ;0O7^fcS13MRnP- z-KpGq&>O*TFN$VZ)nuT4qz=M=>{N?A7(Bq0>nsP18b>ud#Q7g+k%xU*X>|xufD+_8 zlGfJ`Gr3)NC!HX~`Vd_lGH1ak= zCzbyz+LqRpNcU?zT(p)h?gpxk;ut`u3-B*-lK%I4^H=#11bd?tus{&dtsvp_dQ8qA<$Y(R zc81nxyxFVg#$uxqqlMX1!c0%O45Av8DS)lTQXYdrth{aYP+c1Kn$3;ZVH=7Do3w>v zpRYJN`$vnDCELFL6m%q&$YbTx(n-DIXgf5Nd$$+_`6S;?QRh;IG|S*69EaawOusgG z;KmHj^uXLnae0}3#MUU-mQsnrI1F zDnMhoFN&e#0Nd-nyv!)=w_a(|>%ZfkG$MMK2uR9WPOryL?5sV^dc6aYe7o-Tgf3oO z6{pax6~kY8qB*29I1G?tSG{N|CIik-uJaN(>$g_co{qj3&np*vfN{zco z^u$vudQ6u>-lmDAa@l_P@O{FBmgqyz3AGJdCimI_rE!rfhj)}Jk*JFa))#l{~oPY(2V`u*Yqu6s1R zDF8EMjY^^!AmiLxZuPS|0Fct*7072?hC^g8^ujEG=UzSSkUUcpA6_H#CRFY}!!eK( zgI@X@UjSS_XVetS!d7t9(=$P0Cu#HxM$i2v-KPlI`t`||G`Zuu$ zxa6k22$qHYm-|*UXy5^E+g%aZPL2A{ZOaVr*^ao)_0&1cp-O=P^0g;;OgpCOX>8-$ zxfAfX7HzGwZ@*+0=A5tA8&rXD3X>!e{#_7A1 z?VGoEE}H$Rda)lenYV)fS=oIr0pC{w_0JdnTN@tivj9%K!|o5VM;ax8Z+$5OFadso z4UF9UJAnBwp1F8<`W$BR@ctD2KX=l<67WhDa5SbnbBIg+o1^gu0Y?JeG}ScWf$Hao%nXWusUOaL8*EmD#D&HU7d z-=3{b}Oeb+ybD1mOt+7$tOBaY&lIYY z+&8n+;XXGnbgg{+z3a|aSyck>>eCf;-|w*ZPlc5d4&h1?haMJvIoh{Fx~zfNk(m%bBN+o{pj2Cyp~ukxKv5QE+R9I&$iYK@Ud z7V{JRyfNHor}NTPd2V#DOifP1Ez3JfO<-yxr2o;JzhUx6DmqOH(TFxVpU`gR))o>T z*U8 z>f2A&9;)JrhzMT#>7M(gu(=uGW7;H6gQ7o#A(9;KH_wPu^gJUMX`>#Eu?{0QZyO*V z<+EoZY^uDE4&6E5e0j$;=^{VNq7oYo%~?8-;$(gYBppYCA-|Woqm$Xi+dYz~-k0(l z*T22n9lrYJyq{w6Wmh0L+WGQ%UK~ZYEt`|vx-AF0DYh-HRDWDmb57~`Qq05M#FI}< zuOi3GA}c!iV_8F8;xYEVG#He110P)zdo)PM{Sl2(GIe)Zg&*B@Bd9#YED%NT(z-&u zbX!GRtunaX?(l`d8C)mhy(O!1l_@W#ABsl25d$1vntlx&9KXrGoC;eNZQYgm#XBMC zdz8gTt5xRA7Y`kF$4XaSxNFkG3ie5XXfM`9@BDJT1nWg}^tP>9AXhcd zl&^fEuRG{Y$VAWdKlURuJTd)QX&+F%kS!M{nN#bIkSPFlb*A5HDKxJLt`bJ-W`atL zx{1*5TZ<^7LPg()H=-EWc2m41Rl%{}LfRGoaklcJw^3or{7P`{Mp%WH_&WbUWOqY} zwd~Qm$|Db&vL~>Hq&ft);<-BeM4bMl{N+GIAd^#zz=(!9Bfxs zJl=Apwsk!Zj#3^9-O)()zNyu52x5RxEU56Ggv>c5fKq&to38oIwRKwDXc);;_>kh5 zi)n3<^iVG*c<QXo+y7grUIcWdDGbx<*3~~H<(KeHWl%KNryY4f0Nb#=j&-q>`d=6gBJsIkWU_QIQ6z5gq;m?TlJn)=5ua()hJ|q!{&Ab^WGjR=kwIr}!Tx!Ua zi#5Qdh>@N3>y{)%{W_Z!y{(6(uAS#%L7;M*;s?{hvo@omTlsoRNp>_Ory(Z(>tBx!p81j0#GGjL~|& z#^g)jW|Ey*3H#B(+2;V0)!*U4swamOa+#YwwsPY0!rz88;mao1m<4oXquKcH=<-J~ zYYXu-NHZ~lw?viJ6a`8wO^7?%r#%QPWi55NqLz(g-|RAD;#y-ZUwy&y_ikQ~d`KzD z74c5jxZhHnsmzx=M=~ha_7gmYJ0sv0DSxMNti>^?zw7gG_Gfp6g(>psiWLMlic7gYwtVS4ST%UY!7jpSy>`^& zyvzvpw@TDcwevf=i~>6loB_jrmGvS{^4038@*AHkbU06j<;hoSB=zhI=5?~#SC3lv z)AJ3y{oUE2o=|_G<}p5T?Wuo9x}_u**LegX{})7jDRSaCEv7pKjvq_S_=UeRrAtSL z=}y(TjLFe*4cVL#zL@rX{VV+{s8E(!c&xxHPQwdA5Igq@?GU(tPEr8Y)8W{6Gi02m? zOK_wW(8_&(?Nh{#Z4^94-pUkKWEAe4NuGPFWkhPr<;1oojc4vbbkpE-l{t{P;a3vC3W`bB7U*b<<$O_ zzqHkZ;Tpw>rlFEU+h?6N-1ZtHC9Yl0g(Xq!vK)^2fq7o%FiY!9p{W}vy9Qx^PkT{* zwdly{_VT6OpSP^B?c5I%boiC8Rd#^z;0~N}Rup}z$$3rG^)+yKQGZb=&Tf>9@7iCI zA1W=OXwY-W+D9r*O0^AKsY@*+_Q!l05GWVWQq zxD2rU^4%xhiB@}L*4oOH$LF(n-LS&jq`-JwEsEh0A!@|m?Rb^nMq#n-8j|->f;M0Y zk3mBZa)Dzc19`B6SH;kIrS38WNv|ReH@Oc$3gJI3(Mm1qGzxwmKH8Vz}r_(F& zngBm<(JYm=K77Zn%2YYR=-T7}g(6{V)oNYqtEK)vgPTnP8Z9^jr(qH1qF9Q@oaMZE z`z$?2!fu4jU!rL(Pxa7*W0B)}C8*3{^ps%QDB|~r3!LH>@Zp0H5G2-`LwMt(rz>s% ztTq_{>6Y6`x?^73R((L{GP5(y5~g+Zgye#rS~Sl`24<&9mIwl3vcptTf&0YNtz=R7 z7cX2%mNy}ih@1r6S586kd)gN>@MykU787tQK9ar_;ghjnT`6Fw(6GI|_1?P5-Q-}T zia;ah;lO~EA2Z6??2r!si#gG1#G9TYlGd_TrzUf99yKqI5+}8P)%kUvnH#CEx?CxM z`s0UR-+NkF>+*VuCBwhZTL=*A7k8~}C7;0JABwbRAU0c_s38_E14xsfd9Xi1-&o4s z$~}K}K9>aTT-JlP*A-tF+6Ih+$N_eQDDBj$2OO0R`OKS~_rKM{qxIXa$}V;T$gF1s z&|6KD6yXzhEU-@_I+7I(4RaoXg78fI-3e{XcA_M4NnPC3n~cmyZE?4z))Y8>1BwVf zJNhxHBG*$SO9TLV`ojjBgoTGrs??9_j6cUu`l8}O2mEVoNF0XwkKr%^xhx$nPdSY+wjG?is)Zd+=pGPgJ9ziOUr$k^`ub#ITe zW~%*wb66M&I9~(xSY>ZctQGW=+V=szxHs*ELgyZ63^j$vko$^A1gr}{<I+8_J zwK7EwShUe6e9s&WRemVG zlDz^xbeltmKHmnkAHxDaCc$4qu9hzW=rUyN3}Nwl)OQEzMGGvav-tI@*H zwWfi1AUHsZva28I!*~>hb|dcHK%J=udv3Sf6I|YsSVA>WL4~FMkFc)a3^z+dbgU9I ziid7Sj=SX7z34Yh25fADxzl|)?TjQu-P7Q~*FPA+B6eaHqR%urSE@b-J#5C#Tub?F zzE_}^e$mzorLu=?(65hN-?j%BGa7xqwv+!b%3oo{?{N_oP{cy4RDyM zMQw?94rRV?)Nur=p~j$p#3Pq}{W`2$J@NV+?c41w!FJ{&JLnIUr-6D=2kevm4|#)f z5S!NdgWReoC%J=Ys{zC3dsAz~VWY%wHKfM%o_ra`%pI^u;1%R?8F;^*OxZ*1ZI~o= zId(xZi}L#wXZy*YOXc!oxCm~HntH==p5kQ~ZV^#@W?=0)U{3az7=G~ zQ0-X;&JECLPY-PwtX;2+l4qyZxYf)NXzqvDkHn;jWMMav(8qWmPv}?&`XNkNG^uBI zi@iqGD!|z}Q^5uws_zdtx1#GWI}-|OoMo?RfAUoer$I-82hESm-0p-H&Dx+Da~h1D(LgrR?>Kdq=?Q) z!@-FBkyCC(k8AWTz6*_iv!}rXl{M3mML=1=vWU?#VomORO%n5Wd<2aNt9js;OvGkb zXcXmy0Z>>aU5d?-(PB`2BUYa69>o860qPCw`l%6#fZesW#+@Y7If8L??hl4Hg zYB||I(=w|P`>;1-Xjog%UBk__CVX!U$L28gtH89KsX3|UaaDk$#79p$jJOoM>r|Tz z+G&T3NwrFq0qZ^27@H6BXtG2)cslb{1y5$+qxSdPm->38-d|r$mIExjQQk!z!HItI zcJ$l7Xm-;{{qPxD79`rwUl!k3sjHe#S#xQ9^*3DppUV-3Ya0& zB#$oxizN)ZzMb#SVr33|<2`AY_VdJ^dr~e}hMgqn7lvJ4qM@T-X`TR%roGArb4E~K zK9-l^A+#`|-{J{{-{{t&^)&f9m@GG`^F_vflN;3k>6OVXWU3Yzv*u+~U|qE9f^~u6 zZgr|JX0iFkmZ*cQ7+`<%=91hov6~c!`2TOng`N?OoX9OSTo;G~bkdV`ney zdD!>8S;zgR=Oc9N7DtA1W9&87qmsITVOy}=G6q}+S^3aAepAk&&gLjP+gW*ne4_-r z;@$4t7+AxCb& zi@wZq(Y@6~5QF={zFN`KD!@vkt>z^pxQt=5s-WJsqi1*7wFohHxs$Hgn+Mp!EFVkw zT0g!W%)qX|59-gxzMcV`b6OTm?gTmw#rbyrFE%ys&&(2Lh1&q88s;)wUVw~RcqF#0 z#*?)}{k31eeqH>a9x#3k;bkI&(mvQ`(qS)ns^x`KSFgiUG#CL?8_%kF(^;FEXVa>?na7}PN1^Ih+k6+l=*zz2K=*og@=-$DUoi2~TVTYmecz9q zI&ui-xIRb$O(#>c$Bgj5G@Y+b-2ikaE)E{aSO3yF^3nsk(~p(3sz*mh?E#n4AKfXm zxkcybM&#Iu{~L<`H!}a<3B~7~G=CxaTi@nlvsb2xk*ysGFkbul zY@fr^8f!F82Ul+^9{5|-7sv9XI0bWN^aMVA`(5kEN&BM|`1cnOx?{2_FVW^Dmqou| z{X;9g?2LwlI1=K#CzT(aa&vP2usw)%;y-e(FT!8F48s3WhO%>i`B1vTMe}uaTQm7? zDo=KQHp?N5T!bN2Wtiym;y*fQO)V$8tWq=DSK&X4pNJy3#GjLdXM zq`tprqxBH%37|Z&me2IriL{t`d1yvozqOc>_q^S@Rfp-fK=>s0tSknqJ#KaYS5kMA zaydQN8XMFtYX2yIe<_NV-&ODSXV$6rN!5piM((TM>E`U#ypJt{h=9advIY>x>*qZ< zjw}uLSk7tY2Ttz_!R!~F?0hn%x7croX(iq+5JT`A{V>rT_0%0&s=gVUG84Jl=96-) z7T3oF$Q2wQ@#%bYfN*S_P?F4qoJM}#C!_k%OwhDXeAd}NQs~s+*?xS<_&KR|#SdMl za!FGGzjR<-#@-boiE3iT=`}*e-%E&b?mzn~F2$D`cJvQ4sti+UgZKCQeitwoU0c37xd5c>J6O1dbF* z7Rm8K&P&dx-Y@%!Zmaa2&UMg@)xIqkr#qkY(2Ko#=5=OQJB>%WfQWUX^|d$IyFAyX z;?I6x8iW!fMV`e2Lf#)u>Gk89rv9PNpX@P zpt%k9`c4~aX?Q3`dJ9%#@k?@kKdZ;CUwhqgJ$cH&Bh6zk`io0NcIywGXy}TC$I_BX z3+wb+SOG2R2xk|tSYK*BP=+A8GTbbKonP(}vIP5lergHE(eI*^VaexTHpBg!-X=(A zJL@jR54_QFi8j6!qe&)-wxc<_T5bD>vYn=XhdPm1!FG~LQ>;e4@~%YCHA}_3^Y7ix zR(3I1pX}OE40;$=TacY`UbWl0_7>GF9esi%b}QzgP=Ec@j~()iQ(kueBa5k>L(AmK zV7!s`$C@8#UJ&$q|0S4FTUEQHWA{ptY3c=y$^gV-Tpwky*i>ZEMG|VUm4*A&+mR~i z;cl@>hFM@5jRhn-grx8DGNpUO7FZ%`0t>?)yVjmO(SAs#O-PJknZm|(ECg~1ni^!=?9+Y6s z&gio`LEgeU-{qpf40#oI=##(J8#_Ge6pL$Z;bokH#wGAOyh=} zz->zGc5JlM)G5#viYFa_J3;mwyqqTI5qZ_DJb}7&9Njltb!1~t^3UoyT9!IjF3wLD z7|Irs8WFz#LKDrLIDQ@@esd5!&zjS3Wm2TWe?5987r!(2eVloS)sTLB?AA`#+sI*^ zP^&vm4`IBB+eL=>Dv?!3CK>S0Es}Vd6+{)?XQ85v9O&G)%PHX*@J1K(RBdDu>OZKp z9hz0SHh(@&l4E+Vd!M;2@}L)=>c6I#*xBu_Va$qnb^=CMC7XK8GQ=YvIr!B}ogI6^ zkgn7wglFL3lc~3$<{+R#;xXzRqJdd%X3<3k1W8no*S2h$2Q3tF=YYlGr@Ip65Bwi-YI$e4ZEo|C{rUPc;Y|+lc8ZlS4LCZIwXgya355b`}f^#}(RmdIpz@ zflQ_+8Wi2A=u!WxAtR~RR?=qtYc;p6eP3*PxF*#qt)wD^ZL#;fjh)E0bajeCw_By# zF9m6f(V{2f&DtPtyo2Ag@+loFu_g3v2YTfZjnE_57@~&u)-mQxq4eLx-H6N4pNSr~ zQL)O!Z?3)Exne{>MNWzK&ENdpgOaR}uN(KI(ExPBYS}mc`9`U2WoFTl$%)5?mPvRy zD;UI93SL^-p0c`QK4)+xyx&f`#-8QfWetV{J=;}U=bCkRNuLj~A0$%rQc*Ocr` zP9%#a5Nl#$bgrYCPZtqKUR9ps8j~>vwxcEz4z>aP8ECedmTe}Ij)9oJpz_XCJ6E1y z2~{@tF*HnpIMyo71c&Ib;oLe{YT-xFHrSO9E^);Y^ZG6EHsVkfIV|t4Vj^Nr#3`xl|4zR@SL+X4&SeIe> ziakI*W>rSKaUP6}9X1kqRFNuuDqy0B!3v|{4K=!Cxm3Q~Sktj^YNG>P>oxkP;jPcZ zh@6181x5XKgGQF&yL0bf`Fvc}9vEN`X!ht+VaDu9_Tz9fv(b+=a5k^>3Zswz#KCD} zg85655*OR`VFp`ur;~7T`j)o{3Zn3UCk!5#UW*tSY#^*3%lk(~(^@Y=*b?R|KfwC~ zG52D}c4$609H^QIvTnPfcqX%~Z~_yL2FJL$Y$04R@Ma9_hC`pl#k@JLi7WULrSA#- z?JXsmBRH$93|djZb2K7Ht|QzwVstAmm3VP(OX2`D?i3PG^5udeAYVjoMOAvL@6vGhPpy%KPYG zuc4AIj2YwaP#-(iv!oiAl#3A6|+P4bY1AZ$|3?&#iybuai{?02ZPmD)PPz-o^3v42-Fg)V$JupR^ zV0Lty8{#<%Gv7>MoZ~`-KE5#Ns{%nin{tZ!%%J0A$$@F>YK`FzAq$2kmyDv7NM&0u z2@2x1v#n1Zv_)dabVN?g(9XtHD@h(Ht!$fx5Dgwclyk0KK^{{V6Hta__7281@u70^7 zU2R-jychlD_4K#;GK^2quHHO-bbz|@iPqoCQIka~Jbcmuy!YA1PHy zcRR;Xml9|)gI)Z62yFQK!`2*NZLx={6-6RG{b?4^G?ezz+#S9fX|am79mHbiIb<$RtS)1YEWND}U>qxPQ5$btb(8M}Mufg8ghdeg|# zR`TBb*L$!U1_H*p#==c2$p=AfNMjgukVhAWjL-M|R4tbTD?{6c>>olx2hoEcE<7LT zmVB34v+wt0RsA1vCpuSfs1SWo|I3^|kY^sD0ch<7pMa_=)dS0?apW%f4_O zIKXlvvZ3b94Lc0D8wpAp3Q*cCn%-lF4AfrfPP;x_UX84pVYB4KX&h9LaP|h%x)ffw zGhz6U0w^FvG7i+${_feyc%V1>%j*tfJ&UKYUF`dB5B#4`9<>4DG|R0;e;3LA^ZT>o zLO?H4<(uNn2Rc%~=k>l1mN(x$RlET;QeEVJr*f*DtqS+@7apOvH=kh;XpcIXX5kKzahELdiOpH^kP2# z`RZZWfV1NQfHvHd5obDdMZCYt6px5&9jbBHH6rv$%5j|!_l^Ev(>iq=$c%VLbg~{g z&0V09krscU;?OZ#B7w}vzohuZc>i}&Y-8)UPIl+ClVrk>FLjsT3=gv-=(vro2BYn7 z8eEmkqrd&`kJ2ZO{U+>re>}Y-)@yvm%9P#QT0hWW0Au)Cu$MvVwWMLt%n5md{=VSaBivi#d;D06Z zcP#+yNUG)G;{i?hNfL4BLm6S59$+@Hv%XA+vHX#4U_4lBBKSbB<`*&R0EVW}-}gA2 zp}BxDx@CG94`b*EPC#hXM|560bPNUH>>7nj!{X*aR{XEemLCF}$C*$~f9M#_z!-`X zcSH`|y#F@dT?-uxQ^sS_&+aOfmg6M6MudmBIKiK#6=k?X|5n4;oiL%FBV`1m=sM=>Je;!V56qVJh<4h_>$2VQ^D_+qMknaV=xUvrhd*wn&hgRVCsKZT-zlZT94G^g;}gTqbTI zH)v*B2w0?Sm$A|o2UqXr`WfUNv#4=@JZg!)UAwk`0Y5g?kD*n~j>0@lRa6?yNl;%$ zk&$pu*o*Y**6E-W=(_+lPW=Te~qAUTMA&Vi~ijdG~HVN3p00 z>P=UFowt{y#_S#>8v;Dc8DYLGq|v|YHa5nZ55G3(0OiB_`MWT_XQzGm{iX@TTf zZy-`E9X|42=XZfQ_?FygqG#<`$X4!7MO@$*B4ze6DqP;A(*1e#$@vLqBelRo7oorn z;n8JdjSq&trb zQ9G9-A$)_XSm+2m@>V7WY-8H{JrJ463YmdcIgjo23A!a!y3TwTWcIh)sd-x21U-4E znAl?jkWD$!bF@==7mX7=Zm;=hIHV7=+4m|+ayvEAVuM=cob>0`d=@+Z8K)Sc(1aD%}7W%N#|*7Y$e^4;%0Dvphe~V(JMT1nfwr;OP5fgZJFXX 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 ozG)2bV<2Oh!Mp$8+_LY%eRPR0f54)bS7ytkO literal 0 HcmV?d00001 diff --git a/docs/images/rest-api-docs-default-tag-class.png b/docs/images/rest-api-docs-default-tag-class.png new file mode 100644 index 0000000000000000000000000000000000000000..1e070eec3c7a7b632d249d69db055e395652fc76 GIT binary patch literal 212311 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 t&~Ff^kx=w4;<@~ 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%0A%1$Z{%aqtfqM6ZmlF82-yrPU)>1 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 OZWx&wmR@y!`riP&a=$bH literal 0 HcmV?d00001 diff --git a/docs/reference/web/rest_api_docs.md b/docs/reference/web/rest_api_docs.md new file mode 100644 index 000000000..09ab3fa49 --- /dev/null +++ b/docs/reference/web/rest_api_docs.md @@ -0,0 +1,135 @@ +# OpenAPI Documentation + +ASAB's API service generates a [Swagger documentation](https://swagger.io/specification) which automatically +shows all of your endpoints and you can add summaries, descriptions, tags and more. + +If you want Authorization in Swagger docs, you will need an OpenIDConnect endpoint. + +## Creating OpenAPI endpoint + +First you need to initialize the API Service: + +``` python +self.ApiService = asab.api.ApiService(self) #(1)! +self.ApiService.initialize_web() #(2)! +``` + +1. Initializes OpenAPI Service. +2. Introduce Web to OpenAPI Service. + +After initializing the API Service a **/doc** endpoint will become available. +You will notice that some or none of your endpoints have summaries, tags or descriptions. + +That's because you need to add a docstring to your endpoint method: + +``` python +async def endpoint(self, request): + """ + Summary looks like this and takes the first line from docstring. + + Description of what this endpoint does. + + --- + tags: [asab.mymicroservice] + """ +``` + +Also by adding a docstring to your ASAB Application, a description will +be automatically added to the top of the Swagger docs: + +``` python +class TutorialApp(asab.Application): + """ + TutorialApp is the best microservice in the world! + + The description supports HTML tags + """ +``` + +## Authorization in Swagger + +Authorization requires making an OpenIDConnect endpoint with an Authorization and Token endpoint +(like with using [SeaCat Auth](https://github.com/TeskaLabs/seacat-auth)). + +After your endpoint has authorization, [here's an example](https://github.com/TeskaLabs/asab/blob/master/examples/web-authz-userinfo.py), +add the Authorization and Token endpoints into your [configuration](#configuration). + +For the authorization bearer token to be added to the request, a scope is needed to be put into the security parameter in a docstring. +It does not matter what it is called or if it exists, but it's needed to be there. +But `- oAuth` always needs to be there. + +``` python +@asab.web.authz.required("resource:topsecret") +async def top_secret_endpoint(self, request): + """ + Top secret! + + --- + tags: [asab.coolestmicroservice] + security: + - oAuth: + - read + """ +``` + +After setting up Authorization, a green `Authorize` button should appear in the Swagger docs: + +![Authorize button](/images/rest-api-docs-authorize.png) + +## Configuration + +For authorization you will need to add a `authorizationUrl` +and `tokenUrl`: + +``` ini +[asab:doc] +authorizationUrl=http://localhost:8080/openidconnect/authorize +tokenUrl=http://localhost:8080/openidconnect/token +``` + +If you have an endpoint that requires a scope, you can add it with the +configuration file: + +``` ini +[asab:doc] +scopes=read,write +``` + +## Tags + +You can label your handler methods with custom tags. +These tags are used for grouping and sorting your endpoints on the documentation page. + +``` python +async def my_method(self, request): +""" + + +--- +tags: ['custom tag 1', 'custom tag 2', 'custom tag 3'] +""" + ... +``` + +!!! info + Remember to use exactly three dashes on the separate line and put tags in array with `[]` even if you want to have a single tag. + + +If there is no custom tag defined, the tag name is automatically set to +be `module_name`. If you do not want to use custom tags but +still would like to sort the routes, you can configure the options in +the config file: + +``` ini +[asab:doc] +default_route_tag=class_name +``` + +There are two options for `default_route_tag`: + +=== "`module_name`" + All tags without custom name are displayed with the name of the **module** where the handler is defined. + ![Default tag: module name](/images/rest-api-docs-default-tag-module-name.png) +=== "`class_name`" + All tags without custom name are displayed with the name of the **class** where the handler is defined. + ![Default tag: class name](/images/rest-api-docs-default-tag-class.png) \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index c685e8cee..e7094c1a7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -185,6 +185,7 @@ nav: - Utility functions: reference/utils/utils.md - Persistent dictionary: reference/utils/persistent_dictionary.md - Timer: reference/utils/timer.md + - OpenAPI Documentation: reference/web/rest_api_docs.md # Examples are rendered automatically with create_examples.py script # please do not modify this part manually and leave it at the bottom of the file From 975fec144b60b1ab7939da73ab1d740a63ab1852 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 2 Aug 2023 11:00:15 +0200 Subject: [PATCH 101/154] Improve OpenAPI docs --- docs/images/rest-api-docs-authorize.png | Bin 33015 -> 0 bytes .../rest-api-docs-default-tag-class.png | Bin 212311 -> 0 bytes .../rest-api-docs-default-tag-module-name.png | Bin 209639 -> 0 bytes docs/images/rest-api-docs/1-preview.png | Bin 0 -> 157751 bytes .../rest-api-docs/2-preview-with-docs.png | Bin 0 -> 230724 bytes docs/images/rest-api-docs/3-authorization.png | Bin 0 -> 131377 bytes docs/images/rest-api-docs/4-module.png | Bin 0 -> 231477 bytes docs/images/rest-api-docs/5-class.png | Bin 0 -> 233796 bytes docs/reference/web/rest_api_docs.md | 54 ++++++++++-------- 9 files changed, 29 insertions(+), 25 deletions(-) delete mode 100644 docs/images/rest-api-docs-authorize.png delete mode 100644 docs/images/rest-api-docs-default-tag-class.png delete mode 100644 docs/images/rest-api-docs-default-tag-module-name.png create mode 100644 docs/images/rest-api-docs/1-preview.png create mode 100644 docs/images/rest-api-docs/2-preview-with-docs.png create mode 100644 docs/images/rest-api-docs/3-authorization.png create mode 100644 docs/images/rest-api-docs/4-module.png create mode 100644 docs/images/rest-api-docs/5-class.png diff --git a/docs/images/rest-api-docs-authorize.png b/docs/images/rest-api-docs-authorize.png deleted file mode 100644 index 7e70b6674e4021f5b0513097ec0e3d35b80deacd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33015 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%0Dvphe~V(JMT1nfwr;OP5fgZJFXX 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 ozG)2bV<2Oh!Mp$8+_LY%eRPR0f54)bS7ytkO diff --git a/docs/images/rest-api-docs-default-tag-class.png b/docs/images/rest-api-docs-default-tag-class.png deleted file mode 100644 index 1e070eec3c7a7b632d249d69db055e395652fc76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 212311 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 t&~Ff^kx=w4;<@~ z_$k{=Eu}}2@_g0PmPRHTiVujYx+=kHzq`q(ai|aH3~#buC)Pk4n2Z-2bC5~-xBdvM zr`}Ke<4M2N`0{Gc6j^=PkB^U9%y6r36se1<&Cg!7z}>R59P}7;O$)HjS58Ye_bMO? z_9)gjEp(e5)l3z(8-9=(C{{Y{xfqI6DStO``Yf2At71c6(9!W!nX?!srQvJB5iI_0 zrOP3tK&s4RpmMh1f$OsXTYTr>Da2HTtzPS`Sbm+$$sEBtoad9oybfD$U?!=#MHxj9 zPxn!Djo__JUWXcM{J<|m2_?AR+h-}3POEj2uE2WOaW%iF8CO@@O+Rs_#(`t1$*0Ji zjJPt%%FD8)7~*}@wOcX7^O7mW^p9k{I5)36T<_;6i@{RuUU0W$_aEOn3o#Rt zP=j|oiE;YtN#*M!Jq@9i+(k{UFjs^_7yZO_ zNR|}3%#e`uO|8|ZZK7ho!EqtKxEgDifU$>NcO7q@*rBSO-l!1EwebTAl3+v%``1U2 zh&N$+8u|UzrDfS4w2y46UKZCZ#hsqnw0+1P|2O)X(f7>871}Czq1ot4E;QhD-B$0e zQ!I3LztOT@%OQ}ZxQa_IEiR=*O^&rh8)hdi)Fl}VC%x%#G(;-UHxl)_7V!GQNofRX zkF)}MH1)j%C?{$nthV~DL(1UgPdXzrthMfLWOmN^xmU2`9qwQ`{L$Ln(4xJc{sZcwN$a!^AyJ`@ZVWEv=CJfrP}UfHaAYe zH>N&DLwAa~;f-yf$eP?1H!Fl~=>wCrz~s35TJipq#_*7)p~To9}}35?2h0`}{R zd9zK+=ABY}cr22rqpR6XJ;Im107-tryvg05a6N*6GU&zf`Q+QuqqmS zvXAsB^N{mi(Px!togzigesN2(rw8@&TUWo08&{Wzb<=dBp%cK8I$P;htKr86Xmly` zqVpTikr7T|L)a#czd)>H@X)(&70-zn4o`+9p>SI9`OVnoZ^q3#KR&?&;ov?(}zA2C@P5L?s)FfF4T5ZbP=`E-5 zufF4vD30&S^6oE8fO&Ql%YQ4773TOOVD5~2B%op_U6e!aG99QQ00^d);xuLDx_wr)4)AGx0{x(io5v3M&}wL4l1IVuvyKRbs?|vK(@%SU z6HKnNEZo3FJTxQ^(slKsl!)NoAKZ z!iZLQ{#Y=jU^=QSv^FU=)>2Glx8b5FqD+~#$Jxd9ntOVlZAr9XP)yDUypik_^#2QW z4@y)pm?5a-05`bDo<= z7rhf6PIT_YD_*_Nqm6fM6W>pE^YyiR4}B?PjDZ9Bg9kFc@hl&nzy9=z@Hr*Pb5gwZ z=XaXJuI&$|G&OFAF*OqPSjMA=yjGr@XYn1RSuLSlc2aH%!$vS8`cU5XSD(@GTbwDz64^95HOr)Vl8t@C1ENNKjk4b8@vnBXP;6f3b#u>1fe)$t0pbZ- zvnb-Q{mL7-|IDUQz~hJ%q)M|dbOp1I)Q|p2(B>OOP(&@ZBhY6mw>Dt+VqPDb1s#g7 zG3i(Ts*yjK5Tq<(Sm@4HKc(3iSc~y%to?bpsulS)JYFT{JQ**|s;F*V?M2w3x*@K9 zSuX6HKW`u@GA(diZg|tkU~v00;`BD?E`#x)BL!k_h2s zgtcUUkG*;|soKe5HYI));T>Ui=`v~Z>$8V*#&1Le9}jkPDL!`o^x!(@_Am=S*$spB z)(A_r33S_LnyAg9=K5&ut64wzT)}P33YAG8jT2`Qnx%Yf0n{crdLvforft>bAZJMU zdG}ep(`2(A8J!g8z14GWzP?IZU1W~v{IG!XF#D6aXibj2?Iy(KM*s48MjtFOGAmHh zV&865xnsW7^&^qAn7jR&p{I6{szL4M!liqo)MW%khy5+@PxEV*Q31X*5I?(Bv3WKP z%kCqGnTN;(SRQK9b|qVg)KT!=DJ;|ts7Mb5EmW*^)g0>>*v?>i*~7{d+@+`PP#@Ky z9!5*};+$oV5$SMsLsicKse_>DfYrv7G_5Ig8(J8$+#W4qoxC%?x+US`>*+1IM$(^! z3?uD7M63O^PzbV#N??L1B7RsejN3v1I4K!|UiaIqa52D6(0*5{DYh2a#7F99P+5N2 zR?skp!rVkln)mm;f#Xz$a+cr}cWf$*tFa$+4}W%l!MpKRMa_l0XVtQe+@1=$CHi9# zCe*l@c-7PT$kTD=hFbf1+d`FBsfrs(mP4~BiHu&vUn(r%SD7S`cU!UXP|3A9f%uHJ zWdA{ko5BikWS=A(qn;Vaq;T_h?i7aiN{e8@o$SjgX__Y(QR@{w|9J4QuX?>~N+voi zm=(uJ)w^DAQ9t=Qw`O^;W~refwu)n;@0v#B73@_PF+>m0xq8+p~Esd5DBFq6) zg|KZGrC(Akz#N9y15kO8z}+z%d>E|33u3ho=!@`g;W!%_rUR+KqlQv0CNqu-Ll^Bv zw_g)A0R1ToI7Zyo`2PCAqeqImy6-|mL**ZnpL=c&xjllDcfSTx^k_`vB91iGH^?yn zRX*T21IyJ*rwzgGEj;r3YkLP#qrZ}${K;_*;k+Vposn-F@!+QO4sZDD*X20Q&d$KA zFv;5O30@_Z?C6KC7su7Rvp^WUw6w$wES6T$*V&Sn$t>X0oWrXhem!8p!RI9YXZhXV zHTKlc8~CpRI!|_XHW))`ho9sjm#~crUPs20?>ga-1{(n~;`yg&40qP7TYdM1+~-Ut zbwS9i`M*Gl|1mML#G&C*wKfi7B3on4d^qWkDGyHF!LL>$k#)ag*#rlhkUV%9p1|#_YHQ@CNG$hq zve!iJu*?$}x0mHd4>H6sVBek!m#erKo`p}i^Iw>?cM;cx zwe?`l+HZ-MxZes90K5es8S?H9+)}NUs6WlxowzgI!+vKlRYxdt-xxhA_z$yodL)RF zYxDIM=7b{ng#JD^ei?(Xfk-oWA$biFG7H#_>8SsK4Z2J)So;^d{|7ec-DvQd)&EZn z;PJ4_KKOrN0RMmaZ7#3cQT>w(@N3fgKc?~jjqHDK*Z=?4>3`o(;eYiy;of^XI@GF^ z78Q^#OG-kL2;-o#>ieda6&@R*wNXFkx83jJYO&5ynJYbe?O!ZnTv@Oi-Ca$2a)+E8 z#0ebUflF8a#m7g$-n+U7Heo|-I%1a>7xEuF$lv}ZLjZy&KOxrEXdwu@*9)`$B>Wc_ z_s3Gh4V<fR9;lJ{Za}5RID(W4JSa`4#e#`NOIPlsPJ~2aho~*Uq6AfGp zO&9ag-(Mz5{_>KfM^MLv8E80z6Iyo$HN}qxYNdNGa!AJy7+?})Uq#FN`#)bEqT|Az zpGR^PyP*>aylZdo~*UM%BbfBZOhkSIbCJ;;xs^^lo}SR-k3{rTq)vTN(;C?bX(b z2ihf=`xwlcNlz9})~pL^U?j(si|yH|PKBamt=&+DsA?%^K!*=<)P*Nthw)_lRU`oW z(Boq4P6>vAQys2rTPw>c8;PK$*%zCmgEbSOzKCe4c$2_6&hu16h9nIKKFMmb5>Jc# zcGJ@Jg8k)>>P@<_m!cCXe$5Q0H^T)EEQzn^0w*(@d=G68c0BRxH0Jdyzbu_ZZcHRlrJ||gO3{l3 z>vKT~T?hNA&h9_j99eEPcWg}pmxqvm#_nJSGnLo3g62KST1$(Y_etTByy=&_yUy$5xrq{bd)Wt3 zqM%@Xg{PUtZagq!mE70Mi8YZ!GH%|~RpQr~r(tj~;~9EAKWkG97$nFM`r~A#1Bul< zmPNew^$8(fg3LZdgq>Y|FhiVGe=oI35?)vHBl)AliCLq79SpWr9<%VYhlZA!*J@DF z-Z1?@Pz|R%Ge5DM+I0hMWKex_V&J3xqn{{hL0kFtkzAq>{^ZmmhF}>!aF)3ZWJ@AyPbWVS zc@`|9cADEcX$&>*+}WQri^7WfsJLQ<;riPWa>*XX6+b=xw0svb-M3#u9NOw6uL7@o z?F!pb=3K!~FpIpy+mSS5?zfAS=!4GI^&6YqQ;HN*Rz4gkl@o;sp3PYg-sJO7zjcg^ zIXI5mO6_qQ(sT*Tl7M(NJ#HNw_2g{0cKCMcjrqiOv!hvHKqrSQERnf6@M<7mh+X3# zdN!(cb%SF-H`hVOP+ql9m!VFm`RrQ+KeNL zw={5*<1qa6z6t6a0jeNr^Gk_D{IlC1^QeoHxiosYGfI@4TWc513XGw5DBFyO?q2*Q zk>1%9x2N5t1RUZM+kn2DoMHFno~sbhhhZb$m3yEW6A=>=Q}>eAMxz#NFiX-{F|ldZ z*lPX@GoMGN|C%7`Xp=rsUAIBRNEm(o8H50?QA=+3%+qdJWX}TTT#F_jv{r-62b&LxBT+*BKOYRQWEiE{ zLC*FHp#T^Ysh!AIzQG_o?;Lqx)q2+OP#?Op;`ug8r>mqSF#fWm>CwZEH@y=4R8L~B ztVOQm6nq#jwE2xP$Gk+w_IueVP6%&r|qDviDan*Yskp8G29iN6CoIWmd@tbO1<5?TBOO04l&D+=GcvU1d_jT)-O1y<$O{Z-6P(=kockj zES)}0+mgkJ9WVRmYd>2?f2S2kzSbTWOBKf1wc>y$?3UlHm1+`N@$fO*<69dVp@B?% zg3W3^r1Q+o0?jjUDhN7C2Y~S-%qgcB<=T9(;UncC0WLS4C98CogPij_W zgJens*3G&vL5&9mUj6!XD`QENBYfsDn@lcJWf_bB$`hc9xI1(Kw5uT+a~RV;+ML@t zo2pXNNgCWr6K@4x@^V?l9D94`Tz%;va@{IcQgDJ-7G{QRe$`woL8J(5IHxZ&iLVnxNQf!`E$Q`gijPF`CB{bc!33?`n z;D1`}-?B}!hNNo1bBD4=D@9YqbK#(?^l%$KIwc2hPZ#8ld2bM9{>I~Wx1y~rVc2|~Rv zx-$)}zx@%%MP6RMkR44B$?HcFwBp~aQ|qa|(j#X+Y_QYwwZ|=8TJ84s2Bw{B<}d*s z2v6PMW#hszLe<-jw0LOzrvP^Mp8?FLpM%1(J5v&s4wu$gQeX>$XAJI`P>XkLYiwGd zd^qS8f0L)6shM+N)&5AOJaMFS0E&COq-AHZdlzYuAFs2EIqS2unai%75hOtFu!Ej( z*mzcHhcsS8P^Fanf8N~tkT}{i)1#5kEas%i?Wce9@~?OIKhsbq?8}>ieR)IHHlT6n zAUbD^GBS^La_3=>-IswZAvDX2uqeto_&Bs4FrSL|nqKa7FGXvY_X(STXkFe_`438rcHW{E(-J;jCyKQwUk#jM*0B;T zqwVH3Ptj*z;3;nN33GlJ*T$%A#^MRrYRi&_-X!T7?DDcM3H7WdwG3K5%9ukUnj1C~ zN4hsJq)VGrgN{OxoO(y!ebkb`mgmPMty7zLOVV@J$M7>~)+3viSHlzJ2xndb$XtNb zs(*929xI3?l-PbPG$>!&9gS~Lgz(vyn!}Tkfp1&)f zfCbaNf-MpNIpA&Fb;@rtPhLEnxNiSta(DM`c(^Fyk{fhnVi-hRsEI#EGb-A(C2!5v zyVx`*EVC5QsFFETxlaz{`m)>QfUO4?Gxv6DZtkJ35%IK3CP9|fP^TErcNIwSJ=f=Y z5n|AzNyZh6r*LjZ9zW3Lb>SZ|?0hCo_~cMlR(39_XMDm42%Z9A8$9N1F%`yY!{0*Y zma~bGV$l;8b>g11f6%Dh-6=TSo(CRj6j#gsidy`KC^Loxgf_R&Oni8Fd>RXr!2F=n zL2U{(5rl$>mzJ42mO1_(_TDnC$@c#nAEQx3MMOXe6;KdR8l+L_kZ$Cn86^!PRluY} zT3QJ2mkxY{osDI?X~SZkMro`^LdAZ<>!TQm*WEk zw8IcZpyo;vH}!OhuG|1*bU-8D#=Rkjrix0tMlPqv=%?5W&~&_f*$%VlaO1`!HRXFm zO_)SpUdL|4PTV65Afx!~zOUfZM$|Pw-Okxx8_IlsmVachm(Wr=Wr0+LV6 zxGQZJnoUd0YqRtxV>Q?l6!Cw=Rvhlo=NV-_&L`NsU2e4FDQO=AP6gMSoyOTt8O3gb zU4HdQE7%>lEM?Ow)fzeiMn(QjR_^A7hI{^dJyd0zJ)V|bagq);@Fmu-sDaQfC7h^$ z#o=qUhx=%EekbT0IB0flBvp@F=DCN@Y38bRvC^8}q+u#x2Af5p*dB$h+x3D@&?n+1 zoY815y+1g;Peq*7Gu{n3pd2IEC}AC6X=!Pv)y69U7IIaZa&tiT?up9R^C(8sId9YpGH~)9Tg81O7MG5MZZ)2=_w!v_|JQOn)07i(Wu-u zcX_;(F^*AwYX1AWJHPo3fZ%=~&i@~0*9iPj&{yrI{B5l6KVQs(7##LnLjC{v_kVle zpWf*M)rw@)mnpEl`p>`r{@wp8=>Mxx=s3sbSKV356z?-seh05TBEP(A%g)(FBe zcc?*5gx7!@m{pB+Gy$=rk)8vu&Rpnbgs*|5NQyz=ZBCr;b6p~^#1j}7{ za7xnkh)QVKKg8nkiKUavw^=D(C%&OYyyAuxwSO~ zPa?;neFr#+xPfHBfy}NjErBGBGZCIhPECD-u$hC|xQkSQKepLl)ZFcNMl01NHEnlT}Jzp9Y{$LK55(Tv+hlfEQX!w7*mv% zsNt)|XGZ?EcWvqhaWk=YzNe78$;&(FKxY%M#)FfA1ii&4!Mfj-pWlQL$o-2_?qF;N zebStIPc-!3W8jzh+M*Fq*?GjB$G}eTY=t?~TwybxC%CmKNZw#IlHe?JH-dJF5KInA zF(n>vlHcw;PxXtmy=9DinsR;R26IOorcbk zAUIFtW3(q-s~_sTTOZ(jm~Yerc;%=r_umBP@D{#&voW04=fd$}RAJ6t@}M)9HU%N; zr~21po9QY>73W&Q!IMY)mRZh#?;8XuhSwt~!6n86d$}&O+YvZ{jaIlg*F4mm^8&=$ zD4g%_3-I4|vIqyyfvIuTB`VVbkEZ0ELdy=pyyNrymDu{vh70P(XPmFff&5`J$gX3t zX9pyScmcCKnV{lqvJ80PSN+XD?eR03ppWC*KsE66ew{r%|6aq%L8`pl_;0&~6tgRM zPQJFt0_M35d{s%v?otJv#ixlOT!etiZVmaZoDiPBUH&eW;l`XMell=zN6!)b~KzM!fLjG&PvxS^D4_`leMMSrM!}@^-Bh8_eQ-=NVecS6C@ickf z&zpSwu|DDLa+4P=`&(}}uls!K@1wTFMi!<_fr0_mR4z&1)6DKfJ{5{f?P-5llLwZ2 zoXb^7xqZ+2k1T+d)Q4x@Y4RzcolpRPrL1GZeao#B7YxdDbx;=YHk4C8?$*pwewjUr zGn`@Y7aDN;H9{X`kDt31$>%U+z_=1JCf7ej0*1zcA;c)BRK5-V{HD`b0L4@C>t-wp zv#0K2kB|J~cK6v8+Z5Lfx3k*!P+@xdht{QM{qGFlKu7fbuxNYQ*XG@zPETqi4`~35 zd)uM>OfA3svI_h0J0tbrx>rGnoL<15?QjPby~M|^pdNv~dm{6eZ)YlD2;IIl-Svyh4i38wIx_*3B zvY4LWvH1MulL?ii5Gf*8Mapz#+=tf{b4f@}O*lo=BQ{@~v&%eO@`u>&8+TKMSDcFS z9Z{@eDeF5(T#=Lh;moE8x6ofjV?faCE)^m4f1)AMpmWaD+hM+9@)b~Fmd6Y4Ho`g* zi*iv5;}1H_x5qgtLOZm-Ubk2~vAM4VqB|v)q!t?k!su1v;D-v%sWuA2-iX8U7VS4m zOV`cHPW2kx0`{5EeX`q^qvzD)zlfYk4LU;}Xi9fq8i2ZCvco`{PXwOZviXHvb0M57 zpglX@goDdKg2xX|RZ&t8)K+0g#{@oj>haM|NtE+?a!g}gA-}y5fGwSfR!63Sbitb$ zJ$vX^9@JcmtVXF6L2d1n${^y7h;f77fLnp@@fJtIJ-@1=#B2ODX;VIvTuV)lJW}Sm zAYP{@&Djsj1uv%X7^D^+zuZ?+i=V=Yv!Ydo0gq%k;T)Z7a;6# zDPBHEZ?QEG`;1T{fwQk~!;28BwNOXi<)3|iT|eIoQ~i0$2PyQoS4Gt&yaE!s16=cr z9+zp=k<`JFsuuM|zoNRveB18^g&q{41si}XkvPkHBzP>$S4vw}2Y2P|dhE9no$kBlAygGU$ z9`OV^r#|j^NBXGv9A?QpasYCGXeQ16x>JNo59O3cbFZcNg}r$b50o|ZCZ3(kHSc@la>YTeO%xty@PDgH@CiBU)v!t9li6vC1 zSwd2W1O575S777U##)5jg(eA}+;K(Ui4ceHE1n!5W`7$R$x<9)U#kQvf`JV==?6@P zYx_Xw59q_!zvt-XT*yrm>?lkq>5}}WoR-I_7!xsI9+DzdEC3trSU~0|W-OVXJR@FR ziOyAy7%w-WEh-CZk8UH{PE*Pvw}6clFEv!>Hf56t!$*w{PwJT#9&7s5?WS1rTCcm^ zSDUyBls>=i+!PgEss*^|NXjKZB$&Gg8AV&fE$tid<@EQT&(kP+?TcBmc2trII60&( z^BS16Vmv3m^@b9J<`M#7MX--)v;t{Jtu zvD_yS&#DwB!WlJLy>cDZHOtN*Xdfdfc*+tVThmR1OtG9Cb>N+SJ3rhJz1@F?rTkiQkVay4yD)=hE(5%HlNBpz*zBd+?)zA6BA&bGwyFM=|Em+rr|7 zk^4yOV1cKQLQ}Vkfokee?BJA; zSnpO%c6P*Z8KQnhW@a$*Jx0_^ST0TWh}@WG)vDx*%hec)e%GcDPQLN_EUm zK9i)=u|mGK&sd?qj>e2>?IVgyci#W-2J%NwUCu*AOu)XPO^t<6YR;D+fFdxBBZ*l6 zjF+dOC8Dg8s_!WSRp7N65tn$iTfzjrR5GTigo{`|Sf9MVWxDRcz^~c*?-F=V7 zBD_A3tGd;G2a2krL?0B8{j8R9VOPvgXL1~rsFSs0T-n@CzhfyivYc6J^Sfi0e6Xuy zO`80AboNmKp2|G>m%q?;s~=N&!gg~-UkI+ZgFMr+g9cyiUuhw-Y8 z!ygj(c}FVix=TVPlLBV13r%_Xy`EPrf*xd2NyK4NCOdKa)8?()ErcN*7Svx%e3n>$ z4*mM@@W5VB(tNP`TBEHeb!NX9t|NXmo2?z&@@6(hncnVc%!LRSp#{7l$#Jjft8GRnyo4g# zI3zggJ=f!c2tySs$QwY8KHy%T$H&9|M|3+)lCGkUzP(F&(mLIQJ24EKa#yB@l<1wL z8}k~s?#&80MM^K$E|27f79D#Y@Ow9<5A(N_3aaG{<@Q8rE=`P=IrDCvHUZAsT zGPeLkrHqXv(MtNxj{~i%8#xt)!;d7%1_oBAi<-~u5?+!#scAWO^ig=$Ln^(yA4Afb z`G`tQU``duBYEyui!ekRbcr&kkut#j3K2pgRoO9AN)Ugzp%$xt$jnK64D14^IRzY* zCx$!^67|MC_-*wUF`i#KzaGjiL>()9-$ZCXEyF&rNhH|Z-TSn?C$Vpt;%WdXZ0Xri zF^QPmsOc&4(V?8-r%9q;r{OesV3qXxu><|6`+AI)a#;qV^D*_Ia~VVF@vCFK#c4j$?K(`Ecf(uYCF!GhyjiSwlA z!66%0_Om?Z!atrh1FA@tNW(C6uF;Bou|*bpzt3T^E_1jTo7`9o79TfRO18H5bN=fM zbc@k(#P&6LEXas-!qx9#5Ixf&k4`OSnAgP2Thn+H<`P86c1$MKX=BYB`JasIRKs>I zLEyj{vLt2^M39q5cM`=Qs$CW+xwLkm&=G-Td*|w5{{5K{s*9&dQ2?SkGb>r`5N{%W z)cMB__Bx*4R8gUnT5@5WU<2ycf@4R+T`zS zG5QwCT9Oxdx)7~BSQ5ZfF1b%mchA1!j+c3uUwEz+>SKPYW$|~tZzj6;KWdf-t-+Q! zl>ldm^9^johplIpyx~_t$w0|7Ucj<~{di>SA_TirI3z^Gi>CnW+^M|?^}jKv2IyB` z|HzugMUF1wddSNxTs734F<;DTmwr51I`q=mvr!~)uFgJfPrb3Firj1nzR9mPSb3Ez zml#36Y1e-r6FX3)I9l10AZ|J%*pjPb8%B43u*q$={hqCQa~`h#2E@P4hszL`qy3pm z%(>amp@7^@6z?yv|Y`m$j1E-pCyj^em^L!R_b4`cI4`$-t`93soa!Ti> z<84^NJy;p8$)^%+@uj^5tv$EA^L_&6W8zeF6Z*BN)lP% zMsRyJfx?zjV?!u*;9Zg+f7i*Qj<9R>-5PC99cm0h39NQI9n`Um)m?2l!wu7fV*)RC zhO1-NGtoA){0*Zy>BzaD*1~9=0#WGP?IE^_*FC<(+aiSg;u1v=J+8ET1I=$?3=VNW znmWC)Ic#K3qlKR+0|D@w9o2pD3;nnI6Uq8J7U#}}P?!(qa7y1WjyubM}K zSOz;Y&lIJcw&Zt_UEH-=-x{KJXSROrn1dJl^Ac>v>PPO>ia&Y6WGy6tTj0~Ti(6I& zB+UKwM&5uKneisS&@XM@l>Si9(3ilLf@D>Wv7&_c5JYblUd(jKtL={U2{72U+*N8# zR+73ubL!K?u1UGGlE`7YHvciwyqkBn$Rc*By4cEjiU=^jC#?NT+$)V0dX|x<{?Uxn z*hG*@hH|gHIAjjyX7#Jrr!WKxJ8AxkjNZHHF*&c&eogU4m=lQwBbLBCIR}9JR!2*> zptLuoAimPR$!`M#C=Ni@Ci(mg9`OV@iigBX4dbo*MW)m!PT8qp{Cd= zcjOv|-}rMa#+7n)raX*d?ru3%@yh#0iL4(ocTny+kQEUgk2SB|c3Cy)0&a5SorF64DH(slu2Ngh!>yWg$Zgcj>(sB7U|iSg zcotBfGFR^zh?r(8vet{$WY+c;=@jIk@Jq6IL6M0Kd!G>O$CRmI{P~UklZVyIKeMcV z9HRxq0mz;sP~cMIPVfCyQbGXLt5$M_&Bis<%Yy)9AA_m}@uo+$cxALM&^YNSW~pS? zY*g4U_FKI;*cI34RN&WqFZPQ8vG3rW;NmX*mDKOWT(z+wUk$D`Jo#>KXqKii^r=oF z^ETrbs$aue?JUr|U<4g`fO|XWG!{RW*r2o^GUFQ*m>d=;iSIOpezz0QFWmwPOCJQ2 ziq!I-J*UD!Qq_~h`k|WX0^Lz99GV;ro%5XW*9F2voUO{*D_qr6ZZnzX-`m~|mTWL% zcaUu1(NU}=5f9JMcKMb!XII5wApW-9WF6EOxPdW%IABe>!6&Wlyr$)0V;681gzwJycD-Y3 z_vvlGWKVe`uURqmHwgN!{c$wjwadzCN;%eiv<#y&!+dtXqrY++f*Gz}i2lg36L0E& zBh!T5@!QsH0h4d3hQyI`cDJ`*9py+})7VafdjHdkT!`2D${EWyLFmMuGYp%M9pS_q+a&3`pLteDX(jBcB?i*8ZdYD`5!93(pY)lv#)yyJ z)hkeNr?c~G7IfHs#&0_+&&b;)1|$B+O?}lqE@m{lxssI%DW(m9^X{_Q6ls??6`dVf zR&@Z5C*k9S)$fcI^$Mo1;fC|gLHt)KBmUN7nM8iv#&c*fO94B((^0JNiTlz98TIjs z#^mx*XBV|aPhzD<@t*8CTk(=5^1wAlL|=836<1=SUlfx7&2H*G#Bt()*ifWoC*N=A ziOK#&HBLws9Fjyuq4m+Z+5VnV8P!jrF%hcUhhDteJVhq{o=b3-H{)pr1q*5*5+HfS z6=PqhoU)Zz6osTYH&{k5YLVrqV_4;A1}GXZ`vcodzf||borS)SC){G*%UNQF7K0m7 ze*y1^s4#nz72-;CmdtKHeW>6afTG`FS$bwd^$Icu!yB8(fdDJ|=ThblS=Jq}ESF;L zvT*BUP=_mwFl1&;SzgfK2gX^1?492=$;)u+g@uzI234u;JksfAw(A59Yfl=^p8jZl z{iM-Dl|0aV{zq1AUIY+j$O9%9ns%a22GR#eQ!H!1iLVPPHrukC{HOw|k#qwx`k`Di zv^az2YkJNg-_4t2A?)a9jC-h z4Ru1PY15%f+`+sWZ~KeBa^+I}kLm>aP4>alo(FR+&#e^Dz8Y;>L@Q<8Xk}9kxJpSi z2=tX9h^Fg361JV^KWO_KsQ98&s^5gn z=G3z6S_w>QBIUG4M{}*z$(0mXaqTSpc2Tz~-cyTsScBIW3g5;mg2 z54xNddt>-0Ucfb#{dHptj`h(5jtSY&b4o4G4pHBd94lf24MgN*0ilQGZomu!hVW8Y zW3Fr4$1B8t$HBa7Ttl(|(2@-EU66?&G*6|o3?x4QPO%KRcyb-#L>$*d zBJNSE#bAu?+Ql}0kQkejA*whs*{4R1K&$L$IG&T76VR^YLIqJMXwTul|0R3I%nA}4 zsb`4(gZU?Uj|WAtP5q0lNydC$9$H7Vy}d8Vk41e`0LG75E+|C}+>%|;gTFDFW+ntF z7CNc3$*Ms9|Cuw9SZWx zccfIlM}eH+(?#yTPlQH@fO{s)w`-r@^aOVbNMkt)l_J3>eFEcxH1RLL)hfn2@s2<0 zdv{?o4?MP7Z7m(N38be$_UeB_hWv);=|nhplE&KEF?Mz;Q1hm!k;Uc>Y58CBivRg2 z@(3T(Ql`1~aPAo>D$mRC=nI=_Ap15)6L7OLf9*tsBw%ACQ}?x2Z6e^3qFmS1(z{#~H} zIRH{|ZDRdrh|2H^Bn82>63}txh*XF$LtPu!uY0Bc^rA9p@MDJlT2}C5&}fuDr!E5G zCP)ZBefkt1BwVViig;V}#pSF1TJPTPt`Y#87`&8&Z(O9KyKM&IH)y(80qd=8m+szWb{Cf7_+-#VmU;r}wtK zri9uO(bxtoBtDZMT3T8FnkS>@;e~b+(7#sq(CcItuL5sC!otJj$Hw#$_6@U)q9kMd zVC4^z-ux{x9Mt^@&*oOz^-#61O1PC?c`vV;7a<|wIDA?$AWOsxP8-QAf~qozX22=+ zFeWiL&6GH*_jTz*U8jnni1Ph@G9BRayWBG~=+JU1sErBZS7m1SyuO-z`bYI@RGL0i z)HS)50(t^2zp7R)ZF;`_CIMwY(KnRu6p7cYpg+0v!{ zC8l8!W2bU5f7w3&r%Ui&|M0zdeW$>b{wU&0s{Wrx=WupxYDh4xFX_bL#8A*ZTLn z|2vAwS4w=5nwpRyaNu{K9WuQjU>k4~nDoTsD`A`5$}5O#j{bOg_S!5p87aoKB~SEu$hqbTu^REFYFFrMFD1bilh5x{4H;V!1hh{%<}L!bB3&+%5-N4a1F?w=Y6N?-vB-K^EzxnfLMdh9(iq2V^h7iC}s5 z{rf9)2igQn1`_fadB>=w-;F+~27bOiaJra1EB=r9T8H3126|5ZJjpvLZanJXYjjsX zRQE5?prA9K+kdyf5M_1Az2eRJeBssGw{C_c^z;C^W{j^@m;@aqR0jd}a@&3M5Klwh z_mKD2gukmtXTYI1^_eTB40NZnX_G(@^nTvF(C&`EkfS2qdFaxaK*@=?Tc&H5Md;on z3*n6>4x^+swm6)^7O(vMrbh}90A^a8HTO?)sQzuxA!F+RCeHriW)<|G`U`MDcizxh z%)bFaBEIxXe-TLfM=vE{1#^)4P|p)W;Km^w$exytHo@;Ez>Y-YFsY?YiZh5*5}<3O zCH|s0{Lg;*8x4g9px`Nqsd#(lZP5cr@>B8NzhWK!@o1)aERR7lmL)_BlBPzeAc#M~AVl0^uCn>RfLN)`VH_@j!eE{b3Th-qeqt*u3v5iS75=?)h0+@xQo zgMWU^0;TRA3X*z)C*OY)Ch_Rd@Yd_&QVk5oE^F$yIrz##rj$Et{?W<%$A`KL1H6Na*f zIkfX7Zih=?N{NVxEmy8Y&-zXbCv4A@(EvYplm+m6aOAnaf6gUt)JAi*hK?fhNlA}td;dsteb+v*TB$;mCH{dX|4720za@0*XUTYq|W~E9Mi0)2gC#7PH zDxSXY-L<|Y+y=L4VQ|&JrQ9_?ve(CrqZe^BJbc!wk-mqS;wC~jNPTf5)r&{27T>x% z=tQQi(G^a}hpFBZy8bdYHh`pSu1!X~_v`--t4g?( zXl1=~Y1^9`0vp5jPAX+9R(5I>>RnI}_Ea^Y<1-m8)Q54tp=}nBydUZ{(+H>#xcp4+ zlr4U>8O$V-pfuAoDd1EVMEZvO;VcB3cqG+&au)jbP2n+L=k%A9kUd$FrhNWW+&-5e zqHeFM+mLZe6VhOgRb3h=s>b!pyES#6@voG@9&F7I9)3O7E7#6MI0vvXiX-{4)A^(2 z*C7%hYB651WgR}UHPbMwvAjdO(iC-3Hzp#ARmscsl^av^p!kqq6j)F`RS)E^mRFO?#B3lPGp^&21OxxceV(u>+`7)Poo3$UdEt$Y^#|g~!x)?{iQK z*!ZK@JW)g8x*d|IS4+Dn;`!hhLB~Nv52oj#Qx~>NvNYZJp{94dGq?0izy@J8>jxqG zv0J#Kvo0$pif~9hNdh71e)PjLGcl6YPVsm7-1{OOaz{`Nrrb2~&UEp64q* zEQP7Zp(T(@*3SAt9bP*vi}snB3NABiRdZQhxDB8g>y3u=0>w^i4JqtS#@7g(htLci zYLX5yv&yI3JWp%!NC8Dt{Z5l_NpL&X5KO-(|KRdh|EUBfv%$K)viRkpS@#k8D7e$~z zjGtexSOTv@Ms>W~eeO#C3y{;ctdZ07^o0HI>8oVs<@2dC5)on6>H%`<1gk~#fAVjX z`au3?gc|SCtZjosz2{mCNoAVgX`GI+59ZqYAGSn@89SG&P!U70lv(#NHOetR#3Nib zYP7O?j1`mwc_!U7W=>RY@{4IaQ@)#lQ&xT%|KdQ8{Ehs?nPCA411GjbT~!yPoAwm19g>_*Lw z2c7W8a2&SD4~q(3bZ{VkLQZ`v0c=IGG#sCOx?KhY?2UCAPSaz! z;IR#Ve6HIS1R?qTcOr0|Vh+s-5`R!bk^3_NlO~Q+oYbfxHHmUR9{pts5gXs|Yxf=F z%Tw=e(X9OZm^?Dy`dNmx_r>C}=k^zcYKY#xWvYZjoS$IjXU(Ksh#vOx1v-{^BbQG= z8eW3>M5inW$34_moC0r8cz@-#6^B-)ie$wzO~V`1s>uAd*ObjI~1vcSsl;5U~d8{wyA#VAG4pQz~(dr%VZsGC4g-)$%s-r9jM1d@#%Q z#;cd|24+%d&ob|3oWqP-wqkq~9-+#wobVAblNYt9in&*`~gcr(WfWaB4E)vF_eRB2D1$Dr~XOcAk@m zp1XEWiBc_UHUK+)=g>$hwP3HXLDVrLtAc2^jZ?Cc>0&>OmeWM5Gw${caUWK3ApmHp zfIE>UoDPW>B~^RPa8srjG`qd>kTb+9$O&TM?1^ZuX74^&l9=VQ!^X|$#!v%Esf<1u zD z(N9dL;*VVblS>>S+E&c+o+++dR$LmXPqHC)4kqpD%1QIDVydV)`0*nryl5eWp`;o) zBIP;2;M8Hg_?#Q0m8#H{cbP8TvP@NR@R`PkU7giS@gPB8uLUd35x)Xg@}B@q2~55! zC)L9kB{=#d_TL@`J`%4FKOp6l;N6&)jY96KVE=*G!``ZtU^j&t%yRNsbqh8#dB`{U z9xiOX4p&s!!AeVZ&%bZgDN3BQR+41a_|kx^FsT1{*cjE2?V+Z2t{6Emn?|`T5Gzum zR=u-3q?VNBv=KBo;46i{fIMKO3=8yO`@cU&EyFs;_Um#_*aMszaHAKiA!GOC2ubz? z;BBTZGc^YUe+mnOFl<{GV{E>f*iE>{Mih#vC@#tIHhN?;VCEoNt6;ZO-#tI8q1ol# zVRhrP+o^JpRT_3umWX+VL95yruD3%UCq=24rAkvckc( zKwjwBhC>6(rky4FtR0~G#y1r?y{^%O9EGC|V&S+wWarO&t!rB|M2Ijr+`wS$0%X$r zs)$~3{knlIGAEN)cT91Z}jJ`_^)PKCHg=OOH2a>yl1m6{^lY_(^a_#@d1 zl-(p$Ya64Kjog-9%RBf$QA9$YM74<)3LF5_LVR@gg& zP77e+NoWif;5Ru~G=hiSxQVnZBc)pB!DIO;C;2xEb{FP*JDnPvbG;S22KNNyAig_X zLgQ$=O7b>-c_gNH@L?3Ynnq=9E*!u-@<&qn`&Oc@^mop=e5Hx+%DO$D-9#SI`<~g5 zv-uiV0rUywB$)45-B(8A==-$F)8R>R*X(OPvdrrPsndZQrg2>=v;6WysLmuIm?dW+ zr?$V0M*`ZWACaEpBX;x*ItNxrC7)eopUV}L45FR>V;?fd(OM;qPfo6D4m7psaIft2 zHySdP8~Hr8olSp7*&0H{v^!|pcOPD>c4IFM6q90uC)Pci)K*(G;wJ0+l6_6S+ZP1CIE@6Nt25n!o4 zImhAu_?~{nCfDJ@yjqc&$xiAJ!Yz0_)92tPi%aVsa@=)rf>00rq@sZ7dfcKOf4iK_q^tu&2`4LzUo#Y74!Ov2}((hcq(i-`x5=$!rqtoVKE&Dg4S*g zq}s%6QJ9EtKT#L`kzHw_blr(()0?iS>EfB&(?ij++lPZs8bioWnFKhMx)a1_kGZiE z{!&?n;oRE=hltPT`Fexjm{j9-a!xzaq}wj`J9Lv$u&KVk4)3WV!*zFFBBof_#~`o# zX#)U()*3K3vXoYTFUhz7K`+aNw&25#kVP{oW?G5^ZHN(@j@{IIt*1i1Duwp<6D#hx zV(VXx`CB>m08$HYu$~hwXyVq<64LMVSXBGl|;c(G&qF%lXefbB~>4r zwceE5j08%SIzx7|tG*|abH2ddPx)ZD*WnI*``*u)Hl4B2JY6OF_pkMkIRt2)=Jzhn z@s}O)(fr454j|JAK-VIDO5ui8ZnZ_*!+{6iPIZr$`YL4(=F(+zmUkTCChv0X#`7!B zvAry?$zNIJvzEDBR>SP zF~}XzQWEBD(#Q?-6FPfx9Ou*^;l5fa0n$~jV^ZHW_Je5nKEX%|8Pb9N|?+I68 zWu*5RD+QMF;d;Tgiwl6XWq_KR(#oyt9WOSn&vsZ*-9Bna5Nt0+>&M{5m($pve$Z_CdL~v$?NkH3Z z$>f)%iHgT(Y@a;yr{uln+Mi|ST7Ji0)4TmnNs08rj5u43`{8+cJAzV)W*n9>3Rn(y zaxJz}->&qGzZ0(_d1@a&u2uww#Ach-($QBdZ=dONh))4~Shfh0lNl_p`w^@c;&uEY z9@SZ(I0;)ORdQnp1hBNMvCx=gF_D|i{e^TTT^DvC1qsQm{xI53g4^_G0eR*lagLoxykVK`Ls|KaNzQo zodBY}SqBT3?`R>8332vV105p7*Y25$auunM4#O|w9rlt)I1LgOZR*k-_G#gh5S@ZK zg9b27`neZ*cr8`WCe2*Tn95p8ZlW-t>Vw`Fi zFXT}X1AS7oiqs}d6m+ne()ap^~d^f=?fR& z(<7D4&?;^92l*^4v#!mDy~3}eEiP)XC7jmN#w%JaChx%ek~@0+QqgO42C@a$wP+Gv zJ+dX7i&hh9sXM4k2@Zv_2J3Fc_Pwe?=C~W0p1Nx5@l{%OJ^w5la+Z-1`qI4!qVq5> zzv@i5pmj2gv$4pj!qMt+e0qK%q&NmLCVMA1h2GTv9}{;aK5y7*}vzQVlEel4k%VLs)6e53~qfs_i4YQp``f}XGu-Y zm_XpXtmrh^z^B%Sm^s<`R-cLB(9tO!;>{c3;x?4@3$tSvi5IeqAYrq``5QFDUv(jE zr(%&C2UxZVr<0j?&5`pxB2J+Kfo;>Co~yUF2%HtZ1y^Sx8C>@p{nu7#VSbVyPUlL) zyhFp*R*|OhFDSNcreWfyG$%ZLUIK!B)5XhX><9FdTLgs$G_*7jr>gOsoKD@M+H1sL z?4ter(E!N+=b9ro_e@_)VRj^N4)h7WDDW;r2>zDL} zO?OAxq@B@)NQ$}}e1wFBjH;X>cc0N9fQt#WL;20n&pUft$0Za%pLD`*~&Ff&a=8vh|4Hi4iY?s(br;`3bL@gH+{qihMponDP2 zkQ8i)5unM08H*M?IZ^P~;lf?4qIw5q@iua?jaN6$<|vd9q9l7XK##Ca^>@?@&`f_c zjM)`*8p-dhJAfSMm^SaYo0e!eM8K!LjLDwUP{1yo3$$($?Fym1MmL({=e+zy@2eHR zWCsy~LeHt@B&WaF09ImmZT_ufZUe%gs-uZDlVUCd%qlAd6!+h87B_qeb8vS%@C>Fc zx9%gS`CvEVvnC+)qH3H=98uegT+#k8R6E3)?(Y1M7y(vS3hg|DS*?{%j~x7IxsSPt z`W_pu4rFdrTBrHXRFIT1=DH_qe?9ndhOc26+YWVP?a^E~8i{xH6CY3iE?MtIT-6(N zaG{7GSs7w9B^Yf>P{i@=79>ovjr8oQIefhmUY08p)W%8?sQq+usK9JvtJ0XkyTGNg zLPy;zQ8#pS-){Kfo6D2FrYpKa5+8pU6h+_n63FdM2%dq~myAL%f(wsr#O&MUora8% z+|56t`mKDvICzeACzMB>3#@D<^m}J$OvtmXZs71?WF6BQE^%&U&dSQ_sP3zHBk^`| z)8(z&bn%Lra=VQrdq|?ziV2(*@B5_uOEh3-Gi8c71)Y2Y{ z)pAymI6nnn?~S^DTq03fn_!%#xEh!5PxGT-t*KaGK%$`0bGV0jK;qPra!xh=$N*Ke zwh*m$w^435|JbYfq(DZ*fUt(2z&XPqZXx1lLrn`Z{^V%Io6#o?R!7pjw|HOhxN36R zp>a%u(2R0k13wyw5fn4-j&GX-G6J~wURSCk;l8A%<;KQWul$n#u?m)bl8`*S>^$jG zu!z|`!-rekIYwni(Gej!Zf#v5%Eto;_R?g-AVJM!SwO)orOPVo@8_CtB9ZtCXJ@WXKnc+q~NG3y4qv9 z-_R=`=lb{t1>xS#p4fS<_KZ(`P4Hl6^&19o-H{p!vdi4ZqgwZJE-*o0*A%qvZEx8a z{)9b0*?yDzQ-XpN@p$Bee^n$YosWYy7l-huJR3ykV_yD5#-qovWnUYEm4N=zRJ!b= zF&LjI6;GzX>lL4ujbp76jZ_u>*&L@C=QYC*>#L1T8oWN?surr%X|6FrW`CqFT`YMp z>`HS5#_!am{r(K4cROo>&bRz4ja67mmbW@{*&L|Zcy3DVmL&VSr-fx2u&*ZWD1n?x zC4oysCEIt6vFA-G^U`AZ)gn>3Ga8sW*v=$_9LZKMn9SZxTG4aUgnGC^nq}(+#>k0`0 z`$f%D?7gO(H8sYX%CWlOwaWd}^n76o5XZaW$Ur00$fiO+DY-w}_iY9qkOzG-eJNe1 z!*#I%bt>nOC$PKYDrCA-RZu;n(_c4++-!0kwlRf`1T3acNRu+zWHt(T+d`jc_lDJb zHuxQPG`CXH!q;o%^pp&+$+yImEeidHC<)K_8Y3$uuBxf2eWzN7s-+wj$mqesd;nIoeExH7I?ibzBe?OjCG-YF8CVbv%m zb8)x{>~u59!|nOE$0za-=&7>aP3PTO6z@p z%vlgN0&6e}YBs@P|1eC7cA%>)D?B+0C^j^p8xn2MHu8p%Gx%c0Y3+AY_Fq6gISW`F zYmTJ4C6=(~Ntq4wy^*z?O%J_h@6fnrqxCTF!{*6T>Q(WQbG=*Ymgp4EiZ!vb3EP{Q z#Ly?i+!HyUb4m7=;a{B%OJ+Jv4Qrf%QIaOj9ABRp?Pn2fF~Lb^!X)9_0Y%>}pmRu* zBnMfiqGO0&Z1hl?Z>LqmaX#*6Q7-IoB10ufkW$)kMKCvM0%7;@Yss^1fpOUCob0)Z z3IBCllOKe0XBsRwu1lU|Jkkn|SB4ZK5594#=87G^#I+&qwD)qM2(AXyT6$GDeeO!c$n49G-Yhb%V8FpC5H!jO5Y zNGCtF{8vZ~o2qmfK`FHJji~8mXxo6fRM>UrSzv7J5N&VRfLa=4uUflz$ay6QK+ z9Vnn7Vk8mPKmpAI;DO|2zAq;%>LlQQydPq}-^Sl~{`N0x&A&dXTY~#&Kk5s)@KFo= zUJ+$wPNo$mRR+XBb+_%kJy5HfDwB$>qE@)@_K&uqU$_1q$|OYzkTk_D(Ou~*=K+km zdnr(g@{+tD#DB3%Ea_ee2~_Jd%eC5fd(zoh~(BCc;^`z@{~UkWrGMgRCss5U?<7!m)pzX&ey5(>_fqhtBn1%=qc z9Ki;fwbz^zDM-2B;IB0Fr3f}lW#ja4M|(vcYZGw^3AS`}zMjdQuHTwi)Gvdgm3`d0 zN~B=~em7AGQvt%QBLzjXNh*btL3E=vj;}X_>+xg7fAI#>zp(&+Tkq;DP$k`@cfNdm zM^{US!9{4HbAaA_0iyd-kmt432+$VNEs`{p`yfM<0TE_rZ!0S=UkmD6p3Heyu2)?p zQ{nyiPxI%0ABcI6*yMO(6-gs9>VekQ$yL49)!BI+qKdOMr@C+}8jQPyF|UizJgyHA z;U>xoiQ&+O$#%@_=R(UjXJK0GmHTOpe`7H8&&IjM6g1ng?K%2P47*8MzK-QC&!H@% zs0hd*b~_Z_;ULS3!Vl{n66`Z65%OEdBkBw`+5{_oJe;EwF+B8R&$27+wN*tNUdI2u zst@QA^0q-Fl|5CCWup_THJ=4-BIq~*GM7!)gbAD#)tK)8f9;)TR8woW?*objMNmYx zAVuAZf`AQ>j-sGjX+r1_5v7OT0we(yP-!Y6B0?x45D1}#9)h5tAcU5L9*|B5p(OzV zn4s#(-Fv!4C1}@66TM z@cSxx%J^)=xzRYmC;O3YH-G#sj_M{SB*iOw2*6Pb=;fv3`;G!U>CgR7fW7n_yBzm# zII2=`x9VR|_W!t0(uUIfFeY(r2S@GM9q|G9xUJvxyVJVTXLUx~e*7EG{hvJJK51zH zNA1|P+pQj0=5~~0{NMB{{+EmDz6rQ7gR>u+{sz_hrwv7X0G7aZW%~W;|MHzz0V>`w z@x|1CiMVD=0U#JIfomVyGJ>=L$9b*|xw z2jV6F`gpqarTN2v3%QsqeGT5h6MuDU=R~|ZRDWGP{9G`U$#AC>#cctjm=hDj|K=J* zl#3d7+7y^$`cP}q?}e_>jRZk%JN>`}(ku@hh{*e8@x^P$#uF10b@%`(BC1cx35Gz2DGe1Vi_B8kycN< zY(u#Ij#Ol)ZpLfM_t8maS9GfK&KX=Gop4dxf75*%y{w|HK6n;xPOb2G^EkTvwhUjq z$X{O_05Coh3`_6F%K6TJOf$DiQww;w)3?qqUfOsCxKQpRAAN7`vpfnsPz5pPNaP?x zVH(0aO6k*ba@l{#d;HVC-o6`=Q_!x5PjXhF6aL}2(c#&+@SY>jp6X@n*)jOhACsNk z7CJoMz1uJn8cc?pn~IOfo`zq)=KHrcTf4EYAs+bsNCAX^h*0kA1Wd7gCt|T$`OzgU z1l$5F=_nBpgtM^+$hwICbwCiV^WnfbkmSHJMF>avz&;RD$vGj! zn{yx>g-UhyJN7}IsHbq82iK)l1&fj>gI-RUy7YHnItRdvxgEB}GW*Ov0akfyZh2sz z*=wCrkp^N|iu08zaF?O^O1tDgLWEB9+7CvjYyZPo=6`c%I@SONoJ;ceD|WpAc-!Vg zVkX5l;t`O$#7>y3+cfv+BsFX$08zwgslS?V2Y3n~3;>pd*I)UCjtFp27CdUHH#4&M z-T+vt1MysK!y=Hye@q!q`Rg+=?gz{$Nxp+6lqUwP2-?TFV4vB}K8sv#2C&pB-;e$L z|4W(upI-RwPFK72Ystp@lHO%&op>m1*?4~3gY0bS#gdE#>a@+KdylLVZz#c@q> zy^Q<7Mv+TOjXP<)BT-5Mrn&uJ#-U`Z2aQ{TeU1s54oEJ?Q29|`MgT(7{-1{Wr$9{_ zzT=ggi&VQ;fso3Ou|7THzH{c2_vUN%G(h00lo~ryQ-@kD4(E>aoSgU1!~l(I;sxp- zzb6$~P$WY)$L`acq>ztnS`OKHthB4JrI)AfYqB9ds1l$de~T7(^FR;HqjF1Gd70&K zre06>eNt7T$R>z)lz-3E*432;dLX{<;fWAC_v$6j;s*0)e7|y2 z;NVw}raex_7wR7+^>0#tj%+9pwYDMKH%}1oRy4cS9zwhdK`9jBna)(#SR#(2E-m6T zQY$|_lnDZo;n!6JOW0IS!ve}1tK`~U^)RU7xdkK{w02(5hfzJPMeD&P(`y+cIRo67 zT3b&loUJ>r`eRQ+{sVLLE=>4dVpzbt_LP-((CW!!;J|Smz7y~4{FniOKQHO`mtf+H zo+nqf@-zynWRe7J^0 zgc~44u{AjRa`=;pRxH6Q3tIQ%EQ=mQO?ff_JpGzol4E}PJSr>+ zoA61!>fqZ~c2Dq@xQgeaL60(=1pMb~@G&*8|NF#ypv_rlF7CXb=0nIP`#{@|A2|6` zFW20UzF87J6AnpQF$ES}2l}9$OPsh;X$d>7A~sgrD{Os}0I_Df7bVb5dp^?!?L!%^ zX=-*tjkfI!TA7n5XXFHYT9e%8rJ;%)R!u^942&X&gPCYj#k75`#dnrc0=91XgS>rt z-y9k1UOT_c9xeOvS-hn}#k=9bpku-?{cB>pT%eR}hyuS?-Pyeja`2A9k3L1iDu`HU z-4gZ92ToRcHW4ddIne!q!zn-2Ow?8^EwZq89A6N3q+zCmiq2eWy#lf?d6;AHVJ!o{ zHKooP?9M@CzlY>j4mT^{=N}HbWINrNH<;6&NQJFnyr>ahssia>31yfz+zkTcUg-Rt z+VP^pe4hTW2i>|Xa;n$h^TB9q;J)V3+LSObu~)LflVa7aVa&_J?h#Dbl>}Ula2p`~lZ$7;QE6+u_Ai8iFsE!vS~u;mj+b zJBx%MY_C+B0~*x9ENE|HDBw~cnDR;Fgq0n)$g4oWZLmU|RA!|;Ws&i1Z-dG`Zht)o zYT)5}*-fR`IzZfdVHxF!q;S6y`pNBXg9&&23R@Djzin&z;o}O;&24|#@|e~s@GL$b z3wkfBDl)%G_Y(icT9D^vu~VGW%lKAA2fA|zHo)_kM{ZhR@rrtR8K%gxyS%q;xLrSVA%e8|F~T2@T~y;E24P(rZ(+||?> zh`ASzbWAzqXI@{~1{2>u0-uJfPxWQbw-zNI3&y$jd`@i~1uQ)4C%MSZz2~#0tD+XS zboKy8K;xkLMDaT^tFEj`v{o!ALDHS5vGtKYp42M;!Rs+mo0~NYiw+^Z=3QIkZ%~=8 zgC=OHwL?X%&7I^2J)`Lu=wO*gvK?2_{_geFGop6Kx3{|66ib1#PnKUNwX^!#YXWLd zJ^LlrmCXK706C^uF|VZRP$Y6T9Y#L>&Z@xt{dmQ+|GorDavO1*JLFZd?iBdrOd6Cj z9QXnT03JPBocWbLB(_bgp)0xf^i~_gHmGxb325UK(s!{xUW?^I8=8E=AKY@3`vxol zB5)Qs$}XdrKs{PdW3@HbUQ^qPS{B+ITh>#T#rWtqXomg~qu5dGi<=>rS z0^00+`+}Tt9j+}ysI>7qKF7$WH!5X(5_-74ED~5B-4;ak(~qDT!6Y9T8X6{KWPd3fq-MA7&z zW_7lWwcGmi1BzVjV16#jBU;MbUu3byqsWWFV@|3*Trh-hf@29QHN^JY})5g z`TTVUTfqe$ZSu;MnU%x$ANcWyi>}B0PE&Gu0CaGS-2vK}~MmD|50lm3uG?Nb@^+aG@SR_oKl zc@;pwKnk4e^V$9K*zFupFsfbS_d!L1FLXnujb1|hSvuFtzF7LsReQzP?}CcVpc}zj5;|9AI$O=g)tP z`3;n>D4JW?FtjwG1muG0XfTiqjJYDNxna-ESzBMMK|k8sVm}_Eim+HrRitVJ^wbou;CqQ0LFZH{y?9ar#j2Pca6kkY%>1Tm*m1wHY#x{jDm$2vC(n6VpRK zXroWpp3mNGtG}dYeQaHOb1^$$*57L1GiHwO=gO3=`5tbRVyb#jeS@JY{SzzgONtB--Chb*U5`y)r`!S=zK)emnzP}A@DmCa{KYxo2{|@ zM2{pQw;v&C8|EVu8ZhNv(YWioQ~QTVw*rB!&E9h-Km^vny!WoAEEKYW04*(vUUVMh z*}Hv3Bd{wAGT&j6O)tPsMZrB5R$!T_b51W@G`K@|Su>}5Jo=X>ff@qmSw<#eYh%BS z4(((8;*%IC1I{jOQ>e{rP?b$IIlWL0gjNzaMENvoIRZyQ6whB=JdhGllb20jW~Vi+ ztXdPbR_Zjjdi_{2#Kb452k^`Om0ZCU5wV%GF$3F(RBdF$U}0&Gp?bgJwUP%SbEM&r zKGvWYW2}*Af81g)gf(|~5PJ@kzWjaHXFucdFF#D{=GX!~LrF((%!sYL(nbJF7d1WS z^t#Bx)-h4?H)jK~*AewYDdkLl2k_Tf&CP~Sd+}}yX~jf!dU>|RslXR}CcgddSk3tu z#d`kh;K7xS5{bYeh4PW@QT`>ixFyE^!$5o<+kldT8 zN-F_^Kd;cAB^nl6*duau4$S--IiU7FL2KiyY;?*$tnd&QNV%()6nlxtfakF_C@?NDt}r24_1b+3A@dc6c3nz)WlI^Se93k_RPD zh^csbtn0QMw_bMg!4NIq|f?rSg1Ee0! zv`O{;PzAFZN$uO8=@%~RW2CVZoO)@T#5+B9Wm{F9ULwbJ9~Dx| zvr;?!S9*E&E_g{OxJb!9%Jwq=uWcOcoL+@C?Tt>Q_{(=r&oeb^Wi&e0+;3SG@!j1F z@n3&DT=lV<;VfO90 zfbFd%{lNPLO?aF8exVzYDcjs7iqRU-zU0$2m=G@sXlYtCV03bCcmss*{&|oVjAN@F zki01r)EO(H9At$M|2Am-*wPfsAFszvfjMZ7{<7AgvahG(ONvLA%v(T~v?;Xw*f2Ym zpH|f@2>t~8YDGz_4d2n}O4=hiyvRg&DyJ{qem%Q&%t2Q_>J@apO53Ih4Tm1RF{{Kp zQ+q>^58pKtpoI+ql{PP4}qsT)Wyw*uY1G%&sc4*w;mwdw^m2JXP64i(SZ|BF`2x64Gmg+yrX$%KGk1C{(6CoY;a$DesTGKk1a&vpB~9lnXU>C}a=xCuIOW8Rcl5rf~be3z*CyV*rjt(PKauvr`y`baR+ zK1_9YG)xkm=EqteYu?S5JzQ%i<$3v9d((+DQU0eQo5K?jv_51&?snHD^e^j(gd(ts z3~ZHRrA+T?q4zsO z7GG}EHdTN23wuDYDP)AFdN^ZaQIig(Pqxfkq*5<}?2AWjye9ieQNzl8a;(qYLFM3epF2E@YaE$KwkuW~8-qvI0%?Ln>gA6w95wl_(n*>AIKdF$ zyQUHvP~O;DWS>7$?9e214Y~Lwx;{a-X&ti#z8FS(b-hH#eFoFC6&17DX%|5WLS(;8 zFA%r>r7ID6-A)bStgz%S`OBhI73j=N`bBUGW{m{QVvpp zBuSu}L?rBYY{L1D0HGLe*sIt*)E3Iwz|qwi&pW4^dB~H$4(KixW`L((da^o??B&0X zW#K*>t#kvfzx!wYV2H(n}L8D4=cH;qkY-aHM&Vnfb%vM9kVwXY7YtOSb+4*PBCRRSGQg>WRP zPGm9i7)C%P-*vl}uFE+gz}GNWR7|GYAPavSveUIsQ*En+> zLvcKBjzC1B01{^dREV#s{>RM6d4R4o~CTFfUx0eM!rf%tTE z6WqD5B(kmar9gN~eInFr+qf9x7jPh4WG!I6^BZf#8OtjI@7h#gEBZO(SvBo!&~31? zJ7p?z@h+qYEs#^M!~L~_y@C4_)i}KCP#=}GMCnPcThjePve|yT=`7i(utjGJ9n5=p zKS`P2S)}fkNJB{azz_5jbI6IxC3MyN{QNW8SiYEhiN%9>(_5v;6bbDGDV0lR$+xiB zS2GS?U`%WKTJiZ1!^=G0K2GT6x|R4^U6D^LZGLOg{rfx)v@1qz{!c3pMH={r^kRPs zy6m**qmh*eXC|Hs8toIYvj`FS6eU}h<;V&6al~scUfM%fBzZ|bBl{04T(bH1LM3^T z=X$z4i|QkKme{oMv3{cVmIn&C^myOg(HY>G9$se+gJ7-6&j*|e(1wtrmV}oF!*LQ| zB?)AsPawG;Lw~|bqiYb(OIr(@Oq=Z`oV-q|K&vHEePqf@pB_?cP*_~4N#t&E7;qtL z=!o~Q!O2e5*|)+EA=?F83(A9@5{L9vj<~?@9(Vg1ty(EitGQc(UpdRCEhF>fiTjTo zv$_CeRNTKUd@;RK;D~@muvyH4OI{?4T;Jj2V6?SKmHg>~Y%w~K>J4o_(82hX^s?od zxXe+ZnP8&U^v^zb2nkmk-PH1Iw6-TQ`I+0~nvO|Qa0n4Ke~kZkd_W0aPHwJNQs7v6t5bboviZ>d2tI$n54xseV0bmmh|G1pSNAP!B0O9HYsY))N zk4=a|bJ9Z>_-X-QPwDDj^tRbxAlMe-jc~4|60Pv{Q5}3>;-TZp=Z1biB?^|RSQ5XJ zmH7(7jb?^ndCf?+n`+HVneo;a3I@~>7)P+N_T=>%*`L{qc~vViU8<-}+|X5X~C7U`3~YSg?o$RefSN-o_eIRF6=% zwbkMu$%T7~Biv`sW@hSGQwrA>K=gsYa`!r1)x2KZPwX0{U9l^;*Q;TzTaFMAXVIzV z`&B}j*|n+EtmMDTs0hMcMck`MTLBT)btn$t78zks@`PD8LL@yjz@by%`WXy(6Oiom z%W$`Y_6aJjYIRPRc&fQhQev-cUCGPKB>PCC*mUSla2%J?kjWR(GkPTF7@_!v8nA}A{ml(A!x{;L_NBm5d;mNO* z&S`GHb46J}ZIHlpX5&ayeSL7)MYQ|p8rPW*=+@=EQXlV2e+7%~!$HW?POFlJ{)us( zVd9s<%z|yRUY`Rg&~Z9g^*L6T@}L+0@o~!A87Hy!GK5U+h<4d(=u6L0SZCABokWJ9 zim>ZVo?-;Io1rZ%6IV8ZFtAv|5RdbYo-*=5{IfV9ZG4FLM-+hC{=)-JUR15y%}d&0 z5yb8tseP{F%6A`GT0IE@i7(%|dEM+hXv9666u5q!*>qB43s$7L4MUunkZMEVhL!Ul zQ>4-$UGL6;>RB&P^MhwpOPa7{_NHyA}F zih<)cJ?OYkvR@Ud7B>lI-LuuGkeG2=5nV*~J@brfxhKXtR*$YR9&|1RRCVnNpIu^| z@13MxbY8sPSU@y@(B{3gNHDGaBQiiNWI>UzDHe~(%j7SbHPSYh2E{ib}Es%L}Mu39I4Sn4fO`snojYbWpsugT+C{13plD%BJSyq0uboT2yT`e#<3n+&4$ zj`PMk^+LH>Levd>c7j&-V1Byr4p1yEmGMm~G;c$j(byTH#D7L)A@7&x$I49e_riP) z=&znLP#18CDDELe86Yc#!65hefzVEsuas|QgL8pU#o~yk8VN94hUzj4 zW#5c@oq7>pazUiw8~okT0QpYmWdPHY_4aflpq9m}dbjOWB=S>lZ~`Ts=E#mJ0cBY` z)81Q;rwNRs1K~!C(_s@N0E<6k2Vei!V7`VL{Jw6)VR$zOn|Dd-Cm|T(hQ4Kyi&_-&c(hU6s3nq4hgLZ@zRS9|UIV<7amRT}p0 zL;3jZ7P&&xq>O>bTJ$8}jmuRrm1oUdR>u>#SNO!m+?rr4D`#s*!55w@t+z2UR@Xq} zamn<{Kg3{>3Fvq;gM7sXEL$-_VZZVMpyEa z-fAw6Ze?nEj+p>w^~TCoE}Z!-*vv-^40l7BX%;dS!9VgdGYsUlgyYuuM}GmFEGrTh z0v~?BH;UeX{~&y{xH}6tU9w)Btd5A23)fI%wyHB;6=C)WRER@FhZ>84m1%n6EQyX7 zaG4u|^hN^>A`9>|Ma3^ZU^H~TvE|7i=Xk)rUzgmcEk%ApJ_iMzKpSbkeJ*$>Kv%a( zj~2=QATsYm^a3R?Ce6Y*4VGRhhi@)munvkeh+l<@*(6wTG8C6on8(^)$c6{B&(F|? z-7uq#+7{<>{xApUq8n{^h$Ep4ktg{sE*N8sOg{euOlpDm*=@M6Hu4N#L)XBtwYs%? zqg&xpxBhHET!=5=|jgghQzSczKZ^uNKGwh$UHvl z-Jpc#+pxvVr4pql2M8*^C|U-q^<4s@PxlHkm06*E>j*=UA`rrVuKd9X0WgW{9`c2M zwDg%)7cHN}`evt~SX@7iat8?t(vFBqCS4M(F|?hdud;zu@dktfNo%tJDh1{|wnL%U zffzJi>k7Xh+;e6{SLCyakm}Zp-1*0lwyOw%(eB+11NOr;0mAhOJ+D1~cgxtu9+Nhb=~&yTSF`9>j%l>p_0mt)m2f1jObybp#Vs?+1mUPQX3)eUijo}lq=nKxG!t&KCZ_c5DQEg z2g9D-hqxW22QLzBZO@YYD~PUno#jURe_1UzpH2qll~-gncsrXAf^*Cb*>){-KSNG`|HL#Vc_zh&ut1bx#|}dz>qo+i(|r6&*a^H@nG8 zkIQ}+gMKvsE3-Hq1>~Xb+JMjL(PNo4*)6gBA|J)9O)cqy*)1XgPv#EHC2P*~CU;v) zfoZeDbMBSRg1F?~;N>5=x_sCH3qhuNsaT5S<}Fg}nUrswo3u$c`J1>Q(z&`l#oLB7 z`Gqouy@NqNP|lY*)+}r66=dIH%;O)6^g%2=wrjNgPB#^FB(PgO_`-ln`HncpWf%ie za*GiMv(5tK{AVw1!L?pbYjE#|Z%q~jMBc!lyRCmgL#S|$UFwW{3OFC5bV%u}_F^&q z62}0ttI9dg4gOWPW*Tp>sL37?@ihF-Qf_n;MrYi2H$aONlXJp;*la8y8?+s1oOj9~ zvRM5VXT(DVWp;V z@98G78uaa+>QK58MYMWPaXc7$o8)Be?jS`c;h8jYSr8SjXy${OkLZBe4;LH;uQ6vs z9bKHaK2{p0U-j{|L|V$Hi0sp(jj?f>MN2Dy&F0iJ*DqF3t!1oKMBW0DC;5?fmBB)t zU<~~b+qfO>HS?XRD}`ID8)JEl8NHbG6XQyQHG0pLlAxQP0*1x3@M z>jL{j;_b(Eu?^;_Uf>Qu`9pe$h?b}nY$;-~w%~SDF_`hU7lhspt^cT3I zr8{U43uKwS=(ifQqmeWGF>kRsM56}8Z!aW$?}|Hz-XO(+-Kq;|e@s{r3&H@=0sN5E z+(^(yyOwpJ1E4<}^V7pjfO)Xhoj}g`zRLTfA|M(&Qj^uEY3mFyv(6|E3<%Q#COd0L zV(4^acR?<0s@U3_2G197_uoa)9A9`j{N1d(LZlI~=CCc+5Vz%o**`8LV!6u_RWJ}p za1j{o_litK0vj9_4R`88>nGA`MLr5AXRdioCGxUjP$3SzkaHj$E1@8m-@l2&( zAMj>OPb`6)jUtkESRqdx4M6gre^_7~#<%&Cg=MqD{<3&z$~{ z0!pvF*0QI4yX=%D*3J%)EIdxD>weS}_hDW1>AHL8F-i2EnpTP#IM~OdAbTsOzZEkz#_0V}R)srzKwTeG#$@vk ziig}Cf^Hq4XNSc#kF|q^o-}C^5k`; zkK=erjz|3^N5@$D+gcwPE%=h?9BWZi6*ZR`c;3owKMc;97Mw#39E47j)+L}^bbs5_2**9vKcr=VM zy!_NTaFioULkEP)G2@H@s*$ zm4CY2b2f;IkRn6P3+OIe?)U{wgz!_@djZ3q|4>RrR6^K(7hb#HkomPllugMpU&bp97{pQ~4H#)bU&rN@X+4>v<6g*3->pL(bSR0S(YQ~`N zphu5^Baipk^f{1xyVB{DE!nU`dCPcO5+%58^wL<_EnSr}`Il|q(Ud%X8_7k5ZT^7p zj=Bgemaya50bNvf>gx?YET<)o?KZ#Xot3(rtviE7#O?@EF&Zsi4PEW}*1Cw(+^x*X zOnLf=%6QL*Yx8Bqruzq$+LUIRBOfD13KDN!UG0bL6v_(OD6)9Ra`AoW0&cswh`o_^ zLzm`jw8ElnTrfUUHsUOP)m=>1LCN1P{oj>vQR2Ku-$=oF4+8*)Y0SZJLdrCBi*s-h zj&C6j7ZU0OnW7>hAony^)w$0f8nZbh3P7+7?x6s|dSk-fqafPnibh@3VeTqX0F#5D zb*4f^83!Bxgc@dC;9WXdoDO-nXhA#;Qi#zaUeDOrfglO0jtPg)nd~UJ=*47Y+qz@q zq!YHH4kuX$Gd3$QciIOp12_gn-4zPPuFS2PyRJEQ321WS$Q1Lk9Ca>0LOk64O69Z7 z-;p2$Upd*R%8jzD>Q8rG$Q}h}W(ORN5kpsmt&Qo=>vJ0|AnB4ckzC?hauM1Vs5F63 z8l)(=-mtzq29tKXfwafwOGl_=$3*b=?71qs#;9q-dms+vw9Oi6 zO|Ga>kP*~V<%szD-_38~(BEE)nOw8$hJ7be>@q%?x6tY%TVZ@SP5i*qER%Y}GEc4B zm6_odBC%+-I3zbWbytf`U3g>5J%)E@(N?wVtsEkwZ1AI~r=?ujl|OcOHK~J7ge^vt z;9A>wKc#;2Z@O{xee$GI@S%T}JVCs(XN4jg)E2tUxAg$}b~cdgT{pYaO}Xd_(TCy^ zVRkUw{ZufZ00Q4J=_#+MG^^J%yJKE?sj)!bxg%`2Ipmf}SXI&DbxK6*(N2MrHPx;bj7J$2%o^CN zDRu&!Q$>z9gu*Ba~qvbXmF1hD`6$MJ`G zuwPa(@BnLXi?B5IO-uxr=@FKHoXx>fV3upF6(uhv8UR!}Y#%&3BgPdFFcgP+OJuEbCbi z2t=!{rmPDBQ3ZoQlxb&916QcL9u$H=+#q%3JNmxn%UB=ZO9spx>-Wyk`_V{vK2nN_ zG%A05r*JE8YpTddN&nIv(Y3||@J)E-|pPV^GMnSIx`rAJ`vOE( z9wn!i5b}=?rw47){k>IAepR@l1X|`fA8Yf^w*n?S^^bP>p9%l&CH~KZKX=>zdEwv0 zhyNYqpBv|YvG8xA@&D!NgkFQZac4O$t&!Mu6skJ^=}Ql~*tm+~LCy8#oQEO)x@$51 zHyh&g3~Rb}7>4KPz*hlO!-anpL)>7BK$2B{vFTwm#q^nVJ7lo6 zdahr*Veu~aI#TV@P%EMY{YDYKb!Qc9BZoewIOc5!i6UuhyCre(t zPeyKO;a^xx{b%j=?Ro2m^{OjS(lS8>!QojYfsr^DYbGc zhNTuou^8|Guwc*eO{qs&pLONnY_MAz0o0m%A9!~(_zj)e<4@txoq6|8-M?prdvp}@ zNcR?813y=ES-|?M4s4!)#mv(6q%`En#o+=5kI$>cetg!?JpXAszuZe*0Bm^tX-Fq9zA_p*?kY@p>Y(xp_ch{kI#N6 zhqzf&SCdHTJk`V(bcE0dJhloys0he^rw{-ZF>i26CmO61b*>la=0!V=S9adpbJtkU zic(J&cwm&Vx3TsFbTFr5van*Fq0%Yg(e2t5FW#A`E)T&x&7JP7QS^p+7B_~zV!U=$ zqBpR$f9`8MG;hDwvo4B3;DI0_LPTmM-r~&RK|j{yTVm(*KD={9LkvfJ<-R<$IIwzn zNS<>ztXg~s+<)p`e79#b)pR#G0z&O`EzU37WKdUKHt{$bHASv1j3_9h!Q!& z8ZW5SEIZbdFfhrJtc~68EW^~O`Z}3Xwc7T-ixUlxN?Z*bn;%U1#5upZDk`dQ{MLV< z$nh;|;n^5to%?pmbx7rd#eNGBTT~j+cjNOSGbmliL}h8DR4__@|3wE*UX99697Ndu z*s2zkFjZ`EZ=%|N^Ujq9QKF3RXX|>`b@$h$X%ZUms~sOrFR(fiz2ht*&z&dk4cEif z$D6ny87sG?HP8pxFJ}X|=!*H{&uUfP#n5~tSsyHRXnGNZ@pX5T@#^ua`NoVb`DI7; zl$C%FzP%qbLfu>gzSOeO>00#EX9F!Tzl`9>dhB7@-NCCmVLP9g%~NcJ*f+w}!AOPM zKD6m33FD6;@;C|HaxAr?A}1kGWAXb{(FHDc9xiQ_pB!``9vK2hed;X5#iU>XGS^p^ zx@-m~sbjCygMI6{j+bSxzA;heeBEvXYC3Mc{9_CeMg3UhK1tn?Z*AV~*`>kLub(pn zO*Lrk@339W#=Yay;7?X`bh{disbk2ukcCxuajIeYOh!64GEw`M_tly8r1IHV!J)^NgQYKaO3NZPfKnOLv6a)~SX_MNK9Ro8pSSGzXo8bNoXF z!FEmlwtC}1&IpQW8JxFtnVg*FP`l7Trtbkr?k~A>-!!fI1KNya4SbW(zhm zrv7_BH$`^kES_Xe2`xh3C^iHhf6i_LG|O(P3c>8fOOyu$dp2(;_xTHZ8Rm;Fvm zIM_-INGw@C$EY+pXsKqB97g}f)SE$Tiq@FTK8tEyB)g=@#;Lvwp;S9D0uT6>caTJJ z5NE^Xf#o*%%`Iczi;6J(bIVPlvisVB%-%k6V>VqcL{nm6yW@#TM#{W43`lmOjN^B9N>MR_JzzV@3Mh5y~wVbE>E z{$(+%4cFlz@tBncFP)JkFUSKmHMJZOH%5?7x{PXjs^yKWOn3{wPP*w+m&xd&yyt6a zvOcDC0-(sP3mxNRkEnSOm1ac~qRGv{D^n)qGo4&k5t1%lrSiwhf$yciEx6k(v`t~< zWYC7^8#2h&T3zCvS<$e8xNf(gm$ylfy44kOOVu7b+E`VmbCnP|Ly=nsoPD|$?})$c z5H&=iY@yfp#K6(-t92d(2c5?66DRH_N(!g@gr$mBScr9{6z1p$IOS2Ngj&yi)Uj?m ziZbQ&LNPnYKM)*O~f|N9D z=`}qFzLjKk_}(Irq}PDlj)B^()+NV&;Yws35mf8Ccwf0Kuw%f&a@T_-vS&Xmy3seW zx-hYAc^MSBdx48G)X+(RU8vjm675D;V9zJ8V%VLb6n?r>LS5_k{@p~xYs)}?Jt0D!CVceBlp8j?m!IqYJdxM9GABk@dXl(bEafzLr6r}@ixi1<-&uwY23Q_mB&knS z+w-dK6zg_BD_Su3S9#i-A- z()DgU%7RI@m>xMR4nNIdFt((8%9&UFo9OD!GItqr%QUAp$JqlX8Yh7djJ9V8SMh5i z2s9sI-fWOEWP1-+5+fE@4SP4wpHX{qc=t{}`*^Nh%-xM;aT{Kj^mj4lC_*q`%+B*{ zk|rMCtD3CI@%WEY#Wy6N6JHk-FK#@j$clO(y=gj}tHJhzJ-taW#?1Qb*fp_D{1=gM z#%rdX2U(x(@riuzR8h{*Tn8IcMo4*wpL@`hZ;O>9XU7EKO-{8`<=I(=xM?@{1fUSc zIxrl%<~clZnWhGp!*BYwyv7`Su-4gpd+RDv=sS6`L(*KvTeJK{NIa62 z38!tLy~K2w;dQhhAzI zJ}pi@n1@s_2mfgumL;GBVwacdzdIAc=*kRIe5Y8(e%p79FDX?Xnlpc>DgaRcW-b9mVLWf1!P)^G^V{CwB2^Ju)h3Db{F zbLOZv7up~Bni-C4%hEdEY~^}dHkv#gM)h@52c)wuJOUMe^j|%%kf>M_?jle$I_zq3 zFOb7=)Ft}70_U=KijIQ6hPf}H;Htb8ty>$IS~jD&MgNBPfv0i9?qcB4$AgfM}Rw#u9KUjDSh8;8sF$Dd?7 z*5wSDld#5!tjTYB`|jU;qRZVH)+Tdc}xPIP22XdUtNKq zeWdx9Ih!Lz|5XK+Mw|XfKQC`CHcDxqnM3`y|hn2)Z3n* zvTmbO-yAOs@Odd|55kAmiOGDGuJArr{MF>_?54NVhbXt#Gq+iO1}KM6Tvr0U3+7VL z&`BaE0I}u)W868Gp{~M_>9Ej(f7OO^leSRVW?KY`R(1m6eBEPFG+x}czrJ+>5looa z7nwE;I+XY^Rd4Ve*P-*SvheLn`%FlH@+iJ! zRsqvC1!1u(LKCU{z$u~A&}h23b4iOc**Vn!9Y6NmgXUVu%D^rSJ;_~hD%MwXczD`Cwzwio?lqTV2okQlUOvLpOWos7QEJcj=-#C$Y4qDWrLbVGyLW<;xQo~^kR@AL&#g)~KMYim8{3DE4d#4h>U!4=KW0)LNtpYy zb^h>!tkgQ6{8B12+h@4IW+y=fBYn!AQY^hG1iA~=+Vr?ktru{#@`ZF_eW z&)38B%uBYypjQhW9UkJmVC&EGwczvYHv4XzPPL=}&f9$XS~f}2eI-sp%zW(n73%Wm1) zPJR!`itOjfBXi9_hFYiD!&l_0Kfz}5iGmw!lK3m6^X%@@d4p_-9D~i%7es`zNSli! z4wKE>OpP8yg=7gAm?u|(m-!(i9zau$kDxU03QCM)=ajgHmFHodj4|f^=+!3f(mY%9 zpN3t32+-5#bBRXWYc=4`0vQQetrWr=y`3&g6d6{F?6@6gqNj=QRsCP9by8n$)^7CdMJB|zSse#Pkwg9G%{t!?Lx zXWc%MpEr)L@Fs&Oj{?!Xg#@N5(9e9gQZRKcn1jI%zbuv;kzB4&Z;uQ33~7|X&|*`K zh*!Nis}`>(#8~BxrR$X|1s3QPRnDUlRc~2NSK6d%rXpG=T*hH<0~)H&?arHF@O3mm zet`unqc^?F7p`;lUj>L@I`#Pk;FV1l-!P{eVkL)&)eNZxxn$Deel zgHCVr&er_#4g9=z^MyLdf3Mr108&-3g6!kkA@GYP3OQ;?LEHUVWFLq1OzvwgCR;2G zNX`;e{yMYNjs1`2o^(;C9>&PSs5g@i8&f5UXLkl7K2li^CB%Xqaa8uaTJKa+5{|y; zGvHv+&Z+SG|9y1+g+$GST;K);T5>WoWDcw?S> zbZAW6D!3Ol%3TW%MZ5nPVoc<7EWf=rOjH&!ZlfzXTU`c%KP` zmxf5}`_4WE8~H76Nsl9~YN_SR9=sV9>O9YHJ>uQ#JqMIw^TS9N)tyecqodmC9tep84A$v+to7l$2cDA?G(7MTbgP_-gd5f+r+Fw`t1eB!Q*8W%79WV zMm?7IDANM3fZ6Y%CG9kVF-v!{!*)FE*E!-qV^~x{4TD94Wh?~+ZxvzX*?3R`_z+!# zA6UW-@kKOvMO{zYZYPz*b)e-QGy6@}X}+sba-KZ1zS}%}3Q_emtYy6SXz9Y67Swe~ zI3E3K2r;)mPTm}X5?ZnkHJ!jZ7-WVC^xrWk zxOm^X^Zoe}<7`$C71ea~Ql5j6(7Coq<(C(`nv$(}HIioT5o=3ytCCHT>T4W-`8nB>$F{Sz=oRh8awx9=_qYoQU3-W|s~4(`y{vOl^N`xXf3Hs$fdhN3-!8=-toDUHB%^8gr8(<9sdl-!XUP zczKnVqzG39wAOHPTg+#x&)#1CV1HN7r(;Rf{26T!2hP4|L8Y&80_^KJQV-4u=eS87 zY*K^2ChN1}WvnqKpUhz~;YB~Nx*WN^b=0&Si1)uB?d!p5TReRcq4v6oS~OZJ(n#6D03f$o}kS^q0~W&>d&HbR?gVizbhuY;E{Z zAimgT$nYf0Bm=y9Shf1zZu{}rg&H#t{Zp3B{U6Hm{wTt(BOd4$@o`wq z!`-b@tDdjcjO{FMFBRE~%vR)|e<&ocO1G!1+d!R+rEK-H@C)*8OC@v7_tw&KTokO? zv@2Q^lt_71!{W`!s_m$@@>>9jHfF@pOvo_fs)1&;d|hMaNNIo~$F~iyhdad^+n%Fq z<7S}Z%Z)W>(P3soG=FIUz+D&Kz-SVBqAxHwoi8u|5Vaozlf$ZPKinE{)daF-xh>qC zA_(@)i$XsjOzS6bDY%<1NjbQ{S+G)uLYY|F5>5138(b#*1}cLCS*g%Kwgz;;#o!fh ztB1!^8`jAeXOWO{-`sPYOA}8`PW9z(3e;D(c)w#GJgGp@^}joE%8HgynAh)9NxOC; zRszQ65Gx+f4KvVU{C3l6%UN({Ic0kr0()cn~q zau3PVDO#CD%wt)-AP`cM$}P|7;c-3HFv1E;8fZ6XoUKYbRMMT)pXRDZ`9#y@xlv?7 zn>YMCo|?6nNqEC92c=Z>I#I;JYDe@4eYP@N=E~U=;4Q4SV2rzgx_(6;$U|5J#9MQ+ zfJC){cL{2k?8tu3nNX$@$g~feV={w60eG9Gw69|Gd8yg?8Z5~;%B0r8yRPQzesUvd zcO)@APNBI$dEf3<4!V58`9p03+{z9Cdp^oGZeD1gEi=@lE?+zBH104FMXYvFb);7S*n;DCPTxvB5+!+ z_SB`v-c8Pe+i5}R+vKZTb^`H2NT*#`+`_i~slN#9|X^yo5PymY;gHLo03{M&~s<7PdrKZuu+u4c(SqXr?C|#_1 zvRn;_w4CzG!<{0tgTxC4IGI|MH}ZXro%2|)LN8sTRCP^1nrXt@Dq(No)jR3R`sUHS z2yk~|n`ser`&oV7bHAG6sEvp!{;`ii>+*wKCG%RqE7k!(js*`D~mv?`N5K9e4Jn|Y(KfOR{-NUREQ*E!?==Iy$o|Qx!J_VE)CIyH=YklSj+66syAkm7D^#v zX4MO>n&IGAjt14(7j{9m@<*M6bGl`j0ggCAnu+@Ms6~|s+ap;=Xn2}LufkYA@xq{a z=db{6oLs%fv-FE;Am7b|=^PS<3sb6i<3^~RO&#`j&{38hUpaOlVP=AL680I$rXKBR zxtjsR+gv|u2Z3uZUIJL1=GJZI5UPg&T4|Js{92_*U03aXo|SPC-mn*n4AU5Ot4K=r&1pA+}TAVY&vb1hU!| zcit5+gsCB$(kWXrb^=TQj-fq!kL?x#fT1v}xva)srK$``q1qYJLL*v2o{fX!`a+|T z?;)^JLi11-R0rch+W8@}VD8(#-;X`&+Q-hjh2AG-cuPGAY&KGPllD6aL8wht2$&dH z&0+urt*u)cHwK30n{smCnrdt3a{hJD`x#9(eV={2^HYG6JGeFAA~y)BQ*O!>vMWd* z54xRosE*jKtg)n%{rw^+sA`95@56M^)P9|B*e=g54xtAou1o+h;fN#9 z>q$XHG2h=nh6-V)5?2Kc9IrErntAUv-NW$fmU$as9PPhUffZz*bVc+jDz0OQ>+BR;OvVaN42uY&DhT0 zcl6Sno((2XRaM#*f%}}I)&co& zaXe?A_Z$E#&o8(WgtD**dm@pThmq1c5*~~O+JSd+Fqz5j z?zbW$7XCZP9tSJnCuD$$1KI`JIQ@YG|Nf|Xp-YVK%B4{R(tLptR;Z~SmC*~}R5=cP zPii`R9Hupwz7{WUq_J`U{l-Z41K5v21fmDW+U{`GQ3`nFhW;h*z9TEWd9nhW(u!_& zXuZ3pmxuDGe_i8>2KP^~PMrzXN%E--%-(S(ItOmN{I~s%28hLXbWKa zSHh>Za!e&j=<@;hwMFq17igvA}EV9&-_NjO@ zMbZlSI_(CJt^>9aOjO;b(VMmNiOrVqD1CQlW2pyaJn~lhDG;=gV8CucNyVfcRgBeS z3C66*3HnjiW5ZQFO~wG|17hp-hzekOn-g0)=HkX;PUTpJ9L$QqIw*Emk%~%z2lhoP zraYQzM!nCTM`jAwAsB11FPu=Aa-5yxB9LnzESweXnR`ytVA{_{R&MV3{ROp{&qw!K zRMia6dG*nL;f0F3QFZc*%k`U;zc0w_O;pdJ1441BM8Rd(TEi;NVWgH-fd$Sh(b3Vy z2cx~(g>CdPLk?T0>^23Jxn}s_#|;Cg8u}KD0$MuGt%^o5`Hd|!{-|Q=OmZuQtKmad zAW{jZz1pS?^-s;9Ii}o5kt+MASi8u|k^`#YsfQJ9k$=VjW|Pg&Utetg!tNnSfPk_? zIm+XLFNiXW6@_IS((df1@p~-jmB58zoiwxK^sH=Do1> z(;*-^JOKJQKAY}K?f~pXmr^*nD(U2H5>m{VD#WaVD7nfZ{p3||O4Znow`Y17t;4G@ zG?mtkLTChb#jJ?=g*K=dXWux-)W_O+LI+&aT9kN zhUV@8d?1$y?z^}P_JFp)d__W?lYVBS89eX2zh`LN=p5=K4$YA`V3({bdwUf;wqWE! z**aQkR{Inkw8Qaw&EV>qn!+{XtQXc@m#&g6PL-L~3kv9@C9KGL_Yknh&uV&$Ta1i@E6=E|YY{(CE>s@w|ABar ze6rv_TygiMK#@!H4MCNJ>}9!~6-Dck`}f=$GiS}n^o&z)-jgXh+{o=QoS(_ecAx!p zKe27q2UN_EE)#$*grF^N<+X``(2h%_534rH_fEOvEZ({*m=_I@nnu6uh&3D|2%#Lq z(o=*faG}26mj$s$)WL|e7DekT?Y-C9`lhDua6WPw-*5C>*^61Jn5Z;0k(E`k{#dNa z5GLJ;JwdOOw*#d)f06Xp@&L+7N}`^L{Cu#I|M_5^2`)p}Ne^`T{PJ8(buIZ!_{KuQ zqkE)!eS@&(m)cmxXp11ya5iZuz)~Yo&;gSoEdx}AhevC3D9*kTs`#J<80;9^?;JH+ zIO{Wg-0N)ti4wR;)vf|6CT3q=3+Dpr`64MnBK~C0=h!6F0m_LrzUR4Y&6*XZG7;&u ze2DkIT;ezCqlQsc_4!(2c3-9j>Hu%Z2OtsJG8@74k*~1tsE=>gE&Tl9tS<};#`UW! zr(t$@H|QP0Zx^r`QqzD&ro)PtPWfjD4seYSdQv4SEySMrY#Xx62`Wkh(>iRw$L{Wi za&BbVhvU1xe=UhRXn-~fgg40N0r59?m4xLrYpA|pu4=+vE57n#3?%xXgJWh0_?r|v0|iwZ{gQ)MCw(P! z7hjhU)_SiO*?z&G71Ni>`?3WfNqVcZ0{d2=FjkPNK7uVCI8tmZH|*YCH>qgfK`!?G zCOlqcQ-O^5e$=!V2mmUNV2Zbye&r1{Cj{jEdQS3n)0sPGf~BBG27XPXml4(t)%Mnd zlj|{IiH~*U0v3x6I7pb9mU+~Q>_YGOW{kpRT2aJZLz5p92z75CGTNZ_z$p$A1%OM%YvdWjLHNKThWy?OW>uSN844x09Q6$g4TMD}R4{Rw zcW^1&Y}T{i;wwEy%`x(}ZRV=DfkSA9e^#BG?SuxNv&VZbkfJpbR_(P72nkAV_~S}j zcxW9%D{bQ|QEwAoE%dwu*QrQuvEZvrw)=c)pk*950gVLxbO1fQ^}$5zY>Iq-wwU+I zl#qCfxs%}MTA(N+5Zllh;TvTNqF#;$h@GTJJ6~21aYafQTy{9Mqbr{O`o>B|m8#9P zjZHLksKnL+Vd>TzqzCH!LZ5I*2uqec@s8e?L*mpa_w{dl^?)RZf>(nd z5L{L6bPBJjA+H{0J;iDP)sBYuaWhIkf(t=V+-;{-w-@XjPMIOj9>Dl?2<(GM;;wg= zz{g^#Dd5ZsAotuAe;%!)%K^bwY*C zi+s6!=Cf?b7|vG&yKjUQI5m0UYu-t$Bpa3- zftivL+WO~!y3!heVAfs8Dm+yw3@a%5Zn<5dH(B*@>SGXiq50}(h!$||KnRdn6#>t6 z6QmzZ&yHjpmUk40LL!OM&>`D+Rh&@|oRz>pD@2 zi!V-eM%hvh>P3sR7hk+M6r(P^xHU)I`_h3v3GTZGr>sJLZZ!Hbpcgig@#i(dCZ@PXiAWT6X_f4`)V@<#qa>2ZnD5pfzj?l$&HHM~cp{ zg9HEuo<%$-@yc@=^^xu}HGn7IQ+P@x#9OxkdU=o2=+AdRwR6XH?&oWpVK|u(S^v$L z;^!9lkFgByyMSozzwPrMzyAA&|Ep!u>sm8wdnQ9x{px!SUJv~n5xy`*i(&-7Rd z3ZGs_4{0v%r;?LDX^oHc0IhK&ox$g2YrqAg7E;PV(`rML+2!ofvQ>MKoYRUl?6!w) z!J4mNEzxzc8_MDwiSZCq7BO$(5r>>s-@g6sc2RfP#6II6&+;#O_ivZ@shhk4Qe2sw zIyyw@5+z}h5oR^{h-LUjYL42Hz$tKg3`d7^r|{uQ{eV9G1(J)CoQIRdvZGfuxw)Zj(U>s&6$&=FPdwT}eVIsdpNwwkDc zCL%O)V+8LX7j0pK7W3@R$X5q~3yw!Fu;>d!jGQ(O2k%R!xa#NKqKWl929uU-w_9W! z*g&FF-o}w;b$n0@HPO+#gl@y>w8TDASt?weSCsL=HQI~^LW@k+dl`oF`9Y-`h1P-Y zTL)T>BF(r@ce;udr<;Vu0*3D!x8Mu+HqBs5ne%93*8zhu&RG(dr%n(cX-~h!v=@fD z`5jDqNF4;2J#j)_6%fT%Miv-85nWSIz)sg_0O!&aPPf(#blWiCE*%iBMY? z$eoq!@wnvU7GW+C1z}Mp&1(`5a%#wDB=w?9?zjmtyyv|67?0W1HXilwWiPYpM{Brm zx0~7TYeM!mQaxfX+x%{S;0eJu=C-7kk5JTQ==WUOe|F_;FkDndcqAe}A-4XM=G6dg zZ3`q6VnWru9WA?Yl%=kcpTpV6_V#KK=| z>3BGA@V=an7_sHkU=6Zgcap(R4z{a=EGV@3_>Z&LbmH_j4@JUTL$BP}&W`{al!7;9qT&*r zHNulSY@Acs!5~wg-beOe$uv2V+F5n`yShGesT_tjan$#x%h>Gz0$&Rxm#-CV04Wm`C}SrTAh?9V@@rYKZmfvpUj~`Ya4>)S9nnj;`!%s~0%m#oKae zU-oKekI^ZdrfKwIzhThLB_b^xmugene;A08*z0}PAam<>P{8NM$WaP`HA92BLx$5e%tfK9V>$P>voFe$x~G}qqPlv)chKy9=V?2*;)zApm4YD> za_NI&orT?A=X}W4o-oLiO$OdqC{9r?P1!*~D&!iyqI0P0nC0+?K@A75z2s@#Y6<6S z1Y_Vk_`I9!ma80_;8K{d*P?N z&GvdF1|xb>=F!=CjEG2~k3REWdhwH;)ftg?=Cm)UgI6&{{m*}GF|~()#i*Cus*ETI z)ON0z$L(%ry=@jG2e`Z>=e!YAi7jZ&B1-hR-FY6PQjv&6$Fjq z%SAO-=x8I1Jbs|u@4fxryYXV3j%W$o{NzYE9F&o;5taMaA&+&mBFcriYRCOa%eU>u z(pRTZajBHXD;+~qbR zIT)IHF#bwBPi(h_8qCnc0E_GS?t%(G-5Q{Em4y01Uj(_GU+@}A{QWenQ-9Loq0D@0 zRqXYb8I0);a64$s@&^#%@y>dQiOic`(n2h+q)`GSC+hO_o30|*vm1) ziZ+=oMY0#t=Y;rOf!+yQMldYC>_T#9DSikEC*Voj2@zn4s?+@}eMEq4H#wYMyPd@} zfcLS8GfowKpfdakf-w>@TKsyHN#?4&c@YGk6UMRryej>pa`OPJx)iCf+P)uu^FOZz zQ`3VKEziHk+~>|CXYM^}QB0BdM@V>>($WTtQcYJ(Jm~QJZvF{I9+x5yKa_9KH>Ip_ zlPFWY`f~>T&w@$;pb3}7qhg-}liUL2Zj7JXN1D=;T+jVY_TG&Is-RUl4e-;yDa!uX z3AJf3kjPp<*MCJD{hLhoR|V8fKIwcyKbw&H_gz5d3!xAJq=&5*poG6G3IBLH@?>kW zsMz?Qm2&@iO^KWtXzFG}K|QL!Kz;sQ{!RlDo}Dz?t_T0V@{1JB9YO=lp{+3oFZ`;d zKQlg}QTvw`;Lqg*ubvFk_g7i-{f#I5;b_sVK!3)tOVhgXH(~CN-L(1u?Qa0ixbosJ zmiq5KtIeFGg9A#-y?=W8j4W^`a`U<|_22l(AA90;1-em+Bl2?pe|q{F2cWT;h9wkJ z{Jf9+KNi1O2XvI=L1ab>|Mc|#x$6HnuKNFW&(CTzQHnkf8vC2Av4!KYz$665@$g@` zlv#rCyX!xO@?LKEuWoU2CyU#>bxt!;*)#PK&`g&!lysgDw0LvS>p1$A#*1(ia_M@s z#YBz6_Yu7N&A;=JnLwaxnAR~XeWN5tU*|1vWM1->`;#oJd80`8C?3Z{8w|*Rh35qN zVoL$u`_(+zBXjH|We=a$l0MpWkVVw6STtY?e+3mU%;2{l$_{GTc2?}V@YX=a$BvVO zuK#ZXk1243VAtr^+(Kl12%U-~y0B9Bm3=Oook>11=dVGGRrXpEt1lVyuh0h1rMv>& zF3nI{?hV4Dh1ZG1sI;ym%3r%Q7XuJcDyX{M>0fAC9(`gI`@PrN__#%Smd>j>m{X!S z;~d+~M>`z1uLB%6AD|;~IZ~|kD)ylH-liJa6Foa;1I$WfWt#0c8RwYcRW|gKV{2+> zC&~SWQ7tEWs7`?8<+Z;U)D1X0;3(eW&L>F`cE3p_0^PH z_s%cGL`TybH!s4~-`%dzFW9QAwqMWN-P?nCVrOR9#H>G4?5*buyDxMbbVXlo))yZ^ z(@uZ5c6j<+TzpXrt<>@Bt~OvAgk6Mq3%10*_XK-d+WGFjr@da!2_ps7bX=MzBNmo( zptM)`ldVu`vZ8m!tGZ19^;?MQhH=O3cU$AvE$YD{Ecv?a1-8VR3pJZazwMOQtg;43 zOu4ah()K(mLv^Co`TBD%A#Pv)!EOb3>LaJ&aB)qxSHY4yZ({*zj?6HsI;{6@LP5HkGK4U-_--K{S zx1NXvy{0itT1)DdmZw<`M{Y?20Jvt_jnBI7bio*}B^!>>Ec*bVFX#P&NA{TdTcD|Wyi0-e z(}lu#imz532;^1*2z?0-7npJ>cRPX>k<|fL9X&ok%+i zbk}V>%xUI4^``Kf$-DrXu7D?|V=|u7nN271^1pK#%t7X8B&wi;Y6lz8Tk37aB>TZd zVSq4Ht80!0qzS@%8;h}oJcHd6hW=5N$VQ<(pi03HY)V{8zp>~cWHj31=xVl(a39Ll zvQmG0H6}+bMlR&gy3+L5F{SCGK;TdqKN(RnM#B=aUL^JI`1$-W!1@|6|jD6tNRO768}0E~LCMUyU5 zAIs{Xmm)z?|77GifaF=5);0_p+net*35<){54a}8q=i7bQ?%aes}kBp~=pTm%y>D(<2I(z9oXGVUJHWeS*dzU44=|A`jIHE9oPkNOU1%Q2rBJdn4CS(}=< z)B9FtImCf)^BqiM!EtlC$=Ir7W@o-YTo;%GV-as^G2koyNXW|wim%`~{mfhu0Q9d} z?9s9)>{{V}YnBQK(_q%D{N(U=pXgDx0E)kT?{_a-PhA77d(e_Qd@uAX4KV+;z^YY3 zf2+kleA$$&_zu3aLa&&9m3mlvx863RT2K-DrW~N_Y=8k^rNJ9|ZJ%}XUTr9IGfMPA@BX^YzI#RVKr#^h5<4|El)Edd`01E7Gb8 zD>{!u;V**lHz8dBYFkoigO?n4+SwXuHgg1**){Uw^&aoMBPOVN`3*<=9Nz;%-}~A6PFy>@Gm~uawB>KxR5qlI6x{wT9&*e{I=24&UwN>k3+8m| z1O&d{OPTf2UHM+ovnrdu>+*f+ZIDOBEoa_CKYMNYmu1*rPW$|+QXn_{Kq=AIw zVm~}YWFlNvX;AWv`v^1N-y}hFbjZgLC8-2{T1Rz&T7hwUuF?Y?m>Ke-voM(E`+XtJ z#vjxd)9}t>WUwe7g&J~es9_0w?THxts_f1NqOtxsU^DGCr&OPV?8uh?U4cA%>693h)r}RV>c^rqa)cNpm=>CFn7amEPn%# z;ybT^OODVD8KP7HcF(^(F3Ts0ikemrO+<_hW?}a3QnYfmB(T5ur7e_lfHFSjq8o@D z$v4vn@*Rk-&?P*#<-H0A*E@Y0LQzFsfEFFxDJ!k9dkhSd1c5O}3WwI})V)b}=-6eh z1nkqrN(!@{m}wxPCyL46C`GcANBtl!$ze<%T+Z@{vfSMEDfMOBz-G0H8Yer0nXqTi zj0~!4H7T7|SmT{=Lm*#(d+j@FXDlX-lTc)Po-=3c51v5n9}>Or?>bA1LflGC?|@0m z08lin3AZjeZN9sG+p)zIT6RF5&y>DT-rM|Mg<4=9vFfRD;{{0&`r&#+ zrbUC0$$@&oJy__l*o4KOkYj2rYXx4?%|tbjs~6VS7lP(~Pblk2_o zoBvL&o_wXAv0L(kp;mX2(wOt@9aOXPr#=K;%IKrh!YfgYR4{GZ^Xdy`K0u*c>AxVu z;G0e#6ci-XtS1qNzB}B zCz|hfPE93V;MYe>D7+O-Y#KqlVPwU-J}U+Wao-_y%4+h^HxAM`p?rW+!r4NP)(4pW zyM}Kebxo`q7KL+3U3Twz;*!)VW%3=y6)0weF2-0Q3QHF*72*TCARI?MWkE*xuM%%X zj5TGdp-u?4TAJXVgrdikpS>ImUb-mWojm{Ra%~+Lt-5Wl$mvXXf+CxqG&ZjYL^ki^ zC%7uRD)xFF)&E2b{`)k|(42I_YnO~qk)PqUJLz=~ca7zK{jAxOPU14q%Z5+^;K(jn zQ1Im6bg|}_fac%|f8sAb5%3=#^i3DogUEI=+pjx~Kkr`40^l3woAsA|y~sb?fBHmV zZ*B#s$$x?af`gd>G@|)MSML95(tq)wEGEpNJ&Wv;X)$UuXbcSNGM{`5(8`8Uegd^Uw3TKYikV z`nZxQu%(V%1&?2XSO32I|A#KhO`zBpk>?31xTw*{Jlp|DP4bhEr33V2`sFTHK`7NH z<^zfL33ZLj#TlYqC{kHZqF0qNp5GrU0J-|^r{hQ`uQS^61d&_Lww47JMq%|uAYdVE$v&I-+OGfz>CMf@W?s%x@F zS~(*?85n0RuR=`=+{@WqjuXq*qEnB*PH1WpK*j(3SezWrH6U`0c?d-+w+c|Gl*)<* z=DqL)XdkgUXK+{iM@3IF*~oA;RJ}m1Zj3&^n$|VoOG{mYn^FrM&7%w0S1e}e=_eCz z0JD54>+$N>#qlqqn&`zd!5xy_Ptus#-Br;^(uqfb_ruUVSI*n2v%1KwrpVS?eIk6W zFg0Z}+*Dx>T*xrAUiM)weki5>4Q`lRzZZM3S|-Gwv=euewkpirZ>F%y{X}SBgl{Py z!#3Td4Nfc50I_2QdSSnGeI)QT(PbK)7zyr~%+@z1J_~Q$Q~`q5*m~V1kqTi4;fB?do4W3yJSbX)WN_yWHHBUk z(J5Z%u;}J4W7M{n4d*#`{n$v5LB#xR55U#I^lnaOnw}m6xf9SD7yUOQ-wM6eg~%r= z-178xCM%g;x>D7?5M&yom*}jXGXHYnz8=S9latIIevB68NVo;*$(8pbNb7Xa4{P+C9jwHo=&*lIs(AZ}`kYH?jP`@n zxlc90bV!(Cina`s^Gj4RqDAkrRSrs^LF8TdFJrEf|3x4t>F9*Q@60IB*p00E57!vC zwJSzWMjr|F8sf0(d++yfJ6`DS zs_@#d(LC|VQJ+bS=htqE6 zj>vA$;A#hC*12U97iVs#-;CQ2Fw%!e>J^87R3Etd@>X$mukH;m(ezKp^eQ%1*xf`q zE-&<~4dQF~3&Zaeh21IGd0r&8Wp{o2BZGjKtg{xQ3TsE~-6VxIbGBkgtXr}}xg;b# zb*oAqhKndq4lv;s)B8r>{=VWVQC{HsZy~ue0RXvY*mL{2fBE-v4;~J)^jcqZxs`%w zWa37vd*t`$4IuGATMeovQ45 z@FrnmM}twxA)|H@@1Q?jq95WA>I$9VSX$h-%gN_m?zuJ_R*m%6-WZqdZ(^Hwv)_L7 z;LgJbYCKoodI#Et6e^dOMFP38&uJ(qiGW@GkDHyQ8DR3b6kHak1ru&4-MCfwwb1BF zg&zH|`;?fSW!~eC8KgmVe$Y5juZ`uos}w&>nMPH{AAPzSTySi(WUtChk|I_AG)!N- ztiK(o9)(kQRGSL^79p3UVCn7Pp*m*V$PZ!s~CHCe5cW z&Xg^^WiCihT6u6}QiQ*t{{Y4d_SINLJg|Is6w%#u3IsEgEn}8hpb?{R!S$+kD!|El z0{Qo9=LOyyc7qtRvdSE73Di>~ZO7Ss zMzPDRzMeJhO)$>wxkEo!zvP;mRYqaz#xOv%&v^+ar>$de7$|59A9`{&BgR1Li6&xFQ*H zM*&>GiyJsAnkJW?^T6dVATt4gLQ)C}%*(VvduLrb%X|8xJYUf+UdgJf49bW54+!>0 z=35_=#2V>{U(dIa{p`Z6TPKy@UreP0 z+eMAHN)WxjxaS`$1Vk^;U{$8dMQ!wAN9(wLWsJ7dX2c(v;Qu(u?7X zkj`S7tBE)KBq%%ZqYm2W?e}cHtX8o~hA*?_#M9=fq5ii#ZC0Z$O^`fTCJ?E?IY|HQ z(7Mwe(Xk`5Zrcx79%kjAygneAUCz874vj0M4_w?#Ue;o+4;fwYF^LM!%Y7)J*Tj!q zzdHuUE7cjzv;gF@;w(Ckq!N){WSW}l%U(+i>SV?P_w6)UnzjcShcw!Bn3akm2!OBbS>+_nX zYeAVC=#A2SspoHjDQQlgRSE=A{QOHv0xeA-YZ;Ze37AgE#f_zoMCdOq(}Q&rkztqh z(l$HcQ-yer*x=~-yZ!qg7dnneBr`9kx#N4hMbS^HJW{cbbSwsi^1s#b<`3O9fZBqx z2T{fN?QDQ_%=F$B7Bm6>)-KQNbho z%iJ{$pzXKV_~OD0VakS!4JJ+zAn(U4PqL1UyMI`->)WXz@3`OR)^&cPx0hA+I~|lX zIk9vJL#E@OO)=;7E#pS{H zxO~sg-EUHvm%DvFgh@fRQu3}dVDgOp-=x<2I`2F|XMoB%2bmUfn;D8TR z!^Ip8+plJu&x*n0HBc5lkkcH{*t4NVmYz0iW8LibZ|=WS1H^MMBEG@2{CoGS>{pE}wZ5(rx;2?RB5t_T5frXi}qE@~_oZDdQU$ zJaIpCF;a=0(rnlJAyFp3u3iXzz3Su(=I5{PeKvRg7Z(7|89?lEb?vjPUsda}w9205 zC0sEbd8C&rzPd%)CH-D?Ie*AhKvs0C#!(hi`4N|}=+tZSc#+kJEeU>sbO(NZr4Eo3 zdYgMSylCzCozPRDY{L7zNmUFRC$vmFLedZcF{|Dq^;|49_I$on_jD-PjEx!g<>^p> z5wlbA`8;gt(oXg`cRYk{Oen59&rPRf*ze1NVRc(UVMz3t(7r$mM73L{R#LB7VFh36 zvjNFFo|cj-l+sO3jf)-1dNs5|)i7@|eWZ9#uK1niBxEemzdKNzYVP9iTC+!ZN{j~Q z-Xvy2BKm#HGjAcI>9UgAACFFI8zRdMWUUKk4ItBLA*o5w<0>NhyJR!e*w;q~jWsIV8-AMsk~4|^sQ zE+YXlsck9nQj#xR&ujJWEQ9D{C=0vFk^i)=U`omc<`SCcN*TFSUlU7n8!Hg6dddrz zPgNd|So`P}h#oAD2r0|!cHhK*zVv=EYQOF}Je7b*c7Lf+w&s+r8A&V{sh3ErsK=)m z$nb13pu)ps%QB=Pktt6b8}(9gm+N&|1Yv%u5v5uKW@EU_MYv7@NQx@*Vid7InqcP8Q4Lm@OWpQ&l~4 z1%iEXsl;TO44!mHSs7WRJ;l1uJXtlaw)IfJFwvlZErcR%ewp+c3b+feAS`ow(vk5-Ovk&!@o8544?kk zP+KyCE*=(J?sz&;8V%fsgv&JdRB+j)rkYoaU2wLw-2Hrss9BV3^T{c%eK|#Mdtf$t zU?B(=`2}S#&QBMih4C1Wnypj_U6}Iu*=PLQi)hmVn^Db>%IX)6<=-Dt3RF4;tnDqO zZzv{bz$r z2lAl2sqtU>JPimpw&YmrAH(>S#|b(I$Rji`hxV`g)IAXHY5h-ZzXS{a?n3)O9;Z%T z`%lj8f4&{01_;-nQIPG(UoZSCKprCCcl`gQ&%c%JCjtGfY(H6mzm@GLaZrH&wroFH zoxd&HPvSWFzwJg7fNPuGW;#b^76Z(GSNJcUfdU-P^teAy569?%EJok0r*Pq2NfonF zd5@rX7iWI9BnPaM zb@ydnUfyk9mrU>k6G<~w=GsW5Gcw0&Meb)Y9okfsG)&4Cz~!X(Oifcm8t6|1()A;w z1+*f72AD0`{tG4n1>It1lXNmEhoIr`W8U4H3u9mzs)oKSjnF&M{I}voOj$gRrwRPq z%l`5gz>$Zsi}R0EIIu!S%D+?wr2%|;Rtls4GU*G!fMaKB-~H2kenJ;Yv;demuQWjQ z*FsR^1srzpM}?pK(VtL^s{b{&=f>{|% z2hrh$Mc{UUziRG0fJ@>*My!9WW`B$92O<6~vOjj?-&*#=#`%A_F-zEJ{5N+ds#X__ zrwS`E;V&5lTHdI8hW6{5N^9=8V&;Z3_a0t8a^tr@*6y&C0!VDfPo9mUJG0%yIMo-F zu3BszA2IDK%xHds=hQy+@v!9LS}A>V$aL`iBnilaa=Sj8w`r-E8yfviz0`Ti|Ix}Q zy`%yx>Cr*1AT=g7u_wAqr2VGMni>t_e5q_^R*ekL46FHx$P+lUYFh-?YPycciihMl zJCFa6;z)%vt1%S2NXX1&2tUC!(w6L8WIWwQ>jftJd#a6$vw?;N7Kg`cpSOb+F} zfqcPPTzz4{#45Hf70MvTf0TipMbZRnSx_-!PiWRbwbpMba-=hGywT$nW%t7&)R*@5 z$KL7X>uI7wFI~SsW`)Az-qe%o)qa!U|Ic&0bKos3 z2WW%ZS#C2|V8-&b!gv&UCD87fL+;V^R!#H+5fx=FaF4}-oe66HRiiVW-@fc@`QfV_ zj&oeSN+LzVTJ(*bSdh~A^^pvTdQ745;E+3Z!)iKK{{?UhSaYG*C=WHs0=3rHr^-TH-c04f1{ZWOC~}+>AkCEwIj7^h%Esc& zceF_33Vtxj8u#UxaAym5+{k&&c`sdSD^B2?%nxe(qhHCO1=ddEMZO(4G+ODHu4vu& zB(@~IMV2C_ucXaE+ve2{Va|9{;M6*K0$bYVBzp_PcLMOqHqFYz@LsF7@W{R8IvE7< z$xSnglp?03EZe?oD`lTt8{W3HTv6W&+ruLyifU#Cs`d~e*f~Cih#MzHWdppw-y!t2 zr8lFr6vf~}{@Cp*a<=Q#7h7xQdikj!zoKMeP!W20QkDGMI4TdOBfD5src!`dQ0tYZ zdusY0CK3n=io0|cEnK^F|udSGQJK8E&4^E2>G}p&~Sf7JqZ_ zBsjxP;m{QwM<#T??Daq;J3TSLh=AG@X3rI;hkR+C=H_~wYtx#0S){+rZ>b!uEN0o* z?2CrZeDRwClq|1uEZ&UdW#Tfa_ZnWTX^^L@Fc(-qHOF`2W6^&eA&U?&!cukTDN4lY z+vuy=E?$eyPHE{!Qi_b7$X25+Yh#4)F3Fb|Qx_Wu)k-BCBZ$u1F|J_9#%1>D_okmX zqw9Bc1?puY&xyYgNxUdhvotbfv0t(FYFtBd{H#dr+!8VEI+aV_cTb>^i7FSk%a|wd*is@USuhL(B{xaopLVRJ>pV6|cy^8d&o)EbDX0-s+Ae=$pAi7B z%#>it2QL6r6@01O?sP)B(nzb%;26WpgDtBjB*Js;+BL!e8sEA;--q3{+G}Rm9FxZ+ zNkeK)^!jBy$;*|Q>hax1+cFo-{O9|<7kXvwEA5y29p)2&2X$mUO_mU-$=BD%+&|#b zyoT*+iF>Ntdv5TJ_5PhWRPAyd^eze>N4g+;L~6`$9v>i$^3>XyuO3cBre}(+dc2$-6=_ zW4W5Gu$T`*Y_`f`6K%~uqqvLO(~Nwk$6fDYZal<>50vHoLV?;vv}s_rkEj^Nj8bRFi{yJf)Z($p||D}x=tt;wIxC4ql! zM|2~UENf@on@2tzNq;%3ieNQ%H$K06X{*cd?bw@Gacw@k0dTq|$0^Cp;#%tJJl-HV<3z%Vv%#K zRy2|P_3Br%=m-RY{2gB^2+LZhIs2ZF#B#6Jg`=A8L1 z0`9t_1R71z?=zvfdOc%BeeV00XzZH~(n*v&`MM)whu?LGfgz09R}}LiZgk`{l>*nc zkqN8`LckA>zcBSA>7VghI@Jq@7^B?Y11MfV=$-5zsM%xSc0 z2p`C|I+*6YZYD#?aegHgk4wkEFk_M`*_x^Eva(b_qZgDV56`*l9w5>)1{DOi8t;Za zLg$Ltl=0YLM5do}vZM>H0Xcy1Y*&-LhUg9Uz7DE8`IwuxB!Ld7ey>qo^#`iom!Z4s zav)7IpG(6h)#)zaANpm}3I;TRcm%d)?&}A2ZjgbVUWLg?@jr#=kHB5>AcYxZWm|T% z%J)w;I?oeC!-!|Q$=ff9;vQ?eA+ZGy;f6d@3eICpO<7^#dlEAIGS+&?c@9bFlclZQ zYo%&%D)&6FNXz;E39NPF0O5TcXnIT&bN4Jz2P9(F6~WZpPu$0gK~;~4U0IpeLH>id z!5Ipd$uko+;>wJ?hyB&1-<70~Ody;wEa_U@iIKkf=k-I=3s=X26O^0HRqJ?=IPxRX zQYzk{s`3q-5~|YSmMSr>$BRynyAT zqn#}sh8gW6g)^uc6xa@1=AdHAc4iP#JisMobs1W5#I7&TWAt@!rRhky!}@BBEGSLJ z%~#hNn=av|qOiH3uh*N`Tb9#F4eao05tUmR(tzqF_t_`W1*rg<$r&^~;Bzbov^jZL z!Du>#wTnR8t6FIm^B&R>?i$TDF!K?^%+S&X_?+8BrO5DGM~$H=%^?0pZ*iiBER zg_cipJsA9s>VA<(Xo!NfrH7D3pWo%?x>h*S%)u2Oal{wGz3BBo1Zlfo{?fI9b8s5N zQ%ck)jBoQ2+UF=rac>-2vrP3<9O&liNp5=MgDHd0Q~lbg9F|g%De!E>{#raxflP1t zon2?OFw+ZHZMIag-r8FOe)x!@gxr7jpdt$3QQ-n8m{}009Q6bnbv{22GV5gNbfNtb zw*qkQ4NVLmNb~KSva?A#by|q6@d?&MSw=NwwmgHM$X6`*t)svZh}Or|@k(nz4o5Q5<0>6EoaKT($iKg$vc)`Y$8Qw2 zb?u(swMAAm2dl`xxB%tB^`2wco`eJJx8Kz@6>m$bf+y~Ad&?Eo61s`A4n*za-oRF4jr6#p2EN65AWrRcMyq;{!7y=6 zd8gNHhIv4SwX?q;!s1iM@dAjMnSRzg00Pah0OIji(P!UNflm`!hv8pl3lX-6{U_;? z&aXtv3Nz>^969X7j!bBjy_#^-NApovIX0wY=L@F1a~*4^jRzD9B-}OdAC#o1n&#Ee zTG?XnEjC|=Yb6MSG-I1`pH{ilUtWFYdt@SUn4Z;E+4)$#PT)TJ+Sbc{nM<*X16w%b zvK60ia*A=YHWJB?R5Uzj1C!PCYbj~2ssLVrO?d0{V-;`0KHYgyoj!@NOqMRrj=RJJ$pEK#M%#o_M%niZfL49rp{;Q61JJZHSpiybM zK!$Wcf_jY(?uIhXumFmc$TCQjS3CTMhzY=lawaYXdt1yQGX;}T#UDX35N6Y=h)(c? zGVonl^sY~+Q-1eGuey~PZ@!^Zo;qk$_v6TUr3^6uI{sr9il4rq0`ga9NgLm4Q^f}P z6^C!)Mub0V@`A?gJBr&-ntOTgwu3^_UU52C3pgW7sMfQOC`MwnWQ6$dCa`sEJmB{g zMLO1PrdL|Ef6FbMT?U?eYa?DpB2R(_bq(6S+4VilO&iOE?s*bIfcvBr$*yEAAa2qu z9hY%vt;Iu`_*5cZ^&1#V7uBt&+#3Jt`&yZ$G)SnZ>Rh)XnOL>bNQaHOaU!v>0_}{H z*ObMTZx5paSOijB8n18t1~Pjr!*KeLTj?^)_(ri}`pi5+_UOJF;+>+oN9E8Jx|`-_ zHtwZt^;+%J#}`AD%%uHvSaQbGsq*FpDI3V0aC3#(Ox3kPCzE0=ME#RV!4wKPB*@zm z9;k4UE)ZD{oKbpfS={Dvgq*}M{Vmq(B`)5?4epa&nAR7ElFyTE>0jhN%>~ek`mSA+ z72V!h+A#Gk7<`{DN8u8^YM%lMI(iIng*4L=;4X~}Hj0&dZK-M0d9$fd`+B)~*0Efp zv&LI_xrrNe22cY4HK%*5H<)9`h8} zhmN%yETQ`!w{U35Neo91mtZuCXndq^pL|2%0^JT z9V7(_@ozSkY>T>Rwc0+$G%-*g;k_4k5Uk+*__8%#G<__5oBhakDXYxQ&-&A{ESB2V zqp_^$I>S)@z`;b^bvn_N%KS9yisuw1nkBx@mE5 zdqVmY2HLwhH1|&=Y+IYr?~@VmIo07Vyp<5hDT}NMc|ge`en8!WTRd0KFa(EkfEd_! zZ=LZsL`r=y#|(MQ;ug6E&}67+fd4|VjUWCswbQE;MpRBv11s=^0#qvkrNDDVD}t_j z-_9QzP456$LHJ*{W7X`5 zby@krNQ|}Z0>E$uW#jQ&t7>vGOW|x{9{!|pSD~eon672WV^9iskoq}MmXwl8pK^UJ z=~9C!pDf*WgIRLhZfaZy`b=tY8FihjX+1U_xJARg&(dhf6jNcz!f#&EI=*9^ewTyW z>x8fL_!-&Dty<}CoP)+>(VISNMfuHU>afB)ir2ss{L}qX6kvKLz>%M9hfpRZH@rLA zu%)Wblly*MAYZNC>^qY1p9>-=xOo%;{J-Lb1?@D{usqMCLF$Zeh$S~n9x zlzseF1tI~*=LOXFz4ejC$;1@9LpUBB{qj3+0|+0&STdWAzrTg zXPB-}TqQl!C9#~LYzSQxXskM{vRO_FQ zQ2U(>RpkM7oa=pZUQt%^R_%d`nE@{A{_a(FoN#voug#62AyMm;?s zDA3DSshG3@Q?iI2L?0DqD(V@J!J(%?iW}?Z*moU8;b^D2tG>du?!B$w5x!uA z&5(ju-ow_ut%DLKqMMjmzuph(+3&gvt0jH|ITZ;xm>oib4et)H(k*8~fahF{7~#HW z>#91R;;YJ5r~>B8d$%ZLX>%SS+$q2H>owCP$04}j{>X5-s2&y1*9ezsDt7JfW(}SgHtPz zn7ajBO;}IvHFOQ0E>lAn_c~4jewl?taT$6jv5{eR@MV=><~4x9R88?)DOocDMbU7x zwnMX3q5?u>A#c|Q6ForA%%xYOx&`=yF;Nwyqz+7}@>{IvavfDe%f>g3LnH5z1Cl3Q zR$R#)mw=zv=ewRMH31ulzVeAckj;5u7Wy4V@Gmrh9V*3EhsXOA_#ktgl(5TVU_w=M zS))_HAB0JKpo|ZIBQ#!UXZ0EfPfYpRhabw|J>~{PFjE@QWz7Qo{P<=@IpaVm&yB02 zmC8=vrdWx&sB>;VvVnGAGg34p@&($7bYp$4x8A6$?@^Mb#Sp8xN_tad=<-;6m=KJd zd=U13`}XZ7ppbn4dGpXP0~;Qm)s_S)>^9Xt-2O&zMITkY38V=_Kh4pXO4A-sz9Mm; z=%nFVn~Ed$h^3U0rLyk7O+>H@MUbx58oYz;bV`S_l}pPh6D3Tv4F(}J{-fucX8no4IGZ^QhA zi2K6Kmi}TsjwX`p!QQZ`5;jTb6+ZC!Q~yjI-#t_PEv~mdONX1pk_V$|IBx__J$WG+ zFtCp6GW^g#-7w^E1c9vKlY{$*rWGEf$1;<;_0TdduuiqE1hdv$yN)wEU z0rKErkktNELih2DDV%QteAYuVBaa`Jhee#y*hwiWWUwd|s{-$b)3;&y>aeo>z1ZDN z$-4W6fdMozS^xna!*gEWo;{+$1A;KQhLeAr)=LS9w4{uT?sR7#YkC5b$tNAHB{dX<)=aC%({(m?2 zqd@+a*^kQdx1RmrUjDaLgGC0ErU3Q5n7Sxp!F*Ur{1|IS`tY7wVPrHZ|TlPYUgi=76N=rGpW<991iNyLNN0|H~}y z4;gO@I_{57fTRfhW9&6)rtfGEmoyH8Fv4z9t_OPg4{RU9= zPQSM~RF66&7i}j1WL6s}kq`BEXa*PF0Iu(LRMMYn4L_UPY5=QEn^Ell^<*+`1Gwy* zvikRembFznkSM$aft`ps`WxhL|ziFXiE0q zsqmiCLj5Dd-J}{82IN>&<3&>684nhfuBz2r6<#w4ErgF=)t{?3aWgsRb~p)iVC^#+ zsetf|8AyCX720Rh{6uOz7WF6jB;xS?O{3 zo@bjcGb5y2l$%x+eraG|2?B&2bJ+ey-B`H9$ZZ-EUCZ!OXSLITdvIo-f`Y0ki|Ps8 zRr}r4EEmc$Kve)u(%wFAEpJS^Soc%1pwFV2+tG$xd++sxQa5?OofhP)2rk*yQ*FdY z@U6TDl@SrCGR^N_MjuoXD)6*{tW_~ihn&ej+*`(HaPUecj7%aB*HEgvJ}CLEuvh~# zBN~%O4qd0tUakd(BLEC%m{NiGSP9@PUVNPwNM~^DA2T{kfE6|lC1=k04N(w2g&diBmG4{x-E7$3dcjvV=wNRH z5ter!iYLq%aG)4CZGjZe<^CUa{z@YSrFD2D;QLXc9P|FxudTvK>45u z@Zi%$^@)r*1``K4v=Htc9h_fbS>6a|5#sWIAvCsnSu3_aRmSsi$@e?iBtf&CEzXLq z^so4wA%{p)dstc-SgO8snkBh;XO?(%q})#2Sg{hbVPWFe#8pweFNc2R8}F!Y|7+yc ze(`egO66sKUKeQtRSe~W=fG&J3(Aa6KQ3wD4cQ7M9XUEMj%@NYZk4v}LiDc^Is6uJ zUfA61^hh#dE#Nr&l}r4ZDNKE{t`RPI?Kr<}1KYK3_5<7|xLmW*K37lt=;o0q=%)pc z8q4a_@?IJMwU2@!ziLD4Smu9ZD|PFaezjQwl`c}UFp*eV&r*uC*v~yv>Nv=4jaEpy zfj5pV)$H+#d5&(6Y~5Ev_u!(7>vrR+W+Nl78hRq}coqR}FK^sFpqll*!dzQpt{(L` zjdTV1gLU%PNmNhtAKB|RfitJ%{oI{bszz`BWJLdox`JAdUA;;aE*GM7Dk#|l z61O>kc;4P$=IgmmIdeQPQf8__YCVH0J$7xV+>0y16;3CJ`! zjQgthW1Rfn^8VPI7x7euB8nXZgEVU26zkX8#WQ zcojVsn%Z9?L~X~Q*5}AzQgB0y87=PA*(e~Tr$9|f)5(8%i=_wC3Dmc&gVb2fo_NTu z4y8NbjorfarWS-mUL-9nj0|eZ?Gzl?QU{osHmGhmi?iiCYg$DE!uFBzUDznOk8S0P zEnz2vmoNasgu@WT5l571z!&LKg36+BiLm5PsPbPZF{2c0n-2AqTkpBy+96!otilQT zmeZy~Gn%cHKIDdy=c~X13*7JyNE5Q^^{i1QB{tlOm)z6x`4<BjT^&8G_!Z#M%BY~y#{OY5QoR7LZ{)Wz;;Mye zoTBFTm*e(ZO=R01&dABleHm-8z~vXfQ|`_S;y2&7N4#9 z+>^wotqgqq*n{IYc(v~a)mS?31^{Tj!W?K)%^~!cy~hegJslqaj;jRp(?1Pvh^=)} zQL(rO_{Pw8vqoU%OWHZx8lUh0^M9=vfbO(GLf&1+4_B)GM-5w;ayUtFyFPv(leJn5 z+!H=kh-QFw{D1CS9JXJ#|YL)%sFK3=~6X+U=_Pxms%7$dn&4MKF z*m3}jD@S0?AA1)Ql=^6|@`C~vni2_9*{85sSI4}QbUN%fafSMh%(8_eDK^$3znXga z!Hpg2hSqMso#X{=UOd}#oQi`3q(~xlde2~OXtbYRggV5&z!zB><4$WY{^|mgKN26z zB7o;yp}HamrsM1B0ZQ4nws}NTwuz-gU0VO{6X1#9?`v$onw|B*xmya;c*^#(Kvwcd zjR@`43Z)x>HzzNd(uul!5dpqBxc1wxzWU)H4fwzWM%fOyZIQ@YGuo@UfOg&Sao}VH z#kU%X{%X=pszAE$jB4S@9Cu*$ABv+0rwnNTGQsr>;buOdFQqk_U-k9xO1K(8w-vcq z*-aCp0yM;7OW|UdvT^+vHbu!5*!wN6-;M!T7%1cK9%JVT3I--CN;z^}?i|RB=4#|0 zO8AHW(Ut&)H9Y5WH{(69yl8)2TSB<(5a{!441kxe%*KI zL8vnHL6X4258wn#I;R@p8yTmMOgQ1rc|NGnD?r}88F}JV;l~eb(qa!Aa$dj!B*e$r zt~fvtWxmY{i&u8?fs~)XzSh4hFS7%LS&0&*`~X zY9B$lJ)0TSzZPr$Xrcb;1}+r0oU#b2+N$ya+yvhIe`jO z+3Wd!xuBR?*ID$Nidt$FdhpmC(M;U$Gun0+_N=M->a1A0m14AfEMWZnFasI-I-Wo`Df`XGF z&S7>5u3Io#FLN|9jU`+DYWe0yUW9z6N3zUIH%5O8mh&LQ`WvCCommpgAZ9zn&^|Y< zEZk|RM09Esz5I$yoZVnkbn+*WSTI9!C-x_m@9F6=W81U<7Dc`IxIea#jWiuEX1!2O zOyfdSm@d_lw=(lQ7DqO_cXy--BM!y3$aUOloc%~^8A={Vctu2V%h$HiOPZx(Bp;jGZEpZ@nV|Vtr0~{SI_a$7vei7)D_%>-C@giVf^W{B0)!AaNh0%-rkAj?!-NXA$ z6wUP@Oo1b|QV}w%Rm6IL1I4Omba@*|Mnq%!D)E-3ZDyE!NEu)@oCihtHPX)H7r~$0 zO_q=co~5t=0{Q(NsOpxyhyvN)rN~yN^(xafecU=TdX1#*qcHaBF%t9vZ`l%3=5E?8X(aIi_9;sk+88@oBvwq zFi!3tG&$AZUq+p=h6elEv%E6*>)IfERVTj!P>4!)1Q#|+fx2bHp@=;@b+?R7-rjxP z#8-bM;OiZM=9&F;<+H9ynwu3FT z<*&|v%$sQR=w1_FTML}6q*@Oz?h1qX%gC-zv4PC}aN&fxrpUJbK{M`pKT$>W??t4h z4Z^mSmP$wj*HnsI_p6ElGd_Tbaz=|hFY4oBsG}1d5|6K2GjoLRWcBWn^Pu?Zy-3$K zoYySx_h8mkbF>XFa7W$#!l?Oo3Wu7b$G5NQw>OPX0w+5WI}Va#zNVM@%T!7GQM@J?(|c-G{gXe}CV=VbgE$#US$F6Hg#za3qm&M?{VmIHG(qjBb8Ux*Z*7{QZo8mgyzEa2xC&-*!e39@qW4O}8Y!o~J6cU;z zp%Je%B*vryJZJ3Ope_;83)|aEWy+@8_#o()wT_w{lz85zdMwEdcJt=asG^S zTP50SvpdgHtFtmw(?Euy3iDE6aD21u(uxM}#%t9xoYY+F&xQg*AP$(lY0>U3Q%?-G zHuMZgaV>s!sz??e9w5NQ<4{~b;Mm^;5UtY#b`z`cX?ttJHO3W5dY{trVtKl*FFF(> z1<5|j6f37fxT5ul%Z#$PI;&?S>W4_^iC1f)Qj+?{&{#PTV*6dk)c790VC<`3fSbKG zwbP#iLBj$d2Md;zAZkRjf<*OsD4v}!=>dRIaMs${pmt`!33_AGqNlc<;iyt>KQCXo z?d1YUk^mXDxqL(}&)xyMt;SIQEaU0fp_5d8_+Y^t_YbtUbwum=>Lryab@R@F?^AKU z3Z$Zn%?bp64ZWcE;C8(q&inbD+n;}ndURzCgNauC+<9@YQfq48-?k9CniErdPP;~d z-P|%s7c^@3iFerV(g+n-5??xHNK1MLyOA(xpdM0q7DN+}|46e>}@QEuVEckZO25y-6cE4|}@!-5GJ4O5C^Y5R#tEOI^ z`&#Q9NhcVi^_yvv6 z>X)|ZmZKXY(x3>jL1QVhl~MJovGn5+W6XU-%2lVY4c%?gAj2jrNPZ!tB=xOuHg#g& z=nkFju(RnU&_KF!D%L_A^L|7;XF=UbCuCd>OPjxY)2-{qX`yLYaV^<|vIRx5Sj9jb=<_*)&H`jkanqjT@v zeWwvvb{|ymHeH__Cjx~$wdmb{z4{(p<@#*q$=JhAzq@lof^3!>zF)_mo7z!s6Y-h5!AgNJw2MR_D6mA)Rxd$B%-MwUM{{j=!s z4Xp9}LeFI>DFoZl39Sc8cq#rX7S@fFQh6~!??k)v#46x#18y6)@~t@~0($lA@;@!E78_*AfCkz}d0>Wo zUKqc4p_2an=WP+}qSoyuLYZyHwfZ9ymmz3`sckh}_hPOw5?)x<@8CF0tX;=T8Xjf9 zISU1{3L83Z*6o|fcr2eCj1#e&VLJ~?U>OLeV?AA{FtG1tP`Imnlz}tq>}^kEVklJu z$D`TyM4ea3`@t=8&vf{a0%$lS-m-~$q~1%`YeA$Bll+^s+w|Qh0iFyKHiaMbQ!cxGLU^*6TNSjl z@6g3{&P5t{t4K8D+^kYV2W8zwkbY7^&h0PkUf1)+Q%u{<*+r<_jwXYoG$Ya?UUR9Q zn?~boAECdDo<4czNw0ihB~L`0GA6Z{X28uh79@2=P%SAjZ}4gGv7t@Wmv9(K`W(c3 z@obGj$qD+WsHApF(?01n8?{Zx$t#a1E*ov^N8bPZ`-f`|3POIHOU#9u{jW!kS!7=^ z$kz^KMLuY3yl&m+Z0y*O@>QYvOV?zHoweLzlk{q+U84W`=X_)rcF{Yf4{uHXo=f7o`nYOoyu$clm!EBCir`yb+ASEu z5LD;iB6(%DsXD80)sj}C&D6Liru?#SNpa1BnjhL~oJ~NHRMo1>-!@YJx+5Mr{dC?D zU1K^9^~zhivK1w+dcxXIw?DH#Rj+ch@>seu8l_(g+w(_?Jr0yY;=l=f-XiUjCSMB_-$=k5^3ifi-Cg z#ML3w#hJ>WB|j9E`1P|ua>gQ!j?!Pd0S&e|A8}1MFcXy;m++b9WoY=RXt0`vMHD^s z*^RP0+P4!-U*?o$cN+L_CwfyJ4N>!6eoBkrBH%4whDXE%HduU#le7}zQPq<(?@jq? z^oU9n3d5<6sG zN_<)kmoyXo&=Di?c2PC=MBs)|qLk$u$ML#bBndx|Lxn4exHC=K!^g664wNys9sl(U zMk@db+5%&!Y7?ZS20UPNk(M9>Hqvh3JTh_VbHbFc9|x!{L9K_S3w`?qZEc&@87rax z!`^#_HMwQ|!=Z~F1VJoxr3pw;q*p~mq$#}z1!Al86krs;dj;M4{DWM0X zLkOJ!f$-m)Gv~~l8JYR`Ue|j)UnCm5_rCXDef`#2W*3i{{2+e^Oy#yJ6-Ozsfil@Z z;g+<#%aKU%(1rFT$*OE3r>~<_ddE!y77zf_-RYhL!jEQjw@3=B$k74Ckx0f3>Aqlv zJZ2br0vK$*vo7v(jnjsKAOg@+!@jj($wh{Q9+9L4JHf_5IwZ6BZx9 zu!`p{uGdJf-vI*CJe4v~_-j%g+wX(G|NW1~88D)}UOGILjL7jkm>#xG|C2y-7xa~L zV)*vM>BP|w@na@zUk9Bm#CzwfgorQlf+6c~M~#0AdVOZ~1|;BMNnCx1e$Vg2Z>1QVx|HzMr9VjfHR(Xf$ZZF=!U@uJQ^ ztRNx@zfjCTMF(|o$V2>+*d(ZkO~J8aW=?%xz7%Jq@U5MV|so9JC2GrtbK#J3^l8LfgM?g7m zOdF(11Fo6WO(0a>=ae{+leTtjs*JC$WI&9@9i0plXP+9^fL|{y-)EVU0E0E>JuArC$h@BXaU;Xaq+L#CrUB2Wh^yZ{N}~F{uKj z(D9Y|awHd^${WSbG{oclZ-|O~8LbZz_KFZLZ8CbH(q3wT(A%$HBd0)bg6@*qo9`Z|wKKwSQA~QokWQ zH9XD$Zjms?O*~__`M8=U`xxQ_)2VEOFqbZKZhXGCyriK*z}zffN97Ru8Mz_bi!)Q8 z5ljr=h2%l;6GSWLopJ+3NW()zi=hmpOX#f*%FsGE*XX6=#>mMVlHM5Y_Yc@oQ9!?W z!-k*19H{K1oYMg}hzFKq9Xza3f%FH*1ZgeyrqHBg@)d~_$53T!2{HDP)6ahGue$sG<@jiF&(!{j1^64+h!Js5_rt3x>Yp}9 zbDh{hg86GhM2TLn&QMx{n76iUK7539HITWm>iHS+cD29 zlaFPZe|#~42Li6X;cF+&F|YsU6G`_$sokK)xn!Hm$8PhFF9KJ9mzB>VJX;O1!IIsO3N`uw4^Cf%P z?j@cpL=x_Mucuq1)Q~*RWzzeNGMaV6TC^-I9!<`S@UhDUhp6VQgUCoT1Hu=kp>qFh zRm3$t(fw)z00+G!D3WX5;D#BjQkoUqQx&xvy&Q7-fd97 zrf*ZVE6eP1uX+m~BaNK)cbvU9zbo;7UZ3gUbR4gJb7U$m9NBcp+Ek{XeC|l?O8i>VJ?FTxHPV!6%DGMlHW-!NsorAXb#`{94DU(jH||bV zyKn;bWo^1b>2A~~GLscGCI|&N`LOLcsK(?Jhnj;dNI-FxwAKdaE)M;)aHc&;;oW<4 zT2fFkY_KFT>+nm(&}v7-y+2mvnw_s-d~0(>#I`Ronp1_A*lPQylRv57(QwR`^N9$Xc=qJf0D)iVonUitYZxV)t;ZdUkxADs2vp6^e{ zp!cP0${^MoxJYhKfuV}SH=|w(7prjCk?G8H%qA`4x&+GwRL%RmxH9r)Bf=n;T)rva z;lAr_HBByr0sDbIO}4L4s6hfos7bd-_fzj#M)j+kY{8 zGkrS^-Y86=sW;fgxGmYC6%=qUl|a3A(qjTy;V7{0Ty(rTvq0-_7rA zyX&0criXYg_ua|W_1S;2VQn3i%2bn5O>>VE6(!1x36dlh0 zn$WK+uw|~Is<>}Wbm}uBLjw zZ`gdlsg971!HBqPpcnho<7d^DUSX;8-{Y4QW>QvkeccdP#~tsm~hn&8_|4#2}8v9;P#&fK4KGEtZ8R7*wsx7Rj z=)O06{Q{5fYugEJK^lsGyWl_mIx$6@Lj`9(eanm$E|kbZoCMs2ROMCUb3~5xJ9q^9 zx^dcuFJ{qyQMOjk#Guc;Lq+!B-t*TN5N0PsNzCTHym;YSVvkoJ`iKj}jKJjsj6Zf0 z#x4%C?7jLTY$r8;#<7COZn?N-&cC0fsie6n!J@HYM&e{2$j{LL(x<^ zPkq&Ve~0S(h7d3jf>c2KxnBEbxKd*aX?LmwpN5YArKbG7O*=si>FvM+Q#ZHL8}>uW zgwbNDCf`w#iNwSUfSc}V-r;jV6!fcxvq)im{JSaWFtRmJ0leGf9-Fygv_9uJ`k{SmTBci*|&D_(G%| zKHV6CPY8N%PU5ErT*U58ej?*!V{3d~a3q4pd`_REdXl!*_Guv+2reUgqr89)(n+VJ zADo$Ed0iQHLra{krOx56Uq%-gdA5q73*&q0^#wRzLOG}I;5^g#M2J?~w6ZguH?}nw z7L;bjYaC)UGheEduR8f6L2keG&BH0xQ%g|exd6gY`?l$Y|K_y>RseU|cd6Y8dcxve z<4#3(N9WM1=(^yE2{R)~j4U|yYg1euN*i*{b@?kj=`zOM>0y;-auX$DCftq@j6Z!= z#Lxxt*h1>MiD3qUWly@=4KNIK#*yDw8Q^!U7&yccrV52|JCb`@51LIAYOr@r@bRj~ zcLe_1B=CTv0q7yGx?|7WRhDn=$>Nt9u5+S`FqUw=8&b}HBwr~_tMwtNqg(599ehAm zMMa~|YOKZst?h`rFaYX5!tg6~3eQhtus%k%e1UWnjcq0oi|AP0C%;UH{KH;tWCY$$ z-9!3H3ewv9^0@i5>-Ob-xMmF(%pm3WqV0NLhXgJvm`W^gs&%`t&7gneChpfE~CiWVC0!(_N)cQ?opZMB}@`!`aR)}ahky2 zqLCV@mEC<;-}=K@-dLzZ?c3MdIXj7?x^Gj@BWWv+9npQ{2XdTcgUp5=Yoq`5h2N29 zs&p>e=9lv5ZyqISqcq8XBd*_7S75}Eyl=gAo$7x%u=0TrFq7oJFySBfw0Z{kxvU0v zvwjsD{@eb*!W+N+@7It8;V2CIskR&cpo9Oi1rTHYpZk+Rs;wne)Uzc?3PC+n*{Max5`hxW+pb_=Vg5iJO9)w7!=NJp*Uk-MH z9q3Nkl1NpO|9Luq2rtSvQj^vjZN;#5M)MpS|H$B2ZS?od+B|n;fL#T#(9|#IBS)0} z%jNt*Urc~H(#c5o<=F%Tx~VPO&i>MtJvvEE+7l;E++E;5vat++^(y{KkgX!3@eAo_ zF!bQ#h9~jEbjD+7wo#5WwNdYIfrUUzif`EyRyhRRwcX=xH4wly!Lq%GFgG_hfs!@` ztU`nok9)=m>u-z~F3j(_P(Psz^1e;8ss^@>HrBIz7Fe+D{say5-S@)zdFxwd>BsR7 z2+)i+qk*snim?RBaDp3oVw;XOD>M*##B^V-3oFCvoOu1p7WEXMjQi<(DkTN1TtqG9 zFK(xAiqX!#I_7G3vgNG>LOYPh8FceFZ{)X3W||_&M{Ye19V#A}UY`L%TVF zS_gSL4G$hXpf&%5#_%Pp$hW^T4X;UKy}J=)doK=e_*rGoc3C$*F!W;ZH+CMtIGv1kK>nX5A-tN&s&P77Dm-7!egf zJci{EAV$7^)!X=qt-zKMHP>`QI=Tt=sjIk+Mm+gHGweI z?8=1VH|U~VTi$HkX1j_YjSsj(?BLfF$;7JEIWl4E*M}f?ZMPW|_JxHyD z8yJsh6IgHtA#Q2<`lgh*qTD8eO>Mt^2uO?YfV7B&h{So~aX#>Fb+G2NOOcjD5hP|G z(Io84#5Y9}vJT9`j|=5q*9R{V+*HN%PXjt=6R@nh#@NOj$cX&^IgbUBI2Yzrr~={W za+TyV#;akA+VQhgxmKNOR-be%yN!6Kvb$r%$V=m-+R=#_=&0%O9y?Tp3`s~rwXD#|FnSM>3-g1Rvw*n$bh81r+#(j^I3!L_wL z1?@1eUIG%FGd?usHk&)KDLv%;RqmT{Xch6G`4dsXaOF{?Ag4!+H~(U+zs&rX{>wpc zX)Ex2p(aCZ?yC3WsBfPf<#5^82;HsBBJIcPa&XKkK6r!*kE=vyWt|p?TdD7ZRJObc zU7r$6u^5lN87-!P)HaoY)yjbMyKP;c!b$p0?wC8CH4|Aa8cBS@b8w#BjoJ8@5omT! z6=R+_mKtuDYWJxXmlou~`j%%y>vOdci?Ko@PUyICiPzT?g0)%>zw&h0gaL62E2P0L zN3H=4c+s(&{>)uZBFB?~?>EM-KI|W_a1HOB5EH#ee9PqpDd|`E$~VK%gLgRxuHQ~^ zK~A5HYh{Ms`{tQuqV61LdDrP}39Y|d4e8Y!&LH=OsK9TpD6-DL#v>!q+1YtpnWT+1 zIF{J+M!2}SJQ-elC^80#OG@H~ZtjX*_Zy|SUgUeqd#8Rxpfb*ZgsZhe4w;a^sGIP- zjL&MeV6U$%f=TL9KjY`a-~46qRBcJ@M#*!ynU^BhS7K(?=eiGOTSVnwp69!)lU@r= z&)EqiB_qq+tvxSQWHS=9?$@uBxlV`6?AVpy`A?}kQ3&3hP`%zcfA&o6g&}2OB{= z8uvPr*tdJCnjdjm>F@jgfEk1KhfbR}3~Zm2Nvv!qTz+<{(qSzqmmh-&sUN?CZCE;I zP_stuU4XxWughc&i^B|k!XQu%J0@A3d!L`W;HQl(O3!v8j2!CM487}`RVcIYUDQj{ z2NALfa-PhQ6K^0@lhx5bN=t9rjk8ePlhulMTC)p2l$-?n_c!cRnW9;uWqJ2f4GfX9UwEY%>Vm=5n%M3szd z7Z3PvD|=_!sNt7C%kI?yZ~Xdh@RyQD{gM)Xo0Zp2CeZ4cJS3jE=hDM0Rx_KU>)23n zU({|~AS&vC=6?HS&84K4j72SK4j~vC_B!97!XUk1z36Gk^Y*z8cx+5|Hwb%pcll7A zrCNbn_qVY07OVLul}+$TJTf$Z;TKu#8I_U7vm~c2Q$_g;wtN~AMfT@bAB4Vs8O3*U zF5zX?r>dZ;iZ_k&7q8FC7_86WehlWf<&&w*l)Ioh#wy}OTKI)}6mMSq@iETWpfpkj z9SYZIlUm`AUeR@ooSN-HtLiQNJ1GkgU?rCnd_G?B*QP?NZAem*;fj-w0F4oDLkbVsVEV zQ8tu4*!Q-S6Sz4SZaMfqY5=nHO-?D(<74`IAG@b=ghv?NXdySzYEbau;NnC3LciWE zPELdkYn|00w8Zley*?IQVKRruEU`YG_^=~7$fTvSsdqj z)V)+_(lXeP-UQ`NZ07z#$P#7ZTXtKirL|jzVkRYmo8v^F>rAJBSkiqH1yic!#Uxny zu3-MS=Y(Sp-bK(C%8BHCL{b-)Qm&FusSJhbs@S5uJ^{ha6ASGI*@CsHLqoWIQk@kV zT7Ik6J zjB&bi=tR}-p5~9Y?lN?NE%3p~_Yn>8WC-Mqrk!iT2+aCt1)(RV)3)l{u z7D9t~xHghc$C%s=_ORO(`)*Fv4}QMpd40uN-husxy2m39-(TAF#>-2V=O#=vpTW-c zSz&q~%e6jzI9Eew9f;`iyD|mOdMVeQkDjlvY7?{UelTk#oKOWXu!Ao~)hyd=Dlj^x zK;XFgU=Yqx&oLi3tm2IrL~RB$OmX#yoc3(XMTp+>^7^34G|t%%`%3g5dNOj0EF4VX ziqOt~NMP)fH6RQT^T0cHi9=p>IUIaNPk+DHb1yWnFq$4A7+dQdLs+>9i2Ly3L-G?| zN1kga?aEEISCl~D<}V{SMTfN^A&lR5Y`?kU;ZcEtDarS*PehYUT%m(dSO!6MsOX%! zM2H3{==Ks1Z|dG?>YY)B)Vl53E{M6jJj-Wz-?BltQOBU>yLS1wi7I%3gk|P@;_(szzysD_qmoa#?Gs>unCwJwC?Xt<| z?NAegn;g;&tcl>Zt+#zLb@!swhq_UZj;$O5zvy8M{dI>Q#s;E?T^xB8TTiR&LCv0* zhW7%BlTh{jyZ;0!-IK3(D-J~>K{RXdq&?LhcftJm6!FUNj z0;UHaWkG0@Io+F6m2QefzU{G!rQAj{jE?Wi-L9Guro%1{ccw^+E9U{A-9eS%YTG^h zk^?^+MpByKMBX=8R0l`&hHaQ~xN(ZwLa{VPN_AGWO!`B|ip`e{lvy{yuMSb<4EJE1Y_`zm8I=_4J< z{?10GtDD}m5J!S}c7bKTv;V@+^>20bcAQi0sB}ll_d!}QDDpvEtQe8yJbc+gBzCWt zG>PH9zbLHKe+&?wkE4N+$j(4nhyWsB`AA=d%3MOBhT9CB2SFubpYC6n) z_+GWK0EN0{Z>PayvS^F9;)V>E3FL^lI1_l0lTV=i3 zlRge6R?K@rL{^=N_^SDy{x>WIc94A5#hpjp7mVKa{30SHO%-cFskwKn(yS| z39oHB%1#~CcZ6ZKAQeV#{jU6Tkfrq8UMsk5-t98O8*8f^kOA}3VYl2IuKxSI7d>Me zzGE*kI`A68O&b)4xBb|MxS&p4c53JGzKi(kQS0s-WOtl zq*T}n7!A?gAFv&64p7OnGrI9Xz&$;TdU7-*o2W?l(`i5RYP%i#lqIKv#pR*;&;q2J zV@N7fs~4TBWPh(Z1XBuC_j~ON$$wb*y#AD$)YO?NtKoyxIkk%x)XupcG1Zp!wN(~t zug~z1H$GNdnyye&dA!wka%K9CtNGvu^%+vZr4Wb@b&3U_ox62WK7XhTb2+isy0n3) zquopTM(o2vq(TakT~)}GqbZXhg1>^ZMGum1=BZvGOzvlve==?va-ExAe5Z&pcIP-9 zC?jF@(>v3RiYl<|F|OBA!;(2FDr$YuwXi+kbFV|^%SmWsEP(0vBt7qhB8}OH2}aG^ zx?yF@nh(4STC9z3rc3F0puE|;#>c*>D&hu%mW}z}2%anVt#pPr&kMU?~j(c2Y4mQ zOk*5fIo#|&ZRZ>CKxAFHK4~9%d@OK8U!Xw;NUS*#Ph6@q3@tYwD6gv4K!yYJUc~oZ zI<;1r;)bJ@hZ)6cD+-C1Gn#$@di7fRl!^1M#V{j&$+2bHu^G;WW zjvA;mD@OM?csSEXUw)kR$e?!fY>Y-{oeiS{fN+jY?WRSUWWI9V3+TF&WButKRk_SX zD$w>)p~Y51?n*(YY)cy%zAdd|h(v$H6-MU#bF!Xdb>Bt-Gu|$F`oRCQZk1rtwf!f# z4*n)a=6a5UisU$3d%nps&dtxLU4%+%l^O1zDBeuK?!X(48iwc_ zJ%?AC<=B`rA5M}n8zz~Q-X)w$rz_xM5qpfp4C525-8b1bh@Pz$-M4YvzMyV9C==L) zpQ}yrD=XuMb^HDmJ^nLh1d`#=r-FKE3Av{MkWPlZ^F&YvZ~(mpXjX3q5C3yY7Z>z9#jDqWQ!H7V}dRjg(vzm(_|Mfm=_PaLjp)kkt5^__ATza81|0IEJb< zl}!()p0+nhD|IAwPa2L1>NelBvc~I=W$W=VjNB-&!L9gbJ+#_ImC_H$*p5^nx!+#8 zRL^Zi12WN4gFVecZ+*MDCh(XGcCS{!FaL05o@U)m}_66wCSz5 zeuyIXL8S+adf9E?5=oeuIT?t^-%U;p6X)hv-5GwPtLRH049}wSwQNbu3IJt2-y(rH zp2k`m!I#86FwmOpkI2XMew0Sma>jLKW2by(KL?!Gp7Pm)Y48oq@f!&6cQIkF*?-+g zTwIm&#ERXVPgsBH-R&~l>VSiIPzP>}j*+X<9LV$`ADfJj8M~ai`hAHvc%oXQZe3?7d z6|%bF_1kR-<{G`@Z8nu7g!%#is-C%P$d(7H*xx;xaU)1^pzH;e=jmrSgl>dUqwGBd@XDCMJEVoOI{DCDcOBD_38 z(kbluOj}f^ub)rW`XKsb;8ws^@F_mE$9d!C*inhhPhF2Qj7IKwL>L_ieQtsJ!LWSU z)9q2sm{Wdn`z4c}dVnjC?$lH7EqiPWenY+7jqOhI3izFniqfHcadSx`eg1icS2P<- z!@{p$@&FcMUhn1*A_-Ca-trJlv$1c&ziil7=6ieTTcB6Tke+vlcen`Kz={~sXb6Kg z!9IZu4sC$)w*oe+U&P|Emx^pNIQRRffQ*T!Sp|cb%ntRfEElYfN~n|+TiWEf-!Gq> zZezJ3@rhP2+ctY@S!lm}xeyy@(HKuCQWKf5UzSZ&f9w^;+XJtsvOM3odsJS`w*-(Q= zVDa}!76?qd3NwP}OmBvd-0Q97vbze!N@|rEvftdAMo8g?{9{llGPYa(Rh{^IiT<_- zzxi&`$qgWwM9cy@^2exQVk)Ic9bICvB@eT7J+c7xNWd~NXX$bSDtz8kRepRH(oWB1 zJRswq(w7%)R`|F80?)X^2-^y^2~KP2jQdrhHL{E>l}6txYPcP0H4FSv{KX0EnN@9& zwb9}k50O7dyP5?NKUJK$rz-<&k!6=Z;$@#pBbMz)8uosQn;8nC?ANNbeHV!qHrr3J zsD00g?myQVwxqK)e_=efBoHf;?@P0^_Ei#;{<7A0w`(?b1y_~HQ2|2m|W{} z#WIttJkcg@%q``&AGk_=b2F5>EIQsGR(tiXT zeot;i+JG2Y(w&}XXIk%r(uUt=W*?ofcnwMfzKZ{^6(N4!Oh+XPM+GX&e4h_4MUsO| z%*2;6#cpPeW_t14pVsf)FO!h}1rPte7lWf}o{p>ZVlNvx!8<}}St-~j(vE6niW}5G zOkZxZTiI*ZglzP_2C<{V&l%6QERFPlZ{w2 z^zhjkFOvTZ`Tu?!6Dh>bMzWFfS|J=i%dr4Z$lKJ^1nM8E`Z`Y%U4qPBI^xC~5D!NZ zX8-lbY5lcm(%AefL66hvC_9#dKU&`VHDQ8hpFfd$p!BGMKen>2W9Eqm z1gpYCRG#h#=)sR~Vpp!T21xiG(h~NDNSgj7k)0Aqw^~in^t6GneO3tirxE@4Q1_}Q zC`T1{UR8l$Rx~I!a5_M|K}`&1p9P+ADqMGeV)pFqUP8;U$zbY#7Q_&W37tRW0Cya? zjwO{LC~0=~hMowU{CZh=wu?khpe$6Reo!F5aj3+L$I|IPI4=-!1Tbj3C9HPL6aRXz zRsSPY1JvB|#W7%mzj!&|D4NNAs_VuvN#MWEz7YrB%O4(=bZo)WpG)n80-=bwdZYKa z#PDBo7=2VTcpzf={8*y=#}^aaKyC(|qCHhvS*Iy@rG1`(^T0hj*< zFIlG%I_3gaeTk@iNJvObpr9n{QW08?1+oLmDT^WmuJ+z)%-QLm5aZ(d8lb48L`S?~ z{ns7*+uI*4MGJ zr{(LPl!iDd-rr!j#Yj*8_!IiV#bU1PQP;9o5>8?cy$^^_LiWEtJ^98SQuRA8{c8Bs z17z8LtcAx!i}@CTGQ`1qX1Rd}n1^Q70qlU(#8kR&A1F5tZRq_DFPW+98k$~|Zd(5) zLda+|K9&fXf(kueFv&3UZ#jq`6$v7F&3FU7@6fEu91*&amgUnxaS%B=ymR~ZU4)Kz z#uN!rbWA%m{q%9W6(m!?{o?h(HFcjcS5Oh%Y)@bG@q7{ViI5GcAHXdPhMZ5x*)0qt zZ&b(6eYEPi*W$R|_TeQF;nb(jV>g*`Fz0;z=Uek=exq_y`!{bv)gYP{&``mah3E-= zBH&hU_b@;__eAADyyiHZ+Qb}CH`MUe55R(>D*Z@Zg!m`~fd1-WPjm6Hl$Ro_Av+t( z&Ly@HtvPq6rO$j59j1;w5t)tLnjWh?4o$nt0*-0L;1rhh9|#PS?l5^SN-smA{k8#d zgL3v5hwHDP+iRMab&&51JkCMyH~pzno=(o`--jvtvJdxE}qhRN>e zfSS@87NuXy!v9)QEpcQ7i6O&j z(B6lHA>`K#DW7#@5;Dk~zr&^gctkih<<+IgYv36dr&J-S*Sd|#etA-)0ud0R|79i0 z^3i}|n4bO*usIam%rWQwq%IO_7TISy(9sj8!JO!mHV>LK^lpHnk)g0PNess01+;+ry6xcVBI*!y>(E&mVltscJiS_6smDQyw`~Xh7`V}JXSlOzDBEMV3 zcl)H}c}k&EE|~mQ^M|&8>mmtQ%65^tI5Ay#f27dGhR4w)f}@9!(~yY0@UM zT}B+c>oXu<4!`{};fg>+3jF#Ht|AzUWfwcL0-8Fc%%GrR%Hse?{*^*YOL}NVKO1Dk zFIs-GV%}OrMS)5i@>M3rcRvvny z!(r+B&Aq1AlL|`hD-DiudB|$bJFgjjes{LMt0oJ8W`Sk5TRyi=x6x%PPt9I8GlSwMLrPy)jHg}+x_R?QuKPwQ zQ}?xh*A}4C3X^@Rr}W@RM6AT8QsRRHE65r%H(u?pj6>SaxR}cE-r?Z5LRi5chQ*jd zTMl;@qN6nD28uWm7Vv3N>t7H-KUP8~&L$Keq8^lNpkvVqKSKr9pQ}&?9(80XFd}H= z%4!)HmRkGpR801_1Z)p!evf?T8`158KEN3}6_V^xM;&!Hpo8*_b;8XV$b+wpI$a^TIv+KzuIhTl*D@WLZX9%&(F`efo(W*rfq-w z`sbL4DrAZd@kGNRK}pnMr{8_$sJV?mTJ;F^{&Z(tZ}(gbCnD+OfiDM~;Ai8a#sdi` z_px6X%?!>v6-bcb6&NX&nJ1@Cv6EN#_8dV2V$ILW)2Y$HDGU83E(*BG8MtyF70B_Mojoeskiw*;W(~e zukI4?tkd(~-veDKs+HpvM;VJqkiyn>iS(pNd3N~rTD4}W8F92@^n5dOEd6Gac-Q-S zH8{K^Q@<6t^uMHKVc>!aLN8^jr^kaXFRdAEbhn%Fy8NaeTS@~mpIuEoEM^i8TH>GS zP_FSPtp3DYkm~2SN8wQr&Ln#^ip%SJ*}%Oy!`bm0s*L!rMkQ_w*N^({Nc3Fh@$Bew z!Q0bg{Lk?k>-*G?>%2TC@_55?AHSmPjZSskT0~5L4uz|k#Xwp7<^ysLZ<$b@I;AEQ zazX2%ew`sdzK&Wp)#Llg4Hc7Y_a)K0g)EdK9^7RVMb%-#tmK1xExJ6q`H43i*P=Hu z<1ORwdx?j)Fd08VQd0Um)Qum^Ot@z=kYDVtE_=AIk|ew3kC(O;f%*LANEzsEvc)a1 zN~mYwW^pCD(g~hc3 zGq^#KQKN0N>vGfEA&$nUv_1&uYu{<+d0ys^6jh(6nr-?B zeI;#da+$dOdeb<)zTYPFOD_ZD@Sx|R4MCI7d-{7wh6!GeE_EOVvIE-LsBW#oxbDA> zUUIx*{;5v71da|EYB+pzb=R$a$*&{6Ao4qV%Wy-&73Z>4sq;MW1NT<)h~Vej2_=sm zOAD(g8izhLbB;dkWFW<$;f+sA=x3gtUwWC1azniSh{)?+TjOR?TMt?u%WK$Q?~r87 z&_yz_-jHer)=pP3-SjCsjE#=TP>EQZGF>cov{=hl8uz-+lexxoB`$oqI`JF(t&>R} zeG;y7*H?xfLt%qEia91yvR{8VzKwGf4s2K#&|V zyJc!0lwV*2wH;_ppKA;XUU&H@x?PVHeQ18)smM-r(lwuQHd)N^azCPA_GI8GdR}YP z#^*JNJLby~k~3TPDZfXS?!#j8cz`e2!bpQ2u@u!| zu3lK-hk(Oip7JjqE>oH)Wn4)BE{$h<&VWz+D6d(zSfukxZ+RnI0e9uJ2>lDdZ6)vq zU^0C<;Fc;r99ZY2gEZ_zy6a z^h6kpk|HA2CetdlFe(hcO+-Z{&$= zP?I7&*6BA7hV}+Z&x*a`t5QqZ%hlmcLFCz%_>Y`Ux?z)hAkh)Wmms~{H>KIT{~M>y zC28kRH3Qfz$;e1q zA8g+|fR!SpY-eOt>+_JS$8s8V-8^1!+i!kp3FR0|J$`t98#4q$X-hHB8;=>u3m*LB z^FFLg@=!ZTFEC#%W1@kxlFNko6NVDjzo&Y;toQL$Eg_}sDhpY?l#yg^njqm#-{ix- z=Q~#>y4$VajJWhcv!%=aASK=DTDx0eFSqdw zPpxa9_J_l8c}KhqKqX*(vC+se$>a&1!RMk3gEpBNN5Cl#+xzc{5V{f+DXYS3MK`T` z2i_5dkzc2li7nzU1fYcUsfnhBj5^AK(rVon9xZ>6#9~+cJeCF&#OE<1*dW0Fnsr^rQ*o8u0jC! zsLA?T_I2l<9E_a}*F2t51-aWBrrfija(W)YbX6?*q!aGJMwO4KILnO;#ONd5S22uW zJbbq|yPD3HtH@6h+-IWI&hkwkhnLXd z9r?#dCT95Ri&4zxzlp34ug$41^cAO2)(>~2S*G34UK#t?P&-79cOR8B-MzGtOLly-lYdaWRvQOw#_@}floQC8-rjvoC-oe9rT=NhVbx)q{S zW3r;|vb-eoHcd`dHc4px-a1V0P3jK$^A!J_=EGCUB5(Ssb*DR%dIPT9BAMWPCHGP8 z6~iKI0*$m+TKM+1;D9;l$HrUMfO)%N$%X+ez4rtGk6AIHO5U2|Ut?)R``5JZV|rBY z6Xo|*0_?^;)DP;U-{z(C_Y%>{dmjm1?JF1xKi*{OZh*?pH{Fw3*yu^{DTVHQ2^jaH z`n%^jvHlO_Sickpq~34oa}v#}C2+(XO_{M&K{rl%=|GGnHElaDzp<#VA>{yw^PNfGh*LCKuOsv^mRC+c=PH3eXRX5p&s;I&?+ox3 z#1nD>XfEbq&*G4H0j+!3Ivfk#n^8*=ek<$5)!{s54AfDSC`;FPQQQZUXhTsqLdqs# zF_4N|#sQ`8JcTa0Wc72hO=K)$x2@D23%hk`3|(os#Y?H4J=s-Tb*j_-FcPZv%BtXg z-(m~s;mF~I0Nv6MDEvr~VjkNHd_uOWOZ)S<_uTSPO+RYa7UlDxJMn(y(D{ z;diP|xhT|Il%T;P!|xz6h|nJ(vb8iZdwHa?1oE+ zbctZkmV`r7k9s;9dVlcsm0g`U;CfN7k?JTixOL*6B$>>=D_mO+g(wbi^I{|_Io!e?M;w9<>8ub^N4 zPB;rMr%L>)I3(bkUu1L6FbbU`*au6s%d80Q@_33>?ca?!z!I&7d>oH4uA0J`t4nKE zXW{W>T}y-myxN7m@;X-BTlxmIl+P>NxjN-kjP+)DhqM63WJc9>WBR*jN%yy0(*o;0 z8dM##OEjG@no07}n>?Rk%D}Ykj?f5a>Oc`p|2JH(Mt$TOmpqTflY*Sy@$wLHof>5m zVaIyu@?n8Y$PRh0sn6&6OXc=hORdSYQR{C-^?f;v==GtCdzS(qa@`+zsl?21Rm@IX zuE|%RMN)#hRv#j5zxZ1c?1@f6NnhO^cWd{(SAw4_MAdmqH>U|PWV*!Mesv^Wy~-ln~Dp(XVp|?=dYSBRlHrZzqz3!ECw$VT7D7sk12Q zX=P1Tq&1d$ww9a!&6YTCpw^z+r=`DzbmV6#GtLrci|+R)fw<$ikIQ4y>zaU&*~_ZV z5nntaWG6G#r@s}R<=QQwxK}#VjC-%EmsPiY z*(6C-J`SJFKWSpSzve}mSm@lr`px6Ejba`&c2ys~E{{^GBH>e1wO@rw3*{0Q*k5Pj< z#(~9e%}U{|YLuyP%*&RvZ!jOX`UCc+Se-xY+Rlf(@yljn9q zSam!6fG;KTP&Hc1lQ(dzc{F3(D+k!Q5cmz>bWq~@T(=Qkdu8FInSVsU>f;6*$Ab9f z;RZ`wlYf-~EXO*%t6534Y#Hv`13D9x-Ku>#6tW-6-E-J!+p!K(=~(jWIc(&m=FD5q z)_=5O4nVn7znk_qY6Efe{mP1&(jmA3U!azc?54ZP#%bn5Pa<~^?u|ue(l_pI%(yOJ z!%CwS)#m+q_}{p*E}>rA@bnVhoa_8I#Kx*@(Dbc|(x(lQQXto0WR5)%w0RU?r`G8X zmFGGIZ2x?m=4DKxTfpT83u-E-HtP#aOwix#LI5XtGSOWuy8e(jHI8_~+x2{VAJ58= z$NNyDHObS0eU6WC;qFgHsVzH8;_5*F=q{ginUCfXI8po!e$!THUGw9ea(D7d4dOHVa#dnh5r+mX24kkO8_dE@+t6 zAkUrk(DBf8PFjH?BGR#|J_$GOS@Hi!JM(xb+b-~rK}4bySwh)DC`ljj5#*%#*4B6MQ%?!ivyS?xGyvy@EeSV+M@Asc&=Dx4{T<4tY zy3hHZb2+vaWEO{hl^+MZGNe+!ynoAxNI3)xn&?Ua>0_*jOPK!kqr7K5X)sUjG1dnm zUnIp0K_)A;Bv0&6sK5)?vBAT1DFU;x|cxT z^*)8my42^+JXCd{HTY(hPAx(!+;`^ohe7fN9{fLrf>?cIevTRZ5yYTS1Zd3W13d|vj zh3Pbxd=qt3kJ5g_0bvE|#AvbaZ6#0uT^FSbU(wJjpQ>b zjYO{x5ml+1fEzGCIqYxykV(~bv+PzLsSRQ}*RYRP8f zQJ#rh&Px*igyG&P7*DG~Y{s7wXjEaUB&HEx{gUn~SKZkBt@-Fk5BsW*@RhCHGobyf zZ`Wzh1ppE0uPR~hKta4zFNHveZhro6TH)&TvxubcbK@P~v;D)b6rE7!!w~t~#~e4e zMwiK3`)Rtme8TemN`Zz)$yaz)j!G_%belc_TNIc%7NEJ}hpi19_ZG6M9`SO=h$|oU zQNwHoWzlQqc1I7PUG#yXv=@FtUmN?55Ypc(c>fe_x7$`$jSob?$Ey+EoAt$G14*Lc zCJ;(B@~GF0r`J!wgRdZ4BvQpbP;OD9w2 zy)lM6?Y2Vu-_yJT97k&`vm7v=btqnJGXy$vcS_q2X-ZG1R{|#zt?xS?IeGbA)=7~X zx(G#|BrcB*uf=oZStjextWQ><^{KhxUtMeo`dtMe@7dSa#hNPkUyEMA)VRc8L`EQ< zlokbCxI+tZRwhUV(w#Z_tSQJr6gHSk{fH$4Qqj~^V1^Iec1>GNo5+kU@;ovMeBK2% zGk!Xp6hh3Y^d$s&rg|7{pt2w5MME6D%MbFK^Sq$BjDRV@<79@WDFLhMD(`}=nd(>S z-^Bz|6EeP^K%yKHDfaJA6rsg1%6$gc?JhZwH_HMoy%NNl{el|E^9p_UC@tv&*W8rc zemEEr`dugN_nweD4dQjAOq?>&NjB#|#?`AMxoIiWV6)_SyTSZ+FYM72*djSzFfHM8 zYSOrIx8+i)1VGQJ@CkfQW`^H)v!y5W_rQT_M3vw}vpwpHK5v z?6;gQ*Jq#aN-Y6SB#3*#P~#YGi^-J%u2C-|QOmmKVQhC;B!eC5c_>8m;=jkeBlM`; z3LzZmC{}o0lzrwW!RZoY zBuLhK{$m_vG*|KadGw=W^~fR)0Jh_UCySqfq+yHeguV?iS?pBDU@XxP&kt+y$m zAG8}%G$!sjtbYvb~>(v8s3T-a@UC28;+n&~2Q+>k;^?=7L4t z@s2)nI*5fL{UWX+pXr@YhGeU)Z$jme0w>3NuEv+gzdo~HqMRxur4Pcsuh8!DT2MHr zC{z7XIyKYdCwt<5LmHrRs0E}-?Hc4 zH=!U)6LoXsbt`ccsiDAg2V$9!+eu27Q3INpyPR*LY8pTJKl^eJcv=9st&?Q8cZ)u- zA2+c{a|x>ivho(6hp_{Wg z@$&mo<*Z)j(nc^uGEx zY()^jGO%7aW-EXO(M=S`JS^2QsCupY|KWxQ41qKO-Wr4-3sc~R+nV2ApF$SXp8fkV z2dZWQ{g}k0^lslh(-sRzzIfML65K2_1qB@p<*RQsk4v@Sf-tbrVn->^jv%v9xDv#AX;a_huWDy8Sz5uKB73#l}d1r-p+=;jMqdsON;f zqAt>Gr}WBDxdMn_3bXWNuxb=N&;TwabiI4$`e3iUg8&)X=mRCvVsH!1T_8q8#;~H zLp4Ub9v=ST%a<$Qsj2iEzOPjyj@9qmk7OoV zCkpyNSbPxTNSC{!GTX%UQ(Nrd8;$masdW|P-+(s%oS!z1pj4pW|5B*>R!jP2CGjy{ z>$i7vj1Cj|Gq!&uR`4+02PVB)iera5Nbzjx#&D7-rK5fmp~}&`ykW!GWwca8?KIzf zZ-^|z|7KbLvq-5vq(2wQB3J8PKJGEEEM%zIr+?@>h#GPMPi3Sj%ZL5f69iC{(2b}~ zWoPpdt#6i+9n8%%I1hL;!+s+d5LoU^sq-*luS%RA2DEURh_5D!PeZjI`!Ir=#R1;| zv}0vF)Ak{db%S&QKx5@T%|7_erBpM|Z!iS))1auDLOdZ$vfxAjyLJoaVfqSg)NeFn za%jmR$-ELw&HQ`Q0D+akW^MLIOB}mr4_%XanCbwjWhzv^I~DYp0&MPd;=c*4|9PEc z=GmQ7R^{0NoR2y@g6;pxoW25>Q|E;HQZ4^C<}~Ohz?_~Y%RPVfn@9fl3^54+gSC|C zJ;nT|CFw7}ssRA6?9M{MncrIJzg&fC!m)d8za@G9w-5fWf6xK|@6^xqXLtUu0Iwxr zoty&9UDsNSr+#LtPct+v{uWS7QT=fFb`;=jn2v?8dGfjUwCEJa!5DF}hwAGz%>0_~ z-;axyn?ih}>S%`ne)46@0+&Vh^zi~5K(D^t@dpdw*8RHWR+G$X6)q+wMh`_B*fJ|% zk?{92W+H%Db^uZ{J75pcza~q#ABgD_AnZ%>WvA#VN`4K$#2)KbJQVCVn^$Ds zmP9tThHf=G^IA6i{n!FkpU{1LeMLBzwdBg0u!+Fj+qiS|FW1m&7WR)R!sZ;CGt`f} z)_oI9m=4JeG$h;WqX17^F6|V#Gr9vbNm;*NTXrz2D=&OQ(ei@yZ;YSmIk^5TV_S5Q z3Yt~H0KF)T&oSved-meRHQ}H<@ac-=py^QHAZ+K6`_hyQf)vmmU>Es5GBQ5gSouSY z*5fGoIr~s%%4fereVJshZu}TZw^|9B*i!wD<`)nUsG>`tvv4{?rKWSNs`DSuT;eeU zISitJ?$v#kGg=Z`I||w7Vo~E4e=n6)jS=x+LzIBd<66Bp=SAl81ChwUmb0&J@&euf zm^{VWQ=U<=Sl92^0v`A(_@R#=YT4J`p!l@xO!Zmb}T#Lr3PCd=-x8)snZiHg1fGM39B+qfe_YgsCpIJ*mx9W3YX=si+b$|C=LmRC&CCH6++Z zZ1E&`59oxJl3tg>5d=QFQ4QYBLB(}&7{i4#%vjdZLj@0w*X5@_eO03Mjr_O!I9Abr zZ+a~G0edm%@3Lq)?uqtJFg-J@I1okQoO^!TN+uR1S9eC!mVe`8Me^Jt^6z-cfB42L zz%k5IFCQ)>(NdWKSJ{|1ITPg1x*-EX9F^zJnOJBSA>`naxZim|FhJ~bS~!b^sZtzo zx|kH>Z}S}2Ds1Z!QEot^lHVTkqdEzAt%dizHaB@jfX@fRLKnHga=><_n*wrrQVo;JpIKY{N9KS0q-qINsfiUz-bI~hO9PCG&>+hmqz1G|;7qXXa0E5@4nmfCt)s>V zcRX!}mb;tW>p;cj8#&ch1WEC>pS`ebf{#t^QZvF)!Fu_X&20Sn0xN7IS$AceU1GJj zk@_e4XU%LbH=I8*GU@X5-da$&oid^9zFy@R{b1p)H(T|b-DX+ zo&u}!RWyhW5#z?#bi%<066Dpn55^)x(e`Nlc;T`+zB-L;2dxo7mDNceaWcN>;37() z>!YbY;gqfOxR2}8vhuUcXZY)x8QXqPVrI#XsJ2!NJcc57C`JpN61^k^&t2f!*#D$h zf8Lb?6v=htUZXiFMp4P8;iH(Ta1ZJHeZe<68d092_2{xWbo)$97-w(QsN_8QYdkit z+*%7QEn{{`KR@lt@Pza2YYdqW@zyOQ6(H@8iaU>n$EL@Vg{?c{qHW9*qUSDbJxx2y z%xt~-C2t)4ZUCuC7Y8U&e)=HscPz1)nwIQ+sp!PW=b|73h8m!GF`uW)Ut&)4*UuEK>AZ9+2&q4h3Q1=~rIw(a;V!D1yKbFGK4rZ6`tU}|!d4#x}0 z%_sayjL6}c7s>*StXO&O!z-Js9QUH69NgdTr|cmNi0-cXM43V4jk|6s6QCNu1qxSt zGRGV#xwxYj@6G&I)rv9%RLh6I-RF2u4D6HBxP6aznRN1?$y8@m_5j%-Jo(pFZpRn; zq&gfHQ>XR=>TjNu;#^kw#XWC-f(9-c-!6jv0J}#s*YRdBN2lmS@mFF=aDDc~n}u&L zrEJrrFo`sen# zD>f2>&`_Q%zx@5WyzXVK@AGX^Su%41pfp*}I{&TdqjtTDADSUE9l2?Tgk-(1QvvFA z=(t8*H?T>AY2ycG0`{$|b^@;D$a_s~m~H(U4=MNT@(qs& z|6l+#XZLWbS2iBr(N6i8a`hr+C;H2m7d}r(SA=x4+s?deIiV=Nlh5Zhsiz}WQ{%ZT zJzRp}b9;{D6M>uYpR6-?oMYCB!my9?$qdyBJV2dLk+>7E>r^{X{1QY>+m(^njf!Dn_)_{AU%or@~i!F z;|PyrK0ZFp+o>z|#VC_?2VL{ayq9OgT_k6b{ON5I@`5GEEyO?}EG`9pQ*^k8?mQaJ z8_fNY*dH+SyicKX=Y3+klDPse29i-L0p>pk~$qB-}ybOF?pf=L0y!VLL zNjTjcNOpd9+ZirQQV9u4#CVTWN`s=l~OE77P*HEyZAS4pSg zQL#dC=z)ht?){OCv;)Kuv`lzP{p7u;&)#26(zRZd#@a_5tTF8Q-)l9kUK8w_NpJY=v>`yuM^!ppzK*+!v_kM0#g%gq^``%lH zZ&-WM=^vP$!5`ie?+u^J(x{V^1hDY>PU<`lrw1pKkn>QGqV?DNK38jaYHwj``VCo485hY+8u^h1o`nJ9_(qx_AWS6v8#k6R#5Wy=3tt+kNx?Y zx=*7W#!HP@!~$+S0GWLHcHQZ8oGlMD(2DvZZs=47ff@1Nk3q4 zc#zCze{J$JOfnCCHx=j{s`mZa#KG!Vt?_DIs~xutl+>?Zj93}z3mHe&ogPv?n9lc! zRLT5wkXgd5ctL!@{E60y_lvPVy45BWmJzO~Wb#*Lr|`9`s`2iaHEX4rcAxc%-IWgP zgmoWH6H9xb1 zQc`;hSMbBB+va{UFRlTfd2ZO}t*F_3ZMmu>#c|ZzRTU<|?dPbg=I}iv=LompAf6(E zkZN2TMkQf4b4MrUO{<~v;Fg&^9LiW*?Z{l+vyC-IbX4A}m?dI$4<}<45QRI-!|kF4 zPHq*uUBtPf;i||Zr+CfS$QVBl|Ahg0^hJAECAo%o=MqDGPmj`(1Ch(G^pd;)gqvrS zk7lRBt$wnidO$1h^Pyp@{B0u63~86jw}>>a8Vh$d-~a6T9N#~_(ybrwjhaJn%nin4 zqk>&F*8_^N8_yFJ57~?eEp#$NPD&W`63OCCRUs*H)MWcFHko<3)P6y`mK<7FZaX7j zv@?kz;m%bZu#at}$K4C&fPRR{PvI*;qMjUemEI4<@q!3%V}hBk>;MZ5Z1Qvz9!@wP&51fM1zTH;al5KWgJ(bsxMKc)JnXs7)$@i9WDiv@X-nfxkbo zt`swj6n|S?5~Y{(PSMk;UkZJ%WS9((Uxx_NBm4#Zs(eSPO}+1*XM-R!_w}!xXwtDC z+4_9qj$Rs(tWLZEax_IKckiiX&Bhi7QuodmoAYJTRuL?|?j5>5=Zo zhBJCD3L-jjF_5{GN79+pnT+F@eriJ{?j=4$v(&Q(eqBIhzT2{SJQz8Kt_mYEPUa3) zv$z}WT6YnQ5ppn?MYJLfESN}d)Ch*wUF-ciAO;C{U<5152V^`h zaq(qG)kC2xFK4Eoak&J|_d=W&+7+M;2Kq9^!#~Ig%Amvf0&c5s87}KpX1?%I*Qpul zp9iZkCF3~27zqmSefU7o68+(crmRryk3;O)Hyr%mZgY;o3k$wLd+W+pduixagBXk@ z>LR+k>ZCcWcbi)AmtH>8rJU;Vz|QIE6wJT$p`@3atbIa~(aV?LS z3nIL4pY89AhZyv8{4*cRyq+18i!A;*gl^sKP#wp zB)L+LePFhoc6G8=H@b>ce%~Z}An&oU*Z_Y{&lT89V}Y?TZWo2@?GB%_@GC-i#b!^HIC%u9!ydpLE#FrqLFN`h zk`>&cPmJkC!MQ&4Y3?QaCz@iUn92jMz_u5X8gXUTsg6E280<)#5y6p#PTYS_)KGtK zyWBj-p;kh|Wy~2SeBCiNA4Re8^DwgAODo=X&f$^acb_x^8?$V#vhPR6>-Fsy*CwJn zZ`>$&R~eUaGu;$B_R5xb)~aarIH|^>`&{a7BgMu5TV!3}!J5ouKV9#_tZdQGltTy2 zpSE2;Y95OgN(_8$giA^7KZsZL%*3Re1gIM7&-KzT{7uvqG4y+JB$*l|e`JRDx2cm` zUGdm^a;AjZ<>`l*Zs_^%2GrvQsVg~d0cr(Tv3?8Bsug$78#e&C)Y}8GMJ4dfMq$k9I+ywXVHQ&Rpxw_ns zOPhR`za>ie9a`DcY{Y(l>b6!@TVdXdEI>VA2<#`e#8I0!I^^sO=ZqKSFa{R+A|7lz zt#g(7H7Dsi$~cag-HGIm@)akg$rJz)lGy67(-1^$>%>B%R|(=zckfvYD$V+Z$+`OdtIk} zd)cnw^ph0~tR}R5FuRMgYodom7vs8I(jeDAYBShVIG_BN16^qODd6f;tFKV=>L5-{ zuanPiPAvjH9tbDB%22&Y(}bXL4rb(H7TFg4q~CP=(`CMV??>UXCYF0UMxxoSo32hL z7l%}OT+woVYloVK8ZFFX&MJh%J?g!^DeU^b`n`6i@I@VTn08{VZer`lxvXQ+;&e50ijg2$| zt%{;j4wV`yN<)w=q{b}tk#@2oW(|OhS{=Fy#<~`h{&)wr205UYA`)fWsBH|UVU^DZ z^So?hbD$MrpdS%Q%W605S+4GjaXX;UZ+*6k6OBLz7fiIXu!z9UMjJ->uk1XmxTN-h?7Zo$$+_bIdut_h%70$-tZa%T)Ah7a-Z8PWkqMT zq)V$46+Qap#&cezIDL?V-z`+ez8Aaz7T!OXBaZy_)OK)QjL7q9jm8oErgf20)=VLz z^$Fg$KkmH=$U((xDFD8_La48yq%jRCA6{*a;aD*d1zu(i;)|4dZj`8yYrbA&&GdVR z2|i63igzXx;{p+|3gq+jqOpZR_t>GK2A*-QJ7qat70WgT+g<-lP#y<|lT-~ZIeWI4 zZ(jnPuBv~v$rDuubV>9&0lsvF=@ihjhsOC%!+Ug!2+=Okel2Sa)v@y+z2h+3ySB13 zuMau)zPN6fuj;xn^j5l`?I$>jXiNM5On?A zDDzA$O>q~B2*ZRU1E=kz745+chNT&K! z)tc6LRV%r;ZyUCTkunX%0BRrC4s-Zrv0#NJjGY~3VIuX{A#frHhpG?{QC$7XYYUZ< zc_9yNNh9!>@KYP@^o2OZ>YSb;qiYjojvW%SfHyS4W4VKG!ni&5jl7QEnw{x2jiuJF z@U{|SDthwL>K<>JAc@GHc+m&sckA}6`XJQye3+B%bKuqVD@WZ`5~~;pk&p39c8_f& zZG5L@9dt#@pbnQ6oP6w)73>X`{NIXk!^jVWh-sqf4ukDI$lY&eVsUpl;zhA$_lXOQ zI>dE6M6bx9+7C?t5gZXV#Dotqa}D&}E`BB$O4g#Wap34Ee(yV?S*6Fm)eM{MHbS00 zty||V_3m#GlWF<{6-hU;!`i9Y}M4ryka;Utk2Y0WJ32 zYH%I*IFU`+B$Y?hQ;%1EH5jaE`Ezh{xr z`L*b3<)~yRax%5Q+DJNQjate2#|63Tra5^R;|;fGO(iSnrnpi2Mkkb_%U^8)VZ!mr zPVr?Jx#16_5uVh{H5aC%Ow#?Vov=hmC^o9ETg6nEKUYyQA6k-FWOm0I8M9BU=_~k` zk3U>sCyz___Y84W)0D1FI5gK%|5!67p2Otsjc?n(5uKUbZ@#p?ZADS4pMfD0-c90K zgfJ6a9}~yx$m$fAxJNt|d35tr)iM!VGqJUXvY!p{I1)T!8O%w`(p8J< z&nYx9%nTh6HoV=zD$4&o>!~|*n!Ghb@Yw21(y_8xh3_AYZ8l#38RPBh<0dA!z90^^ zd&jcaZ;`P!*qV$U0=!E2fwA@w5Op}(MTXi!Mqg+#8Y*v6Rnrt+wAr52DPR(B-0}B1 zP=LZ0^B)wAMz>ja#JXx#3ILq~Sm^w;>i@}10p$T5!52yQTI!wfBH3lImyXx8K=cJ6d=4 zyBwJ;(fJR;(C5XMigM?!m*VujMRufJ&GYhZPrNy&6my)6Rm@#*3oK_*#0 zsyps5Bx8quc0)WxfSp{!-Qk-M>E!Z(+KIa?TgD)VF2Z0H)~D;GIsL<;#t~{;e^hvRB8j@8_2ZTGMw~)v!N)$j-UvrObUNJOgKmyyM|-Y;3nP~|(USy{ zEjY}reN?_XeH_h8rjM`57>ZK|SXwrxbd&vqC)>jM&_2-a``b9p=ykb(y+PJ`O=EgU z(dZVY=YF!_BX$6YEQFA?$SJ;Bs+g9GxMj2E9L;!lMy1F7o1*>Kh5;Iptn)5iNMUfP zQc~Mf1T>P;n1R;9;2pWN;>0dVS6!}sYp~<%H%~gEN=q%V$9=O#3T zQ8!iCbjJ56A8HcTCU9}4)nphBH=yu~|XRA2r)`*nL=H&GCy!`#CIFWdKOqdzyKy|@Dw|bJn_Q_Q#xUL8tY9O!^ zyvahm!BQY!32b+bA0E_-RoCxDqAK6GrqfSf)v(VTj5BMq!5Nk4rz4 z7t_6U`D>SxwEAB4_~=tO#D1#C?TN>^v*B)4m6**)v2sGV%Yo}1A(hNfy*bX7{Z)Uk z02!iFh^UfJq3DIBfC4WW`zWAJgFcL7!ndR%DGP03yts_na!qp(dR7mO9BObL10M(q zC}t6V`O0Y*XeU?O@v(3jYjFeq>!?r}I_jg8mGh=zJK(P;lu%HC`KLmfJdvvghrTdA z(CGmOmy1+%20+*s=*=$=-n$GW&YT-h3B1->h60;xF)xRHtxumm&7Cwo90G3vbl{nh zo2@=s2D+ZBac7mE4>kY|NMG))&oflWrwo(Nl_J9&8K2sVHxMcd!1#aifjGe+Y#6{> zAA87ur+5Fz-GPC3o=exlPf<{)0I6fL>MtfLx?~_FW%0c8zX?I{Ck6K#*FTF)^ffOL z!D1=AA_->DpTfo%de4yc=7S0YdCXS7WF@;owdlj`kLKhahXbmnTBL%v%Aa+d_M8CV zq`yiT@0<@x0X7;7;}Kq$nJR%{1SPVAr^Xd9Ao=Vm?^b%e;MIFgfx3hGfc|5vQWJ=1ya`|Hm?saMNtCZ@sxzX0 z5$8WL=npM``%xcv%%lZ6sX43G)?NSy9cM=0N&Y|F5KcLzEi&J}o=quN1BMEnXA{xu z1}LPzA2iRy7r-picRlWXMCA%3@KZ#TC*P?$)9rGAP&>oAKF?Nkn&n>e;PjDnRddD6 zVsu+(eM)~1(5OzS0Cl+QC#b%v1COsbpZF*=5y=0SmR%(+(D=YtG)HgqmzsOsvn@I( z(%a;$Em9LjMJ(|A=3+cgj==P7yp`O{U@Kr^M(24~vJE%NmH67=9)ca;2jd(Auz;h^Avvr9a`QI#kfFov1f z9t}5WGgKIE`x3K^F8i*T{ZC*Jl&HtUWCiH)%^R28X@VM<{sRo+iOmxdTBsFeFc+=ok1!m3l~uK(d` z{##Ulqd<+*(7tK}+{9wfb>81T>c2q4plio&Bqsd%Zz#3@+=z*E?DJGw-!c8pD*hn0 zzup1{dtV^Q@^@PJ$ADEA0dF04$SJAz8!7y8MJ8H6d{fsFUxbGLH&FD)b^iNrna6A= z$*q(2xBTC~uq&SXfcdvrePVm=P0uOsex-rpg3@pFIxvv=if;BXM9uUI5W*$p=2PMg z)c(Qd`;+^Lscop;A6-$@-D-xS)-=8{0W8;T^rTwPt4 zSpjHsoa%Rk=wzH7*E%Esqf(mi|tjmIqA*8&w;_YUZp5 zhue|oQl;)$4GMoi`n9}&wfVb=oECcc=~bJN%{`Na?z2XjFP|_un6rS5v*=_Mq4aky zjvZ@^66&4Ued>l~^8(TX4UH&1dU(A@OdE$&R9l_L?T(Kp_1FN)@9zcwDzT|MHF}4D ziQd_4JuBn#>DEQRV>G+|xSM9ns+mQNCD2Wi^M+oRYRkPQ%=WM_d}d~b|9R(yaQV4& z;f03cDHksM{;*cdploV-zD+EgztP?haHIE%z@Nd#MFu~a0h>U|S>K|4%?iAoK}}3j z&Orw?pZ_&a3{ay~awrv8gN;0d88MdTIgJ2b3P<Gfdd@GbZ$cd zG(_flA;l#sPf3 z;kXYv70?IWxwMCgtj?+w)qc$AgRitQ&y-$VV6Xy!gaq}4nNPo4U!;I0$`Lk;nmUz7ol0&3r##(J0c z;T2$Dl#&l>fumbZE6m0S7ln$}Yi_Tja&KD5n}Q5|4y*VjJSM@3*QPGjZlqN7?Mz`W z*3b3|rpL^oisF#_jBV7?1?X=<6Z9GJnJ(=_)Dz)gL1j?@4AkA*edBsGfuGBN+p}%& zT$`E;l<)cx*5d1k%8Mkzz=pCbfh||ViG&;Gk^7r@rUiOxPF+J$TnHFBrpUV^S;{_f<-%lm}(%&uhqy|?0gw$o}K$oqQckq%>zFJr2EqLlWKL_U{Y zXCmZXfcW+6(Fg5<(X!4Kp{;(cRy$7{%mnkF-3_n#_2z!=?oS!4hFXbP-mt=0?XA`s zDB2M;j@uNRE8vF5QS05gm#E86Mml85i<#kKex!1JplgkbWy|7{`-Ib5XuRBmIxPMu zVyd}p;+B`<|CB$^51$ia_pW(hw2DIp9cCUNqC(!PKPYvL{V1xZIhmk*11&cHT@m1v zJ2Jv0$E()sw{OT*Er%zX$z*|KbICoffwhVmrl?1{xH^&SNxb3w*8K*hTyXz9QrNh9 zEh@+qGrM!ns4>!~JNh-{pEOQQ6)+7dfe)8>rho#SQf>{-m#UV`fZSyBd_BTp%XwM4 zoFw3Q5$}fudxwXZi!meF;pgB}L8l@kjmvLcz7yeI;xoP89H|_AIhe-A+y6OGt!9?1 z5q4U4C%-@<^>eT}T=cdtv0Dm+aJ#)Id*E1mGEm0hP%Fuc8#wjXM1*nDFA^1h)x8x- zILzG|*{PNI)Jo}!Kk8QbbOhs07ETu>KN^#^?R+1~EJvKPHkMmX5YExgm4D>g2PU(Pky_9K-up9 zYxFA(j`IRC%7K_2HnI0kjRsD&1Xq;8hg2WJem3Wyx8bT$02oX&`s(LJs;zr~)Y2{F zM8VWTQCNx%!sd*1Pcl@~Jx5b_dA&a8n`3qDw1Bv=K)7jL4GsvJsTfy9zw%hoy?6DE zuwM4-eK`e+jl)QlxT2-}S0c-Dp4{?$E@3^aeoHyJo4t1@YO7DPUEWvOZGxFUjuc`& z^T8LHl`68e;d79P8mDUF{oEbrrLqq(OOi5)C~$UIo-3{?NZmi|4O2kRu?|Gz3=afM z!xYy8i0c(G+1?JkKT~OuKH;KK20A6gx&JlI?DR&qKN&SWNxeOPv6U* z&!nF{|L9hJx@UQ%t%;6Zx`*$wv|%AcWNkmvQzdc@qyK!#$FK;y2(CE&02g&a#x%9a z-d9jtQ#($8@pRN;+m%EGr_yunO^D$y?OSt<=o}l&^St5BNvzMtlf6d;PjIzscb3M> z%l19~1^@ZX&&kZrl%V3_(z{p93KJd|xi_5X@R*C$t z>*e%0U8(r&7rhBm&oneOqYIMVol$;nKV}jQ5*9qu;>3)F7#Y%|=1FX86b??$b}R#9 z3x?anTe$@%AXt9J(;T?T1yPDrUz}Cek*!$DI!!WKI5r|i%=d_IabdQk=%|B(+h44t zVf(`=zb~etjQm#ajjL3_A)+9}UN!2+8DEtXZoHt=^P`#2KdodwLf5=IFZeiaJ~i51 ztuBFZZ$BgTnA0R*Do-~k6 z9N&4A)LvEZ=HeA>AFexvpw44(y8lo9?_g2SO=@7jle(m;AYH6pnv)D83)JRLz6S`v zAxDzln39C%X->r}=RM?>b@{d0?38{$_5~PBc~+#wK{wvk?0U=1%*OCt7aC2S>1R#5 z&kTxJ{9M!BEF?Bt#UGVCP=8Ops-{16ITCdk=U2zzOwNbwc>|!#M{9Ov!4)L7YS0uC z;;U{4@=rO@!ZM2+uL1}_gcYJIPye-wyE!wfD;5i_Bv@7y%on+vP>*K(ga12HsQ#>Y zs4*<%$+Bz;)6t|pT zeYAy|1%ex`?;-o&0;Rk^B(p^Vjq*{XB2P3udwwgP zaRHx?`4h?Hitq}vsM~dG~5O7wfQ#xBvAE;d>ONH2ACuwZT|bc_J{8D%`9z`ljdah^Z# zL6u8=-^*)F9KIwSs_2a}fsfv{jo1XfYTUBZ#eS85b1x|5iy5 zol3Ql;_DhjrYgI;#~2`fEpcYzUl`yKq|`UfU=9LsfI4})at}b`x#~d2()a|JTCh^V zRMoYWr4K@W7mX9@O$rK%qA>-o$+4%j(K9Q)Z4Tdgjr#LInv)g{*NP?VCpvB#Dd zwjcqNGl2J<)LU}`PH?j+bm`L)*M911a=E=LxKd5SoW?fM)0GMoVei+y-wF(E2(CxO zqTQWj>}bbf-}o5laGse?cg{D_{Q5O+GI}^9%0A%1$Z{%aqtfqM6ZmlF82-yrPU)>1 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 OZWx&wmR@y!`riP&a=$bH diff --git a/docs/images/rest-api-docs/1-preview.png b/docs/images/rest-api-docs/1-preview.png new file mode 100644 index 0000000000000000000000000000000000000000..f92a353ddca2df6c8b9560cefbbb1b2d4556755b GIT binary patch literal 157751 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�}oA8VGcZI6s%bbB*ZC!evY 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 z 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 z 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%0DHi|pU#8$M`y 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 C2cXyh literal 0 HcmV?d00001 diff --git a/docs/images/rest-api-docs/3-authorization.png b/docs/images/rest-api-docs/3-authorization.png new file mode 100644 index 0000000000000000000000000000000000000000..c5f868fbb54e6d09d2c3999f66f4f59c643d819c GIT binary patch literal 131377 zcmdq|byQSu)ISWPC`g0SH3Cx7Asq?=0!mAFN;7mL(k%_rB8-T%Fm!iH*N_7YIYZYB z@QmNzqxb#3f4+ab>simW)~vJ6nJf0$dtW;~`&?0KDhdR+)VLTJ7zB!MUTa`rJnX^1 zz*KmIg?@5z_X35!JaCgy)Ov(&{*Npp(f3sDa=PxC&erZ;X0BEkHcrltR$Oitu2xn~ zZXcZ85twaK=uT{ZI?1|PnYr6KJ3ZC1b+p3JbkFDK&UbTlaWc#2=j9jR%;)136BH2R z<&Wv2Pr$%0==lCn#naEd>XP0k)Gb4+6au$$-kC3`BlyE^}jYs5VromIyH`#*v$bT)H2DeA<-@pxs8XNcjjD&^D z0RIgn5fvtlj`=sRzoFp&rAs!~(0`1SFbMC8{2<5}uURdD+3sQZshx?Fl#RTLbs;e6 zEOLSzIKwo=9cL>bS}lmx`BTW-Dd2bXC_sAtpGLu!a45i{}2<{1vTXS{z`*@#37xxZB`2Od?H zwbfg*C9NaKhT!J;R?Fng9(*^GKY0Xuv*< z#c=g{+UJudVEl@gR{n`!R<11;W zL@6m8HVyV595NdTo|Dse)LmTkd9CqHZ<%$!u9CYD=w>Bt$|n7Mbx*rJ*IVM|5`h$BttCH}%$A%2-y;nA( z&?$oPHh9xMT~Dp#Sb!0|MdA$NF7O0Szq8|HGCdt z>~%i%(}!XMA0d~dsJ$t?_p~;d`UT3Ur`ev5P@;w({a>0ZT^1{i6Gg6Hb_nAcIunjz z)X91sKE(1N?Ck+QCpDyhuq3o%S_)Qi0?!Is{V3x3x=%?9j#b`E#64wmM62`vtpYy1 z-<$PE(|@WqwK+c{)LnPFNK}HJJRc$w(@|KF&pxBSssV1XHF9GJwFnTR$?jwej0qHK zeHssbX$Er&D`AGd^M8|F8`nx53 zcG*eOTi!-ZQVdMXl8$gjJkT6OG_2#bYTcN z@(*?_aLHdiW(K|7PTjF;IXbK35(^3H>o@tfs{IJ^xLot=Y6_dT2V@QLd&tvT{nFR!`%RKPRJpkoW-|C^4)Nl)AY@Al4A`{9H1*Tr;BElZHa3L4&2 zGGjxogT=*pk!Y@j^bX(>j0d0oY@2pHxI(W&nTJEujmTJ=aEx!Xu)vi*@g5=87?%a* zL1QqwF3*E7~3p&bxM=&MLXg<2%Qu@ssCgMUuA5URY;1XQu!R zbTRT8+!M_a7p`Aiq;VIk#cMv1@mcp3vU7!QksswMZGTSPOV79fr|&r*_8yGhBeJ5c z0zwIdSek#WQ1*7IQl0y`BT2^DSQG`SCHl-=Xeq{s*g_dLmBQ=>@)*92epm^N@w;hZ zUcN<9^KeE`a@tN6PQ%9mz1@mJf!|Ge`=;$S1Ve~w!pUproJn3$$%!ByMiMIbW19L*i5E$b02Du971%s(RC$w2 zK#!W=;tHRqZrw9&eqs0O*OHDzKCxj@v!v?ruYvwgdpzsXx{LDzon8lC@n8M2)W58G zr+;tYQ(s^hu;8~}OMH$vdgZ(PxYhBA6%ILX@$330y)-p2HA7Yj)YU)T5-2)nx9PCP z*U$PX>=#?D7*)tTrm@b+9FOI0@NOoA|70kJGwmjzbn9ZpS;h-0b)jD<*^-zico_?Z zyA<+?nF^#y4E6QBpq@bdvURvjfsyMOaYFMfg`AicmLwBjtg8Lwsr=mSo^@nVv57Ah zkmMVnbLsmnCz((m($*%2s9Ier#wipu6Wp$@eQ&+f$&c5=lvcc${k^4QNj~8+5zk>D zDZ}isz`o~)w5@sX`~vc*5tVCzaWZQuVQU1TIlQ+=|FaQoVp@?w3)PV$i^2^J<2jEbRnz(cgq&B_ z5903asGr+wHeMiHy)>Q%rX7a{o=7<_*{c3rm#SOB_x0oGxR?D|e;%a9rJ13H0r1$7 z$V~-AGatOD_i1WiC0?nqoUnnOOHy|+88T!E%ry^=HCHSL9ecl^T#d=OSeOz#D`Gs$6{FhQIn$nW zJ{^OP$I--AM>;ggKo&9t?SIoXzml%`$UOAr_55di?7kyDA?6`*d6M0&^2scetgH-pZukT6ZNE6Ki z9i0-ob?{`bBOI_^{wYoz(n8^Kppj#mhlz*xFuZGgA2YK$PSGDM(@`p*w3rY-a!wV$ zY}vN7u+KuXlr?G0Om!o4L9f>~WIAQVYZXVQ=NqBz3;S5qi)&10lKL-b9-|FgNAkYP z>|qAr%{jcWx7SFmQ}Ah(x0Nw*(0t_iuq5q!gOnt(Fn5@1rfWx66;+{G-ZF0v@q1Wo z-HdGtca6puN%FBtR{LN+nh@y2ltJd`u#Zm<4-K*VC@V#6zwlC@+k%l#er#|RYR4=? zo=-yqE3IZglX;X;n&oL=AkGNK7)3&Z%z16#R~@qemH;i)T#NiYsp81{)BqB zDW$;C(0$vyxRHCQ(-Zr`QuN>8SYWkphNr-Rs0d7~!U18~;|_9~CI0kt#g&+z&&EM7 zlW2F4IG3#oRU$12&)Uj5R?;ACEj)W0$p?S^nCK^%2&r_quSHuoO2!s-$9JlaIU%Vk z;?6z|(|bfXr#)lgX0J5n2=1RK!s85YV*341zRbg^?BW9JNT{H8-m2C8(s;I)gC8uS z&_cW3gjJp5O*#&c(&M3H{pq%*l&CbG)tHm7makRLtAlVs9uS;wOwE6W^Mdq6m&>JW zE0lvYlu5v^Yf&yHuWDuLMa?fS<&=Eg!|_O!6>>Dg^Xoc`rU#kc&(FKWEP8#xzt}iS z`!)HsM%Nt9+g8w9SnVGi;}&K#`;^tL%*}5?g0Zk|+Da?S#+B5n?;gz$4{ z4i+a&>@7TaKT}>_rNN_q*h>b9hdoIv<>Y?PdOnq#s`Eo*k(D^ek~T2xy8HP>wt5P! z8&i6y3hS5pcVNSUWHKreZrQT8V#Zf z^;3#5U&_Dfo9pW_=b}r^)Myw!_T-Q5q2c!+Bdm0#mQO2=$r86oaa8yMEE+E$;Kv0#$8^MvOcqwPlL_T?w1REezzawsF+N8US=TmO+7(Hknb@_gG-A1sh?IU z15MXju6^p6?`buEtt{A+FZ7K1NsVWF>CAUQEO!>I7=><%e|%RmJ>S=pL?|XGwCEl& zkXZV|G1o%0+>bi#`=W*UEj+bEMFe16BvZl%F__LH+CJsCJL@W5r|(&pYO_{(Q)Rl1 ze@-~Tg2V2jW|Mp5iA#FHezuZnGZ2dRq_1YAP-eBJ`B%FOB}troH&7`pVbXsVh;u)o zQf&?#aTzE9>i0jQd#0Db=15{ASuMc`R>*m$+WRj#R3Vxs{Tn{3u#rlWQO$R=KK}$X zI*-$fi-C29_O4sb?-Pv)hIKxvRhTy!bvdC23rEoQK_wE(0;1{0ci<&)Si>TyTz9Ev z{^@m=o0bxh5S4^)f&EhO-ma`e;+Y6qi80=t?~ZA4fNs$t54RS~z|5s1k>eI3k&)`I zu+biK?~PSI@>TJz+(Pb( z#Igm;E1sQLTIDKV*-IlzGOc-bwb%66*K?2npXO}4_bdeP<2oaR`{-1Z7y0Z(FKuPs zjj{B!$-nS8QQ!;`zV6vJB|fAg+V0^(i}|E;2G#D#AbOR%yL?b4HX8d1+#$kB7RCB2 ztEDAuAEOskUD@tm`(`@DT zd`?CfL^^_uO@@EYdO7rTc zF?3C};l?yMgZ-elZz9xt-IQSYS6ptfL%*r{q?0UghtWQUOewgDgE#_6?BA*Ll;-yi zz-!xy%ERxizY}cgeep#yKsgF@mUSV~tfzS-n9HwPXN7arJ!y7`N=A|g{{>9?C%34G zdOAdsi8@#Yx+64`RQCh|+_AytK%6f2d!7>cZDTGIfk8@-_K3r8Gb1vE-hs5E(v_As zj^;_awk`Wo&l~*!X+E^;^f_y08b`6OoJDR}-b&;P^N|XBhne05o;1xzE=vjDJI_%F zll4&io2rrc6ic2I)WhCI5kRF5wvX8OEh-yc*_-PJV$5dJsx5@BZRbZ@%IdPe3w&8f zS2exO&qpzKEm-$;fDGXjrF8U@>8L6SS|ggAhiMmOVBkKHyl;{7`v70{yQZfSSU_Y- zm|(&wc`LU;WLXg58{yng zhDUhy-F|+diy39&UIP@nTCx-q8G)d8rFpbmoF4xE6z6Gju+v#*H+x09#2=iL}9#8Z1Id7liZdruC{ zWP;!+qt-F{X1VJjO*o?Jej(y<0nb4RvXDXnK3gHuG;X(mVpc2t>x-2wZ9iu^{~5&i z*r1jT7qpHE9kMYSWZRTKUKdXjq@S2~n8?;%qSN{gI4@R!tc{Lj_Y{f#kOQP=d(T;v zR>|26#yzdjFXDF-ZTu(r8pI#Lv!}8*7&SiOuw+`GAvu7~C9@*rgV)&-jW^RxW=T&$_B|OC;HEA z9MBj=o824Rcvcw6Cc5JUPx~%VgaG4w*S5y#zK36Ahf}dM?+18B^BZoXWgqb-xh8Vv z+DLz|hI3!TC5+Rza}KBH-cKeVeV?u?`gWCYHT^p&p__`);Ly-8 z-Mar@-bG3f<$n2awvE5m$*){QCG#4pq2JiP8Fqh^q|*^p-@af@a?#&W-%(NK;^CN^ ztu2kju8san zTy~vJYXB}raeL@Q~Z_P8qWQz zf9RBzkE75q(6#j8&OX@c{C4AQrCniMJT+$;uz+|~AaN_n=7Zb)7x~>VvW;yQ_^tVTlJ-XMX7-g0SP|%WvTd9Fj_Gwc38jNl$K)Uf<5%%Cy)S69wTcM zV|Zbx;82x_ci_tc%E$DLVz={V5n0VXHMQWPXm;RQPt258l2aB55mPu&=1T~)(L3-> z$@Z9g7n9TSmORtKqP9UhXX$~Ps4zi#ROvO6+69#*K~ zPXWD7c`j8{L*GA)Uv84W5BO2lr#aj~qGd+nE8O*R9e6=DwC z=XrB`!EtQ7(ZAQX)V84rS;!7FXM2xfZ|kA4fb)%9V#Ta#R|D7=!=m1M6R47ni4|>? z5F>|aJ9^{P`?Pk068B;H<`3DmS1yiG;p{Y+%DAM;^rg%vPeZ}BqwSR3BBB>GRJYk< zougC(Zg7XK6bi}R_yTRg&oBqRh944fT$zZ+l>rhU!tbnW;;4~+mLeW9RG6uH#pAG;`p|?KveoMx7ie&}*0rgJ&gSrSV# z>MaDCA7Y;g;6|F3F^~3kls#0kO0Zfn{aG}xq6eTXPXUK4Nr2M*esYP5px<6wsp~`! zrmJ5*KsbHE4>!vYLxmF)$m7r5o90D zH6s}ei;RjZQprl&-WKh_G(^pY+iKw7o&WmvXox_JEL5Zqht?m%;(I98SnOS!q3ffG z>~T-^x_e1eNxHnfYIE_&aWFLk{P=rN%B`62XH^m(t{iE1nX!pnBqFYeuhm^^SQg&h*H{9eG5+_n#+biva^b4{|KZd9}KrlN#5r~h)>mp z*!6jRZ%8wiFa`^J((hq*?}dHU_H;3ClH_jpDsisZ!y+_uqH+|ry1+oVXyAsf`fB!@a<2Q>t)1->Zkp6 z*Y>ZuIo!B)hg?1b!C55S_0L*jbN5_JwpOY73sY#ij8eyElHh~>lf&_)gH+h_RR{@x zmtsCG+)8@AA5JRkO(`}%3lq$hi5;*cuZGs(}e7z%41`84rBQ z7#O9JN8S~V4$C64P$9l{ezag6_=5K09l-qwbrVHqoykA5lIXTRwE%kE6kpN$8h53%K`;vOlj6;|kp-xBqv&YpL~bB4^RE%>Mv1HY5zFOEfV z%}Idf!IxnN+I$$cqci8a$?Ec~0$QJr8mI67@}nB}R8ElqeUEA=aWf z;}%2@bN;_bf8GOCm!I|O4JcPga}m$RI+RWK%?6fcu8Cr;c(F-Dg1N?dEm|z9C~0ST zO+0WgD)xUPikr#eLXN)L@D7ych!K*p!aSLn9!4`K^k7tqhIFg_kPwrHifg^?)P}nN zy>uPi;Evx;!FM8%SliXg#(nhx*YMuT#?mYAqV+^iO($UuSA4Va&CYXKk$Z1fiF?_d zJs7<3&%Pj6&C-ja`!u92S~5TDy3op2Z9k?bHKvKUQX0MSlv&{uiDx(^Xfg;#fd7{? zPTHGM$3y3IP2#x+L0k?L@4@vJFnXkMNyvv#0-;dC6t*9sc^iJk0;& z>djs=m}uZflzV2OhW-6QGFl;dcG8)|N>*7g4x<=qWh= z)bkT9K)nBz{H+UI(AUvV|MeC6KYcgYNaN8|*}9JUVxZ^tS9|)OD^pcMu%pKde%C;c z$nCccav8^F{zFC$Q2#yT2Q_-uQX#e*z?2 z1Z}v(n+It2WUb>29Hur##+C|FbGO^A(;Sx8&cJn)bWkDa7MF3`Jfmo@WA28hY8;&l zB2Ktr(od?ZAvr@iL8RlvCW4^#u))v$*ka|hBx4g|bI{ZrSg3fKqS6K>EGw%`K(YQ= zeJniL9{{=tV`OxFtkS9>vFEynw|9DR*;8F~N+!8w2NlV_}hcK1pOg7w*$E`A=OF(@tgrf_JfCPmq z{SGP6N{M%MgJ29)Bxr0gJK(;M`Ash!R_&0X0siQzAuTN8Nx<(v8t>Ce>xF#sJ{HYi zp!n7IF|HclGk)=&Y+J98MXrR+p_3H+kM}M_?(b6R#=Hn$hw%46=ZqIXlAM)lV;{W2 zEjN#G!efXUihQ_JRLm6av*fo{`=6eHVUUuxfGl7et5kaKDM~V(b4F^>c{_orTbuZg z?2b{3H@OH!S;vP^G%vDM3T~%6cu46{19W0Uf!e&Leiv6LuC9d`jufxk02)Ui^x)pv zUix~DD(QrY}UtuU%qi19u!%GADjej&n)=Sk#cI$rqAK#tg+weY&~ph!Z!G?-8>&^`#`!m7FH!nW-E+7%2WCyRhz>|mOfc6e>z{xt>iKr1~>uk76q|6Cy( zo|;NGt3n|!8ZO^L+9xTxhDO#>{vr%SVqOVKAC{Zt!2X%`c()-Z9!)fr$DPzC^q(*4 zZ^Bq^i#UFg63m6dw^*`r7=U$dDrvfq+*QxH)e!@nGj!=>guCm3oxKhq_O2lNgMA3n z08_p}R;|3|mkoVhOJVrD$=#XB7;@z<@W=EnU&4P-PA>D3Q#t_E0obqrAm<8Z-}9ms zwQsY;8Fy`l`%p%x01aAJ`5>jZK)t)E?`0l~#Sy?EqYeHZQ4=aGLUxn5I=W4*(avtJ zm@NwDrUPZNK4xJ>pCT-tT#sN~AOw#pxHPiQ5oL7a@MkIMO7(#%WtDPGS!#I~fO$`d ztw5to;vR+n8(&CM?I<1Wu?~gj{dT>yc~zM`XyW{nog-#0EY-xNkLb zHcr8{98y=NF-XJNj{1>Vkogb4pBtH*X;kF8`v-h=37+P#!ewEN3YVC0 zx;+x@d*yca(LUq6-mCPLwt=~$Xg5>Q3S<@TIJCLsc6xNP72q4klJiQ%7F4S$ls_49 zJa}n9kWdG$d!6OgFwZ~CWnx;pZC;bH7E(NmW8ej^w%Yw^sL$xmRcM@y^nzQU3l=Wz z@4iL2HkL_oQ1BeZe`45iayhxhDm#39;x~GAYVQz%A^RnZFh-d|&t2d;YtI213P5NF5;(AqtZal#>{8QnYR)LPA;V+ntCn$`UA{6FZ5Po+XH-)j#zQJ zr4NIN)VR~x$rCpH#QqrnsN18O!SOt9?&!;`n;HIfbO&mtnX= z93IVPS?B$uzm_CM`g1;N@U>q^e3D7DYw`bedu*127h~1=G+!&P5Dt1>+`Egex79TG z*clI-X1vp#=eKhnce68W7Lig7M3>953bp6XiubETZ3w@VVjFg;H_7p2z}7Xw%vaa2 z8QeJVw5sWImXbG)8sMqlQ#o7Uhp#Sk&iqc<)w8DVq!5!3B{r_IY7IOb|2!F8>vE~` z$KVhlgF?n3imj4Rsa$|su8B26?2bD$6JUr(Jj%td+ULn}=4i-C2O;LXUb zZ4kb9k|!%7=nhF1`3I7GgwbQ3=-M!hHbA#b&a!2f=nza%@+@_I@*D6iJdD%}5KN(Q z%C#iY;UpZ=PV|T{^7ceMJx)GmnU`V2>lWzo{oSBkpZ#ydY31fLHrbAGky6R{H_2=o zu+|)v#@cuUWn&ly4-Ma-DG1ulIrP>FcWU>cQ`ySKh)R@3$(sg^VnY`qz!yo+a>Lm$ zPFBoHzHv4i!TN!{tb_!HXCoPbG0be0;)TLt_X}*F^u2UB^lWjBTbL08JH1X(l2a;r zJgr1>_Z#evZ(O-&NJBCE;_~6$+V8lKJ(*lsCFp#KpPD(tr3u&POW!Co*v(_bK0|=I zXYN&qu(9*LXs(i-4{-uKbB{aKF7fP){-*iu^uV@9gh*<{$$4U7jD@^VzHzq1&ct}6 zU`+jqyz`iSx%64O)%}R}6-fqKLmOB&;QZ?~sptFeG_zgItYcizy%*4i#Tz9`jb8@% z@@c&BZ*a+WH%SiS7?}11Xp0|gy7(79jf!%7DG8C(k?8!*Ow(gY3bsj9!_AvpGONJ0l~1Dd;Jw z^jZ*V_?};-tPos~GA+H~m;TpPQOZRaoM!JWSHQ?MI;FD>OrKp$Xx;D#=Oj}m`cx+A zRq1s*9<-r=%_ETW2TJW3{Jd=1@A7-ixJI$^S8wW--a>^$b%{dyN=DLffYTKYFBc3S_OyyiY44FFneQO};E^Z!6N4%ysb|CBeD#^EM#|Tj8X5 zR7+;Vy!0d~X@@eh8J?8A_d*htfdkUs;x(}+M@7T8LA{i;*t9VBwhgxwCEE80v>r$H z|BRn_Ea#~8M}M;ekfePbRig9dsAsCl3Vwo^a|!|iJda!^B0pSwvhC*Odk`$`$Ceoz zIq`A9KkT<#?;bNB(p`mN$CIl51-Eh2@R`w_kpY*5pV4(wv~|sg*VTSYA71ZbJ%F#J ziAFvlEg9jeZ1jv8I^k9asY*DSxrMe5qBC#Gb8Nqgkyq;^+bvXBNS*&@p{h6C(?g`Vu7qz#$X?LgrXOK8#bOM%RqinkQI40{it;ikcv#7Vh z6P``9Q0xaR*7bg$k{`=a!7WxW=7YXNqc6Nu_OJa$A15UBk)LL^`Nt{u1zOmNJzW3e z4P2>DThS1T%4BB5da>HK4~$|tKuXKWds$gG3iKG;*Yqq=l(8DsoJ?R-r59VDGDiH~ z`4)y+3YwnWl4Dj3LcRqKOnOTNC-ZLiK?Am!zR=_xNG&8ka~C6VDpIN?R+~FB(JfQ6 ze%S=(cp4)PS)t`s(p(QrMvi3U8wdQF@JzERt|Bq`6AY37za++opN3P#BUG=bKX#nZ zR)2VtVri)-Wf5Gi;8+koyRtDVpKg|&)XjvoB(z7fv~y1agCy%>5q~|!a>~M@<(>Xd zXX)>Us|PGgT+|2mx_FWZj;n4c*Q=Pwr5sH*v| z8ZKQ>J0X&}FW^q&alOb`EJ-1R@DANvZFhkd7Zl$BVlQ_&J$O39qmmgWn)eDSwU-kq z@-C|I-og20co_SP9;da#k^yKQkoXO!@WV?#x15m<#a1fG-4{~34Kx>IUg46yKEdW4 z7*H4g-v`MDr%$k5hK6Siuj2^5gk(IU8eh@{QDF~H6ZszQIY~|XCjMOd_JaEEAYG1& zx@CXdqL#1B@1lM-P=ZsM>e}>=&=^6A2x)Z6`Rk9egNFyhBAfQWSE%9+yy)R+`v-gD zA#&Nrw91RO`KJ!Vl@{#$RMmciOY zC)~qE&w2&3eIQ&A0e&+>!E_zNTr)WJg&fuMVCIj0T(6%;Q8tPew3A9i4WMUX1hzDpG z7+IM$>3boL46UnpCkMnODmuf4e$UOVFORTL5gMymn$-#g(7Cl6)?ypVR&@4ogpbI_ z#4Q?pYv?$`?9_-m=HwEMCi~$OQPyo!)wt5kAF52zu?9U5FVwl+(9pWqFDOQ|79cWnklZly4=h1U!9a)dSA zuDi2wnQVNut@J?%#o(WDNuKCk&zlTbt=7+R;Epetqz=HHRVedg9kp*EB2i=3Ftugx{py zUG_zDs2WX*)10(v6H|Dc`U=g8HsL@)mQ;i~H!gmzUR z#XqMbFs>^Z{yZF$Y5|dvB!EbpS|lb(ge^{AN9kr05~yJHSIlnjcMt~^7USqy%J;Fl;wMlFws#^+Q zUG|y4R9jAzkH+jwol=L|_UL|TV5D=L(Erd&%9La}>C@sllruRc3@3Ntsn+tQRzPz; z;t0Li@q&HD(VyRhGS8piy~EPB>(XXK00J}LxZ>p9%IQ1S>O0%irn^+vlKm_5*ma`FN1S|2R4C!7BQl@AU>>VoP6kSj?w?LIa+n zc>n3meA?2g1t2J-`#xo-vi%f%8Ew0oubeNpLARtPXVa;`urec9UmJAs5^fS#McKJ> z0lQ)iy0F)UoQZNGa{!wLcM}P2Oqg$ToG%SlhVD>s#+#rE9H~FXlR?*x8`d0Z+7 z&*4PSA${vr3t}A|*8rZ@jI3<*8Q<8TVoXpHUe~-{o61+Rh@0eQ1dZ`G-;A-`x;~f* zl1=*dNcAKWjpU6}z0!qt;+b?J?!Me*NFM=ioYHIp6cSfpu)tF$|8=nQ;noO2U1NZ6 zNCt$X%4Ln;1Vz@Ccef#Z!pB*%)8!O8C*d%JitKY+)+uN-mG+r*Qr{bUnd-w z1p#4S$gURJuAT=$mjZ5k?hZ{(E~IkyrI`G06}Yv6ee!~v!?(;6v#*>{U~n*O!_E*?<8)GL(3BUfUEH~)gE#hiY8uf6(Xi-_}1he^q=&t=d&;NGSBp|g7 z`JyMpFB;Hwb(J3ElbeT9xQk6dq4prV`)-m+9)UYdfGt*IB!LvtGvxefaQ^E6+sq-I z^21S{0O6J6ydY+KyQgf7)fMT+zEQKresL9-(G~gAc1Oz>trQ=%OCKKQe?l9y4ZWg2 zxU98n#tb`XUWNH~MD_Rx3~qXz^%!wIBi%P0gaThC3JX*Q1Rk+U_sj%cM(FW=)Z3C= zIow3GSKROi*i+psj2%}9-|`}i<`t*;ZB_M>K}`hT{fDyB^Q=%>KPde4A1jD zpt&+>+Y3M~v+vZk+_|9++EBKEaO3m*vf*o3P#6G--PTjFj4DL|5O){fhj~@Ry+Z)V z(YrXrot6c%x2w)LnWpUs4{|vY)TJ7@o^>^fK#?1NVYVGZ9OD6QDf8xh9pWt|XI8E` z_nZUL^6t7pmo-6m6-S^}Z~dq?(QzTh^JShxuiJH=69KOYY*_i#OvOneA~3{Yeg)dp zy0acaLsNGrc6aG~BN@0l`EEjCbc|d$2$|k+wV1b62nY}cTrLJ>IyVb7B&r6USfHkz zkz9dgwJrCcZjd$^kZ6#Xc-n~@G8uK&c4&{9@U6Q$tIYC81ziEIMuS@9TK!Da6MD<& z;|!dS?c1C#2c`cUkh3J`X*qoixc(jCy@Fisi=z>yN1I$v=9gWzbGgB?;}J z65ZfGk-^fLk*Y!au!c4x?mev_B9oKym66mYovU%-m1jNtsA1MCor~ozVH3fRX17a- zHKHl$kv@HLnxM42>)AcjxOA%+;dIit_gW8*b#y|+jcDJzp0Ga z=&5~Z_b}ocxC4QLs2-~ZowLYhxx!3Z2Jg-Ycus;V9_8*=#*TH0wy5mtogC}*O~f0o}lCO zOGELlg~+j+Ndz=v<;=)`F`bTAWf7*ia&d7Lk!SZ=kGF>d-T#)U85RTUhx>;E?#2^N zvdXe&oKchjRPG+C-{k7~E_R^&3(~Z<44u~Np{r`I@+vWtPB4jq^Bwt}wBH3Ct6YF| zAnJt`^5DQ2wk<~@9{I`WfnP%J`7~SaV@=L0TfyGB7cAPGRTP3Ob-HR63LW8d56Oz? z590UyycWHzrP`#=#rz(=R`Zbt5CMqhvvRJ6VJDgMOBc;BNgnAFtdm{G>}{}w@5Z(WrmM z58h7P^oa<@4H{6-H}}6iwf7I0)2b7`M`kr@Bn%v5C76HubL*@B{nLcc>eFQ7NO=kaS2nMe;l zk6o=|)x6RD`I>tfg0_z}K`KkX;&xeaa`6~Kx8ol4gb~Z2EK9ajy*F=)XP(x{f0&h= zXEt43^7E>@)Oom~kDGcGuVY=lo{=13iCGW~q^(vZaUTBOrB1#w?4Osa02tw=(>PhN z@U#y#5>Nmh-ec02W_vLh-<%PVV23m-a`}mGJ7m_`?W*6}lm`1j=R$pX3B}z97P?{m zKn~5V>pC?xG12JHQ%$6eTpD?P{eDhl_<|!`Lx@8vx9^K)xBy!pLUN>qxvlkzT7@o? zz%VzkUlRqtP(5~(FW7(4eBQ<*YL7J9E`u~`UT`P0>BW>`j0}z1nDoAnpa5GdB8IuI z;%Jc<4c)0<1JCa=e6AnFb00waKn<9%Ml5B4lFXJW?`={4zgp??qQGag|+oFC> zzZ?+k_7lhXF>EgHKFiGxz_1|*nC@BfMip7C*?RISyV9+XV`sDCXcnZCWXHiIxT{v) zfKm(JnGdSiLlHQ(5V6MEwx5i<4I3{tPEXK@9M^|j=P0&zT!ZqU1^W6QY?bTAXnIn* zF058MW>yuqHZ1>-tZx}IzUhZUydD!{Aq^-8nR1rTAqz}AYdpGx-A(VI>nVerw zEE6epBccpq+g%Qb5go5%)6I}%bxr`7_QT)O-#l9huqa3wNfNd`I>2c&r+Lyo5|4e* z^*cScpi^5{c^Os~T`1yc`DJY7i*gQT{u-5d<_)&TlETSi5SY!F#Va|2I7M-V zD7=X4#z%zy75O61zGvJ#R&7R+BA>}y9ja$M( z)=eFXXC=_$Ui9`l^UrE8vlwIQFIRAbR(rpXB}&IfWj0k8Wew@?GjYi|Yx930A}vlj z!QSg_HJ7G=4>{~DzPXJsH3ctV$-&oQ(hf7}qIUd!D*et&(OK#Sgq`_kg!jon%*7aS z!<`T5ZVG)U!7K2C%=uOG?i9(n-Ep~LFb0`L$1F$H`GQ>;k4f+6fo#DB?-p2W%a+lt z=K$t#iI>`kdMwqg<2_Kda(!W*5F9nKpmsC4a>R=jXBi_A7tIp(Pcwyy+qkIv21{>V<;0xKA1l5d5Asr55f$Rm0 zp~U7EN&m?ykEJ#|vm#*W3l*O4(Szdsxi1$#iA*QHaWw>W+~>#LpGF)HHbdvFK@N^s zZbOQ+zk2ZDH={Co92r;V{DCj>gN3F0u^x=y-}n6OL<&x)HW@+ZaD!!ef-rm)FFR6g zmdU*?B4nC%M_c(8N`d_G-rlv$!mc(`V+c7e2^?jhJ_O3wbbLY0P?!+9VdX_I@u6 zAorYlZ%W!2SH{RbXuCiSgkAAm|0~e-Ad%0KS9V4K_h2fhlPeuEF#JLYm!QyHhx-~i zzi$L7`EV|u(?+-Vhs6OB5Yax&{;c--Ac<=JZP4Fu0X~xnw~c-!$F`CyDc61D(IX>e zB{U{^`^d+Db};o$B+jVo@f))ouG~qf*zRm(Ro>3pYFV@^B+VX=pV2J<;aWB zZhbF|UkEKDm3hQ4llOlN=(G8u<+bUDndeWxXdsq{NL*6?t{ z?Q?Uu=*?q#12fq2d1G`?Z}J$Y9opbO=%eqOrl1|13-+lOjA;Buv7f(y8meEAZ| zc37)3{Gqt2glXgZ=EH06-^JmqJRcR9kRRW14F{(i_fajLlD14AlAXRUY)%B{`6q9d z-2=9G--j6nVnxKVGn(3UFW2XGRorE`m)CmPl`4U@X*E@~$_fHy<$DNnM#s#iei^D- z4WB18l?AXj(n4W$}G)O!l z1lyCYFitFJ(Xst@M~HrdmIx!{o?l*1$dh>M4%kUX+Xu4JA3yXOPQ_dGAul!9zs4A^ zjoPqQ4OJ*OeRl9ho2v#pyiY_lLa}-^)+B@x!46j`RTh2K{#UMO7sveyh_+kOdXhIk zi2sOYzLz7%{Ak1;QTb~HC?U5I0`}pVn30N`2spQ*2oib#(`xM+A@Y~0LB|3sUi{)n zvE`hfv#G{{RGRxrKo(!w ziJ7+s56}h;vKzV_i6A$yx8xR_%upqY?0l6l_U!MML<~n?Ac*7C~e-g-50Kv#{)!I-3SSvL`OV zU|-<3`Me*`(WOD0mCUa+;^cBJ=Xo;#fIcyF`l%BCcN{dOr`I_cpET%3E$;Z9|v^P94fkj=>#n>*Jy%qE4l-v8i zSbNK;xVoiXl!OF=2X_b%+}#@s7Tn$4-7N$Q?(XjH?lkV+xVyXF&b#+__CDj@A9tK_ ze$e!oy}G()&5~!wz4OyUl5H?p?(e{~8SMXeor4w@kf#GD)^vP;a@|O|nlnX?hpUIts9$8yu zYU<%sxYBOtjr6cYeMo}ds9+^jrB9`c6-7>e#;8385p0++JtbW?oxMX3 zL1{-)$eML{o@yx*-oXVPKmeRMZC!@fT$4+rN%2-dl6zgqS_(y4ApAZU?zY}^oj%(* zq1XKhhwc5PU9a2$M(O9@6XtBP4NX2gKzzWG8{ia^FE?8Q`LUB zHJoE_Q~GS`EplFi5T5BNWK|)}7+5=@z0331M@92lx|hA}Vvv1_&E}QbIkW9ez^?9_ z$IIKt@uGHLXue3@QWmAm_HmL-C#%+0PZe-J;8Vk?XySb+s-Bu~;nT*j{;kJ^{ep)U z<_z4O$qtbLcGcSTLjT>fWY)tid$AqA8tbUnp55NZCTC*Dt{);d&MsYK2ZZrv#zUeu zH9NU!2!crGUE-n<(ezz{UoKIvW?(EU$@67#?e1B0h=hUymf57s8e+JVx;Er}EX)`Y zR`Z3>CM6}wMI3Uz>Ud;+{>zCuwfO(26CY z_Q@9w+n#l6y+jx7{bqK+W@tdEDysN~>lFnBMV8~_7w1JcyjE$vkqba*joFS2j~}R# zb}s|CrhnF>uAh=wBWJ*Qqe5=y_<|gf*2;3v?YGTwJ`nn4^`52Dt0nCzENCklRQpaZ zv(x8W`*>QoE}MFtPS?P>t6#Cf_;!8APE#5lQ=>GIyn8G*g4;{^-W0F3=ALY_{t!ox zp&~~p<;N{{I4O5hw{Pg})>jd>5{E6jZtw<0Cb@f#+0=Z#6!~CoL{c3#)}o07N_x$G zY}h-f^&a~5IrPz59KAjoBPB;X?yxY+^NYd2>3|%NV9@`Ayp-k_B5#@mI*ovlOi?+x zq+is}YFQ|^G?g`9;@!m9>Y@fYOzHRn^85YUdA*jZg4t)~Kylx!ICYbnyojLSziiG; z&sM5R(QqVXf3~{+NTpsvRWv_>rL-s7OIBn4IlMwpkm{#GPmi->TejeE$j2onXDX51 z7G$qB8(I6W| zYy}Y!4BS4vYD2)~zeX9Bn3=^Z>?0iXUT?@@>DSr`a>OAyUV@6xbAH50vHTn_VFtw@ z1dlBjM!za3rG;8;2sQGd_mo6YQ&O($9PbP3nqUkG}NmD zU5)Rth#66YkqL(;vYwoCFtINmcHzIYd_y%FD^Z`$7J#R9%&kxO7JTIW6FMH{&Q$dh zN?B>(0trvDSO+>j$6A;anK!d$+Oy5jw4yX0fU0{jssG|`A=?Jmih-cp-8lHF zRq7c+EY}*NWXA^y<$s9{%N&3 zVfFwX?7@id>VFfGRa2PnBC0nRni{lj=!9QcMh9Q5G9CPVL z^wkp>HM8g>#pqhhH&RE&^k5{+v&T|U6r2uWp4k%V$*>u$-eAh6EeI+pr0M$*sJA7H zElX`)5dW??@kWbBk18r6N1^T`v>bC>fJ8%YG|sZ%az}C!vm6m|c)swEgzsX}x@p#+ z`nj89TG4LMp0Tz$M6zR@!)YE(Xm4sQy-f|jVXuE&+W;_I^9cePFW1*0pknL^aimi@|mJoi@s5&znqeETj2Mq^+Vddh)E(oQ5!X^^#w zlv9&C|bzMm(1XgT2x60C*F~QzA;s9^9j`7SG+aEMT5*(rCFjAbF?e23=(&*zN)zrpn zb^#x~>Aigjx_?o-EOp&AK2l=Ki)Bd^xc**_M>tjkj0-cY3wb%j)qx6@?i5fMvW(i5 z=h?Z%4XhxeRYSr~>-Z=@yY+HSRnum8GeM2l{LMVB2<5lUEXPa#nIaeyfaiCa8&f(e z94Vm1-1SRO=nD|FZyP2D!J^1wFxOKIrrYU{ds+N!_Of72d%Yg7;F$W^>+$#nCZpw# zC|4S3o{TI#DH5j+lt4uIt)ojVF1ko)nM4td19gk^i(B2j&zB3VH3j1WyYVQKK1C*$ z%XPD5*=xflT~SOgbdXxLX6o&~pPW=jo^DgW>N}8N4*w(Zzc1BhigkHk#l=sv0s`K-ZochDa9rn8Z-h^oFQJb~iE}rdTiw_BXz$Y#QZ~t=2n!7PIeUlwzFH6&@4CJt z4PC?%R*8Ri`u&J|rx&kvr)nhj9eqtUiKo%G!bnFVpF6?)e0v=EO)?~Jwf@{2?XM$} z`zPn~FJTg~aZ#sdRg($!43g~VykGnvTNcw&NHbjSsbTt_V<$fxF!EV<>$-XHhsGZe z1Y&Uk6mc;g^-p#MEkbf5wLAj^MfN)1>Tv?CT zFs(DQm1f^khNHy6Sxf8h)=)6e?jSydnc3=Cm>6ts+%6Tw>Ogm#Tyc49IOh3s1)wcwX8l-QOS87T!P@rn*6QVIhI&!oh{%jSc?dmDKo*j6tIPWU;cz!_aC`y zc0fQ5!(Dhq#_>w|IXdvhJ7FYz?A;|*RsX4Hfq*O{0F$4rKCh_w%X$kY5C(dS#Ze2c zLiWR>GD#`5ylP4?UuT>^K!$Yk6qlPYQC)#~LS?mVLE=lzhq$`WH>^m)e#4XIxJBC7 z-2+{xa7?zcAKHO0te%^KR|_mvB{|5@eQ-aKdw>;BgAaO@Qj8(7_(zgKl6{F1zFvr65Za*?%39Dx#4kRRD(y5^~>@o}|F`lOImVr=8(X2Hv|Bzwy8` zFEG8jm7lKvI}-6~{5ujwfFn^7lMyUL$~>$3((C&1)$$V!BwMr+wdoC_p=&j{i`!T9 zTzhd^_eTb(Pv2Xfa`joOYjUvHqq@;N3@!b?zLF$w{Y%<^MZQH&gla*S?RMz~&q6Jp z*AVT`{i9gpTgc% zKUe)33;f5E{%6FJ?K=h7r|SDD{IohE`)B-5=9kAauz>Up{$bj(U|IOroCZbk3A>|8mr0I+`ww%1FKJ1* z9)45?wKY>@+e}#Mx*JD#_maZ}bZ1djXs`&qlNU{nA-}oK&PE1km4D!Ce!vv^h@)QE z$tfOcG$x(+tzPeF=Mg@{a~Y}=XTu(M$IQ{JcOsy`>{HvuS|2y2)wt{_7ChYXDXNN* zWdi&1h65wbA|v#Pzpyac&rqq~e73Ev_mRVkWq&AOLnN}fexV#h@l3Wy- z0^fEg^|8^M&3$7V)K+(NpAeuvu}XH;pa<9WC_9F7P^-s;{L&$hcNBX<@U-~M=M(~m z@Pd=|ExxYUs=CWjZkiY8o!89^YVG{;t=`#&ka=N?{VQ>bdGBX`lpnaZJUMALOg@Y23S3c>8P`QxB zA_E*;q=}>u6bS#ZLS!byu#?l5|7XAwCk7E)wAa?m|0C4rQ_8`R0*uswIKO=U1=cn| z>=pll)jT;GrA9V3*N0AlYMI_F*3uU6={wgD2DFcFXpVGk_fJ)tNCCI#;E4vcrJ^tB z$^PohnenHSU+c}psV!L~6-e+{VCpM+e=g1T<837f9^z<63W#UCwbzUxBnE15ey169 zs6VrTYV*dYEfC|{n5wM=GQ%dad+2@6H;rhxOU>0w!pUxveqE-DuTn*I5Tiy&)F}LJ zx?us*8Of$IM;)WEjBocNN-~i@8A^~bJ0~=%ZK+3-kkU%Q;lEA_gFiI&3XA+N?br%x zl=Iti9wsU{hG*;Eost_v4Cc2WW7j>v;Rtbs;_))HCyzmNmGn#r+zgl#hX&=|<7i42 z;>DPL8e1c&9kw?WJ4OpYfCpw*Ea``r8ys*6>ml?y7g;qFJDI`X>}jho8OvcWeEB?P zsoat)rkc*a^;H}P{!8n{;ReMYQQ8s(oPbBVD|j(dOY;;OMc+_C=GJj8iNdn302OGU z^7pg~P}xs&G$^TIcw3sF7K~7wvAnkObPFq$skkaLX)4%juHVPiaekYO4kqf{h;!i> zl!*f30&J63MtIB46XKvUYr6|*NvKu<2ejxSDI+-ev4w?B$ME89X3MR^`A{4xP+>Q5nF4YHIUS5rx!IenPHooVJT{H++w)=9{1mu-x2{f_2#9hT2Wbto}SONinX_M~ujr?-Pl$jsr*(Q4rC~)-yyCmm;?`H>LZN zhaV>j9H*F05%GngI-N|KqM&2@QfIwzgNs(c{6jv(_W3hP`0u+>+wiR{;x*G5{X?`A zUCxawbJy^btAgxujpj7(unCb$qwoJ615CI3H!Xwq!bH3^ekjg-ao2O|>AtE1aLCPk z3DVpFg&2xN*WrP0+d9xBt+x2RlJ(4-6o0E_JgZ@&Asdy2Hbo&Ms?(vb-a_h9a=8Ft zE|;4c=jI+UYM%bHqOQWbe8CYRF1D4du?CGYKYCrG{Hs*&D&?=r6HB#(7dj&?mbQXG z17C!PHZGCa{tzhqPOvu34>_0+;*`(`56c-6o29hajL51+A%wVq=zfiqZig?`8N#<& z59Z;?w@BL|VIoZ@2s)VUNLnk0#C<+=3?!{S^BIM@Tll%}f=6{syH!5r(rdxQqcfp) zymCCBMXI5)5^pD4aUzT{R-T;`!V)D;ZEFO1mylnjc(*mEUOvSwBE!tmmR{4ss?b|X zInAbPzVqy;+^9+;WB#zp*Nzs2N-O{+Q%O{&c(`HfYPYe|0{LTc+ zjX+>?mjh7{vEVGWh?pGKb2?!>!2Qb@3!a7vjE!F}AEW|3YK)9fuv1f#!nr35vwXCm zs_!q6|2v3Zut~d0bFz@5ckp16p3(Va%I#V&axI}g;KD}8>;JU@e zy`bK5LCz4-*@3@$Ben!J>{C&4hQaZtHZCW*pe7X(bBj;BywC-!1%W@QVnXUIA}nwS zAal$D+7XeWSi-#JzjHcAt@g`Y43y7m-4e=0sEC$-mj4ir=%upTL6~8Go zqV2m@-*lyf<;^~|YL&q}A^gV5)5lgO#b@Z3(Dnw1OVUY#w@DqsB?M%%ZOdD8V$_17cr-=*>c3NA@NAgh} z>y4vbmK%(yryGc^DD`1N1M7ND=ND)tJhjZY^g2a|%@q8rCe%L3{vx70upPsM;+Hc!B%Of4xAs;Mszj+3&Q zC8{M@T~cD(NSEgN?uef`b=k7;IoMxHec__MLC4`3t%+#b5?P#@$;tq^*7QVPPIzij zKeh@zVOMs2OScu_xAC1#G)8Jd9r3o|JAsr5z2Oe*lSN>l_+8GQ-CyMoYuhCM@jw2H z3~WCOTxp7JHKE?{h+Gpzf%s0Q<5+0TPAf1$VzWdB)NuuyOss-LeuC_$*!$L*eGIlT8~L4cPB?d=ODIVwbGBQ?P%@2dFj}abTCP}maU(NI zkrHwUbQkSqVTBbm_Gm`H7p5_u(xt|$@lwDu_xMKP`jHOmknI*GHJ+9#)yT$t=W*z< zYm|;9ohNcEC9enbWIM+&SpjDcDj2L8$k9j(t!G zD^f#9f@@>CWfU?}!mmlt;V}Iu-NIiG+2D6S3$OKSZ@dnBk|Cj?3%LRRSnJk)Nkv5jr9wg7yTWoG6 zjSDAOrBfrrS3H<@4ir=jDjeNWk(Qbx-eF^KSzI-+T>{m$ub@F~TNT&v4Z z!rPE!SMlncFKzsmupFrSSE{Lu|JsI85MLYH&Jm99ZTLkP3`d*TUNy5{EhgH{7FaJE zOCh^G;vk-&K|IRUcI-wdut{gRSa!IdQDU5VGBRr?jhBm}*P0HXdbZ4Q@;vuAo&oFzMP71VP*abOzk?>$PaTmb zIvLV6BB`E(-ywz=Guaa|w>kGb9=#o?8SmW)!X-B=Oy2w95>Lgo6FaSY>@dKq+b5!D zeFXK-JW|Xbqs&w~_)q-dTz3Yh{L8*jgR7~GDl*l?R_tsYU&#rgo<4}bmr23ZzQ(nC za~+>r)cPVzauuEGU>_Z+QzSD$U_u}|)k~q-XhoRt&YvzKwh+~tSS@+erOQTmD6k8^ zfUC}$^Gz#ke#9dg{(2$)%K)3i6*@nd590|nh3=SHQ)ymL+@D?${g#||d<~Ww{QasI zTO=!wvzi!e%MU*rHj?1zcV|yEixL7}?jxXGUwW15umUVyy2M`&M^~{-sc^L0LQvPR z$A<#YJ)2sR2Y!5r_3=O~JjWY{(pD&SyY_{4HQf_5X99?vyh+gUobxwaS$xNA9|&&* z^rpqb#2p%RofTe0!rkX79?w6_3T8Y!3-P?~QXMHk2^-w)v16tUcR-Gvl&=-8$!u-d z{n+yy8oqJXw7oYAdoqTaIrC0NN)%-b0opFw_yE;f(G46m>RHbPq+5C?>hIGA6QDNA zwx-r~`cs(C_Hr(b>8(bM*Y?)}i90UPt(z`8M~mkvR^K2HVJRsF8RH+6=)XHhj^iD7?3B5#99`ZucGBO|NtLeb<3C6V)L3+b&o{_bU{{o1KHqR`1}~ zbMEH-+kmnNLtCW9K$7t{+CmwMALP9!7CvLBo4HH+bD}gw!ILM1BTGKKu|trSfTnF_ zZS|R7&P(S>W+|2~%TAhh{7K_Ndx~vCw=>2UQ#I~epRnuqt6vV&Ua@w^63{rVV|GvM z{tTEnP#4?OVY&C6H=R6`4;}-~C`yd^MiJgqdV5$IE#LXcUasKjc%0!M)pZ=`TM6HX zxYMGQu2nJ2a{3!dOf)@lo)cVBKZ8x5Yg@XGZ++MXh{a0?2O@hoh}L{n=HIymH9xLm zNfExqZ)Y&uO7Vn>zJJ|$qdN}280tLRjlkTi8PpklKy(OFmNw=&uFfJ*zqk4;5ftM$+##nT&8A z9Z_?*8HSu|r;J<4j2g-161VMUq`7sQ;W5n4tyQcd%|Gn;!5)dG4d!A-8o3dU>@Op| zhpaewJ+E~X-#fltuwHgbOzhXgurr<(ZJjg^s11>HcK$XZUmJ?|cy{Lmv>x5N6%}4m zhh5Jjq(41gcH?=h>Tr6i7KTEXGzT>+EV^fC4jtd~jgr{V=8;*+bC~OlcY=FL;V5xB zlDbdt+j~}a<-WvK&xr3k+(!2@D7FFZ6voys&Qs6!59!Ut&B(e1Vw)}oiY0H@8TNg- zo3G=AXEkunE^H&3cVMMgTO2AWaO}tSuU+!)R)I~2Z)%=OHnHrEZktYa zuW6~fb1-eTE8ac(t{gvX%kUK5CY_zG%s1oadQH%NYd)bpOS)sRp|}1$`GqXq9%G+? zB`y&2ecWvZb2_Fu6;;MF5A@g)WcTKWX=|GC&g1h4lJL~b$7%w;+x2H6>gI7jcf1j3 zw9|tYR1H-x2Ou?F-k)h2dn}#0e8b`#ox$!{KVAH95)AB5uviERagT&_WF9LXhmvVd%c#h zTO$xaI8S?#rFwm}`tmxXr};LCE;(4bd7E0fhi*Y}I@GiJ1U=W&wyE%NosL;0?5n?f z?BcMA5Lq)vvR~^0(X|JXIexq?_u2k!8)9?T=`TU>7`IBd7O*<;ND}1bjk%|z4%yz^ z0uB<_vl5&(txRpS>lYVB?6$AW8g}dALNz`%NfQf?KHCXCh&^QZ?ZFOLaP8sn_7I-_KnC3<-yi zrZ^+0tf~(BEtu@vbv_FVyX|MrxK4R6-M_gI4ih^x-%d25AX(2janeQ(VXlYabNi{d zv@J3Q``>DtfK0^hG)8z2;W6Fm>x z12xX^BQS*x@9F>v=X!khW4GF*9sr-TR(y{W?!eZ!d!ji}0+D7Y>3-WJv%iXqO z`~3B#+FCQc2VkIeB6MxQ=G0qTBhrC9YGb?geIUKG!1nevk)fe0+xXHxhR#;Gb2wh5 zUFwmLZol&xu?Mx(up5UECuESDHyl*$`gTt-ks@lh&ipKETu`K?8NB=P_!xWTt{dX* zVKQG5UZ~8R(qd&bk~_Qy?|P}iHG$eDW#Z1KJ;3MW#9&vV(P1+liD{$TVTpUuDpJ8K z9nu3(xX%O3JMwsgKWH#(-3riNhG|b<_v9Rq5(XG6_X@9EWx~OfdHa>VIl{RhWDW?U z)@kqU-!*}~F-)yF{l=3|rjYKVgQlk*h*2tYzu`o7hbypEoOZ*Pn$W2KE%D-kRwK*n zp2z3)IDCcu0Arl@Wnv|xBa9h?U}!t>WZJz^?0h@ymUS_{jaPKLC6#ak$LfQNjw__g zL|PXDbdX%T*PYX|=jp9OP1}97Eq!|T+`Hy@pT*f$#VI@nuN^8TUBeOy5DNzEDRNBg zBMZTKzs>bvzO^e+#0%PuL$d|j;i*FVmCOR>*5QwHeb1F%<5>pMyMt2#l4IXw0fFTs z2x4CSqe#~rH*v4ny9>7Hr-QSoE?M?>npEnw4Wo?D_B(9eEG#buh#MP3I*i9NSX8W; z@9jpm7nMjxsZqXXggpY}rxLnnni#5F1;u~LG)089P6q;Hs^?E$er-IvE&0F z$FzFRfKqykIX0@ZcWt!ozuLit(*kr5{YOhSwYnf3+xZO03v)7IgUG!Hd}`PI*a4@q z%rynvbnV9I$2-Wik(1#e(THzZ*l1zgDF!a;LAdMBQ~Rfi{>|q!hBtCRhU`K9>$uu= zm{_c3PVLovAC}3hCB5k%BAD)ztn|Hi+-a1Lp~)&!%DpNkJKoStfU*zT4S1cb#{Kps z&&l~F@StQ!AmX=)Sq8X<-98dvmHC^X`Z5vxkhJR$JS}&73WS~JJ!jRZM@V@TyKMB zCw*HkwT8!1Bcvz+0MEuJ@%;YbE_>lR=x^Hu zR^t|=u?kg}@nsn&i_}VJ`fEF3rj}@D=6?2Dn2wEmDtGZ?8y9FS+vM$cwJ_ZzZ(Iby zm~5wh|A`vS@)?#lpBuvmtzLLU{byRZDGz+;05crJBb91bBYzfxpAC2d&A2Ry!Pu2X zm(%7cw0``L31L)669Ixj=;vNtC3c+~by~1?W&jZad!C>@pW)QZ{CV}|qhq|q19uHLg^!l(wXBIORq`~=m>5%ntbc@E)0*_i9Zbn z+2;-#K5FY76DPCQY3?h^{_uV;RuLPsUelxA9z@5lVn2EN06@a=J3UB}I#%ct<-QQo z_{Fl3>bXoK4;;9lT|!T>Icd=gAJD#m>4yP4hwmOi^P4#hf79d;L;oDPL0rJ&O^Ew| z|M&~uG%}iZ$tv2bg*4RDT<#U$QkY7VSAIvy=j$97wqqIl0vniTU-3kPq#h9 zA@%v`cexJl5LDwX^n3$e^q$={e*!AF`*6@>W37k~!uh+_FP&$)>X;0l+=RO;9^*vM z+yax~%*842c~=F^7bCv=e#>(E_-Xlhpo;~+OtJ!8lEic_{Kol8+o6izJLSYgOY0vg z-3YDYp5g(El!Z)pFnfOH+0%i6lagjBWG^?yO91C}uR*WKj35P-pPzkqd$g(lQ*(?( z1aIoNAatGt1@GaktNLVn%~D6-bd?BfZaB zn{=h0u5{cg^LNW@{PUkv(I4y;IgEG?gU*tf4ZoGf3D7V(JlhJ8gQn@a5oo{WbeZP0 zjQiTM^+cDH7LxjW*_{7;x~yJ;k5vFE&8t-Zb(t55mtHd4=PS3?Gmpj<{%ppYT*;fv46F?UUADeqi}ruBJd05`K+t_J)?KaDz`0mEg-bP1yY)D|CeN<&n_4qr3XFX zbOLVJT}ZK3or0ypE+wg{dju(P4?2=+yGV(XG2y8w_77Bl6?Yn{Bm;3 zB+EB$^_m|fxWhiLVAE@h-&Igh5UndfAsT+J>CS1htJ?6MS?NWaI&_&4aUTeK{YSZB z(mTD+EW7&AWcDjlEg!L_nGIWa>=tg$Jca#O#78prkw*xBtkzadEyNE zWU$19U^ib_&Ju4+X}vmY7;3^a;$`` zoJq0$nuVFF(PTaSqiF^{hogKN_Wf(*BLa38nOtWW5}%s%N-)EF`-B?K(1t0&6`Y?d z0)p4+ji&tNcacqgsNK}8EzjpGZcmT_Y})vwcr5ngqr%FyH7O%>nq-{PHJ`Ef*fL*H zxIix!&ST(&vf3}9UQru{(i+yZY_Pn}K@7l?fedpxdheAmNY(gSx6NEtBt2*Z8*nSN zijix>^^9-NB$RjJok`VUHwEhrn`A1GqAeX5Sjyvi1KWvwy?Z1f|g zwth-=PxDwBkbS;$7*$Q-S3?H4osf3mG*f%T-J>xdSlV&)L&;J0hQkmsh&YXh$nz z2dZu!3te5LpyDewS4H1}F;@4wjXh2@FdIt=;@k_D10!(3l;4!P;VNlVJLO^2|L`Ib z0Bgt#udlW+EYXrxY1iA>GnJYP`daALZ^tYqZr5&{-%Lw6n7xt6=G#a33MT|ktD!;7 zdg960FVhK z5v_U27TKO`7}?&~GZ*=|l8JYVUJWOr#;Sz- z<#;3a@7GSNfY8=Xm&G$w%GVnyV`b2<9KG@5(TZqtD_F3?AOB?f+tq4$$KvxvXRcPV z_25Io0{PTyf7tS)ZUvVIQ+^86^IO7kD&bxPwKou73RdTk!rN^#-%=|BsO{4fH4Gxy zi3IZgn5EE7ef8;$2O{;FBB(XFtfiLobtI$Olzt~ziOGHQM100H`xSZF*&Mgd_wtqf zZBM)eh0Av{{9`NwaaTN;vFqTYz z`M%UT@lY__=)2t+o97{;eixX~eovziNBM0yfieW{hp<}Cph&_=xTM#j1plze9SyEJ zMZk1BDD1k;)K`AF?%PKn4==vV4zZLphe`+X<}+>;p0txeonj8sdO5XurPxN!T#-Bm zgEb^a974aTY2UVd^GPdPbf&WuV@4C+MC?jmvB+j6C zdan+vp@-t$!}@7#(M007;w^D8jNSUOl^E&Nf@`(bu_9}!2QvW~W~(>JiLKQml8zSc z^x$^)r~}z3sMBNFH(7>dnugB@o@>VZw`P(@@1)~rh#Z)7QcJ%%K?;A!2&LA_dpedN z%@~Cx0zN2Uty8V4?4d*B+#U>Wijy34%%HPFBT->eN8HAz;lCXQ7K=4{i(+#hIUqK- zY;351%w($gRNy0)V1UFQTB*bNyTE6Nn_a((Mn021s9pF2Gj6{?H*2Xyw`Hr@rPWdj z3ZG>DDK`|&vFGR$5uFS^yUd6{*q79iGJ*C7q9v4bSSf7AIvDMrY^^^tDRUqZpb+-< z{F`rZb^SuyanVN-y4g0|5MwGj5TGs`UhIv-u}5#d@N#(|g{WBfZ>aBT_iSe-EU8u| z?Q%OYUyII(B2kLQrr5!+>Io%wkP@Cdv++UaCEl`TRIlwl(R1%ra^jXCJOoDW(QXtX zEudOg^^}{E0G_iyeZFqgoxO*VOy`cdi$#$;xst6vHVLEJG%p|=&T4lFy?sB!)ht@MbbwNpka~`1kDSGD$xFC;DSW{8zyp!IG5PL%v#|QQO4IDX+)f z#@X51N75IaLX>JZmh(*W;elu;ZJNSr*Tb*{l_?Kbmdr9d{<-&)`Cnj{Pw-yd{@8xP zQc&*{TZsU+dRN+>o}P>AYY)%oA)!6 zj|zfcHB?@NE#pfbUQ8hWSMgvC2_X#Fb9}j6HwxK$*jft1i~WTxai#1Xiu_utd*3ob z`tJjMs5Pw1g{{r|MEn@$?tBlQ)`R~K;FVPnNs;7IHnBL}V!1ZJIH*jAS zb`vV9_P~A`=Wrf)_w&Q5U~1jh^=`NHG~4~l=syIH#H9cBGj1Vd1)lHJ-tXJXXTE9U z8$nB&IFnbZw1kuo5Ev^i4B^o+|6%208&Gm<2n)&SUnV6)Pj%W1U1PnN|5W4J#jbf; z7iA}9sjX-BcVd4@|Jf(`rwDLMNj4m7Du*?3T3#h3axZd6tCF0^Hhg>w-KSiF^r(st zSS9K*K=>XMZn~dbG1&qx{5OTizsCCWWpO};#F(L;UwnYwCqLjN(}*c$(iEH|Eiz%! zn>N*6YI>2WOa9ldZG{v6tK!fnOzzw|f8}M$@j?-TWZxLUxMnPo=12?ewLV=k?TK6T z?0e3UEO|m^^agF+12~#=KZM?Ck}BE=MK7N- z?ab`O)r=YT{|MjeyJ{X?bj;ZJ4pwvXabTuXUP~$zJZAE|0U(%`8r9+D<9(08)I;6& zbM_d8IZP3Z=2DHnjxyo4dR~Y_aLdhW4dxiEy5Y1a)ET~Nci!W3(^u=h4qcWm%b7HkWJpXDAj|;3ZGB~tm`)1wnRafWteMe?b;25+?h>hMY@KI- zLnmSXRnnfMT76i(P^iP*f)k#^a6t##u9-4-u$RwjU(`Gs(jDQ3dh*k(gNHNY=G)y; z7V{GU$m-D4#? z7Hr1YQ;mcg^A(R`f$9ANTnN@J8k2Hv2B$Old2g-cUys{KPK7AzwAup|tR!Y8D}95X zF~!^q`V|Q*Q-=muogFi)|M0zIiP8r_hGjGbJx2zqG5{e%uau{c_x!EU-C0C(GA1{$Aa56ZN2SBMj@xcY`m)>-25xmtzJG>wwoDp1nZT8u{K&APyYwd+Z{i-% zS)nr&QIGo2VkBVcFgt$#@T|<(k#vI!hY^-1G_5{R))WCqb!O9C83aQTtTs~^ZZ=xu zxd-dn+qlN{f4So}>#K^t1=kD`e$s^~PWu>*y)m-1X%zBI^v)r{y6>G|C}twOo!YCE z9h;OaW%gkkmwbp(SWlY+Ue|IGG|U-RH22UT;8l{@v&hSr@5Ej$-Wfa7m>_W4N@sIL zh@ffE5D-ZM(c+}z zI=xV3wc-!@NkXoYeY`*0SMTOxp)2cc70~**&e@f@F#Vd9w}}G>?Im`6w`#WJ!RSJD zr*C_m_PL+dGi9p2fm|7f+Y?uLfFv7Yj4QEUsj$CZotDbt%=XonGWAJaw!=(n)(^U= z2wIZprT(5S{-vbg>`YoFd@Jc4J*4qeOv(j6#0jwG-bwVx5}D#b2X}rxy+_WJ6p14wkNq5;0-gU335*BYt>Rw$EX(0tp^rrc^m=p_b<}J(rt(jHuTPv%|$EC zD^w}i(7Z~S%kgAto)ztv-875V8vu_q-$tS>)qEq)^N(fVNC4&P^2-9D0V+~BaS>Ys zG89i3NN{pg1KGej-jrN6lfg5Pb0B^-GkJJS3hZ!kUdH6$NdLQ5cQRk z9V-0e+|Wc{0B`=!p==jI?>fQuRKhcKyx5a8gqzvO-_x}O-ZPE~_*RngdTR|oQX&5O z9a}4O*L@*cC+z04BD;1c<`J0FJs=MKH$IP+k$P~V;zf$*3J~IkIy}eC;&J0K#d=tDXhf zhq(y#@BKnxl0*;^r>zo12^p^wYN9L38Zw*qkDT{LU||hIuc#e{ClJR2v`3= zk!182HM_iW9wXbZ=_rHETIASFQ#q|{3D!*SUt3` za3=POyLDR+S;#OBCJmw=!viELBRhG>a&QZ!$QlxaOsT2E99WS`P#+e&gC>#E$LBzt zL#%IiVJm?k2x+=bR2ht2w#g-^I*Zwn@Yd?o)#1P{soX=FQZNUuj-!b` z(11qMJp_7)sss?2n)v$<8T76kDrcKF38ubOl73~4@vU8&`9fCHxaShQZy`A9#eE_< zI7zduuH`Q^m6Z+Vs*P_>{rG3Z^YzEScX0GE>Hq93w}wEk8V>H$E{>psFo}#B#j*nt z1_-Dg>DTclvsf63j}nDFvxJM07-z6J{||d_6&=^ItZND^%VLXJvY1&VW@ct)W@g!9 zmc`7>P-13TY%w!4GhKPDz0Tcz?miFQqaXUA-!!VmOl9TFnK9#w_#;x8EQFw$_Fnml zE*UUraDQo*eqQ~o>VAh~!N_`VYpgk>;Z%B->dp?El(Gth0phRcbhq{*lw&Ey*t|wD zy3Fk3I5>BA*MH(M)`If7DSn~Bxb+58+>gqC%@;!XaC=UlF!LnXcG}>O#%r#B#*|6;s#>R_zD5q+r!m!8sd(C;wyk0PN^&*1 z@O~F$V_)7@uE8;OMo@gOppuAY@YlP8{_FxxDpNmD&u5-`dm<{0qJ<4-q%~?_67dp( zIZ4Tq+3)81%g&1{v#MMcm?QDN39Hc-68bv-HMY2Wy!{*M`kBaM=|m#$e+Dy)Hc2XW z*7V=Awv(7FNA(It4<;8q<=PymKF?F$kLJ}2FVSCxV~|Qe$0zEGoIoq(UjOQtaaH;j zhrjn?Iy!&62obnnCVACvIGVzhluZt<*1WOo1R`j;{Jj!`TLeLf*O0=SQ;JZ1pD)Kl z8}n50>-ou&dK!AC#%DC&so?OmISa(H7au(H&g4CpyXYgf8^u6b3D0#ULThfYe5>0po}4Z_5}82Bvpn;{4KD*xjR_ zwRKs2H7O;XN9GHG&>6wsru~w45X0jqoUiBaT6KM>kbh)-ZnS^P_4?kw5`l(yS7vCVzAzRe>hk5+<1>yXE&-&H+@A5#0 z|1K%~1^7!V`S-(=`c%S5N3W5lTc*nlNyX73+kP~?F#bD=d$G^pHEUMInJZe0U z8I1PT*XHA*%wFeBF=Cj@r+NtI#XkGgs948&HJ3bjldRR%=>_Jrc18#POp1eUsjz~I`f1&3OOuCeUJogF9IB@a`P=x4#SYW403I1>;dGvq=m$VF7W%_ZqeLihGPV9j``?dL0v<0tX;%M?#Z=Q|gtZM8DAKM^pF3EXK zfz9~@Z!_jIbi-T7IcHLj4k+LVOp82Zfc} z*Ib6XSZ!`Efv#YX)QLD8=kImi@vW4y1(!P>C=E#H+0)@t##e*d;>K{%RN2kp#t1(8J!Dtd*GNT_uBkInwuMfV(~M<$sfqtL zKJ3F0C_XJV9~9s0y6HV#uX@`vY0Vvp*>gWSZ1G-%ftathIgotf1HgTzM|AW7Uw^9$ z+$NxOKW>}&^?}V&7onrE`a^deQ)&*my2TTBDrVB7d5^`MS;w~BiOOnBDy_#NE6Dbv zOrBk{YAcR}e9ZS_o~&V~aT9%*W0&zqjf}W8V{J~22kM+(oVl^m!+uwL@_ue452(lL zFVx4sb{z?fu#SJig?{ZWse5fF4lk@DoKQ66F7l@TX>squWV0ml)`2Pm29Hv<9Fvp9 zoRbVFDKYmLC95$uHi**Q&~c;2%5w4It-}lyWK4@|kvqG5$=<(+D6wkB|8eyydNO%P zzI-ey!U7~CE<2`(yTtP~#zrQ68?On*;u;1N1a5;iw0aFpb@Ydf8&%?Jp22Pdi=&(0 z>ft=PpO^#V)FX=aTU_ASv+%d?=uCR9h_u@AqbFJDX4g-9e?}G9D}iha!jGnP-{7)} zSJR34M;U)n|0)y?SpU63+xj@QVj1*@_p6`IWNx`e+1+)J_z;Oq=QTAyO8jN4)UUYZ zJ`O&xF1tA1`=F0@q}*7~vpuKfyl?vIR%wdc&0Y^&2Nfq6`ud<_-G=H zR59>2JU#}*RJ;du^m*|w`%J&K@+*1KwfODTs-YsQ>s#aWNypok?xQTbYtXMm-5R|~ zY9AZK!O|EYn{qxn%)8pqUW&He>NAYutD)TNf8vLXII@Zd)*?P?pVNl9)mtoRk4<=? z=P;U^?r|PJOBsz6VtT0@z)mM-5+l+Fo*0ap`QohM_kQFGs@)0Ok4vWv4MgZ_s-Bp0 zSutj*0CNo1#mhAr{Kg@W+1M-zJ4skfwvH04G=C=ptDl|Erp#_d45dtffiN+l#FS!dxQ%8pnttZQMM+aI-KT4Q%oua3k>b_dOkbfNY>@h%&*Z0tf<^ z78H+f0` z*}l+XVzd0kn`Ai&woqcj;iFIYzPJUB;eTMK@zneIAKHx9q5ZbgUFkG@6QIv5wFtm* zAb#~WUgwGgE#lR`uTk`BFvxxM#A@qzcd+d3v7+PY@)`N!3|ZORm`4;q6`xE1h$(x> zvHnt@w*4p%@r=}V|BAw5rPJL~11F}&nL&bn^L_Z$y7TIKNB~y7E}kZwC#R>tKi%Dl z+n7n$EoM`>oc854){Ozl^4jnXHDV_cD6az>8~emh6$vU9`>B`_Lli z@UmP^OYmLOdtG5a;qgd_CCoWd9Df(7DKKhnV0QApJP*`-c$mzwIvN-4t@pM>bGW&g~lzaBkK1L0xG!R)>VsDI@KAjy7BF!aRSzeQwgZ1b^ zna`E;CnPCy_nR-GTp{l3k%xZ8fnC``<~XVi@LkC0ZhcO+qboD-uI^|p-k<>*%?9;g zv4HFTCE9*ji_jc6Aqh7Fk=ZJhzDa9J=lQ!(5mR7Xn_%ecuM`l^;RMHt7wK4S;ibCK zV3KTmD%pC!`zAEAfE}0<&P{=``{SSU3f(>JjN0oI{ChcA5E(MzJTJ8K=Rz@lsCXn{ z8`e-kAigfbv)QuerEZ!OX4DzvDurKV!a}qCgPS!=aNA3p4RRLbZYsv>9Jq$g6wP@N zO4#HZoweJXzRzV0oGX!>ZOB(*k4Ca1hXulG_Xt+5d+|l^hiAA#g*6+mU!w77Ctn#- zwb`7S?1kjiSuZF3P`q~_3bh(=4~mlHnV4(W(73Y+tcpX6v!u9rJVIv@Z-jjhP^~q<@K4+fiW|avMj|i zDSbTpKSO$jJhp~+N|I%l?3OgN{^2yzb3pz^-pJgES4!MGEZpDV|A>j$G3+n87w~t; zS!{16D>$_Bg2!1KRStTxDTlSp1^-*|Yb%OOcofIX>EKKBuz|6DcwYPNcDA{TK5YL0 z)V?S`#lHhg?|9ajbOZ4?H{?k~d$#6Qo)6E$xqn)?cNM)nWnc)gsBSvB=O3n;c~T4@ zHjt-|`Gj-%{D6E$x73C3>Ps?Qf+F2|W5fsaE9ri*qF`g^9{A0^mMxrcd@#mm1M=qMDq#PRn;1^HS$DA!EUUvL*8m`>g)f4)XeJ9fNRGu>QNP@Q*eta+3sV3qfb;J2s|OC z_n^qPop=4vVxdu_0|oSFEoA%mH%8BT*UIT+2Wxj z&2kX2AY^}m??JdonIitGiF|8E;@0D#r;;~-uqg7e0_^>utH$Qu-o?zy?aaeaArE}= z;W~P$49oTq%{F0die;lIV!8txugL!yH$YLE$-e^`-E-~RI7!H~wQkL8HP#U&3P&%$P&Z=ep4 z5ia&4U2bS%JdzBoqszjX*cWj!N%|34O{s<(@J8}g#xZ$j(wf`{GLx4P55zrVSVX>J zJ?_M{j|&7(J`lrJkrErl(owtI0E zGZ+h3?ZFz(DswvpBrF4&c1a8`Af<~PP#uSZCR1(*nm#7PQtO#X`XS<|cww&vWIh+9 z$&D_CL(6co)s6h%Bsto6PVc-bSzzDF4JTw4fPjRM3xy6R9x*~zfiRnLC6|6m4T0h4 zyV(Rj)Vr~Zv@~y_AP$3bqxe`5mHGk8z-#7v#lcQMr8c>~%x|3-Bqbtq#6IVEkjH4~ zdLIZ9;$+xQC1X2+xWwDc218Xm>4kLk7mD*R^ke^S*yHGELXFU& zu)Iqz+;9Q_T?b}a@Dm23iac{*GfG8}4-K{+Ud5!`Oprz;tdFS=p%rVKs5?)20}^sj zUa#HsucS@7*9?gVlJY%cM$vg|^Vv3S8o1cGqlhYHL}a)l281l+7En;f1>3=mGXP%= z-~X5g$JDZBLix9M0t}7VHbth;AR+^TM7B1z z0?=^LIOs7lM+JvM#W89v25@fq!JhX=H@-ikztq;@oFzg-c@9kbIF3J&k~zlurB;?X z+Hn`;**o+QFs9QZ@63Y`Bje$PA7#ug>ezeNV#}HsH@Q&wIm>*M9~DN6Tn2p=scqB8 zD@O$%EP~Y|r6iAPVmo5TM~jv?!T<;dT$2-}JU%kE&PPO0DW?EFep(dNidS;Ta30R3 zhycEj-r-3=g%!=8x?-PV|48SBDvOZ3op?p#TVQoBU?lfs#a}hKqJHf5ECBa4WO)4c z)3<~&5)+#0O`w)52MvUT@!x++LQXi&=jX_sV(qXurzj_F(U(AJEmuRm59<2PZ^-9^ zEPcP$k^!4>qqVu+cYwdfJn+JrS~>fAos_l9UkhD`LI^%#zawEGb9oIZ>&PS#End?z zISXo8;kTFK3JpC6?{d(C_cb=}+Jbzcnn75$%6R;TXJ1-Ze)RU)<90g282|TQrPPs@ z1GU!ux+^kD3_|IKhetrS`Kn7d$affSS=E5B0;0uc_U}Er;f6Vv`E9mf%PiVCe2-Hl z_Nn{&%88$qi5Bjb^#v4^ZuE=PYS_z^kVyq(@Hb~x*=|ZdYm%Yklrx(FpgFRhn4LKW zdJ2l%ewODR88*37gqSG{c5~GKa`hk@krmdLi)(5(#MR8D+*GBY@u(zqaC;S@?MtQa z*D)SD+Gd-r*x_Tb?tGYd;sgBrY1YG_tD{AOD%LzQhl}pc5+hy+7yFu?U(-8D8|8VAj9;|= z>&`<$RJDb)KB4!efh0s|R_Nw2vYb=D(5b40X9AE}+w4MMdYwlR^I)Xe2GgQn@txp? zJ}r76-^WtezEEU!OKb6h(>EAfK2C6<-2|UMnid&&z02!02J#Ww)8R%KFV`IV!Fh=h zA5TPYQoCSkQ~Bor@AFMK`6B{~X)Te*S#U-hEL@)?w|&yykg2oKPDyaQ zcdS$mO==1&-&oQE;T@ziolEYPivFDkyw7&qRe`NkhPR$<@Z#Md;ElxU(#T^fcuCz< zJwbyqpJ*suijjqv)wjx;uy=6IQIpp7a^7U;tgj^J9)R^*q{3LBNM@VGng=T|p9A6p z7{0n3xeiFDNvR>JaiA8yb@|lU`LZONs5g^jut@I%UDD)NQ!l3d5Jodq{-<=>+Of}N z3ySC41S`+R1X->cLg{l5>xHkFv&~;M967zlco4e67*WG=?qze^s<@${`-hW+o;^W~ zN7}pK_4XjV6igPG z{Vb!pg2Pp;Rn9i2>M)l&F)q$slKiF^^?zn750Bo)$0%by!P|~Jh!dH$ss)=a7BW|D zk7q4Wn?UaZW(G&yhUJ>9s#bBvq7zXM=g!FuMZL!fRMBy?BsUZX61wUf-5Q@ls?KCg z4XW^nIZ*QXpE=@rQ6f|X8?Fl;=Ofa8Z%*G*1r<;mY@&N(A{zINml5B3dXHtNx}qfRj-TM{)JuBB#XISUbi((B!Utj;>@sYbDgTYzOr4iUd z$25`jQCXBg$mZMm=HJN(V2T$IQEOqnArcP1^)xqBAH{BB8Nv zA5Hp;Eu0#S{FQs!Cz(B=Z$FL^b}piNAzNQ3+7%Ndf(?Y`E%s5;`u3J zIRZ=jsKFnB%!kb-`6ookOZSFh*dn8+>ZGA2Rg-^3#*{KQ_gYZSlh!kS>AMUTq5@h* z$b77n@$!CG>(axXNW(2&SE_e-jdreF?|sKGgz(_`?9y5?Op=9@7scwW7likr{5QCuYeKX$n(Fdn$@rmLw0#J%4Yb_l}F4-3`=`)OcLV zd&x5_?SsfPn0T8`=W$IqzV8VQ2_ZqGO20zMwz_?4TW+R6U9F?b1ADLa&GUZa)ENQX z6V80H!C∋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%0An0;e{Pd^)b!{c96l@V&&`V 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�tROt{!+x??KU)F|dBS5chaj-ZC6YB=WL0OfjHF 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

`n8PQ?}HuMJjJn?8b~Xy zZ)X&`6Ivv%$!`9gD4t2>ajk6dX9PXXHG<8L?MjbYqvkO0=p{-^45du2bF2Kq+zIqH zwj^m|57OZDeqDNR@P1Wr%Vr+ml!4G2oAytcYC2A=HkW?AaUFfqPkS}Z;-$X)Sjvdh ze20qVI=#QhW>yq3ZVGA#cm1(;r@yapxU~G_u>WHq*Bs-E#y}uZ#(zqeN)voY)cX#i zora(GU@CwXNH_V-Vqw{2tmkxmKY_07N-Pta4QQuqhH_Giuws>0%}j#~4)<2pT=Ql9 zt|pj?J9yxm)C%Fbnq^mN(8mFDaiVrkL4#Hh&3Ms5Z3Faii)*IG%GTBcUND%X`PGX# zlY^C1lob*;Q-LW9aNC-WHLPO~_C|irNw`P7xj~9=r_8d-9V|PFAVF>DX#v zdEKeI#i+We${E>lSg+ewirbOgs`A1 zOz{^;ul9d?aN3urs<)UycDj2gF>t!j5zQWPohvCg_{OK?M&e5{{AH;=%GbHxF|SUu zv4NQ6ZBqtL{qvB`IfD>Q4Tz-u33j%x)~G;NtMLBHQ;74P89wh3lBuQ}Y9ywVz@fn* z;WV4DYj%1Yby}x*BI|cwz_h^u>JH<(#UD<-q@vv93AjY51404Itk- z!7PBdJG{1ld}`WmX)2R{e~>wBLHP4>N%(tmL2G)#Hcl#)WtNUY2z?Az?yT2P&O zKZ&s0ny5kfs^Twd|6DQiozbwwYwWGh!mw3Cg3pxo*3E z-QTa#ccdAtRsC4R2rIy7*b|{$V0H4H+9|c?RE;V99+xHW%SQYg8W8pr|KT!&jIL-HqL_Yh7{x@BZS4S+r0V*2lo5Zb=dalop@Gw?KE3d_wL7)V=0)IP)g4-# z^7g*uV%vdO#o90rYw6h9fh;VrHD;LH>Xm?%TdX^iJ2vn`;q}0g*HW9a6zSE4X~uQ+ zW-7~c)ksWqk-$ZU7=4;uqb8`>OWcrBh(EPqcsaql^)F1U>f zh^0qw_-@2TC|Hs|Q~@337lOoDQ)hg#sN3M`oDQhiaD$1?t0JotgP*O`}}+I;O7Ki7v7dNJy#>aVFiRNx~c+NHc8rAkINr5;5?kSia%D? z_`+0vy&YWJ!<*a%XITy<&0^eqF9q+)j&JU5%rt%!@O{0%Wi@HTY?zGlYR_zcFL)zf zawp}j-&I)_)#b~=UW?qiR$pt&9d_Xr0ccZ5>B`E7Kk6##nc^?Q#z?32W{lMJ4zjxw zE!muUMUe@jfx4K5_Y$Wm$2NLtJTpIa?`2B*k`?OwqQ_JU;>6=k3arEH)FK!z42m@v zu0y(=dw9w%IOA-_BoZ9%s6@OSFr1=)RqDRIN^`KjsUYchz>PU7Amma0F|f|b@^kFE zpqE>5brnfFepnzidU^J6Z?64Eij=WJR@6B#(ti3GxW#{aOmWVfh>aZt)2(I3RiUuE zuEcGIVTkH(?i&7#_IX%|tE27H+J^NzIfQf1?`Zo##jgOx1}}}er|Hf!(l$Q}iW;%G z8v36U!T8_IJgDQZ-_}P3(?>iu+e~4@7_kkO@GGYnFSTQ-i9Fv#glTGz5s0Dx4Wa?p za)rVQJ#>>_Ig!gtx-;>CKK3K6fNs@?sGDoeVcR(Yq*mV&s$1k5)?KTMQd9kX-6jKT z9Q1S~U7S4YN>A%FU|v6Tb_Bu3wdj^}vX?>gV#mMpz5h^+YD!?GD`3D6jfuQ(PFhqqix#Ar}oq(n2VYq|B1B+#)XFL z_QO{2A7$R$zLkr-u-IxpuhA-Br|w@lBdP-@Jvl{*yF|`_i@&C;kT)xdo7%Y-!XW3S zChk0Q2XSTE={cX7VS~5RQsslq3)Ln*AxFMYSg*AAdi;e`23*}ygJ#W!&bnh1q(VVs zYAu!lA)N=Y5y2`f`02{ zEJXm?tdyKQCrRlOMHqh#lqy2tQszR^_DwnFziM_J!+SPamVLjPA8m?_9oG8|E`K`p zWQ@4Zne;Oh-y?G17QX*#s?Sr{e>})BJv2zaV{JjoZc@n!P7VZN$_n!t@1;&OBrz$U zXMcN%cYF9FyYAd{gKq$O_d6ZP8By_Iz9WV|j9iXtH8U4K2XjU|t75Fd+&r{(_WdT4 zd1l=v|D{x6hw&ghy>uy5ac9*^q$Jp|`_7K>gnjkbfRk$v4pqw8h-HWPt3dj#aU)P| z)d>2%Z-Et3qFL)NdA>VO*R6QX0QFqYcBeLHdOz(Y8OeJBBZUDXg@+pTl<={D5KpX4 zW4wg7M!J;iJGhv%t#SUa0avXvipA3lmAEW^hh*rCs+-|r|kGNJI-XDH~xZ6#BEFc$w@gTNQ7zeXLfIj5KnQwtFwKFM! zj(!AR+up5}Z-j!s6Kz=yMjCvghIm;ZV`jDkyRSORkA2ld-}3jl6dZo#@Tuu-)5!vF zK^cP0Jk``k5PVN-H?#<0RO^&}ic0zL;S~36qNW3J9pULyG#xkz+6S)ZYCOQ}&UsCA z76*$baFe_HqTCcKdMa^i8##K@9EOUE2PC`ZUQO~%Ub z9g@O%xWFuF1RN$_b=_y?5VG{uK+pLBQZAKu2Y^aiOW`A4BS2EVVYNpDlMPZ`qSHX4 zM@(p72_W#Uw!4;$+}leD|VB zFzB8KdyGOGmYD4`;k_c_wq%qe8+yph!>E5W&osHES<263VLO?=XNgyDCZ@bNW%mXs z)n}LZ*5)$_2rBO@N!!PDbqpr@JuScGdia_Y6Bh_J(o{6%eK1`QEO#ux&9l|G@kbt- zdmGPeG$ZFH9wc{5-Y6Q7pJ7+95eTiYQi`{PBW#c zYtz-;>jWx@7Sl#AAc+;H$0Vk zfgT3d%MdSG^7>K>n$&)^R`;Z=C3LA966D=zJ;Y#O1slJ{8n|%>1fxOq(}rDsZz8zw zwRGsV6p2rzEXwr${NUy+g;~};lJnNga!3xOPgJ$d^2K|^-?a&*8&Q-8KMPRPqGo~R zU;M@AE*LE-k1h9R`Kmget-nq^e73>@ZRWH$kRTa401<;NAYBdzBnzz(H<1(+Y+`Yj z<(ND{{tI2|cZ|wQ*K=Cc>0wE4ckL(Tz$N!m7zXwEznL|0Pp_f}|`RLyKgm~v!AB(#k{x(2TZ{7f5wkGVRYM^5Apq*H;HG98z4I!jVs#%V z!><8m=o7veQU0WVDFGkqP8(>fuviNv{SP$ zzW)l*VhNh1ghbOxtJ4S?VYWhmodZ{YRH)m4pm1z2Sx;-Ga3=Vu8y)l`QJ67d zpfiEX+uycU8Dukw9Lfyya)(S}PO}D88PlE|@0iVW`7;F$&CV@ZK!n#=fuwaU()dCM zw=oNldf%dIpVVF@nIwPp1kqE)61ZB(03air2FINe6}CH9$_#S|U&t0}Rd>04Gw$~6 zcu%W0%Xbi&tC_0%vNLk&sLpSq_5qRoy3}qw6zM%RYqm$|^wN+E-IMc3^yc`&*6;gs&f03vO8d<9m9Tw>Ng{)0oPBNVLU*i97?zCch&ICyXb}ky1;oYd zajX5EoB-tIHc5mwymo?QHga%=@Y{2xOIuVSZGeJFR)5%js-*N_{()RSe%J(THJ?=P zwrI9TGv?PcBR8tKFV8I__t*6fOK_V74Su|7?2b>I7uD=~80HokH!V~`2< z@W*|*0Pq;d80J14W1}NFcX)qb%(rC39d#14m=q2}#w4<{fp9h5m9<{TQmPTbOCD>u z`1K~aUohRO>Pia$jKCj_9-X!kFncCmFKe0eGJHkgqQCLkUIcu2TiFIDW_`ZqgYp>= z)30&%dQ$qlCjL$Z!c^I0(2QuS^S&}u>V=ynU;`&#fa_{OK0rq`S~NqdYn3P1E(U_R z2Ob@Guk8F7dHTRq6Rw#fldeXGFSHzp8^XnPUjsSM;0mfR({S4Bn6w*r5|nHB(k(O9 zUop%As6c#iW^=}Fwi~0QyJfP0w$lDlmZGAfR=FX2z1va-QWBA2U?eIHKsfrvfk7vp zpNIGOjT+wgPmZ-fYYIU6NO^m!?Qaio)C*n`*dNu=&u{DXq0#dS=O<@>07t|Zwm)%$DYbzISY7)4VW=&b9+1Ad?5^aUYPS%321VUhg7}fQR~hkbvE}}RC40`ho28jrPL)?(@Z!;VbCsI! zYhD87wZ7od@Hh5~zBP(s#f{#?f~BrOqnePffYr-fcVPTfe1W|EdVzONnPfLybu2Pc zMh?_3EzwQzzT2QG3EC59(gT$Y=jxO$a1A9`bZa)qe%gpG`Dxwlr4Fr`yg(8ilLV?e z4F;MJB*Y2Ao7v=`r8dbsM+lipf575wTr1H{kp*|698kA1P?V! z85Dn_hX)NK67^cY%-I6l%tqsuQ#CC_IH0A(uyWQ<&?J0AXy&6Mm2as_$X!X7yXS3S z5Mc|D(eXT;t`}M665FEbC9E(w`K6ACF*m%%2cldRR^Oe)gtaMQyvNDHyam-aXd^3O}bEu>}B_z~R`T6>Q z({{8&vrqK<`eWrvs=gW71IWfN7pl7+_O)K(i*8sf*nI1(0?Rui`fyo z2t$P?77X?5+DnwwAP>PGlE435$*B#LoWh><;%7^3W52d32D*Z62k?{dJ-MvdbHF9w zlkLFz~=Oi9l+ZwR+(Flax*>^|4IH>XrQi&jLvR)26lOb`&k=0YWU z=p2{{MEFbj|RS;QcN z4r7d4d^MNF`fuO4-sK_PvQm<`{VZ=hLFm!iMTn-QnG600GJzvdtv6jt!x9yV`9l}+ z*ZD7)8F)MRt$ATFqWe@gx0ihHB=CnM4P@S}deDAUUq;|^Y|CxA54PoGapjBMt8f&fLO9V4_{&=8V zVUr_|*J(55?a!^vx0Qxa@smOpJ^l69Ro-8}!x1Ancn#F5$5+TV<<@z4H1kP0@8!2s zo`9>_mu^seRGLuXuI6G+{3teR=oshuD$n`Yw%bZ~Au8eMbfV?3(l9X=Nz%q!YnDuv zx}j1G*Y1gy-m}_{rCo}BATe0k5vO%^1dqfg9-)H7J}8D!{hD|Qt@U3oT7-GdJB z`2+ZcimVnlxKuvE{d7>G3O`CH6(x8#{O{fw^h^d!LipqP3v8jZ?vtX4S~|azs?!GQ zxvsmcEBjc%K5D8O9P|bY7k7#`H$!5G&e)TUD%T~%I`|WRy4V+4H@OjVJID~_@R7um zL#Pa|^P)P34n*}OP>9<=s$S18b1BGLe}`?T4(Y@FyBNwWek}949peIQf4d3a+S(;n zPQRTZ>T@T3cWRZ9%R!7_gF9JUS`R?ar@@^DgNu1&CvA*2+XX6w0` zOYgBer=!0Z-;SW3kHK$zy6h_vy~{x77gTkaHSj9w8_`dpk`Lh4@)heLbxQ8Hz#cLk z<%;H4H&b`Ymi{*R>S?xwiE%NHFJd^=(k_%#r`srYI$?ZyQZ1jj+VnGgTV&g|T2%Kv zW@JMZ#GoE@E&Y$I@ZTZp&mi+hT)M^wgz#@4jIV@nKYD?4PK6d3Lzg`n3(AO;kq6vX zuKjAdprhH2h0*=w#cjKdHwis&a&x-iK_;mv_1lN$VIW?RlR4qsBYqLXi5e-cQ;*)F zBFCM_?l*5I9_Nf*-o9d^n*)wf@i=(t~ zA1b_&M&>i7QYw12D54b!exU2n$o5%1ubiaZ4BH~WZlCXIT04d=$crR{ng#HD98dF6 zlPlb2S%bMwKEJbPaytY+{K*c znN-le^1_(&14sm~oB6y(li-hr+@cO;dyZ?_twJ9s-yKHj5O z!h;f97dCQC^v>j&BBn3XpQzAGe^E76e5b@^cRm^{yj1YMV)%KZ-PhvN;WW0G%VHDN zbf8)@7nPKBmvJH8H1WY8rbb8N4!GKq^H@5!W#CQ}O!oJ!RdrbbW?eN$9YT8_nKFaN z#XNtQD=2Nmcc#>Sv`ovc-U%UZ-?{yr<`$>z5$U%|xzo04bP2}xUE{$BfARGxAvsfb z4RXs!ZmS#(zKOy5TM6AYJRhOvIjY4uv}x#Z_u9-44SENsL(sd2Uj}S5o@u3tPZ;XR zg4;PIoeZC0>bx*HO%_E7m`vQ*>_#zx5P?f>^Q!U9a{vP%S-;{0ya<|-*~_-6pb(0z z+0n>|oQnD+iB4@S?bmB$Ci>DlFk5Y-hF^R;rrEQ)C!$(HdaFomBQ4mwce!}GKZIVm zMMKK|boOC>Lv4g@YzcTVuo2x*BEni&^W>zA@LpmeC@?NxLx{S~j{*vUsURq<4Wl<+s5!oJXkPNKKV<<-|CP{+2UFv=@$kYO%s`({z$QK3M z(NKoYD?`a&Py|==d!-~@Eea2f9U+`M9Meeig7xM-%z2~xg|P`*or75isN!r+HVqsJuXiWxEK7x}(ZBNCp#fobo-+pxWPowO_dYpRA=AlUIa)yR zbm3lRfT(6J^_|i~Aiw>!1_!VZ&@B_vL?}IEVI%S@yJuewhTU}wwhcFC^Jep1DkLQ+ zu2DZ(d+(kve6NS7xIEVfML^I^TV`0=9ujQ5zX+)u-6c}JS z-x*;WR)AnKG~$rv32saa@JI2cJWp|`XDe6JTv~mUsBc~_o?a@wR2Nm8I7{vp8p|c3 z**9UNm~Z0F6|uuIocsaIM%~TeX`%l^JTdF;dJ1WPt0@-@U-oJ5ZF=n6hRiE7RX9ml zTz!shd&$IrF7I-CZ3%kfI8toUQCm2VS_Lx_5Fn58m@2Y{wMix)G-Z*w79YvW;9!J@ z_y7sZZ_KHj$+qTD#}aBj^@PbG&?GW|ESP)HbKeAEq>Dlzlu%R&3IX?5> z&h&2itamsfesTC`HT~D=3}`vzflr=PrVJ4MjS2qn&`^XGT$#{x?` zE#VXamiD(#8uCg22!w-Xp#1ZDuK&8}2|F-XBX8fU_Sd`Rf4+z%11LJ{OT+%$$my>T?xQ=iBIj+Da95o}ZZ*3uwSGu%rv; zCj!LRy{i!=AH*w4>HVF&cF4+HH+RBgvN)*wk`n+;-lIjU&mGm@@d5|J5$`rDjTU~< zf%Hm$Jm+aS&KI@SAEOP7IWI0T0U>Uaog4l3qKqNXX>Rn&lg8e2K3v~x?fc$YY}vPe z%A=l`UStUE*%f8u0kwelN;_g0r3XL&C+Ch9>;romDJQEq_oi2(bAuoP<}J8|dm*6x zABFO3(zLVO{>FP0Sa+}#3PL!C-^0E?X{_@&p#7-3jnn~Afs|lIU7mkkX0v<(P!o2Q z1PsgOn~Sf033<({9h?+Df>E9R?q?nintO7v{GNE|7Q?|_+PLkcMoNI(BXQ>`)(fPu z6he)F5bw#7iq#Up<(_H!rs`}nr$s)h#D6C)DS};I88hsbF48m$D6Hc%I>?@SN{7zskW-?`2n%EhD;Ls8kh$kir4bd;G^*iIfbZ4;o0D^Au;OQ{nM3CLNB*+|KLA*_)qwv)af`M_{-E*g)H37bmygH| zp|Oc+cDCL7>#_X8j$QX9eSVoK#|zgd`5klGBEF<_(=^41`2eCQVWf{qy_-6qlF)DP zbfW&0?ez*iAxQD7(H&OeJKqtJ`y#|&ctSnifUtcw1>q}8 zjD^*;^3=?yR-zAw2L&XHR0&AWpyIAvOKdCn6wT2^cj zOYAn^VSDRvD%`EDD#hDzsT3nLd}QRYe&~tW+goYU?2QyN3wuSN4qDsNS-9}mRl+;A zv(D0z)#ox1Q?i2og%{AvHN_y){<1rg--2r(PBm4azr>cEGlfiF z>_(;#IG%dB+Hpz&peR_$sJL7%1&i&g#<8?m4yR0!djs?;n^J6c+)CnGLq(_wsAR9q zpe&lY%1(d0W+8kV(chW(csEi*g@U0LJIOEGSY3@!XO<4^BWejKv9N0~>XjNwwJ?Tv ziB;JHV!7&=IckiP=(@W$8>J!A;w#qQ#XBA!q~d@ zzM1xB)^3P;K{DDJ%WwFW24_i7kF+akmJe-JK`KhWH4*nO8Bk5u2-&*;tidf&%OZ(!PJX%qARx#)b18&(8XY<@U@n`3C{ou*%m*v zV)zDE>Sxq`iB?egxQj72$~U}fx9p1N#8V$c2di$K{a&g4J(F@n3*KK7BPQX8dS6DL z`guCrTsC#P6kMPN5k#;ZAL~*;;|@micr`?1%}_h{Twkh=y{+c(-OgQpe}TRPJe)0L zIC_lg-_5JM6s(KI5S@L0EP-7OGKv$ zl4Ye%Eu%n;EtBC-Dl8!{4i zX=ZSm`5!cUNSLMcylmP0XeMq@ZQVSODcN->{1)J!P>FKQQtyV2OUa`3N>6wmf{xBK z8Q!g|qg%)My3z;CK_~5#0u@=ISOPVW1AdrJ{;zwsklP#zGi0JIe`*0h3}G~(N{VyO zE(p}1M0g%ov#F`rEu_munh zz*2C5Domhxk*7`CQ?GApjV9S_f*VuhG zPA6*cr*gNWjXdIYR0~x5ZuCM0gWp)A{n}BdlRVAxbT5gUxHWR(y9T9IckPyzDh}pD zbp14iCtAR`BYyU9TxHAck2_jo`f3>7sV{V)Lpx72pAd!rw` zvI_5yvwW?yMIL1oK7q|4#sI~NJ@4AB#BfPX{6;v1u;o6H0l+x!icoX{Qc_#6fg{|p zHny@fq-JXOg3>dD)9E z+OLD``{(zJ#N6cGll(ATL3~nXL=V%6uHRnjYx!9+dWGqQ9ZSL9ZWXHXPp_$7HRMfP z?*gP(MvB!1-X^>rq=DkF1I~8}?mx2cgE z{w3fL^b*d>l2ofPA|cQksZ(GaCJzTrw(5Bo0ZXO%o&6(-mTnv>5Uy6;EY}#Q%mxf9 z4yjVylKb(dyTGa=u4M@2dn~K+5|JwX7K3&5rE0;X^75poEXD`{f<%n!&2Jax5EQeu zF|Hohz7j8lpVPdzS)2`)MeR@1g>CeTRwaz8!Q$FwK1HPy8oz=W`wS2 zFr%^qkt(u30;)4kmngA&*xm9au{(ffK5dTRtFFJUgid>>+LtdO8g^rkb&+zd&v3Ff zoaOc)|6PQqZ}*#K!Y9~l=K zG)lk42bSU^Pwa4;GgZEgN9C@W)$%2uA5~xu0Qt+zg?n|$Z^J|1#?1 zch&NiD@Qx3D7~WI4oam5IIE_OU=_pcHbIq0(hDVaZh(Tk__H9ks8(zo+!aC9jo6tS z+x%T>A6677q_{T-^VJQkji6SM;;{~GRc(NHj-{B$lC&Y%{5OuQD!e*N?jDbs(}J!t zP4-Wv7z*aI7S+^VnY}N&uMTJ%PyzKL2GLNnxe*%p;Ukh6>=dnZWA87ywz7h3{)}wczI^WC;*G!MMX^Rsi=Z~*N#4$0|Js2s#VvDU)b3{$U`=k$u;Yt5Hv z``1q>C<7QC`%J0=Oauf35Z@>I z0vC9$KIqvqfIsIcB_DpHz(Eegp4()d@gP`NN-Y>5B4O(2MzK z+C4930fsyhXOBtVZ#WiHrvf3Ky^{M&4TTf@uvPc_A%kI_;YYg%zNjPPb`}bTy|rT_ z9z7mj>~lVQ;$FI6q9uCm1}3XOPuBmFj)8(vQdyHDSex-~^Y>*5UF^+nUy!CnoRtk{GpWRp zk`-1d`O$XiG(&fwxbF=RK*ZV*2x!%yQdmnEe`Vp*fE7TX1k6-$M`Idu@yJ!|7gIfy z>v6zjCDs`ja**Vm96!#`%#pHaUNAH-HglPL0ecWTL2l7_?HV=UL`_KlpPv9=gtbLx z-jHDJefEq9My_o}tqFJAYY_5BKG;+pAvere0`Nn5u;W9es~9*%wq zq!>H&$@+cpA=C)ufB0L{9`amMC+={%I|h=ZY(Z*3;G$7^bw!=ZFA&fX>%Pl%G&0Jd z>4*s)1&Rheq*&D$cw_P)b*W(Z^ySuft`GKnz$jErz%z~XxaPANis7oG3A_6nTZ;!r?b@;k_@pA z(!tBWYXW{l@O6gHti@k!9HbB77L{(a@mjl3f-PEjPadPPVI6I6goRlAqLl}Rr+Li+ zc0L~vc6s(%`5RS#5qv~W`}N8eU>J+)!J5PFs9O&zZ2H-TWwMQ6L3nK-Pq;o%^< zIrcmLJYYRXZ?l;O;6=<-GPRFDAw9HTFEN;4fqfo-nmbMKcYyr6n*h`C&UKLoP^l9W z`;&PGNOF;DL@V9@A9VfS|K&go91|r(snF*9ufOPW4oSOt&U2kn>HFDdya)dss=vJ} zP!EUv;sI)36TKYYe+2STz(6;CCPA3>uW^L`*-Gz9&v+5frF4nEdBT6uGyi$a|5)?f z&2qkP0^{~)f>$VVF9F+PeA{)QD|+03Q94k|4rb5ZF9%_>)hdV_2m3bqOhtO;0fR={ zk0VmQ?_LH5@++2q6b4kfn1m<(Zxoni^^7ymuAWo=w;qut?Z1(B_1VIwkNZ*tuB{US ziI`hC%q@?@ImcM8Sp>Yt7?%%i=xxw(=TM%1IOGlp@_CgLIchH7$|3$=n7WMU7_C_# zH-H%@o3$7%dqu-%O9ZkJVu|BiQCI+-hl77(W|TLk>n%)p0~$mtUd<9kTw{N`lZ85& zWIJpE6#FUIRzu6{d^vXER^VNIeYdoA#(+8CvT)&SGQsoyb z&8av5ndx>s*&7J2aod3}P&Yh++#Sv^4iIi1Sh3qSoqeYOd{P!y&Kn zvyrC6g2BXgr5I&ns#)v)6oaZr5fcE~t6V{k+3+V_Aibj6w7<2OUf|x(9nh%azk|kQ z<5ggM>5I#QncEm_CZ`RqMA*8c`+5^`mBoqQATYDh8+M77)8ehiXtg$PZ=!T~<)O$v zTPlDY15)iufC`ZF-gq6wAgvCR5L|m3s8lvC{qZ9BSq)Jjy&<+ZW-4sH%>W$yRN~tb zm)#Z))u$@fHS4Kv-lpzvy~CdgOHLEAFzkLs?U+eJu?P$%(VAe0mXDUzSJUiU zmz$hk?PQ+OTz7}cTAmxHK#xW%#&_V*Q`U~8&iBDq1NZZ z@uFu2G<=3zBLpthhWv|F21eaa;@Q$mOr_fWy1O-V_`!Qjalmv!nzv+Pm4oiEpC-eD zAU!#HDbthbW<4#^Tww@2`Nx9I6JGZ$-3(NNr?i?=P1+IVe+QSg;xk#^zl(@vt`P#- zX2g|x+xCp>lyRfv+{0&uNkMega{ffzF1>f0FjsKVJ}wi0aMs2?xBvj{bzWUQiO~O| zqI!|e$w_n*JQ<+9FVrLuIrkypz!`<<&wB-Dljw;e!w*+b=4?kKCN+EC=e{kNhgnDj#}HL2SGhy%~H z>G-22e7e!wOsd8nI1->UMTp9}2N+_tN^y;{dabJjDhWXWxXyc$&~_#D^6zrt)x5dw zUjRxiL0Zp?H+R~6`8l)?3H#VW(uVY2OUao*7_!cnFBC+nGoQ_{jsvryo{SX1iJYoz z?IZ!W>mhySucrpL6(Pfxqm!CY-KmxVO%xf$56?kljl+v-U6|+BVo(ksh(EIAaRu+b z;x1I%3|bvGkaWjoCHXB-BT)rC7lUoom;}@fy#S0bU-i>NvZbBQVkig?V9xqj^M|#; zv(;e8E_l-ez|>N2x8Q&3rHgq-oQ<*hK_=>elVuWQe1&bDTZ~=zoZ_N{S?gPZW(IR6 z8obOs!E7h4^Q?bH{gB&SK;hF#^QQaXc}j2yAiet0F6UPBedcse(RTVfk;Q)@mQS&J z(MIYw@Ade)LfQC@KE_1dIw^nUvnrK8WPBUbdh(2B=oY#}ctQnMPGv21Va_Z2P@lSy zUyZZK!a+pQ3hi{fl<9e?{oX{qdxeX6yaPU zm*{Y&bb)7-t~lIre8_fPDqIZHl6qZOoNVlv4=|ICqUyXGIGtG(7F#u{4bhL8&N6NIJ@_N4u zQCm*T`sl~7H`Rpt7iMW3{d$l~Dv=xECd2-{A5F81+>pQF^t&oKy!r)b6*<{UiJ(94+zJ4mI&DYDiK`d2c6jM8W)pmh3i6fzaXAi zpN&{J!FXnXLv|{%3)s`#j=ut&0xYmG0PN`z_#2+nng<|0fL1GtEbb5B)Wnf08}Xdo z{^CKnZJ}|~E7m)Q)0NwP5wz-^ugEc3!b|q5#ml>SebUZTrVlR6F-%qJJEnyKufk_N z(jbA)_Bz_!&q+gM&kIU_a04W0RIgz@Wa>a%|4nI~#Bm8KT$brl-5>%wIedSRz!G>w z3d{ebSDeKNE2a7|EXL7fj?iy?dL-Ge*uLnqHE$SxNC&bHo-H>KK`$|y|9|Ygc|6o# z`#(NJi9!iwSMMl7vah2>N}_E1O>}${Kde+P`AHE9)Z0typrd7&Ol^r(8Ad zSx{Mgv*2OQWDm;ywWLB5z5fHv9R|sk$cSIN6~@!-2n_JVCNs~vJbKAiq+r@l??$}q zyWa`to>@@1ryX*K@M3N!C*OeNmi{X^+Rb%ubuu;^KIbrPVLrS6){@Si_X8aD*N%t z-s-V075C=gGc*R3I+$Y?$+P2Ga+$Bu(CDJZT(zb-%dp3)#!S5#=2N$F{CoG@nZxG~ zdqK>UpHfgpmF`055tC)mfPse#+Y)h+$d^Wny^t9s6-f zbf@yAh)16OmoTcA?h!wv$F;Rd&E@U05N#Hd=1Ws>euw^_VQfLqCHv{y2~n zv=6ac%j*6*RzO_Wo zb>kj((ZX|ABRQ`UgoR$ct~5VJdHf6Gu?IAtpDQ#SVLU{&PvH0|y}qOyiL<K>b7)|IFCl`T;p#jweo2NkUVdZTO?`_eLsyO02mf3y z?nDe_%QVH}qs;X3O_`d9dGJbZ_eqhZY6UvVncEbx0%;lwQYM~ z%3%lzWCKI~N^FMqTWwV88_?9Cp|sCyxns7{qo$kn+Z&`P<#55} zsez$s=59;5m5cPfa#$^S1E)NADWM;!G#eS`6`THbCXd?LXK;EM`^t-kkw?iFw3()2 zVPS-LseJ$6_qUrKRd-TVgZerv!ykbbD1uAdY%?a zkXwHwJ@?AQxOg_GTQni4sZDBoG3g$R!k%}r-#XM_IkE7ZoZZ?(Uhd1X`=qH~a39z> zg}voIlO-7#uTa*|KHHbyR(dK#Zu9vTsX$_tp-o=Qz$i6FX1xqEw{L+{<_LW_#&q{UETi6=@c39qFnBa9b4Yx!UnQq7#bsoZnfN*R*c9I2x_CJe1oMCOX_KTA&}cvJ{%yu z^?W;B;E5(=Kt`{DDOB#vjCJKYkx8S@WshCxOime3kAZoxx1o_Zs*bw4aikkP)ZBJK z9X2wx?davIwWunX6=^3rbezZ^rxKg)M}7`R4!l(kR36eecnqit3BeTe2@*>Y#7G~q zmDCl|hSliKLHH2QI1f3D6god%^PI^%rovHVbh{w?X=|LEnVun87Dbroi~3?2qHXBp z^o}e{7;-|(L*k)G#Jj~RYqYS#muD)MWdk?!n)Z$BJx@IgjbrwnffKr$;8E)dVdoG3 zi#NVpSAyu9(HToqedmjRzEGN@yv77cWqA^Mlv&%z&AMWB*;>?TJacjoB(uz{$?HQ) zPhfCPgZzmC(<}#4_s@@g7)dh5cWVW7X(-sf`LGaDPCn{3w0$>-9m?z4J1@B5Q7W-# z_=u;G=f=UM99F|;8-382H7pN9I5D$bE>-6xMB0Bq%Cx)e;u8c%eqL6h_7`t@IroHK z1SV@mQqw((awIi=LmMG%-~Y*@_Ooc94Mkk5SbRK861rB~Rk|{d9S{v^DymmcNEM{6 zPBq6IAa5_F;tHjPg60Ry>U~czG`EQe>kB`b;rWgQ_$ON=T}B?Bh;`Gc3Yn^O!X#qN z?=3X-^_7R3n{YCNj%TekoktW?l}d^-c=rrPZwm=Svf=ut-Hniyg)APYD+wZ%Tbr|} zm=2G1V!Myj7*c#GCNMjI_aZc)2;TqA8gHv*FeHMZFSA$2e;7G|EACUsAy3Rr7V3w3 z2d>hIR7&1jk4=BJP%-h*vvh;Z3-rQ2c3f$jnyMNvwLhE)y zqNVYTneUGVrIx!GwEX}TRW;?Xqh}0s6U}cjoG6D2vyoeJ=36q0u{p|bI$`5B(~}(g z*z(N3e&)v~!~?PIY_fLT^_+hy$p5guI6no2y^}87>EzF!{HQ(?uYz^NtS(1${4}lI zKWe$E1R03c!sr7i|L#wIoP$LtCFL+*Wd)zgcQXC%yGl-n86i@s-ICh73Gvf+qYHc? zC09jq8V~)K5qa8U0rgre3tPf}-k~2K_czIY*tY*WBum_&iCt;$o$Skn#eVQ9=98Kt zK%+SM2Neb8rOoOlJF`v0Vz8X#=p$sda|*(PD8k{EtTf`8Ljh0zBPKr(Mk%pxM@Hv5 zW89sXuiWcv)QK!m?KGRWEu-E7{2heXTbuNL)`E*UJM-k)aO$1A5CdZfJ0oFn6GIgc3`R{FgAKzN^q%ZKy;Q!i79!!L{W^GJ%jU0@ybtBDXMxu28Q7EltkakbzUr>JbGK@VUX4V$S*)zx3;GLxho78urn>>=O_`GFF zBS-C-XxR9r3D+!RVy5i+dw5wr@^W)f*TOL-=unpV0fen_(3Z3MmQ|Z!?mR7gbljYO zd~X^S=A~8tqHmj>U>z1Jv07`)} zf9o>}sZg+g2etI?I*$987|+axLTufwF083Q1TUl4=x(h(v^)9&!%<*55h-bnQ0y_s z#=K@v5#_>n+eQ%{Kq*gUZlLoeDg`n0vVC?%su*dR7>#>PGhf~EkWSy4y{jtaid*|9 z*^Iu-XH-$I2KBArp2l20BVLzd>I8K{a~YK=UYj13`GY;Vp$_=mQTLz;Z+kUm+BBic z1~Yy{vP#m%ESCJaSH2p)jrxLqlK)|KlN|G$+Pl(ZZVZaLK*+Q4nkWhv8ZCjB*9{{P zY~1(tt|e?|#lytj15dZ{LOIGj{FAo4qM|U=e&dY(_LnY1`O@DJ=4bGg#w=3p) zPiVd9_m<3ftO%c&_jn&&#Kjd8e3Ck7O0^BT)KefWDW;RAqCA9MAjJoZ(Rmc>*E|td`l*Lqz>;2d$0r z3;K~+4e>F~UxXf;j;xCIaZ_(e(gjF0KN#gUbxQmEVB%puM3%Zt10^Sv!=c_iVi~wp zFn+pM19$C>Ev*BRKv;_Mm|5T8q8rkLHV1Xea^}Gz-hVE7MLI=ShcUz4OXVp`X&V*r zMOpZ;twW(LOh0J2AKVbXmozlK*FI%3QI7FGzfgBOnHbk1JJ$VNWkC9PNNc)9v5v|4 zFeOQO(aN9Wu9u zqHVtb(eD+IE{s!z-XqTEu8;+ctu?RS8?MwjDlMJiEfnh((|Q;&zdhAQ*t`w<5Fg=> zKFvr%u=J#4fWR;PIss+o&c&BfT|5q>@f8^;*5;B;vDN~ug}v|}W;rlz>0x0V`yZ+( zlM(RzvxU~SVGm|+tLd(&`XC7XBTM;%UiB%0#aW&kMQ0|x#WJK7-Ezj#DTk-GQ`j|= zm$~yoZ+pZ|J3$*CjMd~7UNsj_73hnmFsD67ei@f5xA>IVDr-^=R%$s%PyS*)aSjz9 z*G=q#20equ_S(J4Dw`p;R-6^Pq9>PHsDZrn{CejaR!U*T(vW$(ayD}kYTDf-wS}$S zIxtjxS!j|FVzOyAgV(_?h31K-5VX?c)vXaKT61xvqi=33#RxQOlzTbrBYSCcja^+= z-|SKOMo5`!v^I3v?>m#Hh%dB<{=o@7r2>3end|`3LlzLfLwzh|r{7h|(9L){-?8_# z?q8OHrID=K##p8u^tD8zKUEgz&ADnGjcs+SyiXp2jSM8|thh}h< zG76gnox5Nw2ZnWYl%k6SxmKHN*Qe&2#`Fk1uE}T5!kJ^!AJJ*EnR`l7zxAJqMqYo~ zkyD}(j zmCLbaQ5s4I)2y>ef2>wN6*UdVIy67X#@E*B zRKD@>;YM$u-&wR81>RY&q-9Z-2+wHF@c4xN!2v&G0<^EG&Bp@~)h}rWUQy=|Dx^K$ zOt)>2n`ku0rX2gUDhdsl^6k&XrIi_J`FK>b(0v-zTwvq0GuNXp&UB5np`G2lA091r zpE+hKeeS^U>b8-BykyFK^NN%?KkIVZiI0ZS)UEy?f+e@4TVz0;=AeA_PoL%EBCv*x zhT06i*p>@(n)64u{V5jrU}yAT=k;iOHGNBsgCXwDERHF(L(a)7mR%cVWRk^YuG@C6 zVZ@aDM|3`hF7~dk7swA9qgMo}+PaBC11nun@0Z#JsZMs9-43+U46Q|S>e?-|XrucW zx#GsPIYWI&1p!vGJonBz1CiY#pJgCxQf%+?S-_>7ybwxdH3aqS9N5}kj5(939{w5R zzixNLQBG{{kt+ppJ+qd`^EzFdEyM2+U6_v+zkQvx8#AfO()(QiJn!crfT zZrFwx4l9w$cnlAZONuRuQ=ec-9nLSBSphjiMW9EwUB)9m&3x)LFrHCuqR5zbb zk+6C?vv>wVnvR}Z5qqr}?gB7-=+kZ?t;H@?f^^=Rb?dTyGMzbQ;orVt&RB)euF{0;HaLZ++~btBpeJtl`mfCv0UrKlW9o9bc=8;G5_!PCMsr z=9+CUOLkM&GL8{2hKfMcCj_|N2Nx>>Wc`b~_bl(&f_6=sgw}nEcLRkxWW+QuT!bmz zL)NS5Pqh`}k3mb3*Aa&E!tAa=k~&@&^M)0(FiRL0y=k|*vSAxjHr9*uaNY3~nnTF)`Z9wqJ|ku2qgP-gJ}qqgqWA zW#x)xbhhRfa7o%);fC)QtIlBph#A&}Z8hVKeQTZC@{)?L+Z3TD5nO?QR>Uc1E~ozb z&1-#HgN`@BbC6rD4Tx&}! zg{^kqIZ`CdB_$upf1lTYI6D)bHy1=0%yhDek8_jrvi)Y>JzqHWV9v+daLT(kBR-O` z*z~+pKbH)(zkkMY%)K&g76GJ5C4H_&k0E|8DWh036CzC=dOFDGTVdl;(OKE_274RD>Akqp%3^cTH<;-^p+K(SIibCprHG-AA~m5OrCxBEgc2EtLQ(Udvj}_huL@yOtSAJ>)NeMaLEx;acF%!`up_3_u+3)0dM6Hqr|^+h`$}& z&ykT45>X>?bk7fq|BW&a*r5mITfYA>CjCx~bBEgGPqOgOCo3HS^iWp%`b&!R``rII z)h|25rO&u~;5YO6VIHR*0D90ojs72F$^hav-D3{=C5gJ5F3Nx&tQ0qy{>Pa6c3i>C z2crLD<7ogrj`LVO_=8vSuV4SoY`Zu9Z)V%20Z#qRY`diKZ_Tz#>nQ!L*>d=#(Gu5~x0x?P8T*d>*CK zz%xm{(X;QDPj=Bxb;lc`$P@l$`*zLY1}$(BPQSwc_f7LVypt02&7|9<^M9GVU zHbVd!>n@n0k#GpyOc5-hWh9|aB>CRSHV-wuyZ7;xKbscNa-NGviHB8s@k7{XQs@(v z1ZK~M0H4>Pxw!g<=WnG>NpIh}Y>kaz-sZhM&OOd=(x6OqoqK!n$=U`wO?JJ^ zueh#!;o!5Px&C@dBhsx{``I@gRX*kJb9gD-BTd9%V1Yv7Tn8lQi8Uvd!U5z>+mL7% z#I}9)K*jjmJ6>7c%dTq*izP>8tga8(ktFger2m4H9o0;1(6gkeui8n#;X5 zON<*#QVwJ(EGln_kP6)<44x3K+t!MY@8=; z40+A7owytnvV(lG$;Y!S#W=NP(pq)R7?is{Ympi}t7TxC94TR~H6Xt}B)wSfRlmQ1 zgUzlAZ+Jj@BG&R(OZYdy~I$#}QbO<-{c*v4-&$!nDLvWae^zk*!gkB(= zu)#`-Llw0Rl`BuEbLKDka2S+1hjgjSq*UYvhx}q7zVk@CFId*z+HP?_)2lqx>8$#W zYC)~(E_B+omPq1E{@aBB!P*@Zn%4qZ)7y&>XIy=AUwwtg%4nhuX0lN;rGBv3fYYQQ zq)pJbEBwLWs!f?9m*hEm>DAghRRl+e1x|E*IC_A?ZD6}WdTsI{?)e@D(zd=jSmTd>vs80IWr=x7wRip%w zUDiMEkjxHvXk|J^&QF)>)=}bu_R#0z`|23+g{@#X&fGliusLaU%YCzt)k>m#y%-wk z3df97*r$K<8J=fnDO>1Wh&x8!Sdep=3r9UmNN{op;u4c&aPtyEpK$HpPK=anDMOGxw?ix$tWC3hdg*)`U z?4I@ckJ=)&#OjC0XMw`yl9K)QgB5SxR@9^dnuIr%5gKnOrD4n2`D@d#ww8DW{-Uj0 zWO-@fSRwt&!Ht!P2|@}ju6W2pq*Z}T*g&5a7jFK@_M1aW3md;r3%P7w9Gm>@Z+x#p4oD-vc6NW)5+-&-VFsB5?$|P`ovB&bOUXz3qC;ZE%R51z* zd0nm>6AX%5#Wpij87o2wZi61g$QZcLHo|qUeHo#X4q4UfszL0?$rD4$DWj@c zJ`59jO3>x%mXUqO7QhwQyR{PpB)3jILQP@)LmiJsh>COjt(JFwQi(3a#z`g=N_CCz zAlQax?AE9p{chLA2q4J#Q9)6g_0N%_K4xbkip+8>Zgw%)bTSCf@zu4PbY#342Oytjb7SL-+EF{LEBBcHGyIv;D+ zbu@9y_d**mnko(7O2ycGZ1%RxQ^^)uvCp{P;Z>h5_HoX#NZ?M25azXCxr5BN83GbM zUP&_3_%8FiePU&n_s2*Ga$LFbr&vqnd1WW6X}?8J@Uc^S@J*Qtikx-h1pkgT$7mM1yu;dj#Dgym!JUx-`!g_;G0vMZ8M z?hc(#a-9fx+@mVYc=>59?BTMjdm=gf%+7#as1LN8{`XUNy}04+cLb7}mC)5;ty1Y@ z9h9ITVT*NFa)u99t;bousGgt+irui}z}F|<$)bUOSf?KwzZqa=U&T{DV<|uDH&szDid?%y9Bv&wjsU=2JE*VWi`^i#OK| zH$wV9vuP%NP`a1%BsAbo~h z_FXbHO@@?goT-eGG})0sLvKy~8@&O1+Y+Pv2|>Y4Ic2;|r#34IuFRKVq3LvSjTxwW-1+}y7}G-K-g6X}#JcY-H} zo@;~PuZxo-t6$1rU~g43EQP72d2g)qI*&I;IW(GT*D+}*a_ZTZ>To#p`sLn2RpBif zvs!Kr1J9%mFEwx&Aaku|^H$KfT3l#=B)q>@F-4~8STnebc9)3Xxdd9+s@-ICM{e>v z5T8!q3L9&d?ciV2>^OSOo9uAcb)~2U zQZ&S|fqLRl%swM-gK}r#Ii=O2W?BHHmJMOEcU+zB7RxSO9tB8xA4BTcq6ebv_^JU*zsGc;?iN@B^`c`u97l#5`ujo06@ja(|2XXJo z)DboP@~U^iH)(l6VY%JFnda-Y;TUW`6h)qw+q)BSC*|ecg6NB!m-<;ntKHnelxY`| zoXS9(MqI9gT|L?>lf7XLBWX9>A4G?Ha5Z8zrQq(D8U@S(@qCI~cy^QK%ti+{GVZO37Ct8X zw3B%~B1fMo!&FZxRbcp*KIQPOQ!@{hJobZ(ytP8mW2Hu_TaegRvKpC5dhxl*3WB=& zB+l*}Co|5Fo0JI z9|p?qP%u{yar`7w5I<#VHbDq!`$=eBk_q-HGsZb^DL=J#)gvEQGCSL+;EB&+`<9^S zp^&{bxwJLowaLxRsSB%b5aX-OC6}Hg54E9tPZ&n6-rRC%77VDaP7MiQRpeyDxEjexE>tWZ*Hc=+F9@zwSsAjsO|wqq6uOb- z3KZ~JH3@-eK88Tc6|*rtm4&i_y}8;8YDuQYYClunC8K$i65oJG;-FBb52dL9$gOnw z>(oC!2{Ei^X}13chc-X>8k!OsiZcH=Gu@|?AE7O0UE~Sz zwqt=5=bVIafee(q_;~lxDF31<-O6pp4%v+A?OQC1TqU1g-vkJZ_LxoUt~?jmsdDnN zQ9zB>fGl!;^bIn&p}sN-Ih3k~j(p``Idx#*$fx-79>WeO9Xw-Sb=nsxgFyk=+LSo$ zFHoy^3h!|_0t_!9MpyDgojU@WuN(oxvFfqHZcx=J^FrYv2dbqe^^90Qb(MKkdCsx|>ga00r4fQh+b38^Kv!|)9>S|4GU znY$@)t>1ql0N7dKbMME0_L2B_+mC{qi*VS0z{guBbL=WjlafsCXir>;VRENPITb99@eUhu;Wt3=)FadLv{TMNTS#jG7OG57pS+~c-^zpri4byE0C6*|j>DF49+ zF}e>Nu=`70>1W$yT~IhGqOp0l%#4s))VacHwpZgmOWL^&!VFg=HCiY?2isajwy<@w zHtSNLi)5b`c$9^QqsC=E;(bUf^Q;h7O-((j*9R#m7V~n|FJDcZ+#w-@?AEv5yW54h z%q|W6Y0=jL5OrQBW#ySGqIe9L% z>*%es#NiZvA>h?~8M%F4za&0>(Kd@>aclN*V1A;M|Iq1b(p*2WmTk^!EcBo|Zv2dQ zd`WNdSkAeamUBsu0TAcl$qWNZs_7FvknGUcUi-y){Q!bvp-Sqn5al@rA?7w3`&7S%Uq{8^y~_CI6T%#9cd;t+swnaE_Ubo zF+jJ@qMXLUt;v3CfrdHPqyU=xROyqSY_)|gWiq|5rt;iK4mMIOHGLr9HJ$5pjHsI{ z7nPgspyXaVaUKQ(?#54OL91AbEiKpid4{1fK_p)sg+7{g_)}E%RB02`Tb?AphCc(D ze??ubA`B=fFjCl0XvL5#AnU|F$V!7C4WS~d%sGB+Irz(00Xt#T@wuPVSx_=n_Opsb_u-Df&7HAs*@ zLKt*`7g%Fl(_CmN7A5tNrxD)u=FD{jg++@49M0xLhp11v{CvNYT!fYm8H9s z5VwwqC6a13Dp5uR-wMaI`ZG5wrRZ*V0Td`X3Xbw_B{Ga**-Ji-Y^;6p&#>RSI6+-~ zEsuINO$V|SECRYB9bHk?CoDmi-^5l;3+MU}3R$Dw`ln^!8v{GRL?wy0gI5kGZ6KDn z@*ttP3U#gRAlqsjKg9NiVK5WVjU7lO=bM4ciD~h#h$&j!yg~w%4V`NX#F(Ty_!WEYCrDd=0F=Ew{NxFgjC%2=HmM)Ac}sk zbb8Nl0q63~9PE)KGqo>*ZkoP&+p^Qa=S3aIQ(-x3kzzt2pNk&HhsWi{w6@NLQJ34P zb4GRV7b&5ou*X9HmYV2oJ>e69m1lS{a~P6ZB+RvmcDEUb@hJD{cMiVll+y63R4mEV zm2IKadX9Np4zFiHHz`8vtLd`xF=z03F*?O`W;PZ}J;9c0okd@XTSs8(RQmcFu*j8G z`Ng@;GK0*pIEmOzPFWut!-LyT)LxTLmA83eXnkWQkzZ4k?;c|UP(2emvl6O+lOGBw z7Ti>5A8mY*I5mH=5_q<}sJDN3Q& zxGkgYQ&k0h^)QOXox(BHHeLrt_($bnDim7PJAncj0*BQ@SRod-q#{iPD)l|5wbo<$ z4@0D;JEvoRQW~c;{ci28&M}=J#Ye@FW3rzAerYcsN5*h*$F z4+_LwmgmkI^HTEZg0JAtmQMB-DMCIDtRo^2m|hFNJT1 zn3V+RVKjY(&^(tn%z0+5Z%w2-?zK387HStgO(1_G!qf(RunD7OnK{nP0=^7#oBKq) zYv12V!v-vk2}v2;_o!OJ=hO=b60&H0yUn}U~fD0_A(kF2Xj0)xqB(6Oc3 zu(ojRO_Dg%#L?08>QxeZd>)X_PX zrCS&Pj)uQx90XzA2OALmL}cO5=~5~)?JS@JMLHo|HrrofI-J~L?mwi=uIU46)~DJT zpdos;m-Joh zmz|h~LeZ%Q$ODbBQcc5=hBM3yJHAHh{}b%f(>gH&8H zxX8GS@Mb3mu9G~+CmvG@z8i(2xDIaE+!d6*hk^J%_~yUsYHqLrCb5jgUr3y#0+SIg zZ#;S<2~e3m*s$TJ)hZnW(O#3gL-a^HDBQH~P%G`*Ng{9SL6n?!a<%Aik$KRewhsT5 zZTFZw?cyN0p=QDv^W_ZqYkIQfq0-=vs24l(`|+IwtGLzFXAyP?BE?o2@^j>J4)hI( zSQ-_td9&X)X5?**V?HYwi&zZt9S1>=ZMLA%fCrs#;7pptu5|*zv;>_l!siw+9U7c^%60i#O3saX7s}Eu4E*@}(t@)MiJGV=Lcj!>NW|Mp>+_Q_WGx3QcyPeDgkf5mtY&}ke^yF#LmgAASf%m zCrPR{<*&15J>R53h`&M@lCb8ufhU#&mKIO8jHaWYlmMg|I!qOvRt-)HmLcw6UY&Mm zad|kp#2+6ZR6KAdM0RU<5>u=p1{0ktqdjnJ`QCu@%G}cEwVYbC+qy1?-0+9V-dq#X zp8HL&g=YGLh~K@JfA5~!twcshTfBl?Hpd2XY5h^LaYlAV-3vimCLfHe^-Cwov}LCC zyPLg7#kZo|m%85Mnh;!Y>tiT3W@cs&iYJhgt)8Z*G)FXnpLbmie(26)ka&;>(huA= z-5?Gb0fgh4hp5A7YE%1x1BDz^x9|(4D0x9o!aVaFrZ}`GOOFm<2=D!ZA+)#+l9a3n zvLs^s)%wTh#L+I9E_RpevUXLJX`6%xu(beNxa{q1k~(C-8_QreBo7GHViMQ#vidls zKk5R2Ntj)ala;s}!p2!lUnMu>LDC@cx1&^ur;k ze^cdOFZ{0aY|m#c5{qv?T54==bQqjW#l=mT7=Iav3Zi*+DN!?{DA)GM7;e%~PbKtA zh{w9#dlEAw;{JZ;3yB?IM!}bJOeli|L84B48xnnCc&aNE^ve`mhQI0BsGh<*Gm{2O zlDfTQXpSIGT_>wUPo>Po1JlC};3Z8p*wsDvJzE$;$3E!(0&^8lQ5tcxN~4wD&KB}{ zhpkD@p+iMjH!n?NZ5?=5o0}Nqa22S zs7<_h7rOe;0uOWnQxrmo(jOwdJsjD3fK5Y|{W})mbS(Qzg!}5lq~ZfViLKIIKP5b) zG&Rbfftq!QH~H`tRK_(_eg^5q=9*l^tt?*zjd(oJGfT7h>xpNmXps(gR-W8|K7C!c z{A!FRos7Rb@y}@K(LuzENc2yF=Ql1e>;`Xf8Edi|LOjt%SQ}rWV%vGd zjlBNw^fn^t;ZlM*kkY17gx7REy`5EJGUB$p+d9BUvU*?r3A;F2&Hwt?YAF~|$Y`kX}xZ-1P>_$%b%pLz>8;PF7dV1?Ik8jPew4dZi%HF-8UuKwi1q1@e&s#nI<&#~?FL>v$cb2*RPsN@8 z0#OBk6D#4v@67)DpzXb2%z8tL?Vpclb}#MksqLc2-&EVhkyL;4+AezhEup)V&i^Cj zA+GFq=!8ncLk6;tAz}=FRMPuC2t5>JU1k{-yj(-oBn_di{SKHrZgCRnDWo+y?pm?7 zO2&l>xxdPhm##;PpXAesIxM7H5F{KYS2vxJbp+#W8rbWSI+vst^F{gd-a$`|0sAga z7#6z&k!hqhZ-B;cnh!XU6Gkfuk85A0b&W1xLxvL)vXP2pNBQN523%G#Hq-&fUkk#Z zB#;E}D7+SN$0Z!`4``pHo*kDUUN85w@C%t=j^6>jZj4hh@v8^T6=M~-$Cxza4*`6g z(8?ipE)d0*`GVA!(RmzyJA@Jd_(Nm%VcDgIytSKSr0jAPX3M%=!B1nnv>rS1z&waA2FiZI%#Z2pkoyINU}dkc~3AmgIwPv$r`t+Z7#}Z|*~Me5m*> znBVU$EkNvO8+x3yD@Kw@7lz-`S_eV=`gdYuRw|k^$L;5;F{3@0dE$jAkiHcZ6nLAL zcRZ&*%Oja~=ys#tcKR_$YWj!4n71D4-P;edQGfN^@dJ$w`4yVO5pSKrlE z#h8&*c8kMxQBf=Ux7PjSA%I~@`GR#$Rvn%z!l={ezl62#_Zt@kw!X^RZk)=BxnwfW z8t1o!+7@_Y%rpLfJCt@oXwVD#py)$+d%%LQF<9b`n zLhbvTCdQkq$3)#kCuqP)83ky&B5BtGDFJ9!2V#r%B~+E*nNHL6S%sC<36a(9+iDfl z0^7!82*G-*j4Tdzy8^>^)26@2ORDlNDv#LRJ8)t6R_0?x8gV0#Fxd-Mg2fIi?$T%F={W2h?YSsQPSW8XPF zEMi`LUbhyJ4v1WO`~sgj{uHE{DWV+YdpjWZ< zn3oF7$3P4+bRUPu0nJi)XXD6itn_57`>GxJDQI(fX07Trv;5@aYe_H`n)2U?3eOE2 zzs<)ef0BQ7o#FnuLp;xSWOW}9lD|Gova}mDf`;vLbm77!-=^IcM^LcA;x*ljy6%Vs z?r>&i7*=j$pLs)5PQ^_;o|U?K2N*0|Iy@^f>t$F}x4Q45V!#e6c;v+8x*4*EAZcT( ziB5q)yw>_mjcB*%4=??FJu04gy-oyih(Uf)=>VJfsZGLyQBH#nvv*HZ1|j@^epqHebcz>~ajg{;c5M#bY2I~n8NH$J2}?(J_C?&GDb z8MbN1=0g(BimpK?A4Mvf)Eh6P=}>HWP}uiVmVu05U^lr>L?nQpv}DsgV;)DU?1iH_ zqkFBQ=y&<)KO$o8-UC@&H&D$>x4(iwYM1t|W?{j>O4j%o`iOUV8s12WrwfY#k!g6uuY7K>z zoD%#Rag^PNtZP#>bs6Br6k&dgJE-+zP?8HkYo(;4jL6GDy=xhII`BV67fN9u`zkdx zCLu$4jnBRX|IlQSlYktlDW5Me*!tESwn8K=eTCxqp{Tnr%=?S2*}GCi-fzOYQqGyR z#=>0MI;pD3gw>TLTs~5-TPywce0!AvxSZGRjR4O1;?4;SNiHW8^b$pk#18y9qPp`M zB#WDtr;o|`?L8a`nu`vAex431!(J!ia>`3~TJgkh061y$!{PqyK~$;9^>}&HH|W4) z5E0uT%b3Z8I2YB~k{Zc_?~--?ywZ)GQfG6aphrr5`*$$$r1eE3+!zvdXlliBsu>%? zXsJRTlho+fjswe=GmunDC)0NI( z%;sVgQG>`!us4D3muz-h6Lan>bA-{bT%7S}?Nw2e`sORJ2GEi;m1tLim@RA&?#Nl7 zH8rQua7@21YNym8%Zg`saZ8p2~)c$qfEuXj1%niAMSaZ7O*cv5+m0^#MKxQBN>7EcI zxEqCdG2Ht2e>#Ex;nft65+s&>()r&#ta<+MMVfVhK<(vD*Jt|o1r5Jmdi2j8@K-?D z-LSJ#>b0L{_3MADxhbitNjJu#|I&-8ju50*6Ls~$l^rF*xjXU=c_CF!@1 zR07X^aAP=EWuD>FP0_!=7|CD^5s6Zk|2;;?&KOTM&@@!4JffnaHw-!${`4ayM!H9j z9#Jh#9%TcUOkDtb$Qq!($B&2E{s01xf+P7D={xtE-1!69eM6~j{BlS+ChON2XH6`G zpC~bcJEit@+&_DS%KP;2(Y0wL|6hOgB58bmPPY{PVV!=%%`Sk&ANVd(L|0GslK-M^DH*+T1Ummtr5Niw>s+Y z_hJ0PwC8-QS-mc)8$Jy~+gASd;>C+Kfx7~}V%6V7FHv=#0@S&DmR^PD1Whlv1dtRQ z67pJ6Z$%Z|aN#f3aMZDTn@3Olfi}ZVeqtTRlTcS*#WTdcc>n%X25oN<>xVWu+yfe( z=Q~%2O?}arpjlT@+H)7P+!i5h@G?7Qx#_7YFKH?$f$z%)+SI>5B2>Le z$^7X@u`56h?f^oY2+&{R!R<`dfTXi$*fu7I7t$)-)o|rct4GmTK;&1K!n7cnO-h(G zinVLz`bQ|JIssH)dT?^;CMfZDdTL*ffS1LrG+V3uq1^TsP#@;mUyZ|9U z9nG2w`t|$OpZ>kBdTzV3uFDz?G*q|2o+l1CKUM;AP$#>eZ<9hdkrRjyr>!w}$ICU&rGV#C(-}?&ezT@`AS!93pRD z&A34-=f1z$-1t(;j*Cn$$z-@)zJPcon$*yk*{7LRKGV6O<}qJtKDMFCyvMQFi!d7o zyy>P6WQgj?F7q(6V9HLBxZg6_a2Bv1#g4I0lV-&LZ9rp!qrR{A6z%bAx8MP!~-^>}cTkK?sm zW96|@)izas+E5SiAxllOFMavu$(j-Lja&gm>W~ItC$^qL^>!XbOO?Q2k9URD$;wm zP^5$&Is{PZ5CI82pmYMECqgLS!&>`Y@4L>@z4!TZuIpUa_s{a=DPzt#<{0<5?=g2n z_Vf}yb~{xCe|jhpf_Zk0M_0Z;Gt-;_hl>xfLiS7Sgq-3^vZQ=bx~$773HhoS=8X;4 z8p_-<7GfBs_)Mi*?1?{=kCr$S!^z0VcJQuJR$pH04VQ=TqZzdwQABM;rX$$aa>6<6 zhNN0_#^}N;4(SUp8HU`Z`5!-i+?Jk(L+t7^w%z%Dv1UVEi3YP|d6RQPv@bD^^K;A1 zF#Aq>*D2AQ%p&A^`jT@5iLZRI9<`-ob8QWDL9l|bFB8M5y0?JUdNY{3fqsYS+BO;uQ1WDUVbbAwWL2chk|_W zjgLBgVYW?ni(SFTL53+-jKHm)UiK>grpr(MpBF!Ses>0yve-uzI4|@Raw!)MZe&OJ z|M;o0I$jx-CF|YkFQbn!@fad%rG3w5B&p?L6`SxWGFG{7$r*}!jd~jXJl%Y&4iZuq zV?Xr%RrAhTAJ%b_aBlta<10Z2RY_c?_W|=Pww;9UY!|a3-JwP`$?y}&TVtmB4_?pe zs>ftL@fczuWwxoH_OJ4<_2<=fXm_m@Uweg%!Feg zLo8kjbBBXY%q4|vo?YdAL$36}j?uAJn)t(8x3bQCO-c!k5qbAB@0HF1y1Y&W2tgKl z({*Tt%Q&oE8x$LT1C)TlV0}T(LA;qQ2}|{;oAvn;gh9cS0JSp<;7pRI8$8v%Ea$}2 z!io(E0-9>G7rwT``{@^w?pRJWs3|pU)EZ}(z1yukOhoh}XeE61>O~+h^tU8ce%&O? zF3s-op?T}EvKbrMAEj;0>FG@Xb$Oz(bIcf?Y_DUh`htTobz=&i_|a*?YHlvrWplNN zgFDYYM*PM)r7RqXGl_ISCi&{ky1c2^ zrYTH(@A>2k(Sb5Wo3&pqi0QT0B7H62!-fpJ(^D*xz-oJGb*e6P+6Zg&DyEgkQ4Zfheu~#qVdUX| zcM8VyrNIrB0>x*^St2je*})5VLC9ScdTfN;0JbsZEALX(fx0?eZ*c()TdijAgS{X( zIz0w{pVlU#O@6IAw}7Jw%kZ?%-OihN`a5sxRfyEHkiI!11? zcf&-CK}X#mC>u7kxUJD+&Q84CrWNu8e$5>pJT`-H-Pyh~m?7{VI~Vsmcta5{G^-M@bX7Mfell z;2|`-00cf7U9U)q%Fi}3-1XNfKCw1+72u7Rsn${nDfX>_n7rx7w{=m)X}T6`d>{;V zNX}zRH;X}1&^DM1k>bT`+y@*ukJ)JYN)*NV@KR;*eN*EZ$>;|qTE=xQe90xvD_9oe z{cVSIarfdW+|D9`+jD8K0&aUDbl=Ed!*`>LDMYmIvQ`|>y4cB4@%6P7)aHKu`}-2G zLbI-N>grl@bJOz&HAM!<(^1v=uyDMQUUzx3i4OTS9_EQ#rx*746_wP!yhbP=pDzdO zO7D7T+`4Xgu+ul-@tMapXnDq0d7ho36u*5NgxoSn9YtDKIBTS4G1?V-r1C<{TavUv zrSNe7*zo@2Mq{(XA79jvt$lK*d({shjXW$C@4#v0OSp6ps+MT)+o}p)*imgYM>~@S zrSz}B;Xh*A?li)l7j3BLaNro_EP>o}52NLcfCKDCxH`8`lAFNj{OxzBM zdGtys;3waS$m7}!>n#4yuc!6JH78}Wu7Mgaga(vHC9=|Vtp8xwNqm~B5h?_{a3X7}&9|xZt_}>(>d4C%?6;98&4?Lh92(S_- zIN(P+AqB(UFnWodI_abC@ZtFxv5~#cluV+kSj-H^ht4#a&{NYKBYr9%OD29#3qrSc z7%@!c*(><1Z!1lkg>=>!g59Qjbgy!ZX-}RT-_F`y9_*{J7h0SPQxJ6eY+hZ6!3hRW zTcrzlYFCXR$>+XYNHwBvt1VFT3~9apUO1N3p@xpXD+lAnqNJiGn%95wP~GNL=w5UZ z(MkzLd8+1}rVf(1Jp@i@;4|bCDnO(VgrgFhFpZx!7NVKt48i4x-zLx1BLX&!`q;WY ze+KL{mY)ASw-O5~GlZ7e!JIyI?r$X5(l)yooLXm`Gl%vcFQJ`x<~~u5pEI6ueY*E? z8#n}&^QMG@T}JSLm+RDEcB5KR0$aZ3j1l+?6uS)sOL>sldx9&+!C>O8*RkLX8CSVv zmzgHzqG7gvna*A&8#1(GIqz+wpi=y@%giC{BJJ=jr?L;dx++1%`H2S4#e^p|Ar=CN zxjp;pv%OQ$Y6axDIfI!&#T!-^s+LVROrvsPByPK7`8FH0+WEa|U}jXIzMNmB2OB=8 zxrmpb#c6`P+G@|i4-G9l#SjF7fvC=4S+aFOu`EnJ z?raM#72d8CNZ{UnquVMIIUS^sbgiG-g>deHgdd9;HtS{lKofs&nWx|F+tRnb$b|Yb z#U_RspOlay9c`09;_RZ}jLhP(XD`SN`s6sqfaAtkT)kFqHR@N0Qas~N@3qJtQB+%2 ziCKRv2xLYRhofTJ-Ouwy9GbaEF413uYL2EL$<2+e%fRohbAxrOtfP`3r<=aq=9kWIKwjU|(v=|B=EWAog7L>m-!iLxx0k`_2X}Q`c2HF1w@)T1Tu4S#~E273vBnH^UtC z>o%i-y`Z!m2ZSO9IKSyPtU&KK?Jiv+IY`m_qo4&QZlai0dR{=5yKq9XS^ey^mYqto zj1U;N;pGCA57&2E$?E&kd))xY?jNb1{LxlE|4XL|+1NL>(135yvC1b+{BJDFQLE|Ova(5_U z`wft-e5Y>Yx;?OwaNRS8*>PWHUuTqaPtqe$Q~1R!KSNpx0jEQ6=YFWb90UX{BVE~M zm$!iPg)1O_8#Fj!(4~I672;onsAqRmHU!Sl#?F0Kk89MiL^y zcfd`yIHayx&*Z3+QiU4(7vy!Ti2;FrXa?VZY{zGV^Iv~$QvzOH_Su3UDNzG(yErYX zPYP{x1X}0JTd zpCQNo*8D0~R(a1OBY}}Rtr56S)C_=0*w@jCRHQDzr!l04A>rR5oe;c~Gk11=YOo|o z3D$QZR(?IAfJFjX-6nNUTqbkx$T41D^*@#9$z`3kKd?;+#YPM1-(yY#CTY06=#2}6 zvRA%t>1XntgX*;%dj7cojOQn7tD1rq-V1Q{%IKs%laeW$GF@>>_ii$g_-Vq#i&8-~YYm|F!3Dm;E3A@qg#i|IgM@_Zvd$94HHb5o3)rg?%cLnl@~5 zXV&^DY5Kn1+}#)pczZM>_(YjM*EILSuZvV?j&sft*mNOL9x_1eL=)y8E!BN;E;8$o z&rKuvz;5Uo83lz#s=&dAk$fg-%82dYB>(ZZtFg*GSH2t#C3_FZ1WaL5eA9l6t$R`9+I(sYVFt!2$HyA=&qe?6P-#==veznSOm8;Iz zXtjZ3ai&hvik6tre7T5T$RgtQ=hHeOuZ;}7Jmv5AWiwrYE$=29&HdjvUMkW!!1IQ_ zT|G}gbi_*KiVX>Z*?3C$t<_9js!~$y>9rQR&Bc`&a-M3gZvY7Toe1JA+EV!XZ3_3qlukd&1bJ5Ig#_1~a6dO1&zSkU8Y zOR$Drxda$mw5QUN<2D4$lLUrS)Eqr$j!B2^lvaqdp$67 z97mq`KX_0d*z6UtFqk~DI__F`ddC#CZW{tMZ+BFm^|Qj|;@8XfF+(a`vb*(Derx0T zb%Cezr|X+A2Q$c88rLv!6gVwlf+vLGWa@cWyvOoJoyz=qkp-l&D#Sf|;eLlVU2XU9 zqT>QW1`p*L)y{vd7OfB2ap+lEhLrKs@R_LZ8+z`Qo)~c-EazHcJ*RnTHvHA$C{slo zwONf-{u@R)*3px_(1{UQx5-Fx0fEQ0PBVPDnYQ1@W_^2#bZkq}3y56(-eg|OrT5RI zvE9d4u3Yi>vOhDRG&5P=-SLHcaRedO`wo7Rl9qO3qAEDu+XX;pPb)oR1NZlRCK?>e zC2$p4G680T*>bLjmy(--I#^M{mxW3trZ}3M097D!-FxaH^XxnGzhd3LO@cRVfJSq% zs4%CBN7QND{G>&gi4TZLLLmSyb==$c)V~P?E&2-CgJQVV2>IqgHrd zxhM?x`s95Dh5Y3yhH}!x8RE7v>IN{l)CgUR(1#S=HkGVZANlk>3iPujCwnoyFbj79 z>kTTka7DC!S}4p7(bzu0G?Zl7jj#V)1j)2}%VvoAX#}4vicPq*KAjtvrU+Gv&SsBF z4N546VVtEs?3g$Mo$nP|7J)RAW6u3*qtT|ScmbC?-b?iUHsd?1LE3*c97Grl1ZG$% z0S4x{Z6cF%a}^bLU&Y4y2C&l3p|lI~iuR_{*P}&0>YEygl-P#Al{Q&+7MEPtLoi$Z zSBv!KtqXTEVHhr>7JEkplKr?yre?%y+R94bjt7h#yk7~`5V5F^=n+xhFM+;DpY!>W zV6Xo?`moh;?j!Ch4NdBL%L-nIoig!?79rUOQ z!368HAV)}i{ACZ6h6pTT*z)0tzD8O06;Qy@OAqE>zy!bvG`vSZf8lbc>H48!qB0{` zanhZ~N0fkf~Kz&_XY&G=&EJFmG>gzob(`mM+Uwn;>4H+n8{@WRpKUJ^5%6pku< z)em;xOk7yp`W~|GI_nm6*-+fJ`54i-P<1}27F=xQo-X2@cZ>+hw2oppH|@ByoEWQ~ zTyef3MuR&9MmUbFnS9zFIbSMQ>wrr+I-Cl5R|6Ip`-mN;p7)`k-w(}vJ$q-Me|VI* ztcTyYf2V!-I*+d;!h6DDEbb8{^7S&(Mq*VkU#+`rCcwHQiERRWZ1&_*19-Rz{IN&M70G>aj{_F;ZlDl-vQD=i}5v+}1d~H{rRw$X%VZ zOH%L}i7bPcRlK1+$r%wLPq(hym;Gjcv@oH$xhkZS@1aO0aJo6KC7UXe>+I$~D{|y3 z#^is$Vag>%s&|GfRh_y~R&LiO`ZBazlNXdz=k|gu4$(bgW9S%k$#Z$odcPdPXaL{l zzA5OJqSGU>6jy6V5_JxIqOvDcL z&KSG$Ss(kg|A@6-f1ZxTc^NMIIMYJHiULm87yio(OJ0?*7&0&OdKGMXU zVyx{kF3eOiBtZvOfq799@MALL{7`OL2J6I!_ob=R#BF8Nea5veLhRw$hfF8IT7Fw6 zw}rHfferS}lm-4f2D=YyNjIrSkLx>h1y%+}?XAjn1i$7>mUcxN)O~`EyoFBK;$9xN z;QMCTSR;>U_Rw_MjV;SHS=A96o;Gi4bLaU$$TfH9E#EP1;EXs=Z-!XD0jQeS6fJ?9 z!?WhtU+j2uTyZ8p9i?KZ(rnLmPXOy#ceN;sl|O$ryG=`kNhlb&b4v|f;nnwvFLYPE zNQAQa!59wkAHS7OO|A}lli5H&!eEMO`aLV|BO4(;(=>J7_`1c@;NwpxIbae;(v5Mi z@`+-R%n95TBu-fQoBZRc9vvHr=!RE|np=a?i#X$GM;DBeAa{iesEN zTh9%@U8U13j}}v-ne|gLM2i6PdQ)d}tdcEbZ6>uuOr)B&4CGTyefl zl8Im6^@kTf21{>NXA!lB!9m`Zasa(1r_9pPl1z=MRbX$l-~uLtgP}fAu$s8f)s?l=7J>S7q7u_!k#I zr)BNJaFIfku*_{)%20GoQb-JAUFRa28VW)kFU#6bcSwlmN@Ic=piVan z@%Rm#>2TFXre=ANcu>-WPQ%Cj40NDw@b{a3CB{=$(ZD2wC75vc$~eP{^;0f6XHHUb zfUvqT^Z!_=z@{xt5#p@6eP$1`i%!BKq3k9sWaIV;{R3|xg}`^ zIp5Z}P|Me{FocZv`~bW+mNk{_SvfCNH>(a*AGTUY*VP;$u&{q1ThLec^25b=7}$= zn>NvAPdkWx^RfbteCNrJ-!0$=_RU@6FA~23et^#P@r!+_eSj!n5!1A(dG%#PTQr?m zO0izaYqQ9+c-sUZT5XMzd&r)_?T-j5hV4Z@f?qg{wCRR8;jyxZZhn3tZBqKATIsS{ zHUow~lAGtvKKT=jwFw9cYNrh5-agnprIAFNeQ8{%f!g0~v00?=iI?g1?}4f6Lg=PX zo&DD1@f*udCk~m-Gb0ULPk-WN7TfWgl`*egy^60xc?ZLr$eg0C@hy1eHqumLRGb`L zeH}UYTefP9qimo}y-ZTL@!5d<9nWFtZb*O-C7pyyO8HU$s>vAW>3l)?;*6}qM%T60 z+P6HWcPE@fylHEa6+##);l4nsWCf&5nq59?*c?4?N5@9nYA|Rjga6!|Sir@k^462V zVCOM6ecY=u(@pP&YYf@z0=l4peaB9fUzzfce_K6cp2qz2ik7b+ClUmiRr`Fnc;g5H zTCw|4k0_f*!`9M!k*ueBwX!%TV$P7wY!?aNqwPW-$7%RJZN#yRx&$|^r#T6;e^UN-z_pByI(a}+ z$#itAr>wJ28=C_7j;36z0b9DVyPg!GA%_S0_G3kbBknS&HD=#5uC=oe^KK0B1vASQ zIoEcNn{s}&BbEHpxIA5f_UiL^ZZNdvJ>pWiSiF&qdhJpl=;>TsW!2%xKGxCksf_;v zNW=HTTVQLikon!d(_@UV8CPidzRoN6-{#j(&w{t2Yh5gHFNg?lg1SC;_Lhib8V8(8 z)=oDhKAU{`GVd)CDO?fIqCi#(aRAZw+H)^s0oqp?1k0ByF)1Dd^j-)Dxo>Zcp(M7IeIU z8{XI;;FN7J8lcaOGneZW0kyh)f8V_4VEHO4$}@n0qTW{XrbUY{urJiCZpEw&qjGAD zHK=5Q_dtbg=|ML^Aq@v~t3v_Z)C%rd^G*}Dva#~)AgtAr_^+a)KQbleG$0iU_w%_y zN4R>MsvBhB>VA}GDCqjmGZ~839uOrTvyLhUVmh7-DHg?|6zAEb+2C1gxusPOruf#D z1S}&EZDtCWvKj3kemHP|H!*X)>#XSM#4UpYb(JE%)&~m8|dOm*rj_%=Y!q z1&L?NdaYdlMPT^Hr?=UjRYg85+$XhS43j5mYovGGIA0!h-lta7ZyN7mJRzw0(ddOy z{zDy!0BrN|zR@VRT4e1Yb!(Z>J3KMEwY~QG&C4v@sRMCoUwjHvCohk!R=)P92E@f(DUH*ADL%8dFgzrIKJ%U2e z^!XosAcOKEOGxATRYRCfwusNne8XoA#r(BCgz>#rM|n+9mY-}_{ndYl)qhT$k~2E* zX!>&NWzt&&rjqqlhBiO7y@rST8UY=Gp(UYUN6q;d%=u&!5Pclo+uz;h&yfJ?Lup+E z0I6J0o?Ez3J#)Fn#G^?xI$v{ui{K^=ft!5VD$(zT5x4{4ZJ-9pY}W{sGHk<&gqHdy zy)zf~R;xX>f3V>*4|bL+v3mpYtO4@f0BgBJo#VGIm6Vx^8Njv9tSl@o9MzOwQ>o5G=pVTm4PB?vKcZ5U6L;lUg6jgTlCp05;{(!EP_FwW{j; zdDsFFi4o~W{mG*KMZEnldRQ<(D#r@lP5l+m=C6vvpATaL9(Kq6@V8~0zb-%G0o^DDw67D#n&4ls48J$0)J<=oqg!>;1_ve*c z)j(Y-H>^SWe|k7G)g554dj&w2d_@CsoG1x)|r zm2C*%%HZ=$JO6`?m_vbM$AF2)rXfd~_n|EXIyF-1+xRQi$R9&RdOfU*u|dutqC=cY zzD?`w8P680{uj>x9Qiq3%@ESOaQP=so=EPgrvCOv?d((l5a*=uL>h>;EdkRog?mU4 zJyU5D_&Iu7dz>yWo@Vo^@*fO||1#&v)e7R)LwL-0{(BXt{SAVIt3Y0ug%XlKCH)E9 zVtw>fQ(3v<6i9u@vip9gQn|_?saCjPwubl0B&j;Q0S4JQIXm80QKEz<{s%A(|%YaWAAix=*U#c?ck9S?3Oa zZztwB*82+u&1BlkDHjstl+x^|O66z?9Y2tZ->`Wlz&vLR*lyO}Lxkwr{WkD%i5|SN zvXcEMI@MyzqenqekrB|qG_Zz0NxMk+y9ENwqU9$KL^suvHZMha@rG#bERvqpw@a?1 zahc1_12c9QkUNTJ&#hi32q7QG0(izOfR&~n8~bo(h?#IrFCfesM1QwbfY30oQfXn~ zg}C1aQtiskoA%{|1%%=Twr|{7=30PthV#jKCI6Lt{1?ilds4O+FaGAWw+h?R?c#@K zZ>u6A2bFbolk|w4rY?-<9(y^XNIxqQDslOXo1$2O!UB8KwgfY`p0GQKJ_4&3LQHTPFe!;VI z>rb!omz(?RuOYz0|0Z1Wg`cqt2m$p1y@9L00y8tAJz1#SO!ggP%9mNOWZho{134Ps zU@gBW0D6?0C*b93kRxw_Q*>-qKXYR)sAGg`&+i^nW(djFO#<=21-aX}fNaWz@ZUstdHO{ZXHI3wQ> zWb<9#ssrdD6(`nOyJqGO*a*!x_r-rxaQ^R@I~<@(Z-iQY?EnB>0>Dn5@7ALtJu42G z=dyH0hSC5gF?;LhPEJrkW0&>pFUR}0jb)V`Fqg}o*Bg2HGiTMSVM|H`sFK9*4gxOM zy@2M|>wD{r+u=&zKu*}s2Mpc1(C432TW5O93&Q-GKr3U$jWeB(Y|Eh`NvT1DK}SbN zGu6_y-`wjjDQNrIG-&qx)J?Tz1l-H9Q8@eQKjloq`x_hW8&lpXEdf{+fbf_PhB~0k z*hhB*fna-YsLNx!L(y-mog~jIJ)sCYK=7N9HajCao%r%Ws1MeOj9Bk&P_*cGBj`ldjByXU@Z{=b%lW;j6r>*lhkKyV`GKEJ{ z+xm1MO8UDGT2C<~>9U?x3j>*5@bF{YS{QjK?x;ckI*)&EmF@ zY>lKGbRsIC^}(BOt=yT$3;!wJ%6=YZi$ zYJ;DiL{jt2dTyEm(A(_FIFKj>KhA;vtO;rb0JK;}8Fu*5kzAqYuw#|Zh0wYnd^T|G zkfKe0*1|T`@#T(2^z_X5(GaeSTQ(kQ439r!@!s7fP8um3>`obg80I#hfHPp*JOZg zth)U}@m!BQFw{M+Nl*DaEH!cRa|nF zW2N&oP1;Sp%9hz<8)bTxC7)cer+~GANBrNCFey9b2bahOQq+DRm|$>Z-40Cqz5H`} ziK`qlsi&49GCZ~{WE8&2S;u#I0o7bAy}(0Jm+{*=1<|PhN7#zVG!P&*nO2#!8Z>F1 z94voa=uOtav@Y}6TctSFGSmU88>^#w747aUoc5yX&QMh>8w-mWmn{B`us!n8{rd@A zc`!oFSUeW(3tC_?QqHojwlSdTVioI$2}V*NMB@CeZF#!iWc+VX;(B z3T%v-4UxCWz=a&omcO6p@$|fD|Mg>8QWLZ^=&0IuAW`u`sgysN5HkPdTz&glsu?$Ypk#jAchs~n}T7lQEE zzQ-eoL@m9oPa~Jp)H=U>QF;1wvUMfyF`>EAJ%~Oi0N|9_Jd{BLJzu>!DE2HZpX58^ z7vz-a%M&Iy69DPf+K1*wR_!LG<18ecqRfW)ysOd;9s)Oi+NX|Pet#R&wz-oatNmhX zLEG<2+ND1=>K3jEb zLYL>a*+G|5KiU3RoS{JR3#||AE;xe%_r~4rhiam!rG3_>QAKFVhcU_gvJlr7{$E_V z*t-TQ&lE0%#O3hz>y17BnM}TIn zn~tH$aCr^Z(LbEy|0d=h_j+%#8hMzU>25rRjuho*j9w@HY%R|8CmUVzI&G0!jJ=xyxt2q@L+}^)iz37M6#>893XlZG^^`II~z*|HFWr#N}@zc?T53BO{0 zG+-HA2h&Is@9b~dP34#Ni_pnfu95C4!xeQH(?8{oio1R~pVkS=lZR@T`FV47FgfnW>thJum^4HtJiOQVohNWc;D(y~CJM$e zA+WL^Lw_)J=rnQ=Ezo|f@g+)a6X&m-cM!nYfQSRcA$@~#KE{v;av{X$3;f`O<=hY? zv_14B9JoQij#ObE0=?PiYQy&I$Y!u46Ylvi-1-0F-0(EHas$D&www4NNQ_ zYTx~})tLj$v?zB&MqM?jxo5H*rnX#HT0HZR{Z6T2Q=<%^fpo&xJ1BlQITx@`tCz1b z5`mOk8!H*AXUc^PZ6=D9EF=b8=GRRWo=-XOjta_TyE^of| z=WZ6wv7IkhzS2IjC*HD*mE(%d{92(~bOn2N0+|lz@d``ERB5hmprKiQkp$22E6*e8)3E zgH&z%vu+*iEK{4>{6x$Il)e?0<}pd(Gh;6qXx0$GSK0Jkw+D_SI)w8_XNtzrikQJ7 z%Dx{kUrj;e2n~=g!@NZh{pToUm|^PO^OFGeM8flWcR_R}l%LYXk?<4ouDW;&_CmV2 zUnv>4r?SK56p+gug>_~*{PzmE4>JK_@#`1!|#zyi{XzIX25dn`UIuBQ>{A2e&3!) zoeCvmf&wVx$P&8@0@$QtHow06G~9kv7DFpFeaL|1SD+vFedN+G>huItV1L7~(Tj7} zI=aK7JMi&a*W57egGHJF&qos{S<)8wEhvISt|6%j_dJ_-;e8aoo5)YP^E5Rb2By~o z=Gs_xrpn|j&qZ4G@?Y4>wnVspYw>y3O$}|4nrTHnd7?jSM z$kT!6$y&y(<(Ycta{REI+()f}2UQnuN}IR{BjV2&V={t~Y-#*0<6NP>>HG=eKrn;Y z;NTwXZeuxKFS(KD#e~uYHBEI%=KE=)J=gtXYt47xMKZ;S&8|5Rf1@R=a~c8{XY!Bf zipWI*x;seD4f7QFkoH4-hmWR_Y@tcZzR<_hfbcvmc#d}MI&al#AFrUtPrIVMAG=7Q z_{keyF!JnKppV|?{t##GZ?k6#RlTY_r@N3&WsK10nJZs07rmMR#qU&%%C>JATFT>? zVk~pJP8g#6G6grVTNE;T;4$l5N6E+kcP#3ZJWqrOD||HCcNMgo#u6t2q_x$Z(w?b? z>dYU3-VOrV``A2kXc(QP6>c>zwD^CaxiuP?s&Q9qC_if1(Tv4tYApe(HX~{mqirwz zM%~1$lsT7uY_7Nk7m6{7akJH)GE~ImzzyStu5UjV*^|O+43$?8pN44U&t;kh7;I{Y ze7A^4lN(!XIl|}~p&;b^b^c6_GqT8Bkx#TgSZ~qT)mP-*D(mpadqO4TkGcDb!2uJE zn7Ub~)ZiczL+XO4)IrbU&%45)9J>w?iex!MSSNWQECY=5^m1w?4c+$#(h|XTJQok` zpyz-O=-mwN1VgpeP#Xs+c60AF z!mFdvV(IdMp)v+HWq$+(-2DmkWvFtV@-4^+cz%4H?wg~-3qZXTR5%heb@HgM|4ZAw zsA58}~fI836&{?6TUkndPCtCNR z{1w0C&5uiyg?f{1eo;#?45|k^Xo=whpkyk}xJQK#gV0fAhl=E5DJG!6mA7QJcw7|| zs#Zg(=-5c3$h=i}PP`RJ(7JdmQD%~9_{P(doq{Tf)hOPa+QmL_FaIe%cTezM1MeGJ z8JqefVTk(I+Wit&E1>xV`*S8sy@$1S*v9=PmkYWfN87fm6Z0*?#BG?)r9&rs;-wF< zGCWfQLdA#%=LtV(;I{(Ecm?dsQXiSrfCIr{dR`dpBt)Gq{j~{{zK&O6vkb97ICptT zjs3#)5WDi9qlk0R`ceMtE2&ybgQn&|DHD@`3J}U)Z15UH|3v)%{ zQu0=VM^|!qSB+{@h6v3mKr|U4Z^pRvp+4SDwYY>#cM4KGrEox~_&R~K<MX@A7c_{Ij2trW4}ad&ET ztpQ&}dra#Lq>|SBFbtRQ9S{H^tzjj)Wh~*5Sl`J$!%tUCpVay97jw3j>vaPf=POe* z2uKp8`pZ>=nG%aC%=Xb@YUbk0iAY17pUZS!n9gF8^BZ9BjM#!^TW|)5dg$uTva3(X zSYUixso3V%!E{wi=vzIpu_a&&jd>T3{we$h0`q_!S#VK%H%uC_->Kz=V%~neu;nc*zH!C62W&d4S}%8_#f#U0*1^JoBP7N7|USgZ(zUGFp@u z+G}hau)Kk)nq5!No?1sZJ2tAjUfw;rD2&JgKOM}hdsG{O&(`BT0HltYck9FS?ghVi zAz{<;oU>p}X0=)^6IRpkX=mgx!*YN9nO~GuPeN>#tR+zL81VRHv$}FKQRC-IMb>Bd z*dCyZU+j=-9U7F4Ny2>6C#V2dPGP~mS+=fc3&y;Q$`Bsn8K6TB}mX4?bH-@BQh4O+K*JLW|L;t-=j9Sxca zxS9POp$@zqXGEHX+|rL!1g(GQ`Tlop-v3H1uRDYWIuf+-X~vlRblo)2S-G>#mkF}X z0}{|1(38=8bB0p^lxSBYQB}mn#&0EHSN5?pM|ksl3`3()YMPL51gyD26e=p?4N&3P z-a1o92-v)O0_-zw`nZRqujNDZK!y6C((8@4T}C>grCg6qI~%?Ge1>ZbE%B(1#&zdN ztZ5b&g!Ki;$i?UPOq;x`QXV0}O*TQRSR0xlHlrD0YyUSG++^NkwVN_7&ztR2E?~Yj zgeSpI&FW&~n#j$M@3-k_$yqSun%|##$Vc7A+2U$U*!bX8rq%cNY{TUc*E+pABbHK@ z*?T(gr2E&^)+T`uPzt{Lz$ru11*gB_){uA|&exlW4 zRbbBoq*pl#zydSKH=6R}{mM)-n=13KgB)M12m)AD=3OorW@9tp3aIHsR?2L8U)DxF zldW*TL^AlGEz?%K;p^)e=QQ?*nsA{?*eA45>ha5p}Ljg{)L?nOPAoDSOV-1nWB z5s1l^1E@qtj-6ru3G`4ghb`PUckO^M2m;~=_81o`WuQhn=amC$R06t3wqFCG4PM(y zvCZVRJoI=FG487WX>Kd;iFt`%713Uf&aGp(m*yX>8T2xM<^i?E!kdS_6BbU*=43R1>QSYqD=?wyDuW{y{>(urskd2Vh01#k1^iCb^GZ8xjeTT84@1x~!FpnFi zp8uds4|0bcYH}Z6?}yyZ6boV-vC*te*|`W!<*f{2KqMtGhEglaLk^ zdsojBpnD^4)T|~9&v$87rOayp$&n?D{D{9AzAWMCx>kJeLzB-J#x|SP(em0rXDldK zi9F5LDV{7!)^s;rJwuw$o^nnX<$F<64$_2@ma6U_?vyEIv-3vuPuuX1Kd~`1uLi@^ zb490gV>U(gM$VPpI3txt=ssqDxjtG_4)gj+mpx^yW`Wxj6SwDds-~$1)S35&Vhdg$ zUe@_i8Zg`_YTDRrH}t-M_5dC#$P08BAqeab411eJ_TIb4$F$0CCGN6d$oEK1wReti zqx}*@MR1WqNaX%R0Di!Cp!)jaV^HbX*F`T^_`DC$6{`&Ppbn!{9CVh(KtMysF17NKjhvY&fjkbevF*b@Khu8r?D_f4#&7jt{8~;q00N6}( zypeU44e;7rklJiCUCXrYG5vF%qn8bv#%3!B@%kFc_CA&XT<<<%i`5w0u0QL61;inI zQ!U=;F+n@!5d03h?AZVCViT~+9P{@ju(v_A*jeY3#tFIB2;HKcgnh$eHCwpdiRM@G zU{^4gTZ^k{f=Oz@srk3N=$o?#T`sFOt#9XQNZiORza9j&Xps25@0iyvbm4U*JCN(& z`N1}DWmw7=qq;5hAXOk_#7WP*WDlnZD#aDzKhD}=ahfia=En>ZPOYDZfG!{9Cz?Ni z7NP&)o0*}6Wh@mrrvOrrXIJ^7YOOkYNo^ZwvvHfCqDzw3Q}G9Ae(qkHp|KuokiK$-G5!Z*TT^UT zPaE%`h2}%DP?49;s65y;;qM>#PP0ttB(3rS8{Dh+eE=|1<0~y&m&Vt3o|E~GN+q`t zi68?6lZ-=i>GAr7p~dXY`s%EG$~AYJ2{1#HBhZN}{p3Sa!~kuu!$^y}vzmv4;y1d2 z_XZ_t`~DU-_D^KM2)dua5XXZ#pfHo(@-otB*{t5}9yYTj3TE#OttBKTH&9b{d{M%u z2pvcSjn~2}&j+!or6!S%ga8O-0!8rj#2L`NgfP7wvi?&+Go4G8LbNZ5ldXIdYB`&$ z&%Na}p-rJ)bBMin^}1HNw9H#zCuMMW1hlGEvW^n$D@JjY=m&8*YcK=t8;+vL8oY~8 zjr$J9ay=pdu)*EpeSiY`yQLq$<5w=yX3JOXE5LH00QitXQ_OXeYraz>$ya^<=PR8; ztDz${o15tQD~y*}^81fq4l~o_uBOID9YR5uX3;`z8HFx0Qkf3>21C}*>RgUHiz5cD zgMBge9{}EKg>$)8*NIo`x&YG~vC*x`f`3XMQQC36HKum^l_x zqQyRDu3!0jxEPC&J)Wj@1=y0u4#`RZ$?>A`nd9JH~N{{VA z%kh1iLY8C8g+DwI%FxMCD8dy&)HWG;(z4f6Ji4?AmDcVKyv&SRkI&)ubqN@Ks%rUl zcVCTqWPqGND){u%q0~yj6)}}fS($|?=P8||i$lRQd&go@kXq~>hr2#t5d}O zbNPV?AQ!|V+Weh?tw|;pG(INuX`hNz6WE&OvS=Q@XwxGjG6t23C7Pey6T|Efzlwd8 z@|o!B-Hfldg@yacgFXQr?F=4>qH`?yv&H0WXHX$_PxBrua<1%|?M=)lP|>imy!)OY z0~x*&7v}J1D-NUFT2;-NR6U%(Mwz|$?CV8t>+Fe4FixF94~`XKRCcnIVa5Us2P9o7cs004!3){2s9i}v`%D{nN4uFCEcsRK0+#Tg?3XdK%3`tw@?g;IW^p}(0fZ0{P-!9+5m z27EHvsR6V~7gC-jB?3<25O+iFJ(q7IdL{t6G(JF5!Frahr~wT=9J%ya`xAOUlrHLo z=dUIdh7WjD(SrC5MFIZN7xCdcZ>c@6c4@^|FZb_s6zrt@A&Q)9X)7}g$;j`l&Q!&r z6}h)aC~t7F^(EC{8UG&*R&SaDkN$vQo>yuU0vH^KEOGL%i)VbbwAGzIT7xtL6{~Tn zI&(?2RB%w=I;U}-^5xZIGfGD$@E;voLUDvswLz|}x3fBjkEp2n4Sx z$6EPi-7^6^7s!X@UtpK~0P1p$RgpIsaBhGy@IK)k3BtNdfWa4OUvjKv*%81QBUod|fQU<;<-i11I&V2_ozQ3?Rh(g(DZn>UtzNg@6($jiTI z(T{k{E(BUwSj_)7;ONEt%j5O#-Ct0X1esmwfq3bMYQ+L=pBKOX{tq5`iH~;nvwO;H zJLK0%v&{$y*L)oH^YJww+@p+s{7!`?dLn}OgZ2X%Lb)$t*FWfg3jFZ)vaP0Ej?#sE z&k{z&Z4#2?8#j_W_c53@)*Ei^C+h;60S#ry#OP>B64IGQ#>4HDr_RLh6~NMvv||Vk z%mgr{GfolUKjh`x-m4?xd#v0R#QRmEPmFSQR>-;esSdu zSP)HP1cTTm)+l3l<*&`n06P*789Ggh6qjQ$0oK0!c$S6m$Ote}V}yDR_;w#ng46*Y zRrPT!OB*wK5{DT7CB8n5IfylP3%6~uSsIY3h@*e4G%bIVDXo01^0*(;D8m9eM!6u>BPiQ|IMVvLDG@Vs`XcMWCUFR`v0_CXTn*XK!pD8+H9 zE5=A%gKweoPX_5h+tKR$>;k1?5?C}fLn6d@r?f8rpe%`utbhVO^2yx}k{8D?_OWY! zPF4LG|0Lr>cz0~jKVVlyb`reG!}+yimAzCZo!9r8PJ!P!hDBD%685o85!OxIyFKk( zb5oS~7gOB&8GquMOW#xyM5Kk6OZat@DEPj&3?;D{9)=UjL5y71Jf?4o=pOj_;)USx z;c?6j!hFs*gfvR96B8Dnq3w!!1Z107Wu`is|AM&s^NA1msz!XX zlK}Nmtz}m7f8^%>-%I}QT>i>f|JR6qHZu8lW)yZZjHI~_g zUFOjo+OD57EjwBt*8E_Ghp^9nXE9e#q1SGm31b!aKqtOCWr}0jh7onyzr1qm2Iy&w z<0`3AMK^52G~dcJlsREqW8Q6HYnj_dFvt#O*jn5yhr04aUG;oyDQ!o3pK< z#Vje~R8_2;jq{HF;)}P31~bjI58!eh078P6{Y9O$Ym`WS+3z;1nC# z9zpV?DyHgoSq@r5+nT=2-VowNr{N5%`x5xw`#xzeHedLa=TK-Ofq}A_!eJ5U5Cy&a zUZ9a8_bhM~yF)9(Voh>`7R_rUp+ZW_yOgYGhqsaH%o9hO*R6baa|1LEwx+A7Ge{@j zbWo#%l>*C=VGJ916Un7{xP| z{EAc|V=KM#TW0TC<|kp)r`)iHIx1@F)SH3qkZuFS9nXkA7Vlp|1dj_M(-=^Nvjme2 zr>Y7#KF};S7QH{UX37A1<^#{7%zj2#6In|6_L1Z_?Y)2v^lB`JhSOm^D8STX%iCDr>-P#A z{@;$HJ#%GVRBt`SQw77Mk>inicK4rJkm4hjoDGy{Amy8I(5%I81mf+oP*G`o zQB{@-7rnf=5&QDvGI)@OyuSViWA_I{x3qH0jWw~?tLywk^R+igNhl~Z-V1olaBTsR zPoIXoAjii-Lz1kH1a$=DmJeV7@s| z!<)cQ%Q3bpm{1aXK_#Knyr6acuK7T;3bzR0C@LBrX*jV zij%RMF3zx=JRyMVl;QMGunrol01ry8xQZR0`}QL4mZ=tQr$`TnXN$_MUOH(KJCKmp zl!BHa^A2|cV&H*D-5#;n3xP>>`+%gx^zQKXYuM8o?tsH%H`DEQuJ(>H4JqClirWN# znnNW&db&Tb0DqoYMfD~Wn9oGYH;W*$msLZoeJ;S|A8wdx*TgR-CN-YE zc=ekATkmCX?`{fKR*ep%qqrrG`Op$E;lBl5_WERc)_Rt-p%4ll%p@>vWpIF2$jBV` zSdHX=+?p)u<9|m5R8;r%{L6ciWE~+#hp$brnW>d0yqW%+k!ezl^P+I~4)(rW9f8d5 z?-4&WRhcG9e1h}j@qkLVeQmfb$8PYWZAw*GQ;}gs?7{A8L`HZJ@Hduc>MQS_GXPIQ zk|yD;j4s($%r+ofL+POF4}}ivL06D%e^&TWgTG!j%Ika+z*&N|6CH z<0>LKD^qM3KbBech80oI$U{tQKz#zK~K892JAgQ#y%)wr})oOk-WA znkF;K=DSiAn0(7WU*{yoe42(1`uRF2+@Faf4bAnTc6UxS>d^zszTNZkF zK)px$4qDjwF0scCUzJ5gz_H+1;W)d%NEO;l)1DN^t5KQolBOh@vj2xDr-@(K9${0iBvV6qR|UBtH%3uc?Xbuc z2SfeSDN)bna}{g#w}1YM{&@h0ful7Rl`!2v*(x7&iw_aw?c5MI!x$14Hll2XnP!A& zq)Et57;a@Owj3Ntcwe6z$Zsvf5)^yw&TnnaUCKZOG(0KV@eY_XKp{7TH8RGsvx;yZ z409fb;ZLPdz!jfK)rXmKExYeLn3b306E@9+V|j+FUK!K*ORw*f*_<83TEn@jyTC3!w#q=O)eY-C&^WLCtA&+-WidWi+)zE|4 z;(kMV4CF_ij=R>sVi;-JE-lxEaF7LR)i4b<<`)r4|4$95FpxXKhU-i*QEtfMjlc6; zSQEDDLQS?!H!D179x-xmP&ce}xZaz4pl2lLOM!vxH9=2XaneUO8XZQsjVjk~w=l;v zE1b}b(~H1P{Bj-LY^#UMjf+pG2(p7*U1ygXTO4YaD<+GR7;CYupDkJ(t(?9*Cz_jy z;EPw*gPLPcia1ekuJn(Xj$8$eT(he5E6m7K?nZ|(Zu+iz^yq04gQ$=8Yi8+N)nA)) zyf&}94kpmN_lT^WAF)d~c1fsW`}c|b^P6V@#JjgO2>(;?4jP7mrQ?-GtNz)C{`|rq z({}Ywg{FT?>HP6md^xbpWv;~9{(0a1$r1zpkFZIC;D1LrG&usHc(~X`xIbHTo}x0<|%chQ|uFXRsvuDXQY7arNizgV9qROqXBWoYB0R8~GQb``0s6sj_TEe{(eA+^p4Ye^HyOVl(lW z>dKWTTtWHx9>Zl#&rE>&+geJ_lWZp{7ei_Ld1ug&E9WPzct1ir`YkC%^^2hDU(G7< z5eMbzsNW0GlO#D^Uv-f1mDFj{hHU@NLg{t3g;(Zw65}Bz8V!%>uU@^iuXi^-`Y`v! z9A^mmuhv!|J<)Xv<+XO}xgq}xXCjQcc;dczwK2h>tdy;1m#nMl?5e;w#9J$eNx84Y zUp5Yi3b|`IZAiiX`WF+x!a`NM6d-D7oihgngdfq{H~@{KPiKqVUNV^sU$+SW>yANB zaOgyB5^!O^^29FHf#;eO>|l=x%p3{U*9g{JujEF_G@a>gj>Ym{Bka2ZX>s&Xn}NYJ z=61}N{4TZX=s)j}zIjhia;Bre8&E?0>z(}Rx2ZEBzkssKV}Nz~O!_3hE{!2*?b1dC zz6d(Wfa-MgXsx=9Az<(=7jxp2a*^8}ca{Io9f%8vRzIccrdHRS(JFKmAjSxEn@|uD z4+Cngecu~qjQsA8t4Wm<$3v5SNYsBdTWK1=KX2!^Ra0(2LDlWlgdTk{=-Gum21x2L z({IbP#J1(vkI%c^_{HNye+Q3aaIt%yvXvcN$l>{7DY0cP@F!1JGDJZu8B)ZJ=I6r~ zkp|yfY>6pjnZkhIP8#k5*4SkbB&eS^6e9K=Ak^+zt znr%5$-h3Qtb+9*KJ-!p49AP;T8?V@>fcB1?1+3vrEz6_=Th#> za-=G+`%EZ&X#D&ug7J-ffcU+y0jY8M$g3oQp2we|OzU?Q>5xUd>6tbu`MBhC4%lKd z!fIzu*wQ8w>$+Hk%5dkZ4_8g#YuJC3VPl|SD3qU&UP<>5CFQmEVZc6SgXv(SizJrM z8T|}_nH`*LpTX(2VZ^a1m5$Nz)t}xEG+}ods`i;l5s4JqM5sQ#Lgay08 zYl_mAD+f^PHfT}K@peNpPHC+z7>gis{jSttOj6QT7!w2WTG|^f{Yq$m0m{e?@?X1S zGmh>fqta1+CrbO1k*L<1OrZ_|{~yDcA}{;cxwiC<6Yue`Ny~-jIMth#3hD~q6+d4m zdf%s$)V4j&q;Yo~(P+w7(zu&-)ZmsG5=PjTkdzcBM1hLoOyKk~t=z0!?`t?zJjC4z z&WJJCPV7iruVs^vP!*Fx%B-Mj1k_N^)EVe$0ShOF&pgYV-?JS;LMrAf>2ooS8wxuu zdxjYpb7NfG%kzm!U{<5CFFS{8({iL6cIMda#XOMDNWALI9XALqN`jFy-jTngiOs&C z`qo&>si7g(I>T;v%U;E*IoFYjh6a%EB*p)rnBZ|oH}b?7piZdgM|V@--&+@FyDniY zWxN~7AReHse3{P@Y5&2->r}BN2>S-DA(TYq47+|_jmzEiQ`U$K&|ekf%_8%t zE~RZ>?tfH@LBJd~_GUJmT-CmBVXY_dT+qK8XG3%NxSbHFrjSNQrhKjj(|%w6?tpT! zmK5Ar>{`t;-+ZSB*P_W~A!8P{1fbPD!IutxCMRcTUbfb7sX&ByX7RG9CEJ;~a~J z3nL`Pb3gl)`xG%qdfYd?dYG0h8&bD*ps6)pe@{K*B{*CgbB>EiI^b`FP>9#6su`bK zMaFJI{c&+}av>e%y@+&s@4c&k3vCEL$r#F-L7Sm$tPt|4^Wpi|rT`A9b2d;0Lb?a= zlk1smyg#%d3cu}!*!A@L!lK_sjlOxvf3q3SrJN)%*i8l^@rBShLKTAjF%Yys?VUp< z8Pq`71Skj-Xn%CaUr?cm6NX-$$uB%^(}tV6x!?a#K=XE&*;k#MS(JTTOsI0OP^_G> z3~tqsHKM~G;9`9!3GyNE)Q{~`rt3Gjxd+ar(EXNlXRy4%SYX*mi2!cVqS2n3+b&vd zCr@@i6~4-MNO8m(>;q5mMJqD!AJ9RB9Z?#03)iflFVLM5bo$zPy1jdc=*ed%j7*q7 zz@v}$w?;@E$quYlmn?Xsj%R$Uv;7RHEosZ{c_L^{OL;O=2WnfGGL4B`>=sqUz6=y+ zA*{l9&5Px$J%_a;|g@U4_FeH?%3{mF<0-`ynF&3Be$0H2R4@~g!u%l zsrV*T9$l4_Qe;_oR4U;6+-7RvAo&_rP)9BB>IqcbfGj6K_+IWgZD#J@oMC82NTblc zH@z!6V}o)3;ct$sh3o0=uvz)su2Ni2kITeN)Eq7K>tbP^jEIz#0Z~3|*|jtraEoXu zvsl0FW_cq)gJT$KxMv4R&j~nT5AFqrY|8X^!`aHZi-ur>pL*G+kgKb2B=a-l8+RTb zT5~{){)_^PJaH6iH2Ytdtry~U^f@2_-kolm zo9!y=QK$TF{vUMs#HG{o$cq$cw#p<+due+CyG9 z+<2+`LRTOU@MPt!qzO+}>SP=8q&(XL4HS0_9mP7dwC6aM zTXLMJI}CSzq>&<|NIYE^UIHNBU&+&ND+nEx4!Tw8?qXL*Ms)RjDrMD4EMJnar?1#@ zKs-kHI3$0FLy({JWG8cS(>LGT+FlFjj<6;#3m4I;Z8Irz$vP@^K)=x@n0lG(zSWVN zQ|eZ$xL{f=LuZIPTbk^=AIZ-V2xLn}RI21ZneVh%(bufCVMZob#%3aoE7H3{eN z1q1_LZE{HmsI_-vjrLshJus{LoBJxdL!@qudFq*o5h@AgZi6v*A=vperNx91K>%7z z9H)3Ane2XslpCjz2N`>y55UYYZQQJDSE#ODNbt(J1eviO8< zG;M2Ui`&G_GEZD+Znke<4{yemo<-78e-q)K)Zv5JqBV)rGB)(AKfm;=55?XT}HXuiB2iM;#@jAk=Ma z&$i-PXUbP+TUv0eb^JZoVtVJA2Vy8b4770Rd@*E9o1sgeP3gWZAFE4&Q}|a-RWvjAUR^CzCl&7x{FmBpBZAzdzP%t>eCms1Wq1PeinBoTNLj z)xkqdt9GdOzmp+m3_$U<~%>^qm-b}Xcps(UNT zRi=`_?TU2E9{d((%^RBzJGy1aDB0;JbM3lb)iXigiyXphOic^B7ocj@BO^(Ii-LbU z1yjDkSCTbLx7tlP__7^gxf`z11q;5lwEc}F&_8!3lz7etqyQM|{l+Bl+b+xvK=$;r zR&ySXC#kiS^y3RosNOa&nc7>@a((tltBv_sAzNwjJ;ZBbhKAn?`8e5z^F-6`yU}7V zlMsvBbK`MwcjVE$N4Gkpkfyu_S{N4G-GlvHqfw%JS86ynX1o#iB~fx7+OMmR`>;N; zY)(RPp=|IIy{h6t%Sq#V(@62PX|UOV-J&`PO#qG06mk;e2~$5+_N&2QRl^B-;N|Z34n3vw0^zA@ zshiJp#g1@{zG{>QpCzm^%KW^yha>~*3CtutG1s&nz$o08dphAkNSPgRt%PElVY-3U z353cMilmtb7gCX^mInp(6?UT}fxcuJ*OT6~50mFUM_yeNvsP48%)Vu-<7J0Zw1?FB zBJgajMm{3ax9W~%z9&w4s)VE8y*KR|T|d;xMBp#To}X_|xibC)&DUjkz0q;}mX)+-X5}7hjZBL1T2Wg_p|AdGKrh+qm=#y&)xVifV4x>)A>A?wY*z$q z7HogsEL!vNHkOw}L?6xhw87SAsRHgxe%RXbBWm&wSBpb57&?#Mmmb-`8~*H@InJf8UhTJ+xnJv=K~ciA;hoG8(YS8D3j6m!x?tNrXX|lUSdH^85nDtGytkMA8?PmS znS09i!ubVBkJhzQ`X?EU5jiS{PduV*80jbxw+}g;g%O|6eLFbT?XpWguI0+4fr$Gu z*?Sez%w7CjYzhb$(%(~#{@g=ml>C&BYPD|uL?C+Bn!9^Hbxe*Ge;G3xse&CNF) z`dbUi#`#IlY_lKF%z0U+$tBO0pXlK(kW-Mw9$mU-9op!#)|mHrebwFg;q8I)I5h@J z>xI5>kiy?yP6{x?{_by^k#D(f#%WlPnO#Fk-)pbhTf&}eh@kA7(r~tc1Cv?`EwG zVy(`+5^eR~;hl{VmJXhBv7rZY~`W{?+hjC<8ZVDkCMC`^u7}-eL zSiIM?!w@e(@0g=#&^MRNOtYA3e|`;-Qr3rqhY*mXwd!$)yR zpL%ZhOL+u3p3?npkqLlbg~!{PxRcTMEm~1~cOT>_>l)pz^r?ES(Xx>}K=ce_J|3*! z(h|X*@=4_SZm<{8-%h{)JlAvvKs%xmxJL-Ginl57@$t?S1Oy{i?7^R&aRMd$<7-bP zMzt%haB9ogjk}c%OIPd|_~I>gCR-s)oF}XGK>KU(kqy@Dq<3w%a6OMU)z0DPPY3EC zoo<1k><7wxpSwHztj==zWmBM8#uEwuQG;5IYIKM>JL9_R6vw}it+hP*#w*$U&y2aS zZ%>pYsP1tvql_oEL#&93}xJ&-?&VnEZYLKxO^5K0YlX%8@eoL5Emc?xH(iS@hz=PrA^sK6Ald@l z#;sHH={sV}vuBj`V|Wz^Bi*Bev>fxR%)nAHnQD=GDQxC;#nwA_AEINgjl8DP7lJqIr^fs@tHl6HO2B$3qBD-Cmud8zCGCg^Qi~L zxAUN0v-tM=j4sfP2D!j<8zPtSU^I#NUG_4#azB8qtl#7jdC7 z=Lmt~o|u@Sdb$`JQPL#qwMbpdsaFiYlGJ61?kBnnk@~MMT8eskxi>`XU0v}U{Fi=yUDFst)Hk*;~=qLKyYbDGQ{nYTlbXf0#C+=V*#GG-cKk&Mglax8EHKU2_%EL z+tAw-;Ui0`EDqUlVUMVuE$PK9&EEWFw@%eP7Kz4hv_&^K3Z5lJ*ReUymuMXq^n)W@ zvuqQ?I6F9~!fC7PjO{(J@;59Y~TK_o1dHC)ko<4n=!G~{_BtiJA={M#BEc7lepB6jB z0Smpy@hqOqKh)ZnzVh=BroDuc1%PhCbv;$pi`Q;P{d}tf4Ej`fm<{2(ceU@|zrU7r z?yC~lbCdgD?_P2V1wM`|F+zlBRvL#KP}b%n3vz!*wAQ`&+~7PM_+7ISzB0G`K(H=#8hb(1codm% zXL2DfmG25r=!%}B@Vs@g|5ri-#_TTK%5xFvn_I_HF=!NX+(eg}t7oZ%Z{61WrAaGH#jRft2jmCMdKt06 z-D%L=rfHI3B__-Oqn;|dC2(IR4WeHFV`XKvn$jc6Idr@i8`TcYApgY`n-cI9SRb(a zQ}Z1=OL1PhbO}y6G<;zwfkl-r2m+c$$)~bQxotTp9NZk8}L=C51gZ;0|v-_<}eL4o&*QdxZs;Po)+S{MDe`@`{u79MYN!U zbZ0%>0aEDrHr+qar2Fg6CD3(=KNV=C$sQszf@-#XgYho8lX9+l#ZIW-SmN9-0i ztmd#kg>AW|K2LL5|`x>+PM{0`}ZxfpM#z3REx)k}(qlO>{ z0N?07_l)<2j1U-;HGx=?97`FIACR_$VqfiCcvWx@k`^HO`sc8;phEC!y6v78hs$8k zz8xj5_kcwU#9jgkC^uL9slulVoIiI8E&;%8{+|%5Q9|+vco@UaeniRwN5#ph%=B@x zv)g&22T!xeFd;CVi~1*1=lT)Yxw?rcnjSznz?Zus^jM==!84UTN#>`6IFFaA)jUJr zQcD$#y~2}f-KA#TtaF9WkhAPb1G{V(S^P(x5~XM7&r>iZ(sHQ9K!uMvIn>kQ0XVv& zXF9lanwMZUHq#$2FCWFgF>P+Hx$;$W%O)axKGDc|%hvU(NnZK6rk1G8=qGB1L%#F^ z9wElwgY&U5hdA5Vx}UVAx>N%*>0pNBV(36@h~gHcc8?2`26(FLa_B~GMNTM-CU=x# zv_W)po}35MrTr%wbq;$1=Al49)mHlv%m=%7KoN6h(f{YiJg1Hd92T`iodW*znNbt1e-T(S4@1FNHuN7m!t3$MCaZq9hVcbUHL zij(wIN-njUW7^h`KOpo#kMY}d*}lqvMY5Z`Z;SSeeTzZuIOQ75Kh}{pl z>9U;*dToZ?OogiubS5K>n}*GzoShdUM>@1G~&} zZ1!U*#$vv565jfNHX-rOto+_HV;|GGj(W*sZ9VU$EFaBdw0OVU3vTg+LkudFqO$IW zn`tV#dZBaK4d{tVCA=BZPrhT3QtmXU9(Iw@Qu-)5W3w-!|Axp7IWZ5rq>Sc&mnCh= z0YMJ0iC6Br*x5|;h*En52R0Hl%}4w$;j0ooM<)J`nURa?O6&%%{`7~+sRs4QkxcbX zTSGRz(vF?^*Ejc3TE-LR)sO5_H$t}XR{xm)p>(@wYIbOrO9@X63JpZ*X=Zt{Zbuqot zYQ*)x7jm>(lFGKF{a(8kS$Sm~!)?L~h1DZ<7s3h8Tc@OEh%DE;2f%9w^0idZ^%y6F zyPGoP2nB_8XwU~>#|~ewi_cdx`LCT1*qTRJFK$n4QK*KVbZG*8?`PGyS0KV4P;x#} zsIGn@nNuc4MvD@fOED_SiQKnz)C#cSbjYOa2mPKD%Qa8Q|4js3B(LfBYXtMh^O)8# z;Yp$IR7vlZ>~Y2ETQ>dYGz-)vmj|8AN?QQaz>9cV)@Tdhn%vgBpM)Q>YD5aSB<${UFa3!*C0JD{k!k^ruxZ!6)eLGtm@sH z+);#!?Hr$5PPhCpp<-BfJv5n*O)ckalZ8El{PyQju1h`F+S0`< z^R??*3ERo$59o_`JKb7dn{17wRhK@UEunJ67VtQJyvpqN2|jk(RR1D_oa1hxPF|Q? z$RcP-C`tsJT#BD(9#|c`%FmwmZ^0slEW{)SO%r*&^~h73c2hnkfIgW#$?4a+>J37R zWVO2IPxlqFRX4KjixRpcyXtM<2-$vBDSiB1*%n#%LKGpcxu2r!I$klj=6{9n(ftF- zNfqS;eyi;#M~9d@-s5S`>m!)CrCyktnUL@QB3_E z7*>?4Q=mqD73Ca#;!j<pftH?ELKnl;mnw#Cb)6v(~xz5VtW&Hh}S; zJo$@zx7)%TL}dBfj^}3Da7jnG9($&6%MM|aq>o2Js#C)~^<-Q#?=~hX)R{NYaWtSZ zVZ0lYvh5L^_HWJ|Fg7SeF~o>bjIqJiCfGWpjM)+jw0D;!q@DL3tsp<}(k9*F>X0_% zA-X`Lj0IU`AVzx$U(^&FZd&-RQOis@0L`JmlE$78OJR0G80P4i@fAlZ5;6qOJ@)vX z!&gy}F+*=|l0>xHLuVNw6ni%ev6&KD-|6W&9`n!1y*pk140!z${1q&6CO>u-sjG0N zPeArc8c$<9qCDekKTcjVsgX)wDhDY&7+TuwV|eDBpvUFLPpyck(KPWua;1Hu{?Kaw zP(@yd9{+$`tlMTmP za-$sU{w5Aze?<2@9Jc(rC_>#?VUIFg5&W=95*R_t_XM@Q6!R_{HJCW;+nHh)>J?7z z=;$@vHFjETQp;A7zfj*)h+v}ru##fxX(D*_ZWZjhIN9mSpwfpA0mqTa@b4bVtnXIe z`x-PJw5uKlAW793l|a^8Y;EYo_V8%ANAhK}8qv(AMa%jmf;6z-<@A>NT4M!RuuU3A zdR8UaU1o>tqb}ckD6^94o^O(uE4e-iV~%fo617rfR5`rM zV{aH=dB@&!K7oYC*WFaWx;qA;2fLP)bxpI@$#H+6d`~T(sC-+su568m~WH_lBkmmK}j0$LWN(3KF9DFUm zEF8f_q?&plR$-rv(=i!_yVt5_N_8|KwiXe5xN%t2U4Bd!z_aJ6`45gr?mklx56>7s zq(e1YA=C8MCMSLDUpN{_xjdBKY!D{PkoG!dZHp5w*?*`IV(c-T(^soO(Mvidu1bW{ zkUnvc?tJ=%h;6PdPwd9Q!w8(f)2SvX{K6N&?7Uv-9w6!KUSXe)+8aHRA{VsZOsdXn z)yi8R0o|p&sLa*Ptf#-!K8fO3NC5=LeVx>*0?-G@H ztINl0c^*X+(tG+7hE@8n8KrrFHcmYmZkK@XRz;wCG5%2Pb$w?!7)D~-Qg7QAt-0J= z79q?C`?r%IXkaT3YibB<6k`K0Z)1JlNSP~V+0AQ0N%vU_&Z+_dpY9h9l)RywAvf~A z4`)=dc_0p#kG`ya^GU^Q=-{S@^psmgV8&-&(}uBh{W~1zn)p(C%#%sHa~mX-cpLVz z<*2vVAjtOVJMTE&P=0z}C+7b$uhe5U7n(CONRm~o8z_Y=En*P$8werLc=PaG*m1+T zYa?jA(MED6{-ywgIHX~Dfj&nMgJ$<4t;mWz=V5qjxkE5cYLafirYTRSJB$5DRm_2M zBsb1R=3P)Hqvs8$j#W@HTpVgV)mXN>&s9`B_;gHr5@4gkB(TE*hdi*|d0{MF4KDv2 zhx$f-&}yA9w9E|&3KApy`oV+k30xxp7*(DGbd4WDj#L*p<^!k$y1d-sb&mIIJ4$Zy z&Hmt6b1yV6K9_CSwytf?`{p#UQ_#E@Xgb___v7L=VH2GLg}YNceX4&{hTfRekc9nRx4${=0SD@Z@JDCh$GX<664T#X_`cz zx+{{BEvi*IQe>XJ@Y~wV%a9RWCVM4xsHt#78*3+1z+Bjx#Fu&eFyvfQN0PtUWCY!c z{nTWRo98mJsO*?Ad1O0_Ibg|lL`=GW{#Nxmta4!T`t?ibgd7}oMR^-Tjv?S5rZ zU(u=?wr30UqyuG|VZxiJ5t)vwbnFt_&x8+A%Ir-8FI5=B$(e=L-+CrPZj^BA@6{Y< zctRw++X?>wjlIFB8ZF*qzub2mxr!`EUwTG2!EL$&uSP%FA1?Pol0GO3;MV_OmW|q{ zgHZSdd?GU{C*6Woj&q_?UJlVaRjF^ywXKUn<9rr zh^UaJn1cOj1`wmMna@J6dylT43f$Wv)67wxm;143k)B4K!37C$`*NK=(QbFQ5M^2s zZsUc_ar^2E`rL<-4y9M`scn&&s0g+@W`y3P4zs66V;M)4yHaqYdLJ9f$+pt7X!6fg zvl@=6CM=W`;^d=RKTQX(`5Y)H30+6DL?m8c+AB= zyFRr-b1zc(%8<}p_uhIXPd1{lAt@aqBC3KBy+I4n@OfHj>|-E$$bbAc1kQ`HHUd>^ zeWOIayQ}%kYc3--_P^Jxje}0(0+NggS);6i7bgytBtw%XHJ$MLjRV>{6VO>xTVz$} zD@JKe;O$o3Abz#`Ea6%eC5>9l-c>p;6VP-vtEbIJZ}Q`jla3QbOM;LIE2*KZLwXJe zKGYvr0C8FA&a9$2!EYMt`)_UslpeoT?L!{=6oa%wzKM$TPFxG&@CeVBtCF?2JB^j? zRw7^*n91j>=f=DtKmYGVrBf1H9)P%Yc z6`yyKMEQ;9lt(x5D6uDZf9JET=KgcDWp}9gAr4TEFgY_vOOv;F-DuvvlGtNxeP8nU zo;m>N5%%9!Es(1)yt}*swjzu2k!KCV1p2aS*4jlrk;4M;O0xSEJo#mfcCJy`a69)C zi$-AeurKzpjWS;YI+YacP&)zjaPRS2&k_<@C>%E{Sw2&#wiQHdlh4xK@ zEhj5EOkzYHdDU>RfF_b|<_z@a@pvJXwdLZjwuU&~r~UxZJqR zFW);k3@XkkegVfvy>$t*%}hi2?cL)lcHdc+Y$6P-Ri&R5K-8i0i+JGS$qzT?+O(cb zBCAWMTgc#&F44BNh2|%L_x$Ha>4Hza0RzloH7*N>0B-OY1y>$1H#;({o60Dr4ud%-uJ; zN3x9<953&Rw^1lsl0w0DBTd-WB^d}-SYwG%x(gr|wqtxh>Z*|Cdv1domf;Q$OrHw6 z`qatD+@w`|BJuX2kv);UN&k#r=h9|IyB3ryuwu|>w-!^5a?PmK%Wbs8Ci1!?cXxwn zwioJeO(t{hC{p*FBD6E5ku{-3*?@c&fMciZ#GQ%^nFM`oJ|e==h~mM9nsCp)7$iib z!uoUNFttg+fIGUohtw>uMpV=bYACb%R2!0qO%2Ip{ZkVg1b>+8pZGp&P))91Z5zDQ z$_XsFFm^$V*fQ(PlD~Y8;jekZ3)1=ek2{$foE={!m8jA$Qukg*CA^B^a8~-Ds>Tap z`ou4f%~TxX&cv-Ti~@jjA4*TE08BYLs^D;LMZd}` zBOfB(FKonxD1YfOUPH$2VC*znAeQj9Mj;QbF?h#+LAy)?^!H}UU;yJTNrjk5&eLLh zv6iKVG{o)_S6gUow|%+eXY_QwV^9Unju%-kuLi^K_ElT`8jXte2ktrJ)J2X3v*9a( z6?t9(GR&if!@f%s?b4~JlDq3>yCUPho+r;m;WH&l%?rrI;ckuOV`YrgVr?$~zGNeZ z#gT^)C^&y2dWjnE#s{+ne8Dcg_Voi7zlbtZ7>y`+h!qg?Uv#Poh&t1xLYEzQqo$7~u4Yq>+a zbRnKTHNj*y?lu?9j=dLoH8|)Y%wo@mbUl0^+CT0-UnUrxR=KdW9{wQA zFHz*oVmD?Us8}I8Q4Y1e?~A+`!xd60;l3?m_t5liv_r~JMs=I_H06ep`O|L&?lScF z`w0H#UAJxl=dq1YU{10)WvcWY@bKCq89irMU@n{jZ}G*gT>?n6{Ke1f;qFUr8`I~Rl_FCphTMFj&T>UA{||fb8P(*r^?iq? zq9Ot!TR{XBkS@J+*Z$JyLc{V`)Ll7*Kzll>N z-4ty-`g*is^=LH45Rx`|n#uRUvK5fXqls%?I;kzeCMo<1wW+6|=3}6-aOz`qiO276 zU;l0+%_{4aIpUW0i5n!&Wjt-n7HdM{it!fOsE(%~hc!YdOO#9M7H!)xcIW|GOT(%J zV>{=KDYco2!HPT1>=N6JK#r6tVtO(ZnoHHK^)N#{skusjVIXo=QUf{smU;X zbeZ#y0;$TLtkTi*q%t}vQ;6QcxXu{M;@theNL2E1SI$Z2R+JvjE zWtJF2eY8UH`<2<;#+*z)Eneq09ktyYb@HCu`IqJ4aC%I_?cGb5{J<@u6o1SCy*A3) z=MUKo921xccs_GG0A6Oq*lS{5)F+UNo|k7f68`Y)>4yoOBX?8?%@#}he?tOScW&ct zU)9}a5nCvym4hH89JQdi z?rowBlerb9{r-{pl)}W*l3>CYVd);E^G>)gofUjGEYJ3*g@8E%RKoJM+_;9VwWcKU zdBaGl*-grhCeJ~2jG*x|Fio6H%N3AFLH9mrPO5gl0x3c5cUc_zdWL=mQ{2-ehQgaFt!R;{7SA zJ?P4WSPYZuO$(Fqtx!+_zzN+$!ey4Ky@d7OD=59#`d+i^A*Lv!9O66v{Rw~D@bxb@ zBerHw!~X}k+@5R*C%NFYX52XVk&7QP8dJTY@%%o?V=vqJRn2nYHn>OnUb2`Yi^2ZU zFhnK%T=S&4PIwraNO|8eoGF9bsU58pf`6n^V0_!gYq7?eI ze$6eVuSYj*PfbGtzndrewO029x8|p$)b=z+RclAsU!d_5R=?ven{>T-tP9g45yzxL zSAtj3T5hA7$u8k^IDx1!{LySv9yg#|KmDniPmKdIIyE%bDhdwnzFtNg4a?+5W;0Kz zfzMVsLv%#58yRm(@h;)P_D?wjUbN;Po2R`Q`;AWL%jj#)g`lVX>!2_zEl7#S_X_pr z$n-p@cWbksO0a*F9oOvl*1C7p$0G2BJobnQuc2Z!X`5$yJgc3HU$^hs>w%Wd+O8fg zhBCX4BaDncNc&9*(U;;?7|TtmIB2x^fe#){>9Z>yJN}3cojjV%s$U0t=5mXGnw40d&I9IU&kHR>vG|~8a;b1 z#UYxIC(?mI6|UuMWi%Cr6$xcl83Ud z&}h7n=EnnNR(*||LCG5uBx$vdvn;tPBYCwaBi(AZ0O#&M+YfbWb)2Zwx^heSp42K% zG3Ba;%$pRxZ8gu0nz;angG zTs-N5n1#u{zK7TjCzda- z+p|#jlW{ldBCR6LK?LfkfJ89u<7Z7pjwIOQK(3LO$BhAuFMm{Q_lvlwT@%kNhv+_M zAUO{cz{gca1S4D&@Cs#LSyKi1K_Hp8CI$wxB<4TQj z?V(VG8fZmW+3Zq4SuE18SgV+sgeh&dW|P#~e66gvSgWXGh^wqepk8R5jpJFDm3bl8^G;t$>s)4TfU&B)%_}K<7C~IoGE+ zVGGeUtIs{4Eh2oEsbshTi95OAcAfBxHUt#hyZ6grs#gJof)i_hz|5H!WHcUR^0J@N zsb>zof77X1{%so>B_LA4%Pv=}bYoapaNW2~$isTVV+_>$NZ>OGV1^}$CDjb+O?~N4 zIduE8rO@QL0i9Un*aWnt^@EM@TA-HT7?JxX_xvkec zQ|YMxJ_`QtlVI82Y%zJuPgM^XpY4!zot=6jtrF~bOIDUuk9=5i1Og(&?@hah)Kt^mu1<=bUriUDy z+GU4d$Wa7=M=i&+&|nuJijQc$T#ZdUF7WbODJzyma;D4dh8=kW5vl*4!hh{XfU-Tl zKqC+jGudjSgCQx_13Q?RlSJ;#?hdfwrHh|w$e56Wr7d^jJ?Dj-*x)eOr00!)5wUk| z%&i798?44&(Fswds|qY~|8MX8@|QS!w1{SoGFI1bHH=67zE4HziC0lj%@SdoxER#) zN{Hqe?DIM@_UaB4FaM&h%sdcf#N>AHsjR;Q#(xNcP=T2YoccNdkTT z{P|X56`FIw#a>hBJl-78OF1|d$~t>NZN$Da&rLtgX+ClP9mO2&L^Lg9I&h{hKc&ig zOO8$fpeD3e2~Tv}TDr%GpLx}5;*Njj@bLa-?zXA45&P{+%n$%DmzIL?LZl7!QrjZek-`A7F< z!P_Fm`%TkAf~mg07r1}FbAN@FkOKew$r4_0CWsJX*1vGG{Yl4~nGlI}ivpZL>f~^;itM4-R_cPHok|4glk#ZThT34LRTz73% z__8PBNb;^(^KV|Jq~yhA;%?@#6%H1s*VA`jc&t*AJOjlUOr13G&M#ZEzdtnu<8Xi} zX@My3-+(N@SKaR~#_dg3sTW;qlq$O3s<0a#dY#`-Ndkqo36u`&zlhdpEN8BA#vS!i*B6rJ zrX{~=0R*3lXjYPor@Gv~Dy9gxak_^0;Td=PjySb_YA3wUmznl(1^<;!UACaRvD z%?(9ymLNaj->lmq!Pf+@dug9@Hez;32+((5>9#5kPHzb&AP<$gJKq5=8YtRuncWp6 zP**qX56Y%Er*WXVdE<9>c6@szWu8Ouu?)aSGeLFPUabJB z5G6el4v=Y2xF|?V{GG}qT^qP*hC$;ikYRVj*5>v+#K!FK!eKff59d^v38d+)@OCOs zC3>jju+bD;@b@Tbx**qjQT?3e9~@8LP|0~*_|39EF9Mp?%0snB7!m<$@bt?Ym4QGu zv9AGM^WmJ=F7^Y7-j5yxbV^^ArHe;rCZ^@Q)b>BG4s`DUph;lgc*7BLmMOKf%;Slp z+~J2HEBsp1a&`r@NTtO!h(&+qeJd1BjQw2~l$;T>7rl_LBv-*zY+8kU9@2d#Y6iqC z3}IJDm1OWyYeQ}IcWWM9>=_<=BW;R4S{AfRk8r?=tWzG?2oXO{wXpYKcu z1y4WR5mQVzzj^jX#AWtKLo|WmlaJ3%nSb{2+oD1}XJBeX2KC+OLh#Gv?!LaOoiyN{ zy>3A6oW=(E?4K91bujkR#NVE6tY<6V{*A1l3pvtY3#YU#6nt^^k+xWe9}^R!4%1c= zX_dNboX}mTy)*TZ`@!E=e7dGH_FybId+tJxGPs77F-@do?b*9bvjb_s&HLqBL#4wI zzq~<>q57lYzOkguu0&-cx^lZ#n7u~R>Bev9nh%Pryx*N2rb8K8%ZCZL_ zV})susr1CDRWAIHC>wZoFZ>6a{u5djO;yD(s(0UM+THJMM4UWzPh`WQnS`$TanHty zJ>Gd*2>r_L?p5}T{Q9*!OxXinNDsN?;k&S&$?PCSSY^#J5`XNTP@hDq0~+Hm+bDL? zjwD#_$_-9f$rRo2>f4x;BUG*dEMQ$a=E;+xJUyL;W>Qtwy=f4pTIJ*nL`>9IO36yrzS za{RQY=vVF?DZDCOB4#`_ktDy4LAxI<^#)>4P@?j9owCAp;e!Cj>SbQ~irN8Erhq8_mq$JC_$v_ zqvcmohHDU!bY(jn1+`(ZHK#)QQ$EC8vcJRZ`{$*NK_$mBg(*vM=h}=!4q{W(wBvyU zHk}rF>A%ZPo*6qAXhNRIg!L4m#iQ#I+2Y>i;#g~cJ~Bo38x1uF$`oRkDTb=%Scx;F zA&AI(9dyyBV6CXa(QxAva*%ayKn^W`2o<7^Y^TaaE+xj3)$vu%1-aW+MNFI)@-}a% z+UX;lF--&5nR^tqB?&xS@D*&OhnyKDK-$Z|-JOSDt|75Tc` z@bQhgo%atKK1#YVM~jr7n0(=QB}Pe4btij^52v#%d?TQT=Kw=St|}%g5qhvG4@Kk&)Y+Fa92#z3)VaZ zy`Pg=W~7csq}b5^mKzoRBw8XZtclI;=|-q`!^=g zc+n>qE|6lZ*c?a_U=??AjAAS_-X!Zv=E(;YJgJ4C8zt8`^gDaUHUZ)qKH7p1+7hmd zj_=V<#n2|cu8T|Ln9*0tX!b+c*z~;{^{`=&iL|~FMI(IY$&*3#AH81ja>)36YH{Xv zDXHC6>fx1GK9lY$YgKKIQ+XE6#wX4#rCD1xFpMSkWcJ7Rm4EhEYDg`Ym$?vxYO6+B!1ttm*_ zA5uJ(^RsHDT%tCG%ZPbz6=(bx3s5@A7lUnCWU)(+-S4*LX{2 zPjzaFf?HJ_invPDb7`AVLD{!r`GJ{k@6mlbqZ4tz#veuphsHtdv60pjYe*fP_;7%B z;W9)xEPSAMf-=PD^oauKSsrSmcB&lYKI^iRX)G_ND zwcC^4skt%!o;NH%EnZ+Y%!yv+>p(tOXsFE_5VQDfo-YL4=4lc^#$^q)abF&GbRv!X zt&WQ7mWbN?b`7oJrrE^He7wb{o+N%{UNZiLP=B;i6Wo71(8y?!g}T7$XiM!CU%PKl zZRAQ<MWRqEH=rr7#Ow!=*No#w&6IHs}vRjn38+CMY zawOldfAE^yR5!}k`{u@I>FhMt`5;SRi+t);O?7`P(n{>K^yt9lXB2zT)RgbJwwr-I zj;EDSZ1p=i8R7(*a}a1mREi zUZwMsYEHss%r33$APP&DTh46P2Q$W`I}op-bpqIm#SeQ4PvurBMH^PIEI!HbqSkcO zdMvzqgH$4M+Iser2mGBwcS1rU#`|3r{Ej6S!La+;2iDn8MW){0+%{Ni;emN4DZLdL z6PvphFY8#-JUl5rrjp?>@*Rl^FvZa)iv}i~oZ3voe86&cU+mbkqNiwcy5x9X<7h{0 zxZ|^2uI^9PWg(u{RMuJBs1fmvz-g&f1`=pL>)g{=F*y^*3nZ8LIHM6U9;+^JW>oKJ z0i})#bUeZ{F=X6gXu4y#T*{F|vn=hk)Wt+p#q+jmgB>bpL zII1Uy@^(CW2-f> zh1?vMqsfCbViECpEja-tJ!ZOcE$3@4LhI?)xH&H-@6I!O-%djeG3yK~$+^s-(}C@# zBAB;hbUbP!d_<8S8CR@yJ!;GcbZ#k4;L=DJV-7ouOCQbF?o{QG8gr0_;hD$?gEV-%8N#b$%`K4z;`FU2r)N(Jw<^1ys*oamOr|eQWz~aZKVU5rcYg0m_X?y8UvD(Z>i6nk_yc1nKWLNaN;)$ z=fUDwgN#IBHktNT&zC-A8-EP3HfJwIEgK39X=;s?j|^egZa{E{r{&y^ZPW)*oiOYzozH+ZsHXtCocdSsCB| zPQ~xpwPtVa?Cm(kE`xzN8{et#rGx}o92jx*8 zS|pfnn`bU~S&M&5N|a$#zG24F$61HBBexA@k&#QKlHtHoXTc0m3sl^Tk*)4q`(sH| zSFrJkljwLi7ZM)4-FWx4HZ#C{=WBA~5<&^XJDaR?L$nyzGPp5b1~FxLI|XJglNYha zkr|bo1$$5JqT^UJhMMmUwzUd!;ha$KqKKb$DBrXXPcf8;O>q$aHPf$cjv@a9X(Mh`w&yLzcEL&FRkGZcy~MsN>KVqXa|-m2?O?7YNP zwt46d30VB1U^lbJ(6Ikj(c8puU{wWVQ{A3Y=G&C?x1ZQl>@h-5J0}W{Lb~nr@runN zYcJ+?4-gAPCAXM)Fnh?)EprK5|qcW_hm} zw=T;VXdO*`lgKgsfY0r``&grk2BtVN1@U#A8(W5ZQLC&tsv3OtdsEoo{Mk1Yj&*6+ z4)dCtWJvaM)W1>4-c1O78sucbL>kMTSE-Ro0dbH|{!Rn7x!63IJ;83&Ebfcu%l;Tv zXx3VIthRC`XQyzgblK14?0@M2 z((=2OoE**!sCTkq3^&XRO2@`to0sA{TctVp3Bv4(*d+8?Mmb0W=LpW|&QkS{?nk~J zF|=SRJSc?t{(KhCh%m4(F1P8Wwox1GUT{u7H@;1AF}P(N$3R-t!3l=H2>?w$t!Nl> zve=r6*-a}ax41szGi>#YUo#YOnnmPVZ*OE8;#Js4c5RyqJP zrK9T4ac`%rMAU$>gGx|NXg*pzsMvSxni)RzC3$*)ty0VDzhQw{nmr>kQT3+E#g3^- zEIs)fT20G=vjEv47Qyb@Rr+ZdCKam`KQ%!Ne$!5Ac)n&pDW+zxtEN$Gnlkfg~0s zbRH*O1T9xrnByd`uD6M}Zcri^YSTPmsP*@Lt?bo&X|Gip)-qWw+~W8A$^j-6-_+$e z^M2=7(rV%6V~Qx_-2lEa^fO|5>Z#l=zJfGiyRzQ2+f>R97|iyqp%#lEj6mi1NxBoC z1e$ufZ~w^Vb`S$=Z$=+Q-nT8YW@PyODx4HViTO*LIjj$aMjM7#Z$LJyjup{nt1BVJ zizEwsg*>(Ij96h}27r}7lC^Xq=1ybRl|uE5kC7N;+$wwKM^5Rr!0(MEzDa&~9d__u zF8!9-0zEOX{SBly)_OzBU~dF{X0`8&sF;Wr>TgN;fn%-p#D+%}s?qG!+TSpG!otwR zb4?&8bqiKSSdC2G;ys-z@>C)+uq*8&{*OT4PueK_2C&aJ#{58Z44*Bi$S;|sMm-757#dcqA zYPSNRCDWm9P*r^dIUmzP9Ai>;TdIeVeMFx*zle%o1Q>s>>}ha8Ux zj;f~hF?Q?1X#qq=eYx5nmWjz;E>Qm~i7M2Ab^a?G84XWWPnk06!uPo1<9$+c<7ZNl zrOkFr+q(_K@I6rgRnERss3otI+8Qkj-W=?>Ex%hn3y4Z?buqD2uoI#po5rmQyi6AR zXY{8O2h>#N7*nn4TY!@_d3x*{NwsRDV>yRgDc%QxQje+GtR8I#-7&Vyxr)zfa{hP8=BKECh%`OK-@NH=|Y=;eq0#t7zV;8|9>M^Duo9@~vU%=?}V=4p>(0~n8+ z_l~VX950F61tIlzxeC?qIg@ILsit}$`iH|2IBM{%CMN+GS2wCpsk=aDH zubX=<6IHhm#ucj3#h7RITABQS^$e^_xvnkFUM|8d*853 ze26rc?hEHc&TSgPYs@H?Q_BOZ7qqvrMveu=A1e6KU_lGw2paY(W61Q9FfBdt6!5^; zG-7O;`;PQB(RA|n-ij~p!wxJ~R8P1P;jDva$>MXZx=JEjI zzp<%jow?wO!f*RNc0A7DU1LYNl|m{J+u^Dy&q)o78lsN$cc8 zY*=OOMI&?@?c_E|L&I)l?I#_Ab*)vQ_0i(zdMvGR4^!f=dFuJJl(*8nOM&>7OvniS z(7fieMvhkhX76#@wPd4&`yi%%3&J#}2K~5_THcy?-8$Lf=C9F@5XO00{LOI<3hag- zD5`U?{9slR_*k#}NVb^{WS`%}t5}rF6l7I1_Ie|#j<9A<&wm-3QZ)COjAI z(w0f!Pi{J2#DPoG^&cU8fgg}9RZbn0YQ5^Tun^7)D+?4OI|_?#+)Rz+BeJWc5>+(wN*^?N(y{AG%%Y3sfgJE zyFv)9kY#fKx=)z8bEMcr!#lO&=q|;iosu09tL%sHW zREOtv2sE8MuB&-!*$QXo!$sG5iv5)~QTdeXlf3gSY@m24bQ_z_kXd-uX|5YiQ`q7k`0)hMGuED(ed7I5f=oxe$U zn>T(}$RjKz@j}_h9#bmTK&v8fQs*9phVL_+KSi$`;I!TW-{YQldZwBeB+XD_e}%XO zzWb(UEPq*OUia4+(1}zVaflZiGe9c7sX-8=YWNnCbbcTVwHzskAL7Uqt%c{h{EEjq zYSy-C*}4DI&tftPX^`3X=vxXD%K6a2Xq%|ZEJ2mz;-#3YRlRmssxoti%~j|qD9D(p zvdj_2Z3ntlbroWx2zEqZNk%sGd#mlGK5CBkhDGVLJ!cPAY@L9$`F0GIHM}>VLJFQcH=YabNQ@+J`Rm@tv%dF_|wfsKQZ7;2T;W6CL zrcA4qCI`#ZiO-q@_ekV>jCCH_r&!daJOLiUiaIonSU^?)F34I!$$;zPWlw}uu80m&3o7X+|Ws9$z*}ONe1z99a&0q##d9QaPNEUeI9qfzP z)1%b}ChUsDz2=tttdniUIHD#t4>!oaE{CxAe7%%8T#T>FDr=)=bYCLXsyRCn+ORt| zIsX_F4U!Bn+lZgX*?JfC37koeUZ=PoU9XzksETyxm~znjyzrDSvr5~ek9+)PV`JT3 z8k14CZsydN6be;`VBG5Xja9vAW}T#>VaC4AS79BKq6A=(&YYezP!w0QEnJLC8~FI^ zJ_~%k-sE5>RjraWA(L+bfwPS*K?=M~%FZIlxQ!Hdfdw$q8xii91Ti4xr#Z{pGiNV} zj8b96pGtPq=8KQpYWngbs*4Y3UM89b)+(egUx9mY{;7F6l@&kiNLesk`B{`8@34jhh$S98SFpTr!53&gB8bSt>7r*q@Q%mk8#wLp0O zyGSLxVMfB^9-Q+Cp~{l=eGUz)V*hq$e*XtJYnF7cqxJQ?ndYZ{xqsuBjeORZn6RoC{W30kq{ryD; z!_I8g@&!& z#xDe~OO;5UMHSTTBD$IXn_niJ(Y`mt1Rnh<>y(;GA1!niLq4n9CDcFto4Q>?av;JB zr2$HvtsI~)HhCW6uFAg%uETQ;??bIv_BLovhiL2)h4*|(y-Dy-#j?&G+>#o+Nk<+n z&ubyPXV}%Ns93Tc6+BRB;VZ5z7ES83(y z%37Xo@EEe}FiZyUz_;1B;@`1`7Y?g~&$ay<)i{%wj0ftKT`_mV)zHcP^udzdpm#N# zzumZS*bKe~>H}xtxq`AO)pIQm!we1NE{29-0_N7~{x**P?0m`NOEhnUSqW;(qF*s= zD*Xo(i2Y$m7Q%K`)@zsfJ;8+>STF@dPEJnA(lSR`a3}ZL08|JwnkT`h^Y>}_?_Hqs zMceD=ue@YgW^iHEh8s3?^C3-+WU4-e>!nzeTjAVD-->h5M)if<|(;K ze&H|)U?@>47iOgB#0Ys$M)GM*UHkoz~aNfm-vqL4>}@eO*F<+~tJ2!d{26VKrS5D>M10a3rq z{T||1RiAa&?*8`0cN6hWk3a(f-ZTe#6tjXjRXR*{*XWm|69H4#CR{Ho3Xm87!v;#a z|3(6rE;{mm*g$GEHX}JYV&M3pCH=o_;D3fe{x2K&|3NmerhU8p`8$sj-xwH{TnH-s zUH%Ww-^>?KX2Eaw<+N}1Lr=v0cG=f2&$S=t(pT^UWDoVx^amE?6(HtNJ!|-yZH3s8 zqPc>C`>zIf>XfL61NWW~ml+%7NQOY-&Bp(}zy52x0Oi+dBsjQkL+^1pj46JpcO!Q{ zS^-to?9b}4Ua7DNSvVH~rh1z)9|6fdJevU^c^(-N5m)gf``&Vj!@YX#(*GAI&^&=X zcI|UGL#2le@uf>1T6h|Gpx$lp*(QaVOXI#n22R{JOA{C`o%bZ^cOxeFOnccQz_%$v*oTUR?T zpV=BfhJ{MV?G8`lauB*R)8vzN{~pYZ>&`#7amN5O2$rsYE=&?gGn>+003P?YO~^O` zEveKZIbLa1D3Q$btGoVB95qDw%pGOv>KqQ}MzH9UiPp)|-92lQIvVCc0kL_@xYdlp;{%uvkn-6;tJi~xl@X7dtDAAJ$nH=6Hr7q6XtxV@gc zc$PEpSw(pAXXH92Yx>E@=DD}=A^%`iO=tmYv8kWt^by^ejyyAJ(U!3CY&Tt1*3c)I zm#E!}({2e@LN)T`cs-x|HyQXW-obL{#EQFiPRSk9C-7~veZhihd8BT&Gf$$fd%X(2 zTzhfF(hygs_gx8Bzmh*!78|mZr=V+Fa1B;jP#t)n;5XlI(0tQSAI_YMw^PVtlY8vJ zIoYamV^Ybv5qncX3D8)OjpeG_A8CN*pn z7mMO@?~R5EpYkt(n9?t7CLHbuC7Y=EN0ImHou&vUEF_K|W`$p=$$XK#&A_H?4m(lL z!l2c5eBnu<;t{-PV!JuxXUHbbF6P#qr6}@|?C{ONS4K*`zRgYm1jICB69QmZ0X=@V z&}*HEV^dSs#Y=bkJk(*IS=EZjVB}_Q#0A ztiT7LlyIu%9c(B1UL})EeRBbmGkO=D|5Gt7LqDVoH5V@<_f`Sd&#vMB%5uOWBbH$i z^2-GI=hGSY9mrc|9o0|y$_jCdpIV{h`&osnBCc(;6f+ecmID`F5JpAmRy}$aMp~CC zw17O~Y>lQNIM3)CppNGn+MxEZV!X*MGCfXT= zM=#@84JJ3&l@uNvZVgbcL?&O_dULCKk3!xKGF>_LxDb6PqrUXPzXkbFadl$zjr-rM zapr4(2-?S$7}h8zz)ox9IP|z>Z9p*{gAHC64mGWEphbkcp7QuEM3s#B{9TX>0@kgq zAA@d$#wiB|-TkXrCw%_T5FcUThn6%X- zX(_2P41;&+{F||#t4E4T5K+e=$D_l|+m=5MKe)@r^cdAOZ71^|V0287_tCT3PXZ@S z@;zzy8c%0BT%r=E7a9;~*vUb7uiPizV39lDbvVtD#|DwB>gil)a8O%3+Bb`2&iBpNRSbNGM3QsbRcr8AB~z7J7SF zCigFFR?w-wl^iw9^>+dw{!ztat+2^_NvCtby6nm=A(ogyE_bU1Y4tu$K> z&Mudp^CkhT?8;veS)}4I20bR6xMI)PEjXp@#hy;uErfdiq-vTlyGGxB>yh1a8i6?~ zW=%=jR=Bs_ktaJq5!q({0D^_f?O|JpZSf@R(|44scIo+E)ODRoG97+`Z3(3! z%Nwla(H!g~4Sfyol_*} z>5NXCymzQB4Nhqa50Yl^P1A!;#{@e?qgtndm%-0_jrzZL56Pz&X(ZgFi++@`Hyt2i zID3oU#Jga(gXR=B#5V<;-h~6hM4dsgbCQxZM-qENObfC!GpfGUT-`AOo9SFS_0urP zA|h^Kh`0m(yeTRu;7by12EUYwF-lwiu*FSF`w6>#ClSR#L9r|IoJGa z=#@!za!95?&qH{9y=S%9L}(-9$Se3Y=$O$vj5#F0yA49j_2Hwx$IQSR2L=JWLXu!o z8gZ5Z&yBlLGdKzAKNR);~4JR6cRld$5Li54nVH-(bL8p{Z08M45WqIfyW4!cDcLSv$UD8sKnd7z&n>ST6U9)SELWfKa4PYs1%@UNQ_zIn^aX( zT=%xq{d1&Bi_Qo@!~~O*@eO)-e`aEqwa^Brfz_$)5m8%9vNf4 z$!}3Ol>Z#bs#^s7A7_u#>ikXW-3{_i5(hEHTPfmBocjZ?^Epz9fwd;NuT7Zg+uJJ# zLkB*tPHaz~+|YP&T)+xx{Y3cr=JIU`H}$>NM$6j%LhYBZy#N_%_c|oc(4JX&=_A0T}g{RFh{|Cr2;V? zsV(_7kdg(5r7{8pDqqEf73dnJfniy*iO*1Mhhe%P=k~ zFgY5q-@?YrN!&|2GJtKi9D(n?Jl!=5dq37(LA#D&g3Nt;0&7&4$Nr}{|NkU1& zdsZ5^jOdI7_JoYEKND9SN@)Z=f1LCgS|6~MGpmW;th-z*F5m*g#2g_i46QQcpdY_X zxagaR`VF&f8*hIMx19AaUTO9V+}8^n6-C|c&6tz80V|Gh$~+k8iX2O*9dj7;csW6E zat`Hl6qUy1@gCRe!_P^q$s06$=C{pRb(}7dt^8CX?y85JUd>HTbBC_KKI&i3@6 z2O&9SX9Ps>OS9~1^~)4KhPkf{vi+$=Q#6@D8O!9~2k$SCk&;PIA!{Qf`mN%MmGbQ>%Q`!-y+P}AYU5)*e4yw5 zKJBwpQ5v_unvr3AbIrC5{kG8k3Ndj*s0KlvjR-nEs88%%%eX#m1N^OThc7im!r{|i z3!^S#YC*`rsCcWouyv$pikso}RHhefg;V84#jHi}gp6kKt@L>fg0U#;w;wG=K|IVX z?^x&gh=H#7~c9`Z0gTTy~%E#Jq1aF~+53J?!CaIACi%7UU@sB&Kt+PX~D* zqebJ1CeYzP{zLPXt@)ok%T+i7n;xNvj%09idmL2`rN7tU zFNC*q>Z6&^&iU=Ml>w=PgEblV=DW$z18) zeIN7b8NU(pLhBUESAVm6h484qv9$7Ug6rsA6+fA5k>a`PTfgui>l6nEmQh>9o;W512iOZ_k{FBVF!Rn1f-n~PLB&C z&FKi+Pf#VT(jQY3$iL_20#3{`;Zd>MV=lGvailX|sYcRAv{idmRfe_3sGrx39P4u| zSOY!|adi{s1MW{>%g7&~H7V*MeYw%O$a$o&v zX^ovMq7LR5CnFa%73_xlaJORcwyl@p`ss zoXwb=n>nUrR)s+EQOP*9V9!w;1Bb14{f7G}(kZ8~`eYvEg4mrWor5+_`};F!nCWrM za;1X)>8BfLfi|1!ZFlpnJgjjy&fLaaB z)8=*8Rs7)NR9XvIYqlM}xMAPd)VWMAw&k%vdwHXBW|H^BXHvAP_ZXN+R=#L&;73UzhAhNVCB6b^a1%xXjYJxZ4=G{9!~jGhC}h<3X$8gf7t&Vg^`ng&^61~qOv zW$o_7aPL)<^kiZ>&dq4*q=Ibv7yz1s86Nro&EwO7XBm z&AKy8?S8~w9`4mM!xOrXkntA$!}>zUtq1dbO*$3+B7UoBdz;@sX`3~jf1a+gQlb6a zVSN2&6EWIL5Bc-7iSZA}0Dn+1YS!SctV-~9_4xQD_ubwbC;{#}vppA&{Q%=fn@zvT zU6uILx+>pY52Y^YL6NrchO}!&2}fHbfi`b$n;L$C6M2Y^9?e~xL0|HDyJ>jN=K+#}q)I^V9NXfbRW9irD+SF35vStY28F!h+ zsSJ2S!LqXNBGw=T81fdO4v)fZBG$1^QfmGlL7sAoRW|-&N}7-K62H0>Lwc{tvk|JQ z92TE~Ow-*%&JHB^DJ(SsCi z`WQ{xZ)N;oZE|-gH+A2)w1`#=8nP)1IZa1)w6qbnd6?W@Q>k0&{J2z$KYi*F_%l4S zTW(btlxODfLHYcQ@hkh*|FlDV+azU&uh3tJvJI3}r<{1jXMpD@ZDq7LU1dk)THyDp zqvc{_W+9}1QyVWW1){6-$oIpOTVq>$N8b}=L|KDLlN67aSCxx(!ke2R{SakOy?#n)B$Ju9l?*D$cU+#0i_`K_p_nl+TIckpa zn`7`;+;C{WT&u$`aT;XMa;^ET_+ePb-juAqjRFx+{P4HF%nBpIe$MIhK~)qn*rt&$ zu`JWAXCxGoOai%EH>L|d>H_5tZ+Q|-BG0x(%_RtI<^jiec4R~D?7{Mj_6`$z0L9vz zr8Oh+XeYYcTRtxzo>^aWV|qIX1n{PwICzIb>qlN`NEq4x&hJ^vjj4pX*>_lzsdar# zX+t7jh9&pX`h03ul%|VTGV9i5{#0=F7^h;rZK@vFek><-W%lA|xZ03>BJDFt$_8!| zBNmW(&^jX?uqkL@xVLQ>e>0w=R#~50F_5h{(qw_0yNldpupK2=pnXz%oWuZ2lL4xV z`4qEZg=#x`?QS7%&-ZEN3(N^EOyl0Mn{PDEcn6L%YgKuTO2y@x9Zl!11=MgukY1kL z`ZTrpP29bSad?%?nr;lHi>Myfrt{vWb56+3v!iX~)2+4`uf)oo__N)#W7G>O`XOt z(EV~#rI)%QP_ca)!fj;&1dL9RAL>%fJK-#@tQEz(*JT}#b^Ju``JTEAc;7n5yq?5+ zPYa1txCR5%ueL&IFSj=_z*^Uef4_r5Re>}sVbEk|`Bh&y62wcsLIyF?m@Tdj%3wge5M|rU7bJfWLMv~lK@0XOLp^A^;{B4 zxA)8NPR#(=YC8|sTu&0v6?(0g**9qqCt28)dpq^QQs;hAFM5kX#K^TH_w$h`MSmA8 zrx0DumFR3sU#{NfoGOIZh)=QB-fFJXD~hlR%1h^YB3sD;&9}#vp&mFDZRtGF*)R@Y ze*o=wRJ1nw8`O_d-d7ici0~{f?I>%o2*vgCY9p-+fco`2Y1Ur*1WauSwAA?mYBZ5* zCu3zWxeLXsC2?`Vy;}G;c+|GP^8tvVZ-P=nLSoxzgf}^=+UG>-XOr0H=F2aE>VpLq z&0g*+4=Y@&cgqTUvprG#FFD>dr<8dQiZsYR`~Fj7y2)yN{`8wG6@SW?|Drv_gLSBr7n@=oiUsDO;MX&!vna2!%Chw&O#M<_A(RBd1~ zIK}xI`)@P%x4ak>y$)c0rDy}XY9)`g*>CO-Q`BG?5}Vh2H_ZuBupQt@@)eY7=GKTv zGE>nY98x2U7G(GgdJTIPf9=!k!vbG@qAP3>rO9*Cxz*^6&yW4L1f$>E2lnCyO|NB{ zeN(XkKu@o#{R1Q~pc&01EcZP&O_ZZw7#bu~p2%K0-ne;^Yi+EDS9g~`9$lK1Q~$DJ zL?Icpxzb^hCMOT1igHc!mvrBH&gxSaFG z@#k#z;oN0Eu1%+Mo2sPceeRiK>TGangl3_b8E_}G`KjD9t5)(f&OQ{oyLhpX**pHT zrnoAEM%m2T_$MMS?zylwHU6!@Cj1F|3G_C3%|YfRX1O-51tEAo#% z-Aokh?U1#Er?%>FWS7RqeO*&>7bd*a&?oz^d*4xWccCHpyPAV4sTewIU^T@lPv+W+IRk-6bjK!yfdbuiZn% zHs0Z3H-Cq-McviuRxNYDMVL|ml8rMjiOD7ZjXfP+Mg!8k$F=b-dJ<=lv1=~p$Uzdd z-8c@@L50C4$hGq}@zdfR)5Pt&jM;edZv_bB)Ae{9o+sJGY94)3x>n=_5q8^y^)VsN zB`|E$h1EANLKD0{2u_<+Tl_s~eGU|wD;4ddG5QbaE0C(?SCIszxR~jVyRB$D{fsja zaZLk`mV`k*KCcVpY2_|HVeA6SF^bYRsK5fS`=WI7qqQQu=k z`PLcGYt1)tPd+A$6~2g|#9_}?#jX(pqZg~my|bE7SViXh`yuG}<>>~RF9IzwVa5M0 zQW)waip24ZiVkc~|2A0r?;QI_;rVk2z%e-T2)bfacz2n3aH2L<)YM&rY61c}*g$HG zkn^TA04+$I!`co0gYrLK|JQdHB>-eyx?Z!+*Yq_N*lcz(LgcvsEh z4uJyVd;Iu4h)-p|4jmzp8TfeJ{4AEAJW#Q0aedwVLs(cPP%-R#^tN^~MD>#FY}NliWs9sTkM<@=6|`Y#$l}=AK@Ogq2eCx)ZjjKDGI=6C9}IQi-QahxfF+p zso&utvPI4$sr>(f80^?xU^B#{myWmtDLK*m@AjGe0?q+O@{*-eqyW17eR_{gPFriP zqd;zNuir!10AQpktYJDx;03&Ywb=gfp-dlWu`Rk4kB1A_8{ByC3$BES zd7zos7Q(MK2OUz;&o!)sq)ZD?MZ=0MN#%)Nt8pRltTY0$xvo+9CNC+}_7Xl%_qViA9 z^8r?En*r}T`=3hgS5Lr=*Iy0%8|LS?e_9m*nYuQnA^uhK=RXAr=sVB(=dWKqode+B z(sX&+_P=rSKl}tPlB4{J_}_II2rLTd%+r_;#zcQE!mpmd?1R5j0DqFZ$N(r``maPJ@F0!(=C|7XJg-t+%AneaJ}?WOLt>&EgIG%T!-Y~xQ(wUb!q zP`U?OY#qZ(YzpazE0uIx$k`D8elq^ce*3KeZf6YdPrxPUrU&>NNW!crWheid*Ng!~ zxP8zMM?>HRYk)lfm&9kSmhulK{4Y6brUw*{6{ooGeKD#r1iyzMHvKv+m%XX2!}_x{ z!Ie{O=A7wByk8mv;4S!Fxxia~VxdnKwN1OxhC76rYV**;M0a4k^`dMzs3PLdsOWK8z~$0iPO{w482sl*^wxOweIdiZG>n-Bev&pJ7imJJqD{ zIrPkH5B4X+I6Sv)YUZCPj(O-{=!~J{QNpe;oCc_h$j{f2}Wo zZKFU&x?lS|=8j{&!xP|}K!9=xOJuW^z?X`z%+2;mN0Eo3whMwOg<)b=_32)yD{?0~!>I?WSv1D5-qr}H}3#c+3jud5A>>fw{=^6Y-c9~aLH^|`O+3*nz;**E;slQ;^ytKf74(*nUQuIF6w8JrHLT$Vx+t69~Fo3dx+V2VQkBE zC2p;3EK@)$@t1)Y55!sl1HGmR2r54MU6Hl1r0`|6v4Ldn`JnjeHC8u`9Qkxuz3GBp zYWB2|n)2JoZ`f&^zWMU0WvwR%?P|Lp+pcd5c@!Rl#zFPoGi$|85flLQkk_2F1h-D6 zz5Y;qi+*ERs!7^W(jyE&w7{9!fNlxM7%Q$PMps#yP!1E@+N5vCZwy$RlbIA})8v^jk3d9o5hVEajCIk>Jk<`t-MafdhC_`{on-7(ii zD;F8;3ZTDo)= z2k#SFJxun7Nc>C{u-Hs->t)_*u6HtvIPqw-;2tIgG{sBOiI{2@(ylH4-MTCD@Sp=9 z-nRxg`G>7@r>;n?dWyuT|5!R3ARQ>nr66@jy6he4z`=>ERAsOgC{JL}6L!JjdQ+kW7o1+`g^Q)NLs;7K4 z;(0{e4=aV{O2box36}))&M1I(eeaMlrGcUzZe0Vymt20d0~}8fItWoZT%A~G@KM;n9ojHlAqI)+tm;*yJJh&ct2UUj0D|sM z>CPJYUxxn9>?9$hV3R#&RxgU0sxXsV?TJ-+D~#o*U1?4YD8q+M*mp;K=|aGR&_d>? z1dHOi6`5wbsnw<}?YfFyS;xP3vD@u37b7DhOUaXMd6wBf|MeDj+2|S>p#J#mVOW8`v?270e!J6(YG_V~mEp8mT zY}uT7ikH)yCJfhsjY4&GcN<{X6N3QHVP1=Rx`G)@>H@)6*2;3B2(patbs_KG1yV6# zFd+qjnU#+y_J6x%zeTxf!x&9)YE0neJ^q$a4wPUMt@si z&~;#o2!x7?+FOnsQ#s9FVIyqR`7*wvcYN|DTz2E65GH&1)}nu65@EWRRb&?%`LP%n z;}rw}KLhk%k5mtkh(HVoG=$H3nSIKOgC2*!wph`-=joQuP$fOhjVYG z`8{{VD|M@JAT>TM5^H_>^d_<`*3-PO{+OAEXqkadUB!rBSbW9OBMxQrf0o~bvTzve z6U{h2aKR=XQVVI>Ptj>|(WO^Nd&I0^7gnw3$^kdTAlvpME)Bsz1z}jn7K{Cfp_Ip zP!%^3$a5sN%lq?x&+*Th(?)<07r!~IC_i50M#$_^h{^7qkes3P#WDga{v$aJYmGJK z9ajZ;gRXX5MP(<_B&-+OJs(g62TOH_C%dklbzri0?HvZH(5mFz=Lfp&4S;7~fBm{! z8P{nwgfZ=*pTyPXxTT(FGqsD%BU!ivpWqBTR^q^0SPoOgZLfAS*1SK{Soj@L){g$0f}=I`oRk zcJS)LyBN?bper|%e^7)o34*9{ZAKWyytX(;R%ErT2H0Layp*GBzuFesbGWrDx@;~`H$%{eYv8gzD$0O0R5QKTER?sAA1kITrFo-ko zipm`IGK$Lo8bvt}5HMATgxZgP8~&dM(!pd0x!8Qu_=R%%&yl1F?nvk`{3-cAC;IzH z_ACJPRS)$4=WhM35vkPBfK?|5{y-}8zc%;xKX0u9AsS3bdLjSsef`%O_^DF20$o+e z=xu5LPyQS{0Zdbu^nl?1Xa)a2u;6|H=w3B8W?vt+y8aK|f@q+9@+wQv*hX~)bk2KC z2oOud{*_hx5601>0T@9Jo7UAIp$r|k@`n5Ve@PaVkB^Tku+NP;fV{+08tkUoVNRm9 zoHv}JU$uCj_fk!|4uE&__W)5oZ891VK79a&mlFE6c*CoA za1aeB`O#~Wf3>}kK}@Rkle4p$>oS~o#0c=Kjb|V>0t3)?HfmhM3vl62!ZtggX21m= z1;xPqgj|$g^AzQSQXF4IL_|6&s@AJ#RNJo~Y(Ju%eTi`%0B~X2vKHXd?(az=V)v1jal{Sose|Eb z?rlw{wtzyK_x7rD6=5<^yZy4s3v^v-UqB;ne)K#9_JA>QP>}-#{`j72@-H_65{a&Z zPB7)cr|cs@J>0xb@I6}O)w_4^P}@i@TR$caz{BomJAuEnT~Mv1(^-p4WH7 znY!|w>@gecj1GC1`PWN>@fty&9G~BpMMuPECFrg(N&!R@+~*X4FwX#R3p|4H>^;I8 zGKA5Y>I+WI7C0X(qbfu$-s)$ zARTE*L8Ubm8E{Yz+E$A%ia`hlh1W;nq`XI{GtoUOKJa$^(*J@Gq&qDQ*8`q zhmNBpap7k`T<=(`c=>zNX9&P`29>^&pjksJ9+Xxg-rp7Ae-nCM3qn{l%pOPv5!qxw z-67s7fenh_62Pz6b`Jg|_}s4+xs??Ac~5mFjfMmxECMub9^VIJFrjpWjd@}HdNl_D z`?byA^-f#dFAE=VQa;t|@E|Kox6WZKR>5gZM%wVFyH%T~hjBt0kJx7{a}V3Q`*Z)< zPlG7lO)S5?KlQ{A;35&P{kpAr=0#i3tdkQhv+uGyNd|81-qtDsBJ85Ho*NE6@b&w+N(AcCkKD`pXCgqz(b^EOy<@18 zH@-CSopoIvs8Xhq0k)8VvBYNS9weqK(dw6;Cax6l@=rcTM*RJ^z{_bq0kz)v?}GtC z+%h_rSpeGoI%|Gu@)+p>+B??k-eAxc0lhgP1qB;m+|%b zGvezF`}p2{Bu;p^F=+cR>HztlXGlQ{Ov)b{g*OmE=8g<>hdOhNtWOXIlvd5*kWb#- zifMg}j*1=+L_6y2C06!deB9}JWOCM`q-95ln}5vL?0I&+l+Yc7_;DD<4O^)3mAbW~ zSzQdw5=KDBf}mm(F^S$*%H<5EJW1pfK|+KxJa-S`5Oa|!A}B`EA!$zP^* z-PK`@zXn=)cbge?elMC*(QW1_)3ZO>99VI zBcuhcsJd*|a$RS|e)8S3v6!v(5$AdIY%kmnME2kTHP$Bg$EYys!>P%S4)a08Bc|WI z`JH;omb;Ljl?#GPa}zq;&4l-{LJ8U8p$k4{f-X?)s`$gzg*e`x#^cD5ly*sn(HF^qW+Xu00{_|xe(H$D})w_@F*JX6-z{PQeG$o*)& zdCehMSgo;h$~i`dl!8zZxaH!kT1)YV*^N3x@Q0tpIa{fJpMAkhYu9|`FrASpg)JA( zwAVYc$}A1rZAxv92ivDeU%bJ{(gIXX{^^iIJLCNd2m{dRp5zdlb(tX#01Du1mL5f0 zPx8ur@f3IREPydz2fg&Ew0}aKQ=JA@V zCS@wmsFX&0R&tHBa&KWO3G4%$O1YGn#Q+&;kdWny*}Kgjj3b@BO=oMRHgl(xF5S~r zTdUnmnT{L7CNlA?P@%)_b`tEdPY5{k7lAn7uU=U3*pvcKK7TfhX3%ZNx>}Il%rKoQ)^1Shj7+BG zAH7UHTs7`E99%u!L1R3Uw15s5&;d^3VLXa6`Ly%X8D7`u?6E$K2`HAX+AC2 zyc$Rq?QOl0SZSBtOFj~@nXdG}x}uGtSBO0m&7-2!D74lKUM_ueAzSCnsY?2nD&fja+4ppHU^PZxG1BxvLw~S%2Ik8z!TSN>E>}kT`nTIgNUi5{ z$k*2UoZsf!K$E(R%@KcC>MS2WIYKts3ts(LBdN&lO)UN17)8Tj9@wY^;gGW|Selsb&hm5LtJm=TAxLjFkQP%! zg7M`Grr%-84#w$UW#UYp*T+9f#~Zh>cxvoX4k3+dXd z`gJtsN*_v{M%NALy()o{6cCUM9+@!{L77gN6o%-Nb}6jpP>e3Dv0lR^Lk^1`KJ@dw z_TEe>r7ueBq8wvVMX)%P5+;fGfXxgsu3_DM#PFzb8QO$B^J zs~s$0`|1=hkseNN@>QJ~)M>?G_MMi$>he7DcH?_qrrDnD;nmTLzKhp|lHPS0hVJkP zn-w)I!>1l6>kOi|SD}r!H=fEZhU7<84kYxH`~gFIVJX6{3OdNG2}T!d{n`Thj;!A^ zz$ZT*b@h3qdu*Z;i~5v{jMcS0A)N8JI3zea`!cOQQvj;MfjqD$95<@arbK8B-k~(l zcwOSRrJi}Ze+u3=wpniSnUj=Br}lSWT>KnN@rhMeaMpSDpxy~K5ZaR7qTWm~5_QdJ zkwLv)Uqx!%zj<=mHHP0W0>x{%z z0}*82*p9RHi*P^pY>nb`onpNP`e#62pCmo~Nf9$d9K7wDRo=Rsk`DJfgOPnqTEg!Q z<(JxKf;f0bjBQyS47)4nM;_(*%qeC`m%*|$D>{GZRalHXB+i73np`5`o&Myz%4)Me z-JYVQqIxyhkcY|#tSMSjn&&R@RD)}adu^sic;w0F2;8R>m`{!-^nGJCE=xP|eH9bo zcJo5+)=sWQ?uuIyl(nKdEuWh%oGD4TiWwqBPxGcIQp_+3pM31Ezn&=3=Y>g2K!XNK zCP+~Ru!Q(1ZVDqwyw(*TXa0+-ZVa9%(Qsn6g0iTDqr+U@YP^*{+!rry0m)Ywh;Cr>mCejiqQ1skv|fYv&O@ururkmJV6BsA*Y9z?IyvTc4Q6Vf?2$BRr1)_o(OPo`a5Uv6&=-q}2v zjHvSPeO>)FkY7KPfSKtAeB%MliJ^Z^sGqhq;-Z%C&xkC;wB@_N3&|WN zLGF2sug;*~LOZe*=Cn+)Jqx3Gay*~QpVigQ^0MmH(yGua#>}-`7q_LR*P)Pd6)_NV z21*~9+N_+H`5t@q8Bm;?&lJaA)ER^)oHFa*czy7()*+YE*?SQx!T>)bA4+#kU~V5I zvr5@=voBH$b>Z+FP`%b9c3!C7wHUMVd6Hc+dgIUGym_xFmn=Gr zm{T^fJUctuMWA&LvrISmT=$zm-1#*c&dVj(Hs_$QjXdFo_j)fIZ=$DH|MXZDfwM*O zQ;M);VW+f>C((>5^!evE4b`4eh0X#Ewjx)h;+0!g{je?LWkUTITORMM@(r(ZIMntw z@@gY@^bB`25U+_pq#K=UioRJfARh89g=U{7a>9;by>3%2w~)HMpA?$;&{MAUz7pwdj`^E{ajX}-few3vCr&2hL-6AYeaNOsr);kyf$$1p?@U*i(S-HU!vCe0w z{+M(~E^VwwT@@RLl1IyNtzI!lp4<*W_g-a66$0rMDK&^m?*6e>rgpp@JztSdb~O58 z5r}9(iga4*(vL}G_#&Z0fdFJXr7IQ z*4&$9fvP=vi(#bRcP}bz2%zK1fWvRZA(%yNjd{IDPRSHW!8vQqECRBbsIEY-u-v-w zQeBnM28EqyIXQnJxkst&`#S&2C{%;l(wBQu!d@?DduzDB*$F^O#zz*8axLvdeZKBT zT{$&cJLWG}^(WQb=a*BKS;nzDP*9J3qRN$r+YI^04`OAo;Mjcy2h;lk$jr zD`5t(z1qB-lpc?0bw2yS+5<6rx|Jj{ZQ=`kzvUtjfqS&DJW#QB%mfGTr+M96kZg=Y zW6&3rmUtY$<#M=u&2_Yk@a*FesD^Y(U>74Sg0+OL_DsC(BP^W)n$Zpqo(b+c^G&d) zzm*fl5g`}+s-seC8$lsrN)ctxGhT8lt~a{>I5Q}?Vbn9D+V+L{!K*gGiI8jfHll%- zK?EwfY@COTs2f|pp*i>n62u*0Ub|2v!%Qslrc`}Z%G=xyOV!Ie@2G>Ow*4wm9W-0* z&1_LXFz+9X&E7SV3L>JOi~5Y%@BfgfI0Bi%w)G^OXTgo#C{n#q8^(!1J!>QxLGnhN zGR5B?1&i~Huul=_qbh!(j_55^X6$*7Ofr!B3x;6Vp(13FsTZ?$#Pwq46Lju)1iRfkR+quKst^$XAY|BHoAKPzv+}95kJP3GV5f z#hw@<6*31c*O6)?+rOb8)#$>V@T{fSYLmE3bOMnJuMKEsI6YV7NuJGdmU364Y|YOA zGoc`S0~)M-x84c!E1i1^a%t2Dlx=2E|B8e+U;dXHeutj{$GhBOxx{Y0SB=ijFICxrnLtL+4El==sMxdWaF4%k#mU8R4G246TrUlmKLboqahclj(u~P zG3Bt6^rO&I)Z$pi+x;N>C+oz90`mSCvqrXQxChBJ_D9r{=14!!<#gXGIz-eL*L@Mc z>9_;jLAl(49qw-tmvfWzc)DUYBKAW_^M04FhRW%BO;SZNxL?4oI`))GNxAG3K6y42 zxwmc%ck~YDy81GndMO>jBbKkbW96*ROuLTaZ*%^P3jy&TSBb^ifR;%-AP(dtRHu$X zTLZ*pRvyAGA4lCopdbJd-ir-UeBQqyXfKyXR!cM%SNGz_tM7@7VvZ&um!P7v9Cm&W zI`(mpTTjHRi>2qsKwTCVkfe!alR$XZd-a94JL3n%6-xy{>YS>n8A1q5|Y976O z?}yX!K$<3Nvcat7qV+!FlI;iFj+fk#Ms9(n77aeH&vS!H&!g^t#wn0}Rrb#QA>|dI z6pjc7I0*94=$SPN3`L}$PX>ih!u@0uE3~pX2nfDwIlK`aVj^aVfv!G!{yGC%pyW3J z^&I7y!Er?Zd`WfaYa6DouZXV$booLtv{l!%wyKyQ5BT~MdFQOZ8ej!A!)=o<*z25= z*Ve2AE7hF!Z8TFQ+U2~6BE<5oU}>Eu16Rb=mS$FzfTDc)K4-7ytH;(g>9{YWk!Z4k zIP$qRluEnG+D-&XQt*d>v(EWf``w^%QOs#qy+!j-8 zhid~XN0;AY$hfY(sXE)tUFyWsstPMmGi!IiHc)LS(W{aij9ggFQm0#Ei&7*pM}Al! z<9mCJv+?EGk1$P@W1)}&g=$J?E8gLPzVbEdd(0pT0j~@T&StYc5#j>s0zokQS6I*G zP!P8cd8mgoNpJ6EnkxW@DBcmLIv$pz%i8RsoQexB-R^fZ>6f5zw&MOoLc;p`3}IG# zbKRdYPhKKh2%$+uD|pnsLQuN4LKVwE{I{g%mMcLr-!dZ;UW}5*k(G$RMj^qc@_4&DTri(fXNohNJfSTG>1JQ6d*?|*nevB&Ka61_s!D#HJYx3j&AVyHN~^Slly}y zQ%5JTBgG#Dc2?>o3_EY9F@?6DnjZ62K;6W8NaVPL=5lp$_Zxx>o$K*HMs*U$hG9qd4lAi8zmT)T*U?R~CR!jB0NEaIc06kb@LJp|cXs!+L36k^lDk#tISKA~j}N4974CXhQSefpJ%#GSZ`Vm2?3@J;q4!ytUOk=W7GyM%jSvbg(ue4)Z5Q6)j8i zhM{wmR&#K8T+(={2wx438o5807kjhmiGWRLqv9c~mm!wB@41zo8R7&ELU!+^K|s3t zzHXhDW={(|0(~YGs|z%F!>z%pAIt9q>opbD$a$ImnDB%eM+IC26^2%)j&DIR78R4Y zxL87W5Dm7C+EHG<-QCGKj2~e0mM=7hK3t5L2>_uQa#K{=pS{k|@;UfQ2LK-yXpN*L zRs6y%h3-As)5Qwfkx)zVH$Mrh%UfX9mqEc9!8pIw5?>ZZV;Oo!sJ4SfX={mT2;c7z z85Mi6cy$qKoU8smbCcZAX{Vl>&inE$>mW7UyJn#7nLm79Ej)69nyBMy0qs51&+2%8 zseQP?4o7=S6Mp}}f@tBHK;=RNBOu3r73oO^Rjw~%4cwC9L`H>qE<(Jssfd$4fkm;nd4MenyU%Lm}VygGLTHmLLs&_mI5dm>( z+HN5#m^+cr2!EX-Yu%ma-8YbO-N`7k>{m_>bl!$$a8Lt5vKjITqve4uho)t(a*A08 zp(z+JU8pl}PES9GjGq4X%n8yO{B& zbYI>*0zABumrIU^T9B8@NAw@;6Oj10kz3CVaK>8953Fz7@~Zsxt*>M|y#(g3DpIQh zyl(>E zA%lg!!0}a8C{BlALfKp3bYF7^kQ}3{qk58>A9n}Pdoh>8ks>btJ zOiT0FOj~PNWWMW8k{b0PzZ38b2|=5#2k97#S!j@hr31mePn=^zPqEBCV-zi8o7qZfQln}|z^ zAV@+>RdNXI;R`rF1+&NbkM9?9f9t$zV^F*zwE|gFE-p3|M*wVcez6bJ_soh^w{#t6 zMM~(x_j~n`X7B}OtEk23S5-7Eg4U|d(Nbi|+JPTQ^UVl+)%Qo{@nb*vqvDLXoDNFc z=;k!c*s!##rdih7iJs-22&?4h?X>Oqn+u`&yK4f9!~z=@=Z#jW(!df%$vbr#g%-E9 z=_RuX;wvU-b#u!eM!nqc@Wlx+pw!V79lsD%Y`}kg)ZFRz=zNd#&b$Ks?z+H7W^5B6 zx0LF5S00_6NAq|y-UDOa?FFD}980Ln-gwH{-Jii%EgP0StY_Vu3PD8bK;z@lx*5*z z{>X>DhbD#c*|pq&i6Sp%R0XkVR`$)piu@u7(yb zBaF0jE4DhP+=D#zb+3hs9hOnbZDw3#az%UD$%6#XFwEeAXH%X(r&|&AcLXcTt_K3r zBZ0{Jhyt4uVC$LwZ3~@o7SH|yf{4~{eTvliuu*%L`+E#;deKzvi(Aj#fn(L;>IiTt zGqq1T!aRV0nG}q81i;09AOSMfS-m3X^h}`nNQ^PteQ+c+MmK!VBZ9TX++Nofhg#sz@GPfPNqE446}o0b_OJ~j$;(V)D0 zRq0!;2Uxyf9I^+k!i7$ghOA0`oFNxZJE-D#VX;679c!q|Gx(+y#@Qr@ z-%DvM@W&SuJe9Hce)}XlsY)y;TeSeB?!A={+fNL<9J8XzK-# zLRc|Now;xG>1j$oI0YZfKCQa;J%*tZqN#wDw$e|`%H4D95-s}iFxliMHwQ!8|b~vUB_;iyh%bj3~91cHKy~Q#cM~4cu z?sb8PaGa^0*MFGb5p7+dMC~geK43=Ux|%{6HZgXY~2O^t>-Ne2eyJq<}7L z2lnzP2ih;ew6`@__jY60a%;1~@ip^I`UHlB>*LLu9^1LV5Pjg;jC`*wo81LZ zwoN~-%1s|_-)2Mp;^Ovmq}IH5JLB28m9{g(DLCfB;p*4xe2`#A9q7oEv(tpk?E>Me z&+vE=uNvP4pOK^~OO>5Xy(I;Zkh1R?+IR$sn*lQ7(QO2!;P(_Gbx>G3i(Si6&P}mK z*X->Ow9Nz3b>OqoLs#v|>C-Y@eb?7wY~Sq15lFxc1-?q?{s*5>9wSzb6>y`N!#j0JBr`52G`UMo>UTu9*$v-u zzuK@6ttmJGo5;tbt}S;2U+pFs5(Av8I} z4?2_78fN??eTFKj1Vz}H%Wb&uRIY*CNWebaSRcFLAv|PK9kK|l2lPbe)`YJi1&J7l zw8(}X^Wl@c*!7b;Xo0}q79DXOrFtee%*Gp>lYbK$Fphh~Vb-xtTH;==%hs z0?9mors|VGzJRePAz*eoS%x>dL3uENbF(*Ql_}Y8sh};k+(^P{nG#g%yLAyQL(%Qj z5+tQT=US{&hSKVO{Oo;D_$K<=wGO*o*+55=2J8CGQUbNtRjt;TIgZJdA|=J^T7wVG zw&?*<0b9PGR-YQa_l~VH0)-jb=!(7wCHSBMBAY3zl|pQ~@kUAX#-6YeGLnA(X~g|K z^awD~A8^^aOFZoOz1B--b3fy(rF4|Fp^fl6{`gAVwNXFtGGctFv~(@VnPB}h?v?hA z5X8OT!TU|bdgn`$giU@8Sk%r}_#Rs=s}f`Q(eCzC#q=R}ru*X#k8{MC_gi>p5Hb%6 z)k5_bdQ6&M8)s7QuaEpNGHIA+e#EudF0>OVd}Ce&lLL~PleT^7_106eMv?r*hEXh@ z>J}MJ?1H4V3oKf-le4|ds$LU9Zx;)MIqF$5`Z)?n9Oi=7oA5;iwKlFNJ>1%TbpLgL zF6uhq%SaV1us0h>Fj}jUDh-B9ZSd;xLi^^>mC5&aX6o&{wiV#S9S9&rs^s(y zoo-1Te@?ikoMUal$-qZJZ|_Xr$pGpU@P+UAa@g&PJ4KF@hF)Bw%^`$rG>wi49Qbr? z-taSqlk&uPT^v3yly*I-=m2yPj8A+qxyDvj%iBJ067xmh9%?_={b~dQ zRgQS?iZB-+O=dUqyp>+IME>=I{g~h5W`#x_Fc+J_)OY)#e}V6OXEg|HU27p+etltO z^8|o1iCXJWBP%}#@FyXqPTBaAebmSBU;}HaVVOy!X~tD;x!dRIjcO>2%{fV;+thZanIp%QttadQ%wk zC`bM4I9$o3MywEB(K3)iWY*^hT3)U$dL=bhOaQut?=dC{dirgTY{neH29w2hnsv?+ z>pXrGkCC8td`o*rP`f3X9X)F%jiuDo9pZB^wd5(keuT0x>2LbE#VYp2@p}97ctP z9t-1Gl>jc~`ZRob?}HL}d(&(6EE6;1ker|;w(3hiX|NI1N;rJ|C45u~rpcyx_+n%? z-T#lI`|tR!`x?OE#(`jYi!n+7K(plzEO$b4#EKBo0C3_mwG(he7yDrOkqWD!OYv&7 zl3v~hk>z8JdF;-o4Lo_zp)87dgSb&i9iL%fVCP8nOP7hdk{=OpMh56ij1P0P4;Byt zndhUn5|canGD!GzEJph+g+*Vcu)}7paUCIpal?h)pZTMI0j>At0gBSxb!ye{rLBR- z4=g>aO09@@w^9b5+4F)F(x6LPkH!4HJ#5tp^}Lxjnzm8DwVR*+rWefcBobW8Ko*!# z^SNdqG3@9*;vBx^Sh3;SYuI0oc>jLz z5f`5uu898%I_YPO3#7Q@hjg%zm0ttj!Jq^cryI=EcsXg^5PC)q11iYeISI2=t z8+jLkb}$8{2o309{%M;3j9cGLJBkm8N#S*Ul=}?H1>h5>$B(}4WQqwP0nu4c+lWtv zpATMx7ig&4XuS2$GLe4u6)`{6N5HsaWK6b?k#PYG9^W%BFHU43mDV|s+fK9e)Y~D> zv$m0%f@6Q0J)yok+#w!-JN%0h`0HaW@T~+hL}V`sU?uFx%yzRQ(Q8RT{;Q!aFPa6v z${M&TK2W`BR&Q0jt%YO%1vm0L3;({zK<{8+N@2^b&@hN&V)3Od!OS3Rpoj@6udOuPuA-;g(OM&AbXP~@ zmkR?{d?*GIx?07IX4Mry$H0gNkR1m{%Vu3^UVXJT`0wvF={)a17=Pa$jMQ3Vx9||D zmDg_mlZdEs-2X+}cZNl^WYIQBk_d_f$ta?NfRc00L6n?95hUlF5d=gs5+x`(XBryl zrU3=XIW|!w=h#5g@D4L`XYReD^M1VV{o(5m=sIP zO3JJ+bB#$mPrOh66VsHz!{7J5pW@_)eeA(_YwlS#9}_>n4ki}X9gz10Kx9{AFalg> z@mo9J3wSjS2?$Xa*iL-(MTkpr4_8`o2^k;Jk^x0e3;wUJ(*%CdJ4J29%AYO;%cEXt zGg+U(Ew(ZzF$EpdAh!uT;s9`|svy-gIRR4~sMYv-O`t5L-@aJUAi^F66|yd9PV41q`Gp33cA zABz0)8D%FA|oR;J@~kp=SqK_(Fgl#;ezWf-4JtWuMZm|W;MUvi#DMzhRG zVe|ud*v-?9Fn#$z4}2Yra$l03T|T3aKBT`jcc2EV2|cFJwPt|Cvh{K)M4dqk7(HQ$ zhx6Ysk2PUhBoQ-aN97dsF57=fH2-xzi(?33u>SmZiNJ+j_xDVF4)?wSmG4w8WxRkh z!{JE}uzve=3^oxZ(^CIq?EdgTxE!z!qrL|&+x-tK{kxB|99Pi! z=%>h--%b8M+68diyElQi7j^m!`7IIR-|Yf$cjVRbbz#~g@;_$vzum+Kh%PFkX)Lyx z|A#sLSWf2AfTKe%DV>S`l+yU!N{&H)g>=7%o7%XBz>JNJg%QD_zX7uUqxbjbS61Zk z37*5duLkNAV|n`&9N@eAp;`aZoM98Of`iQXovC(dF<5tjp$=`n{?>PeWS}NfYR;k-xt`f*!??%vjN%Nr%0w23X$6%LJl- zyMo2<=DDo2bh6mO!ou}HPpdzy^2Z|kpD_T&3$@Glu?Bg}8`wt&}*TAeMnCN(RZM&@h z>LpU7dTEdDV_5eYYg~i?(CtmJVTFvIzhYrsVo6h~d9n;`m<-CecR@YkA+3w_=B~ zPwp#x;w>%21TSMAE0An+<1_(5NCgGG!FK8n0Rsp;B{o;@C^hB(NmDlQ;J}b%Ti|~< zzC3~`mh+!`R)dA@X9Zw+^#E2$lO4f~X=(yWU=x%@y}^dlg3V1qJQ!|EP*IkABaE0$A|iN zHjBXo22mZ9UYsLNa7D1da4Cz!RA2)*DG~I?G7Hp2^51^h@hTLKx|bx0p?bCFtjUETX0O-4xU0DQX=T$i8nRW;CAew7j^54tm-xj?;ai!OQ zMnuqfj;Mzu#K4H`iGS$O2M9D+y>fFyWws9{0f2%=nVJF+doO1bOxynQRRTW(BajB@ z4sYa(?_Zgb?oHXde@3*P^`umwojG^$shaJFz?FAgYONac?Q^>g-YdXNj>;$5M0R76 z2le`OlDS6dvQC$1WcR=V){n#4e(ll(`nsJM5$|JyMD>b+AkMSl1@@!`eDh=KQvfY> zg}D>h>&L%BTz&p5u3KrfXNUp-$xC0B2>1lD})YdD>73E%Ci zWFF_T^K8aFrTfMo0Sx?|2dpsumzeQKG*HjQyc(OC$1e$i8nu^)!yNmQ$&Q@X$0L+T z=BG_%Mo?x=*71*bs`KQdXeQO)O&=Ck|12)&Rq~JyR{q5MVtvf=AsY8ER*ue>Ujcjx zK>ImuzT^4gnP&>`!qJ>QKTVQ06e7#m-MfN}o;aV;2zVc-)$B}61%bmq{mrcy_O7M? z>`{_DhAO}i+k7wg4j~}RDfexKTY4w#LXJ3~I}7{$bZP9`cBhYsVl)GnZPxsHox z_>&RXP(BzSK^MaGf90O&3VEZBZ3}m|<=$?T>LZ`2{rE=lV>4#Le&S$U)N-z@`muqq zoTMb@_nJpsOZ!XRLwSbX(uSk1L>jFAIx2a+$q$h;?)F*iLX3pY;O6%?Ed=d`QDiJi z9nZFGI()u`_nR%Aar`_i9+R7d2&i&a&%*qrjcO_QdymetX`|zMa z_eP>V>>L61U$k~Sn%Y}b<$T$CJLRc!oGn64|GDSt{L8hGFU6jexJd4ZTI;cmJvR2q zDl?TBPi1?fTBpeK-L_~>ae7L8pg8%4S?5-RL(8ocp*MjL?T_qetD3DAsQYpRpk1Ho zpA!10Y9?MK!)M>oaI1{3E~u`H(r69$HJzVZ>g2BtdBn!1r~p z0M3>p1+dpWx6Lw!7R#HDQ_`O z?=K5qEctpi`rxchL+gf-oS-PuN5;xPD1CJxr4zK{$9YA*n*-w4k(zBWJI5x2-;BLW z=w=khhAQtK)sKynJ(z5oeEahYjpY&|{slb@wAl!)Q+zZ!9}brPIyww4 zKVtJQzx|z#=>f+(rH+Jr8)M?{F;eGPTenu2_+J8OmT0Qe6r0mC{R76+-;!Of$q*}T z3G(E^gWUZVq{6uT0ag-_$^=+oDKS4{Apmqx#V9UGgob?X*U zm(`Imt-*%B(_Fy+MRS?{6U{}3;cclv^-4EK^Eu0S%^6AFH>IY}2U}W60RaUMh@xl& ziWu8zP8X44Op^<1?Dw(KIi*51j+B_~P+J5~+IJ?`^|6|* zmG`6%a$jJrjOHA(eZCoYj{!{Iw+w=LEW}073Q4%3&x>DoXJ}G!7qCiQBj#hvU8H*a zKo&$pN5>u*SScnPtAkM?v=QE&`{@?OuC}pVVxhXZJOJWbs_dXopdPpXJ_|)L`Gy=a zGqu58E1zL~YtQ74$ZUvFtbwVNP& z^s$ibkywu~_rXqcey?wtc;NXEZ!G+d`uf?T@7Prym|S?Y@Rt7i{jfz3FK=T9h6# zozzqHqQ%`1QG9nqr^yDEGfqPL#dbrBwr4!3R)y;r84}`vC-@=|S%1x)5(vf_kb%O) ztB^bF6CCx~tv5BTEp7_B?BX4qiCs>cUWfq&`QjL*LM#B!=5$}1nDL>Pfa0qZYYaUX zJoD*?dL71R`d@r&Vh12Sx5`@Vlgs!-6TSiT7S$;upVoSXTZM>Ng*s}}*023N!rzXu z7RGA|xt5l+6*~d;mBJLar7|e^z$QFIz$1X+34BgNYOGMdyN6=tUmS>^1D{32o3BU^ zInwV}RGz>9V3+>t#nH0;>(hNrFv}i!FCw+58S0Jv6nd*@{6q&>c3G~d3CVM(tvH9a z$oRZos?J4KVRPPp(Me+9|Dcn|8kLs0@~#{vvgxO9??kLsW0Mt5l(QN8-&-4@>{v+O zx1Xfk75}!Ga-b~Z#Y}Y0YE@x&iMB8~BSsO-@0mX6gdD8o%Js8Had2G%HLHvlhbo=* z4@?5llpXj1A-?&_-?)mDb_P*5ua$)YD;_?b7vxLJ zJy`Uj-KBU0luVDgKfO`hZ)DsU;v=&?dQ@vM+9S*mgqFkESXR;h3DAbjjj62OygNUG z6J9&UCkA7$iEQsK+%xyxX}-)5Xa`_CUBbdnx=AUEv)(qvUtvV_Pbaj#K;3$;=>n`4 zpbDRg{wxKVzsSyTuF?aQR9+XaX-BbCPS4cMi!FDNY;=$3+~=1f>RaI`PCD+v4+fl; zsLTDGCN?s$deS`Rd{*9z{Pe~g|FWc6Q;!vHYzfIe9>V=N|HN(jVScxW>v~ND$|h?QQ8(u! z=6$@mEZEBP7Pa^HTZbRQmQd-|=;~JBq;9mx+Ra5wj`9nkLheJ~{o`~(F@?1*O z-|(6R!(#8Xhc(Y?>(yDZN3nf&-1;#a=FLD?)0N4QnX=CiBszU_{D4o3-!J}es~u@z zeF%Izq*;dy%Ou0;_AU_+Rl|S;V3H{Fp9ms>!~YMa%;xvojmJYfr<)jev zgUJVm-DJ9ua@q7fe3xEjPj&n7Pe1m zj5tQSwHP!N7D)1j@yt5pk5g^mYM>VEKs28wgZI>x z8?`hHj<*oQ*t`}p;U@Xh`er?Xa@Q|4NMutXygbv_$4IK{u9Y{VkHtJUE9JPK(^&9! z69hOfH>nn5h;elnYSn`A<8OW@V>?c>J=kLP@wTqjAIx&sI~JUEnyTGm@<)vgF68f(7QMrrOU)YhyMd`80uKcpb8 z8;ST(`hoRr)tc~8U7QNdJ6kLu*%RK^tKtU%plgyZg8>4@As2>FQTJf@7{L?k(E|HE zr5d)7Q##vWt9NZteNQz(_BzOSH5S9lMnfbh_fpUf!a6{CVDXcXJG;OMl5uSS_Q7R! zLMwa?i=d-+#C-j5$BJaeHnDNMY8N;bRzLUNXep8FyU!?nIhCMc}3WCGI!y8z&B@ezm3 z*N+U6H?0llCS9DFv|$ndOx!l~-hk+S#g2$_26bp)(0od|CvTHbRBv26a6rX)@I=Jl z!Kc(pHO;xe$v)SaD>OLxdlQ7P7JbB#CwUvm)-hPV!$4$bpZb|y4q(TmO$A~EE{pPO z&!I|1K>=1)*lmO>9I+hDCtVtccT3uM-uY5-+5~7_P;eha*Nq(5ZJxYnr$x3voR{T_ zL1l+69RTcYFwuMW^TJS_v8t!e+$Hqdp@&X>+U(^kf&d|ao-tKXHzrPlj9!qEOBtX< z-n>3tXSZ=m0|4#5x_kp4ZV2gMjUtvAX$_+5VGil0^T_wWB2{b})}+5+OIp^}<2b)? zx5@o5zfA=sEFH~P_OkdL7`Sa0Z!Qn%LvB>PO3n2CC(R{>mUxS195>yeY(7w>0?Gad z7U1FZJ+VulNSBSVP8TrTlm8EPPElB?mWQ;()z1SP4BMb$Ji$ zPaSWX3*KLX&7CPf=qel8tmCkw?VaHusxwNfr!HNZ8Mp+51C(q{y z0*w72IfdM91s9IA!%+xFyB>hmeN*vXn(T9Ie{AD|CuQoaMMX~_nDaN=#DF?PJC_9}vJP1z< zWKccUu}tN^4SAC*+Z%046mT;~Q=LO&k$!ad>>#07g={N`Y9xUT8KQwM$cv!lkq%n( zvBQN|dJ0T+kb@A~1G4W*2z!Fa-W*=MsB@D_DZ^lF6}&!OUbOCuOCCj>{`s3wA689I ze*)`@VQ6!i5eLs9BZl?1-s9pZQGRvf9o%x5URQ8nzKfqZ>q#4CDxY=s7j)<{jRP6z z-X_stmm%xzZ>UBK_$O`F7wJHOpLyHo&F}jj33qA@Mvx!&rq+O6<>ci-X*y*S#4gX_ z{W*Pl=tvaz+fh$FOA+sFmxK8m?Frr5W}`);`_*n_;yA9$$|<>VMr})TP<0uxXN^Sj z3)h9YgEJXxkCHV?o*Rj(nO?_+AJhy9nl48?^hqq%b4=F`LR_G|Q*g1;h-%Osp|rKN z2cROz*2?V=d)IU+RPDHNC6sLD_HOkNlwc>>blZb2`;!!*$ab~4YQke(EKR6i0>{ELjr8UU~lqfxxY=jgn(ia{;~y*F#sc;(HZqjzd zdP@Lx)C18+|xs6h*_MLC0?JWD3S`0vs6Q3qQN^rt(@pzQUB9juE5_-ELuF z2`b&|;Zjv_w_SM8Kx(=RU)Y~c>!_^qvm-4{}bNw@WZUX3SP7r&?BMjj@Jsmt~`-)i7xK5HA^4m25pi z?Td=kLP44D?-%TFp6KoTz`(F(0A0)n5r7$RiRpZvR~D7B91ncCCzy0}>(mu#ANQ0g z+w#Nt%iQp1(bbL4pnC>v`o~1oC1rYK{?byV5mSQGR2Ilo^`Q1ZJ(&#~et@e}F2Q=N zT3hSvA)O5AGc5&O?089dcsGM9fb&xgen;&{wKqNK=J5`nydu<~YmFz=wa$K6S8=0_ zvB0P=>kBZW{87E``(;MNZK08IkOT8%6_+|pO6U41+#knAQFPmVn%2#B#rt>2x{epa z!Rzfok7UB7%kwTXwQLvp7wF9BF{g|+I^geZg{;O23bAk9i4 zkF4c}NwMJQAhzc6OeNGhaVlN?#mZ4wtd#P`MKCs;%Uq>WUz&OZkSmHt&bPz_6CG#V+99%oW8?AhUHoGIoXyE(FM)bj}q@UOV9ms#p9nfe`V zdiA%D;EciD0EWqwFn6G7lpU6bLzmxt)5AisO9y(%#=}<)Xf1hLdeGtuYgBf%x41#S zaX#Nozu3P9vEnq?uK>Ca>BXyB;8HxGKS_;&>GV^i`ibXYR9MYI_o*bm2NiksiZ8N z?b8Da7r!0=6J!*`!m44gHC3yR;4OcunG)$TtK4>r=;k8iMYY<@AZo76`4Hn0DOb;Wy8C>05;d0%6jmOepDinL+Fhs|Y+pUWH}oQMKCEQK`RV3k%5-W?YOwF`thkEXic+0n0k zRqIo`wqfB6LWDv+A_1hUp4hgvztuZi`qKT466X)Eo@sV0*!Ua1^WRm?KEUc2=^CHB z0CtDPqg|A8`4U+%d5U$VW83mjp>w0f_${N*b<<$w0-J9Y!~uKuHF~N^fTpm37xx$d zQC2w5*4*vj2H6dRb5pv(FM{&ao?&fQ3ldx5rhlMldkXxaA-n0|8N@;&la)g*I(_Pk z$$5RJd6bQ{$&Hsi7&Pk7Ej17OK8f9HUspvP>6FXK2@00J1D*<&z!ANK! z*|LSNT`yns={Ocvwx47F@%^)T(7JJ8Gz< zQb<3mRYn+U?6|It7_NvAg}H;$?#bOKRl76_7cm~G>Eu07vbLC%!7_O>9#f5WC9~KD zZowK{*B+Jf@PC6b2Fn%eXwZnBS-i~8hxme;$XATyy?~;*9rr(gt3&|CHNJn)p&(t( z0hQ@|!(0Ke2e;jjc(`b2cqet$OLUSR21LzkwW(Muc?&44;6GR<7#RXj{xGRKDv}sY z0x{mfxK*%`R%enoiHp6FU-QkSP4-A-!{Z9t&o*%Iv-2L1<*nGt2c`u{S{tp93lG^P z9_T5sB6z4=`X#&bs;N+=@(!#9>~@zoF3FTm$=okmT+K#>KCisL3>xcF)zHIT-{_%% zPZc3iJAMNK0gb6e1K&O*7VgNVaC@fN-k1k=h^x9YDOiosJh;2=2o*C|8)uNI-Ac(B z{aml>ji2Ac5L4^EA1CkkP(&@TfS%pZ4({>wCjJYK$aZ(~Hk=^fX$RLe zmPiUVBNpl-K{zBR)Px3?rJA1I;Cszr`ypO(BdRbz^NCpgu0v;oEA`<*h}+pgcEIdG z+w1ba!4KoFZXlB}O&;ebisl@Ss7K2Q(Vc|)f+D<4hMC!x$V!{a^-8NOL!sJ;R8Gub4r$1!Muqb9_~+H?smdBGcsQU6+=FqE z*Lp`{7|!TxTWU&LjdS=zM#=SJ+0gtGP*Kc=rRJu=(m((v))&mTVl_!J0igpo5-e6~ zUXcO^7@%08k{(*fVgAYR56YHagVK7Jw7N-v5#*Zv!)`f3!2E_~@RtejkbRS#b#s&5 zmaOd?*hCr!84HYcv`9O4&h3&ND38VSMW`?K{Pdu^ztQi#JIE*cS`Zp_Jq`=^Vl1)i z<`kx&bQjc6OZ05DkEZo_CAJ!!Ubs+PoY;Pq?ny_wd@;$;Qhpx3LEwx{!K(Fj%`zNR zufB4u*7Wt@?E&rh8ly-%US!qlzQ_HmZN#-M&!%i9v-GA-KPx&#iW&s+_DXo&Aot6u z@F_9(FlnKR!gvA`HQRU5%_Ua+I^srKF5!Iu)D#(kz(1@Sl)WIn{h5l2?D+U#Q}7zx zf3*?~@CZslP=L#NTy zyhU$5DNT%uLaZ<%w+ySjpk8I%-5gpa1rXV4vwo_@rp1D=OhM0(t5hfy{7s|mRg}}l z?Akx(wJ<2a`*Zc_Dxz+yq-9+yZ)rcGkn4!!H=$9aR_PN)^Ru`%ugfah;-g;g%UCdaN$hp|6z#ED6VoV@HYk7QxhFHSH z&sbPGu*hS2ZoK@mRk*@Mb|vh_SOD0h8(C3LtXdZI|Ld2eX zt!6La&R6iS?aGD37YwtQ8RQ^SIlGO}{DrzQ1?g3l_f52nC(_e%V(?&CV9Od4!$Ygt zsS0ZCBUO!<75;xi-cSDmc`ty-$6H4{cF)h692FdNb2^_;V8;^CsASWr(0OKM@*cjW zQc9;++=3-455}DLuPw6Q-o&Z0pYyXN@-;d?^ha8f(JZgmmh%F49u>;zoKnSs#K{ED zG+w-#l_>$jBH0r}soa~C&!qoe*>Yt$Z3WMaH6du(la(hP`N>g`t7qXcL&ZXM4G^DbtO3X{G z_D>e0r@(Aau}peyhHJr}64jjgZ5?TI??M?C+n>c4*XmJeI*eNTlw4-K#>CYiBxj@Y z71hvQp=!>o!Q?L&^Jy-+J{sm zC+&wMAAlrT2HovlNnkVRbbdZV6cGQ$x;}A)CE&Qmg5$%f>EPLM&!n@tc3N+GnjUgc zAKWN=)IfD+9y8@?r3e&3+fAJL;aAT%pudtib1+VKpyx#<{lLnoomnm09dvnT+9> zO4$-;Ht$A4;NBnMlOE zf{;t&VB=KYh2jqh1&;{z{}kC^w)t+ZFu8fL?6)7w^rk=Mv~O|=cHYkw^oQEZ&j1jH z!;R0*3fNBK0U&1-UD)}6%|kL@fYTz(4Kv()R-_lK*cbt-I`?A8G|T*l$2BkYd$%dat)dl z<5JHhO|ZOo5H&3FkA{BnBk=J}eyV$%uVms5fo)A%Mh4JS<>vkf;#aB>c!VjyDh^7k zzA&H#{teJnJvs4s9~qgD;=i2mfgq&X-Zs&~`PULXB;xQ(9N5HTr`6X@O%9`$fE4S; z-CYMvlgmtAudo1BKo3f^a_=toxxP4-3DWHI5yz24F`@jDl5|lbQ7mTc#f-n#Z$)Nf z1Tf{4mv*YQ6sp|n4_Cjk+pi2N zaTk!6Vj}H*@;mqb;{_RZue9F$qwX;NvYkJ*jSXm@I>ab*xBb@4|LSlcoPq&#<6OWz z_)p*dWk*Sv0GE{D9K25YyBGgsL@|MJ;@@3KzIpdIFZ{=&#AAS&iQ6g7)iX~nuc%01 z2a^4z3e=U^OmHM6C1b=vfuO4n@8X+#w6M+7ov&x6@8Aaqp-Q34S&PJ8%Y2jo9KF^}g1k@-2$ z>EXHEHGJ#NowXv&Jj`To>_9jv(Ca1vGikgqQjqnLy|Qw|p`MYvpeBCoxyFT)`!D?y zXjkHq1Gnt!pIuCz(ES(h!^5jI;eAGM3H;X2H}Ooa1}wuMguDsR-xlf?%M|t16J%q( z+h!Gv&4G7M?k{8Yj{*DVkC>>;`<*dXq4(`)n;sIZUH@`ct+5@Wfv>yGswqZeFGkdcFOZL^k`1EJG-E69AuY zVpM=l#Yv_2EG0oNIb-F@O?0;mL?d13f7Mjr=Uafei`L95Bpw4(<7<5X0G2i&u6`0( z9$#>Nw8uN3I4_F43DAQ&x_{XbaRyv$yZ~oVy3*YkEZ~&{0{ZUX{BDI|k7a`H&RA}Q zS5RTYVH*#q!_#bt5tWL`e4li%xs0wW5b`54Yj#O=#}dH;li?g zw0pPN{3j_U7M5rqetWl&Glym6lBSW0l#eW$ir0wNGQW)bRhd+t*E=PY7+=<{dUk2o zE6X;CFwHohSb<;ft#FzjdOR}9ss}^^L}8c;Cx2i8W;RX`7+VO}I2G!;`UcJIs;d3I zf|nO#Drf(W%Kl`w`4zw}exedC#DU6yqx3P!KMM*F!#^ckhYg;kS^^%!TR81o1nCA>pjR;S_d*$7;NUsYhiuKI*6O;apH(MoX_8{TU zmkg(;`8=FvQ`nC*3QWe_cq6MbRY6Sy!S#zBs)-rUMx|WEy4MAl9DLSnjc!|R&~^l9 zLc4mJ4iruEbjkyL4+Z3M(WqlWKt$NC&cJyW`@k<;fcBm(qOOa_H-pzKkLC%|ET4U= zx};y7StSVo#_Ihbz4dzkr{hq;OZBz!<~jqQ~;icBN`(`U;hFKC-d>Ff@$xFweiIktnxy%P#dA<9^AP=-Lb%^@MUqI*3}IsX9N6rtM{AZ-zFSH*2JXQsOt3~W(p6|6jGx+dHu+{pOawY*7^io4{ElvqBxVVlo$2Z}U9jM?6zrhXF?!&+YSFkSFc z`(0gc+9Fzje#$H{nnv_4;}=G?yv^MG5p`Ahgd+DTbqFqe#@i)+FuSAkOHk<28Fg7a zudUv9oNvlrJ70W{miV$vSEp;Ur+wYYyuac)i^Z)C&m|~vK&9IwsMowScZ|?xM@5;r zXHvxS2sbwMw5{xD^01JWS!}pv${Id0rD!6BYc{^t+CMh_!85(#F868nBkCpwK%Vyp z9Y_p0&BbZGZ1es@bUZG7y)hL}83!X{r{>aZvL(q(mZwwwWRoV7$-(Nr$qYydLorIud;j&7l5)5AIe|v%=+?5L-+Ei zd(xVdf6NXXc#?wb=U`HKD(R2>&yPb_A*=>3B-VL6jLINqEJ^6tHaWAAg37Ap72}*$ z9GM)2c-j3iIO8n}3J$M$M+2_drq6(Mh|z&SDj@cQ7ivR+U3TLcBy^o5BF0 z!)A-D+yCR*uz6QKezx#495VQ%XQ&g~U#DTM9L< zq3Ldub9ZG3y027WI62iWW~#?Ei0cw2>iG*j%y6oGTo_L~9uuGUi+R5ujPooz@V%J4 z>=e4!p}6;o;`_H;_C(W;=nq=MmJ}QK_vqXp-OH)#u{BDzfBYvHVXxvS zYL7MVoI)$?AU{>>{VjM}ZVOVYxH|$+jx1VXNHH(fER`@oQPDFytB12{@77D2BT8HQ z!*%w$nZ%~xT0Zk_pewaxk;8(d->t(=N7QS7<}wp)LN3lW?AOk_ijVsR?eVFcWP=eR z(ZGZTAWfY~m&jToah}g&CfmeBmpnfHZ$=y*=~M)CKZb%lklP|dFvB-O;O}90)P9*! z?<-ffFU{>C%c(y}>Q^>=msT>zr^MvsRuVi&&)ZWj)}}L5LFe(hLp~*w)&iXq6pszQ zXZUZ{yEC;$AfT27e4azxg>LSey3n%+@4MpVt`YmHAGQE`G_$n{3pj-2A0K4+DASdm zRzO!8lUW9`ndLeBUhZR&Qh_O+5{m+eOGWa>=kO>^1fQ`#>%lTxMZ(&Ho;HwcFFGFs z$*0uJlhD~=wptN5bPx%1+9>7wu>HvQq@s+B{w|O%kGC#^PGu}68T%zXT5bu3UT)WB zY9=MJr!R|+H)I~geaq~WI1uek;>f(CPF6U#`;HsS7RqttXYh*daH4r90BW3Bii#NV zIFT3x>7YvJl$uYq_ERB+2R63WpKULJ`tnvkDJSb4pgdN z!bKyl@+{8V;bZM+2{I%^nHIioGzxIkcrtnPbHxKO_f3vaxo+wC2AQO5hI8m?W1ov$ z-wLUfQjhnq%8b|0PXJ_Tw37Inn#)Ia%CNr&KyX!TPAW`q>WlSVya4p;xV3ATx9?OKKZzA&~I-tK6`|u}^ z!hT!S$1KQG(3r2Y>*QkPqMYK|P*M)%0H7|bbh@7eT)6QxSwAm-Pjm>t-5&9!bUiPn zq2u%j{@AoCnZj=wQS7A|M22MPC-S$iN{FHYu-2$z5nG+YFKWK(Wb4@QGt?Vp`E0W4 z52CuSkjJBWjH%vBl@~Ur#H=#NAGV{*W}YVt>yOULU#5k`(Dv>(BWL`hEixP2*4aJx zrMosETs9=@vrR++{bsyl!MY7hHZCxWwc!;aYJzWH({2()b88G+1Jf8vjC&kgT-Knb z2V8?m9pqb!F-95{**7jlrg(!&ylb`iFp}84&-Xeqzmt)5cULR~Z9=Zypu9Wh-#o1) zP0agp)RFX6tu-n>Pfa>o$$+)Yt#=C~ z^1ui90Z>Csy`ZiO^lV%R$7uXiZ6?45tMV*%**+|C*&ceql7frlmZG?kA#$czokZQ8 z?ygC$N(T2T2X+o^-qCRYt?q;~XshR5^92d7J4?-fN%&r?##-}aWR29uc)fXI0!BgS zu`7xqY4ajo7Fuu!r=IXRm~j`IK-ws%&y=FLk!w8SR-(sYBVJkN>rz|DgB7-qI0s^} zW#w*QWOrqDhe}1`oQ73W-NEi;97m2ysFqWb?vE2b^=~uzZ~X5FEzll3|1JX_@;%67 zb6V`>llRc6_c?44)~)*KTpb73LD4xI0N~8`hDJtnxWM&h;sce@%b?MnYGQJ3+i6KE zKFf#1$tbr_-TR-l%l+c!u*aW)N)ECT=C^vF>04=xX86Ue!A6||*zhAlkwYJmy?1l~%>!&Ct zj_&E@F`Y-cPn6kNl4))r&sd(h(GZKh0SP;5mXu7SJL#@WlY^{5`)Y0GP9F+IeM-HP zs_i04nP~tdyL(k{u>S+q3~tR5h5h06Ok1)yjmM?7VF$>wNM?pjE92sYZCZB?@MuI* z(j~|0=-ir99jgjZCkg*$G@XEX(Bo2?^Kp#}Oa5ZUQg6`tY}y)lN`sYfW5jRpT5Ln~ z26|ZsIaVn}p`PpYoY_*Qs*uyw9*D;4Mw9wZd4yAK6N|>~zvIzSo&iYa!(84FU2D>& zE%0cTiZV}5{xUXPP?RaVlb^-FG1Q?`6@Kc7j!lAq&>MFc zoyB~{HSY*IeYNoRB^pgX4#el@JBJP)ulZn_AJinKrxDiUVdvOLpnSacvTTic=sqg6{uI&_lx(07_ zOC^EKQI{E8>RguSf(=lMg`Td_t)FF)dr#KZKU|j1EWh_wXNuQ zRr2oDr}qq+{dZ;{`$3-1C9q6NpV*CjE>wOh;qm@QCt2NDMuD{`@!>+?2yxKr4zNRW z^l&aWY&Nmm?mRArSuEsN?Z(Tv)dn1v?O6KU!4L3V^ABN83i^8v>brU1q2zo-Nb{60 z=DbaYG<&G{jjMAtiExq(11rw?BM=PY5m5tUEvMbiI>P6)_uc30eG^3=x1kuKScm&z zVn+lAo-Q`aDn#7TSaA1%EOuA8bHz!|jxfMgU>L&8Fv#+v^upPmO44<6U{q_s%L>?D zlK_(P_Y1{h6&@Ye#HVAKGaidaLyM8x_q#NFt(;k&i=-D@jW#Od{9t{Q7%*n$l0No5 zII!W+fb>ewwB5^I%VrFyLGv>XkYAM+tv+)ErEmq<{==vl45Y@|5+%Ed=_B(6FAX1PWq4(kDJOGJX-!#~9iyB@V~oep zEI9iVF`-t%7OXlVwVLMs8_{B^_VgtKmj>(&e!YxuTbu%Up1D26`>O zmJ_Z)*8fRNZm1FVU@ij479Gwl=Il%T^%#JGeJ;;XN-~kOs~su>+LVh|(kA&X2_%mm ze_a~E`}y%I#{Yu7tSwl}g<8_$^bVIrELi~J zb2i5d=NzCh(;7AHq&&lF^K@OXXY5R4weCUtzDKE?S$~FquUa|V7R2SzL_@#mJsd)^ zm@npQ7DOO*T)5ZtrT|xtc*{9hO{bW^wS3C1+%1kpbH}AOkew0GpCwP>w0%1x#OpeY zR@s2=#u=`=u2$43gU*X)>U3FI3CUPI#`e~5;A_A+kxLE3ph?s zo(oVPx;UitHC{!vO>XG==V^`_`yHu-iv;99%S_ISwhHQU6&ZF81m zd)R6FZNp)a_eW-+tEj+W3%?(f4zt)F^C zbFEeQOB15(iPn>TI2an~A+Ac#hZI_jEEVH^x^G_l?p!8hqdKn(4$;f5$JO5cz&Q1jfq+HJ7F5#BzOmn(WN6d}xI?SPi*>(dswg3h-MmQs z9N)%gZqooqxI!~yirZ%#9rS^$k>MNkhcMG;&Dmk)f|R*ZJuTxE81C*oqrGBAf&AK$ zZ1Zhz&<0)A))cexaN%vYa%s^yAVV&01oL^0fIo$5seXp%O zGe2f#ty%r&E{f~o`|5;!_SyT{?_QCkG1F5mE82tDb$74m>g&?^i5*DC7})Q`%3Ado zz{FwB$G!6%56%?S2vlSJ%52J$g*>NnkC8oxV$<_Kh1v-AL;PU`xjtLWM|~&|cSnYH zlRyhKKFu%uqCq+ZI_Pv;qh{De zUVx742IJ(#`4K#io&XQZ4WAaswK8bkXGh2G?`qh~yqI9HxKfAW+H@7K4h*hfk}RIr zInB1Tynm_CiY+}Es0WVI>X7S}7kUgB@KHa3xmL<9Q%%<~L&4ZrWt#aWc%2_vUI}~D zag_Ls@~iBwu@zd)vUSaBm3Zpl>fDvd!}ghml<4~%1M|+IzFdqoqeSsbB1-ydQ?or& zrZw`lOz&RJpkg>$pEuP*_dqUg9L8_uQrEUO`|p)d;Z% zl0(#cSAB0^v$BR0P<=tf+WcR{JT~4`uNSA-LvqzWg$9>)^H_>X>D^QL#|EHZcaY zM)fr)>Ys;vi6<1t?E0z#MShM=v;1>29bEi$S)3hW+cAy08uTiiEjrb163)5ps|d5j zg<>}UKF`T#4O@$uhVj*Kl6YnW(LfN}j(C~@xIW5T6XYTv%FYHy$(M~krT4Wk#eHJW z=I;urP4Yzf1fUaPSvKW`PSxCc)l00Nuo+TO2_XFupV0zOs($avxt#>ll)O8XfX>L2 z8W)H3qrfSG(Xr>{0Toc z$3kiSn^J~>*W?h%IO5G<(KuY3rK!hg?Ojj~a_VK;P~A5||B@w#{?Ng~C-wJ>plghT z+$ZjnG89AAUi1QuqPEL%wmi*H?uvPH1J%e+m%|!C_``t76_Pt?k49BCYZZN8!yaR1 zb;$RNZBaudHu>aUOIzI)>6_(=XTv*CdG^m`Z7XP2WX$L_Gd-z+as4>29-YuLUIM$6 zCgR#Ma5=gq);=0sqKm#p3*r={Hd2FCY$Tqhv9eTCD;rM3%{Ww|lI?Pn8f&>*N=^#g zwr2-KvpHO~k>V#S+(ubQ1>RR_m z9fhGVP4u-VH{FwFUyHggzUd3KOf}4DAxe59T$>fwUuxCY(VeO3hne3bmrZJ!ih1W8 z?ixd6UQw6GUpwH_RKj+=zDu3qj_@@bpPf@F8S;bqm>7ND?ftbbbowuMo+Q7C)OAFKDVo#Gy;zg(bX)oVp z)7cbV$b09;HTXd`JVD&EKHVmPXKSXXWG0`@eP*GcM!Vvn1lA(p$a*h8+<4EMQ?IyS z#0lBf{dO{Beq>x&RFp-j&olOqztqGHJbaoD^WO+ea=^n&ot(L$ zg|h$5PtV-5+1t6}O0! z+qH4~OtJx8^Sq<#GQC#^TYHyjen)8S2SIQO{95s;U9GTxF+F2ptAtBK{naT>8rZOg4#BuEHR_^V;LuvMl{Lj|i&8Cg3^4yjODyc7C zzLa}FaN@So;e3CbbVCMwF$#Wz=l*F#7Lerl_#0G^#_!)BtY3baUZ29Kayuf;J$a4s z-xSB+e=-TK>$)0wkv%GXo>rEbjjiQu-Me@1pmo~s+vF}bX@jXu-ko0}FbVc2hcq@e zD%jZMwjS{!^we%A`&bvZXfTVs%Q`*#GDk_l#3cPiP!Kr;b5h)O7wQf2 z(tE*S6pRz&0Pd*d!prl^BGJ*8Vl%v^QeyM!(yN_yY>()lgZOiTKA`oY&{H-)xUF(j zNu`X4x(FxWXjC~)TFE*Srdzd1H&_8@;g?8!_)Ln0&|*JF5gyRbW^^p#!Si_Ti1yZS zL}1I}{=*8=%%3CQ|9a4db-)5aq|-~X45fx>6+V$x4Xj9C?T{m`QEjS(NYGzkKf}5# z+oX%-&c0e4vBmSmzgeda}`USkOzw+&RB0C)P zgyzYLw=x6G2>Q&2U$ajE698y61hcrWKuRNqhAs0xQhT-L)$N z$VEY%-(ZFTZz($83i9#w?#|Ld$#L(>2+4lj)8W0Ml~(jGsPD zM{V8d&XRvMlL_);cz^DkzrtzYcLeeQAGohEX|gmg$41Djsm0{sy6xd!kS9GGCIva& zjTZ{@@6| z@a3kd6oCl`1Z$%j#WBw4bnS|;J=6t=-I(41Skf3x8~4v!_Me8v|Kt=1@6hWchZd@U zNnm#s7Q_|4K4E)iV~SXAt1pgb$%M0ZXHNRz&7nLcpNW)zSoq|>&W6AIU1%a0_P1>}rlsqOAUL<(&*I|TIQ5vLy=rha zeh??6-^Fll*^CaUAh6qmJ&S6Z2iVG4o{cs}vdgiu63K$1pp&sPi-v*Kz(e_1Hq&n% zSW2%|R-!9NkVbAk-1Q4d&GdeWH2FS!w_7|&GQQls8^Dm$5t0{ax4+`yGjnr4wyQa~ zzu2=L=F+&ljDz&kx(QOS(WjvkkpJA<<*T~zi@{^419OCDbBFQ*t|eH1&eja1{vvGoRMq6k|!A{^;E^?cqVbc3;pF?hd&{IK8B{*WMau zEZb<*J8bPpZpq3}$?z@}xP1EEcBWtGwvTJxnq|*$SybpgzlmOzWZ>erFf(*(W~Na1 z`s_@`(+2i*$DTk+9%R$kyJy4RWGKL!#nEcfpbx3}Oa=|?Lcl4&(;S`IoZf8goTmyL zIxKU>S+E5=axwaQ$+ z`OOo&p4E<1ok_bCFCN#!d!U@`nM=gHe<M#zAsaMrLUA;R zq)k|ChhUI=8veH){xytivW<8g)^Ra)fd)SrFo@3coR$YpqFD#~Ox;zU)7y(bJgfUr z5a69j|C7$+S`Vd)o0NE%BBsyDp{?S!HpEPI9R}Re5bgW;m}NvQ(t0#1$7jAuQgv&- z1Ky=-vcKPY&Oa?zUADr-M`rEIwwv}Y5OQ@}xtAbf>m7)R9wQnmTfWY3Epd%R%)`(t z$ZU9BJWP-jcLJ&!fL(mwF_Vf}2eqlKJwhKX9fnp*+MTAuP-*b>tR8Na`NetDtzJi` z$(PLD5~yb&F5K{%KI0^*nwf)dCwJSULP-PEh#qaiT~vVlgOd~)RA`f?|6u#n~F`1g-CL`M#fBta!WQZZfU~x{w-o?dW zJ3-4JQNZ^4EGPSNk+E6L2BH>QI$gOqN6oWcoJ{ohO;Go|uFkjGr1||B9_zJ6C(DG; z_-16d$Eb(AQnFl>7)x4pvBe8L12Ory)nsN_E*X!;4Fvg2rWQnY`*OLe4 z54F=0nbSwkTr8ZosB%fDMeS}EcsDTfjoflKF z|H=+pSNw(@WNF>#tvTGH?&5Y?8+yD3(FID>HFo4IBhHP7$0%~ z3i!p2$A=_6m&bBlufI`#v|n=DsKW^k3n^PeCy=h3QX(%O+E)v!)nL}}vvhVj2_p#L zmp@jN`DYE-4tz?rP8RX!OfiU-JkeXH3dt1rmpoZHnMsLEWtSO+`}a$&eIS`f!p&%4 z=(Qr8%`m}Hqq(DoOXwf9u)UTY%OXIkp1c7(Z+!M9uG8QwJOQ5|@j-J4XR(iEZ$bIW zc-i=L@_`DmcMVQKxT10XBNE0`7%T6e;9x6kf$0(6M6X~Fd2)L^|DbPpvNAFk;_*yd zo1xu1zrbv`10>+y>gfFLCFyK(NUflG#SHJeBcOh1(h{?{mE`GRva~}u&&zC3 zEl@NrYM>wU{9j)6KMvOJOTPpYyAN$gxwf>zU>Q3ZrY2qU3K@?kztI`WLRK!b;xoQk z23LOP<4ZgcX!~idX}>>2MrSNeZ?Sj+MZPtec5O1!Q}HS#+fYaP3lF(h5wWj6&1647 zgCaz@W8r+SUx3n`_ph4Ys1~DgSmGf4<-qJt2?Q6e1aeQ_2&qN^z4 zViWy7M5nymW)N*=+5ayvv2dKDQak;@6J2!*O3Is5&{FU6JVNg2^r_g(4@tEiU3tf={x}F06BoZCKrE?}Y^v(W06lP$nnP~bt z=)5FsQ9VU4&mbHisvve(`K^amv^cvw&u4WfA$s;1(d$7c zyoxBpanLbSI!)_v53hr0m;BhL8{~S1Mse}jMh&gnBPa5~YFNan7@`ITTtJ~EFyZZn zvT9!@X45J*g}h$~NPrXiad9I>SmPf(Zp>KIInep!z&LyYC|%@U-mvNT*s;^Zg!JYm zh_(OzB>uL|ew7dA0;VG8;R6JAO+hN+s)T&aQ7yvOBMavk$Jx(fA2Ep${SY|(NKO~@ zeq5me>|F$}^j=)saQe8vfm1bMO-Z$|Q2~vF%K%N;aOz$76)w{`gQUQAsu=Th;Cz)k znPw==qjK#xiK6MX7CPUB={c|V-Bg-?5v-WV7iAyk%ib7H3x8*JF!rg+({wJ>U54I4 z$Tp6$W~=3OccD5jwS)BldNHblS;SBRQ&&IB((Bu&_Ces&_;)qk(#WKTSMyI{!0u1d zs+yNeYSt#c-X)_VvzoKWBy2;JrQJM)+;8yHv3Mro zvvEy~qgPE?Q-FlDw+v$gvjSXK4BH%yH7Y-v*sOV4B|{+rUs$B+V_1?&f3C38)_214 z`I^cMnUIfrV~>L#Gc`8d--Z#d6|aZ2iRY5Mws6jl0b;8L2b+!RPE-4G7^$EhSv2$8 z-O0$BYJ4qjwQa_&5 zT2IjsCi_Y3=mD|k;i8T?F{Wwq1CQf36K(Xe{TxmJDa>BL@-WJC;9KquBf7-Spxdn` z^3u*H{oXqlJ*To_o@8e(iK+G~;&v&kI6dd{ z_?tIpF{qCp3#t)HBablr`=vqp#+xqEf#D6!n}q()Hv*qFNrQ+!O-xVwTRi$JdYN7OxGA}sf*dabWzwn~ntIt*|En}^ewav4Qmc?{+mjpe=E`uyyTGn>V!5~rLLNv3Ry`gPI zmGctw1NcdSiVK%PUOVg`6eeR%U|vPUCk>Pc}tw}R_0UOf{_ zGL5L&GwrF5f%-~X^$WUo<#JwVpV71MiWgaDJC*pCk_YLVaubSFUz7pcQ#kXI$L^b` zzyu7?KGc`cOQUz~@?4x>W36v&O$O1!&ikj}@ejbNVfL8Sssm@0t2X?MPDvWHHm@YU zy?9`ihcn7fTRB)z6OcfX_o%;G@Kmd-gS$Zu8h1OOOn|uj+O=!818ZYWR)iL;kbcrE z>oTQ}_RZ_Zr*x%|s_STeHR0s;JltKepxmrYhjMdoV#dF@o~#p8281Zq@f$rdMEM}T z_M0ozyeT`2hM&`nDZ@N0S)UAF6-7pW+%m+(dyyE4pAdEMUqYXoaBc&D zDcds+W%-C2lN;}W{hBwRumw#qbxaimBG(-_@Tyos`hwZ(;~tS?Hm5bN2aV$h^>wng0yVTPW4 zpR%30Y|!tI1yr3JdQE?|{+bsT3H4!VC>5skc%>69w}cMQ|6YI;Guo=q=9f-tH$A4H z8niO?=>)mMk+P1YIh>HI)EAcVgbq7{$082VDqidE5%y5upQ?f#;{3}P9qxZKtR}#@ zEl7>~l@aVtn(fvb&maDq^^CR0i~G^?k*OKUQ&!HeA%Eq3bjUdt{Cm|kucK)j>pLhR z%6gaC+1)br`i0BR)KQh5R*Q`|Ew|ldt4r41c|qs}_ravt@CJO9Q`LvZ$6uFB$dKhX z=@Mt=uRDMp-zO(^E8*&LK!=O6A@k7U+k2;pTQ@96{W%qtl~B&R zSE@L<^WC$uB|~aC=l-BPWpu>dYlT5#l6e?M^`(#;dz2z`5-f?wvZ9q&fm?JQ_13;r zJ6i|+W_66Iyko5`39_#T4*cB7FB;}nH{MT{o^{bFnKwwt!P&@GmrP)OOCn!I$ONik z8h8Ed3npI{wE_=KGe@HVfLT2b4>1$XQ{H$+#PDJrwdb4GquG}3HshA;A+&Vm|e{aqr{2D$E*9g2^|n%sfH$>gurtYj(IeKk?c1n#}Cp z{Nr>WL=5^fh#M@&KCN89s&F)iRB6Ju>(;bNtp0X{a%&wQ*sZkHv z%a6rtXN9=cqIb3x>9;zAguAIVbzrMY&#zZphw&C^R+7(Lpga7SH;4L&iOr4}xl2TC_q$3-JhUcEKS;3#v+!1K9kdKfCF^5p?z zWid8ry`u=HSO6f?^mja(IRp{9R~KGG*V;7ABc9I${UzXY8U)%K=WZ{dak*b_$jl6x z`*DXs=rsCkoJwi>hHzgM;_bY7)zU}PKol>epS7uKw;9QoChYqlpPiCzlurjhuy@ab(biRl+Q%XWPD0-JNhn% zA$_J{iJ^illXV;#z3AZ^=oZ%)PLwy!T&ySS%aLRt>GSB6xV|w4b2cr>dKJn|qCVn^ zqGdUsZ;sYi9IYC~8xX&mWIPtFb8(GBICs7`NGLq*wt}p33PTr5ufixF#CIu6C%-_c zzK(7b))KUBR(YWhqlYI=%&44T^<IeWf zjw&Eyul_KKR495Yg>=lR#z8C@(;gDcJkL%RnPSSs3}{LZ&XE%Zv? zX#Q0rO~>0LAF8z0J*jJ~dhkts_n*83{V4h+UVzy2G)rid1$n`;=MJ`qIj%&0OjX@c z2VGcG({J1{V7lR|?U!jON$0)c+Y>Qw14%xt{?NDx%XocIDGe7|e;SvTZ*sW)qIV75 zxo&pBut%8B&ph4t)i;XyqOnUy|H=#gGd2EFN{6w4YZ8$f53+3M113Nu_(Hg+S&TFb z0KFV6?u4HA6^ghNd?D7OC}A zcz0Q}c>P+0gbtHT9oDI+e@kULFyH4xnavoR?Qm7pQ<90^C-#6g#kiJ`xlYu5HPZ$_ ziF7?h2US$&=0}Qr-`zfy1Q6ElGRxAp*S(KtL_6J{Qn@1WwH>xJXl@YGu5ZZAj+5*M zS!weYHtz8$b3IuioMsum40RD+A5s=KN3+*%d?TYHOg?9XhM81mdD!>8PeEO-tH^a- zTK1?wkKj#&h9VcgY)f=^5M(YojUKv3awg;!rL-eq7DTT;tJ| z=~fbWrERFmWZS@<&TK;sCzphBAqpJ86z2Bh>^}ht&?2cNQmtEbIgW^!n&ME7L+`8u zL3mMFnLIKCA{4)V{RiDc5VZfwHyp}u0R@16e@#rYvsQ)JBenNTZ9{P<)>LPMSSj#^ z=i10RbuWbMU<6EYlap{KA|#TzR6!6JYrhvqZTDp@7xNgd)ZcPjU&C|kS@|A%O*$Xo z%4a@lq+5Mi( z=T+N2AvH+^kT}*vL?mUfDJz8zfKcxzWTuwIdh9B8YBq9oWZQnyZqbCVv^7IKz!oSy zRM$-^y#<;K2oR5#cnldQ z(o&CCd4{~kGwo7;B!S)ZE_IDCCw59X5&hIawWQMT1ZU7}&#V79Q@kYfY+Zd|IG;kG ztQLhW)le8?Zv4WZEC40HfmcGc4v4z}FJmu$!n;-*cR$e@QK$f4PMvs;Ps|JR?kLV7 zS*T~yZ+p(96PB#e^LpdjoL_vY0Bo0q`FbLH$^rH%Tw2!)lz=^4T22SsTQI*@A#1t2 z9kgeQ`=Lmkh^Z~KzHvAaw#J^Pz@b@L`P$oP&!`5IYNe9h+Yn{3wrQ$RTLg<-opthdEB<&~tj_s(7nL4Qa?G+zS62<&Et4+gJYz88 zt#oX>M{+@M-IVx653KeS&-FY>5wa%nG?e(@LHxH2C+S1nHO7MQVNiqs;(0U=-HDBf z%|JHIDAnf&T>&ok5`^99j$ZDJvIrYLA}o$tK}PQL(d0)eA-M}F58vFvH=eCj%ru$a zd`3n_=h!apFG%|ejx&Cuc`J+VDFS*Y+zz_z=agBZwk z*Q`-xSv`BL&aOGg{P+(rx1O4KsJKEYDUbs1?4F}*iC=A*Nn3}t?JgqI%3xlKn2jIe zka+gS+GU$|Cxm4+PD(~xHTSjvgs#)?4RQACB*;Cq&gf_3OyY_XQ$7g56{$S^?6$T_ zFs;5tI@-B?ouXK7g_K3%C-;+rY zk0Tj4=#_UEZB(6?fxD`^>-!2Qr#>i3Uo{ly^_^;NOqc7qf3tm&ZVC>RyyRRBzdWa8b zwO6oOZC_EmjyNdFjPt6}ITrTZD!v3e`gq|-F_rUBZ-U#pt-hJg-6K#d)S>1iF}X=a zN$kISM0Ng0a&Y7)vBz`1l`?T0hYxiUq=brqpVx*8w-q%3CG#K89ncf8XHO!{fVm>unaO=@K-*UE3PC z*pMReq$b>xM&H6C{oZAcxG8t;#tRRgdgs1)5vVZsEfr4FmYrm(6?Vdw*i#v(nvtns zZN+b@vl_In*|ajaj-)FhDL5-jBCe-@h3lvnYg|qaIl-(OB=8%T+6)wQaS;1FxYK%~ zZ;_qvf*1>G+f?ewc*d%jY?U1#I4J*JzHF4OQE@io@5u1_Kak<}5?gb&N^BYYBd752 zdr#fUs$x!FpZt$~)~Dcb&Oosu5Ut>>_>{iP4CsNectF!GNA;>ce6$@+STL=4)vr(e zaz+&))qE?Kp&r->LF-s&ojk8yjOvQ?slAUKB%0%jLDU@G--~CfcvO^W4OAL!q;!VW z*sYB|tS>qmvkpFTOe?48EwJc%??y6Au`KDX@hNxmz{B|{LNcExV3`|p2z$uTm!*K& zu~YZ`6*>rH(|}r$SUI4+1VIYl4j+p9sE!_Q0%CFnikkV~W*}jjsD3l3O zx_cuGU`PggsDGycM34+%)_76qU)|ql%f59Q^+R)A_Pk=KliuO;$Li+N%(1g zTFB`N^hh57mgDBHu#6LcNCv2dMAeH^0U?9mh#U#CfUje`qjxpH=2TQg!;UjhYL5UQ zBDI^YQOU2`QYFp|sc*@?-YMt0-Wk~7@l%HCpC1|gLCy)!!-q=*MC_s zGydQo|4%IPe`1k;q6PmGi~K2=@b8cRzZHvo_-m%^-zMvS%A5b!l{f!4n7=!sp#S$} zO#dGlOoFokhJF|YozmqsDyw_h&(WH(Z0;KJs`j%H)+WvKhRDNO zLFCuFLCg{o(&w(Ua=j$F9OY!HfQ-G2OhS#b0d=NXk;VYLpqY~ztdfA;2%B!{>YER; z5yRHY)gt|*cl`Lc5sIn?I%TVawAQ9J6 zTLs6E5@a6h`kWVd741SJW}H3srP<>_j2 zSuV)1Ewwx+fSufkCcJGtP9kO+sP~jia*#4 zRo&80$aWuP@qxKTZES2@Y6Q91Lhsx5jui;R$sJqE{(VoBBeLe?u>ov4&&3el0sVCB z#^4!t=XNK{i1f*uKHz@{kN&_=aClMED(dOK@^Y4cPP-rR@~l+ zjEw9qpGIyu?84eb<`BC{=|1xYPTep1vxZ+Xzi!@kO^caiVy*C%fh2cn&v^W80sMKc z6>8KG`uQEqQo!C(+gC-B3RyRUl4ydfr#BKjD5;PFgDZrFHU*_o`Qv-C@bUnhN{sz* zwzyW%Ch`ZDyS$^Gmc^$TB>gS!%#H^(ddbV~AnR}_k{8zp>8&2pP<}Ihbo6|1+7{$_ zRPgH<85zl*uz7b}uG6TkO|0sw_6b~n1{7lua4duU4&~CWCkDNC&0RBZMFjhTayx{0 zxGCUyP>+}_*rwkbjwx)&A+WZ#fWJ7f|Hhe3%Kgc)cB2*Qah&>WhsWf~VvHcf!vt-2 z^5OKCayW(V(MP;qP_c76e#^Awxg!})DB3dl;HidFLD17y#UFUA+r<(vU+fz8 zHEnb1I>X%iqK*oi&x=?THF~i!?APh)UD+Qtn~+K8>XRk{ar51LmKD?Yc|oN&`eS?K zs;FDWRrHQr{p=R9#bm)wND~C;Jy+)wk&z!7_2xPBzPu^69c(f%-|k=CYLCzA@3E8# zxfDk-Mr{rs>=$tTf#LBSO1|XdHBrO1< z^6#nUbFgibqjc?j=e>n~4J!|=F`>H@$Kzjl$BrMdJoN3@?Z&K?s~%Qu8kT$pstE@tVMdA^pPp-6+t8`vE_4XkhhebGV?adK%`CY5CS5mEb=5|o0Y%W_DYwPK%Uf+_?5zfMy0diw^<>U-q1Tz2J$tFR z)8Qjt+q--2I)lS`jY&7dd#uKQbyG;_&Y0m*#evoDYAU>Yc1A39dAu59`t_v9oqpo+ z6@BVPWi~ki+DmT?pbea#ZfHFsg`V+z>}CJ#0r{J;qz4o@i`B2*-+23p;2Q2znKRN} zkMGG7@Tb4AZ;!S|DLxqFxS2G1Ql-iH1bvgY)>FU$flf^*Nkewj9&xf_4;wj7yoJYj z8pByfol&$rK1(++3c+XUkXMwVpUMz5R-)?O*=tW1mEf<}>VAB9H7=W#u^i%YG~+(| zAwqBfq1hS=8~j#g|E1>am&WiDQ@`qfEVDJc>_miKIUD~HUzq#R1a>sz2X90p%r+p4 zEOq)3Gf?i${@uuS>oH_(pxo}>nc&Nue+EuKP-ojZ4Q}U~(ER)N9<2L*n1Sn8ro>V5 zzDKC}tS~Nn=RI z#D2Eo3{a)o@`)A#kJDO?GD)0J`T!{Idb>Vb2;7%+U467nqrU&GjUx=lui}Yn6?2R% ziQip1#8$y^atNFgDW;lmI7nfLYzToz@%3jx}JN#-L4jrTVqr?-~Z{RYO}Ss+-edU?Y01g}s*?q-}Zv+H@EYvcNH9BQSFXOryR zhY%-C^(0OE+<5j59>-x9w?@$?XX;9s^OTQVRjBy=_{TPb&(@jM&Ph?=B7h` zRVO1gN02UXRI(dID&#yDQh9A+5$yR?iTY5I0JU>`cAMEWl8)WJ{U-+AN?uj{?O6A` z4W9}P<1TRv+gnc{HZXm7l!VKEJZKg8E!*nY7Hu%NIjX$rm5v!&!j^(Y??1A!B_$JY z8MMXxUSFyz@jos(061g$1qC`$atN3HZS~g_A;W0{{b$cpvKsmo)nn1Q1<;*0IO6Gt zJ?hh8Oz-e<9N6gHF8q3y!k~c{XxZp}b|N{n3Z&L5*K5@D)$dMdJ9OpilC{^@b0Tov2Mi^;XUb>HH+S8g`pjTTZX^YifZmbXu)+s3{PudJh& zM`f%~*(~fDJ{&z}90j$hw@3PpgGAjH*EQ;TR5W|8S}FxN_ngE$wZ=D#8j@K znqNn99eq4Ae0VY3(PODhjS(ldC$M9$lJu4ju~T6;%bDMjbGGHOw#SR;tkvXH9aGhU zW~m~stMu!M_4sJAJly^`2fqpV%j>an(}4pK5wBkhG`d6r$zyB3Fvvi?MCf_^Kkw%M zzL5R-69w@3^rfaRLB+HuGFTAbi7vaI484190AFGJx`jl*Oa_{Qo#t$`#BdvdXpDqG z)e4?!-r<)LZ|BeNU#WgaqfS5unx)`virg6E#*^3Xw4<_G2vciY!$oEc zR?Ot2QbWp`x!72N6KG4u7+M{@P9~`}l4N#Y)9WsAwqBONC!vka>X}c#z8D_wu#PJ? zD6#oyg1ll;U0SCm+Tr-gtsj+|hkYTYS(JG1{(T+T)stkSG&8{EV@-GjerfFgINOrR z86a-$!5>IBr~-gwU<)P()j*9v5E|p*;a$Hrl_=iYCvT|heBQsz=2+>F#J2~Vnwm4| z=;9J;aeHaNC1Sjf-7MrR+`Qvug1EovYmHJ70sV7BZmEGEQ28=L<8CaFeg@$m95N|t zu#Y;IDMbp*tIF&_xGuzYq*y&LG=5>nnb*m}-g9dcG=}BhvFl$dq5ih_!dHZ~^gd*T zPZ0mNp*V(#&tMbMiI$u{kAs4KN9@It`yH2&6s*cq&Fw88XIF_E*XRK|;`@9C zcOu>E9r7N@5=xQJzl5JSmET_}chsOXhVTJ>q_#7Ba9rsoh!}y1y0w0vq zFhBGmout~GqM+}UraI6%udl9YzRct-wbb_Ii!Y3c&J(;DL%2uj@TXQi8K@X>jgY9H zDI|POUOIe^;*$QD*Hp~lUKvPGFj=0MA8H9q{Of=* zG^x>kwr{Q42AgXYZoZhPzn1;TAd%m<>!>JMOcNm!1=yU}@slqKzT?%(*a3Gbr8Hso z`3}Q^?4Y~Po~IWOa;{gFJ*(Qkqj*y%y_5LEVCl51cIg(=VA=ZH%R^T2Zu zD|_aq3#)N+RoxtEPU!hncH9yc&k31lQazpZ$TJiJqWgwxMo? zixso4udkgLRmD%qs=vJ!CBQV3FSd-F7S=jQPYi6)21n$7zU?@As4OkNb_sd*FSrwzC=E z`DthU$4A6z)n1FGdFL-LMt>QLiQv<7UMMG&@b_oRKVGy7)bS3mXQoIq{cU>w^8x># z4D5dlW^oyz&FEfr8F9kqZw>7AYma8T(Fiv9U_{$oV{`9C)3z*<;O zu)e?4fD2TB4aB?x!+*CbjL0`OH*vta6+2Zjsb`I!^epo?-pKJQJx-Ats7xdJT`Qh3 zCL<#6-L&vYF6jca7+z>E2At~E_U)9P;RHf~)ra%TD8#TI_|**K?;7e%?1F|mhlhtl zel(z=juFC746*?l>KKvy(NHIEO7r2*__*QG(NQiv z@e6VdDC|@hppO0Yg@7(VdKuvWn>YVaU#F&DyFoc8J36qbi>Stlxn=m?Rj%Kx=ZO?t zMx1NRPWtfsvz!X4q>^0>T7G=c{`;2;+$AVNhl;>{5Qq6vrohh)Wc!sY2?C9i7q#3x zzUH6ARMgVt9qF4dE@a$3PyL%EyTKC>5_xT$CODQJdu365^Zm?)O}M{5BnNcVG2((< zy_$~#(K8t6sPo94tYGyZC$<*EO$sfP3of*ty~WJU73=9zBY9t!T)At9bjbrAGon!Bg8U9M^)t#R)hy z;iB#`4EkW*_Qaxm9dRc@9p^ZIJ*;m8zyMfIH>s04oR;ak|52t-1b)Z)w%p+yP63fc z@^7-#2`u0>Eq6w)2An_5Qa`e@3zYhC`tVR*0CWgBQ~cU?J)j2YRI%d>8^M>;%WLHy zLIh{PqbWM|gkC}h&hRPyT2&|DAvt&qpO;;zR3JDi&2I<_-eoWb8=v>bff?S!u^-(V zx>3x7`uoJ`o*^uhJ&REH!NWEIN>Q^a=o!;!v?iCbI(@!=NDL58Z?Y{LWtsjFA>UU{ zkI-fvUmds!>R8FEl@bawOtxY+ZyGSY8yp!VnyDv|40j)UjlQB_VX=1!(SY;IQS?YU zy@t05P48-eFJhnK`D3*UckL=<{sLLn<008K&KpsZ_r5o_N)4z-GR@1lCBKT*Kl!fM z>})DSrPk?gZ!;Vb;tiH=pm^*)Cfq#qNJQhp%Zzotaj<~AdW8-)gVIdKo@qz1YqsyK z+K_41CP4Pd$)`Z&t{x?ijlWvJ)71CzJ?CW5@-Q*)ct&+_Ygf=|c1c~> zY5$X}IB>`_r-JBxX!C+Km_r{n_aJC;zNJW5VCw8)9KU0XE zspfT5J%x${X9E$lb6p#>t}!C*O*_IRT7*lCl~%O0I>BzFw>t`02{BS#2iI~|^HOw#WCm*4C(qZU0kXd`cw77Pl=#6UChhu) zUi?gJ!rj-G+1dE5B$y&34H|A5<^|R`Og`K3sJ4!3B!`H~G)w>I?D;pIx?L;1Jh!1! zU<+?cF-!#Du3duQC%$pFai#A%HxaKDIXfPNoIBQ>=`PV~HrpC}>WP=`62LI%#M7Hd z*a-PDp6ECG{on@X`~mdEEBn$%!R0%M9_-6)Dy{p*I_pSxnRFb}FLTunMstG9ZT zYnzB%trdb!NS058J>{=(YF(>6snO*$s4`*u;`|`1JL6&exYD^R75wVT!?hrIkD#-E zusPLms!gG>0UOz)gx6;|s<=rbv3 z_}*xE4S%3cA3-aAt&OVYMn_*3yAS>a#T`A|3AIS4+ql{qz!oEwXlZ2`EOFe=`LkcS zvUv1pB&yBYxBB|}`o&F>^8!!O5f+lh#_yR~L{xB}P3_sZp7#&(retPC9BDRCJL`Wp zY1$lmo6XGv*@M^C8=Fk9jGy=6&?ENe->|mNHc#_ja$M}%F7fc8le84+4%3(l=~h&VFkMaoX>^7;Synl-_Kw{VwMgq~D)g*U0~#Y@-&cPorjJ zmB+Vxfcl~9Sh1Hdn~3~a%5nI9LU}J}AEm+HsGi2DC#JbIi)7NdIkG=HXBIq1Kq;19 zE4Jg%;DK@$fGD*;z%AI87lSnJ83Ck7Yxh+MFQ>!giGm)v1 zdvbKnqbJpBh98xDW&aQM-a0DEwrw9BNd&NV?esQTd`0H>6R9T zp&JGeRJyxCN*FqZ7#Q|7&)d(d@AvMt_S);W_xk=)moxX=_kGoQp2u+>M+`UAh)WOC z!PC$#Mm3vyyd1S3&#hTznRoC)h59n#FH#J8ZVG=)-Jlmres_i-terL0?qlsHq9>Q~ ztO9w(tA0sctxVfVr`EW1p*>l&Zl1Y8KHK%j;~Z)*%@3ZZo4p$veMRLtIb?qfO+8>!&>=x}v>~${FaDxpSXY1;s3+7Hx zb~8FAL*^ub0+;ND(h>XPbuUX7VsMY(l4m9ldIJNcI1W{mZN{sj2mQ7Qyv7b$Mk zL*DzFF@+5gH?!3az^Y`4dM|)(!dPm++>z5Vc_W{Jy7flvh)=z7GHlL%u{}&q#s$%D zh9U9Z7dPnkd`*1kAdW)tU+XI_T9r$^_>ic}9Wv-d! zscQpE+AYJSvJAp5$N8OoA*Sle$kC-Po!c<2!eVGZF7ega#H>6H$>X96SFes(v@8Jt z=3~4ePZp%gY_}rYT2N^`K4i>$Kee*vlQH_uoJl^!Z-}rXKPySE@;!-rjuM^2f$dBM zD5o8Ti9ok!ZyfC|M&^Y{vH%5~1|2~(cTSA8isj?w>SI)+{>*^CJ92!$ zUps*6&{}S)z>d{wyevXYW1Sf7BdzoX-t+O*KmmRuTseHI6ThlLc-SI4n)u5^g#%aR zjNv2xUTFQZh=tZ`l@HMl=0|J(4i`!Y8|`%6%22lpPETCaK1tQnF2!E?RXU_kH)ewaMF|?oFTDxp4kOS*7}g3s(%k%@$9*{d&BfW{ zK6FJ-yg-+?7*cicI%mOCyUg!v(Ae&qfQl-cF zdAj>|y)tHy+cANLyKU^~Vwwx9{R7D&m9fAeehfOo96*R-V24jsM4g=$Zjg>lBPO1n zpy-V>?(pdIx8yMniMy63pjIqWYUVsa-_t^;?G+_9h=1`$NBS3ds7}jY6epTFN#J&0 z(#I~kb1QkfhLJ4BawhXs?|$XVnrzrKf~^iY5&ujLm^O=fl){vwa$3pY_T_nHI}muX z|GcW=ihJGAw*PY$aTao%Be4A9(aDh`?1m1<2iY(>d#+vmgQM8@HWD_u_Id+6=bjc~ z%J^-j?+pP*fE3R(6})Tc;a1P+`Qyds?O_r(7CSG_Hot!VQ3Dn`wwW_;H*rku1MxlF zdQ#f6$9`lsQuy&E|7$V5(wdXP`-rGloxc=uQz6Q{gqtIHGNgAAB8t<)MC2KW&1;oz zNJ}xMVMn$8F6E9U-1Z~uSFLp5C;@YCX%__jcV?jf?nULJ4p{VjQ~p=nStiFaH`Y4Iy&FX(=C3=g(b=L zLg4;Y_}~z;N5HXFEHIRSmqYCcO9No%qIHY&qG98!bz4dN)`uS#I-{jo;<7RtFy1ig z=OX7Cy_4Ym>Krej_PvAS2NezthH6=>8K?r#en&`7|Iv%YTwYG@74EG6aDCUi*zQu)d*xBJ^MUHTr3R|8wZrYEb`^_n={6UY2poajBDKA>i~jL( zG+ALAacN753B9*x681O=DN+0yBgOVeIw0YrR7kkp@yyAxrwp!MiYK}9^K#w zZoi`*F*)+ILUJq6#b@Bwa+A-$M{W?@XPPKQUsWTmCg}bx$WrcuMp10F2lN4F#S&Mk zL-PIDQn-|k#UiyH;LfA+hO&)|0`%_|4JGN|9zTw2Z7rNrKLKK+nPXU0?00C=TebKPl)*J2+S1z%D;gW^=8u z#_c4ySPc_80cTDVjeD%!qsj@fA3S7+eRQ1~S2g>-H#S_J)04#hE#%v}x-E&0T?_Mm zae|mtg748cE$1`5gZ3Vlq+xO6nd?Hl({nX-Wfh=Jk>lNE&f*w7|Bkh0SXa-?41I96 zsd??^jDa^1=7pv%4lPSngj;&^Epio~q^^m0n%0R23OL%0XO>$s10PAN)4bfO3Jo!2 zxh;SuGDRykqh51Jnr`NB)$!<6lqn_bXsYqQt;cLOKeu&g5)@C*ldB8E z6`zKAxddzA)Galunw}o_WO}5Ie9)3FedrOjHgS+M>8yy;w>lrD8E|8w!Y=mi_wl=O z?sZm85YM(Bi#zMX>*nOM7)`fr9}daz9*HT&&2I0OksKkKwtC4PY97ofqQDuD8Nk?50xiu#) z&(?dtH1|(&%ID9ea%bt4m=eQEp2Aei$3O#?zh`ftF);tDl#94gDgU+Hrlf@vk-sa^ z%87Hjbu&8u)Mug+$!XCOmsO$cslES}y~L$Or4RC0@0p?$vcHe!`J;#WrJ;R!>Trqj z@+UWEqEh`&#_}-A`3WQLNv|@1npb)1NQEDV*Y>w7YXKwmLxm%^+rk_U=nWR)SBJh{ zgjhqilU_f_SO^E zN+(evi<@m>=KkHu;;duOU*s!nig$#$;2XEmAagP+<3--+1lLG+ObSWFzzu8SPC%vg=Wn^N~0CpIS?3NgI0S z*1K&Cwry%d1$%kK{>^^?3y;{VG!|dfE?iJJge_A-W+ufP1#xwN!u35^=cUt!jMUgV z21uI{18*OXo4o}>R-?$fnxB_!a79S{PVruR<6*R)8UGB6?d*B^P!@?~xP4!Ex5bC& zN7J=xdO9|Vdd$Tnbj;J+QzvOuHW;nGr2e7d!Wkn13%qlym^^Y;uPRLwZlU|L@>JSO zLe%j+39D^xslL_(Ruz!L)Bu&Xk1`#LJ(35BS!q3Q!;WU)FYU{L=T3gb;Nsim&J>5d zAac1P;!EXfyXoMZ_qlZ;P~e2_&ga5TPm7o&;9tJMo8~lPZ;%;CoL^2S>Hk2)Z7ty^ zZ!0lj#uw|zM_l=V8WU^P16e>364eaKK*<872HGv6E=$*iU1!6ozgyFSJWfZUHhq8j zrfg^%5DYXsaHxe_{{%5e^b%Ks+{^PGqv-6pjY(k=Q&1M@bn!OGi}!m6GG%*>^Fo$e z>BLcqdiU2lueo$ie-CJFFgJ7+18T3)E%Y$XE?xc#TuW6u(6Pv3^5{b(^(Gf;kcpT3 z-{a;+I|5s#BKJGx(G3;%DIvA%d;NFu`>_o{%EHxGLAT{>C{B@2Yo;9!cm@I6wNZ=) zF>o2!i&xLL?#>^^HpnFk1>7uM?h4mC|CM}hz=Sj2%pGMLmy7yP5u-7jO~;q*V^aG%%@{&{najnmFs+TSW3p9gFrc5 zK%C6M!`a04u3-D~4YBdxU8)Vx|9=-T$8E(_zgg=Avw<*xnj`iGU$$zBdu*>%#N3dtn4R|f-!M?b0HJyG1#4^? z(_h(NfrRJp(LxH*e42vvJ5qrcuJ#XPJ+z(yjbk{2leqsr0k9iNzZ{sC9~i4I;M!vy z;FqW#9#A;SG>$>E3r~;kN5Exs@!f}YI091HS4{kq#9#cj1L^?GBKJQ!pfW2#8Ni#w z#SfqNKBEBe7jO;J`zb`DJYO$HiA}P|!2+dimsE$i4mtWCU45A{8M?+~fL} zf;zF_fPTP6s8kKnC@!`%18SF1-+Z2DJyr=o!IiJrabr2kjK4r}s~Q@Y31zwsLSwQ$ z^rIUarM3?afVj<>RmN+gs#{<(S8Spp(dYH4g?M~EMjGykMk!K0kM4^_Xzl>!6xNP_X-M0L6u7;<~)?7TYE0ejsl zbp0Mqk)A3;vUDReKnh|O$huLjHo1j`xg$cp6z-^xir(@rb5s4?=3!^4z>}}!Sf$6O!xS>pr zO|!AsYUiS`tM=s+d9dj}Jv+@>}|G1BT`CH(NK(2+M z0FiU`!3|<8M4km8rvm-$H>Df7rDi*te=)p&8FE18Z4e_Q@&szWMa%z%wmuFICD@Gr z8*TmBBd}|w{5RVAbwFExR1s+F|8^1nb$SLaV}beq#;5>5)wo7H|BX>W3NR{IJNhq- z3K|u$c@Hou$o3%l`u)4N5ac&H{$L*~!uR#{4F@xw9LxyR7O}bKG}r9a6JYZiz)FGI zSbpC3>zyL-04!4IX^si709X_6f!y2&763+@zye^688;MI0303fBT)?C(Y%PR{>CuD z6A^e0QD0w=VrXHEqZmapkVF1K2{M8m4$TU&uzWv$8yd=jzts2lCHbedTKBN=?#cea z!4*kKNu(^^Trl+)!v{@wD7Vgo8!C)5Keu9sTX7yr8X&MYlv=7)(9w=ya^8DhsQ-57 zKX?Fm=19o}%DvSe$$C=V0oJ@KKhZD)X;AqSg0r;y$EjI&O7Z$Ae_;I)ff$apzD98P){J8YMJZJ3-Fwd#elEO2Z*y+(KG>kUX z+iCrpATdqS)Jplgam!q`DCWg%-ytR=3$6Ua17KDMdwYL)04O$Ih9Gx(Xdnj|79N~C zJ-;)6m|X;$dV|J(5>STZ?XB<&L?peOyE*FwE<`Vsb%7{okf1S@?oG5^%R_FN8_Vwl zxibv1s=@|uuXpzSn-k>UPM4}Mu*IM|3B>O+iesU1^;nym;qtiMntu%l+A~$mwTn6E}bFF3>8&;5G*kjtER~Yc%`1FQ=8Y?5A z@~fay3KFCQB7tsvSNpe8ELgxCSETYGBZ2@#H~YW?V1$5W_!h+7AdK(V@0c+I{3@Sr z5}N6+68qf-lyX`CRCir0hbBSpnIu({{Q5l2`~V_}@q5nH_>>l!CSaC4=TWSyC(^L6FLD#-#xqQphJEG z8#-<9Jv;-PIq=g2{8v;!O%>;Z`kz+)U;oKC0Jb{54=J=a!_%-o)85rZ(F!_#K=@lf z2Jt*gCCrpPkmxUZf@d|IF8|$C#fzEwhK$Hr3VNV$k3g+;KDqJ-;@d@<1o3Y+ zPJf#>{~DT1vw$bD-50qLw6Nft+&tE+2)v#zL!C z1Rd)$vk^%r^&Nekh;!6?Q?wJP`5V}&YplwQsh_`gvmrEE+IU5@ONbT{MlYb^e=^4! zUuhJx&>qd_Cz|+m$N@0!zXn%5~tfNtLY$87YMx(XSc2 zTHE-NC6!Wh%)1ihqVvK;0zNiJu#NB?s0gV&V#0E{!W_Vo~{%UB*tQ>5$&rJO?J6z(jqmrRWYDq;=iZ2#Wx7z1SM z6U`ANbDs(?1bmnL*2b`{5p}&je8-8+@OC_&Jqtv_|0LMeKPz$2YfgA&w0OPCbw0b> zO#l-5_HBf_ort_;=wmOR@vl!0j4_ihoo&86cRu+_+{ZWu)ER_J5dkM`2*XXA{bpL+ zS<2=Xg>q}vRuc{O4jTh+g^_|}EL8n5>Gc=9*NPG8mGZA2rj$!!Mp-GfZZ2R5H8NH-P%Pv#voYl@pDfbT#y14ZBE{GG zGl7MX3cG43Q}u3!2Vtl4n=Uv->uoHujHlcxT2T{bN#LlI-@3EeY_^Nxa9+{PH|0CB zEv~~+tC0$~6~1P@eeYc3>F@~$Yq#v!m@n>wuR?mCzv>^4V8*vZD&^XIah!R@bdP;q z+c7mz6z&h?X864vJPcr4M6%R#B?{R^jJf1=a8+I^I0#xGy) ztJR;Z1NmteHl4iS(<-RPDN9ET!XnQwOwQCaYN0DpwteP_iuXRIFl6^l^>-hR>B<-# z2?lpVUthmW&$rLi8vMn5vNBB|Vn#+#ujS-;=MCGqNtey3opGDwTTuVVY1V#0|7v;H z3y7JYY^q{UzKJ{=Y9}|HYsv!MkCgEeE_tW<#?rEF2Ov+T0S3wjwQivv<>V6DH)+mc zX&+|US6sm?@ZO8#jBC(#KdaDtRsab#I@*6KTMd8Wb0ME{Ysd4jaWD}6Yx3x0v_Ng|0L2GIo-L;8mcnT8mZ}DEvi+#4!WgnE1 zPGT1B;P{rZz)g?Zzg?sV-@8KpktEQdx}kJ=^m(O>;*xHUrFVHEu=ifc0G_ISeSJSR zQ~jYy)nkmqL(9wNn~IRNJh5fqw)M}uZ`F-E?hB7~8r(l{>KvtA;xN3S5qr;l?+w4r zVY--BPQf1CJ^nrykbKLue<3o(x}|Z7y18Bt$|RU%gA{0MXYNWnDGC-I?SHImko_uo zXEZpXKK=Clhqp0tKjnytLMBRw?n3By%%YO&cA!@&{{!#fOx*9$c;f09YpS=t_nt48 zVQNcQBBx%3ZFJL1k_4l}%fkL^RY`&!yGw16dQ07@Y(YUmJ3Vdc+1^#KhmU0Bt9Q)0 zcKWIp3aJ9xpaIEIuK90LggR{_@Lr%L?_r zUJp55(k7no<;ZSw-3rI-^fpt^8}y8UCC!I00zk`5Kx!0NbsfHN^ytgC9(3{5cdm0Zg1BCp~U)A7`WBj$K&v|vQVL0}> z@2M|*`P+!T$!Sf`!`Mv;A5^}VAc_2hJA84YmP31_cbTL503`Kh({(RPzHxG`Z*H=d zrxtQS{f;zB6r}=A_cf6n6gg)Cer%pFe!Fowb^yfQ8j_vhv!i|51UYQPNb_2B`|f&) z*giPCu7>zN&_BC)jOu9u$bYNSu1t{nS<=Ug%po0k}b4xT{K?QB1jDLP~!-LX1H}*PtePzDbDls&>iWnQ|9jSgy$!lswz3?RxmVoxzpytk4ipx5w9H*!JJ}6)0J64Q&H^7?Tlvz(T zjay7!{_1`g%B^$yMb=qDOn;-UwC?B3ZsLqO+gRp;|IUKsu;!yTLu{8^ud)<`2--bR zW@t0Xdv0fUxTI|(IlB-On1WW%_x0h#c$PkcXh zdgvYxQH5!hhYW!z9L*CCfys1aYkto38_ezy71g9i+Dz0>G0|N5GtWb#`3b3fxvIk+ zjnT``G!#~W>!To6jpQ3ZW?h1)UX_#)^xH4L#O9p%UI<6)6LH2XG8!hVW+%1O2Uno*g3C&jR_t%Wum;fUJg3L(g*gW zwaLjjw31)mHl(Lb5VG*UyQ`5vGibqQ@xX#NeeY z1N#{as>#UK=0FRSEOwTWQj=3ZIE71R%qR z!rJ1?G$BR|YOpZ{8`6Ea>Qf8Wm}JouG)?1s2uX-ePrJd2L;aj!AnV*fYA{yH66 zqz

O{UxNM`jMwo()OUvZH6x3cFc72cIJx6kvi~S@&ODp+YoFXEzRHFi}=pvdpHBf0zStqrgJ8a~@IO#;uwXm=Fk zP(|HsCP0dTm^U@v%Au#|xie`>WT|}HDd2JX z@{b;L#q~KT0DZl6MG;t#fAJ^11Fa8kpE(6yNuKVNDy8hi?2AU7H?jy&bh`e}hbUU3ZY@;xE!RKHEx^F*hyh+^$7Iheu{&3j&+q@_0CPTKK(-1__ODR zeyXv2)5f?d;w-_Wk^x`xzE1(3jpfTv@aN!cHmrD-mix2Q_$4!skfk~M&l_2XH45Wi!qXST+g+|HiUe zNGGn*1)}!|A+uG_+8iJ{YL*5-`PcTy%j?SDW;JxGt=|&+)@r9|fB{g-vbgJlC`LI> zjd|7JFu%Ow%C_d5ErPBd?@>6bf00#Byuq$nCplJ%O-kdfOfHDj_fMa9b(^G{@F-r= zZ63>woX?Z0P59I~TxP8+z4diTsMxVQnOL?Q_kgYRbupauE)LwEW$<3sfu4W^kKK4B ze~`yy|NQZoWq;Ajx@nkCI)JRtbmPYnvRBZj-`|JoN$BD24xVdF4XE$SW2w-1h?FT$ zIHIDmwu#QyoCY3NB3>59rs&fcE(5k1`zdoE;&6l<+!k1|K330FlcBoM;>X5PoE@FF znnt}?k@drkZC6Xwtx{{OLD;-*L9oLHY53!~wm})Gm6>&P<8{HE@P1z_h?wz-sg6|) zr>ge;+Gr|$ws*bedcw}ANpx2E(P`FDyCh~SQiFJ+2Y)aufqiDVYjP!)6Ua9hYYd2Ca~N4D-9#4t@2b{4}^p=~N|RggYg&mgHDrX4MJ(oaHj8xokyU zCx2H_if`U?6EpUsz|2O63sS+AD&o|CuNt8r?`hJfP@5t?UBqrlWs?kDw|wb8F2Uc? zVqKIM{iPy%=mVZIb&6)a6|GI)^~!`^wqnilRg;}Z4I}ehIEbZ44V1LN!eCa8sGB{5 zgVzky|48H9-^fSt=Np6VDs#mKnLoO1&c1xNB$sM<3dfR z^>5Up^e-_L1n&jRI!p69|v==E_BthXZP**>o z8WxW$S1VJUNkKXG$9pNbKL6-d>;?Atxm@^)S}g$ybs4(~RYmYz9>zWoeWJK@)M~*cY;QyJ zLla9?66n~@-ouc%(ZrpGwaAZ^WUVj5fPIh>3pi157X4V(Y({@Jh$p(e2Y&AnY0ZRL zB9P%bS{$~rq4d@bXTbW9GeenrWi?FmO?@G>>?*Ho;OQw(!=Zu%KlFVO7Y_Uj5>RhC zB-GRLIxaO#9x{9VOe1vI8epy`q}dg)neo^PEsLQU$%DdahJC&`+{h8`P(UHAi~nN}H>c^B8;4o}Z; zbZ%w>+pgaFq*6omhOf@s{W9wJ#S{w?dD4EWb<(6<;q7@37x+A*eJ*}^-LUk)Q%#Vq z8o4RGudpUu2G(P||5gwh&QmcuzA?5KG@(Cw`n95ck6Lf3qA z0wVcWLe?=7iKvOs3g(b^SEn0I*U=NUXp#pF=wW>dQ;2{yKE>z_-VVXSa#Zo)c@0wb za%Xi8t@0sIey|$cVs4A)c&!BV?~(qW0l7ik{wPFdxISH%?Zo*-_HccrA9_FJO5VyJ ze5{h^so~*=#&w3$v7hZgl1ZIsB{kH-c_m-H!gEEeRLiNGHf1>qcQy*p?gkeN%6WAr z`WH#;t77@68|Ta=`zx}&)e`6XM{4qSv3x8*4f%h;S}S6 zq-Wtz|7w~YY97NuiQ$E%wlVUmS3fgk5mvZmNX;zgf=OZKar|+ut|VmAB0stpG%gFY zb!357@nY+jx!q1Y>Q>Wv$|PPt-d0&pv_)pe8{JLZ{|2$peKu5XJvpw=S6rl77~hZ9 z#hD!Al(Z*N+V`@vj9DCJ{zz4utqCEFL!{8bV)i>I(}YWE^>ON~7YQ}rSlJ+l{jFmP z+zW6=`;-qRh8;bJJFC;F4~Zq!E6&dzkys=m;^$GV;@*2z@u~Kx^G2tgRvPv#q3fm- z6?7M`Uoz$D+357u!P%N5*k*U9O4K_2(E=je`17-}@T_I1?=}JQTCQ~r-I?pDg(kGj zih9GE3NrD0BY32Qp!gWA+EA3wH&9?!w>rE{^*v#AZ~|_o z{C6svX&yzQfCDFuc~_joL`}o15Z$qyuFECkp^B@-LxD2VaG+SM)Ln7iPQkpwMnuG_Ja2lUSa<{HWccu|`PrmY zDd&2trw_y?e6&p7#s)g1o85n`q3&b{^BlGr!<|)5tZWT-iiDqkG&N8q+f$(V@)HJ2 z@ZZ6#E)IWe?(S4qdnJ!3@R4N@LT|Wl^gmewj2EskI9fOd7!Ps#>M>cF;t~ zQ1=q+J;T{bAeW5TXW?I)T6W{xWbRU%f1=5p&+VjNGz3W+@6X?7y;I z`a!0Nhhy|O-N%reL8LwJ4g#H0yU?;3P?BfbQg4NV2&TRpNs&Rplj}PTd;ERKiC4Dp3+NzNVQIA!2RWZY%@j_jWPY3Z? zZHm$C*Br=a8FvX@eR=U(4;|zo#6k6QGa=&Ucij#PkF~*R-E+DDgeNB*+%{G=r<_Q& zZIF&eYr+$=_MXi9{TW~Cmtiy}$`|_QHi#oN7yBG+iR}Mr0$))Tpn6Q2$sbOofGzjwNm($#8) zS_`DUvSwDK7WxvJs)6ucPF{qYmDhT#GwVKCE5s>HE!3FHpX>f9^jh(y=w=ajR!8S* zSjEZFj=Xl<(Qpv4@X)u*5Qe)!DX;X$t%vitla(G%_C8gDC7v_U70>Si(auGtw?eMM zCZxUsv%}kDw093*W!X@PYT(TR%HHCu%ItVQYoSCxJt`1o`yIbj^6`09e&W$&4K*Os zJ8&OHSawNUh`%81iX|+4r+@2jTmW{B8YklUuT2`sFrWiId7K{f$}foJGlzQi`&>hZ zn=eVOl%&irOph!-n@%Fwff2j!#tYXpcW#cbL^({STYc2{cD(rJK(pQfRUmPbpmRA} zKJwL$c657;tTi}3WnXBJCWpl>7D<;{R6d`MrN#7kr<9%A$K3Egn5uSe4{l~whza*m zDo29ya1km-!WMOqB53!Dc<1aQbk}z3+3`TWSL8$BNNQuXf0m@P3rOG%D;buk0z}XF zi;-=jNxuaMo;PUv&}BvpUs`lKWQ+lDL*Q* zH99~eTLp@Kgy-CXP=}x7sgl4E^o2JHqJ3a!h%G)%Kb@L+QlI3yGCr2)sM5y5>_Hm7 z93NtCaP7Wisdb^E6LRyZf%mwkJiLMMRXh*DXX8x?@vfb%C&N2Ky7%e)CG;P3UE$a} z$mVu~<80gW#Z>nwTxc|ECd%wEMsRu=>}c+=xJS}zLI2jv4V zza)X>4~93x^8;%M8pm~}(0Bi5Mq|tJZy1di{CHW0PYTn8vuF#2(B>+ssDcYu4_`g? z-ay67e{C#$`9L1?qHaVWSKUwYa!vy02(}~e& zuF+lc)El@X1AFKusRsWF+j}fyb7X{&ZGvbw&)~c`211JF@gax-=U8IN8h7L~sJkXi zMbvH0n*4qwZQ(hXa%cUgV^uri1GK9k#C^EasSW^H5z>TYZ#URr$_K?m?b3EMlh$|2 zCxTscN&S4POIY}AZ&0&;ec3S1&!1q^^z8%Gp0{VkE!P~yC1D;jIYglh6V)rXve%%( z8fqTraODppGzG$a^Tw%$cc#XZl5?U`=%#y)aTPD~RN?{`k6&qsXkmGaDXHV_&Ah-~*`Vq&u5m`B5Tv%S~Tcx_OknxAB)8JTemR1T?1zm{`zC9!&N zdu>!Fs2zM;Ru}nj@b74JkSidUsCYcH2W%&RW7mG;?lba;?@lzW@xajN{yzs-e{c#~+p#rMFVs&_+-|_O5q0<$L1cOj zi~Yv4V*%j*(>vJ#BKrmUtvyTbihU#7MVi~ZbqVAb|6ES~E2byy`NtlvQlt z5fgvRo8nKZ19G9~RBCa_cDPUImnon9Kja6fAhl?*KFL4t4S#uuhggZv9Grhmz6#Qz+!}GJU2T!=d8f zQSghY`^TlKN(0X|&NGll&dwSU6A@7W+Ryg(TmxP0Zc?8RzCL(Q?lK=-C>&jINCOL@ z4cs&kpt;#vv|gRrk|FVtFEP<0Y2#1W+dpnG^PQAuaO=W)F>j`G6+Quh4o*>FArDwD zmM%~5d9}cdbvdmT#a+39rB!BRF!S=NUEU;)c_4f`Rw-yuR{blIF7|EAVsOD527Ly) z3DZtkO3t^LnN-N=Y0d}w8?zq)vqI4}DLBvv2v@9CT`0pS`b{1PFGSq9p`myv7bA00VF7)Em|q)?oBc1V`uyN=&;0Td2-FjmRtFX|b?AK}tq ztOv|Km7muJswef_9H^JAeU8v-n&d}9KX`vL^&q(RToe}>)p$qTys9V7+Gu}RXkf;H zzR5g(qrJGFD;Z8KmKFMJ{ucfuv{92FpUF{4>HU7j{UVG(fGtxoIxLv}w@js~8=vM1 zHg;i>G{?tBM>>)fhydaMgC~oCVG0GeeY*Sx`+fqsX5B742mg`2aO>C8T8gpb{JmF= z#4n&&Toev)QB#m?c}Y=h8R4|BL-i=~o3oBbUa%&o{ch;Va4W*K&Q`7-Uc~IgG0s+l znVKS6`ThbS6+f#)escCIu2|CU1d8|vOaR?PqMF^T^D!24I0)8F}+ z|NAn3yT|#2;x=GVuU$6;8zlwOj!&_L)xQplS2*_@b)G*)gd4PI z)DpD-FniV?Y4g^?x|txVX+boZ0isEfAI?_4*_W~3YrP1rsq-x1 z=Plf897S#u2PMc6@ttLiwDal=pYz-gnQGsa5NwATXb_5Uu8fUYRRtpLVVVjhCZhFd z`C*4c1=NPKrCVv!0)Qh^;+l$0Z;Z979HP6L`p%Y#;J@i$*T_1&Vk8agp+vpCkm4&BIKhi>f^ zdZkM85Dt-)ToEmhK?BIVmM7(`8nX zN1N`|2DKCx*fUK94529TH)A5tNGTXfe6jJ%O*XRXRTJ{IH%y4HGc%IY#p>Bz(HgLk zEKmP;*`%4$6K4>}2~*?X|3em)Jt!E*QBJN%zro+2?1zA{%|J=o&oKBpdN;hxFH5Vg z`NY?c*~jwDLwy8G#FHne1JKXBF9r`D3RmCU9DUG*gvB)2Xq=nSZGw!pw8-Kry>xJ% zv;L675c>tMCdb>~=YW=Zq5*xkZI>Uvo`#Zg^E4P|ODnM<`b#tGJ-^K-&Bv`&8Vtn@ zg=y|#)6MzqOHm+`QF!pHoD1O6@4a{JY;u3Juxs&moLi3l^vQPkuCei4iRm|Mo$6I8v@j_0*N|Tcc?BQe zLsVLHRyNFJ8XH)R)D&A%!vqb~bYJKKhCRm4CB)J~HDd4uFy7y>lOc*6hUz-HplW zOq=ClO(+??1iOQ3szdyQ?zC97*-%ORu-fGK9zD<)rrMOS&imp$#>ruggd%&ZAt2vJBqyuqwygSz8f#Qc-Y38dJDf^*s%K%B0{l$tFhBrx#O3f--}Y0(?E84)C( ziQJz?v9Mppr)5vS^yNVz(|$K!wZ&AhvOCqsE*5kmx=prqLzr(_)MDh|ShDAR6pu%m zc+ZJU$HL+@68+`1iPDUx`$eu!F(RjDLOpti2}+68t!_X44knpipwG1I)_^4{q{a^R zy}*R*y4bC9WVwR++sUmJ)=al|uO!H=IuCP8eyo%0Z;r4pj9gKrf=9WJZ}stnaBr?n z12>0#OgP1 zLq*ngL*v=4;R)Hl4tk|F&YNDsh#)TFE*D5zfMrODYqWt2oD!6!IPBe2$5e-X%~7}* z1Jt_cZKoU+c?E?KSvau?VLO+QfdzD+eLBTYHq$Frb64{=RI@!AA;m2?1RsHVL|@|3 z9GtHPg5^-!0{df>&)DfQ)ck09{$se~F$UqiS-dEv9|v%XgZp?n}%N_f&*LL;a^Vyw5TO=%Y4z%H>^7Vm1RlR?wj{kCJ^LV(v{H zB`00c1tUDXg7218MC>l?(|Uv_*J4~x>nn0SH*DEc%blyf&nx%WHQ40D>>QeC_|=n5 zzxn%)`Y*ezFvl#{iJLbtTF~+62GXupAcd&D3Fg#?zzsbZdSaEgrM`kv+PmGrW7>SC zfV!z`!Zj9Jd73geSCd~_-{A7vTrGPK)Gw@lidl~CUOQL6qWbyEPSVP}K?4dPIVH}y zV}$p_y3!(Zx*}!Xff3Y7JCWfH&>Xj(>?}Cl7U5c$@jK&^nab0_^UD4bX+<_xdG=}0 zJ5MKJrkb!3fer(fA`OlR!<7nJv$fW;4h7`9V)56l%d|q((;k~s9zH3SyU74q>uFgoj@6u&{i3C`y)yaW2IxDw~<#9Y!kp@-fH9>|n3 znu6>}P9kRDyGvdav?crIRi`~Hm_->cZ{?r5!; z0>@Ks7>*-cq)S<24`*aM1(?Xc5xDK{uz}-P=zr5}Du>p9N9%Y-nb-Z{%s_q(>go-s z?-3NT#_6-p21(&{s?zuAqL%39cldRl9F%mi)%p;*r%05f&e!NgA=L;P8{*Kw>ZG4Y zZ0d9J+Bjllzm}Duki|fR-{aJP!*?@a!Af4~#6f3i52t9?+(5w_y(zjFMpwJoBOcJ^ zA!!@k({RY596;4V9+PNa^+-a$yj$~3giD0Iea!;>JjqAp+Q_DPj~+Xpa?u(;NK0S3 zuqaf&Q#)XF*G&jVPrs$dLoMJil4a`%5WPxk#L z46q0a!Xs=45#N^gLf6f%M3@;=b%g*>+v9HstI;Em~QS*3K;#g;e22ay?`Ls>?n$$GRPS+ zOOqu55%+fGZ6Y@&Iq+#sN3_$O(=qPD15FQJ3zEW7WtW{^dTu;C+1+ zn_&^qMru}z+|XRi=28Ht1o6*)9oAdU+j<)^?_JeRi^NoHZYg~skBMg`3wsq0Z z=?BVJX|G*la&pSiH!jdT7U>d)7}jD)R;B`?kOJbG%_gKb1@>GWbaQKLw_VvZ^WOkl zjNUbzNrj6SF?zbXGcd*bqAgZiUaL>*keBN58)I1#x?SD zvF%~nIr@HvT2c69@DL2O5VFk~~Z$0@y zBF2fzP^I*i+wrapuoe+2ZP~g>KINhd1qw%%BROAu%s)Wxu}U&0k^DCK3Tgyx(qxm> z#->CI@r`{MEvBfttdj4+A!rmG#ne110ah3e)}uYftNJNy=yo&Yuu7-ksH0G*;{b4o zBv0#_+^=)cvu6n=YyySs?{$ImkMO&dg-o;(3E32zgKo>lF!CiI-0FkNELjj;JZWJQN8WS zs@@pFr!eWBlUn+Rp_f-ucq*ryUx;mMYp@yAJk36Mp^1Y`Y1Zqk|AKyhlzWKJrjs7G zEvjW-zoMJ_WF1F%d9B~eUA6D-?}~Nc*gup7Wkt#Ez5kRA|7F)*r~#R60o4G`f4JIT zvb0$SkYb5>p!3@DDH!uSyX^CzppPLPEB>iR$2<^R6W|1(~w7f+FYbF7yn5kT~QGhM@% zaice@1bSK;At0jl0HLkRNNnlvx6Qv@$e#*4BCP-&Q@95%8ylO~h_Lu?zLYPwTKqRI z04@>!dnq|NxyJV|gFy1T0Z_l?P!08O0tVdK$@1m3-z*WSPehizv@|rU z$4=zWiG%RWVy+V63Uh#oU7C_a8Wc$B$nGz2sH~t+A_=_sf*W!8q%YwAX5(!&z&Y3w z5);#JYHC^wJJ+*HrC}A2h1ss=O?G)j)H++Jm8LD>1cszjp5; zJL|<0eu|nuH~Rg(oYtxy6h{=X^DQ!Kda)(TR4EQ9J4n*t+GL!+r<(J+o3fP}gmL=D zi%?Gb-3EZ`QJ|wMJ5H0VaN< zxbk}R#k+GCDJhLPf^uIiK@JJ$}~%eW6=YJpL_@l1GDLo;@FQlwX8Y@ zk(}T9fCPbYvaD?lnt!{qN6iZGuzn2!pb^)oOpW(o_C1(oJ#pbwj1-=@Dv3HCUdMI!ujOMlZx}BV zJZ#kUWncq7Kg2yIK*DP$^J@VY+dS;mAC`L%zOU1ggXA!Hh#rf{sz0L~1zQIm$yLM3DBA^;ki=}bkR`z_b&c=)tmtL&NT<8V`)YQaG33WPd21% z)xh4#PQZ-Pb27n(#6Bn5~AWP8`1`4X8*gBzf=9J?2c{p0#?&TlUk@J)+7 z*Y|-?@D5Mgl`Z~u;^Q}BoU(r-HQ$P54J0`&a1!BT5B*O)6!X%IwBV>7lj``+g#BZl z;x{h{c;L*6W#pLPpRj|6)v_0nZj=OH#5hR|Kment;{W3Ay@Q(U*1z8nkRnn9K|#6# z0t!m+pn?dYC{;R2??{JGf*{!Ggbpf*p%>{8K$PC3_adFpTYyl`V!zL`fBSLk`_7zm z=KOJHn2Bf-?|a>=Tx(sQ>-$wic8sMvR1a?|e>`9!@?9Q$iqe^qp11>?3FQ~j0A}Gsu4Z^!`v9UHBO)7@VkiYan zOUMhKM2nyAZ z%_&Fz{QlaD;X0nvYRA+Uq@~hmv*_Yrx#6mNRI8=qSYfrG&nL7d8uQLzmCHW`jd78h zc^|?Q7Lp}>$>}1Ml_}4)l(&ckE5e{()*V@<)2L*Fpi2tsM+IgVYQZs#f5i!YOJh^SJ|%btobu3hWjyR9Pdw^-B8CK++ix0K9VxhKBnakWG2S8h|NqB z>>s_rV!fmuayW`cLOcg@$GS`0I8hr`Le_nmy1~^1dJu+-9!m65J<6|WZgBTls>Xy- zu01}CyEH#jAdt}sEKlFvN9HmbX0*45WvS)i6`HqV`Az#Th|MP!8TvXLEna-NGTgI+ zjbMj0sfbKmYflh~{_y=(6DVyr8ynu?U;MryZR~fO9HADAKzBs$n9nVvtQo4OTvspf z2-#>x5;0YE?)2|qgzpc%Zc!?CHm_z}#SY-x+m-JRtxNDS{+a;~3njQm&UkGNU44i4 zy4PJ^ZXIdZm5K6c3hPJMrzq{|TZ=;;sg0&2h$6X`g!4_Mpik|)FI^Ia(vcFVLl~^@ zjE7SMztDzoroX7#oPDf&gdq`g=axSk=d=4k{k*ec+%?_G(ihb%SV-BxD}OWWdxC-I z!E)d3TfJwCa9w5|SR)(|)#py6VTDt0Dq&~+EB%g(b#0*E)yyZ*N9rFupO&u%+or$Qbv{_;PcO>etRu=Y z1G<RnH+hfm!F?s#TXfFx{cE{bsUab)$@Ple*vJPp0HLgQxYb*H>*C~D3uRjMHrRh6!yLnkisxGE|qPa?p z)O=ud43y>HLhX2}pp2%^!&gDgqJmNPgF~e8%0#C)=KA9JmYBwOuW%pS3T>Q_OYWh4 z+jerrXFFXwDfdC^fnx6+@wmS;trxvk!HKuAA3i@DC+qiCE<>zZ=+ur5+I@V^)_rmC~)Wb`l_woWv*pDs3D~dhvP*>rt(sHE(olOo~qP4H5o;)oz_zG5fBcSJ8lLZnOoK3N*Q|X2@4kB3q)@!c-E3 zTlw_;!%16=OrBwQ3s(m03u_G;H%uF6l5wjs!uEP)+}{KeCOUzCKTH z8H-MT7)iM6k~%dDU(1cUw1rz(xK=(B@j6{+%^|`sZniD4>TPS!sE9+afw;#ai^zEF zfyuX;lU3xWxB4#x2I9u@R!z6k*O>hd6+fvaJFFdn!^0tN=Ntxq>lRWbN7xE{eDuub z{Hj#{PP}bijCPKGY^R1|=$cMFQ1BfT8!g-50bX@4By~q5ZyOvv#`#G!(7C+98E(!Z zjfXnBVxL~QD$oNoHd-}+Q!{+E9JW0bjHQu)gYQ2PW{<+|@gh3}2_*5eFzyK(#*I`83E3^~VetMfl&&IBzmES{{ zr&@r+vn(OlZgW(h=}EFC+cJe57LsU>^H23fAvu+X3NKdhT1{UxZl1hdzcK;eUb4AU zK4Lz)KvLKrBtD!7@f;nzD0jD@KIB~kpO9P%=HDU(MT67NlJsO~=VqF}ev zex#VcZs=}=-5qRR&G1#rXl^c~W|b&RWM*yTgpy2~qv~cqVeQ9z?;?Tjh9Z{>uYD`B znw=-6#=2o#g}1Wm1A~}PFM-KP{L;*;ICRNT=|sA|9p7UAkyv?OPq=;?Ic5z_Ih%6-F) znDEEqFLtFTje04tUyh+*x~cprmSqQvfYS;U_Nb#IC%$ARf@P)+@^Vjn^YzAEw_x8fe(DT|(?uh_X+mpz34 zXbr!b`CxmEOJvk3iR^>IIcAkrMbwC3-OIeJ zK7QCAO_4m$NzI{LIOQ2K}G4GduE0# z(@IE!i@gMrr0ruEL@07yg|XuU#*PuljJBIwjGSAvKyr4pH*4$78+xfWKM`|_bm0RQ zInE-FQooA}_!lO8ikf{y-iANeVtL`GW_?rAW_$e{{_1t#{SAv>A1wSA+X5nNor>`kD}5B3sB>M2 zfvJr9wmTD9rywL5ealFCB+^}X{tzhPI&IlS#yD@?5J^WRYX!1@dZJNZ&7a;GG4$z) zWW$8yH(>2bEvyy9F6gle&dI97O143!lS)mwoP4lyDMOmnrAKH zz#S$exnh!QjGW!2g@|~4dM-Kgp@1<(IOjOmxHR1L?TQ^Z&y|%8bS4{06n?UIiOYt& zu(-wJ>lWYee$VWu9uZ?6#F{WoqUu6Mbb5tyIb42gA$)qa3Y@iqvXSZWb3*qM*AK7i zZZ1IwoVHnCUZq|y7SgIk^Wx=Du-NUdO6ZT}wgW+w_U4f?$@c0}h-eW`$QP0r*W7}Y zi4vLcQ80>^tP^@8Pl{~Hz=)V#f@CnSIgXUT@|b+hQTyn1P$f0Ki*d{)Qrec%Q2xGA z@KIrIEt@MP zqUkLit0%R@1zFu~m?*@Ud}tLebW$YYi}L2pm@Nf1>_%kXjWROB+RYWEVnr95Y&rIN zx!Vh-6^4Wx-;9cj#mzbCzk=#22N#+{)E2c}F(S;(0A}t?VmCovf+ZY!|SL z2c34aD4crxP`R#ba7ULxGY^~cx|n8?qi?rsm9G<-Asv(XD5>+JX(Qxv>9%9g8i2CL-jlA zZJR?xW<#&o-MRL+Rq#!YmdjnF2x5r$Q(v-pGj+xFzuTivA0HeNpo87+V-T|>z68zaf&3EIq(`fl|Axl)9YN zj$sWd^c7>5xi&xQ20uc6Ua^jO*uRnHSk!J*7edZh0vi@rxtl9WtyHeVTuJm)mo6c> zhvb1<&Fq~YsOUBC2`1qqY4gnUZf(iC5O?M*khrv$_!2YXP&vf(2_`z=oB4hW-j9O3 zyNR2uFz&ezSn}`>&kaF(Q+Z%eHG_^()TxWNI!o*QEsom0lAmu&XFh7Bqz&PV^5Er* z+;zO2#Y%Np|iKvmCjF%6L~4iejjqjk&y1SR>w1jOlL$QhUqrFV1N1olJKx zr;PH>9PKQNxfy$d z(Be#FLDJLR+JSMTaP~DgeBAufs+a>APqt87*`}$j@F;@cUuoBrSY#S$sXfZ~Z8{ua5L$dkM{Ma=cL%PHJgG^Fsdi*yfm z7|r}ox}!+cb4TS1fgX{r$!=-yoHfPdEmMX2??2zC8}whWhJy&FvQB%*+P0@8eGLE6 z$S0MAbkBmH>Kp14SWpDM@@%UUX_+9RDzLi2A@}-LU#{Ncsy0n#^v+ymcai1t$r_%I z+%ed0=4iGr3mMK;sO24Z@0Y(57VVieF4lXP<(pTv>0F82Fh?45Tc#M^duKgqx4Tfi zdSI&@wiD&GqEWt6qTeQ+`rLl+Ad$|JPk>epO`q>LxE}ZBCVWa9*6&S<0K2!Nt2RxC ziy0}cpKsN-yB%VeD#0!WWEHtw=2T1H>)8z?XFPw_Q3;Z(TXVb-DeZpQ6-4>k4mRsz zz6W-T*4&&zknyU03H_&|o!6iH0T*syuOu9lUkwd^jTM34|&`lBW?meu>@^&l49W zn{(saXoH$m66Je6NL7lKn6)gribMDX8g5NCHzuIGt#>vzMaH8r?Z>@(?EcFOw{RwH zD2ds&U=A@hwxmTkml0D}?5STF?0)}Ed#Wj|6R*-*bao8Mc;anGTQ zMM>!*iAY~9m-D1&gxv%)AEqQJ%s7-bGHm^YG8Qsk!uK#Z?<9}yQD+j!eeVSkSUYf= z!4iCJ-1aTiROVH9h))h(@-FabYx1JYp4kcAPSKXNaRF$LxP-?Wnw)FoBGJi@AHNrt z{4r^|cddwEOG{@Mi$TX$T*ZXS9GacvYWZ_D7&d;urP&NF!Cbh{2tj&}gvLfd1jG}l zyeHX8kiZV3MV4w;nPM5oOC3{myURcK3eeP5Tz4s?gWbzp+%K`)H=>PCg*TFGFgY-M zX;I6131$w99}nDC;&(m`@0F2Meq26o&KVXg9gqNyV?!k?B8q|m+CSLj(=tiQQ@mTY z&?$OC;-lAJ=d`MDCP>r9p8YDu5!RUv9UK`Py&?F;ru%bwuRxt^`-w5fh?gOLCdXU- zLGH2cbXdwmNcNV9Z3Dy5lV{^a9pbRus-?5Krgs`F>4oy~@=N+svZK>sMv=Z82tLzH z3m~V?v&W3I1)>$AwBy27L z*|k`Jbselq@U(X?!d5J&3iO21{Q@gKP-t4QXTK}RkAqi>l*XplCPDT>nEfLZsX1Ef z0*Tu164TiCRl}Q>+MAJ2(@ze;uCIn;JIM;)nsMNSdyJzeqrDK%DQ*AI+`Yzv9TdQW zvjn0a)e$G-IAm1b1EXAlfF}0`cuWe z9Zodx)$q5*Ulhhk4@4{pF%=+JPWw3ecsf*Hg~rKIe`75X#(Y!ErY&(cZHK9|O{oUA zJrzrKS-P}uQoaqFE?wKzybRBw@JORTxG8ReBc?`apS!;@UMw=CqOAEwceQ!^lQ0~R zj!qAVsY30kP3=UECnt3O9!nS0*QHQ2dBJ`>4R%rIBi%VlhCk>{DoLh*<9W?AHa!(r?>5&qiaH zvNYzBh1APk%cGIkx-4?99+O#t^zG*@+#o1o)93nl)fKt(DhU1RzT`}A2 zy|_%(csd_UDieG;Fv3y~^g;c`53>Nig5)*`gh0Uo= zK!?ukG`A7wWQ=ce@+Q~_B$8tZTuEk1$Nf5&kqIp9unS0=zRVWW(1CLt&|E-k|AJ=~ zg35(NGC}g&EX?4t=j#|zIrZ_{|zY-CIBv3Y`RI8lGqh|QZ|LPAw*Ufe6lDY=I!0nmj>3~=ODu@ zPxsCD)EbHRP8EFfMqPvdrZOPQ%$DB2ztaEM=%j)a2+_g0ThauDtdqdD`egco7;Va1 za#6Wga<9&z`3OjUZJ)oIi)G?8U!H(^l1iKy4#8We+W`K%0bJla4m|4i^)K}Si+(~Mle_b`MXb%ur`JM z%>w-E-@O3fo=CLd`cjtZ^xp8q!MVf;ND3#0g|Tp|B}WYwvzz;9#qf04dvyG%@{^zt zRDPOfF+`nuL%etq1`fMPNI>N$(PrW;VS>Wbq#>iwyW1?aX9OXts;abPi0Pj{&AKeV zr?)b)s%JkyP$W+Mo`eR;tC?4|Q=;J{Dd|m!5ek^5W)vCX?%lg22p9Q;NVc%k{EHVx zZ4JB)0hDGrIFx*Rs@hI&>2>hXcA$&PKeQ|Up%^Ei_TnCBZTv>+^t$NN1iAXx`g#%s zzW?wgR_G8&jdjpoCSs)=1i9o&zJHlh9GO2vxxQ~QoV}Z7Wo8nZ^5f6f{HB&wW53c} z;g#L+6)HI9Ar~EWvct?M=~STZ#^#A96%lS1yDnXwzqGI5)`t7 zHoqZEeuriKOd_`lSwLh&1i&Ne4m^&Y-uYQuLv`;Ds5P*PVZ0K``Wcq1ggx3RFL@*Yx7BB zGmwdGBYP%`N9&Zg>GsT|+91=PbUn@Gzoa_B+62#J8Vy)~ z-MIee_np!*1TVqWhA9go|5$YWH&b&46x5bYcHYwY<0JX|owwO!Aq-ck+s%JH*7^Gl ze_w=b9Z1jf?zyzl{2$*Lb~=SL%elnW-3W__pc;i3Nd4*75H!RjB)5Ud&e<|>Z+Iyt zynJP6{!I-{qWQ|ae?M;$GvRTr_xV?Z)DYCwxllNz*KvXy@p0*(A$o~`4`%s;Nx}W- z^g2|42;{Ff^REQ9Y!~T&GDCsKyO2~+;tRRh^>Vh5@)uxel>YCA_%-<*MqCzBGc`3u zMN4bpFG#6se4gRzRq)tvgY}Q$LQk7KVFE&9Dr+h)7=2K5B3F2Qi2jPiyP%erK_=8w z-hY}&CNI2rNy%j_sk>z8XQ0#&^b!oTkF5E^nTWtG^kgP!$!W(;HqPa}eD z1^b8(lD^*+fwPaR7M=!Po76MeI%?2|JY8C7SXq9<2+gkk@;(3l^_lvlQ)1J%PK`9< z^m-~98uKhfQZ*uwD(LmSR0vpkFHSbkc0W5crLf$ekK|NSS{{zzN88+Af95p%hvx=? zZjR!(_)A)D1J4oFqJNoEJje&J0%^aGvk>tkJWfdeY>E(MwIuffK+6gL(1R&w{s{(6 zvRF=Sp1jSu2Jt{>A|JHkjr*)K>t+`_x+($t*R1sSL;3fw z0bqS&5Ot}$PuZjbW{1(<*-_$|a6}$W?b=}kTUN>Z50)*jQmpZH^&|e6zK;2xruE-; zBw}vx>C|`!Uf~yD;tKTKEZ=^{^H+Gn?O)_|*@}IA5(fgK=EldrZ>RrAC@oCI{_58Ecu# z-voNrk-(HCJ>=w|Rd}(xys|e(M?cwGb3!JtBNb_1?V+;nE6ky&cRa1C9g z&QY^n7$sKurY(7^u(2rdl&zqxVoNCX;e=xk*}a*Koa*+0r1zCmCs8FpU?v-x9&}_> zOKOZ8Y`hx<=~aGDs}n&!A{$^%k?eEEVK5cNAnplte69I_sj~5>kXgBuQ(#79+*3eB z23Wx&+2qgS#LdP-{;NlVMI0YII59*M7iH6Fl4;*0;u0HFmxlNoq)aZV=`J#;sd)ZX z)VuRPuC4!rQu2=eUzE~(>UxnO+nOUR{5IB`f+{3eF?@xnh#OgqO#zatK7&^K2U(70 z{fXA#j!?K>WR20CPR$-L9}2+C374vYZD# zxE!q6O1zu%&l$!2X)L3A?7kEvS-=*(JW^`>q|#$IdJKb0?CkogGiSD!bQ3rQ?9WUK z&22?r6R=c0rG-4D9Nov)hl2Uq_UD`4#Ay_|luf)_>^c?$f{BeY zpXOb02LUiQqkx-4KF|01x^3^IZLbPw7r0-fD2S*qb3Vhyx5 zT7N^8VDqhPDoE+UUba=REQ0`N_9Tw04o!kcE2W61ddO59AUth12@k|FBkQ-jQp+#Ta#aPg(1Bm=MJ^3k9*W)Mj)7m1ZM{?Cr7+> zkQNVP8uK0rx%cWqd-FpLHO;C!+gK6a|JY-Vywb;K}?gLtl7vJR{K||93^hyYMl*fb-D``v> z>&0lElyuvn|99~#5ur9G3Isf7Pr;p8$;r^_zTBH2T5dMQ#^a|)4o+{2(!c7SFT^^1 za5X+I#b6&lZ@q6-rvEdMRHO|wSZ8R;)hroZo>P*osJ*a76(;TBFBo)9 zt1w8je4f|3D?eH8-o4?{Q;*NNc0()tS4X&AfcSinY6Q8DD{6hd-Gonuy>}NlLApQC zu)AFMHOH=pP^Q%5lOcau$MO~b(x$Cxj+RWVEUBe39sEk7TD1h5@iSY-1vF?1X{Q=N z`~GY7UG`(cWc)TWk4Q*KBh7hY${OY{uG?!8kI?&b`dc!3SxTB_towVBea_1ZPr2-& z78(2x1LsapwwZnNm5zbDe`WSMnMEf^*V2C~Ff7~?^1|hK*jr)4P*pG`)riswACY#d zt^{HG7(ZXabh_jWDa2S{8?Z5N{`nj>Q@S$3{>U=o(RAN=B^hAwb$iZaACyCS8FbPt& zSoC&g#8IR*)WYXtO!WhC4+lOPUS3DFX;_NhOL2!~(#=OX@pFDgSH8cZi98^~ywXN- zaIyn4hn!RBz=e#56MxdpcAz!rV#EC>Pa+skzqb4WhVDdaVWpa$ z5XXRNvFp zCYW|RRUr(FH0&=eIs_LaA3w9QKO))Nz>_l<|XLW3a za%qXtTtEnE`~3SPlBD9JVyt7F!<|n#`u;KN`47sE-YIpbSzmeiO3CoC?7YXT{i-8# zX|-9NC}e^I`k|nvAHckJcN*TtCrCv|G`*dB47EQwt~8Dpc9_aEa5sh?#FDIF`n>MN zi#T$pWE+{vlukE<3S#BIknCP;nNP8ginQ3r@Z^>m442q0df$8u;2#UrRP$y}s7xGt z%4>jqB}ZN4sJaHInq!k$g_GC z*q8DN-tw6zi+z;|z&g`?{YJjRqTmK*V)Ae}3OoFM{O<$RS) zeK@gt<#<(MEunM6kISy%lc{xYTELNXi&fhqke%#oc|%v!j;&u)|6=vfYyCYgy=337 zE5s{N%x zvn0#r6g>occ@YP)#6-LvZo<=;=Cj8;>i#y zmvw~Xl;Sf@GRTaQo?!7i>_`^kCeoTRBzja0{mvnbg#+sKIRs-jH|4l&f#T>K0m}il zWJPa?yIW-<_Ej$$MT1hM^xErseA&qQOrFN$&nFuOSeLRHJ?!$h z>BPtPF9xm#4(adN@MMeeSPq|LW;|-{J6xW@{7EW?6`+T zhFZ+4nJYXnrZF(S8;s&5#g7Nqr#`OKGtjNzWy6U0Vr#CcoXPj=5NaC8*JGx?Byr$H zA{2m?rA`x@dVKISy+(~c6T&3+Bzs}B-|;~w@Ah6ZwOx%R5QxE&TcG*5)h=FDG9Xv)xf^cVf~v z`+C&Q7>}-@`Ka*kuZ^N9WcHfqX@yh7$do5;!8IwErQ~waOGRKP9 zuLU#ZV*j+*ew}3g&2I+tAHKV+?D^37AHchGp%pn^sgvIoHOxzgXy2#k#(nVIc!KtO zyCMCLgR9h9(mi^pCHtY4AgJ{4$2bLmBL=960|CL=)c*nXXgun58e2>5qFVVq%GixM zZqRbf)4<4-2y>Ofk`(F%$PgKhZ;+k4X@>n`HNe$VcjqrqPZ6-(J)^#BHQ4w26jK^@ zu^&$!kCAvtxV?#p?=uh!4cpO3PGjk7= zY<&?ImPk2ac9LG7^yToeNtx3V48#1W4$aBW(W!YSC`ePVs)FCKRwFVy>5%gRmE5!5 zQ!R$K&gh{n-VU261!#y}bOzzKfkXfADaS@ULD-cE$4u!H%h0SHD@Og|{vQNSDdLvI z;hk||@>vXkI`sRYStbs=2Tb#}H1Fy+XKCeIM)O~OoDgG@Nm3(FS0Y1yAa4H-b`k0fV2thdMw zp-jX$=Pk4~Lp`l!HQz4Ub9w*7n1SCj$iS3osf*jx5wJJ+@8PW*&askad@!mpy(~HQZFcy} zLsDz2XMSY-Nn%!;$}UCM{WJjU0E}T~Rt-7I+~CAlKSCa@O&lK)DyH~J&3bRG2W6D_ z4CxonR<14cTW2lP4M zkN_wb<$b($74x5IM@c{W_g8Wh3+-%|_}eqyF@@Q7l0_#|eBzb=4_eUn9UCb!YW)ss z-dWF&6yZjqGxpm3aO>krcigHy3T2QWVi}NgwtopMWb~rS=+V96F_99}j1u>WVU&iY zXO#ym>bk=*{*fI{&w-%UylwnTk&5hR``#B%OAb^5X>ycZ;#Vz4s%;%F*V@n+ypHKi z7S_hvSk8ZM%`5A@o*=>94hK7ohL3%Avla()p5EVX)>KUeW72AL#c?kimxfENnmz{P zl_1*+OV_H4Hs9b+>dEQ(7vM*IcuRiW$Zu3fv>Ffx#x?`HrWsJd(E3uLe6Efg1;#=}A7_A@Vgj z6|Pa8o03kdJOL6}p{+efvlyn@)m9_8K)-oiPboM~>LF}YAZHAx)JXT~)ub8ttUD$> z=*)q)PW{Pw7o3fhjEN1%*f+r3b$1oo=bdI^-{&qF`GykaS6ua684ewRJVMU*&%RBX z13F4AeuhG+);*TXmJQaI+dZ}}TTHn78tRXtM9U|uw#=8euB=Q{YeDz`I5#4d9YUep zbK;~Sg|^#&q63i}x!!2duhr2?djy8_T~Zhc$7sKe4gEh4IsyFk=Fa4D zP|Ywt-c1jBXdSEUnZL8=pj0S?<9lHE*&%Dk}zAv(6VNM8+K*h zeSJE^QbEN_*t^t5)n+k2T*1Kuc9~DV#K-Z@U_3{VJ$D5%ojS~P=$971aBjZPf>e*$<< zoUc>Z_UA#O-N}l_;^2GRPjEwp(sj3 z@w~Ko5M#K$B{{BvDT1m7H&gBe3%7|*m-}GQV&L@bQ z$M3IRp3yt-YnlvqXWrrf#-c>z3}0wwI?w~&RoZ+0UzVr`Bs~^K4Kov@N&sYMm?`=Z zvUgf1k>k@RRhoo&glu+5%!NKePW1QTCB{gb^qIdiRoT(zmTrf`NPuTPKRavQ+&y3hB%s{o z3I4lBZnNg2vn=}H>C5u7Gb_AvC%EA9lNSiFMUgLFu{gye&!U~amaIRtkWIhA3w=)pax~#ipHu&N;6OzIW z%DQ6(K*XHfZtiTnqu@tZEGZ^4lC_pDJ^h;n`0R+C=zUPHyX%^$o2kWv8O5J`XmQfv zW>KSLNLUWG`@-k?A3V}OfOzh3+L|xNlDIn#KZng#a0@5xZvYMnQLNMH=U#3z2G_#g zBHwpx=~*_%U>X6c+Hnoi@9SIqRaHOao&C&ICdIIft!IJX5urX_Cal;UGu+CX;EN=2 z@{T?77V5J8QT5hPT(lHASr-^Qk_nXhHL<2{G5cfXE~RA2N#+HBN#IyRAE6hRY7eBx z8g;WS$vi4=(e#~2X=opj6w9qSE^J@slxR3EPDj=D!)vR>;1C=Y1VkHrFj-rgk3fWb zV)||{dDvygitzz`)^?mEh|QjkjA+)Q?RMR7*u-!Tu;&O}^BL6)xtCzm>whxF=^tC| zw^K)yQ`VmznGkEET5ahb&z?`T#8hiR=gcX{B;ox`_fvV;m$j}2UV)>-GQ~pg9laEM z6UOxiMU6RrL?!(1zwqMcw2nC(xEGBPou<{7^+!jp2l%`ldR>M#WYUuOeq+@0sv%_9mEV@*?A0>B%$lKVQ$tOYdq5dK*D+P->9)dE2cE5(lxnP2M!>eDC zZOi3@E5}knFyjj;xhHKv9!S4~e}V|6;<}^I7Au;!GH*htBi7B!(NYLs%~aZ+Vsg&D-DtLW_J=~&YrlK0s7;$WoH0*Sk`$td z3UV5)2WH?tAcu?(N+(JZx+>8N9_yzk7#q_@HyxfE>XQvhy(tp)TWKXh2zd^`O+m@w z+yuLJGICQz!PJ+L)^Ob|LH%xxyM(Ma&{cZb>@k+h7S$K6FNtJRu4PSr~Tt#S_ zww-lPs(r@LW!DqG$PWoI(h&Dd!kuD%j;1ab+rAHkjl(|R{(5^ehu`Ski!O}wl>~6D z_j2ry&er%o%(As>=+8SG-^MM!N*^&S97pTz&j-aGBxki1w&HeIBJUDW3}sqjA)Y}b zDirZba#Gs(ruMTfhGz4361+dZ=7Z7Mezz(eG!lN(Ukl5M3T2SC%X-!+wZ@=hp1w*m zQf{jAqZ(FhP3hAev?xx9wYl$mI%r~KV%g2%t}w&#!COuq9f0K4P0{O>^G$ zJtzZZCCZbRETFabg!gufy?|WjAUF(bM_1WImbWy~uBI!0a=%@+1H^ z(>z>kCn6I&p(X?$KDLLJZql^0f&y-Kht zAc!}*>T&)2+=-&Zb@{d$up8M;*iWR5ByBY^Y4A|)kXe(w46z+4+?OcoTs{YPT-a+x^6?q_7d6vB zFo`PhCROB2Q82z7D;@Q9S_o&XRQJUjdQWQbRT*S>kp|8MhB4zPVK)l4q>Tz4h(z?n z!B}RBX@=B+6&ajwF;J@F*|T@0PT_33Rp5f3o~ixU&KI-49Y8kLYJlzQ!%f~UQu9ix zP#Zojr2c!%JXwqwXfvvRy=?ixpuBK*LIG5>N8p&sINKwJbQx=QqsM(g7QjOH7}Z_r zAyVEU`Q;;pm86Mu-cGV#%Rt_lUowOQ&k@v6%y*08%>g_%2>C1h=da~tK?aoMUpfY~ z5T2)ns8pDwn?c0S>8tEw&C9Y(Phwin6}@-#H2V@Hf1ywy+-Wm*UyQe zN0~SMpG@Y-ivCilHKTD~PE{W)WDQ*jlB0WtWRyKRrWMSYt&wPl-N;_qsR{qxp%!%I z8tOV(Tj57lnsmbFVCxc|r|jnRfkZ180PZNOuVLTws^WpqS*<*-cb$uadsy?F$jv@| z6r41J0of=LRCsH=#&rFg4-4LNvyS@)eWDJ~Y zzIA33Xre|u&!KZ9V2=i5<5)7HU*Gu^{s?dddCF0${|!J2h*Y2vBNuA=U#tR4%_$y$ zjC+zuoEQfn$hiHdf>69uwVf1e*8h!+m2Ai9=T1pdmM)NS$M+4s#0(vx1fU(Eo-jEp zc%cvZH&pS@bJ1kL%gxhCF0jzCMUii3nKJmh*NBJkKh)tthsUub<7|CO^f#F^7yaiP(JbVk$Q&x z6OI>f$~axxs=Y?pWDhQEly>frcqTwr8|b85VlwFU*>6L*Ftmxe*g zrgxx&yZ4F$(W#4Fz#m>rR}k{<_3OynDKto4kD&Vnckra0f`2nI{#S1a_NuRB$4`0Y9GU7X;BA0vjg7swv9ZB_(r6`?_ed1iKle(Q z^G|3L)Oa#*LJq_VQG`0lQB6(vNhl~dA>@bFra{DJFfbJL?HGb&O-{W*(EsuV*+$Bz zcRy$Ih^7et5FQ}qckj>FEC3Bro?RPe4s?h>&aSJcagws>)byxiP?Q*8uuho>Ap+G?xh;AE%*0M3$xHkbB>=(x z{#hbq-3bIo`+WU&6z)y{(ibbnkuBsyk92V4n5LGW&h5JS&As;zDrAbGaqj5@wi8`+Wmr!MUPRc*>T zai#Df@h?}QyjBKA*%=Rqa()5>C;@u(+#hZL0_B!nZ}mm|-=QS`_?3VC!~c(=Q^HbN zB_$;%e5aj1Hi97uoMezOv)ZXSxz3pga^%>I$ zxMTwIgAsfLc+L<5S-B-$}3oCoPdGPk_annT~Li8zq{#ql%{r?b2%j!Jzd&O1K~f6 zNlG)Q!nAzQa0Jnr4xh@1!4F}!}ssawPavR z;QZpk`%Ppe{_kiz@OQ*Y0rgMWsAbf`{i4ZFiT)g@`!1ARiISH-0D2ufG6W|QMrs6X zqLOA))RHB+3T$C5dzq|tq+g@|D5lrsvX;>_$W6p9E-v2A-_-@g4eP+l$@^%lxsS!< zOd{Cw`u9W1Mk>_7N__bbJyHV{$U{W2Y|Z0O^5Nozvs1IIv2s|`Zn2i=E`jr5imizXdqp#gegGL;8bl3 z_9}ZgSs}1(er(*o;QmhQBW;NkwJY_%6$57Z3_`L%n~L&57EonG{6>YsO0lu z`<#7hbZy|;6-WmMbI9*!%>SwJSodE^BJ#YTg>6tfTOD}K6cWXm1OWQYvApzzrWI50;Dt4 zi$C;c8cO+zuee6%$Q)k}BqWdQMQJnx8|n{zA(bA1X?|l3n+qR9Gbx8;^cww&mu&aV zapYov%$$@wb9OE={9~}Z7rCPetvToP9{vTy^rf3>YS62)zxh#&1&w@FvaCvoD*t>c zq-{|asu+e4Ia?d2@j9wy?aFiK7m`uh-xSJ?(KnozUp4J&yf4K1KgQp9dOQ48=Tzy5 z{fO$TY#A!<>It_aIPUzBA93_Y1OinlEzmb^qIjx)2fn8hO8CuS&_|JyQ}| zQA(mx_LUL081;1NFbWv*&Fh}lvRl;O2RhZzR{hshJ5mN!y=OPI$Yd9TmTTQ{qsO82K*-V(CZ zjU#v9+$i51Dy1f6#MZu*c4cO(v$eT$t$M}2tg2AP7k4g-ihVrHW89bL>+%29-djh- z(KYX)GlK`W5L^R+5Zs;M!GgOd1ed@BhXI0w;2PW=1`qB5g1dWgcL{nrzqRhUdB3~9 zcisQb;g6xG*Xo|$yQ*tfJ^QJu=jXbsaVs;7{}6XDHK29uh(9~!sGF81sKgND;uH5Q6zUf+;%pJtL8c|CDh)Ii;ABPF1L(r z`4{l+-P$!UJnDbFaT;CSy_*Fl4**M}fgK_FL}k%D z2U%9LZe;03Y|gyFXqk`ekumv7XrJG?AR617JUvLh=szUZk_da@S}+vkphUJZtLzLbUOYV!sdU8L z$2sPuRwv%}bt^`F*Fy(_r@!O_*4A&H^(ZELN1|`B$`)}IuGep+aeIDT_x$15?Cpgj z7ey10t1ufub0DD~5pdQOQwj2v?`irNu*+fFE$Ox%6|_il8ywz#yLZAsk+5)+(k%s$ zhnlMGCJpnHl3(nMS*|CMzT!bzN#?ch1>p1b1Y5!NzR6;e7kPWm51wNsZfd=0!pWq~ zCl3*KPUqhc5zje8)p8u}Q(w_rBefVY>our$hmzv5jJzM(|6S=d&&pvs@m4O8BbQmf zTyk?rhst)oHu@@c>Naih_UGYZt6VY9Ah+y}7s|vMP&yx|QuDb#o;Qr$)GceDnP!(1Fxy1 zpz}T-nxsNoGU7@s(y5q z!KbH(90#|tLl_u7rv_0D9d0jvTHLkmCQ{Xx zs845+R_qoVf7UtTZ;W;IpT1swJyy9v6n#Lgab!>(w(M1QSkFFI;UwsGd%!!$5YMbj zU*%kN^M!#T<^*3xFnpJM#OTxE%=284J2BlFyQhaX{qd!E!R?2rZMf_}x^D}!-gi}= zl1HU-lXQ))^4cXvYM>|;H)*2p)v)~@CLQov7Di-)-e- zL$Y;}ubvfuC1Q~sX*TAZ!oh#3QAp+8(qbNJtzK*`5;3?@^C)^*Pciu1$a7RSjrBam zUn?KW;61>43vcboK`yV66ISJIm54>y>*)Uf&X^0_E8V;ITwSAPcjQ#JZ(P?OUZ z3-O43xq88MVq$TjTK<&VZLvZUpN5EgP(wP`wOo?=V*R4 z`g*s$_<{6V*@w}KkJSR+rI%laep>>hgZ08Sn&yi-GITAXJP=u02t$^m&A>(?=jJYn zmy~X;s=j=mkSME+3a^zOMmzJD!3 zm`NfC8^eVkwQY+#lFneRn#1M?RnHN zvA>VWfi!`-62r%40w(<*uRyIw_lkY--dg_eo%)l2k~Vn*i3Suh;F(t`cQ|Nt?ti?O zdz@2b*_BqrCOHsGlDt%G{mV)o~>%*@Ffn@ND7r0rF^464k5}L)T3CxKUfQkOsj+8C^n_TVe0fwB4@dj0yA*c0e!qm>c6a=CpY+k?E2qYf z=MVQK)%25Z-J0Lma+seZ_CCDjSri(2J`Fb_s0{SvIO8=A;bcDb+*-V^)Jdo&DdQW}T>U1}B8!Fso+%I>T z%9?b!7VaBff@HdF?yh@D2ZdcT&s!;+Db4=o(xGDS`vAFj&kd%*s;MPH8-9Uu-j=R50+8`WA;hNyJ2$0qy7Ma2^AZ;yfv!eX^(xu!s)tpTtBA(uuY7zxKOWw>5r(qL=|WQm zN6uH`&ukXzo;Mfr+qJ_!bT#2B|L#KgFT;g!kUSd$U_bw1>@O;`}J<) zn!WEkN0WB;ZBx@mpgU$3XB!DnAmJ%w9TvU~<;U96y}fYPsd7)%pK$bZ7#B;;4|p&d z2(o}teI>YQA{YFmKf4e=EOM(Z!ic{VFbB6~VAL+p2tnVPAWnD4;`Taj3rB<}Kddzt$@@wGqEo+szu94<{Bq@(rxlVY3xxVwv#$I>s1I z6jnBH5>!YBN_R0rX?Q-Ns;r!j$xE%Tw0BAu6sc4t3H??F$GG2)WOi<*JUde|m`gnQ zsI(UnJD`?7^cMaoiwqU+3^S}a-P)Y>HzuFFL*unj^6{Oi7DHMg?APk8Bt$1~ZT6Dc zdf%1Ap}XiCRWG~tk@?Wl_~-df)w}*pN)5KF809{1n&g&w0v06acf%07&D!P5ULh#! zYvv!i4>zP`a_E>V6;l}+#R=civ%SjT+Z%o0;g&AKBWj_S+Ik@cw2cP0QZfZz_=Wwr;#y*iqz})#0FVld^Hys&{rj;y@|7K1lkqm?W^*jJ2xUzSE;3{AyFnsCPFOYUkttoy_I_j%!z|o2%0|X$Ie&1BkOt zyPOp#PpZlaukARb{55f$16K-vm9^4C_a=F;bgbd+0TC{srSVP#l*AS85+v8*Pdjt% z8(wqMPn4(p`Wq-}ES5BPt*91B?Vl!SHfYAZx~*_S$-ZxJsy#mt7Hhb;Q@ycho0~bI z9TXh0!hul}_{+3DG!GuNp^I~AFlj~CJ8h|f!fn8tM}NnJLi9KWxHASP(|3Z_UIiGh z9D6PA=oa|eG#FV-mf>$1rPui5_K zxVU2V*g0sCAfoYIOLWMq8fdo9pq90wtr1r+;-@Wk@5?jgd88WGmiWYl(&sdDf3{i6z2G?595`!y z3=@lgsijo4)1=N@#rdI^&S`6qE%_X3#jAd@TNLs+Ok?DQ?GPAjz1V=+?K@j*ROSFF zkHf)|bvVU-2{!QmT z934CpJhM^!Mh!~ozoAcvMy+sxu}zOH8f`F6Tl}JWRgjh}u&6+@)QTMc8_1+uVxEQm zC(sMaiH(&CS>k#xGkJF^Pxv#z0xj7zj%T^1j%k3wz-;XiHrm^hEWKftq^v8X#f;_W z2q+ja;u1H+QAFXztr2A0rg5$5t;~9r`cv?GY4QvF0sT(0qiK%}M4%ewZ~>?H*N|SE zOL?EWOnLD2^+`-pUsVkTsfcXqIkx0Gwjft+@x+WzY`gdpEA3~`_)N=j<=K~!i*BC| z(^$DlP~GenbB~qkeORkoKIt#R6_^0IdurC*&BYQv1HUq*t0*-03OM^t_Q;*yD1vx*VH0laC4P3Y6B~G38-5JWzX9H+6SsJfGL^>~PVeIznRbPTGeW z1Dk@QjoJc}oU8y$WRfNL!0z@2LBoL=qPw4k^&#eyncc_jYMjCoG6zlP4 zhpcdJkfu`pgu_VMRD{uku*sv8$Q$1je}A<;$ZN>E_bjcE$k27k7F=gBN|gJ4@2Nnz z$XK&AEc{HEQLClI^X;kdY_oL)264%m{U$+`CdK_N<<88i{LV~aD#3WoL9Dst_GEJz zm)%?&>M)KjyB5yAFCGex_`GH5&M?=RWUuN`q8LPrF{7fp1@32pjQMT0ba(=!IE=|a z?`KLQKrdh|t$zP8O%zA{rKjeF=usP`&s}d*wv)x%C!0>`FmTdq{jMLU?*|x}!FA2;?1z7@dG`VcR-gZbN^hA2$Y?LgL^TDaix2uw{pwV+E?Xi z+OI`Kc;BBo$5>{Ch2OJ~=gZ;eF&znVcpP%!Kl9J{(k^jB8mMC65g(5zmb8{8-1r7r zky{ujFLh?nmK1conBm)*qr9AUngiDZD&{KUlxylvy9+J58gY*gJi|GlURrMU&xxr?oYcsUsV>Bjl|lb%lfJ zyjOaJZ0%HRpDupG(qQj5!RGz*(pN+e6T(*ca$)+z-eEIU4EOr&px!%wWMXPT#58OH zm;n~KkL+LY4h}lv0-WkGc@P|Zo~xrEk`wggVp)kVnCJc|SfsUdBtI5^bs5EExr^AG z&XImDK4>6rHIkYs)`An8fWqbYY^jD`yH=64@nP+}Tg~X|c6<-*LPA2SF9|~7okD^d zD+SQ%@Kznz-c0Cp8x4`R~w zCcPM;Fs~Dg(QfnG{Y+22qrpTKG@u)VfP;-EjL zCZ?yPlamnmGc+k4N3s+d>>8AZ+glmwRHqANAkKPk%x8K{{ilb7iF!i-oiBSah;0b$aHPC=+ng4UgvU_Zfjw`RF$`& z68FF1MlQ+f$w1_4f|y#lA>wHBKznc3a_2U9KotqPc-4+G$g+t+$A*JqBM@uc9K1!dRNThVYcz*4B3~Q;ONSPKcoE` z|9SG6j08wI81Carv8cGUpyiKUj@3zi6b>RI%rCgv5W4)?0fS`}SP_=#x9DEpKQ!WE zj~fda0y%c%*+ru;qsj?`5dNs~_p zHx{hoR$5kZu%+Eb7AHjDev5v@qor~;G~M0IV>vbwd~M}64^^!2vt%2(R+^Gp*11me1Esk!Ne`z9E+XOsq%NBh-{SrfaU(e=uN+fsna+(cNsZT}I-u`whM8@&=xR2^4Ta~(| z_^?v0dWSC^udM6=H+y8TYpAki9K4Yk;TMi(>rY!SLfMA~WLKfzuP-5X{Z z*2wxnniO5>RYx!)i*Ln^>LV*07G~gKrJED=S)#ymp25z!RO((dZ4L|G^5vxd$a~#gzh{Jx@*Mxy)sfm>p z-5PUCKJW}4%9QtgSm<<^YYulRyHhkj(t;X(jdw}0d42c+gl)mjp*Tx?pe?Y0Tj|p2 zM=r?51tf8NSFIpL%vEi~_ksVjZq8*%LCr@MT71SN>bp`k6gz7|o8-cnPYro+xJu3U zP!fC#tJiwTkDq)mrj4#FLQWmc(=uj}j8V}GoX~LRtm=-;dcx&kQ=QGwz3*)m->+($ zb!o5Q*A@*b!TUI)M&7@rXg51jgJTyo{Sjt9W(!1o=>(TB${kqdobdO9F|?d_B09+0 zWGO=g+An_xp3lfK7{YCyr#{Xqynz;rPrTGQ^-|2&9Yk#_*s~@Y*}t;Wf8-|pHc=e^ z0?iR6ysNQT7ryg^>8Ousb(r#RfKFsNc#ws) zdqyMd-UM+F|lcFRC~awF=#yJvRf`9P^{n$$a1=aztp?tn+!JQwZCyq1Dw3Pp*dv*P=p}F zK|LjFH{tB=%TF-IC^TRyMTUxSF168ReKe(>Yyf>-*Dep6+d&{8GA1i zVzzgNv$ujL*)YJp8{28_V5X>uI=a0-`-t`#lPhPnL^n73oqCi-odB(h@|X^&d+RB4 z$}8fDRfK8Wh1eO;QC4yf4s}W3;Bf1sh!tW>wPokmlWUCK`Hok}Ciw75r6eW-37!v2 z&M_3z^-|A4GF{9KSjIM?df{sQ7hgo$g+p%=96n}=TS$Z`YYiTP!WBS)Rl^gzlMU@S zZL2r;n!H<4s&jFm(7A$m1Oij!8?C&38G7=n=B`{&sBWt-Q>^ZgIU-~Nt~b7F-gQm$ zynX{DE!I|^Nvl5Nv6w>_1PX451%h`8q}7YOr(C+uNXBa-8Y&$u(KH#<02td1#=s?9 z8_6`&>uD-dEzHY%X$JDyHui&^d&oBX;ubOM(l!RgmBr_gD!iCfbV?>o3*dNY(P+NnZ2 z^Lw^@S_FErK(%5zl98Fz-4Z-8%D=G>GOV;nG_m2X+ile)TmtWZ*)~hXF8rR%V}}cG z+43i8^UY(aaQYfi(IzmeFuv1z`sUj$fkZ14mo4W@))TsURiNJ#7mp=jCDA)T*g^h)1sAXp`psIvWE z=XRib(;SvLsS)ipDFE)>&G-k2srtq`IWcHI36ggAK9(%iF5&#i2Ts%TUa(qnv2exe zE7bG3f-fs{2Z0n1!amI2kXvohlp`Ig=8Q{Ep&|0~CCE5TQr=@oE&++k9m zA117Wo&xNu50@KeOS3J#(rom;XpkEgRY33?*@v*H!mug$7ABgdyU}y5^Fd^zHXFlo zf3L^MuqxEhvxHaoaG?iDJDsyZ^ZP4z^IBFp@Qkhc9Tgg#)gScw;<)0BZY2rEi`KR+ zf2f|2JC36B-1ZHnOb|8lZBU}Gq7wts`Di~4uzgzwlw1V3rekrCEdw8@93hMTwy1y5 zM6bgQ^#vQ5xWy;x>5rht;^e*pHS65{A6rze?NSImX7_>6j$GdFsw^G7Gul!nWJhm6 z(r@(m2uhv1`Hrr?WQY0VV{!*XJ&fGwOAb@=6tt>k;wO(4M1;7z``3IbZl-Rgo9m0S z4)rJ6DGst?(%}*%d|>7^Qy4)sop4U*G3)L>S5v!8I1nT=Wk$Tv z<=!JjdCR!SXFu0eL5%KjtJXC$zB>@uwgm_2@0{(@LwOO^U%rBG>_eY}vh(ci39lpV zNLZ|FlzO0;#uN4d@_UteJBz>jl@fCq6IUms!z8Nfou2+w22xxxSK!@~4cbx-7fJN4 zW9yFeeAKezsI-bNKEIhrl4LTT$i354yJ^t`()+!Zx1Y2Xtj;rJw4RSt7X?f#)>&`a zskyk17?*-exZSB$^VNe&j^xa{Q!;J2yAHHzO1kNk?Zptc zC=FRA7p$3fOVv^si_-^ph2KqJfO11n+I5aOtIs{ z3@p=^xtwrcfpm!=#5YP%rxv)KL0wbnl(KcDsjz((7>y5kYbG1ZCg*pc(-3ekf-_|i zjgbYxvH7dfh89)=@1+vX$3pNzd14{-W+&eS%q&ZOTQRjNO$opfmlsIGLwL~2j>0r< zJx%_6JH-L{5-*&@Qh_2I`(vlZV;fOr&(JPlQp#PJ+5U2&WHiCqYXMi-?cf+%VjXu`C_ZwInHn z1+KpJyWi-WUV(0SiJ;K7;?oV$IDmf8?}j?Cy!HmPRJg(Ywv!m^&Za?0`{0|v0`*P! zsPnbk*(MePXw3uSS9NO14@Ru1$AhVKBXIvZz+ASrvyNP%fs)a_z;2hc`3Eax1r6MY z8oDNo>*Gj_6$$f^ABv$!fqBJNA(7>LQqQ3H@^V-&6JoD6LJhiZLd(qt5 z;485)Hi*OT&MxaM^idwmX!wQ510zi-*mM1LImXOQ8*Zo*!&C6H*E$l=B%xU0WIK$& z$qcBS147McQV|ZT2(y7IFU8r`c_QBrK`Gna`6 zkBb`9JZ~dfLiI>Pyw_r1YL{clnLg2!G9?uQ5de9ZqGes_NTjB7TZTxu-Q~1%Nh1{h z*`bk^o#CE8kg1LnETw5ZQUG@h)W!6=ZSwr~ZL=uz@Fh>wqDkOdPeeMiwZ>-&{}*4v zEVzQ3z|D=xkKa|rI#)4#iD(cG2{Aj;;zXc-0M*Q|@zT5toI82K3z}Ee-p?gXP{9CR zi^Ht4_0%$x+BB8VaV&Vx0uJm`9ZU_*hkLIYu6*tWzrYVMue==8nwN!(H)9vJr2!=m<$rJUVe}rx$Gis~@_ZrJ_|1zuiP#3$A-< zV7=>kx*3O-!4i&tdEt^?fJhGV_c3rI?aFKySqka&4`HLXxYUh97rT?iKLISBHz6RI zfQD_XEKf7@`%E!wGXIGFVml6OG&25nkK3Ai(O#MpnYzI-T|^=fHT5gsCidctQJwLZ zCm)08_~^7BsW0kq=}Ofzt}#9j{bI6v%o|>1Z$6SyXO=QhKorPW<^Lhnp`Cqc^9FiD z_~NbD;_r*+2?CL{_%QUR%*JHCI9vOnj)uWi%^sKI1Vw5CZh{3FVM&PviU(GnJ`=hL zmjdvibTp@|4?LE|rRHRgyXVaXL!*gR`Fy+YeqA}N(HiUyi`q{&v}g^cw9olfFMpGO zBd!pSn<0LGxKTm{r!=KsB9rLaMuJcj&HSneq@} zn6ev}#=soPEo$^a!8NeXmb=6Nh_yOn zhGVnW?Ze34tJt+3?$n?mm!_a13lOf=w?^9PU$gqv4i#?Gu`i7@nXE>-wsF_igQx1d z&TeMbBCM9}WZ^0NR$;R%Oy4V=l6twg_`RVwFY7NMZA>| zY4rAaaq243=Vai?1+hXl6Tvr96 zp%)a(j3aLoJQDL-yBk4D=0YEIs@}6JX>*nIbAA|zy1#wo0E2OQmmgPz3*T0Feuf;2 z%5azZ0LAL3K{l~Sm>RVY7EeCBV^LAFf|5|3)rk}os<+u9%oQl5YAMutYm^2f88cCDzTTX_n$ z$A^ttPWYg=c&NShJCxn_B3x2`ae8sVnN{Y~$JIbgqFH;nbU=EumDGQGexb}*$SFc_ z=;8u5h`enV|FyQqYRS=4mQ7QBjv(Wtj$p=5usR}6-W5!;5D#c^d{x8h*THe@NynQS zyM~T>bF?-G>cP}zF)VU{lEO^ZFA)z%xQealS~z4ynw{Od>Wd=*2xxXGrb$be4GsPd zm>KF)aX)wDf0elq`o|IAMQT(0UD06{I0`*FjDO=0OGDjD zP-8zv^2khVci!D^CnCD9c};G&sl2&?A;Oxvit-?qB8b!~O@O+mcG1~!i=1ufptX&w z9wvN+aJNIS$W$`YuHnN_tlX)!mr{wc6juz@k0?04{w8;CV~f|Rf?2CAIf$2^ofLHEHGn1=x68Mw6`amVbzmt-7$R+* zYK}-rSBvaRge6_4bTI7majoq(ECuvKMs(2OZSkjzcL7h1j*8-}lVIFi#suh+41?+? zo5^K@R&gE>)OJ%;?Q%pX<)L=7e+U_dn57KxBhM30Q1N6#|ExOQDrV_&R8JsFz;Tzj zlNJ!3uhNGlSu2hcB&oW^I?B<1=Xt#tpUnICLTy6joiZ`0))nsjz&^x5?8we>^1vdU zh{iF@3OeXW%Z2%T7pu~Z*Efd-0L2Y)y}lQz~;jmcF|lphi{` zJ{mciRWMZ)X#J@w4=(-G_e+wwfJh7e4+eC@uYU!`FvMsCfa}+566+R0mq8&!7}7yB zK}U#3Dg-RKK*z3>yg8XgXih><+t;~8 zMK0S4VGkKt-lgdAGVr zJvtm*;8{*MdH=9mw`S^|0MyxxpHBac9!vM>&xNz4Qr;r{&< z515e^M2TVa7_p{5{MWKNH+H;WO5pmnAWo!}>(znc|Muj-`5#!o6IXObeV_*0Gl+p_ z=4FEKX~Ed2z&mrbK)}T7CsYT*jyh+Qx@p>y!26eB&_!DOAvbeLbcIKYg#w4+xFQq^ zkR`b`1Mu~pL}uklfy~ZbSsWoRvqoCBvofmIe#Dn7%syCp6e?@Ztaopq&D9zC`luJLvUrE4h z)zJ@}#fU+0g2O>6pvAT4e+Pm8aVhW>5B6t*VMFrKz$E|+)fy$Y8w5fwk&_fx2aUMN z;RRbm;z6EAOTzVDx8I#-qNO16oCc2iPFuhK?Z$1%Xks9W%c=KrG4x?MvQe+^?(Tl{ z1bOr<37PMcqPe~XkYI)hR}3^)elTj=)zLB$YMaa9Le$bchur+M7o8as>k%J-6aSk` za2OEbOSr`KuhiWMTbTfc8xN$stc(?Dg)eh3CR(fm(3h0*J2xm^Fg`E@GBPq|adB~u z4?ZNliKFRI>$T53%5VPd2bPqLJC|t^?2zTdKG@0k#WHp+FQ-GwudqoyWFZuPcm%jS z6q1l7MG&N17?aCzSK^a- zOMrbVzly;9p9w2RG;G9CIGLu66$<`0g~odY#1{L^cd8(z>dwCK7_l6{#5?&#is8{4 zyZqLD&1RQyxJ)Os4KUIF8z&z)UyfTYX?WLaaGZPHZ}}P`mjLK_j^OtuPCN&kjFtZ0 zf7+@46ch+T;LVRMOSJ>!6QrE?d~^AG&-7m|ja2w!C+HCd=jr}>-T&n=WpDnhU-#^r z%2TJx VC;SemDInlaPD)7<{@U2@e*v^A38Vl3 literal 0 HcmV?d00001 diff --git a/docs/images/rest-api-docs/5-class.png b/docs/images/rest-api-docs/5-class.png new file mode 100644 index 0000000000000000000000000000000000000000..b26c2445c3a27212a3c877d3f72f49dc97771634 GIT binary patch literal 233796 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

EtR?xtXq8X;zpNJ@B!N?CLQ;2fh0=P1vv1`)FM( zNV(DGltdO zDoV;daH?9OvDFO=ZJ;6-f)u6lM8RUpbKMWJ=}LAyOwDGc`j2L5$IzZL;}bcxQpR`F zm+P5=4Mf4(@Lu7zFv4tZj}77i`I>d}P*tY^H&7{VbE^1!mxWQ3uzPaw&W8pTLES_l zjKPjIE~@-#sRe=E?eS*wBOL*rCFk*i$(85QnBx8jb|a$n_kQJG-wI)!?yVF$YXBQN z-#?E$wKr@)bdo7Jjf6w?R+gN~hYW-dEn)&Xsbi|67Aafq6;_F`z|;n^6(#3U^4Y`t|2rE4!P1<4L^ZNi?jN zAQ<|o&kQMTwk!`4MB|`$3o@Pr&Jt9(xmva_JSJ9wCsyTTQ{*;RR#w*wMNHn)vwh!u z$gLu@uyfTZc#tj>QAKnW5f!`sSA^xy<85OXxyi%EL52|A2FRDxK2Bu}QvgBbPF{cA zXDWB-DQ`i7-17Vb)@P07M<1SiVYl)KE!B}5$r&r$_CTuw{&d(9B+unTenc(F#ZJF| zs+3!Kl}%kfUSh)xQn;)=ml%4r;A+`!7s8PicPqT8{2r#)KhsAmVB$StiQB0xkGeqj zq|JVvOHq|346$tYfN*ZUq9@Tq0?n z3}hs`%OCsXb18OU5lj>3^qU70YIi;}o7Lr!RZx$PC0Efja%?$&U!31I&3?<8xKKDI z=iPDXm>;>7!yPX6y%3inP*;iNc3_1lZ>d|D)y)TY>ZFvb)AX{LHuuf5OfRAu$_Sz^ zxGHGoV)tr9xC>Txk*#|$4}xLqW)Y0K+p)~5pH^=}VC68I`J%QrE-_Dvj6~qm$b_81n0|8=scA@k5{_19EaUe%Q zI}yW;km*t~&g3N;)W!8=p=pYhmhP_B`3<|s1c-Moh0E(> z_R+fErgSxouU5J#j+XlQRdu30eN9#LF0sDv^k8z7T+If|;!X;ex&)LP z6UMV#5{x=j8FKs@hGp!BZY@&q21Z8kPOXPXjFYY4mzb0bBckBfr zTQj?gqCyQn$E{T$bhd2dgrom5ijH@yj!}Bv1koS%yRw(a1NfQM$vpf$YY$g9gdP(+ zE~;VAG>#9^iJQrJzDZZwvE(zyud#TtS4drvs!=h4?@Kz16CrTn!ihLOhXG0%WvWJw zF-IJ#{Fx7vdg_jo-COA6h3^A-X@g=F)r0!zS8i(XwTaWEOmhun#r4;Peaa-4foiPw z@a#k1)lN2%l-8ywg|qOjJvY<3daI~xq}8G#F6-DiQ{zX8m>v#@{ozoYPpQ3L!iQ`0 zgPPVzp}sojnz|7U=P}QhE)3|0KS&LwHu~0mR|g_g@zTfxSC-)gpO$WE9mrnEXoZQe z@G~|M&!NRqdSD@YDeQB}D?wQ2g$ZN{nN&gMVWWSox(mJJgSm?G`O$K>+ztg!4AH3N zH(E)~TDkjcN%hi7dsgY%NeZJ&`=(?4CD?u3m;ofj<%;{LpD}iK)TGxndp1)we7SmF zW|-cJA%Q8SE->xJXm5}LRa~GBRr^@QZg*JjyCH)QQCyN^Wx=}~`{v*0ng$n5Li7sq z8;my$s})0YwNs*tUPu=}24ow86Np;`>Up;zM?VQx0u~0>sn+UMe1h8>?YPh0pTCcV z>M!mjAU2V82Z{`4WUfMiWj_9&V+9kRL#hi4kIHE{Od!6fTap{pKWpZIsVq-5*Bf~7}lj)wi3O; z4vl`8AtHGY5_AzI76Tb@5rREdsb>R*3)|NGiFd+;Cz{-Q6r&7Oa1-#3s@?b zGa6CCDzk`Tm8Exq|44w4a?*klh=Vb1YW1Ja{yWp(JtfK9emZ~dOP z%LOz^Y^8E%&hT2eg_VkzVr2qr&%?I!Mky+dR*jZn6@hzQ%4WBRmd4`lFil8MHI5|* zoP@Xx+qpFa^?Zt33a)L|Va;B_7fe>NK-|aBhC>yLwsWI7Zo+0Wd8$o*qso=GU%Yxp zg*#QrO=lGQA0$5<$+yEHR^SjOj=e|69zThPp>R4CG{q~Yhl|{XWYaXQ@tV^huvtd6 zu`we&%}_d9UGXk=^4!}I^xabLkR3^;PFRueumn5w_YVVK?;c7GQ)A?AlL{J?uAh%rd&`CbYE$LTL{nXU3_;j3BXOVmR4JXEB0G_y2BLPZ zxZhufktuk$(0VDWeR<|)Y63+hs&ET^@6Qc4A}b!fU-4!0Yad#(p_#H{)E=vzQkT&*(^c_;jCMUJW?%H7x_!HytBtUXbK$S-%`vuo6=wR( z9=V(`&k-w}fXT<>g6p(#u4o3~;S>)e;apxxb!m}%lG>PwqJxy2<+TveQdCHl3lphp zqFYP;`x#J7yNt-4njLJc{EG!}rLaOiT^stAlZUNAS+UE zV&0vyQjSH0K9-_2nSxD+tDT^GXg_Wd*1O9bq4c=v=foUvFd)OZ ze_}u&s9tD%PC#8l&gaStmT&x${3hBPwnN$12fC%j<)CL?f89drM9AL>{(7%Af>%M@ z^!C$OZT#@M8eU8D*1ZQ0)ihn-eGRrq$Sflw9Xl63>Sn{BlS6*vMbRduV=om2T6(Qk z>ItiH*A6MY3wsD&jQx}C^QE>^pLKGmRxZ;?9C*P7Hi5e67Imke5)rthl@BH5l49CO@fDv_G9KV$ zaEezsiQdhPYJbT~FU2ydbP}zvliaV^kwFvQ*nXnab)sloC*b17?q0w}htB`PVblFUzk@q)R%K z|9qz)m_)0Q@R@3azeRA+0FlvsFUeH? zZc6X2@j#zNt;_ldi%Rt)HCUI_!7iwpJwb)w!Z_sYpP6@F3|jcsZL!AvfDG=eN01~e zCd)*HP@?NL?>)>=f9<3O8!0@XVCs9J#szOt7L<1Qvbafbd!0)AUjZ@z4>5K>oGf8( zu?B&$Q`9paw3PQq5E?X$l=j@goi|;VU+XySD>eu^g(oWp@Mhh9NWU?_64lZn>E7P! zgedb)3i>e_v@^U!0dHN}F)zG&v1+B-CENPVTxVs2S32yH;IFU<85eN9Qh{j*?erm1 zu>762IUo5T3-E)|6Hq7+{4tEg{}hY=Gfk)hBc(te%FSJEJRq$C>A48n>1r^qMJ&TC zU?%^slOsoYoh}%d`{W=SF>ETJ9%+L4+mi|0*lW6Z#+7&_+@MI4G=Afij4M z@nLL2>aR@?a~hDt7lACQp8>su@>u#2Sn#aCJ52h){d>Ll$l2tR)TDM&9@QXx$VEw)<31d zRd@hXrm&4sJ$mw_@Xebyj~+R4+S+<=_%09X1oly=7`UDKx9eP#C3&tkc z)6;YG#0k*kd%Nv3>zRp{VAJTi*3yMFvVm%wItDZ`Tgk)6I`3{+iwJ8IAY800m5suG znuotXMoW-~>&&c{aORb4iN)ylM`^6zinaGU`npwAcj^&x*9>ktKZVg_C3zl_Y z3PNE@qKsr2;He^RPwCK7)`#j-6`uC+^eox$;V}+DD(kAB+LoB4|0TFVdfNsa>Gm+f z@APvsAb8K5S&Ayf1LsjJzm_Jf5!g7!J;`q*oUoD3fAqf92g{7J0W3dfyZ^lFXm_d+ z)rpArVq_lm7EsYsVG_XJd)?<@{z$%JSg*@m*qgm8{g^#1?{`c34!Lei!NIWN8vovm z)MXxjutDzoxq&Y10GF}6L;brIL&nOpJ)@+;vrYPb$n&Jrzq!A^UF8Rlfw_5n{!;JH zfzy937!^p^1Zf6{lJ<{&`(Xb30rMHK=uek)YqR`j_5JPF+_MBhhiz=)iT_tt?=dix z;VoArbbdSVKYu_Q3{3EZrH%dLzgOhnWBsQYI(-H##50FFE~%RFNJ>hg$r2TRH(8;q zw1*C7pxXBI7b zzV}LF-ZoHABH^HX{QO7Ay=;JW3ALpDdU}J*waJny`J^K6vAX?Tsf zGe5K*`uBbQ<6kO|=}u`e@7Tlh_tpS;>)f1W{9gUZ)2AhIjo=Cc9gW_qBxcDrKKaR` z7onwdC@4_?0K-23FdWpQUR8Gc?70g@zg;kD6VH%mX!Q8L^d@}P@b*R*&?nMctsJ4e zrw9J#HYWDOX&#WG=x3LYw~PPTS}|OG^Gd;SaJJWBg-|2wOvc~9jP30&T#zl)&VCZ)0{ zl9}9318PpBWlY>>gDL}R#uaYcQX9Ent*-Y1!1%cew+1n`K< zkZEXW#JHg9uJ8Uph_vnO?%tajN5%rlMy+g3)|s3Xm+ipgW504Rm~Fu{T`qs6O%tXK zo)(~kX|IH-91eZ<>G25sZlbx#^(@=VF&CzS&+6I|tYhM8^zBB+oer(5u*S$GEM}xD zL6?s1czfmlsBhZLsA+h!ip?v*-B=M_8KiF9CosfvhZyscI-R|~_H26PlfCB;z(lbp zs(6i5YJ3Gz`aIZvwX4O!rU)!{wC2FGu6YGyB1S^@*@1yZNtno`mHJ&0Nvt(oHA~P94VD){vm_ zGN<*UhRp_2|H_qn3PeZ66UujEQ$vDHB^p~_ zNrxxWT$M`h(w04;;H?sm_1fE}%QLE|*G`hUtQjXK-G<$~w?y~7NtDn*aXu)+w(Ggk zKR03+C|f%9xZs22>F7-`y|V7DM~<`r;_OhUa00WFpG{&a3rpqHwVnd+%bbX~ z%}(Lv&3Ch1W@m+=L1O!3-$jm0PUdnp_Xc=MkostiXS>X;Y!O|@CqH>(-;8VN=eEa= zhY&2jb?j-yo|`wX&ZH?Jgz0bl=;@D=+O4;miH90mhLJ|MPu7%QJD=N@W~Y;y)RbBs<4j zReWWOcmO&lmA856DGD(41z)YM8)|za1`5(R$umjEB96uO^Qzh)6hGm}vcXs>sEsC< zku|i%Ebx|i_iD%n3mMWU25o&fdeif6-f@%i+-M7aJY;)j2X2R-yoz0Tc#So7jr<|s z&Nd9Yip#Sw6-qnF50B*2NC-Hn3|9V@dh00He7wxu2SpE1pkAEm{tO!B%zUHT`y93( z`FnbB{$40AHuu5Bea+Dkmc>3ek^U1sC>HQDJ?Osp zGd;+N|BD{9(z6Fl?29gC%QLw2JmJmR&IDmp^_8NUtp;(#koGylYINPg4=x;(ey0{ajEy!)GGy3DICuL?v33RGjsuF}F=}VE-@YS5 z%g=qUZjKx9eK~s@Z79#BfxG&WFk{i`?K7JYAmydMr2rRsezGhU0mlcJOIYTI0V9s7 za%yK?IsMVAp(T|z^yP~eeB$DBT)VUwh|E;SBxP=|gKo((_`_9vtGNs$r;lz&0Ly( z%e#t_cRw6E`Fd-mm)9bCfwFP6GhJXV@dgpd{E7!`T-q5_P!P8p+AcLYiW*Dl&EQ1o zwm$poi2J9HBF-w~xn0~>zv??!<`sT^`-gDV#)3=j*WG|oy^R}4`K-N%thSR5TG@{8 zZgY*RL6%qr#jfy-gBRf(f!~&#HdU0Av@F}a2CGy;esv=5PHnt*KNHjQP9WkidtGPW zG@pj9X7t-cbiO(sQaQ)|q-1WoAxziv>Ekcaz0bKS_<)AhEu!3u^Qd5-z-;3?W8C%B zjYCH(tLPZ+G)zI~*KVbFC%lbIX^Tg=n3l$0oV0Y>4EetN0+F+9zy9r$tDyz(ARU>v zKWw_`JWe`mD2BX!ukrQ9+=}u{momQP!zV9`W-s!VTl`&dn{8=gATRaO&8%X$wG_w( z4tDp`g@WT|mWp>QaN~!k7ApJD=eQJ>eqai!@0ix5CdQrx1+1PAbLIV<4ZX|=V?f{a zOVu13JJ2;4GGKSM+BEGln%+H`pPhmNDNK8NU5I(Ufd+h3jgdQMAn`bhd4`Lr_JNad zA&Jo0!(q9cdJ4;s#-i?~t=AJ@tx4|aozeKvp+pa1TY!AXHzMX?$AnW(>b3zah=inQ*#4-Q3JAR3s^4x9 zbMwz5+Yj~%aok2t5{7xh2XAPof!f_=4wqMMmJaupkY?pt8{>owV@1;}-_`#?7lOp9l;;lXfrg)qptdWf@Lf>Z z4;R_MABl%AF2ikZ+t_{n;dhnWBe6PkerzScuO$j5_LLh0 zJN@TF#g`@Y-3G4{T|Rhll6tlSuA?UZEe=7$cq(?S*rW7%jkaTO+`euP&GFamb+rfr zBfO}Y3vSF+h-grJM7{K8j7u1FAT4Q7!jE`mYgHsrUVo6XFwZedc8}UO!%go^$1^bv9j}No7wnho zy&IM0JD#(bBNnR)P8}>Ivt9IOi#ai zSu9n!(a=;e4uSpT#4JriPZ1sQ8whuzCg6aO#XeVwZ@2dh48GMVF16M9) z+ETndsNQaGV#|3G8sK<^`@@B2=dQKyn-SjAO!qYRhUcYsdSwJOUKLJ~_nEiiy1t_V z)Tg-N89o<8kXp&B6r8(?-Z=pQrWsSS*3YQBB;%wwP20BLvCIrQEDWx)a)!6xm&9eb zopFDD{5-o+eaqCYTtgn#9C(Ir@+2Ij<{Sa#zIRo!*4HxVx$I zFih8bP^;1Ufhr@htA%WH-x8Xf+?53tSZvuItXfzQUK*!DS_Z+KN4DJwtC_0T2g0S% z3$iwc9QR=iLKBq3 z*8LKb)#~RYo9r^(3^B%c^p`i=e12XGZ?2A7H7bg4jT7@V9Q*vKS*vNcV>)Z6c?(Ox zp{*04j7(gYMxY4Y#BF!sn+%6V54!A%nw*&59QdOyqa>;uM)WaBLIc%${V{-czf0A) zJEw<1jO>k-maI*E@^!c592x_o{R-UeW24WE3N}|74#vE(sM7_HkkwIdp;)=o*GULw z8|4X(tUnOU_V!eWF-238K=Fr2QBl|~+@J0r;~{vt1#kT)=O(kCSy??hc3G@y)^3aembsCxbSwcEgo z(ndZNVA5P3_m!Cmdbv4e?2{BuuIl@Y7S+*B9%6mrr(IlS-(d>McwV7Hzo;H^1PszO zfr$m>H6JVj^&XS^OgTZC2KQ1Z!JwR=T_H)f*wWLq6kKtC?38oUcc|EZ~k-_Cd7253a{JKwRlKmxYfdM+*(ObFOdfq z3j|TGie4~W-{rZNn@Q#|@LvuNN7pTwh?zwhz9Yy_Gg|QGW-8O}xuwrARE* zlRk>4pO8Re0U{~l)}ctiw4B}|XwB7n5kv_Wo`M7UX!TZc+zQ9qqJzs?qqS5JrYkY> z;u}Hrrvd&S6X>n>BVBFe7`{_b-H)hKLT8Svjg5q-V;qQThioJ1VsV*l$ku*Qa-h^) zA=cmEVi}ZKmp3HB$E3Isitv9wXf(KQylaB-;UZ$Jz^UD-NJ|)=_H;3VtQgvUp|G`#+Ok409f6PYQI%yZnhqH!1w41+v&uLCBN`sUGZRFG)vQ+%}@=d zUdhYhMRxZcP7XWUA-Z{OAbS8OY^PvbmpX-^@%WL+Qpb&3%`Q}0D*d(TRNQ zQR5(82#$}kam1DO!6UFc9SbE&4_^!mr4JPrY zl51bdU&FMH+ReRdk)Up5f%3OJZTMQ@)9DU4eGwgwvgpNpiNiqNQvz2psWS!h6rIJF63lPs9)ku#StL7(7*%hkvGFxZU-4B*{ zzZTP^<|bJLWpH+UJ6ZVX3}6|!w1%Uc%krSC802Ou!&7wNis+^(J~Pghpu_s@DpFl4 z&UM8G^c@z*qHp^~qAri0@69*GM=ukdha_v5{^06l!97lyrsZWmel*O{?bM$Rw=1G< z1UWw|Qx)!LK9=h%l7>+yi35&JhjKgeSs>$qE;?o>@>QEI)=}%RIRJj8GOPbJM}*}h zRHw$PS=7vAsnW@RcSPd3tK?k`{j$I|q;y-EzzC*QF?XYHR1!ro@m`fWF@D;KHBWb@ z2=0Nz+beoSF`OD1e>4U>ry9TgbBNuXWmKW+ePoEXVL8j~`PDkd53SV#SFw`)Qr~tD z6eKUPR<3e^iMi4iNC8s{* zX5o*JDIWp?)QzrLySJs{9jamZOgH#a;OeN01rV76+*3(HZ@Kf}^`Ybm6cENK@@)we zcPF<(M&H4pOJGTMDKzplWm5fo0W;M0Q}=2f|NFQ`E`TU}8Wi0G?kB^4Lo zW%8F-K&ixlb1>&nQ2=p|YGaDY#kD`6=ghV2$biJ_4fj(sIVq$PSGf_dt~XeoOb(aj zLS&UADpkXQEi*=%QDi6te^q$PY-2jm;M&ln@LXcFZGli2pfbs*FS`_i(w^oAHwZP=j7+`r zjv6i!^V7zX2NLh$El_T*WA+Y`m!kp@nwRC?9WKg56u`> zP2596`#NQO_Z}c-(B^Z2!$t0Riw>FEQHlY@<0)=RFHMiEpig0J7F16)M*=8C|FhO*mIb?0 z91vyVHg8d}Zd0RC4L+7>w$roDVAYF(Qu2X3{lRPKloo=={3vI&u z!t8EZ^w2)n?x(^@;p#`Ts}T`QH@Ck94Tawu|2w7huXClkV6+MClGb(sjR0hpTJ;}d zLbo8N(oc!qUlHT^bm)=Ri@_%RzNNlhmD5zv2UiLBXn@Ao-OuQdS6jy*c=H#0aNVrs zg1jd0;n?ZJDUdlpCEY)XB=)m)>Asx{b_pg9vWtI1_H0$i`8qocu^LspkA;?ST_RLh z(=_gKAo+UpOC((|N#z}f+_qnn#XLF;z*dot6cX6#_6OKHs8?Ei_#*O6198{v%W=r! zqJ2mD9sEQeAY0G&Ayfd_`h}8Qx=K{vOx=C3q~BmQ=|USN!-?>6uYSdgWw)VCsiJAH za)MNszeCArl+;v<5Tvse)Por}@zq6M$ED;h_rrJWe8=sOyZg$et3@j`DG6l7)H^Q) zv~`RgruJjwpr=U%EDRIgX^MtMbJroYLk6!&Wa`Sp)IkqZm6~u5-LeV!Ro%PGnW^jh zq{?ap2 zux=wb$VfiaS<^YCH@x3Us!vcO&m|w&=NhyY8Z)bKp7Wt9E-&l!=hDNc!y&0@0kZ5X zL6JY?Kb#mUGCL6c8b3Jnd8pTMXggrD@%?D|Nr0==tW2Fek+g+3c|8a>DcC6sw7@Hq zIPH2}Zl!<^29I2L;5jktFwCa(ov%Ejeia0QB0~2^S6STl>xUTwcNjq1tQd{i(iMgF zi9B*+Zt?E;u9YTs2X|%RpK5+-?MS?=se-{G<`OQwRuw( z-9=)IJL6Ky%8cn`j?Gx@L-A1q31`B>&6->w^NE`nJb;piLEt1LPaGQ=nU!53E(k;|^QJ8; z#6c1jf$S?Q^8y0z*-o3+XNjoEkC?*0g2zt(FB}n5Ue!C=l ze4wrc2Pfti6fq+zGe>sjhF9(InaGcal4*iq^JAY_!Lg}`Y5)6N$jsB#j`})Y^Tp(z z4d9@c$6MBJ>(7s5zuCEiv=w^F;#O8Zh98pTDTNp-voN$%C;$>Qpc>b0X*)tu>4yrI zYQaD!vfJ@}8TJPg>YFAQ6`6uAf^=JaO4s;$?^ZN^M*b=O-&s=9zcTqIxX2f45x_@B zP&Q_IV=rKDka(h*eutII!XS`Wd`3`EKs~dM_ZH#lJx`sgdS6^L-(6r+KX}RMLP>TR}R$=2Fd(kw$~kiK{jnl zh7KFSL@N?s-3Cx@Ie$K*p2#c7+MZWB1&iK}{ym_L6*hZok&sika~Fvu;tV<#Yj51w zWPqe*l0Ah}rSz^ymNLESbsi+qi4(+q>Y-Qpv2-flsQxs0zrj~#YQ7W`+)z{uem1KN zHR`gJ(%*U;`KZYF-M#&~1%dDIjW6hElkig5?zq=nM|oxv;rJzw#2~jTyqwiEUSWyH zOPe=>Ytl{WiU|G-)sALHKG>~ND*CG_@#PJ}HwZn=Trcc9PUgzzz#m&?UI}0kO0yAW zSX9)Pmhg>gAhD>2#yFI2L6Zq*2Os!ym^(EtDTyBnEqh@$%=?Glq=na2`lNsb#9-$G zH4euE=dHY8__m|0_xEUnyjz3N78m}>3oM~d1!ie@2FaoXx+y^b%qrM@y;Rz~RpA@r z=7UkZX;$tm@NTw2@p;5%|3Vi?a^(z9N!wh==}!bHlVZ5LONtZ2`f4>nSO3e-+h#9Y zX$WS@<-+k0A=qvDkBNk3Ig{EoeJ3~a$yEB#E;LNOVl_5~w>eR0TA6m&s9jd zl!gO)`>1<)=q`|zCiw-iU-8BfmOrP|JuH_aPX5#x_c<_Po3J|tD z*pF&YRnn5WGh%D1${l-QQ+X~aUwE_tAG{gp;8-y6ge51@d7`8I=(}B9|8!zrZJ(Fz z;ZVuF<*_#@5f?>*@yo-4Mu{FpZu0trxQ4n*Wize?@osK#CpQU1PG-MLSD%Yj!GO1R z;w978c#)~VXBA|{()IvE9C{I0LgyTOfz0;>-IQ2OVZMRX<*6l;RR?*XfMk#K>~tN0 zuUgD+z3LDG>dQ+zn`|vWb>f9$&QsBmrFqj@|GOunF&Fz=IR?Hv00Ds~QU)U~D^!x_ zZ@zvo+O$-FvJubmJM*r4BMts?jkn@mbetRL|!7`+^1-sra*6tN*d;~2t>UT3G#wd z-Z!~(^6sxC{7OhDpv6U4lnU_}cn6z$KKHSYKMl};r3@-iJobOUB0R77X^H;%Q6(KlQ=(>%}EiUj`wPv?bo1Biv;+- z!kf8|wA+T@GN_T%!(;~}c}4)3yo4zHle@v>_?Tv`GK5IK|kfC{`|=En8efh z-%a8mzXR@MgprmqGqi$i?e+7#5?dE$@@;F)f1xg5NUvs({bmrVq(M-Av1X?A05=7( ze183RLRG9tT2-IrJXnF!BZzL@ zIRum)H&l4!0S9BwmHS(g?>_`0|7K=9%^K-KSy)*3MMZVxM1)0EU3!XSDn@0Meoejb zFt-4~FQ$52^vBPiH4O}6uU@^XZhZW}_f(6^=d#li&j33r<_vgA2zxg~hM)i1B}imc zRKl3>Q_b*{4_WGAkOmJh>R&%A6&@qX$dAtsTgC_}x+|Qyc=4hXgpr9!5YkCfepDGF zA@fLO2Q~0Dz`&k6r*RaBqkRVAXyxjB1kCJHDVl4)L7>PjCpJa?fW1l+K9OLrtJkj| z1@ea_f5;z#_0DqA{R&Sp3C;onT_Jf)<`%}z<~*KSpDvs`#W{fO>i-?5Njn|UXsy3f z409D3+r%MD5BeznN|bSbdj9`VqkZ+8YPbIE1OCeXZ@q zXF{u&dDg&!rwDltemCf-2RRH#^{rtAHOC(O!m^Rf+q4-Oo>|6bO^YO16n98%B7(F{ zcxWl#g~H=dER>7hc|?Y9*BqRGv!p{)LRmHz4t$w{=t8P=m}y~PgG^YM**^-^3T;eC zA^Y8mQK6y@u3}>T|3Q8JhH3o!LjQ}<{(nGd|93KfV|e~|W&StZy>_rPO5-1U4f}ch zB|Tjx`{ns-HJ>g@A%yiZ?0etqUK?PFF}%K2-|=T7%U z?{)-iELYQ=OX0UGC1l`R`InUJW~IA6FXF}|?*C+*LKDDy68`0?g!XR@;GaKO3j#K@ zE5qjcKU2NG@L^zp8eigP>9}xYjXG>R_&{IIkK2mdStYc=b!ZJ%eYkG77soFk@Hu$d zr1!JtCwX_h1o+*X|I_swO~ADsvSol;+z1S~D9gEz8UF_!UPTT-FS!yI64W4J5iG#j zlW|%3omD2?{|b=sUP|A*f?`%_qykrB@0R%um->gVqo4_H;Z4rV_dFA$z=V$}9z^_B zMHa02tF)m3^vo&~)M3cs;Ao46<(P&o?ialW>2c2zM8Cwf8S$Hyt9(fiL&Y}KMf3&b zCmSHpo-YFB>kmvY?%SqYEAnUOI>Uh@fu3$^Jj zRT~8Kmr6notYy8Y6CXUZC|NU;XubRtlYLvcIKOjC+W1_J(tZh$`=)wRHCo zt)7QFkDR~eE_^(NT0aR-gO1-X>e?4y&_mdHh7+YGn0fwcprHU4iE(&w%cKQV!%3 zxQq~yDZ#Gz$B!TLiE$r44(bAZV&~EWzCE%bj=)s{f1D69(soQM9=-K8^wOQ}676KU zW+EGzhqFV>)GrOax+R&}HUZ=mOr@(=>j|`By$PuWyrH20Sf0HIDo0LI9;I%4|Nb(x z%*B5jcQVp#^mW+xDC9C>F&aHTAU}3DxW4`cFQ4%T(18&I5DD;e;4GXDZF7b!7`qj) z(_TcOU>Do+50{rc0J^DBQIv`FgrzOeB_xQy(8mv+v15S4sf9WIhj8eHyu1+?E+ilKvybeK` zRTRYv89rr}8O2qRk&glK-=)#buJ1?G4XpaiR@LWkeVTbE6qj`a^jTGeOD$G*cV956 z_IzGwy8mQffq_$b-y_CxAYW%3?(mtMKzM$#FQy#H@dR4!+{>RW`L^FK2gfCnjH%!* zXyXf6?`Lxfm@l!@OrCk|^#ny1Cb>6i*LmV%V96eQHg$h{#bT&M7zZmpP_%})!rwf} zi|v2+{Z^kBdtvOGX5Eh`@vp01W@*nK%?spsaVS*sENcAieRJ9x#|Ha!g{o|`IVc9f z$fYE-s%>c%Fl1U^8(@puNWzE@53!vO)|(YEKY`NI!@d;~>kt0?pgyJ~XhvAbj>jn8@2^9S6u{(}T@_?RalPcq%#;1LrM zH6-&6uqWR;IZX$;WVr(`FGw#jqmEWNy$SsK&Z5`A=Uf$J``L3d+wHes){CS!(=K`% zecIT<5(nz^N=dN58O_IA?xxZSSCUo&`UyEs+x zq|hW5rRD1C`r7nmGgF)<(}+!7Zd~0yb>tJjROn{BkcqbDu^JuC6#4=9YL&j{Tx-(z zGNLTvI;MzlC3pwNB)g7Rw%?f(UXPdcRhUn&S&5$4R~xj{JP(1@J0>3!^L43(Go0Ej zmsB!?uMunPS|3>F1s(;Dx>+xspBqv8KDh3i{YV>oomUf1vQg1@&z-P{(~Ut55rGBlywXYU!68}_J=vpUH@zNJn4;P zYaa8xA+dYaE)~7vHrIc=bdFNAaPs{rfZ-?xEY37bQq8ivXE_e__ts~zo zuVhX2u0E;wYa&D@+hhvy%NOuhy~e>cEQaFB#E+CiMG>JD;LQprurzKTQRlhfGA3?P zvUJ}cwNPKiQEuPGR>8jJa8l}%*_D7FYtmVP{o%`V=G8&hW>Z@Gx*GPbi&|8tX1#+_ ziCrSB?k1^hfBV!1w2`(vai*2~{-bbX;b)u4`*#r?TutForxM1A+r7kk39>cpNvMXE zib}0gt-M!Ep}#wFzYNV7N?_s;9uKbQ4c=Gd3Rd|Xb;AFC)1rGs^lHeq7^Gap3Gr=J z|7-D}%X*~VC5RM(pGlfP-q^P%Dxx}m)Be1Jli^%ooPy0JTytNG;H zT>{JSQ0VEY=@fUrfrE6`_)sqKSGm9=Fs;4I_k#zbJJZxT`D-f^)7YJBYlC z?5zm=XhMF0Gwn!;omL*O(BFL=!LK!TfZ)J*AfhMJh!!&;%LI3Ma!43?Nh04@1N(GaNxX+wZ51&?tEO%cV$k)TAh<&Abd;g$nKNe!6(d44 ziuEMOiUmW&PyD9vi{#yQg6N9;+{c@={?8kyoi?ZUB{M#sM4{+xC@3iS6!xkW+xs;w z&AbkWR=DoN#!l_U?<*=AHBG&J>)2z}_imo6!3ElRgh8|`jY$#?@nc51`nXmfLoX{Z zsG%&QiW`=-A%&Mc(I!vj^0vI6=Zkw=q5R#)T_J_+!<9}2hfiGWnV++t?pE5kiWAzJ zlKcVOjYS4)_!Z?e7BgOmZ*mI7FCC^oXoWRn;POSKnNmLrbs@KA7t;vG?tXdFa4<|W z;LFe8MZgE>j3vEO5rx&dHeB`u?NI8v?OxO1Rz*1)hmxtgI8+2Ncf^c_D6^tkmIB(A z-E)sYXehVaPNMwcFHYs~bC4UIwS)>paSNT6y*D)~E&{ZeCUP?nA}j)3Pb)^eKfI%& zrc}?s%75|dQn=ex>{GRvjtKw4%0eyZS}|&B>>aT9M1OW*yfs4%Rftf&tBg&j?!59} zOY(1f6ILhyV$l8e5yUgmWaJ5=7V%W}bl=>yC07Sa=lC7e8LJ9zQ#lQNx7+O6*a#Y( z)u3+VfD+ewMR#oQN;_WTWU^jcspgd)J^5UWjIE*-$rBs(aN*WAvHlmguRR;NknAQO z{9>j+=>;IMO*5B~*XY0K>p|lL7#3RvGlKc6l~G7pAh zt!=h|+4+U9m6tj72TxT@m)K~5lrAbSm^*l{YH4rXNcQfxSo69-oqG|g{||d_9Ts)h zy^jv1gb0FwD2;%$fD)353X)0;F~A@xjf8ZHD2g-;NU4-C4Ba>i7*w{&;c+4H>d zyzles_dS1{^Sge(bDe*@1{`MgXYaMwUVGj5x>wid(iYk1)kt?|%SV2=2N4OqJsFth zst3sFqeOIbgCdCf>yDvm_V3ttOh*sjL$4%9$(@tn8u_bQ>%Z>c5m4wsyLAD^b<^_mtH)M!v`Oh@Jb_zxd1TK>~zR1F{@3PnmsX`e?L^w!PHF==oHo zPQOHPs;fCk8{1@@9%xbXxnXpThVqq@1r=7yk3zDg?Llqq?{bO|Tt0BtRVp~KF4$9Z?^wtkpWNOU zrwJljZd;?aMzGMGnYMp$P`>eO{_5|CL1+>H64(!KIFbQFswMCx$^?z7|zuk?WfR&&$j~4hJrsI!~_00b12P#(1+g%f!`dyx%T>k#Y#gyphz%a$<kd}IW;vk zyNpesZ_dCHBN^mR*Io0`3fBsl?zgFOQXK#;2T3UKZ4sSAm zs?OlvSCGvj28Ng$YX)=%aZ8Bdq&~N|dy^ftj7@sS48`2Lv~nK0#}oc`-mBD^L}gM< zRnv1-4{t91TauIhv;(4^hF(NA-zH49_9UOyi+cL&8!Xg zvtri66Z{N_>+^nR+x(Pemzg(L!nF@JQsvha5Z6`n(D?ZH+E^g~kHPv{`)c6q2CULQ z__;^=+F;ZH2#+C~z(JJy&a|C2j}a zexb;Q(U9N#={})r0{EaNWlp?%OwKs#bLWjrhXul0FExv?er$cF#XHH0iF!W!EaZ32 zb_5IGdd>PLF@+_8owShIT70SbI*vKFuk;BwRG6V9RmE&$SV~iO`qi)wRQ#PP>*%jk zlw@j=AiAx#tf0-N!Ja4^(?U)dDtloF!?80@G@4HeC;>=Rox{m{=b7-EK7?_g8a{z& zeuTnL3EOD|-^n&e#+^hIwBkcATjY=^WrM~!6%6LTPOi#41m9|2B)TWd(_DmQm0%_-G2|z*e^0gQiGs#C1h;;3Q28lQ zf??irw+)sF1P6xs4G|GpCS&ZEH^xCkjT6d$BR!D%9-Ns&q7GE}BS3m!VATB0Df0wY z>WbtUU&1}eGVaxke>va&>F&WvpANi^`Bh1ghfK2IkPwQBk7o`O0MAG}Ye zST8I*72FR4Bdd0vr7e{sDKmy7a8x!6nR-sIeq|x>f8g16A;5rA%;By{Q;_!Hj_OF1 z1Y9N6`+?V9W64QbGuCzoB7@Ltu8qxhMl+9}9ja`#pQ}xgdmowXeXKLfpTJx0IHxe) z!Tx+Fp2$~PfO$1rXUn8H4@a$h^JV6uPt&gc^tYhMUB?7cU&;@tqiLbR&Gu4WI}?v*K7G#*L>i?(RblZCkKOSm%1m$tb?+ATtx2)(``pjsvc#C zaCK>m-g=})to$OlWuAYOdo zf}bmRB|%Q;`q5XMpw^FlnjY382kOo5KusFRo));BX_k9RLJQ(NOI&Lpoa#3#t;MK} z+5?OsBR(r=hoARSy#hUP{ToDJZ|=iS`%j0~hhC*>oI=E?sM)-v@7VZ^^2^=b*m03h z=y{rC#|}xlwLw2vW$~^pPDG!WitE|hXvm8AOpmH`WQttKBkh3)M8qw8R9qu`yt=}X zYH5l?p+`3TYe1>NBYkn_4PY)P08(h$SNfSWmt=-r`WHBk9b{EUZct*U;E!^>;3s$p{maZNd{BJ>AJ9k#nX z$Sr+#jI7d_Bd|C-dwL?Bq0;*KmEugO^ov%&XjLX~QQ_22FCy9+R+wZdOvA403^y#fVeb8b&_==eJ@$u=|FvWL0;CVEcf0Ym|ORF6Smo+`9 zC@yg7eXUk?|GUP{#y}TqcTrvIrsv9?Zo7%j`xrKe3Ki#h)-Y4Biwl>3bUnw9ptjF| zly#$65*gpZ3fxxg5Hlx|ET?{V*@L&KR?MxPqVCH*keAsllZ4UZO)$eBv}7XBG&deL zy@|abW^he|cL*?p90YlE&)IIacQ$?P1xaD_i*)zhAP%G=#z22+$L+Z6dx2>y6zIW! zWxv9Ay(yF)A!LquGzPNVWBzdz0OGhR^BDgeRmBh}8@Won$+kqFil7Sp~2mj+B*T8VK}QI=TFp;K3cTZFWaL6^eh!(3q@#apjiCz$P8 zWXZJNx=5PiO-#3K`va7NLp3RaVf3gOKvir2o+8%Bef9bs8jTLVDx|~(4JPr^$~9np zN6k}wN@xAmWyPh$+OJQlAq2<%^^07cF;I$Ma&M>59MkgYrJTw1{3i#Dq)XbOSc2$N zAYf}RpRN)gX5EQgU6MZ0a~fQ7oa=}a<7KfKDv79E%efIR;=?U8mdKXRF4_^z0jT!0 zLgV4SzWbW%MBKh9pFf+-yzSlGX>51c0k>%5d&@7_r}-=zQ&+OxcGHy;`8-ZXINaKu z&-N4~y#LMDz-kzMW3>7Df{{yCinE2SGeXIWsZ^E(bWExJ-L?247?&yI~wF@ z^P!R8O7^UIv|6(#mGSWSC;xKsx1ZX2i#@@JVa0lt8%)f;c=%1neI!Z!DK8NXX)`PbS;@JrmYe_FL3<7N->>g8Fr)o>RaNro&cgdK zyliskhO7pt@5%r;ejmeMXmRIf-s5cWEGf0@@kJ~;X2L)=31$WJdHHrt_3m|ezn z>H=a?P+73zi?@5bhg?YKO6`uut|Em&y!z=`>+DK)|1AFp-dDubd8fyrM0fFUaZwZE zw^5H$V$|kl5Yw7d$$Ccv5<;LRQ{~)+o4sGzKaL)pgbD&Vhd5#5x4q}JxO_n-hZCmc zD&aa0;dD~Gt5fb-?0L|jCFr<&>w7q>_TjE~&*7#_M#l=N_ro(iaCx{A zZm_l!=$sQ+shK6g65Y1b5_Q5q-@E4|Hbu`~J7RoqAdiFwxNSHU(qBZ z{0X+kZ=$RI3<&;wHSxi>klEhyD}03rC(mlDPKVIsHVBrpg^jmqa5(TsI3eC24a=O| zc$yb?Dyq8*%iYQ;5tSrI3g{2ddn1AfYQ3Z+c$;KXmRT>hg=-xbHt4tZ73e~$ zOg0>JOm}AzMJ*CW3~H>a^7VvqO!y0FvZ0;qeRt4(cawZ3b(T;d{2U;L77GsatyZov zfL4!a6OmrjP-6%KKdjVNaa*@HOOoAg+edPYqSH!R$3`0Z@~*ynh5Fo!&3h|z%ehMt zXuNScF4Ry_*x5;L2WkIU^{~eAF0G;FO@3X8{w$_mNvGluyO|luRgnpo(=K6CZk9!m6@kOf!%AS%?D)i@TL9Ey|Uy(e8J}7`*4P_7? z(VZ>tc$a&n|F}6&sL5YPSfCxw`8%LC_ry9lA{84@sL`f;xJXjEX^(XXzgDuk(* zaWlZCg;7AnaWKq;uD;;(o<_KB-+M|c8=RD ze(=0qP(**$w^uq~X=Q~Ue$V9g-kprAQus`1jhhgSJAu^7)#*i7d@Ed~iqG@PpX3Ie z^D1^Wm#Qn{PaL>mt?P?|m2=9X3!qp|KsOVqxO#fL#aC#(b;k-lv}<+-CFLqM(&W}E z?)6@9vly75`W`Kwp>$JG&S$F~%8l;~+DC}O(lVgLXkBzr@tO_#v^veQSZ+nXmo1fy zLE`!rO-Ibc#QxJNhSX1{h3u#Y$QK++o~`(`Cn&FY1W&x(3T=EIaLgGdW|c{NE~x15 zL)NX7;$y9G#1naWH@QcC%$99CgNwvWz@YJ<0Hj18wx`i&?>fq{#JiQsm1uXRte&Jo zVrQ~m&ZI@$jBMg;Tvcbh&#kjl3(s&=OZ%uV%X!OnYtnU;z>MF3G^E&4JTu0g%#idj zzSP<>m#c*L<%%^y-ip+rxH%@-!!$Nie$||7n9;SiyxJndaZ>VEmsA1nBeoijJnqR{ zcM8as#=m=6AmvgM)lALhmE6Hm=l9&B*Rtp4fOO840m}{^9IqQ1CetDtloQ#PAwKJ; zas`H`MzpuhKsVjBQ4xvg3a0|TPuZWj5@mbf z^$SI(qJ~S}XpP?S{;Hj6-?Y*f(Yd00BYTd68X{u7{Z{kQ;X(z*q;XrUuQ&sfz}4`s zX+_INCMMf(oJGsV4c7Wj{fu^=4NOh}FbU>T~Wch2=S= zv>mJTpF_}%?EV7Kwmw5mcL_eJfz~MNo@B_n=-($v!1_&Dy>D4>#|w8JwhkSx`0d zfSf;nKAw1UEp<~i`ug?jawB7ybpHx8=&*Kh`l401+_OQOeSqVRrs%K2D<*qc!tCq( zeeP;+srZ?fgso#n+%`o~_aV!-sLr#5rD5aq?d>i%dnoIMWJW+uGoi_rh1eX``bV7l=@=OCBLKBL+TU3! zXyU2P-jZtO!8uuHjYge#3>UBP%yoQ7D^Yf355yPv2NytlWh1M=u}P&1@)%~MD6`bv zb=5!cHM}&WD@z?ERb2dpbvz>3=ddB`R5|-Y|BHmc6jr(5;^h8xeMPr}8N{+re@!oP z_~!ReyU-;4>4gusztIW}KX6*sWkx==G&KAe#ijo>;G=hUw?^9{sFqOKo$rGceI9`0 znMuQuUk5Q5)raWYBQ^M&o2JP7K1BHK;eWUVh zzh@|;e6^Kd0aoZ^YdNe_II`P9wf0@r%)295oPW^202ckTxP5b2S2O$Q^3oOQqh%8A zkJ2eqxAu5peak(=pNdD^tuAf(;D0sQo-du54^N>m4$-ghtRwZf#c=^dH_J1vS~_rs zGRxfrKK1mXBCGMC{pg~=^|iRd%^aP@LrnG2b-SbywWhYIZHvO`>ODk|k1slyPWa(P zI?)?X8ad46-~4btrFEN$cJC`!=RjL|4a%U`Wn}*&?+^HBVmM6-hSd?kbtK6_JRP@c z2MJB6uxGfS`ZlGX24NY9HT6RUaGw0w;ijO!#FsD71^qH>g?oq8>jdxRH-0AD@u6lb zL_4P8zTDChBWONL^=8jtzoC$Vl8RZX=9D5T<1ts1?P+IF@hS3|%7W!mzg?bxAr79i zPw(qU2|c8MRxHzc6cG*1>4r{|@s z`l%m@vWw}Zz3<&|o{yOqY$iINQfE08*pBkm98PfS0W89=yY(O@PrO~IuiYf>IIAb- zG!aJCXn9RyTDdUl1=|t^bjOW+MH17zI_?7N?JPy`bF_aDiFr%4mba%|KkDX4)6$qL z95;9Cp=GSsyHI*bTTSBr+_M6rsCb>b%Wbrd?PHBTEod_XCy9g2naCyvB#UyqNCECM zRh!BeCw#^a-$zET@oxNJ7UcU+|6XfDV9lKO;%0F)y5#O9Naf0Qw*Y=OfDJ{J#mcXM zCMXjjIC&n;sW$xJ8E#uIcdp(hy7_buWG1pLJF@$*jgGOGLC0B4*gb-&*Xs)cF>Qk4 zE_^>Ujvnf?a#{5d57_Fv>$Ki;Sr~d`DXAqS8Msu^KY~8{c(5rGmU#=US)|~${G~L_ zsl2PbEe<~*Cb$9Ea^O>4;%wn=8y9q9AS~&?8&*OO<-zSRuM8x%&$5(si%G>WUWgg43VTG~q z&!0Dq6X^UE)z!r{RCD6?Tg?n}GeJlmxL2l{tq^$dcbGz01T3{!-{6C{6rdm-p>BSNjqj65V=< zwueI%bZGk6ynapOY;Nq-3wQ` z)zg3iUm`>l?@Kwse`X4?7lYJrki5Qn*MSy)1c+%5v~#=x_W9Pg5GT*z=-o>eSg0D& za&{r~R7$6%=~&d`T+{Es)>WWxxy-O7!%r@62j+8|diIde#9zh|Ozk{F=`RVMe@s3; zcJgKBV!)fhNZ3C*D&lv;YN;V|4Q<_ZQt|#@0u|s>Ms$Fr@_mxo_9BDq+4&ilYV0P5;Rh9e6_Uw%FJ!K=fZiLNCw;!z;Efx;TTA-&6fZP>C-J)hMOz)l>%o%r(Q zMi4-{*Z|Tc&*uZWyU^J1z5NGb_?JX`8M>C{{DTg7Pz1Y+USw^p%*Ngx2js<>MapZ! zvg=?nDXwuaPmF>3E^$6Q)R`LNo~(*n>KFOq2&o96PEa6f zdW&&(S8lR>zqZV1cVHglt8&de$KO{Rn0aN7btesex4cX}+yp(jXsF#e^56vuxV|0!+>mm#TN zN=gcf5ulK3hsGp9qdwQS0fF()@&4SJx?MEJs9#g zr045JGe|64ApOly?8)<9RUN7})gsmrP53w%tUB~axv2@^00E(=+m(ME^uL|d8om<< zz_-O<5$|I$vw&aS*#7l*6KvqQ3DQRqpN97TZmGrZkk-G? zNbMHzosvEwwEwl+fol-BrXrMX)oil>kK%s3FMj61s@{+>N#4&)G;iM?B&?;rW#=H z%e~S~ppShITb1OHTQ^no_DlxTp< z^Y(FXrj(hTe1j89lj3^zBOrA6g*DL5_*|3Q}?T!!#Q`(3-!O_oKz`I zs0B2a${EcxMY2?L>qkh`ol=mK8*1XJ6D*sO;nnY41>cYxXL)W>8Mj2zr+8C@h2|f6+SW{uY+>1d8XbQIXTz_~#52~9~wGym^u1UZy=Gr+~@5xvL z<+`)L*RNYUZOYSJG#QCLZ6ZL-@|(3*@XNCg&lEQ@?PPrliU3|9i3dt(^0fSKKEs#L z27Biv2jY`kEFA(h&nlXL@PAj~{+A)k=VFXaJ$D`x5fi^Hy?_<{ zpU?p&m~=Zi_#BQRIH{I4F;^jb2f~avH!*;V@)tM%w;v~FfFDQeuT)V%mIOOXynL$@ zUQM!2JjdFyNZJKLzaIp($&7EJZJO@$$uZ3Z`|_pe7YBq&s5i!?{FaVp&j_Y|FOJ0B zU&b8())^Um{STQU@e@#x)9qaCLDw6Rcj6lCjx;R7X>84PR(Pb|J2C!p=5hfjx|_9N zmS=zsDH67V~|kLC8nSj0c!H--Ii*x1@) zd*q7W1#HOh*w!{srV*gh=D}D<{OIfslcdLX^f}Tc#lqS5Lg_t3s|7p5Hi9qOT)!tt z##f=u9%LQbpSTAU*$x`mR;~!sig;^eb)2}aWNe;rC6cigsT z+s9izAG||}E$+CBxb26(PLSw1sNZ(89LmnuK<$3n;t->YQ)BEIZcbA%uZ!e^*RYVn zZP-bu+rvSc+q4vDrVBv_L%w38gV-2YZnh&)-z7j6OJ#zi#E3D*F>CikT~|B628c0^wB+sz-I9t_Vfxe zl3Cse7%@%E6o<;2bKij`!}qwAlP&&*6L)DO;}|(4^okVJ@`tM)15)=v#ft^D(F*4n zhf;*H1H(BoI=%<*M%h;=-TF?C9g_p#B#0x%GLhb``8J}f`#Tv-&7AC?aq(EEc?9;l5%udZJ5f4|LWG_K$n7qp#71neis0-vqQ$( z_La;-A^-r=J-auSf7|Omz$}d)K#$4Ud^( zZ0BIo_AGoQzdhr#l1rMaFRw5|7N-96N%vj~Cmehk4Z^36ui?I3ICLpyZw`KfK?|-X*Z@mV%Htb=6#Y(~Fb} zd+;vi(ZyFAi+I3s z4Yg*({&F*_rSi*Xecf{CY-PHTMV96o6p>l+Ek8vr)#4>$=3vMu2NpN`Z8_q*>H9xQ0GrwA8$KA_r#k#*>ziV~}9$?$E$UZJ0PO z3?i+nq(T`*bV{rTxk|@$2k`4(P4DMVIW+QM;zjHj;z|wE@z0%W0mO{>#YtN%i+P4S zN~l$CE(Wc7%7bpG3Y3l^o}rpg3VSGds!7o4%10FeVhIuCHOty^;InO z0B|+GQ(s|v@}#TJxmfdtPi1iOt=)6#i6SV2kl?pbI*wyh(n5%#5c;01S=+v38s0dL zgRMC#)MZ-}E}7g9#65MgV^OaeaxSmAgFFBCxCH`rVqeuH2{xdB6^_)(Q81M8op%M? z1K894F9P+cMh#`;uApkH;8~s85~hybv)|jimHOF=dN$6wu_j}*$l--BENabbzC7TR zy|XBMYpTOMW+!Q8TOw`u)5+erP7+2v1CuP+ih>giVaIiNl9Wz4*6g`Jxs>wSdOd{*wapR(3npE0np6<2Ivw z?`U|7XH|wH8d}@8)@#}lMP!L-${RfEruk_l>|+loz8Wn#rlFH(+jI=QHolFwxq(Lv z2a0DTOM3&@lhkHiHA*BL&sp~E9wRJiL8R$ zz0&CrNqtfm=>_j)L36o4!E%w*oFX+p77ve(yRm%5bA?{o3fs~&5Pi%|61p{7ALX!6c& zaIep1fTw(G`q8!ou3?6#7@;2zKXCjr8DTg~_9<9okw5xfOa;}{y^*eKxy^oxW_X4@ z>_0ZctJ1j!`U34jig)o;Y>DRGq?=k?ntq0gaG$HKu*>1|kTCAk;DlyBtHSX@Po2j$ z@TlH|%C-Q|UAJ!L%@f&aAmmic^|}cyIYkZR5 z+J3l(1AUW)6Mk+WqneuU-@sYd@q{IBg(}kW&^!CEAB3JzLq??LyWVE99hFq*!L#1|` zNlW{CK7fVkH$?UyO4bq zb?38L-}-2j@O#g@Z5eO0>=7Qf{aEE1Kc{*{(LvSyLA(ja zS(4kv57BG@S;*&K$Ub-2;J+$qAk@cP&~^oY;QWGaEyI0lkGXskPk0-i|0CS~dy>Y2 zEo_Khj?yr3nac!v}i1%R?E)6RS;_i+CbY>&K z+;^6_%`pj)<+|b4Sv2&+$K~%#+CLQUE?I>YeC5$Z^~T_xYup*k2X$c?Ch7f(oDkct z?Dv_%q|rc~xyZJf2F3SmK+0(U3bzdWq|Tw-#6JhhJEXIw9Cv4IHM2KLR|jiHpN6yC z#MK2{m7ypDOWbij=(FBzH)Hh$oe@2|Y)L(r7fH44k01)1s<|Ag-J_tn)A`n6SZ$*s>cA?|eE_*UepSd|Gj^uf zng998=y-*uoW;|c=1<%gQg6YpV)686JO`_p({2!qoxW;MPM-~t~F}yGf&GW+_poC=f5?_bnhoLyuM}qGdjJJ}-JU(c4 zB}OSLtb*PuK$;cWETMjo{Rw4UI9i&xu(!C^uZ?-@9rtjUcB@iJdT)!Sy(H_(BPEWMQQux_!&1jKiS^T*Y?^s!*<xgdxm`q zT{S1}gY}QhXF0ow6lNQsyyDGo!e6#;)|hclJ>)g{q(iKWK&s@3U4y`=%`P;BFqUS; z_8K6?<$~!b%%5^Khcbv+zRD;`S6rdyQya(^XV0-{pv94oqbx(sFU239z$ z-u;cIDZcxNzcm1%71VH`UDun z9PS5RWQVAt_`6_X%~UHXUCzTA?=GX}PMqC6^x>w}L8qs{*Ao1q zbGb`WI{ZgUud?{mk1bQQra!%AsH#&%>@z%T>(B8RuM_{OYpI9yF1FNOlYDx7U8l;V zW_hf-DN7q(;8dgOoZRg>7~|VF^EuLrq`hFi!t=##%8Dh2=22zW(Q1f=m!%;ZhLR7to%c@5F+7?T ztvth39YalO+#0vP{Af`|>GeX7(&o~hzSO#|wVEJU$3u@g`os>HS!Gn*G_a$$mTBw2 z*J~e*?JkXr8+=JulxLK1Z6@~ie>wGf!<|(BbBRu5AM{H)jwZZNFHdDK!gQ zH3{5n)CCLmA0sOJT1;$Op*&TS1|1rZ*KsHE!?BBxY(f;_O9dSqZ49j-fU5`Ce6JO2 z;q}cHDx~s`9jgx7_T|XgMD^#R8Ovs^&-Vq6v?Jp=%%vx;0!8$l7@|(2Yz5G;#^F&E zQBiK3Sie}S>F%dQDM!l)grYJe+qjolJ#lI*y}QbEX?Ame>UnQTB!{w4ossa;JDiT9 zZ&_BoWzpqkMo&=<P)&xMhVp-Xqkpi(5mrJgq3j>l`nXQILx_JtW1Uyh{kydk(Yq z<+!dpS!CJdJ$+L8dvQ7yL*>MVaw4O4u=>eCp}8RF1jn(`AeS!<&j;gOvyfrdz4@*w zGw+IFZeTzen&tF&ilS|XU&ue+UGCdl?r1|$K`^i@xke)SZoT~8!9E@lnGo+Ey6&el z2zWtKxTV?P254wwyYnC(I+-JYlgB%+;>rsnN21TRNkBVsZeM!YfdJt{)0pXz#7sz% zNsZ`7%zC2BD08BCX=&D(v+7FUED3&V4FAn!WEsELb?d{1Fd8L-ZNLN;-5PNG4~;_$ zt}qS4WrcktJu5_|XJOKaunYw<@xv;l^s=?iI4;D##r$jquN1~JwjS9Vju;dV-MX;r zqMgcJDtpgJff8^3-i`o)o3DRA>d8^}o^5hX0_YWvHHU)7-27xk8)e zfxDDcxYL&OFRV26MEA<#Yzq%c;-v$?OC(jMGU_pVf4@E(WIeR^`X4{xJ}Mf#2OWO? zNb=Lwyk}pW|IS9saqUmsj2X1+&0pB;9+EnImdImJ_Cwe9z@~5{OIVt+Z!jiB`Fq<7 zWjPKMwATYDQAqlZGe|csCtrIOlSWT#2Z((X@waSESCEGZnML018hXQANjthF5Z9hr zUcsj$CP@D$d$(2xk@1?$UwouJcC$fh_Eqt8p3qiQ)Kj(GrLnH2_L|DXN~f@LM`~@w z7faq9oVQ7R?W$34ii9-_LU?N>tllYo^y<^_*jpX0KZOE%S+PHJF4ew&&O*{8=0ILqYy)V|tGKrwF_Ue+%1?3Z_nz3VE82!y2GHIA*f$_MY z2P7Wzz!KqGvisR)SjRwMmB0G(o+*j`&;5g;;%qM`l%y}rB}&+=eDVXJ#-#);<9Id( zgit9HW@18DGf#HQg3Lmf*>)GbK(k$S_MOI;J27m%jt?RWu=qTPo-?oh^=Gjab+-j#`5N=`BWGLY>E!G#{rf^yq zsV7!|3!~pT!Iy>1J6b@W9@Ja|09)1qMA|pI24DJ5k6H-Lr0P8MI!?{+b69*dIKLJ= zJ+d>FDDE8Dgw!hBMfMTTdzo2mcBd&efK~{V2e|bUb@ix|T94RhqHUM<=1az?nL=?V zOLJa46dKR_z!_0oRO}t&oVgE55gxTdmDLZwZ2X7v>HnOKC8W1h;Pr#{f!XqJ*pc4o%0IQ!9ARm z+*YqE2jo4ga&4O+UL2I7oE70!2Jg{3vka6m?*WB*toMmo z(C{Dpy$gTv_a;Cg7fPm~Z>Y%1Li57Vhh1evo^sZL0qQD~n6X)9V2D1qT=550*Hdp$ug+k>LBhb7?P~mp+?==k*_&^}>Ve9ei#DR$)NDr%=68I+cI$`d zQf)xOq7jL2XsnE?ET2tr5|T4f>G4Rdh7vOVoUyKCc6*$g0tIuBh?AHxspsv9zKx65 z1oi{dtSH4b@g|aePIm%J)8o7>MdH0+l;>)beRk87Jj?@&k6pf6!u2o0_FnW=KWmpY zmwZXuhB(iqRr8!^>f2Y%L?lM)=boEcK~=| zcI*S~cC+&rh0x=%k856>Jj}j)D>=UL{k3LeO{6wMCb(SCkwR}f zNg2h|U;G|kPwWo2S(jdN>)w5>^VYR5+s$Dppq@=JI?6+-c!^Bhr)W1u%6fM%N!TWk zX!DF3zGY1%cmmks&p!iFWpUA=&+0Nk!BXk?&XZdn{bS}UbxZrS$46`GeGb#QZb^BE z!sQ1Jpt-2`{91zS>(JPlt~prU8JQXF_ER%4CsH40)#tFDtQkOr)Ak5mqQN7MovBH7 zuLuNOa(xd-wg-Ri!31l$Vb?I^C{O7`l> z73Y(;_vHcs66YMC}j-VB!tZw{GmISO=b92}lk*wrKWSxw`;k^Sxd zgEyhMX#5$@s86bm-*nG3Z)G@5?U;?XE%cau_w}=r2kAGJ&GoesTLcyNSfo08-j9jt z!MUVxRq2DaEOx+`K09{Qjo~wRy3+1`dhE6#a8}vC)0*{k)N$4o)^qa#^1idQ8tNPJ z_%WN+fnl}WR}i<12FmU|BQzP;w- zp{fnh-jS0qL>ze z)T*7P`avxxj>`q##6?$X@#aDBoDWeQB!4F=E|&irQ86z@UU@A>$84_S)dzCX7Tpl- zVRX7t5e#9_7m=r1{DlgA3sl~AT3U@R!4UIfr7q}9VR{R$Oz~JrM@HoZjj>-aySg>O zIP~4hMR9FeLBuSqepilMUL2rtMTJVM3LtS#+jDI-f*QBtdJdm+qL9`b{PP4bMOG_K zd-)FXILSGE?#>kEun1p1j^iMmpSlR@j(Cnzi8D{$%&pCLoQaLUsHBjo07d5+;sPQv zwY&fT95uQ+kB@5sXhR7lNssj3W66L*n|u}4C99+EZ9M%RGn-UI#1{*8V{L4A5xpl~ zznEc=?lCb1gU*)l*rvys1I(Dj(x3A91=x1=jY?Gi2NbdcF5vn^uJMdR0Ex)NWg?=> zvE^9we@JVNS5J$C+}BmlD5 zp4(@i|FlYMifla@f^$<94|fbpE2Q6QyHTwK7zx@sHKI2Pc5X!1c1W@49vqo)GHy*R z)6)H_J3SWcE_)5aSC2NlY8j?#F!epK*d^95BHTZ6GsuA8%rP-JZ5YvUJAqStg2LDL)=871l2*zwuX({P$G=96LDOWe}Pud>DDIjEjfYFg~6P892#!&%iPf z0VY$?Iw8Q=tL-`Jwy;bSzUonmU;AP2Q^CL;$bZPC< zK9~WjAuR|{jpS1`ldOY#$0nhi7o3m2J7uwR`%9zH`lm8G9IWF~Q^_9xWG;7B!b{&H;4&)D z=(=R_^?>e2Rmk0&levmf34di2{5|bUXrhDDL@xRitITei5go!BmJRHjj1ZTBXF_|% zip1Z!OykUbJyqz|Z-!EPx0ZSnDA(Y@zrq-=ngfkn`Fs;u#{mt<4$sgnR z!;|pv|3Awh{4K%wA2ag*(=q?=(=q>#n#|MC>LcIKEbSxF)6{OHp`1*HS7V>d*I2 z1JUz|1nDNd|GG{AZ$R+yM(GyfH+;H3$0P;_!=iH-0j>Wkq|VGD1EFJ~Y&ZRH)MA+q zz-#U}a0E3Wzoe7>IT12%KrHaO`MzTuVSs;a45N2=%!+$C-)$}~HE6D01RKJ8(J5Ht zi{5a`TDeeTYjj#}bHqj`=Wk9X?3ewmd2pMMR*;N5_Orj;at#0TVgKV**jwOROV5LL z7+1j5(g{WD5&jP!o~jP!D$$+}0OfUnB24G$`1Q^2jsxJFnexEG`t78PfC3Vr8aJWz zZRW>+jNs213d07Jg$=g^4&3ieOCBb5+ zD&?QQndUgsiQ3CcojN6250|LFIL?QKFi6@S^%;{)W6Z}rnpQ*Vwo3E>C1{E?c-{?_rcV{QVH z%VFYcWe=`aY0L86oI*Y>FKH^D>$t+N6;tyw;dHxV+$As}7f0rR>XmdXM?4_gTu9I$&v=k)bWG z8u;b+iXE7KyPM>Ue-J+8zph_-%Dph?5`dZ7jI(#L zKjUMktL~ku9>bkDtrk~6-!)c#L+8`sW>=MO)u_}?D#Bc zq&&?hIiwra|2VY2ilBBazVpTQekR4WYweYwwPBYiSJWEz#yv80 zgv(+9f3&q`ZhbOE(5FjKr)pcjU!Wp;>uu@mn?Tgic5zUodAUKZeqk2S$oGFng%s9T z(|xI{Z>D?n1zuXQR9%6;DVLmG+^UEu&x+FFtN0iYPY$l`?X$6WWt&=0eaI@t#&eum z-A)Hva*`v@*LILNTS^+|K0tg=|Ndmvf9}+b<%I( zm{uM$*Dlz3U|O8n=(UB~!-yq=?8;O39hwh8PzrIB{p7vw5>r|6m~ofYh@eO_9mfnR zUN!9)z62x0&%Si8;CRu|6vo@Vh9`@HY0KS%75IDN+)@!)np}@@miI1fJ^W=X*rCeg zwvUWP4;4}D1LTYaUrO2_1km^yu@lGwnsl-I1q9%`RXNayW(^$_vdd>iAcnWvU}Z`M z@lxZ?9b==z3J>@dX)-c<&V06j7ij)LOQQc;YO~WzFmKJLw{Z-J?0kd?BiHWCc22UY zRYQeB6{airCAiz;f9!b3r!=aB&#ZY(yQ87Z=<;V-&(ex|0z*6>0Ev~oSq6wtktON^ zo#5Ei4kzX7@5&+uONXPO(kEQ)!`thwp$54Ir6qSrhui}OY4o*~X5-46<2m-k`W?P% zJhAG%^_!9$K`o}V_5Ouua&Ws56UQZdLk@AI0cz7?xVq1g9xXYi%Or&~>ndXQ6M5ef z#8`uZf((iqLs$7-#=PHoDRX=LU+leSSkv3KH6A*s6h&kUNKpYP0#c=;pmb1rN2N&( zy@hH46$PY9S7}lLNbgnYy@k+%(rf4eLf~CF=j?O$*;nsSUHyp07LDXbw7Z(90uZEuOK2CPN zjY%AAZ^qcE+KfZ}kDn3|6%g+q$@+6|F2wupj?|pqh>&(eSFT(8_;f=W&@bW>J>pR1 z>&|tj%iIyFi13?I;i&Cd{=s5L{s>eRSz~%z0|&IBWN`0@uGRWS^6SO7pFDA*#emIL zfYKME>swc!FVUmY_sI%w!%CLfbNA`MmoOfizkdHT?FIzqKMIE!*_>Oe-9(9LHbDh# zAsozr)C5x%Kni@sDjet7Lh2C@=Dvw~Q=S)$6-(R`0*q1sgX&6xNY6=IQg@!a@{%nIvpiObjcRfL51EeD&Rhp56Rb_4VO+B>2bhl?o*l|6VC+1h3?cS6G=9Bz3~oGoz<45Y?HV!FG1I^`!cX{A zg=#VW28vLt01E;NYj)fzqFT++7LE4%+n zZ&acu4RSCP8^$id-Dz>IP$S`5A;00qk*N{UjGYKWQtpy`!7O-M3^eu+)}|+kW|;j$ zx~lucs?F*b11q|g9@q7KT^V+a^xNADBq%CbD+3X<{o<4BjymE{e5m$!fv&;|2d|c& z&G~*0WD!U`;=2tt$iO?M@&07SgDmk%TlMOb)>f7%wOudyEAnRPWf<{H?!%IdQG`gZCE0BHrR#gX| ze-@y65^EH!KRiO(o)9;lwbqP`(!aj0xmIe1yWeTETJMhYt5=ni)jf1s9_2z_=$HM# z{&9lDlOh+lA^#^AV5xUKNx3XLZ3aIP{bJS%hMe6+qs*rRu#O4Ru=1Fj#-i$V_T-Zv z?+^iH^u#5fe~8B)0@83=A#2;U$QEL5or3j;FO#GuaX<5*>lX$#dT`PVG>Qre8D9o% z8lRR_Y?2~YrK?NhIyGgkhQ-xiD^yEeKl0yp*2l0ojaJtjA9s~sM9n%f%F->@oj0DSE7d zGCpntIvq)35vyME_ti>c2RC}^2oKVA?X6~L`mC~}^*2v8XZ36c%Cp;IHnR)NG7LkvVk$)(I|s@AZu zhE=a>F~?JxlAZ>A43Q<7e8{;?|u@^;{9MM$>#Kzk9D$O@oX0eoU4v z(nRb~U+&js_M2fooJkiEv^*e2*aB&J;LPxb?_K_n`IwxYxpgmn-`!PBk|O5KyYF)G zlFsdqX-|4T)ERi94~J%@fUtaOm+iYmuQ>C-i60==K9*e=w@vCkX?K+H-ax>5M)Xyr zOQ@Zj2oJ4##`&#~+tj^PC6hor#s2V+KC$b4dYcKF$D}f{)DhVqK99LlW7(XMVBM`~ zT1YRV`k3GJ_C446H{}g53*?#0r=4%z)ZCeT!w(LKYxFn4Dj27tDa9MhEz>;pD;Li{ z^J{Svkh=r@-}q2DBNE{U!;c2)UM2~MN=T?YdD2_iYy#i)NQ6OZJ#qSjC1`Sly>EU< z8^e9OrRC{TEf3^pTYNe#?!8omB&tmK_8nJIT3W9k|I9OdXlAE7!2rQ^Oc5laq#>aC zFngF8mXW-Ro*J07GAAgiuX4lO*`9Ab-Cs}-IB9QJim)o)^T0q10?o>N>vkE1N6}mi zlMP`~IwxibtjFaI&lGHzHElQ6PP(R?1G4|}+v@N44090tu0`Or2_fNSF6Z4b7u(U? znl;=`gMU!Uj{S#;bXA^&+dgqjU85$*ejPK>`BC27fC;NW{6gSH+?s|Zk73R-Sn>`BZrQ6!g zRlg7Fe|iX}Fy0T5i=$uy;ttk5rdQJv9&9xR%YTMVPP@-~XklL3bO)OA0EI`@TM!xB zIQtW@lh~fsZ0O`~aEcG4W{SC{7>-=|QS0N{l^JiwYXz-)nCesgIi~VB%B{eqB_7q; z{2kf_RPUVRCsg^X9x(e?CJ*Q6s!yA4yBpVdsW(hN9XGOal%xT`?(E^T=GfOoOkVf#x2V5MWf$TUb&S zfd!i>~<<+PEwb>%PT`E%_3?Z?5Ouub(=sP2FNW&$4o zR+hiH|K>n{IW94flfEs`yZf8oy1#tWvKo{|vS^10e!Xw}%SHXa2l{`(1GTJcJfbwW z!Lfqq{>xkZ%WDdfi#rK#~jzMj{y{E>qX-oA^CH}ze=&d z-`Y(GFq>k6f?B}3Wes$iN9z;YY$)9ZrzX|{4<&MZ_oZAAaq_=pk0W#AEyfDrE6zo*UIfT%<))P=86)#3(yl;215JvGq+WBw*c`xgOro z>Wn`lx9I*izVUy}Ff{IjX=^m%?t*4!l^dlBii$P4K{*hr>YOKXI@P?jJ#KTu-*f!KK8FEKZs+lr{G>zLC1VKvwXZ-mfv~ z5Xf=X-LE6P|C>?w33y>JCGPa$-9v2w0v6wJomWG zTZ+dMsfq}6_UbtzMT+11m&_-i3N=tQ4oXE$C|1Qjbm>B-5fEi^dIN__eO=h z6kPqs@5|J|`Ctv}W$^O7$EppAi9)dm57+-`@wNO1n19>#67e%20DpVT=G7KkBoH^6 zasQY(ON0M#`Ay;3G69@2ZeZvZApscbR5!#@*#5OH(E>;D1he1V=08R0-CScz-F{>{yT zHIj(r*)0fPvT;VU?qk=T?^nNXzj<*P(~^Df|%#yz3&JtrzseT-cE&8{eJl+*g+uWh2;C(lnz_P8606a(wLh z3Qf|`Z)0N{Lc1E+gEt&=0Ggv0&Ll(WaTP9nBEw}iMC;?D0K;O-gnZ)~Gmd(}QFK>d2f-#6 zZ9l@hpuGEo$oG~3dJU{+N~TJz%J$f7MCEjKz!WK$%RLG%!{Qf(Ekq~2MelA3$ubhO zW&SrHy!d_NW)p56hl%St{toS+V^__zovZP}v3c0bT#L=siQTBf!ldJX#92n|c>?Bu85+^-1`E9!iyb@c28(o5K^x*iv?iaCGyM%6pR z_-8VOSoa}u<7}%&j7T10oMx~2Y*@|x?50f~+H4@pe8LfL=9?pIyC1c?k+3T}IvF1{ zU1nd=ohqUkaP)&y`8G_ipnk#5=WBpt)mF%=bippz@EPtNU7)=Yz(+>K6x00jOvgk#OcbMi>D z?X4nQOv`B@{3gPR+Y3F{VEe~h*FxS!3F^nc?=>B#g>cr~5fp^<=EC?T_mf5;w`F9^ zu3i(ud`jAtAl(@ogsK0X*%IkS63#4sRX5dJX@6~+9UV|<^( z(|42%yepS()6)KAXOq$U?7CQjcA*Z!`d{G0YT)Q^Tu-LEb-7q^bw}f$n3VXj$)4fM)F=2?UmxbBVUcb(v{?47$)CHndZ@!rIfY4fjx$A@w!Q-O^kX(IO0 z{B&u4CR#9c%_6HEYC*4kLQpa*yvS?tAXj=PMyFsqLmDG{x)!f5a`DtL33vGHEMH{7 zlw=}zFV7qnUC|B{0OwdNvM|GR>?-Z;1M6<$WW3b9q^P@?bx~tZn=Y0Ec`>UQ@PRuc{UXhCh``!cU>ABmz z+jI+N*auXJWQ^PMU7YhQyqtRs!(Y>gDEVc*12gAD8v3F+D@;5_Vh7W0=#}fcUF|gL zTjw1&0CACbU9$B3gp;bTz)w^lwMxs8`nQDD;SGJv*TW%w9gl!^;>{%15$jla*L5GQno=#e@g0( z$sq+cK(ckY+1(i_18s)KyzW&j!0T`D6_BJ?vEHFk(ExO`7Y(Q)51

o|HCh1P9k*hy`lAbK%Z&XmTVPuQU%~^fSP^SoOsLMY-S``I$B(H{Z zu+Nr5=Ld$4U-l9FEy*|Jh#aLELv8Bwzk=NE%8LEZ^_Ljv=I@SBXsx$q(0DE7Mi=8M zk&v;{TXZcMuX4_KjyH+fd%45(5A}E&_0!1%(yCH3LAhw62>f_V%Rk_`!~WOt6MWQJlU7DUNfCbwC`&Fn%<@k*)Pn|;EP_dmkdC0nMz3tTEcH7=B6|aL^^jMXN7qlvf3R7={W4<+>$Y*wH z$7a}-agQP=F7$7(uM^FtqQS^Jh?z_9}3#{R|*%5`o7kwLKe#!I$HHOs#8q-)gNDyXW^ zcX!2_=k!V%DSzFK5p{w5p7`a`9MECm&G1l8MmteE>-Pi5!=BZs0HWd(q=SlGl!m*MYwNvT7dX$%v z-l$Vz-q6>`Stq=C=*TeY@ia}xYL&QguZOvojGDO|)~W~F=faNbn+M!{PD)i0+&d^n zui`{|#(rdtjK$BgB_^KpI!V*wkeLWwDMQi9bg4$WA>5A6cpw}8uw^0ZXGOJ+_s_3x z)ynH-6tm`KXsCTNQ}#{M>TVr>r)aafn%8{s@YClN0WH2+gIi}J{6o#{`qes<&NO#& z9PpSOKhxm{y`tWQhR=LvX6g$pjLV*KikN#(ry>wzwH{xZ=AP0{_N9nT@s??~ha@q$ zQZh{T)lUKCX%Rjxwc= zS%PsSy_uzLiJzW07vgeS8R`pRkb z(%mPMZB}EE?~7;lko!WZQL);((nHBDhOK7$l3#S|3a;2M^QeL?FHe~Lu(#+4n%L~` z>^9ah62F&?wv>T;z7#>v{YNje5MIXDfNq5+lLUXfK%NCT*#CKJ@aRNpbg>RjQS4x^ z^}u=IfUWBAr}OfOx7Oa53P@#_@o9T%%NF0nlHa}Sg8GA1$#I~Gfzn%K>58ON20Y3G zT4K`^FQ&GcqnnuCMpeOoMchwkWz_cR=>~Blz zReqp&FS3jE!_k*-5BujV>`vx02#$)4lzW(i{74_}p!tcQcQGxHZOBHWTvp$I#pkl9 z-;6k2rLSz(ZXz>ch*!IAHNsT%qq~uVL$Zlq$9KVDUR!umfAh<*d3$X(_?;D8mSA;2 z3w=*uc>v;Z00s@;imQLal&nd?``YbU#AlrV2~Ozm-^NPIE(cCwyYmzqLg){ z`z%jVN{vP+g0j{8zw0?%x}noZ_i-7keKu%hdzpL0YVF{?HP=R-$&{Gz9q;t}dybIF zbYm7S`#9E7foaOd`7bnLpA!c zJ{HK;f*sqXqzT@-$x_2>X*;XDUQ+(|2mLeD+wx#~UK`^w-ysI3DBm4NMAY&vn*6NfSwBIIx$v-`nIm<|P0vA$qH?{FUV^qL z9Y+pq)C3XO>-l%C7In_E?Fz?ua*JXAirAM`Pw4f|KI_X*K(}y>;eErl=-M7Z7zvBG>oA|~sxW2M6SW)jX8vo; z-!iQnd^I@bMsRU%^UAq?2<-lsWsHyZyDt{|5sXxFJRhSwXox{ zK3$?g;v9n{L*NoalGs1)(6=wHTEnNg^nAU*$p?AHI(zQO_!^4MyxDlzuL{1WsjEV;HgGAJ7)&^DQGh6qhTct-|JoQm8%hUUVUuYy0 zUB6TBj-Ea|1+E7iVB`6SM^_uB9$&RFl3rMf9vdaKsXorr?HRYd;Boj`fG?z?t*%z?bTF4{7hESTf3zX0olvu(G zA!CTKD9z6y-JriP^X(rZ!zOKkh4rT=Du2d8^gHd2mL-3g%IzJ{IIV8KjL#VyBOI!m%GRBcY9Qnj8G?@f=WzPWpxlW9u;a|&y9~; z+S1W4W^H;Qb{^T~4W}nmlTJd}4Yu&XFN4>^^-F~eMZ*tG3k!VUY;{4zH6)MsM&0~?O*;w-^N>7zY!?csr-Ec9hSOu=5IXk4Ohqu)K=@w0fFHKI&!@ z54kPMr@@eP2KmG~&B*iwX*}dJbf#JMbdriyYtk>klAt?b=*lnm3m zsF`!^2x*)VNeZo!F@2|d`o0{iYt8W2SCIM9m`beX!s|N8_GWM-egZ94lH;n^g zNH~_J%erDh8Oh+=Lv}xFHmc=?bxg5HUu{Rf!533i>n9yOM#AL?N$*AhWIfL7wOFto zXsONoOi`5Vbw{<>YNa*V7)I0;{GA9vkT9Y+tzF~%NZUDQ4tpHQ^)7cxeS67S2t5F4YW^U7nEVT;VPcP5V z31j)@$>tncoKou=}-gvdRXFa0V8S1e?NFuqWyTdKj5 z1e^FW0BxIQR7)r*Z_#v)<-#zLBk|F)vnnTt$c9sM+9Qpk;L`BbK+NRLp{(9g0_W1h zU7SU##`uQRTcqpr|#tW zj6G(}9+d{{?vD?YjP<1>GlxBxOqs_1-ZdDU+Uq(s7>e70CrBtu{ipx7w5O0H(-;)8 z!DAbGJ;36=C>iwi+Dro=_MYn1(gr(RqXGKI%_$-TrpF1c+G0Qf6V|o^rjdZ7K%d8FO68rBV(b$H(3{v8T#N zjGXCLF08fYnck>F2XfWJ5CzhLTl4zrU#eR4n(GV-%cr{ZlV~BUs8a#DK#;ITr>T)= z+$q#+Ux7huZ*d)aByLRAwCha5g>*~7zA38t<=IYkF_a|_L78hfAkK@+KRT&JtP@@A zogNaO&8 zl=WY54#07c4?yb0sKFqAzcC)XC;m@weSpD&1(W!1m>K`(F39QOi?Dm=`eh0K>5Tlv zOhXyM^oNb_udST_rAMsT`%JC~{E`fN?v@PkAZUk7rYd!3x(hypsebcIUU0L$g1!>> zSw8|$hG0HRh?o%UXu!GtKfqXlL^Jhi9G$Pn+}#`5qGXLMXRbX~`Xz=9vQ;FWsWG8O zM|2OoRDe;2MLa)Gu0a5fLD#_EnR}(lhq6f~SF!M7jvpmJEBk0?f5Z92dxTUm(vVYv zaOwYGQy}<__?R*%c0L_-ZxsFc!Wha}fhUlK?~3)w0gM>^>w^#wKa&TSb9*89A!{TO zJc)#x-G=}g#KWA10#em~-w6I23H&eguviWp;A}rAOLSjyCY-6Pye;m3RO)VKtk9}w zS@pBqbMg4U#mYa^cR2yjBq>#W{J0~UGeY6sJ!Meqe(`b(9sb;>_YX$GWdJd1L@>0m z(#!#6a6k~y6NZGpe*K=n{9+Up=B09z$sHNzkl*#SvPNDzDIvB5iWx>XwWl~vC$k8YS0yhG*VDd>_?C`9hIE8-2FMzaN+)M z8>J$d|K&@O{s{_RC2n>N_);V>>xSQ9Jpifn^T6;w*ue3f3C%F9A2!8IW0?MqG5*Q* zurwyX(A@UHw}3ik#{!Hj7qC6W$O**_8tXa{6wmftb544iqI)y{zFPdbFLWZ*XwN%c zXFj-a;+n(?AR*9;wlV2yMP5lv?pJmBw@(LeOo4?2C*vhNfr|vsZ{z=8kr7OT=W@M& zy&(8&#QxvoMUHh5%utKR;tOZ~*KaD|XJpIIRciljY4}?_wjbgF<-qW&yZ_ra$QYn zh#aUZDHR3&oSmfzt`hl8Y=AfIOdWXb+BNp8SDQ};x=dfCr|eCPaVP zj!@%eVMqhR(MsC$?B33wa33qgS7&iLdb_J8{J$Zv&?FN2q${YIi@=>?CRw_{#Prpf+anD|dyMq-Hq9vF%XPOJCbjQo0Oko7&6Upr zCZfMP!4twZi+iKE_cu_-U`FYk)w&JM0Fy0J_Uk@&(rbkJ7IT@3zt&uQA zv6={j(GM<^Op`DEQZ?T4r%N^sfK3vGH?LaoguLV<*Z&RohMbl4imY19z&y2Ts+5mZ zTyO{}0kLZwKFkv}3rGogW{82$UkPcW=_nmLWMTSmgY4h`y^HrodPvPwOi;u}w7y2f z^pn>_hEQAsTvVGn7yS#lal#qu3eL`usjHk%-tQ>N#Sif53#xIO%=gv!{EomxBL#+V zlMww|;^1z)yo;J??>o6m6bHrxwLdEq49l*CktX!i`0uK`??e>kdy1yr4~h75mi+58 zlv4s01);<4ZeQ7eK?PHDbYJG82|lR+iHX)>QtyNuPcWGbNQpFLsD7Oa`~_9`FOHA{ zIK(4dsPs)7p#{$cNH$RP|8*>|_JjKfzLYIXT#OGV`^jaxU^PJ4>D4hqbWr>c6xzsJ z;D?uI+YM>RJwd2HN@Hscm6O1)qQPz?5@~r z9XJ0JwBNTk>vIJ)0p8@(YKQ6V=WEzi=m2)JxQj0qY_eh$Szrdu&CSKT4AEXPdu5mL z$g(ST-O37pBFy|`_K-FE)MJtYSR$t{V%zZ?XV&z%o0Jwt2(F}Yo#^fIq`ZXxX6n|Zo{8=IT9 z?`6YZ`BjNM6g^FGkBu$3loODS`MCLSq7s(s0$E_(4N0nOT|P%N{-G>IzTaLKLv?f` zwKE@ldS<&S^&C~V-4bE-^F@d2ov)t-Z8mn@dN(v7eoOt2bM!0TOP4<#xO#z}g|jUp zrAQXx`@<&(`}6E&sg)f`Q^4u>^Q(Q!bZgXe^X_`0R<(NvsC_>V-xtw5@r(v!n`=jY z=qYN;b(__>;pL(2wq8@u4@hZ9s&we|M4X}MHrz-eo8`1|s8W2>$$p{M_`ShGsv_dJV8 zi#75Ckaesz(4iGrC&-D7AtqU0lxkot*Ug6mU${_QeRy73_SA>>;gMhBE{0R3O{K@! z&8O_d&n7?rSlWbC=F+koAE`eBr)0!oKw2Md=61*qMG$5U$#XNQBAQ!MKgzl%>h4g! zL;YQuKmfbIP=2#FbB=Y`xy+6U@f@Glcd4xSVpr^U)wtfiPF1OF^f2MfM}{vGkNkR~ z8)m88A!~2#SNR*17d58VBLHcO->_J1p;x0i4fM|TJU>f626@0DNUoE4$PWr%MEMg= zeUS=tBx zc#iGDqHo3@hM}T(RN_>I%GRd$LWkjpZ*_9DbgMBN=sg3%8R7Ta*2Kj?x6!#gMS?V3 zt`lD$Q%s8VI+%U@nXZxI_0_^af1ObWNp{ZO>neQFeP$1ZRSLLMjYl_B&j?L|4z?~# z*Yq`)g0qxiojgCPwpE*7;|fre`L3U0>RDCxue^&dfS%4C`76}_yuiF1ciX0!(oKe7 z6DVq1^{kW$I<{V~>gUZ{D=py=_TTBLm`|scJx|H@<`Nh0Jd3Z~$}pTA6u`l(7vtqbm|Vk$S4W^02G#v+9PC-E#uvthBJb3rm-r0Q4;00ABMgNS8zYSy1e<5G61_m(!SN+}HbR=4k`c6zxEoh^K7ad%j1k~KTOzl= z7koXGyy6d|jzQOBr;j5>-$Y4D#QRnIzDvFxp!Fsp2$`cc{PD0yY&uR;#)$p&xCF(= zV=}siG;X+KN}kjsKS=-v}Vx>Q3Ob4W)+@w zZv%Z|zO`|VZBa7|t0g9eay|Q$tA$oJ&1OA5l?^-T4J(8g$Rou|7CT~c3J+i^5tvM2 zKEj#P52Z)4f`YTm%$;upM0t*OF(K|7cW~h!3CGMurvGD)`iaANxBYz1_BZ)r8w{Th zre(x+2X2MCdhmD$v#s+zv`4;;eZDT%KI6fUX0wQEko~Y|F}BEcJQjhw=t@AI%tNC_ zu$dD7rnFYlwqs%5Sfia$Hca9E;(Gzww|}9hajuiBfF4uqb&dU$BeeOqBq?RJkhOs$ zsmMo!GfIc6PoM3YrCjtQ&CL{pOrN3&Y`3+}`Yip}9{gm%81X|RQFuh^2j&ybwCNd% zn(nj<79)wSmOr9ivN}CMm}4_+XZ6Yni(XJ%yryRGiQq#>n|h*fOm3f)6>3ovZ*|Xz zr*?JVJ;PD;4UU^GJt9_XTQAShM**lG*&qqLlP0U!r@IqKQ?k`);Be@vnJZ?>%iAgq zxM$~kqlv1HR`M*9DOLyZMP=+eV0~M_tvyZ}P~)}!-fJ4xlInC^sXrGTAzNm_Z@6+s z{E=S-5YUV-Nj>Piy}G2+yMj&se3iZT#lni$&jX4GhylhbRn#M^POPk1I|;nRwm3;m zr>eQAu=zgOQ^6n5dyHdfL5npYf)D6+?|)|96=}E}s^@H%XVbjQAQIJl@SKcFxyCbP zEwy&s-NY_$r)sX}WfUTL0_C%fK!D~qURnEsz1^Il{luxojx?DRa0-LnXJ;+Z)3WO{ zohJU7OVdpfEQJ~jXa>FeWR0}u%0^kn#?(8FE%OUI{hcp*$MJZenh@L2D7-<%QlWAZ zhLRrq_*l9lMbh>qK?+@ONC>4U#bMER zYz-P-=eZ*NDVAtCN(*&o@7YdPe#$r7Nx)5pUzVJlr1w!PYWOEvOSH?}+-s_Auvk|c z@tgvbD@9c)HKWV}PQLRVnkc0fZY9@BozQKS6YnbW$bO}!SgHy$H&83!)4pH5r&JBi zQcrn|nWhpt9gv1IiurW#QKk%5y1(|!h8vb>a3taCXnSya{eBB&>ZyVQe*Av+@j;_x zO1oySUW;GD#MfvVl{s0nsBE^~KE!>Yu6LL&{Vw&*bud6?&(|Z+*|8ThzU>uX-CKx3 z6kB!mEPCfZ{k}woE)>qAn2VNL2&h@f<;hg+;{!7`o=<07f7>)Me{Cec~s4E)V)IfSk0d2eAyZ)#cd+D04yVj$r6=DH$4x%F2!r&iJrD#X0H0Kkwtd4dK z7qE}BFWz_{$6UDiMMn%peIyVe6xx#{R*s32VRa2Y%(pG`ytPvoRhv1S%}<8eS;E*% zjZ<3fC);|a)}IE1?QS5=#}mjD!0%rHtB3Zp3jr)r?jKFu94})HF(M~(Y4611_;!FU zp7@H`#|ot6325aDGyiM)4~n&a^5?El1j(;E{q&W`iv#M|q^|Z3;FmX9e~)K6HMh9F zU8!ElaFBHpg@`(;eHY+*lKU)0)LH%W6!q;g_K!Ax@i)@Y`^nX7e?S_n2}8Zqp9&n7 zQD`;mm`e0e$n7oyUlt_ypgJny&G57`U5*Bg&u;reMl)NILhZ+2PPa|+T%naeBrXGe zbN>cef}){{!pxT`kg?v`&0tsD9zuCFZe4ArN;5UjOuaNp*k@>E)=c^cnfX!s>}zeT zfCR8Il%@V-SkbBe@IH25_GHYFhzVZgIF$RGQl(Y%563)x3-wGuo1StUGeYU~+v%3- zeX~_^DWj&=vZkR)x_$TzVnbSD;*nt=27@{s zW7WcVPj4Q^Yt{RS*J$SVj@YEZ;~!c>A5*@g=S#JZaJlPh$^n~ctaqK-LyQ%v6E(ci zl-bBV9zF5z(YA}*C=@5y1S+Tw=)4gQrXg0-i6rRFC}2sD+vC5tOx&oO>N_}DsF`Th zGto(>Z^9Ryr4}i{At&MZ%mIGvX#|W67|OlYC*{q&KV|6vRuyA)g~RA*NEm})>Md&O zw@fnk`NS-SSk>cspp##!;6()n%M?hfjdTJWS<=eZ@gf}r<%XUbgu@2wJ~{%n-2UU| zp4MsF(ip&(RlA4fFs{nS$Rqgbx&c8cLwzDn^cws+t>W#U;)+ z?FB~~x@C>Cb&D<7tGB~Zcj(P@OaSoB%@Vl#TBO@X#*N`afdEX0`ii)cQ|%95n3^5l zW~Fw!^WtT3yDxPJ1RQJ98B^6s+((ZjV+Fh#yKe4;+ym}?lj+tqW{CYqRH-tLPw$$A zNzd`&YGFf0U;~?V&MN1+SDsKPb>bsKd2`A*5hX-mua~=V@x;`Gaaui7R9`&l>WJFG z=@&!8C;Rz_3pHzJu|Z1lPFLnRcN&{n-BQld_k5k*u{rKQ-?5=sidzVNrq7}AzRueC zg^ab;o4YU19AQOTvHwvp3TEP;fs!Z3ZR!tz0?0AEh2-iZuyj|Qr)du+yaOytUdP&r zvFlD!n$q%2L~n7&{K*A~xPG&1a-r9ts`Akb6DY9f%-@>_cK2VHK4 zi))u4_EsaRl!={Jyr%i2VIF&xSefG)iyi)E&Itj<)9=-^8|C&Bh5@L0`P`&8CBQ6k z+(H;K4amO69+#kmSvc$ES$M;Vb<1_mgZ8%&gFIUg2f)vfo$*`SQdBz_9-lQ5j$9or zi-#A%b!$R~Md-e6s1xNgdi8ssq9Ak3qSG$Jav-jnU)Wnv}1gN2hOO zadmp+EVsS;b^K5InDy6}8OrV8aEhPYA66t_eF>5G@|gO>AOYWXDkVlEYV&aq6o4d&Ufn52ERC8V}drv=Zr>dhmqW{6we zdn%VTYgF{;y?ugnT>;!UF#5!w40*4jZ=Baj7cjx81V_vG*N0d zV7Abm^!T|ST+NduzJie#a2E3or(pwwJ_T<~{0;8#yc8+ju}WTfcYMlE#c*5ANs!v( zY3$d+GmoUN14b&rPUK7NhlQxG9%fHxTpbMxUk{7iX&_DLWfJ!O`ql7K!zU@rI0S;# z70paLSuIT*r3J~yKv6P88Tx4(u6aJ*&BibovZi=Glx0m2%k>WIbx+!PO&h-PY8Flq z+{WrR*bpvzp?oyWlJ;|XAgKZ_Z%ur3ZDAVzMG6%J9|S!VKKMUUfa6e&#j@p-ud-m@0eACG44v>HmpCVb~Nz*oX~0a>Tp$E+jGv7 zN!ePm|7g7=Cm}Frb2e%*7r6$ZdMO!d4~oYhV31%YE_^n-{@o&D59gD=12d+zM2==y zCH67NUKcZG;+ta8GFNs=V29)4zYphVs;VKo{Sc`&-E9Ut7B{9;PO@*UAX>;e8L= zclgXC>oRGA((#$#<*5Zu3d=URcT=)-)1e8dG)-VXzkg!M?7TEuR*^$0wmMT&HkFD%dkPwR)d6vQLjIt{B*O>A z#N!!{{IK;dgLo3nX~1;4!pOuT>8jSO7Q5}Dt!px$)4AUi2TBlWBC#dZvfCfmd#g@z zhRn;lie(*TLR%CmJ#{fFFyWvP_NF}jz*gXTCRM=)T@!|a9AJMnmjDn2p2`YoOgybm zLJ4BaS69cM^nPo%iZ|g-Z=^eunqqu8<9)n$jOPLG%O=+OHK^ftcV%a&jy#0})k0+@P z`HyIRFoj5DM`)(pW}j8BgpUmWU1tIHsn9J zV=`9zh9fKHrhLOV^L`=63G2Pk4~U(nsnz!Jsh+k^;p8K4)Sx%v1e-&;JgV9y zP@CKn8Bm)kS$iu0p;4vGPSPiD%fwOKDsInX zzejD^{ss?E5YYul5{+t$hGPS++El_*Dc4Ukr*kB&(B9wRE@ssOMO10Om|A{U3tgpa zt-NZ*0r6~}oLf}Og#`4~o}f;?b?^jvnBn<=d*a9~tcLAGmUb?Prcn1I)^A{O>v;CE zWG!I4BWa@wPS>b9ZNTcY!y!HPlX%V+4)H|m=b=TuxD`S?1E-SE`JfHy)!|yTZ2J~y z%UNS?9I{dKyz-M7f)&)5j!1=e&gCrBK!fa;v3H0iP*XQYo!W?SIimG*7fWsZo&H(DkxiBY5g0Fnhrm}`4MSKnLJfhn-eHwGS zn7l-PK&!|$qN}Yb9I}@&DdAQ6C}!8ilnSISqkFeK0`4W<{nN1<+-N*sz>pq9QXQin zXj5fF;%r3t2)B7zklx#&sU3=;@$;aUCX~He5ZQ-4udjtbpD}v~1{X#uR zw#V^!de~<+tb1dxB&*k>< zij*gA?Q}pi4&QDl5f@cOrHW{KqcXiDfG`j_7p}%lTHce!{?Uu+(&gg>8^Yui!Wl7? zx3P6kGLL)+TKzGQ)hF>+!xx?AO=LE%v0F0 z`CJdQ?o`|DwFWNCSl1{j0$!ND$v1>yJ(Nu844(vK;|iDZ@KS6 zztQ(4;GT^+_}GNU1E6~ty-n{l&_%)H1WU9VLv&9UkaTO!S7(%wzU=$3(l3?8um_s8 z+F7g%&HXp;@Dz9~&yi*&YNHdTtSQz`s>zBBLnbNSDMm0s<7|7`;S;4rU1|}GLJvpt z4OhJ&`9#bP`;{Z;Mr)3kQLB$0RTJtcXgPM~zJkIB|1el0dn8m4b{SRl=Xr4tUz8<*jRNhxhSJ@h_K#p<~`Dau1nCd&6npG#m6?X;XV2gzd>GT zYNE?_fXvB~whtCQ4=j!R3lIe;+M}X&Z6g8)!bcu<28B7oPj&kEdh*?d(~Y4eX)Z5# zfTL2nYRruvMrTj~8~y+|6FXX5Z4iJ#FfnJlF-;d}%>oXZRNT^PSH_8Mmw~Fw-YELh z)q7z|@da0;_*C-(M7|-cFncwvmrMB2>-p9*j@^rE1e2AS$h_KWDV)32K;J7qU9%3q zQ~Q_2C1igNmrYOeT>-4>=?RvK))#RJM|H9t_6}HoceUP3v(F=_33Xv;EA$r!>nPe6 z+MOugcI=iDZ%^TYduwj7?|{%{!mDQe6*p5R++Zs@Nlx9=2PL+J@VkGdL4kG#gJs&E zPuK&0KFo2|HsgXBI&sCx4(bqbc76in*x5(<`4a&u;?Cs%vU^wj)b zQK}@cYcukn7~@?x>gN5C(m8-8CYPwV}S?4fCAXK#f;9=&B~(8o!xF0(|=& z{Ea7dP-sH`Zc&cHu!V@gs9y0LohM&uPH6Q(Nz7Nhx1PXKCS-uY+ctI^*cChKZhnt9 znfpKOeP>ux+qQN|r!>V(_n!OmglP21^CR+8uy+-mu7q8N>rCtCoZbX(YWhl2!l=LaV zRq(K-G*y0Jy?8|%WQIL9ejp3%?fk^TA<#ABqSt;)1Z%&D(UGc|uRsRw^39njR`xmm zu*FlsWg#-e9=#c=QFj)a{=T`?c;4_ajjv_|ZVw1K+>Gay{`@=yKuW%&kNMVUrz=Y9 zFqEsF&3z~gO!1F9YOY$sm|8V2Sr`c|{m={A7t*{qx&Q6i11BVSJ&hFyNF8Qt-+Gu> zC=8&GN9K*3zs^Xg4Kqu6)|ZxyJ%n^FN+@qQl{gGA9}7qgv%;n+qw2fQq0P}LRCMb5L&*w;ax_r7xIydIt)V`T#{fl*HA-N* zC4dwiX0X@?S>RZ*}eDSMuLF?04FKoTzI=3lk(W85bp*%}ZV7RZb+uz2jk%M23 z_HL+XCxarT!cbnL8m16bF9je_TNh;-`ocwiO}=hN4>qoMQVE`_h*3`N)+KMFkW)(l z#{5Rtn%OXI;2bXTPtRI9+tf>BbsY>W50L7G&1)!KGIRVVWsFQqs?#HR8WH;ho^AdsM10f^nU>+b zB!cYl14t91VFQbz#ZfI78prUrCT0OKQUC7Bd|j@O$D)DLO0t)>zjp&GxD0aux#rOF z8p!=^vP8;w_p8c;eoI$MC_Z220Izww#jOh{!Yx;`dAGmdaF;LSN;r2`T+DYygd(%3 z2ihBPCOZ!P*38@tQK;Rc1UlkG5sumBA&R4m5|9tSoZ_tpBUel2Zj}@KVr|&J{RE_{ zEO%%^-$r4IQcDcpnpKaMF*CbHZn|7qK>jPsp|Duq3gF7`^e^JzxNIJfwP$hz(C3`_ zgW0yUCetM^)W8u&Q)%ebIHFIYfEm---t0=Pz5@`^03cb|^Ya3X^8g7_ml>jXQV{sT6Z7xx{daE< z2&n;AUQpq?0?7L_PDDN)xWM>d@>>kvwi)wG|8_|I7u4g{A%@`}fYr}{0@uYw>9%do zUt$1bD)xQ%VLALE|2N7)m4}*2U32s2qap!_5%atBUO=uV62ss9&yK@Q^-nsPU&}yMi&hrDHNq;Bq+J(fpN>JUIb<~+aE--?_+iUKUgoiiZJXnqNpPE2!tvFc98 z0R*O{WyT>-{GZUBN=qN7df)JW^EAIh%m5AX_e{4z{8k6$Q(qIc^8VSTqorj#u=BIB z^DFkK4PasvYQ;HlvOH#BkHiAv&OD&bwzfSR7?pt^oQn3@dyp%43U-gl-_&Xm+G<^% ze>rc%Q|oL+j^7)ROWb$$UtBfQH|O0VsaGs6y z&M2!)*4qU4`2}t0ehtb5zI=2U73OP>WBg+zj^uf>nuV* zixcn5amQ#+)UUB#-NO~g_Q4tPLvL}s?j7f3Jo?v+Ez-?@m1-OK>q!a3U_#aEJz`Gv zIHIit72;um*FK(vG5ALl68YSigiOtxyMSec?SI~35o%I5W-8&77Z(=~y>{4yM4T=5 z4E>kk|Il9fJp~)}mgVXwP7$+fIG3KB%-xiSieQa+nD@*!-9mQaPiN1zI+uXF`Rs!sz4wz55k z?o)rey8g?)>TiK1Ao^9^_pjkee;Nh-9l#5S)6e@p``tVKIUxS?-(Cv=Py66j-^Ks7 zBZF}`VAgMH9T)%GjtoMvz`S{T;&#k`+mRv3CKB{%E#aot-vW()xAB9^fLjqd(qku5 zqaF|t@c4-L#-Cr~_ka7x-|k!z7G?r^G8Ii7jznmrLcmAK)z?_=Mj;Q>WB~-KZkBK46&+RJm8W=p(AMF9|Nsx6Q_hGZv4lV z_YY5YX`boqMnOTrOnCb-K)LQgL{;vGOV@z?HqrjQ!k0&9eiIAjIuP5y4ZW4& zU7Xwj*5eCfiz?NTyYkk5=Svir+)Qpl&AgtX2v8Ibnd-#$Wb-4Z885i`Yp}KVU=qNi z{q#6NN-O09Bd|*0;X_E9vPxC|rWN#e+2k(E)2E>0+Vviz^#9TX*W#w^utYo^7W zHUT&kW@NR5TY*KA7+6F22Dte_z%B1j4-UEHw>5jBL=x4jXOLnM(zkB8FU-og&xXtg z__aPVoG|;F4`(=fIVz>;rbV6NfaEBw6kH0CsbPE1X4`w}s2C7ocu(^h#j`NHWV8j- z%PeYocQHoT5WXaPRPo;Q;=gwL-@V6w#R6{)ZFdx_DwZ9IJuwnB3phlK*o2G3#D}Ak zIj4%+4rfo0w?g$4mpB%wxujnUjGOpS(Bs=IN29KSOlZzb%|lJK!VEWN|8@#YF|tK!-L~Rkv_(b5;~8`x zbDtE5`c+gNWI6x*-4TtPAcmDirjf1QKqthl*WxcC2`&OC=!?t-Eram%@xP|RFdRLt z1;i{q9Zyv5JS_h14RJrwuI+Qcj5+_lQ0tGF?f2irDu4$P=C?e_9tDV(+UhbN70Xq>e5~2R zSWYQ8;VjWhsjAd1?c*m}CCce|gdA)+#+^15p>V_p;!wp+n=6bMBkhyix1PB3dRy*g zcdFX2kVm$9Dl7R$b=V_gMsJO(?%8IIsqI)JOp%@=ON;lj!i*Rv3YFXV)DBe1aybcn zkH6e$C(vKkTY0MOtr#si0MkhHiFw7z>J#BRDAV!sKvFO^fD~NVBkPlM;$&A@?XIHI z&eR#oJ15bk_5q?*;HX2ft82j5k5*k%JK}`IgC_S{J@s0A2kGWF0HtTORF8~3f!Rm5 zg={v#M{O(sA}GSkeWQp-*;4YX+Su6WspQ~=8CVGrs~f+>yM^4w4 z2ynLWx_pU4E9VI?hfH5b*~^`}8n2$m)EtMtP4)?TfrGEj8kAsfA>JmhFRPV(L8se% z-I+BC=qf*+X8aQN$txn=4jYl_c0}*`p3{DgDV|s(&PH$i@o9!Wro$Quu%(&nH-7L3 zbeI>KQo2fo-bfVd2A)fJ{O_XJ-D3Mvla#bbF#_O=cLqm80NNEg-O& z_nwPpduD|pL3!8aD`M)=M2imT}(xKA)A#F|D z%jc3)Qyl?_Syg7()`fsQ*3M+w)iMie3<^pdS-=-NoLQNz8Fs92 zceAGa2!~>Go!|WV7R$Khbgu^R1Z;gtsnfzLJLr1>C3-sCJ>)aJZnX|YUW`1F{_ZOo zdeJ6$+MnjJ>Sa=TUxw(MjbYBFpvPsYo5whK+-S?=ZN2jAgN)SNlFrNYm!>nIptywK zu64;un#h;~(X(FXO-HyxLjUYgZ~dZs{VuKgI@%_}%3Y|FXlv7|2HnU3*rI2ObwGtjqyN*(i#k8(-)hFMS0C&%GymjQXN3KZ z1rP)Op!cA!4YBQq-CVB_rNr0YpG}=xYaWbQYz!Q)>90vBhl3G>SMv#kYUTn9EVQip z%$n6QjdZ(jriV6M*069Z`-7i`qs-E-`c`9!H7G_7&^1KQh7VwC|?2 z*Q82SH-ZmV54xcwpg3ghIB!sgEZX9!*w*@*HhF(as&-rtfkJ&O=oIR8^lowg6{H+8 z$XD>IE|U_`y~=-y)Ho{_k{vvwU{SrIWYH8FjVm%3+akgApyRov6f`Y6VkK<%D~2M- zAP8rTF!Npz~roCx412L_fiWRTiPOxx?;(eCp91LxIOz&YS~jy^+3u3J=n7~jt$vr zxcuw~AupZEgAm5-J6#}4x0;D-E7PB>Uzd=PdF4YsuJmktsAt-l9F!G=<duu`d$apT&v4@ZuX zGDNS&F;2udX;-AlK(`fk^4aVCpJ5VsqM_<`f^ERuE^UnI`q?r5W_H&ojro0QYOT3A z)X}(JSAv*ltzyyW6sNK=(YjS?Bh?ww?p58mJi8ZmMwHliW?5{duj}#kAB{H{yseYo zKI{1CBdM2ly9e2iu}DBjO05k5D^qzFU2&*0V8KDR9I@-9wEFMVF5~IPhJSlg z^BjZNsEHJ*E;X;m2asH~czuYa!PdGAEB4vH7$Tf>cojlimat2kC$I8w?2nz2$Tb*7 z1scUa?ffH<5lU%Z8;_`w)>Xha(LLX&$k4z<uGA@8kMr|gP&(O*VnoxGdIs~4Xj+j zCf0(P25?40Wsb1g0a5-nu@yryR@aIU(@EbLz~W2090fV?I@7nkq-i_ObauJ)`T&ZH zbGENj7JyzxYvqqohT31M+^}|&Y5d{-wuU)D47*eZZIIXvc(cFTWl!_?dRiRlo*c0m z;I~H|g~d>&XeADYj)US$l^vSZDh<0O2<92~u*;u`UX8qr4w**?#s-_^dh+js#y{yh zDnuNlOp4GpVhRZm0lG;zzh$V;IoKv@$OFavnw{r13(mx1XQx;q0t84gdPTFIcp0&e zLyve`a7HLL@jl%i$iyx}@)qzTBF-BJD8^2M5gM zGRNfP-jCz)u}~*xERC+(E6u$=LaFSkn^n+qycMvKDLZ-KBj{()JkTck%Ut7!=4Po! z_>VAA;_Pz7@q__i6b zp29?68v~zrx>f#?AYN8c%%QzOmoG_yUA*N=;c9{ZHUQg>D&`2mjb@Z%ftHskrk4Y{ z*z=|yPejp(=WIf`p1|=QlGQ3yx3dthh@ENENd=jiMkGe@mFWSx%66Duz)Q^g; z+#Sj>*HhtXLQ=rU7vZCP8>9rwO@$BC7iAJO*u5>>&_;R8ei$9-wh`lt^q}E`#RO!E z9T%pUHJM}T{K*hsO!B>1q)6Xr;P@jo=lCk>c(wz=r0nFG7n18=ZxNWy!*|*liG=Zo zuBxAB1_#ncf@d@NM9zk-^%tu8bRgMPSLgPUXGd5?`Oj?yJ0x7|mB}yPe-U_KIZ9!x z?-QlpP0ZL(f?%wdmxT{%EfFRXN(51L6uD0^uu{_Vkot*IC)2KS{FDfz@ouUP0;*TL?0n9KI zejuAVk!W&zUOTbyq}q=gAzEpk!i9gtkY zwcOX&$^FwQo7E>(-zE+uTcR^9l4$sa-leW&BSNRU(E38|FV-NK!t4~Zr1A)7w+ciJP zqUtPS8T`3lb_KOq&hLFkB4;^0#ltHiWvB=^Rzc)UJy<*A1bFd2abw1B@J0RnwMjK> zR|z!~duRjKRF1{&2!r)b{CzVvVMcPZ4M@`FJc(= zqEFT_l>TZ;8Sro1H3M?enw;msQ};Q<+&~RCtFBJ;ty?X89&;_swioE3wRvt$7+5^w zW@=v3S4X#=B*vuoChYVqN-PXjxpL^T$;}gM$Ui1=k2zTDgLC??E5|UF%x1v^jcrfz zj7sSNnU`mSaqFU4+omiH_v85a`D^y5)44sR8eWZM=%SuSXGt9IL4ISC2cM0>yCF2aDGaBN7}HdNehdjKXNt3J>%cfp`UWb))5>pnUh1KBdKk(%N>E zDZeqqT0rDN#!tKW-s91q*$zCn(ii%5U`*E(?}IJHSNc(6Y~uE<8G35_37gcFJiT#p zyF%=vxi&8a|lzz^MLR!EsxgY+pD=?(D?q4_rT+I4tO62!(*s zoKW^6X*DHWY1t{=2j5V3-+n!+4s9zpP@TLi>NgajeK2tbykVx}63gy?_Lx68BsFvP z%+)m75Maqi`?Rqif`i3^4PxJR5@$6w==8iC3lh|%v_iWPql9L+b6CWq);|Wki3#Pk zs6qk9v_dY*MY7zA2-2jCEV%s$M#6IVoA&WEM>n2p+I<|g*|c@PzH)XtVDOFBGxB>< zAbq>D>E6jm4%KZ?eO~9ZYW%f;fw=v!j3MGk54QS@o+4=`Z2Jwnz|8FU6ze2p2Ou&L zP>r7DP?(KJ%r=U`y!>0=a={%uU=TeM_T+b$kwU>&8T2cK}VxNTWlb*qrIWk4c)+*?IovwSIVwW0w3v}zH zv|sgqh_!3=VtpRnxOLX%w7N$;ZL6_=AqX*lEs>uk;`rU!+;G_q{2N(seH-Ec(!vXX zNxQZ{q%nB%ekm65uu=NC1}vHyv9}t-P9@`YNvG}tqs6bfxS~m^Bg3X$sU;ZK0-bbz z5sr4^52j|Ou;eyayaFlu(TD6#TF_k9^qH|^+s>MPzR?=*1=a zS_sY4F(is%<(a~TttGu+qM~Uv$SlgH@Z{KH&Qp$VqyBSot74c`S_j#SpurJo>{w-| z8Nh<^^96fc^*^%za>pjx?SThdAcxxC4W;31J-J{9IVRKPot|y1$}_72+6>MfQeC zvTV*=4fnX3Lox_o;ZIED;w?hJmiO=9AKhFrj@wK(wbeDgS2^AtKem)DFKnE04~u;5 zQda{vnRap?KC4my-@UevOQ2Y@-Et&0Z zz7E66MXxI*v%MQDi$gZys2!Wo3r`f8LV$Cz8q!3y4Uvqx=TQX)7p9XdEX)Cx2On4_ zGhnwk;0}TtUtwhm{h7#^Cv(bQ*MEhT6^;huQulOK8dLd#rzY|JShD27K8M=-a}W=b z_gIf$pThd$fUnm9Vt;7~w#a=_>kMmk)5jC2_U8&UaSbX*`PgLhD0smu8uA~$bp%;- zahH00DSg@k(>NpK7P3;rJ=R~qO{m{d?A%e=T#ta=$luSr?Wi$|l2Jl0&m_GNjfp+O z#^TpdDyghStwk>McePF?YOaiZTo=xTD9Gv?3ulqmook~RzuGi>UvuK9$=AWTN;JM* zc0rN`3fz`=!k1hapOX?OVHeYAkT&?%0I*RRpvuJHV7t)hm@2l^K6oyuEiO;&v)L^!)f zRx=^OxN_h#_ReQIpDVgml(;PqqvFAL_TMqj!*3+C6p?5xLC&{$+ zldHy^#R6zF94sTdimv2;dD5dEQdmau?X(`+eJSbUJhV|KcJ$Egbp-j>^}ZS2qWAk8 zX7SMmtr~Ky9&8`{dtOjZ_M!bn>pLu7c6lzo&v+4`6CR7!3S;a@vEC_#Hax-K%wH~# z5$G{@uuKP54#Q<4q^Wj>S_W z!AT`)?{f8hGi<~+%=54$$ian=a1Wij{tquK!t#<;i9dRNVCe)!JRqy~jMFAvm2Qza zjxSrnUCD@HgF$J#KPo;Km8C8e_!r_p>-ntu76Qn`fu@!{kXqygH%0DsJxE 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 o|CtK%zjVLThe description supports HTML tags """ ``` +![Preview of Swagger documentation with docstrings](/images/rest-api-docs/2-preview-with-docs.png) ## Authorization in Swagger Authorization requires making an OpenIDConnect endpoint with an Authorization and Token endpoint (like with using [SeaCat Auth](https://github.com/TeskaLabs/seacat-auth)). -After your endpoint has authorization, [here's an example](https://github.com/TeskaLabs/asab/blob/master/examples/web-authz-userinfo.py), -add the Authorization and Token endpoints into your [configuration](#configuration). +For authorization you will need to add a `authorizationUrl` +and `tokenUrl` to the configuration: + +``` ini +[asab:doc] +authorizationUrl=http://localhost:8080/openidconnect/authorize +tokenUrl=http://localhost:8080/openidconnect/token +``` + +If you have an endpoint that requires a scope, you can add it with the +configuration file: + +``` ini +[asab:doc] +scopes=read,write +``` + +To set up endpoint authorization, you can use [this example](/examples/web-authz-userinfo). For the authorization bearer token to be added to the request, a scope is needed to be put into the security parameter in a docstring. It does not matter what it is called or if it exists, but it's needed to be there. @@ -72,28 +93,10 @@ async def top_secret_endpoint(self, request): """ ``` -After setting up Authorization, a green `Authorize` button should appear in the Swagger docs: - -![Authorize button](/images/rest-api-docs-authorize.png) - -## Configuration - -For authorization you will need to add a `authorizationUrl` -and `tokenUrl`: - -``` ini -[asab:doc] -authorizationUrl=http://localhost:8080/openidconnect/authorize -tokenUrl=http://localhost:8080/openidconnect/token -``` +After setting up Authorization, a green `Authorize` button should appear in the Swagger docs. After you click on it, you should see the following content: -If you have an endpoint that requires a scope, you can add it with the -configuration file: +![Authorization of Swagger documentation](/images/rest-api-docs/3-authorization.png) -``` ini -[asab:doc] -scopes=read,write -``` ## Tags @@ -129,7 +132,8 @@ There are two options for `default_route_tag`: === "`module_name`" All tags without custom name are displayed with the name of the **module** where the handler is defined. - ![Default tag: module name](/images/rest-api-docs-default-tag-module-name.png) + ![Authorization of Swagger documentation](/images/rest-api-docs/4-module.png) + === "`class_name`" All tags without custom name are displayed with the name of the **class** where the handler is defined. - ![Default tag: class name](/images/rest-api-docs-default-tag-class.png) \ No newline at end of file + ![Authorization of Swagger documentation](/images/rest-api-docs/5-class.png) From 216693e33163657f8d5eced21b737cae0a167ab2 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 2 Aug 2023 15:30:24 +0200 Subject: [PATCH 102/154] Change Example icon --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index e7094c1a7..bb2b6a979 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -45,7 +45,7 @@ theme: warning: fontawesome/solid/triangle-exclamation danger: fontawesome/solid/skull bug: fontawesome/solid/robot - example: fontawesome/solid/flask + example: fontawesome/solid/code quote: fontawesome/solid/quote-left repo: fontawesome/brands/github From 08c7d54a47818236adbf47433439a41626ef0e18 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 2 Aug 2023 19:13:55 +0200 Subject: [PATCH 103/154] Create 'Web server' section --- docs/reference/web/web-server.md | 153 +++++++++++++++++++++++++++++++ mkdocs.yml | 2 + 2 files changed, 155 insertions(+) create mode 100644 docs/reference/web/web-server.md diff --git a/docs/reference/web/web-server.md b/docs/reference/web/web-server.md new file mode 100644 index 000000000..9ced79a91 --- /dev/null +++ b/docs/reference/web/web-server.md @@ -0,0 +1,153 @@ +# The web server + +ASAB provides a web server in a `asab.web` module. +This module offers an integration of [`aiohttp` web server](http://aiohttp.readthedocs.io/en/stable/web.html). + +!!! tip + + For a quick start, we recommend reading the official `aiohttp` tutorial on [how to run a simple web server](https://docs.aiohttp.org/en/stable/web_quickstart.html#run-a-simple-web-server). + +## Creating a web server + +First make sure that you have `aiohttp` module installed: +``` shell +python3 -m pip install aiohttp +``` + +The following code creates a simple web server application: + +``` python linenums="1" +import asab.web +import aiohttp + +class MyApplication(asab.Application): + + async def initialize(self): + self.add_module(asab.web.Module) #(1)! + self.WebService = self.get_service("asab.WebService") #(2)! + + container = asab.web.WebContainer( #(3)! + websvc=self.WebService, + config_section_name='my:web', + config={"listen": "0.0.0.0:8080"} + ) + + container.WebApp.router.add_get('/hello', self.hello) #(4)! + + # This is the web request handler + async def hello(self, request): #(5)! + return aiohttp.web.Response(text='Hello from your ASAB server!\n') + + +if __name__ == '__main__': + app = MyApplication() + app.run() +``` + +1. In order to use `asab.WebService`, first import the corresponding `asab.web.Module`... +2. ...and then locate the Service. +3. Creates the Web container, which is a [`asab.Config.Configurable`](http://localhost:8000/reference/config/reference/#asab.config.Configurable) +4. `asab.web.WebContainer.WebApp` is instance of `aiohttp.web.Application` object. To create a new endpoint, use methods for [`aiohttp.web.Application.router`](https://docs.aiohttp.org/en/stable/web_reference.html?highlight=add_get#router). +5. A request handler must be a coroutine that accepts [`aiohttp.web.Request` instance](https://docs.aiohttp.org/en/stable/web_reference.html#aiohttp.web.Request) as its only parameter and returns [`aiohttp.web.Response` instance](https://docs.aiohttp.org/en/stable/web_reference.html#response). + +You can test if your server is working by sending a request to the `/hello` endpoint, e.e., via the `curl` command: + +```shell +curl http://localhost:8080/hello +``` + +and you should get the response: + +``` +Hello from your ASAB server! +``` + +## Web Service + +Service location example: + +``` {.python} +from asab.web import Module +self.add_module(Module) +svc = self.get_service("asab.WebService") +``` + +## Configuration + +The default configuration of the [web]{.title-ref} container in ASAB is +following: + +``` {.ini} +[web] +listen=0.0.0.0:8080 +``` + +Multiple listening interfaces can be specified: + +``` {.ini} +[web] +listen: + 0.0.0.0:8080 + :: 8080 +``` + +Multiple listening interfaces, one with HTTPS (TLS/SSL) can be +specified: + +``` {.ini} +[web] +listen: + 0.0.0.0 8080 + :: 8080 + 0.0.0.0 8443 ssl:web + +[ssl:web] +cert=... +key=... +... +``` + +Multiple interfaces, one with HTTPS (inline): + +``` {.ini} +[web] +listen: + 0.0.0.0 8080 + :: 8080 + 0.0.0.0 8443 ssl + +# The SSL parameters are inside of the WebContainer section +cert=... +key=... +... +``` + +Other available options are: + +> - [backlog]{.title-ref} +> - [rootdir]{.title-ref} +> - [servertokens]{.title-ref} (default value [full]{.title-ref}) +> - [cors]{.title-ref} +> - [cors\_preflight\_paths]{.title-ref} + +TLS/SSL paramereters: + +> - [cert]{.title-ref} +> - [key]{.title-ref} +> - [password]{.title-ref} +> - [cafile]{.title-ref} +> - [capath]{.title-ref} +> - [ciphers]{.title-ref} +> - [dh\_params]{.title-ref} +> - \`verify\_mode\`: one of [CERT\_NONE]{.title-ref}, +> [CERT\_OPTIONAL]{.title-ref} or [CERT\_REQUIRED]{.title-ref} +> - [check\_hostname]{.title-ref} +> - [options]{.title-ref} + +## Sessions + +ASAB Web Service provides an implementation of the web sessions. + +TODO: \... + +TODO: \... diff --git a/mkdocs.yml b/mkdocs.yml index bb2b6a979..17c02c3c8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -160,6 +160,8 @@ nav: - Reference: - Application: reference/application/reference.md + + - WebServer: reference/web/web-server.md - Configuration: reference/config/reference.md - Logging: reference/logging/reference.md - Library: reference/library/reference.md From 8657a31f3d6afa0cc28b0bfd06399cf268c009d2 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 2 Aug 2023 22:04:51 +0200 Subject: [PATCH 104/154] Add docstrings to WebService --- asab/web/service.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/asab/web/service.py b/asab/web/service.py index 8bc8de373..dbb785d9f 100644 --- a/asab/web/service.py +++ b/asab/web/service.py @@ -11,6 +11,25 @@ class WebService(Service): + """ + Service for running and easy manipulation of the web server. + It is used for registering and running the web container as well as initialization of web request metrics. + + It should be used together with `asab.web.WebContainer` object that handles the web configuration. + + Examples: + + ```python + from asab.web import Module + self.add_module(Module) + web_service = self.get_service("asab.WebService") + container = asab.web.WebContainer( + websvc=web_service, + config_section_name='my:web', + config={"listen": "0.0.0.0:8080"} + ) + ``` + """ ConfigSectionAliases = ["asab:web"] @@ -35,17 +54,17 @@ def _register_container(self, container, config_section_name): @property def WebApp(self): - ''' - This is here to maintain backward compatibility. - ''' + """ + An obsolete property only for maintaining backward compatibility. Please use `asab.web.WebContainer.WebApp` instead. + """ return self.WebContainer.WebApp @property def WebContainer(self): - ''' - This is here to maintain backward compatibility. - ''' + """ + An obsolete property only for maintaining backward compatibility. Please use `asab.web.WebContainer` instead. + """ config_section = "web" # The WebContainer should be configured in the config section [web] From f8a75fee1d37b3d2e63cdfc868761810f4d4e2ae Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 2 Aug 2023 22:05:28 +0200 Subject: [PATCH 105/154] Renaming --- docs/reference/web/web-server.md | 4 ++-- mkdocs.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/reference/web/web-server.md b/docs/reference/web/web-server.md index 9ced79a91..00ebb84f0 100644 --- a/docs/reference/web/web-server.md +++ b/docs/reference/web/web-server.md @@ -26,13 +26,13 @@ class MyApplication(asab.Application): self.add_module(asab.web.Module) #(1)! self.WebService = self.get_service("asab.WebService") #(2)! - container = asab.web.WebContainer( #(3)! + self.WebContainer = asab.web.WebContainer( #(3)! websvc=self.WebService, config_section_name='my:web', config={"listen": "0.0.0.0:8080"} ) - container.WebApp.router.add_get('/hello', self.hello) #(4)! + self.WebContainer.WebApp.router.add_get('/hello', self.hello) #(4)! # This is the web request handler async def hello(self, request): #(5)! diff --git a/mkdocs.yml b/mkdocs.yml index 17c02c3c8..2076487a7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -161,7 +161,7 @@ nav: - Reference: - Application: reference/application/reference.md - - WebServer: reference/web/web-server.md + - Web Server: reference/web/web-server.md - Configuration: reference/config/reference.md - Logging: reference/logging/reference.md - Library: reference/library/reference.md From 97c1df36e96dd4bf92ed3cf494fc5f26c989b914 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 2 Aug 2023 22:25:28 +0200 Subject: [PATCH 106/154] Add type hints --- asab/web/container.py | 6 ++++-- asab/web/service.py | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/asab/web/container.py b/asab/web/container.py index 4096e86ac..4406843e9 100644 --- a/asab/web/container.py +++ b/asab/web/container.py @@ -2,10 +2,12 @@ import logging import aiohttp +import aiohttp.web from .accesslog import AccessLogger from ..config import ConfigObject from ..tls import SSLContextBuilder +from .service import WebService # @@ -91,10 +93,10 @@ class WebContainer(ConfigObject): } - def __init__(self, websvc, config_section_name, config=None): + def __init__(self, websvc: WebService, config_section_name: str, config=None): super().__init__(config_section_name=config_section_name, config=config) - self.Addresses = None # The address is avaiable only at (and after) `WebContainer.started!` pub/sub event + self.Addresses = None # The address is available only after `WebContainer.started!` PubSub message is published. self.BackLog = int(self.Config.get("backlog")) self.CORS = self.Config.get("cors") diff --git a/asab/web/service.py b/asab/web/service.py index dbb785d9f..01faaf66d 100644 --- a/asab/web/service.py +++ b/asab/web/service.py @@ -3,6 +3,7 @@ from ..abc.service import Service from .. import Config from .. import metrics +from .container import WebContainer from .metrics import WebRequestsMetrics @@ -41,13 +42,13 @@ def __init__(self, app, service_name): app.add_module(metrics.Module) self.MetricsService = app.get_service("asab.MetricsService") self.WebRequestsMetrics = WebRequestsMetrics(self.MetricsService) - self.Containers = {} + self.Containers: dict[str, WebContainer] = {} async def finalize(self, app): for containers in self.Containers.values(): await containers._stop(app) - def _register_container(self, container, config_section_name): + def _register_container(self, container: WebContainer, config_section_name: str): self.Containers[config_section_name] = container self.App.TaskService.schedule(container._start(self.App)) From cb853b4fcc96db4f2ad3f04750aa361575ed4ff8 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 2 Aug 2023 22:37:31 +0200 Subject: [PATCH 107/154] Fix circular imports --- asab/web/container.py | 5 +++-- asab/web/service.py | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/asab/web/container.py b/asab/web/container.py index 4406843e9..6b2849108 100644 --- a/asab/web/container.py +++ b/asab/web/container.py @@ -8,6 +8,7 @@ from ..config import ConfigObject from ..tls import SSLContextBuilder from .service import WebService +from ..application import Application # @@ -184,7 +185,7 @@ def __init__(self, websvc: WebService, config_section_name: str, config=None): self.add_preflight_handlers(preflight_paths) - async def _start(self, app): + async def _start(self, app: Application): await self.WebAppRunner.setup() for addr, port, ssl_context in self._listen: @@ -204,7 +205,7 @@ async def _start(self, app): self.WebApp['app'].PubSub.publish("WebContainer.started!", self) - async def _stop(self, app): + async def _stop(self, app: Application): self.WebApp['app'].PubSub.publish("WebContainer.stoped!", self) await self.WebAppRunner.cleanup() diff --git a/asab/web/service.py b/asab/web/service.py index 01faaf66d..c9cb4ddc3 100644 --- a/asab/web/service.py +++ b/asab/web/service.py @@ -3,7 +3,6 @@ from ..abc.service import Service from .. import Config from .. import metrics -from .container import WebContainer from .metrics import WebRequestsMetrics @@ -42,13 +41,13 @@ def __init__(self, app, service_name): app.add_module(metrics.Module) self.MetricsService = app.get_service("asab.MetricsService") self.WebRequestsMetrics = WebRequestsMetrics(self.MetricsService) - self.Containers: dict[str, WebContainer] = {} + self.Containers = {} async def finalize(self, app): for containers in self.Containers.values(): await containers._stop(app) - def _register_container(self, container: WebContainer, config_section_name: str): + def _register_container(self, container, config_section_name: str): self.Containers[config_section_name] = container self.App.TaskService.schedule(container._start(self.App)) From b06d122b244680569298d4e6d99bdf6ca3fad602 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 2 Aug 2023 22:40:08 +0200 Subject: [PATCH 108/154] Add docstring to get_ports() --- asab/web/container.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/asab/web/container.py b/asab/web/container.py index 6b2849108..26bc5f997 100644 --- a/asab/web/container.py +++ b/asab/web/container.py @@ -234,7 +234,13 @@ async def _on_prepare_response(self, request, response): response.headers['Access-Control-Allow-Methods'] = "GET, POST, DELETE, PUT, PATCH, OPTIONS" - def get_ports(self): + def get_ports(self) -> list[str]: + """ + Return list of available ports. + + Returns: + list[str]: List of ports. + """ ports = [] for addr, port, ssl_context in self._listen: ports.append(port) From 4c935f5e35d03e02845558fed373b7a97ecff16e Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 2 Aug 2023 23:18:59 +0200 Subject: [PATCH 109/154] Add autodocs --- docs/reference/web/web-server.md | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/docs/reference/web/web-server.md b/docs/reference/web/web-server.md index 00ebb84f0..ca3695108 100644 --- a/docs/reference/web/web-server.md +++ b/docs/reference/web/web-server.md @@ -46,8 +46,8 @@ if __name__ == '__main__': 1. In order to use `asab.WebService`, first import the corresponding `asab.web.Module`... 2. ...and then locate the Service. -3. Creates the Web container, which is a [`asab.Config.Configurable`](http://localhost:8000/reference/config/reference/#asab.config.Configurable) -4. `asab.web.WebContainer.WebApp` is instance of `aiohttp.web.Application` object. To create a new endpoint, use methods for [`aiohttp.web.Application.router`](https://docs.aiohttp.org/en/stable/web_reference.html?highlight=add_get#router). +3. Creates the Web container, which is instance of [`asab.Config.Configurable`](http://localhost:8000/reference/config/reference/#asab.config.Configurable) object that stores the configuration such as the actual web application. +4. `asab.web.WebContainer.WebApp` is instance of `aiohttp.web.Application` object. To create a new endpoint, use methods for [`aiohttp.web.Application.router` object](https://docs.aiohttp.org/en/stable/web_reference.html?highlight=add_get#router). 5. A request handler must be a coroutine that accepts [`aiohttp.web.Request` instance](https://docs.aiohttp.org/en/stable/web_reference.html#aiohttp.web.Request) as its only parameter and returns [`aiohttp.web.Response` instance](https://docs.aiohttp.org/en/stable/web_reference.html#response). You can test if your server is working by sending a request to the `/hello` endpoint, e.e., via the `curl` command: @@ -62,16 +62,6 @@ and you should get the response: Hello from your ASAB server! ``` -## Web Service - -Service location example: - -``` {.python} -from asab.web import Module -self.add_module(Module) -svc = self.get_service("asab.WebService") -``` - ## Configuration The default configuration of the [web]{.title-ref} container in ASAB is @@ -144,10 +134,10 @@ TLS/SSL paramereters: > - [check\_hostname]{.title-ref} > - [options]{.title-ref} -## Sessions +## Reference -ASAB Web Service provides an implementation of the web sessions. +::: asab.web.Module -TODO: \... +::: asab.web.service.WebService -TODO: \... +::: asab.web.WebContainer From c54246086553350553aee919c44a7c1fb7887533 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 3 Aug 2023 16:03:42 +0200 Subject: [PATCH 110/154] Comment on initialize() and finalize() --- asab/abc/module.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/asab/abc/module.py b/asab/abc/module.py index 82c507c2c..9d11653d8 100644 --- a/asab/abc/module.py +++ b/asab/abc/module.py @@ -8,7 +8,9 @@ class Module(abc.ABC): Modules are registered at the module registry `asab.Application.Modules`, managed by an application object. Module can be loaded by ASAB and typically provides one or more Service objects. - Every module provides asynchronous methods `initialize()` and `finalize()` that are called when the module is being initialized and finalized. + Every module provides asynchronous methods `initialize()` and `finalize()`. + `initialize()` is called in the very beginning of the run-time, + `finalize()` in the gentle shut-down of the application. Examples: From 9d75653298fd93c10ead28b228996bde63a53f14 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 3 Aug 2023 16:20:13 +0200 Subject: [PATCH 111/154] Add warning to docstrings --- asab/library/service.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/asab/library/service.py b/asab/library/service.py index f2d55082f..81e5e75ec 100644 --- a/asab/library/service.py +++ b/asab/library/service.py @@ -159,7 +159,7 @@ async def _set_ready(self, provider): async def read(self, path: str, tenant: typing.Optional[str] = None) -> typing.Optional[typing.IO]: """ - Read the content of the library item specified by `path`. + Read the content of the library item specified by `path`. This method can be used only after the Library is ready. Args: path (str): Path to the file, `LibraryItem.name` can be used directly. @@ -195,7 +195,7 @@ async def read(self, path: str, tenant: typing.Optional[str] = None) -> typing.O async def list(self, path: str = "/", tenant: typing.Optional[str] = None, recursive: bool = False) -> typing.List[LibraryItem]: """ - List the directory of the library specified by the path that are enabled for the specified tenant. + List the directory of the library specified by the path that are enabled for the specified tenant. This method can be used only after the Library is ready. Args: path (str): Path to the directory. From 5edbf119b286db0c97e8492a4564a29a7d4ba620 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 3 Aug 2023 16:29:22 +0200 Subject: [PATCH 112/154] Remove old ConfigObjectDict --- docs/reference/config/reference.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/config/reference.md b/docs/reference/config/reference.md index 37b2c0f33..a98bc0513 100644 --- a/docs/reference/config/reference.md +++ b/docs/reference/config/reference.md @@ -250,6 +250,6 @@ they are not repeated in many sections of the config file(s). ::: asab.config.ConfigParser -::: asab.config.ConfigObjectDict - ::: asab.config.Configurable + +::: asab.config.ConfigurableDict From c62fb3907be68d0b7af0998661bb41bcbc1fba9f Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 3 Aug 2023 17:04:53 +0200 Subject: [PATCH 113/154] Add typing to Configurable --- asab/config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/asab/config.py b/asab/config.py index 5605ad12b..90c8dd914 100644 --- a/asab/config.py +++ b/asab/config.py @@ -7,6 +7,7 @@ import configparser import urllib.parse import collections.abc +import typing from . import utils @@ -396,7 +397,7 @@ def __init__(self, config_section_name, config=None): ConfigDefaults = {} - def __init__(self, config_section_name, config=None): + def __init__(self, config_section_name: str, config: typing.Optional[dict] = None): self.Config = ConfigObjectDict() for base_class in inspect.getmro(self.__class__): From 9aeceebb8f0a6a9caa3a2000bc95d8b5acc505e6 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 3 Aug 2023 17:19:17 +0200 Subject: [PATCH 114/154] Fixing typo in published message --- asab/web/container.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/asab/web/container.py b/asab/web/container.py index 26bc5f997..4e805d508 100644 --- a/asab/web/container.py +++ b/asab/web/container.py @@ -4,6 +4,8 @@ import aiohttp import aiohttp.web +import typing + from .accesslog import AccessLogger from ..config import ConfigObject from ..tls import SSLContextBuilder @@ -94,7 +96,7 @@ class WebContainer(ConfigObject): } - def __init__(self, websvc: WebService, config_section_name: str, config=None): + def __init__(self, websvc: WebService, config_section_name: str, config: typing.Optional[dict] = None): super().__init__(config_section_name=config_section_name, config=config) self.Addresses = None # The address is available only after `WebContainer.started!` PubSub message is published. @@ -158,7 +160,7 @@ def __init__(self, websvc: WebService, config_section_name: str, config=None): L.warning("Missing configuration.") client_max_size = int(self.Config.get("body_max_size")) - self.WebApp = aiohttp.web.Application(client_max_size=client_max_size) + self.WebApp: aiohttp.web.Application = aiohttp.web.Application(client_max_size=client_max_size) self.WebApp.on_response_prepare.append(self._on_prepare_response) self.WebApp['app'] = websvc.App @@ -206,7 +208,7 @@ async def _start(self, app: Application): async def _stop(self, app: Application): - self.WebApp['app'].PubSub.publish("WebContainer.stoped!", self) + self.WebApp['app'].PubSub.publish("WebContainer.stopped!", self) await self.WebAppRunner.cleanup() From bbcc3fa05409936e484842c58f14b6839f1da648 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 3 Aug 2023 17:19:47 +0200 Subject: [PATCH 115/154] Add cross-reference --- asab/web/service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asab/web/service.py b/asab/web/service.py index c9cb4ddc3..dcee0b524 100644 --- a/asab/web/service.py +++ b/asab/web/service.py @@ -15,7 +15,7 @@ class WebService(Service): Service for running and easy manipulation of the web server. It is used for registering and running the web container as well as initialization of web request metrics. - It should be used together with `asab.web.WebContainer` object that handles the web configuration. + It should be used together with [`asab.web.WebContainer`](#asab.web.WebContainer) object that handles the web configuration. Examples: From 4aea0f5997aa7fa36de87b3c7207a51627545a6d Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 3 Aug 2023 17:23:32 +0200 Subject: [PATCH 116/154] Create docstrings for web module --- asab/web/__init__.py | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/asab/web/__init__.py b/asab/web/__init__.py index b1a109fa2..92ce7cea9 100644 --- a/asab/web/__init__.py +++ b/asab/web/__init__.py @@ -1,3 +1,6 @@ +import typing +import aiohttp.web + from ..abc import Module from .container import WebContainer from .websocket import WebSocketFactory @@ -5,6 +8,9 @@ class Module(Module): + """ + Module for running and easy manipulation of the web server. + """ def __init__(self, app): super().__init__(app) @@ -13,12 +19,34 @@ def __init__(self, app): self.service = WebService(app, "asab.WebService") -def create_web_server(app, section="web", config=None): - ''' - Build a web server. +def create_web_server(app, section: str = "web", config: typing.Optional[dict] = None) -> aiohttp.web.UrlDispatcher: + """ + Build the web server with the specified configuration. + + It is an user convenience function that simplifies typical way of how the web server is created. + + Args: + app (asab.Application): A reference to the ASAB Application. + section (str): Configuration section name with which the WebContainer will be created. + config (dict | None): Additional server configuration. + + Returns: + [WebContainer Application Router object](https://docs.aiohttp.org/en/stable/web_reference.html?highlight=router#router). + + Examples: + + ```python + class MyApplication(asab.Application): + def __init__(self): + super().__init__() + web = asab.web.create_web_server(self) + web.add_get('/hello', self.hello) + + async def hello(self, request): + return asab.web.rest.json_response(request, data="Hello, world!\n") - It is an user convenience fucntion that simplifies typical way of how the web server is created. - ''' + ``` + """ app.add_module(Module) websvc = app.get_service("asab.WebService") container = WebContainer(websvc, section, config=config) From fae0772c6aa91e5b8acafb30e97e6425f7f5cd43 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 3 Aug 2023 17:41:37 +0200 Subject: [PATCH 117/154] Add ConfigurableDict --- docs/reference/config/reference.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/config/reference.md b/docs/reference/config/reference.md index 37b2c0f33..a98bc0513 100644 --- a/docs/reference/config/reference.md +++ b/docs/reference/config/reference.md @@ -250,6 +250,6 @@ they are not repeated in many sections of the config file(s). ::: asab.config.ConfigParser -::: asab.config.ConfigObjectDict - ::: asab.config.Configurable + +::: asab.config.ConfigurableDict From 2ffaa5e5ddab9a268f7cc639156ccf528d2d5cb8 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 4 Aug 2023 09:57:34 +0200 Subject: [PATCH 118/154] Modify docstrings --- asab/web/__init__.py | 3 +- asab/web/container.py | 82 +++++++++---------------------------------- 2 files changed, 17 insertions(+), 68 deletions(-) diff --git a/asab/web/__init__.py b/asab/web/__init__.py index 92ce7cea9..ef210850f 100644 --- a/asab/web/__init__.py +++ b/asab/web/__init__.py @@ -37,8 +37,7 @@ def create_web_server(app, section: str = "web", config: typing.Optional[dict] = ```python class MyApplication(asab.Application): - def __init__(self): - super().__init__() + async def initialize(self): web = asab.web.create_web_server(self) web.add_get('/hello', self.hello) diff --git a/asab/web/container.py b/asab/web/container.py index 30fffec6f..aff25a9f5 100644 --- a/asab/web/container.py +++ b/asab/web/container.py @@ -20,70 +20,10 @@ class WebContainer(Configurable): - - ''' -# Configuration examples - -## HTTP on TCP port 8080, IPv4 and IPv6 if applicable - -[web] -listen=8080 - - -## Interface specified - -[web] -listen=0.0.0.0 8080 - - -## Multiple interfaces - -[web] -listen: - 0.0.0.0 8080 - :: 8080 - - -## Multiple interfaces, one with HTTPS - -[web] -listen: - 0.0.0.0 8080 - :: 8080 - 0.0.0.0 8443 ssl:web - 0.0.0.0:8001 - -[ssl:web] -cert=... -key=... -... - - -## Multiple interfaces, one with HTTPS (inline) - -[web] -listen: - 0.0.0.0 8080 - :: 8080 - 0.0.0.0 8443 ssl - 0.0.0.0:8001 - -# The SSL parameters are inside of the WebContainer section -cert=... -key=... - -... - - -# Preflight paths -Preflight requests are sent by the browser, for some cross domain request (custom header etc.). -Browser sends preflight request first. -It is request on same endpoint as app demanded request, but of OPTIONS method. -Only when satisfactory response is returned, browser proceeds with sending original request. -Use `cors_preflight_paths` to specify all paths and path prefixes (separated by comma) for which you -want to allow OPTIONS method for preflight requests. - ''' - + """ + Configurable object that serves as a backend for `asab.WebService`. + It contains everything needed for the web server existence, namely all the configuration and the server Application object. + """ ConfigDefaults = { 'listen': '0.0.0.0 8080', # Can be multiline @@ -161,6 +101,16 @@ def __init__(self, websvc: WebService, config_section_name: str, config: typing. client_max_size = int(self.Config.get("body_max_size")) self.WebApp: aiohttp.web.Application = aiohttp.web.Application(client_max_size=client_max_size) + """ + The Web Application object. See [aiohttp documentation](https://docs.aiohttp.org/en/stable/web_reference.html?highlight=Application#application) for the details. + + It is a *dict-like* object, so you can use it for sharing data globally by storing arbitrary properties for later access from a handler. + + Attributes: + WebApp["app"] (asab.Application): Reference to the ASAB Application. + + WebApp["rootdir"] (asab.web.staticdir.StaticDirProvider): Reference to the root path specified by `rootdir` configuration. + """ self.WebApp.on_response_prepare.append(self._on_prepare_response) self.WebApp['app'] = websvc.App @@ -212,7 +162,7 @@ async def _stop(self, app: Application): await self.WebAppRunner.cleanup() - def add_preflight_handlers(self, preflight_paths): + def add_preflight_handlers(self, preflight_paths: typing.List[str]): for path in preflight_paths: self.WebApp.router.add_route("OPTIONS", path, self._preflight_handler) @@ -236,7 +186,7 @@ async def _on_prepare_response(self, request, response): response.headers['Access-Control-Allow-Methods'] = "GET, POST, DELETE, PUT, PATCH, OPTIONS" - def get_ports(self) -> list[str]: + def get_ports(self) -> typing.List[str]: """ Return list of available ports. From ff6945ee9e0ff18bcc4e6ff8e439c2cdaad9b622 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 4 Aug 2023 13:38:20 +0200 Subject: [PATCH 119/154] Redesign web server section --- docs/reference/module.md | 0 docs/reference/web/web-server.md | 233 ++++++++++++++++++++++--------- 2 files changed, 165 insertions(+), 68 deletions(-) delete mode 100644 docs/reference/module.md diff --git a/docs/reference/module.md b/docs/reference/module.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/docs/reference/web/web-server.md b/docs/reference/web/web-server.md index ca3695108..063435c9b 100644 --- a/docs/reference/web/web-server.md +++ b/docs/reference/web/web-server.md @@ -5,7 +5,31 @@ This module offers an integration of [`aiohttp` web server](http://aiohttp.readt !!! tip - For a quick start, we recommend reading the official `aiohttp` tutorial on [how to run a simple web server](https://docs.aiohttp.org/en/stable/web_quickstart.html#run-a-simple-web-server). + For a quick start, we recommend reading the official `aiohttp` tutorial on [how to run a simple web server](https://docs.aiohttp.org/en/stable/web_quickstart.html#run-a-simple-web-server). + +## Handlers, routes and resources + +`aiohttp` servers use the concept of Handlers, Routes and Resources. Here we provide a very quick explanation that should help you to get into the terminology. + +- **Handler**, more precisely *"a web request handler"*, is a function that does the logic when you send HTTP request to the endpoint. It is a coroutine that accepts `aiohttp.web.Request` instance as its only parameter and returns a `aiohttp.web.Response` object. + + ```python + async def handler(request): + return aiohttp.web.Response() + ``` + +- **Route** corresponds to handling HTTP method by calling web handler. Routes are added to the route table that is stored in the Web Application object. + + ```python + web_app.add_routes( + [web.get('/path1', get_1), + web.post('/path1', post_1), + web.get('/path2', get_2), + web.post('/path2', post_2)] + ``` + +- **Resource** is an entry in route table which corresponds to requested URL. Resource in turn has at least one route. When you add a route, the resource object is created under the hood. + ## Creating a web server @@ -14,82 +38,143 @@ First make sure that you have `aiohttp` module installed: python3 -m pip install aiohttp ``` -The following code creates a simple web server application: +!!! example "Creating a web server 1: One method does it all!" -``` python linenums="1" -import asab.web -import aiohttp + To build a web server quickly, ASAB provides a method [`asab.web.create_web_server()`](#asab.web.create_web_server) that does all the magic. -class MyApplication(asab.Application): + ```python linenums="1" + import asab.web + import aiohttp - async def initialize(self): - self.add_module(asab.web.Module) #(1)! - self.WebService = self.get_service("asab.WebService") #(2)! + class MyApplication(asab.Application): + async def initialize(): #(1)! + web = asab.web.create_web_server(self) #(2)! + web.add_get('/hello', self.hello) #(3)! - self.WebContainer = asab.web.WebContainer( #(3)! - websvc=self.WebService, - config_section_name='my:web', - config={"listen": "0.0.0.0:8080"} - ) + # This is the web request handler + async def hello(self, request): #(4)! + return aiohttp.web.Response(data="Hello from your ASAB server!\n") - self.WebContainer.WebApp.router.add_get('/hello', self.hello) #(4)! + if __name__ == '__main__': + app = MyApplication() + app.run() + ``` - # This is the web request handler - async def hello(self, request): #(5)! - return aiohttp.web.Response(text='Hello from your ASAB server!\n') + 1. Web server configuration should be prepared during [the init-time](/reference/application/reference/#init-time) of the application lifecycle. + 2. `asab.web.create_web_server()` creates web server and returns instance of + [`aiohttp.web.UrlDispatcher` object](https://docs.aiohttp.org/en/stable/web_reference.html?highlight=router#router) (which is usually referred to as a "router"). The method takes the argument `app` which is used as the reference to the base `asab.Application` object, and optional parameters that expand configuration options. + 3. You can easily create a new endpoint by [`aiohttp.web.UrlDispatcher.add_route()` method](https://docs.aiohttp.org/en/stable/web_reference.html?highlight=router#aiohttp.web.UrlDispatcher.add_route) + that appends a request handler to the router table. This one is a shortcut for adding a **GET** handler. + 4. A request handler must be a coroutine that accepts [`aiohttp.web.Request` instance](https://docs.aiohttp.org/en/stable/web_reference.html#aiohttp.web.Request) as its only parameter and returns [`aiohttp.web.Response` instance](https://docs.aiohttp.org/en/stable/web_reference.html#response). + By default, ASAB server runs on `0.0.0.0:8080`. + You can test if your server is working by sending a request to the `/hello` endpoint, e.g., via the `curl` command: -if __name__ == '__main__': - app = MyApplication() - app.run() -``` + ```shell + curl http://localhost:8080/hello + ``` -1. In order to use `asab.WebService`, first import the corresponding `asab.web.Module`... -2. ...and then locate the Service. -3. Creates the Web container, which is instance of [`asab.Config.Configurable`](http://localhost:8000/reference/config/reference/#asab.config.Configurable) object that stores the configuration such as the actual web application. -4. `asab.web.WebContainer.WebApp` is instance of `aiohttp.web.Application` object. To create a new endpoint, use methods for [`aiohttp.web.Application.router` object](https://docs.aiohttp.org/en/stable/web_reference.html?highlight=add_get#router). -5. A request handler must be a coroutine that accepts [`aiohttp.web.Request` instance](https://docs.aiohttp.org/en/stable/web_reference.html#aiohttp.web.Request) as its only parameter and returns [`aiohttp.web.Response` instance](https://docs.aiohttp.org/en/stable/web_reference.html#response). + and you should get the response: -You can test if your server is working by sending a request to the `/hello` endpoint, e.e., via the `curl` command: + ``` + Hello from your ASAB server! + ``` -```shell -curl http://localhost:8080/hello -``` +!!! example "Creating a web server 2: Under the hood." -and you should get the response: + The code below does exactly the same as in the previous example. -``` -Hello from your ASAB server! + ``` python linenums="1" + import asab.web + import aiohttp + + class MyApplication(asab.Application): + + async def initialize(self): + self.add_module(asab.web.Module) #(1)! + self.WebService = self.get_service("asab.WebService") #(2)! + + self.WebContainer = asab.web.WebContainer( #(3)! + websvc=self.WebService, + config_section_name='my:web', + config={"listen": "0.0.0.0:8080"} + ) + + self.WebContainer.WebApp.router.add_get('/hello', self.hello) #(4)! + + # This is the web request handler + async def hello(self, request): #(5)! + return aiohttp.web.Response(text='Hello from your ASAB server!\n') + + + if __name__ == '__main__': + app = MyApplication() + app.run() + ``` + + 1. In order to use `asab.WebService`, first import the corresponding `asab.web.Module`... + 2. ...and then locate the Service. + 3. Creates the Web container, which is instance of [`asab.Config.Configurable`](http://localhost:8000/reference/config/reference/#asab.config.Configurable) object that stores the configuration such as the actual web application. + 4. `asab.web.WebContainer.WebApp` is instance of `aiohttp.web.Application` object. To create a new endpoint, use methods for [`aiohttp.web.Application.router` object](https://docs.aiohttp.org/en/stable/web_reference.html?highlight=add_get#router). + 5. A request handler must be a coroutine that accepts [`aiohttp.web.Request` instance](https://docs.aiohttp.org/en/stable/web_reference.html#aiohttp.web.Request) as its only parameter and returns [`aiohttp.web.Response` instance](https://docs.aiohttp.org/en/stable/web_reference.html#response). + +!!! tip + + Resources may also have variable path, see [the documentation](https://docs.aiohttp.org/en/stable/web_quickstart.html#variable-resources). + + ```python + web.get('/users/{user}/age', user_age_handler) + web.get(r'/{name:\d+}', name_handler) + ``` + +!!! note + + `aiohttp` also supports the *Flask style* for creating web request handlers via decorators. ASAB applications use the *Django style* way of creating routes, i.e. without decorators. + +## Web server configuration + +Configuration is passed to the `asab.web.WebContainer` object. + +### The default configuration + +```ini +[web] +listen=0.0.0.0 8080 +backlog=128 +rootdir= +servertokens=full +cors= +cors_preflight_paths=/openidconnect/*, /test/* +body_max_size=1024**2 ``` -## Configuration +### Socket addresses -The default configuration of the [web]{.title-ref} container in ASAB is -following: +The default configuration of the web socket address in `asab.web.WebContainer` is the following: -``` {.ini} +``` ini [web] listen=0.0.0.0:8080 ``` Multiple listening interfaces can be specified: -``` {.ini} +``` ini [web] listen: - 0.0.0.0:8080 - :: 8080 + 0.0.0.0:8080 + :: 8080 ``` Multiple listening interfaces, one with HTTPS (TLS/SSL) can be specified: -``` {.ini} +``` ini [web] listen: - 0.0.0.0 8080 - :: 8080 - 0.0.0.0 8443 ssl:web + 0.0.0.0 8080 + :: 8080 + 0.0.0.0 8443 ssl:web [ssl:web] cert=... @@ -99,45 +184,57 @@ key=... Multiple interfaces, one with HTTPS (inline): -``` {.ini} +``` ini [web] listen: - 0.0.0.0 8080 - :: 8080 - 0.0.0.0 8443 ssl + 0.0.0.0 8080 + :: 8080 + 0.0.0.0 8443 ssl # The SSL parameters are inside of the WebContainer section cert=... key=... -... ``` -Other available options are: +You can also enable listening on TCP port 8080, IPv4 and IPv6 if applicable: + +```ini +[web] +listen=8080 +``` + +### Preflight paths -> - [backlog]{.title-ref} -> - [rootdir]{.title-ref} -> - [servertokens]{.title-ref} (default value [full]{.title-ref}) -> - [cors]{.title-ref} -> - [cors\_preflight\_paths]{.title-ref} +Preflight requests are sent by the browser, for some cross domain request (custom header etc.). +Browser sends preflight request first. +It is request on same endpoint as app demanded request, but of **OPTIONS** method. +Only when satisfactory response is returned, browser proceeds with sending original request. +Use `cors_preflight_paths` to specify all paths and path prefixes (separated by comma) for which you +want to allow OPTIONS method for preflight requests. -TLS/SSL paramereters: -> - [cert]{.title-ref} -> - [key]{.title-ref} -> - [password]{.title-ref} -> - [cafile]{.title-ref} -> - [capath]{.title-ref} -> - [ciphers]{.title-ref} -> - [dh\_params]{.title-ref} -> - \`verify\_mode\`: one of [CERT\_NONE]{.title-ref}, -> [CERT\_OPTIONAL]{.title-ref} or [CERT\_REQUIRED]{.title-ref} -> - [check\_hostname]{.title-ref} -> - [options]{.title-ref} +### Configuration of TLS/SSL connection: + +ASAB provides `asab.tls.SSLContextBuilder` + +- cert +- key +- password +- cafile +- capath +- ciphers +- dh_params +- verify_mode: one of `CERT_NONE`, `CERT_OPTIONAL` or `CERT_REQUIRED` +- check_hostname +- options ## Reference +::: asab.web.create_web_server + ::: asab.web.Module ::: asab.web.service.WebService ::: asab.web.WebContainer + From 30ff83967052a797795db7a94d920b5f63c2d78a Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 4 Aug 2023 13:46:20 +0200 Subject: [PATCH 120/154] Add incomplete icon --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index 77b333731..3767d733d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -47,6 +47,7 @@ theme: bug: fontawesome/solid/robot example: fontawesome/solid/code quote: fontawesome/solid/quote-left + incomplete: material/excavator repo: fontawesome/brands/github From b2284e33ebcf76b1ce33ab82959f572684bf034f Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 4 Aug 2023 13:46:40 +0200 Subject: [PATCH 121/154] Create TLS section --- docs/reference/web/tls.md | 7 +++++++ mkdocs.yml | 1 + 2 files changed, 8 insertions(+) create mode 100644 docs/reference/web/tls.md diff --git a/docs/reference/web/tls.md b/docs/reference/web/tls.md new file mode 100644 index 000000000..a412b4190 --- /dev/null +++ b/docs/reference/web/tls.md @@ -0,0 +1,7 @@ +# Transport Layer Security + +**Transport Layer Security** protocol (*TLS*, also known as *"Secure Sockets Layer"*) is a cryptographic protocol that provides communication security over a computer network, so that the web servers can use **HTTPS**. + +For adding the HTTPS to ASAB web applications, there is a `asab.tls.SSLContextBuilder` class that is connected to `asab.web.WebContainer`. + +::: asab.tls.SSLContextBuilder diff --git a/mkdocs.yml b/mkdocs.yml index 3767d733d..a46dae628 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -166,6 +166,7 @@ nav: - Configuration: reference/config/reference.md - Logging: reference/logging/reference.md - Library: reference/library/reference.md + - TLS/SSL: reference/web/tls.md - Metrics: - MetricsService: reference/metrics/service.md - Gauge: reference/metrics/gauge.md From 1a0a0b07e2e969245570fbb4284d455553552778 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 4 Aug 2023 13:49:57 +0200 Subject: [PATCH 122/154] Add reference --- docs/reference/web/tls.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/web/tls.md b/docs/reference/web/tls.md index a412b4190..1486e26c2 100644 --- a/docs/reference/web/tls.md +++ b/docs/reference/web/tls.md @@ -2,6 +2,6 @@ **Transport Layer Security** protocol (*TLS*, also known as *"Secure Sockets Layer"*) is a cryptographic protocol that provides communication security over a computer network, so that the web servers can use **HTTPS**. -For adding the HTTPS to ASAB web applications, there is a `asab.tls.SSLContextBuilder` class that is connected to `asab.web.WebContainer`. +For adding the HTTPS to ASAB web applications, there is a `asab.tls.SSLContextBuilder` class that is connected to [`asab.web.WebContainer`](/reference/web/web-server/#asab.web.WebContainer). ::: asab.tls.SSLContextBuilder From 9ab02bf14a48cbef452299aa5b41fe6656d57181 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 4 Aug 2023 14:33:08 +0200 Subject: [PATCH 123/154] Add docstrings and configuration for SSL --- asab/tls.py | 29 ++++++++++++++++++++++------- docs/reference/web/tls.md | 18 ++++++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/asab/tls.py b/asab/tls.py index 1f179dd23..e2e1f1e9e 100644 --- a/asab/tls.py +++ b/asab/tls.py @@ -3,6 +3,17 @@ class SSLContextBuilder(Configurable): + """ + Class for creating SSL context from a configuration. + + Examples: + + ```python + ssl_context_builder = asab.tls.SSLContextBuilder(config_section) + ssl_context = ssl_context_builder.build(protocol=ssl.PROTOCOL_TLS_CLIENT) + # ssl_context is later used as a parameter when making HTTP requests + ``` + """ ConfigDefaults = { 'cert': '', # The certfile string must be the path to a PEM file containing the certificate as well as any number of CA certificates needed to establish the certificate’s authenticity. @@ -22,15 +33,19 @@ class SSLContextBuilder(Configurable): 'options': '', } - def build(self, protocol=ssl.PROTOCOL_TLS): - ''' - ## SSL Server - ssl_context = self.SSLContextBuilder.build() + def build(self, protocol=ssl.PROTOCOL_TLS) -> ssl.SSLContext: + """ + Create SSL Context for the specified protocol. + + Allowed `protocol` values: - ## SSL Client + - ssl.PROTOCOL_TLS + - ssl.PROTOCOL_TLS_CLIENT: used for the client + - ssl.PROTOCOL_TLS_SERVER: used for the server - ssl_context = self.SSLContextBuilder.build(ssl.PROTOCOL_TLS_CLIENT) - ''' + Args: + protocol: TLS protocol used for the communication. + """ ctx = ssl.SSLContext(protocol=protocol) ctx.options |= ssl.OP_NO_SSLv2 diff --git a/docs/reference/web/tls.md b/docs/reference/web/tls.md index 1486e26c2..9260b51cf 100644 --- a/docs/reference/web/tls.md +++ b/docs/reference/web/tls.md @@ -1,7 +1,25 @@ # Transport Layer Security +!!! warning + :material-excavator: This part of ASAB is currently under construction. :material-excavator: + **Transport Layer Security** protocol (*TLS*, also known as *"Secure Sockets Layer"*) is a cryptographic protocol that provides communication security over a computer network, so that the web servers can use **HTTPS**. For adding the HTTPS to ASAB web applications, there is a `asab.tls.SSLContextBuilder` class that is connected to [`asab.web.WebContainer`](/reference/web/web-server/#asab.web.WebContainer). +## Configuration options + +| Option | Meaning | +| --- | --- | +| `cert` | Path to a PEM file containing the certificate as well as any number of CA certificates needed to establish the certificate’s authenticity. | +| `key` | Path to a file containing the private key. If not provided, the private key will be taken from the file specified in `cert`.| +| `cafile` | Path to a file containing the CA. | +| `capath` | Path to a directory containing CA certificates. | +| `cadata` | String containing CA certificates in PEM format. | +| `ciphers` | String specifying the allowed SSL/TLS ciphers for the connection. | +| `dh_params` | Path to a file containing Diffie-Hellman parameters for key exchange. | +| `verify_mode` | Control the verification mode for peer certificates. Possible values are `'CERT_NONE'` (no certificate verification), `'CERT_OPTIONAL'` (verification but not required), and `'CERT_REQUIRED'` (verification required). | +| `check_hostname` | :material-excavator: | +| `options` | :material-excavator: | + ::: asab.tls.SSLContextBuilder From e1767ca6427df767a4a58110075a0c3111f216c8 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 4 Aug 2023 14:46:25 +0200 Subject: [PATCH 124/154] Synchronize TODOs --- docs/TODO.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/docs/TODO.md b/docs/TODO.md index 6d4cb2601..d85ac6b04 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -1,5 +1,26 @@ # TODOs +- Create a Dockerfile +- Experiment with search boosting: https://squidfunk.github.io/mkdocs-material/setup/setting-up-site-search/#search-boosting +- Override the CSS for 'h2.doc-heading' so that we can use different heading level and improve the design + +## Missing sections + +- PubSub +- AlertService +- ProactorService +- SSL/TLS +- Authorization and multitenancy +- CORS +- Metrics (needs to be modified) +- Zookeeper + +- Containerisation (needs to be modified) +- Systemd + + +## Useful hyperlinks: + https://squidfunk.github.io/mkdocs-material/reference/code-blocks/ https://realpython.com/python-project-documentation-with-mkdocs/#step-1-set-up-your-environment-for-building-documentation @@ -27,7 +48,4 @@ patch path/to/file.py path/to/file.py.patch ``` -- Create a Dockerfile -- Experiment with search boosting: https://squidfunk.github.io/mkdocs-material/setup/setting-up-site-search/#search-boosting -- Override the CSS for 'h2.doc-heading' so that we can use different heading level and improve the design From f0aed585aed8a6978dacbe2ff919561f3afb2404 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 4 Aug 2023 15:07:16 +0200 Subject: [PATCH 125/154] Change docstrings to Google style format --- asab/web/auth/decorator.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/asab/web/auth/decorator.py b/asab/web/auth/decorator.py index a41d31351..9f0926eb7 100644 --- a/asab/web/auth/decorator.py +++ b/asab/web/auth/decorator.py @@ -13,20 +13,20 @@ def require(*resources): """ - Specifies resources required for endpoint access. + Specify resources required for endpoint access. Requests without these resources result in HTTP 403 response. - :param resources: Resources required to access the decorated method. - :type resources: typing.Iterable + Args: + resources (Iterable): Resources required to access the decorated method. - Usage: + Examples: - .. code:: python - - @asab.web.authz.require("my-app:token:generate") - async def generate_token(self, request): - data = await self.service.generate_token() - return asab.web.rest.json_response(request, data) + ```python + @asab.web.authz.require("my-app:token:generate") + async def generate_token(self, request): + data = await self.service.generate_token() + return asab.web.rest.json_response(request, data) + ``` """ def decorator_require(handler): @@ -51,17 +51,17 @@ async def wrapper(*args, **kwargs): def noauth(handler): """ - Exempts the decorated handler from authentication and authorization. + Exempt the decorated handler from authentication and authorization. The `tenant`, `user_info` and `resources` arguments are not available in the handler. - Usage: - - .. code:: python + Examples: - @asab.web.authz.noauth - async def get_public_info(self, request): - data = await self.service.get_public_info() - return asab.web.rest.json_response(request, data) + ```python + @asab.web.authz.noauth + async def get_public_info(self, request): + data = await self.service.get_public_info() + return asab.web.rest.json_response(request, data) + ``` """ argspec = inspect.getfullargspec(handler) args = set(argspec.kwonlyargs).union(argspec.args) From 4d2c95082e6545d5578304d601e7e7061167ca0c Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 4 Aug 2023 15:07:48 +0200 Subject: [PATCH 126/154] Create authorization and multitenancy section --- .../web/authorization_multitenancy.md | 201 ++++++++++++++++++ mkdocs.yml | 8 +- 2 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 docs/reference/web/authorization_multitenancy.md diff --git a/docs/reference/web/authorization_multitenancy.md b/docs/reference/web/authorization_multitenancy.md new file mode 100644 index 000000000..08686976b --- /dev/null +++ b/docs/reference/web/authorization_multitenancy.md @@ -0,0 +1,201 @@ +# Authorization and multitenancy + +The `asab.web.auth` module provides [authentication](https://en.wikipedia.org/wiki/Authentication) and +[authorization](https://en.wikipedia.org/wiki/Authorization) of incoming requests. +This enables your application to differentiate between users, +grant or deny them API access depending on their permissions and work +with other relevant user data. + +The module also implements [multitenancy](https://en.wikipedia.org/wiki/Multitenancy), +meaning that your application can be used by a number of independent subjects +(tenants, for example companies) without interfering with each other. + +The `auth` module requires an authorization server to function. +It works best with [Seacat Auth](https://github.com/TeskaLabs/seacat-auth) +authorization server +(See [its documentation](https://docs.teskalabs.com/seacat-auth/getting-started/quick-start) for setup instructions). + +## Getting started + +To get started, initialize `AuthService` and install it in your `asab.web.WebContainer`: + +``` python +class MyApplication(asab.Application): + def __init__(self): + super().__init__() + + # Initialize web container + self.add_module(asab.web.Module) + self.WebService = self.get_service("asab.WebService") + self.WebContainer = asab.web.WebContainer(self.WebService, "web") + + # Initialize authorization service and install the decorators + self.AuthService = asab.web.auth.AuthService(self) + self.AuthService.install(self.WebContainer) +``` + +!!! note + + You may also need to specify your authorization server's `public_keys_url` + (also known as `jwks_uri` in [OAuth 2.0](https://www.rfc-editor.org/rfc/rfc8414#section-2)). + In case you don't have any authorization server at hand, + you can run the auth module in `dev_mode`. See the `configuration` section for details. + + +Every handler in `WebContainer` now accepts only requests with a valid authentication. +Unauthenticated requests are automatically answered with +[HTTP 401: Unauthorized](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401). +Authenticated requests will be inspected for user info, authorized user tenant and resources. +These attributes are passed to the handler method, if the method in question has +the corresponding keyword arguments (`user_info`, `tenant` and `resources`). +In the following example, the method will receive `user_info` and `resources` from the request: + +``` python +async def order_breakfast(self, request, *, tenant, user_info, resources): + user_id = user_info["sub"] + user_name = user_info["preferred_username"] + if "pancakes:eat" in resources: + ... + return asab.web.rest.json_response(request, {"result": "Your breakfast is being prepared!"}) +``` + +See [examples/web-auth.py](https://github.com/TeskaLabs/asab/blob/master/examples/web-auth.py) for a full demo ASAB application with auth module. + +## Configuration + +The `asab.web.auth` module is configured +in the `[auth]` section with the following options: + +- public_keys_url + +`(URL, default: http://localhost:8081/openidconnect/public_keys)` The +URL of the authorization server\'s public keys (also known as `jwks_uri` +in [OAuth 2.0](https://www.rfc-editor.org/rfc/rfc8414#section-2)). + +- multitenancy + +`(boolean, default: yes)` Toggles the behavior of endpoints with +configurable tenant parameter. When enabled, the tenant query paramerter +is required. When disabled, the tenant query paramerter is ignored and +set to `None`. In dev mode, the multitenancy switch is ignored and the +tenant parameter is taken into account only when it is present in query, +otherwise it is set to `None`. + +- dev_mode + +`(boolean, default: no)` In dev mode, all incoming requests are +authenticated and authorized with mock user info. There is no +communication with authorization server (so it is not necessary to +configure `public_keys_url` in dev mode). + +- dev_user_info_path + +`(path, default: /conf/dev-userinfo.json)` Path to JSON file that +contains mock user info used in dev mode. The structure of user info +should follow the [OpenID Connect userinfo +definition](https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse) +and also contain the `resources` object. + +## Multitenancy + +### Strictly multitenant endpoints + +Strictly multitenant endpoints always operate within a tenant, hence they need the `tenant` parameter to be always provided. +Such endpoints must define the `tenant` parameter in their **URL path** and include `tenant` argument in the handler method. +Auth service extracts the tenant from the URL path, validates the tenant existence, +checks if the request is authorized for the tenant and finally passes the tenant name to the handler method. + +!!! example "Example handler:" + + ``` python + class MenuHandler: + def __init__(self, app): + self.MenuService = app.get_service("MenuService") + router = app.WebContainer.WebApp.router + # Add a path with `tenant` parameter + router.add_get("/{tenant}/todays-menu", self.get_todays_menu) + + # Define handler method with `tenant` argument in the signature + async def get_todays_menu(self, request, *, tenant): + menu = await self.MenuService.get_todays_menu(tenant) + return asab.web.rest.json_response(request, data=menu) + ``` + +!!! example "Example request:" + + ``` + GET http://localhost:8080/lazy-raccoon-bistro/todays-menu + ``` + + +### Configurable multitenant endpoints + +Configurable multitenant endpoints usually operate within a tenant, but +they can also operate in tenantless mode if the application is +configured so. When you create an endpoint *without* `tenant` parameter +in the URL path and *with* `tenant` argument in the handler method, the +Auth service will either expect the `tenant` parameter to be provided in +the **URL query** if mutlitenancy is enabled, or to not be provided at +all if multitenancy is disabled. Use the `multitenancy` boolean switch +in the `[auth]` config section to control the multitenancy setting. + + +If multitenancy is **enabled**, the request\'s **query string** must include a tenant parameter. +Requests without the tenant query result in Bad request (HTTP 400). + +If multitenancy is **disabled**, the tenant argument in the handler method is set to `None`. +Any `tenant` parameter in the query string is ignored. + +!!! example "Example handler:" + + ``` python + class MenuHandler: + def __init__(self, app): + self.MenuService = app.get_service("MenuService") + router = app.WebContainer.WebApp.router + # Add a path without `tenant` parameter + router.add_get("/todays-menu", self.get_todays_menu) + + # Define handler method with `tenant` argument in the signature + async def get_todays_menu(self, request, *, tenant): + menu = await self.MenuService.get_todays_menu(tenant) + return asab.web.rest.json_response(request, data=menu) + ``` + +!!! example "Example requests:" + + 1. with multitenancy on:. + + ``` + GET http://localhost:8080/todays-menu?tenant=lazy-raccoon-bistro + ``` + + 2. with multitenancy off: + + ``` + GET http://localhost:8080/todays-menu + ``` + +## Development mode + +In dev mode, actual authorization is disabled and replaced with mock authorization. +Useful for developing ASAB apps without authorization server. Activate by enabling `dev_mode` in the `[auth]` config section. +You can also specify a path to a JSON file with your own mocked userinfo payload `[auth] dev_user_info_path`: + +``` ini +[auth] +dev_mode=yes +dev_user_info_path=${THIS_DIR}/mock_userinfo.json +``` + +When dev mode is enabled, you don't have to provide +`[public_keys_url]` as this option is ignored. + +## Reference + +::: asab.web.auth.AuthService + + +::: asab.web.auth.require + +::: asab.web.auth.noauth diff --git a/mkdocs.yml b/mkdocs.yml index a46dae628..f8860e412 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -162,11 +162,15 @@ nav: - Reference: - Application: reference/application/reference.md - Modules and Services: reference/modules_services/reference.md - - Web Server: reference/web/web-server.md + + - Web Server: + - Creating a web server: reference/web/web-server.md + - TLS/SSL: reference/web/tls.md + - Authorization and multitenancy: reference/web/authorization_multitenancy.md + - Configuration: reference/config/reference.md - Logging: reference/logging/reference.md - Library: reference/library/reference.md - - TLS/SSL: reference/web/tls.md - Metrics: - MetricsService: reference/metrics/service.md - Gauge: reference/metrics/gauge.md From ad7f45672e112e2b0c4185ac72bbba569974e23a Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 4 Aug 2023 15:24:40 +0200 Subject: [PATCH 127/154] Change formatting --- .../web/authorization_multitenancy.md | 74 ++++++++----------- 1 file changed, 30 insertions(+), 44 deletions(-) diff --git a/docs/reference/web/authorization_multitenancy.md b/docs/reference/web/authorization_multitenancy.md index 08686976b..b8e05a8d5 100644 --- a/docs/reference/web/authorization_multitenancy.md +++ b/docs/reference/web/authorization_multitenancy.md @@ -66,35 +66,21 @@ See [examples/web-auth.py](https://github.com/TeskaLabs/asab/blob/master/example The `asab.web.auth` module is configured in the `[auth]` section with the following options: -- public_keys_url - -`(URL, default: http://localhost:8081/openidconnect/public_keys)` The -URL of the authorization server\'s public keys (also known as `jwks_uri` -in [OAuth 2.0](https://www.rfc-editor.org/rfc/rfc8414#section-2)). - -- multitenancy - -`(boolean, default: yes)` Toggles the behavior of endpoints with -configurable tenant parameter. When enabled, the tenant query paramerter -is required. When disabled, the tenant query paramerter is ignored and -set to `None`. In dev mode, the multitenancy switch is ignored and the -tenant parameter is taken into account only when it is present in query, -otherwise it is set to `None`. - -- dev_mode - -`(boolean, default: no)` In dev mode, all incoming requests are -authenticated and authorized with mock user info. There is no -communication with authorization server (so it is not necessary to -configure `public_keys_url` in dev mode). - -- dev_user_info_path - -`(path, default: /conf/dev-userinfo.json)` Path to JSON file that -contains mock user info used in dev mode. The structure of user info -should follow the [OpenID Connect userinfo -definition](https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse) -and also contain the `resources` object. +| Option | Type | Meaning | +| --- | --- | --- | +| `public_keys_url` | URL | The URL of the authorization server's public keys (also known as `jwks_uri` in [OAuth 2.0](https://www.rfc-editor.org/rfc/rfc8414#section-2)). | +| `multitenancy` | boolean | Toggles the behavior of endpoints with configurable tenant parameter. When enabled, the tenant query paramerter is required. When disabled, the tenant query parameter is ignored and set to `None`. In dev mode, the multitenancy switch is ignored and the tenant parameter is taken into account only when it is present in query, otherwise it is set to `None`. | +| `dev_mode` | boolean | In dev mode, all incoming requests are authenticated and authorized with mock user info. There is no communication with authorization server (so it is not necessary to configure `public_keys_url` in dev mode). +| `dev_user_info_path` | path | Path to JSON file that contains mock user info used in dev mode. The structure of user info should follow the [OpenID Connect userinfo definition](https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse) and also contain the `resources` object. + +Default options: + +```ini +public_keys_url=http://localhost:8081/openidconnect/public_keys +multitenancy=yes +dev_mode=no +dev_user_info_path=/conf/dev-userinfo.json +``` ## Multitenancy @@ -130,17 +116,17 @@ checks if the request is authorized for the tenant and finally passes the tenant ### Configurable multitenant endpoints -Configurable multitenant endpoints usually operate within a tenant, but -they can also operate in tenantless mode if the application is -configured so. When you create an endpoint *without* `tenant` parameter -in the URL path and *with* `tenant` argument in the handler method, the -Auth service will either expect the `tenant` parameter to be provided in -the **URL query** if mutlitenancy is enabled, or to not be provided at -all if multitenancy is disabled. Use the `multitenancy` boolean switch -in the `[auth]` config section to control the multitenancy setting. +Configurable multitenant endpoints usually operate within a tenant, but they can also operate in tenantless mode if the application is configured so. + +When you create an endpoint *without* `tenant` parameter in the URL path and *with* `tenant` argument in the handler method, the +Auth service will either expect the `tenant` parameter +to be provided in the **URL query** if mutlitenancy is enabled, +or to not be provided at all if multitenancy is disabled. +Use the `multitenancy` boolean switch in the `[auth]` config section to control the multitenancy setting. -If multitenancy is **enabled**, the request\'s **query string** must include a tenant parameter. + +If multitenancy is **enabled**, the request's **query string** must include a tenant parameter. Requests without the tenant query result in Bad request (HTTP 400). If multitenancy is **disabled**, the tenant argument in the handler method is set to `None`. @@ -166,15 +152,15 @@ Any `tenant` parameter in the query string is ignored. 1. with multitenancy on:. - ``` - GET http://localhost:8080/todays-menu?tenant=lazy-raccoon-bistro - ``` + ``` + GET http://localhost:8080/todays-menu?tenant=lazy-raccoon-bistro + ``` 2. with multitenancy off: - ``` - GET http://localhost:8080/todays-menu - ``` + ``` + GET http://localhost:8080/todays-menu + ``` ## Development mode From 1016644c28c866b9509baaefcc7bfa36508d07e9 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Fri, 4 Aug 2023 16:41:41 +0200 Subject: [PATCH 128/154] Fix indentation for mkdocstring --- asab/web/__init__.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/asab/web/__init__.py b/asab/web/__init__.py index ef210850f..ebffc81ab 100644 --- a/asab/web/__init__.py +++ b/asab/web/__init__.py @@ -21,30 +21,30 @@ def __init__(self, app): def create_web_server(app, section: str = "web", config: typing.Optional[dict] = None) -> aiohttp.web.UrlDispatcher: """ - Build the web server with the specified configuration. +Build the web server with the specified configuration. - It is an user convenience function that simplifies typical way of how the web server is created. +It is an user convenience function that simplifies typical way of how the web server is created. - Args: - app (asab.Application): A reference to the ASAB Application. - section (str): Configuration section name with which the WebContainer will be created. - config (dict | None): Additional server configuration. +Args: + app (asab.Application): A reference to the ASAB Application. + section (str): Configuration section name with which the WebContainer will be created. + config (dict | None): Additional server configuration. - Returns: - [WebContainer Application Router object](https://docs.aiohttp.org/en/stable/web_reference.html?highlight=router#router). +Returns: + [WebContainer Application Router object](https://docs.aiohttp.org/en/stable/web_reference.html?highlight=router#router). - Examples: +Examples: - ```python - class MyApplication(asab.Application): - async def initialize(self): - web = asab.web.create_web_server(self) - web.add_get('/hello', self.hello) +```python +class MyApplication(asab.Application): + async def initialize(self): + web = asab.web.create_web_server(self) + web.add_get('/hello', self.hello) - async def hello(self, request): - return asab.web.rest.json_response(request, data="Hello, world!\n") + async def hello(self, request): + return asab.web.rest.json_response(request, data="Hello, world!\n") - ``` +``` """ app.add_module(Module) websvc = app.get_service("asab.WebService") From 25a09463da57ca1799b9a53e3a015e73567c2e61 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 7 Aug 2023 10:42:41 +0200 Subject: [PATCH 129/154] Add CORS section --- docs/reference/web/cors.md | 30 ++++++++++++++++++++++++++++++ mkdocs.yml | 1 + 2 files changed, 31 insertions(+) create mode 100644 docs/reference/web/cors.md diff --git a/docs/reference/web/cors.md b/docs/reference/web/cors.md new file mode 100644 index 000000000..0cbde5b9c --- /dev/null +++ b/docs/reference/web/cors.md @@ -0,0 +1,30 @@ +# Cross-Origin Resource Sharing (CORS) + +!!! tip + + [This article](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) explains very well the key concept of CORS. + +The Cross-Origin Resource Sharing standard works by adding new HTTP headers that let servers describe which origins are permitted to read that information from a web browser. Additionally, for HTTP request methods that can cause side-effects on server data (in particular, HTTP methods other than **GET**, or **POST** with certain MIME types), the specification mandates that browsers **"preflight"** the request, soliciting supported methods from the server with the HTTP **OPTIONS** request method, and then, upon "approval" from the server, sending the actual request. Servers can also inform clients whether "credentials" (such as Cookies and HTTP Authentication) should be sent with requests. + + +## Preflight paths + +Preflight requests are sent by the browser, for some cross domain request (custom header etc.). +Browser sends preflight request first. +It is request on the same endpoint as app demanded request, but of **OPTIONS** method. +Only when satisfactory response is returned, browser proceeds with sending original request. +Use `cors_preflight_paths` option to specify all paths and path prefixes (separated by comma) for which you +want to allow OPTIONS method for preflight requests. + +You can then configure CORS by running your app with a config file with this contents: + +``` ini +[web] +cors=* +cors_preflight_paths=/* +``` + +| Option | Meaning | +| --- | --- | +| `cors` | Contents of the Access-Control-Allow-Origin header | +| `cors_preflight_paths` | Pattern for endpoints that shall return responses to pre-flight requests (**OPTIONS**). Value must start with `"/"`. | diff --git a/mkdocs.yml b/mkdocs.yml index f8860e412..91ada6617 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -167,6 +167,7 @@ nav: - Creating a web server: reference/web/web-server.md - TLS/SSL: reference/web/tls.md - Authorization and multitenancy: reference/web/authorization_multitenancy.md + - Cross-Origin Resource Sharing: reference/web/cors.md - Configuration: reference/config/reference.md - Logging: reference/logging/reference.md From 43c2d82685face89d8cf958d55ccfdb825f057b6 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 7 Aug 2023 10:42:57 +0200 Subject: [PATCH 130/154] Add docstring to preflight handlers --- asab/web/container.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/asab/web/container.py b/asab/web/container.py index aff25a9f5..63f39c60b 100644 --- a/asab/web/container.py +++ b/asab/web/container.py @@ -163,6 +163,19 @@ async def _stop(self, app: Application): def add_preflight_handlers(self, preflight_paths: typing.List[str]): + """ + Add handlers with preflight resources. + + Preflight requests are sent by the browser, for some cross domain request (custom header etc.). + Browser sends preflight request first. + It is request on the same endpoint as app demanded request, but of **OPTIONS** method. + Only when satisfactory response is returned, browser proceeds with sending original request. + Use `cors_preflight_paths` option to specify all paths and path prefixes (separated by comma) for which you + want to allow **OPTIONS** method for preflight requests. + + Args: + preflight_paths (list[str]): List of routes that will be provided with **OPTIONS** handler. + """ for path in preflight_paths: self.WebApp.router.add_route("OPTIONS", path, self._preflight_handler) From a288c21d0c87599ae2d4e91b65be1304a26b35d1 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 7 Aug 2023 10:43:22 +0200 Subject: [PATCH 131/154] Add configuration table --- docs/reference/web/web-server.md | 37 +++++++++++--------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/docs/reference/web/web-server.md b/docs/reference/web/web-server.md index 063435c9b..edaf0ae16 100644 --- a/docs/reference/web/web-server.md +++ b/docs/reference/web/web-server.md @@ -135,6 +135,17 @@ python3 -m pip install aiohttp Configuration is passed to the `asab.web.WebContainer` object. +| Parameter | Meaning | +| --- | --- | +| `listen` | The socket address to which the web server will listen. | +| `backlog` | A number of unaccepted connections that the system will allow before refusing new connections, see [`socket.socket.listen()`](https://docs.python.org/3/library/socket.html#socket.socket.listen) for details. | +| `rootdir` | The root path for the server. In case of many web containers, each one can implement a different root. | +| `servertokens` | Controls whether `'Server'` response header field is included (`'full'`) or faked (`'prod'`). | +| `cors` | See [Cross-Origin Resource Sharing](/reference/web/cors) section. | +| `body_max_size`| Client's maximum size in a request, in bytes. If a **POST** request exceeds this value, `aiohttp.HTTPRequestEntityTooLarge` exception is raised. See [the documentation](https://docs.aiohttp.org/en/stable/web_reference.html?highlight=client_max_size#aiohttp.web.Application) for more information. | +| `cors` | Contents of the Access-Control-Allow-Origin header. See the [CORS section](./cors) | +| `cors_preflight_paths` | Pattern for endpoints that shall return responses to pre-flight requests (**OPTIONS**). Value must start with `"/"`. See the [CORS section](./cors)| + ### The default configuration ```ini @@ -148,6 +159,7 @@ cors_preflight_paths=/openidconnect/*, /test/* body_max_size=1024**2 ``` + ### Socket addresses The default configuration of the web socket address in `asab.web.WebContainer` is the following: @@ -203,31 +215,6 @@ You can also enable listening on TCP port 8080, IPv4 and IPv6 if applicable: listen=8080 ``` -### Preflight paths - -Preflight requests are sent by the browser, for some cross domain request (custom header etc.). -Browser sends preflight request first. -It is request on same endpoint as app demanded request, but of **OPTIONS** method. -Only when satisfactory response is returned, browser proceeds with sending original request. -Use `cors_preflight_paths` to specify all paths and path prefixes (separated by comma) for which you -want to allow OPTIONS method for preflight requests. - - -### Configuration of TLS/SSL connection: - -ASAB provides `asab.tls.SSLContextBuilder` - -- cert -- key -- password -- cafile -- capath -- ciphers -- dh_params -- verify_mode: one of `CERT_NONE`, `CERT_OPTIONAL` or `CERT_REQUIRED` -- check_hostname -- options - ## Reference ::: asab.web.create_web_server From 5b905806142e459259b61c20a29b388bdc951d2a Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 7 Aug 2023 10:46:43 +0200 Subject: [PATCH 132/154] Add better typing --- asab/web/container.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asab/web/container.py b/asab/web/container.py index 63f39c60b..76a5d3bd3 100644 --- a/asab/web/container.py +++ b/asab/web/container.py @@ -204,7 +204,7 @@ def get_ports(self) -> typing.List[str]: Return list of available ports. Returns: - list[str]: List of ports. + (list[str]) List of ports. """ ports = [] for addr, port, ssl_context in self._listen: From f1a2cf447955f3e7dd65b70020326106dbbfb2de Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 7 Aug 2023 10:46:59 +0200 Subject: [PATCH 133/154] Fix a typo --- docs/reference/web/web-server.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/web/web-server.md b/docs/reference/web/web-server.md index edaf0ae16..ef9751622 100644 --- a/docs/reference/web/web-server.md +++ b/docs/reference/web/web-server.md @@ -143,8 +143,8 @@ Configuration is passed to the `asab.web.WebContainer` object. | `servertokens` | Controls whether `'Server'` response header field is included (`'full'`) or faked (`'prod'`). | | `cors` | See [Cross-Origin Resource Sharing](/reference/web/cors) section. | | `body_max_size`| Client's maximum size in a request, in bytes. If a **POST** request exceeds this value, `aiohttp.HTTPRequestEntityTooLarge` exception is raised. See [the documentation](https://docs.aiohttp.org/en/stable/web_reference.html?highlight=client_max_size#aiohttp.web.Application) for more information. | -| `cors` | Contents of the Access-Control-Allow-Origin header. See the [CORS section](./cors) | -| `cors_preflight_paths` | Pattern for endpoints that shall return responses to pre-flight requests (**OPTIONS**). Value must start with `"/"`. See the [CORS section](./cors)| +| `cors` | Contents of the Access-Control-Allow-Origin header. See the [CORS section](./cors). | +| `cors_preflight_paths` | Pattern for endpoints that shall return responses to pre-flight requests (**OPTIONS**). Value must start with `"/"`. See the [CORS section](./cors). | ### The default configuration From caab83246d6d6149d214f928e94934023b5d6fbc Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 7 Aug 2023 11:46:19 +0200 Subject: [PATCH 134/154] Reference preflight method --- docs/reference/web/cors.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/reference/web/cors.md b/docs/reference/web/cors.md index 0cbde5b9c..da285587f 100644 --- a/docs/reference/web/cors.md +++ b/docs/reference/web/cors.md @@ -28,3 +28,8 @@ cors_preflight_paths=/* | --- | --- | | `cors` | Contents of the Access-Control-Allow-Origin header | | `cors_preflight_paths` | Pattern for endpoints that shall return responses to pre-flight requests (**OPTIONS**). Value must start with `"/"`. | + +## Reference + +::: asab.web.WebContainer.add_preflight_handlers + From 40ee4d649ce2f6d559121d89cae3264858276880 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 7 Aug 2023 13:25:57 +0200 Subject: [PATCH 135/154] Add docstring to asab.Config --- asab/config.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/asab/config.py b/asab/config.py index d9fdb0a52..c010af57f 100644 --- a/asab/config.py +++ b/asab/config.py @@ -373,6 +373,15 @@ def before_read(self, parser, section, option, value): Config = ConfigParser(interpolation=_Interpolation()) +""" +Object for accessing the configuration of the ASAB application. + +Examples: + +```python +my_conf_value = asab.Config['section_name']['key'] +``` +""" class Configurable(object): From 5d4e565254b56c6be4a9984213b46a5500ee011d Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 7 Aug 2023 13:26:36 +0200 Subject: [PATCH 136/154] Proofreading --- docs/reference/config/reference.md | 42 ++++++++---------- docs/reference/logging/reference.md | 67 +++++++++++++++-------------- 2 files changed, 53 insertions(+), 56 deletions(-) diff --git a/docs/reference/config/reference.md b/docs/reference/config/reference.md index a98bc0513..e6ce906a3 100644 --- a/docs/reference/config/reference.md +++ b/docs/reference/config/reference.md @@ -12,20 +12,20 @@ app = asab.Application() #(1)! my_conf_value = asab.Config['section_name']['key1'] #(2)! ``` -1. Initializes application object and hence the configuration. -2. You can access the configuration values anywhere. +1. Configuration is initialized during the application [init-time](/reference/application/reference/init-time). +2. You can access the configuration values from anywhere in the code. ## Based on ConfigParser object -`asab.Config` is inherited from [`configparser.ConfigParser` class](https://docs.python.org/3/library/configparser.html#customizing-parser-behaviour) -which implements a basic configuration language that provides a structure similar to what's found in Microsoft Windows INI files. +`asab.Config` is an instance of [`asab.config.ConfigParser`](#asab.config.Configparser) class, derived from the Python standard [`configparser.ConfigParser`](https://docs.python.org/3/library/configparser.html#customizing-parser-behaviour). +The class implements a basic configuration language that provides a structure similar to what's found in Microsoft Windows INI files. !!! example "Basic usage:" - Example of the configuration file: + This is an example of the configuration file. We hope that it might help you to quickly understand what the rules are: - ``` ini + ``` ini title='configuration.conf' [section name] key=value keys can contain spaces = values can contain spaces @@ -34,6 +34,8 @@ which implements a basic configuration language that provides a structure simila as well as: colons extra spaces are : removed + be careful: 'quotes are parsed as quotes' + [another section] final answer = 42 are you sure = true @@ -82,14 +84,16 @@ which implements a basic configuration language that provides a structure simila I sleep all night and I work all day ``` + However, there are some configurable options where the newline is used as a separator, see [](). + ## Loading configuration from a file If a configuration file name is specified,the configuration is automatically -loaded from a configuration file during [initialization time of `Application`](../../application/reference/#init-time). -There are three ways how to include a configuration file: +loaded from a configuration file during [the Application init-time](../../application/reference/#init-time). +There are two ways to include a configuration file: -1. by specifying the `-c` command-line argument: +1. by using the `-c` command-line argument: ``` shell python3 my_app.py -c ./etc/sample.conf @@ -103,22 +107,11 @@ There are three ways how to include a configuration file: python3 my_app.py ``` -3. by setting the variable during the init-time: - - ```python - class MyApplication(asab.Application) - async def initialize(self): - asab.Config["general"]["config_file"] = "./etc/sample.conf" - ``` - - - ### Including other configuration files You can specify one or more additional configuration files that are -loaded and merged from an main configuration file. -It is done by `[general] include` configuration value. +loaded and merged from an main configuration file: ``` ini [general] @@ -128,7 +121,9 @@ include=./etc/site.conf:./etc/site.d/*.conf Multiple paths are separated by [`os.pathsep`](https://docs.python.org/3/library/os.html?highlight=os%20pathsep#os.pathsep) value, which is `:` on Unix and `;` on Windows. The path can be specified as a glob (e.g. use of `*` and `?` wildcard characters), it will be expanded by [`glob` module](https://docs.python.org/3/library/glob.html?highlight=glob#module-glob). -Included configuration files may not exists, this situation is silently ignored. + +!!! warning + If the additional configuration files do not exist, the situation is ignored silently! You can also use a multiline configuration entry: @@ -141,7 +136,7 @@ include= ### Including ZooKeeper node in the configuration -The separator between includes is newline or space - it means that space MUST NOT be in the names of nodes in the ZooKeeper. +The separator between includes is newline or space - it means that the space character *must not* be in the names of nodes in the ZooKeeper. The ZooKeeper node can contain a configuration file in .conf, .json or .yaml format. @@ -247,6 +242,7 @@ they are not repeated in many sections of the config file(s). | `THIS_DIR` | Directory that contains a current configuration file. | | `HOSTNAME` | The application hostname. | +::: asab.Config ::: asab.config.ConfigParser diff --git a/docs/reference/logging/reference.md b/docs/reference/logging/reference.md index 162e46ae1..593b53d1a 100644 --- a/docs/reference/logging/reference.md +++ b/docs/reference/logging/reference.md @@ -79,33 +79,39 @@ Level | Numeric value | Syslog Severity level | ## Verbose mode -The command-line argument `-v` enables verbose logging. It means that -log entries with levels `DEBUG` and `INFO` will be visible. It also -enables `asyncio` debug logging. - -The actual verbose mode is available at `asab.Config["logging"]["verbose"]` boolean option. +By default, only logs with the level bigger than 20 are visible, so `DEBUG` and `INFO` levels are not displayed. For accessing these levels, the application must be started with the **verbose mode**. This is done by the command-line argument `-v`. !!! example - There are three options to display `DEBUG` and `INFO` log messages. + There are three ways to display `DEBUG` and `INFO` log messages. + + 1. By enabling the verbose mode with command-line argument: + + ```shell + python3 myapp.py -v + ``` + + 2. By accessing the `asab.Config["logging"]["verbose"]` boolean option: - 1. ```ini [logging] verbose = true ``` + The string `true` is interpreted by `ConfigParser` via [`this method`](#asab.utils.string_to_boolean). - 2. + 3. By setting the logging level directly: + ```ini [logging] level = DEBUG ``` - 3. - ```shell - python3 myapp.py -v - ``` + +!!! note + + The verbose mode also enables `asyncio` and Zookeeper debug logging. + ## Structured data @@ -147,13 +153,19 @@ ASAB supports a structured data to be added to a log entry. Structured data are 27-Jul-2023 16:54:22.311522 ERROR myapp.mymodule [sd a="24" b="0"] Division by zero. ``` +## Logging to console + +ASAB application will log to the console only if it detects that it is running on the terminal +(using [`os.isatty()`](https://www.w3schools.com/python/ref_os_isatty.asp) function) or if the +environment variable `ASABFORCECONSOLE` is set to `1`. This is useful setup for eg. PyCharm. + + ## Logging to a file -The command-line argument `-l` on command-line enables logging to file. -Also non-empty `path` option in the section `[logging:file]` of -configuration file enables logging to file as well. +The command-line argument `-l` enables logging to a file. +Also non-empty `path` option in the section `[logging:file]` of the configuration file enables logging to a file as well. -!!! example "Example of the configuration file section:" +!!! example "Example of the configuration section:" ```ini [logging:file] @@ -179,29 +191,18 @@ configuration file enables logging to file as well. different folders, which is an intended behavior, since race conditions may occur when different application instances log into the same file. -## Logging to console - - -ASAB will log to the console only if it detects that it runs in the -foreground respectively on the terminal using `os.isatty` or if the -environment variable `ASABFORCECONSOLE` is set to `1`. This is useful -setup for eg. PyCharm. - ## Log rotation ASAB supports a [log rotation](https://en.wikipedia.org/wiki/Log_rotation). -The log rotation is triggered by a UNIX signal `SIGHUP`, which can be used e.g. to -integrate with `logrotate` utility. It is implemented using -[`logging.handlers.RotatingFileHandler` from a Python standard library](https://docs.python.org/3/library/logging.handlers.html#baserotatinghandler). +The log rotation is triggered by a UNIX signal `SIGHUP`, which can be used e.g. to integrate with `logrotate` utility. +It is implemented using [`logging.handlers.RotatingFileHandler`](https://docs.python.org/3/library/logging.handlers.html#baserotatinghandler) from the Python standard library. Also, a time-based log rotation can be configured using `rotate_every` option. -- `backup_count` specifies a number of old files to be kept prior their removal. -The system will save old log files by appending the extensions '.1', '.2' etc., to the filename. +| Option | Meaning | +| --- | --- | +| `backup_count` | A number of old files to be kept prior their removal. The system will save old log files by appending the extensions '.1', '.2' etc., to the filename. | +| `rotate_every` | Time interval of a log rotation. Default value is empty string, which means that the time-based log rotation is disabled. The interval is specified by an integer value and an unit, e.g. 1d (for 1 day) or 30M (30 minutes). Known units are `H` for hours, `M` for minutes, `d` for days and `s` for seconds.| -- `rotate_every` specifies an time interval of a log rotation. -Default value is empty string, which means that the time-based log rotation is disabled. -The interval is specified by an integer value and an unit, e.g. 1d (for 1 day) or 30M (30 minutes). -Known units are `H` for hours, `M` for minutes, `d` for days and `s` for seconds. ## Logging to syslog From 61cd89103c764986291d709a55de865af5b77041 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 7 Aug 2023 13:47:37 +0200 Subject: [PATCH 137/154] Enhance web server section --- docs/reference/web/web-server.md | 17 +++++++++-------- mkdocs.yml | 10 +++++----- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/reference/web/web-server.md b/docs/reference/web/web-server.md index ef9751622..5118e802c 100644 --- a/docs/reference/web/web-server.md +++ b/docs/reference/web/web-server.md @@ -1,12 +1,17 @@ -# The web server +# Web server -ASAB provides a web server in a `asab.web` module. -This module offers an integration of [`aiohttp` web server](http://aiohttp.readthedocs.io/en/stable/web.html). +For starting, accessing and manipulating of a web server, ASAB provides `asab.web` module together with `asab.WebService` and `asab.web.WebContainer`. +This module offers an integration of [`aiohttp` web server](http://aiohttp.readthedocs.io/en/stable/web.html). It is possible to run multiple web servers from one application. The configuration for each server is stored in dedicated **web container**. **Web Service** registers these containers and runs the servers. !!! tip For a quick start, we recommend reading the official `aiohttp` tutorial on [how to run a simple web server](https://docs.aiohttp.org/en/stable/web_quickstart.html#run-a-simple-web-server). +In order to use ASAB Web Service, first make sure that you have `aiohttp` module installed: +``` shell +python3 -m pip install aiohttp +``` + ## Handlers, routes and resources `aiohttp` servers use the concept of Handlers, Routes and Resources. Here we provide a very quick explanation that should help you to get into the terminology. @@ -31,12 +36,8 @@ This module offers an integration of [`aiohttp` web server](http://aiohttp.readt - **Resource** is an entry in route table which corresponds to requested URL. Resource in turn has at least one route. When you add a route, the resource object is created under the hood. -## Creating a web server +## Running a simple web server -First make sure that you have `aiohttp` module installed: -``` shell -python3 -m pip install aiohttp -``` !!! example "Creating a web server 1: One method does it all!" diff --git a/mkdocs.yml b/mkdocs.yml index 91ada6617..beef515d4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -163,16 +163,16 @@ nav: - Application: reference/application/reference.md - Modules and Services: reference/modules_services/reference.md - - Web Server: - - Creating a web server: reference/web/web-server.md + - Web Service: + - Web server: reference/web/web-server.md - TLS/SSL: reference/web/tls.md - Authorization and multitenancy: reference/web/authorization_multitenancy.md - Cross-Origin Resource Sharing: reference/web/cors.md - Configuration: reference/config/reference.md - Logging: reference/logging/reference.md - - Library: reference/library/reference.md - - Metrics: + - Library Service: reference/library/reference.md + - Metrics Service: - MetricsService: reference/metrics/service.md - Gauge: reference/metrics/gauge.md - Counter: reference/metrics/counter.md @@ -183,7 +183,7 @@ nav: - CounterWithDynamicTags: reference/metrics/counter_with_dynamic_tags.md - AggregationCounterWithDynamicTags: reference/metrics/aggregation_counter_with_dynamic_tags.md - HistogramWithDynamicTags: reference/metrics/histogram_with_dynamic_tags.md - - Storage: + - Storage Service: - StorageService: reference/storage/service.md - Upsertor: reference/storage/upsertor.md - Exceptions: reference/storage/exceptions.md From a10a5b1fe088c2a8595acbe42a921678ea751288 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 7 Aug 2023 15:13:01 +0200 Subject: [PATCH 138/154] Create PubSub section --- docs/reference/pubsub/reference.md | 221 +++++++++++++++++++++++++++++ mkdocs.yml | 1 + 2 files changed, 222 insertions(+) create mode 100644 docs/reference/pubsub/reference.md diff --git a/docs/reference/pubsub/reference.md b/docs/reference/pubsub/reference.md new file mode 100644 index 000000000..499a96e76 --- /dev/null +++ b/docs/reference/pubsub/reference.md @@ -0,0 +1,221 @@ +# Publish-Subscribe + +Publish-subscribe is a messaging pattern where senders of messages, called **publishers**, +send the messages to receivers, called **subscribers**, via PubSub message bus. +Publishers don't directly interact with subscribers in any way. +Similarly, subscribers express interest in one or more message types and only receive messages that are of interest, +without knowledge of which publishers, if any, there are. + +ASAB `PubSub` operates with a simple messages, defined by their *message type*, which is a string. +We recommend to add `!` (an exclamation mark) at the end of the message type in order to distinguish this object from +other types such as Python class names or functions. +Example of the message type is e.g. `Application.run!` or `Application.tick/600!`. + +The message can carry an optional positional and keyword arguments. +The delivery of a message is implemented as a the standard Python function. + +!!! note + There is an default, application-wide Publish-Subscribe message + bus at `Application.PubSub` that can be used to send messages. + Alternatively, you can create your own instance of `PubSub` and enjoy isolated PubSub delivery space. + +## Subscription + +The method `PubSub.subscribe()` subscribes to a message type. Messages will be delivered to a `callback` callable (function or method). +The `callback` can be a standard callable or an `async` coroutine. +Asynchronous `callback` means that the delivery of the message will happen in a `Future`, asynchronously. + +`Callback` callable will be called with the first argument. + +!!! example + + Example of a subscription to an `Application.tick!` messages: + + ``` python + class MyClass(object): + def __init__(self, app): + app.PubSub.subscribe("Application.tick!", self.on_tick) + + def on_tick(self, message_type): + print(message_type) + ``` + +!!! example + + Asynchronous version of the above: + + ``` python + class MyClass(object): + def __init__(self, app): + app.PubSub.subscribe("Application.tick!", self.on_tick) + + async def on_tick(self, message_type): + await asyncio.sleep(5) + print(message_type) + ``` + +To simplify the process of subscription to `PubSub`, ASAB offers the decorator-based *"subscribe all"* functionality. + +!!! example + + In the following example, both `on_tick()` and `on_exit()` methods are subscribed to `Application.PubSub` message bus. + + ``` python + class MyClass(object): + def __init__(self, app): + app.PubSub.subscribe_all(self) + + @asab.subscribe("Application.tick!") + async def on_tick(self, message_type): + print(message_type) + + @asab.subscribe("Application.exit!") + def on_exit(self, message_type): + print(message_type) + ``` + +Unsubscribe from a message delivery. + +asab.Subscriber + +The subscriber object can be also used as [an asynchonous +generator]{.title-ref}. The example of the subscriber object usage in +[async for]{.title-ref} statement: + +``` python +async def my_coroutine(self): + # Subscribe for a two application events + subscriber = asab.Subscriber( + self.PubSub, + "Application.tick!", + "Application.exit!" + ) + async for message_type, args, kwargs in subscriber: + if message_type == "Application.exit!": + break; + print("Tick.") +``` + +## Publishing + +Publish a message to the PubSub message bus. It will be delivered to +each subscriber synchronously. It means that the method returns after +each subscribed `callback` is called. + +The example of a message publish to the +`Application.PubSub`{.interpreted-text role="any"} message bus: + +``` python +def my_function(app): + app.PubSub.publish("mymessage!") +``` + +Asynchronous publishing of a message is requested by +`asynchronously=True` argument. The `publish()` method returns +immediately and the delivery of the message to subscribers happens, +when control returns to the event loop. + +The example of a **asynchronous version** of a message publish to the +`Application.PubSub`{.interpreted-text role="any"} message bus: + +``` {.python} +def my_function(app): + app.PubSub.publish("mymessage!", asynchronously=True) +``` + +## Synchronous vs. asynchronous messaging + +ASAB PubSub supports both modes of a message delivery: synchronous and +asynchronous. Moreover, PubSub also deals with modes, when asynchronous +code (coroutine) does publish to synchronous code and vice versa. + +| | Synchronous publish | Asynchronous publish | +| --- | --- | --- | +| Synchronous subscribe | called immediately | `call_soon()` | +| Asynchronous subscribe | `ensure_future()` | `call_soon()` and `ensure_future()` | + + +## Application-wide PubSub + +The ASAB provides the application-wide Publish-Subscribe message bus. + +### Well-Known Messages + +ASAB itself publishes various well-known messages published on `Application.PubSub`: + +| Message | Published when... | +| ---: | --- | +| **Application.init!** | ...the application is in the [init-time](/reference/application/reference/#init-time) after the configuration is loaded, logging is setup, the event loop is constructed etc. | +| **Application.run!** | ...the application enters the [run-time](/reference/application/reference/#run-time). | +| **Application.stop!** | ...the application wants to stop the [run-time](/reference/application/reference/#run-time). It can be sent multiple times because of a process of graceful run-time termination. The first argument of the message is a counter that increases with every **Application.stop!** event. | +| **Application.exit!** | ...the application enters the [exit-time](/reference/application/reference/#exit-time). | +| **Application.hup!** | ...the application receives UNIX signal `SIGHUP` or equivalent.| +| **Application.housekeeping!** | ...the application is on the time for [housekeeping](#housekeeping). | +| Tick messages | ...periodically with the specified tick frequency. | + +### Tick messages + +Tick messages are published by the application periodically. +For example, **Application.tick!** is published every tick, **Application.tick/10!** is published every 10th tick etc. +The tick frequency is configurable to whole seconds, the default is *1 second*. + +```ini +[general] +# tick every 3 seconds +tick_period = 3 +``` + +| Message | Default period | +| ---: | --- | +| **Application.tick!** | Every second. | +| **Application.tick/10!** | Every 10 seconds. | +| **Application.tick/60!** | Every minute. | +| **Application.tick/300!** | Every 5 minutes. | +| **Application.tick/600!** | Every 10 minutes. | +| **Application.tick/1800!** | Every 30 minutes. | +| **Application.tick/3600!** | Every hour. | +| **Application.tick/43200!** | Every 12 hours. | +| **Application.tick/86400!** | Every 24 hours. | + + +### Housekeeping + +Housekeeping is intended for scheduled processes that run once a day, e.g. for cleaning server databases. + +```python +app.PubSub.subscribe("Application.housekeeping!", clean_recycle_bin) + +def clean_recycle_bin(msg): + ... +``` + +The application checks every ten minutes if it's time for housekeeping. +If the UTC time reaches the value for housekeeping, the app will publish **Application.housekeeping!** +and schedules the next housekeeping for tomorrow at the same time. +There is also a time limit, which is set to 05:00 AM UTC by default. + +By default, the time for housekeeping is set to 03:00 AM UTC and the limit to 05:00 AM UTC. + + +Housekeeping can be also configured to run during the application [init-time](/reference/application/reference/#init-time). +Housekeeping time, time limit and housekeeping at startup can be changed in the configuration file: + +``` ini +[housekeeping] +at=19:30 +limit=21:00 +run_at_startup=yes +``` + +This sets the housekeeping time to 7:30 PM UTC and the time limit to 9:00 PM UTC. +The time must be written in the format 'HH:MM'. +Remind yourself that the time is set to UTC, so you should be careful when operating in a different timezone. + +!!! note + + If the computer is in a sleep state, housekeeping will not be performed. + Then, when the computer is reawakened again, it will check if it has exceeded the time limit. + If not, then housekeeping will be published. If it has exceeded it, it simply informs the user and sets the housekeeping time for the next day. + Note that this only limits the time when the housekeeping can start. + If the housekeeping event triggers a procedure that takes a long time to finish, it will not be terminated when the time limit is reached. + diff --git a/mkdocs.yml b/mkdocs.yml index beef515d4..592b4c637 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -171,6 +171,7 @@ nav: - Configuration: reference/config/reference.md - Logging: reference/logging/reference.md + - PubSub: reference/pubsub/reference.md - Library Service: reference/library/reference.md - Metrics Service: - MetricsService: reference/metrics/service.md From f2856a1a39e8cfbe793ff7df2fb2c9e29d7a6a6c Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 7 Aug 2023 17:16:10 +0200 Subject: [PATCH 139/154] Modify PubSub docstrings --- asab/pubsub.py | 227 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 164 insertions(+), 63 deletions(-) diff --git a/asab/pubsub.py b/asab/pubsub.py index 6bc5cb095..3190b845b 100644 --- a/asab/pubsub.py +++ b/asab/pubsub.py @@ -2,12 +2,18 @@ import asyncio import weakref import functools +import typing L = logging.getLogger(__name__) class PubSub(object): + """ + Object for delivering messages across the ASAB application. + + A message is a function or coroutine with specific `message_type` that can be published and subscribed at various places in the code. + """ def __init__(self, app): @@ -15,10 +21,24 @@ def __init__(self, app): self.Loop = app.Loop - def subscribe(self, message_type, callback): + def subscribe(self, message_type: str, callback: typing.Callable): """ - Subscribe a subscriber to the an message type. - It could be even plain function, method or its coroutine variant (then it will be delivered in a dedicated future) + Set `callback` that will be called when `message_type` is received. + + Args: + message_type: Message to be subscribed to. It should end with an exclamation mark `"!"`. + callback: Function or coroutine that is called when the message is received. `message_type` is passed as the first argument to the callback. + + Examples: + + ```python + class MyClass: + def __init__(self, app): + app.PubSub.subscribe("Application.tick!", self.on_tick) + + def on_tick(self, message_type): + print(message_type) + ``` """ # If subscribe is a bound method, do special treatment @@ -36,7 +56,23 @@ def subscribe(self, message_type, callback): def subscribe_all(self, obj): """ - Find all @asab.subscribe decorated methods on the obj and do subscription + Find all methods decorated by `@asab.subscribe` on the object and subscribe for them. + + Examples: + + ```python + class MyClass: + def __init__(self, app): + app.PubSub.subscribe_all(self) + + @asab.subscribe("Application.tick!") + async def on_tick(self, message_type): + print(message_type) + + @asab.subscribe("Application.exit!") + def on_exit(self, message_type): + print(message_type) + ``` """ for member_name in dir(obj): member = getattr(obj, member_name) @@ -47,8 +83,23 @@ def subscribe_all(self, obj): def unsubscribe(self, message_type, callback): - """ Remove a subscriber of an message type from the set. """ + """ + Remove `callback` from the subscribed `message_type`. + + When the subscription does not exist, warning is displayed. + + Examples: + + ```python + class MyClass: + def __init__(self, app): + app.PubSub.subscribe("Application.tick!", self.only_once) + def only_once(self, message_type): + print("This message is displayed only once!") + app.PubSub.unsubscribe("Application.tick!", self.only_once) + ``` + """ callback_list = self.Subscribers.get(message_type) if callback_list is None: L.warning("Message type subscription '{}'' not found.".format(message_type)) @@ -113,9 +164,33 @@ def _deliver_async(loop, callback, message_type, *args, **kwargs): callback_list.remove(callback_ref) - def publish(self, message_type, *args, **kwargs): + def publish(self, message_type: str, *args, **kwargs): """ - Notify subscribers of an `message type`. Including arguments. + Publish the message and notify the subscribers of an `message type`. + + `message_type` is passed as the first argument to the subscribed callback. + + Args: + message_type: The emitted message. + asynchronously (bool, optional): If `True`, `call_soon()` method will be used for the asynchronous delivery of the message. Defaults to `False`. + + Examples: + + ```python + class MyApplication(asab.Application): + async def initialize(self): + self.Count = 0 + self.PubSub.subscribe("Fireworks.started!", self.on_fireworks) + + async def main(self): + for i in range(3): + self.Count += 1 + self.PubSub.publish("Fireworks.started!", self.Count) + await asyncio.sleep(1) + + def on_fireworks(self, message_type, count): + print("boom " * count) + ``` """ asynchronously = kwargs.pop('asynchronously', False) @@ -132,44 +207,62 @@ def publish(self, message_type, *args, **kwargs): L.exception("Error in a PubSub callback", struct_data={'message_type': message_type}) - def publish_threadsafe(self, message_type, *args, **kwargs): + def publish_threadsafe(self, message_type: str, *args, **kwargs): """ - Notify subscribers of an `message type` safely form a different that main thread. + Publish the message and notify the subscribers of an `message type` safely form a different that main thread. + + `message_type` is passed as the first argument to the subscribed callback. + + Args: + message_type: The emitted message. + asynchronously (bool, optional): If `True`, `call_soon()` method will be used for the asynchronous delivery of the message. Defaults to `False`. """ def in_main_thread(): self.publish(message_type, *args, **kwargs) self.Loop.call_soon_threadsafe(in_main_thread) - async def message(self, message_type): - ''' - This method allows to await a specific message from a coroutine. - It is a convenience method for `Subscriber` object. + async def message(self, message_type: str) -> tuple: + """ + Await specific message from a coroutine. It is a convenience method for the `Subscriber` object. - Usage: - ``` - message_type, args, kwargs = await self.PubSub.message("Library.ready!") - ``` + Args: + message_type: Message to be awaited. + + Returns: + Triple (message_type, args, kwargs). - `message_type`, `args` and `kwargs` are the same as in PubSub callback. + Examples: - ''' + ```python + message_type, args, kwargs = await self.PubSub.message("Library.ready!") + ``` + """ subscriber = Subscriber(self, message_type) message_type, args, kwargs = await subscriber.message() return message_type, args, kwargs class subscribe(object): + """ + Decorator function that simplifies the process of subscription together with `PubSub.subscribe_all()` method. + + Examples: + ```python + class MyClass(object): + def __init__(self, app): + app.PubSub.subscribe_all(self) - ''' - Decorator + @asab.subscribe("Application.tick!") + async def on_tick(self, message_type): + print(message_type) - Usage: + @asab.subscribe("Application.exit!") + def on_exit(self, message_type): + print(message_type) + ``` + """ - @asab.subscribe("tick") - def on_tick(self, message_type): - print("Service tick") - ''' def __init__(self, message_type): self.message_type = message_type @@ -184,21 +277,31 @@ def __call__(self, f): class Subscriber(object): + """ + Object for consuming PubSub messages in coroutines. - ''' -:any:`Subscriber` object allows to consume PubSub messages in coroutines. -It subscribes for various message types and consumes them. -It works on FIFO basis (First message In, first message Out). -If ``pubsub`` argument is None, the initial subscription is skipped. + It subscribes for various message types and consumes them. + It is built on (first-in, first-out) basis. + If `pubsub` argument is `None`, the initial subscription is skipped. -.. code:: python + Examples: - subscriber = asab.Subscriber( - app.PubSub, - "Application.tick!", - "Application.stop!" - ) - ''' + The example of the subscriber object usage in async for statement: + + ```python + async def my_coroutine(self): + # Subscribe for two application events + subscriber = asab.Subscriber( + self.PubSub, + "Application.tick!", + "Application.exit!" + ) + async for message_type, args, kwargs in subscriber: + if message_type == "Application.exit!": + break; + print("Tick.") + ``` + """ def __init__(self, pubsub=None, *message_types): @@ -211,9 +314,9 @@ def __init__(self, pubsub=None, *message_types): def subscribe(self, pubsub, message_type): - ''' -Subscribe for more message types. This method can be called many times with various ``pubsub`` objects. - ''' + """ + Subscribe for more message types. This method can be called many times with various `pubsub` objects. + """ pubsub.subscribe(message_type, self) self._subscriptions.append((pubsub, message_type)) @@ -223,28 +326,26 @@ def __call__(self, message_type, *args, **kwargs): def message(self): - ''' -Wait for a message asynchronously. -Returns a three-members tuple ``(message_type, args, kwargs)``. - -Example of the `await message()` use: - -.. code:: python - - async def my_coroutine(app): - # Subscribe for a two application events - subscriber = asab.Subscriber( - app.PubSub, - "Application.tick!", - "Application.exit!" - ) - while True: - message_type, args, kwargs = await subscriber.message() - if message_type == "Application.exit!": - break - print("Tick.") - - ''' + """ + Wait for a message asynchronously and return triple `(message_type, args, kwargs)`. + + Examples: + + ```python + async def my_coroutine(app): + # Subscribe for a two application events + subscriber = asab.Subscriber( + app.PubSub, + "Application.tick!", + "Application.exit!" + ) + while True: + message_type, args, kwargs = await subscriber.message() + if message_type == "Application.exit!": + break + print("Tick.") + ``` + """ return self._q.get() From 9bf9d45c45c0507d444b5db3d1ab3c6be3e9e689 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Mon, 7 Aug 2023 17:16:21 +0200 Subject: [PATCH 140/154] Add reference --- docs/reference/pubsub/reference.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/reference/pubsub/reference.md b/docs/reference/pubsub/reference.md index 499a96e76..444308073 100644 --- a/docs/reference/pubsub/reference.md +++ b/docs/reference/pubsub/reference.md @@ -32,7 +32,7 @@ Asynchronous `callback` means that the delivery of the message will happen in a Example of a subscription to an `Application.tick!` messages: ``` python - class MyClass(object): + class MyClass: def __init__(self, app): app.PubSub.subscribe("Application.tick!", self.on_tick) @@ -45,12 +45,13 @@ Asynchronous `callback` means that the delivery of the message will happen in a Asynchronous version of the above: ``` python - class MyClass(object): + class MyClass: def __init__(self, app): app.PubSub.subscribe("Application.tick!", self.on_tick) async def on_tick(self, message_type): - await asyncio.sleep(5) + print("Wait for it...") + await asyncio.sleep(3.0) print(message_type) ``` @@ -61,7 +62,7 @@ To simplify the process of subscription to `PubSub`, ASAB offers the decorator-b In the following example, both `on_tick()` and `on_exit()` methods are subscribed to `Application.PubSub` message bus. ``` python - class MyClass(object): + class MyClass: def __init__(self, app): app.PubSub.subscribe_all(self) @@ -219,3 +220,12 @@ Remind yourself that the time is set to UTC, so you should be careful when opera Note that this only limits the time when the housekeeping can start. If the housekeeping event triggers a procedure that takes a long time to finish, it will not be terminated when the time limit is reached. +## Reference: + +::: asab.pubsub.PubSub + +::: asab.pubsub.Subscriber + +::: asab.pubsub.subscribe + + From ed7f731e283dc2022a3fa8f323afe9aa899d5ca8 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 8 Aug 2023 09:26:55 +0200 Subject: [PATCH 141/154] Add getmultiline method --- asab/config.py | 38 +++++++++++++++++++++++++++++++-- examples/config_getmultiline.py | 36 +++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 examples/config_getmultiline.py diff --git a/asab/config.py b/asab/config.py index 2e0ca6422..a69ac9b38 100644 --- a/asab/config.py +++ b/asab/config.py @@ -8,6 +8,8 @@ import urllib.parse import collections.abc +import typing + from . import utils @@ -270,7 +272,7 @@ def getseconds(self, section, option, *, raw=False, vars=None, fallback=None, ** return self._get_conv(section, option, utils.convert_to_seconds, raw=raw, vars=vars, fallback=fallback, **kwargs) - def geturl(self, section, option, raw=False, vars=None, fallback=None, scheme=None, **kwargs): + def geturl(self, section, option, *, raw=False, vars=None, fallback=None, scheme=None, **kwargs): """Gets URL from config and removes all leading and trailing whitespaces and trailing slashes. @@ -278,7 +280,39 @@ def geturl(self, section, option, raw=False, vars=None, fallback=None, scheme=No :type scheme: str, tuple :return: validated URL, raises ValueError when scheme requirements are not met if set. """ - return utils.validate_url(self.get(section, option, raw=False, vars=None, fallback=fallback), scheme) + return utils.validate_url(self.get(section, option, raw=raw, vars=vars, fallback=fallback), scheme) + + + def getmultiline(self, section, option, *, raw=False, vars=None, fallback=None, **kwargs) -> typing.List[str]: + """ + Get multiline data from config. + + Examples: + + ```ini + [places] + visited: + Praha + Brno + Ústí nad Labem + unvisited: + ``` + + ```python + >>> asab.Config.getmultiline("places", "visited") + ["Praha", "Brno", "Ústí nad Labem"] + >>> asab.Config.getmultiline("places", "unvisited") + [] + >>> asab.Config.getmultiline("places", "nonexisting", fallback=["Gottwaldov"]) + ["Gottwaldov"] + ``` + """ + values = self.get(section, option, raw=raw, vars=vars, fallback=fallback) + if isinstance(values, str): + return [item.strip() for item in values.splitlines() if len(item) > 0] + else: + # fallback can be anything + return values class _Interpolation(configparser.ExtendedInterpolation): diff --git a/examples/config_getmultiline.py b/examples/config_getmultiline.py new file mode 100644 index 000000000..741defb05 --- /dev/null +++ b/examples/config_getmultiline.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +import asab +import logging + +# + +L = logging.getLogger(__name__) + +# + +asab.Config.read_string( + """ + [places] + visited: + Praha + Brno + Ústí nad Labem + """ +) + + +class MyApplication(asab.Application): + + async def main(self): + visited = asab.Config.getmultiline("places", "visited") + unvisited = asab.Config.getmultiline("places", "unvisited", fallback=[]) + nonexisting = asab.Config.getmultiline("places", "nonexisting", fallback=["Gottwaldov"]) + L.log(asab.LOG_NOTICE, "Places I've already visited: {}".format(visited)) + L.log(asab.LOG_NOTICE, "Places I want to visit: {}".format(unvisited)) + L.log(asab.LOG_NOTICE, "Places that don't exist: {}".format(nonexisting)) + self.stop() + + +if __name__ == "__main__": + app = MyApplication() + app.run() From 347076ffa2182fde8a6292434cb60f2dcbf3d8c6 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 8 Aug 2023 10:48:26 +0200 Subject: [PATCH 142/154] Add splitting by spaces --- asab/config.py | 7 ++++--- examples/config_getmultiline.py | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/asab/config.py b/asab/config.py index a69ac9b38..b27f483f4 100644 --- a/asab/config.py +++ b/asab/config.py @@ -1,5 +1,6 @@ import os import sys +import re import glob import logging import inspect @@ -294,13 +295,13 @@ def getmultiline(self, section, option, *, raw=False, vars=None, fallback=None, visited: Praha Brno - Ústí nad Labem + Pardubice Plzeň unvisited: ``` ```python >>> asab.Config.getmultiline("places", "visited") - ["Praha", "Brno", "Ústí nad Labem"] + ["Praha", "Brno", "Pardubice", "Plzeň"] >>> asab.Config.getmultiline("places", "unvisited") [] >>> asab.Config.getmultiline("places", "nonexisting", fallback=["Gottwaldov"]) @@ -309,7 +310,7 @@ def getmultiline(self, section, option, *, raw=False, vars=None, fallback=None, """ values = self.get(section, option, raw=raw, vars=vars, fallback=fallback) if isinstance(values, str): - return [item.strip() for item in values.splitlines() if len(item) > 0] + return [item.strip() for item in re.split(r"\s+", values) if len(item) > 0] else: # fallback can be anything return values diff --git a/examples/config_getmultiline.py b/examples/config_getmultiline.py index 741defb05..087b757c3 100644 --- a/examples/config_getmultiline.py +++ b/examples/config_getmultiline.py @@ -14,7 +14,7 @@ visited: Praha Brno - Ústí nad Labem + Pardubice Plzeň """ ) From 2fc18f05936738cc9bb78da7f544900d8cd54f3e Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 8 Aug 2023 16:37:34 +0200 Subject: [PATCH 143/154] Change formatting --- docs/reference/pubsub/reference.md | 65 +++++++++++++++++------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/docs/reference/pubsub/reference.md b/docs/reference/pubsub/reference.md index 444308073..1a3245410 100644 --- a/docs/reference/pubsub/reference.md +++ b/docs/reference/pubsub/reference.md @@ -1,19 +1,29 @@ # Publish-Subscribe -Publish-subscribe is a messaging pattern where senders of messages, called **publishers**, -send the messages to receivers, called **subscribers**, via PubSub message bus. +**Publish-subscribe** is a messaging pattern where senders of messages, called **publishers**, +send the messages to receivers, called **subscribers**, via PubSub **message bus**. + Publishers don't directly interact with subscribers in any way. Similarly, subscribers express interest in one or more message types and only receive messages that are of interest, without knowledge of which publishers, if any, there are. -ASAB `PubSub` operates with a simple messages, defined by their *message type*, which is a string. -We recommend to add `!` (an exclamation mark) at the end of the message type in order to distinguish this object from -other types such as Python class names or functions. -Example of the message type is e.g. `Application.run!` or `Application.tick/600!`. - +ASAB `PubSub` module operates with a simple messages, defined by their *message type*, which is a string. The message can carry an optional positional and keyword arguments. The delivery of a message is implemented as a the standard Python function. +!!! note + We recommend to add `!` (an exclamation mark) at the end of the message type in order to distinguish this object from + other types such as Python class names or functions. + + Examples: + + - `Application.run!` + + - `Application.tick/600!` + + - `Message.received!` + + !!! note There is an default, application-wide Publish-Subscribe message bus at `Application.PubSub` that can be used to send messages. @@ -99,36 +109,35 @@ async def my_coroutine(self): ## Publishing -Publish a message to the PubSub message bus. It will be delivered to -each subscriber synchronously. It means that the method returns after -each subscribed `callback` is called. +`PubSub.publish()` publishes a message to the PubSub message bus. It will be delivered to each subscriber synchronously. +It means that the method returns after each subscribed `callback` is called. + +!!! example -The example of a message publish to the -`Application.PubSub`{.interpreted-text role="any"} message bus: + The example of a message publish to the `Application.PubSub` message bus: -``` python -def my_function(app): - app.PubSub.publish("mymessage!") -``` + ``` python + def my_function(app): + app.PubSub.publish("mymessage!") + ``` -Asynchronous publishing of a message is requested by -`asynchronously=True` argument. The `publish()` method returns -immediately and the delivery of the message to subscribers happens, +Asynchronous publishing of a message is requested by `asynchronously=True` argument. +The `publish()` method returns immediately and the delivery of the message to subscribers happens, when control returns to the event loop. -The example of a **asynchronous version** of a message publish to the -`Application.PubSub`{.interpreted-text role="any"} message bus: +!!! example -``` {.python} -def my_function(app): - app.PubSub.publish("mymessage!", asynchronously=True) -``` + The example of a **asynchronous version** of a message publish to the `Application.PubSub` message bus: + + ``` python + def my_function(app): + app.PubSub.publish("mymessage!", asynchronously=True) + ``` ## Synchronous vs. asynchronous messaging -ASAB PubSub supports both modes of a message delivery: synchronous and -asynchronous. Moreover, PubSub also deals with modes, when asynchronous -code (coroutine) does publish to synchronous code and vice versa. +ASAB PubSub supports both modes of a message delivery: synchronous and asynchronous. +Moreover, PubSub also deals with modes, when asynchronous code (coroutine) does publish to synchronous code and vice versa. | | Synchronous publish | Asynchronous publish | | --- | --- | --- | From 624cdebbef1d515c9f79293438fbb56dd2559e28 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 8 Aug 2023 16:50:38 +0200 Subject: [PATCH 144/154] Add Alert Service section --- docs/reference/alert/reference.md | 70 +++++++++++++++++++++++++++++++ mkdocs.yml | 1 + 2 files changed, 71 insertions(+) create mode 100644 docs/reference/alert/reference.md diff --git a/docs/reference/alert/reference.md b/docs/reference/alert/reference.md new file mode 100644 index 000000000..7fb70dd0a --- /dev/null +++ b/docs/reference/alert/reference.md @@ -0,0 +1,70 @@ +# Alert Service + +Integrate ASAB Application with alert managers. + +There are currently two possible target systems for the alerts +available: + +- Opsgenie - (https://www.atlassian.com/software/opsgenie) +- PagerDuty - (https://events.pagerduty.com) + +Everything you need to do is to import the service, trigger the alert +and specify the target in the configuration. + +``` python +class MyApplication(asab.Application): + async def initialize(self): + from asab.alert import AlertService + self.AlertService = AlertService(self) + self.AlertService.trigger( + source="my-tenant", + alert_cls="my-class", + alert_id="deduplication-id01", + title="Something went wrong.", + detail={ + "example1": "additional-info", + "example2": "additional-info", + }, + ) + +if __name__ == '__main__': + app = MyApplication() + app.run() +``` + +## Opsgenie + +- Create an account at Opsgenie. +- In your Opsgenie account, create a new **Team**. +- Add integration to your Team - choose **API**. +- API Key will be generated for you. + + +``` ini title='my_application.conf' +[asab:alert:opsgenie] +api_key=my-api-key +tags=my-tag, my-application +url=https://api.eu.opsgenie.com # this is default value +``` + +## PagerDuty + +- Create an account at PagerDuty. +- In your PagerDuty account, generate **Api Key** (Integrations > Developer Tools > Api Access Keys). +- Create a new Service in Service Directory and add integration in the Integrations folder. +- Choose **Events API V2**. An **Integration Key** will be generated for you. + +``` ini title='my_application.conf' +[asab:alert:pagerduty] +api_key=my-api-key +integration_key=my-integration-key +url=https://events.pagerduty.com # this is default value +``` + +## De-duplication + +`alert_id` argument serves as a de-duplication ID for the third-party services. +It enables the grouping of alerts and prevents noise. More about alert grouping: + +- Opsgenie: (https://support.atlassian.com/opsgenie/docs/what-is-alert-de-duplication) +- PagerDuty: (https://support.pagerduty.com/docs/intelligent-alert-grouping) diff --git a/mkdocs.yml b/mkdocs.yml index 592b4c637..62e69102f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -191,6 +191,7 @@ nav: - ElasticSearch: reference/storage/elasticsearch.md - MongoDB: reference/storage/mongodb.md - In-Memory: reference/storage/inmemory.md + - Alert Service: reference/alert/reference.md - Utility functions and classes: - Utility functions: reference/utils/utils.md - Persistent dictionary: reference/utils/persistent_dictionary.md From 0e2f48403886432c8fa6a9aa283c053f8f09f084 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 8 Aug 2023 17:23:52 +0200 Subject: [PATCH 145/154] Add reference for Storage --- docs/reference/storage/elasticsearch.md | 1 - docs/reference/storage/exceptions.md | 1 - docs/reference/storage/inmemory.md | 1 - docs/reference/storage/mongodb.md | 1 - docs/reference/storage/reference.md | 309 +++++++++++++++ docs/reference/storage/service.md | 1 - docs/reference/storage/upsertor.md | 1 - docs/topics/admin/command-line.md | 76 ---- docs/topics/admin/systemd.md | 39 -- docs/topics/asab/alert.md | 83 ---- docs/topics/asab/config.md | 243 ------------ docs/topics/asab/library.md | 360 ------------------ docs/topics/asab/log.md | 243 ------------ docs/topics/asab/module.md | 53 --- docs/topics/asab/pubsub.md | 280 -------------- docs/topics/asab/service.md | 53 --- docs/topics/asab/storage/elasticsearch.md | 28 -- docs/topics/asab/storage/encryption.md | 105 ----- docs/topics/asab/storage/inmemory.md | 24 -- docs/topics/asab/storage/intro.md | 44 --- .../storage/manipulation_with_databases.md | 107 ------ docs/topics/asab/storage/mongodb.md | 50 --- docs/topics/asab/various.md | 51 --- docs/topics/asab/web/auth.md | 18 - docs/topics/asab/web/cors.md | 23 -- docs/topics/asab/web/index.md | 148 ------- docs/topics/asab/web/restapidocs.md | 141 ------- docs/topics/asab/zookeeper.md | 190 --------- mkdocs.yml | 9 +- 29 files changed, 310 insertions(+), 2373 deletions(-) delete mode 100644 docs/reference/storage/elasticsearch.md delete mode 100644 docs/reference/storage/exceptions.md delete mode 100644 docs/reference/storage/inmemory.md delete mode 100644 docs/reference/storage/mongodb.md create mode 100644 docs/reference/storage/reference.md delete mode 100644 docs/reference/storage/service.md delete mode 100644 docs/reference/storage/upsertor.md delete mode 100644 docs/topics/admin/command-line.md delete mode 100644 docs/topics/admin/systemd.md delete mode 100644 docs/topics/asab/alert.md delete mode 100644 docs/topics/asab/config.md delete mode 100644 docs/topics/asab/library.md delete mode 100644 docs/topics/asab/log.md delete mode 100644 docs/topics/asab/module.md delete mode 100644 docs/topics/asab/pubsub.md delete mode 100644 docs/topics/asab/service.md delete mode 100644 docs/topics/asab/storage/elasticsearch.md delete mode 100644 docs/topics/asab/storage/encryption.md delete mode 100644 docs/topics/asab/storage/inmemory.md delete mode 100644 docs/topics/asab/storage/intro.md delete mode 100644 docs/topics/asab/storage/manipulation_with_databases.md delete mode 100644 docs/topics/asab/storage/mongodb.md delete mode 100644 docs/topics/asab/various.md delete mode 100644 docs/topics/asab/web/auth.md delete mode 100644 docs/topics/asab/web/cors.md delete mode 100644 docs/topics/asab/web/index.md delete mode 100644 docs/topics/asab/web/restapidocs.md delete mode 100644 docs/topics/asab/zookeeper.md diff --git a/docs/reference/storage/elasticsearch.md b/docs/reference/storage/elasticsearch.md deleted file mode 100644 index 9cfe8c5ef..000000000 --- a/docs/reference/storage/elasticsearch.md +++ /dev/null @@ -1 +0,0 @@ -::: asab.storage.elasticsearch.StorageService \ No newline at end of file diff --git a/docs/reference/storage/exceptions.md b/docs/reference/storage/exceptions.md deleted file mode 100644 index 3ceeb8c23..000000000 --- a/docs/reference/storage/exceptions.md +++ /dev/null @@ -1 +0,0 @@ -::: asab.storage.exceptions \ No newline at end of file diff --git a/docs/reference/storage/inmemory.md b/docs/reference/storage/inmemory.md deleted file mode 100644 index 6898d373c..000000000 --- a/docs/reference/storage/inmemory.md +++ /dev/null @@ -1 +0,0 @@ -::: asab.storage.inmemory.StorageService \ No newline at end of file diff --git a/docs/reference/storage/mongodb.md b/docs/reference/storage/mongodb.md deleted file mode 100644 index 289005905..000000000 --- a/docs/reference/storage/mongodb.md +++ /dev/null @@ -1 +0,0 @@ -::: asab.storage.mongodb.StorageService \ No newline at end of file diff --git a/docs/reference/storage/reference.md b/docs/reference/storage/reference.md new file mode 100644 index 000000000..0f792b55c --- /dev/null +++ b/docs/reference/storage/reference.md @@ -0,0 +1,309 @@ +# Storage Service + +The ASAB's Storage Service supports data storage in-memory or in dedicated document databases, including +[MongoDB](https://www.mongodb.com/) and [ElasticSearch](https://www.elastic.co/). + +## Configuration + +First, specify the storage type in the configuration. The options for the storage type are: + +- `inmemory`: Collects data directly in memory +- `mongodb`: Collects data using MongoDB database. Depends on [pymongo](https://pymongo.readthedocs.io/en/stable/) and + [motor](https://motor.readthedocs.io/en/stable/api-asyncio/asyncio_motor_collection.html) libraries. +- `elasticsearch`: Collects data using ElasticSearch database. Depends on [aiohttp](https://docs.aiohttp.org/en/latest/) library. + +Storage Service provides a unified interface for accessing and +manipulating collections across multiple database technologies. + +``` ini +[asab:storage] +type=mongodb +``` + +For accessing the storage, simply add `asab.storage.Module` when initializing and register the +service. + +``` python +class MyApplication(asab.Application): + + async def initialize(self): + + self.add_module(asab.storage.Module) + + async def main(self): + storage = self.get_service("asab.StorageService") +``` + +## Manipulation with databases + +### Upsertor + +Upsertor is an object that works like a pointer to the specified +database and optionally to object id. It is used for inserting new +objects, updating existing objects and deleting them. + +``` python +u = storage.upsertor("test-collection") +``` + +The `StorageService.upsertor()`{.interpreted-text role="func"} method +creates an upsertor object associated with the specified collection. It +takes [collection]{.title-ref} as an argument and can have two +parameters [obj\_id]{.title-ref} and [version]{.title-ref}, which are +used for getting an existing object by its ID and version. + +### Inserting an object + +For inserting an object to the collection, use the +`Upsertor.set()`{.interpreted-text role="func"} method. + +``` python +u.set("key", "value") +``` + +To execute these procedures, simply run the `Upsertor.execute()` coroutine method, +which commits the upsertor data to the storage and returns the ID of the object. +Since it is a coroutine, it must be awaited. + +``` python +object_id = await u.execute() +``` + +The `Upsertor.execute()` method has optional parameters +`custom_data` and `event_type`, which are used for webhook requests. + +``` python +object_id = await u.execute( + custom_data= {"foo": "bar"}, + event_type="object_created" + ) +``` + +### Getting a single object + +For getting a single object, use `StorageService.get()` coroutine method +that takes two arguments `collection` and `obj_id` and finds an object by its ID in collection. + +``` python +obj = await storage.get(collection="test-collection", obj_id=object_id) +print(obj) +``` + +When the requested object is not found in the collection, the method +raises `KeyError`. Remember to handle this exception properly when using +databases in your services and prevent them from crashing! + +!!! note + MongoDB storage service in addition provides a coroutine method `get_by()` which is used for accessing an object by finding its key-value pair. + +``` python +obj = await storage.get_by(database="test-collection", key="key", value="value") +``` + +### Updating an object + +For updating an object, first obtain the upsertor specifying its `obj_id` and `version`. + +``` python +u = storage.upsertor( + collection="test-collection", + obj_id=object_id, + version=obj['_v'] +) +``` + +We strongly recommend to read the version from the object such as above. +That creates a soft lock on the record. It means that if the object is +updated by other component in meanwhile, your upsertor will fail and you +should retry the whole operation. The new objects should have a version +set to 0, which is done by default. + +After obtaining an upsertor, you can update the object via the +`Upsertor.set()` coroutine. + +``` python +u.set("key", "new_value") +object_id = await u.execute() +``` + +### Deleting an object + +For deleting an object from database, use the `StorageService.delete()` coroutine method which takes arguments `collection` and `obj_id`, +deletes the object and returns its ID. + +``` python +deleted_id = await u.delete("test-collection", object_id) +``` + +## Storing data in memory + +If the option `inmemory` is set, ASAB will store data in its own memory. +In particular, `asab.StorageService` is initialized with an attribute `InMemoryCollections` which is +a dictionary where all the collections are stored in. + +!!! note + + You can go through all the databases directly by accessing + [InMemoryCollections]{.title-ref} attribute, although we do not + recommend that. + + ``` python + import pprint + storage = self.get_service("asab.StorageService") + pprint.pprint(storage.InMemoryCollections, indent=2) + ``` + +## Storing data in MongoDB + +If the option `mongodb` is set, ASAB will store data in MongoDB database. + +ASAB uses [motor library](https://pypi.org/project/motor/) which +provides non-blocking MongoDB driver for [asyncio]{.title-ref}. + +You can specify the database name and URL for MongoDB in config file +(the following example is the default configuration): + +``` ini +[asab:storage] +type=mongodb +mongodb_uri=mongodb://localhost:27017 +mongodb_database=asabdb +``` + +You can use all the methods from the abstract class. MongoDB Storage class provides in addition two methods, +`StorageService.get_by()` and `StorageService.collection()`. + +The method `StorageService.get_by()` is used in the same way as `StorageService.get()`. + +``` python +obj = await storage.get_by(database="test-collection", key="key", value="value") +``` + +The method `collection()` is used for accessing the database directly. +It takes `collection` as the argument and returns `motor.motor_asyncio.AsyncIOMotorCollection` object, which can be used for calling MongoDB directives. + +``` python +collection = await storage.collection("test-collection") +cursor = collection.find({}) +while await cursor.fetch_next: + data = cursor.next_object() + pprint.pprint(data) +``` + +The full list of methods suitable for this object is described in the +[official documentation](https://motor.readthedocs.io/en/stable/api-asyncio/asyncio_motor_collection.html). + +## Storing data in ElasticSearch + +When using ElasticSearch, add configurations for URL, username and +password. + +``` ini +[asab:storage] +type=elasticsearch +elasticsearch_url=http://localhost:9200/ +elasticsearch_username=JohnDoe +elasticsearch_password=lorem_ipsum_dolor?sit_amet!2023 +``` + +You can also specify the [refreshing parameter](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-refresh.html#docs-refresh) +and scroll timeout for [ElasticSearch Scroll API](https://www.elastic.co/guide/en/elasticsearch//reference/current/scroll-api.html). + +``` ini +[asab:storage] +refresh=true +scroll_timeout=1m +``` + +ElasticSearch Storage provides in addition other methods for creating index templates, mappings etc (see the Reference section). + +## Encryption and decryption + +Data stored in the database can be encrypted using an algorithm that adheres to the Advanced Encryption Standard (AES). + +### AES Key settings + +In order to use encryption, first make sure you have the [cryptography package](https://pypi.org/project/cryptography/) installed. Then specify +the AES Key in the config file. + +``` ini +[asab:storage] +aes_key=random_key_string +``` + +!!! note + + The AES Key is used as both an encryption and decryption key. + It is recommended to keep it in [a separate configuration file](https://asab.readthedocs.io/en/latest/asab/config.html#including-other-configuration-files) + that is not exposed anywhere publicly. + + The actual binary AES Key is obtained from the `aes_key` + specified in the config file by encoding and hashing it using the + standard [hashlib](https://docs.python.org/3/library/hashlib.html) + algorithms, so do not worry about the length and type of the key. + +### Encrypting data + +The `Upsertor.set()` method has an +optional boolean parameter `encrypt` for encrypting the data before they are stored. +Only values of the type `bytes` can be encrypted. If you want to encrypt other values, encode them first. + +``` python +message = "This is a super secret message!" +number = 2023 +message_binary = message.encode("ascii") +number_binary = number.encode("ascii") + +u.set("message", message_binary, encrypt=True) +u.set("number", number_binary, encrypt=True) +object_id = await u.execute() +``` + +### Decrypting data + +The `StorageService.get()` coroutine method has an optional parameter `decrypt` which takes an `iterable` object (i.e. a list, tuple, set, \...) +with the names of keys whose values are to be decrypted. + +``` python +data = await storage.get( + collection="test-collection", + obj_id=object_id, + decrypt=["message", "number"] + ) +``` + +If some of the keys to be decrypted are missing in the required document, the method will ignore them and continue. + +!!! note + Data that has been encrypted can be identified by the prefix `"$aes-cbc$"` and are stored in a binary format. + +### Under the hood + +For encrypting data, we use the certified symmetric AES-CBC algorithm. +In fact, the abstract base class `StorageServiceABC` provides two methods `aes_encrypt()` and `aes_decrypt()` +that are called automatically in `Upsertor.set()` and `StorageService.get()` methods when +the parameter `encrypt` or `decrypt` is specified. + +AES-CBC is a mode of operation for the Advanced Encryption Standard +(AES) algorithm that provides confidentiality and integrity for data. +In AES-CBC, the plaintext is divided into blocks of fixed size (usually 128 bits), +and each block is encrypted using the AES algorithm with a secret key. + +CBC stands for \"Cipher Block Chaining\" and it is a technique that adds an extra step to the encryption +process to ensure that each ciphertext block depends on the previous one. +This means that any modification to the ciphertext will produce a completely different plaintext after decryption. + +The algorithm is a symmetric cipher, which is suitable for encrypting large amounts of data. +It requires much less computation power than asymmetric ciphers and is much more useful for bulk encrypting large amounts of data. + +## Reference + +::: asab.storage.Module + +::: asab.storage.service.StorageServiceABC + +::: asab.storage.inmemory.StorageService + +::: asab.storage.mongodb.StorageService + +::: asab.storage.elasticsearch.StorageService diff --git a/docs/reference/storage/service.md b/docs/reference/storage/service.md deleted file mode 100644 index 110864d53..000000000 --- a/docs/reference/storage/service.md +++ /dev/null @@ -1 +0,0 @@ -::: asab.storage.service.StorageServiceABC diff --git a/docs/reference/storage/upsertor.md b/docs/reference/storage/upsertor.md deleted file mode 100644 index c3110870c..000000000 --- a/docs/reference/storage/upsertor.md +++ /dev/null @@ -1 +0,0 @@ -::: asab.storage.upsertor.UpsertorABC diff --git a/docs/topics/admin/command-line.md b/docs/topics/admin/command-line.md deleted file mode 100644 index 1f8b3b946..000000000 --- a/docs/topics/admin/command-line.md +++ /dev/null @@ -1,76 +0,0 @@ -ASAB Command-line interface -=========================== - -ASAB-based application provides the command-line interface by default. -Here is an overview of the common command-line arguments. - -%TODO: option% --h , \--help -xxx - -Show a help. - -Configuration -------------- - -%TODO: option% --c \,\--config \ -xxx - -Load configuration file from a file CONFIG. - -Logging -------- - -%TODO: option% --v , \--verbose -xxx - -Increase the logging level to DEBUG aka be more verbose about what is -happening. - -%TODO: option% --l \,\--log-file \ -xxx - -Log to a file LOG\_FILE. - -%TODO: option% --s , \--syslog -xxx - -Log to a syslog. - -Daemon ------- - -Python module :py`python-daemon`{.interpreted-text role="mod"} has to be -installed in order to support daemonosation functions. - -``` {.bash} -$ pip3 install asab python-daemon -``` - -%TODO: option% --d , \--daemonize -xxx - -Launch the application in the background aka daemonized. - -Daemon-related section of `Config`{.interpreted-text role="any"} file: - - [daemon] - pidfile=/var/run/myapp.pid - uid=nobody - gid=nobody - working_dir=/tmp - -Configuration options `pidfile`, `uid` , `gid` and `working_dir` are -supported. - -%TODO: option% --k , \--kill -xxx - -Shutdown the application running in the background (started previously -with `-d` argument). diff --git a/docs/topics/admin/systemd.md b/docs/topics/admin/systemd.md deleted file mode 100644 index ba6c71961..000000000 --- a/docs/topics/admin/systemd.md +++ /dev/null @@ -1,39 +0,0 @@ -systemd -======= - -1. Create a new Systemd unit file in /etc/systemd/system/: - -``` {.bash} -$ sudo vi /etc/systemd/system/asab.service -``` - -Adjust the example of [SystemD unit -file](https://github.com/TeskaLabs/asab/blob/master/doc/asab.service). - -2. Let systemd know that there is a new service: - -``` {.bash} -$ sudo systemctl enable asab -``` - -To reload existing unit file after changing, use this: - -``` {.bash} -$ sudo systemctl daemon-reload -``` - -3. ASAB Application Server service for systemd is now ready. - -Start of ASAB Server --------------------- - -``` {.bash} -$ sudo service asab start -``` - -Stop of ASAB Server -------------------- - -``` {.bash} -$ sudo service asab stop -``` diff --git a/docs/topics/asab/alert.md b/docs/topics/asab/alert.md deleted file mode 100644 index c2372b575..000000000 --- a/docs/topics/asab/alert.md +++ /dev/null @@ -1,83 +0,0 @@ -Alert Service -============= - -Integrate ASAB Application with alert managers. - -There are currently two possible target systems for the alerts -available: - -- Opsgenie - -- PagerDuty - - -Everything you need to do is to import the service, trigger the alert -and specify the target in the **configuration**. - -``` {.python} -class MyApplication(asab.Application): - async def initialize(self): - from asab.alert import AlertService - self.AlertService = AlertService(self) - self.AlertService.trigger( - source="my-tenant", - alert_cls="my-class", - alert_id="deduplication-id01", - title="Something went wrong.", - detail={ - "example1": "additional-info", - "example2": "additional-info", - }, - ) - -if __name__ == '__main__': - app = MyApplication() - app.run() -``` - -Opsgenie --------- - -- Create an account at Opsgenie. -- In your Opsgenie account, create a new **Team**. -- Add integration to your Team - choose **API**. -- API Key will be generated for you. - -*myapplication.conf* - -``` {.} -[asab:alert:opsgenie] -api_key=my-api-key -tags=my-tag, my-application -url=https://api.eu.opsgenie.com # this is default value -``` - -PagerDuty ---------- - -- Create an account at PagerDuty. -- In your PagerDuty account, generate **Api Key** (Integrations \> - Developer Tools \> Api Access Keys). -- Create a new Service in Service Directory and add integration in the - Integrations folder. -- Choose **Events API V2**. An **Integration Key** will be generated - for you. - -*myapplication.conf* - -``` {.} -[asab:alert:pagerduty] -api_key=my-api-key -integration_key=my-integration-key -url=https://events.pagerduty.com # this is default value -``` - -De-duplication --------------- - -[alert\_id]{.title-ref} argument serves as a de-duplication ID for the -third-party services. It enables the grouping of alerts and prevents -noise. More about alert grouping: - -- Opsgenie: - -- PagerDuty: - diff --git a/docs/topics/asab/config.md b/docs/topics/asab/config.md deleted file mode 100644 index 6cea44e79..000000000 --- a/docs/topics/asab/config.md +++ /dev/null @@ -1,243 +0,0 @@ -Configuration {#configuration-ref} -============= - -The configuration is provided by :py`Config`{.interpreted-text -role="obj"} object which is a singleton. It means that you can access -:py`Config`{.interpreted-text role="obj"} from any place of your code, -without need of explicit initialisation. - -``` {.python} -import asab - -# Initialize application object and hence the configuration -app = asab.Application() - -# Access configuration values anywhere -my_conf_value = asab.Config['section_name']['key1'] -``` - -Based on ConfigParser ---------------------- - -The :py`Config`{.interpreted-text role="obj"} is inherited from Python -Standard Library :py`configparser.ConfigParser`{.interpreted-text -role="class"} class. which implements a basic configuration language -which provides a structure similar to what's found in Microsoft Windows -INI files. - -Example of the configuration file: - -``` {.ini} -[bitbucket.org] -User = hg - -[topsecret.server.com] -Port = 50022 -ForwardX11 = no -``` - -And this is how you access configuration values: - -``` {.python} ->>> asab.Config['topsecret.server.com']['ForwardX11'] -'no' -``` - -Multiline configuration entry ------------------------------ - -A multiline configuration entries are supported. An example: - -``` {.ini} -[section] -key= - line1 - line2 - line3 -another_key=foo -``` - -Automatic load of configuration -------------------------------- - -If a configuration file name is specified, the configuration is -automatically loaded from a configuration file during initialiation time -of :py`Application`{.interpreted-text role="class"}. The configuration -file name can be specified by one of `-c` command-line argument (1), -`ASAB_CONFIG` environment variable (2) or config `[general] config_file` -default value (3). - -``` {.shell} -./sample_app.py -c ./etc/sample.conf -``` - -Including other configuration files ------------------------------------ - -You can specify one or more additional configuration files that are -loaded and merged from an main configuration file. It is done by -`[general] include` configuration value. Multiple paths are separated by -`os.pathsep` (`:` on Unix). The path can be specified as a glob (e.g. -use of `*` and `?` wildcard characters), it will be expanded by `glob` -module from Python Standard Library. Included configuration files may -not exists, this situation is silently ignored. - -``` {.ini} -[general] -include=./etc/site.conf:./etc/site.d/*.conf -``` - -You can also use a multiline configuration entry: - -``` {.ini} -[general] -include= - ./etc/site.conf - ./etc/site.d/*.conf -``` - -Configuration default values ----------------------------- - -This is how you can extend configuration default values: - -``` {.python} -asab.Config.add_defaults( - { - 'section_name': { - 'key1': 'value', - 'key2': 'another value' - }, - 'other_section': { - 'key3': 'value', - }, - } -) -``` - -Only simple types (`string`, `int` and `float`) are allowed in the -configuration values. Don\'t use complex types such as lists, -dictionaries or objects because these are impossible to provide via -configuration files etc. - -Environment variables in configration -------------------------------------- - -Environment variables found in values are automatically expanded. - -``` {.ini} -[section_name] -persistent_dir=${HOME}/.myapp/ -``` - -``` {.python} ->>> asab.Config['section_name']['persistent_dir'] -'/home/user/.myapp/' -``` - -There is a special environment variable [\${THIS\_DIR}]{.title-ref} that -is expanded to a directory that contains a current configuration file. -It is useful in complex configurations that utilizes included -configuration files etc. - -``` {.ini} -[section_name] -my_file=${THIS_DIR}/my_file.txt -``` - -Another environment variable [\${HOSTNAME}]{.title-ref} contains the -application hostname to be used f. e. in logging file path. - -``` {.ini} -[section_name] -my_file=${THIS_DIR}/${HOSTNAME}/my_file.txt -``` - -Passwords in configration -------------------------- - -\[passwords\] section in the configuration serves to securely store -passwords, which are then not shown publicly in the default API config -endpoint\'s output. - -It is convenient for the user to store passwords at one place, so that -they are not repeated in many sections of the config file(s). - -Usage is as follows: - -``` {.ini} -[connection:KafkaConnection] -password=${passwords:kafka_password} - -[passwords] -kafka_password= -``` - -Obtaining seconds ------------------ - -The seconds can be obtained using [getseconds()]{.title-ref} method for -values with different time units specified in the configuration: - -``` {.ini} -[sleep] -sleep_time=5.2s -another_sleep_time=10d -``` - -The available units are: - -> - `y` \... years -> - `M` \... months -> - `w` \... weeks -> - `d` \... days -> - `h` \... hours -> - `m` \... minutes -> - `s` \... seconds -> - `ms` .. miliseconds - -If no unit is specified, float of seconds is expected. - -The obtainment of the second value in the code can be achieved in two -ways: - -``` {.python} -self.SleepTime = asab.Config["sleep"].getseconds("sleep_time") -self.AnotherSleepTime = asab.Config.getseconds("sleep", "another_sleep_time") -``` - -Obtaining URLs --------------- - -A URL can be obtained using a [geturl()]{.title-ref} method that takes -the URL from the config and removes leading and trailing whitespaces and -trailing backslashes. - -There is an optional parameter called [scheme]{.title-ref} that can have -any URL scheme like http, https, mongodb etc. Setting it to None, scheme -validation gets bypassed. - -Setting the scheme parameter to the same scheme as in the config, it -will return the URL. If it\'s not the same it will raise an error. - -There are two ways of obtaining the URL: - -``` {.py} -asab.Config["urls"].geturl("teskalabs", scheme="https") -asab.Config.geturl("urls", "github", scheme=None) -``` - -Example: - -``` {.python} ->>> asab.Config["urls"].geturl("teskalabs", scheme="https") - 'https://www.teskalabs.com' -``` - -For reference this would be the configuration file: - -``` {.ini} -[urls] -teskalabs=https://www.teskalabs.com/ -github=github.com -``` diff --git a/docs/topics/asab/library.md b/docs/topics/asab/library.md deleted file mode 100644 index 01fe8434e..000000000 --- a/docs/topics/asab/library.md +++ /dev/null @@ -1,360 +0,0 @@ -Library {#library-ref} -======= - -The ASAB Library ([asab.library]{.title-ref}) is a concept of the shared -data content across microservices in the cluster. In the cluster/cloud -microservice architectures, all microservices must have access to -unified resources. The [asab.library]{.title-ref} provides a read-only -interface for listing and reading this content. - -[asab.library]{.title-ref} is designed to be read-only. It also allows -to \"stack\" various libraries into one view (overlayed) that merges the -content of each library into one united space. - -The library can also notify the ASAB microservice about changes, e.g. -for automated update/reload. - -There is a companion microservice [asab-library]{.title-ref} that can be -used for the management and editing of the library content. The -[asab.library]{.title-ref} can however operate without -[asab-library]{.title-ref} microservice. - -Library structure ------------------ - -The library content is organized in a simplified filesystem manner, with -directories and files. - -Example of the library structure: - -``` {.} -+ /folder1/ - - /folder1/item1.yaml - - /folder1/item2.json -+ /folder2/ - - /folder2/item3.yaml - + /folder2/folder2.3/ - - /folder2/folder2.3/item4.json -``` - -Library path rules ------------------- - -- Any path must start with [/]{.title-ref}, including the root path - ([/]{.title-ref}). -- The folder path must end with [/]{.title-ref}. -- The item path must end with an extension (e.g. [.json]{.title-ref}). - -Layers ------- - -The library content can be organized into an unlimited number of layers. -Each layer is represented by a [provider]{.title-ref} with a specific -configuration. - -The layers of the library are like slices of Swiss cheese layered on top -of each other. Only if there is a hole in the top layer can you see the -layer that shows through underneath. It means that files of the upper -layer overwrite files with the same path in the lower layers. - -The first provider is responsible for providing -[/.disabled.yaml]{.title-ref} that controls the visibility of items. If -[/.disabled.yaml]{.title-ref} is not present, then is considered empty. - -Library service ---------------- - -Example of the use: - -``` {.python} -import asab -import asab.library - - -# this substitutes configuration file -asab.Config.read_string( - """ -[library] -providers=git+https://github.com/TeskaLabs/asab-maestro-library.git -""" - ) - - -class MyApplication(asab.Application): - - def __init__(self): - super().__init__() - # Initialize the library service - self.LibraryService = asab.library.LibraryService(self, "LibraryService") - self.PubSub.subscribe("Library.ready!", self.on_library_ready) - - async def on_library_ready(self, event_name, library): - print("# Library\n") - - for item in await self.LibraryService.list("/", recursive=True): - print(" *", item) - if item.type == 'item': - itemio = await self.LibraryService.read(item.name) - if itemio is not None: - with itemio: - content = itemio.read() - print(" - content: {} bytes".format(len(content))) - else: - print(" - (DISABLED)") - -if __name__ == '__main__': - app = MyApplication() - app.run() -``` - -The library service may exist in multiple instances, with different -[paths]{.title-ref} setups. For that reason, you have to provide a -unique [service\_name]{.title-ref} and there is no default value for -that. - -For more examples of Library usage, please see [ASAB -examples](https://github.com/TeskaLabs/asab/tree/master/examples) - -Library configuration ---------------------- - -Example: - -``` {.ini} -[library] -providers: - provider+1://... - provider+2://... - provider+3://... -``` - -PubSub messages ---------------- - -Read more about `PubSub`{.interpreted-text role="ref"} in -ASAB. - -%TODO: option% -Library.ready! -xxx - -A library is created in a "not ready" state. Only after all providers -are ready, the library itself becomes ready. The library indicates that -by the PubSub event [Library.ready!]{.title-ref}. - -%TODO: option% -Library.not\_ready! -xxx - -The readiness of the library (connection to external technologies) can -be lost. You can also subscribe to [Library.not\_ready!]{.title-ref} -event. - -%TODO: option% -Library.change! -xxx - -You can get [Notification on Changes](#notification-on-changes) in the -library. Specify a path or paths that you would like to \"listen to\". -Then subscribe to [Library.change!]{.title-ref} PubSub event. Available -for Git and FileSystem providers for now. - -Notification on changes ------------------------ - -# TODO: autofunction% -LibraryService.subscribe -xxx - -Providers ---------- - -The library can be configured to work with the following \"backends\" -(aka providers): - -### Filesystem - -The most basic provider that reads data from the local filesystem. The -notification on changes functionality is available only for Linux -systems, as it implements -[inotify](https://en.wikipedia.org/wiki/Inotify) - -Configuration examples: - -``` {.ini} -[library] -providers: /home/user/directory -``` - -``` {.ini} -[library] -providers: ./this_directory -``` - -``` {.ini} -[library] -providers: file:///home/user/directory -``` - -### Apache Zookeeper - -ZooKeeper as a consensus technology is vital for microservices in the -cluster. - -There are several configuration strategies: - -1) Configuration from \[zookeeper\] section. - -``` {.ini} -[zookeeper] -servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 -path=/library - -[library] -providers: - zk:// -``` - -2) Specify a path of a ZooKeeper node where only library lives. - - > The library path will be [/library]{.title-ref}. - -``` {.ini} -[zookeeper] -servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 -path=/else - -[library] -providers: - zk:///library - - -The library path will be `/`. -``` - -``` {.ini} -[zookeeper] -servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 -path=/else - -[library] -providers: - zk:/// -``` - -3) Configuration from the URL in the \[library\] section. - -``` {.ini} -[library] -providers: - zk://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/library -``` - -4) Configuration from \[zookeeper\] section and joined - [path]{.title-ref} from \[zookeeper\] and \[library\] sections. - - > The resulting path will be [/else/library]{.title-ref}. - -``` {.ini} -[zookeeper] -servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 -path=/else - -[library] -providers: - zk://./library -``` - -If a [path]{.title-ref} from the \[zookeeper\] section is missing, an -application class name will be used E.g. -[/BSQueryApp/library]{.title-ref} - -### Microsoft Azure Storage - -Reads from the Microsoft Azure Storage container. - -Configuration: - -``` {.ini} -[library] -providers: azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER -``` - -If Container Public Access Level is not set to \"Public access\", then -\"Access Policy\" must be created with \"Read\" and \"List\" permissions -and \"Shared Access Signature\" (SAS) query string must be added to a -URL in a configuration: - -``` {.ini} -[library] -providers: azure+https://ACCOUNT-NAME.blob.core.windows.net/BLOB-CONTAINER?sv=2020-10-02&si=XXXX&sr=c&sig=XXXXXXXXXXXXXX -``` - -### Git repository - -Connection to git repositories requires -[pygit2](https://www.pygit2.org/) library to be installed. - -Configuration: - -``` {.ini} -[library] -providers: git+https://github.com/john/awesome_project.git -``` - -#### Deploy tokens in GitLab - -GitLab uses deploy tokens to enable authentication of deployment tasks, -independent of a user account. Authentication through deploy tokens is -the only supported option for now. - -If you want to create a deploy token for your GitLab repository, follow -these steps from the -[manual](https://docs.gitlab.com/ee/user/project/deploy_tokens/#create-a-deploy-token): - -1. Go to **Settings \> Repository \> Deploy tokens** section in your - repository. (Note that you have to possess a \"Maintainer\" or - \"Owner\" role for the repository.) -2. Expand the \"Deploy tokens\" section. The list of current Active - Deploy Tokens will be displayed. -3. Complete the fields and scopes. We recommend a custom \"username\", - as you will need it later for the URL in the configuration. -4. Record the deploy token\'s values *before leaving or refreshing the - page*! After that, you cannot access it again. - -After the deploy token is created, use the URL for the repository in the -following format: - -``` {.ini} -[library] -providers: git+https://:@gitlab.example.com/john/awesome_project.git -``` - -#### Where does the repository clone? - -The git provider clones the repository into a temporary directory. The -default path for the cloned repository is -[/tmp/asab.library.git/]{.title-ref} and it can be changed manually: - -``` {.ini} -[library:git] -repodir=path/to/repository/cache -``` - -### Reference - -# TODO: autoclass% -LibraryService - -# TODO: autofunction% -read -xxx - -# TODO: autofunction% -list -xxx - -# TODO: autofunction% -export -xxx -xxx diff --git a/docs/topics/asab/log.md b/docs/topics/asab/log.md deleted file mode 100644 index e155fe57b..000000000 --- a/docs/topics/asab/log.md +++ /dev/null @@ -1,243 +0,0 @@ -Logging -======= - -ASAB logging is built on top of a standard Python `logging` module. It -means that it logs to `stderr` when running on a console and ASAB also -provides file and syslog output (both RFC5424 and RFC3164) for -background mode of operations. - -Log timestamps are captured with sub-second precision (depending on the -system capabilities) and displayed including microsecond part. - -Recommended use ---------------- - -We recommend to create a logger `L` in every module that captures all -necessary logging output. Alternative logging strategies are also -supported. - -``` {.python} -import logging -L = logging.getLogger(__name__) - -... - -L.warning("Hello world!") -``` - -Example of the output to the console: - -`25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule Hello world!` - -Logging Levels --------------- - -ASAB uses Python logging levels with the addition of `LOG_NOTICE` level. -`LOG_NOTICE` level is similar to `logging.INFO` level but it is visible -in even in non-verbose mode. - -``` {.python} -L.log(asab.LOG_NOTICE, "This message will be visible regardless verbose configuration.") -``` - - --------------------------------------------------------------- - Level Numeric value Syslog Severity level - ---------------- --------------- ------------------------------ - `CRITICAL` 50 Critical / `crit` / 2 - - `ERROR` 40 Error / `err` / 3 - - `WARNING` 30 Warning / `warning` / 4 - - `LOG_NOTICE` 25 Notice / `notice` / 5 - - `INFO` 20 Informational / `info` / 6 - - `DEBUG` 10 Debug / `debug` / 7 - - `NOTSET` 0 - --------------------------------------------------------------- - -Example of a custom level configuration: - -``` {.ini} -[logging] -levels= - myApp.module1 DEBUG - myApp.module2 WARNING - customLogger ERROR -``` - -The logger name and the corresponding logging level are separated by a -space, each logger is on a separate line. - -Verbose mode ------------- - -The command-line argument `-v` enables verbose logging. It means that -log entries with levels `DEBUG` and `INFO` will be visible. It also -enables `asyncio` debug logging. - -The actual verbose mode is avaiable at -`asab.Config["logging"]["verbose"]` boolean option. - -``` {.python} -L.debug("This message will be visible only in verbose mode.") -``` - -Structured data ---------------- - -ASAB supports a structured data to be added to a log entry. It follows -the [RFC 5424](https://tools.ietf.org/html/rfc5424), section -`STRUCTURED-DATA`. Structured data are a dictionary, that has to be -seriazable to JSON. - -``` {.python} -L.warning("Hello world!", struct_data={'key1':'value1', 'key2':2}) -``` - -Example of the output to the console: - -`25-Mar-2018 23:33:58.044595 WARNING myapp.mymodule [sd key1="value1" key2="2"] Hello world!` - -Logging to file ---------------- - -The command-line argument `-l` on command-line enables logging to file. -Also non-empty `path` option in the section `[logging:file]` of -configuration file enables logging to file as well. - -Example of the configuration file section: - -``` {.ini} -[logging:file] -path=/var/log/asab.log -format="%%(asctime)s %%(levelname)s %%(name)s %%(struct_data)s%%(message)s", -datefmt="%%d-%%b-%%Y %%H:%%M:%%S.%%f" -backup_count=3 -rotate_every=1d -``` - -When the deployment expects more instances of the same application to be -logging into the same file, it is recommended, that the variable -hostname is used in the file path: - -``` {.ini} -[logging:file] -path=/var/log/${HOSTNAME}/asab.log -``` - -In this way, the applications will log to seperate log files in -different folders, which is an intended behavior, since race conditions -may occur when different application instances log into the same file. - -Logging to console ------------------- - -ASAB will log to the console only if it detects that it runs in the -foreground respectively on the terminal using `os.isatty` or if the -environment variable `ASABFORCECONSOLE` is set to `1`. This is useful -setup for eg. PyCharm. - -### Log rotation - -ASAB supports a [log -rotation](https://en.wikipedia.org/wiki/Log_rotation). The log rotation -is triggered by a UNIX signal `SIGHUP`, which can be used e.g. to -integrate with `logrotate` utility. It is implemented using -`logging.handlers.RotatingFileHandler` from a Python standard library. -Also, a time-based log rotation can be configured using `rotate_every` -option. - -`backup_count` specifies a number of old files to be kept prior their -removal. The system will save old log files by appending the extensions -'.1', '.2' etc., to the filename. - -`rotate_every` specifies an time interval of a log rotation. Default -value is empty string, which means that the time-based log rotation is -disabled. The interval is specified by an integer value and an unit, -e.g. 1d (for 1 day) or 30M (30 minutes). Known units are [H]{.title-ref} -for hours, [M]{.title-ref} for minutes, [d]{.title-ref} for days and -[s]{.title-ref} for seconds. - -Logging to syslog ------------------ - -The command-line argument `-s` enables logging to syslog. - -A configuration section `[logging:syslog]` can be used to specify -details about desired syslog logging. - -Example of the configuration file section: - -``` {.ini} -[logging:syslog] -enabled=true -format=5 -address=tcp://syslog.server.lan:1554/ -``` - -`enabled` is equivalent to command-line switch `-s` and it enables -syslog logging target. - -`format` speficies which logging format will be used. Possible values -are: - -- `5` for (new) syslog format ([RFC - 5424](https://tools.ietf.org/html/rfc5424) ) , -- `3` for old BSD syslog format ([RFC - 3164](https://tools.ietf.org/html/rfc3164) ), typically used by - `/dev/log` and -- `m` for Mac OSX syslog flavour that is based on BSD syslog format - but it is not fully compatible. - -The default value is `3` on Linux and `m` on Mac OSX. - -`address` specifies the location of the Syslog server. It could be a -UNIX path such as `/dev/log` or URL. Possible URL values: - -- `tcp://syslog.server.lan:1554/` for Syslog over TCP -- `udp://syslog.server.lan:1554/` for Syslog over UDP -- `unix-connect:///path/to/syslog.socket` for Syslog over UNIX socket - (stream) -- `unix-sendto:///path/to/syslog.socket` for Syslog over UNIX socket - (datagram), equivalent to `/path/to/syslog.socket`, used by a - `/dev/log`. - -The default value is a `/dev/log` on Linux or `/var/run/syslog` on Mac -OSX. - -Logging of obsolete features ----------------------------- - -It proved to be essential to inform operators about features that are -going to be obsoleted. ASAB offers the unified \"obsolete\" logger. This -logger can indicate that a particular feature is marked as \"obsolete\" -thru logs. Such a log message can then be \"grepped\" from logs -uniformly. - -It is recommended to include [eol]{.title-ref} attribute in the -[struct\_data]{.title-ref} of the log with a [YYYY-MM-DD]{.title-ref} -date/time of the planned obsoletion of the feature. - -Hint: We suggest automating the detection of obsolete warnings in logs -so that the operations are informed well ahead of the actual removal of -the feature. The string to seek in logs is \" OBSOLETE \". - -Example of the use: - -``` {.python} -asab.LogObsolete.warning("Use of the obsolete function", struct_data={'eol':'2022-31-12'}) -``` - -Log example: - -`21-Jul-2022 14:32:40.983884 WARNING OBSOLETE [eol="2022-31-12"] Use of the obsolete function` - -Reference ---------- - -# TODO: automodule members="" undoc-members="" show-inheritance=""} -asab.log -xxx diff --git a/docs/topics/asab/module.md b/docs/topics/asab/module.md deleted file mode 100644 index 9e8f0ca9c..000000000 --- a/docs/topics/asab/module.md +++ /dev/null @@ -1,53 +0,0 @@ -Module -====== - -Modules are registered at the module registry, managed by an application -object. See `Application.Modules`{.interpreted-text role="any"} for more -details. Module can be loaded by ASAB and typically provides one or more -`Service`{.interpreted-text role="any"} objects. - -Structure ---------- - -Recommended structure of the ASAB module: - - mymodule/ - __init__.py - myservice.py - -Content of the \`\_\_init\_\_.py\`: - -``` {.python} -import asab -from .myservice import MyService - -# Extend ASAB configuration defaults -asab.Config.add_defaults({ - 'mymodule': { - 'foo': 'bar' - } -}) - -class MyModule(asab.Module): - def __init__(self, app): - super().__init__(app) - self.service = MyService(app, "MyService") -``` - -And this is how the module is loaded: - -``` {.python} -from mymodule import MyModule -app.add_module(MyModule) -``` - -For more details see `Application.add_module`{.interpreted-text -role="any"}. - -Lifecycle ---------- - -Called when the module is initialized. It can be overriden by an user. - -Called when the module is finalized e.g. during application exit-time. -It can be overriden by an user. diff --git a/docs/topics/asab/pubsub.md b/docs/topics/asab/pubsub.md deleted file mode 100644 index a8bd534ff..000000000 --- a/docs/topics/asab/pubsub.md +++ /dev/null @@ -1,280 +0,0 @@ -Publish-Subscribe {Xpubsub_page} -================= - -Publish--subscribe is a messaging pattern where senders of messages, -called publishers, send the messages to receivers, called subscribers, -via PubSub message bus. Publishers don\'t directly interact with -subscribers in any way. Similarly, subscribers express interest in one -or more message types and only receive messages that are of interest, -without knowledge of which publishers, if any, there are. - -ASAB `PubSub` operates with a simple messages, defined by their *message -type*, which is a string. We recommend to add `!` (explamation mark) at -the end of the message type in order to distinguish this object from -other types such as Python class names or functions. Example of the -message type is e.g. `Application.run!`{.interpreted-text role="any"} or -`Application.tick/600!`{.interpreted-text role="any"}. - -The message can carry an optional positional and keyword arguments. The -delivery of a message is implemented as a the standard Python function. - -*Note:* There is an default, application-wide Publish-Subscribe message -bus at `Application.PubSub`{.interpreted-text role="any"} that can be -used to send messages. Alternatively, you can create your own instance -of :py`PubSub`{.interpreted-text role="class"} and enjoy isolated PubSub -delivery space. - -Subscription ------------- - -Subscribe to a message type. Messages will be delivered to a `callback` -callable (function or method). The `callback` can be a standard callable -or an `async` coroutine. Asynchronous `callback` means that the delivery -of the message will happen in a `Future`, asynchronously. - -`Callback` callable will be called with the first argument - -Example of a subscription to an `Application.tick!`{.interpreted-text -role="any"} messages. - -``` {.python} -class MyClass(object): - def __init__(self, app): - app.PubSub.subscribe("Application.tick!", self.on_tick) - - def on_tick(self, message_type): - print(message_type) -``` - -Asynchronous version of the above: - -``` {.python} -class MyClass(object): - def __init__(self, app): - app.PubSub.subscribe("Application.tick!", self.on_tick) - - async def on_tick(self, message_type): - await asyncio.sleep(5) - print(message_type) -``` - -To simplify the process of subscription to `PubSub`{.interpreted-text -role="any"}, ASAB offers the decorator-based *\"subscribe all\"* -functionality. - -In the followin example, both `on_tick()` and `on_exit()` methods are -subscribed to `Application.PubSub`{.interpreted-text role="any"} message -bus. - -``` {.python} -class MyClass(object): - def __init__(self, app): - app.PubSub.subscribe_all(self) - - @asab.subscribe("Application.tick!") - async def on_tick(self, message_type): - print(message_type) - - @asab.subscribe("Application.exit!")python - def on_exit(self, message_type): - print(message_type) -``` - -Unsubscribe from a message delivery. - -X TODO: autoclass members="" undoc-members=""} -asab.Subscriber -xxx - -The subscriber object can be also used as [an asynchonous -generator]{.title-ref}. The example of the subscriber object usage in -[async for]{.title-ref} statement: - -``` {.python} -async def my_coroutine(self): - X Subscribe for a two application events - subscriber = asab.Subscriber( - self.PubSub, - "Application.tick!", - "Application.exit!" - ) - async for message_type, args, kwargs in subscriber: - if message_type == "Application.exit!": - break; - print("Tick.") -``` - -Publishing ----------- - -Publish a message to the PubSub message bus. It will be delivered to -each subscriber synchronously. It means that the method returns after -each subscribed `callback` is called. - -The example of a message publish to the -`Application.PubSub`{.interpreted-text role="any"} message bus: - -``` {.python} -def my_function(app): - app.PubSub.publish("mymessage!") -``` - -Asynchronous publishing of a message is requested by -`asynchronously=True` argument. The `publish()` method returns -immediatelly and the delivery of the message to subscribers happens, -when control returns to the event loop. - -The example of a **asynchronous version** of a message publish to the -`Application.PubSub`{.interpreted-text role="any"} message bus: - -``` {.python} -def my_function(app): - app.PubSub.publish("mymessage!", asynchronously=True) -``` - -Synchronous vs. asynchronous messaging --------------------------------------- - -ASAB PubSub supports both modes of a message delivery: synchronous and -asynchronous. Moreover, PubSub also deals with modes, when asynchronous -code (coroutine) does publish to synchronous code and vice versa. - - -------------- ---------------------- ------------------------------------ - Sync publish Async publish - - Sync subscribe Called immediately `call_soon(...)` - - Async `ensure_future(...)` `call_soon(...)` & - subscribe `ensure_future(...)` - -------------- ---------------------- ------------------------------------ - -Application-wide PubSub ------------------------ - -The ASAB provides the application-wide Publish-Subscribe message bus. - -XXX Well-Known Messages - -This is a list of well-known messages, that are published on a -`Application.PubSub` by ASAB itself. - -%TODO: option% -Application.init! -xxx - -This message is published when application is in the init-time. It is -actually one of the last things done in init-time, so the application -environment is almost ready for use. It means that configuration is -loaded, logging is setup, the event loop is constructed etc. - -%TODO: option% -Application.run! -xxx - -This message is emitted when application enters the run-time. - -%TODO: option% -Application.stop! -xxx - -This message is emitted when application wants to stop the run-time. It -can be sent multiple times because of a process of graceful run-time -termination. The first argument of the message is a counter that -increases with every `Application.stop!` event. - -%TODO: option% -Application.exit! -xxx - -This message is emitted when application enter the exit-time. - -%TODO: option% -Application.tick! -xxx - -%TODO: option% -Application.tick/10! -xxx - -%TODO: option% -Application.tick/60! -xxx - -%TODO: option% -Application.tick/300! -xxx - -%TODO: option% -Application.tick/600! -xxx - -%TODO: option% -Application.tick/1800! -xxx - -%TODO: option% -Application.tick/3600! -xxx - -%TODO: option% -Application.tick/43200! -xxx - -%TODO: option% -Application.tick/86400! -xxx - -The application publish periodically \"tick\" messages. The default tick -frequency is 1 second but you can change it by configuration -`[general] tick_period`. `Application.tick!`{.interpreted-text -role="any"} is published every tick. -`Application.tick/10!`{.interpreted-text role="any"} is published every -10th tick and so on. - -%TODO: option% -Application.hup! -xxx - -This message is emitted when application receives UNIX signal `SIGHUP` -or equivalent. - -%TODO: option% -Application.housekeeping! -xxx - -This message is published when application is on the time for -housekeeping. The time for housekeeping is set to 03:00 AM UTC by -default. - -The app listens every ten minutes to see if it\'s time for housekeeping. -If the UTC time reaches the value for housekeeping, the app will publish -it and set the time for the next housekeeping for the next day at the -same time. There is also a time limit, which is set to 05:00 AM UTC by -default. If the computer is in a sleep state, housekeeping will not be -performed. Then, when the computer is reawakened again, it will check if -it has exceeded the time limit. If not, then housekeeping will be -published. If it has exceeded it, it simply informs the user and sets -the housekeeping time for the next day. Note that this only limits the -time when the housekeeping can start. If the housekeeping event triggers -a procedure that takes a long time to finish, it will not be terminated -when the time limit is reached. - -Both housekeeping time and time limit can be changed in the -configuration file: - -``` {.ini} -[housekeeping] -at=19:30 -limit=21:00 -``` - -This sets the housekeeping time to 7:30 PM UTC and the time limit to -9:00 PM UTC. The time must be written in the format \'HH:MM\'. Remind -yourself that the time is set to UTC, so you should be careful when -operating in a different timezone. - - -Reference ---------- - -::: asab.pubsub \ No newline at end of file diff --git a/docs/topics/asab/service.md b/docs/topics/asab/service.md deleted file mode 100644 index 48c98523d..000000000 --- a/docs/topics/asab/service.md +++ /dev/null @@ -1,53 +0,0 @@ -Service -======= - -Service objects are registered at the service registry, managed by an -application object. See `Application.Services`{.interpreted-text -role="any"} for more details. - -An example of a typical service class skeleton: - -``` {.python} -class MyService(asab.Service): - - def __init__(self, app, service_name): - super().__init__(app, service_name) - ... - - async def initialize(self, app): - ... - - - async def finalize(self, app): - ... - - - def service_method(self): - .... -``` - -This is how a service is created and registered: - -``` {.python} -mysvc = MyService(app, "my_service") -``` - -This is how a service is located and used: - -``` {.python} -mysvc = app.get_service("my_service") -mysvc.service_method() -``` - -Each service is identified by its name. - -A reference to an :py`Application`{.interpreted-text role="class"} -object instance. - -Lifecycle ---------- - -Called when the service is initialized. It can be overriden by an user. - -Called when the service is finalized e.g. during application exit-time. -It can be overriden by an user. diff --git a/docs/topics/asab/storage/elasticsearch.md b/docs/topics/asab/storage/elasticsearch.md deleted file mode 100644 index c903ec368..000000000 --- a/docs/topics/asab/storage/elasticsearch.md +++ /dev/null @@ -1,28 +0,0 @@ - -Storing data in ElasticSearch ------------------------------ - -When using ElasticSearch, add configurations for URL, username and -password. - -``` {.ini} -[asab:storage] -type=elasticsearch -elasticsearch_url=http://localhost:9200/ -elasticsearch_username=JohnDoe -elasticsearch_password=lorem_ipsum_dolor?sit_amet!2023 -``` - -You can also specify the [refreshing -parameter](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-refresh.html#docs-refresh) -and scroll timeout for [ElasticSearch Scroll -API](https://www.elastic.co/guide/en/elasticsearch//reference/current/scroll-api.html). - -``` {.ini} -[asab:storage] -refresh=true -scroll_timeout=1m -``` - -ElasticSearch Storage provides in addition other methods for creating -index templates, mappings etc (see the Reference section). \ No newline at end of file diff --git a/docs/topics/asab/storage/encryption.md b/docs/topics/asab/storage/encryption.md deleted file mode 100644 index 43f91ca83..000000000 --- a/docs/topics/asab/storage/encryption.md +++ /dev/null @@ -1,105 +0,0 @@ -Encryption and decryption -------------------------- - -Data stored in the database can be encrypted using an algorithm that -adheres to the Advanced Encryption Standard (AES). - -### AES Key settings - -In order to use encryption, first make sure you have the [cryptography -package](https://pypi.org/project/cryptography/) installed. Then specify -the AES Key in the config file. - -``` {.ini} -[asab:storage] -aes_key=random_key_string -``` - -xxx {.note} -xxx {.title} -Note -xxx - -The AES Key is used as both an encryption and decryption key. It is -recommended to keep it in [a separate configuration -file](https://asab.readthedocs.io/en/latest/asab/config.html#including-other-configuration-files) -that is not exposed anywhere publicly. - -The actual binary AES Key is obtained from the [aes_key]{.title-ref} -specified in the config file by encoding and hashing it using the -standard [hashlib](https://docs.python.org/3/library/hashlib.html) -algorithms, so do not worry about the length and type of the key. -xxx - -### Encrypting data - -The `Upsertor.set()`{.interpreted-text role="func"} method has an -optional boolean parameter [encrypt]{.title-ref} for encrypting the data -before they are stored. Only values of the type `bytes` can be -encrypted. If you want to encrypt other values, encode them first. - -``` {.python} -message = "This is a super secret message!" -number = 2023 -message_binary = message.encode("ascii") -number_binary = number.encode("ascii") - -u.set("message", message_binary, encrypt=True) -u.set("number", number_binary, encrypt=True) -object_id = await u.execute() -``` - -### Decrypting data - -The `StorageService.get()`{.interpreted-text role="func"} coroutine -method has an optional parameter [decrypt]{.title-ref} which takes an -`iterable` object (i.e. a list, tuple, set, ...) with the names of keys -whose values are to be decrypted. - -``` {.python} -data = await storage.get( - collection="test-collection", - obj_id=object_id, - decrypt=["message", "number"] - ) -``` - -If some of the keys to be decrypted are missing in the required -document, the method will ignore them and continue. - -xxx {.note} -xxx {.title} -Note -xxx - -Data that has been encrypted can be identified by the prefix -"$aes-cbc$" and are stored in a binary format. -xxx - -### Under the hood - -For encrypting data, we use the certified symmetric AES-CBC algorithm. -In fact, the abstract base class `StorageServiceABC`{.interpreted-text -role="class"} provides two methods `aes_encrypt()`{.interpreted-text -role="func"} and `aes_decrypt()`{.interpreted-text role="func"} that are -called automatically in `Upsertor.set()`{.interpreted-text role="func"} -and `StorageService.get()`{.interpreted-text role="func"} methods when -the parameter [encrypt]{.title-ref} or [decrypt]{.title-ref} is -specified. - -AES-CBC is a mode of operation for the Advanced Encryption Standard -(AES) algorithm that provides confidentiality and integrity for data. In -AES-CBC, the plaintext is divided into blocks of fixed size (usually 128 -bits), and each block is encrypted using the AES algorithm with a secret -key. - -CBC stands for "Cipher Block Chaining" and it is a technique that adds -an extra step to the encryption process to ensure that each ciphertext -block depends on the previous one. This means that any modification to -the ciphertext will produce a completely different plaintext after -decryption. - -The algorithm is a symmetric cipher, which is suitable for encrypting -large amounts of data. It requires much less computation power than -asymmetric ciphers and is much more useful for bulk encrypting large -amounts of data. diff --git a/docs/topics/asab/storage/inmemory.md b/docs/topics/asab/storage/inmemory.md deleted file mode 100644 index c06df6c62..000000000 --- a/docs/topics/asab/storage/inmemory.md +++ /dev/null @@ -1,24 +0,0 @@ -Storing data in memory ----------------------- - -If the option [inmemory]{.title-ref} is set, ASAB will store data in its -own memory. In particular, [asab.StorageService]{.title-ref} is -initialized with an attribute [InMemoryCollections]{.title-ref} which is -a dictionary where all the collections are stored in. - -xxx {.note} -xxx {.title} -Note -xxx - -You can go through all the databases directly by accessing -[InMemoryCollections]{.title-ref} attribute, although we do not -recommend that. - -``` {.python} -import pprint - -storage = self.get_service("asab.StorageService") -pprint.pprint(storage.InMemoryCollections, indent=2) -``` -xxx \ No newline at end of file diff --git a/docs/topics/asab/storage/intro.md b/docs/topics/asab/storage/intro.md deleted file mode 100644 index 4d2bca088..000000000 --- a/docs/topics/asab/storage/intro.md +++ /dev/null @@ -1,44 +0,0 @@ -Storage -======= - -The ASAB's Storage Service supports data storage in-memory or in -dedicated document databases, including -[MongoDB](https://www.mongodb.com/) and -[ElasticSearch](https://www.elastic.co/). - -Configuration -------------- - -First, specify the storage type in the configuration. The options for -the storage type are: - -- `inmemory`: Collects data directly in memory -- `mongodb`: Collects data using MongoDB database. Depends on - [pymongo](https://pymongo.readthedocs.io/en/stable/) and - [motor](https://motor.readthedocs.io/en/stable/api-asyncio/asyncio_motor_collection.html) - libraries. -- `elasticsearch`: Collects data using ElasticSearch database. - Depends on [aiohttp](https://docs.aiohttp.org/en/latest/) library. - -Storage Service provides a unified interface for accessing and -manipulating collections across multiple database technologies. - -``` {.ini} -[asab:storage] -type=mongodb -``` - -For accessing the storage, simply add -[asab.storage.Module]{.title-ref}` when initializing and register the -service. - -``` {.python} -class MyApplication(asab.Application): - - async def initialize(self): - - self.add_module(asab.storage.Module) - - async def main(self): - storage = self.get_service("asab.StorageService") -``` diff --git a/docs/topics/asab/storage/manipulation_with_databases.md b/docs/topics/asab/storage/manipulation_with_databases.md deleted file mode 100644 index ef5327226..000000000 --- a/docs/topics/asab/storage/manipulation_with_databases.md +++ /dev/null @@ -1,107 +0,0 @@ - -Manipulation with databases ---------------------------- - -### Upsertor - -Upsertor is an object that works like a pointer to the specified -database and optionally to object id. It is used for inserting new -objects, updating existing objects and deleting them. - -``` python -u = storage.upsertor("test-collection") -``` - -The `StorageService.upsertor()` method -creates an upsertor object associated with the specified collection. It -takes [collection]{.title-ref} as an argument and can have two -parameters [obj_id]{.title-ref} and [version]{.title-ref}, which are -used for getting an existing object by its ID and version. - -### Inserting an object - -For inserting an object to the collection, use the `Upsertor.set()` method. - -``` python -u.set("key", "value") -``` - -To execute these procedures, simply run the `Upsertor.execute()` coroutine method, which commits the upsertor data to the storage and returns the ID of the object. Since it is a coroutine, it must be awaited. - -``` python -object_id = await u.execute() -``` - -The `Upsertor.execute()` method has optional parameters `custom_data` and `event_type`, which are used for webhook requests. - -``` python -object_id = await u.execute( - custom_data= {"foo": "bar"}, - event_type="object_created" - ) -``` - -### Getting a single object - -For getting a single object, use -`StorageService.get()`coroutine method -that takes two arguments `collection` and -`obj_id` and finds an object by its ID in collection. - -``` python -obj = await storage.get(collection="test-collection", obj_id=object_id) -print(obj) -``` - -When the requested object is not found in the collection, the method -raises `KeyError`. Remember to handle this exception properly when using -databases in your services and prevent them from crashing! - - -!!! note - - MongoDB storage service in addition provides a coroutine method - `get_by()` which is used for accessing an - object by finding its key-value pair. - - ``` python - obj = await storage.get_by(database="test-collection", key="key", value="value") - ``` - -### Updating an object - -For updating an object, first obtain the upsertor specifying its -`obj_id` and `version`. - -``` python -u = storage.upsertor( - collection="test-collection", - obj_id=object_id, - version=obj['_v'] -) -``` - -We strongly recommend to read the version from the object such as above. -That creates a soft lock on the record. It means that if the object is -updated by other component in meanwhile, your upsertor will fail and you -should retry the whole operation. The new objects should have a version -set to 0, which is done by default. - -After obtaining an upsertor, you can update the object via the -(Upsertor.set)(reference/storage/upsertor/#asab.storage.upsertor.UpsertorABC.set) coroutine. - -``` python -u.set("key", "new_value") -object_id = await u.execute() -``` - -### Deleting an object - -For deleting an object from database, use the -`StorageService.delete()`{.interpreted-text role="func"} coroutine -method which takes arguments [collection]{.title-ref} and -[obj_id]{.title-ref}, deletes the object and returns its ID. - -``` python -deleted_id = await u.delete("test-collection", object_id) -``` diff --git a/docs/topics/asab/storage/mongodb.md b/docs/topics/asab/storage/mongodb.md deleted file mode 100644 index 27bffabab..000000000 --- a/docs/topics/asab/storage/mongodb.md +++ /dev/null @@ -1,50 +0,0 @@ -Storing data in MongoDB ------------------------ - -If the option [mongodb]{.title-ref} is set, ASAB will store data in -MongoDB database. - -ASAB uses [motor library](https://pypi.org/project/motor/) which -provides non-blocking MongoDB driver for [asyncio]{.title-ref}. - -You can specify the database name and URL for MongoDB in config file -(the following example is the default configuration): - -``` {.ini} -[asab:storage] -type=mongodb -mongodb_uri=mongodb://localhost:27017 -mongodb_database=asabdb -``` - -You can use all the methods from the abstract class. MongoDB Storage -class provides in addition two methods, -`StorageService.get_by()`{.interpreted-text role="func"} and -`StorageService.collection()`{.interpreted-text role="func"}. - -The method `StorageService.get_by()`{.interpreted-text role="func"} is -used in the same way as `StorageService.get()`{.interpreted-text -role="func"} except that it takes the arguments [key]{.title-ref} and -[value]{.title-ref} instead of [obj_id]{.title-ref}. - -``` {.python} -obj = await storage.get_by(database="test-collection", key="key", value="value") -``` - -The method `collection()`{.interpreted-text role="func"} is used for -accessing the database directly. It takes [collection]{.title-ref} as -the argument and returns -[motor.motor_asyncio.AsyncIOMotorCollection]{.title-ref} object, which -can be used for calling MongoDB directives. - -``` {.python} -collection = await storage.collection("test-collection") -cursor = collection.find({}) -while await cursor.fetch_next: - data = cursor.next_object() - pprint.pprint(data) -``` - -The full list of methods suitable for this object is described in the -[official -documentation](https://motor.readthedocs.io/en/stable/api-asyncio/asyncio_motor_collection.html). diff --git a/docs/topics/asab/various.md b/docs/topics/asab/various.md deleted file mode 100644 index 1c82ddbd5..000000000 --- a/docs/topics/asab/various.md +++ /dev/null @@ -1,51 +0,0 @@ -Various utility classes -======================= - -# TODO: automodule members="" undoc-members="" show-inheritance=""} -asab.abc -xxx - -Singleton ---------- - -# TODO: automodule members="" undoc-members=""} -asab.abc.singleton -xxx - -Usage: - -``` {.python} -import asab - -class MyClass(metaclass=asab.Singleton): - ... -``` - -Persistent dictionary ---------------------- - -# TODO: automodule members="" undoc-members="" show-inheritance=""} -asab.pdict -xxx - -*Note*: A recommended way of initializing the persistent dictionary: - -``` {.python} -PersistentState = asab.PersistentDict("some.file") -PersistentState.setdefault('foo', 0) -PersistentState.setdefault('bar', 2) -``` - -Timer ------ - -# TODO: automodule members="" undoc-members="" show-inheritance=""} -asab.timer -xxx - -Sockets -------- - -# TODO: automodule members="" undoc-members="" show-inheritance=""} -asab.socket -xxx diff --git a/docs/topics/asab/web/auth.md b/docs/topics/asab/web/auth.md deleted file mode 100644 index c92e015d9..000000000 --- a/docs/topics/asab/web/auth.md +++ /dev/null @@ -1,18 +0,0 @@ -Authorization -============= - -# TODO: autofunction% -require -xxx - -# TODO: autofunction% -noauth -xxx - -# TODO: autoclass% -AuthService - -# TODO: automethod% -install -xxx -xxx diff --git a/docs/topics/asab/web/cors.md b/docs/topics/asab/web/cors.md deleted file mode 100644 index 5ec171940..000000000 --- a/docs/topics/asab/web/cors.md +++ /dev/null @@ -1,23 +0,0 @@ -Cross-Origin Resource Sharing (CORS) -==================================== - -When you create a web container, you specify a config section name. In -the example below it's \`myapp:web\`: - -``` {.python} -asab.web.WebContainer(self.WebService, "myapp:web") -``` - -You can then configure CORS by running your app with a config file with -this contents: - -``` {.INI} -[myapp:web] -cors=* -cors_preflight_paths=/* -``` - -- **cors**: contents of the Access-Control-Allow-Origin header -- **cors\_preflight\_paths**: a pattern for endpoints that shall - return responses to pre-flight requests (OPTIONS). Value must start - with \"/\". diff --git a/docs/topics/asab/web/index.md b/docs/topics/asab/web/index.md deleted file mode 100644 index 190bcd206..000000000 --- a/docs/topics/asab/web/index.md +++ /dev/null @@ -1,148 +0,0 @@ -The web server -============== - -ASAB provides a web server in a :py`asab.web`{.interpreted-text -role="mod"} module. This module offers an integration of a -:py`aiohttp`{.interpreted-text role="mod"} [web -server](http://aiohttp.readthedocs.io/en/stable/web.html). - -1. Before you start, make sure that you have - :py`aiohttp`{.interpreted-text role="mod"} module installed. - -``` {.bash} -$ pip3 install aiohttp -``` - -2. The following code creates a simple web server application - -``` {.python} -#!/usr/bin/env python3 -import asab -import asab.web -import aiohttp - -class MyApplication(asab.Application): - - def __init__(self): - super().__init__() - - # Load the ASAB Web module - self.add_module(asab.web.Module) - - # Locate the ASAB Web service - websvc = self.get_service("asab.WebService") - - # Create the Web container - container = asab.web.WebContainer(websvc, 'my:web', config={"listen": "0.0.0.0:8080"}) - - # Add a route to the handler - container.WebApp.router.add_get('/hello', self.hello) - - # This is the web request handler - async def hello(self, request): - return aiohttp.web.Response(text='Hello!\n') - -if __name__ == '__main__': - app = MyApplication() - app.run() -``` - -3. Test it with [curl]{.title-ref} - -``` {.bash} -$ curl http://localhost:8080/hello -Hello! -``` - -Web Service ------------ - -Service location example: - -``` {.python} -from asab.web import Module -self.add_module(Module) -svc = self.get_service("asab.WebService") -``` - -Configuration -------------- - -The default configuration of the [web]{.title-ref} container in ASAB is -following: - -``` {.ini} -[web] -listen=0.0.0.0:8080 -``` - -Multiple listening interfaces can be specified: - -``` {.ini} -[web] -listen: - 0.0.0.0:8080 - :: 8080 -``` - -Multiple listening interfaces, one with HTTPS (TLS/SSL) can be -specified: - -``` {.ini} -[web] -listen: - 0.0.0.0 8080 - :: 8080 - 0.0.0.0 8443 ssl:web - -[ssl:web] -cert=... -key=... -... -``` - -Multiple interfaces, one with HTTPS (inline): - -``` {.ini} -[web] -listen: - 0.0.0.0 8080 - :: 8080 - 0.0.0.0 8443 ssl - -# The SSL parameters are inside of the WebContainer section -cert=... -key=... -... -``` - -Other available options are: - -> - [backlog]{.title-ref} -> - [rootdir]{.title-ref} -> - [servertokens]{.title-ref} (default value [full]{.title-ref}) -> - [cors]{.title-ref} -> - [cors\_preflight\_paths]{.title-ref} - -TLS/SSL paramereters: - -> - [cert]{.title-ref} -> - [key]{.title-ref} -> - [password]{.title-ref} -> - [cafile]{.title-ref} -> - [capath]{.title-ref} -> - [ciphers]{.title-ref} -> - [dh\_params]{.title-ref} -> - \`verify\_mode\`: one of [CERT\_NONE]{.title-ref}, -> [CERT\_OPTIONAL]{.title-ref} or [CERT\_REQUIRED]{.title-ref} -> - [check\_hostname]{.title-ref} -> - [options]{.title-ref} - -Sessions --------- - -ASAB Web Service provides an implementation of the web sessions. - -TODO: \... - -TODO: \... diff --git a/docs/topics/asab/web/restapidocs.md b/docs/topics/asab/web/restapidocs.md deleted file mode 100644 index a5aa6ff23..000000000 --- a/docs/topics/asab/web/restapidocs.md +++ /dev/null @@ -1,141 +0,0 @@ -REST API Docs -============= - -ASAB\'s API service generates a [Swagger -documentation](https://swagger.io/specification) which automatically -shows all of your endpoints and you can add summaries, descriptions, -tags and more. - -If you want Authorization in Swagger docs, you will need an -OpenIDConnect endpoint. - -In your microservice --------------------- - -First you need to initialize the API Service: - -``` {.python} -# Initialize API service -self.ApiService = asab.api.ApiService(self) - -# Introduce Web to API Service -self.ApiService.initialize_web() -``` - -After initializing the API Service a **/doc** endpoint will become -available. You will notice that some or none of your endpoints have -summaries, tags or descriptions. - -That\'s because you need to add a docstring to your endpoint method: - -``` {.python} -async def endpoint(self, request): - """ - Summary looks like this and takes the first line from docstring. - - Description of what this endpoint does. - - --- - tags: [asab.mymicroservice] - """ -``` - -Also by adding a docstring to your ASAB Application, a description will -be automatically added to the top of the Swagger docs: - -``` {.python} -class TutorialApp(asab.Application): - """ - TutorialApp is the best microservice in the world! - - The description supports HTML tags - """ -``` - -Authorization in Swagger ------------------------- - -Authorization requires making an OpenIDConnect endpoint with an -Authorization and Token endpoint (like with using [SeaCat -Auth](https://github.com/TeskaLabs/seacat-auth)). - -After your endpoint has authorization, [here\'s an -example](https://github.com/TeskaLabs/asab/blob/master/examples/web-authz-userinfo.py), -add the Authorization and Token endpoints into your -[config](#configuration). - -For the authorization bearer token to be added to the request, a scope -is needed to be put into the security parameter in a docstring. It does -not matter what it is called or if it exists, but it\'s needed to be -there. But \"[- oAuth:]{.title-ref}\" always needs to be there. - -``` {.python} -@asab.web.authz.required("resource:topsecret") -async def top_secret_endpoint(self, request): - """ - Top secret! - - --- - tags: [asab.coolestmicroservice] - security: - - oAuth: - - read - """ -``` - -After setting up Authorization, a green [Authorize]{.title-ref} button -should appear in the Swagger docs. - -Configuration -------------- - -For authorization you will need to add a [authorizationUrl]{.title-ref} -and \`tokenUrl\`: - -``` {.ini} -[asab:doc] -authorizationUrl=http://localhost:8080/openidconnect/authorize -tokenUrl=http://localhost:8080/openidconnect/token -``` - -If you have an endpoint that requires a scope, you can add it with the -configuration file: - -``` {.ini} -[asab:doc] -scopes=read,write -``` - -Tags ----- - -You can label your handler methods with custom tags. These tags are used -for grouping and sorting your endpoints on the documentation page. - -``` {.python} -async def my_method(self, request): -""" ---- -tags: ['custom tag 1', 'custom tag 2', 'custom tag 3'] -""" -``` - -(Remember to use exactly three dashes on the separate line and put tags -in array with [\[\]]{.title-ref} even if you want to have a single tag). - -If there is no custom tag defined, the tag name is automatically set to -be [module\_name]{.title-ref}. If you do not want to use custom tags but -still would like to sort the routes, you can configure the options in -the config file: - -``` {.ini} -[asab:doc] -default_route_tag=class_name -``` - -There are two options for \`default\_route\_tag\`: - -- \`module\_name\`: All tags without custom name are displayed with - the name of the **module** where the handler is defined. -- \`class\_name\`: All tags without custom name are displayed with the - name of the **class** where the handler is defined. diff --git a/docs/topics/asab/zookeeper.md b/docs/topics/asab/zookeeper.md deleted file mode 100644 index d3a9a0f9f..000000000 --- a/docs/topics/asab/zookeeper.md +++ /dev/null @@ -1,190 +0,0 @@ -Zookeeper {#zookeeper-ref} -========= - -The [asab.zookeeper]{.title-ref} is a [Apache -Zookeeper](https://zookeeper.apache.org) asynchronous client based on -[Kazoo](https://github.com/python-zk/kazoo) library. - -Apache ZooKeeper is a distributed coordination service that provides a -hierarchical key-value data store, called a znode tree, to store and -manage configuration, coordination, and synchronization data. The znode -tree is similar to a file system tree, where each znode is like a file -or a directory. - -Apache ZooKeeper can be used to design microservices in a stateless -manner by managing and coordinating the state information between -microservices. In this design, each microservice does not store any -state information, but instead relies on ZooKeeper for state management. - -Zookeeper container -------------------- - -A Zookeeper container represents a connectivity to Apache Zookeeper -server(s). The application can operate multiple instances of Zookeeper -container. - -This code illustrates the typical way how to create Zookeeper container: - -``` {.python} -import asab.zookeeper - -class MyApplication(asab.Application): - - def __init__(self): - ... - - # Load the ASAB Zookeeper module - self.add_module(asab.zookeeper.Module) - - # Initialize ZooKeeper Service - self.ZooKeeperService = self.get_service("asab.ZooKeeperService") - - # Create the Zookeeper container - self.ZooKeeperContainer = asab.zookeeper.ZooKeeperContainer(self.ZooKeeperService) - - # Subscribe to Zookeeper container ready event - self.PubSub.subscribe("ZooKeeperContainer.state/CONNECTED!", self._on_zk_connected) - - - async def _on_zk_connected(self, event_name, zookeeper): - if zookeeper != self.ZooKeeperContainer: - return - - print("Connected to Zookeeper!") -``` - -# TODO: autoclass% -ZooKeeperContainer -xxx - -Specifications are obtained from: - -1. [z\_path]{.title-ref} argument, which is Zookeeper URL (see below) -2. the configuration section specified by - [config\_section\_name]{.title-ref} argument -3. [ASAB\_ZOOKEEPER\_SERVERS]{.title-ref} environment variable - -The [z\_path]{.title-ref} argument has precedence over config but the -implementation will look at configuration if [z\_path]{.title-ref} URL -is missing completely or partially. Also, if configuration section -doesn\'t provide information about servers, -[ASAB\_ZOOKEEPER\_SERVERS]{.title-ref} environment variable is used. - -### Example of configuration section - -``` {.ini} -[zookeeper] -servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 -path=myfolder -``` - -### Example of [ASAB\_ZOOKEEPER\_SERVERS]{.title-ref} environment variable - -``` {.ini} -ASAB_ZOOKEEPER_SERVERS=zookeeper-1:2181,zookeeper-2:2181 -``` - -### Supported types of [z\_path]{.title-ref} URLs - -1. Absolute URL - - > [zookeeper://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/etc/configs/file1]{.title-ref} - > - > The URL contains all information for a connectivity. - -2. URL without servers with absolute path - - > [zookeepers:///etc/configs/file1]{.title-ref} - > - > In this case the relative url is expanded as follows: - > [zookeeper://{zookeeper\_servers}/etc/configs/file1]{.title-ref} - > - > Where [{zookeeper\_servers}]{.title-ref} is substituted with the - > [servers]{.title-ref} entry of the \[zookeeper\] configuration - > file section. - -3. URL without servers with relative path - - > [zookeeper:./etc/configs/file1]{.title-ref} - > - > In this case, the relative URL is expanded as follows: - > [zookeper://{zookeeper\_servers}/{zookeeper\_path}/etc/configs/file1]{.title-ref} - > - > Where {zookeeper\_servers} is substituted with the - > [servers]{.title-ref} entry of the \[zookeeper\] configuration - > file section and {zookeeper\_path} is substituted with the - > \"path\" entry of the \[zookeeper\] configuration file section. - -# TODO: automethod% -ZooKeeperContainer.is\_connected -xxx - -Reading from Zookeeeper ------------------------ - -# TODO: automethod% -ZooKeeperContainer.get\_children -xxx - -# TODO: automethod% -ZooKeeperContainer.get\_data -xxx - -# TODO: automethod% -ZooKeeperContainer.get\_raw\_data -xxx - -Advertisement into Zookeeper ----------------------------- - -# TODO: automethod% -ZooKeeperContainer.advertise -xxx - -PubSub messages ---------------- - -%TODO: option% -ZooKeeperContainer.state/CONNECTED! -xxx - -%TODO: option% -ZooKeeperContainer.state/LOST! -xxx - -%TODO: option% -ZooKeeperContainer.state/SUSPENDED! -xxx - -When a Zookeeper connection is first created, it is in the LOST state. -After a connection is established it transitions to the CONNECTED state. -If any connection issues come up or if it needs to connect to a -different Zookeeper cluster node, it will transition to SUSPENDED to let -you know that commands cannot currently be run. The connection will also -be lost if the Zookeeper node is no longer part of the quorum, resulting -in a SUSPENDED state. - -Upon re-establishing a connection the client could transition to LOST if -the session has expired, or CONNECTED if the session is still valid. - -For mor info, visit: - - -Kazoo ------ - -Kazoo is the synchronous Python library for Apache Zookeeper. - -It can be used directly for a more complicated tasks. Kazoo -[client]{.title-ref} is accessible at -[ZooKeeperContainer.ZooKeeper.Client]{.title-ref}. Synchronous methods -of Kazoo client must be executed using [ProactorService]{.title-ref}. - -Here is the example: - -``` {.python} -def write_to_zk(): - self.ZooKeeperContainer.ZooKeeper.Client.create(path, data, sequence=True, ephemeral=True, makepath=True) - -await self.ZooKeeperContainer.ZooKeeper.ProactorService.execute(write_to_zk) -``` diff --git a/mkdocs.yml b/mkdocs.yml index 62e69102f..eb1df2489 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -184,14 +184,7 @@ nav: - CounterWithDynamicTags: reference/metrics/counter_with_dynamic_tags.md - AggregationCounterWithDynamicTags: reference/metrics/aggregation_counter_with_dynamic_tags.md - HistogramWithDynamicTags: reference/metrics/histogram_with_dynamic_tags.md - - Storage Service: - - StorageService: reference/storage/service.md - - Upsertor: reference/storage/upsertor.md - - Exceptions: reference/storage/exceptions.md - - ElasticSearch: reference/storage/elasticsearch.md - - MongoDB: reference/storage/mongodb.md - - In-Memory: reference/storage/inmemory.md - - Alert Service: reference/alert/reference.md + - Storage Service: reference/storage/reference.md - Utility functions and classes: - Utility functions: reference/utils/utils.md - Persistent dictionary: reference/utils/persistent_dictionary.md From 976f1cb1df5524d622a13400f454a44d60dc2b47 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 8 Aug 2023 17:24:52 +0200 Subject: [PATCH 146/154] Change docstrings indentation --- asab/storage/service.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/asab/storage/service.py b/asab/storage/service.py index 0ffc6fd89..56df15b64 100644 --- a/asab/storage/service.py +++ b/asab/storage/service.py @@ -63,27 +63,26 @@ def upsertor(self, collection: str, obj_id=None, version: int = 0) -> None: - If there will be a colliding object already stored in a storage, `execute()` method will fail on `DuplicateError`. Args: - - collection (str): Name of collection to work with - obj_id: Primary identification of an object in the storage (e.g. primary key) - version (int): Specify a current version of the object and hence prevent byzantine faults. \ - You should always read the version from the storage upfront, prior using an upsertor. \ - That creates a soft lock on the record. It means that if the object is updated by other \ - component in meanwhile, your upsertor will fail and you should retry the whole operation. \ - The new objects should have a `version` set to 0. + collection: Name of collection to work with + obj_id: Primary identification of an object in the storage (e.g. primary key) + version: Specify a current version of the object and hence prevent byzantine faults. \ + You should always read the version from the storage upfront, prior using an upsertor. \ + That creates a soft lock on the record. It means that if the object is updated by other \ + component in meanwhile, your upsertor will fail and you should retry the whole operation. \ + The new objects should have a `version` set to 0. """ pass @abc.abstractmethod - async def get(self, collection: str, obj_id, decrypt=None) -> dict: + async def get(self, collection: str, obj_id, decrypt: bool = None) -> dict: """ Get object from collection by its ID. Args: - collection (str): Collection to get from. + collection: Collection to get from. obj_id: Object identification. - decrypt (bool): Set of fields to decrypt. + decrypt: Set of fields to decrypt. Returns: The object retrieved from a storage. From 344ee334538c1808e283932512e99556b922bde7 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 8 Aug 2023 17:41:15 +0200 Subject: [PATCH 147/154] Add Zookeeper section --- docs/reference/zookeeper/reference.md | 143 ++++++++++++++++++++++++++ mkdocs.yml | 2 +- 2 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 docs/reference/zookeeper/reference.md diff --git a/docs/reference/zookeeper/reference.md b/docs/reference/zookeeper/reference.md new file mode 100644 index 000000000..ac971c356 --- /dev/null +++ b/docs/reference/zookeeper/reference.md @@ -0,0 +1,143 @@ +# Zookeeper + +The `asab.zookeeper` is a [ApacheZookeeper](https://zookeeper.apache.org) asynchronous client based on [Kazoo](https://github.com/python-zk/kazoo) library. + +Apache ZooKeeper is a distributed coordination service that provides a hierarchical key-value data store, +called **a znode tree**, to store and manage configuration, coordination, and synchronization data. +The znode tree is similar to a file system tree, where each znode is like a file or a directory. + +Apache ZooKeeper can be used to design microservices in a stateless manner by managing and coordinating the state information between microservices. +In this design, each microservice does not store any state information, but instead relies on ZooKeeper for state management. + +## Zookeeper container + +A Zookeeper container represents a connectivity to Apache Zookeeper server(s). +The application can operate multiple instances of Zookeeper container. + +This code illustrates the typical way how to create Zookeeper container: + +``` python +import asab.zookeeper + +class MyApplication(asab.Application): + + async def initialize(self): + # Load the ASAB Zookeeper module + self.add_module(asab.zookeeper.Module) + + # Initialize ZooKeeper Service + self.ZooKeeperService = self.get_service("asab.ZooKeeperService") + + # Create the Zookeeper container + self.ZooKeeperContainer = asab.zookeeper.ZooKeeperContainer(self.ZooKeeperService) + + # Subscribe to Zookeeper container ready event + self.PubSub.subscribe("ZooKeeperContainer.state/CONNECTED!", self._on_zk_connected) + + async def _on_zk_connected(self, event_name, zookeeper): + if zookeeper != self.ZooKeeperContainer: + return + print("Connected to Zookeeper!") +``` + +Specifications are obtained from: + +1. `z_path` argument, which is Zookeeper URL (see below) +2. the configuration section specified by `config_section_name` argument +3. `$ASAB_ZOOKEEPER_SERVERS` environment variable + +The `z_path` argument has precedence over config but the implementation will +look at configuration if `z_path` URL is missing completely or partially. +Also, if configuration section doesn't provide information about servers, +`ASAB_ZOOKEEPER_SERVERS` environment variable is used. + +!!! example "Example of configuration section" + + ``` ini + [zookeeper] + servers=zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181 + path=myfolder + ``` + +!!! example "Example of `$ASAB_ZOOKEEPERS_SERVERS` environment variable" + + ``` ini + ASAB_ZOOKEEPER_SERVERS=zookeeper-1:2181,zookeeper-2:2181 + ``` + +### Supported types of `z_path` URLs + +1. Absolute URL: + + ``` ini + zookeeper://zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181/etc/configs/file1 + ``` + The URL contains all information for a connectivity. + +2. URL without servers with absolute path: + + ``` ini + zookeepers:///etc/configs/file1 + ``` + In this case the relative url is expanded as follows: + + ```ini + zookeeper://{zookeeper_servers}/etc/configs/file1 + ``` + Where `{zookeeper_servers}` is substituted with the `servers` entry of the `[zookeeper]` configuration file section. + +3. URL without servers with relative path + + ```ini + zookeeper:./etc/configs/file1 + ``` + + In this case, the relative URL is expanded as follows: + + ```ini + zookeper://{zookeeper_servers}/{zookeeper_path}/etc/configs/file1 + ``` + + Where `{zookeeper_servers}` is substituted with the servers entry of the `[zookeeper]` configuration file section + a nd `{zookeeper_path}` is substituted with the "path" entry of the `[zookeeper]` configuration file section. + + +## Reading from Zookeeeper + +## Advertisement into Zookeeper + +## PubSub messages + +ZooKeeperContainer.state/CONNECTED! + +ZooKeeperContainer.state/LOST! + +ZooKeeperContainer.state/SUSPENDED! + +When a Zookeeper connection is first created, it is in the LOST state. +After a connection is established it transitions to the CONNECTED state. +If any connection issues come up or if it needs to connect to a +different Zookeeper cluster node, it will transition to SUSPENDED to let +you know that commands cannot currently be run. The connection will also +be lost if the Zookeeper node is no longer part of the quorum, resulting +in a SUSPENDED state. + +Upon re-establishing a connection the client could transition to LOST if +the session has expired, or CONNECTED if the session is still valid. + +For mor info, visit (https://kazoo.readthedocs.io/en/latest/basic_usage.html#understanding-kazoo-states) + +## Kazoo + +Kazoo is the synchronous Python library for Apache Zookeeper. + +It can be used directly for a more complicated tasks. Kazoo `client` is accessible at `ZooKeeperContainer.ZooKeeper.Client`. +Synchronous methods of Kazoo client must be executed using `ProactorService`. + +!!! example + ``` python + def write_to_zk(): + self.ZooKeeperContainer.ZooKeeper.Client.create(path, data, sequence=True, ephemeral=True, makepath=True) + + await self.ZooKeeperContainer.ZooKeeper.ProactorService.execute(write_to_zk) + ``` diff --git a/mkdocs.yml b/mkdocs.yml index eb1df2489..ac541bf7c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -168,7 +168,6 @@ nav: - TLS/SSL: reference/web/tls.md - Authorization and multitenancy: reference/web/authorization_multitenancy.md - Cross-Origin Resource Sharing: reference/web/cors.md - - Configuration: reference/config/reference.md - Logging: reference/logging/reference.md - PubSub: reference/pubsub/reference.md @@ -185,6 +184,7 @@ nav: - AggregationCounterWithDynamicTags: reference/metrics/aggregation_counter_with_dynamic_tags.md - HistogramWithDynamicTags: reference/metrics/histogram_with_dynamic_tags.md - Storage Service: reference/storage/reference.md + - Zookeeper: reference/zookeeper/reference.md - Utility functions and classes: - Utility functions: reference/utils/utils.md - Persistent dictionary: reference/utils/persistent_dictionary.md From 40d754954ebfcc972ab436c34c3dce4e9d0c7520 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Tue, 8 Aug 2023 17:45:13 +0200 Subject: [PATCH 148/154] Merge Metrics into one file --- docs/reference/metrics/reference.md | 378 ++++++++++++++++++++++++++ docs/topics/asab/metrics/built-ins.md | 63 ----- docs/topics/asab/metrics/intro.md | 110 -------- docs/topics/asab/metrics/tags.md | 66 ----- docs/topics/asab/metrics/targets.md | 137 ---------- mkdocs.yml | 12 +- 6 files changed, 379 insertions(+), 387 deletions(-) create mode 100644 docs/reference/metrics/reference.md delete mode 100644 docs/topics/asab/metrics/built-ins.md delete mode 100644 docs/topics/asab/metrics/intro.md delete mode 100644 docs/topics/asab/metrics/tags.md delete mode 100644 docs/topics/asab/metrics/targets.md diff --git a/docs/reference/metrics/reference.md b/docs/reference/metrics/reference.md new file mode 100644 index 000000000..4ffefe190 --- /dev/null +++ b/docs/reference/metrics/reference.md @@ -0,0 +1,378 @@ +# Metrics + +Metrics document the state of the application in a timescale manner. +For further analysis, connect your ASAB application to a time-series +database. [Influx](https://www.influxdata.com/) and +[Prometheus](https://prometheus.io/) are supported. + + +!!! example + + ``` python + class MyApplication(asab.Application): + async def initialize(self): + from asab.metrics import Module # (1)! + self.add_module(Module) + self.MetricsService = self.get_service('asab.MetricsService') # (2)! + self.MyCounter = self.MetricsService.create_counter("mycounter", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0}) # (3)! + + if __name__ == '__main__': + app = MyApplication() + app.run() + ``` + + 1. Import asab.metrics Module and add it to the application. + 2. Then, you can localize MetricsService. + 3. Use MetricsService to intialize the counter. + + +See the full example [here](https://github.com/TeskaLabs/asab/blob/master/examples/metrics.py). + +See reference [here](./../../../reference/metrics/service.md). + +## Types of Metrics + +- `Gauge` stores single numerical values which can go up and down. + Implements `set` method to set the metric values. +- `Counter` is a cumulative metric whose values can increase or decrease. + Implements `add` and `sub` methods. +- Event per Second Counter (`EPSCounter`) divides all values by delta time. +- `DutyCycle` measures the fraction of a period in which a signal/system is active +- `AggregationCounter` allows to `set` values based on an aggregation function. + `max` function is default. +- `Histogram` represents cumulative histogram with `set` method. + +`Counter`, `AggregationCounter` and `Histogram` come also in variants +respecting dynamic tags. (See section [Dynamic Tags](./tags.md)) + +All methods that create new metrics objects can be found in the Metrics +Service reference. You should never initiate a new metrics object on its +own, but always through Metrics Service. Metris initialization is meant +to be done in the init time of your application and **should not be done +during runtime**. + +## ASAB Metrics Interpretation + +Metrics Service not only creates new metrics but also periodically +collects their values and sends them to selected databases. Every 60 +seconds in the application lifetime, Metrics Service gathers values of +all ASAB metrics. All Counters (and metric types that inherit from +`Counter`) reset at this event to their +initial values by default. Interpretation of ASAB Counters is affected +by their resetable nature. Even though they monotonously increase, +resetting every minute gives them a different meaning. In a long-term +observation (that's how you most probably monitor the metrics in +time-series databases), these metrics count **events per minute**. Thus, +resettable Counters are presented to Prometheus database as gauge-type +metrics. Set the `reset` argument to `False` +when creating a new Counter to disable Counter resetting. This periodic +"flush" cycle also causes 60s delay of metric propagation into +supported time-series databases. +Please, see the Timestamp section explaining the origin of a timestamp in each metric record. + +## Initial Values + +You can initiate your metric instance **with or without initial values**. +Initial values are always present and presented to databases even without a single event changing the metric values. +You will always find a pair of value name and its value in resulting dataset. +Values (name and value pairs) added during runtime last only 60 s. +You might spot this feature as missing values in the resulting time-series dataset. + + +## Timestamp + +**Timestamp** contains the record of the precise moment the metric's +value was created or committed to the database. There are two types of +metrics: resettable (`is_reset` = True) and non-resettable +(`is_reset` = False). To reset a metric means to set it +back to its initial value (for example, back to 0). The metric's type +is determined by the `reset: bool = True` parameter of the metric's +constructor at the moment of creation. We measure values of non-resettable +metrics at the time of their creation (there are several possible +methods depending on the metric's general logic), while +the resettable ones are measured when we reset the data +(which is also the moment of them being sent into the database). + +| Metric Type | Description / Methods | Origin of the timestamp | is_reset | +| :-------------------------------- | :------------------------------------------- | :--------------------- | :-------- | +| `Gauge` | Stores single numerical values which can go up and down. `set()` | When value is set. `set()` | **False** | +| `Counter` (*Allows dynamic tags*) | A cumulative metric; values can increase or decrease. Never stops. `add()`, `sub()` | When value is set. `add()` or `sub()` | **False** | +| `Counter` (*Allows dynamic tags*) | A cumulative metric; values can increase or decrease. Set to 0 every 60 seconds. | On `flush()`, every 60 seconds | **True** | +| `EPSCounter` | Divides the count of events by the time of the application run. | On `flush()`, every 60 seconds | **False** | +| `EPSCounter` | Divides the count of events by the time difference between measurements. | On `flush()`, every 60 seconds | **True** | +| `DutyCycle` | The fraction of one period in which a signal/system is active. A 60% DC means the signal is on 60% and off 40% of the time. | On `flush()`, every 60 seconds | **True** | +| `Aggregation Counter` (*Allows dynamic tags*) | Keeps track of max or min value of the Counter. Keeps maximum value by default. | When value is set. `set()` | **False** | +| `Aggregation Counter` (*Allows dynamic tags*)| Keeps track of max or min value of the Counter in each 60s window. Keeps maximum value by default. | On `flush()`, every 60 seconds | **True** | +| `Histogram` (*Allows dynamic tags*) | Cumulative histogram with a `set()` method. | When value is set. `set()` | **False** | +| `Histogram` (*Allows dynamic tags*) | Cumulative histogram with a `set()` method. | On `flush()`, every 60 seconds | **True** | + + +# Monitoring +The Metrics module in ASAB serves to produce data - metrics. It does not store them, nor analyse. To get some overview, you must collect the metrics in a time-series database, or choose some custom way of monitoring. +InfluxDB and Prometheus databases are supported by ASAB and several endpoints can be used for data monitoring or collecting as well. + +## InfluxDB + +Metrics can be collected in the Influx time-series database. Metrics are being sent in 60s intervals to configured Influx instance. + +!!! example "Configuration example" + ``` {.} + [asab:metrics] + target=influxdb + + [asab:metrics:influxdb] + url=http://localhost:8086/ + bucket=my_bucket + org=my_org + token=my_token + ``` + +**InfluxDB 2.0 API parameters**: + +- **url** - (required) URL string of your InfluxDB. +- **bucket** - (required) Destination bucket for writing. +- **org** - (required) Destination organization for writing. +- **orgid** - (optional) ID of the destination organization for writing. + : (NOTE: If both orgID and org are specified, org takes + precedence) +- **token** - (required) API token to authenticate to the InfluxDB + +**InfluxDB \<1.8 API parameters**: +- **url** - (required) URL string of your InfluxDB. +- **username** - (required) name of InfluxDB user. +- **password** - (required) password of InfluxDB user. + +## Prometheus +Prometheus is a "pull model" time-series database. +Prometheus accesses `asab/v1/metrics` endpoint of ASAB ApiService. Thus, connecting ASAB to +Prometheus requires APIService initialization. All other configuration is required on the Prometheus side. +ASAB metrics are presented to Prometheus in [OpenMetrics](https://openmetrics.io/) standard format. + +!!! example "ApiService initialization" + + ``` python + class MyApplication(asab.Application): + async def initialize(self): + from asab.metrics import Module + self.add_module(Module) + self.MetricsService = self.get_service('asab.MetricsService') + self.MyCounter = self.MetricsService.create_counter("mycounter", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0}) + + # Initialize API service + self.ApiService = asab.api.ApiService(self) + self.ApiService.initialize_web() + + if __name__ == '__main__': + app = MyApplication() + app.run() + ``` + +!!! example "prometheus.yaml configuration file example" + + ``` {.yaml} + global: + scrape_interval: 15s + scrape_timeout: 10s + evaluation_interval: 15s + + scrape_configs: + - job_name: 'metrics_example' + metrics_path: '/asab/v1/metrics' + scrape_interval: 10s + static_configs: + - targets: ['127.0.0.1:8080'] + ``` + +!!! note + + To satisfy the OpenMetrics format required by Prometheus, you should + follow the instructions below: + + - Metrics names must fit regex `[a-zA-Z:][a-zA-Z0-9_:]*`. (Any other + characters are replaced by an underscore. Leading underscores and + numbers are stripped. These changes proceed without warning.) + - Metrics names MUST NOT end with "total" or "created". + - Tags SHOULD contain items "unit" and "help" providing metadata to + Prometheus. + - Values MUST be float or integer. + + +## Metrics Endpoints + +The **API Service** in ASAB offers several endpoints that monitor +internal ASAB functionality. Some of them present the current state of +metrics. Check for Swagger documentation of your ASAB Application REST +API by visiting the `/doc` endpoint. + +`/asab/v1/metrics` + +- This endpoint returns metrics in OpenMetrics format and its primary + purpose is to satisfy Prometheus database needs. + +`/asab/v1/metrics.json` + +- This endpoint presents metrics data in JSON format. + +`/asab/v1/watch_metrics` + +- Use this endpoint for developing or monitoring your app from the + terminal. It returns a simple table of ASAB metrics. You can filter + metrics by name using the `filter` parameter and `tags` parameter to + show or hide tags. + +!!! example + + ``` {.} + watch curl localhost:8080/asab/v1/watch_metrics + ``` + + ``` {.} + watch curl localhost:8080/asab/v1/watch_metrics?name=web_requests_duration_max,tags=True + ``` + +## HTTP Target + +For use cases requiring a push model of metrics digestion, there is an +HTTP Target. HTTP Target creates a POST request every 60 seconds to configured URL with +the current metrics state sent as JSON body. Configuration is required. + +!!! example "Configuration example" + ``` {.} + [asab:metrics] + target=http + + [asab:metrics:http] + url=http://consumer_example:8080/consume + ``` + + +# Tags +Tags allow filtering and aggregating collected metrics. +They provide dimensions for further analysis of the collected data. +There are two means of assigning a tag to a metric. Static tags are given to the metric when it is initialized. +Dynamic tags are assigned whenever a value is set. + +## Static Tags +!!! example + + ``` python + MyCounter = MetricsService.create_counter( + "mycounter", + tags={'origin': 'MyApplication'}, + init_values={'v1': 0, 'v2': 0} + ) + ``` + +You can see the new tag `origin` in the initialization of `MyCounter`. You can locate the origin of each record in the time-series database by this tag. +To make tracking of each metric record easier, there are several built-in static tags. + +### Built-in Tags + +- `host`: +Hostname of the server or machine where the application is running. + +- `appclass`: +Name of the application. It is the name of the class that inherits from the ASAB Application object. + +- `node_id`: +Present if NODE_ID environmental variable is specified. It names a node in the cluster. + +- `service_id`: +Present if SERVICE_ID environmental variable is specified. It names a service in the cluster. + +- `instance_id`: +Present if INSTANCE_ID environmental variable is specified. It names an instance in the cluster. + + +## Dynamic Tags +!!! example + + ``` python + MyCounter = MetricsService.create_counter( + "mycounter", + tags={'origin': 'MyApplication'}, + init_values={'v1': 0, 'v2': 0}, + dynamic_tags=True + ) + + MyCounter.add("v1", 1, {"method": "GET"}): + ``` +Some metric types (Counter, AggregationCounter, Histogram) allow you to +use dynamic tags. +You can create values with a specific tag-set during runtime. +Specific tag-sets expire after a defined period. +This might be spotted in your time-series database like a mysterious disappearance of unused tags. +Specify the expiration period in the configuration, default is 60 s. + +!!! example "Configuration example" + + ``` {.} + [asab:metrics] + expiration=60 + ``` + +See [webrequests metrics](./built-ins.md#web-requests-metrics) as an example of metrics with dynamic tags. + +# Built-in Metrics + +## Web Requests Metrics + +ASAB `WebService` class automatically +provides metrics counting web requests. There are 5 metrics quantifying +requests to all ASAB endpoints. They use dynamic tags to provide infromation about method, path and status of the response. + +- `web_requests` - Counts requests to asab endpoints as + events per minute. +- `web_requests_duration` - Counts total requests + duration to asab endpoints per minute. +- `web_requests_duration_min` - Counts minimal request + duration to asab endpoints per minute. +- `web_requests_duration_max` - Counts maximum request + duration to asab endpoints per minute. +- `web_requests_duration_hist` - Cumulative histogram + counting requests in buckets defined by the request duration. + +Web Requests Metrics are switched off by default. Use configuration to allow them. +Be aware that both Web module and Metrics module must be initialized for these metrics. + +!!! example "Configuration example" + ``` {.} + [asab:metrics] + web_requests_metrics=true + ``` + +## Native Metrics + +You can opt out of Native Metrics through configuration by setting +`native_metrics` to `false`. Default is `true`. + +!!! example "Configuration example" + ``` {.} + [asab:metrics] + native_metrics=true + ``` + +### Memory Metrics + +A gauge with the name `os.stat` gathers information about memory usage +by your application. + +You can find several metric values there: + +- VmPeak - Peak virtual memory size +- VmLck - Locked memory size +- VmPin - Pinned memory size +- VmHWM - Peak resident set size (\"high water mark\") +- VmRSS - Resident set size +- VmData, VmStk, VmExe - Size of data, stack, and text segments +- VmLib - Shared library code size +- VmPTE - Page table entries size +- VmPMD - Size of second-level page tables +- VmSwap - Swapped-out virtual memory size by anonymous private pages; + shmem swap usage is not included + +### Logs Counter + +There is a default Counter named `logs` with values `warnings`, +`errors`, and `critical`, counting logs with respective levels. It is a +humble tool for application health monitoring. \ No newline at end of file diff --git a/docs/topics/asab/metrics/built-ins.md b/docs/topics/asab/metrics/built-ins.md deleted file mode 100644 index b680124ec..000000000 --- a/docs/topics/asab/metrics/built-ins.md +++ /dev/null @@ -1,63 +0,0 @@ -# Built-in Metrics - -## Web Requests Metrics - -ASAB `WebService` class automatically -provides metrics counting web requests. There are 5 metrics quantifying -requests to all ASAB endpoints. They use dynamic tags to provide infromation about method, path and status of the response. - -- `web_requests` - Counts requests to asab endpoints as - events per minute. -- `web_requests_duration` - Counts total requests - duration to asab endpoints per minute. -- `web_requests_duration_min` - Counts minimal request - duration to asab endpoints per minute. -- `web_requests_duration_max` - Counts maximum request - duration to asab endpoints per minute. -- `web_requests_duration_hist` - Cumulative histogram - counting requests in buckets defined by the request duration. - -Web Requests Metrics are switched off by default. Use configuration to allow them. -Be aware that both Web module and Metrics module must be initialized for these metrics. - -!!! example "Configuration example" - ``` {.} - [asab:metrics] - web_requests_metrics=true - ``` - -## Native Metrics - -You can opt out of Native Metrics through configuration by setting -`native_metrics` to `false`. Default is `true`. - -!!! example "Configuration example" - ``` {.} - [asab:metrics] - native_metrics=true - ``` - -### Memory Metrics - -A gauge with the name `os.stat` gathers information about memory usage -by your application. - -You can find several metric values there: - -- VmPeak - Peak virtual memory size -- VmLck - Locked memory size -- VmPin - Pinned memory size -- VmHWM - Peak resident set size (\"high water mark\") -- VmRSS - Resident set size -- VmData, VmStk, VmExe - Size of data, stack, and text segments -- VmLib - Shared library code size -- VmPTE - Page table entries size -- VmPMD - Size of second-level page tables -- VmSwap - Swapped-out virtual memory size by anonymous private pages; - shmem swap usage is not included - -### Logs Counter - -There is a default Counter named `logs` with values `warnings`, -`errors`, and `critical`, counting logs with respective levels. It is a -humble tool for application health monitoring. \ No newline at end of file diff --git a/docs/topics/asab/metrics/intro.md b/docs/topics/asab/metrics/intro.md deleted file mode 100644 index 6af9859c6..000000000 --- a/docs/topics/asab/metrics/intro.md +++ /dev/null @@ -1,110 +0,0 @@ -# Metrics - -Metrics document the state of the application in a timescale manner. -For further analysis, connect your ASAB application to a time-series -database. [Influx](https://www.influxdata.com/) and -[Prometheus](https://prometheus.io/) are supported. - - -!!! example - - ``` python - class MyApplication(asab.Application): - async def initialize(self): - from asab.metrics import Module # (1)! - self.add_module(Module) - self.MetricsService = self.get_service('asab.MetricsService') # (2)! - self.MyCounter = self.MetricsService.create_counter("mycounter", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0}) # (3)! - - if __name__ == '__main__': - app = MyApplication() - app.run() - ``` - - 1. Import asab.metrics Module and add it to the application. - 2. Then, you can localize MetricsService. - 3. Use MetricsService to intialize the counter. - - -See the full example [here](https://github.com/TeskaLabs/asab/blob/master/examples/metrics.py). - -See reference [here](./../../../reference/metrics/service.md). - -## Types of Metrics - -- `Gauge` stores single numerical values which can go up and down. - Implements `set` method to set the metric values. -- `Counter` is a cumulative metric whose values can increase or decrease. - Implements `add` and `sub` methods. -- Event per Second Counter (`EPSCounter`) divides all values by delta time. -- `DutyCycle` measures the fraction of a period in which a signal/system is active -- `AggregationCounter` allows to `set` values based on an aggregation function. - `max` function is default. -- `Histogram` represents cumulative histogram with `set` method. - -`Counter`, `AggregationCounter` and `Histogram` come also in variants -respecting dynamic tags. (See section [Dynamic Tags](./tags.md)) - -All methods that create new metrics objects can be found in the Metrics -Service reference. You should never initiate a new metrics object on its -own, but always through Metrics Service. Metris initialization is meant -to be done in the init time of your application and **should not be done -during runtime**. - -## ASAB Metrics Interpretation - -Metrics Service not only creates new metrics but also periodically -collects their values and sends them to selected databases. Every 60 -seconds in the application lifetime, Metrics Service gathers values of -all ASAB metrics. All Counters (and metric types that inherit from -`Counter`) reset at this event to their -initial values by default. Interpretation of ASAB Counters is affected -by their resetable nature. Even though they monotonously increase, -resetting every minute gives them a different meaning. In a long-term -observation (that's how you most probably monitor the metrics in -time-series databases), these metrics count **events per minute**. Thus, -resettable Counters are presented to Prometheus database as gauge-type -metrics. Set the `reset` argument to `False` -when creating a new Counter to disable Counter resetting. This periodic -"flush" cycle also causes 60s delay of metric propagation into -supported time-series databases. -Please, see the Timestamp section explaining the origin of a timestamp in each metric record. - -## Initial Values - -You can initiate your metric instance **with or without initial values**. -Initial values are always present and presented to databases even without a single event changing the metric values. -You will always find a pair of value name and its value in resulting dataset. -Values (name and value pairs) added during runtime last only 60 s. -You might spot this feature as missing values in the resulting time-series dataset. - - -## Timestamp - -**Timestamp** contains the record of the precise moment the metric's -value was created or committed to the database. There are two types of -metrics: resettable (`is_reset` = True) and non-resettable -(`is_reset` = False). To reset a metric means to set it -back to its initial value (for example, back to 0). The metric's type -is determined by the `reset: bool = True` parameter of the metric's -constructor at the moment of creation. We measure values of non-resettable -metrics at the time of their creation (there are several possible -methods depending on the metric's general logic), while -the resettable ones are measured when we reset the data -(which is also the moment of them being sent into the database). - -| Metric Type | Description / Methods | Origin of the timestamp | is_reset | -| :-------------------------------- | :------------------------------------------- | :--------------------- | :-------- | -| `Gauge` | Stores single numerical values which can go up and down. `set()` | When value is set. `set()` | **False** | -| `Counter` (*Allows dynamic tags*) | A cumulative metric; values can increase or decrease. Never stops. `add()`, `sub()` | When value is set. `add()` or `sub()` | **False** | -| `Counter` (*Allows dynamic tags*) | A cumulative metric; values can increase or decrease. Set to 0 every 60 seconds. | On `flush()`, every 60 seconds | **True** | -| `EPSCounter` | Divides the count of events by the time of the application run. | On `flush()`, every 60 seconds | **False** | -| `EPSCounter` | Divides the count of events by the time difference between measurements. | On `flush()`, every 60 seconds | **True** | -| `DutyCycle` | The fraction of one period in which a signal/system is active. A 60% DC means the signal is on 60% and off 40% of the time. | On `flush()`, every 60 seconds | **True** | -| `Aggregation Counter` (*Allows dynamic tags*) | Keeps track of max or min value of the Counter. Keeps maximum value by default. | When value is set. `set()` | **False** | -| `Aggregation Counter` (*Allows dynamic tags*)| Keeps track of max or min value of the Counter in each 60s window. Keeps maximum value by default. | On `flush()`, every 60 seconds | **True** | -| `Histogram` (*Allows dynamic tags*) | Cumulative histogram with a `set()` method. | When value is set. `set()` | **False** | -| `Histogram` (*Allows dynamic tags*) | Cumulative histogram with a `set()` method. | On `flush()`, every 60 seconds | **True** | - - - diff --git a/docs/topics/asab/metrics/tags.md b/docs/topics/asab/metrics/tags.md deleted file mode 100644 index 4607af994..000000000 --- a/docs/topics/asab/metrics/tags.md +++ /dev/null @@ -1,66 +0,0 @@ -# Tags -Tags allow filtering and aggregating collected metrics. -They provide dimensions for further analysis of the collected data. -There are two means of assigning a tag to a metric. Static tags are given to the metric when it is initialized. -Dynamic tags are assigned whenever a value is set. - -## Static Tags -!!! example - - ``` python - MyCounter = MetricsService.create_counter( - "mycounter", - tags={'origin': 'MyApplication'}, - init_values={'v1': 0, 'v2': 0} - ) - ``` - -You can see the new tag `origin` in the initialization of `MyCounter`. You can locate the origin of each record in the time-series database by this tag. -To make tracking of each metric record easier, there are several built-in static tags. - -### Built-in Tags - -- `host`: -Hostname of the server or machine where the application is running. - -- `appclass`: -Name of the application. It is the name of the class that inherits from the ASAB Application object. - -- `node_id`: -Present if NODE_ID environmental variable is specified. It names a node in the cluster. - -- `service_id`: -Present if SERVICE_ID environmental variable is specified. It names a service in the cluster. - -- `instance_id`: -Present if INSTANCE_ID environmental variable is specified. It names an instance in the cluster. - - -## Dynamic Tags -!!! example - - ``` python - MyCounter = MetricsService.create_counter( - "mycounter", - tags={'origin': 'MyApplication'}, - init_values={'v1': 0, 'v2': 0}, - dynamic_tags=True - ) - - MyCounter.add("v1", 1, {"method": "GET"}): - ``` -Some metric types (Counter, AggregationCounter, Histogram) allow you to -use dynamic tags. -You can create values with a specific tag-set during runtime. -Specific tag-sets expire after a defined period. -This might be spotted in your time-series database like a mysterious disappearance of unused tags. -Specify the expiration period in the configuration, default is 60 s. - -!!! example "Configuration example" - - ``` {.} - [asab:metrics] - expiration=60 - ``` - -See [webrequests metrics](./built-ins.md#web-requests-metrics) as an example of metrics with dynamic tags. \ No newline at end of file diff --git a/docs/topics/asab/metrics/targets.md b/docs/topics/asab/metrics/targets.md deleted file mode 100644 index 3f8cb52fe..000000000 --- a/docs/topics/asab/metrics/targets.md +++ /dev/null @@ -1,137 +0,0 @@ -# Monitoring -The Metrics module in ASAB serves to produce data - metrics. It does not store them, nor analyse. To get some overview, you must collect the metrics in a time-series database, or choose some custom way of monitoring. -InfluxDB and Prometheus databases are supported by ASAB and several endpoints can be used for data monitoring or collecting as well. - -## InfluxDB - -Metrics can be collected in the Influx time-series database. Metrics are being sent in 60s intervals to configured Influx instance. - -!!! example "Configuration example" - ``` {.} - [asab:metrics] - target=influxdb - - [asab:metrics:influxdb] - url=http://localhost:8086/ - bucket=my_bucket - org=my_org - token=my_token - ``` - -**InfluxDB 2.0 API parameters**: - -- **url** - (required) URL string of your InfluxDB. -- **bucket** - (required) Destination bucket for writing. -- **org** - (required) Destination organization for writing. -- **orgid** - (optional) ID of the destination organization for writing. - : (NOTE: If both orgID and org are specified, org takes - precedence) -- **token** - (required) API token to authenticate to the InfluxDB - -**InfluxDB \<1.8 API parameters**: -- **url** - (required) URL string of your InfluxDB. -- **username** - (required) name of InfluxDB user. -- **password** - (required) password of InfluxDB user. - -## Prometheus -Prometheus is a "pull model" time-series database. -Prometheus accesses `asab/v1/metrics` endpoint of ASAB ApiService. Thus, connecting ASAB to -Prometheus requires APIService initialization. All other configuration is required on the Prometheus side. -ASAB metrics are presented to Prometheus in [OpenMetrics](https://openmetrics.io/) standard format. - -!!! example "ApiService initialization" - - ``` python - class MyApplication(asab.Application): - async def initialize(self): - from asab.metrics import Module - self.add_module(Module) - self.MetricsService = self.get_service('asab.MetricsService') - self.MyCounter = self.MetricsService.create_counter("mycounter", tags={'foo': 'bar'}, init_values={'v1': 0, 'v2': 0}) - - # Initialize API service - self.ApiService = asab.api.ApiService(self) - self.ApiService.initialize_web() - - if __name__ == '__main__': - app = MyApplication() - app.run() - ``` - -!!! example "prometheus.yaml configuration file example" - - ``` {.yaml} - global: - scrape_interval: 15s - scrape_timeout: 10s - evaluation_interval: 15s - - scrape_configs: - - job_name: 'metrics_example' - metrics_path: '/asab/v1/metrics' - scrape_interval: 10s - static_configs: - - targets: ['127.0.0.1:8080'] - ``` - -!!! note - - To satisfy the OpenMetrics format required by Prometheus, you should - follow the instructions below: - - - Metrics names must fit regex `[a-zA-Z:][a-zA-Z0-9_:]*`. (Any other - characters are replaced by an underscore. Leading underscores and - numbers are stripped. These changes proceed without warning.) - - Metrics names MUST NOT end with "total" or "created". - - Tags SHOULD contain items "unit" and "help" providing metadata to - Prometheus. - - Values MUST be float or integer. - - -## Metrics Endpoints - -The **API Service** in ASAB offers several endpoints that monitor -internal ASAB functionality. Some of them present the current state of -metrics. Check for Swagger documentation of your ASAB Application REST -API by visiting the `/doc` endpoint. - -`/asab/v1/metrics` - -- This endpoint returns metrics in OpenMetrics format and its primary - purpose is to satisfy Prometheus database needs. - -`/asab/v1/metrics.json` - -- This endpoint presents metrics data in JSON format. - -`/asab/v1/watch_metrics` - -- Use this endpoint for developing or monitoring your app from the - terminal. It returns a simple table of ASAB metrics. You can filter - metrics by name using the `filter` parameter and `tags` parameter to - show or hide tags. - -!!! example - - ``` {.} - watch curl localhost:8080/asab/v1/watch_metrics - ``` - - ``` {.} - watch curl localhost:8080/asab/v1/watch_metrics?name=web_requests_duration_max,tags=True - ``` - -## HTTP Target - -For use cases requiring a push model of metrics digestion, there is an -HTTP Target. HTTP Target creates a POST request every 60 seconds to configured URL with -the current metrics state sent as JSON body. Configuration is required. - -!!! example "Configuration example" - ``` {.} - [asab:metrics] - target=http - - [asab:metrics:http] - url=http://consumer_example:8080/consume - ``` \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index ac541bf7c..8fd8977e6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -172,17 +172,7 @@ nav: - Logging: reference/logging/reference.md - PubSub: reference/pubsub/reference.md - Library Service: reference/library/reference.md - - Metrics Service: - - MetricsService: reference/metrics/service.md - - Gauge: reference/metrics/gauge.md - - Counter: reference/metrics/counter.md - - EPSCounter: reference/metrics/eps_counter.md - - DutyCycle: reference/metrics/duty_cycle.md - - AggregationCounter: reference/metrics/aggregation_counter.md - - Histogram: reference/metrics/histogram.md - - CounterWithDynamicTags: reference/metrics/counter_with_dynamic_tags.md - - AggregationCounterWithDynamicTags: reference/metrics/aggregation_counter_with_dynamic_tags.md - - HistogramWithDynamicTags: reference/metrics/histogram_with_dynamic_tags.md + - Metrics Service: reference/metrics/reference.md - Storage Service: reference/storage/reference.md - Zookeeper: reference/zookeeper/reference.md - Utility functions and classes: From f4aeff695adc234807b1e151e7c269ca74a5f825 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 9 Aug 2023 10:00:26 +0200 Subject: [PATCH 149/154] Sync TODOs --- docs/TODO.md | 15 +++++---------- docs/contributing.md | 2 -- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/docs/TODO.md b/docs/TODO.md index d85ac6b04..b3b11f06a 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -6,19 +6,11 @@ ## Missing sections -- PubSub -- AlertService -- ProactorService -- SSL/TLS -- Authorization and multitenancy -- CORS -- Metrics (needs to be modified) -- Zookeeper - -- Containerisation (needs to be modified) - Systemd + + ## Useful hyperlinks: https://squidfunk.github.io/mkdocs-material/reference/code-blocks/ @@ -47,5 +39,8 @@ pyment path/to/file.py -o google patch path/to/file.py path/to/file.py.patch ``` +## Converting .rst format to .md + +Use pandoc. diff --git a/docs/contributing.md b/docs/contributing.md index 4f841a332..00d291289 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -131,5 +131,3 @@ def fetch_smalltable_rows( ``` - -## Creating examples From 5f9ebaf6c2ee3373cbaaab26d14f0621f1154a18 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 9 Aug 2023 10:20:54 +0200 Subject: [PATCH 150/154] Fix: remove web Module causing cycle import --- docs/reference/web/web-server.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/reference/web/web-server.md b/docs/reference/web/web-server.md index 5118e802c..4744050b9 100644 --- a/docs/reference/web/web-server.md +++ b/docs/reference/web/web-server.md @@ -220,8 +220,6 @@ listen=8080 ::: asab.web.create_web_server -::: asab.web.Module - ::: asab.web.service.WebService ::: asab.web.WebContainer From 26d0f93e9f509455c756ea8453b1cf11d8e93374 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 9 Aug 2023 11:18:18 +0200 Subject: [PATCH 151/154] Add description --- docs/reference/utils/utils.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/reference/utils/utils.md b/docs/reference/utils/utils.md index ae7271ada..98ee75743 100644 --- a/docs/reference/utils/utils.md +++ b/docs/reference/utils/utils.md @@ -1 +1,5 @@ +# Utility functions + +`asab.utils` provides several helper functions for manipulation with URLs, time conversion etc. + :::asab.utils \ No newline at end of file From 63b34b13cab5a29e5d352f352d1ebc634ad17123 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Wed, 9 Aug 2023 11:28:52 +0200 Subject: [PATCH 152/154] Change labels --- docs/index.md | 2 +- mkdocs.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index a9a8a2867..bc165b60e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,7 +11,7 @@ ASAB-based microservice via Docker or Kubernetes in a breeze. Anyone can (and is encouraged to) use ASAB in his or her projects, for free. -[Get started](getting-started/installation_first_app.md){ .md-button .md-button--primary } [Read more about TeskaLabs](https://docs.teskalabs.com/){ .md-button .md-button--primary } [Contribute](contributing.md){ .md-button .md-button--primary } +[Get started](getting-started/installation_first_app.md){ .md-button .md-button--primary } [About TeskaLabs](https://docs.teskalabs.com/){ .md-button .md-button--primary } [Contribute](contributing.md){ .md-button .md-button--primary } !!! success "ASAB is the right choice when:" diff --git a/mkdocs.yml b/mkdocs.yml index 8fd8977e6..3f5fa0eab 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -159,7 +159,7 @@ nav: - How-Tos: - Creating a microservice with REST API: how-tos/03_rest_api.md - - Reference: + - Documentation: - Application: reference/application/reference.md - Modules and Services: reference/modules_services/reference.md From 58c71c53a210eb11ce6b46b2afa35a1bafc26c14 Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 10 Aug 2023 10:03:05 +0200 Subject: [PATCH 153/154] Change deploy staging branch to master --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 216d184b8..4fb7ac442 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,7 +21,7 @@ deploy staging: # - (cd ./cs && mkdocs build --site-dir /output/cs) - rsync -r -a -v -e ssh --delete /output/ "$RSYNC_USER"@"$TARGET_SERVER":"$STAGING_DIR" only: - - "docs/mkdocs-migration" + - master deploy production: stage: deploy From 3b440ba59ff889dd1171d5549ad43e63dbd756ef Mon Sep 17 00:00:00 2001 From: mejroslav Date: Thu, 10 Aug 2023 10:03:15 +0200 Subject: [PATCH 154/154] Switch to blue --- mkdocs.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 3f5fa0eab..e971214f5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -56,13 +56,13 @@ theme: palette: - scheme: default - primary: teal - accent: teal + primary: blue + accent: blue toggle: icon: material/brightness-7 name: Switch to dark mode - scheme: slate - primary: teal + primary: blue accent: yellow toggle: icon: material/brightness-4

A{V-$f;rutH~#w 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�i}Q~8nXT}i6e7tXSAMaeq{*9s_Jy6dO6bZ8 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�`q%<}y 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 z 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 A)Bpeg literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/get-started.doctree b/old_docs/_build/doctrees/get-started.doctree new file mode 100644 index 0000000000000000000000000000000000000000..9a3c38868b8a86855f107710233f969a277c03f9 GIT binary patch literal 14516 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 HGg|)ubDc2@ literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/tutorial/web/chapter1.doctree b/old_docs/_build/doctrees/tutorial/web/chapter1.doctree new file mode 100644 index 0000000000000000000000000000000000000000..6b7f4dec1c0b55882fffca658eab01f2c55958ff GIT binary patch literal 17854 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 LvO`05+-?6462Ji_ literal 0 HcmV?d00001 diff --git a/old_docs/_build/doctrees/tutorial/web/chapter2.doctree b/old_docs/_build/doctrees/tutorial/web/chapter2.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4855a8fdc95d814688c8bddb20fb10f7a7b0a2e2 GIT binary patch literal 58108 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