From 18497d434333f82c8d4057b5b6349983d4963e9c Mon Sep 17 00:00:00 2001 From: trevor Date: Wed, 7 May 2025 15:41:03 +0900 Subject: [PATCH] new models, frontend functions, public pages --- .history/backend/api/models_20250507135815.py | 35 + .history/backend/api/models_20250507135936.py | 41 + .history/backend/api/models_20250507140013.py | 45 + .history/backend/api/models_20250507145448.py | 54 + .../backend/api/serializers_20250507134438.py | 60 + .../backend/api/serializers_20250507142241.py | 65 + .../backend/api/serializers_20250507145525.py | 66 + .../backend/api/serializers_20250507145609.py | 48 + .history/backend/api/urls_20250507072806.py | 24 + .history/backend/api/urls_20250507072816.py | 25 + .history/backend/api/urls_20250507080627.py | 28 + .history/backend/api/urls_20250507080637.py | 29 + .history/backend/api/urls_20250507080822.py | 35 + .history/backend/api/urls_20250507081428.py | 35 + .history/backend/api/urls_20250507081622.py | 35 + .history/backend/api/views_20250507072833.py | 113 + .history/backend/api/views_20250507072920.py | 118 + .history/backend/api/views_20250507073141.py | 109 + .history/backend/api/views_20250507073143.py | 109 + .history/backend/api/views_20250507141914.py | 119 + .history/backend/api/views_20250507141924.py | 119 + .history/backend/api/views_20250507142311.py | 95 + .history/backend/api/views_20250507142317.py | 98 + .history/backend/api/views_20250507142335.py | 119 + .history/backend/api/views_20250507145006.py | 151 + .history/backend/api/views_20250507145615.py | 248 + .history/backend/api/views_20250507150101.py | 272 + .history/backend/api/views_20250507150709.py | 267 + .history/backend/api/views_20250507150738.py | 272 + .history/backend/api/views_20250507150907.py | 119 + .history/backend/api/views_20250507151205.py | 150 + .history/backend/api/views_20250507151600.py | 119 + .../backend/settings_20250507080801.py | 164 + .../backend/settings_20250507080850.py | 165 + .../backend/settings_20250507081134.py | 165 + .../backend/settings_20250507081237.py | 165 + .../backend/settings_20250507082006.py | 166 + .../backend/settings_20250507082028.py | 168 + .../backend/backend/urls_20250507080600.py | 60 + .../backend/backend/urls_20250507081420.py | 60 + .../app/dashboard/page_20250507074450.ts | 84 + .../app/dashboard/page_20250507074950.ts | 84 + .../next.config_20250507131744.ts | 35 + .../next.config_20250507133920.ts | 37 + .../next.config_20250507133940.ts | 37 + .../package_20250507131936.json | 31 + .../public/manifest_20250507074158.json | 0 .../public/manifest_20250507074202.json | 21 + .../public/manifest_20250507074217.json | 45 + .../public/manifest_20250507074316.json | 25 + .../auth/register/page_20250507082845.tsx | 0 .../auth/register/page_20250507082848.tsx | 238 + .../dashboard/page_20250506191940.tsx | 0 .../dashboard/page_20250507074950.tsx | 199 + .../dashboard/page_20250507102038.tsx | 423 + .../dashboard/page_20250507102107.tsx | 423 + .../dashboard/page_20250507140312.tsx | 638 + .../dashboard/page_20250507140327.tsx | 638 + .../dashboard/page_20250507140923.tsx | 213 + .../dashboard/page_20250507143628.tsx | 390 + .../app/(protected)/layout_20250507074711.tsx | 0 .../app/(protected)/layout_20250507074730.tsx | 15 + .../app/(protected)/layout_20250507075127.tsx | 176 + .../app/(protected)/layout_20250507075632.tsx | 176 + .../app/(protected)/layout_20250507101018.tsx | 177 + .../app/(protected)/layout_20250507101046.tsx | 173 + .../app/(protected)/layout_20250507101125.tsx | 173 + .../app/(protected)/layout_20250507101149.tsx | 127 + .../app/(protected)/layout_20250507101154.tsx | 127 + .../app/(protected)/layout_20250507101201.tsx | 173 + .../app/(protected)/layout_20250507101421.tsx | 173 + .../app/(protected)/layout_20250507101434.tsx | 34 + .../app/(protected)/layout_20250507101459.tsx | 173 + .../app/(protected)/layout_20250507134134.tsx | 171 + .../app/(protected)/layout_20250507134143.tsx | 173 + .../app/(protected)/layout_20250507140825.tsx | 19 + .../app/(protected)/layout_20250507142027.tsx | 80 + .../app/(protected)/layout_20250507142048.tsx | 80 + .../app/(protected)/layout_20250507142055.tsx | 80 + .../app/(protected)/page_20250507075005.tsx | 0 .../app/(protected)/page_20250507075027.tsx | 76 + .../app/[username]/layout_20250507073825.tsx | 0 .../app/[username]/layout_20250507073826.tsx | 16 + .../app/[username]/layout_20250507073827.tsx | 16 + .../app/[username]/layout_20250507075136.tsx | 7 + .../app/[username]/layout_20250507075137.tsx | 7 + .../app/[username]/layout_20250507075251.tsx | 7 + .../app/[username]/layout_20250507075252.tsx | 7 + .../app/[username]/layout_20250507075546.tsx | 24 + .../app/[username]/layout_20250507075547.tsx | 24 + .../app/[username]/layout_20250507075723.tsx | 24 + .../app/[username]/layout_20250507075724.tsx | 24 + .../app/[username]/layout_20250507075842.tsx | 69 + .../app/[username]/layout_20250507075843.tsx | 69 + .../app/[username]/layout_20250507095308.tsx | 114 + .../app/[username]/layout_20250507095309.tsx | 114 + .../app/[username]/layout_20250507095439.tsx | 176 + .../app/[username]/layout_20250507095440.tsx | 176 + .../app/[username]/layout_20250507095616.tsx | 131 + .../app/[username]/layout_20250507095617.tsx | 131 + .../app/[username]/layout_20250507100758.tsx | 31 + .../app/[username]/page_20250507071916.tsx | 101 + .../app/[username]/page_20250507072425.tsx | 109 + .../app/[username]/page_20250507072426.tsx | 109 + .../app/[username]/page_20250507072646.tsx | 108 + .../app/[username]/page_20250507072648.tsx | 108 + .../app/[username]/page_20250507073425.tsx | 132 + .../app/[username]/page_20250507073426.tsx | 132 + .../app/[username]/page_20250507073635.tsx | 131 + .../app/[username]/page_20250507073636.tsx | 131 + .../app/[username]/page_20250507080146.tsx | 132 + .../app/[username]/page_20250507080147.tsx | 132 + .../app/[username]/page_20250507150317.tsx | 135 + .../app/[username]/page_20250507150318.tsx | 135 + .../app/[username]/page_20250507151531.tsx | 138 + .../app/[username]/page_20250507151532.tsx | 138 + .../app/[username]/page_20250507151554.tsx | 135 + .../app/[username]/page_20250507151555.tsx | 135 + .../app/[username]/page_20250507152817.tsx | 141 + .../app/[username]/page_20250507152818.tsx | 141 + .../app/[username]/page_20250507152851.tsx | 141 + .../LayoutWrapper_20250507100116.tsx | 0 .../LayoutWrapper_20250507100121.tsx | 85 + .../LayoutWrapper_20250507100540.tsx | 157 + .../components/ProfileCard_20250507141524.tsx | 66 + .../app/components/modal_20250507101831.tsx | 0 .../app/components/modal_20250507101834.tsx | 29 + .../src/app/layout_20250507074303.tsx | 176 + .../src/app/layout_20250507075244.tsx | 19 + .../src/app/layout_20250507075850.tsx | 62 + .../src/app/layout_20250507094757.tsx | 164 + .../src/app/layout_20250507095932.tsx | 173 + .../src/app/layout_20250507100131.tsx | 78 + .../src/app/layout_20250507100150.tsx | 78 + .../src/app/layout_20250507100157.tsx | 78 + .../src/app/layout_20250507100158.tsx | 78 + .../src/app/layout_20250507100751.tsx | 80 + .../src/app/layout_20250507100816.tsx | 80 + .../src/app/page_20250507075037.tsx | 0 .../src/app/page_20250507075101.tsx | 75 + .../src/app/username/page_20250507071917.tsx | 101 + .venv/bin/jsonschema | 8 + .../PyYAML-6.0.2.dist-info/INSTALLER | 1 + .../PyYAML-6.0.2.dist-info/LICENSE | 20 + .../PyYAML-6.0.2.dist-info/METADATA | 46 + .../PyYAML-6.0.2.dist-info/RECORD | 43 + .../PyYAML-6.0.2.dist-info/WHEEL | 6 + .../PyYAML-6.0.2.dist-info/top_level.txt | 2 + .../site-packages/_yaml/__init__.py | 33 + .../python3.10/site-packages/attr/__init__.py | 104 + .../site-packages/attr/__init__.pyi | 389 + .../lib/python3.10/site-packages/attr/_cmp.py | 160 + .../python3.10/site-packages/attr/_cmp.pyi | 13 + .../python3.10/site-packages/attr/_compat.py | 94 + .../python3.10/site-packages/attr/_config.py | 31 + .../python3.10/site-packages/attr/_funcs.py | 468 + .../python3.10/site-packages/attr/_make.py | 3123 +++++ .../site-packages/attr/_next_gen.py | 623 + .../site-packages/attr/_typing_compat.pyi | 15 + .../site-packages/attr/_version_info.py | 86 + .../site-packages/attr/_version_info.pyi | 9 + .../site-packages/attr/converters.py | 162 + .../site-packages/attr/converters.pyi | 19 + .../site-packages/attr/exceptions.py | 95 + .../site-packages/attr/exceptions.pyi | 17 + .../python3.10/site-packages/attr/filters.py | 72 + .../python3.10/site-packages/attr/filters.pyi | 6 + .../python3.10/site-packages/attr/py.typed | 0 .../python3.10/site-packages/attr/setters.py | 79 + .../python3.10/site-packages/attr/setters.pyi | 20 + .../site-packages/attr/validators.py | 710 + .../site-packages/attr/validators.pyi | 86 + .../attrs-25.3.0.dist-info/INSTALLER | 1 + .../attrs-25.3.0.dist-info/METADATA | 232 + .../attrs-25.3.0.dist-info/RECORD | 55 + .../attrs-25.3.0.dist-info/WHEEL | 4 + .../attrs-25.3.0.dist-info/licenses/LICENSE | 21 + .../site-packages/attrs/__init__.py | 69 + .../site-packages/attrs/__init__.pyi | 263 + .../site-packages/attrs/converters.py | 3 + .../site-packages/attrs/exceptions.py | 3 + .../python3.10/site-packages/attrs/filters.py | 3 + .../python3.10/site-packages/attrs/py.typed | 0 .../python3.10/site-packages/attrs/setters.py | 3 + .../site-packages/attrs/validators.py | 3 + .../django_extensions-4.1.dist-info/INSTALLER | 1 + .../django_extensions-4.1.dist-info/METADATA | 175 + .../django_extensions-4.1.dist-info/RECORD | 278 + .../django_extensions-4.1.dist-info/REQUESTED | 0 .../django_extensions-4.1.dist-info/WHEEL | 5 + .../licenses/LICENSE | 19 + .../top_level.txt | 1 + .../django_extensions/__init__.py | 6 + .../django_extensions/admin/__init__.py | 195 + .../django_extensions/admin/filter.py | 57 + .../django_extensions/admin/widgets.py | 100 + .../site-packages/django_extensions/apps.py | 7 + .../django_extensions/auth/__init__.py | 0 .../django_extensions/auth/mixins.py | 15 + .../django_extensions/collision_resolvers.py | 294 + .../site-packages/django_extensions/compat.py | 68 + .../conf/app_template/__init__.py.tmpl | 0 .../conf/app_template/forms.py.tmpl | 3 + .../app_template/migrations/__init__.py.tmpl | 0 .../conf/app_template/models.py.tmpl | 3 + .../conf/app_template/urls.py.tmpl | 3 + .../conf/app_template/views.py.tmpl | 1 + .../management/__init__.py.tmpl | 0 .../management/commands/__init__.py.tmpl | 0 .../management/commands/sample.py.tmpl | 11 + .../conf/jobs_template/jobs/__init__.py.tmpl | 0 .../jobs_template/jobs/daily/__init__.py.tmpl | 0 .../jobs/hourly/__init__.py.tmpl | 0 .../jobs/monthly/__init__.py.tmpl | 0 .../conf/jobs_template/jobs/sample.py.tmpl | 9 + .../jobs/weekly/__init__.py.tmpl | 0 .../jobs/yearly/__init__.py.tmpl | 0 .../templatetags/__init__.py.tmpl | 0 .../templatetags/sample.py.tmpl | 3 + .../django_extensions/db/__init__.py | 0 .../django_extensions/db/fields/__init__.py | 638 + .../django_extensions/db/fields/json.py | 115 + .../django_extensions/db/models.py | 150 + .../django_extensions/import_subclasses.py | 61 + .../django_extensions/jobs/__init__.py | 0 .../django_extensions/jobs/daily/__init__.py | 0 .../jobs/daily/cache_cleanup.py | 24 + .../jobs/daily/daily_cleanup.py | 18 + .../django_extensions/jobs/hourly/__init__.py | 0 .../jobs/minutely/__init__.py | 0 .../jobs/monthly/__init__.py | 0 .../django_extensions/jobs/weekly/__init__.py | 0 .../django_extensions/jobs/yearly/__init__.py | 0 .../locale/ar/LC_MESSAGES/django.po | 109 + .../locale/da/LC_MESSAGES/django.mo | Bin 0 -> 797 bytes .../locale/da/LC_MESSAGES/django.po | 79 + .../locale/de/LC_MESSAGES/django.mo | Bin 0 -> 1227 bytes .../locale/de/LC_MESSAGES/django.po | 77 + .../locale/el/LC_MESSAGES/django.mo | Bin 0 -> 1581 bytes .../locale/el/LC_MESSAGES/django.po | 79 + .../locale/en/LC_MESSAGES/django.mo | Bin 0 -> 367 bytes .../locale/en/LC_MESSAGES/django.po | 112 + .../locale/es/LC_MESSAGES/django.mo | Bin 0 -> 1260 bytes .../locale/es/LC_MESSAGES/django.po | 77 + .../locale/fr/LC_MESSAGES/django.mo | Bin 0 -> 743 bytes .../locale/fr/LC_MESSAGES/django.po | 81 + .../locale/hu/LC_MESSAGES/django.mo | Bin 0 -> 1242 bytes .../locale/hu/LC_MESSAGES/django.po | 77 + .../locale/id/LC_MESSAGES/django.mo | Bin 0 -> 1508 bytes .../locale/id/LC_MESSAGES/django.po | 98 + .../locale/it/LC_MESSAGES/django.mo | Bin 0 -> 1247 bytes .../locale/it/LC_MESSAGES/django.po | 77 + .../locale/ja/LC_MESSAGES/django.mo | Bin 0 -> 1397 bytes .../locale/ja/LC_MESSAGES/django.po | 77 + .../locale/pl/LC_MESSAGES/django.mo | Bin 0 -> 2002 bytes .../locale/pl/LC_MESSAGES/django.po | 109 + .../locale/pt/LC_MESSAGES/django.mo | Bin 0 -> 1262 bytes .../locale/pt/LC_MESSAGES/django.po | 77 + .../locale/pt_BR/LC_MESSAGES/django.mo | Bin 0 -> 1310 bytes .../locale/pt_BR/LC_MESSAGES/django.po | 79 + .../locale/ro/LC_MESSAGES/django.mo | Bin 0 -> 1352 bytes .../locale/ro/LC_MESSAGES/django.po | 80 + .../locale/ru/LC_MESSAGES/django.mo | Bin 0 -> 2009 bytes .../locale/ru/LC_MESSAGES/django.po | 126 + .../django_extensions/logging/__init__.py | 0 .../django_extensions/logging/filters.py | 36 + .../django_extensions/management/__init__.py | 0 .../django_extensions/management/base.py | 53 + .../django_extensions/management/color.py | 29 + .../management/commands/__init__.py | 0 .../management/commands/admin_generator.py | 395 + .../management/commands/clean_pyc.py | 55 + .../management/commands/clear_cache.py | 42 + .../management/commands/compile_pyc.py | 44 + .../management/commands/create_command.py | 112 + .../management/commands/create_jobs.py | 69 + .../commands/create_template_tags.py | 80 + .../commands/delete_squashed_migrations.py | 214 + .../management/commands/describe_form.py | 96 + .../management/commands/drop_test_database.py | 254 + .../management/commands/dumpscript.py | 855 ++ .../management/commands/export_emails.py | 212 + .../management/commands/find_template.py | 22 + .../management/commands/generate_password.py | 36 + .../commands/generate_secret_key.py | 17 + .../management/commands/graph_models.py | 486 + .../management/commands/list_model_info.py | 185 + .../management/commands/list_signals.py | 91 + .../management/commands/mail_debug.py | 103 + .../management/commands/managestate.py | 204 + .../commands/merge_model_instances.py | 235 + .../management/commands/notes.py | 74 + .../management/commands/print_settings.py | 88 + .../commands/print_user_for_session.py | 63 + .../commands/raise_test_exception.py | 23 + .../management/commands/reset_db.py | 252 + .../management/commands/reset_schema.py | 100 + .../management/commands/runjob.py | 64 + .../management/commands/runjobs.py | 103 + .../management/commands/runprofileserver.py | 295 + .../management/commands/runscript.py | 356 + .../management/commands/runserver_plus.py | 756 ++ .../management/commands/set_default_site.py | 82 + .../management/commands/set_fake_emails.py | 129 + .../management/commands/set_fake_passwords.py | 63 + .../management/commands/shell_plus.py | 701 + .../management/commands/show_permissions.py | 61 + .../management/commands/show_template_tags.py | 115 + .../management/commands/show_urls.py | 305 + .../management/commands/sqlcreate.py | 125 + .../management/commands/sqldiff.py | 1794 +++ .../management/commands/sqldsn.py | 213 + .../management/commands/sync_s3.py | 468 + .../management/commands/syncdata.py | 281 + .../management/commands/unreferenced_files.py | 48 + .../management/commands/update_permissions.py | 78 + .../management/commands/validate_templates.py | 124 + .../management/debug_cursor.py | 144 + .../management/email_notifications.py | 150 + .../django_extensions/management/jobs.py | 208 + .../django_extensions/management/modelviz.py | 526 + .../django_extensions/management/mysql.py | 46 + .../management/notebook_extension.py | 10 + .../django_extensions/management/shells.py | 432 + .../django_extensions/management/signals.py | 13 + .../management/technical_response.py | 45 + .../django_extensions/management/utils.py | 83 + .../site-packages/django_extensions/models.py | 0 .../django_extensions/mongodb/__init__.py | 0 .../mongodb/fields/__init__.py | 284 + .../django_extensions/mongodb/fields/json.py | 80 + .../django_extensions/mongodb/models.py | 98 + .../site-packages/django_extensions/py.typed | 0 .../django_extensions/settings.py | 45 + .../css/jquery.autocomplete.css | 38 + .../django_extensions/img/indicator.gif | Bin 0 -> 1553 bytes .../django_extensions/js/jquery.ajaxQueue.js | 116 + .../js/jquery.autocomplete.js | 1152 ++ .../django_extensions/js/jquery.bgiframe.js | 39 + .../graph_models/django2018/digraph.dot | 28 + .../graph_models/django2018/label.dot | 33 + .../graph_models/django2018/relation.dot | 10 + .../graph_models/django2018style/digraph.dot | 27 + .../graph_models/django2018style/label.dot | 39 + .../graph_models/django2018style/relation.dot | 10 + .../graph_models/original/digraph.dot | 28 + .../graph_models/original/label.dot | 33 + .../graph_models/original/relation.dot | 10 + .../widgets/foreignkey_searchinput.html | 61 + .../templatetags/__init__.py | 0 .../templatetags/debugger_tags.py | 37 + .../templatetags/highlighting.py | 104 + .../templatetags/indent_text.py | 55 + .../templatetags/syntax_color.py | 118 + .../django_extensions/templatetags/widont.py | 74 + .../django_extensions/utils/__init__.py | 2 + .../django_extensions/utils/deprecation.py | 9 + .../django_extensions/utils/dia2django.py | 272 + .../django_extensions/utils/internal_ips.py | 70 + .../django_extensions/validators.py | 124 + .../INSTALLER | 1 + .../drf_spectacular-0.28.0.dist-info/LICENSE | 30 + .../drf_spectacular-0.28.0.dist-info/METADATA | 359 + .../drf_spectacular-0.28.0.dist-info/RECORD | 83 + .../REQUESTED | 0 .../drf_spectacular-0.28.0.dist-info/WHEEL | 5 + .../top_level.txt | 1 + .../site-packages/drf_spectacular/__init__.py | 6 + .../site-packages/drf_spectacular/apps.py | 9 + .../drf_spectacular/authentication.py | 42 + .../site-packages/drf_spectacular/checks.py | 26 + .../drf_spectacular/contrib/__init__.py | 15 + .../drf_spectacular/contrib/django_filters.py | 305 + .../contrib/django_oauth_toolkit.py | 49 + .../contrib/djangorestframework_camel_case.py | 62 + .../contrib/knox_auth_token.py | 13 + .../drf_spectacular/contrib/pydantic.py | 50 + .../drf_spectacular/contrib/rest_auth.py | 173 + .../drf_spectacular/contrib/rest_framework.py | 32 + .../contrib/rest_framework_dataclasses.py | 36 + .../contrib/rest_framework_gis.py | 219 + .../contrib/rest_framework_jwt.py | 16 + .../contrib/rest_framework_recursive.py | 16 + .../contrib/rest_framework_simplejwt.py | 87 + .../contrib/rest_polymorphic.py | 81 + .../site-packages/drf_spectacular/drainage.py | 220 + .../drf_spectacular/extensions.py | 143 + .../drf_spectacular/generators.py | 293 + .../site-packages/drf_spectacular/helpers.py | 42 + .../site-packages/drf_spectacular/hooks.py | 210 + .../drf_spectacular/management/__init__.py | 0 .../management/commands/__init__.py | 0 .../management/commands/spectacular.py | 98 + .../site-packages/drf_spectacular/openapi.py | 1664 +++ .../site-packages/drf_spectacular/plumbing.py | 1545 +++ .../site-packages/drf_spectacular/py.typed | 0 .../drf_spectacular/renderers.py | 82 + .../drf_spectacular/serializers.py | 94 + .../site-packages/drf_spectacular/settings.py | 288 + .../templates/drf_spectacular/redoc.html | 32 + .../templates/drf_spectacular/swagger_ui.html | 31 + .../templates/drf_spectacular/swagger_ui.js | 126 + .../site-packages/drf_spectacular/types.py | 177 + .../site-packages/drf_spectacular/utils.py | 693 + .../drf_spectacular/validation/__init__.py | 34 + .../validation/openapi_3_0_schema.json | 1666 +++ .../validation/openapi_3_1_schema.json | 1449 +++ .../site-packages/drf_spectacular/views.py | 288 + .../INSTALLER | 1 + .../METADATA | 99 + .../RECORD | 24 + .../REQUESTED | 0 .../WHEEL | 5 + .../licenses/LICENSE | 28 + .../top_level.txt | 1 + .../drf_spectacular_sidecar/__init__.py | 6 + .../drf_spectacular_sidecar/apps.py | 6 + .../drf_spectacular_sidecar/py.typed | 0 .../redoc/bundles/redoc.standalone.js | 1832 +++ .../bundles/redoc.standalone.js.LICENSE.txt | 102 + .../redoc/bundles/redoc.standalone.js.map | 1 + .../swagger-ui-dist/favicon-32x32.png | Bin 0 -> 628 bytes .../swagger-ui-dist/oauth2-redirect.html | 79 + .../swagger-ui-dist/swagger-ui-bundle.js | 2 + .../swagger-ui-bundle.js.LICENSE.txt | 202 + .../swagger-ui-dist/swagger-ui-bundle.js.map | 1 + .../swagger-ui-standalone-preset.js | 2 + .../swagger-ui-standalone-preset.js.map | 1 + .../swagger-ui-dist/swagger-ui.css | 3 + .../swagger-ui-dist/swagger-ui.css.map | 1 + .../inflection-0.5.1.dist-info/INSTALLER | 1 + .../inflection-0.5.1.dist-info/LICENSE | 19 + .../inflection-0.5.1.dist-info/METADATA | 49 + .../inflection-0.5.1.dist-info/RECORD | 11 + .../inflection-0.5.1.dist-info/WHEEL | 6 + .../inflection-0.5.1.dist-info/top_level.txt | 1 + .../python3.10/site-packages/inflection.py | 426 + .../site-packages/inflection/__init__.py | 426 + .../site-packages/inflection/py.typed | 0 .../jsonschema-4.23.0.dist-info/INSTALLER | 1 + .../jsonschema-4.23.0.dist-info/METADATA | 176 + .../jsonschema-4.23.0.dist-info/RECORD | 76 + .../jsonschema-4.23.0.dist-info/WHEEL | 4 + .../entry_points.txt | 2 + .../licenses/COPYING | 19 + .../site-packages/jsonschema/__init__.py | 120 + .../site-packages/jsonschema/__main__.py | 6 + .../site-packages/jsonschema/_format.py | 519 + .../site-packages/jsonschema/_keywords.py | 449 + .../jsonschema/_legacy_keywords.py | 449 + .../site-packages/jsonschema/_types.py | 200 + .../site-packages/jsonschema/_typing.py | 28 + .../site-packages/jsonschema/_utils.py | 351 + .../jsonschema/benchmarks/__init__.py | 5 + .../jsonschema/benchmarks/const_vs_enum.py | 30 + .../jsonschema/benchmarks/contains.py | 28 + .../jsonschema/benchmarks/issue232.py | 25 + .../jsonschema/benchmarks/issue232/issue.json | 2653 ++++ .../benchmarks/json_schema_test_suite.py | 12 + .../jsonschema/benchmarks/nested_schemas.py | 56 + .../jsonschema/benchmarks/subcomponents.py | 42 + .../jsonschema/benchmarks/unused_registry.py | 35 + .../benchmarks/useless_applicator_schemas.py | 106 + .../jsonschema/benchmarks/useless_keywords.py | 32 + .../benchmarks/validator_creation.py | 14 + .../site-packages/jsonschema/cli.py | 296 + .../site-packages/jsonschema/exceptions.py | 487 + .../site-packages/jsonschema/protocols.py | 236 + .../jsonschema/tests/__init__.py | 0 .../site-packages/jsonschema/tests/_suite.py | 276 + .../jsonschema/tests/fuzz_validate.py | 50 + .../jsonschema/tests/test_cli.py | 907 ++ .../jsonschema/tests/test_deprecations.py | 432 + .../jsonschema/tests/test_exceptions.py | 702 + .../jsonschema/tests/test_format.py | 91 + .../tests/test_jsonschema_test_suite.py | 269 + .../jsonschema/tests/test_types.py | 221 + .../jsonschema/tests/test_utils.py | 138 + .../jsonschema/tests/test_validators.py | 2575 ++++ .../site-packages/jsonschema/validators.py | 1410 ++ .../INSTALLER | 1 + .../METADATA | 54 + .../RECORD | 33 + .../WHEEL | 4 + .../licenses/COPYING | 19 + .../jsonschema_specifications/__init__.py | 12 + .../jsonschema_specifications/_core.py | 38 + .../schemas/draft201909/metaschema.json | 42 + .../draft201909/vocabularies/applicator | 56 + .../schemas/draft201909/vocabularies/content | 17 + .../schemas/draft201909/vocabularies/core | 57 + .../draft201909/vocabularies/meta-data | 37 + .../draft201909/vocabularies/validation | 98 + .../schemas/draft202012/metaschema.json | 58 + .../draft202012/vocabularies/applicator | 48 + .../schemas/draft202012/vocabularies/content | 17 + .../schemas/draft202012/vocabularies/core | 51 + .../schemas/draft202012/vocabularies/format | 14 + .../vocabularies/format-annotation | 14 + .../draft202012/vocabularies/format-assertion | 14 + .../draft202012/vocabularies/meta-data | 37 + .../draft202012/vocabularies/unevaluated | 15 + .../draft202012/vocabularies/validation | 98 + .../schemas/draft3/metaschema.json | 172 + .../schemas/draft4/metaschema.json | 149 + .../schemas/draft6/metaschema.json | 153 + .../schemas/draft7/metaschema.json | 166 + .../tests/__init__.py | 0 .../tests/test_jsonschema_specifications.py | 41 + .../referencing-0.36.2.dist-info/INSTALLER | 1 + .../referencing-0.36.2.dist-info/METADATA | 64 + .../referencing-0.36.2.dist-info/RECORD | 33 + .../referencing-0.36.2.dist-info/WHEEL | 4 + .../licenses/COPYING | 19 + .../site-packages/referencing/__init__.py | 7 + .../site-packages/referencing/_attrs.py | 31 + .../site-packages/referencing/_attrs.pyi | 20 + .../site-packages/referencing/_core.py | 739 ++ .../site-packages/referencing/exceptions.py | 165 + .../site-packages/referencing/jsonschema.py | 642 + .../site-packages/referencing/py.typed | 0 .../site-packages/referencing/retrieval.py | 92 + .../referencing/tests/__init__.py | 0 .../referencing/tests/test_core.py | 1057 ++ .../referencing/tests/test_exceptions.py | 34 + .../referencing/tests/test_jsonschema.py | 382 + .../tests/test_referencing_suite.py | 66 + .../referencing/tests/test_retrieval.py | 106 + .../site-packages/referencing/typing.py | 61 + .../python3.10/site-packages/rpds/__init__.py | 5 + .../site-packages/rpds/__init__.pyi | 77 + .../python3.10/site-packages/rpds/py.typed | 0 .../rpds/rpds.cpython-310-x86_64-linux-gnu.so | Bin 0 -> 1047104 bytes .../rpds_py-0.24.0.dist-info/INSTALLER | 1 + .../rpds_py-0.24.0.dist-info/METADATA | 99 + .../rpds_py-0.24.0.dist-info/RECORD | 10 + .../rpds_py-0.24.0.dist-info/WHEEL | 4 + .../rpds_py-0.24.0.dist-info/licenses/LICENSE | 19 + .../uritemplate-4.1.1.dist-info/INSTALLER | 1 + .../uritemplate-4.1.1.dist-info/LICENSE | 3 + .../uritemplate-4.1.1.dist-info/METADATA | 92 + .../uritemplate-4.1.1.dist-info/RECORD | 17 + .../uritemplate-4.1.1.dist-info/WHEEL | 6 + .../uritemplate-4.1.1.dist-info/top_level.txt | 1 + .../site-packages/uritemplate/__init__.py | 35 + .../site-packages/uritemplate/api.py | 85 + .../site-packages/uritemplate/orderedset.py | 92 + .../site-packages/uritemplate/py.typed | 0 .../site-packages/uritemplate/template.py | 169 + .../site-packages/uritemplate/variable.py | 419 + .../python3.10/site-packages/yaml/__init__.py | 390 + .../_yaml.cpython-310-x86_64-linux-gnu.so | Bin 0 -> 2383664 bytes .../python3.10/site-packages/yaml/composer.py | 139 + .../site-packages/yaml/constructor.py | 748 ++ .../python3.10/site-packages/yaml/cyaml.py | 101 + .../python3.10/site-packages/yaml/dumper.py | 62 + .../python3.10/site-packages/yaml/emitter.py | 1137 ++ .../python3.10/site-packages/yaml/error.py | 75 + .../python3.10/site-packages/yaml/events.py | 86 + .../python3.10/site-packages/yaml/loader.py | 63 + .../python3.10/site-packages/yaml/nodes.py | 49 + .../python3.10/site-packages/yaml/parser.py | 589 + .../python3.10/site-packages/yaml/reader.py | 185 + .../site-packages/yaml/representer.py | 389 + .../python3.10/site-packages/yaml/resolver.py | 227 + .../python3.10/site-packages/yaml/scanner.py | 1435 +++ .../site-packages/yaml/serializer.py | 111 + .../python3.10/site-packages/yaml/tokens.py | 104 + .../migrations/0002_linkgroup_description.py | 18 + backend/api/migrations/0003_linkgroup_icon.py | 18 + ...eated_at_linkgroup_is_favorite_and_more.py | 35 + ...on_alter_linkgroup_is_favorite_and_more.py | 28 + backend/api/models.py | 27 +- backend/api/serializers.py | 69 +- backend/api/urls.py | 17 +- backend/api/views.py | 102 +- backend/backend/settings.py | 8 +- backend/backend/urls.py | 1 + .../staticfiles/admin/css/autocomplete.css | 279 + backend/staticfiles/admin/css/base.css | 1183 ++ backend/staticfiles/admin/css/changelists.css | 343 + backend/staticfiles/admin/css/dark_mode.css | 130 + backend/staticfiles/admin/css/dashboard.css | 29 + backend/staticfiles/admin/css/forms.css | 498 + backend/staticfiles/admin/css/login.css | 61 + backend/staticfiles/admin/css/nav_sidebar.css | 150 + backend/staticfiles/admin/css/responsive.css | 908 ++ .../staticfiles/admin/css/responsive_rtl.css | 89 + backend/staticfiles/admin/css/rtl.css | 293 + .../admin/css/unusable_password_field.css | 19 + .../css/vendor/select2/LICENSE-SELECT2.md | 21 + .../admin/css/vendor/select2/select2.css | 481 + .../admin/css/vendor/select2/select2.min.css | 1 + backend/staticfiles/admin/css/widgets.css | 613 + backend/staticfiles/admin/img/LICENSE | 20 + backend/staticfiles/admin/img/README.txt | 7 + .../staticfiles/admin/img/calendar-icons.svg | 63 + .../admin/img/gis/move_vertex_off.svg | 1 + .../admin/img/gis/move_vertex_on.svg | 1 + .../staticfiles/admin/img/icon-addlink.svg | 3 + backend/staticfiles/admin/img/icon-alert.svg | 3 + .../staticfiles/admin/img/icon-calendar.svg | 9 + .../staticfiles/admin/img/icon-changelink.svg | 3 + backend/staticfiles/admin/img/icon-clock.svg | 9 + .../staticfiles/admin/img/icon-deletelink.svg | 3 + .../staticfiles/admin/img/icon-hidelink.svg | 3 + backend/staticfiles/admin/img/icon-no.svg | 3 + .../admin/img/icon-unknown-alt.svg | 3 + .../staticfiles/admin/img/icon-unknown.svg | 3 + .../staticfiles/admin/img/icon-viewlink.svg | 3 + backend/staticfiles/admin/img/icon-yes.svg | 3 + .../staticfiles/admin/img/inline-delete.svg | 3 + backend/staticfiles/admin/img/search.svg | 3 + .../staticfiles/admin/img/selector-icons.svg | 34 + .../staticfiles/admin/img/sorting-icons.svg | 19 + backend/staticfiles/admin/img/tooltag-add.svg | 3 + .../admin/img/tooltag-arrowright.svg | 3 + backend/staticfiles/admin/js/SelectBox.js | 116 + backend/staticfiles/admin/js/SelectFilter2.js | 307 + backend/staticfiles/admin/js/actions.js | 204 + .../admin/js/admin/DateTimeShortcuts.js | 408 + .../admin/js/admin/RelatedObjectLookups.js | 252 + backend/staticfiles/admin/js/autocomplete.js | 33 + backend/staticfiles/admin/js/calendar.js | 239 + backend/staticfiles/admin/js/cancel.js | 29 + backend/staticfiles/admin/js/change_form.js | 16 + backend/staticfiles/admin/js/core.js | 184 + backend/staticfiles/admin/js/filters.js | 30 + backend/staticfiles/admin/js/inlines.js | 359 + backend/staticfiles/admin/js/jquery.init.js | 8 + backend/staticfiles/admin/js/nav_sidebar.js | 79 + .../staticfiles/admin/js/popup_response.js | 15 + backend/staticfiles/admin/js/prepopulate.js | 43 + .../staticfiles/admin/js/prepopulate_init.js | 15 + backend/staticfiles/admin/js/theme.js | 51 + .../admin/js/unusable_password_field.js | 29 + backend/staticfiles/admin/js/urlify.js | 169 + .../admin/js/vendor/jquery/LICENSE.txt | 20 + .../admin/js/vendor/jquery/jquery.js | 10716 ++++++++++++++++ .../admin/js/vendor/jquery/jquery.min.js | 2 + .../admin/js/vendor/select2/LICENSE.md | 21 + .../admin/js/vendor/select2/i18n/af.js | 3 + .../admin/js/vendor/select2/i18n/ar.js | 3 + .../admin/js/vendor/select2/i18n/az.js | 3 + .../admin/js/vendor/select2/i18n/bg.js | 3 + .../admin/js/vendor/select2/i18n/bn.js | 3 + .../admin/js/vendor/select2/i18n/bs.js | 3 + .../admin/js/vendor/select2/i18n/ca.js | 3 + .../admin/js/vendor/select2/i18n/cs.js | 3 + .../admin/js/vendor/select2/i18n/da.js | 3 + .../admin/js/vendor/select2/i18n/de.js | 3 + .../admin/js/vendor/select2/i18n/dsb.js | 3 + .../admin/js/vendor/select2/i18n/el.js | 3 + .../admin/js/vendor/select2/i18n/en.js | 3 + .../admin/js/vendor/select2/i18n/es.js | 3 + .../admin/js/vendor/select2/i18n/et.js | 3 + .../admin/js/vendor/select2/i18n/eu.js | 3 + .../admin/js/vendor/select2/i18n/fa.js | 3 + .../admin/js/vendor/select2/i18n/fi.js | 3 + .../admin/js/vendor/select2/i18n/fr.js | 3 + .../admin/js/vendor/select2/i18n/gl.js | 3 + .../admin/js/vendor/select2/i18n/he.js | 3 + .../admin/js/vendor/select2/i18n/hi.js | 3 + .../admin/js/vendor/select2/i18n/hr.js | 3 + .../admin/js/vendor/select2/i18n/hsb.js | 3 + .../admin/js/vendor/select2/i18n/hu.js | 3 + .../admin/js/vendor/select2/i18n/hy.js | 3 + .../admin/js/vendor/select2/i18n/id.js | 3 + .../admin/js/vendor/select2/i18n/is.js | 3 + .../admin/js/vendor/select2/i18n/it.js | 3 + .../admin/js/vendor/select2/i18n/ja.js | 3 + .../admin/js/vendor/select2/i18n/ka.js | 3 + .../admin/js/vendor/select2/i18n/km.js | 3 + .../admin/js/vendor/select2/i18n/ko.js | 3 + .../admin/js/vendor/select2/i18n/lt.js | 3 + .../admin/js/vendor/select2/i18n/lv.js | 3 + .../admin/js/vendor/select2/i18n/mk.js | 3 + .../admin/js/vendor/select2/i18n/ms.js | 3 + .../admin/js/vendor/select2/i18n/nb.js | 3 + .../admin/js/vendor/select2/i18n/ne.js | 3 + .../admin/js/vendor/select2/i18n/nl.js | 3 + .../admin/js/vendor/select2/i18n/pl.js | 3 + .../admin/js/vendor/select2/i18n/ps.js | 3 + .../admin/js/vendor/select2/i18n/pt-BR.js | 3 + .../admin/js/vendor/select2/i18n/pt.js | 3 + .../admin/js/vendor/select2/i18n/ro.js | 3 + .../admin/js/vendor/select2/i18n/ru.js | 3 + .../admin/js/vendor/select2/i18n/sk.js | 3 + .../admin/js/vendor/select2/i18n/sl.js | 3 + .../admin/js/vendor/select2/i18n/sq.js | 3 + .../admin/js/vendor/select2/i18n/sr-Cyrl.js | 3 + .../admin/js/vendor/select2/i18n/sr.js | 3 + .../admin/js/vendor/select2/i18n/sv.js | 3 + .../admin/js/vendor/select2/i18n/th.js | 3 + .../admin/js/vendor/select2/i18n/tk.js | 3 + .../admin/js/vendor/select2/i18n/tr.js | 3 + .../admin/js/vendor/select2/i18n/uk.js | 3 + .../admin/js/vendor/select2/i18n/vi.js | 3 + .../admin/js/vendor/select2/i18n/zh-CN.js | 3 + .../admin/js/vendor/select2/i18n/zh-TW.js | 3 + .../admin/js/vendor/select2/select2.full.js | 6820 ++++++++++ .../js/vendor/select2/select2.full.min.js | 2 + .../admin/js/vendor/xregexp/LICENSE.txt | 21 + .../admin/js/vendor/xregexp/xregexp.js | 6126 +++++++++ .../admin/js/vendor/xregexp/xregexp.min.js | 17 + .../css/jquery.autocomplete.css | 38 + .../django_extensions/img/indicator.gif | Bin 0 -> 1553 bytes .../django_extensions/js/jquery.ajaxQueue.js | 116 + .../js/jquery.autocomplete.js | 1152 ++ .../django_extensions/js/jquery.bgiframe.js | 39 + .../redoc/bundles/redoc.standalone.js | 1832 +++ .../bundles/redoc.standalone.js.LICENSE.txt | 102 + .../redoc/bundles/redoc.standalone.js.map | 1 + .../swagger-ui-dist/favicon-32x32.png | Bin 0 -> 628 bytes .../swagger-ui-dist/oauth2-redirect.html | 79 + .../swagger-ui-dist/swagger-ui-bundle.js | 2 + .../swagger-ui-bundle.js.LICENSE.txt | 202 + .../swagger-ui-dist/swagger-ui-bundle.js.map | 1 + .../swagger-ui-standalone-preset.js | 2 + .../swagger-ui-standalone-preset.js.map | 1 + .../swagger-ui-dist/swagger-ui.css | 3 + .../swagger-ui-dist/swagger-ui.css.map | 1 + .../css/bootstrap-theme.min.css | 6 + .../css/bootstrap-theme.min.css.map | 1 + .../rest_framework/css/bootstrap-tweaks.css | 237 + .../rest_framework/css/bootstrap.min.css | 6 + .../rest_framework/css/bootstrap.min.css.map | 1 + .../rest_framework/css/default.css | 82 + .../rest_framework/css/font-awesome-4.0.3.css | 1338 ++ .../rest_framework/css/prettify.css | 30 + .../rest_framework/docs/css/base.css | 359 + .../rest_framework/docs/css/highlight.css | 125 + .../docs/css/jquery.json-view.min.css | 11 + .../rest_framework/docs/img/favicon.ico | Bin 0 -> 5430 bytes .../rest_framework/docs/img/grid.png | Bin 0 -> 1458 bytes .../staticfiles/rest_framework/docs/js/api.js | 315 + .../rest_framework/docs/js/highlight.pack.js | 2 + .../docs/js/jquery.json-view.min.js | 7 + .../fonts/fontawesome-webfont.eot | Bin 0 -> 38205 bytes .../fonts/fontawesome-webfont.svg | 414 + .../fonts/fontawesome-webfont.ttf | Bin 0 -> 80652 bytes .../fonts/fontawesome-webfont.woff | Bin 0 -> 44432 bytes .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes .../img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes .../img/glyphicons-halflings.png | Bin 0 -> 12762 bytes .../staticfiles/rest_framework/img/grid.png | Bin 0 -> 1458 bytes .../rest_framework/js/ajax-form.js | 133 + .../rest_framework/js/bootstrap.min.js | 6 + .../rest_framework/js/coreapi-0.1.1.js | 2043 +++ backend/staticfiles/rest_framework/js/csrf.js | 53 + .../staticfiles/rest_framework/js/default.js | 47 + .../rest_framework/js/jquery-3.7.1.min.js | 2 + .../rest_framework/js/load-ajax-form.js | 3 + .../rest_framework/js/prettify-min.js | 28 + .../storage/avatars/Дизайн_без_названия.png | Bin 0 -> 22113 bytes .../customization/Дизайн_без_названия.png | Bin 0 -> 22113 bytes backend/storage/link_groups/1.png | Bin 0 -> 481951 bytes backend/storage/link_groups/3.png | Bin 0 -> 11921 bytes .../link_groups/Дизайн_без_названия.png | Bin 0 -> 22113 bytes backend/storage/links/2.png | Bin 0 -> 8674 bytes backend/storage/links/3.png | Bin 0 -> 11921 bytes .../ChatGPT_Image_3_мая_2025_г._11_35_43.png | Bin 0 -> 1298967 bytes backend/storage/links/favicon-16x16.png | Bin 0 -> 629 bytes .../links/photo_2022-03-20_22-03-49.jpg | Bin 0 -> 12795 bytes frontend/linktree-frontend/next.config.ts | 35 +- .../public/assets/img/iceland.jpg | Bin 0 -> 67944 bytes .../public/assets/img/iceland.png | Bin 0 -> 481951 bytes .../linktree-frontend/public/manifest.json | 25 + .../app/{ => (protected)}/auth/login/page.tsx | 0 .../app/(protected)/auth/register/page.tsx | 238 + .../src/app/(protected)/dashboard/page.tsx | 390 + .../src/app/(protected)/layout.tsx | 80 + .../src/app/(protected)/page.tsx | 76 + .../src/app/[username]/layout.tsx | 31 + .../src/app/[username]/page.tsx | 141 + .../src/app/components/LayoutWrapper.tsx | 157 + .../src/app/components/ProfileCard.tsx | 92 +- .../src/app/components/modal.tsx | 29 + frontend/linktree-frontend/src/app/layout.tsx | 113 +- .../src/app/username/page.tsx | 52 - 784 files changed, 124024 insertions(+), 289 deletions(-) create mode 100644 .history/backend/api/models_20250507135815.py create mode 100644 .history/backend/api/models_20250507135936.py create mode 100644 .history/backend/api/models_20250507140013.py create mode 100644 .history/backend/api/models_20250507145448.py create mode 100644 .history/backend/api/serializers_20250507134438.py create mode 100644 .history/backend/api/serializers_20250507142241.py create mode 100644 .history/backend/api/serializers_20250507145525.py create mode 100644 .history/backend/api/serializers_20250507145609.py create mode 100644 .history/backend/api/urls_20250507072806.py create mode 100644 .history/backend/api/urls_20250507072816.py create mode 100644 .history/backend/api/urls_20250507080627.py create mode 100644 .history/backend/api/urls_20250507080637.py create mode 100644 .history/backend/api/urls_20250507080822.py create mode 100644 .history/backend/api/urls_20250507081428.py create mode 100644 .history/backend/api/urls_20250507081622.py create mode 100644 .history/backend/api/views_20250507072833.py create mode 100644 .history/backend/api/views_20250507072920.py create mode 100644 .history/backend/api/views_20250507073141.py create mode 100644 .history/backend/api/views_20250507073143.py create mode 100644 .history/backend/api/views_20250507141914.py create mode 100644 .history/backend/api/views_20250507141924.py create mode 100644 .history/backend/api/views_20250507142311.py create mode 100644 .history/backend/api/views_20250507142317.py create mode 100644 .history/backend/api/views_20250507142335.py create mode 100644 .history/backend/api/views_20250507145006.py create mode 100644 .history/backend/api/views_20250507145615.py create mode 100644 .history/backend/api/views_20250507150101.py create mode 100644 .history/backend/api/views_20250507150709.py create mode 100644 .history/backend/api/views_20250507150738.py create mode 100644 .history/backend/api/views_20250507150907.py create mode 100644 .history/backend/api/views_20250507151205.py create mode 100644 .history/backend/api/views_20250507151600.py create mode 100644 .history/backend/backend/settings_20250507080801.py create mode 100644 .history/backend/backend/settings_20250507080850.py create mode 100644 .history/backend/backend/settings_20250507081134.py create mode 100644 .history/backend/backend/settings_20250507081237.py create mode 100644 .history/backend/backend/settings_20250507082006.py create mode 100644 .history/backend/backend/settings_20250507082028.py create mode 100644 .history/backend/backend/urls_20250507080600.py create mode 100644 .history/backend/backend/urls_20250507081420.py create mode 100644 .history/frontend/linktree-frontend/.next/types/app/dashboard/page_20250507074450.ts create mode 100644 .history/frontend/linktree-frontend/.next/types/app/dashboard/page_20250507074950.ts create mode 100644 .history/frontend/linktree-frontend/next.config_20250507131744.ts create mode 100644 .history/frontend/linktree-frontend/next.config_20250507133920.ts create mode 100644 .history/frontend/linktree-frontend/next.config_20250507133940.ts create mode 100644 .history/frontend/linktree-frontend/package_20250507131936.json create mode 100644 .history/frontend/linktree-frontend/public/manifest_20250507074158.json create mode 100644 .history/frontend/linktree-frontend/public/manifest_20250507074202.json create mode 100644 .history/frontend/linktree-frontend/public/manifest_20250507074217.json create mode 100644 .history/frontend/linktree-frontend/public/manifest_20250507074316.json create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/auth/register/page_20250507082845.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/auth/register/page_20250507082848.tsx rename frontend/linktree-frontend/src/app/dashboard/page.tsx => .history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250506191940.tsx (100%) create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507074950.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507102038.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507102107.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507140312.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507140327.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507140923.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507143628.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507074711.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507074730.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507075127.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507075632.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507101018.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507101046.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507101125.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507101149.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507101154.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507101201.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507101421.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507101434.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507101459.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507134134.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507134143.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507140825.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507142027.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507142048.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/layout_20250507142055.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/page_20250507075005.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/(protected)/page_20250507075027.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507073825.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507073826.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507073827.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507075136.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507075137.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507075251.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507075252.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507075546.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507075547.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507075723.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507075724.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507075842.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507075843.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507095308.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507095309.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507095439.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507095440.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507095616.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507095617.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/layout_20250507100758.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507071916.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507072425.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507072426.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507072646.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507072648.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507073425.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507073426.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507073635.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507073636.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507080146.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507080147.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507150317.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507150318.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507151531.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507151532.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507151554.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507151555.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507152817.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507152818.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/[username]/page_20250507152851.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/components/LayoutWrapper_20250507100116.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/components/LayoutWrapper_20250507100121.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/components/LayoutWrapper_20250507100540.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/components/ProfileCard_20250507141524.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/components/modal_20250507101831.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/components/modal_20250507101834.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/layout_20250507074303.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/layout_20250507075244.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/layout_20250507075850.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/layout_20250507094757.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/layout_20250507095932.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/layout_20250507100131.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/layout_20250507100150.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/layout_20250507100157.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/layout_20250507100158.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/layout_20250507100751.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/layout_20250507100816.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/page_20250507075037.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/page_20250507075101.tsx create mode 100644 .history/frontend/linktree-frontend/src/app/username/page_20250507071917.tsx create mode 100755 .venv/bin/jsonschema create mode 100644 .venv/lib/python3.10/site-packages/PyYAML-6.0.2.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/PyYAML-6.0.2.dist-info/LICENSE create mode 100644 .venv/lib/python3.10/site-packages/PyYAML-6.0.2.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/PyYAML-6.0.2.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/PyYAML-6.0.2.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/PyYAML-6.0.2.dist-info/top_level.txt create mode 100644 .venv/lib/python3.10/site-packages/_yaml/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/attr/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/attr/__init__.pyi create mode 100644 .venv/lib/python3.10/site-packages/attr/_cmp.py create mode 100644 .venv/lib/python3.10/site-packages/attr/_cmp.pyi create mode 100644 .venv/lib/python3.10/site-packages/attr/_compat.py create mode 100644 .venv/lib/python3.10/site-packages/attr/_config.py create mode 100644 .venv/lib/python3.10/site-packages/attr/_funcs.py create mode 100644 .venv/lib/python3.10/site-packages/attr/_make.py create mode 100644 .venv/lib/python3.10/site-packages/attr/_next_gen.py create mode 100644 .venv/lib/python3.10/site-packages/attr/_typing_compat.pyi create mode 100644 .venv/lib/python3.10/site-packages/attr/_version_info.py create mode 100644 .venv/lib/python3.10/site-packages/attr/_version_info.pyi create mode 100644 .venv/lib/python3.10/site-packages/attr/converters.py create mode 100644 .venv/lib/python3.10/site-packages/attr/converters.pyi create mode 100644 .venv/lib/python3.10/site-packages/attr/exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/attr/exceptions.pyi create mode 100644 .venv/lib/python3.10/site-packages/attr/filters.py create mode 100644 .venv/lib/python3.10/site-packages/attr/filters.pyi create mode 100644 .venv/lib/python3.10/site-packages/attr/py.typed create mode 100644 .venv/lib/python3.10/site-packages/attr/setters.py create mode 100644 .venv/lib/python3.10/site-packages/attr/setters.pyi create mode 100644 .venv/lib/python3.10/site-packages/attr/validators.py create mode 100644 .venv/lib/python3.10/site-packages/attr/validators.pyi create mode 100644 .venv/lib/python3.10/site-packages/attrs-25.3.0.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/attrs-25.3.0.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/attrs-25.3.0.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/attrs-25.3.0.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/attrs-25.3.0.dist-info/licenses/LICENSE create mode 100644 .venv/lib/python3.10/site-packages/attrs/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/attrs/__init__.pyi create mode 100644 .venv/lib/python3.10/site-packages/attrs/converters.py create mode 100644 .venv/lib/python3.10/site-packages/attrs/exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/attrs/filters.py create mode 100644 .venv/lib/python3.10/site-packages/attrs/py.typed create mode 100644 .venv/lib/python3.10/site-packages/attrs/setters.py create mode 100644 .venv/lib/python3.10/site-packages/attrs/validators.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions-4.1.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/django_extensions-4.1.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/django_extensions-4.1.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/django_extensions-4.1.dist-info/REQUESTED create mode 100644 .venv/lib/python3.10/site-packages/django_extensions-4.1.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/django_extensions-4.1.dist-info/licenses/LICENSE create mode 100644 .venv/lib/python3.10/site-packages/django_extensions-4.1.dist-info/top_level.txt create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/admin/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/admin/filter.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/admin/widgets.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/apps.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/auth/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/auth/mixins.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/collision_resolvers.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/compat.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/app_template/__init__.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/app_template/forms.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/app_template/migrations/__init__.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/app_template/models.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/app_template/urls.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/app_template/views.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/command_template/management/__init__.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/command_template/management/commands/__init__.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/command_template/management/commands/sample.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/jobs_template/jobs/__init__.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/jobs_template/jobs/daily/__init__.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/jobs_template/jobs/hourly/__init__.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/jobs_template/jobs/monthly/__init__.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/jobs_template/jobs/sample.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/jobs_template/jobs/weekly/__init__.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/jobs_template/jobs/yearly/__init__.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/template_tags_template/templatetags/__init__.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/conf/template_tags_template/templatetags/sample.py.tmpl create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/db/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/db/fields/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/db/fields/json.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/db/models.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/import_subclasses.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/jobs/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/jobs/daily/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/jobs/daily/cache_cleanup.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/jobs/daily/daily_cleanup.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/jobs/hourly/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/jobs/minutely/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/jobs/monthly/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/jobs/weekly/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/jobs/yearly/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/ar/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/da/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/da/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/de/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/de/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/el/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/el/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/en/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/en/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/es/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/es/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/fr/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/fr/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/hu/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/hu/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/id/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/id/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/it/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/it/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/ja/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/ja/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/pl/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/pl/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/pt/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/pt/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/pt_BR/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/pt_BR/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/ro/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/ro/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/ru/LC_MESSAGES/django.mo create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/locale/ru/LC_MESSAGES/django.po create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/logging/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/logging/filters.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/base.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/color.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/admin_generator.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/clean_pyc.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/clear_cache.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/compile_pyc.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/create_command.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/create_jobs.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/create_template_tags.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/delete_squashed_migrations.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/describe_form.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/drop_test_database.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/dumpscript.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/export_emails.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/find_template.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/generate_password.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/generate_secret_key.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/graph_models.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/list_model_info.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/list_signals.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/mail_debug.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/managestate.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/merge_model_instances.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/notes.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/print_settings.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/print_user_for_session.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/raise_test_exception.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/reset_db.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/reset_schema.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/runjob.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/runjobs.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/runprofileserver.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/runscript.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/runserver_plus.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/set_default_site.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/set_fake_emails.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/set_fake_passwords.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/shell_plus.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/show_permissions.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/show_template_tags.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/show_urls.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/sqlcreate.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/sqldiff.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/sqldsn.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/sync_s3.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/syncdata.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/unreferenced_files.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/update_permissions.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/commands/validate_templates.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/debug_cursor.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/email_notifications.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/jobs.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/modelviz.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/mysql.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/notebook_extension.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/shells.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/signals.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/technical_response.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/management/utils.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/models.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/mongodb/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/mongodb/fields/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/mongodb/fields/json.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/mongodb/models.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/py.typed create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/settings.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/static/django_extensions/css/jquery.autocomplete.css create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/static/django_extensions/img/indicator.gif create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/static/django_extensions/js/jquery.ajaxQueue.js create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/static/django_extensions/js/jquery.autocomplete.js create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/static/django_extensions/js/jquery.bgiframe.js create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templates/django_extensions/graph_models/django2018/digraph.dot create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templates/django_extensions/graph_models/django2018/label.dot create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templates/django_extensions/graph_models/django2018/relation.dot create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templates/django_extensions/graph_models/django2018style/digraph.dot create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templates/django_extensions/graph_models/django2018style/label.dot create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templates/django_extensions/graph_models/django2018style/relation.dot create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templates/django_extensions/graph_models/original/digraph.dot create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templates/django_extensions/graph_models/original/label.dot create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templates/django_extensions/graph_models/original/relation.dot create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templates/django_extensions/widgets/foreignkey_searchinput.html create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templatetags/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templatetags/debugger_tags.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templatetags/highlighting.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templatetags/indent_text.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templatetags/syntax_color.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/templatetags/widont.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/utils/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/utils/deprecation.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/utils/dia2django.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/utils/internal_ips.py create mode 100644 .venv/lib/python3.10/site-packages/django_extensions/validators.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular-0.28.0.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular-0.28.0.dist-info/LICENSE create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular-0.28.0.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular-0.28.0.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular-0.28.0.dist-info/REQUESTED create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular-0.28.0.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular-0.28.0.dist-info/top_level.txt create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/apps.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/authentication.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/checks.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/contrib/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/contrib/django_filters.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/contrib/django_oauth_toolkit.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/contrib/djangorestframework_camel_case.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/contrib/knox_auth_token.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/contrib/pydantic.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/contrib/rest_auth.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/contrib/rest_framework.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/contrib/rest_framework_dataclasses.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/contrib/rest_framework_gis.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/contrib/rest_framework_jwt.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/contrib/rest_framework_recursive.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/contrib/rest_framework_simplejwt.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/contrib/rest_polymorphic.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/drainage.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/extensions.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/generators.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/helpers.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/hooks.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/management/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/management/commands/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/management/commands/spectacular.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/openapi.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/plumbing.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/py.typed create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/renderers.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/serializers.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/settings.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/templates/drf_spectacular/redoc.html create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/templates/drf_spectacular/swagger_ui.html create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/templates/drf_spectacular/swagger_ui.js create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/types.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/utils.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/validation/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/validation/openapi_3_0_schema.json create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/validation/openapi_3_1_schema.json create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular/views.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar-2025.5.1.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar-2025.5.1.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar-2025.5.1.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar-2025.5.1.dist-info/REQUESTED create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar-2025.5.1.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar-2025.5.1.dist-info/licenses/LICENSE create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar-2025.5.1.dist-info/top_level.txt create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/apps.py create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/py.typed create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/static/drf_spectacular_sidecar/redoc/bundles/redoc.standalone.js create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/static/drf_spectacular_sidecar/redoc/bundles/redoc.standalone.js.LICENSE.txt create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/static/drf_spectacular_sidecar/redoc/bundles/redoc.standalone.js.map create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/static/drf_spectacular_sidecar/swagger-ui-dist/favicon-32x32.png create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/static/drf_spectacular_sidecar/swagger-ui-dist/oauth2-redirect.html create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/static/drf_spectacular_sidecar/swagger-ui-dist/swagger-ui-bundle.js create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/static/drf_spectacular_sidecar/swagger-ui-dist/swagger-ui-bundle.js.LICENSE.txt create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/static/drf_spectacular_sidecar/swagger-ui-dist/swagger-ui-bundle.js.map create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/static/drf_spectacular_sidecar/swagger-ui-dist/swagger-ui-standalone-preset.js create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/static/drf_spectacular_sidecar/swagger-ui-dist/swagger-ui-standalone-preset.js.map create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/static/drf_spectacular_sidecar/swagger-ui-dist/swagger-ui.css create mode 100644 .venv/lib/python3.10/site-packages/drf_spectacular_sidecar/static/drf_spectacular_sidecar/swagger-ui-dist/swagger-ui.css.map create mode 100644 .venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/LICENSE create mode 100644 .venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/top_level.txt create mode 100644 .venv/lib/python3.10/site-packages/inflection.py create mode 100644 .venv/lib/python3.10/site-packages/inflection/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/inflection/py.typed create mode 100644 .venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/entry_points.txt create mode 100644 .venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/licenses/COPYING create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/__main__.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/_format.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/_keywords.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/_legacy_keywords.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/_types.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/_typing.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/_utils.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/benchmarks/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/benchmarks/const_vs_enum.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/benchmarks/contains.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/benchmarks/issue232.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/benchmarks/issue232/issue.json create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/benchmarks/json_schema_test_suite.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/benchmarks/nested_schemas.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/benchmarks/subcomponents.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/benchmarks/unused_registry.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/benchmarks/useless_applicator_schemas.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/benchmarks/useless_keywords.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/benchmarks/validator_creation.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/cli.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/protocols.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/tests/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/tests/_suite.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/tests/fuzz_validate.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/tests/test_cli.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/tests/test_deprecations.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/tests/test_exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/tests/test_format.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/tests/test_jsonschema_test_suite.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/tests/test_types.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/tests/test_utils.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/tests/test_validators.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema/validators.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/licenses/COPYING create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/_core.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/metaschema.json create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/applicator create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/content create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/core create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/meta-data create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/validation create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/metaschema.json create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/applicator create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/content create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/core create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format-annotation create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format-assertion create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/meta-data create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/unevaluated create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/validation create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft3/metaschema.json create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft4/metaschema.json create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft6/metaschema.json create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft7/metaschema.json create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/tests/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/jsonschema_specifications/tests/test_jsonschema_specifications.py create mode 100644 .venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/licenses/COPYING create mode 100644 .venv/lib/python3.10/site-packages/referencing/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/referencing/_attrs.py create mode 100644 .venv/lib/python3.10/site-packages/referencing/_attrs.pyi create mode 100644 .venv/lib/python3.10/site-packages/referencing/_core.py create mode 100644 .venv/lib/python3.10/site-packages/referencing/exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/referencing/jsonschema.py create mode 100644 .venv/lib/python3.10/site-packages/referencing/py.typed create mode 100644 .venv/lib/python3.10/site-packages/referencing/retrieval.py create mode 100644 .venv/lib/python3.10/site-packages/referencing/tests/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/referencing/tests/test_core.py create mode 100644 .venv/lib/python3.10/site-packages/referencing/tests/test_exceptions.py create mode 100644 .venv/lib/python3.10/site-packages/referencing/tests/test_jsonschema.py create mode 100644 .venv/lib/python3.10/site-packages/referencing/tests/test_referencing_suite.py create mode 100644 .venv/lib/python3.10/site-packages/referencing/tests/test_retrieval.py create mode 100644 .venv/lib/python3.10/site-packages/referencing/typing.py create mode 100644 .venv/lib/python3.10/site-packages/rpds/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/rpds/__init__.pyi create mode 100644 .venv/lib/python3.10/site-packages/rpds/py.typed create mode 100755 .venv/lib/python3.10/site-packages/rpds/rpds.cpython-310-x86_64-linux-gnu.so create mode 100644 .venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/licenses/LICENSE create mode 100644 .venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/INSTALLER create mode 100644 .venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/LICENSE create mode 100644 .venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/METADATA create mode 100644 .venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/RECORD create mode 100644 .venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/WHEEL create mode 100644 .venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/top_level.txt create mode 100644 .venv/lib/python3.10/site-packages/uritemplate/__init__.py create mode 100644 .venv/lib/python3.10/site-packages/uritemplate/api.py create mode 100644 .venv/lib/python3.10/site-packages/uritemplate/orderedset.py create mode 100644 .venv/lib/python3.10/site-packages/uritemplate/py.typed create mode 100644 .venv/lib/python3.10/site-packages/uritemplate/template.py create mode 100644 .venv/lib/python3.10/site-packages/uritemplate/variable.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/__init__.py create mode 100755 .venv/lib/python3.10/site-packages/yaml/_yaml.cpython-310-x86_64-linux-gnu.so create mode 100644 .venv/lib/python3.10/site-packages/yaml/composer.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/constructor.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/cyaml.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/dumper.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/emitter.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/error.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/events.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/loader.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/nodes.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/parser.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/reader.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/representer.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/resolver.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/scanner.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/serializer.py create mode 100644 .venv/lib/python3.10/site-packages/yaml/tokens.py create mode 100644 backend/api/migrations/0002_linkgroup_description.py create mode 100644 backend/api/migrations/0003_linkgroup_icon.py create mode 100644 backend/api/migrations/0004_linkgroup_created_at_linkgroup_is_favorite_and_more.py create mode 100644 backend/api/migrations/0005_alter_link_icon_alter_linkgroup_is_favorite_and_more.py create mode 100644 backend/staticfiles/admin/css/autocomplete.css create mode 100644 backend/staticfiles/admin/css/base.css create mode 100644 backend/staticfiles/admin/css/changelists.css create mode 100644 backend/staticfiles/admin/css/dark_mode.css create mode 100644 backend/staticfiles/admin/css/dashboard.css create mode 100644 backend/staticfiles/admin/css/forms.css create mode 100644 backend/staticfiles/admin/css/login.css create mode 100644 backend/staticfiles/admin/css/nav_sidebar.css create mode 100644 backend/staticfiles/admin/css/responsive.css create mode 100644 backend/staticfiles/admin/css/responsive_rtl.css create mode 100644 backend/staticfiles/admin/css/rtl.css create mode 100644 backend/staticfiles/admin/css/unusable_password_field.css create mode 100644 backend/staticfiles/admin/css/vendor/select2/LICENSE-SELECT2.md create mode 100644 backend/staticfiles/admin/css/vendor/select2/select2.css create mode 100644 backend/staticfiles/admin/css/vendor/select2/select2.min.css create mode 100644 backend/staticfiles/admin/css/widgets.css create mode 100644 backend/staticfiles/admin/img/LICENSE create mode 100644 backend/staticfiles/admin/img/README.txt create mode 100644 backend/staticfiles/admin/img/calendar-icons.svg create mode 100644 backend/staticfiles/admin/img/gis/move_vertex_off.svg create mode 100644 backend/staticfiles/admin/img/gis/move_vertex_on.svg create mode 100644 backend/staticfiles/admin/img/icon-addlink.svg create mode 100644 backend/staticfiles/admin/img/icon-alert.svg create mode 100644 backend/staticfiles/admin/img/icon-calendar.svg create mode 100644 backend/staticfiles/admin/img/icon-changelink.svg create mode 100644 backend/staticfiles/admin/img/icon-clock.svg create mode 100644 backend/staticfiles/admin/img/icon-deletelink.svg create mode 100644 backend/staticfiles/admin/img/icon-hidelink.svg create mode 100644 backend/staticfiles/admin/img/icon-no.svg create mode 100644 backend/staticfiles/admin/img/icon-unknown-alt.svg create mode 100644 backend/staticfiles/admin/img/icon-unknown.svg create mode 100644 backend/staticfiles/admin/img/icon-viewlink.svg create mode 100644 backend/staticfiles/admin/img/icon-yes.svg create mode 100644 backend/staticfiles/admin/img/inline-delete.svg create mode 100644 backend/staticfiles/admin/img/search.svg create mode 100644 backend/staticfiles/admin/img/selector-icons.svg create mode 100644 backend/staticfiles/admin/img/sorting-icons.svg create mode 100644 backend/staticfiles/admin/img/tooltag-add.svg create mode 100644 backend/staticfiles/admin/img/tooltag-arrowright.svg create mode 100644 backend/staticfiles/admin/js/SelectBox.js create mode 100644 backend/staticfiles/admin/js/SelectFilter2.js create mode 100644 backend/staticfiles/admin/js/actions.js create mode 100644 backend/staticfiles/admin/js/admin/DateTimeShortcuts.js create mode 100644 backend/staticfiles/admin/js/admin/RelatedObjectLookups.js create mode 100644 backend/staticfiles/admin/js/autocomplete.js create mode 100644 backend/staticfiles/admin/js/calendar.js create mode 100644 backend/staticfiles/admin/js/cancel.js create mode 100644 backend/staticfiles/admin/js/change_form.js create mode 100644 backend/staticfiles/admin/js/core.js create mode 100644 backend/staticfiles/admin/js/filters.js create mode 100644 backend/staticfiles/admin/js/inlines.js create mode 100644 backend/staticfiles/admin/js/jquery.init.js create mode 100644 backend/staticfiles/admin/js/nav_sidebar.js create mode 100644 backend/staticfiles/admin/js/popup_response.js create mode 100644 backend/staticfiles/admin/js/prepopulate.js create mode 100644 backend/staticfiles/admin/js/prepopulate_init.js create mode 100644 backend/staticfiles/admin/js/theme.js create mode 100644 backend/staticfiles/admin/js/unusable_password_field.js create mode 100644 backend/staticfiles/admin/js/urlify.js create mode 100644 backend/staticfiles/admin/js/vendor/jquery/LICENSE.txt create mode 100644 backend/staticfiles/admin/js/vendor/jquery/jquery.js create mode 100644 backend/staticfiles/admin/js/vendor/jquery/jquery.min.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/LICENSE.md create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/af.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/ar.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/az.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/bg.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/bn.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/bs.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/ca.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/cs.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/da.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/de.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/dsb.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/el.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/en.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/es.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/et.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/eu.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/fa.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/fi.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/fr.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/gl.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/he.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/hi.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/hr.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/hsb.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/hu.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/hy.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/id.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/is.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/it.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/ja.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/ka.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/km.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/ko.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/lt.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/lv.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/mk.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/ms.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/nb.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/ne.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/nl.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/pl.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/ps.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/pt-BR.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/pt.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/ro.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/ru.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/sk.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/sl.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/sq.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/sr-Cyrl.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/sr.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/sv.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/th.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/tk.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/tr.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/uk.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/vi.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/zh-CN.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/i18n/zh-TW.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/select2.full.js create mode 100644 backend/staticfiles/admin/js/vendor/select2/select2.full.min.js create mode 100644 backend/staticfiles/admin/js/vendor/xregexp/LICENSE.txt create mode 100644 backend/staticfiles/admin/js/vendor/xregexp/xregexp.js create mode 100644 backend/staticfiles/admin/js/vendor/xregexp/xregexp.min.js create mode 100644 backend/staticfiles/django_extensions/css/jquery.autocomplete.css create mode 100644 backend/staticfiles/django_extensions/img/indicator.gif create mode 100644 backend/staticfiles/django_extensions/js/jquery.ajaxQueue.js create mode 100644 backend/staticfiles/django_extensions/js/jquery.autocomplete.js create mode 100644 backend/staticfiles/django_extensions/js/jquery.bgiframe.js create mode 100644 backend/staticfiles/drf_spectacular_sidecar/redoc/bundles/redoc.standalone.js create mode 100644 backend/staticfiles/drf_spectacular_sidecar/redoc/bundles/redoc.standalone.js.LICENSE.txt create mode 100644 backend/staticfiles/drf_spectacular_sidecar/redoc/bundles/redoc.standalone.js.map create mode 100644 backend/staticfiles/drf_spectacular_sidecar/swagger-ui-dist/favicon-32x32.png create mode 100644 backend/staticfiles/drf_spectacular_sidecar/swagger-ui-dist/oauth2-redirect.html create mode 100644 backend/staticfiles/drf_spectacular_sidecar/swagger-ui-dist/swagger-ui-bundle.js create mode 100644 backend/staticfiles/drf_spectacular_sidecar/swagger-ui-dist/swagger-ui-bundle.js.LICENSE.txt create mode 100644 backend/staticfiles/drf_spectacular_sidecar/swagger-ui-dist/swagger-ui-bundle.js.map create mode 100644 backend/staticfiles/drf_spectacular_sidecar/swagger-ui-dist/swagger-ui-standalone-preset.js create mode 100644 backend/staticfiles/drf_spectacular_sidecar/swagger-ui-dist/swagger-ui-standalone-preset.js.map create mode 100644 backend/staticfiles/drf_spectacular_sidecar/swagger-ui-dist/swagger-ui.css create mode 100644 backend/staticfiles/drf_spectacular_sidecar/swagger-ui-dist/swagger-ui.css.map create mode 100644 backend/staticfiles/rest_framework/css/bootstrap-theme.min.css create mode 100644 backend/staticfiles/rest_framework/css/bootstrap-theme.min.css.map create mode 100644 backend/staticfiles/rest_framework/css/bootstrap-tweaks.css create mode 100644 backend/staticfiles/rest_framework/css/bootstrap.min.css create mode 100644 backend/staticfiles/rest_framework/css/bootstrap.min.css.map create mode 100644 backend/staticfiles/rest_framework/css/default.css create mode 100644 backend/staticfiles/rest_framework/css/font-awesome-4.0.3.css create mode 100644 backend/staticfiles/rest_framework/css/prettify.css create mode 100644 backend/staticfiles/rest_framework/docs/css/base.css create mode 100644 backend/staticfiles/rest_framework/docs/css/highlight.css create mode 100644 backend/staticfiles/rest_framework/docs/css/jquery.json-view.min.css create mode 100644 backend/staticfiles/rest_framework/docs/img/favicon.ico create mode 100644 backend/staticfiles/rest_framework/docs/img/grid.png create mode 100644 backend/staticfiles/rest_framework/docs/js/api.js create mode 100644 backend/staticfiles/rest_framework/docs/js/highlight.pack.js create mode 100644 backend/staticfiles/rest_framework/docs/js/jquery.json-view.min.js create mode 100644 backend/staticfiles/rest_framework/fonts/fontawesome-webfont.eot create mode 100644 backend/staticfiles/rest_framework/fonts/fontawesome-webfont.svg create mode 100644 backend/staticfiles/rest_framework/fonts/fontawesome-webfont.ttf create mode 100644 backend/staticfiles/rest_framework/fonts/fontawesome-webfont.woff create mode 100644 backend/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.eot create mode 100644 backend/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.svg create mode 100644 backend/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.ttf create mode 100644 backend/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.woff create mode 100644 backend/staticfiles/rest_framework/fonts/glyphicons-halflings-regular.woff2 create mode 100644 backend/staticfiles/rest_framework/img/glyphicons-halflings-white.png create mode 100644 backend/staticfiles/rest_framework/img/glyphicons-halflings.png create mode 100644 backend/staticfiles/rest_framework/img/grid.png create mode 100644 backend/staticfiles/rest_framework/js/ajax-form.js create mode 100644 backend/staticfiles/rest_framework/js/bootstrap.min.js create mode 100644 backend/staticfiles/rest_framework/js/coreapi-0.1.1.js create mode 100644 backend/staticfiles/rest_framework/js/csrf.js create mode 100644 backend/staticfiles/rest_framework/js/default.js create mode 100644 backend/staticfiles/rest_framework/js/jquery-3.7.1.min.js create mode 100644 backend/staticfiles/rest_framework/js/load-ajax-form.js create mode 100644 backend/staticfiles/rest_framework/js/prettify-min.js create mode 100644 backend/storage/avatars/Дизайн_без_названия.png create mode 100644 backend/storage/customization/Дизайн_без_названия.png create mode 100644 backend/storage/link_groups/1.png create mode 100644 backend/storage/link_groups/3.png create mode 100644 backend/storage/link_groups/Дизайн_без_названия.png create mode 100644 backend/storage/links/2.png create mode 100644 backend/storage/links/3.png create mode 100644 backend/storage/links/ChatGPT_Image_3_мая_2025_г._11_35_43.png create mode 100644 backend/storage/links/favicon-16x16.png create mode 100644 backend/storage/links/photo_2022-03-20_22-03-49.jpg create mode 100644 frontend/linktree-frontend/public/assets/img/iceland.jpg create mode 100644 frontend/linktree-frontend/public/assets/img/iceland.png create mode 100644 frontend/linktree-frontend/public/manifest.json rename frontend/linktree-frontend/src/app/{ => (protected)}/auth/login/page.tsx (100%) create mode 100644 frontend/linktree-frontend/src/app/(protected)/auth/register/page.tsx create mode 100644 frontend/linktree-frontend/src/app/(protected)/dashboard/page.tsx create mode 100644 frontend/linktree-frontend/src/app/(protected)/layout.tsx create mode 100644 frontend/linktree-frontend/src/app/(protected)/page.tsx create mode 100644 frontend/linktree-frontend/src/app/[username]/layout.tsx create mode 100644 frontend/linktree-frontend/src/app/[username]/page.tsx create mode 100644 frontend/linktree-frontend/src/app/components/LayoutWrapper.tsx create mode 100644 frontend/linktree-frontend/src/app/components/modal.tsx delete mode 100644 frontend/linktree-frontend/src/app/username/page.tsx diff --git a/.history/backend/api/models_20250507135815.py b/.history/backend/api/models_20250507135815.py new file mode 100644 index 0000000..62bb23e --- /dev/null +++ b/.history/backend/api/models_20250507135815.py @@ -0,0 +1,35 @@ +from django.db import models +from django.conf import settings + +class LinkGroup(models.Model): + owner = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + related_name='api_link_groups' # уникальное имя, чтобы не конфликтовать с links app + ) + name = models.CharField(max_length=100) + order = models.PositiveIntegerField(default=0) + description = models.TextField(blank=True, null=True) + def __str__(self): + return f"{self.owner.username} - {self.name}" + +class Link(models.Model): + owner = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + related_name='links' + ) + group = models.ForeignKey( + LinkGroup, + on_delete=models.SET_NULL, + null=True, + blank=True, + related_name='links' + ) + title = models.CharField(max_length=200) + url = models.URLField() + icon = models.URLField(blank=True, null=True) + order = models.PositiveIntegerField(default=0) + + def __str__(self): + return self.title \ No newline at end of file diff --git a/.history/backend/api/models_20250507135936.py b/.history/backend/api/models_20250507135936.py new file mode 100644 index 0000000..b6cf020 --- /dev/null +++ b/.history/backend/api/models_20250507135936.py @@ -0,0 +1,41 @@ +from django.db import models +from django.conf import settings + +class LinkGroup(models.Model): + owner = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + related_name='api_link_groups' # уникальное имя, чтобы не конфликтовать с links app + ) + name = models.CharField(max_length=100) + order = models.PositiveIntegerField(default=0) + description = models.TextField(blank=True, null=True) + icon = models.ImageField( + upload_to='link_groups/', + null=True, + blank=True, + help_text='Иконка группы ссылок' + ) + def __str__(self): + return f"{self.owner.username} - {self.name}" + +class Link(models.Model): + owner = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + related_name='links' + ) + group = models.ForeignKey( + LinkGroup, + on_delete=models.SET_NULL, + null=True, + blank=True, + related_name='links' + ) + title = models.CharField(max_length=200) + url = models.URLField() + icon = models.URLField(blank=True, null=True) + order = models.PositiveIntegerField(default=0) + + def __str__(self): + return self.title \ No newline at end of file diff --git a/.history/backend/api/models_20250507140013.py b/.history/backend/api/models_20250507140013.py new file mode 100644 index 0000000..853988e --- /dev/null +++ b/.history/backend/api/models_20250507140013.py @@ -0,0 +1,45 @@ +from django.db import models +from django.conf import settings + +class LinkGroup(models.Model): + owner = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + related_name='api_link_groups' # уникальное имя, чтобы не конфликтовать с links app + ) + name = models.CharField(max_length=100) + order = models.PositiveIntegerField(default=0) + description = models.TextField(blank=True, null=True) + icon = models.ImageField( + upload_to='link_groups/', + null=True, + blank=True, + help_text='Иконка группы ссылок' + ) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + is_public = models.BooleanField(default=False, help_text='Публичная группа ссылок') + is_favorite = models.BooleanField(default=False, help_text='Избранная группа ссылок') + def __str__(self): + return f"{self.owner.username} - {self.name}" + +class Link(models.Model): + owner = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + related_name='links' + ) + group = models.ForeignKey( + LinkGroup, + on_delete=models.SET_NULL, + null=True, + blank=True, + related_name='links' + ) + title = models.CharField(max_length=200) + url = models.URLField() + icon = models.URLField(blank=True, null=True) + order = models.PositiveIntegerField(default=0) + + def __str__(self): + return self.title \ No newline at end of file diff --git a/.history/backend/api/models_20250507145448.py b/.history/backend/api/models_20250507145448.py new file mode 100644 index 0000000..1c0863e --- /dev/null +++ b/.history/backend/api/models_20250507145448.py @@ -0,0 +1,54 @@ +# backend/api/models.py + +from django.db import models +from django.conf import settings + +class LinkGroup(models.Model): + owner = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + related_name='api_link_groups' + ) + name = models.CharField(max_length=100) + order = models.PositiveIntegerField(default=0) + description = models.TextField(blank=True, null=True) + icon = models.ImageField( + upload_to='link_groups/', + null=True, + blank=True, + help_text='Иконка группы ссылок' + ) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + is_public = models.BooleanField(default=False) + is_favorite = models.BooleanField(default=False) + + def __str__(self): + return f"{self.owner.username} — {self.name}" + + +class Link(models.Model): + owner = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + related_name='links' + ) + group = models.ForeignKey( + LinkGroup, + on_delete=models.SET_NULL, + null=True, + blank=True, + related_name='links' + ) + title = models.CharField(max_length=200) + url = models.URLField() + icon = models.ImageField( + upload_to='links/', + null=True, + blank=True, + help_text='Иконка для этой ссылки' + ) + order = models.PositiveIntegerField(default=0) + + def __str__(self): + return self.title diff --git a/.history/backend/api/serializers_20250507134438.py b/.history/backend/api/serializers_20250507134438.py new file mode 100644 index 0000000..98da7ec --- /dev/null +++ b/.history/backend/api/serializers_20250507134438.py @@ -0,0 +1,60 @@ +# api/serializers.py +from rest_framework import serializers +from django.contrib.auth import get_user_model +from .models import Link, LinkGroup + +User = get_user_model() + +class RegisterSerializer(serializers.ModelSerializer): + password = serializers.CharField(write_only=True) + + class Meta: + model = User + fields = ('username', 'email', 'password') + + def create(self, validated_data): + user = User( + username=validated_data['username'], + email=validated_data.get('email', '') + ) + user.set_password(validated_data['password']) + user.save() + return user +# api/serializers.py +from rest_framework import serializers +from django.conf import settings +from .models import Link, LinkGroup + +# сериализатор для ссылок +class LinkSerializer(serializers.ModelSerializer): + class Meta: + model = Link + fields = ['id', 'title', 'url', 'icon', 'order', 'group'] + +# сериализатор для групп со вложенными ссылками +class LinkGroupSerializer(serializers.ModelSerializer): + owner = serializers.ReadOnlyField(source='owner.username') + + class Meta: + model = LinkGroup + fields = [ + 'id', + 'name', + 'description', + 'icon', + 'owner', + 'created_at', + ] + read_only_fields = ['id', 'owner', 'created_at'] + + +from django.contrib.auth import get_user_model +from rest_framework import serializers + +User = get_user_model() + +class UserSerializer(serializers.ModelSerializer): + class Meta: + model = User + # поля, которые хотите отдавать на фронт: + fields = ['id', 'username', 'email', 'full_name', 'bio', 'avatar', 'last_login', 'date_joined'] diff --git a/.history/backend/api/serializers_20250507142241.py b/.history/backend/api/serializers_20250507142241.py new file mode 100644 index 0000000..dcee8e5 --- /dev/null +++ b/.history/backend/api/serializers_20250507142241.py @@ -0,0 +1,65 @@ +# api/serializers.py +from rest_framework import serializers +from django.contrib.auth import get_user_model +from .models import Link, LinkGroup + +User = get_user_model() + +class RegisterSerializer(serializers.ModelSerializer): + password = serializers.CharField(write_only=True) + + class Meta: + model = User + fields = ('username', 'email', 'password') + + def create(self, validated_data): + user = User( + username=validated_data['username'], + email=validated_data.get('email', '') + ) + user.set_password(validated_data['password']) + user.save() + return user +# api/serializers.py +from rest_framework import serializers +from django.conf import settings +from .models import Link, LinkGroup + +# сериализатор для ссылок +class LinkSerializer(serializers.ModelSerializer): + class Meta: + model = Link + fields = ['id', 'title', 'url', 'icon', 'order', 'group'] + +# сериализатор для групп со вложенными ссылками +class LinkGroupSerializer(serializers.ModelSerializer): + owner = serializers.ReadOnlyField(source='owner.username') + + class Meta: + model = LinkGroup + fields = [ + 'id', + 'name', + 'description', + 'icon', + 'owner', + 'created_at', + ] + read_only_fields = ['id', 'owner', 'created_at'] + + +from django.contrib.auth import get_user_model +from rest_framework import serializers + +User = get_user_model() + +class UserSerializer(serializers.ModelSerializer): + class Meta: + model = User + # поля, которые хотите отдавать на фронт: + fields = ['id', 'username', 'email', 'full_name', 'bio', 'avatar', 'last_login', 'date_joined'] + + +class PublicUserGroupsSerializer(serializers.Serializer): + username = serializers.CharField() + groups = LinkGroupSerializer(many=True) \ No newline at end of file diff --git a/.history/backend/api/serializers_20250507145525.py b/.history/backend/api/serializers_20250507145525.py new file mode 100644 index 0000000..1cfd830 --- /dev/null +++ b/.history/backend/api/serializers_20250507145525.py @@ -0,0 +1,66 @@ +# api/serializers.py +from rest_framework import serializers +from django.contrib.auth import get_user_model +from .models import Link, LinkGroup + +User = get_user_model() + +class RegisterSerializer(serializers.ModelSerializer): + password2 = serializers.CharField(write_only=True) + class Meta: + model = User + fields = ['username', 'email', 'first_name', 'last_name', 'password', 'password2'] + extra_kwargs = {'password': {'write_only': True}} + + def validate(self, attrs): + if attrs['password'] != attrs.pop('password2'): + raise serializers.ValidationError("Пароли не совпадают") + return attrs + + def create(self, validated_data): + return User.objects.create_user(**validated_data) + + +# api/serializers.py +from rest_framework import serializers +from django.conf import settings +from .models import Link, LinkGroup + +# сериализатор для ссылок +class LinkSerializer(serializers.ModelSerializer): + class Meta: + model = Link + fields = ['id', 'title', 'url', 'icon', 'order', 'group'] + +# сериализатор для групп со вложенными ссылками +class LinkGroupSerializer(serializers.ModelSerializer): + owner = serializers.ReadOnlyField(source='owner.username') + + class Meta: + model = LinkGroup + fields = [ + 'id', + 'name', + 'description', + 'icon', + 'owner', + 'created_at', + ] + read_only_fields = ['id', 'owner', 'created_at'] + + +from django.contrib.auth import get_user_model +from rest_framework import serializers + +User = get_user_model() + +class UserSerializer(serializers.ModelSerializer): + class Meta: + model = User + # поля, которые хотите отдавать на фронт: + fields = ['id', 'username', 'email', 'full_name', 'bio', 'avatar', 'last_login', 'date_joined'] + + +class PublicUserGroupsSerializer(serializers.Serializer): + username = serializers.CharField() + groups = LinkGroupSerializer(many=True) \ No newline at end of file diff --git a/.history/backend/api/serializers_20250507145609.py b/.history/backend/api/serializers_20250507145609.py new file mode 100644 index 0000000..0be3437 --- /dev/null +++ b/.history/backend/api/serializers_20250507145609.py @@ -0,0 +1,48 @@ +# api/serializers.py +from rest_framework import serializers +from django.contrib.auth import get_user_model +from .models import Link, LinkGroup +from django.conf import settings +from .models import Link, LinkGroup +User = get_user_model() + +class RegisterSerializer(serializers.ModelSerializer): + password2 = serializers.CharField(write_only=True) + class Meta: + model = User + fields = ['username', 'email', 'first_name', 'last_name', 'password', 'password2'] + extra_kwargs = {'password': {'write_only': True}} + + def validate(self, attrs): + if attrs['password'] != attrs.pop('password2'): + raise serializers.ValidationError("Пароли не совпадают") + return attrs + + def create(self, validated_data): + return User.objects.create_user(**validated_data) + + + + +# сериализатор для ссылок +class UserSerializer(serializers.ModelSerializer): + class Meta: + model = User + fields = ['id', 'username', 'email', 'full_name', 'bio', 'avatar', 'last_login', 'date_joined'] + + +class LinkGroupSerializer(serializers.ModelSerializer): + icon = serializers.ImageField(required=False, allow_null=True) + class Meta: + model = LinkGroup + fields = ['id', 'name', 'description', 'icon', 'order', 'is_public', 'is_favorite', + 'created_at', 'updated_at'] + read_only_fields = ['id', 'created_at', 'updated_at'] + + +class LinkSerializer(serializers.ModelSerializer): + icon = serializers.ImageField(required=False, allow_null=True) + class Meta: + model = Link + fields = ['id', 'title', 'url', 'icon', 'group', 'order'] + read_only_fields = ['id'] \ No newline at end of file diff --git a/.history/backend/api/urls_20250507072806.py b/.history/backend/api/urls_20250507072806.py new file mode 100644 index 0000000..8a910cd --- /dev/null +++ b/.history/backend/api/urls_20250507072806.py @@ -0,0 +1,24 @@ +from django.urls import path +from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView +from .views import ( + RegisterView, + UserProfileView, + LinkViewSet, + LinkGroupViewSet +) +from rest_framework.routers import DefaultRouter + +router = DefaultRouter() +router.register('links', LinkViewSet, basename='link') +router.register('groups', LinkGroupViewSet, basename='group') + +urlpatterns = [ + path('auth/register/', RegisterView.as_view(), name='auth_register'), + path('auth/login/', TokenObtainPairView.as_view(), name='token_obtain_pair'), + path('auth/refresh/', TokenRefreshView.as_view(), name='token_refresh'), + path('auth/user/', UserProfileView.as_view(), name='user-profile'), # ← новый + path('users//public/', + PublicUserGroupsView.as_view(), + name='public-user-groups' + ), +] + router.urls \ No newline at end of file diff --git a/.history/backend/api/urls_20250507072816.py b/.history/backend/api/urls_20250507072816.py new file mode 100644 index 0000000..9b3abb3 --- /dev/null +++ b/.history/backend/api/urls_20250507072816.py @@ -0,0 +1,25 @@ +from django.urls import path +from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView +from .views import ( + RegisterView, + UserProfileView, + LinkViewSet, + LinkGroupViewSet, + PublicUserGroupsView +) +from rest_framework.routers import DefaultRouter + +router = DefaultRouter() +router.register('links', LinkViewSet, basename='link') +router.register('groups', LinkGroupViewSet, basename='group') + +urlpatterns = [ + path('auth/register/', RegisterView.as_view(), name='auth_register'), + path('auth/login/', TokenObtainPairView.as_view(), name='token_obtain_pair'), + path('auth/refresh/', TokenRefreshView.as_view(), name='token_refresh'), + path('auth/user/', UserProfileView.as_view(), name='user-profile'), # ← новый + path('users//public/', + PublicUserGroupsView.as_view(), + name='public-user-groups' + ), +] + router.urls \ No newline at end of file diff --git a/.history/backend/api/urls_20250507080627.py b/.history/backend/api/urls_20250507080627.py new file mode 100644 index 0000000..9864697 --- /dev/null +++ b/.history/backend/api/urls_20250507080627.py @@ -0,0 +1,28 @@ +from django.urls import path +from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView +from .views import ( + RegisterView, + UserProfileView, + LinkViewSet, + LinkGroupViewSet, + PublicUserGroupsView +) +from rest_framework.routers import DefaultRouter + +router = DefaultRouter() +router.register('links', LinkViewSet, basename='link') +router.register('groups', LinkGroupViewSet, basename='group') + +urlpatterns = [ + path('auth/register/', RegisterView.as_view(), name='auth_register'), + path('auth/login/', TokenObtainPairView.as_view(), name='token_obtain_pair'), + path('auth/refresh/', TokenRefreshView.as_view(), name='token_refresh'), + path('auth/user/', UserProfileView.as_view(), name='user-profile'), # ← новый + path('users//public/', + PublicUserGroupsView.as_view(), + name='public-user-groups' + ), + path('schema/', SpectacularAPIView.as_view(), name='schema'), + path('swagger/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), + +] + router.urls \ No newline at end of file diff --git a/.history/backend/api/urls_20250507080637.py b/.history/backend/api/urls_20250507080637.py new file mode 100644 index 0000000..3952cfd --- /dev/null +++ b/.history/backend/api/urls_20250507080637.py @@ -0,0 +1,29 @@ +from django.urls import path +from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView +from .views import ( + RegisterView, + UserProfileView, + LinkViewSet, + LinkGroupViewSet, + PublicUserGroupsView +) +from rest_framework.routers import DefaultRouter +from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView + +router = DefaultRouter() +router.register('links', LinkViewSet, basename='link') +router.register('groups', LinkGroupViewSet, basename='group') + +urlpatterns = [ + path('auth/register/', RegisterView.as_view(), name='auth_register'), + path('auth/login/', TokenObtainPairView.as_view(), name='token_obtain_pair'), + path('auth/refresh/', TokenRefreshView.as_view(), name='token_refresh'), + path('auth/user/', UserProfileView.as_view(), name='user-profile'), # ← новый + path('users//public/', + PublicUserGroupsView.as_view(), + name='public-user-groups' + ), + path('schema/', SpectacularAPIView.as_view(), name='schema'), + path('swagger/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), + +] + router.urls \ No newline at end of file diff --git a/.history/backend/api/urls_20250507080822.py b/.history/backend/api/urls_20250507080822.py new file mode 100644 index 0000000..966b362 --- /dev/null +++ b/.history/backend/api/urls_20250507080822.py @@ -0,0 +1,35 @@ +from django.urls import path +from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView +from .views import ( + RegisterView, + UserProfileView, + LinkViewSet, + LinkGroupViewSet, + PublicUserGroupsView +) +from rest_framework.routers import DefaultRouter +from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView + +router = DefaultRouter() +router.register('links', LinkViewSet, basename='link') +router.register('groups', LinkGroupViewSet, basename='group') + +urlpatterns = [ + path('auth/register/', RegisterView.as_view(), name='auth_register'), + path('auth/login/', TokenObtainPairView.as_view(), name='token_obtain_pair'), + path('auth/refresh/', TokenRefreshView.as_view(), name='token_refresh'), + path('auth/user/', UserProfileView.as_view(), name='user-profile'), # ← новый + path('users//public/', + PublicUserGroupsView.as_view(), + name='public-user-groups' + ), + # схема OpenAPI + path('api/schema/', SpectacularAPIView.as_view(), name='schema'), + # Swagger UI, берёт шаблон из drf_spectacular_sidecar + path( + 'api/swagger/', + SpectacularSwaggerView.as_view(url_name='schema'), + name='swagger-ui' + ), + +] + router.urls \ No newline at end of file diff --git a/.history/backend/api/urls_20250507081428.py b/.history/backend/api/urls_20250507081428.py new file mode 100644 index 0000000..966b362 --- /dev/null +++ b/.history/backend/api/urls_20250507081428.py @@ -0,0 +1,35 @@ +from django.urls import path +from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView +from .views import ( + RegisterView, + UserProfileView, + LinkViewSet, + LinkGroupViewSet, + PublicUserGroupsView +) +from rest_framework.routers import DefaultRouter +from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView + +router = DefaultRouter() +router.register('links', LinkViewSet, basename='link') +router.register('groups', LinkGroupViewSet, basename='group') + +urlpatterns = [ + path('auth/register/', RegisterView.as_view(), name='auth_register'), + path('auth/login/', TokenObtainPairView.as_view(), name='token_obtain_pair'), + path('auth/refresh/', TokenRefreshView.as_view(), name='token_refresh'), + path('auth/user/', UserProfileView.as_view(), name='user-profile'), # ← новый + path('users//public/', + PublicUserGroupsView.as_view(), + name='public-user-groups' + ), + # схема OpenAPI + path('api/schema/', SpectacularAPIView.as_view(), name='schema'), + # Swagger UI, берёт шаблон из drf_spectacular_sidecar + path( + 'api/swagger/', + SpectacularSwaggerView.as_view(url_name='schema'), + name='swagger-ui' + ), + +] + router.urls \ No newline at end of file diff --git a/.history/backend/api/urls_20250507081622.py b/.history/backend/api/urls_20250507081622.py new file mode 100644 index 0000000..03f19eb --- /dev/null +++ b/.history/backend/api/urls_20250507081622.py @@ -0,0 +1,35 @@ +from django.urls import path +from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView +from .views import ( + RegisterView, + UserProfileView, + LinkViewSet, + LinkGroupViewSet, + PublicUserGroupsView +) +from rest_framework.routers import DefaultRouter +from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView + +router = DefaultRouter() +router.register('links', LinkViewSet, basename='link') +router.register('groups', LinkGroupViewSet, basename='group') + +urlpatterns = [ + path('auth/register/', RegisterView.as_view(), name='auth_register'), + path('auth/login/', TokenObtainPairView.as_view(), name='token_obtain_pair'), + path('auth/refresh/', TokenRefreshView.as_view(), name='token_refresh'), + path('auth/user/', UserProfileView.as_view(), name='user-profile'), # ← новый + path('users//public/', + PublicUserGroupsView.as_view(), + name='public-user-groups' + ), + # схема OpenAPI + path('schema/', SpectacularAPIView.as_view(), name='schema'), + # Swagger UI, берёт шаблон из drf_spectacular_sidecar + path( + 'swagger/', + SpectacularSwaggerView.as_view(url_name='schema'), + name='swagger-ui' + ), + +] + router.urls \ No newline at end of file diff --git a/.history/backend/api/views_20250507072833.py b/.history/backend/api/views_20250507072833.py new file mode 100644 index 0000000..dbbf49e --- /dev/null +++ b/.history/backend/api/views_20250507072833.py @@ -0,0 +1,113 @@ +# api/views.py +from rest_framework import generics, viewsets, permissions +from django.contrib.auth import get_user_model +from rest_framework_simplejwt.views import TokenObtainPairView +from .serializers import RegisterSerializer, LinkSerializer, LinkGroupSerializer +from .models import Link, LinkGroup + +User = get_user_model() + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = (permissions.AllowAny,) + serializer_class = RegisterSerializer + +class LoginView(TokenObtainPairView): + permission_classes = (permissions.AllowAny,) + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + # возвращаем только группы текущего пользователя + return self.queryset.filter(owner=self.request.user).order_by('order') + +class LinkViewSet(viewsets.ModelViewSet): + serializer_class = LinkSerializer + permission_classes = (permissions.IsAuthenticated,) + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = (permissions.AllowAny,) + + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +from .serializers import UserSerializer # нужно завести сериализатор для пользователя + +User = get_user_model() + +class UserProfileView(generics.RetrieveAPIView): + """ + Возвращает данные авторизованного пользователя. + GET /api/auth/user/ + """ + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_object(self): + return self.request.user + + +class PublicUserGroupsView(APIView): + """ + GET /api/users/{username}/public/ + Возвращает публичную страницу пользователя: + { + "username": "...", + "groups": [ + { + "id": 1, + "name": "...", + "icon": "/storage/images/link_groups/1.png", + "links": [ + { + "id": 5, + "title": "...", + "url": "...", + "icon": "/storage/images/links/5.png" + }, + … + ] + }, + … + ] + } + """ + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + User = get_user_model() + user = get_object_or_404(User, username=username) + # достаём все группы пользователя вместе с их ссылками + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + data = { + "username": user.username, + "groups": [] + } + for grp in groups_qs: + grp_data = { + "id": grp.id, + "name": grp.name, + "icon": grp.icon.url if grp.icon else None, + "links": [] + } + for ln in grp.links.all(): + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "icon": ln.icon.url if ln.icon else None + }) + data["groups"].append(grp_data) + return Response(data, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/.history/backend/api/views_20250507072920.py b/.history/backend/api/views_20250507072920.py new file mode 100644 index 0000000..afa757c --- /dev/null +++ b/.history/backend/api/views_20250507072920.py @@ -0,0 +1,118 @@ +# api/views.py +from rest_framework import generics, viewsets, permissions,status +from django.contrib.auth import get_user_model +from rest_framework_simplejwt.views import TokenObtainPairView +from .serializers import RegisterSerializer, LinkSerializer, LinkGroupSerializer +from .models import Link, LinkGroup +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 + + + +User = get_user_model() + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = (permissions.AllowAny,) + serializer_class = RegisterSerializer + +class LoginView(TokenObtainPairView): + permission_classes = (permissions.AllowAny,) + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + # возвращаем только группы текущего пользователя + return self.queryset.filter(owner=self.request.user).order_by('order') + +class LinkViewSet(viewsets.ModelViewSet): + serializer_class = LinkSerializer + permission_classes = (permissions.IsAuthenticated,) + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = (permissions.AllowAny,) + + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +from .serializers import UserSerializer # нужно завести сериализатор для пользователя + +User = get_user_model() + +class UserProfileView(generics.RetrieveAPIView): + """ + Возвращает данные авторизованного пользователя. + GET /api/auth/user/ + """ + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_object(self): + return self.request.user + + +class PublicUserGroupsView(APIView): + """ + GET /api/users/{username}/public/ + Возвращает публичную страницу пользователя: + { + "username": "...", + "groups": [ + { + "id": 1, + "name": "...", + "icon": "/storage/images/link_groups/1.png", + "links": [ + { + "id": 5, + "title": "...", + "url": "...", + "icon": "/storage/images/links/5.png" + }, + … + ] + }, + … + ] + } + """ + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + User = get_user_model() + user = get_object_or_404(User, username=username) + # достаём все группы пользователя вместе с их ссылками + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + data = { + "username": user.username, + "groups": [] + } + for grp in groups_qs: + grp_data = { + "id": grp.id, + "name": grp.name, + "icon": grp.icon.url if grp.icon else None, + "links": [] + } + for ln in grp.links.all(): + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "icon": ln.icon.url if ln.icon else None + }) + data["groups"].append(grp_data) + return Response(data, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/.history/backend/api/views_20250507073141.py b/.history/backend/api/views_20250507073141.py new file mode 100644 index 0000000..cdce00f --- /dev/null +++ b/.history/backend/api/views_20250507073141.py @@ -0,0 +1,109 @@ +# api/views.py +from rest_framework import generics, viewsets, permissions,status +from django.contrib.auth import get_user_model +from rest_framework_simplejwt.views import TokenObtainPairView +from .serializers import RegisterSerializer, LinkSerializer, LinkGroupSerializer +from .models import Link, LinkGroup +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 + + + +User = get_user_model() + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = (permissions.AllowAny,) + serializer_class = RegisterSerializer + +class LoginView(TokenObtainPairView): + permission_classes = (permissions.AllowAny,) + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + # возвращаем только группы текущего пользователя + return self.queryset.filter(owner=self.request.user).order_by('order') + +class LinkViewSet(viewsets.ModelViewSet): + serializer_class = LinkSerializer + permission_classes = (permissions.IsAuthenticated,) + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = (permissions.AllowAny,) + + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +from .serializers import UserSerializer # нужно завести сериализатор для пользователя + +User = get_user_model() + +class UserProfileView(generics.RetrieveAPIView): + """ + Возвращает данные авторизованного пользователя. + GET /api/auth/user/ + """ + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_object(self): + return self.request.user + + +class PublicUserGroupsView(APIView): + """ + GET /api/users/{username}/public/ + """ + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + User = get_user_model() + user = get_object_or_404(User, username=username) + + # Берём все группы пользователя вместе с их ссылками + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + + result = { + "username": user.username, + "groups": [] + } + + for grp in groups_qs: + # поле image у группы + grp_image_url = grp.image.url if getattr(grp, 'image', None) else None + + grp_data = { + "id": grp.id, + "name": grp.name, + "image": grp_image_url, + "links": [], + } + + for ln in grp.links.all(): + # поле image у отдельной ссылки + link_image_url = ln.image.url if getattr(ln, 'image', None) else None + + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "image": link_image_url, + }) + + result["groups"].append(grp_data) + + return Response(result, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/.history/backend/api/views_20250507073143.py b/.history/backend/api/views_20250507073143.py new file mode 100644 index 0000000..cdce00f --- /dev/null +++ b/.history/backend/api/views_20250507073143.py @@ -0,0 +1,109 @@ +# api/views.py +from rest_framework import generics, viewsets, permissions,status +from django.contrib.auth import get_user_model +from rest_framework_simplejwt.views import TokenObtainPairView +from .serializers import RegisterSerializer, LinkSerializer, LinkGroupSerializer +from .models import Link, LinkGroup +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 + + + +User = get_user_model() + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = (permissions.AllowAny,) + serializer_class = RegisterSerializer + +class LoginView(TokenObtainPairView): + permission_classes = (permissions.AllowAny,) + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + # возвращаем только группы текущего пользователя + return self.queryset.filter(owner=self.request.user).order_by('order') + +class LinkViewSet(viewsets.ModelViewSet): + serializer_class = LinkSerializer + permission_classes = (permissions.IsAuthenticated,) + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = (permissions.AllowAny,) + + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +from .serializers import UserSerializer # нужно завести сериализатор для пользователя + +User = get_user_model() + +class UserProfileView(generics.RetrieveAPIView): + """ + Возвращает данные авторизованного пользователя. + GET /api/auth/user/ + """ + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_object(self): + return self.request.user + + +class PublicUserGroupsView(APIView): + """ + GET /api/users/{username}/public/ + """ + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + User = get_user_model() + user = get_object_or_404(User, username=username) + + # Берём все группы пользователя вместе с их ссылками + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + + result = { + "username": user.username, + "groups": [] + } + + for grp in groups_qs: + # поле image у группы + grp_image_url = grp.image.url if getattr(grp, 'image', None) else None + + grp_data = { + "id": grp.id, + "name": grp.name, + "image": grp_image_url, + "links": [], + } + + for ln in grp.links.all(): + # поле image у отдельной ссылки + link_image_url = ln.image.url if getattr(ln, 'image', None) else None + + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "image": link_image_url, + }) + + result["groups"].append(grp_data) + + return Response(result, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/.history/backend/api/views_20250507141914.py b/.history/backend/api/views_20250507141914.py new file mode 100644 index 0000000..0764ae1 --- /dev/null +++ b/.history/backend/api/views_20250507141914.py @@ -0,0 +1,119 @@ +# api/views.py +from rest_framework import generics, viewsets, permissions,status +from django.contrib.auth import get_user_model +from rest_framework_simplejwt.views import TokenObtainPairView +from .serializers import RegisterSerializer, LinkSerializer, LinkGroupSerializer +from .models import Link, LinkGroup +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 + + + +User = get_user_model() + +@extend_schema( + parameters=[ + OpenApiParameter( + name='id', + type=int, + location=OpenApiParameter.PATH + ) + ] +) + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = (permissions.AllowAny,) + serializer_class = RegisterSerializer + +class LoginView(TokenObtainPairView): + permission_classes = (permissions.AllowAny,) + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + # возвращаем только группы текущего пользователя + return self.queryset.filter(owner=self.request.user).order_by('order') + +class LinkViewSet(viewsets.ModelViewSet): + serializer_class = LinkSerializer + permission_classes = (permissions.IsAuthenticated,) + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = (permissions.AllowAny,) + + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +from .serializers import UserSerializer # нужно завести сериализатор для пользователя + +User = get_user_model() + +class UserProfileView(generics.RetrieveAPIView): + """ + Возвращает данные авторизованного пользователя. + GET /api/auth/user/ + """ + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_object(self): + return self.request.user + + +class PublicUserGroupsView(APIView): + """ + GET /api/users/{username}/public/ + """ + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + User = get_user_model() + user = get_object_or_404(User, username=username) + + # Берём все группы пользователя вместе с их ссылками + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + + result = { + "username": user.username, + "groups": [] + } + + for grp in groups_qs: + # поле image у группы + grp_image_url = grp.image.url if getattr(grp, 'image', None) else None + + grp_data = { + "id": grp.id, + "name": grp.name, + "image": grp_image_url, + "links": [], + } + + for ln in grp.links.all(): + # поле image у отдельной ссылки + link_image_url = ln.image.url if getattr(ln, 'image', None) else None + + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "image": link_image_url, + }) + + result["groups"].append(grp_data) + + return Response(result, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/.history/backend/api/views_20250507141924.py b/.history/backend/api/views_20250507141924.py new file mode 100644 index 0000000..f2cc20b --- /dev/null +++ b/.history/backend/api/views_20250507141924.py @@ -0,0 +1,119 @@ +# api/views.py +from rest_framework import generics, viewsets, permissions,status +from django.contrib.auth import get_user_model +from rest_framework_simplejwt.views import TokenObtainPairView +from .serializers import RegisterSerializer, LinkSerializer, LinkGroupSerializer +from .models import Link, LinkGroup +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 +from drf_spectacular.utils import extend_schema, OpenApiParameter + + +User = get_user_model() + +@extend_schema( + parameters=[ + OpenApiParameter( + name='id', + type=int, + location=OpenApiParameter.PATH + ) + ] +) + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = (permissions.AllowAny,) + serializer_class = RegisterSerializer + +class LoginView(TokenObtainPairView): + permission_classes = (permissions.AllowAny,) + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + # возвращаем только группы текущего пользователя + return self.queryset.filter(owner=self.request.user).order_by('order') + +class LinkViewSet(viewsets.ModelViewSet): + serializer_class = LinkSerializer + permission_classes = (permissions.IsAuthenticated,) + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = (permissions.AllowAny,) + + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +from .serializers import UserSerializer # нужно завести сериализатор для пользователя + +User = get_user_model() + +class UserProfileView(generics.RetrieveAPIView): + """ + Возвращает данные авторизованного пользователя. + GET /api/auth/user/ + """ + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_object(self): + return self.request.user + + +class PublicUserGroupsView(APIView): + """ + GET /api/users/{username}/public/ + """ + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + User = get_user_model() + user = get_object_or_404(User, username=username) + + # Берём все группы пользователя вместе с их ссылками + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + + result = { + "username": user.username, + "groups": [] + } + + for grp in groups_qs: + # поле image у группы + grp_image_url = grp.image.url if getattr(grp, 'image', None) else None + + grp_data = { + "id": grp.id, + "name": grp.name, + "image": grp_image_url, + "links": [], + } + + for ln in grp.links.all(): + # поле image у отдельной ссылки + link_image_url = ln.image.url if getattr(ln, 'image', None) else None + + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "image": link_image_url, + }) + + result["groups"].append(grp_data) + + return Response(result, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/.history/backend/api/views_20250507142311.py b/.history/backend/api/views_20250507142311.py new file mode 100644 index 0000000..46d4b2c --- /dev/null +++ b/.history/backend/api/views_20250507142311.py @@ -0,0 +1,95 @@ +# api/views.py +from rest_framework import generics, viewsets, permissions,status +from django.contrib.auth import get_user_model +from rest_framework_simplejwt.views import TokenObtainPairView +from .serializers import RegisterSerializer, LinkSerializer, LinkGroupSerializer +from .models import Link, LinkGroup +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 +from drf_spectacular.utils import extend_schema, OpenApiParameter + + +User = get_user_model() + +@extend_schema( + parameters=[ + OpenApiParameter( + name='id', + type=int, + location=OpenApiParameter.PATH + ) + ] +) + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = (permissions.AllowAny,) + serializer_class = RegisterSerializer + +class LoginView(TokenObtainPairView): + permission_classes = (permissions.AllowAny,) + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + # возвращаем только группы текущего пользователя + return self.queryset.filter(owner=self.request.user).order_by('order') + +class LinkViewSet(viewsets.ModelViewSet): + serializer_class = LinkSerializer + permission_classes = (permissions.IsAuthenticated,) + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = (permissions.AllowAny,) + + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +from .serializers import UserSerializer # нужно завести сериализатор для пользователя + +User = get_user_model() + +class UserProfileView(generics.RetrieveAPIView): + """ + Возвращает данные авторизованного пользователя. + GET /api/auth/user/ + """ + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_object(self): + return self.request.user + + +@extend_schema( + responses=PublicUserGroupsSerializer +) +class PublicUserGroupsView(generics.GenericAPIView): + """ + Возвращает публичные группы и их ссылки для заданного username. + GET /api/users/{username}/public/ + """ + serializer_class = PublicUserGroupsSerializer + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + user = get_object_or_404(User, username=username) + groups = LinkGroup.objects.filter(owner=user, is_public=True).prefetch_related('links') + # Формируем ответ в виде словаря — GenericAPIView сам вызовет нужный сериализатор: + return Response({ + 'username': user.username, + 'groups': groups + }) \ No newline at end of file diff --git a/.history/backend/api/views_20250507142317.py b/.history/backend/api/views_20250507142317.py new file mode 100644 index 0000000..0b0aa65 --- /dev/null +++ b/.history/backend/api/views_20250507142317.py @@ -0,0 +1,98 @@ +# api/views.py +from rest_framework import generics, viewsets, permissions,status +from django.contrib.auth import get_user_model +from rest_framework_simplejwt.views import TokenObtainPairView +from .serializers import RegisterSerializer, LinkSerializer, LinkGroupSerializer +from .models import Link, LinkGroup +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 +from drf_spectacular.utils import extend_schema, OpenApiParameter + + +User = get_user_model() + +@extend_schema( + parameters=[ + OpenApiParameter( + name='id', + type=int, + location=OpenApiParameter.PATH + ) + ] +) + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = (permissions.AllowAny,) + serializer_class = RegisterSerializer + +class LoginView(TokenObtainPairView): + permission_classes = (permissions.AllowAny,) + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + # возвращаем только группы текущего пользователя + return self.queryset.filter(owner=self.request.user).order_by('order') + +class LinkViewSet(viewsets.ModelViewSet): + serializer_class = LinkSerializer + permission_classes = (permissions.IsAuthenticated,) + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = (permissions.AllowAny,) + + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +from .serializers import UserSerializer # нужно завести сериализатор для пользователя + +User = get_user_model() + +class UserProfileView(generics.RetrieveAPIView): + """ + Возвращает данные авторизованного пользователя. + GET /api/auth/user/ + """ + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_object(self): + return self.request.user + +from users.models import User +from links.models import LinkGroup +from .serializers import PublicUserGroupsSerializer + +@extend_schema( + responses=PublicUserGroupsSerializer +) +class PublicUserGroupsView(generics.GenericAPIView): + """ + Возвращает публичные группы и их ссылки для заданного username. + GET /api/users/{username}/public/ + """ + serializer_class = PublicUserGroupsSerializer + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + user = get_object_or_404(User, username=username) + groups = LinkGroup.objects.filter(owner=user, is_public=True).prefetch_related('links') + # Формируем ответ в виде словаря — GenericAPIView сам вызовет нужный сериализатор: + return Response({ + 'username': user.username, + 'groups': groups + }) \ No newline at end of file diff --git a/.history/backend/api/views_20250507142335.py b/.history/backend/api/views_20250507142335.py new file mode 100644 index 0000000..f2cc20b --- /dev/null +++ b/.history/backend/api/views_20250507142335.py @@ -0,0 +1,119 @@ +# api/views.py +from rest_framework import generics, viewsets, permissions,status +from django.contrib.auth import get_user_model +from rest_framework_simplejwt.views import TokenObtainPairView +from .serializers import RegisterSerializer, LinkSerializer, LinkGroupSerializer +from .models import Link, LinkGroup +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 +from drf_spectacular.utils import extend_schema, OpenApiParameter + + +User = get_user_model() + +@extend_schema( + parameters=[ + OpenApiParameter( + name='id', + type=int, + location=OpenApiParameter.PATH + ) + ] +) + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = (permissions.AllowAny,) + serializer_class = RegisterSerializer + +class LoginView(TokenObtainPairView): + permission_classes = (permissions.AllowAny,) + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + # возвращаем только группы текущего пользователя + return self.queryset.filter(owner=self.request.user).order_by('order') + +class LinkViewSet(viewsets.ModelViewSet): + serializer_class = LinkSerializer + permission_classes = (permissions.IsAuthenticated,) + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = (permissions.AllowAny,) + + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +from .serializers import UserSerializer # нужно завести сериализатор для пользователя + +User = get_user_model() + +class UserProfileView(generics.RetrieveAPIView): + """ + Возвращает данные авторизованного пользователя. + GET /api/auth/user/ + """ + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_object(self): + return self.request.user + + +class PublicUserGroupsView(APIView): + """ + GET /api/users/{username}/public/ + """ + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + User = get_user_model() + user = get_object_or_404(User, username=username) + + # Берём все группы пользователя вместе с их ссылками + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + + result = { + "username": user.username, + "groups": [] + } + + for grp in groups_qs: + # поле image у группы + grp_image_url = grp.image.url if getattr(grp, 'image', None) else None + + grp_data = { + "id": grp.id, + "name": grp.name, + "image": grp_image_url, + "links": [], + } + + for ln in grp.links.all(): + # поле image у отдельной ссылки + link_image_url = ln.image.url if getattr(ln, 'image', None) else None + + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "image": link_image_url, + }) + + result["groups"].append(grp_data) + + return Response(result, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/.history/backend/api/views_20250507145006.py b/.history/backend/api/views_20250507145006.py new file mode 100644 index 0000000..b31f7d7 --- /dev/null +++ b/.history/backend/api/views_20250507145006.py @@ -0,0 +1,151 @@ +# backend/api/views.py + +from rest_framework import generics, viewsets, permissions, status +from django.contrib.auth import get_user_model +from rest_framework_simplejwt.views import TokenObtainPairView +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 +from drf_spectacular.utils import extend_schema, OpenApiParameter + +from .models import Link, LinkGroup +from .serializers import ( + RegisterSerializer, + UserSerializer, + LinkSerializer, + LinkGroupSerializer, +) + +User = get_user_model() + + +@extend_schema( + parameters=[ + OpenApiParameter( + name='id', + type=int, + location=OpenApiParameter.PATH + ) + ] +) +class RegisterView(generics.CreateAPIView): + """ + POST /api/auth/register/ + Регистрирует нового пользователя. + """ + queryset = User.objects.all() + permission_classes = (permissions.AllowAny,) + serializer_class = RegisterSerializer + + +class LoginView(TokenObtainPairView): + """ + POST /api/auth/login/ + Возвращает JWT-токены. + """ + permission_classes = (permissions.AllowAny,) + + +class LinkGroupViewSet(viewsets.ModelViewSet): + """ + /api/groups/ + CRUD для групп ссылок текущего пользователя. + """ + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + # Возвращаем только свои группы, упорядоченные по полю order + return self.queryset.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + # При создании модели автоматически ставим owner = текущий пользователь + serializer.save(owner=self.request.user) + + +class LinkViewSet(viewsets.ModelViewSet): + """ + /api/links/ + CRUD для ссылок текущего пользователя. + """ + serializer_class = LinkSerializer + permission_classes = (permissions.IsAuthenticated,) + + def get_queryset(self): + # Возвращаем только свои ссылки, упорядоченные по полю order + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + # При создании модели автоматически ставим owner = текущий пользователь + serializer.save(owner=self.request.user) + + +class UserLinksListView(generics.ListAPIView): + """ + GET /api/users/{username}/links/ + Список публичных ссылок пользователя (без группировки). + """ + serializer_class = LinkSerializer + permission_classes = (permissions.AllowAny,) + + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +class UserProfileView(generics.RetrieveAPIView): + """ + GET /api/auth/user/ + Возвращает данные авторизованного пользователя. + """ + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_object(self): + return self.request.user + + +class PublicUserGroupsView(APIView): + """ + GET /api/users/{username}/public/ + Возвращает публичные группы и ссылки пользователя. + """ + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + user = get_object_or_404(User, username=username) + + # Берем все группы пользователя вместе с их ссылками + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + + result = { + "username": user.username, + "groups": [] + } + + for grp in groups_qs: + # URL иконки группы (поле icon в модели) + grp_icon_url = grp.icon.url if grp.icon else None + + grp_data = { + "id": grp.id, + "name": grp.name, + "icon": grp_icon_url, + "links": [], + } + + for ln in grp.links.all(): + # URL иконки ссылки (поле icon в модели Link — URLField) + link_icon_url = ln.icon if ln.icon else None + + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "icon": link_icon_url, + }) + + result["groups"].append(grp_data) + + return Response(result, status=status.HTTP_200_OK) diff --git a/.history/backend/api/views_20250507145615.py b/.history/backend/api/views_20250507145615.py new file mode 100644 index 0000000..3ec54f4 --- /dev/null +++ b/.history/backend/api/views_20250507145615.py @@ -0,0 +1,248 @@ +# # backend/api/views.py + +# from rest_framework import generics, viewsets, permissions, status +# from django.contrib.auth import get_user_model +# from rest_framework_simplejwt.views import TokenObtainPairView +# from rest_framework.views import APIView +# from rest_framework.response import Response +# from django.shortcuts import get_object_or_404 +# from drf_spectacular.utils import extend_schema, OpenApiParameter + +# from .models import Link, LinkGroup +# from .serializers import ( +# RegisterSerializer, +# UserSerializer, +# LinkSerializer, +# LinkGroupSerializer, +# ) + +# User = get_user_model() + + +# @extend_schema( +# parameters=[ +# OpenApiParameter( +# name='id', +# type=int, +# location=OpenApiParameter.PATH +# ) +# ] +# ) +# class RegisterView(generics.CreateAPIView): +# """ +# POST /api/auth/register/ +# Регистрирует нового пользователя. +# """ +# queryset = User.objects.all() +# permission_classes = (permissions.AllowAny,) +# serializer_class = RegisterSerializer + + +# class LoginView(TokenObtainPairView): +# """ +# POST /api/auth/login/ +# Возвращает JWT-токены. +# """ +# permission_classes = (permissions.AllowAny,) + + +# class LinkGroupViewSet(viewsets.ModelViewSet): +# """ +# /api/groups/ +# CRUD для групп ссылок текущего пользователя. +# """ +# queryset = LinkGroup.objects.all() +# serializer_class = LinkGroupSerializer +# permission_classes = [permissions.IsAuthenticated] + +# def get_queryset(self): +# # Возвращаем только свои группы, упорядоченные по полю order +# return self.queryset.filter(owner=self.request.user).order_by('order') + +# def perform_create(self, serializer): +# # При создании модели автоматически ставим owner = текущий пользователь +# serializer.save(owner=self.request.user) + + +# class LinkViewSet(viewsets.ModelViewSet): +# """ +# /api/links/ +# CRUD для ссылок текущего пользователя. +# """ +# serializer_class = LinkSerializer +# permission_classes = (permissions.IsAuthenticated,) + +# def get_queryset(self): +# # Возвращаем только свои ссылки, упорядоченные по полю order +# return Link.objects.filter(owner=self.request.user).order_by('order') + +# def perform_create(self, serializer): +# # При создании модели автоматически ставим owner = текущий пользователь +# serializer.save(owner=self.request.user) + + +# class UserLinksListView(generics.ListAPIView): +# """ +# GET /api/users/{username}/links/ +# Список публичных ссылок пользователя (без группировки). +# """ +# serializer_class = LinkSerializer +# permission_classes = (permissions.AllowAny,) + +# def get_queryset(self): +# username = self.kwargs['username'] +# return Link.objects.filter(owner__username=username).order_by('order') + + +# class UserProfileView(generics.RetrieveAPIView): +# """ +# GET /api/auth/user/ +# Возвращает данные авторизованного пользователя. +# """ +# serializer_class = UserSerializer +# permission_classes = [permissions.IsAuthenticated] + +# def get_object(self): +# return self.request.user + + +# class PublicUserGroupsView(APIView): +# """ +# GET /api/users/{username}/public/ +# Возвращает публичные группы и ссылки пользователя. +# """ +# permission_classes = [permissions.AllowAny] + +# def get(self, request, username): +# user = get_object_or_404(User, username=username) + +# # Берем все группы пользователя вместе с их ссылками +# groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + +# result = { +# "username": user.username, +# "groups": [] +# } + +# for grp in groups_qs: +# # URL иконки группы (поле icon в модели) +# grp_icon_url = grp.icon.url if grp.icon else None + +# grp_data = { +# "id": grp.id, +# "name": grp.name, +# "icon": grp_icon_url, +# "links": [], +# } + +# for ln in grp.links.all(): +# # URL иконки ссылки (поле icon в модели Link — URLField) +# link_icon_url = ln.icon if ln.icon else None + +# grp_data["links"].append({ +# "id": ln.id, +# "title": ln.title, +# "url": ln.url, +# "icon": link_icon_url, +# }) + +# result["groups"].append(grp_data) + +# return Response(result, status=status.HTTP_200_OK) + +# backend/api/views.py + +from rest_framework import generics, viewsets, permissions, status +from rest_framework.parsers import MultiPartParser, FormParser, JSONParser +from rest_framework_simplejwt.views import TokenObtainPairView +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 +from drf_spectacular.utils import extend_schema, OpenApiParameter +from django.contrib.auth import get_user_model + +from .models import Link, LinkGroup +from .serializers import ( + RegisterSerializer, + UserSerializer, + LinkSerializer, + LinkGroupSerializer, +) + +User = get_user_model() + + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = [permissions.AllowAny] + serializer_class = RegisterSerializer + + +class LoginView(TokenObtainPairView): + permission_classes = [permissions.AllowAny] + + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + parser_classes = [MultiPartParser, FormParser, JSONParser] + + def get_queryset(self): + return self.queryset.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class LinkViewSet(viewsets.ModelViewSet): + queryset = Link.objects.all() + serializer_class = LinkSerializer + permission_classes = [permissions.IsAuthenticated] + parser_classes = [MultiPartParser, FormParser, JSONParser] + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class UserProfileView(generics.RetrieveAPIView): + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + def get_object(self): + return self.request.user + + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = [permissions.AllowAny] + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +class PublicUserGroupsView(APIView): + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + user = get_object_or_404(User, username=username) + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + result = {"username": user.username, "groups": []} + + for grp in groups_qs: + grp_icon = grp.icon.url if grp.icon else None + grp_data = {"id": grp.id, "name": grp.name, "icon": grp_icon, "links": []} + + for ln in grp.links.all(): + link_icon = ln.icon.url if hasattr(ln.icon, 'url') else ln.icon + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "icon": link_icon, + }) + result["groups"].append(grp_data) + + return Response(result, status=status.HTTP_200_OK) diff --git a/.history/backend/api/views_20250507150101.py b/.history/backend/api/views_20250507150101.py new file mode 100644 index 0000000..91c4e90 --- /dev/null +++ b/.history/backend/api/views_20250507150101.py @@ -0,0 +1,272 @@ +# # backend/api/views.py + +# from rest_framework import generics, viewsets, permissions, status +# from django.contrib.auth import get_user_model +# from rest_framework_simplejwt.views import TokenObtainPairView +# from rest_framework.views import APIView +# from rest_framework.response import Response +# from django.shortcuts import get_object_or_404 +# from drf_spectacular.utils import extend_schema, OpenApiParameter + +# from .models import Link, LinkGroup +# from .serializers import ( +# RegisterSerializer, +# UserSerializer, +# LinkSerializer, +# LinkGroupSerializer, +# ) + +# User = get_user_model() + + +# @extend_schema( +# parameters=[ +# OpenApiParameter( +# name='id', +# type=int, +# location=OpenApiParameter.PATH +# ) +# ] +# ) +# class RegisterView(generics.CreateAPIView): +# """ +# POST /api/auth/register/ +# Регистрирует нового пользователя. +# """ +# queryset = User.objects.all() +# permission_classes = (permissions.AllowAny,) +# serializer_class = RegisterSerializer + + +# class LoginView(TokenObtainPairView): +# """ +# POST /api/auth/login/ +# Возвращает JWT-токены. +# """ +# permission_classes = (permissions.AllowAny,) + + +# class LinkGroupViewSet(viewsets.ModelViewSet): +# """ +# /api/groups/ +# CRUD для групп ссылок текущего пользователя. +# """ +# queryset = LinkGroup.objects.all() +# serializer_class = LinkGroupSerializer +# permission_classes = [permissions.IsAuthenticated] + +# def get_queryset(self): +# # Возвращаем только свои группы, упорядоченные по полю order +# return self.queryset.filter(owner=self.request.user).order_by('order') + +# def perform_create(self, serializer): +# # При создании модели автоматически ставим owner = текущий пользователь +# serializer.save(owner=self.request.user) + + +# class LinkViewSet(viewsets.ModelViewSet): +# """ +# /api/links/ +# CRUD для ссылок текущего пользователя. +# """ +# serializer_class = LinkSerializer +# permission_classes = (permissions.IsAuthenticated,) + +# def get_queryset(self): +# # Возвращаем только свои ссылки, упорядоченные по полю order +# return Link.objects.filter(owner=self.request.user).order_by('order') + +# def perform_create(self, serializer): +# # При создании модели автоматически ставим owner = текущий пользователь +# serializer.save(owner=self.request.user) + + +# class UserLinksListView(generics.ListAPIView): +# """ +# GET /api/users/{username}/links/ +# Список публичных ссылок пользователя (без группировки). +# """ +# serializer_class = LinkSerializer +# permission_classes = (permissions.AllowAny,) + +# def get_queryset(self): +# username = self.kwargs['username'] +# return Link.objects.filter(owner__username=username).order_by('order') + + +# class UserProfileView(generics.RetrieveAPIView): +# """ +# GET /api/auth/user/ +# Возвращает данные авторизованного пользователя. +# """ +# serializer_class = UserSerializer +# permission_classes = [permissions.IsAuthenticated] + +# def get_object(self): +# return self.request.user + + +# class PublicUserGroupsView(APIView): +# """ +# GET /api/users/{username}/public/ +# Возвращает публичные группы и ссылки пользователя. +# """ +# permission_classes = [permissions.AllowAny] + +# def get(self, request, username): +# user = get_object_or_404(User, username=username) + +# # Берем все группы пользователя вместе с их ссылками +# groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + +# result = { +# "username": user.username, +# "groups": [] +# } + +# for grp in groups_qs: +# # URL иконки группы (поле icon в модели) +# grp_icon_url = grp.icon.url if grp.icon else None + +# grp_data = { +# "id": grp.id, +# "name": grp.name, +# "icon": grp_icon_url, +# "links": [], +# } + +# for ln in grp.links.all(): +# # URL иконки ссылки (поле icon в модели Link — URLField) +# link_icon_url = ln.icon if ln.icon else None + +# grp_data["links"].append({ +# "id": ln.id, +# "title": ln.title, +# "url": ln.url, +# "icon": link_icon_url, +# }) + +# result["groups"].append(grp_data) + +# return Response(result, status=status.HTTP_200_OK) + +# backend/api/views.py + +from rest_framework import generics, viewsets, permissions, status +from rest_framework.parsers import MultiPartParser, FormParser, JSONParser +from rest_framework_simplejwt.views import TokenObtainPairView +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 +from drf_spectacular.utils import extend_schema, OpenApiParameter +from django.contrib.auth import get_user_model + +from .models import Link, LinkGroup +from .serializers import ( + RegisterSerializer, + UserSerializer, + LinkSerializer, + LinkGroupSerializer, +) + +User = get_user_model() + + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = [permissions.AllowAny] + serializer_class = RegisterSerializer + + +class LoginView(TokenObtainPairView): + permission_classes = [permissions.AllowAny] + + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + parser_classes = [MultiPartParser, FormParser, JSONParser] + + def get_queryset(self): + return self.queryset.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class LinkViewSet(viewsets.ModelViewSet): + queryset = Link.objects.all() + serializer_class = LinkSerializer + permission_classes = [permissions.IsAuthenticated] + parser_classes = [MultiPartParser, FormParser, JSONParser] + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class UserProfileView(generics.RetrieveAPIView): + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + def get_object(self): + return self.request.user + + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = [permissions.AllowAny] + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +class PublicUserGroupsView(APIView): + """ + GET /api/users/{username}/public/ + """ + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + # 1. Ищем пользователя + user = get_object_or_404(User, username=username) + + # 2. Берём его группы со ссылками + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + + result = { + "username": user.username, + "groups": [] + } + + for grp in groups_qs: + # icon у группы (абсолютный URL) + grp_icon_url = None + if grp.icon: + grp_icon_url = request.build_absolute_uri(grp.icon.url) + + grp_data = { + "id": grp.id, + "name": grp.name, + "icon": grp_icon_url, + "links": [], + } + + for ln in grp.links.all(): + # icon у ссылки + ln_icon_url = None + if ln.icon: + ln_icon_url = request.build_absolute_uri(ln.icon.url) + + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "icon": ln_icon_url, + }) + + result["groups"].append(grp_data) + + return Response(result, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/.history/backend/api/views_20250507150709.py b/.history/backend/api/views_20250507150709.py new file mode 100644 index 0000000..f4f34ee --- /dev/null +++ b/.history/backend/api/views_20250507150709.py @@ -0,0 +1,267 @@ +# # backend/api/views.py + +# from rest_framework import generics, viewsets, permissions, status +# from django.contrib.auth import get_user_model +# from rest_framework_simplejwt.views import TokenObtainPairView +# from rest_framework.views import APIView +# from rest_framework.response import Response +# from django.shortcuts import get_object_or_404 +# from drf_spectacular.utils import extend_schema, OpenApiParameter + +# from .models import Link, LinkGroup +# from .serializers import ( +# RegisterSerializer, +# UserSerializer, +# LinkSerializer, +# LinkGroupSerializer, +# ) + +# User = get_user_model() + + +# @extend_schema( +# parameters=[ +# OpenApiParameter( +# name='id', +# type=int, +# location=OpenApiParameter.PATH +# ) +# ] +# ) +# class RegisterView(generics.CreateAPIView): +# """ +# POST /api/auth/register/ +# Регистрирует нового пользователя. +# """ +# queryset = User.objects.all() +# permission_classes = (permissions.AllowAny,) +# serializer_class = RegisterSerializer + + +# class LoginView(TokenObtainPairView): +# """ +# POST /api/auth/login/ +# Возвращает JWT-токены. +# """ +# permission_classes = (permissions.AllowAny,) + + +# class LinkGroupViewSet(viewsets.ModelViewSet): +# """ +# /api/groups/ +# CRUD для групп ссылок текущего пользователя. +# """ +# queryset = LinkGroup.objects.all() +# serializer_class = LinkGroupSerializer +# permission_classes = [permissions.IsAuthenticated] + +# def get_queryset(self): +# # Возвращаем только свои группы, упорядоченные по полю order +# return self.queryset.filter(owner=self.request.user).order_by('order') + +# def perform_create(self, serializer): +# # При создании модели автоматически ставим owner = текущий пользователь +# serializer.save(owner=self.request.user) + + +# class LinkViewSet(viewsets.ModelViewSet): +# """ +# /api/links/ +# CRUD для ссылок текущего пользователя. +# """ +# serializer_class = LinkSerializer +# permission_classes = (permissions.IsAuthenticated,) + +# def get_queryset(self): +# # Возвращаем только свои ссылки, упорядоченные по полю order +# return Link.objects.filter(owner=self.request.user).order_by('order') + +# def perform_create(self, serializer): +# # При создании модели автоматически ставим owner = текущий пользователь +# serializer.save(owner=self.request.user) + + +# class UserLinksListView(generics.ListAPIView): +# """ +# GET /api/users/{username}/links/ +# Список публичных ссылок пользователя (без группировки). +# """ +# serializer_class = LinkSerializer +# permission_classes = (permissions.AllowAny,) + +# def get_queryset(self): +# username = self.kwargs['username'] +# return Link.objects.filter(owner__username=username).order_by('order') + + +# class UserProfileView(generics.RetrieveAPIView): +# """ +# GET /api/auth/user/ +# Возвращает данные авторизованного пользователя. +# """ +# serializer_class = UserSerializer +# permission_classes = [permissions.IsAuthenticated] + +# def get_object(self): +# return self.request.user + + +# class PublicUserGroupsView(APIView): +# """ +# GET /api/users/{username}/public/ +# Возвращает публичные группы и ссылки пользователя. +# """ +# permission_classes = [permissions.AllowAny] + +# def get(self, request, username): +# user = get_object_or_404(User, username=username) + +# # Берем все группы пользователя вместе с их ссылками +# groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + +# result = { +# "username": user.username, +# "groups": [] +# } + +# for grp in groups_qs: +# # URL иконки группы (поле icon в модели) +# grp_icon_url = grp.icon.url if grp.icon else None + +# grp_data = { +# "id": grp.id, +# "name": grp.name, +# "icon": grp_icon_url, +# "links": [], +# } + +# for ln in grp.links.all(): +# # URL иконки ссылки (поле icon в модели Link — URLField) +# link_icon_url = ln.icon if ln.icon else None + +# grp_data["links"].append({ +# "id": ln.id, +# "title": ln.title, +# "url": ln.url, +# "icon": link_icon_url, +# }) + +# result["groups"].append(grp_data) + +# return Response(result, status=status.HTTP_200_OK) + +# backend/api/views.py + +from rest_framework import generics, viewsets, permissions, status +from rest_framework.parsers import MultiPartParser, FormParser, JSONParser +from rest_framework_simplejwt.views import TokenObtainPairView +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 +from drf_spectacular.utils import extend_schema, OpenApiParameter +from django.contrib.auth import get_user_model + +from .models import Link, LinkGroup +from .serializers import ( + RegisterSerializer, + UserSerializer, + LinkSerializer, + LinkGroupSerializer, +) + +User = get_user_model() + + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = [permissions.AllowAny] + serializer_class = RegisterSerializer + + +class LoginView(TokenObtainPairView): + permission_classes = [permissions.AllowAny] + + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + parser_classes = [MultiPartParser, FormParser, JSONParser] + + def get_queryset(self): + return self.queryset.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class LinkViewSet(viewsets.ModelViewSet): + queryset = Link.objects.all() + serializer_class = LinkSerializer + permission_classes = [permissions.IsAuthenticated] + parser_classes = [MultiPartParser, FormParser, JSONParser] + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class UserProfileView(generics.RetrieveAPIView): + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + def get_object(self): + return self.request.user + + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = [permissions.AllowAny] + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +class PublicUserGroupsView(APIView): + """ + GET /api/users/{username}/public/ + """ + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + user = get_object_or_404(User, username=username) + + # Берём все группы пользователя вместе с их ссылками + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + + result = { + "username": user.username, + "groups": [] + } + + for grp in groups_qs: + # поле icon у группы — это ImageField + grp_icon_url = grp.icon.url if grp.icon else None + + grp_data = { + "id": grp.id, + "name": grp.name, + "image": grp_icon_url, # отдаём под ключом "image", как ждёт фронт + "links": [], + } + + for ln in grp.links.all(): + # поле icon у ссылки — это URLField, сразу строка + link_icon_url = ln.icon if ln.icon else None + + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "image": link_icon_url, # тоже "image" + }) + + result["groups"].append(grp_data) + + return Response(result, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/.history/backend/api/views_20250507150738.py b/.history/backend/api/views_20250507150738.py new file mode 100644 index 0000000..91c4e90 --- /dev/null +++ b/.history/backend/api/views_20250507150738.py @@ -0,0 +1,272 @@ +# # backend/api/views.py + +# from rest_framework import generics, viewsets, permissions, status +# from django.contrib.auth import get_user_model +# from rest_framework_simplejwt.views import TokenObtainPairView +# from rest_framework.views import APIView +# from rest_framework.response import Response +# from django.shortcuts import get_object_or_404 +# from drf_spectacular.utils import extend_schema, OpenApiParameter + +# from .models import Link, LinkGroup +# from .serializers import ( +# RegisterSerializer, +# UserSerializer, +# LinkSerializer, +# LinkGroupSerializer, +# ) + +# User = get_user_model() + + +# @extend_schema( +# parameters=[ +# OpenApiParameter( +# name='id', +# type=int, +# location=OpenApiParameter.PATH +# ) +# ] +# ) +# class RegisterView(generics.CreateAPIView): +# """ +# POST /api/auth/register/ +# Регистрирует нового пользователя. +# """ +# queryset = User.objects.all() +# permission_classes = (permissions.AllowAny,) +# serializer_class = RegisterSerializer + + +# class LoginView(TokenObtainPairView): +# """ +# POST /api/auth/login/ +# Возвращает JWT-токены. +# """ +# permission_classes = (permissions.AllowAny,) + + +# class LinkGroupViewSet(viewsets.ModelViewSet): +# """ +# /api/groups/ +# CRUD для групп ссылок текущего пользователя. +# """ +# queryset = LinkGroup.objects.all() +# serializer_class = LinkGroupSerializer +# permission_classes = [permissions.IsAuthenticated] + +# def get_queryset(self): +# # Возвращаем только свои группы, упорядоченные по полю order +# return self.queryset.filter(owner=self.request.user).order_by('order') + +# def perform_create(self, serializer): +# # При создании модели автоматически ставим owner = текущий пользователь +# serializer.save(owner=self.request.user) + + +# class LinkViewSet(viewsets.ModelViewSet): +# """ +# /api/links/ +# CRUD для ссылок текущего пользователя. +# """ +# serializer_class = LinkSerializer +# permission_classes = (permissions.IsAuthenticated,) + +# def get_queryset(self): +# # Возвращаем только свои ссылки, упорядоченные по полю order +# return Link.objects.filter(owner=self.request.user).order_by('order') + +# def perform_create(self, serializer): +# # При создании модели автоматически ставим owner = текущий пользователь +# serializer.save(owner=self.request.user) + + +# class UserLinksListView(generics.ListAPIView): +# """ +# GET /api/users/{username}/links/ +# Список публичных ссылок пользователя (без группировки). +# """ +# serializer_class = LinkSerializer +# permission_classes = (permissions.AllowAny,) + +# def get_queryset(self): +# username = self.kwargs['username'] +# return Link.objects.filter(owner__username=username).order_by('order') + + +# class UserProfileView(generics.RetrieveAPIView): +# """ +# GET /api/auth/user/ +# Возвращает данные авторизованного пользователя. +# """ +# serializer_class = UserSerializer +# permission_classes = [permissions.IsAuthenticated] + +# def get_object(self): +# return self.request.user + + +# class PublicUserGroupsView(APIView): +# """ +# GET /api/users/{username}/public/ +# Возвращает публичные группы и ссылки пользователя. +# """ +# permission_classes = [permissions.AllowAny] + +# def get(self, request, username): +# user = get_object_or_404(User, username=username) + +# # Берем все группы пользователя вместе с их ссылками +# groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + +# result = { +# "username": user.username, +# "groups": [] +# } + +# for grp in groups_qs: +# # URL иконки группы (поле icon в модели) +# grp_icon_url = grp.icon.url if grp.icon else None + +# grp_data = { +# "id": grp.id, +# "name": grp.name, +# "icon": grp_icon_url, +# "links": [], +# } + +# for ln in grp.links.all(): +# # URL иконки ссылки (поле icon в модели Link — URLField) +# link_icon_url = ln.icon if ln.icon else None + +# grp_data["links"].append({ +# "id": ln.id, +# "title": ln.title, +# "url": ln.url, +# "icon": link_icon_url, +# }) + +# result["groups"].append(grp_data) + +# return Response(result, status=status.HTTP_200_OK) + +# backend/api/views.py + +from rest_framework import generics, viewsets, permissions, status +from rest_framework.parsers import MultiPartParser, FormParser, JSONParser +from rest_framework_simplejwt.views import TokenObtainPairView +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 +from drf_spectacular.utils import extend_schema, OpenApiParameter +from django.contrib.auth import get_user_model + +from .models import Link, LinkGroup +from .serializers import ( + RegisterSerializer, + UserSerializer, + LinkSerializer, + LinkGroupSerializer, +) + +User = get_user_model() + + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = [permissions.AllowAny] + serializer_class = RegisterSerializer + + +class LoginView(TokenObtainPairView): + permission_classes = [permissions.AllowAny] + + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + parser_classes = [MultiPartParser, FormParser, JSONParser] + + def get_queryset(self): + return self.queryset.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class LinkViewSet(viewsets.ModelViewSet): + queryset = Link.objects.all() + serializer_class = LinkSerializer + permission_classes = [permissions.IsAuthenticated] + parser_classes = [MultiPartParser, FormParser, JSONParser] + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class UserProfileView(generics.RetrieveAPIView): + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + def get_object(self): + return self.request.user + + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = [permissions.AllowAny] + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +class PublicUserGroupsView(APIView): + """ + GET /api/users/{username}/public/ + """ + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + # 1. Ищем пользователя + user = get_object_or_404(User, username=username) + + # 2. Берём его группы со ссылками + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + + result = { + "username": user.username, + "groups": [] + } + + for grp in groups_qs: + # icon у группы (абсолютный URL) + grp_icon_url = None + if grp.icon: + grp_icon_url = request.build_absolute_uri(grp.icon.url) + + grp_data = { + "id": grp.id, + "name": grp.name, + "icon": grp_icon_url, + "links": [], + } + + for ln in grp.links.all(): + # icon у ссылки + ln_icon_url = None + if ln.icon: + ln_icon_url = request.build_absolute_uri(ln.icon.url) + + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "icon": ln_icon_url, + }) + + result["groups"].append(grp_data) + + return Response(result, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/.history/backend/api/views_20250507150907.py b/.history/backend/api/views_20250507150907.py new file mode 100644 index 0000000..f655d7d --- /dev/null +++ b/.history/backend/api/views_20250507150907.py @@ -0,0 +1,119 @@ +# coding: utf-8 +from rest_framework import generics, viewsets, permissions, status +from rest_framework.parsers import MultiPartParser, FormParser, JSONParser +from rest_framework_simplejwt.views import TokenObtainPairView +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 +from drf_spectacular.utils import extend_schema, OpenApiParameter +from django.contrib.auth import get_user_model + +from .models import Link, LinkGroup +from .serializers import ( + RegisterSerializer, + UserSerializer, + LinkSerializer, + LinkGroupSerializer, +) + +User = get_user_model() + + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = [permissions.AllowAny] + serializer_class = RegisterSerializer + + +class LoginView(TokenObtainPairView): + permission_classes = [permissions.AllowAny] + + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + parser_classes = [MultiPartParser, FormParser, JSONParser] + + def get_queryset(self): + return self.queryset.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class LinkViewSet(viewsets.ModelViewSet): + queryset = Link.objects.all() + serializer_class = LinkSerializer + permission_classes = [permissions.IsAuthenticated] + parser_classes = [MultiPartParser, FormParser, JSONParser] + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class UserProfileView(generics.RetrieveAPIView): + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + def get_object(self): + return self.request.user + + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = [permissions.AllowAny] + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +class PublicUserGroupsView(APIView): + """ + GET /api/users/{username}/public/ + """ + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + # 1. Ищем пользователя + user = get_object_or_404(User, username=username) + + # 2. Берём его группы со ссылками + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + + result = { + "username": user.username, + "groups": [] + } + + for grp in groups_qs: + # icon у группы (абсолютный URL) + grp_icon_url = None + if grp.icon: + grp_icon_url = request.build_absolute_uri(grp.icon.url) + + grp_data = { + "id": grp.id, + "name": grp.name, + "icon": grp_icon_url, + "links": [], + } + + for ln in grp.links.all(): + # icon у ссылки + ln_icon_url = None + if ln.icon: + ln_icon_url = request.build_absolute_uri(ln.icon.url) + + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "icon": ln_icon_url, + }) + + result["groups"].append(grp_data) + + return Response(result, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/.history/backend/api/views_20250507151205.py b/.history/backend/api/views_20250507151205.py new file mode 100644 index 0000000..6e50d67 --- /dev/null +++ b/.history/backend/api/views_20250507151205.py @@ -0,0 +1,150 @@ +# api/views.py + +from django.contrib.auth import get_user_model +from django.shortcuts import get_object_or_404 + +from rest_framework import generics, viewsets, permissions, status +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework_simplejwt.views import TokenObtainPairView + +from drf_spectacular.utils import extend_schema, OpenApiParameter + +from .models import Link, LinkGroup +from .serializers import ( + RegisterSerializer, + UserSerializer, + LinkSerializer, + LinkGroupSerializer, +) + +User = get_user_model() + + +@extend_schema( + parameters=[ + OpenApiParameter( + name='id', + type=int, + location=OpenApiParameter.PATH, + description='ID создаваемого или изменяемого объекта', + ) + ] +) +class RegisterView(generics.CreateAPIView): + """ + POST /api/auth/register/ + Регистрация нового пользователя. + """ + queryset = User.objects.all() + permission_classes = (permissions.AllowAny,) + serializer_class = RegisterSerializer + + +class LoginView(TokenObtainPairView): + """ + POST /api/auth/login/ + Получение JWT-токенов для входа. + """ + permission_classes = (permissions.AllowAny,) + + +class LinkGroupViewSet(viewsets.ModelViewSet): + """ + CRUD для групп ссылок текущего пользователя. + /api/groups/ + """ + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + # Только свои группы + return self.queryset.filter(owner=self.request.user).order_by('order') + + +class LinkViewSet(viewsets.ModelViewSet): + """ + CRUD для ссылок текущего пользователя. + /api/links/ + """ + serializer_class = LinkSerializer + permission_classes = [permissions.IsAuthenticated] + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + # При создании автоматически ставим владельца + serializer.save(owner=self.request.user) + + +class UserLinksListView(generics.ListAPIView): + """ + GET /api/users/{username}/links/ + Список всех ссылок публичного пользователя. + """ + serializer_class = LinkSerializer + permission_classes = (permissions.AllowAny,) + + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +class UserProfileView(generics.RetrieveAPIView): + """ + GET /api/auth/user/ + Данные текущего авторизованного пользователя. + """ + serializer_class = UserSerializer + permission_classes = (permissions.IsAuthenticated,) + + def get_object(self): + return self.request.user + + +class PublicUserGroupsView(APIView): + """ + GET /api/users/{username}/public/ + Публичные группы ссылок пользователя вместе с их ссылками. + """ + permission_classes = (permissions.AllowAny,) + + def get(self, request, username): + # Находим пользователя по имени + user = get_object_or_404(User, username=username) + + # Берём его группы с предзагрузкой ссылок + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + + result = { + "username": user.username, + "groups": [] + } + + for grp in groups_qs: + # иконка группы (ImageField) + grp_icon_url = grp.icon.url if grp.icon else None + + grp_data = { + "id": grp.id, + "name": grp.name, + "image": grp_icon_url, + "links": [] + } + + for ln in grp.links.all(): + # иконка ссылки (URLField) + link_icon_url = ln.icon if ln.icon else None + + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "image": link_icon_url, + }) + + result["groups"].append(grp_data) + + return Response(result, status=status.HTTP_200_OK) diff --git a/.history/backend/api/views_20250507151600.py b/.history/backend/api/views_20250507151600.py new file mode 100644 index 0000000..f655d7d --- /dev/null +++ b/.history/backend/api/views_20250507151600.py @@ -0,0 +1,119 @@ +# coding: utf-8 +from rest_framework import generics, viewsets, permissions, status +from rest_framework.parsers import MultiPartParser, FormParser, JSONParser +from rest_framework_simplejwt.views import TokenObtainPairView +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 +from drf_spectacular.utils import extend_schema, OpenApiParameter +from django.contrib.auth import get_user_model + +from .models import Link, LinkGroup +from .serializers import ( + RegisterSerializer, + UserSerializer, + LinkSerializer, + LinkGroupSerializer, +) + +User = get_user_model() + + +class RegisterView(generics.CreateAPIView): + queryset = User.objects.all() + permission_classes = [permissions.AllowAny] + serializer_class = RegisterSerializer + + +class LoginView(TokenObtainPairView): + permission_classes = [permissions.AllowAny] + + +class LinkGroupViewSet(viewsets.ModelViewSet): + queryset = LinkGroup.objects.all() + serializer_class = LinkGroupSerializer + permission_classes = [permissions.IsAuthenticated] + parser_classes = [MultiPartParser, FormParser, JSONParser] + + def get_queryset(self): + return self.queryset.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class LinkViewSet(viewsets.ModelViewSet): + queryset = Link.objects.all() + serializer_class = LinkSerializer + permission_classes = [permissions.IsAuthenticated] + parser_classes = [MultiPartParser, FormParser, JSONParser] + + def get_queryset(self): + return Link.objects.filter(owner=self.request.user).order_by('order') + + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + +class UserProfileView(generics.RetrieveAPIView): + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + def get_object(self): + return self.request.user + + +class UserLinksListView(generics.ListAPIView): + serializer_class = LinkSerializer + permission_classes = [permissions.AllowAny] + def get_queryset(self): + username = self.kwargs['username'] + return Link.objects.filter(owner__username=username).order_by('order') + + +class PublicUserGroupsView(APIView): + """ + GET /api/users/{username}/public/ + """ + permission_classes = [permissions.AllowAny] + + def get(self, request, username): + # 1. Ищем пользователя + user = get_object_or_404(User, username=username) + + # 2. Берём его группы со ссылками + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + + result = { + "username": user.username, + "groups": [] + } + + for grp in groups_qs: + # icon у группы (абсолютный URL) + grp_icon_url = None + if grp.icon: + grp_icon_url = request.build_absolute_uri(grp.icon.url) + + grp_data = { + "id": grp.id, + "name": grp.name, + "icon": grp_icon_url, + "links": [], + } + + for ln in grp.links.all(): + # icon у ссылки + ln_icon_url = None + if ln.icon: + ln_icon_url = request.build_absolute_uri(ln.icon.url) + + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "icon": ln_icon_url, + }) + + result["groups"].append(grp_data) + + return Response(result, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/.history/backend/backend/settings_20250507080801.py b/.history/backend/backend/settings_20250507080801.py new file mode 100644 index 0000000..4cf2897 --- /dev/null +++ b/.history/backend/backend/settings_20250507080801.py @@ -0,0 +1,164 @@ +""" +Django settings for backend project. + +Generated by 'django-admin startproject' using Django 5.2. + +For more information on this file, see +https://docs.djangoproject.com/en/5.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.2/ref/settings/ +""" + +from pathlib import Path +from dotenv import load_dotenv +import os +# Load environment variables from .env file +load_dotenv() + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = os.getenv('DJANGO_SECRET_KEY') + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = os.getenv('DJANGO_DEBUG', 'False') == 'True' + +ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', '127.0.0.1').split(',') + +CORS_ALLOWED_ORIGINS = [ + "http://127.0.0.1:3001", + "http://localhost:3001", +] + +# Application definition + +INSTALLED_APPS = [ + "corsheaders", + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'users', + 'links', + 'customization', + 'api', + 'rest_framework', + 'rest_framework_simplejwt', + 'drf_spectacular', + 'drf_spectacular_sidecar', +] + +MIDDLEWARE = [ + "corsheaders.middleware.CorsMiddleware", + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'backend.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'backend.wsgi.application' + +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework_simplejwt.authentication.JWTAuthentication', + ), + 'DEFAULT_PERMISSION_CLASSES': ( + 'rest_framework.permissions.IsAuthenticatedOrReadOnly', + ), +} + +from datetime import timedelta +SIMPLE_JWT = { + 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60), + 'REFRESH_TOKEN_LIFETIME': timedelta(days=1), + 'AUTH_HEADER_TYPES': ('Bearer',), +} + +# Database +# https://docs.djangoproject.com/en/5.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': os.getenv('DATABASE_ENGINE', 'django.db.backends.postgresql'), + 'NAME': os.getenv('DATABASE_NAME'), + 'USER': os.getenv('DATABASE_USER'), + 'PASSWORD': os.getenv('DATABASE_PASSWORD'), + 'HOST': os.getenv('DATABASE_HOST'), + 'PORT': os.getenv('DATABASE_PORT'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators + +AUTH_USER_MODEL = 'users.User' + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.2/topics/i18n/ + +LANGUAGE_CODE = 'ru-ru' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.2/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +MEDIA_URL = '/storage/' +MEDIA_ROOT = BASE_DIR / 'storage' \ No newline at end of file diff --git a/.history/backend/backend/settings_20250507080850.py b/.history/backend/backend/settings_20250507080850.py new file mode 100644 index 0000000..037ea01 --- /dev/null +++ b/.history/backend/backend/settings_20250507080850.py @@ -0,0 +1,165 @@ +""" +Django settings for backend project. + +Generated by 'django-admin startproject' using Django 5.2. + +For more information on this file, see +https://docs.djangoproject.com/en/5.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.2/ref/settings/ +""" + +from pathlib import Path +from dotenv import load_dotenv +import os +# Load environment variables from .env file +load_dotenv() + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = os.getenv('DJANGO_SECRET_KEY') + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = os.getenv('DJANGO_DEBUG', 'False') == 'True' + +ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', '127.0.0.1').split(',') + +CORS_ALLOWED_ORIGINS = [ + "http://127.0.0.1:3001", + "http://localhost:3001", +] + +# Application definition + +INSTALLED_APPS = [ + "corsheaders", + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'users', + 'links', + 'customization', + 'api', + 'rest_framework', + 'rest_framework_simplejwt', + 'drf_spectacular', + 'drf_spectacular_sidecar', + 'django_extensions', +] + +MIDDLEWARE = [ + "corsheaders.middleware.CorsMiddleware", + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'backend.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'backend.wsgi.application' + +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework_simplejwt.authentication.JWTAuthentication', + ), + 'DEFAULT_PERMISSION_CLASSES': ( + 'rest_framework.permissions.IsAuthenticatedOrReadOnly', + ), +} + +from datetime import timedelta +SIMPLE_JWT = { + 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60), + 'REFRESH_TOKEN_LIFETIME': timedelta(days=1), + 'AUTH_HEADER_TYPES': ('Bearer',), +} + +# Database +# https://docs.djangoproject.com/en/5.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': os.getenv('DATABASE_ENGINE', 'django.db.backends.postgresql'), + 'NAME': os.getenv('DATABASE_NAME'), + 'USER': os.getenv('DATABASE_USER'), + 'PASSWORD': os.getenv('DATABASE_PASSWORD'), + 'HOST': os.getenv('DATABASE_HOST'), + 'PORT': os.getenv('DATABASE_PORT'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators + +AUTH_USER_MODEL = 'users.User' + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.2/topics/i18n/ + +LANGUAGE_CODE = 'ru-ru' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.2/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +MEDIA_URL = '/storage/' +MEDIA_ROOT = BASE_DIR / 'storage' \ No newline at end of file diff --git a/.history/backend/backend/settings_20250507081134.py b/.history/backend/backend/settings_20250507081134.py new file mode 100644 index 0000000..23852c2 --- /dev/null +++ b/.history/backend/backend/settings_20250507081134.py @@ -0,0 +1,165 @@ +""" +Django settings for backend project. + +Generated by 'django-admin startproject' using Django 5.2. + +For more information on this file, see +https://docs.djangoproject.com/en/5.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.2/ref/settings/ +""" + +from pathlib import Path +from dotenv import load_dotenv +import os +# Load environment variables from .env file +load_dotenv() + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = os.getenv('DJANGO_SECRET_KEY') + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = os.getenv('DJANGO_DEBUG', 'False') == 'True' + +ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', '127.0.0.1').split(',') + +CORS_ALLOWED_ORIGINS = [ + "http://127.0.0.1:3001", + "http://localhost:3001", +] + +# Application definition + +INSTALLED_APPS = [ + "corsheaders", + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'users', + 'links', + 'customization', + 'api', + 'rest_framework', + 'rest_framework_simplejwt', + 'drf_spectacular', + "drf_spectacular_sidecar", + 'django_extensions', +] + +MIDDLEWARE = [ + "corsheaders.middleware.CorsMiddleware", + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'backend.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'backend.wsgi.application' + +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework_simplejwt.authentication.JWTAuthentication', + ), + 'DEFAULT_PERMISSION_CLASSES': ( + 'rest_framework.permissions.IsAuthenticatedOrReadOnly', + ), +} + +from datetime import timedelta +SIMPLE_JWT = { + 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60), + 'REFRESH_TOKEN_LIFETIME': timedelta(days=1), + 'AUTH_HEADER_TYPES': ('Bearer',), +} + +# Database +# https://docs.djangoproject.com/en/5.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': os.getenv('DATABASE_ENGINE', 'django.db.backends.postgresql'), + 'NAME': os.getenv('DATABASE_NAME'), + 'USER': os.getenv('DATABASE_USER'), + 'PASSWORD': os.getenv('DATABASE_PASSWORD'), + 'HOST': os.getenv('DATABASE_HOST'), + 'PORT': os.getenv('DATABASE_PORT'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators + +AUTH_USER_MODEL = 'users.User' + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.2/topics/i18n/ + +LANGUAGE_CODE = 'ru-ru' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.2/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +MEDIA_URL = '/storage/' +MEDIA_ROOT = BASE_DIR / 'storage' \ No newline at end of file diff --git a/.history/backend/backend/settings_20250507081237.py b/.history/backend/backend/settings_20250507081237.py new file mode 100644 index 0000000..fa73ebc --- /dev/null +++ b/.history/backend/backend/settings_20250507081237.py @@ -0,0 +1,165 @@ +""" +Django settings for backend project. + +Generated by 'django-admin startproject' using Django 5.2. + +For more information on this file, see +https://docs.djangoproject.com/en/5.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.2/ref/settings/ +""" + +from pathlib import Path +from dotenv import load_dotenv +import os +# Load environment variables from .env file +load_dotenv() + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = os.getenv('DJANGO_SECRET_KEY') + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = os.getenv('DJANGO_DEBUG', 'False') == 'True' + +ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', '127.0.0.1').split(',') + +CORS_ALLOWED_ORIGINS = [ + "http://127.0.0.1:3001", + "http://localhost:3001", +] + +# Application definition + +INSTALLED_APPS = [ + "corsheaders", + 'drf_spectacular', + "drf_spectacular_sidecar", + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'users', + 'links', + 'customization', + 'api', + 'rest_framework', + 'rest_framework_simplejwt', + 'django_extensions', +] + +MIDDLEWARE = [ + "corsheaders.middleware.CorsMiddleware", + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'backend.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'backend.wsgi.application' + +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework_simplejwt.authentication.JWTAuthentication', + ), + 'DEFAULT_PERMISSION_CLASSES': ( + 'rest_framework.permissions.IsAuthenticatedOrReadOnly', + ), +} + +from datetime import timedelta +SIMPLE_JWT = { + 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60), + 'REFRESH_TOKEN_LIFETIME': timedelta(days=1), + 'AUTH_HEADER_TYPES': ('Bearer',), +} + +# Database +# https://docs.djangoproject.com/en/5.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': os.getenv('DATABASE_ENGINE', 'django.db.backends.postgresql'), + 'NAME': os.getenv('DATABASE_NAME'), + 'USER': os.getenv('DATABASE_USER'), + 'PASSWORD': os.getenv('DATABASE_PASSWORD'), + 'HOST': os.getenv('DATABASE_HOST'), + 'PORT': os.getenv('DATABASE_PORT'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators + +AUTH_USER_MODEL = 'users.User' + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.2/topics/i18n/ + +LANGUAGE_CODE = 'ru-ru' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.2/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +MEDIA_URL = '/storage/' +MEDIA_ROOT = BASE_DIR / 'storage' \ No newline at end of file diff --git a/.history/backend/backend/settings_20250507082006.py b/.history/backend/backend/settings_20250507082006.py new file mode 100644 index 0000000..3668ee2 --- /dev/null +++ b/.history/backend/backend/settings_20250507082006.py @@ -0,0 +1,166 @@ +""" +Django settings for backend project. + +Generated by 'django-admin startproject' using Django 5.2. + +For more information on this file, see +https://docs.djangoproject.com/en/5.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.2/ref/settings/ +""" + +from pathlib import Path +from dotenv import load_dotenv +import os +# Load environment variables from .env file +load_dotenv() + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = os.getenv('DJANGO_SECRET_KEY') + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = os.getenv('DJANGO_DEBUG', 'False') == 'True' + +ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', '127.0.0.1').split(',') + +CORS_ALLOWED_ORIGINS = [ + "http://127.0.0.1:3001", + "http://localhost:3001", +] + +# Application definition + +INSTALLED_APPS = [ + "corsheaders", + 'drf_spectacular', + "drf_spectacular_sidecar", + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'users', + 'links', + 'customization', + 'api', + 'rest_framework', + 'rest_framework_simplejwt', + 'django_extensions', +] + +MIDDLEWARE = [ + "corsheaders.middleware.CorsMiddleware", + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'backend.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'backend.wsgi.application' + +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework_simplejwt.authentication.JWTAuthentication', + ), + 'DEFAULT_PERMISSION_CLASSES': ( + 'rest_framework.permissions.IsAuthenticatedOrReadOnly', + ), + 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', +} + +from datetime import timedelta +SIMPLE_JWT = { + 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60), + 'REFRESH_TOKEN_LIFETIME': timedelta(days=1), + 'AUTH_HEADER_TYPES': ('Bearer',), +} + +# Database +# https://docs.djangoproject.com/en/5.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': os.getenv('DATABASE_ENGINE', 'django.db.backends.postgresql'), + 'NAME': os.getenv('DATABASE_NAME'), + 'USER': os.getenv('DATABASE_USER'), + 'PASSWORD': os.getenv('DATABASE_PASSWORD'), + 'HOST': os.getenv('DATABASE_HOST'), + 'PORT': os.getenv('DATABASE_PORT'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators + +AUTH_USER_MODEL = 'users.User' + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.2/topics/i18n/ + +LANGUAGE_CODE = 'ru-ru' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.2/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +MEDIA_URL = '/storage/' +MEDIA_ROOT = BASE_DIR / 'storage' \ No newline at end of file diff --git a/.history/backend/backend/settings_20250507082028.py b/.history/backend/backend/settings_20250507082028.py new file mode 100644 index 0000000..8ed99f0 --- /dev/null +++ b/.history/backend/backend/settings_20250507082028.py @@ -0,0 +1,168 @@ +""" +Django settings for backend project. + +Generated by 'django-admin startproject' using Django 5.2. + +For more information on this file, see +https://docs.djangoproject.com/en/5.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.2/ref/settings/ +""" + +from pathlib import Path +from dotenv import load_dotenv +import os +# Load environment variables from .env file +load_dotenv() + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = os.getenv('DJANGO_SECRET_KEY') + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = os.getenv('DJANGO_DEBUG', 'False') == 'True' + +ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', '127.0.0.1').split(',') + +CORS_ALLOWED_ORIGINS = [ + "http://127.0.0.1:3001", + "http://localhost:3001", +] + +# Application definition + +INSTALLED_APPS = [ + "corsheaders", + 'drf_spectacular', + "drf_spectacular_sidecar", + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'users', + 'links', + 'customization', + 'api', + 'rest_framework', + 'rest_framework_simplejwt', + 'django_extensions', +] + +MIDDLEWARE = [ + "corsheaders.middleware.CorsMiddleware", + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'backend.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'backend.wsgi.application' + +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework_simplejwt.authentication.JWTAuthentication', + ), + 'DEFAULT_PERMISSION_CLASSES': ( + 'rest_framework.permissions.IsAuthenticatedOrReadOnly', + ), + 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', +} + +from datetime import timedelta +SIMPLE_JWT = { + 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60), + 'REFRESH_TOKEN_LIFETIME': timedelta(days=1), + 'AUTH_HEADER_TYPES': ('Bearer',), +} + +# Database +# https://docs.djangoproject.com/en/5.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': os.getenv('DATABASE_ENGINE', 'django.db.backends.postgresql'), + 'NAME': os.getenv('DATABASE_NAME'), + 'USER': os.getenv('DATABASE_USER'), + 'PASSWORD': os.getenv('DATABASE_PASSWORD'), + 'HOST': os.getenv('DATABASE_HOST'), + 'PORT': os.getenv('DATABASE_PORT'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators + +AUTH_USER_MODEL = 'users.User' + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.2/topics/i18n/ + +LANGUAGE_CODE = 'ru-ru' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.2/howto/static-files/ + +STATIC_ROOT = BASE_DIR / 'staticfiles' + +# URL, по которому статика будет доступна +STATIC_URL = '/static/' +# Default primary key field type +# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +MEDIA_URL = '/storage/' +MEDIA_ROOT = BASE_DIR / 'storage' \ No newline at end of file diff --git a/.history/backend/backend/urls_20250507080600.py b/.history/backend/backend/urls_20250507080600.py new file mode 100644 index 0000000..dc6185b --- /dev/null +++ b/.history/backend/backend/urls_20250507080600.py @@ -0,0 +1,60 @@ +from django.contrib import admin +from django.urls import path, include +from django.conf import settings +from django.conf.urls.static import static +from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView + +urlpatterns = [ + path('admin/', admin.site.urls), + path('api/', include('api.urls')), # API endpoints + path('users/', include('users.urls')), # User management app + path('links/', include('links.urls')), # Link management app + path('customization/', include('customization.urls')), # Design customization app + path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), +] + +if settings.DEBUG: + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + + +# Summary of API Endpoints: +# POST /api/auth/register/ - Register new user +# POST /api/auth/login/ - Obtain JWT tokens (access & refresh) +# GET /api/users//links/ - Public list of user's links +# GET /api/links/ - List authenticated user's links +# POST /api/links/ - Create a new link +# GET /api/links/{id}/ - Retrieve a specific link +# PUT /api/links/{id}/ - Update a specific link +# PATCH /api/links/{id}/ - Partially update a link +# DELETE /api/links/{id}/ - Delete a specific link +# GET /api/groups/ - List authenticated user's link groups +# POST /api/groups/ - Create a new link group +# GET /api/groups/{id}/ - Retrieve a specific link group +# PUT /api/groups/{id}/ - Update a link group +# PATCH /api/groups/{id}/ - Partially update a link group +# DELETE /api/groups/{id}/ - Delete a specific link group + +# To avoid URL configuration errors, ensure the following placeholder URLConfs exist: +# users/urls.py +# ---------------- +# from django.urls import path, include +# +# urlpatterns = [ +# # Define user-management endpoints here (e.g., profile, settings) +# ] + +# links/urls.py +# ---------------- +# from django.urls import path, include +# +# urlpatterns = [ +# # Define additional link-management endpoints here if needed +# ] + +# customization/urls.py +# ---------------- +# from django.urls import path, include +# +# urlpatterns = [ +# # Define design customization endpoints here +# ] diff --git a/.history/backend/backend/urls_20250507081420.py b/.history/backend/backend/urls_20250507081420.py new file mode 100644 index 0000000..0f6228d --- /dev/null +++ b/.history/backend/backend/urls_20250507081420.py @@ -0,0 +1,60 @@ +from django.contrib import admin +from django.urls import path, include +from django.conf import settings +from django.conf.urls.static import static + + +urlpatterns = [ + path('admin/', admin.site.urls), + path('api/', include('api.urls')), # API endpoints + path('users/', include('users.urls')), # User management app + path('links/', include('links.urls')), # Link management app + path('customization/', include('customization.urls')), # Design customization app + path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), +] + +if settings.DEBUG: + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + + +# Summary of API Endpoints: +# POST /api/auth/register/ - Register new user +# POST /api/auth/login/ - Obtain JWT tokens (access & refresh) +# GET /api/users//links/ - Public list of user's links +# GET /api/links/ - List authenticated user's links +# POST /api/links/ - Create a new link +# GET /api/links/{id}/ - Retrieve a specific link +# PUT /api/links/{id}/ - Update a specific link +# PATCH /api/links/{id}/ - Partially update a link +# DELETE /api/links/{id}/ - Delete a specific link +# GET /api/groups/ - List authenticated user's link groups +# POST /api/groups/ - Create a new link group +# GET /api/groups/{id}/ - Retrieve a specific link group +# PUT /api/groups/{id}/ - Update a link group +# PATCH /api/groups/{id}/ - Partially update a link group +# DELETE /api/groups/{id}/ - Delete a specific link group + +# To avoid URL configuration errors, ensure the following placeholder URLConfs exist: +# users/urls.py +# ---------------- +# from django.urls import path, include +# +# urlpatterns = [ +# # Define user-management endpoints here (e.g., profile, settings) +# ] + +# links/urls.py +# ---------------- +# from django.urls import path, include +# +# urlpatterns = [ +# # Define additional link-management endpoints here if needed +# ] + +# customization/urls.py +# ---------------- +# from django.urls import path, include +# +# urlpatterns = [ +# # Define design customization endpoints here +# ] diff --git a/.history/frontend/linktree-frontend/.next/types/app/dashboard/page_20250507074450.ts b/.history/frontend/linktree-frontend/.next/types/app/dashboard/page_20250507074450.ts new file mode 100644 index 0000000..e5cebfe --- /dev/null +++ b/.history/frontend/linktree-frontend/.next/types/app/dashboard/page_20250507074450.ts @@ -0,0 +1,84 @@ +// File: /home/trevor/links/frontend/linktree-frontend/src/app/dashboard/page.tsx +import * as entry from '../../../../src/app/dashboard/page.js' +import type { ResolvingMetadata, ResolvingViewport } from 'next/dist/lib/metadata/types/metadata-interface.js' + +type TEntry = typeof import('../../../../src/app/dashboard/page.js') + +type SegmentParams = T extends Record + ? { [K in keyof T]: T[K] extends string ? string | string[] | undefined : never } + : T + +// Check that the entry is a valid entry +checkFields | false + dynamic?: 'auto' | 'force-dynamic' | 'error' | 'force-static' + dynamicParams?: boolean + fetchCache?: 'auto' | 'force-no-store' | 'only-no-store' | 'default-no-store' | 'default-cache' | 'only-cache' | 'force-cache' + preferredRegion?: 'auto' | 'global' | 'home' | string | string[] + runtime?: 'nodejs' | 'experimental-edge' | 'edge' + maxDuration?: number + + metadata?: any + generateMetadata?: Function + viewport?: any + generateViewport?: Function + experimental_ppr?: boolean + +}, TEntry, ''>>() + + +// Check the prop type of the entry function +checkFields, 'default'>>() + +// Check the arguments and return type of the generateMetadata function +if ('generateMetadata' in entry) { + checkFields>, 'generateMetadata'>>() + checkFields>, 'generateMetadata'>>() +} + +// Check the arguments and return type of the generateViewport function +if ('generateViewport' in entry) { + checkFields>, 'generateViewport'>>() + checkFields>, 'generateViewport'>>() +} + +// Check the arguments and return type of the generateStaticParams function +if ('generateStaticParams' in entry) { + checkFields>, 'generateStaticParams'>>() + checkFields }, { __tag__: 'generateStaticParams', __return_type__: ReturnType> }>>() +} + +export interface PageProps { + params?: Promise + searchParams?: Promise +} +export interface LayoutProps { + children?: React.ReactNode + + params?: Promise +} + +// ============= +// Utility types +type RevalidateRange = T extends { revalidate: any } ? NonNegative : never + +// If T is unknown or any, it will be an empty {} type. Otherwise, it will be the same as Omit. +type OmitWithTag = Omit +type Diff = 0 extends (1 & T) ? {} : OmitWithTag + +type FirstArg = T extends (...args: [infer T, any]) => any ? unknown extends T ? any : T : never +type SecondArg = T extends (...args: [any, infer T]) => any ? unknown extends T ? any : T : never +type MaybeField = T extends { [k in K]: infer G } ? G extends Function ? G : never : never + + + +function checkFields<_ extends { [k in keyof any]: never }>() {} + +// https://github.com/sindresorhus/type-fest +type Numeric = number | bigint +type Zero = 0 | 0n +type Negative = T extends Zero ? never : `${T}` extends `-${string}` ? T : never +type NonNegative = T extends Zero ? T : Negative extends never ? T : '__invalid_negative_number__' diff --git a/.history/frontend/linktree-frontend/.next/types/app/dashboard/page_20250507074950.ts b/.history/frontend/linktree-frontend/.next/types/app/dashboard/page_20250507074950.ts new file mode 100644 index 0000000..d351c31 --- /dev/null +++ b/.history/frontend/linktree-frontend/.next/types/app/dashboard/page_20250507074950.ts @@ -0,0 +1,84 @@ +// File: /home/trevor/links/frontend/linktree-frontend/src/app/dashboard/page.tsx +import * as entry from '../../../../src/app/(protected)/dashboard/page.jsx' +import type { ResolvingMetadata, ResolvingViewport } from 'next/dist/lib/metadata/types/metadata-interface.js' + +type TEntry = typeof import('../../../../src/app/(protected)/dashboard/page.jsx') + +type SegmentParams = T extends Record + ? { [K in keyof T]: T[K] extends string ? string | string[] | undefined : never } + : T + +// Check that the entry is a valid entry +checkFields | false + dynamic?: 'auto' | 'force-dynamic' | 'error' | 'force-static' + dynamicParams?: boolean + fetchCache?: 'auto' | 'force-no-store' | 'only-no-store' | 'default-no-store' | 'default-cache' | 'only-cache' | 'force-cache' + preferredRegion?: 'auto' | 'global' | 'home' | string | string[] + runtime?: 'nodejs' | 'experimental-edge' | 'edge' + maxDuration?: number + + metadata?: any + generateMetadata?: Function + viewport?: any + generateViewport?: Function + experimental_ppr?: boolean + +}, TEntry, ''>>() + + +// Check the prop type of the entry function +checkFields, 'default'>>() + +// Check the arguments and return type of the generateMetadata function +if ('generateMetadata' in entry) { + checkFields>, 'generateMetadata'>>() + checkFields>, 'generateMetadata'>>() +} + +// Check the arguments and return type of the generateViewport function +if ('generateViewport' in entry) { + checkFields>, 'generateViewport'>>() + checkFields>, 'generateViewport'>>() +} + +// Check the arguments and return type of the generateStaticParams function +if ('generateStaticParams' in entry) { + checkFields>, 'generateStaticParams'>>() + checkFields }, { __tag__: 'generateStaticParams', __return_type__: ReturnType> }>>() +} + +export interface PageProps { + params?: Promise + searchParams?: Promise +} +export interface LayoutProps { + children?: React.ReactNode + + params?: Promise +} + +// ============= +// Utility types +type RevalidateRange = T extends { revalidate: any } ? NonNegative : never + +// If T is unknown or any, it will be an empty {} type. Otherwise, it will be the same as Omit. +type OmitWithTag = Omit +type Diff = 0 extends (1 & T) ? {} : OmitWithTag + +type FirstArg = T extends (...args: [infer T, any]) => any ? unknown extends T ? any : T : never +type SecondArg = T extends (...args: [any, infer T]) => any ? unknown extends T ? any : T : never +type MaybeField = T extends { [k in K]: infer G } ? G extends Function ? G : never : never + + + +function checkFields<_ extends { [k in keyof any]: never }>() {} + +// https://github.com/sindresorhus/type-fest +type Numeric = number | bigint +type Zero = 0 | 0n +type Negative = T extends Zero ? never : `${T}` extends `-${string}` ? T : never +type NonNegative = T extends Zero ? T : Negative extends never ? T : '__invalid_negative_number__' diff --git a/.history/frontend/linktree-frontend/next.config_20250507131744.ts b/.history/frontend/linktree-frontend/next.config_20250507131744.ts new file mode 100644 index 0000000..95f125e --- /dev/null +++ b/.history/frontend/linktree-frontend/next.config_20250507131744.ts @@ -0,0 +1,35 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + images: { + remotePatterns: [ + { + protocol: 'http', + hostname: '127.0.0.1', + port: '8000', // <-- обязательно 8000, где Django отдаёт медиа + pathname: '/storage/**', // <-- подпапкиstorage/avatars, images/link_groups и т.д. + }, + + ], + }, + // Разрешаем в деве обращения с вашего адреса + allowedDevOrigins: [ + 'http://localhost:3001', + 'http://192.168.219.114:3001', + 'http://0.0.0.0:3001', + 'http://localhost:3000', + 'http://192.168.219.114:3000', + 'http://127.0.0.1:3001', + ], + + // Проксируем все запросы /api/* на Django + async rewrites() { + return [ + { + source: '/api/:path*', // локальный путь на фронте + destination: 'http://127.0.0.1:8000/api/:path*/' // куда реально уходит запрос + } + ] + }, +}; + +module.exports = nextConfig; diff --git a/.history/frontend/linktree-frontend/next.config_20250507133920.ts b/.history/frontend/linktree-frontend/next.config_20250507133920.ts new file mode 100644 index 0000000..b8d6501 --- /dev/null +++ b/.history/frontend/linktree-frontend/next.config_20250507133920.ts @@ -0,0 +1,37 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + images: { + remotePatterns: [ + { + protocol: 'http', + hostname: '127.0.0.1', + port: '8000', // where Django serves media + pathname: '/storage/**', // storage/avatars, images/link_groups, etc. + }, + ], + }, + + // proxy all /api/* calls to Django + async rewrites() { + return [ + { + source: '/api/:path*', + destination: 'http://127.0.0.1:8000/api/:path*/', + }, + ]; + }, + + experimental: { + // whitelist origins you’ll browse from in dev + allowedDevOrigins: [ + 'http://localhost:3001', + 'http://127.0.0.1:3001', + 'http://192.168.219.114:3001', + 'http://0.0.0.0:3001', + 'http://localhost:3000', + 'http://192.168.219.114:3000', + ], + }, +}; + +module.exports = nextConfig; diff --git a/.history/frontend/linktree-frontend/next.config_20250507133940.ts b/.history/frontend/linktree-frontend/next.config_20250507133940.ts new file mode 100644 index 0000000..2240e33 --- /dev/null +++ b/.history/frontend/linktree-frontend/next.config_20250507133940.ts @@ -0,0 +1,37 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + images: { + remotePatterns: [ + { + protocol: 'http', + hostname: '127.0.0.1', + port: '8000', // where Django serves media + pathname: '/storage/**', // storage/avatars, images/link_groups, etc. + }, + ], + }, + + // proxy all /api/* calls to Django + async rewrites() { + return [ + { + source: '/api/:path*', + destination: 'http://127.0.0.1:8000/api/:path*', + }, + ]; + }, + + experimental: { + // whitelist origins you’ll browse from in dev + allowedDevOrigins: [ + 'http://localhost:3001', + 'http://127.0.0.1:3001', + 'http://192.168.219.114:3001', + 'http://0.0.0.0:3001', + 'http://localhost:3000', + 'http://192.168.219.114:3000', + ], + }, +}; + +module.exports = nextConfig; diff --git a/.history/frontend/linktree-frontend/package_20250507131936.json b/.history/frontend/linktree-frontend/package_20250507131936.json new file mode 100644 index 0000000..7601bae --- /dev/null +++ b/.history/frontend/linktree-frontend/package_20250507131936.json @@ -0,0 +1,31 @@ +{ + "name": "linktree-frontend", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "axios": "^1.9.0", + "next": "15.3.1", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-hook-form": "^7.56.2" + }, + "devDependencies": { + "@eslint/eslintrc": "^3", + "@tailwindcss/postcss": "^4.1.5", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "autoprefixer": "^10.4.21", + "eslint": "^9", + "eslint-config-next": "15.3.1", + "postcss": "^8.5.3", + "tailwindcss": "^4.1.5", + "typescript": "^5" + } +} diff --git a/.history/frontend/linktree-frontend/public/manifest_20250507074158.json b/.history/frontend/linktree-frontend/public/manifest_20250507074158.json new file mode 100644 index 0000000..e69de29 diff --git a/.history/frontend/linktree-frontend/public/manifest_20250507074202.json b/.history/frontend/linktree-frontend/public/manifest_20250507074202.json new file mode 100644 index 0000000..d2245a9 --- /dev/null +++ b/.history/frontend/linktree-frontend/public/manifest_20250507074202.json @@ -0,0 +1,21 @@ +{ + "name": "CatLink", + "short_name": "CatLink", + "icons": [ + { + "src": "/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" + } \ No newline at end of file diff --git a/.history/frontend/linktree-frontend/public/manifest_20250507074217.json b/.history/frontend/linktree-frontend/public/manifest_20250507074217.json new file mode 100644 index 0000000..fbb3476 --- /dev/null +++ b/.history/frontend/linktree-frontend/public/manifest_20250507074217.json @@ -0,0 +1,45 @@ +{ + "name": "CatLink", + "short_name": "CatLink", + "icons": [ + { + "src": "/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" + + "name": "CatLink", + "short_name": "CatLink", + "description": "Все ваши ссылки в одном месте. Публикуйте CatLink в био, мессенджерах и письмах.", + "start_url": "/", + "scope": "/", + "display": "standalone", + "theme_color": "#ffffff", + "background_color": "#ffffff", + "icons": [ + { + "src": "/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] + } + \ No newline at end of file diff --git a/.history/frontend/linktree-frontend/public/manifest_20250507074316.json b/.history/frontend/linktree-frontend/public/manifest_20250507074316.json new file mode 100644 index 0000000..d2ee75d --- /dev/null +++ b/.history/frontend/linktree-frontend/public/manifest_20250507074316.json @@ -0,0 +1,25 @@ +{ + "name": "CatLink", + "short_name": "CatLink", + "description": "Все ваши ссылки в одном месте. Публикуйте CatLink в био, мессенджерах и письмах.", + "start_url": "/", + "scope": "/", + "display": "standalone", + "theme_color": "#ffffff", + "background_color": "#ffffff", + "icons": [ + { + "src": "/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] + } + \ No newline at end of file diff --git a/.history/frontend/linktree-frontend/src/app/(protected)/auth/register/page_20250507082845.tsx b/.history/frontend/linktree-frontend/src/app/(protected)/auth/register/page_20250507082845.tsx new file mode 100644 index 0000000..e69de29 diff --git a/.history/frontend/linktree-frontend/src/app/(protected)/auth/register/page_20250507082848.tsx b/.history/frontend/linktree-frontend/src/app/(protected)/auth/register/page_20250507082848.tsx new file mode 100644 index 0000000..f63f3f1 --- /dev/null +++ b/.history/frontend/linktree-frontend/src/app/(protected)/auth/register/page_20250507082848.tsx @@ -0,0 +1,238 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { useForm } from 'react-hook-form'; +import { useRouter } from 'next/navigation'; +import Link from 'next/link'; +import Image from 'next/image'; + +type FormData = { + username: string; + email: string; + first_name?: string; + last_name?: string; + password: string; + password2: string; +}; + +export default function RegisterPage() { + const router = useRouter(); + const { + register, + handleSubmit, + formState: { errors, isSubmitting }, + } = useForm(); + const [apiError, setApiError] = useState(null); + + // если уже залогинен — редирект на дашборд + useEffect(() => { + if (typeof window !== 'undefined' && localStorage.getItem('token')) { + router.push('/dashboard'); + } + }, [router]); + + async function onSubmit(data: FormData) { + setApiError(null); + try { + const res = await fetch('/api/auth/register/', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(data), + }); + if (!res.ok) { + const json = await res.json(); + // берём первую ошибку из ответа + const firstKey = Object.keys(json)[0]; + setApiError( + Array.isArray(json[firstKey]) + ? (json[firstKey] as string[])[0] + : json[firstKey].toString() + ); + return; + } + // при успехе — редирект на логин + router.push('/auth/login'); + } catch (e) { + setApiError('Сетевая ошибка, попробуйте снова.'); + } + } + + return ( +
+
+
+
+
+
+ {/* Левая половина с картинкой */} +
+
+
+ + {/* Правая — сама форма */} +
+
+
+

Регистрация

+
+
+ {/* Username */} +
+ + {errors.username && ( +
+ {errors.username.message} +
+ )} +
+ + {/* Email */} +
+ + {errors.email && ( +
+ {errors.email.message} +
+ )} +
+ + {/* First / Last name */} +
+
+ +
+
+ +
+
+ + {/* Password */} +
+ + {errors.password && ( +
+ {errors.password.message} +
+ )} +
+ + {/* Confirm Password */} +
+ + value === formValues.password || + 'Пароли не совпадают', + })} + /> + {errors.password2 && ( +
+ {errors.password2.message} +
+ )} +
+ + {/* API Error */} + {apiError && ( +
+ {apiError} +
+ )} + + {/* Кнопка */} + +
+ + {/* Ссылка на вход */} +
+
+ + Уже есть аккаунт?{' '} + + Войти + + +
+
+
+
+
+
+
+
+
+ ); +} diff --git a/frontend/linktree-frontend/src/app/dashboard/page.tsx b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250506191940.tsx similarity index 100% rename from frontend/linktree-frontend/src/app/dashboard/page.tsx rename to .history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250506191940.tsx diff --git a/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507074950.tsx b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507074950.tsx new file mode 100644 index 0000000..b04283d --- /dev/null +++ b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507074950.tsx @@ -0,0 +1,199 @@ +// src/app/dashboard/page.tsx +'use client' + +import React, { useEffect, useState, Fragment } from 'react' +import { useRouter } from 'next/navigation' +import Link from 'next/link' +import { ProfileCard } from '../../components/ProfileCard' + +interface UserProfile { + avatar: string + full_name: string + email: string + bio?: string + last_login: string + date_joined: string +} + +interface LinkItem { + id: number + title: string + url: string +} + +interface Group { + id: number + name: string + links?: LinkItem[] +} + +export default function DashboardPage() { + const router = useRouter() + const [user, setUser] = useState(null) + const [groups, setGroups] = useState([]) + const [expandedGroup, setExpandedGroup] = useState(null) + const [loading, setLoading] = useState(true) + + useEffect(() => { + const token = localStorage.getItem('token') + if (!token) { + router.push('/auth/login') + return + } + + const fetchData = async () => { + try { + // 1) Профиль + const uRes = await fetch(`/api/auth/user/`, { + headers: { Authorization: `Bearer ${token}` }, + }) + if (uRes.status === 401) { + localStorage.removeItem('token') + router.push('/auth/login') + return + } + if (!uRes.ok) throw new Error('Не удалось получить профиль') + const userData: UserProfile = await uRes.json() + + // 2) Группы + const gRes = await fetch(`/api/groups/`, { + headers: { Authorization: `Bearer ${token}` }, + }) + if (gRes.status === 401) { + localStorage.removeItem('token') + router.push('/auth/login') + return + } + if (!gRes.ok) throw new Error('Не удалось загрузить группы') + const groupsData: Group[] = await gRes.json() + + setUser(userData) + setGroups(groupsData) + } catch (err) { + // на любую ошибку — редирект на логин + console.error(err) + localStorage.removeItem('token') + router.push('/auth/login') + } finally { + setLoading(false) + } + } + + fetchData() + }, [router]) + + if (loading) { + return
Загрузка...
+ } + + return ( +
+
+
+
+ {/* Профиль пользователя */} + {user && ( + + )} + + {/* Секция групп ссылок */} +
+
+
Группы ссылок
+ +
+
+ {groups.map((group) => ( + +
+ + setExpandedGroup( + expandedGroup === group.id ? null : group.id + ) + } + > + {group.name}{' '} + + {group.links?.length ?? 0} + + +
+ + + +
+
+ {expandedGroup === group.id && ( +
+ +
+ )} +
+ ))} +
+
+ +
+
+
+
+
+
+ ) +} diff --git a/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507102038.tsx b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507102038.tsx new file mode 100644 index 0000000..34a498d --- /dev/null +++ b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507102038.tsx @@ -0,0 +1,423 @@ +'use client' + +import React, { useEffect, useState, Fragment } from 'react' +import { useRouter } from 'next/navigation' +import Image from 'next/image' +import { Modal } from '../components/Modal' // Модалка из примера выше + +interface UserProfile { + id: number + username: string + email: string + full_name: string + bio?: string + avatar: string + last_login: string + date_joined: string +} + +interface LinkItem { + id: number + title: string + url: string + icon?: string +} + +interface Group { + id: number + name: string + image?: string + links: LinkItem[] + _open?: boolean // флаг аккордеона +} + +type ModalType = + | 'addGroup' + | 'editGroup' + | 'deleteGroup' + | 'addLink' + | 'editLink' + | 'deleteLink' + | null + +export default function DashboardPage() { + const router = useRouter() + const API = process.env.NEXT_PUBLIC_API_URL + const token = typeof window !== 'undefined' ? localStorage.getItem('token') : null + + const [user, setUser] = useState(null) + const [groups, setGroups] = useState([]) + const [loading, setLoading] = useState(true) + const [error, setError] = useState(null) + + // для модалки + const [modalType, setModalType] = useState(null) + const [currentGroup, setCurrentGroup] = useState(null) + const [currentLink, setCurrentLink] = useState(null) + const [formValue, setFormValue] = useState<{ name?: string; url?: string }>({}) + + // загрузка пользователя и групп + useEffect(() => { + if (!token) { + router.replace('/auth/login') + return + } + Promise.all([ + fetch(`${API}/api/auth/user/`, { + headers: { Authorization: `Bearer ${token}` }, + }), + fetch(`${API}/api/groups/`, { + headers: { Authorization: `Bearer ${token}` }, + }), + ]) + .then(async ([uRes, gRes]) => { + if (!uRes.ok) throw new Error('Не удалось получить профиль') + if (!gRes.ok) throw new Error('Не удалось загрузить группы') + const [u, g] = await Promise.all([uRes.json(), gRes.json()]) + setUser(u) + setGroups(g) + }) + .catch((err) => setError((err as Error).message)) + .finally(() => setLoading(false)) + }, [router, API, token]) + + if (loading) return
Загрузка...
+ if (error) return
{error}
+ + // закрыть модалку + const closeModal = () => { + setModalType(null) + setCurrentGroup(null) + setCurrentLink(null) + setFormValue({}) + } + + // === Группы === + async function handleGroupSubmit() { + if (!modalType) return + const isNew = modalType === 'addGroup' + const url = isNew + ? `${API}/api/groups/` + : `${API}/api/groups/${currentGroup!.id}/` + const method = isNew ? 'POST' : 'PUT' + const res = await fetch(url, { + method, + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify({ name: formValue.name }), + }) + if (res.ok) { + const grp = await res.json() + setGroups((prev) => + isNew + ? [...prev, { ...grp, links: [] }] + : prev.map((g) => (g.id === grp.id ? { ...g, name: grp.name } : g)) + ) + closeModal() + } else { + alert('Ошибка при сохранении группы') + } + } + + async function handleGroupDelete() { + if (!currentGroup) return + const res = await fetch(`${API}/api/groups/${currentGroup.id}/`, { + method: 'DELETE', + headers: { Authorization: `Bearer ${token}` }, + }) + if (res.ok) { + setGroups((prev) => prev.filter((g) => g.id !== currentGroup.id)) + closeModal() + } else { + alert('Ошибка при удалении группы') + } + } + + // === Ссылки === + async function handleLinkSubmit() { + if (!currentGroup) return + const isEdit = modalType === 'editLink' + const url = isEdit + ? `${API}/api/links/${currentLink!.id}/` + : `${API}/api/links/` + const method = isEdit ? 'PUT' : 'POST' + const payload = { + title: formValue.name, + url: formValue.url, + group: currentGroup.id, + } + const res = await fetch(url, { + method, + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify(payload), + }) + if (res.ok) { + const linkData = await res.json() + setGroups((prev) => + prev.map((g) => + g.id === currentGroup.id + ? { + ...g, + links: isEdit + ? g.links.map((l) => (l.id === linkData.id ? linkData : l)) + : [...g.links, linkData], + } + : g + ) + ) + closeModal() + } else { + alert('Ошибка при сохранении ссылки') + } + } + + async function handleLinkDelete() { + if (!currentLink || !currentGroup) return + const res = await fetch(`${API}/api/links/${currentLink.id}/`, { + method: 'DELETE', + headers: { Authorization: `Bearer ${token}` }, + }) + if (res.ok) { + setGroups((prev) => + prev.map((g) => + g.id === currentGroup.id + ? { ...g, links: g.links.filter((l) => l.id !== currentLink.id) } + : g + ) + ) + closeModal() + } else { + alert('Ошибка при удалении ссылки') + } + } + + return ( +
+ {/* Профиль */} + {user && ( +
+
+ Avatar +
+
+ {user.full_name || user.username} +
+

{user.email}

+
+
+
+ )} + + {/* Заголовок с кнопкой «Добавить группу» */} +
+

Группы ссылок

+ +
+ + {/* Список групп (аккордеон) */} + {groups.map((group) => ( + +
+
+
+ {/* Редактировать имя группы */} + { + e.preventDefault() + setCurrentGroup(group) + setFormValue({ name: group.name }) + setModalType('editGroup') + }} + > + + + {/* Открыть/закрыть аккордеон */} + + setGroups((pg) => + pg.map((g) => + g.id === group.id + ? { ...g, _open: !g._open } + : g + ) + ) + } + > + {group.name}{' '} + + {group.links.length} + + +
+
+ {/* Добавить ссылку */} + + {/* Удалить группу */} + +
+
+ {/* Ссылки в раскрытом состоянии */} + {group._open && ( +
    + {group.links.map((link) => ( +
  • + + {link.title} + +
    + + +
    +
  • + ))} +
+ )} +
+
+ ))} + + {/* Универсальная модалка */} + {modalType && ( + + {/* Группа: добавить/редактировать */} + {(modalType === 'addGroup' || modalType === 'editGroup') && ( + <> +
+ {modalType === 'addGroup' ? 'Новая группа' : 'Редактировать группу'} +
+ + setFormValue({ ...formValue, name: e.target.value }) + } + /> + + + )} + {/* Подтверждение удаления группы */} + {modalType === 'deleteGroup' && ( + <> +
Удалить группу?
+

Группа «{currentGroup?.name}» будет удалена навсегда.

+ + + + )} + {/* Ссылка: добавить/редактировать */} + {(modalType === 'addLink' || modalType === 'editLink') && ( + <> +
{modalType === 'addLink' ? 'Новая ссылка' : 'Редактировать ссылку'}
+ + setFormValue({ ...formValue, name: e.target.value }) + } + /> + + setFormValue({ ...formValue, url: e.target.value }) + } + /> + + + )} + {/* Подтверждение удаления ссылки */} + {modalType === 'deleteLink' && ( + <> +
Удалить ссылку?
+

Ссылка «{currentLink?.title}» будет удалена.

+ + + + )} +
+ )} +
+ ) +} diff --git a/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507102107.tsx b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507102107.tsx new file mode 100644 index 0000000..a2e5da9 --- /dev/null +++ b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507102107.tsx @@ -0,0 +1,423 @@ +'use client' + +import React, { useEffect, useState, Fragment } from 'react' +import { useRouter } from 'next/navigation' +import Image from 'next/image' +import { Modal } from '../../components/modal' // Модалка из примера выше + +interface UserProfile { + id: number + username: string + email: string + full_name: string + bio?: string + avatar: string + last_login: string + date_joined: string +} + +interface LinkItem { + id: number + title: string + url: string + icon?: string +} + +interface Group { + id: number + name: string + image?: string + links: LinkItem[] + _open?: boolean // флаг аккордеона +} + +type ModalType = + | 'addGroup' + | 'editGroup' + | 'deleteGroup' + | 'addLink' + | 'editLink' + | 'deleteLink' + | null + +export default function DashboardPage() { + const router = useRouter() + const API = process.env.NEXT_PUBLIC_API_URL + const token = typeof window !== 'undefined' ? localStorage.getItem('token') : null + + const [user, setUser] = useState(null) + const [groups, setGroups] = useState([]) + const [loading, setLoading] = useState(true) + const [error, setError] = useState(null) + + // для модалки + const [modalType, setModalType] = useState(null) + const [currentGroup, setCurrentGroup] = useState(null) + const [currentLink, setCurrentLink] = useState(null) + const [formValue, setFormValue] = useState<{ name?: string; url?: string }>({}) + + // загрузка пользователя и групп + useEffect(() => { + if (!token) { + router.replace('/auth/login') + return + } + Promise.all([ + fetch(`${API}/api/auth/user/`, { + headers: { Authorization: `Bearer ${token}` }, + }), + fetch(`${API}/api/groups/`, { + headers: { Authorization: `Bearer ${token}` }, + }), + ]) + .then(async ([uRes, gRes]) => { + if (!uRes.ok) throw new Error('Не удалось получить профиль') + if (!gRes.ok) throw new Error('Не удалось загрузить группы') + const [u, g] = await Promise.all([uRes.json(), gRes.json()]) + setUser(u) + setGroups(g) + }) + .catch((err) => setError((err as Error).message)) + .finally(() => setLoading(false)) + }, [router, API, token]) + + if (loading) return
Загрузка...
+ if (error) return
{error}
+ + // закрыть модалку + const closeModal = () => { + setModalType(null) + setCurrentGroup(null) + setCurrentLink(null) + setFormValue({}) + } + + // === Группы === + async function handleGroupSubmit() { + if (!modalType) return + const isNew = modalType === 'addGroup' + const url = isNew + ? `${API}/api/groups/` + : `${API}/api/groups/${currentGroup!.id}/` + const method = isNew ? 'POST' : 'PUT' + const res = await fetch(url, { + method, + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify({ name: formValue.name }), + }) + if (res.ok) { + const grp = await res.json() + setGroups((prev) => + isNew + ? [...prev, { ...grp, links: [] }] + : prev.map((g) => (g.id === grp.id ? { ...g, name: grp.name } : g)) + ) + closeModal() + } else { + alert('Ошибка при сохранении группы') + } + } + + async function handleGroupDelete() { + if (!currentGroup) return + const res = await fetch(`${API}/api/groups/${currentGroup.id}/`, { + method: 'DELETE', + headers: { Authorization: `Bearer ${token}` }, + }) + if (res.ok) { + setGroups((prev) => prev.filter((g) => g.id !== currentGroup.id)) + closeModal() + } else { + alert('Ошибка при удалении группы') + } + } + + // === Ссылки === + async function handleLinkSubmit() { + if (!currentGroup) return + const isEdit = modalType === 'editLink' + const url = isEdit + ? `${API}/api/links/${currentLink!.id}/` + : `${API}/api/links/` + const method = isEdit ? 'PUT' : 'POST' + const payload = { + title: formValue.name, + url: formValue.url, + group: currentGroup.id, + } + const res = await fetch(url, { + method, + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify(payload), + }) + if (res.ok) { + const linkData = await res.json() + setGroups((prev) => + prev.map((g) => + g.id === currentGroup.id + ? { + ...g, + links: isEdit + ? g.links.map((l) => (l.id === linkData.id ? linkData : l)) + : [...g.links, linkData], + } + : g + ) + ) + closeModal() + } else { + alert('Ошибка при сохранении ссылки') + } + } + + async function handleLinkDelete() { + if (!currentLink || !currentGroup) return + const res = await fetch(`${API}/api/links/${currentLink.id}/`, { + method: 'DELETE', + headers: { Authorization: `Bearer ${token}` }, + }) + if (res.ok) { + setGroups((prev) => + prev.map((g) => + g.id === currentGroup.id + ? { ...g, links: g.links.filter((l) => l.id !== currentLink.id) } + : g + ) + ) + closeModal() + } else { + alert('Ошибка при удалении ссылки') + } + } + + return ( +
+ {/* Профиль */} + {user && ( +
+
+ Avatar +
+
+ {user.full_name || user.username} +
+

{user.email}

+
+
+
+ )} + + {/* Заголовок с кнопкой «Добавить группу» */} +
+

Группы ссылок

+ +
+ + {/* Список групп (аккордеон) */} + {groups.map((group) => ( + +
+
+
+ {/* Редактировать имя группы */} + { + e.preventDefault() + setCurrentGroup(group) + setFormValue({ name: group.name }) + setModalType('editGroup') + }} + > + + + {/* Открыть/закрыть аккордеон */} + + setGroups((pg) => + pg.map((g) => + g.id === group.id + ? { ...g, _open: !g._open } + : g + ) + ) + } + > + {group.name}{' '} + + {group.links.length} + + +
+
+ {/* Добавить ссылку */} + + {/* Удалить группу */} + +
+
+ {/* Ссылки в раскрытом состоянии */} + {group._open && ( +
    + {group.links.map((link) => ( +
  • + + {link.title} + +
    + + +
    +
  • + ))} +
+ )} +
+
+ ))} + + {/* Универсальная модалка */} + {modalType && ( + + {/* Группа: добавить/редактировать */} + {(modalType === 'addGroup' || modalType === 'editGroup') && ( + <> +
+ {modalType === 'addGroup' ? 'Новая группа' : 'Редактировать группу'} +
+ + setFormValue({ ...formValue, name: e.target.value }) + } + /> + + + )} + {/* Подтверждение удаления группы */} + {modalType === 'deleteGroup' && ( + <> +
Удалить группу?
+

Группа «{currentGroup?.name}» будет удалена навсегда.

+ + + + )} + {/* Ссылка: добавить/редактировать */} + {(modalType === 'addLink' || modalType === 'editLink') && ( + <> +
{modalType === 'addLink' ? 'Новая ссылка' : 'Редактировать ссылку'}
+ + setFormValue({ ...formValue, name: e.target.value }) + } + /> + + setFormValue({ ...formValue, url: e.target.value }) + } + /> + + + )} + {/* Подтверждение удаления ссылки */} + {modalType === 'deleteLink' && ( + <> +
Удалить ссылку?
+

Ссылка «{currentLink?.title}» будет удалена.

+ + + + )} +
+ )} +
+ ) +} diff --git a/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507140312.tsx b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507140312.tsx new file mode 100644 index 0000000..d362e72 --- /dev/null +++ b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507140312.tsx @@ -0,0 +1,638 @@ +// 'use client' + +// import React, { useEffect, useState, Fragment } from 'react' +// import { useRouter } from 'next/navigation' +// import Image from 'next/image' +// import { Modal } from '../../components/modal' // Модалка из примера выше + +// interface UserProfile { +// id: number +// username: string +// email: string +// full_name: string +// bio?: string +// avatar: string +// last_login: string +// date_joined: string +// } + +// interface LinkItem { +// id: number +// title: string +// url: string +// icon?: string +// } + +// interface Group { +// id: number +// name: string +// image?: string +// links: LinkItem[] +// _open?: boolean // флаг аккордеона +// } + +// type ModalType = +// | 'addGroup' +// | 'editGroup' +// | 'deleteGroup' +// | 'addLink' +// | 'editLink' +// | 'deleteLink' +// | null + +// export default function DashboardPage() { +// const router = useRouter() +// const API = process.env.NEXT_PUBLIC_API_URL +// const token = typeof window !== 'undefined' ? localStorage.getItem('token') : null + +// const [user, setUser] = useState(null) +// const [groups, setGroups] = useState([]) +// const [loading, setLoading] = useState(true) +// const [error, setError] = useState(null) + +// // для модалки +// const [modalType, setModalType] = useState(null) +// const [currentGroup, setCurrentGroup] = useState(null) +// const [currentLink, setCurrentLink] = useState(null) +// const [formValue, setFormValue] = useState<{ name?: string; url?: string }>({}) + +// // загрузка пользователя и групп +// useEffect(() => { +// if (!token) { +// router.replace('/auth/login') +// return +// } +// Promise.all([ +// fetch(`${API}/api/auth/user/`, { +// headers: { Authorization: `Bearer ${token}` }, +// }), +// fetch(`${API}/api/groups/`, { +// headers: { Authorization: `Bearer ${token}` }, +// }), +// ]) +// .then(async ([uRes, gRes]) => { +// if (!uRes.ok) throw new Error('Не удалось получить профиль') +// if (!gRes.ok) throw new Error('Не удалось загрузить группы') +// const [u, g] = await Promise.all([uRes.json(), gRes.json()]) +// setUser(u) +// setGroups(g) +// }) +// .catch((err) => setError((err as Error).message)) +// .finally(() => setLoading(false)) +// }, [router, API, token]) + +// if (loading) return
Загрузка...
+// if (error) return
{error}
+ +// // закрыть модалку +// const closeModal = () => { +// setModalType(null) +// setCurrentGroup(null) +// setCurrentLink(null) +// setFormValue({}) +// } + +// // === Группы === +// async function handleGroupSubmit() { +// if (!modalType) return +// const isNew = modalType === 'addGroup' +// const url = isNew +// ? `${API}/api/groups/` +// : `${API}/api/groups/${currentGroup!.id}/` +// const method = isNew ? 'POST' : 'PUT' +// const res = await fetch(url, { +// method, +// headers: { +// 'Content-Type': 'application/json', +// Authorization: `Bearer ${token}`, +// }, +// body: JSON.stringify({ name: formValue.name }), +// }) +// if (res.ok) { +// const grp = await res.json() +// setGroups((prev) => +// isNew +// ? [...prev, { ...grp, links: [] }] +// : prev.map((g) => (g.id === grp.id ? { ...g, name: grp.name } : g)) +// ) +// closeModal() +// } else { +// alert('Ошибка при сохранении группы') +// } +// } + +// async function handleGroupDelete() { +// if (!currentGroup) return +// const res = await fetch(`${API}/api/groups/${currentGroup.id}/`, { +// method: 'DELETE', +// headers: { Authorization: `Bearer ${token}` }, +// }) +// if (res.ok) { +// setGroups((prev) => prev.filter((g) => g.id !== currentGroup.id)) +// closeModal() +// } else { +// alert('Ошибка при удалении группы') +// } +// } + +// // === Ссылки === +// async function handleLinkSubmit() { +// if (!currentGroup) return +// const isEdit = modalType === 'editLink' +// const url = isEdit +// ? `${API}/api/links/${currentLink!.id}/` +// : `${API}/api/links/` +// const method = isEdit ? 'PUT' : 'POST' +// const payload = { +// title: formValue.name, +// url: formValue.url, +// group: currentGroup.id, +// } +// const res = await fetch(url, { +// method, +// headers: { +// 'Content-Type': 'application/json', +// Authorization: `Bearer ${token}`, +// }, +// body: JSON.stringify(payload), +// }) +// if (res.ok) { +// const linkData = await res.json() +// setGroups((prev) => +// prev.map((g) => +// g.id === currentGroup.id +// ? { +// ...g, +// links: isEdit +// ? g.links.map((l) => (l.id === linkData.id ? linkData : l)) +// : [...g.links, linkData], +// } +// : g +// ) +// ) +// closeModal() +// } else { +// alert('Ошибка при сохранении ссылки') +// } +// } + +// async function handleLinkDelete() { +// if (!currentLink || !currentGroup) return +// const res = await fetch(`${API}/api/links/${currentLink.id}/`, { +// method: 'DELETE', +// headers: { Authorization: `Bearer ${token}` }, +// }) +// if (res.ok) { +// setGroups((prev) => +// prev.map((g) => +// g.id === currentGroup.id +// ? { ...g, links: g.links.filter((l) => l.id !== currentLink.id) } +// : g +// ) +// ) +// closeModal() +// } else { +// alert('Ошибка при удалении ссылки') +// } +// } + +// return ( +//
+// {/* Профиль */} +// {user && ( +//
+//
+// Avatar +//
+//
+// {user.full_name || user.username} +//
+//

{user.email}

+//
+//
+//
+// )} + +// {/* Заголовок с кнопкой «Добавить группу» */} +//
+//

Группы ссылок

+// +//
+ +// {/* Список групп (аккордеон) */} +// {groups.map((group) => ( +// +//
+//
+//
+// {/* Редактировать имя группы */} +// { +// e.preventDefault() +// setCurrentGroup(group) +// setFormValue({ name: group.name }) +// setModalType('editGroup') +// }} +// > +// +// +// {/* Открыть/закрыть аккордеон */} +// +// setGroups((pg) => +// pg.map((g) => +// g.id === group.id +// ? { ...g, _open: !g._open } +// : g +// ) +// ) +// } +// > +// {group.name}{' '} +// +// {group.links.length} +// +// +//
+//
+// {/* Добавить ссылку */} +// +// {/* Удалить группу */} +// +//
+//
+// {/* Ссылки в раскрытом состоянии */} +// {group._open && ( +//
    +// {group.links.map((link) => ( +//
  • +// +// {link.title} +// +//
    +// +// +//
    +//
  • +// ))} +//
+// )} +//
+//
+// ))} + +// {/* Универсальная модалка */} +// {modalType && ( +// +// {/* Группа: добавить/редактировать */} +// {(modalType === 'addGroup' || modalType === 'editGroup') && ( +// <> +//
+// {modalType === 'addGroup' ? 'Новая группа' : 'Редактировать группу'} +//
+// +// setFormValue({ ...formValue, name: e.target.value }) +// } +// /> +// +// +// )} +// {/* Подтверждение удаления группы */} +// {modalType === 'deleteGroup' && ( +// <> +//
Удалить группу?
+//

Группа «{currentGroup?.name}» будет удалена навсегда.

+// +// +// +// )} +// {/* Ссылка: добавить/редактировать */} +// {(modalType === 'addLink' || modalType === 'editLink') && ( +// <> +//
{modalType === 'addLink' ? 'Новая ссылка' : 'Редактировать ссылку'}
+// +// setFormValue({ ...formValue, name: e.target.value }) +// } +// /> +// +// setFormValue({ ...formValue, url: e.target.value }) +// } +// /> +// +// +// )} +// {/* Подтверждение удаления ссылки */} +// {modalType === 'deleteLink' && ( +// <> +//
Удалить ссылку?
+//

Ссылка «{currentLink?.title}» будет удалена.

+// +// +// +// )} +//
+// )} +//
+// ) +// } + +// src/app/(protected)/dashboard/page.tsx +'use client' + +import React, { useEffect, useState, Fragment } from 'react' +import { useRouter } from 'next/navigation' +import Link from 'next/link' +import { ProfileCard } from '../components/ProfileCard' + +interface UserProfile { + id: number + username: string + email: string + full_name: string + bio?: string + avatar: string + last_login: string + date_joined: string +} + +interface LinkItem { + id: number + title: string + url: string + icon?: string + group: number +} + +interface Group { + id: number + name: string + icon?: string + // we'll always fill this in as an array: + links: LinkItem[] +} + +export default function DashboardPage() { + const router = useRouter() + const [user, setUser] = useState(null) + const [groups, setGroups] = useState([]) + const [expandedGroup, setExpandedGroup] = useState(null) + const [loading, setLoading] = useState(true) + const [error, setError] = useState(null) + + useEffect(() => { + const token = localStorage.getItem('token') + if (!token) { + router.push('/auth/login') + return + } + const API = process.env.NEXT_PUBLIC_API_URL ?? '' + + // 1) fetch profile + // 2) fetch all groups + // 3) fetch all links + Promise.all([ + fetch(`${API}/api/auth/user/`, { + headers: { Authorization: `Bearer ${token}` }, + }), + fetch(`${API}/api/groups/`, { + headers: { Authorization: `Bearer ${token}` }, + }), + fetch(`${API}/api/links/`, { + headers: { Authorization: `Bearer ${token}` }, + }), + ]) + .then(async ([uRes, gRes, lRes]) => { + if (!uRes.ok) throw new Error('Не удалось получить профиль') + if (!gRes.ok) throw new Error('Не удалось загрузить группы') + if (!lRes.ok) throw new Error('Не удалось загрузить ссылки') + + const userData = await uRes.json() + const groupsData = await gRes.json() + const linksData = await lRes.json() + + // group.links might not exist on the payload, so we build it: + const enrichedGroups: Group[] = groupsData.map((grp: any) => ({ + ...grp, + links: linksData.filter((link: LinkItem) => link.group === grp.id) + })) + + setUser(userData) + setGroups(enrichedGroups) + }) + .catch(err => setError((err as Error).message)) + .finally(() => setLoading(false)) + }, [router]) + + if (loading) { + return
Загрузка...
+ } + if (error) { + return
{error}
+ } + + // Подсчёт: всего групп и всего ссылок + const totalGroups = groups.length + const totalLinks = groups.reduce((sum, grp) => sum + grp.links.length, 0) + + return ( +
+ {user && ( + + )} + +
+
+
+
Группы ссылок
+ +
+ +
+ {groups.map((group) => ( + +
+
+ setExpandedGroup(expandedGroup === group.id ? null : group.id) + } + > + {group.icon && ( + {group.name} + )} + {group.name} + + {group.links.length} + +
+
+ + + +
+
+ + {expandedGroup === group.id && ( +
+
    + {group.links.map((link) => ( +
  • +
    + {link.icon && ( + {link.title} + )} + + {link.title} + +
    +
    + + +
    +
  • + ))} +
+
+ )} +
+ ))} +
+
+
+
+ ) +} diff --git a/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507140327.tsx b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507140327.tsx new file mode 100644 index 0000000..ec3b9e5 --- /dev/null +++ b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507140327.tsx @@ -0,0 +1,638 @@ +// 'use client' + +// import React, { useEffect, useState, Fragment } from 'react' +// import { useRouter } from 'next/navigation' +// import Image from 'next/image' +// import { Modal } from '../../components/modal' // Модалка из примера выше + +// interface UserProfile { +// id: number +// username: string +// email: string +// full_name: string +// bio?: string +// avatar: string +// last_login: string +// date_joined: string +// } + +// interface LinkItem { +// id: number +// title: string +// url: string +// icon?: string +// } + +// interface Group { +// id: number +// name: string +// image?: string +// links: LinkItem[] +// _open?: boolean // флаг аккордеона +// } + +// type ModalType = +// | 'addGroup' +// | 'editGroup' +// | 'deleteGroup' +// | 'addLink' +// | 'editLink' +// | 'deleteLink' +// | null + +// export default function DashboardPage() { +// const router = useRouter() +// const API = process.env.NEXT_PUBLIC_API_URL +// const token = typeof window !== 'undefined' ? localStorage.getItem('token') : null + +// const [user, setUser] = useState(null) +// const [groups, setGroups] = useState([]) +// const [loading, setLoading] = useState(true) +// const [error, setError] = useState(null) + +// // для модалки +// const [modalType, setModalType] = useState(null) +// const [currentGroup, setCurrentGroup] = useState(null) +// const [currentLink, setCurrentLink] = useState(null) +// const [formValue, setFormValue] = useState<{ name?: string; url?: string }>({}) + +// // загрузка пользователя и групп +// useEffect(() => { +// if (!token) { +// router.replace('/auth/login') +// return +// } +// Promise.all([ +// fetch(`${API}/api/auth/user/`, { +// headers: { Authorization: `Bearer ${token}` }, +// }), +// fetch(`${API}/api/groups/`, { +// headers: { Authorization: `Bearer ${token}` }, +// }), +// ]) +// .then(async ([uRes, gRes]) => { +// if (!uRes.ok) throw new Error('Не удалось получить профиль') +// if (!gRes.ok) throw new Error('Не удалось загрузить группы') +// const [u, g] = await Promise.all([uRes.json(), gRes.json()]) +// setUser(u) +// setGroups(g) +// }) +// .catch((err) => setError((err as Error).message)) +// .finally(() => setLoading(false)) +// }, [router, API, token]) + +// if (loading) return
Загрузка...
+// if (error) return
{error}
+ +// // закрыть модалку +// const closeModal = () => { +// setModalType(null) +// setCurrentGroup(null) +// setCurrentLink(null) +// setFormValue({}) +// } + +// // === Группы === +// async function handleGroupSubmit() { +// if (!modalType) return +// const isNew = modalType === 'addGroup' +// const url = isNew +// ? `${API}/api/groups/` +// : `${API}/api/groups/${currentGroup!.id}/` +// const method = isNew ? 'POST' : 'PUT' +// const res = await fetch(url, { +// method, +// headers: { +// 'Content-Type': 'application/json', +// Authorization: `Bearer ${token}`, +// }, +// body: JSON.stringify({ name: formValue.name }), +// }) +// if (res.ok) { +// const grp = await res.json() +// setGroups((prev) => +// isNew +// ? [...prev, { ...grp, links: [] }] +// : prev.map((g) => (g.id === grp.id ? { ...g, name: grp.name } : g)) +// ) +// closeModal() +// } else { +// alert('Ошибка при сохранении группы') +// } +// } + +// async function handleGroupDelete() { +// if (!currentGroup) return +// const res = await fetch(`${API}/api/groups/${currentGroup.id}/`, { +// method: 'DELETE', +// headers: { Authorization: `Bearer ${token}` }, +// }) +// if (res.ok) { +// setGroups((prev) => prev.filter((g) => g.id !== currentGroup.id)) +// closeModal() +// } else { +// alert('Ошибка при удалении группы') +// } +// } + +// // === Ссылки === +// async function handleLinkSubmit() { +// if (!currentGroup) return +// const isEdit = modalType === 'editLink' +// const url = isEdit +// ? `${API}/api/links/${currentLink!.id}/` +// : `${API}/api/links/` +// const method = isEdit ? 'PUT' : 'POST' +// const payload = { +// title: formValue.name, +// url: formValue.url, +// group: currentGroup.id, +// } +// const res = await fetch(url, { +// method, +// headers: { +// 'Content-Type': 'application/json', +// Authorization: `Bearer ${token}`, +// }, +// body: JSON.stringify(payload), +// }) +// if (res.ok) { +// const linkData = await res.json() +// setGroups((prev) => +// prev.map((g) => +// g.id === currentGroup.id +// ? { +// ...g, +// links: isEdit +// ? g.links.map((l) => (l.id === linkData.id ? linkData : l)) +// : [...g.links, linkData], +// } +// : g +// ) +// ) +// closeModal() +// } else { +// alert('Ошибка при сохранении ссылки') +// } +// } + +// async function handleLinkDelete() { +// if (!currentLink || !currentGroup) return +// const res = await fetch(`${API}/api/links/${currentLink.id}/`, { +// method: 'DELETE', +// headers: { Authorization: `Bearer ${token}` }, +// }) +// if (res.ok) { +// setGroups((prev) => +// prev.map((g) => +// g.id === currentGroup.id +// ? { ...g, links: g.links.filter((l) => l.id !== currentLink.id) } +// : g +// ) +// ) +// closeModal() +// } else { +// alert('Ошибка при удалении ссылки') +// } +// } + +// return ( +//
+// {/* Профиль */} +// {user && ( +//
+//
+// Avatar +//
+//
+// {user.full_name || user.username} +//
+//

{user.email}

+//
+//
+//
+// )} + +// {/* Заголовок с кнопкой «Добавить группу» */} +//
+//

Группы ссылок

+// +//
+ +// {/* Список групп (аккордеон) */} +// {groups.map((group) => ( +// +//
+//
+//
+// {/* Редактировать имя группы */} +// { +// e.preventDefault() +// setCurrentGroup(group) +// setFormValue({ name: group.name }) +// setModalType('editGroup') +// }} +// > +// +// +// {/* Открыть/закрыть аккордеон */} +// +// setGroups((pg) => +// pg.map((g) => +// g.id === group.id +// ? { ...g, _open: !g._open } +// : g +// ) +// ) +// } +// > +// {group.name}{' '} +// +// {group.links.length} +// +// +//
+//
+// {/* Добавить ссылку */} +// +// {/* Удалить группу */} +// +//
+//
+// {/* Ссылки в раскрытом состоянии */} +// {group._open && ( +//
    +// {group.links.map((link) => ( +//
  • +// +// {link.title} +// +//
    +// +// +//
    +//
  • +// ))} +//
+// )} +//
+//
+// ))} + +// {/* Универсальная модалка */} +// {modalType && ( +// +// {/* Группа: добавить/редактировать */} +// {(modalType === 'addGroup' || modalType === 'editGroup') && ( +// <> +//
+// {modalType === 'addGroup' ? 'Новая группа' : 'Редактировать группу'} +//
+// +// setFormValue({ ...formValue, name: e.target.value }) +// } +// /> +// +// +// )} +// {/* Подтверждение удаления группы */} +// {modalType === 'deleteGroup' && ( +// <> +//
Удалить группу?
+//

Группа «{currentGroup?.name}» будет удалена навсегда.

+// +// +// +// )} +// {/* Ссылка: добавить/редактировать */} +// {(modalType === 'addLink' || modalType === 'editLink') && ( +// <> +//
{modalType === 'addLink' ? 'Новая ссылка' : 'Редактировать ссылку'}
+// +// setFormValue({ ...formValue, name: e.target.value }) +// } +// /> +// +// setFormValue({ ...formValue, url: e.target.value }) +// } +// /> +// +// +// )} +// {/* Подтверждение удаления ссылки */} +// {modalType === 'deleteLink' && ( +// <> +//
Удалить ссылку?
+//

Ссылка «{currentLink?.title}» будет удалена.

+// +// +// +// )} +//
+// )} +//
+// ) +// } + +// src/app/(protected)/dashboard/page.tsx +'use client' + +import React, { useEffect, useState, Fragment } from 'react' +import { useRouter } from 'next/navigation' +import Link from 'next/link' +import { ProfileCard } from '../../components/ProfileCard' + +interface UserProfile { + id: number + username: string + email: string + full_name: string + bio?: string + avatar: string + last_login: string + date_joined: string +} + +interface LinkItem { + id: number + title: string + url: string + icon?: string + group: number +} + +interface Group { + id: number + name: string + icon?: string + // we'll always fill this in as an array: + links: LinkItem[] +} + +export default function DashboardPage() { + const router = useRouter() + const [user, setUser] = useState(null) + const [groups, setGroups] = useState([]) + const [expandedGroup, setExpandedGroup] = useState(null) + const [loading, setLoading] = useState(true) + const [error, setError] = useState(null) + + useEffect(() => { + const token = localStorage.getItem('token') + if (!token) { + router.push('/auth/login') + return + } + const API = process.env.NEXT_PUBLIC_API_URL ?? '' + + // 1) fetch profile + // 2) fetch all groups + // 3) fetch all links + Promise.all([ + fetch(`${API}/api/auth/user/`, { + headers: { Authorization: `Bearer ${token}` }, + }), + fetch(`${API}/api/groups/`, { + headers: { Authorization: `Bearer ${token}` }, + }), + fetch(`${API}/api/links/`, { + headers: { Authorization: `Bearer ${token}` }, + }), + ]) + .then(async ([uRes, gRes, lRes]) => { + if (!uRes.ok) throw new Error('Не удалось получить профиль') + if (!gRes.ok) throw new Error('Не удалось загрузить группы') + if (!lRes.ok) throw new Error('Не удалось загрузить ссылки') + + const userData = await uRes.json() + const groupsData = await gRes.json() + const linksData = await lRes.json() + + // group.links might not exist on the payload, so we build it: + const enrichedGroups: Group[] = groupsData.map((grp: any) => ({ + ...grp, + links: linksData.filter((link: LinkItem) => link.group === grp.id) + })) + + setUser(userData) + setGroups(enrichedGroups) + }) + .catch(err => setError((err as Error).message)) + .finally(() => setLoading(false)) + }, [router]) + + if (loading) { + return
Загрузка...
+ } + if (error) { + return
{error}
+ } + + // Подсчёт: всего групп и всего ссылок + const totalGroups = groups.length + const totalLinks = groups.reduce((sum, grp) => sum + grp.links.length, 0) + + return ( +
+ {user && ( + + )} + +
+
+
+
Группы ссылок
+ +
+ +
+ {groups.map((group) => ( + +
+
+ setExpandedGroup(expandedGroup === group.id ? null : group.id) + } + > + {group.icon && ( + {group.name} + )} + {group.name} + + {group.links.length} + +
+
+ + + +
+
+ + {expandedGroup === group.id && ( +
+
    + {group.links.map((link) => ( +
  • +
    + {link.icon && ( + {link.title} + )} + + {link.title} + +
    +
    + + +
    +
  • + ))} +
+
+ )} +
+ ))} +
+
+
+
+ ) +} diff --git a/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507140923.tsx b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507140923.tsx new file mode 100644 index 0000000..566a9be --- /dev/null +++ b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507140923.tsx @@ -0,0 +1,213 @@ +'use client' + +import React, { useEffect, useState, Fragment } from 'react' +import { useRouter } from 'next/navigation' +import Link from 'next/link' +import { ProfileCard } from '../../components/ProfileCard' + +interface UserProfile { + id: number + username: string + email: string + full_name: string + bio?: string + avatar: string + last_login: string + date_joined: string +} + +interface LinkItem { + id: number + title: string + url: string + icon?: string + group: number +} + +interface Group { + id: number + name: string + icon?: string + // we'll always fill this in as an array: + links: LinkItem[] +} + +export default function DashboardPage() { + const router = useRouter() + const [user, setUser] = useState(null) + const [groups, setGroups] = useState([]) + const [expandedGroup, setExpandedGroup] = useState(null) + const [loading, setLoading] = useState(true) + const [error, setError] = useState(null) + + useEffect(() => { + const token = localStorage.getItem('token') + if (!token) { + router.push('/auth/login') + return + } + const API = process.env.NEXT_PUBLIC_API_URL ?? '' + + // 1) fetch profile + // 2) fetch all groups + // 3) fetch all links + Promise.all([ + fetch(`${API}/api/auth/user/`, { + headers: { Authorization: `Bearer ${token}` }, + }), + fetch(`${API}/api/groups/`, { + headers: { Authorization: `Bearer ${token}` }, + }), + fetch(`${API}/api/links/`, { + headers: { Authorization: `Bearer ${token}` }, + }), + ]) + .then(async ([uRes, gRes, lRes]) => { + if (!uRes.ok) throw new Error('Не удалось получить профиль') + if (!gRes.ok) throw new Error('Не удалось загрузить группы') + if (!lRes.ok) throw new Error('Не удалось загрузить ссылки') + + const userData = await uRes.json() + const groupsData = await gRes.json() + const linksData = await lRes.json() + + // group.links might not exist on the payload, so we build it: + const enrichedGroups: Group[] = groupsData.map((grp: any) => ({ + ...grp, + links: linksData.filter((link: LinkItem) => link.group === grp.id) + })) + + setUser(userData) + setGroups(enrichedGroups) + }) + .catch(err => setError((err as Error).message)) + .finally(() => setLoading(false)) + }, [router]) + + if (loading) { + return
Загрузка...
+ } + if (error) { + return
{error}
+ } + + // Подсчёт: всего групп и всего ссылок + const totalGroups = groups.length + const totalLinks = groups.reduce((sum, grp) => sum + grp.links.length, 0) + + return ( +
+ {user && ( + + )} + +
+
+
+
Группы ссылок
+ +
+ +
+ {groups.map((group) => ( + +
+
+ setExpandedGroup(expandedGroup === group.id ? null : group.id) + } + > + {group.icon && ( + {group.name} + )} + {group.name} + + {group.links.length} + +
+
+ + + +
+
+ + {expandedGroup === group.id && ( +
+
    + {group.links.map((link) => ( +
  • +
    + {link.icon && ( + {link.title} + )} + + {link.title} + +
    +
    + + +
    +
  • + ))} +
+
+ )} +
+ ))} +
+
+
+
+ ) +} diff --git a/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507143628.tsx b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507143628.tsx new file mode 100644 index 0000000..dc92316 --- /dev/null +++ b/.history/frontend/linktree-frontend/src/app/(protected)/dashboard/page_20250507143628.tsx @@ -0,0 +1,390 @@ +'use client' + +import React, { useEffect, useState, Fragment } from 'react' +import { useRouter } from 'next/navigation' +import Link from 'next/link' +import Image from 'next/image' +import { ProfileCard } from '../../components/ProfileCard' + +interface UserProfile { + id: number + username: string + email: string + full_name: string + bio?: string + avatar: string + last_login: string + date_joined: string +} + +interface LinkItem { + id: number + title: string + url: string + icon?: string + group: number +} + +interface Group { + id: number + name: string + icon?: string + links: LinkItem[] +} + +export default function DashboardPage() { + const router = useRouter() + const [user, setUser] = useState(null) + const [groups, setGroups] = useState([]) + const [expandedGroup, setExpandedGroup] = useState(null) + const [loading, setLoading] = useState(true) + const [error, setError] = useState(null) + + // === Для модалок групп === + const [showGroupModal, setShowGroupModal] = useState(false) + const [groupModalMode, setGroupModalMode] = useState<'add' | 'edit'>('add') + const [editingGroup, setEditingGroup] = useState(null) + const [groupForm, setGroupForm] = useState<{ name: string; iconFile: File | null }>({ + name: '', + iconFile: null, + }) + + // === Для модалок ссылок === + const [showLinkModal, setShowLinkModal] = useState(false) + const [linkModalMode, setLinkModalMode] = useState<'add' | 'edit'>('add') + const [editingLink, setEditingLink] = useState(null) + const [currentGroupIdForLink, setCurrentGroupIdForLink] = useState(null) + const [linkForm, setLinkForm] = useState<{ title: string; url: string; iconFile: File | null }>({ + title: '', + url: '', + iconFile: null, + }) + + const API = process.env.NEXT_PUBLIC_API_URL ?? '' + + useEffect(() => { + const token = localStorage.getItem('token') + if (!token) { + router.push('/auth/login') + return + } + // загружаем профиль, группы и ссылки + Promise.all([ + fetch(`${API}/api/auth/user/`, { headers: { Authorization: `Bearer ${token}` } }), + fetch(`${API}/api/groups/`, { headers: { Authorization: `Bearer ${token}` } }), + fetch(`${API}/api/links/`, { headers: { Authorization: `Bearer ${token}` } }), + ]) + .then(async ([uRes, gRes, lRes]) => { + if (!uRes.ok) throw new Error('Не удалось получить профиль') + if (!gRes.ok) throw new Error('Не удалось загрузить группы') + if (!lRes.ok) throw new Error('Не удалось загрузить ссылки') + const userData = await uRes.json() + const groupsData = await gRes.json() + const linksData = await lRes.json() + + // «привязываем» ссылки к группам + const enrichedGroups: Group[] = groupsData.map((grp: any) => ({ + ...grp, + links: linksData.filter((link: LinkItem) => link.group === grp.id), + })) + setUser(userData) + setGroups(enrichedGroups) + }) + .catch(err => setError((err as Error).message)) + .finally(() => setLoading(false)) + }, [router]) + + // Перезагрузка списка групп и ссылок + async function reloadData() { + const token = localStorage.getItem('token')! + const [gRes, lRes] = await Promise.all([ + fetch(`${API}/api/groups/`, { headers: { Authorization: `Bearer ${token}` } }), + fetch(`${API}/api/links/`, { headers: { Authorization: `Bearer ${token}` } }), + ]) + const groupsData = await gRes.json() + const linksData = await lRes.json() + const enrichedGroups: Group[] = groupsData.map((grp: any) => ({ + ...grp, + links: linksData.filter((link: LinkItem) => link.group === grp.id), + })) + setGroups(enrichedGroups) + } + + // === Обработчики групп === + function openAddGroup() { + setGroupModalMode('add') + setGroupForm({ name: '', iconFile: null }) + setShowGroupModal(true) + } + function openEditGroup(grp: Group) { + setGroupModalMode('edit') + setEditingGroup(grp) + setGroupForm({ name: grp.name, iconFile: null }) + setShowGroupModal(true) + } + async function handleGroupSubmit() { + const token = localStorage.getItem('token')! + const fd = new FormData() + fd.append('name', groupForm.name) + if (groupForm.iconFile) fd.append('icon', groupForm.iconFile) + const url = groupModalMode === 'add' + ? `${API}/api/groups/` + : `${API}/api/groups/${editingGroup?.id}/` + const method = groupModalMode === 'add' ? 'POST' : 'PATCH' + await fetch(url, { + method, + headers: { Authorization: `Bearer ${token}` }, + body: fd, + }) + setShowGroupModal(false) + await reloadData() + } + async function handleDeleteGroup(grp: Group) { + if (!confirm(`Удалить группу "${grp.name}"?`)) return + const token = localStorage.getItem('token')! + await fetch(`${API}/api/groups/${grp.id}/`, { + method: 'DELETE', + headers: { Authorization: `Bearer ${token}` }, + }) + await reloadData() + } + + // === Обработчики ссылок === + function openAddLink(grp: Group) { + setLinkModalMode('add') + setCurrentGroupIdForLink(grp.id) + setLinkForm({ title: '', url: '', iconFile: null }) + setShowLinkModal(true) + } + function openEditLink(link: LinkItem) { + setLinkModalMode('edit') + setEditingLink(link) + setCurrentGroupIdForLink(link.group) + setLinkForm({ title: link.title, url: link.url, iconFile: null }) + setShowLinkModal(true) + } + async function handleLinkSubmit() { + const token = localStorage.getItem('token')! + const fd = new FormData() + fd.append('title', linkForm.title) + fd.append('url', linkForm.url) + if (linkForm.iconFile) fd.append('icon', linkForm.iconFile) + fd.append('group', String(currentGroupIdForLink)) + const url = linkModalMode === 'add' + ? `${API}/api/links/` + : `${API}/api/links/${editingLink?.id}/` + const method = linkModalMode === 'add' ? 'POST' : 'PATCH' + await fetch(url, { + method, + headers: { Authorization: `Bearer ${token}` }, + body: fd, + }) + setShowLinkModal(false) + await reloadData() + } + async function handleDeleteLink(link: LinkItem) { + if (!confirm(`Удалить ссылку "${link.title}"?`)) return + const token = localStorage.getItem('token')! + await fetch(`${API}/api/links/${link.id}/`, { + method: 'DELETE', + headers: { Authorization: `Bearer ${token}` }, + }) + await reloadData() + } + + if (loading) return
Загрузка...
+ if (error) return
{error}
+ + const totalGroups = groups.length + const totalLinks = groups.reduce((sum, grp) => sum + grp.links.length, 0) + + return ( +
+ {user && ( + + )} + +
+
+
+
Группы ссылок
+ +
+ +
+ {groups.map(group => ( + +
+
+ setExpandedGroup(expandedGroup === group.id ? null : group.id) + } + > + {group.icon && ( + {group.name} + )} + {group.name} + + {group.links.length} + +
+
+ + + +
+
+ + {expandedGroup === group.id && ( +
+
    + {group.links.map(link => ( +
  • +
    + {link.icon && ( + {link.title} + )} + + {link.title} + +
    +
    + + +
    +
  • + ))} +
+
+ )} +
+ ))} +
+
+
+ + {/* Модалка добавления/редактирования группы */} +
+
+
+
+
{groupModalMode === 'add' ? 'Добавить группу' : 'Редактировать группу'}
+
+
+
+ + setGroupForm(f => ({ ...f, name: e.target.value }))} + /> +
+
+ + setGroupForm(f => ({ ...f, iconFile: e.target.files?.[0] || null }))} + /> +
+
+
+ + +
+
+
+
+ + {/* Модалка добавления/редактирования ссылки */} +
+
+
+
+
{linkModalMode === 'add' ? 'Добавить ссылку' : 'Редактировать ссылку'}
+
+
+
+ + setLinkForm(f => ({ ...f, title: e.target.value }))} + /> +
+
+ + setLinkForm(f => ({ ...f, url: e.target.value }))} + /> +
+
+ + setLinkForm(f => ({ ...f, iconFile: e.target.files?.[0] || null }))} + /> +
+
+
+ + +
+
+
+
+
+ ) +} diff --git a/.history/frontend/linktree-frontend/src/app/(protected)/layout_20250507074711.tsx b/.history/frontend/linktree-frontend/src/app/(protected)/layout_20250507074711.tsx new file mode 100644 index 0000000..e69de29 diff --git a/.history/frontend/linktree-frontend/src/app/(protected)/layout_20250507074730.tsx b/.history/frontend/linktree-frontend/src/app/(protected)/layout_20250507074730.tsx new file mode 100644 index 0000000..07e952f --- /dev/null +++ b/.history/frontend/linktree-frontend/src/app/(protected)/layout_20250507074730.tsx @@ -0,0 +1,15 @@ +// src/app/(protected)/layout.tsx +"use client" +import { ReactNode } from "react" +import { Header } from "../components/Header" +import { Footer } from "../components/Footer" + +export default function ProtectedLayout({ children }: { children: ReactNode }) { + return ( + <> +
+
{children}
+
+ + ) +} diff --git a/.history/frontend/linktree-frontend/src/app/(protected)/layout_20250507075127.tsx b/.history/frontend/linktree-frontend/src/app/(protected)/layout_20250507075127.tsx new file mode 100644 index 0000000..254af9a --- /dev/null +++ b/.history/frontend/linktree-frontend/src/app/(protected)/layout_20250507075127.tsx @@ -0,0 +1,176 @@ +// src/app/layout.tsx +import type { Metadata } from "next"; +import { Geist, Geist_Mono } from "next/font/google"; +import "./globals.css"; +import { ReactNode } from "react"; +import Script from "next/script"; +import Link from "next/link"; +import Image from "next/image"; + +const geistSans = Geist({ + variable: "--font-geist-sans", + subsets: ["latin"], +}); + +const geistMono = Geist_Mono({ + variable: "--font-geist-mono", + subsets: ["latin"], +}); + +export const metadata: Metadata = { + title: "CatLink", + description: "Ваши ссылки в одном месте", +}; + +export default function RootLayout({ + children, +}: { + children: ReactNode; +}) { + return ( + + + + + + + + + + + + + + + + + {/* Header (fixed to top) */} + + + {/* Main content: добавляем дополнительный отступ сверху */} +
+ {children} +
+ {/* Footer (fixed to bottom) */} +
+
+
+
+
    +
  • + About +
  • +
  • +
  • + Contact +
  • +
  • +
  • + Terms of Use +
  • +
  • +
  • + Privacy Policy +
  • +
+

© CatLink 2025

+
+
+
    +
  • + + + +
  • +
  • + + + +
  • +
  • + + + +
  • +
+
+
+
+
+ + {/* Scripts */} + +
    + + */ +/* + * Queued Ajax requests. + * A new Ajax request won't be started until the previous queued + * request has finished. + */ + +/* + * Synced Ajax requests. + * The Ajax request will happen as soon as you call this method, but + * the callbacks (success/error/complete) won't fire until all previous + * synced requests have been completed. + */ + + +(function(jQuery) { + + var ajax = jQuery.ajax; + + var pendingRequests = {}; + + var synced = []; + var syncedData = []; + + jQuery.ajax = function(settings) { + // create settings for compatibility with ajaxSetup + settings = jQuery.extend(settings, jQuery.extend({}, jQuery.ajaxSettings, settings)); + + var port = settings.port; + + switch(settings.mode) { + case "abort": + if ( pendingRequests[port] ) { + pendingRequests[port].abort(); + } + return pendingRequests[port] = ajax.apply(this, arguments); + case "queue": + var _old = settings.complete; + settings.complete = function(){ + if ( _old ) + _old.apply( this, arguments ); + jQuery([ajax]).dequeue("ajax" + port );; + }; + + jQuery([ ajax ]).queue("ajax" + port, function(){ + ajax( settings ); + }); + return; + case "sync": + var pos = synced.length; + + synced[ pos ] = { + error: settings.error, + success: settings.success, + complete: settings.complete, + done: false + }; + + syncedData[ pos ] = { + error: [], + success: [], + complete: [] + }; + + settings.error = function(){ syncedData[ pos ].error = arguments; }; + settings.success = function(){ syncedData[ pos ].success = arguments; }; + settings.complete = function(){ + syncedData[ pos ].complete = arguments; + synced[ pos ].done = true; + + if ( pos == 0 || !synced[ pos-1 ] ) + for ( var i = pos; i < synced.length && synced[i].done; i++ ) { + if ( synced[i].error ) synced[i].error.apply( jQuery, syncedData[i].error ); + if ( synced[i].success ) synced[i].success.apply( jQuery, syncedData[i].success ); + if ( synced[i].complete ) synced[i].complete.apply( jQuery, syncedData[i].complete ); + + synced[i] = null; + syncedData[i] = null; + } + }; + } + return ajax.apply(this, arguments); + }; + +})((typeof window.jQuery == 'undefined' && typeof window.django != 'undefined') + ? django.jQuery + : jQuery +); diff --git a/.venv/lib/python3.10/site-packages/django_extensions/static/django_extensions/js/jquery.autocomplete.js b/.venv/lib/python3.10/site-packages/django_extensions/static/django_extensions/js/jquery.autocomplete.js new file mode 100644 index 0000000..77c1db6 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/django_extensions/static/django_extensions/js/jquery.autocomplete.js @@ -0,0 +1,1152 @@ +/** + * @fileOverview jquery-autocomplete, the jQuery Autocompleter + * @author Dylan Verheul + * @version 2.4.4 + * @requires jQuery 1.6+ + * @license MIT | GPL | Apache 2.0, see LICENSE.txt + * @see https://github.com/dyve/jquery-autocomplete + */ +(function($) { + "use strict"; + + /** + * jQuery autocomplete plugin + * @param {object|string} options + * @returns (object} jQuery object + */ + $.fn.autocomplete = function(options) { + var url; + if (arguments.length > 1) { + url = options; + options = arguments[1]; + options.url = url; + } else if (typeof options === 'string') { + url = options; + options = { url: url }; + } + var opts = $.extend({}, $.fn.autocomplete.defaults, options); + return this.each(function() { + var $this = $(this); + $this.data('autocompleter', new $.Autocompleter( + $this, + $.meta ? $.extend({}, opts, $this.data()) : opts + )); + }); + }; + + /** + * Store default options + * @type {object} + */ + $.fn.autocomplete.defaults = { + inputClass: 'acInput', + loadingClass: 'acLoading', + resultsClass: 'acResults', + selectClass: 'acSelect', + queryParamName: 'q', + extraParams: {}, + remoteDataType: false, + lineSeparator: '\n', + cellSeparator: '|', + minChars: 2, + maxItemsToShow: 10, + delay: 400, + useCache: true, + maxCacheLength: 10, + matchSubset: true, + matchCase: false, + matchInside: true, + mustMatch: false, + selectFirst: false, + selectOnly: false, + showResult: null, + preventDefaultReturn: 1, + preventDefaultTab: 0, + autoFill: false, + filterResults: true, + filter: true, + sortResults: true, + sortFunction: null, + onItemSelect: null, + onNoMatch: null, + onFinish: null, + matchStringConverter: null, + beforeUseConverter: null, + autoWidth: 'min-width', + useDelimiter: false, + delimiterChar: ',', + delimiterKeyCode: 188, + processData: null, + onError: null, + enabled: true + }; + + /** + * Sanitize result + * @param {Object} result + * @returns {Object} object with members value (String) and data (Object) + * @private + */ + var sanitizeResult = function(result) { + var value, data; + var type = typeof result; + if (type === 'string') { + value = result; + data = {}; + } else if ($.isArray(result)) { + value = result[0]; + data = result.slice(1); + } else if (type === 'object') { + value = result.value; + data = result.data; + } + value = String(value); + if (typeof data !== 'object') { + data = {}; + } + return { + value: value, + data: data + }; + }; + + /** + * Sanitize integer + * @param {mixed} value + * @param {Object} options + * @returns {Number} integer + * @private + */ + var sanitizeInteger = function(value, stdValue, options) { + var num = parseInt(value, 10); + options = options || {}; + if (isNaN(num) || (options.min && num < options.min)) { + num = stdValue; + } + return num; + }; + + /** + * Create partial url for a name/value pair + */ + var makeUrlParam = function(name, value) { + return [name, encodeURIComponent(value)].join('='); + }; + + /** + * Build an url + * @param {string} url Base url + * @param {object} [params] Dictionary of parameters + */ + var makeUrl = function(url, params) { + var urlAppend = []; + $.each(params, function(index, value) { + urlAppend.push(makeUrlParam(index, value)); + }); + if (urlAppend.length) { + url += url.indexOf('?') === -1 ? '?' : '&'; + url += urlAppend.join('&'); + } + return url; + }; + + /** + * Default sort filter + * @param {object} a + * @param {object} b + * @param {boolean} matchCase + * @returns {number} + */ + var sortValueAlpha = function(a, b, matchCase) { + a = String(a.value); + b = String(b.value); + if (!matchCase) { + a = a.toLowerCase(); + b = b.toLowerCase(); + } + if (a > b) { + return 1; + } + if (a < b) { + return -1; + } + return 0; + }; + + /** + * Parse data received in text format + * @param {string} text Plain text input + * @param {string} lineSeparator String that separates lines + * @param {string} cellSeparator String that separates cells + * @returns {array} Array of autocomplete data objects + */ + var plainTextParser = function(text, lineSeparator, cellSeparator) { + var results = []; + var i, j, data, line, value, lines; + // Be nice, fix linebreaks before splitting on lineSeparator + lines = String(text).replace('\r\n', '\n').split(lineSeparator); + for (i = 0; i < lines.length; i++) { + line = lines[i].split(cellSeparator); + data = []; + for (j = 0; j < line.length; j++) { + data.push(decodeURIComponent(line[j])); + } + value = data.shift(); + results.push({ value: value, data: data }); + } + return results; + }; + + /** + * Autocompleter class + * @param {object} $elem jQuery object with one input tag + * @param {object} options Settings + * @constructor + */ + $.Autocompleter = function($elem, options) { + + /** + * Assert parameters + */ + if (!$elem || !($elem instanceof $) || $elem.length !== 1 || $elem.get(0).tagName.toUpperCase() !== 'INPUT') { + throw new Error('Invalid parameter for jquery.Autocompleter, jQuery object with one element with INPUT tag expected.'); + } + + /** + * @constant Link to this instance + * @type object + * @private + */ + var self = this; + + /** + * @property {object} Options for this instance + * @public + */ + this.options = options; + + /** + * @property object Cached data for this instance + * @private + */ + this.cacheData_ = {}; + + /** + * @property {number} Number of cached data items + * @private + */ + this.cacheLength_ = 0; + + /** + * @property {string} Class name to mark selected item + * @private + */ + this.selectClass_ = 'jquery-autocomplete-selected-item'; + + /** + * @property {number} Handler to activation timeout + * @private + */ + this.keyTimeout_ = null; + + /** + * @property {number} Handler to finish timeout + * @private + */ + this.finishTimeout_ = null; + + /** + * @property {number} Last key pressed in the input field (store for behavior) + * @private + */ + this.lastKeyPressed_ = null; + + /** + * @property {string} Last value processed by the autocompleter + * @private + */ + this.lastProcessedValue_ = null; + + /** + * @property {string} Last value selected by the user + * @private + */ + this.lastSelectedValue_ = null; + + /** + * @property {boolean} Is this autocompleter active (showing results)? + * @see showResults + * @private + */ + this.active_ = false; + + /** + * @property {boolean} Is this autocompleter allowed to finish on blur? + * @private + */ + this.finishOnBlur_ = true; + + /** + * Sanitize options + */ + this.options.minChars = sanitizeInteger(this.options.minChars, $.fn.autocomplete.defaults.minChars, { min: 0 }); + this.options.maxItemsToShow = sanitizeInteger(this.options.maxItemsToShow, $.fn.autocomplete.defaults.maxItemsToShow, { min: 0 }); + this.options.maxCacheLength = sanitizeInteger(this.options.maxCacheLength, $.fn.autocomplete.defaults.maxCacheLength, { min: 1 }); + this.options.delay = sanitizeInteger(this.options.delay, $.fn.autocomplete.defaults.delay, { min: 0 }); + if (this.options.preventDefaultReturn != 2) { + this.options.preventDefaultReturn = this.options.preventDefaultReturn ? 1 : 0; + } + if (this.options.preventDefaultTab != 2) { + this.options.preventDefaultTab = this.options.preventDefaultTab ? 1 : 0; + } + + /** + * Init DOM elements repository + */ + this.dom = {}; + + /** + * Store the input element we're attached to in the repository + */ + this.dom.$elem = $elem; + + /** + * Switch off the native autocomplete and add the input class + */ + this.dom.$elem.attr('autocomplete', 'off').addClass(this.options.inputClass); + + /** + * Create DOM element to hold results, and force absolute position + */ + this.dom.$results = $('
    ').hide().addClass(this.options.resultsClass).css({ + position: 'absolute' + }); + $('body').append(this.dom.$results); + + /** + * Attach keyboard monitoring to $elem + */ + $elem.keydown(function(e) { + self.lastKeyPressed_ = e.keyCode; + switch(self.lastKeyPressed_) { + + case self.options.delimiterKeyCode: // comma = 188 + if (self.options.useDelimiter && self.active_) { + self.selectCurrent(); + } + break; + + // ignore navigational & special keys + case 35: // end + case 36: // home + case 16: // shift + case 17: // ctrl + case 18: // alt + case 37: // left + case 39: // right + break; + + case 38: // up + e.preventDefault(); + if (self.active_) { + self.focusPrev(); + } else { + self.activate(); + } + return false; + + case 40: // down + e.preventDefault(); + if (self.active_) { + self.focusNext(); + } else { + self.activate(); + } + return false; + + case 9: // tab + if (self.active_) { + self.selectCurrent(); + if (self.options.preventDefaultTab) { + e.preventDefault(); + return false; + } + } + if (self.options.preventDefaultTab === 2) { + e.preventDefault(); + return false; + } + break; + + case 13: // return + if (self.active_) { + self.selectCurrent(); + if (self.options.preventDefaultReturn) { + e.preventDefault(); + return false; + } + } + if (self.options.preventDefaultReturn === 2) { + e.preventDefault(); + return false; + } + break; + + case 27: // escape + if (self.active_) { + e.preventDefault(); + self.deactivate(true); + return false; + } + break; + + default: + self.activate(); + + } + }); + + /** + * Attach paste event listener because paste may occur much later then keydown or even without a keydown at all + */ + $elem.on('paste', function() { + self.activate(); + }); + + /** + * Finish on blur event + * Use a timeout because instant blur gives race conditions + */ + var onBlurFunction = function() { + self.deactivate(true); + } + $elem.blur(function() { + if (self.finishOnBlur_) { + self.finishTimeout_ = setTimeout(onBlurFunction, 200); + } + }); + /** + * Catch a race condition on form submit + */ + $elem.parents('form').on('submit', onBlurFunction); + + }; + + /** + * Position output DOM elements + * @private + */ + $.Autocompleter.prototype.position = function() { + var offset = this.dom.$elem.offset(); + var height = this.dom.$results.outerHeight(); + var totalHeight = $(window).outerHeight(); + var inputBottom = offset.top + this.dom.$elem.outerHeight(); + var bottomIfDown = inputBottom + height; + // Set autocomplete results at the bottom of input + var position = {top: inputBottom, left: offset.left}; + if (bottomIfDown > totalHeight) { + // Try to set autocomplete results at the top of input + var topIfUp = offset.top - height; + if (topIfUp >= 0) { + position.top = topIfUp; + } + } + this.dom.$results.css(position); + }; + + /** + * Read from cache + * @private + */ + $.Autocompleter.prototype.cacheRead = function(filter) { + var filterLength, searchLength, search, maxPos, pos; + if (this.options.useCache) { + filter = String(filter); + filterLength = filter.length; + if (this.options.matchSubset) { + searchLength = 1; + } else { + searchLength = filterLength; + } + while (searchLength <= filterLength) { + if (this.options.matchInside) { + maxPos = filterLength - searchLength; + } else { + maxPos = 0; + } + pos = 0; + while (pos <= maxPos) { + search = filter.substr(0, searchLength); + if (this.cacheData_[search] !== undefined) { + return this.cacheData_[search]; + } + pos++; + } + searchLength++; + } + } + return false; + }; + + /** + * Write to cache + * @private + */ + $.Autocompleter.prototype.cacheWrite = function(filter, data) { + if (this.options.useCache) { + if (this.cacheLength_ >= this.options.maxCacheLength) { + this.cacheFlush(); + } + filter = String(filter); + if (this.cacheData_[filter] !== undefined) { + this.cacheLength_++; + } + this.cacheData_[filter] = data; + return this.cacheData_[filter]; + } + return false; + }; + + /** + * Flush cache + * @public + */ + $.Autocompleter.prototype.cacheFlush = function() { + this.cacheData_ = {}; + this.cacheLength_ = 0; + }; + + /** + * Call hook + * Note that all called hooks are passed the autocompleter object + * @param {string} hook + * @param data + * @returns Result of called hook, false if hook is undefined + */ + $.Autocompleter.prototype.callHook = function(hook, data) { + var f = this.options[hook]; + if (f && $.isFunction(f)) { + return f(data, this); + } + return false; + }; + + /** + * Set timeout to activate autocompleter + */ + $.Autocompleter.prototype.activate = function() { + if (!this.options.enabled) return; + var self = this; + if (this.keyTimeout_) { + clearTimeout(this.keyTimeout_); + } + this.keyTimeout_ = setTimeout(function() { + self.activateNow(); + }, this.options.delay); + }; + + /** + * Activate autocompleter immediately + */ + $.Autocompleter.prototype.activateNow = function() { + var value = this.beforeUseConverter(this.dom.$elem.val()); + if (value !== this.lastProcessedValue_ && value !== this.lastSelectedValue_) { + this.fetchData(value); + } + }; + + /** + * Get autocomplete data for a given value + * @param {string} value Value to base autocompletion on + * @private + */ + $.Autocompleter.prototype.fetchData = function(value) { + var self = this; + var processResults = function(results, filter) { + if (self.options.processData) { + results = self.options.processData(results); + } + self.showResults(self.filterResults(results, filter), filter); + }; + this.lastProcessedValue_ = value; + if (value.length < this.options.minChars) { + processResults([], value); + } else if (this.options.data) { + processResults(this.options.data, value); + } else { + this.fetchRemoteData(value, function(remoteData) { + processResults(remoteData, value); + }); + } + }; + + /** + * Get remote autocomplete data for a given value + * @param {string} filter The filter to base remote data on + * @param {function} callback The function to call after data retrieval + * @private + */ + $.Autocompleter.prototype.fetchRemoteData = function(filter, callback) { + var data = this.cacheRead(filter); + if (data) { + callback(data); + } else { + var self = this; + var dataType = self.options.remoteDataType === 'json' ? 'json' : 'text'; + var ajaxCallback = function(data) { + var parsed = false; + if (data !== false) { + parsed = self.parseRemoteData(data); + self.cacheWrite(filter, parsed); + } + self.dom.$elem.removeClass(self.options.loadingClass); + callback(parsed); + }; + this.dom.$elem.addClass(this.options.loadingClass); + $.ajax({ + url: this.makeUrl(filter), + success: ajaxCallback, + error: function(jqXHR, textStatus, errorThrown) { + if($.isFunction(self.options.onError)) { + self.options.onError(jqXHR, textStatus, errorThrown); + } else { + ajaxCallback(false); + } + }, + dataType: dataType + }); + } + }; + + /** + * Create or update an extra parameter for the remote request + * @param {string} name Parameter name + * @param {string} value Parameter value + * @public + */ + $.Autocompleter.prototype.setExtraParam = function(name, value) { + var index = $.trim(String(name)); + if (index) { + if (!this.options.extraParams) { + this.options.extraParams = {}; + } + if (this.options.extraParams[index] !== value) { + this.options.extraParams[index] = value; + this.cacheFlush(); + } + } + + return this; + }; + + /** + * Build the url for a remote request + * If options.queryParamName === false, append query to url instead of using a GET parameter + * @param {string} param The value parameter to pass to the backend + * @returns {string} The finished url with parameters + */ + $.Autocompleter.prototype.makeUrl = function(param) { + var self = this; + var url = this.options.url; + var params = $.extend({}, this.options.extraParams); + + if (this.options.queryParamName === false) { + url += encodeURIComponent(param); + } else { + params[this.options.queryParamName] = param; + } + + return makeUrl(url, params); + }; + + /** + * Parse data received from server + * @param remoteData Data received from remote server + * @returns {array} Parsed data + */ + $.Autocompleter.prototype.parseRemoteData = function(remoteData) { + var remoteDataType; + var data = remoteData; + if (this.options.remoteDataType === 'json') { + remoteDataType = typeof(remoteData); + switch (remoteDataType) { + case 'object': + data = remoteData; + break; + case 'string': + data = $.parseJSON(remoteData); + break; + default: + throw new Error("Unexpected remote data type: " + remoteDataType); + } + return data; + } + return plainTextParser(data, this.options.lineSeparator, this.options.cellSeparator); + }; + + /** + * Default filter for results + * @param {Object} result + * @param {String} filter + * @returns {boolean} Include this result + * @private + */ + $.Autocompleter.prototype.defaultFilter = function(result, filter) { + if (!result.value) { + return false; + } + if (this.options.filterResults) { + var pattern = this.matchStringConverter(filter); + var testValue = this.matchStringConverter(result.value); + if (!this.options.matchCase) { + pattern = pattern.toLowerCase(); + testValue = testValue.toLowerCase(); + } + var patternIndex = testValue.indexOf(pattern); + if (this.options.matchInside) { + return patternIndex > -1; + } else { + return patternIndex === 0; + } + } + return true; + }; + + /** + * Filter result + * @param {Object} result + * @param {String} filter + * @returns {boolean} Include this result + * @private + */ + $.Autocompleter.prototype.filterResult = function(result, filter) { + // No filter + if (this.options.filter === false) { + return true; + } + // Custom filter + if ($.isFunction(this.options.filter)) { + return this.options.filter(result, filter); + } + // Default filter + return this.defaultFilter(result, filter); + }; + + /** + * Filter results + * @param results + * @param filter + */ + $.Autocompleter.prototype.filterResults = function(results, filter) { + var filtered = []; + var i, result; + + for (i = 0; i < results.length; i++) { + result = sanitizeResult(results[i]); + if (this.filterResult(result, filter)) { + filtered.push(result); + } + } + if (this.options.sortResults) { + filtered = this.sortResults(filtered, filter); + } + if (this.options.maxItemsToShow > 0 && this.options.maxItemsToShow < filtered.length) { + filtered.length = this.options.maxItemsToShow; + } + return filtered; + }; + + /** + * Sort results + * @param results + * @param filter + */ + $.Autocompleter.prototype.sortResults = function(results, filter) { + var self = this; + var sortFunction = this.options.sortFunction; + if (!$.isFunction(sortFunction)) { + sortFunction = function(a, b, f) { + return sortValueAlpha(a, b, self.options.matchCase); + }; + } + results.sort(function(a, b) { + return sortFunction(a, b, filter, self.options); + }); + return results; + }; + + /** + * Convert string before matching + * @param s + * @param a + * @param b + */ + $.Autocompleter.prototype.matchStringConverter = function(s, a, b) { + var converter = this.options.matchStringConverter; + if ($.isFunction(converter)) { + s = converter(s, a, b); + } + return s; + }; + + /** + * Convert string before use + * @param {String} s + */ + $.Autocompleter.prototype.beforeUseConverter = function(s) { + s = this.getValue(s); + var converter = this.options.beforeUseConverter; + if ($.isFunction(converter)) { + s = converter(s); + } + return s; + }; + + /** + * Enable finish on blur event + */ + $.Autocompleter.prototype.enableFinishOnBlur = function() { + this.finishOnBlur_ = true; + }; + + /** + * Disable finish on blur event + */ + $.Autocompleter.prototype.disableFinishOnBlur = function() { + this.finishOnBlur_ = false; + }; + + /** + * Create a results item (LI element) from a result + * @param result + */ + $.Autocompleter.prototype.createItemFromResult = function(result) { + var self = this; + var $li = $('
  • '); + $li.html(this.showResult(result.value, result.data)); + $li.data({value: result.value, data: result.data}) + .click(function() { + self.selectItem($li); + }) + .mousedown(self.disableFinishOnBlur) + .mouseup(self.enableFinishOnBlur) + ; + return $li; + }; + + /** + * Get all items from the results list + * @param result + */ + $.Autocompleter.prototype.getItems = function() { + return $('>ul>li', this.dom.$results); + }; + + /** + * Show all results + * @param results + * @param filter + */ + $.Autocompleter.prototype.showResults = function(results, filter) { + var numResults = results.length; + var self = this; + var $ul = $('
      '); + var i, result, $li, autoWidth, first = false, $first = false; + + if (numResults) { + for (i = 0; i < numResults; i++) { + result = results[i]; + $li = this.createItemFromResult(result); + $ul.append($li); + if (first === false) { + first = String(result.value); + $first = $li; + $li.addClass(this.options.firstItemClass); + } + if (i === numResults - 1) { + $li.addClass(this.options.lastItemClass); + } + } + + this.dom.$results.html($ul).show(); + + // Always recalculate position since window size or + // input element location may have changed. + this.position(); + if (this.options.autoWidth) { + autoWidth = this.dom.$elem.outerWidth() - this.dom.$results.outerWidth() + this.dom.$results.width(); + this.dom.$results.css(this.options.autoWidth, autoWidth); + } + this.getItems().hover( + function() { self.focusItem(this); }, + function() { /* void */ } + ); + if (this.autoFill(first, filter) || this.options.selectFirst || (this.options.selectOnly && numResults === 1)) { + this.focusItem($first); + } + this.active_ = true; + } else { + this.hideResults(); + this.active_ = false; + } + }; + + $.Autocompleter.prototype.showResult = function(value, data) { + if ($.isFunction(this.options.showResult)) { + return this.options.showResult(value, data); + } else { + return $('

      ').text(value).html(); + } + }; + + $.Autocompleter.prototype.autoFill = function(value, filter) { + var lcValue, lcFilter, valueLength, filterLength; + if (this.options.autoFill && this.lastKeyPressed_ !== 8) { + lcValue = String(value).toLowerCase(); + lcFilter = String(filter).toLowerCase(); + valueLength = value.length; + filterLength = filter.length; + if (lcValue.substr(0, filterLength) === lcFilter) { + var d = this.getDelimiterOffsets(); + var pad = d.start ? ' ' : ''; // if there is a preceding delimiter + this.setValue( pad + value ); + var start = filterLength + d.start + pad.length; + var end = valueLength + d.start + pad.length; + this.selectRange(start, end); + return true; + } + } + return false; + }; + + $.Autocompleter.prototype.focusNext = function() { + this.focusMove(+1); + }; + + $.Autocompleter.prototype.focusPrev = function() { + this.focusMove(-1); + }; + + $.Autocompleter.prototype.focusMove = function(modifier) { + var $items = this.getItems(); + modifier = sanitizeInteger(modifier, 0); + if (modifier) { + for (var i = 0; i < $items.length; i++) { + if ($($items[i]).hasClass(this.selectClass_)) { + this.focusItem(i + modifier); + return; + } + } + } + this.focusItem(0); + }; + + $.Autocompleter.prototype.focusItem = function(item) { + var $item, $items = this.getItems(); + if ($items.length) { + $items.removeClass(this.selectClass_).removeClass(this.options.selectClass); + if (typeof item === 'number') { + if (item < 0) { + item = 0; + } else if (item >= $items.length) { + item = $items.length - 1; + } + $item = $($items[item]); + } else { + $item = $(item); + } + if ($item) { + $item.addClass(this.selectClass_).addClass(this.options.selectClass); + } + } + }; + + $.Autocompleter.prototype.selectCurrent = function() { + var $item = $('li.' + this.selectClass_, this.dom.$results); + if ($item.length === 1) { + this.selectItem($item); + } else { + this.deactivate(false); + } + }; + + $.Autocompleter.prototype.selectItem = function($li) { + var value = $li.data('value'); + var data = $li.data('data'); + var displayValue = this.displayValue(value, data); + var processedDisplayValue = this.beforeUseConverter(displayValue); + this.lastProcessedValue_ = processedDisplayValue; + this.lastSelectedValue_ = processedDisplayValue; + var d = this.getDelimiterOffsets(); + var delimiter = this.options.delimiterChar; + var elem = this.dom.$elem; + var extraCaretPos = 0; + if ( this.options.useDelimiter ) { + // if there is a preceding delimiter, add a space after the delimiter + if ( elem.val().substring(d.start-1, d.start) == delimiter && delimiter != ' ' ) { + displayValue = ' ' + displayValue; + } + // if there is not already a delimiter trailing this value, add it + if ( elem.val().substring(d.end, d.end+1) != delimiter && this.lastKeyPressed_ != this.options.delimiterKeyCode ) { + displayValue = displayValue + delimiter; + } else { + // move the cursor after the existing trailing delimiter + extraCaretPos = 1; + } + } + this.setValue(displayValue); + this.setCaret(d.start + displayValue.length + extraCaretPos); + this.callHook('onItemSelect', { value: value, data: data }); + this.deactivate(true); + elem.focus(); + }; + + $.Autocompleter.prototype.displayValue = function(value, data) { + if ($.isFunction(this.options.displayValue)) { + return this.options.displayValue(value, data); + } + return value; + }; + + $.Autocompleter.prototype.hideResults = function() { + this.dom.$results.hide(); + }; + + $.Autocompleter.prototype.deactivate = function(finish) { + if (this.finishTimeout_) { + clearTimeout(this.finishTimeout_); + } + if (this.keyTimeout_) { + clearTimeout(this.keyTimeout_); + } + if (finish) { + if (this.lastProcessedValue_ !== this.lastSelectedValue_) { + if (this.options.mustMatch) { + this.setValue(''); + } + this.callHook('onNoMatch'); + } + if (this.active_) { + this.callHook('onFinish'); + } + this.lastKeyPressed_ = null; + this.lastProcessedValue_ = null; + this.lastSelectedValue_ = null; + this.active_ = false; + } + this.hideResults(); + }; + + $.Autocompleter.prototype.selectRange = function(start, end) { + var input = this.dom.$elem.get(0); + if (input.setSelectionRange) { + input.focus(); + input.setSelectionRange(start, end); + } else if (input.createTextRange) { + var range = input.createTextRange(); + range.collapse(true); + range.moveEnd('character', end); + range.moveStart('character', start); + range.select(); + } + }; + + /** + * Move caret to position + * @param {Number} pos + */ + $.Autocompleter.prototype.setCaret = function(pos) { + this.selectRange(pos, pos); + }; + + /** + * Get caret position + */ + $.Autocompleter.prototype.getCaret = function() { + var $elem = this.dom.$elem; + var elem = $elem[0]; + var val, selection, range, start, end, stored_range; + if (elem.createTextRange) { // IE + selection = document.selection; + if (elem.tagName.toLowerCase() != 'textarea') { + val = $elem.val(); + range = selection.createRange().duplicate(); + range.moveEnd('character', val.length); + if (range.text === '') { + start = val.length; + } else { + start = val.lastIndexOf(range.text); + } + range = selection.createRange().duplicate(); + range.moveStart('character', -val.length); + end = range.text.length; + } else { + range = selection.createRange(); + stored_range = range.duplicate(); + stored_range.moveToElementText(elem); + stored_range.setEndPoint('EndToEnd', range); + start = stored_range.text.length - range.text.length; + end = start + range.text.length; + } + } else { + start = $elem[0].selectionStart; + end = $elem[0].selectionEnd; + } + return { + start: start, + end: end + }; + }; + + /** + * Set the value that is currently being autocompleted + * @param {String} value + */ + $.Autocompleter.prototype.setValue = function(value) { + if ( this.options.useDelimiter ) { + // set the substring between the current delimiters + var val = this.dom.$elem.val(); + var d = this.getDelimiterOffsets(); + var preVal = val.substring(0, d.start); + var postVal = val.substring(d.end); + value = preVal + value + postVal; + } + this.dom.$elem.val(value); + }; + + /** + * Get the value currently being autocompleted + * @param {String} value + */ + $.Autocompleter.prototype.getValue = function(value) { + if ( this.options.useDelimiter ) { + var d = this.getDelimiterOffsets(); + return value.substring(d.start, d.end).trim(); + } else { + return value; + } + }; + + /** + * Get the offsets of the value currently being autocompleted + */ + $.Autocompleter.prototype.getDelimiterOffsets = function() { + var val = this.dom.$elem.val(); + if ( this.options.useDelimiter ) { + var preCaretVal = val.substring(0, this.getCaret().start); + var start = preCaretVal.lastIndexOf(this.options.delimiterChar) + 1; + var postCaretVal = val.substring(this.getCaret().start); + var end = postCaretVal.indexOf(this.options.delimiterChar); + if ( end == -1 ) end = val.length; + end += this.getCaret().start; + } else { + start = 0; + end = val.length; + } + return { + start: start, + end: end + }; + }; + +})((typeof window.jQuery == 'undefined' && typeof window.django != 'undefined')? django.jQuery : jQuery); diff --git a/.venv/lib/python3.10/site-packages/django_extensions/static/django_extensions/js/jquery.bgiframe.js b/.venv/lib/python3.10/site-packages/django_extensions/static/django_extensions/js/jquery.bgiframe.js new file mode 100644 index 0000000..1a452ba --- /dev/null +++ b/.venv/lib/python3.10/site-packages/django_extensions/static/django_extensions/js/jquery.bgiframe.js @@ -0,0 +1,39 @@ +/*! Copyright (c) 2010 Brandon Aaron (http://brandon.aaron.sh/) + * Licensed under the MIT License (LICENSE.txt). + * + * Version 2.1.2 + */ + +(function($){ + +$.fn.bgiframe = ($.browser.msie && /msie 6\.0/i.test(navigator.userAgent) ? function(s) { + s = $.extend({ + top : 'auto', // auto == .currentStyle.borderTopWidth + left : 'auto', // auto == .currentStyle.borderLeftWidth + width : 'auto', // auto == offsetWidth + height : 'auto', // auto == offsetHeight + opacity : true, + src : 'javascript:false;' + }, s); + var html = '\n *
    • \n *\n * */\n\n.aspect-ratio {\n height: 0;\n position: relative;\n}\n\n.aspect-ratio--16x9 { padding-bottom: 56.25%; }\n.aspect-ratio--9x16 { padding-bottom: 177.77%; }\n\n.aspect-ratio--4x3 { padding-bottom: 75%; }\n.aspect-ratio--3x4 { padding-bottom: 133.33%; }\n\n.aspect-ratio--6x4 { padding-bottom: 66.6%; }\n.aspect-ratio--4x6 { padding-bottom: 150%; }\n\n.aspect-ratio--8x5 { padding-bottom: 62.5%; }\n.aspect-ratio--5x8 { padding-bottom: 160%; }\n\n.aspect-ratio--7x5 { padding-bottom: 71.42%; }\n.aspect-ratio--5x7 { padding-bottom: 140%; }\n\n.aspect-ratio--1x1 { padding-bottom: 100%; }\n\n.aspect-ratio--object {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 100;\n}\n\n@media #{$breakpoint-not-small}{\n .aspect-ratio-ns {\n height: 0;\n position: relative;\n }\n .aspect-ratio--16x9-ns { padding-bottom: 56.25%; }\n .aspect-ratio--9x16-ns { padding-bottom: 177.77%; }\n .aspect-ratio--4x3-ns { padding-bottom: 75%; }\n .aspect-ratio--3x4-ns { padding-bottom: 133.33%; }\n .aspect-ratio--6x4-ns { padding-bottom: 66.6%; }\n .aspect-ratio--4x6-ns { padding-bottom: 150%; }\n .aspect-ratio--8x5-ns { padding-bottom: 62.5%; }\n .aspect-ratio--5x8-ns { padding-bottom: 160%; }\n .aspect-ratio--7x5-ns { padding-bottom: 71.42%; }\n .aspect-ratio--5x7-ns { padding-bottom: 140%; }\n .aspect-ratio--1x1-ns { padding-bottom: 100%; }\n .aspect-ratio--object-ns {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 100;\n }\n}\n\n@media #{$breakpoint-medium}{\n .aspect-ratio-m {\n height: 0;\n position: relative;\n }\n .aspect-ratio--16x9-m { padding-bottom: 56.25%; }\n .aspect-ratio--9x16-m { padding-bottom: 177.77%; }\n .aspect-ratio--4x3-m { padding-bottom: 75%; }\n .aspect-ratio--3x4-m { padding-bottom: 133.33%; }\n .aspect-ratio--6x4-m { padding-bottom: 66.6%; }\n .aspect-ratio--4x6-m { padding-bottom: 150%; }\n .aspect-ratio--8x5-m { padding-bottom: 62.5%; }\n .aspect-ratio--5x8-m { padding-bottom: 160%; }\n .aspect-ratio--7x5-m { padding-bottom: 71.42%; }\n .aspect-ratio--5x7-m { padding-bottom: 140%; }\n .aspect-ratio--1x1-m { padding-bottom: 100%; }\n .aspect-ratio--object-m {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 100;\n }\n}\n\n@media #{$breakpoint-large}{\n .aspect-ratio-l {\n height: 0;\n position: relative;\n }\n .aspect-ratio--16x9-l { padding-bottom: 56.25%; }\n .aspect-ratio--9x16-l { padding-bottom: 177.77%; }\n .aspect-ratio--4x3-l { padding-bottom: 75%; }\n .aspect-ratio--3x4-l { padding-bottom: 133.33%; }\n .aspect-ratio--6x4-l { padding-bottom: 66.6%; }\n .aspect-ratio--4x6-l { padding-bottom: 150%; }\n .aspect-ratio--8x5-l { padding-bottom: 62.5%; }\n .aspect-ratio--5x8-l { padding-bottom: 160%; }\n .aspect-ratio--7x5-l { padding-bottom: 71.42%; }\n .aspect-ratio--5x7-l { padding-bottom: 140%; }\n .aspect-ratio--1x1-l { padding-bottom: 100%; }\n .aspect-ratio--object-l {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 100;\n }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n IMAGES\n Docs: http://tachyons.io/docs/elements/images/\n\n*/\n\n/* Responsive images! */\n\nimg { max-width: 100%; }\n\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n BACKGROUND SIZE\n Docs: http://tachyons.io/docs/themes/background-size/\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n/*\n Often used in combination with background image set as an inline style\n on an html element.\n*/\n\n .cover { background-size: cover!important; }\n .contain { background-size: contain!important; }\n\n@media #{$breakpoint-not-small} {\n .cover-ns { background-size: cover!important; }\n .contain-ns { background-size: contain!important; }\n}\n\n@media #{$breakpoint-medium} {\n .cover-m { background-size: cover!important; }\n .contain-m { background-size: contain!important; }\n}\n\n@media #{$breakpoint-large} {\n .cover-l { background-size: cover!important; }\n .contain-l { background-size: contain!important; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n BACKGROUND POSITION\n\n Base:\n bg = background\n\n Modifiers:\n -center = center center\n -top = top center\n -right = center right\n -bottom = bottom center\n -left = center left\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n */\n\n.bg-center { \n background-repeat: no-repeat;\n background-position: center center; \n}\n\n.bg-top { \n background-repeat: no-repeat; \n background-position: top center; \n}\n\n.bg-right { \n background-repeat: no-repeat; \n background-position: center right; \n}\n\n.bg-bottom { \n background-repeat: no-repeat; \n background-position: bottom center; \n}\n\n.bg-left { \n background-repeat: no-repeat; \n background-position: center left; \n}\n\n@media #{$breakpoint-not-small} {\n .bg-center-ns { \n background-repeat: no-repeat;\n background-position: center center; \n }\n\n .bg-top-ns { \n background-repeat: no-repeat; \n background-position: top center; \n }\n\n .bg-right-ns { \n background-repeat: no-repeat; \n background-position: center right; \n }\n\n .bg-bottom-ns { \n background-repeat: no-repeat; \n background-position: bottom center; \n }\n\n .bg-left-ns { \n background-repeat: no-repeat; \n background-position: center left; \n }\n}\n\n@media #{$breakpoint-medium} {\n .bg-center-m { \n background-repeat: no-repeat;\n background-position: center center; \n }\n\n .bg-top-m { \n background-repeat: no-repeat; \n background-position: top center; \n }\n\n .bg-right-m { \n background-repeat: no-repeat; \n background-position: center right; \n }\n\n .bg-bottom-m { \n background-repeat: no-repeat; \n background-position: bottom center; \n }\n\n .bg-left-m { \n background-repeat: no-repeat; \n background-position: center left; \n }\n}\n\n@media #{$breakpoint-large} {\n .bg-center-l { \n background-repeat: no-repeat;\n background-position: center center; \n }\n\n .bg-top-l { \n background-repeat: no-repeat; \n background-position: top center; \n }\n\n .bg-right-l { \n background-repeat: no-repeat; \n background-position: center right; \n }\n\n .bg-bottom-l { \n background-repeat: no-repeat; \n background-position: bottom center; \n }\n\n .bg-left-l { \n background-repeat: no-repeat; \n background-position: center left; \n }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n OUTLINES\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n.outline { outline: 1px solid; }\n.outline-transparent { outline: 1px solid transparent; }\n.outline-0 { outline: 0; }\n\n@media #{$breakpoint-not-small} {\n .outline-ns { outline: 1px solid; }\n .outline-transparent-ns { outline: 1px solid transparent; }\n .outline-0-ns { outline: 0; }\n}\n\n@media #{$breakpoint-medium} {\n .outline-m { outline: 1px solid; }\n .outline-transparent-m { outline: 1px solid transparent; }\n .outline-0-m { outline: 0; }\n}\n\n@media #{$breakpoint-large} {\n .outline-l { outline: 1px solid; }\n .outline-transparent-l { outline: 1px solid transparent; }\n .outline-0-l { outline: 0; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n BORDERS\n Docs: http://tachyons.io/docs/themes/borders/\n\n Base:\n b = border\n\n Modifiers:\n a = all\n t = top\n r = right\n b = bottom\n l = left\n n = none\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n .ba { border-style: solid; border-width: 1px; }\n .bt { border-top-style: solid; border-top-width: 1px; }\n .br { border-right-style: solid; border-right-width: 1px; }\n .bb { border-bottom-style: solid; border-bottom-width: 1px; }\n .bl { border-left-style: solid; border-left-width: 1px; }\n .bn { border-style: none; border-width: 0; }\n\n\n@media #{$breakpoint-not-small} {\n .ba-ns { border-style: solid; border-width: 1px; }\n .bt-ns { border-top-style: solid; border-top-width: 1px; }\n .br-ns { border-right-style: solid; border-right-width: 1px; }\n .bb-ns { border-bottom-style: solid; border-bottom-width: 1px; }\n .bl-ns { border-left-style: solid; border-left-width: 1px; }\n .bn-ns { border-style: none; border-width: 0; }\n}\n\n@media #{$breakpoint-medium} {\n .ba-m { border-style: solid; border-width: 1px; }\n .bt-m { border-top-style: solid; border-top-width: 1px; }\n .br-m { border-right-style: solid; border-right-width: 1px; }\n .bb-m { border-bottom-style: solid; border-bottom-width: 1px; }\n .bl-m { border-left-style: solid; border-left-width: 1px; }\n .bn-m { border-style: none; border-width: 0; }\n}\n\n@media #{$breakpoint-large} {\n .ba-l { border-style: solid; border-width: 1px; }\n .bt-l { border-top-style: solid; border-top-width: 1px; }\n .br-l { border-right-style: solid; border-right-width: 1px; }\n .bb-l { border-bottom-style: solid; border-bottom-width: 1px; }\n .bl-l { border-left-style: solid; border-left-width: 1px; }\n .bn-l { border-style: none; border-width: 0; }\n}\n\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n BORDER COLORS\n Docs: http://tachyons.io/docs/themes/borders/\n\n Border colors can be used to extend the base\n border classes ba,bt,bb,br,bl found in the _borders.css file.\n\n The base border class by default will set the color of the border\n to that of the current text color. These classes are for the cases\n where you desire for the text and border colors to be different.\n\n Base:\n b = border\n\n Modifiers:\n --color-name = each color variable name is also a border color name\n\n*/\n\n.b--black { border-color: $black; }\n.b--near-black { border-color: $near-black; }\n.b--dark-gray { border-color: $dark-gray; }\n.b--mid-gray { border-color: $mid-gray; }\n.b--gray { border-color: $gray; }\n.b--silver { border-color: $silver; }\n.b--light-silver { border-color: $light-silver; }\n.b--moon-gray { border-color: $moon-gray; }\n.b--light-gray { border-color: $light-gray; }\n.b--near-white { border-color: $near-white; }\n.b--white { border-color: $white; }\n\n.b--white-90 { border-color: $white-90; }\n.b--white-80 { border-color: $white-80; }\n.b--white-70 { border-color: $white-70; }\n.b--white-60 { border-color: $white-60; }\n.b--white-50 { border-color: $white-50; }\n.b--white-40 { border-color: $white-40; }\n.b--white-30 { border-color: $white-30; }\n.b--white-20 { border-color: $white-20; }\n.b--white-10 { border-color: $white-10; }\n.b--white-05 { border-color: $white-05; }\n.b--white-025 { border-color: $white-025; }\n.b--white-0125 { border-color: $white-0125; }\n\n.b--black-90 { border-color: $black-90; }\n.b--black-80 { border-color: $black-80; }\n.b--black-70 { border-color: $black-70; }\n.b--black-60 { border-color: $black-60; }\n.b--black-50 { border-color: $black-50; }\n.b--black-40 { border-color: $black-40; }\n.b--black-30 { border-color: $black-30; }\n.b--black-20 { border-color: $black-20; }\n.b--black-10 { border-color: $black-10; }\n.b--black-05 { border-color: $black-05; }\n.b--black-025 { border-color: $black-025; }\n.b--black-0125 { border-color: $black-0125; }\n\n.b--dark-red { border-color: $dark-red; }\n.b--red { border-color: $red; }\n.b--light-red { border-color: $light-red; }\n.b--orange { border-color: $orange; }\n.b--gold { border-color: $gold; }\n.b--yellow { border-color: $yellow; }\n.b--light-yellow { border-color: $light-yellow; }\n.b--purple { border-color: $purple; }\n.b--light-purple { border-color: $light-purple; }\n.b--dark-pink { border-color: $dark-pink; }\n.b--hot-pink { border-color: $hot-pink; }\n.b--pink { border-color: $pink; }\n.b--light-pink { border-color: $light-pink; }\n.b--dark-green { border-color: $dark-green; }\n.b--green { border-color: $green; }\n.b--light-green { border-color: $light-green; }\n.b--navy { border-color: $navy; }\n.b--dark-blue { border-color: $dark-blue; }\n.b--blue { border-color: $blue; }\n.b--light-blue { border-color: $light-blue; }\n.b--lightest-blue { border-color: $lightest-blue; }\n.b--washed-blue { border-color: $washed-blue; }\n.b--washed-green { border-color: $washed-green; }\n.b--washed-yellow { border-color: $washed-yellow; }\n.b--washed-red { border-color: $washed-red; }\n\n.b--transparent { border-color: $transparent; }\n.b--inherit { border-color: inherit; }\n","\n// Converted Variables\n\n$sans-serif: -apple-system, BlinkMacSystemFont, 'avenir next', avenir, helvetica, 'helvetica neue', ubuntu, roboto, noto, 'segoe ui', arial, sans-serif !default;\n$serif: georgia, serif !default;\n$code: consolas, monaco, monospace !default;\n$font-size-headline: 6rem !default;\n$font-size-subheadline: 5rem !default;\n$font-size-1: 3rem !default;\n$font-size-2: 2.25rem !default;\n$font-size-3: 1.5rem !default;\n$font-size-4: 1.25rem !default;\n$font-size-5: 1rem !default;\n$font-size-6: .875rem !default;\n$font-size-7: .75rem !default;\n$letter-spacing-tight: -.05em !default;\n$letter-spacing-1: .1em !default;\n$letter-spacing-2: .25em !default;\n$line-height-solid: 1 !default;\n$line-height-title: 1.25 !default;\n$line-height-copy: 1.5 !default;\n$measure: 30em !default;\n$measure-narrow: 20em !default;\n$measure-wide: 34em !default;\n$spacing-none: 0 !default;\n$spacing-extra-small: .25rem !default;\n$spacing-small: .5rem !default;\n$spacing-medium: 1rem !default;\n$spacing-large: 2rem !default;\n$spacing-extra-large: 4rem !default;\n$spacing-extra-extra-large: 8rem !default;\n$spacing-extra-extra-extra-large: 16rem !default;\n$spacing-copy-separator: 1.5em !default;\n$height-1: 1rem !default;\n$height-2: 2rem !default;\n$height-3: 4rem !default;\n$height-4: 8rem !default;\n$height-5: 16rem !default;\n$width-1: 1rem !default;\n$width-2: 2rem !default;\n$width-3: 4rem !default;\n$width-4: 8rem !default;\n$width-5: 16rem !default;\n$max-width-1: 1rem !default;\n$max-width-2: 2rem !default;\n$max-width-3: 4rem !default;\n$max-width-4: 8rem !default;\n$max-width-5: 16rem !default;\n$max-width-6: 32rem !default;\n$max-width-7: 48rem !default;\n$max-width-8: 64rem !default;\n$max-width-9: 96rem !default;\n$border-radius-none: 0 !default;\n$border-radius-1: .125rem !default;\n$border-radius-2: .25rem !default;\n$border-radius-3: .5rem !default;\n$border-radius-4: 1rem !default;\n$border-radius-circle: 100% !default;\n$border-radius-pill: 9999px !default;\n$border-width-none: 0 !default;\n$border-width-1: .125rem !default;\n$border-width-2: .25rem !default;\n$border-width-3: .5rem !default;\n$border-width-4: 1rem !default;\n$border-width-5: 2rem !default;\n$box-shadow-1: 0px 0px 4px 2px rgba( 0, 0, 0, 0.2 ) !default;\n$box-shadow-2: 0px 0px 8px 2px rgba( 0, 0, 0, 0.2 ) !default;\n$box-shadow-3: 2px 2px 4px 2px rgba( 0, 0, 0, 0.2 ) !default;\n$box-shadow-4: 2px 2px 8px 0px rgba( 0, 0, 0, 0.2 ) !default;\n$box-shadow-5: 4px 4px 8px 0px rgba( 0, 0, 0, 0.2 ) !default;\n$black: #000 !default;\n$near-black: #111 !default;\n$dark-gray: #333 !default;\n$mid-gray: #555 !default;\n$gray: #777 !default;\n$silver: #999 !default;\n$light-silver: #aaa !default;\n$moon-gray: #ccc !default;\n$light-gray: #eee !default;\n$near-white: #f4f4f4 !default;\n$white: #fff !default;\n$transparent: transparent !default;\n$black-90: rgba(0,0,0,.9) !default;\n$black-80: rgba(0,0,0,.8) !default;\n$black-70: rgba(0,0,0,.7) !default;\n$black-60: rgba(0,0,0,.6) !default;\n$black-50: rgba(0,0,0,.5) !default;\n$black-40: rgba(0,0,0,.4) !default;\n$black-30: rgba(0,0,0,.3) !default;\n$black-20: rgba(0,0,0,.2) !default;\n$black-10: rgba(0,0,0,.1) !default;\n$black-05: rgba(0,0,0,.05) !default;\n$black-025: rgba(0,0,0,.025) !default;\n$black-0125: rgba(0,0,0,.0125) !default;\n$white-90: rgba(255,255,255,.9) !default;\n$white-80: rgba(255,255,255,.8) !default;\n$white-70: rgba(255,255,255,.7) !default;\n$white-60: rgba(255,255,255,.6) !default;\n$white-50: rgba(255,255,255,.5) !default;\n$white-40: rgba(255,255,255,.4) !default;\n$white-30: rgba(255,255,255,.3) !default;\n$white-20: rgba(255,255,255,.2) !default;\n$white-10: rgba(255,255,255,.1) !default;\n$white-05: rgba(255,255,255,.05) !default;\n$white-025: rgba(255,255,255,.025) !default;\n$white-0125: rgba(255,255,255,.0125) !default;\n$dark-red: #e7040f !default;\n$red: #ff4136 !default;\n$light-red: #ff725c !default;\n$orange: #ff6300 !default;\n$gold: #ffb700 !default;\n$yellow: #ffd700 !default;\n$light-yellow: #fbf1a9 !default;\n$purple: #5e2ca5 !default;\n$light-purple: #a463f2 !default;\n$dark-pink: #d5008f !default;\n$hot-pink: #ff41b4 !default;\n$pink: #ff80cc !default;\n$light-pink: #ffa3d7 !default;\n$dark-green: #137752 !default;\n$green: #19a974 !default;\n$light-green: #9eebcf !default;\n$navy: #001b44 !default;\n$dark-blue: #00449e !default;\n$blue: #357edd !default;\n$light-blue: #96ccff !default;\n$lightest-blue: #cdecff !default;\n$washed-blue: #f6fffe !default;\n$washed-green: #e8fdf5 !default;\n$washed-yellow: #fffceb !default;\n$washed-red: #ffdfdf !default;\n\n// Custom Media Query Variables\n\n$breakpoint-not-small: 'screen and (min-width: 30em)' !default;\n$breakpoint-medium: 'screen and (min-width: 30em) and (max-width: 60em)' !default;\n$breakpoint-large: 'screen and (min-width: 60em)' !default;\n\n/*\n\n VARIABLES\n\n*/\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n BORDER RADIUS\n Docs: http://tachyons.io/docs/themes/border-radius/\n\n Base:\n br = border-radius\n\n Modifiers:\n 0 = 0/none\n 1 = 1st step in scale\n 2 = 2nd step in scale\n 3 = 3rd step in scale\n 4 = 4th step in scale\n\n Literal values:\n -100 = 100%\n -pill = 9999px\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n .br0 { border-radius: $border-radius-none }\n .br1 { border-radius: $border-radius-1; }\n .br2 { border-radius: $border-radius-2; }\n .br3 { border-radius: $border-radius-3; }\n .br4 { border-radius: $border-radius-4; }\n .br-100 { border-radius: $border-radius-circle; }\n .br-pill { border-radius: $border-radius-pill; }\n .br--bottom {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n }\n .br--top {\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n }\n .br--right {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n .br--left {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n\n@media #{$breakpoint-not-small} {\n .br0-ns { border-radius: $border-radius-none }\n .br1-ns { border-radius: $border-radius-1; }\n .br2-ns { border-radius: $border-radius-2; }\n .br3-ns { border-radius: $border-radius-3; }\n .br4-ns { border-radius: $border-radius-4; }\n .br-100-ns { border-radius: $border-radius-circle; }\n .br-pill-ns { border-radius: $border-radius-pill; }\n .br--bottom-ns {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n }\n .br--top-ns {\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n }\n .br--right-ns {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n .br--left-ns {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n}\n\n@media #{$breakpoint-medium} {\n .br0-m { border-radius: $border-radius-none }\n .br1-m { border-radius: $border-radius-1; }\n .br2-m { border-radius: $border-radius-2; }\n .br3-m { border-radius: $border-radius-3; }\n .br4-m { border-radius: $border-radius-4; }\n .br-100-m { border-radius: $border-radius-circle; }\n .br-pill-m { border-radius: $border-radius-pill; }\n .br--bottom-m {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n }\n .br--top-m {\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n }\n .br--right-m {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n .br--left-m {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n}\n\n@media #{$breakpoint-large} {\n .br0-l { border-radius: $border-radius-none }\n .br1-l { border-radius: $border-radius-1; }\n .br2-l { border-radius: $border-radius-2; }\n .br3-l { border-radius: $border-radius-3; }\n .br4-l { border-radius: $border-radius-4; }\n .br-100-l { border-radius: $border-radius-circle; }\n .br-pill-l { border-radius: $border-radius-pill; }\n .br--bottom-l {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n }\n .br--top-l {\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n }\n .br--right-l {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n .br--left-l {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n BORDER STYLES\n Docs: http://tachyons.io/docs/themes/borders/\n\n Depends on base border module in _borders.css\n\n Base:\n b = border-style\n\n Modifiers:\n --none = none\n --dotted = dotted\n --dashed = dashed\n --solid = solid\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n */\n\n.b--dotted { border-style: dotted; }\n.b--dashed { border-style: dashed; }\n.b--solid { border-style: solid; }\n.b--none { border-style: none; }\n\n@media #{$breakpoint-not-small} {\n .b--dotted-ns { border-style: dotted; }\n .b--dashed-ns { border-style: dashed; }\n .b--solid-ns { border-style: solid; }\n .b--none-ns { border-style: none; }\n}\n\n@media #{$breakpoint-medium} {\n .b--dotted-m { border-style: dotted; }\n .b--dashed-m { border-style: dashed; }\n .b--solid-m { border-style: solid; }\n .b--none-m { border-style: none; }\n}\n\n@media #{$breakpoint-large} {\n .b--dotted-l { border-style: dotted; }\n .b--dashed-l { border-style: dashed; }\n .b--solid-l { border-style: solid; }\n .b--none-l { border-style: none; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n BORDER WIDTHS\n Docs: http://tachyons.io/docs/themes/borders/\n\n Base:\n bw = border-width\n\n Modifiers:\n 0 = 0 width border\n 1 = 1st step in border-width scale\n 2 = 2nd step in border-width scale\n 3 = 3rd step in border-width scale\n 4 = 4th step in border-width scale\n 5 = 5th step in border-width scale\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n.bw0 { border-width: $border-width-none; }\n.bw1 { border-width: $border-width-1; }\n.bw2 { border-width: $border-width-2; }\n.bw3 { border-width: $border-width-3; }\n.bw4 { border-width: $border-width-4; }\n.bw5 { border-width: $border-width-5; }\n\n/* Resets */\n.bt-0 { border-top-width: $border-width-none }\n.br-0 { border-right-width: $border-width-none }\n.bb-0 { border-bottom-width: $border-width-none }\n.bl-0 { border-left-width: $border-width-none }\n\n@media #{$breakpoint-not-small} {\n .bw0-ns { border-width: $border-width-none; }\n .bw1-ns { border-width: $border-width-1; }\n .bw2-ns { border-width: $border-width-2; }\n .bw3-ns { border-width: $border-width-3; }\n .bw4-ns { border-width: $border-width-4; }\n .bw5-ns { border-width: $border-width-5; }\n .bt-0-ns { border-top-width: $border-width-none }\n .br-0-ns { border-right-width: $border-width-none }\n .bb-0-ns { border-bottom-width: $border-width-none }\n .bl-0-ns { border-left-width: $border-width-none }\n}\n\n@media #{$breakpoint-medium} {\n .bw0-m { border-width: $border-width-none; }\n .bw1-m { border-width: $border-width-1; }\n .bw2-m { border-width: $border-width-2; }\n .bw3-m { border-width: $border-width-3; }\n .bw4-m { border-width: $border-width-4; }\n .bw5-m { border-width: $border-width-5; }\n .bt-0-m { border-top-width: $border-width-none }\n .br-0-m { border-right-width: $border-width-none }\n .bb-0-m { border-bottom-width: $border-width-none }\n .bl-0-m { border-left-width: $border-width-none }\n}\n\n@media #{$breakpoint-large} {\n .bw0-l { border-width: $border-width-none; }\n .bw1-l { border-width: $border-width-1; }\n .bw2-l { border-width: $border-width-2; }\n .bw3-l { border-width: $border-width-3; }\n .bw4-l { border-width: $border-width-4; }\n .bw5-l { border-width: $border-width-5; }\n .bt-0-l { border-top-width: $border-width-none }\n .br-0-l { border-right-width: $border-width-none }\n .bb-0-l { border-bottom-width: $border-width-none }\n .bl-0-l { border-left-width: $border-width-none }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n BOX-SHADOW\n Docs: http://tachyons.io/docs/themes/box-shadow/\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n */\n\n.shadow-1 { box-shadow: $box-shadow-1; }\n.shadow-2 { box-shadow: $box-shadow-2; }\n.shadow-3 { box-shadow: $box-shadow-3; }\n.shadow-4 { box-shadow: $box-shadow-4; }\n.shadow-5 { box-shadow: $box-shadow-5; }\n\n@media #{$breakpoint-not-small} {\n .shadow-1-ns { box-shadow: $box-shadow-1; }\n .shadow-2-ns { box-shadow: $box-shadow-2; }\n .shadow-3-ns { box-shadow: $box-shadow-3; }\n .shadow-4-ns { box-shadow: $box-shadow-4; }\n .shadow-5-ns { box-shadow: $box-shadow-5; }\n}\n\n@media #{$breakpoint-medium} {\n .shadow-1-m { box-shadow: $box-shadow-1; }\n .shadow-2-m { box-shadow: $box-shadow-2; }\n .shadow-3-m { box-shadow: $box-shadow-3; }\n .shadow-4-m { box-shadow: $box-shadow-4; }\n .shadow-5-m { box-shadow: $box-shadow-5; }\n}\n\n@media #{$breakpoint-large} {\n .shadow-1-l { box-shadow: $box-shadow-1; }\n .shadow-2-l { box-shadow: $box-shadow-2; }\n .shadow-3-l { box-shadow: $box-shadow-3; }\n .shadow-4-l { box-shadow: $box-shadow-4; }\n .shadow-5-l { box-shadow: $box-shadow-5; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n CODE\n\n*/\n\n.pre {\n overflow-x: auto;\n overflow-y: hidden;\n overflow: scroll;\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n COORDINATES\n Docs: http://tachyons.io/docs/layout/position/\n\n Use in combination with the position module.\n\n Base:\n top\n bottom\n right\n left\n\n Modifiers:\n -0 = literal value 0\n -1 = literal value 1\n -2 = literal value 2\n --1 = literal value -1\n --2 = literal value -2\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n.top-0 { top: 0; }\n.right-0 { right: 0; }\n.bottom-0 { bottom: 0; }\n.left-0 { left: 0; }\n\n.top-1 { top: 1rem; }\n.right-1 { right: 1rem; }\n.bottom-1 { bottom: 1rem; }\n.left-1 { left: 1rem; }\n\n.top-2 { top: 2rem; }\n.right-2 { right: 2rem; }\n.bottom-2 { bottom: 2rem; }\n.left-2 { left: 2rem; }\n\n.top--1 { top: -1rem; }\n.right--1 { right: -1rem; }\n.bottom--1 { bottom: -1rem; }\n.left--1 { left: -1rem; }\n\n.top--2 { top: -2rem; }\n.right--2 { right: -2rem; }\n.bottom--2 { bottom: -2rem; }\n.left--2 { left: -2rem; }\n\n\n.absolute--fill {\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n}\n\n@media #{$breakpoint-not-small} {\n .top-0-ns { top: 0; }\n .left-0-ns { left: 0; }\n .right-0-ns { right: 0; }\n .bottom-0-ns { bottom: 0; }\n .top-1-ns { top: 1rem; }\n .left-1-ns { left: 1rem; }\n .right-1-ns { right: 1rem; }\n .bottom-1-ns { bottom: 1rem; }\n .top-2-ns { top: 2rem; }\n .left-2-ns { left: 2rem; }\n .right-2-ns { right: 2rem; }\n .bottom-2-ns { bottom: 2rem; }\n .top--1-ns { top: -1rem; }\n .right--1-ns { right: -1rem; }\n .bottom--1-ns { bottom: -1rem; }\n .left--1-ns { left: -1rem; }\n .top--2-ns { top: -2rem; }\n .right--2-ns { right: -2rem; }\n .bottom--2-ns { bottom: -2rem; }\n .left--2-ns { left: -2rem; }\n .absolute--fill-ns {\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n }\n}\n\n@media #{$breakpoint-medium} {\n .top-0-m { top: 0; }\n .left-0-m { left: 0; }\n .right-0-m { right: 0; }\n .bottom-0-m { bottom: 0; }\n .top-1-m { top: 1rem; }\n .left-1-m { left: 1rem; }\n .right-1-m { right: 1rem; }\n .bottom-1-m { bottom: 1rem; }\n .top-2-m { top: 2rem; }\n .left-2-m { left: 2rem; }\n .right-2-m { right: 2rem; }\n .bottom-2-m { bottom: 2rem; }\n .top--1-m { top: -1rem; }\n .right--1-m { right: -1rem; }\n .bottom--1-m { bottom: -1rem; }\n .left--1-m { left: -1rem; }\n .top--2-m { top: -2rem; }\n .right--2-m { right: -2rem; }\n .bottom--2-m { bottom: -2rem; }\n .left--2-m { left: -2rem; }\n .absolute--fill-m {\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n }\n}\n\n@media #{$breakpoint-large} {\n .top-0-l { top: 0; }\n .left-0-l { left: 0; }\n .right-0-l { right: 0; }\n .bottom-0-l { bottom: 0; }\n .top-1-l { top: 1rem; }\n .left-1-l { left: 1rem; }\n .right-1-l { right: 1rem; }\n .bottom-1-l { bottom: 1rem; }\n .top-2-l { top: 2rem; }\n .left-2-l { left: 2rem; }\n .right-2-l { right: 2rem; }\n .bottom-2-l { bottom: 2rem; }\n .top--1-l { top: -1rem; }\n .right--1-l { right: -1rem; }\n .bottom--1-l { bottom: -1rem; }\n .left--1-l { left: -1rem; }\n .top--2-l { top: -2rem; }\n .right--2-l { right: -2rem; }\n .bottom--2-l { bottom: -2rem; }\n .left--2-l { left: -2rem; }\n .absolute--fill-l {\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n CLEARFIX\n http://tachyons.io/docs/layout/clearfix/\n\n*/\n\n/* Nicolas Gallaghers Clearfix solution\n Ref: http://nicolasgallagher.com/micro-clearfix-hack/ */\n\n.cf:before,\n.cf:after { content: \" \"; display: table; }\n.cf:after { clear: both; }\n.cf { *zoom: 1; }\n\n.cl { clear: left; }\n.cr { clear: right; }\n.cb { clear: both; }\n.cn { clear: none; }\n\n@media #{$breakpoint-not-small} {\n .cl-ns { clear: left; }\n .cr-ns { clear: right; }\n .cb-ns { clear: both; }\n .cn-ns { clear: none; }\n}\n\n@media #{$breakpoint-medium} {\n .cl-m { clear: left; }\n .cr-m { clear: right; }\n .cb-m { clear: both; }\n .cn-m { clear: none; }\n}\n\n@media #{$breakpoint-large} {\n .cl-l { clear: left; }\n .cr-l { clear: right; }\n .cb-l { clear: both; }\n .cn-l { clear: none; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n FLEXBOX\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n.flex { display: flex; }\n.inline-flex { display: inline-flex; }\n\n/* 1. Fix for Chrome 44 bug.\n * https://code.google.com/p/chromium/issues/detail?id=506893 */\n.flex-auto {\n flex: 1 1 auto;\n min-width: 0; /* 1 */\n min-height: 0; /* 1 */\n}\n\n.flex-none { flex: none; }\n\n.flex-column { flex-direction: column; }\n.flex-row { flex-direction: row; }\n.flex-wrap { flex-wrap: wrap; }\n.flex-nowrap { flex-wrap: nowrap; }\n.flex-wrap-reverse { flex-wrap: wrap-reverse; }\n.flex-column-reverse { flex-direction: column-reverse; }\n.flex-row-reverse { flex-direction: row-reverse; }\n\n.items-start { align-items: flex-start; }\n.items-end { align-items: flex-end; }\n.items-center { align-items: center; }\n.items-baseline { align-items: baseline; }\n.items-stretch { align-items: stretch; }\n\n.self-start { align-self: flex-start; }\n.self-end { align-self: flex-end; }\n.self-center { align-self: center; }\n.self-baseline { align-self: baseline; }\n.self-stretch { align-self: stretch; }\n\n.justify-start { justify-content: flex-start; }\n.justify-end { justify-content: flex-end; }\n.justify-center { justify-content: center; }\n.justify-between { justify-content: space-between; }\n.justify-around { justify-content: space-around; }\n\n.content-start { align-content: flex-start; }\n.content-end { align-content: flex-end; }\n.content-center { align-content: center; }\n.content-between { align-content: space-between; }\n.content-around { align-content: space-around; }\n.content-stretch { align-content: stretch; }\n\n.order-0 { order: 0; }\n.order-1 { order: 1; }\n.order-2 { order: 2; }\n.order-3 { order: 3; }\n.order-4 { order: 4; }\n.order-5 { order: 5; }\n.order-6 { order: 6; }\n.order-7 { order: 7; }\n.order-8 { order: 8; }\n.order-last { order: 99999; }\n\n.flex-grow-0 { flex-grow: 0; }\n.flex-grow-1 { flex-grow: 1; }\n\n.flex-shrink-0 { flex-shrink: 0; }\n.flex-shrink-1 { flex-shrink: 1; }\n\n@media #{$breakpoint-not-small} {\n .flex-ns { display: flex; }\n .inline-flex-ns { display: inline-flex; }\n .flex-auto-ns {\n flex: 1 1 auto;\n min-width: 0; /* 1 */\n min-height: 0; /* 1 */\n }\n .flex-none-ns { flex: none; }\n .flex-column-ns { flex-direction: column; }\n .flex-row-ns { flex-direction: row; }\n .flex-wrap-ns { flex-wrap: wrap; }\n .flex-nowrap-ns { flex-wrap: nowrap; }\n .flex-wrap-reverse-ns { flex-wrap: wrap-reverse; }\n .flex-column-reverse-ns { flex-direction: column-reverse; }\n .flex-row-reverse-ns { flex-direction: row-reverse; }\n .items-start-ns { align-items: flex-start; }\n .items-end-ns { align-items: flex-end; }\n .items-center-ns { align-items: center; }\n .items-baseline-ns { align-items: baseline; }\n .items-stretch-ns { align-items: stretch; }\n\n .self-start-ns { align-self: flex-start; }\n .self-end-ns { align-self: flex-end; }\n .self-center-ns { align-self: center; }\n .self-baseline-ns { align-self: baseline; }\n .self-stretch-ns { align-self: stretch; }\n\n .justify-start-ns { justify-content: flex-start; }\n .justify-end-ns { justify-content: flex-end; }\n .justify-center-ns { justify-content: center; }\n .justify-between-ns { justify-content: space-between; }\n .justify-around-ns { justify-content: space-around; }\n\n .content-start-ns { align-content: flex-start; }\n .content-end-ns { align-content: flex-end; }\n .content-center-ns { align-content: center; }\n .content-between-ns { align-content: space-between; }\n .content-around-ns { align-content: space-around; }\n .content-stretch-ns { align-content: stretch; }\n\n .order-0-ns { order: 0; }\n .order-1-ns { order: 1; }\n .order-2-ns { order: 2; }\n .order-3-ns { order: 3; }\n .order-4-ns { order: 4; }\n .order-5-ns { order: 5; }\n .order-6-ns { order: 6; }\n .order-7-ns { order: 7; }\n .order-8-ns { order: 8; }\n .order-last-ns { order: 99999; }\n\n .flex-grow-0-ns { flex-grow: 0; }\n .flex-grow-1-ns { flex-grow: 1; }\n\n .flex-shrink-0-ns { flex-shrink: 0; }\n .flex-shrink-1-ns { flex-shrink: 1; }\n}\n@media #{$breakpoint-medium} {\n .flex-m { display: flex; }\n .inline-flex-m { display: inline-flex; }\n .flex-auto-m {\n flex: 1 1 auto;\n min-width: 0; /* 1 */\n min-height: 0; /* 1 */\n }\n .flex-none-m { flex: none; }\n .flex-column-m { flex-direction: column; }\n .flex-row-m { flex-direction: row; }\n .flex-wrap-m { flex-wrap: wrap; }\n .flex-nowrap-m { flex-wrap: nowrap; }\n .flex-wrap-reverse-m { flex-wrap: wrap-reverse; }\n .flex-column-reverse-m { flex-direction: column-reverse; }\n .flex-row-reverse-m { flex-direction: row-reverse; }\n .items-start-m { align-items: flex-start; }\n .items-end-m { align-items: flex-end; }\n .items-center-m { align-items: center; }\n .items-baseline-m { align-items: baseline; }\n .items-stretch-m { align-items: stretch; }\n\n .self-start-m { align-self: flex-start; }\n .self-end-m { align-self: flex-end; }\n .self-center-m { align-self: center; }\n .self-baseline-m { align-self: baseline; }\n .self-stretch-m { align-self: stretch; }\n\n .justify-start-m { justify-content: flex-start; }\n .justify-end-m { justify-content: flex-end; }\n .justify-center-m { justify-content: center; }\n .justify-between-m { justify-content: space-between; }\n .justify-around-m { justify-content: space-around; }\n\n .content-start-m { align-content: flex-start; }\n .content-end-m { align-content: flex-end; }\n .content-center-m { align-content: center; }\n .content-between-m { align-content: space-between; }\n .content-around-m { align-content: space-around; }\n .content-stretch-m { align-content: stretch; }\n\n .order-0-m { order: 0; }\n .order-1-m { order: 1; }\n .order-2-m { order: 2; }\n .order-3-m { order: 3; }\n .order-4-m { order: 4; }\n .order-5-m { order: 5; }\n .order-6-m { order: 6; }\n .order-7-m { order: 7; }\n .order-8-m { order: 8; }\n .order-last-m { order: 99999; }\n\n .flex-grow-0-m { flex-grow: 0; }\n .flex-grow-1-m { flex-grow: 1; }\n\n .flex-shrink-0-m { flex-shrink: 0; }\n .flex-shrink-1-m { flex-shrink: 1; }\n}\n\n@media #{$breakpoint-large} {\n .flex-l { display: flex; }\n .inline-flex-l { display: inline-flex; }\n .flex-auto-l {\n flex: 1 1 auto;\n min-width: 0; /* 1 */\n min-height: 0; /* 1 */\n }\n .flex-none-l { flex: none; }\n .flex-column-l { flex-direction: column; }\n .flex-row-l { flex-direction: row; }\n .flex-wrap-l { flex-wrap: wrap; }\n .flex-nowrap-l { flex-wrap: nowrap; }\n .flex-wrap-reverse-l { flex-wrap: wrap-reverse; }\n .flex-column-reverse-l { flex-direction: column-reverse; }\n .flex-row-reverse-l { flex-direction: row-reverse; }\n\n .items-start-l { align-items: flex-start; }\n .items-end-l { align-items: flex-end; }\n .items-center-l { align-items: center; }\n .items-baseline-l { align-items: baseline; }\n .items-stretch-l { align-items: stretch; }\n\n .self-start-l { align-self: flex-start; }\n .self-end-l { align-self: flex-end; }\n .self-center-l { align-self: center; }\n .self-baseline-l { align-self: baseline; }\n .self-stretch-l { align-self: stretch; }\n\n .justify-start-l { justify-content: flex-start; }\n .justify-end-l { justify-content: flex-end; }\n .justify-center-l { justify-content: center; }\n .justify-between-l { justify-content: space-between; }\n .justify-around-l { justify-content: space-around; }\n\n .content-start-l { align-content: flex-start; }\n .content-end-l { align-content: flex-end; }\n .content-center-l { align-content: center; }\n .content-between-l { align-content: space-between; }\n .content-around-l { align-content: space-around; }\n .content-stretch-l { align-content: stretch; }\n\n .order-0-l { order: 0; }\n .order-1-l { order: 1; }\n .order-2-l { order: 2; }\n .order-3-l { order: 3; }\n .order-4-l { order: 4; }\n .order-5-l { order: 5; }\n .order-6-l { order: 6; }\n .order-7-l { order: 7; }\n .order-8-l { order: 8; }\n .order-last-l { order: 99999; }\n\n .flex-grow-0-l { flex-grow: 0; }\n .flex-grow-1-l { flex-grow: 1; }\n\n .flex-shrink-0-l { flex-shrink: 0; }\n .flex-shrink-1-l { flex-shrink: 1; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n DISPLAY\n Docs: http://tachyons.io/docs/layout/display\n\n Base:\n d = display\n\n Modifiers:\n n = none\n b = block\n ib = inline-block\n it = inline-table\n t = table\n tc = table-cell\n tr = table-row\n tcol = table-column\n tcolg = table-column-group\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n.dn { display: none; }\n.di { display: inline; }\n.db { display: block; }\n.dib { display: inline-block; }\n.dit { display: inline-table; }\n.dt { display: table; }\n.dtc { display: table-cell; }\n.dt-row { display: table-row; }\n.dt-row-group { display: table-row-group; }\n.dt-column { display: table-column; }\n.dt-column-group { display: table-column-group; }\n\n/*\n This will set table to full width and then\n all cells will be equal width\n*/\n.dt--fixed {\n table-layout: fixed;\n width: 100%;\n}\n\n@media #{$breakpoint-not-small} {\n .dn-ns { display: none; }\n .di-ns { display: inline; }\n .db-ns { display: block; }\n .dib-ns { display: inline-block; }\n .dit-ns { display: inline-table; }\n .dt-ns { display: table; }\n .dtc-ns { display: table-cell; }\n .dt-row-ns { display: table-row; }\n .dt-row-group-ns { display: table-row-group; }\n .dt-column-ns { display: table-column; }\n .dt-column-group-ns { display: table-column-group; }\n\n .dt--fixed-ns {\n table-layout: fixed;\n width: 100%;\n }\n}\n\n@media #{$breakpoint-medium} {\n .dn-m { display: none; }\n .di-m { display: inline; }\n .db-m { display: block; }\n .dib-m { display: inline-block; }\n .dit-m { display: inline-table; }\n .dt-m { display: table; }\n .dtc-m { display: table-cell; }\n .dt-row-m { display: table-row; }\n .dt-row-group-m { display: table-row-group; }\n .dt-column-m { display: table-column; }\n .dt-column-group-m { display: table-column-group; }\n\n .dt--fixed-m {\n table-layout: fixed;\n width: 100%;\n }\n}\n\n@media #{$breakpoint-large} {\n .dn-l { display: none; }\n .di-l { display: inline; }\n .db-l { display: block; }\n .dib-l { display: inline-block; }\n .dit-l { display: inline-table; }\n .dt-l { display: table; }\n .dtc-l { display: table-cell; }\n .dt-row-l { display: table-row; }\n .dt-row-group-l { display: table-row-group; }\n .dt-column-l { display: table-column; }\n .dt-column-group-l { display: table-column-group; }\n\n .dt--fixed-l {\n table-layout: fixed;\n width: 100%;\n }\n}\n\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n FLOATS\n http://tachyons.io/docs/layout/floats/\n\n 1. Floated elements are automatically rendered as block level elements.\n Setting floats to display inline will fix the double margin bug in\n ie6. You know... just in case.\n\n 2. Don't forget to clearfix your floats with .cf\n\n Base:\n f = float\n\n Modifiers:\n l = left\n r = right\n n = none\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n\n\n.fl { float: left; _display: inline; }\n.fr { float: right; _display: inline; }\n.fn { float: none; }\n\n@media #{$breakpoint-not-small} {\n .fl-ns { float: left; _display: inline; }\n .fr-ns { float: right; _display: inline; }\n .fn-ns { float: none; }\n}\n\n@media #{$breakpoint-medium} {\n .fl-m { float: left; _display: inline; }\n .fr-m { float: right; _display: inline; }\n .fn-m { float: none; }\n}\n\n@media #{$breakpoint-large} {\n .fl-l { float: left; _display: inline; }\n .fr-l { float: right; _display: inline; }\n .fn-l { float: none; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n FONT FAMILY GROUPS\n Docs: http://tachyons.io/docs/typography/font-family/\n\n*/\n\n\n.sans-serif {\n font-family: $sans-serif;\n}\n\n.serif {\n font-family: $serif;\n}\n\n.system-sans-serif {\n font-family: sans-serif;\n}\n\n.system-serif {\n font-family: serif;\n}\n\n\n/* Monospaced Typefaces (for code) */\n\n/* From http://cssfontstack.com */\ncode, .code {\n font-family: Consolas,\n monaco,\n monospace;\n}\n\n.courier {\n font-family: 'Courier Next',\n courier,\n monospace;\n}\n\n\n/* Sans-Serif Typefaces */\n\n.helvetica {\n font-family: 'helvetica neue', helvetica,\n sans-serif;\n}\n\n.avenir {\n font-family: 'avenir next', avenir,\n sans-serif;\n}\n\n\n/* Serif Typefaces */\n\n.athelas {\n font-family: athelas,\n georgia,\n serif;\n}\n\n.georgia {\n font-family: georgia,\n serif;\n}\n\n.times {\n font-family: times,\n serif;\n}\n\n.bodoni {\n font-family: \"Bodoni MT\",\n serif;\n}\n\n.calisto {\n font-family: \"Calisto MT\",\n serif;\n}\n\n.garamond {\n font-family: garamond,\n serif;\n}\n\n.baskerville {\n font-family: baskerville,\n serif;\n}\n\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n FONT STYLE\n Docs: http://tachyons.io/docs/typography/font-style/\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n.i { font-style: italic; }\n.fs-normal { font-style: normal; }\n\n@media #{$breakpoint-not-small} {\n .i-ns { font-style: italic; }\n .fs-normal-ns { font-style: normal; }\n}\n\n@media #{$breakpoint-medium} {\n .i-m { font-style: italic; }\n .fs-normal-m { font-style: normal; }\n}\n\n@media #{$breakpoint-large} {\n .i-l { font-style: italic; }\n .fs-normal-l { font-style: normal; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n FONT WEIGHT\n Docs: http://tachyons.io/docs/typography/font-weight/\n\n Base\n fw = font-weight\n\n Modifiers:\n 1 = literal value 100\n 2 = literal value 200\n 3 = literal value 300\n 4 = literal value 400\n 5 = literal value 500\n 6 = literal value 600\n 7 = literal value 700\n 8 = literal value 800\n 9 = literal value 900\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n.normal { font-weight: normal; }\n.b { font-weight: bold; }\n.fw1 { font-weight: 100; }\n.fw2 { font-weight: 200; }\n.fw3 { font-weight: 300; }\n.fw4 { font-weight: 400; }\n.fw5 { font-weight: 500; }\n.fw6 { font-weight: 600; }\n.fw7 { font-weight: 700; }\n.fw8 { font-weight: 800; }\n.fw9 { font-weight: 900; }\n\n\n@media #{$breakpoint-not-small} {\n .normal-ns { font-weight: normal; }\n .b-ns { font-weight: bold; }\n .fw1-ns { font-weight: 100; }\n .fw2-ns { font-weight: 200; }\n .fw3-ns { font-weight: 300; }\n .fw4-ns { font-weight: 400; }\n .fw5-ns { font-weight: 500; }\n .fw6-ns { font-weight: 600; }\n .fw7-ns { font-weight: 700; }\n .fw8-ns { font-weight: 800; }\n .fw9-ns { font-weight: 900; }\n}\n\n@media #{$breakpoint-medium} {\n .normal-m { font-weight: normal; }\n .b-m { font-weight: bold; }\n .fw1-m { font-weight: 100; }\n .fw2-m { font-weight: 200; }\n .fw3-m { font-weight: 300; }\n .fw4-m { font-weight: 400; }\n .fw5-m { font-weight: 500; }\n .fw6-m { font-weight: 600; }\n .fw7-m { font-weight: 700; }\n .fw8-m { font-weight: 800; }\n .fw9-m { font-weight: 900; }\n}\n\n@media #{$breakpoint-large} {\n .normal-l { font-weight: normal; }\n .b-l { font-weight: bold; }\n .fw1-l { font-weight: 100; }\n .fw2-l { font-weight: 200; }\n .fw3-l { font-weight: 300; }\n .fw4-l { font-weight: 400; }\n .fw5-l { font-weight: 500; }\n .fw6-l { font-weight: 600; }\n .fw7-l { font-weight: 700; }\n .fw8-l { font-weight: 800; }\n .fw9-l { font-weight: 900; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n FORMS\n \n*/\n\n.input-reset {\n -webkit-appearance: none;\n -moz-appearance: none;\n}\n\n.button-reset::-moz-focus-inner,\n.input-reset::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n HEIGHTS\n Docs: http://tachyons.io/docs/layout/heights/\n\n Base:\n h = height\n min-h = min-height\n min-vh = min-height vertical screen height\n vh = vertical screen height\n\n Modifiers\n 1 = 1st step in height scale\n 2 = 2nd step in height scale\n 3 = 3rd step in height scale\n 4 = 4th step in height scale\n 5 = 5th step in height scale\n\n -25 = literal value 25%\n -50 = literal value 50%\n -75 = literal value 75%\n -100 = literal value 100%\n\n -auto = string value of auto\n -inherit = string value of inherit\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n/* Height Scale */\n\n.h1 { height: $height-1; }\n.h2 { height: $height-2; }\n.h3 { height: $height-3; }\n.h4 { height: $height-4; }\n.h5 { height: $height-5; }\n\n/* Height Percentages - Based off of height of parent */\n\n.h-25 { height: 25%; }\n.h-50 { height: 50%; }\n.h-75 { height: 75%; }\n.h-100 { height: 100%; }\n\n.min-h-100 { min-height: 100%; }\n\n/* Screen Height Percentage */\n\n.vh-25 { height: 25vh; }\n.vh-50 { height: 50vh; }\n.vh-75 { height: 75vh; }\n.vh-100 { height: 100vh; }\n\n.min-vh-100 { min-height: 100vh; }\n\n\n/* String Properties */\n\n.h-auto { height: auto; }\n.h-inherit { height: inherit; }\n\n@media #{$breakpoint-not-small} {\n .h1-ns { height: $height-1; }\n .h2-ns { height: $height-2; }\n .h3-ns { height: $height-3; }\n .h4-ns { height: $height-4; }\n .h5-ns { height: $height-5; }\n .h-25-ns { height: 25%; }\n .h-50-ns { height: 50%; }\n .h-75-ns { height: 75%; }\n .h-100-ns { height: 100%; }\n .min-h-100-ns { min-height: 100%; }\n .vh-25-ns { height: 25vh; }\n .vh-50-ns { height: 50vh; }\n .vh-75-ns { height: 75vh; }\n .vh-100-ns { height: 100vh; }\n .min-vh-100-ns { min-height: 100vh; }\n .h-auto-ns { height: auto; }\n .h-inherit-ns { height: inherit; }\n}\n\n@media #{$breakpoint-medium} {\n .h1-m { height: $height-1; }\n .h2-m { height: $height-2; }\n .h3-m { height: $height-3; }\n .h4-m { height: $height-4; }\n .h5-m { height: $height-5; }\n .h-25-m { height: 25%; }\n .h-50-m { height: 50%; }\n .h-75-m { height: 75%; }\n .h-100-m { height: 100%; }\n .min-h-100-m { min-height: 100%; }\n .vh-25-m { height: 25vh; }\n .vh-50-m { height: 50vh; }\n .vh-75-m { height: 75vh; }\n .vh-100-m { height: 100vh; }\n .min-vh-100-m { min-height: 100vh; }\n .h-auto-m { height: auto; }\n .h-inherit-m { height: inherit; }\n}\n\n@media #{$breakpoint-large} {\n .h1-l { height: $height-1; }\n .h2-l { height: $height-2; }\n .h3-l { height: $height-3; }\n .h4-l { height: $height-4; }\n .h5-l { height: $height-5; }\n .h-25-l { height: 25%; }\n .h-50-l { height: 50%; }\n .h-75-l { height: 75%; }\n .h-100-l { height: 100%; }\n .min-h-100-l { min-height: 100%; }\n .vh-25-l { height: 25vh; }\n .vh-50-l { height: 50vh; }\n .vh-75-l { height: 75vh; }\n .vh-100-l { height: 100vh; }\n .min-vh-100-l { min-height: 100vh; }\n .h-auto-l { height: auto; }\n .h-inherit-l { height: inherit; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n LETTER SPACING\n Docs: http://tachyons.io/docs/typography/tracking/\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n.tracked { letter-spacing: $letter-spacing-1; }\n.tracked-tight { letter-spacing: $letter-spacing-tight; }\n.tracked-mega { letter-spacing: $letter-spacing-2; }\n\n@media #{$breakpoint-not-small} {\n .tracked-ns { letter-spacing: $letter-spacing-1; }\n .tracked-tight-ns { letter-spacing: $letter-spacing-tight; }\n .tracked-mega-ns { letter-spacing: $letter-spacing-2; }\n}\n\n@media #{$breakpoint-medium} {\n .tracked-m { letter-spacing: $letter-spacing-1; }\n .tracked-tight-m { letter-spacing: $letter-spacing-tight; }\n .tracked-mega-m { letter-spacing: $letter-spacing-2; }\n}\n\n@media #{$breakpoint-large} {\n .tracked-l { letter-spacing: $letter-spacing-1; }\n .tracked-tight-l { letter-spacing: $letter-spacing-tight; }\n .tracked-mega-l { letter-spacing: $letter-spacing-2; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n LINE HEIGHT / LEADING\n Docs: http://tachyons.io/docs/typography/line-height\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n .lh-solid { line-height: $line-height-solid; }\n .lh-title { line-height: $line-height-title; }\n .lh-copy { line-height: $line-height-copy; }\n\n@media #{$breakpoint-not-small} {\n .lh-solid-ns { line-height: $line-height-solid; }\n .lh-title-ns { line-height: $line-height-title; }\n .lh-copy-ns { line-height: $line-height-copy; }\n}\n\n@media #{$breakpoint-medium} {\n .lh-solid-m { line-height: $line-height-solid; }\n .lh-title-m { line-height: $line-height-title; }\n .lh-copy-m { line-height: $line-height-copy; }\n}\n\n@media #{$breakpoint-large} {\n .lh-solid-l { line-height: $line-height-solid; }\n .lh-title-l { line-height: $line-height-title; }\n .lh-copy-l { line-height: $line-height-copy; }\n}\n\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n LINKS\n Docs: http://tachyons.io/docs/elements/links/\n\n*/\n\n.link {\n text-decoration: none;\n transition: color .15s ease-in;\n}\n\n.link:link,\n.link:visited {\n transition: color .15s ease-in;\n}\n.link:hover {\n transition: color .15s ease-in;\n}\n.link:active {\n transition: color .15s ease-in;\n}\n.link:focus {\n transition: color .15s ease-in;\n outline: 1px dotted currentColor;\n}\n\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n LISTS\n http://tachyons.io/docs/elements/lists/\n\n*/\n\n.list { list-style-type: none; }\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n MAX WIDTHS\n Docs: http://tachyons.io/docs/layout/max-widths/\n\n Base:\n mw = max-width\n\n Modifiers\n 1 = 1st step in width scale\n 2 = 2nd step in width scale\n 3 = 3rd step in width scale\n 4 = 4th step in width scale\n 5 = 5th step in width scale\n 6 = 6st step in width scale\n 7 = 7nd step in width scale\n 8 = 8rd step in width scale\n 9 = 9th step in width scale\n\n -100 = literal value 100%\n\n -none = string value none\n\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n/* Max Width Percentages */\n\n.mw-100 { max-width: 100%; }\n\n/* Max Width Scale */\n\n.mw1 { max-width: $max-width-1; }\n.mw2 { max-width: $max-width-2; }\n.mw3 { max-width: $max-width-3; }\n.mw4 { max-width: $max-width-4; }\n.mw5 { max-width: $max-width-5; }\n.mw6 { max-width: $max-width-6; }\n.mw7 { max-width: $max-width-7; }\n.mw8 { max-width: $max-width-8; }\n.mw9 { max-width: $max-width-9; }\n\n/* Max Width String Properties */\n\n.mw-none { max-width: none; }\n\n@media #{$breakpoint-not-small} {\n .mw-100-ns { max-width: 100%; }\n\n .mw1-ns { max-width: $max-width-1; }\n .mw2-ns { max-width: $max-width-2; }\n .mw3-ns { max-width: $max-width-3; }\n .mw4-ns { max-width: $max-width-4; }\n .mw5-ns { max-width: $max-width-5; }\n .mw6-ns { max-width: $max-width-6; }\n .mw7-ns { max-width: $max-width-7; }\n .mw8-ns { max-width: $max-width-8; }\n .mw9-ns { max-width: $max-width-9; }\n\n .mw-none-ns { max-width: none; }\n}\n\n@media #{$breakpoint-medium} {\n .mw-100-m { max-width: 100%; }\n\n .mw1-m { max-width: $max-width-1; }\n .mw2-m { max-width: $max-width-2; }\n .mw3-m { max-width: $max-width-3; }\n .mw4-m { max-width: $max-width-4; }\n .mw5-m { max-width: $max-width-5; }\n .mw6-m { max-width: $max-width-6; }\n .mw7-m { max-width: $max-width-7; }\n .mw8-m { max-width: $max-width-8; }\n .mw9-m { max-width: $max-width-9; }\n\n .mw-none-m { max-width: none; }\n}\n\n@media #{$breakpoint-large} {\n .mw-100-l { max-width: 100%; }\n\n .mw1-l { max-width: $max-width-1; }\n .mw2-l { max-width: $max-width-2; }\n .mw3-l { max-width: $max-width-3; }\n .mw4-l { max-width: $max-width-4; }\n .mw5-l { max-width: $max-width-5; }\n .mw6-l { max-width: $max-width-6; }\n .mw7-l { max-width: $max-width-7; }\n .mw8-l { max-width: $max-width-8; }\n .mw9-l { max-width: $max-width-9; }\n\n .mw-none-l { max-width: none; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n WIDTHS\n Docs: http://tachyons.io/docs/layout/widths/\n\n Base:\n w = width\n\n Modifiers\n 1 = 1st step in width scale\n 2 = 2nd step in width scale\n 3 = 3rd step in width scale\n 4 = 4th step in width scale\n 5 = 5th step in width scale\n\n -10 = literal value 10%\n -20 = literal value 20%\n -25 = literal value 25%\n -30 = literal value 30%\n -33 = literal value 33%\n -34 = literal value 34%\n -40 = literal value 40%\n -50 = literal value 50%\n -60 = literal value 60%\n -70 = literal value 70%\n -75 = literal value 75%\n -80 = literal value 80%\n -90 = literal value 90%\n -100 = literal value 100%\n\n -third = 100% / 3 (Not supported in opera mini or IE8)\n -two-thirds = 100% / 1.5 (Not supported in opera mini or IE8)\n -auto = string value auto\n\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n */\n\n/* Width Scale */\n\n.w1 { width: $width-1; }\n.w2 { width: $width-2; }\n.w3 { width: $width-3; }\n.w4 { width: $width-4; }\n.w5 { width: $width-5; }\n\n.w-10 { width: 10%; }\n.w-20 { width: 20%; }\n.w-25 { width: 25%; }\n.w-30 { width: 30%; }\n.w-33 { width: 33%; }\n.w-34 { width: 34%; }\n.w-40 { width: 40%; }\n.w-50 { width: 50%; }\n.w-60 { width: 60%; }\n.w-70 { width: 70%; }\n.w-75 { width: 75%; }\n.w-80 { width: 80%; }\n.w-90 { width: 90%; }\n.w-100 { width: 100%; }\n\n.w-third { width: (100% / 3); }\n.w-two-thirds { width: (100% / 1.5); }\n.w-auto { width: auto; }\n\n@media #{$breakpoint-not-small} {\n .w1-ns { width: $width-1; }\n .w2-ns { width: $width-2; }\n .w3-ns { width: $width-3; }\n .w4-ns { width: $width-4; }\n .w5-ns { width: $width-5; }\n .w-10-ns { width: 10%; }\n .w-20-ns { width: 20%; }\n .w-25-ns { width: 25%; }\n .w-30-ns { width: 30%; }\n .w-33-ns { width: 33%; }\n .w-34-ns { width: 34%; }\n .w-40-ns { width: 40%; }\n .w-50-ns { width: 50%; }\n .w-60-ns { width: 60%; }\n .w-70-ns { width: 70%; }\n .w-75-ns { width: 75%; }\n .w-80-ns { width: 80%; }\n .w-90-ns { width: 90%; }\n .w-100-ns { width: 100%; }\n .w-third-ns { width: (100% / 3); }\n .w-two-thirds-ns { width: (100% / 1.5); }\n .w-auto-ns { width: auto; }\n}\n\n@media #{$breakpoint-medium} {\n .w1-m { width: $width-1; }\n .w2-m { width: $width-2; }\n .w3-m { width: $width-3; }\n .w4-m { width: $width-4; }\n .w5-m { width: $width-5; }\n .w-10-m { width: 10%; }\n .w-20-m { width: 20%; }\n .w-25-m { width: 25%; }\n .w-30-m { width: 30%; }\n .w-33-m { width: 33%; }\n .w-34-m { width: 34%; }\n .w-40-m { width: 40%; }\n .w-50-m { width: 50%; }\n .w-60-m { width: 60%; }\n .w-70-m { width: 70%; }\n .w-75-m { width: 75%; }\n .w-80-m { width: 80%; }\n .w-90-m { width: 90%; }\n .w-100-m { width: 100%; }\n .w-third-m { width: (100% / 3); }\n .w-two-thirds-m { width: (100% / 1.5); }\n .w-auto-m { width: auto; }\n}\n\n@media #{$breakpoint-large} {\n .w1-l { width: $width-1; }\n .w2-l { width: $width-2; }\n .w3-l { width: $width-3; }\n .w4-l { width: $width-4; }\n .w5-l { width: $width-5; }\n .w-10-l { width: 10%; }\n .w-20-l { width: 20%; }\n .w-25-l { width: 25%; }\n .w-30-l { width: 30%; }\n .w-33-l { width: 33%; }\n .w-34-l { width: 34%; }\n .w-40-l { width: 40%; }\n .w-50-l { width: 50%; }\n .w-60-l { width: 60%; }\n .w-70-l { width: 70%; }\n .w-75-l { width: 75%; }\n .w-80-l { width: 80%; }\n .w-90-l { width: 90%; }\n .w-100-l { width: 100%; }\n .w-third-l { width: (100% / 3); }\n .w-two-thirds-l { width: (100% / 1.5); }\n .w-auto-l { width: auto; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n OVERFLOW\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n */\n\n.overflow-visible { overflow: visible; }\n.overflow-hidden { overflow: hidden; }\n.overflow-scroll { overflow: scroll; }\n.overflow-auto { overflow: auto; }\n\n.overflow-x-visible { overflow-x: visible; }\n.overflow-x-hidden { overflow-x: hidden; }\n.overflow-x-scroll { overflow-x: scroll; }\n.overflow-x-auto { overflow-x: auto; }\n\n.overflow-y-visible { overflow-y: visible; }\n.overflow-y-hidden { overflow-y: hidden; }\n.overflow-y-scroll { overflow-y: scroll; }\n.overflow-y-auto { overflow-y: auto; }\n\n@media #{$breakpoint-not-small} {\n .overflow-visible-ns { overflow: visible; }\n .overflow-hidden-ns { overflow: hidden; }\n .overflow-scroll-ns { overflow: scroll; }\n .overflow-auto-ns { overflow: auto; }\n .overflow-x-visible-ns { overflow-x: visible; }\n .overflow-x-hidden-ns { overflow-x: hidden; }\n .overflow-x-scroll-ns { overflow-x: scroll; }\n .overflow-x-auto-ns { overflow-x: auto; }\n\n .overflow-y-visible-ns { overflow-y: visible; }\n .overflow-y-hidden-ns { overflow-y: hidden; }\n .overflow-y-scroll-ns { overflow-y: scroll; }\n .overflow-y-auto-ns { overflow-y: auto; }\n}\n\n@media #{$breakpoint-medium} {\n .overflow-visible-m { overflow: visible; }\n .overflow-hidden-m { overflow: hidden; }\n .overflow-scroll-m { overflow: scroll; }\n .overflow-auto-m { overflow: auto; }\n\n .overflow-x-visible-m { overflow-x: visible; }\n .overflow-x-hidden-m { overflow-x: hidden; }\n .overflow-x-scroll-m { overflow-x: scroll; }\n .overflow-x-auto-m { overflow-x: auto; }\n\n .overflow-y-visible-m { overflow-y: visible; }\n .overflow-y-hidden-m { overflow-y: hidden; }\n .overflow-y-scroll-m { overflow-y: scroll; }\n .overflow-y-auto-m { overflow-y: auto; }\n}\n\n@media #{$breakpoint-large} {\n .overflow-visible-l { overflow: visible; }\n .overflow-hidden-l { overflow: hidden; }\n .overflow-scroll-l { overflow: scroll; }\n .overflow-auto-l { overflow: auto; }\n\n .overflow-x-visible-l { overflow-x: visible; }\n .overflow-x-hidden-l { overflow-x: hidden; }\n .overflow-x-scroll-l { overflow-x: scroll; }\n .overflow-x-auto-l { overflow-x: auto; }\n\n .overflow-y-visible-l { overflow-y: visible; }\n .overflow-y-hidden-l { overflow-y: hidden; }\n .overflow-y-scroll-l { overflow-y: scroll; }\n .overflow-y-auto-l { overflow-y: auto; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n POSITIONING\n Docs: http://tachyons.io/docs/layout/position/\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n.static { position: static; }\n.relative { position: relative; }\n.absolute { position: absolute; }\n.fixed { position: fixed; }\n\n@media #{$breakpoint-not-small} {\n .static-ns { position: static; }\n .relative-ns { position: relative; }\n .absolute-ns { position: absolute; }\n .fixed-ns { position: fixed; }\n}\n\n@media #{$breakpoint-medium} {\n .static-m { position: static; }\n .relative-m { position: relative; }\n .absolute-m { position: absolute; }\n .fixed-m { position: fixed; }\n}\n\n@media #{$breakpoint-large} {\n .static-l { position: static; }\n .relative-l { position: relative; }\n .absolute-l { position: absolute; }\n .fixed-l { position: fixed; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n OPACITY\n Docs: http://tachyons.io/docs/themes/opacity/\n\n*/\n\n.o-100 { opacity: 1; }\n.o-90 { opacity: .9; }\n.o-80 { opacity: .8; }\n.o-70 { opacity: .7; }\n.o-60 { opacity: .6; }\n.o-50 { opacity: .5; }\n.o-40 { opacity: .4; }\n.o-30 { opacity: .3; }\n.o-20 { opacity: .2; }\n.o-10 { opacity: .1; }\n.o-05 { opacity: .05; }\n.o-025 { opacity: .025; }\n.o-0 { opacity: 0; }\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n ROTATIONS\n\n*/\n\n.rotate-45 { transform: rotate(45deg); }\n.rotate-90 { transform: rotate(90deg); }\n.rotate-135 { transform: rotate(135deg); }\n.rotate-180 { transform: rotate(180deg); }\n.rotate-225 { transform: rotate(225deg); }\n.rotate-270 { transform: rotate(270deg); }\n.rotate-315 { transform: rotate(315deg); }\n\n@media #{$breakpoint-not-small}{\n .rotate-45-ns { transform: rotate(45deg); }\n .rotate-90-ns { transform: rotate(90deg); }\n .rotate-135-ns { transform: rotate(135deg); }\n .rotate-180-ns { transform: rotate(180deg); }\n .rotate-225-ns { transform: rotate(225deg); }\n .rotate-270-ns { transform: rotate(270deg); }\n .rotate-315-ns { transform: rotate(315deg); }\n}\n\n@media #{$breakpoint-medium}{\n .rotate-45-m { transform: rotate(45deg); }\n .rotate-90-m { transform: rotate(90deg); }\n .rotate-135-m { transform: rotate(135deg); }\n .rotate-180-m { transform: rotate(180deg); }\n .rotate-225-m { transform: rotate(225deg); }\n .rotate-270-m { transform: rotate(270deg); }\n .rotate-315-m { transform: rotate(315deg); }\n}\n\n@media #{$breakpoint-large}{\n .rotate-45-l { transform: rotate(45deg); }\n .rotate-90-l { transform: rotate(90deg); }\n .rotate-135-l { transform: rotate(135deg); }\n .rotate-180-l { transform: rotate(180deg); }\n .rotate-225-l { transform: rotate(225deg); }\n .rotate-270-l { transform: rotate(270deg); }\n .rotate-315-l { transform: rotate(315deg); }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n SKINS\n Docs: http://tachyons.io/docs/themes/skins/\n\n Classes for setting foreground and background colors on elements.\n If you haven't declared a border color, but set border on an element, it will\n be set to the current text color.\n\n*/\n\n/* Text colors */\n\n.black-90 { color: $black-90; }\n.black-80 { color: $black-80; }\n.black-70 { color: $black-70; }\n.black-60 { color: $black-60; }\n.black-50 { color: $black-50; }\n.black-40 { color: $black-40; }\n.black-30 { color: $black-30; }\n.black-20 { color: $black-20; }\n.black-10 { color: $black-10; }\n.black-05 { color: $black-05; }\n\n.white-90 { color: $white-90; }\n.white-80 { color: $white-80; }\n.white-70 { color: $white-70; }\n.white-60 { color: $white-60; }\n.white-50 { color: $white-50; }\n.white-40 { color: $white-40; }\n.white-30 { color: $white-30; }\n.white-20 { color: $white-20; }\n.white-10 { color: $white-10; }\n\n.black { color: $black; }\n.near-black { color: $near-black; }\n.dark-gray { color: $dark-gray; }\n.mid-gray { color: $mid-gray; }\n.gray { color: $gray; }\n.silver { color: $silver; }\n.light-silver { color: $light-silver; }\n.moon-gray { color: $moon-gray; }\n.light-gray { color: $light-gray; }\n.near-white { color: $near-white; }\n.white { color: $white; }\n\n.dark-red { color: $dark-red; }\n.red { color: $red; }\n.light-red { color: $light-red; }\n.orange { color: $orange; }\n.gold { color: $gold; }\n.yellow { color: $yellow; }\n.light-yellow { color: $light-yellow; }\n.purple { color: $purple; }\n.light-purple { color: $light-purple; }\n.dark-pink { color: $dark-pink; }\n.hot-pink { color: $hot-pink; }\n.pink { color: $pink; }\n.light-pink { color: $light-pink; }\n.dark-green { color: $dark-green; }\n.green { color: $green; }\n.light-green { color: $light-green; }\n.navy { color: $navy; }\n.dark-blue { color: $dark-blue; }\n.blue { color: $blue; }\n.light-blue { color: $light-blue; }\n.lightest-blue { color: $lightest-blue; }\n.washed-blue { color: $washed-blue; }\n.washed-green { color: $washed-green; }\n.washed-yellow { color: $washed-yellow; }\n.washed-red { color: $washed-red; }\n.color-inherit { color: inherit; }\n\n.bg-black-90 { background-color: $black-90; }\n.bg-black-80 { background-color: $black-80; }\n.bg-black-70 { background-color: $black-70; }\n.bg-black-60 { background-color: $black-60; }\n.bg-black-50 { background-color: $black-50; }\n.bg-black-40 { background-color: $black-40; }\n.bg-black-30 { background-color: $black-30; }\n.bg-black-20 { background-color: $black-20; }\n.bg-black-10 { background-color: $black-10; }\n.bg-black-05 { background-color: $black-05; }\n.bg-white-90 { background-color: $white-90; }\n.bg-white-80 { background-color: $white-80; }\n.bg-white-70 { background-color: $white-70; }\n.bg-white-60 { background-color: $white-60; }\n.bg-white-50 { background-color: $white-50; }\n.bg-white-40 { background-color: $white-40; }\n.bg-white-30 { background-color: $white-30; }\n.bg-white-20 { background-color: $white-20; }\n.bg-white-10 { background-color: $white-10; }\n\n\n\n/* Background colors */\n\n.bg-black { background-color: $black; }\n.bg-near-black { background-color: $near-black; }\n.bg-dark-gray { background-color: $dark-gray; }\n.bg-mid-gray { background-color: $mid-gray; }\n.bg-gray { background-color: $gray; }\n.bg-silver { background-color: $silver; }\n.bg-light-silver { background-color: $light-silver; }\n.bg-moon-gray { background-color: $moon-gray; }\n.bg-light-gray { background-color: $light-gray; }\n.bg-near-white { background-color: $near-white; }\n.bg-white { background-color: $white; }\n.bg-transparent { background-color: $transparent; }\n\n.bg-dark-red { background-color: $dark-red; }\n.bg-red { background-color: $red; }\n.bg-light-red { background-color: $light-red; }\n.bg-orange { background-color: $orange; }\n.bg-gold { background-color: $gold; }\n.bg-yellow { background-color: $yellow; }\n.bg-light-yellow { background-color: $light-yellow; }\n.bg-purple { background-color: $purple; }\n.bg-light-purple { background-color: $light-purple; }\n.bg-dark-pink { background-color: $dark-pink; }\n.bg-hot-pink { background-color: $hot-pink; }\n.bg-pink { background-color: $pink; }\n.bg-light-pink { background-color: $light-pink; }\n.bg-dark-green { background-color: $dark-green; }\n.bg-green { background-color: $green; }\n.bg-light-green { background-color: $light-green; }\n.bg-navy { background-color: $navy; }\n.bg-dark-blue { background-color: $dark-blue; }\n.bg-blue { background-color: $blue; }\n.bg-light-blue { background-color: $light-blue; }\n.bg-lightest-blue { background-color: $lightest-blue; }\n.bg-washed-blue { background-color: $washed-blue; }\n.bg-washed-green { background-color: $washed-green; }\n.bg-washed-yellow { background-color: $washed-yellow; }\n.bg-washed-red { background-color: $washed-red; }\n.bg-inherit { background-color: inherit; }\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n SKINS:PSEUDO\n\n Customize the color of an element when\n it is focused or hovered over.\n\n */\n\n.hover-black:hover,\n.hover-black:focus { color: $black; }\n.hover-near-black:hover,\n.hover-near-black:focus { color: $near-black; }\n.hover-dark-gray:hover,\n.hover-dark-gray:focus { color: $dark-gray; }\n.hover-mid-gray:hover,\n.hover-mid-gray:focus { color: $mid-gray; }\n.hover-gray:hover,\n.hover-gray:focus { color: $gray; }\n.hover-silver:hover,\n.hover-silver:focus { color: $silver; }\n.hover-light-silver:hover,\n.hover-light-silver:focus { color: $light-silver; }\n.hover-moon-gray:hover,\n.hover-moon-gray:focus { color: $moon-gray; }\n.hover-light-gray:hover,\n.hover-light-gray:focus { color: $light-gray; }\n.hover-near-white:hover,\n.hover-near-white:focus { color: $near-white; }\n.hover-white:hover,\n.hover-white:focus { color: $white; }\n\n.hover-black-90:hover,\n.hover-black-90:focus { color: $black-90; }\n.hover-black-80:hover,\n.hover-black-80:focus { color: $black-80; }\n.hover-black-70:hover,\n.hover-black-70:focus { color: $black-70; }\n.hover-black-60:hover,\n.hover-black-60:focus { color: $black-60; }\n.hover-black-50:hover,\n.hover-black-50:focus { color: $black-50; }\n.hover-black-40:hover,\n.hover-black-40:focus { color: $black-40; }\n.hover-black-30:hover,\n.hover-black-30:focus { color: $black-30; }\n.hover-black-20:hover,\n.hover-black-20:focus { color: $black-20; }\n.hover-black-10:hover,\n.hover-black-10:focus { color: $black-10; }\n.hover-white-90:hover,\n.hover-white-90:focus { color: $white-90; }\n.hover-white-80:hover,\n.hover-white-80:focus { color: $white-80; }\n.hover-white-70:hover,\n.hover-white-70:focus { color: $white-70; }\n.hover-white-60:hover,\n.hover-white-60:focus { color: $white-60; }\n.hover-white-50:hover,\n.hover-white-50:focus { color: $white-50; }\n.hover-white-40:hover,\n.hover-white-40:focus { color: $white-40; }\n.hover-white-30:hover,\n.hover-white-30:focus { color: $white-30; }\n.hover-white-20:hover,\n.hover-white-20:focus { color: $white-20; }\n.hover-white-10:hover,\n.hover-white-10:focus { color: $white-10; }\n.hover-inherit:hover,\n.hover-inherit:focus { color: inherit; }\n\n.hover-bg-black:hover,\n.hover-bg-black:focus { background-color: $black; }\n.hover-bg-near-black:hover,\n.hover-bg-near-black:focus { background-color: $near-black; }\n.hover-bg-dark-gray:hover,\n.hover-bg-dark-gray:focus { background-color: $dark-gray; }\n.hover-bg-mid-gray:hover,\n.hover-bg-mid-gray:focus { background-color: $mid-gray; }\n.hover-bg-gray:hover,\n.hover-bg-gray:focus { background-color: $gray; }\n.hover-bg-silver:hover,\n.hover-bg-silver:focus { background-color: $silver; }\n.hover-bg-light-silver:hover,\n.hover-bg-light-silver:focus { background-color: $light-silver; }\n.hover-bg-moon-gray:hover,\n.hover-bg-moon-gray:focus { background-color: $moon-gray; }\n.hover-bg-light-gray:hover,\n.hover-bg-light-gray:focus { background-color: $light-gray; }\n.hover-bg-near-white:hover,\n.hover-bg-near-white:focus { background-color: $near-white; }\n.hover-bg-white:hover,\n.hover-bg-white:focus { background-color: $white; }\n.hover-bg-transparent:hover,\n.hover-bg-transparent:focus { background-color: $transparent; }\n\n.hover-bg-black-90:hover,\n.hover-bg-black-90:focus { background-color: $black-90; }\n.hover-bg-black-80:hover,\n.hover-bg-black-80:focus { background-color: $black-80; }\n.hover-bg-black-70:hover,\n.hover-bg-black-70:focus { background-color: $black-70; }\n.hover-bg-black-60:hover,\n.hover-bg-black-60:focus { background-color: $black-60; }\n.hover-bg-black-50:hover,\n.hover-bg-black-50:focus { background-color: $black-50; }\n.hover-bg-black-40:hover,\n.hover-bg-black-40:focus { background-color: $black-40; }\n.hover-bg-black-30:hover,\n.hover-bg-black-30:focus { background-color: $black-30; }\n.hover-bg-black-20:hover,\n.hover-bg-black-20:focus { background-color: $black-20; }\n.hover-bg-black-10:hover,\n.hover-bg-black-10:focus { background-color: $black-10; }\n.hover-bg-white-90:hover,\n.hover-bg-white-90:focus { background-color: $white-90; }\n.hover-bg-white-80:hover,\n.hover-bg-white-80:focus { background-color: $white-80; }\n.hover-bg-white-70:hover,\n.hover-bg-white-70:focus { background-color: $white-70; }\n.hover-bg-white-60:hover,\n.hover-bg-white-60:focus { background-color: $white-60; }\n.hover-bg-white-50:hover,\n.hover-bg-white-50:focus { background-color: $white-50; }\n.hover-bg-white-40:hover,\n.hover-bg-white-40:focus { background-color: $white-40; }\n.hover-bg-white-30:hover,\n.hover-bg-white-30:focus { background-color: $white-30; }\n.hover-bg-white-20:hover,\n.hover-bg-white-20:focus { background-color: $white-20; }\n.hover-bg-white-10:hover,\n.hover-bg-white-10:focus { background-color: $white-10; }\n\n.hover-dark-red:hover,\n.hover-dark-red:focus { color: $dark-red; }\n.hover-red:hover,\n.hover-red:focus { color: $red; }\n.hover-light-red:hover,\n.hover-light-red:focus { color: $light-red; }\n.hover-orange:hover,\n.hover-orange:focus { color: $orange; }\n.hover-gold:hover,\n.hover-gold:focus { color: $gold; }\n.hover-yellow:hover,\n.hover-yellow:focus { color: $yellow; }\n.hover-light-yellow:hover,\n.hover-light-yellow:focus { color: $light-yellow; }\n.hover-purple:hover,\n.hover-purple:focus { color: $purple; }\n.hover-light-purple:hover,\n.hover-light-purple:focus { color: $light-purple; }\n.hover-dark-pink:hover,\n.hover-dark-pink:focus { color: $dark-pink; }\n.hover-hot-pink:hover,\n.hover-hot-pink:focus { color: $hot-pink; }\n.hover-pink:hover,\n.hover-pink:focus { color: $pink; }\n.hover-light-pink:hover,\n.hover-light-pink:focus { color: $light-pink; }\n.hover-dark-green:hover,\n.hover-dark-green:focus { color: $dark-green; }\n.hover-green:hover,\n.hover-green:focus { color: $green; }\n.hover-light-green:hover,\n.hover-light-green:focus { color: $light-green; }\n.hover-navy:hover,\n.hover-navy:focus { color: $navy; }\n.hover-dark-blue:hover,\n.hover-dark-blue:focus { color: $dark-blue; }\n.hover-blue:hover,\n.hover-blue:focus { color: $blue; }\n.hover-light-blue:hover,\n.hover-light-blue:focus { color: $light-blue; }\n.hover-lightest-blue:hover,\n.hover-lightest-blue:focus { color: $lightest-blue; }\n.hover-washed-blue:hover,\n.hover-washed-blue:focus { color: $washed-blue; }\n.hover-washed-green:hover,\n.hover-washed-green:focus { color: $washed-green; }\n.hover-washed-yellow:hover,\n.hover-washed-yellow:focus { color: $washed-yellow; }\n.hover-washed-red:hover,\n.hover-washed-red:focus { color: $washed-red; }\n\n.hover-bg-dark-red:hover,\n.hover-bg-dark-red:focus { background-color: $dark-red; }\n.hover-bg-red:hover,\n.hover-bg-red:focus { background-color: $red; }\n.hover-bg-light-red:hover,\n.hover-bg-light-red:focus { background-color: $light-red; }\n.hover-bg-orange:hover,\n.hover-bg-orange:focus { background-color: $orange; }\n.hover-bg-gold:hover,\n.hover-bg-gold:focus { background-color: $gold; }\n.hover-bg-yellow:hover,\n.hover-bg-yellow:focus { background-color: $yellow; }\n.hover-bg-light-yellow:hover,\n.hover-bg-light-yellow:focus { background-color: $light-yellow; }\n.hover-bg-purple:hover,\n.hover-bg-purple:focus { background-color: $purple; }\n.hover-bg-light-purple:hover,\n.hover-bg-light-purple:focus { background-color: $light-purple; }\n.hover-bg-dark-pink:hover,\n.hover-bg-dark-pink:focus { background-color: $dark-pink; }\n.hover-bg-hot-pink:hover,\n.hover-bg-hot-pink:focus { background-color: $hot-pink; }\n.hover-bg-pink:hover,\n.hover-bg-pink:focus { background-color: $pink; }\n.hover-bg-light-pink:hover,\n.hover-bg-light-pink:focus { background-color: $light-pink; }\n.hover-bg-dark-green:hover,\n.hover-bg-dark-green:focus { background-color: $dark-green; }\n.hover-bg-green:hover,\n.hover-bg-green:focus { background-color: $green; }\n.hover-bg-light-green:hover,\n.hover-bg-light-green:focus { background-color: $light-green; }\n.hover-bg-navy:hover,\n.hover-bg-navy:focus { background-color: $navy; }\n.hover-bg-dark-blue:hover,\n.hover-bg-dark-blue:focus { background-color: $dark-blue; }\n.hover-bg-blue:hover,\n.hover-bg-blue:focus { background-color: $blue; }\n.hover-bg-light-blue:hover,\n.hover-bg-light-blue:focus { background-color: $light-blue; }\n.hover-bg-lightest-blue:hover,\n.hover-bg-lightest-blue:focus { background-color: $lightest-blue; }\n.hover-bg-washed-blue:hover,\n.hover-bg-washed-blue:focus { background-color: $washed-blue; }\n.hover-bg-washed-green:hover,\n.hover-bg-washed-green:focus { background-color: $washed-green; }\n.hover-bg-washed-yellow:hover,\n.hover-bg-washed-yellow:focus { background-color: $washed-yellow; }\n.hover-bg-washed-red:hover,\n.hover-bg-washed-red:focus { background-color: $washed-red; }\n.hover-bg-inherit:hover,\n.hover-bg-inherit:focus { background-color: inherit; }\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/* Variables */\n\n/*\n SPACING\n Docs: http://tachyons.io/docs/layout/spacing/\n\n An eight step powers of two scale ranging from 0 to 16rem.\n\n Base:\n p = padding\n m = margin\n\n Modifiers:\n a = all\n h = horizontal\n v = vertical\n t = top\n r = right\n b = bottom\n l = left\n\n 0 = none\n 1 = 1st step in spacing scale\n 2 = 2nd step in spacing scale\n 3 = 3rd step in spacing scale\n 4 = 4th step in spacing scale\n 5 = 5th step in spacing scale\n 6 = 6th step in spacing scale\n 7 = 7th step in spacing scale\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n\n.pa0 { padding: $spacing-none; }\n.pa1 { padding: $spacing-extra-small; }\n.pa2 { padding: $spacing-small; }\n.pa3 { padding: $spacing-medium; }\n.pa4 { padding: $spacing-large; }\n.pa5 { padding: $spacing-extra-large; }\n.pa6 { padding: $spacing-extra-extra-large; }\n.pa7 { padding: $spacing-extra-extra-extra-large; }\n\n.pl0 { padding-left: $spacing-none; }\n.pl1 { padding-left: $spacing-extra-small; }\n.pl2 { padding-left: $spacing-small; }\n.pl3 { padding-left: $spacing-medium; }\n.pl4 { padding-left: $spacing-large; }\n.pl5 { padding-left: $spacing-extra-large; }\n.pl6 { padding-left: $spacing-extra-extra-large; }\n.pl7 { padding-left: $spacing-extra-extra-extra-large; }\n\n.pr0 { padding-right: $spacing-none; }\n.pr1 { padding-right: $spacing-extra-small; }\n.pr2 { padding-right: $spacing-small; }\n.pr3 { padding-right: $spacing-medium; }\n.pr4 { padding-right: $spacing-large; }\n.pr5 { padding-right: $spacing-extra-large; }\n.pr6 { padding-right: $spacing-extra-extra-large; }\n.pr7 { padding-right: $spacing-extra-extra-extra-large; }\n\n.pb0 { padding-bottom: $spacing-none; }\n.pb1 { padding-bottom: $spacing-extra-small; }\n.pb2 { padding-bottom: $spacing-small; }\n.pb3 { padding-bottom: $spacing-medium; }\n.pb4 { padding-bottom: $spacing-large; }\n.pb5 { padding-bottom: $spacing-extra-large; }\n.pb6 { padding-bottom: $spacing-extra-extra-large; }\n.pb7 { padding-bottom: $spacing-extra-extra-extra-large; }\n\n.pt0 { padding-top: $spacing-none; }\n.pt1 { padding-top: $spacing-extra-small; }\n.pt2 { padding-top: $spacing-small; }\n.pt3 { padding-top: $spacing-medium; }\n.pt4 { padding-top: $spacing-large; }\n.pt5 { padding-top: $spacing-extra-large; }\n.pt6 { padding-top: $spacing-extra-extra-large; }\n.pt7 { padding-top: $spacing-extra-extra-extra-large; }\n\n.pv0 {\n padding-top: $spacing-none;\n padding-bottom: $spacing-none;\n}\n.pv1 {\n padding-top: $spacing-extra-small;\n padding-bottom: $spacing-extra-small;\n}\n.pv2 {\n padding-top: $spacing-small;\n padding-bottom: $spacing-small;\n}\n.pv3 {\n padding-top: $spacing-medium;\n padding-bottom: $spacing-medium;\n}\n.pv4 {\n padding-top: $spacing-large;\n padding-bottom: $spacing-large;\n}\n.pv5 {\n padding-top: $spacing-extra-large;\n padding-bottom: $spacing-extra-large;\n}\n.pv6 {\n padding-top: $spacing-extra-extra-large;\n padding-bottom: $spacing-extra-extra-large;\n}\n\n.pv7 {\n padding-top: $spacing-extra-extra-extra-large;\n padding-bottom: $spacing-extra-extra-extra-large;\n}\n\n.ph0 {\n padding-left: $spacing-none;\n padding-right: $spacing-none;\n}\n\n.ph1 {\n padding-left: $spacing-extra-small;\n padding-right: $spacing-extra-small;\n}\n\n.ph2 {\n padding-left: $spacing-small;\n padding-right: $spacing-small;\n}\n\n.ph3 {\n padding-left: $spacing-medium;\n padding-right: $spacing-medium;\n}\n\n.ph4 {\n padding-left: $spacing-large;\n padding-right: $spacing-large;\n}\n\n.ph5 {\n padding-left: $spacing-extra-large;\n padding-right: $spacing-extra-large;\n}\n\n.ph6 {\n padding-left: $spacing-extra-extra-large;\n padding-right: $spacing-extra-extra-large;\n}\n\n.ph7 {\n padding-left: $spacing-extra-extra-extra-large;\n padding-right: $spacing-extra-extra-extra-large;\n}\n\n.ma0 { margin: $spacing-none; }\n.ma1 { margin: $spacing-extra-small; }\n.ma2 { margin: $spacing-small; }\n.ma3 { margin: $spacing-medium; }\n.ma4 { margin: $spacing-large; }\n.ma5 { margin: $spacing-extra-large; }\n.ma6 { margin: $spacing-extra-extra-large; }\n.ma7 { margin: $spacing-extra-extra-extra-large; }\n\n.ml0 { margin-left: $spacing-none; }\n.ml1 { margin-left: $spacing-extra-small; }\n.ml2 { margin-left: $spacing-small; }\n.ml3 { margin-left: $spacing-medium; }\n.ml4 { margin-left: $spacing-large; }\n.ml5 { margin-left: $spacing-extra-large; }\n.ml6 { margin-left: $spacing-extra-extra-large; }\n.ml7 { margin-left: $spacing-extra-extra-extra-large; }\n\n.mr0 { margin-right: $spacing-none; }\n.mr1 { margin-right: $spacing-extra-small; }\n.mr2 { margin-right: $spacing-small; }\n.mr3 { margin-right: $spacing-medium; }\n.mr4 { margin-right: $spacing-large; }\n.mr5 { margin-right: $spacing-extra-large; }\n.mr6 { margin-right: $spacing-extra-extra-large; }\n.mr7 { margin-right: $spacing-extra-extra-extra-large; }\n\n.mb0 { margin-bottom: $spacing-none; }\n.mb1 { margin-bottom: $spacing-extra-small; }\n.mb2 { margin-bottom: $spacing-small; }\n.mb3 { margin-bottom: $spacing-medium; }\n.mb4 { margin-bottom: $spacing-large; }\n.mb5 { margin-bottom: $spacing-extra-large; }\n.mb6 { margin-bottom: $spacing-extra-extra-large; }\n.mb7 { margin-bottom: $spacing-extra-extra-extra-large; }\n\n.mt0 { margin-top: $spacing-none; }\n.mt1 { margin-top: $spacing-extra-small; }\n.mt2 { margin-top: $spacing-small; }\n.mt3 { margin-top: $spacing-medium; }\n.mt4 { margin-top: $spacing-large; }\n.mt5 { margin-top: $spacing-extra-large; }\n.mt6 { margin-top: $spacing-extra-extra-large; }\n.mt7 { margin-top: $spacing-extra-extra-extra-large; }\n\n.mv0 {\n margin-top: $spacing-none;\n margin-bottom: $spacing-none;\n}\n.mv1 {\n margin-top: $spacing-extra-small;\n margin-bottom: $spacing-extra-small;\n}\n.mv2 {\n margin-top: $spacing-small;\n margin-bottom: $spacing-small;\n}\n.mv3 {\n margin-top: $spacing-medium;\n margin-bottom: $spacing-medium;\n}\n.mv4 {\n margin-top: $spacing-large;\n margin-bottom: $spacing-large;\n}\n.mv5 {\n margin-top: $spacing-extra-large;\n margin-bottom: $spacing-extra-large;\n}\n.mv6 {\n margin-top: $spacing-extra-extra-large;\n margin-bottom: $spacing-extra-extra-large;\n}\n.mv7 {\n margin-top: $spacing-extra-extra-extra-large;\n margin-bottom: $spacing-extra-extra-extra-large;\n}\n\n.mh0 {\n margin-left: $spacing-none;\n margin-right: $spacing-none;\n}\n.mh1 {\n margin-left: $spacing-extra-small;\n margin-right: $spacing-extra-small;\n}\n.mh2 {\n margin-left: $spacing-small;\n margin-right: $spacing-small;\n}\n.mh3 {\n margin-left: $spacing-medium;\n margin-right: $spacing-medium;\n}\n.mh4 {\n margin-left: $spacing-large;\n margin-right: $spacing-large;\n}\n.mh5 {\n margin-left: $spacing-extra-large;\n margin-right: $spacing-extra-large;\n}\n.mh6 {\n margin-left: $spacing-extra-extra-large;\n margin-right: $spacing-extra-extra-large;\n}\n.mh7 {\n margin-left: $spacing-extra-extra-extra-large;\n margin-right: $spacing-extra-extra-extra-large;\n}\n\n@media #{$breakpoint-not-small} {\n .pa0-ns { padding: $spacing-none; }\n .pa1-ns { padding: $spacing-extra-small; }\n .pa2-ns { padding: $spacing-small; }\n .pa3-ns { padding: $spacing-medium; }\n .pa4-ns { padding: $spacing-large; }\n .pa5-ns { padding: $spacing-extra-large; }\n .pa6-ns { padding: $spacing-extra-extra-large; }\n .pa7-ns { padding: $spacing-extra-extra-extra-large; }\n\n .pl0-ns { padding-left: $spacing-none; }\n .pl1-ns { padding-left: $spacing-extra-small; }\n .pl2-ns { padding-left: $spacing-small; }\n .pl3-ns { padding-left: $spacing-medium; }\n .pl4-ns { padding-left: $spacing-large; }\n .pl5-ns { padding-left: $spacing-extra-large; }\n .pl6-ns { padding-left: $spacing-extra-extra-large; }\n .pl7-ns { padding-left: $spacing-extra-extra-extra-large; }\n\n .pr0-ns { padding-right: $spacing-none; }\n .pr1-ns { padding-right: $spacing-extra-small; }\n .pr2-ns { padding-right: $spacing-small; }\n .pr3-ns { padding-right: $spacing-medium; }\n .pr4-ns { padding-right: $spacing-large; }\n .pr5-ns { padding-right: $spacing-extra-large; }\n .pr6-ns { padding-right: $spacing-extra-extra-large; }\n .pr7-ns { padding-right: $spacing-extra-extra-extra-large; }\n\n .pb0-ns { padding-bottom: $spacing-none; }\n .pb1-ns { padding-bottom: $spacing-extra-small; }\n .pb2-ns { padding-bottom: $spacing-small; }\n .pb3-ns { padding-bottom: $spacing-medium; }\n .pb4-ns { padding-bottom: $spacing-large; }\n .pb5-ns { padding-bottom: $spacing-extra-large; }\n .pb6-ns { padding-bottom: $spacing-extra-extra-large; }\n .pb7-ns { padding-bottom: $spacing-extra-extra-extra-large; }\n\n .pt0-ns { padding-top: $spacing-none; }\n .pt1-ns { padding-top: $spacing-extra-small; }\n .pt2-ns { padding-top: $spacing-small; }\n .pt3-ns { padding-top: $spacing-medium; }\n .pt4-ns { padding-top: $spacing-large; }\n .pt5-ns { padding-top: $spacing-extra-large; }\n .pt6-ns { padding-top: $spacing-extra-extra-large; }\n .pt7-ns { padding-top: $spacing-extra-extra-extra-large; }\n\n .pv0-ns {\n padding-top: $spacing-none;\n padding-bottom: $spacing-none;\n }\n .pv1-ns {\n padding-top: $spacing-extra-small;\n padding-bottom: $spacing-extra-small;\n }\n .pv2-ns {\n padding-top: $spacing-small;\n padding-bottom: $spacing-small;\n }\n .pv3-ns {\n padding-top: $spacing-medium;\n padding-bottom: $spacing-medium;\n }\n .pv4-ns {\n padding-top: $spacing-large;\n padding-bottom: $spacing-large;\n }\n .pv5-ns {\n padding-top: $spacing-extra-large;\n padding-bottom: $spacing-extra-large;\n }\n .pv6-ns {\n padding-top: $spacing-extra-extra-large;\n padding-bottom: $spacing-extra-extra-large;\n }\n .pv7-ns {\n padding-top: $spacing-extra-extra-extra-large;\n padding-bottom: $spacing-extra-extra-extra-large;\n }\n .ph0-ns {\n padding-left: $spacing-none;\n padding-right: $spacing-none;\n }\n .ph1-ns {\n padding-left: $spacing-extra-small;\n padding-right: $spacing-extra-small;\n }\n .ph2-ns {\n padding-left: $spacing-small;\n padding-right: $spacing-small;\n }\n .ph3-ns {\n padding-left: $spacing-medium;\n padding-right: $spacing-medium;\n }\n .ph4-ns {\n padding-left: $spacing-large;\n padding-right: $spacing-large;\n }\n .ph5-ns {\n padding-left: $spacing-extra-large;\n padding-right: $spacing-extra-large;\n }\n .ph6-ns {\n padding-left: $spacing-extra-extra-large;\n padding-right: $spacing-extra-extra-large;\n }\n .ph7-ns {\n padding-left: $spacing-extra-extra-extra-large;\n padding-right: $spacing-extra-extra-extra-large;\n }\n\n .ma0-ns { margin: $spacing-none; }\n .ma1-ns { margin: $spacing-extra-small; }\n .ma2-ns { margin: $spacing-small; }\n .ma3-ns { margin: $spacing-medium; }\n .ma4-ns { margin: $spacing-large; }\n .ma5-ns { margin: $spacing-extra-large; }\n .ma6-ns { margin: $spacing-extra-extra-large; }\n .ma7-ns { margin: $spacing-extra-extra-extra-large; }\n\n .ml0-ns { margin-left: $spacing-none; }\n .ml1-ns { margin-left: $spacing-extra-small; }\n .ml2-ns { margin-left: $spacing-small; }\n .ml3-ns { margin-left: $spacing-medium; }\n .ml4-ns { margin-left: $spacing-large; }\n .ml5-ns { margin-left: $spacing-extra-large; }\n .ml6-ns { margin-left: $spacing-extra-extra-large; }\n .ml7-ns { margin-left: $spacing-extra-extra-extra-large; }\n\n .mr0-ns { margin-right: $spacing-none; }\n .mr1-ns { margin-right: $spacing-extra-small; }\n .mr2-ns { margin-right: $spacing-small; }\n .mr3-ns { margin-right: $spacing-medium; }\n .mr4-ns { margin-right: $spacing-large; }\n .mr5-ns { margin-right: $spacing-extra-large; }\n .mr6-ns { margin-right: $spacing-extra-extra-large; }\n .mr7-ns { margin-right: $spacing-extra-extra-extra-large; }\n\n .mb0-ns { margin-bottom: $spacing-none; }\n .mb1-ns { margin-bottom: $spacing-extra-small; }\n .mb2-ns { margin-bottom: $spacing-small; }\n .mb3-ns { margin-bottom: $spacing-medium; }\n .mb4-ns { margin-bottom: $spacing-large; }\n .mb5-ns { margin-bottom: $spacing-extra-large; }\n .mb6-ns { margin-bottom: $spacing-extra-extra-large; }\n .mb7-ns { margin-bottom: $spacing-extra-extra-extra-large; }\n\n .mt0-ns { margin-top: $spacing-none; }\n .mt1-ns { margin-top: $spacing-extra-small; }\n .mt2-ns { margin-top: $spacing-small; }\n .mt3-ns { margin-top: $spacing-medium; }\n .mt4-ns { margin-top: $spacing-large; }\n .mt5-ns { margin-top: $spacing-extra-large; }\n .mt6-ns { margin-top: $spacing-extra-extra-large; }\n .mt7-ns { margin-top: $spacing-extra-extra-extra-large; }\n\n .mv0-ns {\n margin-top: $spacing-none;\n margin-bottom: $spacing-none;\n }\n .mv1-ns {\n margin-top: $spacing-extra-small;\n margin-bottom: $spacing-extra-small;\n }\n .mv2-ns {\n margin-top: $spacing-small;\n margin-bottom: $spacing-small;\n }\n .mv3-ns {\n margin-top: $spacing-medium;\n margin-bottom: $spacing-medium;\n }\n .mv4-ns {\n margin-top: $spacing-large;\n margin-bottom: $spacing-large;\n }\n .mv5-ns {\n margin-top: $spacing-extra-large;\n margin-bottom: $spacing-extra-large;\n }\n .mv6-ns {\n margin-top: $spacing-extra-extra-large;\n margin-bottom: $spacing-extra-extra-large;\n }\n .mv7-ns {\n margin-top: $spacing-extra-extra-extra-large;\n margin-bottom: $spacing-extra-extra-extra-large;\n }\n\n .mh0-ns {\n margin-left: $spacing-none;\n margin-right: $spacing-none;\n }\n .mh1-ns {\n margin-left: $spacing-extra-small;\n margin-right: $spacing-extra-small;\n }\n .mh2-ns {\n margin-left: $spacing-small;\n margin-right: $spacing-small;\n }\n .mh3-ns {\n margin-left: $spacing-medium;\n margin-right: $spacing-medium;\n }\n .mh4-ns {\n margin-left: $spacing-large;\n margin-right: $spacing-large;\n }\n .mh5-ns {\n margin-left: $spacing-extra-large;\n margin-right: $spacing-extra-large;\n }\n .mh6-ns {\n margin-left: $spacing-extra-extra-large;\n margin-right: $spacing-extra-extra-large;\n }\n .mh7-ns {\n margin-left: $spacing-extra-extra-extra-large;\n margin-right: $spacing-extra-extra-extra-large;\n }\n\n}\n\n@media #{$breakpoint-medium} {\n .pa0-m { padding: $spacing-none; }\n .pa1-m { padding: $spacing-extra-small; }\n .pa2-m { padding: $spacing-small; }\n .pa3-m { padding: $spacing-medium; }\n .pa4-m { padding: $spacing-large; }\n .pa5-m { padding: $spacing-extra-large; }\n .pa6-m { padding: $spacing-extra-extra-large; }\n .pa7-m { padding: $spacing-extra-extra-extra-large; }\n\n .pl0-m { padding-left: $spacing-none; }\n .pl1-m { padding-left: $spacing-extra-small; }\n .pl2-m { padding-left: $spacing-small; }\n .pl3-m { padding-left: $spacing-medium; }\n .pl4-m { padding-left: $spacing-large; }\n .pl5-m { padding-left: $spacing-extra-large; }\n .pl6-m { padding-left: $spacing-extra-extra-large; }\n .pl7-m { padding-left: $spacing-extra-extra-extra-large; }\n\n .pr0-m { padding-right: $spacing-none; }\n .pr1-m { padding-right: $spacing-extra-small; }\n .pr2-m { padding-right: $spacing-small; }\n .pr3-m { padding-right: $spacing-medium; }\n .pr4-m { padding-right: $spacing-large; }\n .pr5-m { padding-right: $spacing-extra-large; }\n .pr6-m { padding-right: $spacing-extra-extra-large; }\n .pr7-m { padding-right: $spacing-extra-extra-extra-large; }\n\n .pb0-m { padding-bottom: $spacing-none; }\n .pb1-m { padding-bottom: $spacing-extra-small; }\n .pb2-m { padding-bottom: $spacing-small; }\n .pb3-m { padding-bottom: $spacing-medium; }\n .pb4-m { padding-bottom: $spacing-large; }\n .pb5-m { padding-bottom: $spacing-extra-large; }\n .pb6-m { padding-bottom: $spacing-extra-extra-large; }\n .pb7-m { padding-bottom: $spacing-extra-extra-extra-large; }\n\n .pt0-m { padding-top: $spacing-none; }\n .pt1-m { padding-top: $spacing-extra-small; }\n .pt2-m { padding-top: $spacing-small; }\n .pt3-m { padding-top: $spacing-medium; }\n .pt4-m { padding-top: $spacing-large; }\n .pt5-m { padding-top: $spacing-extra-large; }\n .pt6-m { padding-top: $spacing-extra-extra-large; }\n .pt7-m { padding-top: $spacing-extra-extra-extra-large; }\n\n .pv0-m {\n padding-top: $spacing-none;\n padding-bottom: $spacing-none;\n }\n .pv1-m {\n padding-top: $spacing-extra-small;\n padding-bottom: $spacing-extra-small;\n }\n .pv2-m {\n padding-top: $spacing-small;\n padding-bottom: $spacing-small;\n }\n .pv3-m {\n padding-top: $spacing-medium;\n padding-bottom: $spacing-medium;\n }\n .pv4-m {\n padding-top: $spacing-large;\n padding-bottom: $spacing-large;\n }\n .pv5-m {\n padding-top: $spacing-extra-large;\n padding-bottom: $spacing-extra-large;\n }\n .pv6-m {\n padding-top: $spacing-extra-extra-large;\n padding-bottom: $spacing-extra-extra-large;\n }\n .pv7-m {\n padding-top: $spacing-extra-extra-extra-large;\n padding-bottom: $spacing-extra-extra-extra-large;\n }\n\n .ph0-m {\n padding-left: $spacing-none;\n padding-right: $spacing-none;\n }\n .ph1-m {\n padding-left: $spacing-extra-small;\n padding-right: $spacing-extra-small;\n }\n .ph2-m {\n padding-left: $spacing-small;\n padding-right: $spacing-small;\n }\n .ph3-m {\n padding-left: $spacing-medium;\n padding-right: $spacing-medium;\n }\n .ph4-m {\n padding-left: $spacing-large;\n padding-right: $spacing-large;\n }\n .ph5-m {\n padding-left: $spacing-extra-large;\n padding-right: $spacing-extra-large;\n }\n .ph6-m {\n padding-left: $spacing-extra-extra-large;\n padding-right: $spacing-extra-extra-large;\n }\n .ph7-m {\n padding-left: $spacing-extra-extra-extra-large;\n padding-right: $spacing-extra-extra-extra-large;\n }\n\n .ma0-m { margin: $spacing-none; }\n .ma1-m { margin: $spacing-extra-small; }\n .ma2-m { margin: $spacing-small; }\n .ma3-m { margin: $spacing-medium; }\n .ma4-m { margin: $spacing-large; }\n .ma5-m { margin: $spacing-extra-large; }\n .ma6-m { margin: $spacing-extra-extra-large; }\n .ma7-m { margin: $spacing-extra-extra-extra-large; }\n\n .ml0-m { margin-left: $spacing-none; }\n .ml1-m { margin-left: $spacing-extra-small; }\n .ml2-m { margin-left: $spacing-small; }\n .ml3-m { margin-left: $spacing-medium; }\n .ml4-m { margin-left: $spacing-large; }\n .ml5-m { margin-left: $spacing-extra-large; }\n .ml6-m { margin-left: $spacing-extra-extra-large; }\n .ml7-m { margin-left: $spacing-extra-extra-extra-large; }\n\n .mr0-m { margin-right: $spacing-none; }\n .mr1-m { margin-right: $spacing-extra-small; }\n .mr2-m { margin-right: $spacing-small; }\n .mr3-m { margin-right: $spacing-medium; }\n .mr4-m { margin-right: $spacing-large; }\n .mr5-m { margin-right: $spacing-extra-large; }\n .mr6-m { margin-right: $spacing-extra-extra-large; }\n .mr7-m { margin-right: $spacing-extra-extra-extra-large; }\n\n .mb0-m { margin-bottom: $spacing-none; }\n .mb1-m { margin-bottom: $spacing-extra-small; }\n .mb2-m { margin-bottom: $spacing-small; }\n .mb3-m { margin-bottom: $spacing-medium; }\n .mb4-m { margin-bottom: $spacing-large; }\n .mb5-m { margin-bottom: $spacing-extra-large; }\n .mb6-m { margin-bottom: $spacing-extra-extra-large; }\n .mb7-m { margin-bottom: $spacing-extra-extra-extra-large; }\n\n .mt0-m { margin-top: $spacing-none; }\n .mt1-m { margin-top: $spacing-extra-small; }\n .mt2-m { margin-top: $spacing-small; }\n .mt3-m { margin-top: $spacing-medium; }\n .mt4-m { margin-top: $spacing-large; }\n .mt5-m { margin-top: $spacing-extra-large; }\n .mt6-m { margin-top: $spacing-extra-extra-large; }\n .mt7-m { margin-top: $spacing-extra-extra-extra-large; }\n\n .mv0-m {\n margin-top: $spacing-none;\n margin-bottom: $spacing-none;\n }\n .mv1-m {\n margin-top: $spacing-extra-small;\n margin-bottom: $spacing-extra-small;\n }\n .mv2-m {\n margin-top: $spacing-small;\n margin-bottom: $spacing-small;\n }\n .mv3-m {\n margin-top: $spacing-medium;\n margin-bottom: $spacing-medium;\n }\n .mv4-m {\n margin-top: $spacing-large;\n margin-bottom: $spacing-large;\n }\n .mv5-m {\n margin-top: $spacing-extra-large;\n margin-bottom: $spacing-extra-large;\n }\n .mv6-m {\n margin-top: $spacing-extra-extra-large;\n margin-bottom: $spacing-extra-extra-large;\n }\n .mv7-m {\n margin-top: $spacing-extra-extra-extra-large;\n margin-bottom: $spacing-extra-extra-extra-large;\n }\n\n .mh0-m {\n margin-left: $spacing-none;\n margin-right: $spacing-none;\n }\n .mh1-m {\n margin-left: $spacing-extra-small;\n margin-right: $spacing-extra-small;\n }\n .mh2-m {\n margin-left: $spacing-small;\n margin-right: $spacing-small;\n }\n .mh3-m {\n margin-left: $spacing-medium;\n margin-right: $spacing-medium;\n }\n .mh4-m {\n margin-left: $spacing-large;\n margin-right: $spacing-large;\n }\n .mh5-m {\n margin-left: $spacing-extra-large;\n margin-right: $spacing-extra-large;\n }\n .mh6-m {\n margin-left: $spacing-extra-extra-large;\n margin-right: $spacing-extra-extra-large;\n }\n .mh7-m {\n margin-left: $spacing-extra-extra-extra-large;\n margin-right: $spacing-extra-extra-extra-large;\n }\n\n}\n\n@media #{$breakpoint-large} {\n .pa0-l { padding: $spacing-none; }\n .pa1-l { padding: $spacing-extra-small; }\n .pa2-l { padding: $spacing-small; }\n .pa3-l { padding: $spacing-medium; }\n .pa4-l { padding: $spacing-large; }\n .pa5-l { padding: $spacing-extra-large; }\n .pa6-l { padding: $spacing-extra-extra-large; }\n .pa7-l { padding: $spacing-extra-extra-extra-large; }\n\n .pl0-l { padding-left: $spacing-none; }\n .pl1-l { padding-left: $spacing-extra-small; }\n .pl2-l { padding-left: $spacing-small; }\n .pl3-l { padding-left: $spacing-medium; }\n .pl4-l { padding-left: $spacing-large; }\n .pl5-l { padding-left: $spacing-extra-large; }\n .pl6-l { padding-left: $spacing-extra-extra-large; }\n .pl7-l { padding-left: $spacing-extra-extra-extra-large; }\n\n .pr0-l { padding-right: $spacing-none; }\n .pr1-l { padding-right: $spacing-extra-small; }\n .pr2-l { padding-right: $spacing-small; }\n .pr3-l { padding-right: $spacing-medium; }\n .pr4-l { padding-right: $spacing-large; }\n .pr5-l { padding-right: $spacing-extra-large; }\n .pr6-l { padding-right: $spacing-extra-extra-large; }\n .pr7-l { padding-right: $spacing-extra-extra-extra-large; }\n\n .pb0-l { padding-bottom: $spacing-none; }\n .pb1-l { padding-bottom: $spacing-extra-small; }\n .pb2-l { padding-bottom: $spacing-small; }\n .pb3-l { padding-bottom: $spacing-medium; }\n .pb4-l { padding-bottom: $spacing-large; }\n .pb5-l { padding-bottom: $spacing-extra-large; }\n .pb6-l { padding-bottom: $spacing-extra-extra-large; }\n .pb7-l { padding-bottom: $spacing-extra-extra-extra-large; }\n\n .pt0-l { padding-top: $spacing-none; }\n .pt1-l { padding-top: $spacing-extra-small; }\n .pt2-l { padding-top: $spacing-small; }\n .pt3-l { padding-top: $spacing-medium; }\n .pt4-l { padding-top: $spacing-large; }\n .pt5-l { padding-top: $spacing-extra-large; }\n .pt6-l { padding-top: $spacing-extra-extra-large; }\n .pt7-l { padding-top: $spacing-extra-extra-extra-large; }\n\n .pv0-l {\n padding-top: $spacing-none;\n padding-bottom: $spacing-none;\n }\n .pv1-l {\n padding-top: $spacing-extra-small;\n padding-bottom: $spacing-extra-small;\n }\n .pv2-l {\n padding-top: $spacing-small;\n padding-bottom: $spacing-small;\n }\n .pv3-l {\n padding-top: $spacing-medium;\n padding-bottom: $spacing-medium;\n }\n .pv4-l {\n padding-top: $spacing-large;\n padding-bottom: $spacing-large;\n }\n .pv5-l {\n padding-top: $spacing-extra-large;\n padding-bottom: $spacing-extra-large;\n }\n .pv6-l {\n padding-top: $spacing-extra-extra-large;\n padding-bottom: $spacing-extra-extra-large;\n }\n .pv7-l {\n padding-top: $spacing-extra-extra-extra-large;\n padding-bottom: $spacing-extra-extra-extra-large;\n }\n\n .ph0-l {\n padding-left: $spacing-none;\n padding-right: $spacing-none;\n }\n .ph1-l {\n padding-left: $spacing-extra-small;\n padding-right: $spacing-extra-small;\n }\n .ph2-l {\n padding-left: $spacing-small;\n padding-right: $spacing-small;\n }\n .ph3-l {\n padding-left: $spacing-medium;\n padding-right: $spacing-medium;\n }\n .ph4-l {\n padding-left: $spacing-large;\n padding-right: $spacing-large;\n }\n .ph5-l {\n padding-left: $spacing-extra-large;\n padding-right: $spacing-extra-large;\n }\n .ph6-l {\n padding-left: $spacing-extra-extra-large;\n padding-right: $spacing-extra-extra-large;\n }\n .ph7-l {\n padding-left: $spacing-extra-extra-extra-large;\n padding-right: $spacing-extra-extra-extra-large;\n }\n\n .ma0-l { margin: $spacing-none; }\n .ma1-l { margin: $spacing-extra-small; }\n .ma2-l { margin: $spacing-small; }\n .ma3-l { margin: $spacing-medium; }\n .ma4-l { margin: $spacing-large; }\n .ma5-l { margin: $spacing-extra-large; }\n .ma6-l { margin: $spacing-extra-extra-large; }\n .ma7-l { margin: $spacing-extra-extra-extra-large; }\n\n .ml0-l { margin-left: $spacing-none; }\n .ml1-l { margin-left: $spacing-extra-small; }\n .ml2-l { margin-left: $spacing-small; }\n .ml3-l { margin-left: $spacing-medium; }\n .ml4-l { margin-left: $spacing-large; }\n .ml5-l { margin-left: $spacing-extra-large; }\n .ml6-l { margin-left: $spacing-extra-extra-large; }\n .ml7-l { margin-left: $spacing-extra-extra-extra-large; }\n\n .mr0-l { margin-right: $spacing-none; }\n .mr1-l { margin-right: $spacing-extra-small; }\n .mr2-l { margin-right: $spacing-small; }\n .mr3-l { margin-right: $spacing-medium; }\n .mr4-l { margin-right: $spacing-large; }\n .mr5-l { margin-right: $spacing-extra-large; }\n .mr6-l { margin-right: $spacing-extra-extra-large; }\n .mr7-l { margin-right: $spacing-extra-extra-extra-large; }\n\n .mb0-l { margin-bottom: $spacing-none; }\n .mb1-l { margin-bottom: $spacing-extra-small; }\n .mb2-l { margin-bottom: $spacing-small; }\n .mb3-l { margin-bottom: $spacing-medium; }\n .mb4-l { margin-bottom: $spacing-large; }\n .mb5-l { margin-bottom: $spacing-extra-large; }\n .mb6-l { margin-bottom: $spacing-extra-extra-large; }\n .mb7-l { margin-bottom: $spacing-extra-extra-extra-large; }\n\n .mt0-l { margin-top: $spacing-none; }\n .mt1-l { margin-top: $spacing-extra-small; }\n .mt2-l { margin-top: $spacing-small; }\n .mt3-l { margin-top: $spacing-medium; }\n .mt4-l { margin-top: $spacing-large; }\n .mt5-l { margin-top: $spacing-extra-large; }\n .mt6-l { margin-top: $spacing-extra-extra-large; }\n .mt7-l { margin-top: $spacing-extra-extra-extra-large; }\n\n .mv0-l {\n margin-top: $spacing-none;\n margin-bottom: $spacing-none;\n }\n .mv1-l {\n margin-top: $spacing-extra-small;\n margin-bottom: $spacing-extra-small;\n }\n .mv2-l {\n margin-top: $spacing-small;\n margin-bottom: $spacing-small;\n }\n .mv3-l {\n margin-top: $spacing-medium;\n margin-bottom: $spacing-medium;\n }\n .mv4-l {\n margin-top: $spacing-large;\n margin-bottom: $spacing-large;\n }\n .mv5-l {\n margin-top: $spacing-extra-large;\n margin-bottom: $spacing-extra-large;\n }\n .mv6-l {\n margin-top: $spacing-extra-extra-large;\n margin-bottom: $spacing-extra-extra-large;\n }\n .mv7-l {\n margin-top: $spacing-extra-extra-extra-large;\n margin-bottom: $spacing-extra-extra-extra-large;\n }\n\n .mh0-l {\n margin-left: $spacing-none;\n margin-right: $spacing-none;\n }\n .mh1-l {\n margin-left: $spacing-extra-small;\n margin-right: $spacing-extra-small;\n }\n .mh2-l {\n margin-left: $spacing-small;\n margin-right: $spacing-small;\n }\n .mh3-l {\n margin-left: $spacing-medium;\n margin-right: $spacing-medium;\n }\n .mh4-l {\n margin-left: $spacing-large;\n margin-right: $spacing-large;\n }\n .mh5-l {\n margin-left: $spacing-extra-large;\n margin-right: $spacing-extra-large;\n }\n .mh6-l {\n margin-left: $spacing-extra-extra-large;\n margin-right: $spacing-extra-extra-large;\n }\n .mh7-l {\n margin-left: $spacing-extra-extra-extra-large;\n margin-right: $spacing-extra-extra-extra-large;\n }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n NEGATIVE MARGINS\n\n Base:\n n = negative\n\n Modifiers:\n a = all\n t = top\n r = right\n b = bottom\n l = left\n\n 1 = 1st step in spacing scale\n 2 = 2nd step in spacing scale\n 3 = 3rd step in spacing scale\n 4 = 4th step in spacing scale\n 5 = 5th step in spacing scale\n 6 = 6th step in spacing scale\n 7 = 7th step in spacing scale\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n\n\n.na1 { margin: -$spacing-extra-small; }\n.na2 { margin: -$spacing-small; }\n.na3 { margin: -$spacing-medium; }\n.na4 { margin: -$spacing-large; }\n.na5 { margin: -$spacing-extra-large; }\n.na6 { margin: -$spacing-extra-extra-large; }\n.na7 { margin: -$spacing-extra-extra-extra-large; }\n\n.nl1 { margin-left: -$spacing-extra-small; }\n.nl2 { margin-left: -$spacing-small; }\n.nl3 { margin-left: -$spacing-medium; }\n.nl4 { margin-left: -$spacing-large; }\n.nl5 { margin-left: -$spacing-extra-large; }\n.nl6 { margin-left: -$spacing-extra-extra-large; }\n.nl7 { margin-left: -$spacing-extra-extra-extra-large; }\n\n.nr1 { margin-right: -$spacing-extra-small; }\n.nr2 { margin-right: -$spacing-small; }\n.nr3 { margin-right: -$spacing-medium; }\n.nr4 { margin-right: -$spacing-large; }\n.nr5 { margin-right: -$spacing-extra-large; }\n.nr6 { margin-right: -$spacing-extra-extra-large; }\n.nr7 { margin-right: -$spacing-extra-extra-extra-large; }\n\n.nb1 { margin-bottom: -$spacing-extra-small; }\n.nb2 { margin-bottom: -$spacing-small; }\n.nb3 { margin-bottom: -$spacing-medium; }\n.nb4 { margin-bottom: -$spacing-large; }\n.nb5 { margin-bottom: -$spacing-extra-large; }\n.nb6 { margin-bottom: -$spacing-extra-extra-large; }\n.nb7 { margin-bottom: -$spacing-extra-extra-extra-large; }\n\n.nt1 { margin-top: -$spacing-extra-small; }\n.nt2 { margin-top: -$spacing-small; }\n.nt3 { margin-top: -$spacing-medium; }\n.nt4 { margin-top: -$spacing-large; }\n.nt5 { margin-top: -$spacing-extra-large; }\n.nt6 { margin-top: -$spacing-extra-extra-large; }\n.nt7 { margin-top: -$spacing-extra-extra-extra-large; }\n\n@media #{$breakpoint-not-small} {\n\n .na1-ns { margin: -$spacing-extra-small; }\n .na2-ns { margin: -$spacing-small; }\n .na3-ns { margin: -$spacing-medium; }\n .na4-ns { margin: -$spacing-large; }\n .na5-ns { margin: -$spacing-extra-large; }\n .na6-ns { margin: -$spacing-extra-extra-large; }\n .na7-ns { margin: -$spacing-extra-extra-extra-large; }\n\n .nl1-ns { margin-left: -$spacing-extra-small; }\n .nl2-ns { margin-left: -$spacing-small; }\n .nl3-ns { margin-left: -$spacing-medium; }\n .nl4-ns { margin-left: -$spacing-large; }\n .nl5-ns { margin-left: -$spacing-extra-large; }\n .nl6-ns { margin-left: -$spacing-extra-extra-large; }\n .nl7-ns { margin-left: -$spacing-extra-extra-extra-large; }\n\n .nr1-ns { margin-right: -$spacing-extra-small; }\n .nr2-ns { margin-right: -$spacing-small; }\n .nr3-ns { margin-right: -$spacing-medium; }\n .nr4-ns { margin-right: -$spacing-large; }\n .nr5-ns { margin-right: -$spacing-extra-large; }\n .nr6-ns { margin-right: -$spacing-extra-extra-large; }\n .nr7-ns { margin-right: -$spacing-extra-extra-extra-large; }\n\n .nb1-ns { margin-bottom: -$spacing-extra-small; }\n .nb2-ns { margin-bottom: -$spacing-small; }\n .nb3-ns { margin-bottom: -$spacing-medium; }\n .nb4-ns { margin-bottom: -$spacing-large; }\n .nb5-ns { margin-bottom: -$spacing-extra-large; }\n .nb6-ns { margin-bottom: -$spacing-extra-extra-large; }\n .nb7-ns { margin-bottom: -$spacing-extra-extra-extra-large; }\n\n .nt1-ns { margin-top: -$spacing-extra-small; }\n .nt2-ns { margin-top: -$spacing-small; }\n .nt3-ns { margin-top: -$spacing-medium; }\n .nt4-ns { margin-top: -$spacing-large; }\n .nt5-ns { margin-top: -$spacing-extra-large; }\n .nt6-ns { margin-top: -$spacing-extra-extra-large; }\n .nt7-ns { margin-top: -$spacing-extra-extra-extra-large; }\n\n}\n\n@media #{$breakpoint-medium} {\n .na1-m { margin: -$spacing-extra-small; }\n .na2-m { margin: -$spacing-small; }\n .na3-m { margin: -$spacing-medium; }\n .na4-m { margin: -$spacing-large; }\n .na5-m { margin: -$spacing-extra-large; }\n .na6-m { margin: -$spacing-extra-extra-large; }\n .na7-m { margin: -$spacing-extra-extra-extra-large; }\n\n .nl1-m { margin-left: -$spacing-extra-small; }\n .nl2-m { margin-left: -$spacing-small; }\n .nl3-m { margin-left: -$spacing-medium; }\n .nl4-m { margin-left: -$spacing-large; }\n .nl5-m { margin-left: -$spacing-extra-large; }\n .nl6-m { margin-left: -$spacing-extra-extra-large; }\n .nl7-m { margin-left: -$spacing-extra-extra-extra-large; }\n\n .nr1-m { margin-right: -$spacing-extra-small; }\n .nr2-m { margin-right: -$spacing-small; }\n .nr3-m { margin-right: -$spacing-medium; }\n .nr4-m { margin-right: -$spacing-large; }\n .nr5-m { margin-right: -$spacing-extra-large; }\n .nr6-m { margin-right: -$spacing-extra-extra-large; }\n .nr7-m { margin-right: -$spacing-extra-extra-extra-large; }\n\n .nb1-m { margin-bottom: -$spacing-extra-small; }\n .nb2-m { margin-bottom: -$spacing-small; }\n .nb3-m { margin-bottom: -$spacing-medium; }\n .nb4-m { margin-bottom: -$spacing-large; }\n .nb5-m { margin-bottom: -$spacing-extra-large; }\n .nb6-m { margin-bottom: -$spacing-extra-extra-large; }\n .nb7-m { margin-bottom: -$spacing-extra-extra-extra-large; }\n\n .nt1-m { margin-top: -$spacing-extra-small; }\n .nt2-m { margin-top: -$spacing-small; }\n .nt3-m { margin-top: -$spacing-medium; }\n .nt4-m { margin-top: -$spacing-large; }\n .nt5-m { margin-top: -$spacing-extra-large; }\n .nt6-m { margin-top: -$spacing-extra-extra-large; }\n .nt7-m { margin-top: -$spacing-extra-extra-extra-large; }\n\n}\n\n@media #{$breakpoint-large} {\n .na1-l { margin: -$spacing-extra-small; }\n .na2-l { margin: -$spacing-small; }\n .na3-l { margin: -$spacing-medium; }\n .na4-l { margin: -$spacing-large; }\n .na5-l { margin: -$spacing-extra-large; }\n .na6-l { margin: -$spacing-extra-extra-large; }\n .na7-l { margin: -$spacing-extra-extra-extra-large; }\n\n .nl1-l { margin-left: -$spacing-extra-small; }\n .nl2-l { margin-left: -$spacing-small; }\n .nl3-l { margin-left: -$spacing-medium; }\n .nl4-l { margin-left: -$spacing-large; }\n .nl5-l { margin-left: -$spacing-extra-large; }\n .nl6-l { margin-left: -$spacing-extra-extra-large; }\n .nl7-l { margin-left: -$spacing-extra-extra-extra-large; }\n\n .nr1-l { margin-right: -$spacing-extra-small; }\n .nr2-l { margin-right: -$spacing-small; }\n .nr3-l { margin-right: -$spacing-medium; }\n .nr4-l { margin-right: -$spacing-large; }\n .nr5-l { margin-right: -$spacing-extra-large; }\n .nr6-l { margin-right: -$spacing-extra-extra-large; }\n .nr7-l { margin-right: -$spacing-extra-extra-extra-large; }\n\n .nb1-l { margin-bottom: -$spacing-extra-small; }\n .nb2-l { margin-bottom: -$spacing-small; }\n .nb3-l { margin-bottom: -$spacing-medium; }\n .nb4-l { margin-bottom: -$spacing-large; }\n .nb5-l { margin-bottom: -$spacing-extra-large; }\n .nb6-l { margin-bottom: -$spacing-extra-extra-large; }\n .nb7-l { margin-bottom: -$spacing-extra-extra-extra-large; }\n\n .nt1-l { margin-top: -$spacing-extra-small; }\n .nt2-l { margin-top: -$spacing-small; }\n .nt3-l { margin-top: -$spacing-medium; }\n .nt4-l { margin-top: -$spacing-large; }\n .nt5-l { margin-top: -$spacing-extra-large; }\n .nt6-l { margin-top: -$spacing-extra-extra-large; }\n .nt7-l { margin-top: -$spacing-extra-extra-extra-large; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n TABLES\n Docs: http://tachyons.io/docs/elements/tables/\n\n*/\n\n.collapse {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\n.striped--light-silver:nth-child(odd) {\n background-color: $light-silver;\n}\n\n.striped--moon-gray:nth-child(odd) {\n background-color: $moon-gray;\n}\n\n.striped--light-gray:nth-child(odd) {\n background-color: $light-gray;\n}\n\n.striped--near-white:nth-child(odd) {\n background-color: $near-white;\n}\n\n.stripe-light:nth-child(odd) {\n background-color: $white-10;\n}\n\n.stripe-dark:nth-child(odd) {\n background-color: $black-10;\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n TEXT DECORATION\n Docs: http://tachyons.io/docs/typography/text-decoration/\n\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n.strike { text-decoration: line-through; }\n.underline { text-decoration: underline; }\n.no-underline { text-decoration: none; }\n\n\n@media #{$breakpoint-not-small} {\n .strike-ns { text-decoration: line-through; }\n .underline-ns { text-decoration: underline; }\n .no-underline-ns { text-decoration: none; }\n}\n\n@media #{$breakpoint-medium} {\n .strike-m { text-decoration: line-through; }\n .underline-m { text-decoration: underline; }\n .no-underline-m { text-decoration: none; }\n}\n\n@media #{$breakpoint-large} {\n .strike-l { text-decoration: line-through; }\n .underline-l { text-decoration: underline; }\n .no-underline-l { text-decoration: none; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n TEXT ALIGN\n Docs: http://tachyons.io/docs/typography/text-align/\n\n Base\n t = text-align\n\n Modifiers\n l = left\n r = right\n c = center\n j = justify\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n.tl { text-align: left; }\n.tr { text-align: right; }\n.tc { text-align: center; }\n.tj { text-align: justify; }\n\n@media #{$breakpoint-not-small} {\n .tl-ns { text-align: left; }\n .tr-ns { text-align: right; }\n .tc-ns { text-align: center; }\n .tj-ns { text-align: justify; }\n}\n\n@media #{$breakpoint-medium} {\n .tl-m { text-align: left; }\n .tr-m { text-align: right; }\n .tc-m { text-align: center; }\n .tj-m { text-align: justify; }\n}\n\n@media #{$breakpoint-large} {\n .tl-l { text-align: left; }\n .tr-l { text-align: right; }\n .tc-l { text-align: center; }\n .tj-l { text-align: justify; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n TEXT TRANSFORM\n Docs: http://tachyons.io/docs/typography/text-transform/\n\n Base:\n tt = text-transform\n\n Modifiers\n c = capitalize\n l = lowercase\n u = uppercase\n n = none\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n.ttc { text-transform: capitalize; }\n.ttl { text-transform: lowercase; }\n.ttu { text-transform: uppercase; }\n.ttn { text-transform: none; }\n\n@media #{$breakpoint-not-small} {\n .ttc-ns { text-transform: capitalize; }\n .ttl-ns { text-transform: lowercase; }\n .ttu-ns { text-transform: uppercase; }\n .ttn-ns { text-transform: none; }\n}\n\n@media #{$breakpoint-medium} {\n .ttc-m { text-transform: capitalize; }\n .ttl-m { text-transform: lowercase; }\n .ttu-m { text-transform: uppercase; }\n .ttn-m { text-transform: none; }\n}\n\n@media #{$breakpoint-large} {\n .ttc-l { text-transform: capitalize; }\n .ttl-l { text-transform: lowercase; }\n .ttu-l { text-transform: uppercase; }\n .ttn-l { text-transform: none; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n TYPE SCALE\n Docs: http://tachyons.io/docs/typography/scale/\n\n Base:\n f = font-size\n\n Modifiers\n 1 = 1st step in size scale\n 2 = 2nd step in size scale\n 3 = 3rd step in size scale\n 4 = 4th step in size scale\n 5 = 5th step in size scale\n 6 = 6th step in size scale\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n*/\n\n/*\n * For Hero/Marketing Titles\n *\n * These generally are too large for mobile\n * so be careful using them on smaller screens.\n * */\n\n.f-6,\n.f-headline {\n font-size: $font-size-headline;\n}\n.f-5,\n.f-subheadline {\n font-size: $font-size-subheadline;\n}\n\n\n/* Type Scale */\n\n\n.f1 { font-size: $font-size-1; }\n.f2 { font-size: $font-size-2; }\n.f3 { font-size: $font-size-3; }\n.f4 { font-size: $font-size-4; }\n.f5 { font-size: $font-size-5; }\n.f6 { font-size: $font-size-6; }\n.f7 { font-size: $font-size-7; }\n\n@media #{$breakpoint-not-small}{\n .f-6-ns,\n .f-headline-ns { font-size: $font-size-headline; }\n .f-5-ns,\n .f-subheadline-ns { font-size: $font-size-subheadline; }\n .f1-ns { font-size: $font-size-1; }\n .f2-ns { font-size: $font-size-2; }\n .f3-ns { font-size: $font-size-3; }\n .f4-ns { font-size: $font-size-4; }\n .f5-ns { font-size: $font-size-5; }\n .f6-ns { font-size: $font-size-6; }\n .f7-ns { font-size: $font-size-7; }\n}\n\n@media #{$breakpoint-medium} {\n .f-6-m,\n .f-headline-m { font-size: $font-size-headline; }\n .f-5-m,\n .f-subheadline-m { font-size: $font-size-subheadline; }\n .f1-m { font-size: $font-size-1; }\n .f2-m { font-size: $font-size-2; }\n .f3-m { font-size: $font-size-3; }\n .f4-m { font-size: $font-size-4; }\n .f5-m { font-size: $font-size-5; }\n .f6-m { font-size: $font-size-6; }\n .f7-m { font-size: $font-size-7; }\n}\n\n@media #{$breakpoint-large} {\n .f-6-l,\n .f-headline-l {\n font-size: $font-size-headline;\n }\n .f-5-l,\n .f-subheadline-l {\n font-size: $font-size-subheadline;\n }\n .f1-l { font-size: $font-size-1; }\n .f2-l { font-size: $font-size-2; }\n .f3-l { font-size: $font-size-3; }\n .f4-l { font-size: $font-size-4; }\n .f5-l { font-size: $font-size-5; }\n .f6-l { font-size: $font-size-6; }\n .f7-l { font-size: $font-size-7; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n TYPOGRAPHY\n http://tachyons.io/docs/typography/measure/\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n\n\n/* Measure is limited to ~66 characters */\n.measure {\n max-width: $measure;\n}\n\n/* Measure is limited to ~80 characters */\n.measure-wide {\n max-width: $measure-wide;\n}\n\n/* Measure is limited to ~45 characters */\n.measure-narrow {\n max-width: $measure-narrow;\n}\n\n/* Book paragraph style - paragraphs are indented with no vertical spacing. */\n.indent {\n text-indent: 1em;\n margin-top: 0;\n margin-bottom: 0;\n}\n\n.small-caps {\n font-variant: small-caps;\n}\n\n/* Combine this class with a width to truncate text (or just leave as is to truncate at width of containing element. */\n\n.truncate {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n@media #{$breakpoint-not-small} {\n .measure-ns {\n max-width: $measure;\n }\n .measure-wide-ns {\n max-width: $measure-wide;\n }\n .measure-narrow-ns {\n max-width: $measure-narrow;\n }\n .indent-ns {\n text-indent: 1em;\n margin-top: 0;\n margin-bottom: 0;\n }\n .small-caps-ns {\n font-variant: small-caps;\n }\n .truncate-ns {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n}\n\n@media #{$breakpoint-medium} {\n .measure-m {\n max-width: $measure;\n }\n .measure-wide-m {\n max-width: $measure-wide;\n }\n .measure-narrow-m {\n max-width: $measure-narrow;\n }\n .indent-m {\n text-indent: 1em;\n margin-top: 0;\n margin-bottom: 0;\n }\n .small-caps-m {\n font-variant: small-caps;\n }\n .truncate-m {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n}\n\n@media #{$breakpoint-large} {\n .measure-l {\n max-width: $measure;\n }\n .measure-wide-l {\n max-width: $measure-wide;\n }\n .measure-narrow-l {\n max-width: $measure-narrow;\n }\n .indent-l {\n text-indent: 1em;\n margin-top: 0;\n margin-bottom: 0;\n }\n .small-caps-l {\n font-variant: small-caps;\n }\n .truncate-l {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n UTILITIES\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n/* Equivalent to .overflow-y-scroll */\n.overflow-container {\n overflow-y: scroll;\n}\n\n.center {\n margin-right: auto;\n margin-left: auto;\n}\n\n.mr-auto { margin-right: auto; }\n.ml-auto { margin-left: auto; }\n\n@media #{$breakpoint-not-small}{\n .center-ns {\n margin-right: auto;\n margin-left: auto;\n }\n .mr-auto-ns { margin-right: auto; }\n .ml-auto-ns { margin-left: auto; }\n}\n\n@media #{$breakpoint-medium}{\n .center-m {\n margin-right: auto;\n margin-left: auto;\n }\n .mr-auto-m { margin-right: auto; }\n .ml-auto-m { margin-left: auto; }\n}\n\n@media #{$breakpoint-large}{\n .center-l {\n margin-right: auto;\n margin-left: auto;\n }\n .mr-auto-l { margin-right: auto; }\n .ml-auto-l { margin-left: auto; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n VISIBILITY\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n\n/*\n Text that is hidden but accessible\n Ref: http://snook.ca/archives/html_and_css/hiding-content-for-accessibility\n*/\n\n.clip {\n position: fixed !important;\n _position: absolute !important;\n clip: rect(1px 1px 1px 1px); /* IE6, IE7 */\n clip: rect(1px, 1px, 1px, 1px);\n}\n\n@media #{$breakpoint-not-small} {\n .clip-ns {\n position: fixed !important;\n _position: absolute !important;\n clip: rect(1px 1px 1px 1px); /* IE6, IE7 */\n clip: rect(1px, 1px, 1px, 1px);\n }\n}\n\n@media #{$breakpoint-medium} {\n .clip-m {\n position: fixed !important;\n _position: absolute !important;\n clip: rect(1px 1px 1px 1px); /* IE6, IE7 */\n clip: rect(1px, 1px, 1px, 1px);\n }\n}\n\n@media #{$breakpoint-large} {\n .clip-l {\n position: fixed !important;\n _position: absolute !important;\n clip: rect(1px 1px 1px 1px); /* IE6, IE7 */\n clip: rect(1px, 1px, 1px, 1px);\n }\n}\n\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n WHITE SPACE\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n\n.ws-normal { white-space: normal; }\n.nowrap { white-space: nowrap; }\n.pre { white-space: pre; }\n\n@media #{$breakpoint-not-small} {\n .ws-normal-ns { white-space: normal; }\n .nowrap-ns { white-space: nowrap; }\n .pre-ns { white-space: pre; }\n}\n\n@media #{$breakpoint-medium} {\n .ws-normal-m { white-space: normal; }\n .nowrap-m { white-space: nowrap; }\n .pre-m { white-space: pre; }\n}\n\n@media #{$breakpoint-large} {\n .ws-normal-l { white-space: normal; }\n .nowrap-l { white-space: nowrap; }\n .pre-l { white-space: pre; }\n}\n\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n VERTICAL ALIGN\n\n Media Query Extensions:\n -ns = not-small\n -m = medium\n -l = large\n\n*/\n\n.v-base { vertical-align: baseline; }\n.v-mid { vertical-align: middle; }\n.v-top { vertical-align: top; }\n.v-btm { vertical-align: bottom; }\n\n@media #{$breakpoint-not-small} {\n .v-base-ns { vertical-align: baseline; }\n .v-mid-ns { vertical-align: middle; }\n .v-top-ns { vertical-align: top; }\n .v-btm-ns { vertical-align: bottom; }\n}\n\n@media #{$breakpoint-medium} {\n .v-base-m { vertical-align: baseline; }\n .v-mid-m { vertical-align: middle; }\n .v-top-m { vertical-align: top; }\n .v-btm-m { vertical-align: bottom; }\n}\n\n@media #{$breakpoint-large} {\n .v-base-l { vertical-align: baseline; }\n .v-mid-l { vertical-align: middle; }\n .v-top-l { vertical-align: top; }\n .v-btm-l { vertical-align: bottom; }\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n HOVER EFFECTS\n Docs: http://tachyons.io/docs/themes/hovers/\n\n - Dim\n - Glow\n - Hide Child\n - Underline text\n - Grow\n - Pointer\n - Shadow\n\n*/\n\n/*\n\n Dim element on hover by adding the dim class.\n\n*/\n.dim {\n opacity: 1;\n transition: opacity .15s ease-in;\n}\n.dim:hover,\n.dim:focus {\n opacity: .5;\n transition: opacity .15s ease-in;\n}\n.dim:active {\n opacity: .8; transition: opacity .15s ease-out;\n}\n\n/*\n\n Animate opacity to 100% on hover by adding the glow class.\n\n*/\n.glow {\n transition: opacity .15s ease-in;\n}\n.glow:hover,\n.glow:focus {\n opacity: 1;\n transition: opacity .15s ease-in;\n}\n\n/*\n\n Hide child & reveal on hover:\n\n Put the hide-child class on a parent element and any nested element with the\n child class will be hidden and displayed on hover or focus.\n\n
      \n
      Hidden until hover or focus
      \n
      Hidden until hover or focus
      \n
      Hidden until hover or focus
      \n
      Hidden until hover or focus
      \n
      \n*/\n\n.hide-child .child {\n opacity: 0;\n transition: opacity .15s ease-in;\n}\n.hide-child:hover .child,\n.hide-child:focus .child,\n.hide-child:active .child {\n opacity: 1;\n transition: opacity .15s ease-in;\n}\n\n.underline-hover:hover,\n.underline-hover:focus {\n text-decoration: underline;\n}\n\n/* Can combine this with overflow-hidden to make background images grow on hover\n * even if you are using background-size: cover */\n\n.grow {\n -moz-osx-font-smoothing: grayscale;\n backface-visibility: hidden;\n transform: translateZ(0);\n transition: transform 0.25s ease-out;\n}\n\n.grow:hover,\n.grow:focus {\n transform: scale(1.05);\n}\n\n.grow:active {\n transform: scale(.90);\n}\n\n.grow-large {\n -moz-osx-font-smoothing: grayscale;\n backface-visibility: hidden;\n transform: translateZ(0);\n transition: transform .25s ease-in-out;\n}\n\n.grow-large:hover,\n.grow-large:focus {\n transform: scale(1.2);\n}\n\n.grow-large:active {\n transform: scale(.95);\n}\n\n/* Add pointer on hover */\n\n.pointer:hover {\n cursor: pointer;\n}\n\n/*\n Add shadow on hover.\n\n Performant box-shadow animation pattern from\n http://tobiasahlin.com/blog/how-to-animate-box-shadow/\n*/\n\n.shadow-hover {\n cursor: pointer;\n position: relative;\n transition: all 0.5s cubic-bezier(0.165, 0.84, 0.44, 1);\n}\n\n.shadow-hover::after {\n content: '';\n box-shadow: 0px 0px 16px 2px rgba( 0, 0, 0, .2 );\n border-radius: inherit;\n opacity: 0;\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: -1;\n transition: opacity 0.5s cubic-bezier(0.165, 0.84, 0.44, 1);\n}\n\n.shadow-hover:hover::after,\n.shadow-hover:focus::after {\n opacity: 1;\n}\n\n/* Combine with classes in skins and skins-pseudo for\n * many different transition possibilities. */\n\n.bg-animate,\n.bg-animate:hover,\n.bg-animate:focus {\n transition: background-color .15s ease-in-out;\n}\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n Z-INDEX\n\n Base\n z = z-index\n\n Modifiers\n -0 = literal value 0\n -1 = literal value 1\n -2 = literal value 2\n -3 = literal value 3\n -4 = literal value 4\n -5 = literal value 5\n -999 = literal value 999\n -9999 = literal value 9999\n\n -max = largest accepted z-index value as integer\n\n -inherit = string value inherit\n -initial = string value initial\n -unset = string value unset\n\n MDN: https://developer.mozilla.org/en/docs/Web/CSS/z-index\n Spec: http://www.w3.org/TR/CSS2/zindex.html\n Articles:\n https://philipwalton.com/articles/what-no-one-told-you-about-z-index/\n\n Tips on extending:\n There might be a time worth using negative z-index values.\n Or if you are using tachyons with another project, you might need to\n adjust these values to suit your needs.\n\n*/\n\n.z-0 { z-index: 0; }\n.z-1 { z-index: 1; }\n.z-2 { z-index: 2; }\n.z-3 { z-index: 3; }\n.z-4 { z-index: 4; }\n.z-5 { z-index: 5; }\n\n.z-999 { z-index: 999; }\n.z-9999 { z-index: 9999; }\n\n.z-max {\n z-index: 2147483647;\n}\n\n.z-inherit { z-index: inherit; }\n.z-initial { z-index: initial; }\n.z-unset { z-index: unset; }\n\n","\n// Converted Variables\n\n\n// Custom Media Query Variables\n\n\n/*\n\n NESTED\n Tachyons module for styling nested elements\n that are generated by a cms.\n\n*/\n\n.nested-copy-line-height p,\n.nested-copy-line-height ul,\n.nested-copy-line-height ol {\n line-height: $line-height-copy;\n}\n\n.nested-headline-line-height h1,\n.nested-headline-line-height h2,\n.nested-headline-line-height h3,\n.nested-headline-line-height h4,\n.nested-headline-line-height h5,\n.nested-headline-line-height h6 {\n line-height: $line-height-title;\n}\n\n.nested-list-reset ul,\n.nested-list-reset ol {\n padding-left: 0;\n margin-left: 0;\n list-style-type: none;\n}\n\n.nested-copy-indent p+p {\n text-indent: $letter-spacing-1;\n margin-top: $spacing-none;\n margin-bottom: $spacing-none;\n}\n\n.nested-copy-seperator p+p {\n margin-top: $spacing-copy-separator;\n}\n\n.nested-img img {\n width: 100%;\n max-width: 100%;\n display: block;\n}\n\n.nested-links a {\n color: $blue;\n transition: color .15s ease-in;\n}\n\n.nested-links a:hover,\n.nested-links a:focus {\n color: $light-blue;\n transition: color .15s ease-in;\n}\n","@use \"sass:meta\";\n@use \"variables\" as *;\n@use \"type\";\n@use \"mixins\";\n\n.wrapper {\n width: 100%;\n max-width: 1460px;\n margin: 0 auto;\n padding: 0 20px;\n box-sizing: border-box;\n}\n\n.opblock-tag-section {\n display: flex;\n flex-direction: column;\n}\n\n.try-out.btn-group {\n padding: 0;\n display: flex;\n flex: 0.1 2 auto;\n}\n\n.try-out__btn {\n margin-left: 1.25rem;\n}\n\n.opblock-tag {\n display: flex;\n align-items: center;\n\n padding: 10px 20px 10px 10px;\n\n cursor: pointer;\n transition: all 0.2s;\n\n border-bottom: 1px solid rgba($opblock-tag-border-bottom-color, 0.3);\n\n &:hover {\n background: rgba($opblock-tag-background-color-hover, 0.02);\n }\n}\n\n.opblock-tag {\n font-size: 24px;\n\n margin: 0 0 5px 0;\n\n @include type.text_headline();\n\n &.no-desc {\n span {\n flex: 1;\n }\n }\n\n svg {\n transition: all 0.4s;\n }\n\n small {\n font-size: 14px;\n font-weight: normal;\n\n flex: 2;\n\n padding: 0 10px;\n\n @include type.text_body();\n }\n\n > div {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n flex: 1 1 150px;\n font-weight: 400;\n }\n\n @media (max-width: 640px) {\n small {\n flex: 1;\n }\n\n > div {\n flex: 1;\n }\n }\n\n .info__externaldocs {\n text-align: right;\n }\n}\n\n.parameter__type {\n font-size: 12px;\n\n padding: 5px 0;\n\n @include type.text_code();\n}\n\n.parameter-controls {\n margin-top: 0.75em;\n}\n\n.examples {\n &__title {\n display: block;\n font-size: 1.1em;\n font-weight: bold;\n margin-bottom: 0.75em;\n }\n\n &__section {\n margin-top: 1.5em;\n }\n &__section-header {\n font-weight: bold;\n font-size: 0.9rem;\n margin-bottom: 0.5rem;\n }\n}\n\n.examples-select {\n margin-bottom: 0.75em;\n display: inline-block;\n .examples-select-element {\n width: 100%;\n }\n &__section-label {\n font-weight: bold;\n font-size: 0.9rem;\n margin-right: 0.5rem;\n }\n}\n\n.example {\n &__section {\n margin-top: 1.5em;\n }\n &__section-header {\n font-weight: bold;\n font-size: 0.9rem;\n margin-bottom: 0.5rem;\n }\n}\n\n.view-line-link {\n position: relative;\n top: 3px;\n\n width: 20px;\n margin: 0 5px;\n\n cursor: pointer;\n transition: all 0.5s;\n}\n\n.opblock {\n margin: 0 0 15px 0;\n\n border: 1px solid $opblock-border-color;\n border-radius: 4px;\n box-shadow: 0 0 3px rgba($opblock-box-shadow-color, 0.19);\n\n .tab-header {\n display: flex;\n\n flex: 1;\n\n .tab-item {\n padding: 0 40px;\n\n cursor: pointer;\n\n &:first-of-type {\n padding: 0 40px 0 0;\n }\n &.active {\n h4 {\n span {\n position: relative;\n\n &:after {\n position: absolute;\n bottom: -15px;\n left: 50%;\n\n width: 120%;\n height: 4px;\n\n content: \"\";\n transform: translateX(-50%);\n\n background: $opblock-tab-header-tab-item-active-h4-span-after-background-color;\n }\n }\n }\n }\n }\n }\n\n &.is-open {\n .opblock-summary {\n border-bottom: 1px solid $opblock-isopen-summary-border-bottom-color;\n }\n }\n\n .opblock-section-header {\n display: flex;\n align-items: center;\n\n padding: 8px 20px;\n\n min-height: 50px;\n\n background: rgba($opblock-isopen-section-header-background-color, 0.8);\n box-shadow: 0 1px 2px\n rgba($opblock-isopen-section-header-box-shadow-color, 0.1);\n\n > label {\n font-size: 12px;\n font-weight: bold;\n\n display: flex;\n align-items: center;\n\n margin: 0 0 0 auto;\n\n @include type.text_headline();\n\n > span {\n padding: 0 10px 0 0;\n }\n }\n\n h4 {\n font-size: 14px;\n\n flex: 1;\n\n margin: 0;\n\n @include type.text_headline();\n }\n }\n\n .opblock-summary-method {\n font-size: 14px;\n font-weight: bold;\n\n min-width: 80px;\n padding: 6px 0;\n\n text-align: center;\n\n border-radius: 3px;\n background: $opblock-summary-method-background-color;\n text-shadow: 0 1px 0 rgba($opblock-summary-method-text-shadow-color, 0.1);\n\n @include type.text_headline($opblock-summary-method-font-color);\n\n @media (max-width: 768px) {\n font-size: 12px;\n }\n }\n\n .opblock-summary-path,\n .opblock-summary-operation-id,\n .opblock-summary-path__deprecated {\n font-size: 16px;\n\n display: flex;\n align-items: center;\n\n word-break: break-word;\n\n @include type.text_code();\n\n @media (max-width: 768px) {\n font-size: 12px;\n }\n }\n\n .opblock-summary-path {\n flex-shrink: 1;\n }\n\n @media (max-width: 640px) {\n .opblock-summary-path {\n max-width: 100%;\n }\n }\n\n .opblock-summary-path__deprecated {\n text-decoration: line-through;\n }\n\n .opblock-summary-operation-id {\n font-size: 14px;\n }\n\n .opblock-summary-description {\n font-size: 13px;\n\n word-break: break-word;\n\n @include type.text_body();\n }\n\n .opblock-summary-path-description-wrapper {\n display: flex;\n flex-direction: row;\n align-items: center;\n flex-wrap: wrap;\n gap: 0px 10px;\n\n padding: 0 10px;\n\n flex-grow: 1;\n }\n\n @media (max-width: 550px) {\n .opblock-summary-path-description-wrapper {\n flex-direction: column;\n align-items: flex-start;\n }\n }\n\n .opblock-summary {\n display: flex;\n align-items: center;\n\n padding: 5px;\n\n cursor: pointer;\n\n .view-line-link {\n position: relative;\n top: 2px;\n\n width: 0;\n margin: 0;\n\n cursor: pointer;\n transition: all 0.5s;\n }\n\n &:hover {\n .view-line-link {\n width: 18px;\n margin: 0 5px;\n\n &.copy-to-clipboard {\n width: 24px;\n }\n }\n }\n }\n\n &.opblock-post {\n @include mixins.method($color-post);\n }\n\n &.opblock-put {\n @include mixins.method($color-put);\n }\n\n &.opblock-delete {\n @include mixins.method($color-delete);\n }\n\n &.opblock-get {\n @include mixins.method($color-get);\n }\n\n &.opblock-patch {\n @include mixins.method($color-patch);\n }\n\n &.opblock-head {\n @include mixins.method($color-head);\n }\n\n &.opblock-options {\n @include mixins.method($color-options);\n }\n\n &.opblock-deprecated {\n opacity: 0.6;\n\n @include mixins.method($color-disabled);\n }\n\n .opblock-schemes {\n padding: 8px 20px;\n\n .schemes-title {\n padding: 0 10px 0 0;\n }\n }\n}\n\n.filter {\n .operation-filter-input {\n width: 100%;\n margin: 20px 0;\n padding: 10px 10px;\n\n border: 2px solid $operational-filter-input-border-color;\n }\n}\n\n.filter,\n.download-url-wrapper {\n .failed {\n color: red;\n }\n\n .loading {\n color: #aaa;\n }\n}\n\n.model-example {\n margin-top: 1em;\n\n .model-container {\n width: 100%;\n overflow-x: auto;\n\n .model-hint:not(.model-hint--embedded) {\n top: -1.15em;\n }\n }\n}\n\n.tab {\n display: flex;\n\n padding: 0;\n\n list-style: none;\n\n li {\n font-size: 12px;\n\n min-width: 60px;\n padding: 0;\n\n cursor: pointer;\n\n @include type.text_headline();\n\n &:first-of-type {\n position: relative;\n\n padding-left: 0;\n padding-right: 12px;\n\n &:after {\n position: absolute;\n top: 0;\n right: 6px;\n\n width: 1px;\n height: 100%;\n\n content: \"\";\n\n background: rgba($tab-list-item-first-background-color, 0.2);\n }\n }\n\n &.active {\n font-weight: bold;\n }\n\n button.tablinks {\n background: none;\n border: 0;\n padding: 0;\n\n color: inherit;\n font-family: inherit;\n font-weight: inherit;\n }\n }\n}\n\n.opblock-description-wrapper,\n.opblock-external-docs-wrapper,\n.opblock-title_normal {\n font-size: 12px;\n\n margin: 0 0 5px 0;\n padding: 15px 20px;\n\n @include type.text_body();\n\n h4 {\n font-size: 12px;\n\n margin: 0 0 5px 0;\n\n @include type.text_body();\n }\n\n p {\n font-size: 14px;\n\n margin: 0;\n\n @include type.text_body();\n }\n}\n\n.opblock-external-docs-wrapper {\n h4 {\n padding-left: 0px;\n }\n}\n\n.execute-wrapper {\n padding: 20px;\n\n text-align: right;\n\n .btn {\n width: 100%;\n padding: 8px 40px;\n }\n}\n\n.body-param-options {\n display: flex;\n flex-direction: column;\n\n .body-param-edit {\n padding: 10px 0;\n }\n\n label {\n padding: 8px 0;\n select {\n margin: 3px 0 0 0;\n }\n }\n}\n\n.responses-inner {\n padding: 20px;\n\n h5,\n h4 {\n font-size: 12px;\n\n margin: 10px 0 5px 0;\n\n @include type.text_body();\n }\n\n .curl {\n overflow-y: auto;\n max-height: 400px;\n min-height: 6em;\n }\n}\n\n.response-col_status {\n font-size: 14px;\n\n @include type.text_body();\n\n .response-undocumented {\n font-size: 11px;\n\n @include type.text_code($response-col-status-undocumented-font-color);\n }\n}\n\n.response-col_links {\n padding-left: 2em;\n max-width: 40em;\n font-size: 14px;\n\n @include type.text_body();\n\n .response-undocumented {\n font-size: 11px;\n\n @include type.text_code($response-col-links-font-color);\n }\n\n .operation-link {\n margin-bottom: 1.5em;\n\n .description {\n margin-bottom: 0.5em;\n }\n }\n}\n\n.opblock-body {\n .opblock-loading-animation {\n display: block;\n margin: 3em auto;\n }\n}\n\n.opblock-body pre.microlight {\n font-size: 12px;\n\n margin: 0;\n padding: 10px;\n\n white-space: pre-wrap;\n word-wrap: break-word;\n word-break: break-all;\n word-break: break-word;\n hyphens: auto;\n\n border-radius: 4px;\n background: $opblock-body-background-color;\n\n overflow-wrap: break-word;\n @include type.text_code($opblock-body-font-color);\n\n // disabled to have syntax highliting with react-syntax-highlight\n // span\n // {\n // color: $opblock-body-font-color !important;\n // }\n\n .headerline {\n display: block;\n }\n}\n\n.highlight-code {\n position: relative;\n\n > .microlight {\n overflow-y: auto;\n max-height: 400px;\n min-height: 6em;\n\n code {\n white-space: pre-wrap !important;\n word-break: break-all;\n }\n }\n}\n.curl-command {\n position: relative;\n}\n\n.download-contents {\n position: absolute;\n bottom: 10px;\n right: 10px;\n background: #7d8293;\n text-align: center;\n padding: 5px;\n border: none;\n border-radius: 4px;\n font-family: sans-serif;\n font-weight: 600;\n color: white;\n font-size: 14px;\n height: 30px;\n justify-content: center;\n align-items: center;\n display: flex;\n}\n\n.scheme-container {\n margin: 0 0 20px 0;\n padding: 30px 0;\n\n background: $scheme-container-background-color;\n box-shadow: 0 1px 2px 0 rgba($scheme-container-box-shadow-color, 0.15);\n\n .schemes {\n display: flex;\n align-items: flex-end;\n justify-content: space-between;\n flex-wrap: wrap;\n\n gap: 10px;\n\n /*\n This wraps the servers or schemes selector.\n This was added to make sure the Authorize button is always on the right\n and the servers or schemes selector is always on the left.\n */\n > .schemes-server-container {\n display: flex;\n flex-wrap: wrap;\n\n gap: 10px;\n\n > label {\n font-size: 12px;\n font-weight: bold;\n\n display: flex;\n flex-direction: column;\n\n margin: -20px 15px 0 0;\n\n @include type.text_headline();\n\n select {\n min-width: 130px;\n\n text-transform: uppercase;\n }\n }\n }\n\n /*\n This checks if the schemes-server-container is not present and\n aligns the authorize button to the right\n */\n &:not(:has(.schemes-server-container)) {\n justify-content: flex-end;\n }\n\n /*\n Target Authorize Button in schemes wrapper\n This was added here to fix responsiveness issues with the authorize button\n within the schemes wrapper without affecting other instances of it's usage\n */\n .auth-wrapper {\n flex: none;\n justify-content: start;\n\n .authorize {\n padding-right: 20px;\n margin: 0;\n\n display: flex;\n\n flex-wrap: nowrap;\n }\n }\n }\n}\n\n.loading-container {\n padding: 40px 0 60px;\n margin-top: 1em;\n min-height: 1px;\n display: flex;\n justify-content: center;\n align-items: center;\n flex-direction: column;\n\n .loading {\n position: relative;\n\n &:after {\n font-size: 10px;\n font-weight: bold;\n\n position: absolute;\n top: 50%;\n left: 50%;\n\n content: \"loading\";\n transform: translate(-50%, -50%);\n text-transform: uppercase;\n\n @include type.text_headline();\n }\n\n &:before {\n position: absolute;\n top: 50%;\n left: 50%;\n\n display: block;\n\n width: 60px;\n height: 60px;\n margin: -30px -30px;\n\n content: \"\";\n animation:\n rotation 1s infinite linear,\n opacity 0.5s;\n\n opacity: 1;\n border: 2px solid rgba($loading-container-before-border-color, 0.1);\n border-top-color: rgba($loading-container-before-border-top-color, 0.6);\n border-radius: 100%;\n\n backface-visibility: hidden;\n\n @keyframes rotation {\n to {\n transform: rotate(360deg);\n }\n }\n }\n }\n}\n\n.response-controls {\n padding-top: 1em;\n display: flex;\n}\n\n.response-control-media-type {\n margin-right: 1em;\n\n &--accept-controller {\n select {\n border-color: $response-content-type-controls-accept-header-select-border-color;\n }\n }\n\n &__accept-message {\n color: $response-content-type-controls-accept-header-small-font-color;\n font-size: 0.7em;\n }\n\n &__title {\n display: block;\n margin-bottom: 0.2em;\n font-size: 0.7em;\n }\n}\n\n.response-control-examples {\n &__title {\n display: block;\n margin-bottom: 0.2em;\n font-size: 0.7em;\n }\n}\n\n@keyframes blinker {\n 50% {\n opacity: 0;\n }\n}\n\n.hidden {\n display: none;\n}\n\n.no-margin {\n height: auto;\n border: none;\n margin: 0;\n padding: 0;\n}\n\n.float-right {\n float: right;\n}\n\n.svg-assets {\n position: absolute;\n width: 0;\n height: 0;\n}\n\nsection {\n h3 {\n @include type.text_headline();\n }\n}\n\na.nostyle {\n text-decoration: inherit;\n color: inherit;\n cursor: pointer;\n display: inline;\n\n &:visited {\n text-decoration: inherit;\n color: inherit;\n cursor: pointer;\n }\n}\n\n.fallback {\n padding: 1em;\n color: #aaa;\n}\n\n.version-pragma {\n height: 100%;\n padding: 5em 0px;\n\n &__message {\n display: flex;\n justify-content: center;\n height: 100%;\n font-size: 1.2em;\n text-align: center;\n line-height: 1.5em;\n\n padding: 0px 0.6em;\n\n > div {\n max-width: 55ch;\n flex: 1;\n }\n\n code {\n background-color: #dedede;\n padding: 4px 4px 2px;\n white-space: pre;\n }\n }\n}\n\n.opblock-link {\n font-weight: normal;\n\n &.shown {\n font-weight: bold;\n }\n}\n\nspan {\n &.token-string {\n color: #555;\n }\n\n &.token-not-formatted {\n color: #555;\n font-weight: bold;\n }\n}\n","@use \"sass:color\";\n@use \"variables\" as *;\n\n// - - - - - - - - - - - - - - - - - - -\n// - - _mixins.scss module\n// styles for the _mixins.scss module\n@function calculateRem($size) {\n $remSize: $size / 16px;\n @return $remSize * 1rem;\n}\n\n@mixin font-size($size) {\n font-size: $size;\n font-size: calculateRem($size);\n}\n\n%clearfix {\n &:before,\n &:after {\n display: table;\n\n content: \" \";\n }\n &:after {\n clear: both;\n }\n}\n\n@mixin size($width, $height: $width) {\n width: $width;\n height: $height;\n}\n\n$ease: (\n in-quad: cubic-bezier(0.55, 0.085, 0.68, 0.53),\n in-cubic: cubic-bezier(0.55, 0.055, 0.675, 0.19),\n in-quart: cubic-bezier(0.895, 0.03, 0.685, 0.22),\n in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06),\n in-sine: cubic-bezier(0.47, 0, 0.745, 0.715),\n in-expo: cubic-bezier(0.95, 0.05, 0.795, 0.035),\n in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.335),\n in-back: cubic-bezier(0.6, -0.28, 0.735, 0.045),\n out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94),\n out-cubic: cubic-bezier(0.215, 0.61, 0.355, 1),\n out-quart: cubic-bezier(0.165, 0.84, 0.44, 1),\n out-quint: cubic-bezier(0.23, 1, 0.32, 1),\n out-sine: cubic-bezier(0.39, 0.575, 0.565, 1),\n out-expo: cubic-bezier(0.19, 1, 0.22, 1),\n out-circ: cubic-bezier(0.075, 0.82, 0.165, 1),\n out-back: cubic-bezier(0.175, 0.885, 0.32, 1.275),\n in-out-quad: cubic-bezier(0.455, 0.03, 0.515, 0.955),\n in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1),\n in-out-quart: cubic-bezier(0.77, 0, 0.175, 1),\n in-out-quint: cubic-bezier(0.86, 0, 0.07, 1),\n in-out-sine: cubic-bezier(0.445, 0.05, 0.55, 0.95),\n in-out-expo: cubic-bezier(1, 0, 0, 1),\n in-out-circ: cubic-bezier(0.785, 0.135, 0.15, 0.86),\n in-out-back: cubic-bezier(0.68, -0.55, 0.265, 1.55),\n);\n\n@function ease($key) {\n @if map-has-key($ease, $key) {\n @return map-get($ease, $key);\n }\n\n @warn 'Unkown \\'#{$key}\\' in $ease.';\n @return null;\n}\n\n@mixin ease($key) {\n transition-timing-function: ease($key);\n}\n\n@mixin text-truncate {\n overflow: hidden;\n\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n@mixin aspect-ratio($width, $height) {\n position: relative;\n &:before {\n display: block;\n\n width: 100%;\n padding-top: ($height / $width) * 100%;\n\n content: \"\";\n }\n > iframe {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n }\n}\n\n$browser-context: 16;\n\n@function em($pixels, $context: $browser-context) {\n @if (unitless($pixels)) {\n $pixels: $pixels * 1px;\n }\n\n @if (unitless($context)) {\n $context: $context * 1px;\n }\n\n @return $pixels / $context * 1em;\n}\n\n@mixin maxHeight($height) {\n @media (max-height: $height) {\n @content;\n }\n}\n\n@mixin breakpoint($class) {\n @if $class == tablet {\n @media (min-width: 768px) and (max-width: 1024px) {\n @content;\n }\n } @else if $class == mobile {\n @media (min-width: 320px) and (max-width: 736px) {\n @content;\n }\n } @else if $class == desktop {\n @media (min-width: 1400px) {\n @content;\n }\n } @else {\n @warn 'Breakpoint mixin supports: tablet, mobile, desktop';\n }\n}\n\n@mixin invalidFormElement() {\n animation: shake 0.4s 1;\n border-color: $color-delete;\n background: color.adjust($color-delete, $lightness: 35%);\n}\n\n@mixin method($color) {\n border-color: $color;\n background: rgba($color, 0.1);\n\n .opblock-summary-method {\n background: $color;\n }\n\n .opblock-summary {\n border-color: $color;\n }\n\n .tab-header .tab-item.active h4 span:after {\n background: $color;\n }\n}\n","@use \"variables\" as *;\n@use \"type\";\n@use \"mixins\";\n\n.btn {\n font-size: 14px;\n font-weight: bold;\n\n padding: 5px 23px;\n\n transition: all 0.3s;\n\n border: 2px solid $btn-border-color;\n border-radius: 4px;\n background: transparent;\n box-shadow: 0 1px 2px rgba($btn-box-shadow-color, 0.1);\n\n @include type.text_headline();\n\n &.btn-sm {\n font-size: 12px;\n padding: 4px 23px;\n }\n\n &[disabled] {\n cursor: not-allowed;\n\n opacity: 0.3;\n }\n\n &:hover {\n box-shadow: 0 0 5px rgba($btn-box-shadow-color, 0.3);\n }\n\n &.cancel {\n border-color: $btn-cancel-border-color;\n background-color: $btn-cancel-background-color;\n @include type.text_headline($btn-cancel-font-color);\n }\n\n &.authorize {\n line-height: 1;\n\n display: inline;\n\n color: $btn-authorize-font-color;\n border-color: $btn-authorize-border-color;\n background-color: $btn-authorize-background-color;\n\n span {\n float: left;\n\n padding: 4px 20px 0 0;\n }\n\n svg {\n fill: $btn-authorize-svg-fill-color;\n }\n }\n\n &.execute {\n background-color: $btn-execute-background-color-alt;\n color: $btn-execute-font-color;\n border-color: $btn-execute-border-color;\n }\n}\n\n.btn-group {\n display: flex;\n\n padding: 30px;\n\n .btn {\n flex: 1;\n\n &:first-child {\n border-radius: 4px 0 0 4px;\n }\n\n &:last-child {\n border-radius: 0 4px 4px 0;\n }\n }\n}\n\n.authorization__btn {\n padding: 0 0 0 10px;\n\n border: none;\n background: none;\n\n .locked {\n opacity: 1;\n }\n\n .unlocked {\n opacity: 0.4;\n }\n}\n\n.opblock-summary-control,\n.models-control,\n.model-box-control {\n all: inherit;\n flex: 1;\n border-bottom: 0;\n padding: 0;\n cursor: pointer;\n\n &:focus {\n outline: auto;\n }\n}\n\n.expand-methods,\n.expand-operation {\n border: none;\n background: none;\n\n svg {\n width: 20px;\n height: 20px;\n }\n}\n\n.expand-methods {\n padding: 0 10px;\n\n &:hover {\n svg {\n fill: $expand-methods-svg-fill-color-hover;\n }\n }\n\n svg {\n transition: all 0.3s;\n\n fill: $expand-methods-svg-fill-color;\n }\n}\n\nbutton {\n cursor: pointer;\n\n &.invalid {\n @include mixins.invalidFormElement();\n }\n}\n\n.copy-to-clipboard {\n position: absolute;\n display: flex;\n justify-content: center;\n align-items: center;\n bottom: 10px;\n right: 100px;\n width: 30px;\n height: 30px;\n background: #7d8293;\n border-radius: 4px;\n border: none;\n\n button {\n flex-grow: 1;\n flex-shrink: 1;\n border: none;\n height: 25px;\n background: url(\"data:image/svg+xml, \")\n center center no-repeat;\n }\n}\n\n.copy-to-clipboard:active {\n background: #5e626f;\n}\n\n.opblock-control-arrow {\n border: none;\n text-align: center;\n background: none;\n}\n\n// overrides for smaller copy button for curl command\n.curl-command .copy-to-clipboard {\n bottom: 5px;\n right: 10px;\n width: 20px;\n height: 20px;\n\n button {\n height: 18px;\n }\n}\n\n// overrides for copy to clipboard button\n.opblock .opblock-summary .view-line-link.copy-to-clipboard {\n height: 26px;\n position: unset;\n}\n","@use \"variables\" as *;\n@use \"mixins\";\n@use \"type\";\n\nselect {\n font-size: 14px;\n font-weight: bold;\n\n padding: 5px 40px 5px 10px;\n\n border: 2px solid $form-select-border-color;\n border-radius: 4px;\n background: $form-select-background-color\n url('data:image/svg+xml, ')\n right 10px center no-repeat;\n background-size: 20px;\n box-shadow: 0 1px 2px 0 rgba($form-select-box-shadow-color, 0.25);\n\n @include type.text_headline();\n appearance: none;\n\n &[multiple] {\n margin: 5px 0;\n padding: 5px;\n\n background: $form-select-background-color;\n }\n\n &.invalid {\n @include mixins.invalidFormElement();\n }\n}\n\n.opblock-body select {\n min-width: 230px;\n @media (max-width: 768px) {\n min-width: 180px;\n }\n @media (max-width: 640px) {\n width: 100%;\n min-width: 100%;\n }\n}\n\nlabel {\n font-size: 12px;\n font-weight: bold;\n\n margin: 0 0 5px 0;\n\n @include type.text_headline();\n}\n\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"search\"],\ninput[type=\"email\"],\ninput[type=\"file\"] {\n line-height: 1;\n\n @media (max-width: 768px) {\n max-width: 175px;\n }\n}\n\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"search\"],\ninput[type=\"email\"],\ninput[type=\"file\"],\ntextarea {\n min-width: 100px;\n margin: 5px 0;\n padding: 8px 10px;\n\n border: 1px solid $form-input-border-color;\n border-radius: 4px;\n background: $form-input-background-color;\n\n &.invalid {\n @include mixins.invalidFormElement();\n }\n}\n\ninput,\ntextarea,\nselect {\n &[disabled] {\n background-color: #fafafa;\n color: #888;\n cursor: not-allowed;\n }\n}\n\nselect[disabled] {\n border-color: #888;\n}\n\ntextarea[disabled] {\n background-color: #41444e;\n color: #fff;\n}\n\n@keyframes shake {\n 10%,\n 90% {\n transform: translate3d(-1px, 0, 0);\n }\n\n 20%,\n 80% {\n transform: translate3d(2px, 0, 0);\n }\n\n 30%,\n 50%,\n 70% {\n transform: translate3d(-4px, 0, 0);\n }\n\n 40%,\n 60% {\n transform: translate3d(4px, 0, 0);\n }\n}\n\ntextarea {\n font-size: 12px;\n\n width: 100%;\n min-height: 280px;\n padding: 10px;\n\n border: none;\n border-radius: 4px;\n outline: none;\n background: rgba($form-textarea-background-color, 0.8);\n\n @include type.text_code();\n\n &:focus {\n border: 2px solid $form-textarea-focus-border-color;\n }\n\n &.curl {\n font-size: 12px;\n\n min-height: 100px;\n margin: 0;\n padding: 10px;\n\n resize: none;\n\n border-radius: 4px;\n background: $form-textarea-curl-background-color;\n\n @include type.text_code($form-textarea-curl-font-color);\n }\n}\n\n.checkbox {\n padding: 5px 0 10px;\n\n transition: opacity 0.5s;\n\n color: $form-checkbox-label-font-color;\n\n label {\n display: flex;\n }\n\n p {\n font-weight: normal !important;\n font-style: italic;\n\n margin: 0 !important;\n\n @include type.text_code();\n }\n\n input[type=\"checkbox\"] {\n display: none;\n\n & + label > .item {\n position: relative;\n top: 3px;\n\n display: inline-block;\n\n width: 16px;\n height: 16px;\n margin: 0 8px 0 0;\n padding: 5px;\n\n cursor: pointer;\n\n border-radius: 1px;\n background: $form-checkbox-background-color;\n box-shadow: 0 0 0 2px $form-checkbox-box-shadow-color;\n\n flex: none;\n\n &:active {\n transform: scale(0.9);\n }\n }\n\n &:checked + label > .item {\n background: $form-checkbox-background-color\n url('data:image/svg+xml, ')\n center center no-repeat;\n }\n }\n}\n","@use \"variables\" as *;\n@use \"type\";\n\n.dialog-ux {\n position: fixed;\n z-index: 9999;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n\n .backdrop-ux {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n\n background: rgba($dialog-ux-backdrop-background-color, 0.8);\n }\n\n .modal-ux {\n position: absolute;\n z-index: 9999;\n top: 50%;\n left: 50%;\n\n width: 100%;\n min-width: 300px;\n max-width: 650px;\n\n transform: translate(-50%, -50%);\n\n border: 1px solid $dialog-ux-modal-border-color;\n border-radius: 4px;\n background: $dialog-ux-modal-background-color;\n box-shadow: 0 10px 30px 0 rgba($dialog-ux-modal-box-shadow-color, 0.2);\n }\n\n .modal-ux-content {\n overflow-y: auto;\n\n max-height: 540px;\n padding: 20px;\n\n p {\n font-size: 12px;\n\n margin: 0 0 5px 0;\n\n color: $dialog-ux-modal-content-font-color;\n\n @include type.text_body();\n }\n\n h4 {\n font-size: 18px;\n font-weight: 600;\n\n margin: 15px 0 0 0;\n\n @include type.text_headline();\n }\n }\n\n .modal-ux-header {\n display: flex;\n\n padding: 12px 0;\n\n border-bottom: 1px solid $dialog-ux-modal-header-border-bottom-color;\n\n align-items: center;\n\n .close-modal {\n padding: 0 10px;\n\n border: none;\n background: none;\n\n appearance: none;\n }\n\n h3 {\n font-size: 20px;\n font-weight: 600;\n\n margin: 0;\n padding: 0 20px;\n\n flex: 1;\n @include type.text_headline();\n }\n }\n}\n","@use \"variables\" as *;\n@use \"type\";\n\n.model {\n font-size: 12px;\n font-weight: 300;\n\n @include type.text_code();\n\n .deprecated {\n span,\n td {\n color: $model-deprecated-font-color !important;\n }\n\n > td:first-of-type {\n text-decoration: line-through;\n }\n }\n &-toggle {\n font-size: 10px;\n\n position: relative;\n top: 6px;\n\n display: inline-block;\n\n margin: auto 0.3em;\n\n cursor: pointer;\n transition: transform 0.15s ease-in;\n transform: rotate(90deg);\n transform-origin: 50% 50%;\n\n &.collapsed {\n transform: rotate(0deg);\n }\n\n &:after {\n display: block;\n\n width: 20px;\n height: 20px;\n\n content: \"\";\n\n background: url('data:image/svg+xml, ')\n center no-repeat;\n background-size: 100%;\n }\n }\n\n &-jump-to-path {\n position: relative;\n\n cursor: pointer;\n\n .view-line-link {\n position: absolute;\n top: -0.4em;\n\n cursor: pointer;\n }\n }\n\n &-title {\n position: relative;\n\n &:hover .model-hint {\n display: block;\n }\n }\n\n &-hint {\n position: absolute;\n top: -1.8em;\n\n display: none;\n\n padding: 0.1em 0.5em;\n\n white-space: nowrap;\n\n color: $model-hint-font-color;\n border-radius: 4px;\n background: rgba($model-hint-background-color, 0.7);\n }\n\n p {\n margin: 0 0 1em 0;\n }\n\n .property {\n color: #999;\n font-style: italic;\n\n &.primitive {\n color: #6b6b6b;\n\n &.extension {\n display: block;\n\n > td:first-child {\n padding-left: 0;\n padding-right: 0;\n width: auto;\n\n &:after {\n content: \":\\00a0\";\n }\n }\n }\n }\n }\n\n .external-docs {\n color: #666;\n font-weight: normal;\n }\n}\n\ntable.model {\n tr {\n &.description {\n color: #666;\n font-weight: normal;\n\n td:first-child {\n font-weight: bold;\n }\n }\n\n &.property-row {\n &.required td:first-child {\n font-weight: bold;\n }\n\n td {\n vertical-align: top;\n\n &:first-child {\n padding-right: 0.2em;\n }\n }\n\n .star {\n color: red;\n }\n }\n\n &.extension {\n color: #777;\n\n td:last-child {\n vertical-align: top;\n }\n }\n\n &.external-docs {\n td:first-child {\n font-weight: bold;\n }\n }\n\n .renderedMarkdown p:first-child {\n margin-top: 0;\n }\n }\n}\n\nsection.models {\n margin: 30px 0;\n\n border: 1px solid rgba($section-models-border-color, 0.3);\n border-radius: 4px;\n\n .pointer {\n cursor: pointer;\n }\n\n &.is-open {\n padding: 0 0 20px;\n h4 {\n margin: 0 0 5px 0;\n\n border-bottom: 1px solid\n rgba($section-models-isopen-h4-border-bottom-color, 0.3);\n }\n }\n h4 {\n font-size: 16px;\n\n display: flex;\n align-items: center;\n\n margin: 0;\n padding: 10px 20px 10px 10px;\n\n cursor: pointer;\n transition: all 0.2s;\n\n @include type.text_headline($section-models-h4-font-color);\n\n svg {\n transition: all 0.4s;\n }\n\n span {\n flex: 1;\n }\n\n &:hover {\n background: rgba($section-models-h4-background-color-hover, 0.02);\n }\n }\n\n h5 {\n font-size: 16px;\n\n margin: 0 0 10px 0;\n\n @include type.text_headline($section-models-h5-font-color);\n }\n\n .model-jump-to-path {\n position: relative;\n top: 5px;\n }\n\n .model-container {\n margin: 0 20px 15px;\n position: relative;\n\n transition: all 0.5s;\n\n border-radius: 4px;\n background: rgba($section-models-model-container-background-color, 0.05);\n\n &:hover {\n background: rgba($section-models-model-container-background-color, 0.07);\n }\n\n &:first-of-type {\n margin: 20px;\n }\n\n &:last-of-type {\n margin: 0 20px;\n }\n\n .models-jump-to-path {\n position: absolute;\n top: 8px;\n right: 5px;\n opacity: 0.65;\n }\n }\n\n .model-box {\n background: none;\n\n &:has(.model-box) {\n width: 100%;\n overflow-x: auto;\n }\n }\n}\n\n.model-box {\n padding: 10px;\n display: inline-block;\n\n border-radius: 4px;\n background: rgba($section-models-model-box-background-color, 0.1);\n\n .model-jump-to-path {\n position: relative;\n top: 4px;\n }\n\n &.deprecated {\n opacity: 0.5;\n }\n}\n\n.model-title {\n font-size: 16px;\n\n @include type.text_headline($section-models-model-title-font-color);\n\n img {\n margin-left: 1em;\n position: relative;\n bottom: 0px;\n }\n}\n\n.model-deprecated-warning {\n font-size: 16px;\n font-weight: 600;\n\n margin-right: 1em;\n\n @include type.text_headline($color-delete);\n}\n\nspan {\n > span.model {\n .brace-close {\n padding: 0 0 0 10px;\n }\n }\n}\n\n.prop-name {\n display: inline-block;\n\n margin-right: 1em;\n}\n\n.prop-type {\n color: $prop-type-font-color;\n}\n\n.prop-enum {\n display: block;\n}\n.prop-format {\n color: $prop-format-font-color;\n}\n","@use \"variables\" as *;\n@use \"type\";\n\n.servers {\n > label {\n font-size: 12px;\n\n margin: -20px 15px 0 0;\n\n @include type.text_headline();\n\n select {\n min-width: 130px;\n max-width: 100%;\n width: 100%;\n }\n }\n\n h4.message {\n padding-bottom: 2em;\n }\n\n table {\n tr {\n width: 30em;\n }\n td {\n display: inline-block;\n max-width: 15em;\n vertical-align: middle;\n padding-top: 10px;\n padding-bottom: 10px;\n\n &:first-of-type {\n padding-right: 1em;\n }\n\n input {\n width: 100%;\n height: 100%;\n }\n }\n }\n\n .computed-url {\n margin: 2em 0;\n\n code {\n display: inline-block;\n padding: 4px;\n font-size: 16px;\n margin: 0 1em;\n }\n }\n}\n\n.servers-title {\n font-size: 12px;\n font-weight: bold;\n}\n\n.operation-servers {\n h4.message {\n margin-bottom: 2em;\n }\n}\n","@use \"type\";\n@use \"variables\" as *;\n\ntable {\n width: 100%;\n padding: 0 10px;\n\n border-collapse: collapse;\n\n &.model {\n tbody {\n tr {\n td {\n padding: 0;\n\n vertical-align: top;\n\n &:first-of-type {\n width: 174px;\n padding: 0 0 0 2em;\n }\n }\n }\n }\n }\n\n &.headers {\n td {\n font-size: 12px;\n font-weight: 300;\n\n vertical-align: middle;\n\n @include type.text_code();\n }\n\n .header-example {\n color: #999;\n font-style: italic;\n }\n }\n\n tbody {\n tr {\n td {\n padding: 10px 0 0 0;\n\n vertical-align: top;\n\n &:first-of-type {\n min-width: 6em;\n padding: 10px 0;\n }\n\n &:has(.model-box) {\n max-width: 1px; // fits content in available space instead of growing the table beyond its container\n }\n }\n }\n }\n\n thead {\n tr {\n th,\n td {\n font-size: 12px;\n font-weight: bold;\n\n padding: 12px 0;\n\n text-align: left;\n\n border-bottom: 1px solid rgba($table-thead-td-border-bottom-color, 0.2);\n\n @include type.text_body();\n }\n }\n }\n}\n\n.parameters-col_description {\n width: 99%; // forces other columns to shrink to their content widths\n margin-bottom: 2em;\n input {\n width: 100%;\n max-width: 340px;\n }\n\n select {\n border-width: 1px;\n }\n\n .markdown,\n .renderedMarkdown {\n p {\n margin: 0;\n }\n }\n}\n\n.parameter__name {\n font-size: 16px;\n font-weight: normal;\n\n // hack to give breathing room to the name column\n // TODO: refactor all of this to flexbox\n margin-right: 0.75em;\n\n @include type.text_headline();\n\n &.required {\n font-weight: bold;\n\n span {\n color: red;\n }\n\n &:after {\n font-size: 10px;\n\n position: relative;\n top: -6px;\n\n padding: 5px;\n\n content: \"required\";\n\n color: rgba($table-parameter-name-required-font-color, 0.6);\n }\n }\n}\n\n.parameter__in,\n.parameter__extension {\n font-size: 12px;\n font-style: italic;\n\n @include type.text_code($table-parameter-in-font-color);\n}\n\n.parameter__deprecated {\n font-size: 12px;\n font-style: italic;\n\n @include type.text_code($table-parameter-deprecated-font-color);\n}\n\n.parameter__empty_value_toggle {\n display: block;\n font-size: 13px;\n padding-top: 5px;\n padding-bottom: 12px;\n\n input {\n margin-right: 7px;\n width: auto;\n }\n\n &.disabled {\n opacity: 0.7;\n }\n}\n\n.table-container {\n padding: 20px;\n}\n\n.response-col_description {\n width: 99%; // forces other columns to shrink to their content widths\n\n .markdown,\n .renderedMarkdown {\n p {\n margin: 0;\n }\n }\n}\n\n.response-col_links {\n min-width: 6em;\n}\n\n.response__extension {\n font-size: 12px;\n font-style: italic;\n\n @include type.text_code($table-parameter-in-font-color);\n}\n","@use \"variables\" as *;\n@use \"type\";\n\n.topbar {\n padding: 10px 0;\n\n background-color: $topbar-background-color;\n .topbar-wrapper {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 10px;\n }\n @media (max-width: 550px) {\n .topbar-wrapper {\n flex-direction: column;\n align-items: start;\n }\n }\n\n a {\n font-size: 1.5em;\n font-weight: bold;\n\n display: flex;\n align-items: center;\n flex: 1;\n\n max-width: 300px;\n\n text-decoration: none;\n\n @include type.text_headline($topbar-link-font-color);\n\n span {\n margin: 0;\n padding: 0 10px;\n }\n }\n\n .download-url-wrapper {\n display: flex;\n flex: 3;\n justify-content: flex-end;\n\n input[type=\"text\"] {\n width: 100%;\n max-width: 100%;\n margin: 0;\n\n border: 2px solid $topbar-download-url-wrapper-element-border-color;\n border-radius: 4px 0 0 4px;\n outline: none;\n }\n\n .select-label {\n display: flex;\n align-items: center;\n\n width: 100%;\n max-width: 600px;\n margin: 0;\n color: #f0f0f0;\n span {\n font-size: 16px;\n\n flex: 1;\n\n padding: 0 10px 0 0;\n\n text-align: right;\n }\n\n select {\n flex: 2;\n\n width: 100%;\n\n border: 2px solid $topbar-download-url-wrapper-element-border-color;\n outline: none;\n box-shadow: none;\n }\n }\n\n .download-url-button {\n font-size: 16px;\n font-weight: bold;\n\n padding: 4px 30px;\n\n border: none;\n border-radius: 0 4px 4px 0;\n background: $topbar-download-url-button-background-color;\n\n @include type.text_headline($topbar-download-url-button-font-color);\n }\n }\n @media (max-width: 550px) {\n .download-url-wrapper {\n width: 100%;\n }\n }\n}\n","@use \"sass:color\";\n@use \"variables\" as *;\n@use \"type\";\n\n.info {\n margin: 50px 0;\n\n &.failed-config {\n max-width: 880px;\n margin-left: auto;\n margin-right: auto;\n text-align: center;\n }\n\n hgroup.main {\n margin: 0 0 20px 0;\n a {\n font-size: 12px;\n }\n }\n pre {\n font-size: 14px;\n }\n p,\n li,\n table {\n font-size: 14px;\n\n @include type.text_body();\n }\n\n h1,\n h2,\n h3,\n h4,\n h5 {\n @include type.text_body();\n }\n\n a {\n font-size: 14px;\n\n transition: all 0.4s;\n\n @include type.text_body($info-link-font-color);\n\n &:hover {\n color: color.adjust($info-link-font-color-hover, $lightness: -15%);\n }\n }\n > div {\n margin: 0 0 5px 0;\n }\n\n .base-url {\n font-size: 12px;\n font-weight: 300 !important;\n\n margin: 0;\n\n @include type.text_code();\n }\n\n .title {\n font-size: 36px;\n\n margin: 0;\n\n @include type.text_body();\n\n small {\n font-size: 10px;\n\n position: relative;\n top: -5px;\n\n display: inline-block;\n\n margin: 0 0 0 5px;\n padding: 2px 4px;\n\n vertical-align: super;\n\n border-radius: 57px;\n background: $info-title-small-background-color;\n\n &.version-stamp {\n background-color: #89bf04;\n }\n\n pre {\n margin: 0;\n padding: 0;\n\n @include type.text_headline($info-title-small-pre-font-color);\n }\n }\n }\n}\n","@use \"variables\" as *;\n@use \"type\";\n\n.auth-btn-wrapper {\n display: flex;\n\n padding: 10px 0;\n\n justify-content: center;\n\n .btn-done {\n margin-right: 1em;\n }\n}\n\n.auth-wrapper {\n display: flex;\n\n flex: 1;\n justify-content: flex-end;\n\n .authorize {\n padding-right: 20px;\n margin-left: 10px;\n margin-right: 10px;\n }\n}\n\n.auth-container {\n margin: 0 0 10px 0;\n padding: 10px 20px;\n\n border-bottom: 1px solid $auth-container-border-color;\n\n &:last-of-type {\n margin: 0;\n padding: 10px 20px;\n\n border: 0;\n }\n\n h4 {\n margin: 5px 0 15px 0 !important;\n }\n\n .wrapper {\n margin: 0;\n padding: 0;\n }\n\n input[type=\"text\"],\n input[type=\"password\"] {\n min-width: 230px;\n }\n\n .errors {\n font-size: 12px;\n\n padding: 10px;\n\n border-radius: 4px;\n\n background-color: #ffeeee;\n\n color: red;\n\n margin: 1em;\n\n @include type.text_code();\n\n b {\n text-transform: capitalize;\n margin-right: 1em;\n }\n }\n}\n\n.scopes {\n h2 {\n font-size: 14px;\n\n @include type.text_headline();\n\n a {\n font-size: 12px;\n color: $auth-select-all-none-link-font-color;\n cursor: pointer;\n padding-left: 10px;\n text-decoration: underline;\n }\n }\n}\n\n.scope-def {\n padding: 0 0 20px 0;\n}\n","@use \"variables\" as *;\n@use \"type\";\n\n.errors-wrapper {\n margin: 20px;\n padding: 10px 20px;\n\n animation: scaleUp 0.5s;\n\n border: 2px solid $color-delete;\n border-radius: 4px;\n background: rgba($color-delete, 0.1);\n\n .error-wrapper {\n margin: 0 0 10px 0;\n }\n\n .errors {\n h4 {\n font-size: 14px;\n\n margin: 0;\n\n @include type.text_code();\n }\n\n small {\n color: $errors-wrapper-errors-small-font-color;\n }\n\n .message {\n white-space: pre-line;\n\n &.thrown {\n max-width: 100%;\n }\n }\n\n .error-line {\n text-decoration: underline;\n cursor: pointer;\n }\n }\n\n hgroup {\n display: flex;\n\n align-items: center;\n\n h4 {\n font-size: 20px;\n\n margin: 0;\n\n flex: 1;\n @include type.text_headline();\n }\n }\n}\n\n@keyframes scaleUp {\n 0% {\n transform: scale(0.8);\n\n opacity: 0;\n }\n 100% {\n transform: scale(1);\n\n opacity: 1;\n }\n}\n",".Resizer.vertical.disabled {\n display: none;\n}\n","@use \"variables\" as *;\n@use \"type\";\n\n.markdown,\n.renderedMarkdown {\n p,\n pre {\n margin: 1em auto;\n\n word-break: break-all; /* Fallback trick */\n word-break: break-word;\n }\n pre {\n color: black;\n font-weight: normal;\n white-space: pre-wrap;\n background: none;\n padding: 0px;\n }\n\n code {\n font-size: 14px;\n padding: 5px 7px;\n\n border-radius: 4px;\n background: rgba($info-code-background-color, 0.05);\n\n @include type.text_code($info-code-font-color);\n }\n\n pre > code {\n display: block;\n }\n}\n","@use \"./../../../components/mixins\";\n\n.json-schema-2020-12 {\n &-keyword--\\$vocabulary {\n ul {\n @include mixins.expansion-border;\n }\n }\n\n &-\\$vocabulary-uri {\n margin-left: 35px;\n\n &--disabled {\n text-decoration: line-through;\n }\n }\n}\n","@use \"./../../../../style/variables\" as *;\n@use \"./../../../../style/type\";\n\n@mixin expansion-border {\n margin: 0 0 0 20px;\n border-left: 1px dashed\n rgba($section-models-model-container-background-color, 0.1);\n}\n\n@mixin json-schema-2020-12-keyword--primary {\n color: $text-code-default-font-color;\n font-style: normal;\n}\n\n@mixin json-schema-2020-12-keyword--extension {\n color: #929292;\n font-style: italic;\n}\n\n@mixin json-schema-2020-12-keyword {\n margin: 5px 0 5px 0;\n\n &__children {\n @include expansion-border;\n padding: 0;\n\n &--collapsed {\n display: none;\n }\n }\n\n &__name {\n font-size: 12px;\n margin-left: 20px;\n font-weight: bold;\n\n &--primary {\n @include json-schema-2020-12-keyword--primary;\n }\n\n &--secondary {\n color: #6b6b6b;\n font-style: italic;\n }\n\n &--extension {\n @include json-schema-2020-12-keyword--extension;\n }\n }\n\n &__value {\n color: #6b6b6b;\n font-style: italic;\n font-size: 12px;\n font-weight: normal;\n\n &--primary {\n @include json-schema-2020-12-keyword--primary;\n }\n\n &--secondary {\n color: #6b6b6b;\n font-style: italic;\n }\n\n &--extension {\n @include json-schema-2020-12-keyword--extension;\n }\n\n &--warning {\n @include type.text_code();\n font-style: normal;\n display: inline-block;\n margin-left: 10px;\n line-height: 1.5;\n padding: 1px 4px 1px 4px;\n border-radius: 4px;\n color: red;\n border: 1px dashed red;\n }\n }\n}\n","@use \"./../../mixins\";\n\n.json-schema-2020-12-keyword--const {\n .json-schema-2020-12-json-viewer__name {\n @include mixins.json-schema-2020-12-keyword--primary;\n }\n\n .json-schema-2020-12-json-viewer__value {\n @include mixins.json-schema-2020-12-keyword--primary;\n }\n}\n","@use \"./../../../../../../style/type\";\n\n.json-schema-2020-12__constraint {\n @include type.text_code();\n margin-left: 10px;\n line-height: 1.5;\n padding: 1px 3px;\n color: white;\n background-color: #805ad5;\n border-radius: 4px;\n\n &--string {\n color: white;\n background-color: #d69e2e;\n }\n}\n","@use \"./../../mixins\";\n\n.json-schema-2020-12-keyword--default {\n .json-schema-2020-12-json-viewer__name {\n @include mixins.json-schema-2020-12-keyword--primary;\n }\n\n .json-schema-2020-12-json-viewer__value {\n @include mixins.json-schema-2020-12-keyword--primary;\n }\n}\n",".json-schema-2020-12-keyword--dependentRequired {\n & > ul {\n display: inline-block;\n padding: 0;\n margin: 0;\n\n li {\n display: inline;\n list-style-type: none;\n }\n }\n}\n",".json-schema-2020-12-keyword--description {\n color: #6b6b6b;\n font-size: 12px;\n margin-left: 20px;\n\n & p {\n margin: 0;\n }\n}\n","@use \"./../../mixins\";\n\n.json-schema-2020-12-keyword--examples {\n .json-schema-2020-12-json-viewer__name {\n @include mixins.json-schema-2020-12-keyword--primary;\n }\n\n .json-schema-2020-12-json-viewer__value {\n @include mixins.json-schema-2020-12-keyword--primary;\n }\n}\n","@use \"./../../mixins\";\n\n.json-schema-2020-12-json-viewer-extension-keyword {\n .json-schema-2020-12-json-viewer__name {\n @include mixins.json-schema-2020-12-keyword--extension;\n }\n\n .json-schema-2020-12-json-viewer__value {\n @include mixins.json-schema-2020-12-keyword--extension;\n }\n}\n","@use \"./../../../../../../style/variables\" as *;\n\n.json-schema-2020-12 {\n &-keyword--patternProperties {\n ul {\n margin: 0;\n padding: 0;\n border: none;\n }\n\n .json-schema-2020-12__title:first-of-type::before {\n color: $prop-type-font-color;\n content: \"/\";\n }\n\n .json-schema-2020-12__title:first-of-type::after {\n color: $prop-type-font-color;\n content: \"/\";\n }\n }\n}\n",".json-schema-2020-12 {\n &-keyword--properties {\n & > ul {\n margin: 0;\n padding: 0;\n border: none;\n }\n }\n\n &-property {\n list-style-type: none;\n\n &--required {\n &\n > .json-schema-2020-12:first-of-type\n > .json-schema-2020-12-head\n .json-schema-2020-12__title:after {\n content: \"*\";\n color: red;\n font-weight: bold;\n }\n }\n }\n}\n","@use \"./../../../../../../style/variables\" as *;\n@use \"./../../../../../../style/type\";\n\n.json-schema-2020-12 {\n &__title {\n @include type.text_headline($section-models-model-title-font-color);\n display: inline-block;\n font-weight: bold;\n font-size: 12px;\n line-height: normal;\n\n & .json-schema-2020-12-keyword__name {\n margin: 0;\n }\n }\n\n &-property {\n margin: 7px 0;\n\n .json-schema-2020-12__title {\n @include type.text_code();\n font-size: 12px;\n vertical-align: middle;\n }\n }\n}\n","@use \"./../../../../../style/variables\" as *;\n@use \"./../mixins\";\n@use \"./$vocabulary/$vocabulary\" as vocabulary;\n@use \"./Const/const\";\n@use \"./Constraint/constraint\";\n@use \"./Default/default\";\n@use \"./DependentRequired/dependent-required\";\n@use \"./Description/description\";\n@use \"./Enum/enum\";\n@use \"./Examples/examples\";\n@use \"./ExtensionKeywords/extension-keywords\";\n@use \"./PatternProperties/pattern-properties\";\n@use \"./Properties/properties\";\n@use \"./Title/title\";\n\n.json-schema-2020-12-keyword {\n @include mixins.json-schema-2020-12-keyword;\n}\n\n.json-schema-2020-12-keyword__name--secondary\n + .json-schema-2020-12-keyword__value--secondary::before {\n content: \"=\";\n}\n\n.json-schema-2020-12__attribute {\n font-family: monospace;\n color: $text-code-default-font-color;\n font-size: 12px;\n text-transform: lowercase;\n padding-left: 10px;\n\n &--primary {\n color: $prop-type-font-color;\n }\n\n &--muted {\n color: gray;\n }\n\n &--warning {\n color: red;\n }\n}\n","@use \"./../mixins\";\n@use \"./../keywords/all\";\n\n.json-schema-2020-12-json-viewer {\n @include mixins.json-schema-2020-12-keyword;\n}\n\n.json-schema-2020-12-json-viewer__name--secondary\n + .json-schema-2020-12-json-viewer__value--secondary::before {\n content: \"=\";\n}\n","@use \"./../../../../../style/variables\" as *;\n@use \"./../../components/mixins\";\n\n.json-schema-2020-12 {\n margin: 0 20px 15px 20px;\n border-radius: 4px;\n padding: 12px 0 12px 20px;\n background-color: rgba(\n $section-models-model-container-background-color,\n 0.05\n );\n\n &:first-of-type {\n margin: 20px;\n }\n\n &:last-of-type {\n margin: 0 20px;\n }\n\n &--embedded {\n background-color: inherit;\n padding: 0 inherit 0 inherit;\n }\n\n &-body {\n @include mixins.expansion-border;\n margin: 2px 0;\n\n &--collapsed {\n display: none;\n }\n }\n}\n",".json-schema-2020-12-accordion {\n outline: none;\n border: none;\n padding-left: 0;\n\n &__children {\n display: inline-block;\n }\n\n &__icon {\n width: 18px;\n height: 18px;\n display: inline-block;\n vertical-align: bottom;\n\n &--expanded {\n transition: transform 0.15s ease-in;\n transform: rotate(-90deg);\n transform-origin: 50% 50%;\n }\n\n &--collapsed {\n transition: transform 0.15s ease-in;\n transform: rotate(0deg);\n transform-origin: 50% 50%;\n }\n\n & svg {\n height: 20px;\n width: 20px;\n }\n }\n}\n","@use \"./../../../../../style/variables\" as *;\n@use \"./../../../../../style/type\";\n\n.json-schema-2020-12-expand-deep-button {\n @include type.text_headline($section-models-model-title-font-color);\n font-size: 12px;\n color: rgb(175, 174, 174);\n border: none;\n padding-right: 0;\n}\n",".model-box {\n // inferred names of Schema Objects\n &\n .json-schema-2020-12:not(.json-schema-2020-12--embedded)\n > .json-schema-2020-12-head\n .json-schema-2020-12__title:first-of-type {\n font-size: 16px;\n }\n\n & > .json-schema-2020-12 {\n margin: 0;\n }\n\n .json-schema-2020-12 {\n padding: 0;\n background-color: transparent;\n }\n\n .json-schema-2020-12-accordion,\n .json-schema-2020-12-expand-deep-button {\n background-color: transparent;\n }\n}\n",".models\n .json-schema-2020-12:not(.json-schema-2020-12--embedded)\n > .json-schema-2020-12-head\n .json-schema-2020-12__title:first-of-type {\n font-size: 16px;\n}\n\n.models .json-schema-2020-12:not(.json-schema-2020-12--embedded) {\n width: calc(100% - 40px);\n overflow-x: auto;\n}\n"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/INSTALLER b/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/LICENSE b/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/LICENSE new file mode 100644 index 0000000..74c7482 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2012-2020 Janne Vanhala + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/METADATA b/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/METADATA new file mode 100644 index 0000000..9b15e08 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/METADATA @@ -0,0 +1,49 @@ +Metadata-Version: 2.1 +Name: inflection +Version: 0.5.1 +Summary: A port of Ruby on Rails inflector to Python +Home-page: https://github.com/jpvanhal/inflection +Author: Janne Vanhala +Author-email: janne.vanhala@gmail.com +License: MIT +Platform: UNKNOWN +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: Natural Language :: English +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Requires-Python: >=3.5 + +Inflection +========== + +|build status|_ + +.. |build status| image:: https://travis-ci.org/jpvanhal/inflection.svg?branch=master + :alt: Build Status +.. _build status: http://travis-ci.org/jpvanhal/inflection + +Inflection is a string transformation library. It singularizes and pluralizes +English words, and transforms strings from CamelCase to underscored string. +Inflection is a port of `Ruby on Rails`_' `inflector`_ to Python. + +.. _Ruby on Rails: http://rubyonrails.org +.. _inflector: http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html + +Resources +--------- + +- `Documentation `_ +- `Issue Tracker `_ +- `Code `_ +- `Development Version + `_ + + diff --git a/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/RECORD b/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/RECORD new file mode 100644 index 0000000..cdebf7c --- /dev/null +++ b/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/RECORD @@ -0,0 +1,11 @@ +__pycache__/inflection.cpython-310.pyc,, +inflection-0.5.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +inflection-0.5.1.dist-info/LICENSE,sha256=np-bSy51Q60UhvEyi_nsUOWl4rucrOtZZSSW3WHmQTM,1062 +inflection-0.5.1.dist-info/METADATA,sha256=HzhEOEIN1xKH0DD-z9mPJ2_4ZXu_mYk4DVDxmcHiDCU,1730 +inflection-0.5.1.dist-info/RECORD,, +inflection-0.5.1.dist-info/WHEEL,sha256=ADKeyaGyKF5DwBNE0sRE5pvW-bSkFMJfBuhzZ3rceP4,110 +inflection-0.5.1.dist-info/top_level.txt,sha256=AT2vYRZGMGYnasNdj4oJbpSddltYSZ3cZGH8Bjo7xQo,11 +inflection.py,sha256=kJmjhziRjCeORghR4iWBJQqmXLOpFRwseGVW6gFheas,11437 +inflection/__init__.py,sha256=Py387trh0P9zmcI45w2gLrDAplji9kmtGr5s7DY3TD8,11437 +inflection/__pycache__/__init__.cpython-310.pyc,, +inflection/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/WHEEL b/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/WHEEL new file mode 100644 index 0000000..6d38aa0 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.35.1) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/top_level.txt b/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/top_level.txt new file mode 100644 index 0000000..8d3ece7 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/inflection-0.5.1.dist-info/top_level.txt @@ -0,0 +1 @@ +inflection diff --git a/.venv/lib/python3.10/site-packages/inflection.py b/.venv/lib/python3.10/site-packages/inflection.py new file mode 100644 index 0000000..252b024 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/inflection.py @@ -0,0 +1,426 @@ +# -*- coding: utf-8 -*- +""" + inflection + ~~~~~~~~~~~~ + + A port of Ruby on Rails' inflector to Python. + + :copyright: (c) 2012-2020 by Janne Vanhala + + :license: MIT, see LICENSE for more details. +""" +import re +import unicodedata + +__version__ = '0.5.0' + +PLURALS = [ + (r"(?i)(quiz)$", r'\1zes'), + (r"(?i)^(oxen)$", r'\1'), + (r"(?i)^(ox)$", r'\1en'), + (r"(?i)(m|l)ice$", r'\1ice'), + (r"(?i)(m|l)ouse$", r'\1ice'), + (r"(?i)(passer)s?by$", r'\1sby'), + (r"(?i)(matr|vert|ind)(?:ix|ex)$", r'\1ices'), + (r"(?i)(x|ch|ss|sh)$", r'\1es'), + (r"(?i)([^aeiouy]|qu)y$", r'\1ies'), + (r"(?i)(hive)$", r'\1s'), + (r"(?i)([lr])f$", r'\1ves'), + (r"(?i)([^f])fe$", r'\1ves'), + (r"(?i)sis$", 'ses'), + (r"(?i)([ti])a$", r'\1a'), + (r"(?i)([ti])um$", r'\1a'), + (r"(?i)(buffal|potat|tomat)o$", r'\1oes'), + (r"(?i)(bu)s$", r'\1ses'), + (r"(?i)(alias|status)$", r'\1es'), + (r"(?i)(octop|vir)i$", r'\1i'), + (r"(?i)(octop|vir)us$", r'\1i'), + (r"(?i)^(ax|test)is$", r'\1es'), + (r"(?i)s$", 's'), + (r"$", 's'), +] + +SINGULARS = [ + (r"(?i)(database)s$", r'\1'), + (r"(?i)(quiz)zes$", r'\1'), + (r"(?i)(matr)ices$", r'\1ix'), + (r"(?i)(vert|ind)ices$", r'\1ex'), + (r"(?i)(passer)sby$", r'\1by'), + (r"(?i)^(ox)en", r'\1'), + (r"(?i)(alias|status)(es)?$", r'\1'), + (r"(?i)(octop|vir)(us|i)$", r'\1us'), + (r"(?i)^(a)x[ie]s$", r'\1xis'), + (r"(?i)(cris|test)(is|es)$", r'\1is'), + (r"(?i)(shoe)s$", r'\1'), + (r"(?i)(o)es$", r'\1'), + (r"(?i)(bus)(es)?$", r'\1'), + (r"(?i)(m|l)ice$", r'\1ouse'), + (r"(?i)(x|ch|ss|sh)es$", r'\1'), + (r"(?i)(m)ovies$", r'\1ovie'), + (r"(?i)(s)eries$", r'\1eries'), + (r"(?i)([^aeiouy]|qu)ies$", r'\1y'), + (r"(?i)([lr])ves$", r'\1f'), + (r"(?i)(tive)s$", r'\1'), + (r"(?i)(hive)s$", r'\1'), + (r"(?i)([^f])ves$", r'\1fe'), + (r"(?i)(t)he(sis|ses)$", r"\1hesis"), + (r"(?i)(s)ynop(sis|ses)$", r"\1ynopsis"), + (r"(?i)(p)rogno(sis|ses)$", r"\1rognosis"), + (r"(?i)(p)arenthe(sis|ses)$", r"\1arenthesis"), + (r"(?i)(d)iagno(sis|ses)$", r"\1iagnosis"), + (r"(?i)(b)a(sis|ses)$", r"\1asis"), + (r"(?i)(a)naly(sis|ses)$", r"\1nalysis"), + (r"(?i)([ti])a$", r'\1um'), + (r"(?i)(n)ews$", r'\1ews'), + (r"(?i)(ss)$", r'\1'), + (r"(?i)s$", ''), +] + +UNCOUNTABLES = { + 'equipment', + 'fish', + 'information', + 'jeans', + 'money', + 'rice', + 'series', + 'sheep', + 'species'} + + +def _irregular(singular: str, plural: str) -> None: + """ + A convenience function to add appropriate rules to plurals and singular + for irregular words. + + :param singular: irregular word in singular form + :param plural: irregular word in plural form + """ + def caseinsensitive(string: str) -> str: + return ''.join('[' + char + char.upper() + ']' for char in string) + + if singular[0].upper() == plural[0].upper(): + PLURALS.insert(0, ( + r"(?i)({}){}$".format(singular[0], singular[1:]), + r'\1' + plural[1:] + )) + PLURALS.insert(0, ( + r"(?i)({}){}$".format(plural[0], plural[1:]), + r'\1' + plural[1:] + )) + SINGULARS.insert(0, ( + r"(?i)({}){}$".format(plural[0], plural[1:]), + r'\1' + singular[1:] + )) + else: + PLURALS.insert(0, ( + r"{}{}$".format(singular[0].upper(), + caseinsensitive(singular[1:])), + plural[0].upper() + plural[1:] + )) + PLURALS.insert(0, ( + r"{}{}$".format(singular[0].lower(), + caseinsensitive(singular[1:])), + plural[0].lower() + plural[1:] + )) + PLURALS.insert(0, ( + r"{}{}$".format(plural[0].upper(), caseinsensitive(plural[1:])), + plural[0].upper() + plural[1:] + )) + PLURALS.insert(0, ( + r"{}{}$".format(plural[0].lower(), caseinsensitive(plural[1:])), + plural[0].lower() + plural[1:] + )) + SINGULARS.insert(0, ( + r"{}{}$".format(plural[0].upper(), caseinsensitive(plural[1:])), + singular[0].upper() + singular[1:] + )) + SINGULARS.insert(0, ( + r"{}{}$".format(plural[0].lower(), caseinsensitive(plural[1:])), + singular[0].lower() + singular[1:] + )) + + +def camelize(string: str, uppercase_first_letter: bool = True) -> str: + """ + Convert strings to CamelCase. + + Examples:: + + >>> camelize("device_type") + 'DeviceType' + >>> camelize("device_type", False) + 'deviceType' + + :func:`camelize` can be thought of as a inverse of :func:`underscore`, + although there are some cases where that does not hold:: + + >>> camelize(underscore("IOError")) + 'IoError' + + :param uppercase_first_letter: if set to `True` :func:`camelize` converts + strings to UpperCamelCase. If set to `False` :func:`camelize` produces + lowerCamelCase. Defaults to `True`. + """ + if uppercase_first_letter: + return re.sub(r"(?:^|_)(.)", lambda m: m.group(1).upper(), string) + else: + return string[0].lower() + camelize(string)[1:] + + +def dasherize(word: str) -> str: + """Replace underscores with dashes in the string. + + Example:: + + >>> dasherize("puni_puni") + 'puni-puni' + + """ + return word.replace('_', '-') + + +def humanize(word: str) -> str: + """ + Capitalize the first word and turn underscores into spaces and strip a + trailing ``"_id"``, if any. Like :func:`titleize`, this is meant for + creating pretty output. + + Examples:: + + >>> humanize("employee_salary") + 'Employee salary' + >>> humanize("author_id") + 'Author' + + """ + word = re.sub(r"_id$", "", word) + word = word.replace('_', ' ') + word = re.sub(r"(?i)([a-z\d]*)", lambda m: m.group(1).lower(), word) + word = re.sub(r"^\w", lambda m: m.group(0).upper(), word) + return word + + +def ordinal(number: int) -> str: + """ + Return the suffix that should be added to a number to denote the position + in an ordered sequence such as 1st, 2nd, 3rd, 4th. + + Examples:: + + >>> ordinal(1) + 'st' + >>> ordinal(2) + 'nd' + >>> ordinal(1002) + 'nd' + >>> ordinal(1003) + 'rd' + >>> ordinal(-11) + 'th' + >>> ordinal(-1021) + 'st' + + """ + number = abs(int(number)) + if number % 100 in (11, 12, 13): + return "th" + else: + return { + 1: "st", + 2: "nd", + 3: "rd", + }.get(number % 10, "th") + + +def ordinalize(number: int) -> str: + """ + Turn a number into an ordinal string used to denote the position in an + ordered sequence such as 1st, 2nd, 3rd, 4th. + + Examples:: + + >>> ordinalize(1) + '1st' + >>> ordinalize(2) + '2nd' + >>> ordinalize(1002) + '1002nd' + >>> ordinalize(1003) + '1003rd' + >>> ordinalize(-11) + '-11th' + >>> ordinalize(-1021) + '-1021st' + + """ + return "{}{}".format(number, ordinal(number)) + + +def parameterize(string: str, separator: str = '-') -> str: + """ + Replace special characters in a string so that it may be used as part of a + 'pretty' URL. + + Example:: + + >>> parameterize(u"Donald E. Knuth") + 'donald-e-knuth' + + """ + string = transliterate(string) + # Turn unwanted chars into the separator + string = re.sub(r"(?i)[^a-z0-9\-_]+", separator, string) + if separator: + re_sep = re.escape(separator) + # No more than one of the separator in a row. + string = re.sub(r'%s{2,}' % re_sep, separator, string) + # Remove leading/trailing separator. + string = re.sub(r"(?i)^{sep}|{sep}$".format(sep=re_sep), '', string) + + return string.lower() + + +def pluralize(word: str) -> str: + """ + Return the plural form of a word. + + Examples:: + + >>> pluralize("posts") + 'posts' + >>> pluralize("octopus") + 'octopi' + >>> pluralize("sheep") + 'sheep' + >>> pluralize("CamelOctopus") + 'CamelOctopi' + + """ + if not word or word.lower() in UNCOUNTABLES: + return word + else: + for rule, replacement in PLURALS: + if re.search(rule, word): + return re.sub(rule, replacement, word) + return word + + +def singularize(word: str) -> str: + """ + Return the singular form of a word, the reverse of :func:`pluralize`. + + Examples:: + + >>> singularize("posts") + 'post' + >>> singularize("octopi") + 'octopus' + >>> singularize("sheep") + 'sheep' + >>> singularize("word") + 'word' + >>> singularize("CamelOctopi") + 'CamelOctopus' + + """ + for inflection in UNCOUNTABLES: + if re.search(r'(?i)\b(%s)\Z' % inflection, word): + return word + + for rule, replacement in SINGULARS: + if re.search(rule, word): + return re.sub(rule, replacement, word) + return word + + +def tableize(word: str) -> str: + """ + Create the name of a table like Rails does for models to table names. This + method uses the :func:`pluralize` method on the last word in the string. + + Examples:: + + >>> tableize('RawScaledScorer') + 'raw_scaled_scorers' + >>> tableize('egg_and_ham') + 'egg_and_hams' + >>> tableize('fancyCategory') + 'fancy_categories' + """ + return pluralize(underscore(word)) + + +def titleize(word: str) -> str: + """ + Capitalize all the words and replace some characters in the string to + create a nicer looking title. :func:`titleize` is meant for creating pretty + output. + + Examples:: + + >>> titleize("man from the boondocks") + 'Man From The Boondocks' + >>> titleize("x-men: the last stand") + 'X Men: The Last Stand' + >>> titleize("TheManWithoutAPast") + 'The Man Without A Past' + >>> titleize("raiders_of_the_lost_ark") + 'Raiders Of The Lost Ark' + + """ + return re.sub( + r"\b('?\w)", + lambda match: match.group(1).capitalize(), + humanize(underscore(word)).title() + ) + + +def transliterate(string: str) -> str: + """ + Replace non-ASCII characters with an ASCII approximation. If no + approximation exists, the non-ASCII character is ignored. The string must + be ``unicode``. + + Examples:: + + >>> transliterate('älämölö') + 'alamolo' + >>> transliterate('Ærøskøbing') + 'rskbing' + + """ + normalized = unicodedata.normalize('NFKD', string) + return normalized.encode('ascii', 'ignore').decode('ascii') + + +def underscore(word: str) -> str: + """ + Make an underscored, lowercase form from the expression in the string. + + Example:: + + >>> underscore("DeviceType") + 'device_type' + + As a rule of thumb you can think of :func:`underscore` as the inverse of + :func:`camelize`, though there are cases where that does not hold:: + + >>> camelize(underscore("IOError")) + 'IoError' + + """ + word = re.sub(r"([A-Z]+)([A-Z][a-z])", r'\1_\2', word) + word = re.sub(r"([a-z\d])([A-Z])", r'\1_\2', word) + word = word.replace("-", "_") + return word.lower() + + +_irregular('person', 'people') +_irregular('man', 'men') +_irregular('human', 'humans') +_irregular('child', 'children') +_irregular('sex', 'sexes') +_irregular('move', 'moves') +_irregular('cow', 'kine') +_irregular('zombie', 'zombies') diff --git a/.venv/lib/python3.10/site-packages/inflection/__init__.py b/.venv/lib/python3.10/site-packages/inflection/__init__.py new file mode 100644 index 0000000..c18a0b6 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/inflection/__init__.py @@ -0,0 +1,426 @@ +# -*- coding: utf-8 -*- +""" + inflection + ~~~~~~~~~~~~ + + A port of Ruby on Rails' inflector to Python. + + :copyright: (c) 2012-2020 by Janne Vanhala + + :license: MIT, see LICENSE for more details. +""" +import re +import unicodedata + +__version__ = '0.5.1' + +PLURALS = [ + (r"(?i)(quiz)$", r'\1zes'), + (r"(?i)^(oxen)$", r'\1'), + (r"(?i)^(ox)$", r'\1en'), + (r"(?i)(m|l)ice$", r'\1ice'), + (r"(?i)(m|l)ouse$", r'\1ice'), + (r"(?i)(passer)s?by$", r'\1sby'), + (r"(?i)(matr|vert|ind)(?:ix|ex)$", r'\1ices'), + (r"(?i)(x|ch|ss|sh)$", r'\1es'), + (r"(?i)([^aeiouy]|qu)y$", r'\1ies'), + (r"(?i)(hive)$", r'\1s'), + (r"(?i)([lr])f$", r'\1ves'), + (r"(?i)([^f])fe$", r'\1ves'), + (r"(?i)sis$", 'ses'), + (r"(?i)([ti])a$", r'\1a'), + (r"(?i)([ti])um$", r'\1a'), + (r"(?i)(buffal|potat|tomat)o$", r'\1oes'), + (r"(?i)(bu)s$", r'\1ses'), + (r"(?i)(alias|status)$", r'\1es'), + (r"(?i)(octop|vir)i$", r'\1i'), + (r"(?i)(octop|vir)us$", r'\1i'), + (r"(?i)^(ax|test)is$", r'\1es'), + (r"(?i)s$", 's'), + (r"$", 's'), +] + +SINGULARS = [ + (r"(?i)(database)s$", r'\1'), + (r"(?i)(quiz)zes$", r'\1'), + (r"(?i)(matr)ices$", r'\1ix'), + (r"(?i)(vert|ind)ices$", r'\1ex'), + (r"(?i)(passer)sby$", r'\1by'), + (r"(?i)^(ox)en", r'\1'), + (r"(?i)(alias|status)(es)?$", r'\1'), + (r"(?i)(octop|vir)(us|i)$", r'\1us'), + (r"(?i)^(a)x[ie]s$", r'\1xis'), + (r"(?i)(cris|test)(is|es)$", r'\1is'), + (r"(?i)(shoe)s$", r'\1'), + (r"(?i)(o)es$", r'\1'), + (r"(?i)(bus)(es)?$", r'\1'), + (r"(?i)(m|l)ice$", r'\1ouse'), + (r"(?i)(x|ch|ss|sh)es$", r'\1'), + (r"(?i)(m)ovies$", r'\1ovie'), + (r"(?i)(s)eries$", r'\1eries'), + (r"(?i)([^aeiouy]|qu)ies$", r'\1y'), + (r"(?i)([lr])ves$", r'\1f'), + (r"(?i)(tive)s$", r'\1'), + (r"(?i)(hive)s$", r'\1'), + (r"(?i)([^f])ves$", r'\1fe'), + (r"(?i)(t)he(sis|ses)$", r"\1hesis"), + (r"(?i)(s)ynop(sis|ses)$", r"\1ynopsis"), + (r"(?i)(p)rogno(sis|ses)$", r"\1rognosis"), + (r"(?i)(p)arenthe(sis|ses)$", r"\1arenthesis"), + (r"(?i)(d)iagno(sis|ses)$", r"\1iagnosis"), + (r"(?i)(b)a(sis|ses)$", r"\1asis"), + (r"(?i)(a)naly(sis|ses)$", r"\1nalysis"), + (r"(?i)([ti])a$", r'\1um'), + (r"(?i)(n)ews$", r'\1ews'), + (r"(?i)(ss)$", r'\1'), + (r"(?i)s$", ''), +] + +UNCOUNTABLES = { + 'equipment', + 'fish', + 'information', + 'jeans', + 'money', + 'rice', + 'series', + 'sheep', + 'species'} + + +def _irregular(singular: str, plural: str) -> None: + """ + A convenience function to add appropriate rules to plurals and singular + for irregular words. + + :param singular: irregular word in singular form + :param plural: irregular word in plural form + """ + def caseinsensitive(string: str) -> str: + return ''.join('[' + char + char.upper() + ']' for char in string) + + if singular[0].upper() == plural[0].upper(): + PLURALS.insert(0, ( + r"(?i)({}){}$".format(singular[0], singular[1:]), + r'\1' + plural[1:] + )) + PLURALS.insert(0, ( + r"(?i)({}){}$".format(plural[0], plural[1:]), + r'\1' + plural[1:] + )) + SINGULARS.insert(0, ( + r"(?i)({}){}$".format(plural[0], plural[1:]), + r'\1' + singular[1:] + )) + else: + PLURALS.insert(0, ( + r"{}{}$".format(singular[0].upper(), + caseinsensitive(singular[1:])), + plural[0].upper() + plural[1:] + )) + PLURALS.insert(0, ( + r"{}{}$".format(singular[0].lower(), + caseinsensitive(singular[1:])), + plural[0].lower() + plural[1:] + )) + PLURALS.insert(0, ( + r"{}{}$".format(plural[0].upper(), caseinsensitive(plural[1:])), + plural[0].upper() + plural[1:] + )) + PLURALS.insert(0, ( + r"{}{}$".format(plural[0].lower(), caseinsensitive(plural[1:])), + plural[0].lower() + plural[1:] + )) + SINGULARS.insert(0, ( + r"{}{}$".format(plural[0].upper(), caseinsensitive(plural[1:])), + singular[0].upper() + singular[1:] + )) + SINGULARS.insert(0, ( + r"{}{}$".format(plural[0].lower(), caseinsensitive(plural[1:])), + singular[0].lower() + singular[1:] + )) + + +def camelize(string: str, uppercase_first_letter: bool = True) -> str: + """ + Convert strings to CamelCase. + + Examples:: + + >>> camelize("device_type") + 'DeviceType' + >>> camelize("device_type", False) + 'deviceType' + + :func:`camelize` can be thought of as a inverse of :func:`underscore`, + although there are some cases where that does not hold:: + + >>> camelize(underscore("IOError")) + 'IoError' + + :param uppercase_first_letter: if set to `True` :func:`camelize` converts + strings to UpperCamelCase. If set to `False` :func:`camelize` produces + lowerCamelCase. Defaults to `True`. + """ + if uppercase_first_letter: + return re.sub(r"(?:^|_)(.)", lambda m: m.group(1).upper(), string) + else: + return string[0].lower() + camelize(string)[1:] + + +def dasherize(word: str) -> str: + """Replace underscores with dashes in the string. + + Example:: + + >>> dasherize("puni_puni") + 'puni-puni' + + """ + return word.replace('_', '-') + + +def humanize(word: str) -> str: + """ + Capitalize the first word and turn underscores into spaces and strip a + trailing ``"_id"``, if any. Like :func:`titleize`, this is meant for + creating pretty output. + + Examples:: + + >>> humanize("employee_salary") + 'Employee salary' + >>> humanize("author_id") + 'Author' + + """ + word = re.sub(r"_id$", "", word) + word = word.replace('_', ' ') + word = re.sub(r"(?i)([a-z\d]*)", lambda m: m.group(1).lower(), word) + word = re.sub(r"^\w", lambda m: m.group(0).upper(), word) + return word + + +def ordinal(number: int) -> str: + """ + Return the suffix that should be added to a number to denote the position + in an ordered sequence such as 1st, 2nd, 3rd, 4th. + + Examples:: + + >>> ordinal(1) + 'st' + >>> ordinal(2) + 'nd' + >>> ordinal(1002) + 'nd' + >>> ordinal(1003) + 'rd' + >>> ordinal(-11) + 'th' + >>> ordinal(-1021) + 'st' + + """ + number = abs(int(number)) + if number % 100 in (11, 12, 13): + return "th" + else: + return { + 1: "st", + 2: "nd", + 3: "rd", + }.get(number % 10, "th") + + +def ordinalize(number: int) -> str: + """ + Turn a number into an ordinal string used to denote the position in an + ordered sequence such as 1st, 2nd, 3rd, 4th. + + Examples:: + + >>> ordinalize(1) + '1st' + >>> ordinalize(2) + '2nd' + >>> ordinalize(1002) + '1002nd' + >>> ordinalize(1003) + '1003rd' + >>> ordinalize(-11) + '-11th' + >>> ordinalize(-1021) + '-1021st' + + """ + return "{}{}".format(number, ordinal(number)) + + +def parameterize(string: str, separator: str = '-') -> str: + """ + Replace special characters in a string so that it may be used as part of a + 'pretty' URL. + + Example:: + + >>> parameterize(u"Donald E. Knuth") + 'donald-e-knuth' + + """ + string = transliterate(string) + # Turn unwanted chars into the separator + string = re.sub(r"(?i)[^a-z0-9\-_]+", separator, string) + if separator: + re_sep = re.escape(separator) + # No more than one of the separator in a row. + string = re.sub(r'%s{2,}' % re_sep, separator, string) + # Remove leading/trailing separator. + string = re.sub(r"(?i)^{sep}|{sep}$".format(sep=re_sep), '', string) + + return string.lower() + + +def pluralize(word: str) -> str: + """ + Return the plural form of a word. + + Examples:: + + >>> pluralize("posts") + 'posts' + >>> pluralize("octopus") + 'octopi' + >>> pluralize("sheep") + 'sheep' + >>> pluralize("CamelOctopus") + 'CamelOctopi' + + """ + if not word or word.lower() in UNCOUNTABLES: + return word + else: + for rule, replacement in PLURALS: + if re.search(rule, word): + return re.sub(rule, replacement, word) + return word + + +def singularize(word: str) -> str: + """ + Return the singular form of a word, the reverse of :func:`pluralize`. + + Examples:: + + >>> singularize("posts") + 'post' + >>> singularize("octopi") + 'octopus' + >>> singularize("sheep") + 'sheep' + >>> singularize("word") + 'word' + >>> singularize("CamelOctopi") + 'CamelOctopus' + + """ + for inflection in UNCOUNTABLES: + if re.search(r'(?i)\b(%s)\Z' % inflection, word): + return word + + for rule, replacement in SINGULARS: + if re.search(rule, word): + return re.sub(rule, replacement, word) + return word + + +def tableize(word: str) -> str: + """ + Create the name of a table like Rails does for models to table names. This + method uses the :func:`pluralize` method on the last word in the string. + + Examples:: + + >>> tableize('RawScaledScorer') + 'raw_scaled_scorers' + >>> tableize('egg_and_ham') + 'egg_and_hams' + >>> tableize('fancyCategory') + 'fancy_categories' + """ + return pluralize(underscore(word)) + + +def titleize(word: str) -> str: + """ + Capitalize all the words and replace some characters in the string to + create a nicer looking title. :func:`titleize` is meant for creating pretty + output. + + Examples:: + + >>> titleize("man from the boondocks") + 'Man From The Boondocks' + >>> titleize("x-men: the last stand") + 'X Men: The Last Stand' + >>> titleize("TheManWithoutAPast") + 'The Man Without A Past' + >>> titleize("raiders_of_the_lost_ark") + 'Raiders Of The Lost Ark' + + """ + return re.sub( + r"\b('?\w)", + lambda match: match.group(1).capitalize(), + humanize(underscore(word)).title() + ) + + +def transliterate(string: str) -> str: + """ + Replace non-ASCII characters with an ASCII approximation. If no + approximation exists, the non-ASCII character is ignored. The string must + be ``unicode``. + + Examples:: + + >>> transliterate('älämölö') + 'alamolo' + >>> transliterate('Ærøskøbing') + 'rskbing' + + """ + normalized = unicodedata.normalize('NFKD', string) + return normalized.encode('ascii', 'ignore').decode('ascii') + + +def underscore(word: str) -> str: + """ + Make an underscored, lowercase form from the expression in the string. + + Example:: + + >>> underscore("DeviceType") + 'device_type' + + As a rule of thumb you can think of :func:`underscore` as the inverse of + :func:`camelize`, though there are cases where that does not hold:: + + >>> camelize(underscore("IOError")) + 'IoError' + + """ + word = re.sub(r"([A-Z]+)([A-Z][a-z])", r'\1_\2', word) + word = re.sub(r"([a-z\d])([A-Z])", r'\1_\2', word) + word = word.replace("-", "_") + return word.lower() + + +_irregular('person', 'people') +_irregular('man', 'men') +_irregular('human', 'humans') +_irregular('child', 'children') +_irregular('sex', 'sexes') +_irregular('move', 'moves') +_irregular('cow', 'kine') +_irregular('zombie', 'zombies') diff --git a/.venv/lib/python3.10/site-packages/inflection/py.typed b/.venv/lib/python3.10/site-packages/inflection/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/INSTALLER b/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/METADATA b/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/METADATA new file mode 100644 index 0000000..d9536b6 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/METADATA @@ -0,0 +1,176 @@ +Metadata-Version: 2.3 +Name: jsonschema +Version: 4.23.0 +Summary: An implementation of JSON Schema validation for Python +Project-URL: Homepage, https://github.com/python-jsonschema/jsonschema +Project-URL: Documentation, https://python-jsonschema.readthedocs.io/ +Project-URL: Issues, https://github.com/python-jsonschema/jsonschema/issues/ +Project-URL: Funding, https://github.com/sponsors/Julian +Project-URL: Tidelift, https://tidelift.com/subscription/pkg/pypi-jsonschema?utm_source=pypi-jsonschema&utm_medium=referral&utm_campaign=pypi-link +Project-URL: Changelog, https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst +Project-URL: Source, https://github.com/python-jsonschema/jsonschema +Author-email: Julian Berman +License: MIT +License-File: COPYING +Keywords: data validation,json,json schema,jsonschema,validation +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: File Formats :: JSON +Classifier: Topic :: File Formats :: JSON :: JSON Schema +Requires-Python: >=3.8 +Requires-Dist: attrs>=22.2.0 +Requires-Dist: importlib-resources>=1.4.0; python_version < '3.9' +Requires-Dist: jsonschema-specifications>=2023.03.6 +Requires-Dist: pkgutil-resolve-name>=1.3.10; python_version < '3.9' +Requires-Dist: referencing>=0.28.4 +Requires-Dist: rpds-py>=0.7.1 +Provides-Extra: format +Requires-Dist: fqdn; extra == 'format' +Requires-Dist: idna; extra == 'format' +Requires-Dist: isoduration; extra == 'format' +Requires-Dist: jsonpointer>1.13; extra == 'format' +Requires-Dist: rfc3339-validator; extra == 'format' +Requires-Dist: rfc3987; extra == 'format' +Requires-Dist: uri-template; extra == 'format' +Requires-Dist: webcolors>=1.11; extra == 'format' +Provides-Extra: format-nongpl +Requires-Dist: fqdn; extra == 'format-nongpl' +Requires-Dist: idna; extra == 'format-nongpl' +Requires-Dist: isoduration; extra == 'format-nongpl' +Requires-Dist: jsonpointer>1.13; extra == 'format-nongpl' +Requires-Dist: rfc3339-validator; extra == 'format-nongpl' +Requires-Dist: rfc3986-validator>0.1.0; extra == 'format-nongpl' +Requires-Dist: uri-template; extra == 'format-nongpl' +Requires-Dist: webcolors>=24.6.0; extra == 'format-nongpl' +Description-Content-Type: text/x-rst + +========== +jsonschema +========== + +|PyPI| |Pythons| |CI| |ReadTheDocs| |Precommit| |Zenodo| + +.. |PyPI| image:: https://img.shields.io/pypi/v/jsonschema.svg + :alt: PyPI version + :target: https://pypi.org/project/jsonschema/ + +.. |Pythons| image:: https://img.shields.io/pypi/pyversions/jsonschema.svg + :alt: Supported Python versions + :target: https://pypi.org/project/jsonschema/ + +.. |CI| image:: https://github.com/python-jsonschema/jsonschema/workflows/CI/badge.svg + :alt: Build status + :target: https://github.com/python-jsonschema/jsonschema/actions?query=workflow%3ACI + +.. |ReadTheDocs| image:: https://readthedocs.org/projects/python-jsonschema/badge/?version=stable&style=flat + :alt: ReadTheDocs status + :target: https://python-jsonschema.readthedocs.io/en/stable/ + +.. |Precommit| image:: https://results.pre-commit.ci/badge/github/python-jsonschema/jsonschema/main.svg + :alt: pre-commit.ci status + :target: https://results.pre-commit.ci/latest/github/python-jsonschema/jsonschema/main + +.. |Zenodo| image:: https://zenodo.org/badge/3072629.svg + :alt: Zenodo DOI + :target: https://zenodo.org/badge/latestdoi/3072629 + + +``jsonschema`` is an implementation of the `JSON Schema `_ specification for Python. + +.. code:: python + + >>> from jsonschema import validate + + >>> # A sample schema, like what we'd get from json.load() + >>> schema = { + ... "type" : "object", + ... "properties" : { + ... "price" : {"type" : "number"}, + ... "name" : {"type" : "string"}, + ... }, + ... } + + >>> # If no exception is raised by validate(), the instance is valid. + >>> validate(instance={"name" : "Eggs", "price" : 34.99}, schema=schema) + + >>> validate( + ... instance={"name" : "Eggs", "price" : "Invalid"}, schema=schema, + ... ) # doctest: +IGNORE_EXCEPTION_DETAIL + Traceback (most recent call last): + ... + ValidationError: 'Invalid' is not of type 'number' + +It can also be used from the command line by installing `check-jsonschema `_. + +Features +-------- + +* Full support for `Draft 2020-12 `_, `Draft 2019-09 `_, `Draft 7 `_, `Draft 6 `_, `Draft 4 `_ and `Draft 3 `_ + +* `Lazy validation `_ that can iteratively report *all* validation errors. + +* `Programmatic querying `_ of which properties or items failed validation. + + +Installation +------------ + +``jsonschema`` is available on `PyPI `_. You can install using `pip `_: + +.. code:: bash + + $ pip install jsonschema + + +Extras +====== + +Two extras are available when installing the package, both currently related to ``format`` validation: + + * ``format`` + * ``format-nongpl`` + +They can be used when installing in order to include additional dependencies, e.g.: + +.. code:: bash + + $ pip install jsonschema'[format]' + +Be aware that the mere presence of these dependencies – or even the specification of ``format`` checks in a schema – do *not* activate format checks (as per the specification). +Please read the `format validation documentation `_ for further details. + +About +----- + +I'm Julian Berman. + +``jsonschema`` is on `GitHub `_. + +Get in touch, via GitHub or otherwise, if you've got something to contribute, it'd be most welcome! + +You can also generally find me on Libera (nick: ``Julian``) in various channels, including ``#python``. + +If you feel overwhelmingly grateful, you can also `sponsor me `_. + +And for companies who appreciate ``jsonschema`` and its continued support and growth, ``jsonschema`` is also now supportable via `TideLift `_. + + +Release Information +------------------- + +v4.23.0 +======= + +* Do not reorder dictionaries (schemas, instances) that are printed as part of validation errors. +* Declare support for Py3.13 diff --git a/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/RECORD b/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/RECORD new file mode 100644 index 0000000..9b92d29 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/RECORD @@ -0,0 +1,76 @@ +../../../bin/jsonschema,sha256=3h_ivM07LP9sft0K_jsXx4W2ImRlH95DBeynCf4swXQ,233 +jsonschema-4.23.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +jsonschema-4.23.0.dist-info/METADATA,sha256=Hd96gAfdO0v5RpFeT25qjyo7PvhASy56F4Jw3FUUTlo,7906 +jsonschema-4.23.0.dist-info/RECORD,, +jsonschema-4.23.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87 +jsonschema-4.23.0.dist-info/entry_points.txt,sha256=vO7rX4Fs_xIVJy2pnAtKgTSxfpnozAVQ0DjCmpMxnWE,51 +jsonschema-4.23.0.dist-info/licenses/COPYING,sha256=T5KgFaE8TRoEC-8BiqE0MLTxvHO0Gxa7hGw0Z2bedDk,1057 +jsonschema/__init__.py,sha256=LkPwscySlJ9lTOp7ZB1M7jQ8mbG7-bYG41iBwbZ-o9s,3941 +jsonschema/__main__.py,sha256=iLsZf2upUB3ilBKTlMnyK-HHt2Cnnfkwwxi_c6gLvSA,115 +jsonschema/__pycache__/__init__.cpython-310.pyc,, +jsonschema/__pycache__/__main__.cpython-310.pyc,, +jsonschema/__pycache__/_format.cpython-310.pyc,, +jsonschema/__pycache__/_keywords.cpython-310.pyc,, +jsonschema/__pycache__/_legacy_keywords.cpython-310.pyc,, +jsonschema/__pycache__/_types.cpython-310.pyc,, +jsonschema/__pycache__/_typing.cpython-310.pyc,, +jsonschema/__pycache__/_utils.cpython-310.pyc,, +jsonschema/__pycache__/cli.cpython-310.pyc,, +jsonschema/__pycache__/exceptions.cpython-310.pyc,, +jsonschema/__pycache__/protocols.cpython-310.pyc,, +jsonschema/__pycache__/validators.cpython-310.pyc,, +jsonschema/_format.py,sha256=F_MA52IkrhOIxDqD8x-01bH37mG5nh0kyNrWUSLtWb8,14591 +jsonschema/_keywords.py,sha256=r8_DrqAfn6QLwQnmXEggveiSU-UaIL2p2nuPINelfFc,14949 +jsonschema/_legacy_keywords.py,sha256=2tWuwRPWbYS7EAl8wBIC_rabGuv1J4dfYLqNEPpShhA,15191 +jsonschema/_types.py,sha256=HQ5QD_oL85zF1FSW2v-5rvfYF0967HJdxSR88kzw2mY,5367 +jsonschema/_typing.py,sha256=NZhPhkBOn9INYZk8G69rDeuRamztgXCMLh10z9cfT6g,610 +jsonschema/_utils.py,sha256=ODga3vrJ6K2wMGxerpgn4ipc9q7ZSqBsvwKU4embLEE,10642 +jsonschema/benchmarks/__init__.py,sha256=A0sQrxDBVHSyQ-8ru3L11hMXf3q9gVuB9x_YgHb4R9M,70 +jsonschema/benchmarks/__pycache__/__init__.cpython-310.pyc,, +jsonschema/benchmarks/__pycache__/const_vs_enum.cpython-310.pyc,, +jsonschema/benchmarks/__pycache__/contains.cpython-310.pyc,, +jsonschema/benchmarks/__pycache__/issue232.cpython-310.pyc,, +jsonschema/benchmarks/__pycache__/json_schema_test_suite.cpython-310.pyc,, +jsonschema/benchmarks/__pycache__/nested_schemas.cpython-310.pyc,, +jsonschema/benchmarks/__pycache__/subcomponents.cpython-310.pyc,, +jsonschema/benchmarks/__pycache__/unused_registry.cpython-310.pyc,, +jsonschema/benchmarks/__pycache__/useless_applicator_schemas.cpython-310.pyc,, +jsonschema/benchmarks/__pycache__/useless_keywords.cpython-310.pyc,, +jsonschema/benchmarks/__pycache__/validator_creation.cpython-310.pyc,, +jsonschema/benchmarks/const_vs_enum.py,sha256=DVFi3WDqBalZFOibnjpX1uTSr3Rxa2cPgFcowd7Ukrs,830 +jsonschema/benchmarks/contains.py,sha256=gexQoUrCOwECofbt19BeosQZ7WFL6PDdkX49DWwBlOg,786 +jsonschema/benchmarks/issue232.py,sha256=3LLYLIlBGQnVuyyo2iAv-xky5P6PRFHANx4-zIIQOoE,521 +jsonschema/benchmarks/issue232/issue.json,sha256=eaPOZjMRu5u8RpKrsA9uk7ucPZS5tkKG4D_hkOTQ3Hk,117105 +jsonschema/benchmarks/json_schema_test_suite.py,sha256=PvfabpUYcF4_7csYDTcTauED8rnFEGYbdY5RqTXD08s,320 +jsonschema/benchmarks/nested_schemas.py,sha256=mo07dx-CIgmSOI62CNs4g5xu1FzHklLBpkQoDxWYcKs,1892 +jsonschema/benchmarks/subcomponents.py,sha256=fEyiMzsWeK2pd7DEGCuuY-vzGunwhHczRBWEnBRLKIo,1113 +jsonschema/benchmarks/unused_registry.py,sha256=hwRwONc9cefPtYzkoX_TYRO3GyUojriv0-YQaK3vnj0,940 +jsonschema/benchmarks/useless_applicator_schemas.py,sha256=EVm5-EtOEFoLP_Vt2j4SrCwlx05NhPqNuZQ6LIMP1Dc,3342 +jsonschema/benchmarks/useless_keywords.py,sha256=bj_zKr1oVctFlqyZaObCsYTgFjiiNgPzC0hr1Y868mE,867 +jsonschema/benchmarks/validator_creation.py,sha256=UkUQlLAnussnr_KdCIdad6xx2pXxQLmYtsXoiirKeWQ,285 +jsonschema/cli.py,sha256=SGy9JPg02mgXhNxugU8iXhYNivfSjBhKTNAgV90ty-M,8551 +jsonschema/exceptions.py,sha256=RxE2T5xxgg_B6ttR8a3lCbZyh29RUtFe4oZKMoHPBAE,15035 +jsonschema/protocols.py,sha256=7mpZxO1gfRNMCGXwldwsSN3nEugVfIVyKZ_HZgN1vSw,7174 +jsonschema/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +jsonschema/tests/__pycache__/__init__.cpython-310.pyc,, +jsonschema/tests/__pycache__/_suite.cpython-310.pyc,, +jsonschema/tests/__pycache__/fuzz_validate.cpython-310.pyc,, +jsonschema/tests/__pycache__/test_cli.cpython-310.pyc,, +jsonschema/tests/__pycache__/test_deprecations.cpython-310.pyc,, +jsonschema/tests/__pycache__/test_exceptions.cpython-310.pyc,, +jsonschema/tests/__pycache__/test_format.cpython-310.pyc,, +jsonschema/tests/__pycache__/test_jsonschema_test_suite.cpython-310.pyc,, +jsonschema/tests/__pycache__/test_types.cpython-310.pyc,, +jsonschema/tests/__pycache__/test_utils.cpython-310.pyc,, +jsonschema/tests/__pycache__/test_validators.cpython-310.pyc,, +jsonschema/tests/_suite.py,sha256=QAfBj34zMbJQ5_JJ2ogpiTlw9hQ6Is43dvo_bpS0EdM,8156 +jsonschema/tests/fuzz_validate.py,sha256=fUA7yTJIihaCwJplkUehZeyB84HcXEcqtY5oPJXIO7I,1114 +jsonschema/tests/test_cli.py,sha256=uFMu2YbIfbSDCnykhLL4-VR3-jg1tvQLJn2Bliwp_Bw,28587 +jsonschema/tests/test_deprecations.py,sha256=9VxOCfWzMG1Tg4OD8riU_Znd6HDOQZkepzVgxsdUdU8,15760 +jsonschema/tests/test_exceptions.py,sha256=JgC-E1ZFZK2puVBp35WFRnG8CNOiSWLYtyLjh9IvFKI,22591 +jsonschema/tests/test_format.py,sha256=eVm5SMaWF2lOPO28bPAwNvkiQvHCQKy-MnuAgEchfEc,3188 +jsonschema/tests/test_jsonschema_test_suite.py,sha256=a2saPs2Cwwg0sdRdu-uJ8goSXLbqrS-pC48QJy0K4DE,8674 +jsonschema/tests/test_types.py,sha256=cF51KTDmdsx06MrIc4fXKt0X9fIsVgw5uhT8CamVa8U,6977 +jsonschema/tests/test_utils.py,sha256=sao74o1PyYMxBfqweokQN48CFSS6yhJk5FkCfMJ5PsI,4163 +jsonschema/tests/test_validators.py,sha256=eiaigsZMzHYYsniQ1UPygaS56a1d-_7-9NC4wVXAhzs,87975 +jsonschema/validators.py,sha256=H31FwHdyB7LP5eunxdBrZ9E57hpvozfnRlZaOYy45jU,47045 diff --git a/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/WHEEL b/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/WHEEL new file mode 100644 index 0000000..cdd68a4 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: hatchling 1.25.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/entry_points.txt b/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/entry_points.txt new file mode 100644 index 0000000..eecef9d --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +jsonschema = jsonschema.cli:main diff --git a/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/licenses/COPYING b/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/licenses/COPYING new file mode 100644 index 0000000..af9cfbd --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema-4.23.0.dist-info/licenses/COPYING @@ -0,0 +1,19 @@ +Copyright (c) 2013 Julian Berman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/.venv/lib/python3.10/site-packages/jsonschema/__init__.py b/.venv/lib/python3.10/site-packages/jsonschema/__init__.py new file mode 100644 index 0000000..79924cf --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/__init__.py @@ -0,0 +1,120 @@ +""" +An implementation of JSON Schema for Python. + +The main functionality is provided by the validator classes for each of the +supported JSON Schema versions. + +Most commonly, `jsonschema.validators.validate` is the quickest way to simply +validate a given instance under a schema, and will create a validator +for you. +""" +import warnings + +from jsonschema._format import FormatChecker +from jsonschema._types import TypeChecker +from jsonschema.exceptions import SchemaError, ValidationError +from jsonschema.validators import ( + Draft3Validator, + Draft4Validator, + Draft6Validator, + Draft7Validator, + Draft201909Validator, + Draft202012Validator, + validate, +) + + +def __getattr__(name): + if name == "__version__": + warnings.warn( + "Accessing jsonschema.__version__ is deprecated and will be " + "removed in a future release. Use importlib.metadata directly " + "to query for jsonschema's version.", + DeprecationWarning, + stacklevel=2, + ) + + from importlib import metadata + return metadata.version("jsonschema") + elif name == "RefResolver": + from jsonschema.validators import _RefResolver + warnings.warn( + _RefResolver._DEPRECATION_MESSAGE, + DeprecationWarning, + stacklevel=2, + ) + return _RefResolver + elif name == "ErrorTree": + warnings.warn( + "Importing ErrorTree directly from the jsonschema package " + "is deprecated and will become an ImportError. Import it from " + "jsonschema.exceptions instead.", + DeprecationWarning, + stacklevel=2, + ) + from jsonschema.exceptions import ErrorTree + return ErrorTree + elif name == "FormatError": + warnings.warn( + "Importing FormatError directly from the jsonschema package " + "is deprecated and will become an ImportError. Import it from " + "jsonschema.exceptions instead.", + DeprecationWarning, + stacklevel=2, + ) + from jsonschema.exceptions import FormatError + return FormatError + elif name == "Validator": + warnings.warn( + "Importing Validator directly from the jsonschema package " + "is deprecated and will become an ImportError. Import it from " + "jsonschema.protocols instead.", + DeprecationWarning, + stacklevel=2, + ) + from jsonschema.protocols import Validator + return Validator + elif name == "RefResolutionError": + from jsonschema.exceptions import _RefResolutionError + warnings.warn( + _RefResolutionError._DEPRECATION_MESSAGE, + DeprecationWarning, + stacklevel=2, + ) + return _RefResolutionError + + format_checkers = { + "draft3_format_checker": Draft3Validator, + "draft4_format_checker": Draft4Validator, + "draft6_format_checker": Draft6Validator, + "draft7_format_checker": Draft7Validator, + "draft201909_format_checker": Draft201909Validator, + "draft202012_format_checker": Draft202012Validator, + } + ValidatorForFormat = format_checkers.get(name) + if ValidatorForFormat is not None: + warnings.warn( + f"Accessing jsonschema.{name} is deprecated and will be " + "removed in a future release. Instead, use the FORMAT_CHECKER " + "attribute on the corresponding Validator.", + DeprecationWarning, + stacklevel=2, + ) + return ValidatorForFormat.FORMAT_CHECKER + + raise AttributeError(f"module {__name__} has no attribute {name}") + + +__all__ = [ + "Draft201909Validator", + "Draft202012Validator", + "Draft3Validator", + "Draft4Validator", + "Draft6Validator", + "Draft7Validator", + "FormatChecker", + "SchemaError", + "TypeChecker", + "ValidationError", + "validate", +] diff --git a/.venv/lib/python3.10/site-packages/jsonschema/__main__.py b/.venv/lib/python3.10/site-packages/jsonschema/__main__.py new file mode 100644 index 0000000..fb260ae --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/__main__.py @@ -0,0 +1,6 @@ +""" +The jsonschema CLI is now deprecated in favor of check-jsonschema. +""" +from jsonschema.cli import main + +main() diff --git a/.venv/lib/python3.10/site-packages/jsonschema/_format.py b/.venv/lib/python3.10/site-packages/jsonschema/_format.py new file mode 100644 index 0000000..6e87620 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/_format.py @@ -0,0 +1,519 @@ +from __future__ import annotations + +from contextlib import suppress +from datetime import date, datetime +from uuid import UUID +import ipaddress +import re +import typing +import warnings + +from jsonschema.exceptions import FormatError + +_FormatCheckCallable = typing.Callable[[object], bool] +#: A format checker callable. +_F = typing.TypeVar("_F", bound=_FormatCheckCallable) +_RaisesType = typing.Union[ + typing.Type[Exception], typing.Tuple[typing.Type[Exception], ...], +] + +_RE_DATE = re.compile(r"^\d{4}-\d{2}-\d{2}$", re.ASCII) + + +class FormatChecker: + """ + A ``format`` property checker. + + JSON Schema does not mandate that the ``format`` property actually do any + validation. If validation is desired however, instances of this class can + be hooked into validators to enable format validation. + + `FormatChecker` objects always return ``True`` when asked about + formats that they do not know how to validate. + + To add a check for a custom format use the `FormatChecker.checks` + decorator. + + Arguments: + + formats: + + The known formats to validate. This argument can be used to + limit which formats will be used during validation. + + """ + + checkers: dict[ + str, + tuple[_FormatCheckCallable, _RaisesType], + ] = {} # noqa: RUF012 + + def __init__(self, formats: typing.Iterable[str] | None = None): + if formats is None: + formats = self.checkers.keys() + self.checkers = {k: self.checkers[k] for k in formats} + + def __repr__(self): + return f"" + + def checks( + self, format: str, raises: _RaisesType = (), + ) -> typing.Callable[[_F], _F]: + """ + Register a decorated function as validating a new format. + + Arguments: + + format: + + The format that the decorated function will check. + + raises: + + The exception(s) raised by the decorated function when an + invalid instance is found. + + The exception object will be accessible as the + `jsonschema.exceptions.ValidationError.cause` attribute of the + resulting validation error. + + """ + + def _checks(func: _F) -> _F: + self.checkers[format] = (func, raises) + return func + + return _checks + + @classmethod + def cls_checks( + cls, format: str, raises: _RaisesType = (), + ) -> typing.Callable[[_F], _F]: + warnings.warn( + ( + "FormatChecker.cls_checks is deprecated. Call " + "FormatChecker.checks on a specific FormatChecker instance " + "instead." + ), + DeprecationWarning, + stacklevel=2, + ) + return cls._cls_checks(format=format, raises=raises) + + @classmethod + def _cls_checks( + cls, format: str, raises: _RaisesType = (), + ) -> typing.Callable[[_F], _F]: + def _checks(func: _F) -> _F: + cls.checkers[format] = (func, raises) + return func + + return _checks + + def check(self, instance: object, format: str) -> None: + """ + Check whether the instance conforms to the given format. + + Arguments: + + instance (*any primitive type*, i.e. str, number, bool): + + The instance to check + + format: + + The format that instance should conform to + + Raises: + + FormatError: + + if the instance does not conform to ``format`` + + """ + if format not in self.checkers: + return + + func, raises = self.checkers[format] + result, cause = None, None + try: + result = func(instance) + except raises as e: + cause = e + if not result: + raise FormatError(f"{instance!r} is not a {format!r}", cause=cause) + + def conforms(self, instance: object, format: str) -> bool: + """ + Check whether the instance conforms to the given format. + + Arguments: + + instance (*any primitive type*, i.e. str, number, bool): + + The instance to check + + format: + + The format that instance should conform to + + Returns: + + bool: whether it conformed + + """ + try: + self.check(instance, format) + except FormatError: + return False + else: + return True + + +draft3_format_checker = FormatChecker() +draft4_format_checker = FormatChecker() +draft6_format_checker = FormatChecker() +draft7_format_checker = FormatChecker() +draft201909_format_checker = FormatChecker() +draft202012_format_checker = FormatChecker() + +_draft_checkers: dict[str, FormatChecker] = dict( + draft3=draft3_format_checker, + draft4=draft4_format_checker, + draft6=draft6_format_checker, + draft7=draft7_format_checker, + draft201909=draft201909_format_checker, + draft202012=draft202012_format_checker, +) + + +def _checks_drafts( + name=None, + draft3=None, + draft4=None, + draft6=None, + draft7=None, + draft201909=None, + draft202012=None, + raises=(), +) -> typing.Callable[[_F], _F]: + draft3 = draft3 or name + draft4 = draft4 or name + draft6 = draft6 or name + draft7 = draft7 or name + draft201909 = draft201909 or name + draft202012 = draft202012 or name + + def wrap(func: _F) -> _F: + if draft3: + func = _draft_checkers["draft3"].checks(draft3, raises)(func) + if draft4: + func = _draft_checkers["draft4"].checks(draft4, raises)(func) + if draft6: + func = _draft_checkers["draft6"].checks(draft6, raises)(func) + if draft7: + func = _draft_checkers["draft7"].checks(draft7, raises)(func) + if draft201909: + func = _draft_checkers["draft201909"].checks(draft201909, raises)( + func, + ) + if draft202012: + func = _draft_checkers["draft202012"].checks(draft202012, raises)( + func, + ) + + # Oy. This is bad global state, but relied upon for now, until + # deprecation. See #519 and test_format_checkers_come_with_defaults + FormatChecker._cls_checks( + draft202012 or draft201909 or draft7 or draft6 or draft4 or draft3, + raises, + )(func) + return func + + return wrap + + +@_checks_drafts(name="idn-email") +@_checks_drafts(name="email") +def is_email(instance: object) -> bool: + if not isinstance(instance, str): + return True + return "@" in instance + + +@_checks_drafts( + draft3="ip-address", + draft4="ipv4", + draft6="ipv4", + draft7="ipv4", + draft201909="ipv4", + draft202012="ipv4", + raises=ipaddress.AddressValueError, +) +def is_ipv4(instance: object) -> bool: + if not isinstance(instance, str): + return True + return bool(ipaddress.IPv4Address(instance)) + + +@_checks_drafts(name="ipv6", raises=ipaddress.AddressValueError) +def is_ipv6(instance: object) -> bool: + if not isinstance(instance, str): + return True + address = ipaddress.IPv6Address(instance) + return not getattr(address, "scope_id", "") + + +with suppress(ImportError): + from fqdn import FQDN + + @_checks_drafts( + draft3="host-name", + draft4="hostname", + draft6="hostname", + draft7="hostname", + draft201909="hostname", + draft202012="hostname", + ) + def is_host_name(instance: object) -> bool: + if not isinstance(instance, str): + return True + return FQDN(instance, min_labels=1).is_valid + + +with suppress(ImportError): + # The built-in `idna` codec only implements RFC 3890, so we go elsewhere. + import idna + + @_checks_drafts( + draft7="idn-hostname", + draft201909="idn-hostname", + draft202012="idn-hostname", + raises=(idna.IDNAError, UnicodeError), + ) + def is_idn_host_name(instance: object) -> bool: + if not isinstance(instance, str): + return True + idna.encode(instance) + return True + + +try: + import rfc3987 +except ImportError: + with suppress(ImportError): + from rfc3986_validator import validate_rfc3986 + + @_checks_drafts(name="uri") + def is_uri(instance: object) -> bool: + if not isinstance(instance, str): + return True + return validate_rfc3986(instance, rule="URI") + + @_checks_drafts( + draft6="uri-reference", + draft7="uri-reference", + draft201909="uri-reference", + draft202012="uri-reference", + raises=ValueError, + ) + def is_uri_reference(instance: object) -> bool: + if not isinstance(instance, str): + return True + return validate_rfc3986(instance, rule="URI_reference") + +else: + + @_checks_drafts( + draft7="iri", + draft201909="iri", + draft202012="iri", + raises=ValueError, + ) + def is_iri(instance: object) -> bool: + if not isinstance(instance, str): + return True + return rfc3987.parse(instance, rule="IRI") + + @_checks_drafts( + draft7="iri-reference", + draft201909="iri-reference", + draft202012="iri-reference", + raises=ValueError, + ) + def is_iri_reference(instance: object) -> bool: + if not isinstance(instance, str): + return True + return rfc3987.parse(instance, rule="IRI_reference") + + @_checks_drafts(name="uri", raises=ValueError) + def is_uri(instance: object) -> bool: + if not isinstance(instance, str): + return True + return rfc3987.parse(instance, rule="URI") + + @_checks_drafts( + draft6="uri-reference", + draft7="uri-reference", + draft201909="uri-reference", + draft202012="uri-reference", + raises=ValueError, + ) + def is_uri_reference(instance: object) -> bool: + if not isinstance(instance, str): + return True + return rfc3987.parse(instance, rule="URI_reference") + + +with suppress(ImportError): + from rfc3339_validator import validate_rfc3339 + + @_checks_drafts(name="date-time") + def is_datetime(instance: object) -> bool: + if not isinstance(instance, str): + return True + return validate_rfc3339(instance.upper()) + + @_checks_drafts( + draft7="time", + draft201909="time", + draft202012="time", + ) + def is_time(instance: object) -> bool: + if not isinstance(instance, str): + return True + return is_datetime("1970-01-01T" + instance) + + +@_checks_drafts(name="regex", raises=re.error) +def is_regex(instance: object) -> bool: + if not isinstance(instance, str): + return True + return bool(re.compile(instance)) + + +@_checks_drafts( + draft3="date", + draft7="date", + draft201909="date", + draft202012="date", + raises=ValueError, +) +def is_date(instance: object) -> bool: + if not isinstance(instance, str): + return True + return bool(_RE_DATE.fullmatch(instance) and date.fromisoformat(instance)) + + +@_checks_drafts(draft3="time", raises=ValueError) +def is_draft3_time(instance: object) -> bool: + if not isinstance(instance, str): + return True + return bool(datetime.strptime(instance, "%H:%M:%S")) # noqa: DTZ007 + + +with suppress(ImportError): + import webcolors + + @_checks_drafts(draft3="color", raises=(ValueError, TypeError)) + def is_css21_color(instance: object) -> bool: + if isinstance(instance, str): + try: + webcolors.name_to_hex(instance) + except ValueError: + webcolors.normalize_hex(instance.lower()) + return True + + +with suppress(ImportError): + import jsonpointer + + @_checks_drafts( + draft6="json-pointer", + draft7="json-pointer", + draft201909="json-pointer", + draft202012="json-pointer", + raises=jsonpointer.JsonPointerException, + ) + def is_json_pointer(instance: object) -> bool: + if not isinstance(instance, str): + return True + return bool(jsonpointer.JsonPointer(instance)) + + # TODO: I don't want to maintain this, so it + # needs to go either into jsonpointer (pending + # https://github.com/stefankoegl/python-json-pointer/issues/34) or + # into a new external library. + @_checks_drafts( + draft7="relative-json-pointer", + draft201909="relative-json-pointer", + draft202012="relative-json-pointer", + raises=jsonpointer.JsonPointerException, + ) + def is_relative_json_pointer(instance: object) -> bool: + # Definition taken from: + # https://tools.ietf.org/html/draft-handrews-relative-json-pointer-01#section-3 + if not isinstance(instance, str): + return True + if not instance: + return False + + non_negative_integer, rest = [], "" + for i, character in enumerate(instance): + if character.isdigit(): + # digits with a leading "0" are not allowed + if i > 0 and int(instance[i - 1]) == 0: + return False + + non_negative_integer.append(character) + continue + + if not non_negative_integer: + return False + + rest = instance[i:] + break + return (rest == "#") or bool(jsonpointer.JsonPointer(rest)) + + +with suppress(ImportError): + import uri_template + + @_checks_drafts( + draft6="uri-template", + draft7="uri-template", + draft201909="uri-template", + draft202012="uri-template", + ) + def is_uri_template(instance: object) -> bool: + if not isinstance(instance, str): + return True + return uri_template.validate(instance) + + +with suppress(ImportError): + import isoduration + + @_checks_drafts( + draft201909="duration", + draft202012="duration", + raises=isoduration.DurationParsingException, + ) + def is_duration(instance: object) -> bool: + if not isinstance(instance, str): + return True + isoduration.parse_duration(instance) + # FIXME: See bolsote/isoduration#25 and bolsote/isoduration#21 + return instance.endswith(tuple("DMYWHMS")) + + +@_checks_drafts( + draft201909="uuid", + draft202012="uuid", + raises=ValueError, +) +def is_uuid(instance: object) -> bool: + if not isinstance(instance, str): + return True + UUID(instance) + return all(instance[position] == "-" for position in (8, 13, 18, 23)) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/_keywords.py b/.venv/lib/python3.10/site-packages/jsonschema/_keywords.py new file mode 100644 index 0000000..f30f954 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/_keywords.py @@ -0,0 +1,449 @@ +from fractions import Fraction +import re + +from jsonschema._utils import ( + ensure_list, + equal, + extras_msg, + find_additional_properties, + find_evaluated_item_indexes_by_schema, + find_evaluated_property_keys_by_schema, + uniq, +) +from jsonschema.exceptions import FormatError, ValidationError + + +def patternProperties(validator, patternProperties, instance, schema): + if not validator.is_type(instance, "object"): + return + + for pattern, subschema in patternProperties.items(): + for k, v in instance.items(): + if re.search(pattern, k): + yield from validator.descend( + v, subschema, path=k, schema_path=pattern, + ) + + +def propertyNames(validator, propertyNames, instance, schema): + if not validator.is_type(instance, "object"): + return + + for property in instance: + yield from validator.descend(instance=property, schema=propertyNames) + + +def additionalProperties(validator, aP, instance, schema): + if not validator.is_type(instance, "object"): + return + + extras = set(find_additional_properties(instance, schema)) + + if validator.is_type(aP, "object"): + for extra in extras: + yield from validator.descend(instance[extra], aP, path=extra) + elif not aP and extras: + if "patternProperties" in schema: + verb = "does" if len(extras) == 1 else "do" + joined = ", ".join(repr(each) for each in sorted(extras)) + patterns = ", ".join( + repr(each) for each in sorted(schema["patternProperties"]) + ) + error = f"{joined} {verb} not match any of the regexes: {patterns}" + yield ValidationError(error) + else: + error = "Additional properties are not allowed (%s %s unexpected)" + yield ValidationError(error % extras_msg(sorted(extras, key=str))) + + +def items(validator, items, instance, schema): + if not validator.is_type(instance, "array"): + return + + prefix = len(schema.get("prefixItems", [])) + total = len(instance) + extra = total - prefix + if extra <= 0: + return + + if items is False: + rest = instance[prefix:] if extra != 1 else instance[prefix] + item = "items" if prefix != 1 else "item" + yield ValidationError( + f"Expected at most {prefix} {item} but found {extra} " + f"extra: {rest!r}", + ) + else: + for index in range(prefix, total): + yield from validator.descend( + instance=instance[index], + schema=items, + path=index, + ) + + +def const(validator, const, instance, schema): + if not equal(instance, const): + yield ValidationError(f"{const!r} was expected") + + +def contains(validator, contains, instance, schema): + if not validator.is_type(instance, "array"): + return + + matches = 0 + min_contains = schema.get("minContains", 1) + max_contains = schema.get("maxContains", len(instance)) + + contains_validator = validator.evolve(schema=contains) + + for each in instance: + if contains_validator.is_valid(each): + matches += 1 + if matches > max_contains: + yield ValidationError( + "Too many items match the given schema " + f"(expected at most {max_contains})", + validator="maxContains", + validator_value=max_contains, + ) + return + + if matches < min_contains: + if not matches: + yield ValidationError( + f"{instance!r} does not contain items " + "matching the given schema", + ) + else: + yield ValidationError( + "Too few items match the given schema (expected at least " + f"{min_contains} but only {matches} matched)", + validator="minContains", + validator_value=min_contains, + ) + + +def exclusiveMinimum(validator, minimum, instance, schema): + if not validator.is_type(instance, "number"): + return + + if instance <= minimum: + yield ValidationError( + f"{instance!r} is less than or equal to " + f"the minimum of {minimum!r}", + ) + + +def exclusiveMaximum(validator, maximum, instance, schema): + if not validator.is_type(instance, "number"): + return + + if instance >= maximum: + yield ValidationError( + f"{instance!r} is greater than or equal " + f"to the maximum of {maximum!r}", + ) + + +def minimum(validator, minimum, instance, schema): + if not validator.is_type(instance, "number"): + return + + if instance < minimum: + message = f"{instance!r} is less than the minimum of {minimum!r}" + yield ValidationError(message) + + +def maximum(validator, maximum, instance, schema): + if not validator.is_type(instance, "number"): + return + + if instance > maximum: + message = f"{instance!r} is greater than the maximum of {maximum!r}" + yield ValidationError(message) + + +def multipleOf(validator, dB, instance, schema): + if not validator.is_type(instance, "number"): + return + + if isinstance(dB, float): + quotient = instance / dB + try: + failed = int(quotient) != quotient + except OverflowError: + # When `instance` is large and `dB` is less than one, + # quotient can overflow to infinity; and then casting to int + # raises an error. + # + # In this case we fall back to Fraction logic, which is + # exact and cannot overflow. The performance is also + # acceptable: we try the fast all-float option first, and + # we know that fraction(dB) can have at most a few hundred + # digits in each part. The worst-case slowdown is therefore + # for already-slow enormous integers or Decimals. + failed = (Fraction(instance) / Fraction(dB)).denominator != 1 + else: + failed = instance % dB + + if failed: + yield ValidationError(f"{instance!r} is not a multiple of {dB}") + + +def minItems(validator, mI, instance, schema): + if validator.is_type(instance, "array") and len(instance) < mI: + message = "should be non-empty" if mI == 1 else "is too short" + yield ValidationError(f"{instance!r} {message}") + + +def maxItems(validator, mI, instance, schema): + if validator.is_type(instance, "array") and len(instance) > mI: + message = "is expected to be empty" if mI == 0 else "is too long" + yield ValidationError(f"{instance!r} {message}") + + +def uniqueItems(validator, uI, instance, schema): + if ( + uI + and validator.is_type(instance, "array") + and not uniq(instance) + ): + yield ValidationError(f"{instance!r} has non-unique elements") + + +def pattern(validator, patrn, instance, schema): + if ( + validator.is_type(instance, "string") + and not re.search(patrn, instance) + ): + yield ValidationError(f"{instance!r} does not match {patrn!r}") + + +def format(validator, format, instance, schema): + if validator.format_checker is not None: + try: + validator.format_checker.check(instance, format) + except FormatError as error: + yield ValidationError(error.message, cause=error.cause) + + +def minLength(validator, mL, instance, schema): + if validator.is_type(instance, "string") and len(instance) < mL: + message = "should be non-empty" if mL == 1 else "is too short" + yield ValidationError(f"{instance!r} {message}") + + +def maxLength(validator, mL, instance, schema): + if validator.is_type(instance, "string") and len(instance) > mL: + message = "is expected to be empty" if mL == 0 else "is too long" + yield ValidationError(f"{instance!r} {message}") + + +def dependentRequired(validator, dependentRequired, instance, schema): + if not validator.is_type(instance, "object"): + return + + for property, dependency in dependentRequired.items(): + if property not in instance: + continue + + for each in dependency: + if each not in instance: + message = f"{each!r} is a dependency of {property!r}" + yield ValidationError(message) + + +def dependentSchemas(validator, dependentSchemas, instance, schema): + if not validator.is_type(instance, "object"): + return + + for property, dependency in dependentSchemas.items(): + if property not in instance: + continue + yield from validator.descend( + instance, dependency, schema_path=property, + ) + + +def enum(validator, enums, instance, schema): + if all(not equal(each, instance) for each in enums): + yield ValidationError(f"{instance!r} is not one of {enums!r}") + + +def ref(validator, ref, instance, schema): + yield from validator._validate_reference(ref=ref, instance=instance) + + +def dynamicRef(validator, dynamicRef, instance, schema): + yield from validator._validate_reference(ref=dynamicRef, instance=instance) + + +def type(validator, types, instance, schema): + types = ensure_list(types) + + if not any(validator.is_type(instance, type) for type in types): + reprs = ", ".join(repr(type) for type in types) + yield ValidationError(f"{instance!r} is not of type {reprs}") + + +def properties(validator, properties, instance, schema): + if not validator.is_type(instance, "object"): + return + + for property, subschema in properties.items(): + if property in instance: + yield from validator.descend( + instance[property], + subschema, + path=property, + schema_path=property, + ) + + +def required(validator, required, instance, schema): + if not validator.is_type(instance, "object"): + return + for property in required: + if property not in instance: + yield ValidationError(f"{property!r} is a required property") + + +def minProperties(validator, mP, instance, schema): + if validator.is_type(instance, "object") and len(instance) < mP: + message = ( + "should be non-empty" if mP == 1 + else "does not have enough properties" + ) + yield ValidationError(f"{instance!r} {message}") + + +def maxProperties(validator, mP, instance, schema): + if not validator.is_type(instance, "object"): + return + if validator.is_type(instance, "object") and len(instance) > mP: + message = ( + "is expected to be empty" if mP == 0 + else "has too many properties" + ) + yield ValidationError(f"{instance!r} {message}") + + +def allOf(validator, allOf, instance, schema): + for index, subschema in enumerate(allOf): + yield from validator.descend(instance, subschema, schema_path=index) + + +def anyOf(validator, anyOf, instance, schema): + all_errors = [] + for index, subschema in enumerate(anyOf): + errs = list(validator.descend(instance, subschema, schema_path=index)) + if not errs: + break + all_errors.extend(errs) + else: + yield ValidationError( + f"{instance!r} is not valid under any of the given schemas", + context=all_errors, + ) + + +def oneOf(validator, oneOf, instance, schema): + subschemas = enumerate(oneOf) + all_errors = [] + for index, subschema in subschemas: + errs = list(validator.descend(instance, subschema, schema_path=index)) + if not errs: + first_valid = subschema + break + all_errors.extend(errs) + else: + yield ValidationError( + f"{instance!r} is not valid under any of the given schemas", + context=all_errors, + ) + + more_valid = [ + each for _, each in subschemas + if validator.evolve(schema=each).is_valid(instance) + ] + if more_valid: + more_valid.append(first_valid) + reprs = ", ".join(repr(schema) for schema in more_valid) + yield ValidationError(f"{instance!r} is valid under each of {reprs}") + + +def not_(validator, not_schema, instance, schema): + if validator.evolve(schema=not_schema).is_valid(instance): + message = f"{instance!r} should not be valid under {not_schema!r}" + yield ValidationError(message) + + +def if_(validator, if_schema, instance, schema): + if validator.evolve(schema=if_schema).is_valid(instance): + if "then" in schema: + then = schema["then"] + yield from validator.descend(instance, then, schema_path="then") + elif "else" in schema: + else_ = schema["else"] + yield from validator.descend(instance, else_, schema_path="else") + + +def unevaluatedItems(validator, unevaluatedItems, instance, schema): + if not validator.is_type(instance, "array"): + return + evaluated_item_indexes = find_evaluated_item_indexes_by_schema( + validator, instance, schema, + ) + unevaluated_items = [ + item for index, item in enumerate(instance) + if index not in evaluated_item_indexes + ] + if unevaluated_items: + error = "Unevaluated items are not allowed (%s %s unexpected)" + yield ValidationError(error % extras_msg(unevaluated_items)) + + +def unevaluatedProperties(validator, unevaluatedProperties, instance, schema): + if not validator.is_type(instance, "object"): + return + evaluated_keys = find_evaluated_property_keys_by_schema( + validator, instance, schema, + ) + unevaluated_keys = [] + for property in instance: + if property not in evaluated_keys: + for _ in validator.descend( + instance[property], + unevaluatedProperties, + path=property, + schema_path=property, + ): + # FIXME: Include context for each unevaluated property + # indicating why it's invalid under the subschema. + unevaluated_keys.append(property) # noqa: PERF401 + + if unevaluated_keys: + if unevaluatedProperties is False: + error = "Unevaluated properties are not allowed (%s %s unexpected)" + extras = sorted(unevaluated_keys, key=str) + yield ValidationError(error % extras_msg(extras)) + else: + error = ( + "Unevaluated properties are not valid under " + "the given schema (%s %s unevaluated and invalid)" + ) + yield ValidationError(error % extras_msg(unevaluated_keys)) + + +def prefixItems(validator, prefixItems, instance, schema): + if not validator.is_type(instance, "array"): + return + + for (index, item), subschema in zip(enumerate(instance), prefixItems): + yield from validator.descend( + instance=item, + schema=subschema, + schema_path=index, + path=index, + ) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/_legacy_keywords.py b/.venv/lib/python3.10/site-packages/jsonschema/_legacy_keywords.py new file mode 100644 index 0000000..c691589 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/_legacy_keywords.py @@ -0,0 +1,449 @@ +import re + +from referencing.jsonschema import lookup_recursive_ref + +from jsonschema import _utils +from jsonschema.exceptions import ValidationError + + +def ignore_ref_siblings(schema): + """ + Ignore siblings of ``$ref`` if it is present. + + Otherwise, return all keywords. + + Suitable for use with `create`'s ``applicable_validators`` argument. + """ + ref = schema.get("$ref") + if ref is not None: + return [("$ref", ref)] + else: + return schema.items() + + +def dependencies_draft3(validator, dependencies, instance, schema): + if not validator.is_type(instance, "object"): + return + + for property, dependency in dependencies.items(): + if property not in instance: + continue + + if validator.is_type(dependency, "object"): + yield from validator.descend( + instance, dependency, schema_path=property, + ) + elif validator.is_type(dependency, "string"): + if dependency not in instance: + message = f"{dependency!r} is a dependency of {property!r}" + yield ValidationError(message) + else: + for each in dependency: + if each not in instance: + message = f"{each!r} is a dependency of {property!r}" + yield ValidationError(message) + + +def dependencies_draft4_draft6_draft7( + validator, + dependencies, + instance, + schema, +): + """ + Support for the ``dependencies`` keyword from pre-draft 2019-09. + + In later drafts, the keyword was split into separate + ``dependentRequired`` and ``dependentSchemas`` validators. + """ + if not validator.is_type(instance, "object"): + return + + for property, dependency in dependencies.items(): + if property not in instance: + continue + + if validator.is_type(dependency, "array"): + for each in dependency: + if each not in instance: + message = f"{each!r} is a dependency of {property!r}" + yield ValidationError(message) + else: + yield from validator.descend( + instance, dependency, schema_path=property, + ) + + +def disallow_draft3(validator, disallow, instance, schema): + for disallowed in _utils.ensure_list(disallow): + if validator.evolve(schema={"type": [disallowed]}).is_valid(instance): + message = f"{disallowed!r} is disallowed for {instance!r}" + yield ValidationError(message) + + +def extends_draft3(validator, extends, instance, schema): + if validator.is_type(extends, "object"): + yield from validator.descend(instance, extends) + return + for index, subschema in enumerate(extends): + yield from validator.descend(instance, subschema, schema_path=index) + + +def items_draft3_draft4(validator, items, instance, schema): + if not validator.is_type(instance, "array"): + return + + if validator.is_type(items, "object"): + for index, item in enumerate(instance): + yield from validator.descend(item, items, path=index) + else: + for (index, item), subschema in zip(enumerate(instance), items): + yield from validator.descend( + item, subschema, path=index, schema_path=index, + ) + + +def additionalItems(validator, aI, instance, schema): + if ( + not validator.is_type(instance, "array") + or validator.is_type(schema.get("items", {}), "object") + ): + return + + len_items = len(schema.get("items", [])) + if validator.is_type(aI, "object"): + for index, item in enumerate(instance[len_items:], start=len_items): + yield from validator.descend(item, aI, path=index) + elif not aI and len(instance) > len(schema.get("items", [])): + error = "Additional items are not allowed (%s %s unexpected)" + yield ValidationError( + error % _utils.extras_msg(instance[len(schema.get("items", [])):]), + ) + + +def items_draft6_draft7_draft201909(validator, items, instance, schema): + if not validator.is_type(instance, "array"): + return + + if validator.is_type(items, "array"): + for (index, item), subschema in zip(enumerate(instance), items): + yield from validator.descend( + item, subschema, path=index, schema_path=index, + ) + else: + for index, item in enumerate(instance): + yield from validator.descend(item, items, path=index) + + +def minimum_draft3_draft4(validator, minimum, instance, schema): + if not validator.is_type(instance, "number"): + return + + if schema.get("exclusiveMinimum", False): + failed = instance <= minimum + cmp = "less than or equal to" + else: + failed = instance < minimum + cmp = "less than" + + if failed: + message = f"{instance!r} is {cmp} the minimum of {minimum!r}" + yield ValidationError(message) + + +def maximum_draft3_draft4(validator, maximum, instance, schema): + if not validator.is_type(instance, "number"): + return + + if schema.get("exclusiveMaximum", False): + failed = instance >= maximum + cmp = "greater than or equal to" + else: + failed = instance > maximum + cmp = "greater than" + + if failed: + message = f"{instance!r} is {cmp} the maximum of {maximum!r}" + yield ValidationError(message) + + +def properties_draft3(validator, properties, instance, schema): + if not validator.is_type(instance, "object"): + return + + for property, subschema in properties.items(): + if property in instance: + yield from validator.descend( + instance[property], + subschema, + path=property, + schema_path=property, + ) + elif subschema.get("required", False): + error = ValidationError(f"{property!r} is a required property") + error._set( + validator="required", + validator_value=subschema["required"], + instance=instance, + schema=schema, + ) + error.path.appendleft(property) + error.schema_path.extend([property, "required"]) + yield error + + +def type_draft3(validator, types, instance, schema): + types = _utils.ensure_list(types) + + all_errors = [] + for index, type in enumerate(types): + if validator.is_type(type, "object"): + errors = list(validator.descend(instance, type, schema_path=index)) + if not errors: + return + all_errors.extend(errors) + elif validator.is_type(instance, type): + return + + reprs = [] + for type in types: + try: + reprs.append(repr(type["name"])) + except Exception: # noqa: BLE001 + reprs.append(repr(type)) + yield ValidationError( + f"{instance!r} is not of type {', '.join(reprs)}", + context=all_errors, + ) + + +def contains_draft6_draft7(validator, contains, instance, schema): + if not validator.is_type(instance, "array"): + return + + if not any( + validator.evolve(schema=contains).is_valid(element) + for element in instance + ): + yield ValidationError( + f"None of {instance!r} are valid under the given schema", + ) + + +def recursiveRef(validator, recursiveRef, instance, schema): + resolved = lookup_recursive_ref(validator._resolver) + yield from validator.descend( + instance, + resolved.contents, + resolver=resolved.resolver, + ) + + +def find_evaluated_item_indexes_by_schema(validator, instance, schema): + """ + Get all indexes of items that get evaluated under the current schema. + + Covers all keywords related to unevaluatedItems: items, prefixItems, if, + then, else, contains, unevaluatedItems, allOf, oneOf, anyOf + """ + if validator.is_type(schema, "boolean"): + return [] + evaluated_indexes = [] + + ref = schema.get("$ref") + if ref is not None: + resolved = validator._resolver.lookup(ref) + evaluated_indexes.extend( + find_evaluated_item_indexes_by_schema( + validator.evolve( + schema=resolved.contents, + _resolver=resolved.resolver, + ), + instance, + resolved.contents, + ), + ) + + if "$recursiveRef" in schema: + resolved = lookup_recursive_ref(validator._resolver) + evaluated_indexes.extend( + find_evaluated_item_indexes_by_schema( + validator.evolve( + schema=resolved.contents, + _resolver=resolved.resolver, + ), + instance, + resolved.contents, + ), + ) + + if "items" in schema: + if "additionalItems" in schema: + return list(range(len(instance))) + + if validator.is_type(schema["items"], "object"): + return list(range(len(instance))) + evaluated_indexes += list(range(len(schema["items"]))) + + if "if" in schema: + if validator.evolve(schema=schema["if"]).is_valid(instance): + evaluated_indexes += find_evaluated_item_indexes_by_schema( + validator, instance, schema["if"], + ) + if "then" in schema: + evaluated_indexes += find_evaluated_item_indexes_by_schema( + validator, instance, schema["then"], + ) + elif "else" in schema: + evaluated_indexes += find_evaluated_item_indexes_by_schema( + validator, instance, schema["else"], + ) + + for keyword in ["contains", "unevaluatedItems"]: + if keyword in schema: + for k, v in enumerate(instance): + if validator.evolve(schema=schema[keyword]).is_valid(v): + evaluated_indexes.append(k) + + for keyword in ["allOf", "oneOf", "anyOf"]: + if keyword in schema: + for subschema in schema[keyword]: + errs = next(validator.descend(instance, subschema), None) + if errs is None: + evaluated_indexes += find_evaluated_item_indexes_by_schema( + validator, instance, subschema, + ) + + return evaluated_indexes + + +def unevaluatedItems_draft2019(validator, unevaluatedItems, instance, schema): + if not validator.is_type(instance, "array"): + return + evaluated_item_indexes = find_evaluated_item_indexes_by_schema( + validator, instance, schema, + ) + unevaluated_items = [ + item for index, item in enumerate(instance) + if index not in evaluated_item_indexes + ] + if unevaluated_items: + error = "Unevaluated items are not allowed (%s %s unexpected)" + yield ValidationError(error % _utils.extras_msg(unevaluated_items)) + + +def find_evaluated_property_keys_by_schema(validator, instance, schema): + if validator.is_type(schema, "boolean"): + return [] + evaluated_keys = [] + + ref = schema.get("$ref") + if ref is not None: + resolved = validator._resolver.lookup(ref) + evaluated_keys.extend( + find_evaluated_property_keys_by_schema( + validator.evolve( + schema=resolved.contents, + _resolver=resolved.resolver, + ), + instance, + resolved.contents, + ), + ) + + if "$recursiveRef" in schema: + resolved = lookup_recursive_ref(validator._resolver) + evaluated_keys.extend( + find_evaluated_property_keys_by_schema( + validator.evolve( + schema=resolved.contents, + _resolver=resolved.resolver, + ), + instance, + resolved.contents, + ), + ) + + for keyword in [ + "properties", "additionalProperties", "unevaluatedProperties", + ]: + if keyword in schema: + schema_value = schema[keyword] + if validator.is_type(schema_value, "boolean") and schema_value: + evaluated_keys += instance.keys() + + elif validator.is_type(schema_value, "object"): + for property in schema_value: + if property in instance: + evaluated_keys.append(property) + + if "patternProperties" in schema: + for property in instance: + for pattern in schema["patternProperties"]: + if re.search(pattern, property): + evaluated_keys.append(property) + + if "dependentSchemas" in schema: + for property, subschema in schema["dependentSchemas"].items(): + if property not in instance: + continue + evaluated_keys += find_evaluated_property_keys_by_schema( + validator, instance, subschema, + ) + + for keyword in ["allOf", "oneOf", "anyOf"]: + if keyword in schema: + for subschema in schema[keyword]: + errs = next(validator.descend(instance, subschema), None) + if errs is None: + evaluated_keys += find_evaluated_property_keys_by_schema( + validator, instance, subschema, + ) + + if "if" in schema: + if validator.evolve(schema=schema["if"]).is_valid(instance): + evaluated_keys += find_evaluated_property_keys_by_schema( + validator, instance, schema["if"], + ) + if "then" in schema: + evaluated_keys += find_evaluated_property_keys_by_schema( + validator, instance, schema["then"], + ) + elif "else" in schema: + evaluated_keys += find_evaluated_property_keys_by_schema( + validator, instance, schema["else"], + ) + + return evaluated_keys + + +def unevaluatedProperties_draft2019(validator, uP, instance, schema): + if not validator.is_type(instance, "object"): + return + evaluated_keys = find_evaluated_property_keys_by_schema( + validator, instance, schema, + ) + unevaluated_keys = [] + for property in instance: + if property not in evaluated_keys: + for _ in validator.descend( + instance[property], + uP, + path=property, + schema_path=property, + ): + # FIXME: Include context for each unevaluated property + # indicating why it's invalid under the subschema. + unevaluated_keys.append(property) # noqa: PERF401 + + if unevaluated_keys: + if uP is False: + error = "Unevaluated properties are not allowed (%s %s unexpected)" + extras = sorted(unevaluated_keys, key=str) + yield ValidationError(error % _utils.extras_msg(extras)) + else: + error = ( + "Unevaluated properties are not valid under " + "the given schema (%s %s unevaluated and invalid)" + ) + yield ValidationError(error % _utils.extras_msg(unevaluated_keys)) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/_types.py b/.venv/lib/python3.10/site-packages/jsonschema/_types.py new file mode 100644 index 0000000..bf25e7e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/_types.py @@ -0,0 +1,200 @@ +from __future__ import annotations + +from typing import Any, Callable, Mapping +import numbers + +from attrs import evolve, field, frozen +from rpds import HashTrieMap + +from jsonschema.exceptions import UndefinedTypeCheck + + +# unfortunately, the type of HashTrieMap is generic, and if used as an attrs +# converter, the generic type is presented to mypy, which then fails to match +# the concrete type of a type checker mapping +# this "do nothing" wrapper presents the correct information to mypy +def _typed_map_converter( + init_val: Mapping[str, Callable[[TypeChecker, Any], bool]], +) -> HashTrieMap[str, Callable[[TypeChecker, Any], bool]]: + return HashTrieMap.convert(init_val) + + +def is_array(checker, instance): + return isinstance(instance, list) + + +def is_bool(checker, instance): + return isinstance(instance, bool) + + +def is_integer(checker, instance): + # bool inherits from int, so ensure bools aren't reported as ints + if isinstance(instance, bool): + return False + return isinstance(instance, int) + + +def is_null(checker, instance): + return instance is None + + +def is_number(checker, instance): + # bool inherits from int, so ensure bools aren't reported as ints + if isinstance(instance, bool): + return False + return isinstance(instance, numbers.Number) + + +def is_object(checker, instance): + return isinstance(instance, dict) + + +def is_string(checker, instance): + return isinstance(instance, str) + + +def is_any(checker, instance): + return True + + +@frozen(repr=False) +class TypeChecker: + """ + A :kw:`type` property checker. + + A `TypeChecker` performs type checking for a `Validator`, converting + between the defined JSON Schema types and some associated Python types or + objects. + + Modifying the behavior just mentioned by redefining which Python objects + are considered to be of which JSON Schema types can be done using + `TypeChecker.redefine` or `TypeChecker.redefine_many`, and types can be + removed via `TypeChecker.remove`. Each of these return a new `TypeChecker`. + + Arguments: + + type_checkers: + + The initial mapping of types to their checking functions. + + """ + + _type_checkers: HashTrieMap[ + str, Callable[[TypeChecker, Any], bool], + ] = field(default=HashTrieMap(), converter=_typed_map_converter) + + def __repr__(self): + types = ", ".join(repr(k) for k in sorted(self._type_checkers)) + return f"<{self.__class__.__name__} types={{{types}}}>" + + def is_type(self, instance, type: str) -> bool: + """ + Check if the instance is of the appropriate type. + + Arguments: + + instance: + + The instance to check + + type: + + The name of the type that is expected. + + Raises: + + `jsonschema.exceptions.UndefinedTypeCheck`: + + if ``type`` is unknown to this object. + + """ + try: + fn = self._type_checkers[type] + except KeyError: + raise UndefinedTypeCheck(type) from None + + return fn(self, instance) + + def redefine(self, type: str, fn) -> TypeChecker: + """ + Produce a new checker with the given type redefined. + + Arguments: + + type: + + The name of the type to check. + + fn (collections.abc.Callable): + + A callable taking exactly two parameters - the type + checker calling the function and the instance to check. + The function should return true if instance is of this + type and false otherwise. + + """ + return self.redefine_many({type: fn}) + + def redefine_many(self, definitions=()) -> TypeChecker: + """ + Produce a new checker with the given types redefined. + + Arguments: + + definitions (dict): + + A dictionary mapping types to their checking functions. + + """ + type_checkers = self._type_checkers.update(definitions) + return evolve(self, type_checkers=type_checkers) + + def remove(self, *types) -> TypeChecker: + """ + Produce a new checker with the given types forgotten. + + Arguments: + + types: + + the names of the types to remove. + + Raises: + + `jsonschema.exceptions.UndefinedTypeCheck`: + + if any given type is unknown to this object + + """ + type_checkers = self._type_checkers + for each in types: + try: + type_checkers = type_checkers.remove(each) + except KeyError: + raise UndefinedTypeCheck(each) from None + return evolve(self, type_checkers=type_checkers) + + +draft3_type_checker = TypeChecker( + { + "any": is_any, + "array": is_array, + "boolean": is_bool, + "integer": is_integer, + "object": is_object, + "null": is_null, + "number": is_number, + "string": is_string, + }, +) +draft4_type_checker = draft3_type_checker.remove("any") +draft6_type_checker = draft4_type_checker.redefine( + "integer", + lambda checker, instance: ( + is_integer(checker, instance) + or isinstance(instance, float) and instance.is_integer() + ), +) +draft7_type_checker = draft6_type_checker +draft201909_type_checker = draft7_type_checker +draft202012_type_checker = draft201909_type_checker diff --git a/.venv/lib/python3.10/site-packages/jsonschema/_typing.py b/.venv/lib/python3.10/site-packages/jsonschema/_typing.py new file mode 100644 index 0000000..d283dc4 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/_typing.py @@ -0,0 +1,28 @@ +""" +Some (initially private) typing helpers for jsonschema's types. +""" +from typing import Any, Callable, Iterable, Protocol, Tuple, Union + +import referencing.jsonschema + +from jsonschema.protocols import Validator + + +class SchemaKeywordValidator(Protocol): + def __call__( + self, + validator: Validator, + value: Any, + instance: Any, + schema: referencing.jsonschema.Schema, + ) -> None: + ... + + +id_of = Callable[[referencing.jsonschema.Schema], Union[str, None]] + + +ApplicableValidators = Callable[ + [referencing.jsonschema.Schema], + Iterable[Tuple[str, Any]], +] diff --git a/.venv/lib/python3.10/site-packages/jsonschema/_utils.py b/.venv/lib/python3.10/site-packages/jsonschema/_utils.py new file mode 100644 index 0000000..54d28c0 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/_utils.py @@ -0,0 +1,351 @@ +from collections.abc import Mapping, MutableMapping, Sequence +from urllib.parse import urlsplit +import itertools +import re + + +class URIDict(MutableMapping): + """ + Dictionary which uses normalized URIs as keys. + """ + + def normalize(self, uri): + return urlsplit(uri).geturl() + + def __init__(self, *args, **kwargs): + self.store = dict() + self.store.update(*args, **kwargs) + + def __getitem__(self, uri): + return self.store[self.normalize(uri)] + + def __setitem__(self, uri, value): + self.store[self.normalize(uri)] = value + + def __delitem__(self, uri): + del self.store[self.normalize(uri)] + + def __iter__(self): + return iter(self.store) + + def __len__(self): # pragma: no cover -- untested, but to be removed + return len(self.store) + + def __repr__(self): # pragma: no cover -- untested, but to be removed + return repr(self.store) + + +class Unset: + """ + An as-of-yet unset attribute or unprovided default parameter. + """ + + def __repr__(self): # pragma: no cover + return "" + + +def format_as_index(container, indices): + """ + Construct a single string containing indexing operations for the indices. + + For example for a container ``bar``, [1, 2, "foo"] -> bar[1][2]["foo"] + + Arguments: + + container (str): + + A word to use for the thing being indexed + + indices (sequence): + + The indices to format. + + """ + if not indices: + return container + return f"{container}[{']['.join(repr(index) for index in indices)}]" + + +def find_additional_properties(instance, schema): + """ + Return the set of additional properties for the given ``instance``. + + Weeds out properties that should have been validated by ``properties`` and + / or ``patternProperties``. + + Assumes ``instance`` is dict-like already. + """ + properties = schema.get("properties", {}) + patterns = "|".join(schema.get("patternProperties", {})) + for property in instance: + if property not in properties: + if patterns and re.search(patterns, property): + continue + yield property + + +def extras_msg(extras): + """ + Create an error message for extra items or properties. + """ + verb = "was" if len(extras) == 1 else "were" + return ", ".join(repr(extra) for extra in extras), verb + + +def ensure_list(thing): + """ + Wrap ``thing`` in a list if it's a single str. + + Otherwise, return it unchanged. + """ + if isinstance(thing, str): + return [thing] + return thing + + +def _mapping_equal(one, two): + """ + Check if two mappings are equal using the semantics of `equal`. + """ + if len(one) != len(two): + return False + return all( + key in two and equal(value, two[key]) + for key, value in one.items() + ) + + +def _sequence_equal(one, two): + """ + Check if two sequences are equal using the semantics of `equal`. + """ + if len(one) != len(two): + return False + return all(equal(i, j) for i, j in zip(one, two)) + + +def equal(one, two): + """ + Check if two things are equal evading some Python type hierarchy semantics. + + Specifically in JSON Schema, evade `bool` inheriting from `int`, + recursing into sequences to do the same. + """ + if one is two: + return True + if isinstance(one, str) or isinstance(two, str): + return one == two + if isinstance(one, Sequence) and isinstance(two, Sequence): + return _sequence_equal(one, two) + if isinstance(one, Mapping) and isinstance(two, Mapping): + return _mapping_equal(one, two) + return unbool(one) == unbool(two) + + +def unbool(element, true=object(), false=object()): + """ + A hack to make True and 1 and False and 0 unique for ``uniq``. + """ + if element is True: + return true + elif element is False: + return false + return element + + +def uniq(container): + """ + Check if all of a container's elements are unique. + + Tries to rely on the container being recursively sortable, or otherwise + falls back on (slow) brute force. + """ + try: + sort = sorted(unbool(i) for i in container) + sliced = itertools.islice(sort, 1, None) + + for i, j in zip(sort, sliced): + if equal(i, j): + return False + + except (NotImplementedError, TypeError): + seen = [] + for e in container: + e = unbool(e) + + for i in seen: + if equal(i, e): + return False + + seen.append(e) + return True + + +def find_evaluated_item_indexes_by_schema(validator, instance, schema): + """ + Get all indexes of items that get evaluated under the current schema. + + Covers all keywords related to unevaluatedItems: items, prefixItems, if, + then, else, contains, unevaluatedItems, allOf, oneOf, anyOf + """ + if validator.is_type(schema, "boolean"): + return [] + evaluated_indexes = [] + + if "items" in schema: + return list(range(len(instance))) + + ref = schema.get("$ref") + if ref is not None: + resolved = validator._resolver.lookup(ref) + evaluated_indexes.extend( + find_evaluated_item_indexes_by_schema( + validator.evolve( + schema=resolved.contents, + _resolver=resolved.resolver, + ), + instance, + resolved.contents, + ), + ) + + dynamicRef = schema.get("$dynamicRef") + if dynamicRef is not None: + resolved = validator._resolver.lookup(dynamicRef) + evaluated_indexes.extend( + find_evaluated_item_indexes_by_schema( + validator.evolve( + schema=resolved.contents, + _resolver=resolved.resolver, + ), + instance, + resolved.contents, + ), + ) + + if "prefixItems" in schema: + evaluated_indexes += list(range(len(schema["prefixItems"]))) + + if "if" in schema: + if validator.evolve(schema=schema["if"]).is_valid(instance): + evaluated_indexes += find_evaluated_item_indexes_by_schema( + validator, instance, schema["if"], + ) + if "then" in schema: + evaluated_indexes += find_evaluated_item_indexes_by_schema( + validator, instance, schema["then"], + ) + elif "else" in schema: + evaluated_indexes += find_evaluated_item_indexes_by_schema( + validator, instance, schema["else"], + ) + + for keyword in ["contains", "unevaluatedItems"]: + if keyword in schema: + for k, v in enumerate(instance): + if validator.evolve(schema=schema[keyword]).is_valid(v): + evaluated_indexes.append(k) + + for keyword in ["allOf", "oneOf", "anyOf"]: + if keyword in schema: + for subschema in schema[keyword]: + errs = next(validator.descend(instance, subschema), None) + if errs is None: + evaluated_indexes += find_evaluated_item_indexes_by_schema( + validator, instance, subschema, + ) + + return evaluated_indexes + + +def find_evaluated_property_keys_by_schema(validator, instance, schema): + """ + Get all keys of items that get evaluated under the current schema. + + Covers all keywords related to unevaluatedProperties: properties, + additionalProperties, unevaluatedProperties, patternProperties, + dependentSchemas, allOf, oneOf, anyOf, if, then, else + """ + if validator.is_type(schema, "boolean"): + return [] + evaluated_keys = [] + + ref = schema.get("$ref") + if ref is not None: + resolved = validator._resolver.lookup(ref) + evaluated_keys.extend( + find_evaluated_property_keys_by_schema( + validator.evolve( + schema=resolved.contents, + _resolver=resolved.resolver, + ), + instance, + resolved.contents, + ), + ) + + dynamicRef = schema.get("$dynamicRef") + if dynamicRef is not None: + resolved = validator._resolver.lookup(dynamicRef) + evaluated_keys.extend( + find_evaluated_property_keys_by_schema( + validator.evolve( + schema=resolved.contents, + _resolver=resolved.resolver, + ), + instance, + resolved.contents, + ), + ) + + for keyword in [ + "properties", "additionalProperties", "unevaluatedProperties", + ]: + if keyword in schema: + schema_value = schema[keyword] + if validator.is_type(schema_value, "boolean") and schema_value: + evaluated_keys += instance.keys() + + elif validator.is_type(schema_value, "object"): + for property in schema_value: + if property in instance: + evaluated_keys.append(property) + + if "patternProperties" in schema: + for property in instance: + for pattern in schema["patternProperties"]: + if re.search(pattern, property): + evaluated_keys.append(property) + + if "dependentSchemas" in schema: + for property, subschema in schema["dependentSchemas"].items(): + if property not in instance: + continue + evaluated_keys += find_evaluated_property_keys_by_schema( + validator, instance, subschema, + ) + + for keyword in ["allOf", "oneOf", "anyOf"]: + if keyword in schema: + for subschema in schema[keyword]: + errs = next(validator.descend(instance, subschema), None) + if errs is None: + evaluated_keys += find_evaluated_property_keys_by_schema( + validator, instance, subschema, + ) + + if "if" in schema: + if validator.evolve(schema=schema["if"]).is_valid(instance): + evaluated_keys += find_evaluated_property_keys_by_schema( + validator, instance, schema["if"], + ) + if "then" in schema: + evaluated_keys += find_evaluated_property_keys_by_schema( + validator, instance, schema["then"], + ) + elif "else" in schema: + evaluated_keys += find_evaluated_property_keys_by_schema( + validator, instance, schema["else"], + ) + + return evaluated_keys diff --git a/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/__init__.py b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/__init__.py new file mode 100644 index 0000000..e3dcc68 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/__init__.py @@ -0,0 +1,5 @@ +""" +Benchmarks for validation. + +This package is *not* public API. +""" diff --git a/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/const_vs_enum.py b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/const_vs_enum.py new file mode 100644 index 0000000..c6fecd1 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/const_vs_enum.py @@ -0,0 +1,30 @@ +""" +A benchmark for comparing equivalent validation of `const` and `enum`. +""" + +from pyperf import Runner + +from jsonschema import Draft202012Validator + +value = [37] * 100 +const_schema = {"const": list(value)} +enum_schema = {"enum": [list(value)]} + +valid = list(value) +invalid = [*valid, 73] + +const = Draft202012Validator(const_schema) +enum = Draft202012Validator(enum_schema) + +assert const.is_valid(valid) +assert enum.is_valid(valid) +assert not const.is_valid(invalid) +assert not enum.is_valid(invalid) + + +if __name__ == "__main__": + runner = Runner() + runner.bench_func("const valid", lambda: const.is_valid(valid)) + runner.bench_func("const invalid", lambda: const.is_valid(invalid)) + runner.bench_func("enum valid", lambda: enum.is_valid(valid)) + runner.bench_func("enum invalid", lambda: enum.is_valid(invalid)) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/contains.py b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/contains.py new file mode 100644 index 0000000..739cd04 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/contains.py @@ -0,0 +1,28 @@ +""" +A benchmark for validation of the `contains` keyword. +""" + +from pyperf import Runner + +from jsonschema import Draft202012Validator + +schema = { + "type": "array", + "contains": {"const": 37}, +} +validator = Draft202012Validator(schema) + +size = 1000 +beginning = [37] + [0] * (size - 1) +middle = [0] * (size // 2) + [37] + [0] * (size // 2) +end = [0] * (size - 1) + [37] +invalid = [0] * size + + +if __name__ == "__main__": + runner = Runner() + runner.bench_func("baseline", lambda: validator.is_valid([])) + runner.bench_func("beginning", lambda: validator.is_valid(beginning)) + runner.bench_func("middle", lambda: validator.is_valid(middle)) + runner.bench_func("end", lambda: validator.is_valid(end)) + runner.bench_func("invalid", lambda: validator.is_valid(invalid)) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/issue232.py b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/issue232.py new file mode 100644 index 0000000..efd0715 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/issue232.py @@ -0,0 +1,25 @@ +""" +A performance benchmark using the example from issue #232. + +See https://github.com/python-jsonschema/jsonschema/pull/232. +""" +from pathlib import Path + +from pyperf import Runner +from referencing import Registry + +from jsonschema.tests._suite import Version +import jsonschema + +issue232 = Version( + path=Path(__file__).parent / "issue232", + remotes=Registry(), + name="issue232", +) + + +if __name__ == "__main__": + issue232.benchmark( + runner=Runner(), + Validator=jsonschema.Draft4Validator, + ) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/issue232/issue.json b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/issue232/issue.json new file mode 100644 index 0000000..804c340 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/issue232/issue.json @@ -0,0 +1,2653 @@ +[ + { + "description": "Petstore", + "schema": { + "title": "A JSON Schema for Swagger 2.0 API.", + "id": "http://swagger.io/v2/schema.json#", + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "required": [ + "swagger", + "info", + "paths" + ], + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "swagger": { + "type": "string", + "enum": [ + "2.0" + ], + "description": "The Swagger version of this document." + }, + "info": { + "$ref": "#/definitions/info" + }, + "host": { + "type": "string", + "pattern": "^[^{}/ :\\\\]+(?::\\d+)?$", + "description": "The host (name or ip) of the API. Example: 'swagger.io'" + }, + "basePath": { + "type": "string", + "pattern": "^/", + "description": "The base path to the API. Example: '/api'." + }, + "schemes": { + "$ref": "#/definitions/schemesList" + }, + "consumes": { + "description": "A list of MIME types accepted by the API.", + "allOf": [ + { + "$ref": "#/definitions/mediaTypeList" + } + ] + }, + "produces": { + "description": "A list of MIME types the API can produce.", + "allOf": [ + { + "$ref": "#/definitions/mediaTypeList" + } + ] + }, + "paths": { + "$ref": "#/definitions/paths" + }, + "definitions": { + "$ref": "#/definitions/definitions" + }, + "parameters": { + "$ref": "#/definitions/parameterDefinitions" + }, + "responses": { + "$ref": "#/definitions/responseDefinitions" + }, + "security": { + "$ref": "#/definitions/security" + }, + "securityDefinitions": { + "$ref": "#/definitions/securityDefinitions" + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/definitions/tag" + }, + "uniqueItems": true + }, + "externalDocs": { + "$ref": "#/definitions/externalDocs" + } + }, + "definitions": { + "info": { + "type": "object", + "description": "General information about the API.", + "required": [ + "version", + "title" + ], + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "title": { + "type": "string", + "description": "A unique and precise title of the API." + }, + "version": { + "type": "string", + "description": "A semantic version number of the API." + }, + "description": { + "type": "string", + "description": "A longer description of the API. Should be different from the title. GitHub Flavored Markdown is allowed." + }, + "termsOfService": { + "type": "string", + "description": "The terms of service for the API." + }, + "contact": { + "$ref": "#/definitions/contact" + }, + "license": { + "$ref": "#/definitions/license" + } + } + }, + "contact": { + "type": "object", + "description": "Contact information for the owners of the API.", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "description": "The identifying name of the contact person/organization." + }, + "url": { + "type": "string", + "description": "The URL pointing to the contact information.", + "format": "uri" + }, + "email": { + "type": "string", + "description": "The email address of the contact person/organization.", + "format": "email" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "license": { + "type": "object", + "required": [ + "name" + ], + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "description": "The name of the license type. It's encouraged to use an OSI compatible license." + }, + "url": { + "type": "string", + "description": "The URL pointing to the license.", + "format": "uri" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "paths": { + "type": "object", + "description": "Relative paths to the individual endpoints. They must be relative to the 'basePath'.", + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + }, + "^/": { + "$ref": "#/definitions/pathItem" + } + }, + "additionalProperties": false + }, + "definitions": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/schema" + }, + "description": "One or more JSON objects describing the schemas being consumed and produced by the API." + }, + "parameterDefinitions": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/parameter" + }, + "description": "One or more JSON representations for parameters" + }, + "responseDefinitions": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/response" + }, + "description": "One or more JSON representations for parameters" + }, + "externalDocs": { + "type": "object", + "additionalProperties": false, + "description": "information about external documentation", + "required": [ + "url" + ], + "properties": { + "description": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "examples": { + "type": "object", + "additionalProperties": true + }, + "mimeType": { + "type": "string", + "description": "The MIME type of the HTTP message." + }, + "operation": { + "type": "object", + "required": [ + "responses" + ], + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "summary": { + "type": "string", + "description": "A brief summary of the operation." + }, + "description": { + "type": "string", + "description": "A longer description of the operation, GitHub Flavored Markdown is allowed." + }, + "externalDocs": { + "$ref": "#/definitions/externalDocs" + }, + "operationId": { + "type": "string", + "description": "A unique identifier of the operation." + }, + "produces": { + "description": "A list of MIME types the API can produce.", + "allOf": [ + { + "$ref": "#/definitions/mediaTypeList" + } + ] + }, + "consumes": { + "description": "A list of MIME types the API can consume.", + "allOf": [ + { + "$ref": "#/definitions/mediaTypeList" + } + ] + }, + "parameters": { + "$ref": "#/definitions/parametersList" + }, + "responses": { + "$ref": "#/definitions/responses" + }, + "schemes": { + "$ref": "#/definitions/schemesList" + }, + "deprecated": { + "type": "boolean", + "default": false + }, + "security": { + "$ref": "#/definitions/security" + } + } + }, + "pathItem": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "$ref": { + "type": "string" + }, + "get": { + "$ref": "#/definitions/operation" + }, + "put": { + "$ref": "#/definitions/operation" + }, + "post": { + "$ref": "#/definitions/operation" + }, + "delete": { + "$ref": "#/definitions/operation" + }, + "options": { + "$ref": "#/definitions/operation" + }, + "head": { + "$ref": "#/definitions/operation" + }, + "patch": { + "$ref": "#/definitions/operation" + }, + "parameters": { + "$ref": "#/definitions/parametersList" + } + } + }, + "responses": { + "type": "object", + "description": "Response objects names can either be any valid HTTP status code or 'default'.", + "minProperties": 1, + "additionalProperties": false, + "patternProperties": { + "^([0-9]{3})$|^(default)$": { + "$ref": "#/definitions/responseValue" + }, + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "not": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + } + }, + "responseValue": { + "oneOf": [ + { + "$ref": "#/definitions/response" + }, + { + "$ref": "#/definitions/jsonReference" + } + ] + }, + "response": { + "type": "object", + "required": [ + "description" + ], + "properties": { + "description": { + "type": "string" + }, + "schema": { + "oneOf": [ + { + "$ref": "#/definitions/schema" + }, + { + "$ref": "#/definitions/fileSchema" + } + ] + }, + "headers": { + "$ref": "#/definitions/headers" + }, + "examples": { + "$ref": "#/definitions/examples" + } + }, + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "headers": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/header" + } + }, + "header": { + "type": "object", + "additionalProperties": false, + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "string", + "number", + "integer", + "boolean", + "array" + ] + }, + "format": { + "type": "string" + }, + "items": { + "$ref": "#/definitions/primitivesItems" + }, + "collectionFormat": { + "$ref": "#/definitions/collectionFormat" + }, + "default": { + "$ref": "#/definitions/default" + }, + "maximum": { + "$ref": "#/definitions/maximum" + }, + "exclusiveMaximum": { + "$ref": "#/definitions/exclusiveMaximum" + }, + "minimum": { + "$ref": "#/definitions/minimum" + }, + "exclusiveMinimum": { + "$ref": "#/definitions/exclusiveMinimum" + }, + "maxLength": { + "$ref": "#/definitions/maxLength" + }, + "minLength": { + "$ref": "#/definitions/minLength" + }, + "pattern": { + "$ref": "#/definitions/pattern" + }, + "maxItems": { + "$ref": "#/definitions/maxItems" + }, + "minItems": { + "$ref": "#/definitions/minItems" + }, + "uniqueItems": { + "$ref": "#/definitions/uniqueItems" + }, + "enum": { + "$ref": "#/definitions/enum" + }, + "multipleOf": { + "$ref": "#/definitions/multipleOf" + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "vendorExtension": { + "description": "Any property starting with x- is valid.", + "additionalProperties": true, + "additionalItems": true + }, + "bodyParameter": { + "type": "object", + "required": [ + "name", + "in", + "schema" + ], + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "description": { + "type": "string", + "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." + }, + "name": { + "type": "string", + "description": "The name of the parameter." + }, + "in": { + "type": "string", + "description": "Determines the location of the parameter.", + "enum": [ + "body" + ] + }, + "required": { + "type": "boolean", + "description": "Determines whether or not this parameter is required or optional.", + "default": false + }, + "schema": { + "$ref": "#/definitions/schema" + } + }, + "additionalProperties": false + }, + "headerParameterSubSchema": { + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "required": { + "type": "boolean", + "description": "Determines whether or not this parameter is required or optional.", + "default": false + }, + "in": { + "type": "string", + "description": "Determines the location of the parameter.", + "enum": [ + "header" + ] + }, + "description": { + "type": "string", + "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." + }, + "name": { + "type": "string", + "description": "The name of the parameter." + }, + "type": { + "type": "string", + "enum": [ + "string", + "number", + "boolean", + "integer", + "array" + ] + }, + "format": { + "type": "string" + }, + "items": { + "$ref": "#/definitions/primitivesItems" + }, + "collectionFormat": { + "$ref": "#/definitions/collectionFormat" + }, + "default": { + "$ref": "#/definitions/default" + }, + "maximum": { + "$ref": "#/definitions/maximum" + }, + "exclusiveMaximum": { + "$ref": "#/definitions/exclusiveMaximum" + }, + "minimum": { + "$ref": "#/definitions/minimum" + }, + "exclusiveMinimum": { + "$ref": "#/definitions/exclusiveMinimum" + }, + "maxLength": { + "$ref": "#/definitions/maxLength" + }, + "minLength": { + "$ref": "#/definitions/minLength" + }, + "pattern": { + "$ref": "#/definitions/pattern" + }, + "maxItems": { + "$ref": "#/definitions/maxItems" + }, + "minItems": { + "$ref": "#/definitions/minItems" + }, + "uniqueItems": { + "$ref": "#/definitions/uniqueItems" + }, + "enum": { + "$ref": "#/definitions/enum" + }, + "multipleOf": { + "$ref": "#/definitions/multipleOf" + } + } + }, + "queryParameterSubSchema": { + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "required": { + "type": "boolean", + "description": "Determines whether or not this parameter is required or optional.", + "default": false + }, + "in": { + "type": "string", + "description": "Determines the location of the parameter.", + "enum": [ + "query" + ] + }, + "description": { + "type": "string", + "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." + }, + "name": { + "type": "string", + "description": "The name of the parameter." + }, + "allowEmptyValue": { + "type": "boolean", + "default": false, + "description": "allows sending a parameter by name only or with an empty value." + }, + "type": { + "type": "string", + "enum": [ + "string", + "number", + "boolean", + "integer", + "array" + ] + }, + "format": { + "type": "string" + }, + "items": { + "$ref": "#/definitions/primitivesItems" + }, + "collectionFormat": { + "$ref": "#/definitions/collectionFormatWithMulti" + }, + "default": { + "$ref": "#/definitions/default" + }, + "maximum": { + "$ref": "#/definitions/maximum" + }, + "exclusiveMaximum": { + "$ref": "#/definitions/exclusiveMaximum" + }, + "minimum": { + "$ref": "#/definitions/minimum" + }, + "exclusiveMinimum": { + "$ref": "#/definitions/exclusiveMinimum" + }, + "maxLength": { + "$ref": "#/definitions/maxLength" + }, + "minLength": { + "$ref": "#/definitions/minLength" + }, + "pattern": { + "$ref": "#/definitions/pattern" + }, + "maxItems": { + "$ref": "#/definitions/maxItems" + }, + "minItems": { + "$ref": "#/definitions/minItems" + }, + "uniqueItems": { + "$ref": "#/definitions/uniqueItems" + }, + "enum": { + "$ref": "#/definitions/enum" + }, + "multipleOf": { + "$ref": "#/definitions/multipleOf" + } + } + }, + "formDataParameterSubSchema": { + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "required": { + "type": "boolean", + "description": "Determines whether or not this parameter is required or optional.", + "default": false + }, + "in": { + "type": "string", + "description": "Determines the location of the parameter.", + "enum": [ + "formData" + ] + }, + "description": { + "type": "string", + "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." + }, + "name": { + "type": "string", + "description": "The name of the parameter." + }, + "allowEmptyValue": { + "type": "boolean", + "default": false, + "description": "allows sending a parameter by name only or with an empty value." + }, + "type": { + "type": "string", + "enum": [ + "string", + "number", + "boolean", + "integer", + "array", + "file" + ] + }, + "format": { + "type": "string" + }, + "items": { + "$ref": "#/definitions/primitivesItems" + }, + "collectionFormat": { + "$ref": "#/definitions/collectionFormatWithMulti" + }, + "default": { + "$ref": "#/definitions/default" + }, + "maximum": { + "$ref": "#/definitions/maximum" + }, + "exclusiveMaximum": { + "$ref": "#/definitions/exclusiveMaximum" + }, + "minimum": { + "$ref": "#/definitions/minimum" + }, + "exclusiveMinimum": { + "$ref": "#/definitions/exclusiveMinimum" + }, + "maxLength": { + "$ref": "#/definitions/maxLength" + }, + "minLength": { + "$ref": "#/definitions/minLength" + }, + "pattern": { + "$ref": "#/definitions/pattern" + }, + "maxItems": { + "$ref": "#/definitions/maxItems" + }, + "minItems": { + "$ref": "#/definitions/minItems" + }, + "uniqueItems": { + "$ref": "#/definitions/uniqueItems" + }, + "enum": { + "$ref": "#/definitions/enum" + }, + "multipleOf": { + "$ref": "#/definitions/multipleOf" + } + } + }, + "pathParameterSubSchema": { + "additionalProperties": false, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "required": [ + "required" + ], + "properties": { + "required": { + "type": "boolean", + "enum": [ + true + ], + "description": "Determines whether or not this parameter is required or optional." + }, + "in": { + "type": "string", + "description": "Determines the location of the parameter.", + "enum": [ + "path" + ] + }, + "description": { + "type": "string", + "description": "A brief description of the parameter. This could contain examples of use. GitHub Flavored Markdown is allowed." + }, + "name": { + "type": "string", + "description": "The name of the parameter." + }, + "type": { + "type": "string", + "enum": [ + "string", + "number", + "boolean", + "integer", + "array" + ] + }, + "format": { + "type": "string" + }, + "items": { + "$ref": "#/definitions/primitivesItems" + }, + "collectionFormat": { + "$ref": "#/definitions/collectionFormat" + }, + "default": { + "$ref": "#/definitions/default" + }, + "maximum": { + "$ref": "#/definitions/maximum" + }, + "exclusiveMaximum": { + "$ref": "#/definitions/exclusiveMaximum" + }, + "minimum": { + "$ref": "#/definitions/minimum" + }, + "exclusiveMinimum": { + "$ref": "#/definitions/exclusiveMinimum" + }, + "maxLength": { + "$ref": "#/definitions/maxLength" + }, + "minLength": { + "$ref": "#/definitions/minLength" + }, + "pattern": { + "$ref": "#/definitions/pattern" + }, + "maxItems": { + "$ref": "#/definitions/maxItems" + }, + "minItems": { + "$ref": "#/definitions/minItems" + }, + "uniqueItems": { + "$ref": "#/definitions/uniqueItems" + }, + "enum": { + "$ref": "#/definitions/enum" + }, + "multipleOf": { + "$ref": "#/definitions/multipleOf" + } + } + }, + "nonBodyParameter": { + "type": "object", + "required": [ + "name", + "in", + "type" + ], + "oneOf": [ + { + "$ref": "#/definitions/headerParameterSubSchema" + }, + { + "$ref": "#/definitions/formDataParameterSubSchema" + }, + { + "$ref": "#/definitions/queryParameterSubSchema" + }, + { + "$ref": "#/definitions/pathParameterSubSchema" + } + ] + }, + "parameter": { + "oneOf": [ + { + "$ref": "#/definitions/bodyParameter" + }, + { + "$ref": "#/definitions/nonBodyParameter" + } + ] + }, + "schema": { + "type": "object", + "description": "A deterministic version of a JSON Schema object.", + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "properties": { + "$ref": { + "type": "string" + }, + "format": { + "type": "string" + }, + "title": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/title" + }, + "description": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/description" + }, + "default": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/default" + }, + "multipleOf": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf" + }, + "maximum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/maximum" + }, + "exclusiveMaximum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum" + }, + "minimum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/minimum" + }, + "exclusiveMinimum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum" + }, + "maxLength": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" + }, + "minLength": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" + }, + "pattern": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/pattern" + }, + "maxItems": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" + }, + "minItems": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" + }, + "uniqueItems": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems" + }, + "maxProperties": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" + }, + "minProperties": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" + }, + "required": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray" + }, + "enum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/enum" + }, + "additionalProperties": { + "anyOf": [ + { + "$ref": "#/definitions/schema" + }, + { + "type": "boolean" + } + ], + "default": {} + }, + "type": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/type" + }, + "items": { + "anyOf": [ + { + "$ref": "#/definitions/schema" + }, + { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/schema" + } + } + ], + "default": {} + }, + "allOf": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/schema" + } + }, + "properties": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/schema" + }, + "default": {} + }, + "discriminator": { + "type": "string" + }, + "readOnly": { + "type": "boolean", + "default": false + }, + "xml": { + "$ref": "#/definitions/xml" + }, + "externalDocs": { + "$ref": "#/definitions/externalDocs" + }, + "example": {} + }, + "additionalProperties": false + }, + "fileSchema": { + "type": "object", + "description": "A deterministic version of a JSON Schema object.", + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + }, + "required": [ + "type" + ], + "properties": { + "format": { + "type": "string" + }, + "title": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/title" + }, + "description": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/description" + }, + "default": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/default" + }, + "required": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray" + }, + "type": { + "type": "string", + "enum": [ + "file" + ] + }, + "readOnly": { + "type": "boolean", + "default": false + }, + "externalDocs": { + "$ref": "#/definitions/externalDocs" + }, + "example": {} + }, + "additionalProperties": false + }, + "primitivesItems": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "string", + "number", + "integer", + "boolean", + "array" + ] + }, + "format": { + "type": "string" + }, + "items": { + "$ref": "#/definitions/primitivesItems" + }, + "collectionFormat": { + "$ref": "#/definitions/collectionFormat" + }, + "default": { + "$ref": "#/definitions/default" + }, + "maximum": { + "$ref": "#/definitions/maximum" + }, + "exclusiveMaximum": { + "$ref": "#/definitions/exclusiveMaximum" + }, + "minimum": { + "$ref": "#/definitions/minimum" + }, + "exclusiveMinimum": { + "$ref": "#/definitions/exclusiveMinimum" + }, + "maxLength": { + "$ref": "#/definitions/maxLength" + }, + "minLength": { + "$ref": "#/definitions/minLength" + }, + "pattern": { + "$ref": "#/definitions/pattern" + }, + "maxItems": { + "$ref": "#/definitions/maxItems" + }, + "minItems": { + "$ref": "#/definitions/minItems" + }, + "uniqueItems": { + "$ref": "#/definitions/uniqueItems" + }, + "enum": { + "$ref": "#/definitions/enum" + }, + "multipleOf": { + "$ref": "#/definitions/multipleOf" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "security": { + "type": "array", + "items": { + "$ref": "#/definitions/securityRequirement" + }, + "uniqueItems": true + }, + "securityRequirement": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + "xml": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "prefix": { + "type": "string" + }, + "attribute": { + "type": "boolean", + "default": false + }, + "wrapped": { + "type": "boolean", + "default": false + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "tag": { + "type": "object", + "additionalProperties": false, + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "externalDocs": { + "$ref": "#/definitions/externalDocs" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "securityDefinitions": { + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/definitions/basicAuthenticationSecurity" + }, + { + "$ref": "#/definitions/apiKeySecurity" + }, + { + "$ref": "#/definitions/oauth2ImplicitSecurity" + }, + { + "$ref": "#/definitions/oauth2PasswordSecurity" + }, + { + "$ref": "#/definitions/oauth2ApplicationSecurity" + }, + { + "$ref": "#/definitions/oauth2AccessCodeSecurity" + } + ] + } + }, + "basicAuthenticationSecurity": { + "type": "object", + "additionalProperties": false, + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "basic" + ] + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "apiKeySecurity": { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "name", + "in" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "apiKey" + ] + }, + "name": { + "type": "string" + }, + "in": { + "type": "string", + "enum": [ + "header", + "query" + ] + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "oauth2ImplicitSecurity": { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "flow", + "authorizationUrl" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "oauth2" + ] + }, + "flow": { + "type": "string", + "enum": [ + "implicit" + ] + }, + "scopes": { + "$ref": "#/definitions/oauth2Scopes" + }, + "authorizationUrl": { + "type": "string", + "format": "uri" + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "oauth2PasswordSecurity": { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "flow", + "tokenUrl" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "oauth2" + ] + }, + "flow": { + "type": "string", + "enum": [ + "password" + ] + }, + "scopes": { + "$ref": "#/definitions/oauth2Scopes" + }, + "tokenUrl": { + "type": "string", + "format": "uri" + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "oauth2ApplicationSecurity": { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "flow", + "tokenUrl" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "oauth2" + ] + }, + "flow": { + "type": "string", + "enum": [ + "application" + ] + }, + "scopes": { + "$ref": "#/definitions/oauth2Scopes" + }, + "tokenUrl": { + "type": "string", + "format": "uri" + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "oauth2AccessCodeSecurity": { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "flow", + "authorizationUrl", + "tokenUrl" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "oauth2" + ] + }, + "flow": { + "type": "string", + "enum": [ + "accessCode" + ] + }, + "scopes": { + "$ref": "#/definitions/oauth2Scopes" + }, + "authorizationUrl": { + "type": "string", + "format": "uri" + }, + "tokenUrl": { + "type": "string", + "format": "uri" + }, + "description": { + "type": "string" + } + }, + "patternProperties": { + "^x-": { + "$ref": "#/definitions/vendorExtension" + } + } + }, + "oauth2Scopes": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "mediaTypeList": { + "type": "array", + "items": { + "$ref": "#/definitions/mimeType" + }, + "uniqueItems": true + }, + "parametersList": { + "type": "array", + "description": "The parameters needed to send a valid API call.", + "additionalItems": false, + "items": { + "oneOf": [ + { + "$ref": "#/definitions/parameter" + }, + { + "$ref": "#/definitions/jsonReference" + } + ] + }, + "uniqueItems": true + }, + "schemesList": { + "type": "array", + "description": "The transfer protocol of the API.", + "items": { + "type": "string", + "enum": [ + "http", + "https", + "ws", + "wss" + ] + }, + "uniqueItems": true + }, + "collectionFormat": { + "type": "string", + "enum": [ + "csv", + "ssv", + "tsv", + "pipes" + ], + "default": "csv" + }, + "collectionFormatWithMulti": { + "type": "string", + "enum": [ + "csv", + "ssv", + "tsv", + "pipes", + "multi" + ], + "default": "csv" + }, + "title": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/title" + }, + "description": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/description" + }, + "default": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/default" + }, + "multipleOf": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf" + }, + "maximum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/maximum" + }, + "exclusiveMaximum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum" + }, + "minimum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/minimum" + }, + "exclusiveMinimum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum" + }, + "maxLength": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" + }, + "minLength": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" + }, + "pattern": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/pattern" + }, + "maxItems": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger" + }, + "minItems": { + "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0" + }, + "uniqueItems": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems" + }, + "enum": { + "$ref": "http://json-schema.org/draft-04/schema#/properties/enum" + }, + "jsonReference": { + "type": "object", + "required": [ + "$ref" + ], + "additionalProperties": false, + "properties": { + "$ref": { + "type": "string" + } + } + } + } + }, + "tests": [ + { + "description": "Example petsore", + "data": { + "swagger": "2.0", + "info": { + "description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.", + "version": "1.0.0", + "title": "Swagger Petstore", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "email": "apiteam@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "host": "petstore.swagger.io", + "basePath": "/v2", + "tags": [ + { + "name": "pet", + "description": "Everything about your Pets", + "externalDocs": { + "description": "Find out more", + "url": "http://swagger.io" + } + }, + { + "name": "store", + "description": "Access to Petstore orders" + }, + { + "name": "user", + "description": "Operations about user", + "externalDocs": { + "description": "Find out more about our store", + "url": "http://swagger.io" + } + } + ], + "schemes": [ + "http" + ], + "paths": { + "/pet": { + "post": { + "tags": [ + "pet" + ], + "summary": "Add a new pet to the store", + "description": "", + "operationId": "addPet", + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Pet object that needs to be added to the store", + "required": true, + "schema": { + "$ref": "#/definitions/Pet" + } + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "put": { + "tags": [ + "pet" + ], + "summary": "Update an existing pet", + "description": "", + "operationId": "updatePet", + "consumes": [ + "application/json", + "application/xml" + ], + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Pet object that needs to be added to the store", + "required": true, + "schema": { + "$ref": "#/definitions/Pet" + } + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + }, + "405": { + "description": "Validation exception" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByStatus": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by status", + "description": "Multiple status values can be provided with comma separated strings", + "operationId": "findPetsByStatus", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Status values that need to be considered for filter", + "required": true, + "type": "array", + "items": { + "type": "string", + "enum": [ + "available", + "pending", + "sold" + ], + "default": "available" + }, + "collectionFormat": "multi" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Pet" + } + } + }, + "400": { + "description": "Invalid status value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/findByTags": { + "get": { + "tags": [ + "pet" + ], + "summary": "Finds Pets by tags", + "description": "Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", + "operationId": "findPetsByTags", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "tags", + "in": "query", + "description": "Tags to filter by", + "required": true, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Pet" + } + } + }, + "400": { + "description": "Invalid tag value" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ], + "deprecated": true + } + }, + "/pet/{petId}": { + "get": { + "tags": [ + "pet" + ], + "summary": "Find pet by ID", + "description": "Returns a single pet", + "operationId": "getPetById", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to return", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/Pet" + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "tags": [ + "pet" + ], + "summary": "Updates a pet in the store with form data", + "description": "", + "operationId": "updatePetWithForm", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet that needs to be updated", + "required": true, + "type": "integer", + "format": "int64" + }, + { + "name": "name", + "in": "formData", + "description": "Updated name of the pet", + "required": false, + "type": "string" + }, + { + "name": "status", + "in": "formData", + "description": "Updated status of the pet", + "required": false, + "type": "string" + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + }, + "delete": { + "tags": [ + "pet" + ], + "summary": "Deletes a pet", + "description": "", + "operationId": "deletePet", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "api_key", + "in": "header", + "required": false, + "type": "string" + }, + { + "name": "petId", + "in": "path", + "description": "Pet id to delete", + "required": true, + "type": "integer", + "format": "int64" + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/pet/{petId}/uploadImage": { + "post": { + "tags": [ + "pet" + ], + "summary": "uploads an image", + "description": "", + "operationId": "uploadFile", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "ID of pet to update", + "required": true, + "type": "integer", + "format": "int64" + }, + { + "name": "additionalMetadata", + "in": "formData", + "description": "Additional data to pass to server", + "required": false, + "type": "string" + }, + { + "name": "file", + "in": "formData", + "description": "file to upload", + "required": false, + "type": "file" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/ApiResponse" + } + } + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets" + ] + } + ] + } + }, + "/store/inventory": { + "get": { + "tags": [ + "store" + ], + "summary": "Returns pet inventories by status", + "description": "Returns a map of status codes to quantities", + "operationId": "getInventory", + "produces": [ + "application/json" + ], + "parameters": [], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "int32" + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/store/order": { + "post": { + "tags": [ + "store" + ], + "summary": "Place an order for a pet", + "description": "", + "operationId": "placeOrder", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "order placed for purchasing the pet", + "required": true, + "schema": { + "$ref": "#/definitions/Order" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/Order" + } + }, + "400": { + "description": "Invalid Order" + } + } + } + }, + "/store/order/{orderId}": { + "get": { + "tags": [ + "store" + ], + "summary": "Find purchase order by ID", + "description": "For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions", + "operationId": "getOrderById", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of pet that needs to be fetched", + "required": true, + "type": "integer", + "maximum": 10.0, + "minimum": 1.0, + "format": "int64" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/Order" + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + }, + "delete": { + "tags": [ + "store" + ], + "summary": "Delete purchase order by ID", + "description": "For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors", + "operationId": "deleteOrder", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "orderId", + "in": "path", + "description": "ID of the order that needs to be deleted", + "required": true, + "type": "integer", + "minimum": 1.0, + "format": "int64" + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + } + }, + "/user": { + "post": { + "tags": [ + "user" + ], + "summary": "Create user", + "description": "This can only be done by the logged in user.", + "operationId": "createUser", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "Created user object", + "required": true, + "schema": { + "$ref": "#/definitions/User" + } + } + ], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/createWithArray": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "description": "", + "operationId": "createUsersWithArrayInput", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "List of user object", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/User" + } + } + } + ], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/createWithList": { + "post": { + "tags": [ + "user" + ], + "summary": "Creates list of users with given input array", + "description": "", + "operationId": "createUsersWithListInput", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "List of user object", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/User" + } + } + } + ], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/login": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs user into the system", + "description": "", + "operationId": "loginUser", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "username", + "in": "query", + "description": "The user name for login", + "required": true, + "type": "string" + }, + { + "name": "password", + "in": "query", + "description": "The password for login in clear text", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "type": "string" + }, + "headers": { + "X-Rate-Limit": { + "type": "integer", + "format": "int32", + "description": "calls per hour allowed by the user" + }, + "X-Expires-After": { + "type": "string", + "format": "date-time", + "description": "date in UTC when token expires" + } + } + }, + "400": { + "description": "Invalid username/password supplied" + } + } + } + }, + "/user/logout": { + "get": { + "tags": [ + "user" + ], + "summary": "Logs out current logged in user session", + "description": "", + "operationId": "logoutUser", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [], + "responses": { + "default": { + "description": "successful operation" + } + } + } + }, + "/user/{username}": { + "get": { + "tags": [ + "user" + ], + "summary": "Get user by user name", + "description": "", + "operationId": "getUserByName", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be fetched. Use user1 for testing. ", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/User" + } + }, + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + }, + "put": { + "tags": [ + "user" + ], + "summary": "Updated user", + "description": "This can only be done by the logged in user.", + "operationId": "updateUser", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "username", + "in": "path", + "description": "name that need to be updated", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body", + "description": "Updated user object", + "required": true, + "schema": { + "$ref": "#/definitions/User" + } + } + ], + "responses": { + "400": { + "description": "Invalid user supplied" + }, + "404": { + "description": "User not found" + } + } + }, + "delete": { + "tags": [ + "user" + ], + "summary": "Delete user", + "description": "This can only be done by the logged in user.", + "operationId": "deleteUser", + "produces": [ + "application/xml", + "application/json" + ], + "parameters": [ + { + "name": "username", + "in": "path", + "description": "The name that needs to be deleted", + "required": true, + "type": "string" + } + ], + "responses": { + "400": { + "description": "Invalid username supplied" + }, + "404": { + "description": "User not found" + } + } + } + } + }, + "securityDefinitions": { + "petstore_auth": { + "type": "oauth2", + "authorizationUrl": "http://petstore.swagger.io/oauth/dialog", + "flow": "implicit", + "scopes": { + "write:pets": "modify pets in your account", + "read:pets": "read your pets" + } + }, + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + } + }, + "definitions": { + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "petId": { + "type": "integer", + "format": "int64" + }, + "quantity": { + "type": "integer", + "format": "int32" + }, + "shipDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Order Status", + "enum": [ + "placed", + "approved", + "delivered" + ] + }, + "complete": { + "type": "boolean", + "default": false + } + }, + "xml": { + "name": "Order" + } + }, + "Category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "Category" + } + }, + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "username": { + "type": "string" + }, + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "userStatus": { + "type": "integer", + "format": "int32", + "description": "User Status" + } + }, + "xml": { + "name": "User" + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "Tag" + } + }, + "Pet": { + "type": "object", + "required": [ + "name", + "photoUrls" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "category": { + "$ref": "#/definitions/Category" + }, + "name": { + "type": "string", + "example": "doggie" + }, + "photoUrls": { + "type": "array", + "xml": { + "name": "photoUrl", + "wrapped": true + }, + "items": { + "type": "string" + } + }, + "tags": { + "type": "array", + "xml": { + "name": "tag", + "wrapped": true + }, + "items": { + "$ref": "#/definitions/Tag" + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + } + }, + "xml": { + "name": "Pet" + } + }, + "ApiResponse": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "string" + }, + "message": { + "type": "string" + } + } + } + }, + "externalDocs": { + "description": "Find out more about Swagger", + "url": "http://swagger.io" + } + }, + "valid": true + } + ] + } +] diff --git a/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/json_schema_test_suite.py b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/json_schema_test_suite.py new file mode 100644 index 0000000..905fb6a --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/json_schema_test_suite.py @@ -0,0 +1,12 @@ +""" +A performance benchmark using the official test suite. + +This benchmarks jsonschema using every valid example in the +JSON-Schema-Test-Suite. It will take some time to complete. +""" +from pyperf import Runner + +from jsonschema.tests._suite import Suite + +if __name__ == "__main__": + Suite().benchmark(runner=Runner()) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/nested_schemas.py b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/nested_schemas.py new file mode 100644 index 0000000..b025c47 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/nested_schemas.py @@ -0,0 +1,56 @@ +""" +Validating highly nested schemas shouldn't cause exponential time blowups. + +See https://github.com/python-jsonschema/jsonschema/issues/1097. +""" +from itertools import cycle + +from jsonschema.validators import validator_for + +metaschemaish = { + "$id": "https://example.com/draft/2020-12/schema/strict", + "$schema": "https://json-schema.org/draft/2020-12/schema", + + "$vocabulary": { + "https://json-schema.org/draft/2020-12/vocab/core": True, + "https://json-schema.org/draft/2020-12/vocab/applicator": True, + "https://json-schema.org/draft/2020-12/vocab/unevaluated": True, + "https://json-schema.org/draft/2020-12/vocab/validation": True, + "https://json-schema.org/draft/2020-12/vocab/meta-data": True, + "https://json-schema.org/draft/2020-12/vocab/format-annotation": True, + "https://json-schema.org/draft/2020-12/vocab/content": True, + }, + "$dynamicAnchor": "meta", + + "$ref": "https://json-schema.org/draft/2020-12/schema", + "unevaluatedProperties": False, +} + + +def nested_schema(levels): + """ + Produce a schema which validates deeply nested objects and arrays. + """ + + names = cycle(["foo", "bar", "baz", "quux", "spam", "eggs"]) + schema = {"type": "object", "properties": {"ham": {"type": "string"}}} + for _, name in zip(range(levels - 1), names): + schema = {"type": "object", "properties": {name: schema}} + return schema + + +validator = validator_for(metaschemaish)(metaschemaish) + +if __name__ == "__main__": + from pyperf import Runner + runner = Runner() + + not_nested = nested_schema(levels=1) + runner.bench_func("not nested", lambda: validator.is_valid(not_nested)) + + for levels in range(1, 11, 3): + schema = nested_schema(levels=levels) + runner.bench_func( + f"nested * {levels}", + lambda schema=schema: validator.is_valid(schema), + ) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/subcomponents.py b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/subcomponents.py new file mode 100644 index 0000000..6d78c7b --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/subcomponents.py @@ -0,0 +1,42 @@ +""" +A benchmark which tries to compare the possible slow subparts of validation. +""" +from referencing import Registry +from referencing.jsonschema import DRAFT202012 +from rpds import HashTrieMap, HashTrieSet + +from jsonschema import Draft202012Validator + +schema = { + "type": "array", + "minLength": 1, + "maxLength": 1, + "items": {"type": "integer"}, +} + +hmap = HashTrieMap() +hset = HashTrieSet() + +registry = Registry() + +v = Draft202012Validator(schema) + + +def registry_data_structures(): + return hmap.insert("foo", "bar"), hset.insert("foo") + + +def registry_add(): + resource = DRAFT202012.create_resource(schema) + return registry.with_resource(uri="urn:example", resource=resource) + + +if __name__ == "__main__": + from pyperf import Runner + runner = Runner() + + runner.bench_func("HashMap/HashSet insertion", registry_data_structures) + runner.bench_func("Registry insertion", registry_add) + runner.bench_func("Success", lambda: v.is_valid([1])) + runner.bench_func("Failure", lambda: v.is_valid(["foo"])) + runner.bench_func("Metaschema validation", lambda: v.check_schema(schema)) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/unused_registry.py b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/unused_registry.py new file mode 100644 index 0000000..7b272c2 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/unused_registry.py @@ -0,0 +1,35 @@ +""" +An unused schema registry should not cause slower validation. + +"Unused" here means one where no reference resolution is occurring anyhow. + +See https://github.com/python-jsonschema/jsonschema/issues/1088. +""" +from pyperf import Runner +from referencing import Registry +from referencing.jsonschema import DRAFT201909 + +from jsonschema import Draft201909Validator + +registry = Registry().with_resource( + "urn:example:foo", + DRAFT201909.create_resource({}), +) + +schema = {"$ref": "https://json-schema.org/draft/2019-09/schema"} +instance = {"maxLength": 4} + +no_registry = Draft201909Validator(schema) +with_useless_registry = Draft201909Validator(schema, registry=registry) + +if __name__ == "__main__": + runner = Runner() + + runner.bench_func( + "no registry", + lambda: no_registry.is_valid(instance), + ) + runner.bench_func( + "useless registry", + lambda: with_useless_registry.is_valid(instance), + ) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/useless_applicator_schemas.py b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/useless_applicator_schemas.py new file mode 100644 index 0000000..f3229c0 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/useless_applicator_schemas.py @@ -0,0 +1,106 @@ + +""" +A benchmark for validation of applicators containing lots of useless schemas. + +Signals a small possible optimization to remove all such schemas ahead of time. +""" + +from pyperf import Runner + +from jsonschema import Draft202012Validator as Validator + +NUM_USELESS = 100000 + +subschema = {"const": 37} + +valid = 37 +invalid = 12 + +baseline = Validator(subschema) + + +# These should be indistinguishable from just `subschema` +by_name = { + "single subschema": { + "anyOf": Validator({"anyOf": [subschema]}), + "allOf": Validator({"allOf": [subschema]}), + "oneOf": Validator({"oneOf": [subschema]}), + }, + "redundant subschemas": { + "anyOf": Validator({"anyOf": [subschema] * NUM_USELESS}), + "allOf": Validator({"allOf": [subschema] * NUM_USELESS}), + }, + "useless successful subschemas (beginning)": { + "anyOf": Validator({"anyOf": [subschema, *[True] * NUM_USELESS]}), + "allOf": Validator({"allOf": [subschema, *[True] * NUM_USELESS]}), + }, + "useless successful subschemas (middle)": { + "anyOf": Validator( + { + "anyOf": [ + *[True] * (NUM_USELESS // 2), + subschema, + *[True] * (NUM_USELESS // 2), + ], + }, + ), + "allOf": Validator( + { + "allOf": [ + *[True] * (NUM_USELESS // 2), + subschema, + *[True] * (NUM_USELESS // 2), + ], + }, + ), + }, + "useless successful subschemas (end)": { + "anyOf": Validator({"anyOf": [*[True] * NUM_USELESS, subschema]}), + "allOf": Validator({"allOf": [*[True] * NUM_USELESS, subschema]}), + }, + "useless failing subschemas (beginning)": { + "anyOf": Validator({"anyOf": [subschema, *[False] * NUM_USELESS]}), + "oneOf": Validator({"oneOf": [subschema, *[False] * NUM_USELESS]}), + }, + "useless failing subschemas (middle)": { + "anyOf": Validator( + { + "anyOf": [ + *[False] * (NUM_USELESS // 2), + subschema, + *[False] * (NUM_USELESS // 2), + ], + }, + ), + "oneOf": Validator( + { + "oneOf": [ + *[False] * (NUM_USELESS // 2), + subschema, + *[False] * (NUM_USELESS // 2), + ], + }, + ), + }, + "useless failing subschemas (end)": { + "anyOf": Validator({"anyOf": [*[False] * NUM_USELESS, subschema]}), + "oneOf": Validator({"oneOf": [*[False] * NUM_USELESS, subschema]}), + }, +} + +if __name__ == "__main__": + runner = Runner() + + runner.bench_func("baseline valid", lambda: baseline.is_valid(valid)) + runner.bench_func("baseline invalid", lambda: baseline.is_valid(invalid)) + + for group, applicators in by_name.items(): + for applicator, validator in applicators.items(): + runner.bench_func( + f"{group}: {applicator} valid", + lambda validator=validator: validator.is_valid(valid), + ) + runner.bench_func( + f"{group}: {applicator} invalid", + lambda validator=validator: validator.is_valid(invalid), + ) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/useless_keywords.py b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/useless_keywords.py new file mode 100644 index 0000000..50f4359 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/useless_keywords.py @@ -0,0 +1,32 @@ +""" +A benchmark for validation of schemas containing lots of useless keywords. + +Checks we filter them out once, ahead of time. +""" + +from pyperf import Runner + +from jsonschema import Draft202012Validator + +NUM_USELESS = 100000 +schema = dict( + [ + ("not", {"const": 42}), + *((str(i), i) for i in range(NUM_USELESS)), + ("type", "integer"), + *((str(i), i) for i in range(NUM_USELESS, NUM_USELESS)), + ("minimum", 37), + ], +) +validator = Draft202012Validator(schema) + +valid = 3737 +invalid = 12 + + +if __name__ == "__main__": + runner = Runner() + runner.bench_func("beginning of schema", lambda: validator.is_valid(42)) + runner.bench_func("middle of schema", lambda: validator.is_valid("foo")) + runner.bench_func("end of schema", lambda: validator.is_valid(12)) + runner.bench_func("valid", lambda: validator.is_valid(3737)) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/validator_creation.py b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/validator_creation.py new file mode 100644 index 0000000..4baeb3a --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/benchmarks/validator_creation.py @@ -0,0 +1,14 @@ +from pyperf import Runner + +from jsonschema import Draft202012Validator + +schema = { + "type": "array", + "minLength": 1, + "maxLength": 1, + "items": {"type": "integer"}, +} + + +if __name__ == "__main__": + Runner().bench_func("validator creation", Draft202012Validator, schema) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/cli.py b/.venv/lib/python3.10/site-packages/jsonschema/cli.py new file mode 100644 index 0000000..cf6298e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/cli.py @@ -0,0 +1,296 @@ +""" +The ``jsonschema`` command line. +""" + +from importlib import metadata +from json import JSONDecodeError +from textwrap import dedent +import argparse +import json +import sys +import traceback +import warnings + +try: + from pkgutil import resolve_name +except ImportError: + from pkgutil_resolve_name import resolve_name # type: ignore[no-redef] + +from attrs import define, field + +from jsonschema.exceptions import SchemaError +from jsonschema.validators import _RefResolver, validator_for + +warnings.warn( + ( + "The jsonschema CLI is deprecated and will be removed in a future " + "version. Please use check-jsonschema instead, which can be installed " + "from https://pypi.org/project/check-jsonschema/" + ), + DeprecationWarning, + stacklevel=2, +) + + +class _CannotLoadFile(Exception): + pass + + +@define +class _Outputter: + + _formatter = field() + _stdout = field() + _stderr = field() + + @classmethod + def from_arguments(cls, arguments, stdout, stderr): + if arguments["output"] == "plain": + formatter = _PlainFormatter(arguments["error_format"]) + elif arguments["output"] == "pretty": + formatter = _PrettyFormatter() + return cls(formatter=formatter, stdout=stdout, stderr=stderr) + + def load(self, path): + try: + file = open(path) # noqa: SIM115, PTH123 + except FileNotFoundError as error: + self.filenotfound_error(path=path, exc_info=sys.exc_info()) + raise _CannotLoadFile() from error + + with file: + try: + return json.load(file) + except JSONDecodeError as error: + self.parsing_error(path=path, exc_info=sys.exc_info()) + raise _CannotLoadFile() from error + + def filenotfound_error(self, **kwargs): + self._stderr.write(self._formatter.filenotfound_error(**kwargs)) + + def parsing_error(self, **kwargs): + self._stderr.write(self._formatter.parsing_error(**kwargs)) + + def validation_error(self, **kwargs): + self._stderr.write(self._formatter.validation_error(**kwargs)) + + def validation_success(self, **kwargs): + self._stdout.write(self._formatter.validation_success(**kwargs)) + + +@define +class _PrettyFormatter: + + _ERROR_MSG = dedent( + """\ + ===[{type}]===({path})=== + + {body} + ----------------------------- + """, + ) + _SUCCESS_MSG = "===[SUCCESS]===({path})===\n" + + def filenotfound_error(self, path, exc_info): + return self._ERROR_MSG.format( + path=path, + type="FileNotFoundError", + body=f"{path!r} does not exist.", + ) + + def parsing_error(self, path, exc_info): + exc_type, exc_value, exc_traceback = exc_info + exc_lines = "".join( + traceback.format_exception(exc_type, exc_value, exc_traceback), + ) + return self._ERROR_MSG.format( + path=path, + type=exc_type.__name__, + body=exc_lines, + ) + + def validation_error(self, instance_path, error): + return self._ERROR_MSG.format( + path=instance_path, + type=error.__class__.__name__, + body=error, + ) + + def validation_success(self, instance_path): + return self._SUCCESS_MSG.format(path=instance_path) + + +@define +class _PlainFormatter: + + _error_format = field() + + def filenotfound_error(self, path, exc_info): + return f"{path!r} does not exist.\n" + + def parsing_error(self, path, exc_info): + return "Failed to parse {}: {}\n".format( + "" if path == "" else repr(path), + exc_info[1], + ) + + def validation_error(self, instance_path, error): + return self._error_format.format(file_name=instance_path, error=error) + + def validation_success(self, instance_path): + return "" + + +def _resolve_name_with_default(name): + if "." not in name: + name = "jsonschema." + name + return resolve_name(name) + + +parser = argparse.ArgumentParser( + description="JSON Schema Validation CLI", +) +parser.add_argument( + "-i", "--instance", + action="append", + dest="instances", + help=""" + a path to a JSON instance (i.e. filename.json) to validate (may + be specified multiple times). If no instances are provided via this + option, one will be expected on standard input. + """, +) +parser.add_argument( + "-F", "--error-format", + help=""" + the format to use for each validation error message, specified + in a form suitable for str.format. This string will be passed + one formatted object named 'error' for each ValidationError. + Only provide this option when using --output=plain, which is the + default. If this argument is unprovided and --output=plain is + used, a simple default representation will be used. + """, +) +parser.add_argument( + "-o", "--output", + choices=["plain", "pretty"], + default="plain", + help=""" + an output format to use. 'plain' (default) will produce minimal + text with one line for each error, while 'pretty' will produce + more detailed human-readable output on multiple lines. + """, +) +parser.add_argument( + "-V", "--validator", + type=_resolve_name_with_default, + help=""" + the fully qualified object name of a validator to use, or, for + validators that are registered with jsonschema, simply the name + of the class. + """, +) +parser.add_argument( + "--base-uri", + help=""" + a base URI to assign to the provided schema, even if it does not + declare one (via e.g. $id). This option can be used if you wish to + resolve relative references to a particular URI (or local path) + """, +) +parser.add_argument( + "--version", + action="version", + version=metadata.version("jsonschema"), +) +parser.add_argument( + "schema", + help="the path to a JSON Schema to validate with (i.e. schema.json)", +) + + +def parse_args(args): # noqa: D103 + arguments = vars(parser.parse_args(args=args or ["--help"])) + if arguments["output"] != "plain" and arguments["error_format"]: + raise parser.error( + "--error-format can only be used with --output plain", + ) + if arguments["output"] == "plain" and arguments["error_format"] is None: + arguments["error_format"] = "{error.instance}: {error.message}\n" + return arguments + + +def _validate_instance(instance_path, instance, validator, outputter): + invalid = False + for error in validator.iter_errors(instance): + invalid = True + outputter.validation_error(instance_path=instance_path, error=error) + + if not invalid: + outputter.validation_success(instance_path=instance_path) + return invalid + + +def main(args=sys.argv[1:]): # noqa: D103 + sys.exit(run(arguments=parse_args(args=args))) + + +def run(arguments, stdout=sys.stdout, stderr=sys.stderr, stdin=sys.stdin): # noqa: D103 + outputter = _Outputter.from_arguments( + arguments=arguments, + stdout=stdout, + stderr=stderr, + ) + + try: + schema = outputter.load(arguments["schema"]) + except _CannotLoadFile: + return 1 + + Validator = arguments["validator"] + if Validator is None: + Validator = validator_for(schema) + + try: + Validator.check_schema(schema) + except SchemaError as error: + outputter.validation_error( + instance_path=arguments["schema"], + error=error, + ) + return 1 + + if arguments["instances"]: + load, instances = outputter.load, arguments["instances"] + else: + def load(_): + try: + return json.load(stdin) + except JSONDecodeError as error: + outputter.parsing_error( + path="", exc_info=sys.exc_info(), + ) + raise _CannotLoadFile() from error + instances = [""] + + resolver = _RefResolver( + base_uri=arguments["base_uri"], + referrer=schema, + ) if arguments["base_uri"] is not None else None + + validator = Validator(schema, resolver=resolver) + exit_code = 0 + for each in instances: + try: + instance = load(each) + except _CannotLoadFile: + exit_code = 1 + else: + exit_code |= _validate_instance( + instance_path=each, + instance=instance, + validator=validator, + outputter=outputter, + ) + + return exit_code diff --git a/.venv/lib/python3.10/site-packages/jsonschema/exceptions.py b/.venv/lib/python3.10/site-packages/jsonschema/exceptions.py new file mode 100644 index 0000000..78da49f --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/exceptions.py @@ -0,0 +1,487 @@ +""" +Validation errors, and some surrounding helpers. +""" +from __future__ import annotations + +from collections import defaultdict, deque +from pprint import pformat +from textwrap import dedent, indent +from typing import TYPE_CHECKING, Any, ClassVar +import heapq +import itertools +import warnings + +from attrs import define +from referencing.exceptions import Unresolvable as _Unresolvable + +from jsonschema import _utils + +if TYPE_CHECKING: + from collections.abc import Iterable, Mapping, MutableMapping, Sequence + + from jsonschema import _types + +WEAK_MATCHES: frozenset[str] = frozenset(["anyOf", "oneOf"]) +STRONG_MATCHES: frozenset[str] = frozenset() + +_unset = _utils.Unset() + + +def _pretty(thing: Any, prefix: str): + """ + Format something for an error message as prettily as we currently can. + """ + return indent(pformat(thing, width=72, sort_dicts=False), prefix).lstrip() + + +def __getattr__(name): + if name == "RefResolutionError": + warnings.warn( + _RefResolutionError._DEPRECATION_MESSAGE, + DeprecationWarning, + stacklevel=2, + ) + return _RefResolutionError + raise AttributeError(f"module {__name__} has no attribute {name}") + + +class _Error(Exception): + + _word_for_schema_in_error_message: ClassVar[str] + _word_for_instance_in_error_message: ClassVar[str] + + def __init__( + self, + message: str, + validator: str = _unset, # type: ignore[assignment] + path: Iterable[str | int] = (), + cause: Exception | None = None, + context=(), + validator_value: Any = _unset, + instance: Any = _unset, + schema: Mapping[str, Any] | bool = _unset, # type: ignore[assignment] + schema_path: Iterable[str | int] = (), + parent: _Error | None = None, + type_checker: _types.TypeChecker = _unset, # type: ignore[assignment] + ) -> None: + super().__init__( + message, + validator, + path, + cause, + context, + validator_value, + instance, + schema, + schema_path, + parent, + ) + self.message = message + self.path = self.relative_path = deque(path) + self.schema_path = self.relative_schema_path = deque(schema_path) + self.context = list(context) + self.cause = self.__cause__ = cause + self.validator = validator + self.validator_value = validator_value + self.instance = instance + self.schema = schema + self.parent = parent + self._type_checker = type_checker + + for error in context: + error.parent = self + + def __repr__(self) -> str: + return f"<{self.__class__.__name__}: {self.message!r}>" + + def __str__(self) -> str: + essential_for_verbose = ( + self.validator, self.validator_value, self.instance, self.schema, + ) + if any(m is _unset for m in essential_for_verbose): + return self.message + + schema_path = _utils.format_as_index( + container=self._word_for_schema_in_error_message, + indices=list(self.relative_schema_path)[:-1], + ) + instance_path = _utils.format_as_index( + container=self._word_for_instance_in_error_message, + indices=self.relative_path, + ) + prefix = 16 * " " + + return dedent( + f"""\ + {self.message} + + Failed validating {self.validator!r} in {schema_path}: + {_pretty(self.schema, prefix=prefix)} + + On {instance_path}: + {_pretty(self.instance, prefix=prefix)} + """.rstrip(), + ) + + @classmethod + def create_from(cls, other: _Error): + return cls(**other._contents()) + + @property + def absolute_path(self) -> Sequence[str | int]: + parent = self.parent + if parent is None: + return self.relative_path + + path = deque(self.relative_path) + path.extendleft(reversed(parent.absolute_path)) + return path + + @property + def absolute_schema_path(self) -> Sequence[str | int]: + parent = self.parent + if parent is None: + return self.relative_schema_path + + path = deque(self.relative_schema_path) + path.extendleft(reversed(parent.absolute_schema_path)) + return path + + @property + def json_path(self) -> str: + path = "$" + for elem in self.absolute_path: + if isinstance(elem, int): + path += "[" + str(elem) + "]" + else: + path += "." + elem + return path + + def _set( + self, + type_checker: _types.TypeChecker | None = None, + **kwargs: Any, + ) -> None: + if type_checker is not None and self._type_checker is _unset: + self._type_checker = type_checker + + for k, v in kwargs.items(): + if getattr(self, k) is _unset: + setattr(self, k, v) + + def _contents(self): + attrs = ( + "message", "cause", "context", "validator", "validator_value", + "path", "schema_path", "instance", "schema", "parent", + ) + return {attr: getattr(self, attr) for attr in attrs} + + def _matches_type(self) -> bool: + try: + # We ignore this as we want to simply crash if this happens + expected = self.schema["type"] # type: ignore[index] + except (KeyError, TypeError): + return False + + if isinstance(expected, str): + return self._type_checker.is_type(self.instance, expected) + + return any( + self._type_checker.is_type(self.instance, expected_type) + for expected_type in expected + ) + + +class ValidationError(_Error): + """ + An instance was invalid under a provided schema. + """ + + _word_for_schema_in_error_message = "schema" + _word_for_instance_in_error_message = "instance" + + +class SchemaError(_Error): + """ + A schema was invalid under its corresponding metaschema. + """ + + _word_for_schema_in_error_message = "metaschema" + _word_for_instance_in_error_message = "schema" + + +@define(slots=False) +class _RefResolutionError(Exception): + """ + A ref could not be resolved. + """ + + _DEPRECATION_MESSAGE = ( + "jsonschema.exceptions.RefResolutionError is deprecated as of version " + "4.18.0. If you wish to catch potential reference resolution errors, " + "directly catch referencing.exceptions.Unresolvable." + ) + + _cause: Exception + + def __eq__(self, other): + if self.__class__ is not other.__class__: + return NotImplemented # pragma: no cover -- uncovered but deprecated # noqa: E501 + return self._cause == other._cause + + def __str__(self) -> str: + return str(self._cause) + + +class _WrappedReferencingError(_RefResolutionError, _Unresolvable): # pragma: no cover -- partially uncovered but to be removed # noqa: E501 + def __init__(self, cause: _Unresolvable): + object.__setattr__(self, "_wrapped", cause) + + def __eq__(self, other): + if other.__class__ is self.__class__: + return self._wrapped == other._wrapped + elif other.__class__ is self._wrapped.__class__: + return self._wrapped == other + return NotImplemented + + def __getattr__(self, attr): + return getattr(self._wrapped, attr) + + def __hash__(self): + return hash(self._wrapped) + + def __repr__(self): + return f"" + + def __str__(self): + return f"{self._wrapped.__class__.__name__}: {self._wrapped}" + + +class UndefinedTypeCheck(Exception): + """ + A type checker was asked to check a type it did not have registered. + """ + + def __init__(self, type: str) -> None: + self.type = type + + def __str__(self) -> str: + return f"Type {self.type!r} is unknown to this type checker" + + +class UnknownType(Exception): + """ + A validator was asked to validate an instance against an unknown type. + """ + + def __init__(self, type, instance, schema): + self.type = type + self.instance = instance + self.schema = schema + + def __str__(self): + prefix = 16 * " " + + return dedent( + f"""\ + Unknown type {self.type!r} for validator with schema: + {_pretty(self.schema, prefix=prefix)} + + While checking instance: + {_pretty(self.instance, prefix=prefix)} + """.rstrip(), + ) + + +class FormatError(Exception): + """ + Validating a format failed. + """ + + def __init__(self, message, cause=None): + super().__init__(message, cause) + self.message = message + self.cause = self.__cause__ = cause + + def __str__(self): + return self.message + + +class ErrorTree: + """ + ErrorTrees make it easier to check which validations failed. + """ + + _instance = _unset + + def __init__(self, errors: Iterable[ValidationError] = ()): + self.errors: MutableMapping[str, ValidationError] = {} + self._contents: Mapping[str, ErrorTree] = defaultdict(self.__class__) + + for error in errors: + container = self + for element in error.path: + container = container[element] + container.errors[error.validator] = error + + container._instance = error.instance + + def __contains__(self, index: str | int): + """ + Check whether ``instance[index]`` has any errors. + """ + return index in self._contents + + def __getitem__(self, index): + """ + Retrieve the child tree one level down at the given ``index``. + + If the index is not in the instance that this tree corresponds + to and is not known by this tree, whatever error would be raised + by ``instance.__getitem__`` will be propagated (usually this is + some subclass of `LookupError`. + """ + if self._instance is not _unset and index not in self: + self._instance[index] + return self._contents[index] + + def __setitem__(self, index: str | int, value: ErrorTree): + """ + Add an error to the tree at the given ``index``. + + .. deprecated:: v4.20.0 + + Setting items on an `ErrorTree` is deprecated without replacement. + To populate a tree, provide all of its sub-errors when you + construct the tree. + """ + warnings.warn( + "ErrorTree.__setitem__ is deprecated without replacement.", + DeprecationWarning, + stacklevel=2, + ) + self._contents[index] = value # type: ignore[index] + + def __iter__(self): + """ + Iterate (non-recursively) over the indices in the instance with errors. + """ + return iter(self._contents) + + def __len__(self): + """ + Return the `total_errors`. + """ + return self.total_errors + + def __repr__(self): + total = len(self) + errors = "error" if total == 1 else "errors" + return f"<{self.__class__.__name__} ({total} total {errors})>" + + @property + def total_errors(self): + """ + The total number of errors in the entire tree, including children. + """ + child_errors = sum(len(tree) for _, tree in self._contents.items()) + return len(self.errors) + child_errors + + +def by_relevance(weak=WEAK_MATCHES, strong=STRONG_MATCHES): + """ + Create a key function that can be used to sort errors by relevance. + + Arguments: + weak (set): + a collection of validation keywords to consider to be + "weak". If there are two errors at the same level of the + instance and one is in the set of weak validation keywords, + the other error will take priority. By default, :kw:`anyOf` + and :kw:`oneOf` are considered weak keywords and will be + superseded by other same-level validation errors. + + strong (set): + a collection of validation keywords to consider to be + "strong" + + """ + + def relevance(error): + validator = error.validator + return ( # prefer errors which are ... + -len(error.path), # 'deeper' and thereby more specific + error.path, # earlier (for sibling errors) + validator not in weak, # for a non-low-priority keyword + validator in strong, # for a high priority keyword + not error._matches_type(), # at least match the instance's type + ) # otherwise we'll treat them the same + + return relevance + + +relevance = by_relevance() +""" +A key function (e.g. to use with `sorted`) which sorts errors by relevance. + +Example: + +.. code:: python + + sorted(validator.iter_errors(12), key=jsonschema.exceptions.relevance) +""" + + +def best_match(errors, key=relevance): + """ + Try to find an error that appears to be the best match among given errors. + + In general, errors that are higher up in the instance (i.e. for which + `ValidationError.path` is shorter) are considered better matches, + since they indicate "more" is wrong with the instance. + + If the resulting match is either :kw:`oneOf` or :kw:`anyOf`, the + *opposite* assumption is made -- i.e. the deepest error is picked, + since these keywords only need to match once, and any other errors + may not be relevant. + + Arguments: + errors (collections.abc.Iterable): + + the errors to select from. Do not provide a mixture of + errors from different validation attempts (i.e. from + different instances or schemas), since it won't produce + sensical output. + + key (collections.abc.Callable): + + the key to use when sorting errors. See `relevance` and + transitively `by_relevance` for more details (the default is + to sort with the defaults of that function). Changing the + default is only useful if you want to change the function + that rates errors but still want the error context descent + done by this function. + + Returns: + the best matching error, or ``None`` if the iterable was empty + + .. note:: + + This function is a heuristic. Its return value may change for a given + set of inputs from version to version if better heuristics are added. + + """ + errors = iter(errors) + best = next(errors, None) + if best is None: + return + best = max(itertools.chain([best], errors), key=key) + + while best.context: + # Calculate the minimum via nsmallest, because we don't recurse if + # all nested errors have the same relevance (i.e. if min == max == all) + smallest = heapq.nsmallest(2, best.context, key=key) + if len(smallest) == 2 and key(smallest[0]) == key(smallest[1]): # noqa: PLR2004 + return best + best = smallest[0] + return best diff --git a/.venv/lib/python3.10/site-packages/jsonschema/protocols.py b/.venv/lib/python3.10/site-packages/jsonschema/protocols.py new file mode 100644 index 0000000..39e56d0 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/protocols.py @@ -0,0 +1,236 @@ +""" +typing.Protocol classes for jsonschema interfaces. +""" + +# for reference material on Protocols, see +# https://www.python.org/dev/peps/pep-0544/ + +from __future__ import annotations + +from typing import ( + TYPE_CHECKING, + Any, + ClassVar, + Iterable, + Protocol, + runtime_checkable, +) + +# in order for Sphinx to resolve references accurately from type annotations, +# it needs to see names like `jsonschema.TypeChecker` +# therefore, only import at type-checking time (to avoid circular references), +# but use `jsonschema` for any types which will otherwise not be resolvable +if TYPE_CHECKING: + from collections.abc import Mapping + + import referencing.jsonschema + + from jsonschema import _typing + from jsonschema.exceptions import ValidationError + import jsonschema + import jsonschema.validators + +# For code authors working on the validator protocol, these are the three +# use-cases which should be kept in mind: +# +# 1. As a protocol class, it can be used in type annotations to describe the +# available methods and attributes of a validator +# 2. It is the source of autodoc for the validator documentation +# 3. It is runtime_checkable, meaning that it can be used in isinstance() +# checks. +# +# Since protocols are not base classes, isinstance() checking is limited in +# its capabilities. See docs on runtime_checkable for detail + + +@runtime_checkable +class Validator(Protocol): + """ + The protocol to which all validator classes adhere. + + Arguments: + + schema: + + The schema that the validator object will validate with. + It is assumed to be valid, and providing + an invalid schema can lead to undefined behavior. See + `Validator.check_schema` to validate a schema first. + + registry: + + a schema registry that will be used for looking up JSON references + + resolver: + + a resolver that will be used to resolve :kw:`$ref` + properties (JSON references). If unprovided, one will be created. + + .. deprecated:: v4.18.0 + + `RefResolver <_RefResolver>` has been deprecated in favor of + `referencing`, and with it, this argument. + + format_checker: + + if provided, a checker which will be used to assert about + :kw:`format` properties present in the schema. If unprovided, + *no* format validation is done, and the presence of format + within schemas is strictly informational. Certain formats + require additional packages to be installed in order to assert + against instances. Ensure you've installed `jsonschema` with + its `extra (optional) dependencies ` when + invoking ``pip``. + + .. deprecated:: v4.12.0 + + Subclassing validator classes now explicitly warns this is not part of + their public API. + + """ + + #: An object representing the validator's meta schema (the schema that + #: describes valid schemas in the given version). + META_SCHEMA: ClassVar[Mapping] + + #: A mapping of validation keywords (`str`\s) to functions that + #: validate the keyword with that name. For more information see + #: `creating-validators`. + VALIDATORS: ClassVar[Mapping] + + #: A `jsonschema.TypeChecker` that will be used when validating + #: :kw:`type` keywords in JSON schemas. + TYPE_CHECKER: ClassVar[jsonschema.TypeChecker] + + #: A `jsonschema.FormatChecker` that will be used when validating + #: :kw:`format` keywords in JSON schemas. + FORMAT_CHECKER: ClassVar[jsonschema.FormatChecker] + + #: A function which given a schema returns its ID. + ID_OF: _typing.id_of + + #: The schema that will be used to validate instances + schema: Mapping | bool + + def __init__( + self, + schema: Mapping | bool, + registry: referencing.jsonschema.SchemaRegistry, + format_checker: jsonschema.FormatChecker | None = None, + ) -> None: + ... + + @classmethod + def check_schema(cls, schema: Mapping | bool) -> None: + """ + Validate the given schema against the validator's `META_SCHEMA`. + + Raises: + + `jsonschema.exceptions.SchemaError`: + + if the schema is invalid + + """ + + def is_type(self, instance: Any, type: str) -> bool: + """ + Check if the instance is of the given (JSON Schema) type. + + Arguments: + + instance: + + the value to check + + type: + + the name of a known (JSON Schema) type + + Returns: + + whether the instance is of the given type + + Raises: + + `jsonschema.exceptions.UnknownType`: + + if ``type`` is not a known type + + """ + + def is_valid(self, instance: Any) -> bool: + """ + Check if the instance is valid under the current `schema`. + + Returns: + + whether the instance is valid or not + + >>> schema = {"maxItems" : 2} + >>> Draft202012Validator(schema).is_valid([2, 3, 4]) + False + + """ + + def iter_errors(self, instance: Any) -> Iterable[ValidationError]: + r""" + Lazily yield each of the validation errors in the given instance. + + >>> schema = { + ... "type" : "array", + ... "items" : {"enum" : [1, 2, 3]}, + ... "maxItems" : 2, + ... } + >>> v = Draft202012Validator(schema) + >>> for error in sorted(v.iter_errors([2, 3, 4]), key=str): + ... print(error.message) + 4 is not one of [1, 2, 3] + [2, 3, 4] is too long + + .. deprecated:: v4.0.0 + + Calling this function with a second schema argument is deprecated. + Use `Validator.evolve` instead. + """ + + def validate(self, instance: Any) -> None: + """ + Check if the instance is valid under the current `schema`. + + Raises: + + `jsonschema.exceptions.ValidationError`: + + if the instance is invalid + + >>> schema = {"maxItems" : 2} + >>> Draft202012Validator(schema).validate([2, 3, 4]) + Traceback (most recent call last): + ... + ValidationError: [2, 3, 4] is too long + + """ + + def evolve(self, **kwargs) -> Validator: + """ + Create a new validator like this one, but with given changes. + + Preserves all other attributes, so can be used to e.g. create a + validator with a different schema but with the same :kw:`$ref` + resolution behavior. + + >>> validator = Draft202012Validator({}) + >>> validator.evolve(schema={"type": "number"}) + Draft202012Validator(schema={'type': 'number'}, format_checker=None) + + The returned object satisfies the validator protocol, but may not + be of the same concrete class! In particular this occurs + when a :kw:`$ref` occurs to a schema with a different + :kw:`$schema` than this one (i.e. for a different draft). + + >>> validator.evolve( + ... schema={"$schema": Draft7Validator.META_SCHEMA["$id"]} + ... ) + Draft7Validator(schema=..., format_checker=None) + """ diff --git a/.venv/lib/python3.10/site-packages/jsonschema/tests/__init__.py b/.venv/lib/python3.10/site-packages/jsonschema/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/.venv/lib/python3.10/site-packages/jsonschema/tests/_suite.py b/.venv/lib/python3.10/site-packages/jsonschema/tests/_suite.py new file mode 100644 index 0000000..0da6503 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/tests/_suite.py @@ -0,0 +1,276 @@ +""" +Python representations of the JSON Schema Test Suite tests. +""" +from __future__ import annotations + +from contextlib import suppress +from functools import partial +from pathlib import Path +from typing import TYPE_CHECKING, Any +import json +import os +import re +import subprocess +import sys +import unittest + +from attrs import field, frozen +from referencing import Registry +import referencing.jsonschema + +if TYPE_CHECKING: + from collections.abc import Iterable, Mapping, Sequence + + import pyperf + +from jsonschema.validators import _VALIDATORS +import jsonschema + +_DELIMITERS = re.compile(r"[\W\- ]+") + + +def _find_suite(): + root = os.environ.get("JSON_SCHEMA_TEST_SUITE") + if root is not None: + return Path(root) + + root = Path(jsonschema.__file__).parent.parent / "json" + if not root.is_dir(): # pragma: no cover + raise ValueError( + ( + "Can't find the JSON-Schema-Test-Suite directory. " + "Set the 'JSON_SCHEMA_TEST_SUITE' environment " + "variable or run the tests from alongside a checkout " + "of the suite." + ), + ) + return root + + +@frozen +class Suite: + + _root: Path = field(factory=_find_suite) + _remotes: referencing.jsonschema.SchemaRegistry = field(init=False) + + def __attrs_post_init__(self): + jsonschema_suite = self._root.joinpath("bin", "jsonschema_suite") + argv = [sys.executable, str(jsonschema_suite), "remotes"] + remotes = subprocess.check_output(argv).decode("utf-8") + + resources = json.loads(remotes) + + li = "http://localhost:1234/locationIndependentIdentifierPre2019.json" + li4 = "http://localhost:1234/locationIndependentIdentifierDraft4.json" + + registry = Registry().with_resources( + [ + ( + li, + referencing.jsonschema.DRAFT7.create_resource( + contents=resources.pop(li), + ), + ), + ( + li4, + referencing.jsonschema.DRAFT4.create_resource( + contents=resources.pop(li4), + ), + ), + ], + ).with_contents( + resources.items(), + default_specification=referencing.jsonschema.DRAFT202012, + ) + object.__setattr__(self, "_remotes", registry) + + def benchmark(self, runner: pyperf.Runner): # pragma: no cover + for name, Validator in _VALIDATORS.items(): + self.version(name=name).benchmark( + runner=runner, + Validator=Validator, + ) + + def version(self, name) -> Version: + return Version( + name=name, + path=self._root / "tests" / name, + remotes=self._remotes, + ) + + +@frozen +class Version: + + _path: Path + _remotes: referencing.jsonschema.SchemaRegistry + + name: str + + def benchmark(self, **kwargs): # pragma: no cover + for case in self.cases(): + case.benchmark(**kwargs) + + def cases(self) -> Iterable[_Case]: + return self._cases_in(paths=self._path.glob("*.json")) + + def format_cases(self) -> Iterable[_Case]: + return self._cases_in(paths=self._path.glob("optional/format/*.json")) + + def optional_cases_of(self, name: str) -> Iterable[_Case]: + return self._cases_in(paths=[self._path / "optional" / f"{name}.json"]) + + def to_unittest_testcase(self, *groups, **kwargs): + name = kwargs.pop("name", "Test" + self.name.title().replace("-", "")) + methods = { + method.__name__: method + for method in ( + test.to_unittest_method(**kwargs) + for group in groups + for case in group + for test in case.tests + ) + } + cls = type(name, (unittest.TestCase,), methods) + + # We're doing crazy things, so if they go wrong, like a function + # behaving differently on some other interpreter, just make them + # not happen. + with suppress(Exception): + cls.__module__ = _someone_save_us_the_module_of_the_caller() + + return cls + + def _cases_in(self, paths: Iterable[Path]) -> Iterable[_Case]: + for path in paths: + for case in json.loads(path.read_text(encoding="utf-8")): + yield _Case.from_dict( + case, + version=self, + subject=path.stem, + remotes=self._remotes, + ) + + +@frozen +class _Case: + + version: Version + + subject: str + description: str + schema: Mapping[str, Any] | bool + tests: list[_Test] + comment: str | None = None + specification: Sequence[dict[str, str]] = () + + @classmethod + def from_dict(cls, data, remotes, **kwargs): + data.update(kwargs) + tests = [ + _Test( + version=data["version"], + subject=data["subject"], + case_description=data["description"], + schema=data["schema"], + remotes=remotes, + **test, + ) for test in data.pop("tests") + ] + return cls(tests=tests, **data) + + def benchmark(self, runner: pyperf.Runner, **kwargs): # pragma: no cover + for test in self.tests: + runner.bench_func( + test.fully_qualified_name, + partial(test.validate_ignoring_errors, **kwargs), + ) + + +@frozen(repr=False) +class _Test: + + version: Version + + subject: str + case_description: str + description: str + + data: Any + schema: Mapping[str, Any] | bool + + valid: bool + + _remotes: referencing.jsonschema.SchemaRegistry + + comment: str | None = None + + def __repr__(self): # pragma: no cover + return f"" + + @property + def fully_qualified_name(self): # pragma: no cover + return " > ".join( # noqa: FLY002 + [ + self.version.name, + self.subject, + self.case_description, + self.description, + ], + ) + + def to_unittest_method(self, skip=lambda test: None, **kwargs): + if self.valid: + def fn(this): + self.validate(**kwargs) + else: + def fn(this): + with this.assertRaises(jsonschema.ValidationError): + self.validate(**kwargs) + + fn.__name__ = "_".join( + [ + "test", + _DELIMITERS.sub("_", self.subject), + _DELIMITERS.sub("_", self.case_description), + _DELIMITERS.sub("_", self.description), + ], + ) + reason = skip(self) + if reason is None or os.environ.get("JSON_SCHEMA_DEBUG", "0") != "0": + return fn + elif os.environ.get("JSON_SCHEMA_EXPECTED_FAILURES", "0") != "0": # pragma: no cover # noqa: E501 + return unittest.expectedFailure(fn) + else: + return unittest.skip(reason)(fn) + + def validate(self, Validator, **kwargs): + Validator.check_schema(self.schema) + validator = Validator( + schema=self.schema, + registry=self._remotes, + **kwargs, + ) + if os.environ.get("JSON_SCHEMA_DEBUG", "0") != "0": # pragma: no cover + breakpoint() # noqa: T100 + validator.validate(instance=self.data) + + def validate_ignoring_errors(self, Validator): # pragma: no cover + with suppress(jsonschema.ValidationError): + self.validate(Validator=Validator) + + +def _someone_save_us_the_module_of_the_caller(): + """ + The FQON of the module 2nd stack frames up from here. + + This is intended to allow us to dynamically return test case classes that + are indistinguishable from being defined in the module that wants them. + + Otherwise, trial will mis-print the FQON, and copy pasting it won't re-run + the class that really is running. + + Save us all, this is all so so so so so terrible. + """ + + return sys._getframe(2).f_globals["__name__"] diff --git a/.venv/lib/python3.10/site-packages/jsonschema/tests/fuzz_validate.py b/.venv/lib/python3.10/site-packages/jsonschema/tests/fuzz_validate.py new file mode 100644 index 0000000..c12e88b --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/tests/fuzz_validate.py @@ -0,0 +1,50 @@ +""" +Fuzzing setup for OSS-Fuzz. + +See https://github.com/google/oss-fuzz/tree/master/projects/jsonschema for the +other half of the setup here. +""" +import sys + +from hypothesis import given, strategies + +import jsonschema + +PRIM = strategies.one_of( + strategies.booleans(), + strategies.integers(), + strategies.floats(allow_nan=False, allow_infinity=False), + strategies.text(), +) +DICT = strategies.recursive( + base=strategies.one_of( + strategies.booleans(), + strategies.dictionaries(strategies.text(), PRIM), + ), + extend=lambda inner: strategies.dictionaries(strategies.text(), inner), +) + + +@given(obj1=DICT, obj2=DICT) +def test_schemas(obj1, obj2): + try: + jsonschema.validate(instance=obj1, schema=obj2) + except jsonschema.exceptions.ValidationError: + pass + except jsonschema.exceptions.SchemaError: + pass + + +def main(): + atheris.instrument_all() + atheris.Setup( + sys.argv, + test_schemas.hypothesis.fuzz_one_input, + enable_python_coverage=True, + ) + atheris.Fuzz() + + +if __name__ == "__main__": + import atheris + main() diff --git a/.venv/lib/python3.10/site-packages/jsonschema/tests/test_cli.py b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_cli.py new file mode 100644 index 0000000..79d2a15 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_cli.py @@ -0,0 +1,907 @@ +from contextlib import redirect_stderr, redirect_stdout +from importlib import metadata +from io import StringIO +from json import JSONDecodeError +from pathlib import Path +from textwrap import dedent +from unittest import TestCase +import json +import os +import subprocess +import sys +import tempfile +import warnings + +from jsonschema import Draft4Validator, Draft202012Validator +from jsonschema.exceptions import ( + SchemaError, + ValidationError, + _RefResolutionError, +) +from jsonschema.validators import _LATEST_VERSION, validate + +with warnings.catch_warnings(): + warnings.simplefilter("ignore") + from jsonschema import cli + + +def fake_validator(*errors): + errors = list(reversed(errors)) + + class FakeValidator: + def __init__(self, *args, **kwargs): + pass + + def iter_errors(self, instance): + if errors: + return errors.pop() + return [] # pragma: no cover + + @classmethod + def check_schema(self, schema): + pass + + return FakeValidator + + +def fake_open(all_contents): + def open(path): + contents = all_contents.get(path) + if contents is None: + raise FileNotFoundError(path) + return StringIO(contents) + return open + + +def _message_for(non_json): + try: + json.loads(non_json) + except JSONDecodeError as error: + return str(error) + else: # pragma: no cover + raise RuntimeError("Tried and failed to capture a JSON dump error.") + + +class TestCLI(TestCase): + def run_cli( + self, argv, files=None, stdin=StringIO(), exit_code=0, **override, + ): + arguments = cli.parse_args(argv) + arguments.update(override) + + self.assertFalse(hasattr(cli, "open")) + cli.open = fake_open(files or {}) + try: + stdout, stderr = StringIO(), StringIO() + actual_exit_code = cli.run( + arguments, + stdin=stdin, + stdout=stdout, + stderr=stderr, + ) + finally: + del cli.open + + self.assertEqual( + actual_exit_code, exit_code, msg=dedent( + f""" + Expected an exit code of {exit_code} != {actual_exit_code}. + + stdout: {stdout.getvalue()} + + stderr: {stderr.getvalue()} + """, + ), + ) + return stdout.getvalue(), stderr.getvalue() + + def assertOutputs(self, stdout="", stderr="", **kwargs): + self.assertEqual( + self.run_cli(**kwargs), + (dedent(stdout), dedent(stderr)), + ) + + def test_invalid_instance(self): + error = ValidationError("I am an error!", instance=12) + self.assertOutputs( + files=dict( + some_schema='{"does not": "matter since it is stubbed"}', + some_instance=json.dumps(error.instance), + ), + validator=fake_validator([error]), + + argv=["-i", "some_instance", "some_schema"], + + exit_code=1, + stderr="12: I am an error!\n", + ) + + def test_invalid_instance_pretty_output(self): + error = ValidationError("I am an error!", instance=12) + self.assertOutputs( + files=dict( + some_schema='{"does not": "matter since it is stubbed"}', + some_instance=json.dumps(error.instance), + ), + validator=fake_validator([error]), + + argv=["-i", "some_instance", "--output", "pretty", "some_schema"], + + exit_code=1, + stderr="""\ + ===[ValidationError]===(some_instance)=== + + I am an error! + ----------------------------- + """, + ) + + def test_invalid_instance_explicit_plain_output(self): + error = ValidationError("I am an error!", instance=12) + self.assertOutputs( + files=dict( + some_schema='{"does not": "matter since it is stubbed"}', + some_instance=json.dumps(error.instance), + ), + validator=fake_validator([error]), + + argv=["--output", "plain", "-i", "some_instance", "some_schema"], + + exit_code=1, + stderr="12: I am an error!\n", + ) + + def test_invalid_instance_multiple_errors(self): + instance = 12 + first = ValidationError("First error", instance=instance) + second = ValidationError("Second error", instance=instance) + + self.assertOutputs( + files=dict( + some_schema='{"does not": "matter since it is stubbed"}', + some_instance=json.dumps(instance), + ), + validator=fake_validator([first, second]), + + argv=["-i", "some_instance", "some_schema"], + + exit_code=1, + stderr="""\ + 12: First error + 12: Second error + """, + ) + + def test_invalid_instance_multiple_errors_pretty_output(self): + instance = 12 + first = ValidationError("First error", instance=instance) + second = ValidationError("Second error", instance=instance) + + self.assertOutputs( + files=dict( + some_schema='{"does not": "matter since it is stubbed"}', + some_instance=json.dumps(instance), + ), + validator=fake_validator([first, second]), + + argv=["-i", "some_instance", "--output", "pretty", "some_schema"], + + exit_code=1, + stderr="""\ + ===[ValidationError]===(some_instance)=== + + First error + ----------------------------- + ===[ValidationError]===(some_instance)=== + + Second error + ----------------------------- + """, + ) + + def test_multiple_invalid_instances(self): + first_instance = 12 + first_errors = [ + ValidationError("An error", instance=first_instance), + ValidationError("Another error", instance=first_instance), + ] + second_instance = "foo" + second_errors = [ValidationError("BOOM", instance=second_instance)] + + self.assertOutputs( + files=dict( + some_schema='{"does not": "matter since it is stubbed"}', + some_first_instance=json.dumps(first_instance), + some_second_instance=json.dumps(second_instance), + ), + validator=fake_validator(first_errors, second_errors), + + argv=[ + "-i", "some_first_instance", + "-i", "some_second_instance", + "some_schema", + ], + + exit_code=1, + stderr="""\ + 12: An error + 12: Another error + foo: BOOM + """, + ) + + def test_multiple_invalid_instances_pretty_output(self): + first_instance = 12 + first_errors = [ + ValidationError("An error", instance=first_instance), + ValidationError("Another error", instance=first_instance), + ] + second_instance = "foo" + second_errors = [ValidationError("BOOM", instance=second_instance)] + + self.assertOutputs( + files=dict( + some_schema='{"does not": "matter since it is stubbed"}', + some_first_instance=json.dumps(first_instance), + some_second_instance=json.dumps(second_instance), + ), + validator=fake_validator(first_errors, second_errors), + + argv=[ + "--output", "pretty", + "-i", "some_first_instance", + "-i", "some_second_instance", + "some_schema", + ], + + exit_code=1, + stderr="""\ + ===[ValidationError]===(some_first_instance)=== + + An error + ----------------------------- + ===[ValidationError]===(some_first_instance)=== + + Another error + ----------------------------- + ===[ValidationError]===(some_second_instance)=== + + BOOM + ----------------------------- + """, + ) + + def test_custom_error_format(self): + first_instance = 12 + first_errors = [ + ValidationError("An error", instance=first_instance), + ValidationError("Another error", instance=first_instance), + ] + second_instance = "foo" + second_errors = [ValidationError("BOOM", instance=second_instance)] + + self.assertOutputs( + files=dict( + some_schema='{"does not": "matter since it is stubbed"}', + some_first_instance=json.dumps(first_instance), + some_second_instance=json.dumps(second_instance), + ), + validator=fake_validator(first_errors, second_errors), + + argv=[ + "--error-format", ":{error.message}._-_.{error.instance}:", + "-i", "some_first_instance", + "-i", "some_second_instance", + "some_schema", + ], + + exit_code=1, + stderr=":An error._-_.12::Another error._-_.12::BOOM._-_.foo:", + ) + + def test_invalid_schema(self): + self.assertOutputs( + files=dict(some_schema='{"type": 12}'), + argv=["some_schema"], + + exit_code=1, + stderr="""\ + 12: 12 is not valid under any of the given schemas + """, + ) + + def test_invalid_schema_pretty_output(self): + schema = {"type": 12} + + with self.assertRaises(SchemaError) as e: + validate(schema=schema, instance="") + error = str(e.exception) + + self.assertOutputs( + files=dict(some_schema=json.dumps(schema)), + argv=["--output", "pretty", "some_schema"], + + exit_code=1, + stderr=( + "===[SchemaError]===(some_schema)===\n\n" + + str(error) + + "\n-----------------------------\n" + ), + ) + + def test_invalid_schema_multiple_errors(self): + self.assertOutputs( + files=dict(some_schema='{"type": 12, "items": 57}'), + argv=["some_schema"], + + exit_code=1, + stderr="""\ + 57: 57 is not of type 'object', 'boolean' + """, + ) + + def test_invalid_schema_multiple_errors_pretty_output(self): + schema = {"type": 12, "items": 57} + + with self.assertRaises(SchemaError) as e: + validate(schema=schema, instance="") + error = str(e.exception) + + self.assertOutputs( + files=dict(some_schema=json.dumps(schema)), + argv=["--output", "pretty", "some_schema"], + + exit_code=1, + stderr=( + "===[SchemaError]===(some_schema)===\n\n" + + str(error) + + "\n-----------------------------\n" + ), + ) + + def test_invalid_schema_with_invalid_instance(self): + """ + "Validating" an instance that's invalid under an invalid schema + just shows the schema error. + """ + self.assertOutputs( + files=dict( + some_schema='{"type": 12, "minimum": 30}', + some_instance="13", + ), + argv=["-i", "some_instance", "some_schema"], + + exit_code=1, + stderr="""\ + 12: 12 is not valid under any of the given schemas + """, + ) + + def test_invalid_schema_with_invalid_instance_pretty_output(self): + instance, schema = 13, {"type": 12, "minimum": 30} + + with self.assertRaises(SchemaError) as e: + validate(schema=schema, instance=instance) + error = str(e.exception) + + self.assertOutputs( + files=dict( + some_schema=json.dumps(schema), + some_instance=json.dumps(instance), + ), + argv=["--output", "pretty", "-i", "some_instance", "some_schema"], + + exit_code=1, + stderr=( + "===[SchemaError]===(some_schema)===\n\n" + + str(error) + + "\n-----------------------------\n" + ), + ) + + def test_invalid_instance_continues_with_the_rest(self): + self.assertOutputs( + files=dict( + some_schema='{"minimum": 30}', + first_instance="not valid JSON!", + second_instance="12", + ), + argv=[ + "-i", "first_instance", + "-i", "second_instance", + "some_schema", + ], + + exit_code=1, + stderr="""\ + Failed to parse 'first_instance': {} + 12: 12 is less than the minimum of 30 + """.format(_message_for("not valid JSON!")), + ) + + def test_custom_error_format_applies_to_schema_errors(self): + instance, schema = 13, {"type": 12, "minimum": 30} + + with self.assertRaises(SchemaError): + validate(schema=schema, instance=instance) + + self.assertOutputs( + files=dict(some_schema=json.dumps(schema)), + + argv=[ + "--error-format", ":{error.message}._-_.{error.instance}:", + "some_schema", + ], + + exit_code=1, + stderr=":12 is not valid under any of the given schemas._-_.12:", + ) + + def test_instance_is_invalid_JSON(self): + instance = "not valid JSON!" + + self.assertOutputs( + files=dict(some_schema="{}", some_instance=instance), + argv=["-i", "some_instance", "some_schema"], + + exit_code=1, + stderr=f"""\ + Failed to parse 'some_instance': {_message_for(instance)} + """, + ) + + def test_instance_is_invalid_JSON_pretty_output(self): + stdout, stderr = self.run_cli( + files=dict( + some_schema="{}", + some_instance="not valid JSON!", + ), + + argv=["--output", "pretty", "-i", "some_instance", "some_schema"], + + exit_code=1, + ) + self.assertFalse(stdout) + self.assertIn( + "(some_instance)===\n\nTraceback (most recent call last):\n", + stderr, + ) + self.assertNotIn("some_schema", stderr) + + def test_instance_is_invalid_JSON_on_stdin(self): + instance = "not valid JSON!" + + self.assertOutputs( + files=dict(some_schema="{}"), + stdin=StringIO(instance), + + argv=["some_schema"], + + exit_code=1, + stderr=f"""\ + Failed to parse : {_message_for(instance)} + """, + ) + + def test_instance_is_invalid_JSON_on_stdin_pretty_output(self): + stdout, stderr = self.run_cli( + files=dict(some_schema="{}"), + stdin=StringIO("not valid JSON!"), + + argv=["--output", "pretty", "some_schema"], + + exit_code=1, + ) + self.assertFalse(stdout) + self.assertIn( + "()===\n\nTraceback (most recent call last):\n", + stderr, + ) + self.assertNotIn("some_schema", stderr) + + def test_schema_is_invalid_JSON(self): + schema = "not valid JSON!" + + self.assertOutputs( + files=dict(some_schema=schema), + + argv=["some_schema"], + + exit_code=1, + stderr=f"""\ + Failed to parse 'some_schema': {_message_for(schema)} + """, + ) + + def test_schema_is_invalid_JSON_pretty_output(self): + stdout, stderr = self.run_cli( + files=dict(some_schema="not valid JSON!"), + + argv=["--output", "pretty", "some_schema"], + + exit_code=1, + ) + self.assertFalse(stdout) + self.assertIn( + "(some_schema)===\n\nTraceback (most recent call last):\n", + stderr, + ) + + def test_schema_and_instance_are_both_invalid_JSON(self): + """ + Only the schema error is reported, as we abort immediately. + """ + schema, instance = "not valid JSON!", "also not valid JSON!" + self.assertOutputs( + files=dict(some_schema=schema, some_instance=instance), + + argv=["some_schema"], + + exit_code=1, + stderr=f"""\ + Failed to parse 'some_schema': {_message_for(schema)} + """, + ) + + def test_schema_and_instance_are_both_invalid_JSON_pretty_output(self): + """ + Only the schema error is reported, as we abort immediately. + """ + stdout, stderr = self.run_cli( + files=dict( + some_schema="not valid JSON!", + some_instance="also not valid JSON!", + ), + + argv=["--output", "pretty", "-i", "some_instance", "some_schema"], + + exit_code=1, + ) + self.assertFalse(stdout) + self.assertIn( + "(some_schema)===\n\nTraceback (most recent call last):\n", + stderr, + ) + self.assertNotIn("some_instance", stderr) + + def test_instance_does_not_exist(self): + self.assertOutputs( + files=dict(some_schema="{}"), + argv=["-i", "nonexisting_instance", "some_schema"], + + exit_code=1, + stderr="""\ + 'nonexisting_instance' does not exist. + """, + ) + + def test_instance_does_not_exist_pretty_output(self): + self.assertOutputs( + files=dict(some_schema="{}"), + argv=[ + "--output", "pretty", + "-i", "nonexisting_instance", + "some_schema", + ], + + exit_code=1, + stderr="""\ + ===[FileNotFoundError]===(nonexisting_instance)=== + + 'nonexisting_instance' does not exist. + ----------------------------- + """, + ) + + def test_schema_does_not_exist(self): + self.assertOutputs( + argv=["nonexisting_schema"], + + exit_code=1, + stderr="'nonexisting_schema' does not exist.\n", + ) + + def test_schema_does_not_exist_pretty_output(self): + self.assertOutputs( + argv=["--output", "pretty", "nonexisting_schema"], + + exit_code=1, + stderr="""\ + ===[FileNotFoundError]===(nonexisting_schema)=== + + 'nonexisting_schema' does not exist. + ----------------------------- + """, + ) + + def test_neither_instance_nor_schema_exist(self): + self.assertOutputs( + argv=["-i", "nonexisting_instance", "nonexisting_schema"], + + exit_code=1, + stderr="'nonexisting_schema' does not exist.\n", + ) + + def test_neither_instance_nor_schema_exist_pretty_output(self): + self.assertOutputs( + argv=[ + "--output", "pretty", + "-i", "nonexisting_instance", + "nonexisting_schema", + ], + + exit_code=1, + stderr="""\ + ===[FileNotFoundError]===(nonexisting_schema)=== + + 'nonexisting_schema' does not exist. + ----------------------------- + """, + ) + + def test_successful_validation(self): + self.assertOutputs( + files=dict(some_schema="{}", some_instance="{}"), + argv=["-i", "some_instance", "some_schema"], + stdout="", + stderr="", + ) + + def test_successful_validation_pretty_output(self): + self.assertOutputs( + files=dict(some_schema="{}", some_instance="{}"), + argv=["--output", "pretty", "-i", "some_instance", "some_schema"], + stdout="===[SUCCESS]===(some_instance)===\n", + stderr="", + ) + + def test_successful_validation_of_stdin(self): + self.assertOutputs( + files=dict(some_schema="{}"), + stdin=StringIO("{}"), + argv=["some_schema"], + stdout="", + stderr="", + ) + + def test_successful_validation_of_stdin_pretty_output(self): + self.assertOutputs( + files=dict(some_schema="{}"), + stdin=StringIO("{}"), + argv=["--output", "pretty", "some_schema"], + stdout="===[SUCCESS]===()===\n", + stderr="", + ) + + def test_successful_validation_of_just_the_schema(self): + self.assertOutputs( + files=dict(some_schema="{}", some_instance="{}"), + argv=["-i", "some_instance", "some_schema"], + stdout="", + stderr="", + ) + + def test_successful_validation_of_just_the_schema_pretty_output(self): + self.assertOutputs( + files=dict(some_schema="{}", some_instance="{}"), + argv=["--output", "pretty", "-i", "some_instance", "some_schema"], + stdout="===[SUCCESS]===(some_instance)===\n", + stderr="", + ) + + def test_successful_validation_via_explicit_base_uri(self): + ref_schema_file = tempfile.NamedTemporaryFile(delete=False) + ref_schema_file.close() + self.addCleanup(os.remove, ref_schema_file.name) + + ref_path = Path(ref_schema_file.name) + ref_path.write_text('{"definitions": {"num": {"type": "integer"}}}') + + schema = f'{{"$ref": "{ref_path.name}#/definitions/num"}}' + + self.assertOutputs( + files=dict(some_schema=schema, some_instance="1"), + argv=[ + "-i", "some_instance", + "--base-uri", ref_path.parent.as_uri() + "/", + "some_schema", + ], + stdout="", + stderr="", + ) + + def test_unsuccessful_validation_via_explicit_base_uri(self): + ref_schema_file = tempfile.NamedTemporaryFile(delete=False) + ref_schema_file.close() + self.addCleanup(os.remove, ref_schema_file.name) + + ref_path = Path(ref_schema_file.name) + ref_path.write_text('{"definitions": {"num": {"type": "integer"}}}') + + schema = f'{{"$ref": "{ref_path.name}#/definitions/num"}}' + + self.assertOutputs( + files=dict(some_schema=schema, some_instance='"1"'), + argv=[ + "-i", "some_instance", + "--base-uri", ref_path.parent.as_uri() + "/", + "some_schema", + ], + exit_code=1, + stdout="", + stderr="1: '1' is not of type 'integer'\n", + ) + + def test_nonexistent_file_with_explicit_base_uri(self): + schema = '{"$ref": "someNonexistentFile.json#definitions/num"}' + instance = "1" + + with self.assertRaises(_RefResolutionError) as e: + self.assertOutputs( + files=dict( + some_schema=schema, + some_instance=instance, + ), + argv=[ + "-i", "some_instance", + "--base-uri", Path.cwd().as_uri(), + "some_schema", + ], + ) + error = str(e.exception) + self.assertIn(f"{os.sep}someNonexistentFile.json'", error) + + def test_invalid_explicit_base_uri(self): + schema = '{"$ref": "foo.json#definitions/num"}' + instance = "1" + + with self.assertRaises(_RefResolutionError) as e: + self.assertOutputs( + files=dict( + some_schema=schema, + some_instance=instance, + ), + argv=[ + "-i", "some_instance", + "--base-uri", "not@UR1", + "some_schema", + ], + ) + error = str(e.exception) + self.assertEqual( + error, "unknown url type: 'foo.json'", + ) + + def test_it_validates_using_the_latest_validator_when_unspecified(self): + # There isn't a better way now I can think of to ensure that the + # latest version was used, given that the call to validator_for + # is hidden inside the CLI, so guard that that's the case, and + # this test will have to be updated when versions change until + # we can think of a better way to ensure this behavior. + self.assertIs(Draft202012Validator, _LATEST_VERSION) + + self.assertOutputs( + files=dict(some_schema='{"const": "check"}', some_instance='"a"'), + argv=["-i", "some_instance", "some_schema"], + exit_code=1, + stdout="", + stderr="a: 'check' was expected\n", + ) + + def test_it_validates_using_draft7_when_specified(self): + """ + Specifically, `const` validation applies for Draft 7. + """ + schema = """ + { + "$schema": "http://json-schema.org/draft-07/schema#", + "const": "check" + } + """ + instance = '"foo"' + self.assertOutputs( + files=dict(some_schema=schema, some_instance=instance), + argv=["-i", "some_instance", "some_schema"], + exit_code=1, + stdout="", + stderr="foo: 'check' was expected\n", + ) + + def test_it_validates_using_draft4_when_specified(self): + """ + Specifically, `const` validation *does not* apply for Draft 4. + """ + schema = """ + { + "$schema": "http://json-schema.org/draft-04/schema#", + "const": "check" + } + """ + instance = '"foo"' + self.assertOutputs( + files=dict(some_schema=schema, some_instance=instance), + argv=["-i", "some_instance", "some_schema"], + stdout="", + stderr="", + ) + + +class TestParser(TestCase): + + FakeValidator = fake_validator() + + def test_find_validator_by_fully_qualified_object_name(self): + arguments = cli.parse_args( + [ + "--validator", + "jsonschema.tests.test_cli.TestParser.FakeValidator", + "--instance", "mem://some/instance", + "mem://some/schema", + ], + ) + self.assertIs(arguments["validator"], self.FakeValidator) + + def test_find_validator_in_jsonschema(self): + arguments = cli.parse_args( + [ + "--validator", "Draft4Validator", + "--instance", "mem://some/instance", + "mem://some/schema", + ], + ) + self.assertIs(arguments["validator"], Draft4Validator) + + def cli_output_for(self, *argv): + stdout, stderr = StringIO(), StringIO() + with redirect_stdout(stdout), redirect_stderr(stderr): # noqa: SIM117 + with self.assertRaises(SystemExit): + cli.parse_args(argv) + return stdout.getvalue(), stderr.getvalue() + + def test_unknown_output(self): + stdout, stderr = self.cli_output_for( + "--output", "foo", + "mem://some/schema", + ) + self.assertIn("invalid choice: 'foo'", stderr) + self.assertFalse(stdout) + + def test_useless_error_format(self): + stdout, stderr = self.cli_output_for( + "--output", "pretty", + "--error-format", "foo", + "mem://some/schema", + ) + self.assertIn( + "--error-format can only be used with --output plain", + stderr, + ) + self.assertFalse(stdout) + + +class TestCLIIntegration(TestCase): + def test_license(self): + output = subprocess.check_output( + [sys.executable, "-m", "pip", "show", "jsonschema"], + stderr=subprocess.STDOUT, + ) + self.assertIn(b"License: MIT", output) + + def test_version(self): + version = subprocess.check_output( + [sys.executable, "-W", "ignore", "-m", "jsonschema", "--version"], + stderr=subprocess.STDOUT, + ) + version = version.decode("utf-8").strip() + self.assertEqual(version, metadata.version("jsonschema")) + + def test_no_arguments_shows_usage_notes(self): + output = subprocess.check_output( + [sys.executable, "-m", "jsonschema"], + stderr=subprocess.STDOUT, + ) + output_for_help = subprocess.check_output( + [sys.executable, "-m", "jsonschema", "--help"], + stderr=subprocess.STDOUT, + ) + self.assertEqual(output, output_for_help) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/tests/test_deprecations.py b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_deprecations.py new file mode 100644 index 0000000..aea922d --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_deprecations.py @@ -0,0 +1,432 @@ +from contextlib import contextmanager +from io import BytesIO +from unittest import TestCase, mock +import importlib.metadata +import json +import subprocess +import sys +import urllib.request + +import referencing.exceptions + +from jsonschema import FormatChecker, exceptions, protocols, validators + + +class TestDeprecations(TestCase): + def test_version(self): + """ + As of v4.0.0, __version__ is deprecated in favor of importlib.metadata. + """ + + message = "Accessing jsonschema.__version__ is deprecated" + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema import __version__ + + self.assertEqual(__version__, importlib.metadata.version("jsonschema")) + self.assertEqual(w.filename, __file__) + + def test_validators_ErrorTree(self): + """ + As of v4.0.0, importing ErrorTree from jsonschema.validators is + deprecated in favor of doing so from jsonschema.exceptions. + """ + + message = "Importing ErrorTree from jsonschema.validators is " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema.validators import ErrorTree + + self.assertEqual(ErrorTree, exceptions.ErrorTree) + self.assertEqual(w.filename, __file__) + + def test_import_ErrorTree(self): + """ + As of v4.18.0, importing ErrorTree from the package root is + deprecated in favor of doing so from jsonschema.exceptions. + """ + + message = "Importing ErrorTree directly from the jsonschema package " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema import ErrorTree + + self.assertEqual(ErrorTree, exceptions.ErrorTree) + self.assertEqual(w.filename, __file__) + + def test_ErrorTree_setitem(self): + """ + As of v4.20.0, setting items on an ErrorTree is deprecated. + """ + + e = exceptions.ValidationError("some error", path=["foo"]) + tree = exceptions.ErrorTree() + subtree = exceptions.ErrorTree(errors=[e]) + + message = "ErrorTree.__setitem__ is " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + tree["foo"] = subtree + + self.assertEqual(tree["foo"], subtree) + self.assertEqual(w.filename, __file__) + + def test_import_FormatError(self): + """ + As of v4.18.0, importing FormatError from the package root is + deprecated in favor of doing so from jsonschema.exceptions. + """ + + message = "Importing FormatError directly from the jsonschema package " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema import FormatError + + self.assertEqual(FormatError, exceptions.FormatError) + self.assertEqual(w.filename, __file__) + + def test_import_Validator(self): + """ + As of v4.19.0, importing Validator from the package root is + deprecated in favor of doing so from jsonschema.protocols. + """ + + message = "Importing Validator directly from the jsonschema package " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema import Validator + + self.assertEqual(Validator, protocols.Validator) + self.assertEqual(w.filename, __file__) + + def test_validators_validators(self): + """ + As of v4.0.0, accessing jsonschema.validators.validators is + deprecated. + """ + + message = "Accessing jsonschema.validators.validators is deprecated" + with self.assertWarnsRegex(DeprecationWarning, message) as w: + value = validators.validators + + self.assertEqual(value, validators._VALIDATORS) + self.assertEqual(w.filename, __file__) + + def test_validators_meta_schemas(self): + """ + As of v4.0.0, accessing jsonschema.validators.meta_schemas is + deprecated. + """ + + message = "Accessing jsonschema.validators.meta_schemas is deprecated" + with self.assertWarnsRegex(DeprecationWarning, message) as w: + value = validators.meta_schemas + + self.assertEqual(value, validators._META_SCHEMAS) + self.assertEqual(w.filename, __file__) + + def test_RefResolver_in_scope(self): + """ + As of v4.0.0, RefResolver.in_scope is deprecated. + """ + + resolver = validators._RefResolver.from_schema({}) + message = "jsonschema.RefResolver.in_scope is deprecated " + with self.assertWarnsRegex(DeprecationWarning, message) as w: # noqa: SIM117 + with resolver.in_scope("foo"): + pass + + self.assertEqual(w.filename, __file__) + + def test_Validator_is_valid_two_arguments(self): + """ + As of v4.0.0, calling is_valid with two arguments (to provide a + different schema) is deprecated. + """ + + validator = validators.Draft7Validator({}) + message = "Passing a schema to Validator.is_valid is deprecated " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + result = validator.is_valid("foo", {"type": "number"}) + + self.assertFalse(result) + self.assertEqual(w.filename, __file__) + + def test_Validator_iter_errors_two_arguments(self): + """ + As of v4.0.0, calling iter_errors with two arguments (to provide a + different schema) is deprecated. + """ + + validator = validators.Draft7Validator({}) + message = "Passing a schema to Validator.iter_errors is deprecated " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + error, = validator.iter_errors("foo", {"type": "number"}) + + self.assertEqual(error.validator, "type") + self.assertEqual(w.filename, __file__) + + def test_Validator_resolver(self): + """ + As of v4.18.0, accessing Validator.resolver is deprecated. + """ + + validator = validators.Draft7Validator({}) + message = "Accessing Draft7Validator.resolver is " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + self.assertIsInstance(validator.resolver, validators._RefResolver) + + self.assertEqual(w.filename, __file__) + + def test_RefResolver(self): + """ + As of v4.18.0, RefResolver is fully deprecated. + """ + + message = "jsonschema.RefResolver is deprecated" + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema import RefResolver + self.assertEqual(w.filename, __file__) + + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema.validators import RefResolver # noqa: F401, F811 + self.assertEqual(w.filename, __file__) + + def test_RefResolutionError(self): + """ + As of v4.18.0, RefResolutionError is deprecated in favor of directly + catching errors from the referencing library. + """ + + message = "jsonschema.exceptions.RefResolutionError is deprecated" + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema import RefResolutionError + + self.assertEqual(RefResolutionError, exceptions._RefResolutionError) + self.assertEqual(w.filename, __file__) + + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema.exceptions import RefResolutionError + + self.assertEqual(RefResolutionError, exceptions._RefResolutionError) + self.assertEqual(w.filename, __file__) + + def test_catching_Unresolvable_directly(self): + """ + This behavior is the intended behavior (i.e. it's not deprecated), but + given we do "tricksy" things in the iterim to wrap exceptions in a + multiple inheritance subclass, we need to be extra sure it works and + stays working. + """ + validator = validators.Draft202012Validator({"$ref": "urn:nothing"}) + + with self.assertRaises(referencing.exceptions.Unresolvable) as e: + validator.validate(12) + + expected = referencing.exceptions.Unresolvable(ref="urn:nothing") + self.assertEqual( + (e.exception, str(e.exception)), + (expected, "Unresolvable: urn:nothing"), + ) + + def test_catching_Unresolvable_via_RefResolutionError(self): + """ + Until RefResolutionError is removed, it is still possible to catch + exceptions from reference resolution using it, even though they may + have been raised by referencing. + """ + with self.assertWarns(DeprecationWarning): + from jsonschema import RefResolutionError + + validator = validators.Draft202012Validator({"$ref": "urn:nothing"}) + + with self.assertRaises(referencing.exceptions.Unresolvable) as u: + validator.validate(12) + + with self.assertRaises(RefResolutionError) as e: + validator.validate(12) + + self.assertEqual( + (e.exception, str(e.exception)), + (u.exception, "Unresolvable: urn:nothing"), + ) + + def test_WrappedReferencingError_hashability(self): + """ + Ensure the wrapped referencing errors are hashable when possible. + """ + with self.assertWarns(DeprecationWarning): + from jsonschema import RefResolutionError + + validator = validators.Draft202012Validator({"$ref": "urn:nothing"}) + + with self.assertRaises(referencing.exceptions.Unresolvable) as u: + validator.validate(12) + + with self.assertRaises(RefResolutionError) as e: + validator.validate(12) + + self.assertIn(e.exception, {u.exception}) + self.assertIn(u.exception, {e.exception}) + + def test_Validator_subclassing(self): + """ + As of v4.12.0, subclassing a validator class produces an explicit + deprecation warning. + + This was never intended to be public API (and some comments over the + years in issues said so, but obviously that's not a great way to make + sure it's followed). + + A future version will explicitly raise an error. + """ + + message = "Subclassing validator classes is " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + class Subclass(validators.Draft202012Validator): + pass + + self.assertEqual(w.filename, __file__) + + with self.assertWarnsRegex(DeprecationWarning, message) as w: + class AnotherSubclass(validators.create(meta_schema={})): + pass + + def test_FormatChecker_cls_checks(self): + """ + As of v4.14.0, FormatChecker.cls_checks is deprecated without + replacement. + """ + + self.addCleanup(FormatChecker.checkers.pop, "boom", None) + + message = "FormatChecker.cls_checks " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + FormatChecker.cls_checks("boom") + + self.assertEqual(w.filename, __file__) + + def test_draftN_format_checker(self): + """ + As of v4.16.0, accessing jsonschema.draftn_format_checker is deprecated + in favor of Validator.FORMAT_CHECKER. + """ + + message = "Accessing jsonschema.draft202012_format_checker is " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema import draft202012_format_checker + + self.assertIs( + draft202012_format_checker, + validators.Draft202012Validator.FORMAT_CHECKER, + ) + self.assertEqual(w.filename, __file__) + + message = "Accessing jsonschema.draft201909_format_checker is " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema import draft201909_format_checker + + self.assertIs( + draft201909_format_checker, + validators.Draft201909Validator.FORMAT_CHECKER, + ) + self.assertEqual(w.filename, __file__) + + message = "Accessing jsonschema.draft7_format_checker is " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema import draft7_format_checker + + self.assertIs( + draft7_format_checker, + validators.Draft7Validator.FORMAT_CHECKER, + ) + self.assertEqual(w.filename, __file__) + + message = "Accessing jsonschema.draft6_format_checker is " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema import draft6_format_checker + + self.assertIs( + draft6_format_checker, + validators.Draft6Validator.FORMAT_CHECKER, + ) + self.assertEqual(w.filename, __file__) + + message = "Accessing jsonschema.draft4_format_checker is " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema import draft4_format_checker + + self.assertIs( + draft4_format_checker, + validators.Draft4Validator.FORMAT_CHECKER, + ) + self.assertEqual(w.filename, __file__) + + message = "Accessing jsonschema.draft3_format_checker is " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + from jsonschema import draft3_format_checker + + self.assertIs( + draft3_format_checker, + validators.Draft3Validator.FORMAT_CHECKER, + ) + self.assertEqual(w.filename, __file__) + + with self.assertRaises(ImportError): + from jsonschema import draft1234_format_checker # noqa: F401 + + def test_import_cli(self): + """ + As of v4.17.0, importing jsonschema.cli is deprecated. + """ + + message = "The jsonschema CLI is deprecated and will be removed " + with self.assertWarnsRegex(DeprecationWarning, message) as w: + import jsonschema.cli + importlib.reload(jsonschema.cli) + + self.assertEqual(w.filename, importlib.__file__) + + def test_cli(self): + """ + As of v4.17.0, the jsonschema CLI is deprecated. + """ + + process = subprocess.run( + [sys.executable, "-m", "jsonschema"], + capture_output=True, + check=True, + ) + self.assertIn(b"The jsonschema CLI is deprecated ", process.stderr) + + def test_automatic_remote_retrieval(self): + """ + Automatic retrieval of remote references is deprecated as of v4.18.0. + """ + ref = "http://bar#/$defs/baz" + schema = {"$defs": {"baz": {"type": "integer"}}} + + if "requests" in sys.modules: # pragma: no cover + self.addCleanup( + sys.modules.__setitem__, "requests", sys.modules["requests"], + ) + sys.modules["requests"] = None + + @contextmanager + def fake_urlopen(request): + self.assertIsInstance(request, urllib.request.Request) + self.assertEqual(request.full_url, "http://bar") + + # Ha ha urllib.request.Request "normalizes" header names and + # Request.get_header does not also normalize them... + (header, value), = request.header_items() + self.assertEqual(header.lower(), "user-agent") + self.assertEqual( + value, "python-jsonschema (deprecated $ref resolution)", + ) + yield BytesIO(json.dumps(schema).encode("utf8")) + + validator = validators.Draft202012Validator({"$ref": ref}) + + message = "Automatically retrieving remote references " + patch = mock.patch.object(urllib.request, "urlopen", new=fake_urlopen) + + with patch, self.assertWarnsRegex(DeprecationWarning, message): + self.assertEqual( + (validator.is_valid({}), validator.is_valid(37)), + (False, True), + ) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/tests/test_exceptions.py b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_exceptions.py new file mode 100644 index 0000000..69114e1 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_exceptions.py @@ -0,0 +1,702 @@ +from unittest import TestCase +import textwrap + +from jsonschema import exceptions +from jsonschema.validators import _LATEST_VERSION + + +class TestBestMatch(TestCase): + def best_match_of(self, instance, schema): + errors = list(_LATEST_VERSION(schema).iter_errors(instance)) + msg = f"No errors found for {instance} under {schema!r}!" + self.assertTrue(errors, msg=msg) + + best = exceptions.best_match(iter(errors)) + reversed_best = exceptions.best_match(reversed(errors)) + + self.assertEqual( + best._contents(), + reversed_best._contents(), + f"No consistent best match!\nGot: {best}\n\nThen: {reversed_best}", + ) + return best + + def test_shallower_errors_are_better_matches(self): + schema = { + "properties": { + "foo": { + "minProperties": 2, + "properties": {"bar": {"type": "object"}}, + }, + }, + } + best = self.best_match_of(instance={"foo": {"bar": []}}, schema=schema) + self.assertEqual(best.validator, "minProperties") + + def test_oneOf_and_anyOf_are_weak_matches(self): + """ + A property you *must* match is probably better than one you have to + match a part of. + """ + + schema = { + "minProperties": 2, + "anyOf": [{"type": "string"}, {"type": "number"}], + "oneOf": [{"type": "string"}, {"type": "number"}], + } + best = self.best_match_of(instance={}, schema=schema) + self.assertEqual(best.validator, "minProperties") + + def test_if_the_most_relevant_error_is_anyOf_it_is_traversed(self): + """ + If the most relevant error is an anyOf, then we traverse its context + and select the otherwise *least* relevant error, since in this case + that means the most specific, deep, error inside the instance. + + I.e. since only one of the schemas must match, we look for the most + relevant one. + """ + + schema = { + "properties": { + "foo": { + "anyOf": [ + {"type": "string"}, + {"properties": {"bar": {"type": "array"}}}, + ], + }, + }, + } + best = self.best_match_of(instance={"foo": {"bar": 12}}, schema=schema) + self.assertEqual(best.validator_value, "array") + + def test_no_anyOf_traversal_for_equally_relevant_errors(self): + """ + We don't traverse into an anyOf (as above) if all of its context errors + seem to be equally "wrong" against the instance. + """ + + schema = { + "anyOf": [ + {"type": "string"}, + {"type": "integer"}, + {"type": "object"}, + ], + } + best = self.best_match_of(instance=[], schema=schema) + self.assertEqual(best.validator, "anyOf") + + def test_anyOf_traversal_for_single_equally_relevant_error(self): + """ + We *do* traverse anyOf with a single nested error, even though it is + vacuously equally relevant to itself. + """ + + schema = { + "anyOf": [ + {"type": "string"}, + ], + } + best = self.best_match_of(instance=[], schema=schema) + self.assertEqual(best.validator, "type") + + def test_anyOf_traversal_for_single_sibling_errors(self): + """ + We *do* traverse anyOf with a single subschema that fails multiple + times (e.g. on multiple items). + """ + + schema = { + "anyOf": [ + {"items": {"const": 37}}, + ], + } + best = self.best_match_of(instance=[12, 12], schema=schema) + self.assertEqual(best.validator, "const") + + def test_anyOf_traversal_for_non_type_matching_sibling_errors(self): + """ + We *do* traverse anyOf with multiple subschemas when one does not type + match. + """ + + schema = { + "anyOf": [ + {"type": "object"}, + {"items": {"const": 37}}, + ], + } + best = self.best_match_of(instance=[12, 12], schema=schema) + self.assertEqual(best.validator, "const") + + def test_if_the_most_relevant_error_is_oneOf_it_is_traversed(self): + """ + If the most relevant error is an oneOf, then we traverse its context + and select the otherwise *least* relevant error, since in this case + that means the most specific, deep, error inside the instance. + + I.e. since only one of the schemas must match, we look for the most + relevant one. + """ + + schema = { + "properties": { + "foo": { + "oneOf": [ + {"type": "string"}, + {"properties": {"bar": {"type": "array"}}}, + ], + }, + }, + } + best = self.best_match_of(instance={"foo": {"bar": 12}}, schema=schema) + self.assertEqual(best.validator_value, "array") + + def test_no_oneOf_traversal_for_equally_relevant_errors(self): + """ + We don't traverse into an oneOf (as above) if all of its context errors + seem to be equally "wrong" against the instance. + """ + + schema = { + "oneOf": [ + {"type": "string"}, + {"type": "integer"}, + {"type": "object"}, + ], + } + best = self.best_match_of(instance=[], schema=schema) + self.assertEqual(best.validator, "oneOf") + + def test_oneOf_traversal_for_single_equally_relevant_error(self): + """ + We *do* traverse oneOf with a single nested error, even though it is + vacuously equally relevant to itself. + """ + + schema = { + "oneOf": [ + {"type": "string"}, + ], + } + best = self.best_match_of(instance=[], schema=schema) + self.assertEqual(best.validator, "type") + + def test_oneOf_traversal_for_single_sibling_errors(self): + """ + We *do* traverse oneOf with a single subschema that fails multiple + times (e.g. on multiple items). + """ + + schema = { + "oneOf": [ + {"items": {"const": 37}}, + ], + } + best = self.best_match_of(instance=[12, 12], schema=schema) + self.assertEqual(best.validator, "const") + + def test_oneOf_traversal_for_non_type_matching_sibling_errors(self): + """ + We *do* traverse oneOf with multiple subschemas when one does not type + match. + """ + + schema = { + "oneOf": [ + {"type": "object"}, + {"items": {"const": 37}}, + ], + } + best = self.best_match_of(instance=[12, 12], schema=schema) + self.assertEqual(best.validator, "const") + + def test_if_the_most_relevant_error_is_allOf_it_is_traversed(self): + """ + Now, if the error is allOf, we traverse but select the *most* relevant + error from the context, because all schemas here must match anyways. + """ + + schema = { + "properties": { + "foo": { + "allOf": [ + {"type": "string"}, + {"properties": {"bar": {"type": "array"}}}, + ], + }, + }, + } + best = self.best_match_of(instance={"foo": {"bar": 12}}, schema=schema) + self.assertEqual(best.validator_value, "string") + + def test_nested_context_for_oneOf(self): + """ + We traverse into nested contexts (a oneOf containing an error in a + nested oneOf here). + """ + + schema = { + "properties": { + "foo": { + "oneOf": [ + {"type": "string"}, + { + "oneOf": [ + {"type": "string"}, + { + "properties": { + "bar": {"type": "array"}, + }, + }, + ], + }, + ], + }, + }, + } + best = self.best_match_of(instance={"foo": {"bar": 12}}, schema=schema) + self.assertEqual(best.validator_value, "array") + + def test_it_prioritizes_matching_types(self): + schema = { + "properties": { + "foo": { + "anyOf": [ + {"type": "array", "minItems": 2}, + {"type": "string", "minLength": 10}, + ], + }, + }, + } + best = self.best_match_of(instance={"foo": "bar"}, schema=schema) + self.assertEqual(best.validator, "minLength") + + reordered = { + "properties": { + "foo": { + "anyOf": [ + {"type": "string", "minLength": 10}, + {"type": "array", "minItems": 2}, + ], + }, + }, + } + best = self.best_match_of(instance={"foo": "bar"}, schema=reordered) + self.assertEqual(best.validator, "minLength") + + def test_it_prioritizes_matching_union_types(self): + schema = { + "properties": { + "foo": { + "anyOf": [ + {"type": ["array", "object"], "minItems": 2}, + {"type": ["integer", "string"], "minLength": 10}, + ], + }, + }, + } + best = self.best_match_of(instance={"foo": "bar"}, schema=schema) + self.assertEqual(best.validator, "minLength") + + reordered = { + "properties": { + "foo": { + "anyOf": [ + {"type": "string", "minLength": 10}, + {"type": "array", "minItems": 2}, + ], + }, + }, + } + best = self.best_match_of(instance={"foo": "bar"}, schema=reordered) + self.assertEqual(best.validator, "minLength") + + def test_boolean_schemas(self): + schema = {"properties": {"foo": False}} + best = self.best_match_of(instance={"foo": "bar"}, schema=schema) + self.assertIsNone(best.validator) + + def test_one_error(self): + validator = _LATEST_VERSION({"minProperties": 2}) + error, = validator.iter_errors({}) + self.assertEqual( + exceptions.best_match(validator.iter_errors({})).validator, + "minProperties", + ) + + def test_no_errors(self): + validator = _LATEST_VERSION({}) + self.assertIsNone(exceptions.best_match(validator.iter_errors({}))) + + +class TestByRelevance(TestCase): + def test_short_paths_are_better_matches(self): + shallow = exceptions.ValidationError("Oh no!", path=["baz"]) + deep = exceptions.ValidationError("Oh yes!", path=["foo", "bar"]) + match = max([shallow, deep], key=exceptions.relevance) + self.assertIs(match, shallow) + + match = max([deep, shallow], key=exceptions.relevance) + self.assertIs(match, shallow) + + def test_global_errors_are_even_better_matches(self): + shallow = exceptions.ValidationError("Oh no!", path=[]) + deep = exceptions.ValidationError("Oh yes!", path=["foo"]) + + errors = sorted([shallow, deep], key=exceptions.relevance) + self.assertEqual( + [list(error.path) for error in errors], + [["foo"], []], + ) + + errors = sorted([deep, shallow], key=exceptions.relevance) + self.assertEqual( + [list(error.path) for error in errors], + [["foo"], []], + ) + + def test_weak_keywords_are_lower_priority(self): + weak = exceptions.ValidationError("Oh no!", path=[], validator="a") + normal = exceptions.ValidationError("Oh yes!", path=[], validator="b") + + best_match = exceptions.by_relevance(weak="a") + + match = max([weak, normal], key=best_match) + self.assertIs(match, normal) + + match = max([normal, weak], key=best_match) + self.assertIs(match, normal) + + def test_strong_keywords_are_higher_priority(self): + weak = exceptions.ValidationError("Oh no!", path=[], validator="a") + normal = exceptions.ValidationError("Oh yes!", path=[], validator="b") + strong = exceptions.ValidationError("Oh fine!", path=[], validator="c") + + best_match = exceptions.by_relevance(weak="a", strong="c") + + match = max([weak, normal, strong], key=best_match) + self.assertIs(match, strong) + + match = max([strong, normal, weak], key=best_match) + self.assertIs(match, strong) + + +class TestErrorTree(TestCase): + def test_it_knows_how_many_total_errors_it_contains(self): + # FIXME: #442 + errors = [ + exceptions.ValidationError("Something", validator=i) + for i in range(8) + ] + tree = exceptions.ErrorTree(errors) + self.assertEqual(tree.total_errors, 8) + + def test_it_contains_an_item_if_the_item_had_an_error(self): + errors = [exceptions.ValidationError("a message", path=["bar"])] + tree = exceptions.ErrorTree(errors) + self.assertIn("bar", tree) + + def test_it_does_not_contain_an_item_if_the_item_had_no_error(self): + errors = [exceptions.ValidationError("a message", path=["bar"])] + tree = exceptions.ErrorTree(errors) + self.assertNotIn("foo", tree) + + def test_keywords_that_failed_appear_in_errors_dict(self): + error = exceptions.ValidationError("a message", validator="foo") + tree = exceptions.ErrorTree([error]) + self.assertEqual(tree.errors, {"foo": error}) + + def test_it_creates_a_child_tree_for_each_nested_path(self): + errors = [ + exceptions.ValidationError("a bar message", path=["bar"]), + exceptions.ValidationError("a bar -> 0 message", path=["bar", 0]), + ] + tree = exceptions.ErrorTree(errors) + self.assertIn(0, tree["bar"]) + self.assertNotIn(1, tree["bar"]) + + def test_children_have_their_errors_dicts_built(self): + e1, e2 = ( + exceptions.ValidationError("1", validator="foo", path=["bar", 0]), + exceptions.ValidationError("2", validator="quux", path=["bar", 0]), + ) + tree = exceptions.ErrorTree([e1, e2]) + self.assertEqual(tree["bar"][0].errors, {"foo": e1, "quux": e2}) + + def test_multiple_errors_with_instance(self): + e1, e2 = ( + exceptions.ValidationError( + "1", + validator="foo", + path=["bar", "bar2"], + instance="i1"), + exceptions.ValidationError( + "2", + validator="quux", + path=["foobar", 2], + instance="i2"), + ) + exceptions.ErrorTree([e1, e2]) + + def test_it_does_not_contain_subtrees_that_are_not_in_the_instance(self): + error = exceptions.ValidationError("123", validator="foo", instance=[]) + tree = exceptions.ErrorTree([error]) + + with self.assertRaises(IndexError): + tree[0] + + def test_if_its_in_the_tree_anyhow_it_does_not_raise_an_error(self): + """ + If a keyword refers to a path that isn't in the instance, the + tree still properly returns a subtree for that path. + """ + + error = exceptions.ValidationError( + "a message", validator="foo", instance={}, path=["foo"], + ) + tree = exceptions.ErrorTree([error]) + self.assertIsInstance(tree["foo"], exceptions.ErrorTree) + + def test_iter(self): + e1, e2 = ( + exceptions.ValidationError( + "1", + validator="foo", + path=["bar", "bar2"], + instance="i1"), + exceptions.ValidationError( + "2", + validator="quux", + path=["foobar", 2], + instance="i2"), + ) + tree = exceptions.ErrorTree([e1, e2]) + self.assertEqual(set(tree), {"bar", "foobar"}) + + def test_repr_single(self): + error = exceptions.ValidationError( + "1", + validator="foo", + path=["bar", "bar2"], + instance="i1", + ) + tree = exceptions.ErrorTree([error]) + self.assertEqual(repr(tree), "") + + def test_repr_multiple(self): + e1, e2 = ( + exceptions.ValidationError( + "1", + validator="foo", + path=["bar", "bar2"], + instance="i1"), + exceptions.ValidationError( + "2", + validator="quux", + path=["foobar", 2], + instance="i2"), + ) + tree = exceptions.ErrorTree([e1, e2]) + self.assertEqual(repr(tree), "") + + def test_repr_empty(self): + tree = exceptions.ErrorTree([]) + self.assertEqual(repr(tree), "") + + +class TestErrorInitReprStr(TestCase): + def make_error(self, **kwargs): + defaults = dict( + message="hello", + validator="type", + validator_value="string", + instance=5, + schema={"type": "string"}, + ) + defaults.update(kwargs) + return exceptions.ValidationError(**defaults) + + def assertShows(self, expected, **kwargs): + expected = textwrap.dedent(expected).rstrip("\n") + + error = self.make_error(**kwargs) + message_line, _, rest = str(error).partition("\n") + self.assertEqual(message_line, error.message) + self.assertEqual(rest, expected) + + def test_it_calls_super_and_sets_args(self): + error = self.make_error() + self.assertGreater(len(error.args), 1) + + def test_repr(self): + self.assertEqual( + repr(exceptions.ValidationError(message="Hello!")), + "", + ) + + def test_unset_error(self): + error = exceptions.ValidationError("message") + self.assertEqual(str(error), "message") + + kwargs = { + "validator": "type", + "validator_value": "string", + "instance": 5, + "schema": {"type": "string"}, + } + # Just the message should show if any of the attributes are unset + for attr in kwargs: + k = dict(kwargs) + del k[attr] + error = exceptions.ValidationError("message", **k) + self.assertEqual(str(error), "message") + + def test_empty_paths(self): + self.assertShows( + """ + Failed validating 'type' in schema: + {'type': 'string'} + + On instance: + 5 + """, + path=[], + schema_path=[], + ) + + def test_one_item_paths(self): + self.assertShows( + """ + Failed validating 'type' in schema: + {'type': 'string'} + + On instance[0]: + 5 + """, + path=[0], + schema_path=["items"], + ) + + def test_multiple_item_paths(self): + self.assertShows( + """ + Failed validating 'type' in schema['items'][0]: + {'type': 'string'} + + On instance[0]['a']: + 5 + """, + path=[0, "a"], + schema_path=["items", 0, 1], + ) + + def test_uses_pprint(self): + self.assertShows( + """ + Failed validating 'maxLength' in schema: + {0: 0, + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + 6: 6, + 7: 7, + 8: 8, + 9: 9, + 10: 10, + 11: 11, + 12: 12, + 13: 13, + 14: 14, + 15: 15, + 16: 16, + 17: 17, + 18: 18, + 19: 19} + + On instance: + [0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24] + """, + instance=list(range(25)), + schema=dict(zip(range(20), range(20))), + validator="maxLength", + ) + + def test_does_not_reorder_dicts(self): + self.assertShows( + """ + Failed validating 'type' in schema: + {'do': 3, 'not': 7, 'sort': 37, 'me': 73} + + On instance: + {'here': 73, 'too': 37, 'no': 7, 'sorting': 3} + """, + schema={ + "do": 3, + "not": 7, + "sort": 37, + "me": 73, + }, + instance={ + "here": 73, + "too": 37, + "no": 7, + "sorting": 3, + }, + ) + + def test_str_works_with_instances_having_overriden_eq_operator(self): + """ + Check for #164 which rendered exceptions unusable when a + `ValidationError` involved instances with an `__eq__` method + that returned truthy values. + """ + + class DontEQMeBro: + def __eq__(this, other): # pragma: no cover + self.fail("Don't!") + + def __ne__(this, other): # pragma: no cover + self.fail("Don't!") + + instance = DontEQMeBro() + error = exceptions.ValidationError( + "a message", + validator="foo", + instance=instance, + validator_value="some", + schema="schema", + ) + self.assertIn(repr(instance), str(error)) + + +class TestHashable(TestCase): + def test_hashable(self): + {exceptions.ValidationError("")} + {exceptions.SchemaError("")} diff --git a/.venv/lib/python3.10/site-packages/jsonschema/tests/test_format.py b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_format.py new file mode 100644 index 0000000..d829f98 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_format.py @@ -0,0 +1,91 @@ +""" +Tests for the parts of jsonschema related to the :kw:`format` keyword. +""" + +from unittest import TestCase + +from jsonschema import FormatChecker, ValidationError +from jsonschema.exceptions import FormatError +from jsonschema.validators import Draft4Validator + +BOOM = ValueError("Boom!") +BANG = ZeroDivisionError("Bang!") + + +def boom(thing): + if thing == "bang": + raise BANG + raise BOOM + + +class TestFormatChecker(TestCase): + def test_it_can_validate_no_formats(self): + checker = FormatChecker(formats=()) + self.assertFalse(checker.checkers) + + def test_it_raises_a_key_error_for_unknown_formats(self): + with self.assertRaises(KeyError): + FormatChecker(formats=["o noes"]) + + def test_it_can_register_cls_checkers(self): + original = dict(FormatChecker.checkers) + self.addCleanup(FormatChecker.checkers.pop, "boom") + with self.assertWarns(DeprecationWarning): + FormatChecker.cls_checks("boom")(boom) + self.assertEqual( + FormatChecker.checkers, + dict(original, boom=(boom, ())), + ) + + def test_it_can_register_checkers(self): + checker = FormatChecker() + checker.checks("boom")(boom) + self.assertEqual( + checker.checkers, + dict(FormatChecker.checkers, boom=(boom, ())), + ) + + def test_it_catches_registered_errors(self): + checker = FormatChecker() + checker.checks("boom", raises=type(BOOM))(boom) + + with self.assertRaises(FormatError) as cm: + checker.check(instance=12, format="boom") + + self.assertIs(cm.exception.cause, BOOM) + self.assertIs(cm.exception.__cause__, BOOM) + self.assertEqual(str(cm.exception), "12 is not a 'boom'") + + # Unregistered errors should not be caught + with self.assertRaises(type(BANG)): + checker.check(instance="bang", format="boom") + + def test_format_error_causes_become_validation_error_causes(self): + checker = FormatChecker() + checker.checks("boom", raises=ValueError)(boom) + validator = Draft4Validator({"format": "boom"}, format_checker=checker) + + with self.assertRaises(ValidationError) as cm: + validator.validate("BOOM") + + self.assertIs(cm.exception.cause, BOOM) + self.assertIs(cm.exception.__cause__, BOOM) + + def test_format_checkers_come_with_defaults(self): + # This is bad :/ but relied upon. + # The docs for quite awhile recommended people do things like + # validate(..., format_checker=FormatChecker()) + # We should change that, but we can't without deprecation... + checker = FormatChecker() + with self.assertRaises(FormatError): + checker.check(instance="not-an-ipv4", format="ipv4") + + def test_repr(self): + checker = FormatChecker(formats=()) + checker.checks("foo")(lambda thing: True) # pragma: no cover + checker.checks("bar")(lambda thing: True) # pragma: no cover + checker.checks("baz")(lambda thing: True) # pragma: no cover + self.assertEqual( + repr(checker), + "", + ) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/tests/test_jsonschema_test_suite.py b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_jsonschema_test_suite.py new file mode 100644 index 0000000..282c136 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_jsonschema_test_suite.py @@ -0,0 +1,269 @@ +""" +Test runner for the JSON Schema official test suite + +Tests comprehensive correctness of each draft's validator. + +See https://github.com/json-schema-org/JSON-Schema-Test-Suite for details. +""" + +import sys + +from jsonschema.tests._suite import Suite +import jsonschema + +SUITE = Suite() +DRAFT3 = SUITE.version(name="draft3") +DRAFT4 = SUITE.version(name="draft4") +DRAFT6 = SUITE.version(name="draft6") +DRAFT7 = SUITE.version(name="draft7") +DRAFT201909 = SUITE.version(name="draft2019-09") +DRAFT202012 = SUITE.version(name="draft2020-12") + + +def skip(message, **kwargs): + def skipper(test): + if all(value == getattr(test, attr) for attr, value in kwargs.items()): + return message + return skipper + + +def missing_format(Validator): + def missing_format(test): # pragma: no cover + schema = test.schema + if ( + schema is True + or schema is False + or "format" not in schema + or schema["format"] in Validator.FORMAT_CHECKER.checkers + or test.valid + ): + return + + return f"Format checker {schema['format']!r} not found." + return missing_format + + +def complex_email_validation(test): + if test.subject != "email": + return + + message = "Complex email validation is (intentionally) unsupported." + return skip( + message=message, + description="an invalid domain", + )(test) or skip( + message=message, + description="an invalid IPv4-address-literal", + )(test) or skip( + message=message, + description="dot after local part is not valid", + )(test) or skip( + message=message, + description="dot before local part is not valid", + )(test) or skip( + message=message, + description="two subsequent dots inside local part are not valid", + )(test) + + +if sys.version_info < (3, 9): # pragma: no cover + message = "Rejecting leading zeros is 3.9+" + allowed_leading_zeros = skip( + message=message, + subject="ipv4", + description="invalid leading zeroes, as they are treated as octals", + ) +else: + def allowed_leading_zeros(test): # pragma: no cover + return + + +def leap_second(test): + message = "Leap seconds are unsupported." + return skip( + message=message, + subject="time", + description="a valid time string with leap second", + )(test) or skip( + message=message, + subject="time", + description="a valid time string with leap second, Zulu", + )(test) or skip( + message=message, + subject="time", + description="a valid time string with leap second with offset", + )(test) or skip( + message=message, + subject="time", + description="valid leap second, positive time-offset", + )(test) or skip( + message=message, + subject="time", + description="valid leap second, negative time-offset", + )(test) or skip( + message=message, + subject="time", + description="valid leap second, large positive time-offset", + )(test) or skip( + message=message, + subject="time", + description="valid leap second, large negative time-offset", + )(test) or skip( + message=message, + subject="time", + description="valid leap second, zero time-offset", + )(test) or skip( + message=message, + subject="date-time", + description="a valid date-time with a leap second, UTC", + )(test) or skip( + message=message, + subject="date-time", + description="a valid date-time with a leap second, with minus offset", + )(test) + + +TestDraft3 = DRAFT3.to_unittest_testcase( + DRAFT3.cases(), + DRAFT3.format_cases(), + DRAFT3.optional_cases_of(name="bignum"), + DRAFT3.optional_cases_of(name="non-bmp-regex"), + DRAFT3.optional_cases_of(name="zeroTerminatedFloats"), + Validator=jsonschema.Draft3Validator, + format_checker=jsonschema.Draft3Validator.FORMAT_CHECKER, + skip=lambda test: ( + missing_format(jsonschema.Draft3Validator)(test) + or complex_email_validation(test) + ), +) + + +TestDraft4 = DRAFT4.to_unittest_testcase( + DRAFT4.cases(), + DRAFT4.format_cases(), + DRAFT4.optional_cases_of(name="bignum"), + DRAFT4.optional_cases_of(name="float-overflow"), + DRAFT4.optional_cases_of(name="id"), + DRAFT4.optional_cases_of(name="non-bmp-regex"), + DRAFT4.optional_cases_of(name="zeroTerminatedFloats"), + Validator=jsonschema.Draft4Validator, + format_checker=jsonschema.Draft4Validator.FORMAT_CHECKER, + skip=lambda test: ( + allowed_leading_zeros(test) + or leap_second(test) + or missing_format(jsonschema.Draft4Validator)(test) + or complex_email_validation(test) + ), +) + + +TestDraft6 = DRAFT6.to_unittest_testcase( + DRAFT6.cases(), + DRAFT6.format_cases(), + DRAFT6.optional_cases_of(name="bignum"), + DRAFT6.optional_cases_of(name="float-overflow"), + DRAFT6.optional_cases_of(name="id"), + DRAFT6.optional_cases_of(name="non-bmp-regex"), + Validator=jsonschema.Draft6Validator, + format_checker=jsonschema.Draft6Validator.FORMAT_CHECKER, + skip=lambda test: ( + allowed_leading_zeros(test) + or leap_second(test) + or missing_format(jsonschema.Draft6Validator)(test) + or complex_email_validation(test) + ), +) + + +TestDraft7 = DRAFT7.to_unittest_testcase( + DRAFT7.cases(), + DRAFT7.format_cases(), + DRAFT7.optional_cases_of(name="bignum"), + DRAFT7.optional_cases_of(name="cross-draft"), + DRAFT7.optional_cases_of(name="float-overflow"), + DRAFT6.optional_cases_of(name="id"), + DRAFT7.optional_cases_of(name="non-bmp-regex"), + DRAFT7.optional_cases_of(name="unknownKeyword"), + Validator=jsonschema.Draft7Validator, + format_checker=jsonschema.Draft7Validator.FORMAT_CHECKER, + skip=lambda test: ( + allowed_leading_zeros(test) + or leap_second(test) + or missing_format(jsonschema.Draft7Validator)(test) + or complex_email_validation(test) + ), +) + + +TestDraft201909 = DRAFT201909.to_unittest_testcase( + DRAFT201909.cases(), + DRAFT201909.optional_cases_of(name="anchor"), + DRAFT201909.optional_cases_of(name="bignum"), + DRAFT201909.optional_cases_of(name="cross-draft"), + DRAFT201909.optional_cases_of(name="float-overflow"), + DRAFT201909.optional_cases_of(name="id"), + DRAFT201909.optional_cases_of(name="no-schema"), + DRAFT201909.optional_cases_of(name="non-bmp-regex"), + DRAFT201909.optional_cases_of(name="refOfUnknownKeyword"), + DRAFT201909.optional_cases_of(name="unknownKeyword"), + Validator=jsonschema.Draft201909Validator, + skip=skip( + message="Vocabulary support is still in-progress.", + subject="vocabulary", + description=( + "no validation: invalid number, but it still validates" + ), + ), +) + + +TestDraft201909Format = DRAFT201909.to_unittest_testcase( + DRAFT201909.format_cases(), + name="TestDraft201909Format", + Validator=jsonschema.Draft201909Validator, + format_checker=jsonschema.Draft201909Validator.FORMAT_CHECKER, + skip=lambda test: ( + complex_email_validation(test) + or allowed_leading_zeros(test) + or leap_second(test) + or missing_format(jsonschema.Draft201909Validator)(test) + or complex_email_validation(test) + ), +) + + +TestDraft202012 = DRAFT202012.to_unittest_testcase( + DRAFT202012.cases(), + DRAFT201909.optional_cases_of(name="anchor"), + DRAFT202012.optional_cases_of(name="bignum"), + DRAFT202012.optional_cases_of(name="cross-draft"), + DRAFT202012.optional_cases_of(name="float-overflow"), + DRAFT202012.optional_cases_of(name="id"), + DRAFT202012.optional_cases_of(name="no-schema"), + DRAFT202012.optional_cases_of(name="non-bmp-regex"), + DRAFT202012.optional_cases_of(name="refOfUnknownKeyword"), + DRAFT202012.optional_cases_of(name="unknownKeyword"), + Validator=jsonschema.Draft202012Validator, + skip=skip( + message="Vocabulary support is still in-progress.", + subject="vocabulary", + description=( + "no validation: invalid number, but it still validates" + ), + ), +) + + +TestDraft202012Format = DRAFT202012.to_unittest_testcase( + DRAFT202012.format_cases(), + name="TestDraft202012Format", + Validator=jsonschema.Draft202012Validator, + format_checker=jsonschema.Draft202012Validator.FORMAT_CHECKER, + skip=lambda test: ( + complex_email_validation(test) + or allowed_leading_zeros(test) + or leap_second(test) + or missing_format(jsonschema.Draft202012Validator)(test) + or complex_email_validation(test) + ), +) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/tests/test_types.py b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_types.py new file mode 100644 index 0000000..bd97b18 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_types.py @@ -0,0 +1,221 @@ +""" +Tests for the `TypeChecker`-based type interface. + +The actual correctness of the type checking is handled in +`test_jsonschema_test_suite`; these tests check that TypeChecker +functions correctly at a more granular level. +""" +from collections import namedtuple +from unittest import TestCase + +from jsonschema import ValidationError, _keywords +from jsonschema._types import TypeChecker +from jsonschema.exceptions import UndefinedTypeCheck, UnknownType +from jsonschema.validators import Draft202012Validator, extend + + +def equals_2(checker, instance): + return instance == 2 + + +def is_namedtuple(instance): + return isinstance(instance, tuple) and getattr(instance, "_fields", None) + + +def is_object_or_named_tuple(checker, instance): + if Draft202012Validator.TYPE_CHECKER.is_type(instance, "object"): + return True + return is_namedtuple(instance) + + +class TestTypeChecker(TestCase): + def test_is_type(self): + checker = TypeChecker({"two": equals_2}) + self.assertEqual( + ( + checker.is_type(instance=2, type="two"), + checker.is_type(instance="bar", type="two"), + ), + (True, False), + ) + + def test_is_unknown_type(self): + with self.assertRaises(UndefinedTypeCheck) as e: + TypeChecker().is_type(4, "foobar") + self.assertIn( + "'foobar' is unknown to this type checker", + str(e.exception), + ) + self.assertTrue( + e.exception.__suppress_context__, + msg="Expected the internal KeyError to be hidden.", + ) + + def test_checks_can_be_added_at_init(self): + checker = TypeChecker({"two": equals_2}) + self.assertEqual(checker, TypeChecker().redefine("two", equals_2)) + + def test_redefine_existing_type(self): + self.assertEqual( + TypeChecker().redefine("two", object()).redefine("two", equals_2), + TypeChecker().redefine("two", equals_2), + ) + + def test_remove(self): + self.assertEqual( + TypeChecker({"two": equals_2}).remove("two"), + TypeChecker(), + ) + + def test_remove_unknown_type(self): + with self.assertRaises(UndefinedTypeCheck) as context: + TypeChecker().remove("foobar") + self.assertIn("foobar", str(context.exception)) + + def test_redefine_many(self): + self.assertEqual( + TypeChecker().redefine_many({"foo": int, "bar": str}), + TypeChecker().redefine("foo", int).redefine("bar", str), + ) + + def test_remove_multiple(self): + self.assertEqual( + TypeChecker({"foo": int, "bar": str}).remove("foo", "bar"), + TypeChecker(), + ) + + def test_type_check_can_raise_key_error(self): + """ + Make sure no one writes: + + try: + self._type_checkers[type](...) + except KeyError: + + ignoring the fact that the function itself can raise that. + """ + + error = KeyError("Stuff") + + def raises_keyerror(checker, instance): + raise error + + with self.assertRaises(KeyError) as context: + TypeChecker({"foo": raises_keyerror}).is_type(4, "foo") + + self.assertIs(context.exception, error) + + def test_repr(self): + checker = TypeChecker({"foo": is_namedtuple, "bar": is_namedtuple}) + self.assertEqual(repr(checker), "") + + +class TestCustomTypes(TestCase): + def test_simple_type_can_be_extended(self): + def int_or_str_int(checker, instance): + if not isinstance(instance, (int, str)): + return False + try: + int(instance) + except ValueError: + return False + return True + + CustomValidator = extend( + Draft202012Validator, + type_checker=Draft202012Validator.TYPE_CHECKER.redefine( + "integer", int_or_str_int, + ), + ) + validator = CustomValidator({"type": "integer"}) + + validator.validate(4) + validator.validate("4") + + with self.assertRaises(ValidationError): + validator.validate(4.4) + + with self.assertRaises(ValidationError): + validator.validate("foo") + + def test_object_can_be_extended(self): + schema = {"type": "object"} + + Point = namedtuple("Point", ["x", "y"]) + + type_checker = Draft202012Validator.TYPE_CHECKER.redefine( + "object", is_object_or_named_tuple, + ) + + CustomValidator = extend( + Draft202012Validator, + type_checker=type_checker, + ) + validator = CustomValidator(schema) + + validator.validate(Point(x=4, y=5)) + + def test_object_extensions_require_custom_validators(self): + schema = {"type": "object", "required": ["x"]} + + type_checker = Draft202012Validator.TYPE_CHECKER.redefine( + "object", is_object_or_named_tuple, + ) + + CustomValidator = extend( + Draft202012Validator, + type_checker=type_checker, + ) + validator = CustomValidator(schema) + + Point = namedtuple("Point", ["x", "y"]) + # Cannot handle required + with self.assertRaises(ValidationError): + validator.validate(Point(x=4, y=5)) + + def test_object_extensions_can_handle_custom_validators(self): + schema = { + "type": "object", + "required": ["x"], + "properties": {"x": {"type": "integer"}}, + } + + type_checker = Draft202012Validator.TYPE_CHECKER.redefine( + "object", is_object_or_named_tuple, + ) + + def coerce_named_tuple(fn): + def coerced(validator, value, instance, schema): + if is_namedtuple(instance): + instance = instance._asdict() + return fn(validator, value, instance, schema) + return coerced + + required = coerce_named_tuple(_keywords.required) + properties = coerce_named_tuple(_keywords.properties) + + CustomValidator = extend( + Draft202012Validator, + type_checker=type_checker, + validators={"required": required, "properties": properties}, + ) + + validator = CustomValidator(schema) + + Point = namedtuple("Point", ["x", "y"]) + # Can now process required and properties + validator.validate(Point(x=4, y=5)) + + with self.assertRaises(ValidationError): + validator.validate(Point(x="not an integer", y=5)) + + # As well as still handle objects. + validator.validate({"x": 4, "y": 5}) + + with self.assertRaises(ValidationError): + validator.validate({"x": "not an integer", "y": 5}) + + def test_unknown_type(self): + with self.assertRaises(UnknownType) as e: + Draft202012Validator({}).is_type(12, "some unknown type") + self.assertIn("'some unknown type'", str(e.exception)) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/tests/test_utils.py b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_utils.py new file mode 100644 index 0000000..d9764b0 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_utils.py @@ -0,0 +1,138 @@ +from math import nan +from unittest import TestCase + +from jsonschema._utils import equal + + +class TestEqual(TestCase): + def test_none(self): + self.assertTrue(equal(None, None)) + + def test_nan(self): + self.assertTrue(equal(nan, nan)) + + +class TestDictEqual(TestCase): + def test_equal_dictionaries(self): + dict_1 = {"a": "b", "c": "d"} + dict_2 = {"c": "d", "a": "b"} + self.assertTrue(equal(dict_1, dict_2)) + + def test_equal_dictionaries_with_nan(self): + dict_1 = {"a": nan, "c": "d"} + dict_2 = {"c": "d", "a": nan} + self.assertTrue(equal(dict_1, dict_2)) + + def test_missing_key(self): + dict_1 = {"a": "b", "c": "d"} + dict_2 = {"c": "d", "x": "b"} + self.assertFalse(equal(dict_1, dict_2)) + + def test_additional_key(self): + dict_1 = {"a": "b", "c": "d"} + dict_2 = {"c": "d", "a": "b", "x": "x"} + self.assertFalse(equal(dict_1, dict_2)) + + def test_missing_value(self): + dict_1 = {"a": "b", "c": "d"} + dict_2 = {"c": "d", "a": "x"} + self.assertFalse(equal(dict_1, dict_2)) + + def test_empty_dictionaries(self): + dict_1 = {} + dict_2 = {} + self.assertTrue(equal(dict_1, dict_2)) + + def test_one_none(self): + dict_1 = None + dict_2 = {"a": "b", "c": "d"} + self.assertFalse(equal(dict_1, dict_2)) + + def test_same_item(self): + dict_1 = {"a": "b", "c": "d"} + self.assertTrue(equal(dict_1, dict_1)) + + def test_nested_equal(self): + dict_1 = {"a": {"a": "b", "c": "d"}, "c": "d"} + dict_2 = {"c": "d", "a": {"a": "b", "c": "d"}} + self.assertTrue(equal(dict_1, dict_2)) + + def test_nested_dict_unequal(self): + dict_1 = {"a": {"a": "b", "c": "d"}, "c": "d"} + dict_2 = {"c": "d", "a": {"a": "b", "c": "x"}} + self.assertFalse(equal(dict_1, dict_2)) + + def test_mixed_nested_equal(self): + dict_1 = {"a": ["a", "b", "c", "d"], "c": "d"} + dict_2 = {"c": "d", "a": ["a", "b", "c", "d"]} + self.assertTrue(equal(dict_1, dict_2)) + + def test_nested_list_unequal(self): + dict_1 = {"a": ["a", "b", "c", "d"], "c": "d"} + dict_2 = {"c": "d", "a": ["b", "c", "d", "a"]} + self.assertFalse(equal(dict_1, dict_2)) + + +class TestListEqual(TestCase): + def test_equal_lists(self): + list_1 = ["a", "b", "c"] + list_2 = ["a", "b", "c"] + self.assertTrue(equal(list_1, list_2)) + + def test_equal_lists_with_nan(self): + list_1 = ["a", nan, "c"] + list_2 = ["a", nan, "c"] + self.assertTrue(equal(list_1, list_2)) + + def test_unsorted_lists(self): + list_1 = ["a", "b", "c"] + list_2 = ["b", "b", "a"] + self.assertFalse(equal(list_1, list_2)) + + def test_first_list_larger(self): + list_1 = ["a", "b", "c"] + list_2 = ["a", "b"] + self.assertFalse(equal(list_1, list_2)) + + def test_second_list_larger(self): + list_1 = ["a", "b"] + list_2 = ["a", "b", "c"] + self.assertFalse(equal(list_1, list_2)) + + def test_list_with_none_unequal(self): + list_1 = ["a", "b", None] + list_2 = ["a", "b", "c"] + self.assertFalse(equal(list_1, list_2)) + + list_1 = ["a", "b", None] + list_2 = [None, "b", "c"] + self.assertFalse(equal(list_1, list_2)) + + def test_list_with_none_equal(self): + list_1 = ["a", None, "c"] + list_2 = ["a", None, "c"] + self.assertTrue(equal(list_1, list_2)) + + def test_empty_list(self): + list_1 = [] + list_2 = [] + self.assertTrue(equal(list_1, list_2)) + + def test_one_none(self): + list_1 = None + list_2 = [] + self.assertFalse(equal(list_1, list_2)) + + def test_same_list(self): + list_1 = ["a", "b", "c"] + self.assertTrue(equal(list_1, list_1)) + + def test_equal_nested_lists(self): + list_1 = ["a", ["b", "c"], "d"] + list_2 = ["a", ["b", "c"], "d"] + self.assertTrue(equal(list_1, list_2)) + + def test_unequal_nested_lists(self): + list_1 = ["a", ["b", "c"], "d"] + list_2 = ["a", [], "c"] + self.assertFalse(equal(list_1, list_2)) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/tests/test_validators.py b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_validators.py new file mode 100644 index 0000000..28cc402 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/tests/test_validators.py @@ -0,0 +1,2575 @@ +from __future__ import annotations + +from collections import deque, namedtuple +from contextlib import contextmanager +from decimal import Decimal +from io import BytesIO +from typing import Any +from unittest import TestCase, mock +from urllib.request import pathname2url +import json +import os +import sys +import tempfile +import warnings + +from attrs import define, field +from referencing.jsonschema import DRAFT202012 +import referencing.exceptions + +from jsonschema import ( + FormatChecker, + TypeChecker, + exceptions, + protocols, + validators, +) + + +def fail(validator, errors, instance, schema): + for each in errors: + each.setdefault("message", "You told me to fail!") + yield exceptions.ValidationError(**each) + + +class TestCreateAndExtend(TestCase): + def setUp(self): + self.addCleanup( + self.assertEqual, + validators._META_SCHEMAS, + dict(validators._META_SCHEMAS), + ) + self.addCleanup( + self.assertEqual, + validators._VALIDATORS, + dict(validators._VALIDATORS), + ) + + self.meta_schema = {"$id": "some://meta/schema"} + self.validators = {"fail": fail} + self.type_checker = TypeChecker() + self.Validator = validators.create( + meta_schema=self.meta_schema, + validators=self.validators, + type_checker=self.type_checker, + ) + + def test_attrs(self): + self.assertEqual( + ( + self.Validator.VALIDATORS, + self.Validator.META_SCHEMA, + self.Validator.TYPE_CHECKER, + ), ( + self.validators, + self.meta_schema, + self.type_checker, + ), + ) + + def test_init(self): + schema = {"fail": []} + self.assertEqual(self.Validator(schema).schema, schema) + + def test_iter_errors_successful(self): + schema = {"fail": []} + validator = self.Validator(schema) + + errors = list(validator.iter_errors("hello")) + self.assertEqual(errors, []) + + def test_iter_errors_one_error(self): + schema = {"fail": [{"message": "Whoops!"}]} + validator = self.Validator(schema) + + expected_error = exceptions.ValidationError( + "Whoops!", + instance="goodbye", + schema=schema, + validator="fail", + validator_value=[{"message": "Whoops!"}], + schema_path=deque(["fail"]), + ) + + errors = list(validator.iter_errors("goodbye")) + self.assertEqual(len(errors), 1) + self.assertEqual(errors[0]._contents(), expected_error._contents()) + + def test_iter_errors_multiple_errors(self): + schema = { + "fail": [ + {"message": "First"}, + {"message": "Second!", "validator": "asdf"}, + {"message": "Third"}, + ], + } + validator = self.Validator(schema) + + errors = list(validator.iter_errors("goodbye")) + self.assertEqual(len(errors), 3) + + def test_if_a_version_is_provided_it_is_registered(self): + Validator = validators.create( + meta_schema={"$id": "something"}, + version="my version", + ) + self.addCleanup(validators._META_SCHEMAS.pop, "something") + self.addCleanup(validators._VALIDATORS.pop, "my version") + self.assertEqual(Validator.__name__, "MyVersionValidator") + self.assertEqual(Validator.__qualname__, "MyVersionValidator") + + def test_repr(self): + Validator = validators.create( + meta_schema={"$id": "something"}, + version="my version", + ) + self.addCleanup(validators._META_SCHEMAS.pop, "something") + self.addCleanup(validators._VALIDATORS.pop, "my version") + self.assertEqual( + repr(Validator({})), + "MyVersionValidator(schema={}, format_checker=None)", + ) + + def test_long_repr(self): + Validator = validators.create( + meta_schema={"$id": "something"}, + version="my version", + ) + self.addCleanup(validators._META_SCHEMAS.pop, "something") + self.addCleanup(validators._VALIDATORS.pop, "my version") + self.assertEqual( + repr(Validator({"a": list(range(1000))})), ( + "MyVersionValidator(schema={'a': [0, 1, 2, 3, 4, 5, ...]}, " + "format_checker=None)" + ), + ) + + def test_repr_no_version(self): + Validator = validators.create(meta_schema={}) + self.assertEqual( + repr(Validator({})), + "Validator(schema={}, format_checker=None)", + ) + + def test_dashes_are_stripped_from_validator_names(self): + Validator = validators.create( + meta_schema={"$id": "something"}, + version="foo-bar", + ) + self.addCleanup(validators._META_SCHEMAS.pop, "something") + self.addCleanup(validators._VALIDATORS.pop, "foo-bar") + self.assertEqual(Validator.__qualname__, "FooBarValidator") + + def test_if_a_version_is_not_provided_it_is_not_registered(self): + original = dict(validators._META_SCHEMAS) + validators.create(meta_schema={"id": "id"}) + self.assertEqual(validators._META_SCHEMAS, original) + + def test_validates_registers_meta_schema_id(self): + meta_schema_key = "meta schema id" + my_meta_schema = {"id": meta_schema_key} + + validators.create( + meta_schema=my_meta_schema, + version="my version", + id_of=lambda s: s.get("id", ""), + ) + self.addCleanup(validators._META_SCHEMAS.pop, meta_schema_key) + self.addCleanup(validators._VALIDATORS.pop, "my version") + + self.assertIn(meta_schema_key, validators._META_SCHEMAS) + + def test_validates_registers_meta_schema_draft6_id(self): + meta_schema_key = "meta schema $id" + my_meta_schema = {"$id": meta_schema_key} + + validators.create( + meta_schema=my_meta_schema, + version="my version", + ) + self.addCleanup(validators._META_SCHEMAS.pop, meta_schema_key) + self.addCleanup(validators._VALIDATORS.pop, "my version") + + self.assertIn(meta_schema_key, validators._META_SCHEMAS) + + def test_create_default_types(self): + Validator = validators.create(meta_schema={}, validators=()) + self.assertTrue( + all( + Validator({}).is_type(instance=instance, type=type) + for type, instance in [ + ("array", []), + ("boolean", True), + ("integer", 12), + ("null", None), + ("number", 12.0), + ("object", {}), + ("string", "foo"), + ] + ), + ) + + def test_check_schema_with_different_metaschema(self): + """ + One can create a validator class whose metaschema uses a different + dialect than itself. + """ + + NoEmptySchemasValidator = validators.create( + meta_schema={ + "$schema": validators.Draft202012Validator.META_SCHEMA["$id"], + "not": {"const": {}}, + }, + ) + NoEmptySchemasValidator.check_schema({"foo": "bar"}) + + with self.assertRaises(exceptions.SchemaError): + NoEmptySchemasValidator.check_schema({}) + + NoEmptySchemasValidator({"foo": "bar"}).validate("foo") + + def test_check_schema_with_different_metaschema_defaults_to_self(self): + """ + A validator whose metaschema doesn't declare $schema defaults to its + own validation behavior, not the latest "normal" specification. + """ + + NoEmptySchemasValidator = validators.create( + meta_schema={"fail": [{"message": "Meta schema whoops!"}]}, + validators={"fail": fail}, + ) + with self.assertRaises(exceptions.SchemaError): + NoEmptySchemasValidator.check_schema({}) + + def test_extend(self): + original = dict(self.Validator.VALIDATORS) + new = object() + + Extended = validators.extend( + self.Validator, + validators={"new": new}, + ) + self.assertEqual( + ( + Extended.VALIDATORS, + Extended.META_SCHEMA, + Extended.TYPE_CHECKER, + self.Validator.VALIDATORS, + ), ( + dict(original, new=new), + self.Validator.META_SCHEMA, + self.Validator.TYPE_CHECKER, + original, + ), + ) + + def test_extend_idof(self): + """ + Extending a validator preserves its notion of schema IDs. + """ + def id_of(schema): + return schema.get("__test__", self.Validator.ID_OF(schema)) + correct_id = "the://correct/id/" + meta_schema = { + "$id": "the://wrong/id/", + "__test__": correct_id, + } + Original = validators.create( + meta_schema=meta_schema, + validators=self.validators, + type_checker=self.type_checker, + id_of=id_of, + ) + self.assertEqual(Original.ID_OF(Original.META_SCHEMA), correct_id) + + Derived = validators.extend(Original) + self.assertEqual(Derived.ID_OF(Derived.META_SCHEMA), correct_id) + + def test_extend_applicable_validators(self): + """ + Extending a validator preserves its notion of applicable validators. + """ + + schema = { + "$defs": {"test": {"type": "number"}}, + "$ref": "#/$defs/test", + "maximum": 1, + } + + draft4 = validators.Draft4Validator(schema) + self.assertTrue(draft4.is_valid(37)) # as $ref ignores siblings + + Derived = validators.extend(validators.Draft4Validator) + self.assertTrue(Derived(schema).is_valid(37)) + + +class TestValidationErrorMessages(TestCase): + def message_for(self, instance, schema, *args, **kwargs): + cls = kwargs.pop("cls", validators._LATEST_VERSION) + cls.check_schema(schema) + validator = cls(schema, *args, **kwargs) + errors = list(validator.iter_errors(instance)) + self.assertTrue(errors, msg=f"No errors were raised for {instance!r}") + self.assertEqual( + len(errors), + 1, + msg=f"Expected exactly one error, found {errors!r}", + ) + return errors[0].message + + def test_single_type_failure(self): + message = self.message_for(instance=1, schema={"type": "string"}) + self.assertEqual(message, "1 is not of type 'string'") + + def test_single_type_list_failure(self): + message = self.message_for(instance=1, schema={"type": ["string"]}) + self.assertEqual(message, "1 is not of type 'string'") + + def test_multiple_type_failure(self): + types = "string", "object" + message = self.message_for(instance=1, schema={"type": list(types)}) + self.assertEqual(message, "1 is not of type 'string', 'object'") + + def test_object_with_named_type_failure(self): + schema = {"type": [{"name": "Foo", "minimum": 3}]} + message = self.message_for( + instance=1, + schema=schema, + cls=validators.Draft3Validator, + ) + self.assertEqual(message, "1 is not of type 'Foo'") + + def test_minimum(self): + message = self.message_for(instance=1, schema={"minimum": 2}) + self.assertEqual(message, "1 is less than the minimum of 2") + + def test_maximum(self): + message = self.message_for(instance=1, schema={"maximum": 0}) + self.assertEqual(message, "1 is greater than the maximum of 0") + + def test_dependencies_single_element(self): + depend, on = "bar", "foo" + schema = {"dependencies": {depend: on}} + message = self.message_for( + instance={"bar": 2}, + schema=schema, + cls=validators.Draft3Validator, + ) + self.assertEqual(message, "'foo' is a dependency of 'bar'") + + def test_object_without_title_type_failure_draft3(self): + type = {"type": [{"minimum": 3}]} + message = self.message_for( + instance=1, + schema={"type": [type]}, + cls=validators.Draft3Validator, + ) + self.assertEqual( + message, + "1 is not of type {'type': [{'minimum': 3}]}", + ) + + def test_dependencies_list_draft3(self): + depend, on = "bar", "foo" + schema = {"dependencies": {depend: [on]}} + message = self.message_for( + instance={"bar": 2}, + schema=schema, + cls=validators.Draft3Validator, + ) + self.assertEqual(message, "'foo' is a dependency of 'bar'") + + def test_dependencies_list_draft7(self): + depend, on = "bar", "foo" + schema = {"dependencies": {depend: [on]}} + message = self.message_for( + instance={"bar": 2}, + schema=schema, + cls=validators.Draft7Validator, + ) + self.assertEqual(message, "'foo' is a dependency of 'bar'") + + def test_additionalItems_single_failure(self): + message = self.message_for( + instance=[2], + schema={"items": [], "additionalItems": False}, + cls=validators.Draft3Validator, + ) + self.assertIn("(2 was unexpected)", message) + + def test_additionalItems_multiple_failures(self): + message = self.message_for( + instance=[1, 2, 3], + schema={"items": [], "additionalItems": False}, + cls=validators.Draft3Validator, + ) + self.assertIn("(1, 2, 3 were unexpected)", message) + + def test_additionalProperties_single_failure(self): + additional = "foo" + schema = {"additionalProperties": False} + message = self.message_for(instance={additional: 2}, schema=schema) + self.assertIn("('foo' was unexpected)", message) + + def test_additionalProperties_multiple_failures(self): + schema = {"additionalProperties": False} + message = self.message_for( + instance=dict.fromkeys(["foo", "bar"]), + schema=schema, + ) + + self.assertIn(repr("foo"), message) + self.assertIn(repr("bar"), message) + self.assertIn("were unexpected)", message) + + def test_const(self): + schema = {"const": 12} + message = self.message_for( + instance={"foo": "bar"}, + schema=schema, + ) + self.assertIn("12 was expected", message) + + def test_contains_draft_6(self): + schema = {"contains": {"const": 12}} + message = self.message_for( + instance=[2, {}, []], + schema=schema, + cls=validators.Draft6Validator, + ) + self.assertEqual( + message, + "None of [2, {}, []] are valid under the given schema", + ) + + def test_invalid_format_default_message(self): + checker = FormatChecker(formats=()) + checker.checks("thing")(lambda value: False) + + schema = {"format": "thing"} + message = self.message_for( + instance="bla", + schema=schema, + format_checker=checker, + ) + + self.assertIn(repr("bla"), message) + self.assertIn(repr("thing"), message) + self.assertIn("is not a", message) + + def test_additionalProperties_false_patternProperties(self): + schema = {"type": "object", + "additionalProperties": False, + "patternProperties": { + "^abc$": {"type": "string"}, + "^def$": {"type": "string"}, + }} + message = self.message_for( + instance={"zebra": 123}, + schema=schema, + cls=validators.Draft4Validator, + ) + self.assertEqual( + message, + "{} does not match any of the regexes: {}, {}".format( + repr("zebra"), repr("^abc$"), repr("^def$"), + ), + ) + message = self.message_for( + instance={"zebra": 123, "fish": 456}, + schema=schema, + cls=validators.Draft4Validator, + ) + self.assertEqual( + message, + "{}, {} do not match any of the regexes: {}, {}".format( + repr("fish"), repr("zebra"), repr("^abc$"), repr("^def$"), + ), + ) + + def test_False_schema(self): + message = self.message_for( + instance="something", + schema=False, + ) + self.assertEqual(message, "False schema does not allow 'something'") + + def test_multipleOf(self): + message = self.message_for( + instance=3, + schema={"multipleOf": 2}, + ) + self.assertEqual(message, "3 is not a multiple of 2") + + def test_minItems(self): + message = self.message_for(instance=[], schema={"minItems": 2}) + self.assertEqual(message, "[] is too short") + + def test_maxItems(self): + message = self.message_for(instance=[1, 2, 3], schema={"maxItems": 2}) + self.assertEqual(message, "[1, 2, 3] is too long") + + def test_minItems_1(self): + message = self.message_for(instance=[], schema={"minItems": 1}) + self.assertEqual(message, "[] should be non-empty") + + def test_maxItems_0(self): + message = self.message_for(instance=[1, 2, 3], schema={"maxItems": 0}) + self.assertEqual(message, "[1, 2, 3] is expected to be empty") + + def test_minLength(self): + message = self.message_for( + instance="", + schema={"minLength": 2}, + ) + self.assertEqual(message, "'' is too short") + + def test_maxLength(self): + message = self.message_for( + instance="abc", + schema={"maxLength": 2}, + ) + self.assertEqual(message, "'abc' is too long") + + def test_minLength_1(self): + message = self.message_for(instance="", schema={"minLength": 1}) + self.assertEqual(message, "'' should be non-empty") + + def test_maxLength_0(self): + message = self.message_for(instance="abc", schema={"maxLength": 0}) + self.assertEqual(message, "'abc' is expected to be empty") + + def test_minProperties(self): + message = self.message_for(instance={}, schema={"minProperties": 2}) + self.assertEqual(message, "{} does not have enough properties") + + def test_maxProperties(self): + message = self.message_for( + instance={"a": {}, "b": {}, "c": {}}, + schema={"maxProperties": 2}, + ) + self.assertEqual( + message, + "{'a': {}, 'b': {}, 'c': {}} has too many properties", + ) + + def test_minProperties_1(self): + message = self.message_for(instance={}, schema={"minProperties": 1}) + self.assertEqual(message, "{} should be non-empty") + + def test_maxProperties_0(self): + message = self.message_for( + instance={1: 2}, + schema={"maxProperties": 0}, + ) + self.assertEqual(message, "{1: 2} is expected to be empty") + + def test_prefixItems_with_items(self): + message = self.message_for( + instance=[1, 2, "foo"], + schema={"items": False, "prefixItems": [{}, {}]}, + ) + self.assertEqual( + message, + "Expected at most 2 items but found 1 extra: 'foo'", + ) + + def test_prefixItems_with_multiple_extra_items(self): + message = self.message_for( + instance=[1, 2, "foo", 5], + schema={"items": False, "prefixItems": [{}, {}]}, + ) + self.assertEqual( + message, + "Expected at most 2 items but found 2 extra: ['foo', 5]", + ) + + def test_pattern(self): + message = self.message_for( + instance="bbb", + schema={"pattern": "^a*$"}, + ) + self.assertEqual(message, "'bbb' does not match '^a*$'") + + def test_does_not_contain(self): + message = self.message_for( + instance=[], + schema={"contains": {"type": "string"}}, + ) + self.assertEqual( + message, + "[] does not contain items matching the given schema", + ) + + def test_contains_too_few(self): + message = self.message_for( + instance=["foo", 1], + schema={"contains": {"type": "string"}, "minContains": 2}, + ) + self.assertEqual( + message, + "Too few items match the given schema " + "(expected at least 2 but only 1 matched)", + ) + + def test_contains_too_few_both_constrained(self): + message = self.message_for( + instance=["foo", 1], + schema={ + "contains": {"type": "string"}, + "minContains": 2, + "maxContains": 4, + }, + ) + self.assertEqual( + message, + "Too few items match the given schema (expected at least 2 but " + "only 1 matched)", + ) + + def test_contains_too_many(self): + message = self.message_for( + instance=["foo", "bar", "baz"], + schema={"contains": {"type": "string"}, "maxContains": 2}, + ) + self.assertEqual( + message, + "Too many items match the given schema (expected at most 2)", + ) + + def test_contains_too_many_both_constrained(self): + message = self.message_for( + instance=["foo"] * 5, + schema={ + "contains": {"type": "string"}, + "minContains": 2, + "maxContains": 4, + }, + ) + self.assertEqual( + message, + "Too many items match the given schema (expected at most 4)", + ) + + def test_exclusiveMinimum(self): + message = self.message_for( + instance=3, + schema={"exclusiveMinimum": 5}, + ) + self.assertEqual( + message, + "3 is less than or equal to the minimum of 5", + ) + + def test_exclusiveMaximum(self): + message = self.message_for(instance=3, schema={"exclusiveMaximum": 2}) + self.assertEqual( + message, + "3 is greater than or equal to the maximum of 2", + ) + + def test_required(self): + message = self.message_for(instance={}, schema={"required": ["foo"]}) + self.assertEqual(message, "'foo' is a required property") + + def test_dependentRequired(self): + message = self.message_for( + instance={"foo": {}}, + schema={"dependentRequired": {"foo": ["bar"]}}, + ) + self.assertEqual(message, "'bar' is a dependency of 'foo'") + + def test_oneOf_matches_none(self): + message = self.message_for(instance={}, schema={"oneOf": [False]}) + self.assertEqual( + message, + "{} is not valid under any of the given schemas", + ) + + def test_oneOf_matches_too_many(self): + message = self.message_for(instance={}, schema={"oneOf": [True, True]}) + self.assertEqual(message, "{} is valid under each of True, True") + + def test_unevaluated_items(self): + schema = {"type": "array", "unevaluatedItems": False} + message = self.message_for(instance=["foo", "bar"], schema=schema) + self.assertIn( + message, + "Unevaluated items are not allowed ('foo', 'bar' were unexpected)", + ) + + def test_unevaluated_items_on_invalid_type(self): + schema = {"type": "array", "unevaluatedItems": False} + message = self.message_for(instance="foo", schema=schema) + self.assertEqual(message, "'foo' is not of type 'array'") + + def test_unevaluated_properties_invalid_against_subschema(self): + schema = { + "properties": {"foo": {"type": "string"}}, + "unevaluatedProperties": {"const": 12}, + } + message = self.message_for( + instance={ + "foo": "foo", + "bar": "bar", + "baz": 12, + }, + schema=schema, + ) + self.assertEqual( + message, + "Unevaluated properties are not valid under the given schema " + "('bar' was unevaluated and invalid)", + ) + + def test_unevaluated_properties_disallowed(self): + schema = {"type": "object", "unevaluatedProperties": False} + message = self.message_for( + instance={ + "foo": "foo", + "bar": "bar", + }, + schema=schema, + ) + self.assertEqual( + message, + "Unevaluated properties are not allowed " + "('bar', 'foo' were unexpected)", + ) + + def test_unevaluated_properties_on_invalid_type(self): + schema = {"type": "object", "unevaluatedProperties": False} + message = self.message_for(instance="foo", schema=schema) + self.assertEqual(message, "'foo' is not of type 'object'") + + def test_single_item(self): + schema = {"prefixItems": [{}], "items": False} + message = self.message_for( + instance=["foo", "bar", "baz"], + schema=schema, + ) + self.assertEqual( + message, + "Expected at most 1 item but found 2 extra: ['bar', 'baz']", + ) + + def test_heterogeneous_additionalItems_with_Items(self): + schema = {"items": [{}], "additionalItems": False} + message = self.message_for( + instance=["foo", "bar", 37], + schema=schema, + cls=validators.Draft7Validator, + ) + self.assertEqual( + message, + "Additional items are not allowed ('bar', 37 were unexpected)", + ) + + def test_heterogeneous_items_prefixItems(self): + schema = {"prefixItems": [{}], "items": False} + message = self.message_for( + instance=["foo", "bar", 37], + schema=schema, + ) + self.assertEqual( + message, + "Expected at most 1 item but found 2 extra: ['bar', 37]", + ) + + def test_heterogeneous_unevaluatedItems_prefixItems(self): + schema = {"prefixItems": [{}], "unevaluatedItems": False} + message = self.message_for( + instance=["foo", "bar", 37], + schema=schema, + ) + self.assertEqual( + message, + "Unevaluated items are not allowed ('bar', 37 were unexpected)", + ) + + def test_heterogeneous_properties_additionalProperties(self): + """ + Not valid deserialized JSON, but this should not blow up. + """ + schema = {"properties": {"foo": {}}, "additionalProperties": False} + message = self.message_for( + instance={"foo": {}, "a": "baz", 37: 12}, + schema=schema, + ) + self.assertEqual( + message, + "Additional properties are not allowed (37, 'a' were unexpected)", + ) + + def test_heterogeneous_properties_unevaluatedProperties(self): + """ + Not valid deserialized JSON, but this should not blow up. + """ + schema = {"properties": {"foo": {}}, "unevaluatedProperties": False} + message = self.message_for( + instance={"foo": {}, "a": "baz", 37: 12}, + schema=schema, + ) + self.assertEqual( + message, + "Unevaluated properties are not allowed (37, 'a' were unexpected)", + ) + + +class TestValidationErrorDetails(TestCase): + # TODO: These really need unit tests for each individual keyword, rather + # than just these higher level tests. + def test_anyOf(self): + instance = 5 + schema = { + "anyOf": [ + {"minimum": 20}, + {"type": "string"}, + ], + } + + validator = validators.Draft4Validator(schema) + errors = list(validator.iter_errors(instance)) + self.assertEqual(len(errors), 1) + e = errors[0] + + self.assertEqual(e.validator, "anyOf") + self.assertEqual(e.validator_value, schema["anyOf"]) + self.assertEqual(e.instance, instance) + self.assertEqual(e.schema, schema) + self.assertIsNone(e.parent) + + self.assertEqual(e.path, deque([])) + self.assertEqual(e.relative_path, deque([])) + self.assertEqual(e.absolute_path, deque([])) + self.assertEqual(e.json_path, "$") + + self.assertEqual(e.schema_path, deque(["anyOf"])) + self.assertEqual(e.relative_schema_path, deque(["anyOf"])) + self.assertEqual(e.absolute_schema_path, deque(["anyOf"])) + + self.assertEqual(len(e.context), 2) + + e1, e2 = sorted_errors(e.context) + + self.assertEqual(e1.validator, "minimum") + self.assertEqual(e1.validator_value, schema["anyOf"][0]["minimum"]) + self.assertEqual(e1.instance, instance) + self.assertEqual(e1.schema, schema["anyOf"][0]) + self.assertIs(e1.parent, e) + + self.assertEqual(e1.path, deque([])) + self.assertEqual(e1.absolute_path, deque([])) + self.assertEqual(e1.relative_path, deque([])) + self.assertEqual(e1.json_path, "$") + + self.assertEqual(e1.schema_path, deque([0, "minimum"])) + self.assertEqual(e1.relative_schema_path, deque([0, "minimum"])) + self.assertEqual( + e1.absolute_schema_path, deque(["anyOf", 0, "minimum"]), + ) + + self.assertFalse(e1.context) + + self.assertEqual(e2.validator, "type") + self.assertEqual(e2.validator_value, schema["anyOf"][1]["type"]) + self.assertEqual(e2.instance, instance) + self.assertEqual(e2.schema, schema["anyOf"][1]) + self.assertIs(e2.parent, e) + + self.assertEqual(e2.path, deque([])) + self.assertEqual(e2.relative_path, deque([])) + self.assertEqual(e2.absolute_path, deque([])) + self.assertEqual(e2.json_path, "$") + + self.assertEqual(e2.schema_path, deque([1, "type"])) + self.assertEqual(e2.relative_schema_path, deque([1, "type"])) + self.assertEqual(e2.absolute_schema_path, deque(["anyOf", 1, "type"])) + + self.assertEqual(len(e2.context), 0) + + def test_type(self): + instance = {"foo": 1} + schema = { + "type": [ + {"type": "integer"}, + { + "type": "object", + "properties": {"foo": {"enum": [2]}}, + }, + ], + } + + validator = validators.Draft3Validator(schema) + errors = list(validator.iter_errors(instance)) + self.assertEqual(len(errors), 1) + e = errors[0] + + self.assertEqual(e.validator, "type") + self.assertEqual(e.validator_value, schema["type"]) + self.assertEqual(e.instance, instance) + self.assertEqual(e.schema, schema) + self.assertIsNone(e.parent) + + self.assertEqual(e.path, deque([])) + self.assertEqual(e.relative_path, deque([])) + self.assertEqual(e.absolute_path, deque([])) + self.assertEqual(e.json_path, "$") + + self.assertEqual(e.schema_path, deque(["type"])) + self.assertEqual(e.relative_schema_path, deque(["type"])) + self.assertEqual(e.absolute_schema_path, deque(["type"])) + + self.assertEqual(len(e.context), 2) + + e1, e2 = sorted_errors(e.context) + + self.assertEqual(e1.validator, "type") + self.assertEqual(e1.validator_value, schema["type"][0]["type"]) + self.assertEqual(e1.instance, instance) + self.assertEqual(e1.schema, schema["type"][0]) + self.assertIs(e1.parent, e) + + self.assertEqual(e1.path, deque([])) + self.assertEqual(e1.relative_path, deque([])) + self.assertEqual(e1.absolute_path, deque([])) + self.assertEqual(e1.json_path, "$") + + self.assertEqual(e1.schema_path, deque([0, "type"])) + self.assertEqual(e1.relative_schema_path, deque([0, "type"])) + self.assertEqual(e1.absolute_schema_path, deque(["type", 0, "type"])) + + self.assertFalse(e1.context) + + self.assertEqual(e2.validator, "enum") + self.assertEqual(e2.validator_value, [2]) + self.assertEqual(e2.instance, 1) + self.assertEqual(e2.schema, {"enum": [2]}) + self.assertIs(e2.parent, e) + + self.assertEqual(e2.path, deque(["foo"])) + self.assertEqual(e2.relative_path, deque(["foo"])) + self.assertEqual(e2.absolute_path, deque(["foo"])) + self.assertEqual(e2.json_path, "$.foo") + + self.assertEqual( + e2.schema_path, deque([1, "properties", "foo", "enum"]), + ) + self.assertEqual( + e2.relative_schema_path, deque([1, "properties", "foo", "enum"]), + ) + self.assertEqual( + e2.absolute_schema_path, + deque(["type", 1, "properties", "foo", "enum"]), + ) + + self.assertFalse(e2.context) + + def test_single_nesting(self): + instance = {"foo": 2, "bar": [1], "baz": 15, "quux": "spam"} + schema = { + "properties": { + "foo": {"type": "string"}, + "bar": {"minItems": 2}, + "baz": {"maximum": 10, "enum": [2, 4, 6, 8]}, + }, + } + + validator = validators.Draft3Validator(schema) + errors = validator.iter_errors(instance) + e1, e2, e3, e4 = sorted_errors(errors) + + self.assertEqual(e1.path, deque(["bar"])) + self.assertEqual(e2.path, deque(["baz"])) + self.assertEqual(e3.path, deque(["baz"])) + self.assertEqual(e4.path, deque(["foo"])) + + self.assertEqual(e1.relative_path, deque(["bar"])) + self.assertEqual(e2.relative_path, deque(["baz"])) + self.assertEqual(e3.relative_path, deque(["baz"])) + self.assertEqual(e4.relative_path, deque(["foo"])) + + self.assertEqual(e1.absolute_path, deque(["bar"])) + self.assertEqual(e2.absolute_path, deque(["baz"])) + self.assertEqual(e3.absolute_path, deque(["baz"])) + self.assertEqual(e4.absolute_path, deque(["foo"])) + + self.assertEqual(e1.json_path, "$.bar") + self.assertEqual(e2.json_path, "$.baz") + self.assertEqual(e3.json_path, "$.baz") + self.assertEqual(e4.json_path, "$.foo") + + self.assertEqual(e1.validator, "minItems") + self.assertEqual(e2.validator, "enum") + self.assertEqual(e3.validator, "maximum") + self.assertEqual(e4.validator, "type") + + def test_multiple_nesting(self): + instance = [1, {"foo": 2, "bar": {"baz": [1]}}, "quux"] + schema = { + "type": "string", + "items": { + "type": ["string", "object"], + "properties": { + "foo": {"enum": [1, 3]}, + "bar": { + "type": "array", + "properties": { + "bar": {"required": True}, + "baz": {"minItems": 2}, + }, + }, + }, + }, + } + + validator = validators.Draft3Validator(schema) + errors = validator.iter_errors(instance) + e1, e2, e3, e4, e5, e6 = sorted_errors(errors) + + self.assertEqual(e1.path, deque([])) + self.assertEqual(e2.path, deque([0])) + self.assertEqual(e3.path, deque([1, "bar"])) + self.assertEqual(e4.path, deque([1, "bar", "bar"])) + self.assertEqual(e5.path, deque([1, "bar", "baz"])) + self.assertEqual(e6.path, deque([1, "foo"])) + + self.assertEqual(e1.json_path, "$") + self.assertEqual(e2.json_path, "$[0]") + self.assertEqual(e3.json_path, "$[1].bar") + self.assertEqual(e4.json_path, "$[1].bar.bar") + self.assertEqual(e5.json_path, "$[1].bar.baz") + self.assertEqual(e6.json_path, "$[1].foo") + + self.assertEqual(e1.schema_path, deque(["type"])) + self.assertEqual(e2.schema_path, deque(["items", "type"])) + self.assertEqual( + list(e3.schema_path), ["items", "properties", "bar", "type"], + ) + self.assertEqual( + list(e4.schema_path), + ["items", "properties", "bar", "properties", "bar", "required"], + ) + self.assertEqual( + list(e5.schema_path), + ["items", "properties", "bar", "properties", "baz", "minItems"], + ) + self.assertEqual( + list(e6.schema_path), ["items", "properties", "foo", "enum"], + ) + + self.assertEqual(e1.validator, "type") + self.assertEqual(e2.validator, "type") + self.assertEqual(e3.validator, "type") + self.assertEqual(e4.validator, "required") + self.assertEqual(e5.validator, "minItems") + self.assertEqual(e6.validator, "enum") + + def test_recursive(self): + schema = { + "definitions": { + "node": { + "anyOf": [{ + "type": "object", + "required": ["name", "children"], + "properties": { + "name": { + "type": "string", + }, + "children": { + "type": "object", + "patternProperties": { + "^.*$": { + "$ref": "#/definitions/node", + }, + }, + }, + }, + }], + }, + }, + "type": "object", + "required": ["root"], + "properties": {"root": {"$ref": "#/definitions/node"}}, + } + + instance = { + "root": { + "name": "root", + "children": { + "a": { + "name": "a", + "children": { + "ab": { + "name": "ab", + # missing "children" + }, + }, + }, + }, + }, + } + validator = validators.Draft4Validator(schema) + + e, = validator.iter_errors(instance) + self.assertEqual(e.absolute_path, deque(["root"])) + self.assertEqual( + e.absolute_schema_path, deque(["properties", "root", "anyOf"]), + ) + self.assertEqual(e.json_path, "$.root") + + e1, = e.context + self.assertEqual(e1.absolute_path, deque(["root", "children", "a"])) + self.assertEqual( + e1.absolute_schema_path, deque( + [ + "properties", + "root", + "anyOf", + 0, + "properties", + "children", + "patternProperties", + "^.*$", + "anyOf", + ], + ), + ) + self.assertEqual(e1.json_path, "$.root.children.a") + + e2, = e1.context + self.assertEqual( + e2.absolute_path, deque( + ["root", "children", "a", "children", "ab"], + ), + ) + self.assertEqual( + e2.absolute_schema_path, deque( + [ + "properties", + "root", + "anyOf", + 0, + "properties", + "children", + "patternProperties", + "^.*$", + "anyOf", + 0, + "properties", + "children", + "patternProperties", + "^.*$", + "anyOf", + ], + ), + ) + self.assertEqual(e2.json_path, "$.root.children.a.children.ab") + + def test_additionalProperties(self): + instance = {"bar": "bar", "foo": 2} + schema = {"additionalProperties": {"type": "integer", "minimum": 5}} + + validator = validators.Draft3Validator(schema) + errors = validator.iter_errors(instance) + e1, e2 = sorted_errors(errors) + + self.assertEqual(e1.path, deque(["bar"])) + self.assertEqual(e2.path, deque(["foo"])) + + self.assertEqual(e1.json_path, "$.bar") + self.assertEqual(e2.json_path, "$.foo") + + self.assertEqual(e1.validator, "type") + self.assertEqual(e2.validator, "minimum") + + def test_patternProperties(self): + instance = {"bar": 1, "foo": 2} + schema = { + "patternProperties": { + "bar": {"type": "string"}, + "foo": {"minimum": 5}, + }, + } + + validator = validators.Draft3Validator(schema) + errors = validator.iter_errors(instance) + e1, e2 = sorted_errors(errors) + + self.assertEqual(e1.path, deque(["bar"])) + self.assertEqual(e2.path, deque(["foo"])) + + self.assertEqual(e1.json_path, "$.bar") + self.assertEqual(e2.json_path, "$.foo") + + self.assertEqual(e1.validator, "type") + self.assertEqual(e2.validator, "minimum") + + def test_additionalItems(self): + instance = ["foo", 1] + schema = { + "items": [], + "additionalItems": {"type": "integer", "minimum": 5}, + } + + validator = validators.Draft3Validator(schema) + errors = validator.iter_errors(instance) + e1, e2 = sorted_errors(errors) + + self.assertEqual(e1.path, deque([0])) + self.assertEqual(e2.path, deque([1])) + + self.assertEqual(e1.json_path, "$[0]") + self.assertEqual(e2.json_path, "$[1]") + + self.assertEqual(e1.validator, "type") + self.assertEqual(e2.validator, "minimum") + + def test_additionalItems_with_items(self): + instance = ["foo", "bar", 1] + schema = { + "items": [{}], + "additionalItems": {"type": "integer", "minimum": 5}, + } + + validator = validators.Draft3Validator(schema) + errors = validator.iter_errors(instance) + e1, e2 = sorted_errors(errors) + + self.assertEqual(e1.path, deque([1])) + self.assertEqual(e2.path, deque([2])) + + self.assertEqual(e1.json_path, "$[1]") + self.assertEqual(e2.json_path, "$[2]") + + self.assertEqual(e1.validator, "type") + self.assertEqual(e2.validator, "minimum") + + def test_propertyNames(self): + instance = {"foo": 12} + schema = {"propertyNames": {"not": {"const": "foo"}}} + + validator = validators.Draft7Validator(schema) + error, = validator.iter_errors(instance) + + self.assertEqual(error.validator, "not") + self.assertEqual( + error.message, + "'foo' should not be valid under {'const': 'foo'}", + ) + self.assertEqual(error.path, deque([])) + self.assertEqual(error.json_path, "$") + self.assertEqual(error.schema_path, deque(["propertyNames", "not"])) + + def test_if_then(self): + schema = { + "if": {"const": 12}, + "then": {"const": 13}, + } + + validator = validators.Draft7Validator(schema) + error, = validator.iter_errors(12) + + self.assertEqual(error.validator, "const") + self.assertEqual(error.message, "13 was expected") + self.assertEqual(error.path, deque([])) + self.assertEqual(error.json_path, "$") + self.assertEqual(error.schema_path, deque(["then", "const"])) + + def test_if_else(self): + schema = { + "if": {"const": 12}, + "else": {"const": 13}, + } + + validator = validators.Draft7Validator(schema) + error, = validator.iter_errors(15) + + self.assertEqual(error.validator, "const") + self.assertEqual(error.message, "13 was expected") + self.assertEqual(error.path, deque([])) + self.assertEqual(error.json_path, "$") + self.assertEqual(error.schema_path, deque(["else", "const"])) + + def test_boolean_schema_False(self): + validator = validators.Draft7Validator(False) + error, = validator.iter_errors(12) + + self.assertEqual( + ( + error.message, + error.validator, + error.validator_value, + error.instance, + error.schema, + error.schema_path, + error.json_path, + ), + ( + "False schema does not allow 12", + None, + None, + 12, + False, + deque([]), + "$", + ), + ) + + def test_ref(self): + ref, schema = "someRef", {"additionalProperties": {"type": "integer"}} + validator = validators.Draft7Validator( + {"$ref": ref}, + resolver=validators._RefResolver("", {}, store={ref: schema}), + ) + error, = validator.iter_errors({"foo": "notAnInteger"}) + + self.assertEqual( + ( + error.message, + error.validator, + error.validator_value, + error.instance, + error.absolute_path, + error.schema, + error.schema_path, + error.json_path, + ), + ( + "'notAnInteger' is not of type 'integer'", + "type", + "integer", + "notAnInteger", + deque(["foo"]), + {"type": "integer"}, + deque(["additionalProperties", "type"]), + "$.foo", + ), + ) + + def test_prefixItems(self): + schema = {"prefixItems": [{"type": "string"}, {}, {}, {"maximum": 3}]} + validator = validators.Draft202012Validator(schema) + type_error, min_error = validator.iter_errors([1, 2, "foo", 5]) + self.assertEqual( + ( + type_error.message, + type_error.validator, + type_error.validator_value, + type_error.instance, + type_error.absolute_path, + type_error.schema, + type_error.schema_path, + type_error.json_path, + ), + ( + "1 is not of type 'string'", + "type", + "string", + 1, + deque([0]), + {"type": "string"}, + deque(["prefixItems", 0, "type"]), + "$[0]", + ), + ) + self.assertEqual( + ( + min_error.message, + min_error.validator, + min_error.validator_value, + min_error.instance, + min_error.absolute_path, + min_error.schema, + min_error.schema_path, + min_error.json_path, + ), + ( + "5 is greater than the maximum of 3", + "maximum", + 3, + 5, + deque([3]), + {"maximum": 3}, + deque(["prefixItems", 3, "maximum"]), + "$[3]", + ), + ) + + def test_prefixItems_with_items(self): + schema = { + "items": {"type": "string"}, + "prefixItems": [{}], + } + validator = validators.Draft202012Validator(schema) + e1, e2 = validator.iter_errors(["foo", 2, "bar", 4, "baz"]) + self.assertEqual( + ( + e1.message, + e1.validator, + e1.validator_value, + e1.instance, + e1.absolute_path, + e1.schema, + e1.schema_path, + e1.json_path, + ), + ( + "2 is not of type 'string'", + "type", + "string", + 2, + deque([1]), + {"type": "string"}, + deque(["items", "type"]), + "$[1]", + ), + ) + self.assertEqual( + ( + e2.message, + e2.validator, + e2.validator_value, + e2.instance, + e2.absolute_path, + e2.schema, + e2.schema_path, + e2.json_path, + ), + ( + "4 is not of type 'string'", + "type", + "string", + 4, + deque([3]), + {"type": "string"}, + deque(["items", "type"]), + "$[3]", + ), + ) + + def test_contains_too_many(self): + """ + `contains` + `maxContains` produces only one error, even if there are + many more incorrectly matching elements. + """ + schema = {"contains": {"type": "string"}, "maxContains": 2} + validator = validators.Draft202012Validator(schema) + error, = validator.iter_errors(["foo", 2, "bar", 4, "baz", "quux"]) + self.assertEqual( + ( + error.message, + error.validator, + error.validator_value, + error.instance, + error.absolute_path, + error.schema, + error.schema_path, + error.json_path, + ), + ( + "Too many items match the given schema (expected at most 2)", + "maxContains", + 2, + ["foo", 2, "bar", 4, "baz", "quux"], + deque([]), + {"contains": {"type": "string"}, "maxContains": 2}, + deque(["contains"]), + "$", + ), + ) + + def test_contains_too_few(self): + schema = {"contains": {"type": "string"}, "minContains": 2} + validator = validators.Draft202012Validator(schema) + error, = validator.iter_errors(["foo", 2, 4]) + self.assertEqual( + ( + error.message, + error.validator, + error.validator_value, + error.instance, + error.absolute_path, + error.schema, + error.schema_path, + error.json_path, + ), + ( + ( + "Too few items match the given schema " + "(expected at least 2 but only 1 matched)" + ), + "minContains", + 2, + ["foo", 2, 4], + deque([]), + {"contains": {"type": "string"}, "minContains": 2}, + deque(["contains"]), + "$", + ), + ) + + def test_contains_none(self): + schema = {"contains": {"type": "string"}, "minContains": 2} + validator = validators.Draft202012Validator(schema) + error, = validator.iter_errors([2, 4]) + self.assertEqual( + ( + error.message, + error.validator, + error.validator_value, + error.instance, + error.absolute_path, + error.schema, + error.schema_path, + error.json_path, + ), + ( + "[2, 4] does not contain items matching the given schema", + "contains", + {"type": "string"}, + [2, 4], + deque([]), + {"contains": {"type": "string"}, "minContains": 2}, + deque(["contains"]), + "$", + ), + ) + + def test_ref_sibling(self): + schema = { + "$defs": {"foo": {"required": ["bar"]}}, + "properties": { + "aprop": { + "$ref": "#/$defs/foo", + "required": ["baz"], + }, + }, + } + + validator = validators.Draft202012Validator(schema) + e1, e2 = validator.iter_errors({"aprop": {}}) + self.assertEqual( + ( + e1.message, + e1.validator, + e1.validator_value, + e1.instance, + e1.absolute_path, + e1.schema, + e1.schema_path, + e1.relative_schema_path, + e1.json_path, + ), + ( + "'bar' is a required property", + "required", + ["bar"], + {}, + deque(["aprop"]), + {"required": ["bar"]}, + deque(["properties", "aprop", "required"]), + deque(["properties", "aprop", "required"]), + "$.aprop", + ), + ) + self.assertEqual( + ( + e2.message, + e2.validator, + e2.validator_value, + e2.instance, + e2.absolute_path, + e2.schema, + e2.schema_path, + e2.relative_schema_path, + e2.json_path, + ), + ( + "'baz' is a required property", + "required", + ["baz"], + {}, + deque(["aprop"]), + {"$ref": "#/$defs/foo", "required": ["baz"]}, + deque(["properties", "aprop", "required"]), + deque(["properties", "aprop", "required"]), + "$.aprop", + ), + ) + + +class MetaSchemaTestsMixin: + # TODO: These all belong upstream + def test_invalid_properties(self): + with self.assertRaises(exceptions.SchemaError): + self.Validator.check_schema({"properties": 12}) + + def test_minItems_invalid_string(self): + with self.assertRaises(exceptions.SchemaError): + # needs to be an integer + self.Validator.check_schema({"minItems": "1"}) + + def test_enum_allows_empty_arrays(self): + """ + Technically, all the spec says is they SHOULD have elements, not MUST. + + (As of Draft 6. Previous drafts do say MUST). + + See #529. + """ + if self.Validator in { + validators.Draft3Validator, + validators.Draft4Validator, + }: + with self.assertRaises(exceptions.SchemaError): + self.Validator.check_schema({"enum": []}) + else: + self.Validator.check_schema({"enum": []}) + + def test_enum_allows_non_unique_items(self): + """ + Technically, all the spec says is they SHOULD be unique, not MUST. + + (As of Draft 6. Previous drafts do say MUST). + + See #529. + """ + if self.Validator in { + validators.Draft3Validator, + validators.Draft4Validator, + }: + with self.assertRaises(exceptions.SchemaError): + self.Validator.check_schema({"enum": [12, 12]}) + else: + self.Validator.check_schema({"enum": [12, 12]}) + + def test_schema_with_invalid_regex(self): + with self.assertRaises(exceptions.SchemaError): + self.Validator.check_schema({"pattern": "*notaregex"}) + + def test_schema_with_invalid_regex_with_disabled_format_validation(self): + self.Validator.check_schema( + {"pattern": "*notaregex"}, + format_checker=None, + ) + + +class ValidatorTestMixin(MetaSchemaTestsMixin): + def test_it_implements_the_validator_protocol(self): + self.assertIsInstance(self.Validator({}), protocols.Validator) + + def test_valid_instances_are_valid(self): + schema, instance = self.valid + self.assertTrue(self.Validator(schema).is_valid(instance)) + + def test_invalid_instances_are_not_valid(self): + schema, instance = self.invalid + self.assertFalse(self.Validator(schema).is_valid(instance)) + + def test_non_existent_properties_are_ignored(self): + self.Validator({object(): object()}).validate(instance=object()) + + def test_evolve(self): + schema, format_checker = {"type": "integer"}, FormatChecker() + original = self.Validator( + schema, + format_checker=format_checker, + ) + new = original.evolve( + schema={"type": "string"}, + format_checker=self.Validator.FORMAT_CHECKER, + ) + + expected = self.Validator( + {"type": "string"}, + format_checker=self.Validator.FORMAT_CHECKER, + _resolver=new._resolver, + ) + + self.assertEqual(new, expected) + self.assertNotEqual(new, original) + + def test_evolve_with_subclass(self): + """ + Subclassing validators isn't supported public API, but some users have + done it, because we don't actually error entirely when it's done :/ + + We need to deprecate doing so first to help as many of these users + ensure they can move to supported APIs, but this test ensures that in + the interim, we haven't broken those users. + """ + + with self.assertWarns(DeprecationWarning): + @define + class OhNo(self.Validator): + foo = field(factory=lambda: [1, 2, 3]) + _bar = field(default=37) + + validator = OhNo({}, bar=12) + self.assertEqual(validator.foo, [1, 2, 3]) + + new = validator.evolve(schema={"type": "integer"}) + self.assertEqual(new.foo, [1, 2, 3]) + self.assertEqual(new._bar, 12) + + def test_is_type_is_true_for_valid_type(self): + self.assertTrue(self.Validator({}).is_type("foo", "string")) + + def test_is_type_is_false_for_invalid_type(self): + self.assertFalse(self.Validator({}).is_type("foo", "array")) + + def test_is_type_evades_bool_inheriting_from_int(self): + self.assertFalse(self.Validator({}).is_type(True, "integer")) + self.assertFalse(self.Validator({}).is_type(True, "number")) + + def test_it_can_validate_with_decimals(self): + schema = {"items": {"type": "number"}} + Validator = validators.extend( + self.Validator, + type_checker=self.Validator.TYPE_CHECKER.redefine( + "number", + lambda checker, thing: isinstance( + thing, (int, float, Decimal), + ) and not isinstance(thing, bool), + ), + ) + + validator = Validator(schema) + validator.validate([1, 1.1, Decimal(1) / Decimal(8)]) + + invalid = ["foo", {}, [], True, None] + self.assertEqual( + [error.instance for error in validator.iter_errors(invalid)], + invalid, + ) + + def test_it_returns_true_for_formats_it_does_not_know_about(self): + validator = self.Validator( + {"format": "carrot"}, format_checker=FormatChecker(), + ) + validator.validate("bugs") + + def test_it_does_not_validate_formats_by_default(self): + validator = self.Validator({}) + self.assertIsNone(validator.format_checker) + + def test_it_validates_formats_if_a_checker_is_provided(self): + checker = FormatChecker() + bad = ValueError("Bad!") + + @checker.checks("foo", raises=ValueError) + def check(value): + if value == "good": + return True + elif value == "bad": + raise bad + else: # pragma: no cover + self.fail(f"What is {value}? [Baby Don't Hurt Me]") + + validator = self.Validator( + {"format": "foo"}, format_checker=checker, + ) + + validator.validate("good") + with self.assertRaises(exceptions.ValidationError) as cm: + validator.validate("bad") + + # Make sure original cause is attached + self.assertIs(cm.exception.cause, bad) + + def test_non_string_custom_type(self): + non_string_type = object() + schema = {"type": [non_string_type]} + Crazy = validators.extend( + self.Validator, + type_checker=self.Validator.TYPE_CHECKER.redefine( + non_string_type, + lambda checker, thing: isinstance(thing, int), + ), + ) + Crazy(schema).validate(15) + + def test_it_properly_formats_tuples_in_errors(self): + """ + A tuple instance properly formats validation errors for uniqueItems. + + See #224 + """ + TupleValidator = validators.extend( + self.Validator, + type_checker=self.Validator.TYPE_CHECKER.redefine( + "array", + lambda checker, thing: isinstance(thing, tuple), + ), + ) + with self.assertRaises(exceptions.ValidationError) as e: + TupleValidator({"uniqueItems": True}).validate((1, 1)) + self.assertIn("(1, 1) has non-unique elements", str(e.exception)) + + def test_check_redefined_sequence(self): + """ + Allow array to validate against another defined sequence type + """ + schema = {"type": "array", "uniqueItems": True} + MyMapping = namedtuple("MyMapping", "a, b") + Validator = validators.extend( + self.Validator, + type_checker=self.Validator.TYPE_CHECKER.redefine_many( + { + "array": lambda checker, thing: isinstance( + thing, (list, deque), + ), + "object": lambda checker, thing: isinstance( + thing, (dict, MyMapping), + ), + }, + ), + ) + validator = Validator(schema) + + valid_instances = [ + deque(["a", None, "1", "", True]), + deque([[False], [0]]), + [deque([False]), deque([0])], + [[deque([False])], [deque([0])]], + [[[[[deque([False])]]]], [[[[deque([0])]]]]], + [deque([deque([False])]), deque([deque([0])])], + [MyMapping("a", 0), MyMapping("a", False)], + [ + MyMapping("a", [deque([0])]), + MyMapping("a", [deque([False])]), + ], + [ + MyMapping("a", [MyMapping("a", deque([0]))]), + MyMapping("a", [MyMapping("a", deque([False]))]), + ], + [deque(deque(deque([False]))), deque(deque(deque([0])))], + ] + + for instance in valid_instances: + validator.validate(instance) + + invalid_instances = [ + deque(["a", "b", "a"]), + deque([[False], [False]]), + [deque([False]), deque([False])], + [[deque([False])], [deque([False])]], + [[[[[deque([False])]]]], [[[[deque([False])]]]]], + [deque([deque([False])]), deque([deque([False])])], + [MyMapping("a", False), MyMapping("a", False)], + [ + MyMapping("a", [deque([False])]), + MyMapping("a", [deque([False])]), + ], + [ + MyMapping("a", [MyMapping("a", deque([False]))]), + MyMapping("a", [MyMapping("a", deque([False]))]), + ], + [deque(deque(deque([False]))), deque(deque(deque([False])))], + ] + + for instance in invalid_instances: + with self.assertRaises(exceptions.ValidationError): + validator.validate(instance) + + def test_it_creates_a_ref_resolver_if_not_provided(self): + with self.assertWarns(DeprecationWarning): + resolver = self.Validator({}).resolver + self.assertIsInstance(resolver, validators._RefResolver) + + def test_it_upconverts_from_deprecated_RefResolvers(self): + ref, schema = "someCoolRef", {"type": "integer"} + resolver = validators._RefResolver("", {}, store={ref: schema}) + validator = self.Validator({"$ref": ref}, resolver=resolver) + + with self.assertRaises(exceptions.ValidationError): + validator.validate(None) + + def test_it_upconverts_from_yet_older_deprecated_legacy_RefResolvers(self): + """ + Legacy RefResolvers support only the context manager form of + resolution. + """ + + class LegacyRefResolver: + @contextmanager + def resolving(this, ref): + self.assertEqual(ref, "the ref") + yield {"type": "integer"} + + resolver = LegacyRefResolver() + schema = {"$ref": "the ref"} + + with self.assertRaises(exceptions.ValidationError): + self.Validator(schema, resolver=resolver).validate(None) + + +class AntiDraft6LeakMixin: + """ + Make sure functionality from draft 6 doesn't leak backwards in time. + """ + + def test_True_is_not_a_schema(self): + with self.assertRaises(exceptions.SchemaError) as e: + self.Validator.check_schema(True) + self.assertIn("True is not of type", str(e.exception)) + + def test_False_is_not_a_schema(self): + with self.assertRaises(exceptions.SchemaError) as e: + self.Validator.check_schema(False) + self.assertIn("False is not of type", str(e.exception)) + + def test_True_is_not_a_schema_even_if_you_forget_to_check(self): + with self.assertRaises(Exception) as e: + self.Validator(True).validate(12) + self.assertNotIsInstance(e.exception, exceptions.ValidationError) + + def test_False_is_not_a_schema_even_if_you_forget_to_check(self): + with self.assertRaises(Exception) as e: + self.Validator(False).validate(12) + self.assertNotIsInstance(e.exception, exceptions.ValidationError) + + +class TestDraft3Validator(AntiDraft6LeakMixin, ValidatorTestMixin, TestCase): + Validator = validators.Draft3Validator + valid: tuple[dict, dict] = ({}, {}) + invalid = {"type": "integer"}, "foo" + + def test_any_type_is_valid_for_type_any(self): + validator = self.Validator({"type": "any"}) + validator.validate(object()) + + def test_any_type_is_redefinable(self): + """ + Sigh, because why not. + """ + Crazy = validators.extend( + self.Validator, + type_checker=self.Validator.TYPE_CHECKER.redefine( + "any", lambda checker, thing: isinstance(thing, int), + ), + ) + validator = Crazy({"type": "any"}) + validator.validate(12) + with self.assertRaises(exceptions.ValidationError): + validator.validate("foo") + + def test_is_type_is_true_for_any_type(self): + self.assertTrue(self.Validator({"type": "any"}).is_valid(object())) + + def test_is_type_does_not_evade_bool_if_it_is_being_tested(self): + self.assertTrue(self.Validator({}).is_type(True, "boolean")) + self.assertTrue(self.Validator({"type": "any"}).is_valid(True)) + + +class TestDraft4Validator(AntiDraft6LeakMixin, ValidatorTestMixin, TestCase): + Validator = validators.Draft4Validator + valid: tuple[dict, dict] = ({}, {}) + invalid = {"type": "integer"}, "foo" + + +class TestDraft6Validator(ValidatorTestMixin, TestCase): + Validator = validators.Draft6Validator + valid: tuple[dict, dict] = ({}, {}) + invalid = {"type": "integer"}, "foo" + + +class TestDraft7Validator(ValidatorTestMixin, TestCase): + Validator = validators.Draft7Validator + valid: tuple[dict, dict] = ({}, {}) + invalid = {"type": "integer"}, "foo" + + +class TestDraft201909Validator(ValidatorTestMixin, TestCase): + Validator = validators.Draft201909Validator + valid: tuple[dict, dict] = ({}, {}) + invalid = {"type": "integer"}, "foo" + + +class TestDraft202012Validator(ValidatorTestMixin, TestCase): + Validator = validators.Draft202012Validator + valid: tuple[dict, dict] = ({}, {}) + invalid = {"type": "integer"}, "foo" + + +class TestLatestValidator(TestCase): + """ + These really apply to multiple versions but are easiest to test on one. + """ + + def test_ref_resolvers_may_have_boolean_schemas_stored(self): + ref = "someCoolRef" + schema = {"$ref": ref} + resolver = validators._RefResolver("", {}, store={ref: False}) + validator = validators._LATEST_VERSION(schema, resolver=resolver) + + with self.assertRaises(exceptions.ValidationError): + validator.validate(None) + + +class TestValidatorFor(TestCase): + def test_draft_3(self): + schema = {"$schema": "http://json-schema.org/draft-03/schema"} + self.assertIs( + validators.validator_for(schema), + validators.Draft3Validator, + ) + + schema = {"$schema": "http://json-schema.org/draft-03/schema#"} + self.assertIs( + validators.validator_for(schema), + validators.Draft3Validator, + ) + + def test_draft_4(self): + schema = {"$schema": "http://json-schema.org/draft-04/schema"} + self.assertIs( + validators.validator_for(schema), + validators.Draft4Validator, + ) + + schema = {"$schema": "http://json-schema.org/draft-04/schema#"} + self.assertIs( + validators.validator_for(schema), + validators.Draft4Validator, + ) + + def test_draft_6(self): + schema = {"$schema": "http://json-schema.org/draft-06/schema"} + self.assertIs( + validators.validator_for(schema), + validators.Draft6Validator, + ) + + schema = {"$schema": "http://json-schema.org/draft-06/schema#"} + self.assertIs( + validators.validator_for(schema), + validators.Draft6Validator, + ) + + def test_draft_7(self): + schema = {"$schema": "http://json-schema.org/draft-07/schema"} + self.assertIs( + validators.validator_for(schema), + validators.Draft7Validator, + ) + + schema = {"$schema": "http://json-schema.org/draft-07/schema#"} + self.assertIs( + validators.validator_for(schema), + validators.Draft7Validator, + ) + + def test_draft_201909(self): + schema = {"$schema": "https://json-schema.org/draft/2019-09/schema"} + self.assertIs( + validators.validator_for(schema), + validators.Draft201909Validator, + ) + + schema = {"$schema": "https://json-schema.org/draft/2019-09/schema#"} + self.assertIs( + validators.validator_for(schema), + validators.Draft201909Validator, + ) + + def test_draft_202012(self): + schema = {"$schema": "https://json-schema.org/draft/2020-12/schema"} + self.assertIs( + validators.validator_for(schema), + validators.Draft202012Validator, + ) + + schema = {"$schema": "https://json-schema.org/draft/2020-12/schema#"} + self.assertIs( + validators.validator_for(schema), + validators.Draft202012Validator, + ) + + def test_True(self): + self.assertIs( + validators.validator_for(True), + validators._LATEST_VERSION, + ) + + def test_False(self): + self.assertIs( + validators.validator_for(False), + validators._LATEST_VERSION, + ) + + def test_custom_validator(self): + Validator = validators.create( + meta_schema={"id": "meta schema id"}, + version="12", + id_of=lambda s: s.get("id", ""), + ) + schema = {"$schema": "meta schema id"} + self.assertIs( + validators.validator_for(schema), + Validator, + ) + + def test_custom_validator_draft6(self): + Validator = validators.create( + meta_schema={"$id": "meta schema $id"}, + version="13", + ) + schema = {"$schema": "meta schema $id"} + self.assertIs( + validators.validator_for(schema), + Validator, + ) + + def test_validator_for_jsonschema_default(self): + self.assertIs(validators.validator_for({}), validators._LATEST_VERSION) + + def test_validator_for_custom_default(self): + self.assertIs(validators.validator_for({}, default=None), None) + + def test_warns_if_meta_schema_specified_was_not_found(self): + with self.assertWarns(DeprecationWarning) as cm: + validators.validator_for(schema={"$schema": "unknownSchema"}) + + self.assertEqual(cm.filename, __file__) + self.assertEqual( + str(cm.warning), + "The metaschema specified by $schema was not found. " + "Using the latest draft to validate, but this will raise " + "an error in the future.", + ) + + def test_does_not_warn_if_meta_schema_is_unspecified(self): + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + validators.validator_for(schema={}, default={}) + self.assertFalse(w) + + def test_validator_for_custom_default_with_schema(self): + schema, default = {"$schema": "mailto:foo@example.com"}, object() + self.assertIs(validators.validator_for(schema, default), default) + + +class TestValidate(TestCase): + def assertUses(self, schema, Validator): + result = [] + with mock.patch.object(Validator, "check_schema", result.append): + validators.validate({}, schema) + self.assertEqual(result, [schema]) + + def test_draft3_validator_is_chosen(self): + self.assertUses( + schema={"$schema": "http://json-schema.org/draft-03/schema#"}, + Validator=validators.Draft3Validator, + ) + # Make sure it works without the empty fragment + self.assertUses( + schema={"$schema": "http://json-schema.org/draft-03/schema"}, + Validator=validators.Draft3Validator, + ) + + def test_draft4_validator_is_chosen(self): + self.assertUses( + schema={"$schema": "http://json-schema.org/draft-04/schema#"}, + Validator=validators.Draft4Validator, + ) + # Make sure it works without the empty fragment + self.assertUses( + schema={"$schema": "http://json-schema.org/draft-04/schema"}, + Validator=validators.Draft4Validator, + ) + + def test_draft6_validator_is_chosen(self): + self.assertUses( + schema={"$schema": "http://json-schema.org/draft-06/schema#"}, + Validator=validators.Draft6Validator, + ) + # Make sure it works without the empty fragment + self.assertUses( + schema={"$schema": "http://json-schema.org/draft-06/schema"}, + Validator=validators.Draft6Validator, + ) + + def test_draft7_validator_is_chosen(self): + self.assertUses( + schema={"$schema": "http://json-schema.org/draft-07/schema#"}, + Validator=validators.Draft7Validator, + ) + # Make sure it works without the empty fragment + self.assertUses( + schema={"$schema": "http://json-schema.org/draft-07/schema"}, + Validator=validators.Draft7Validator, + ) + + def test_draft202012_validator_is_chosen(self): + self.assertUses( + schema={ + "$schema": "https://json-schema.org/draft/2020-12/schema#", + }, + Validator=validators.Draft202012Validator, + ) + # Make sure it works without the empty fragment + self.assertUses( + schema={ + "$schema": "https://json-schema.org/draft/2020-12/schema", + }, + Validator=validators.Draft202012Validator, + ) + + def test_draft202012_validator_is_the_default(self): + self.assertUses(schema={}, Validator=validators.Draft202012Validator) + + def test_validation_error_message(self): + with self.assertRaises(exceptions.ValidationError) as e: + validators.validate(12, {"type": "string"}) + self.assertRegex( + str(e.exception), + "(?s)Failed validating '.*' in schema.*On instance", + ) + + def test_schema_error_message(self): + with self.assertRaises(exceptions.SchemaError) as e: + validators.validate(12, {"type": 12}) + self.assertRegex( + str(e.exception), + "(?s)Failed validating '.*' in metaschema.*On schema", + ) + + def test_it_uses_best_match(self): + schema = { + "oneOf": [ + {"type": "number", "minimum": 20}, + {"type": "array"}, + ], + } + with self.assertRaises(exceptions.ValidationError) as e: + validators.validate(12, schema) + self.assertIn("12 is less than the minimum of 20", str(e.exception)) + + +class TestThreading(TestCase): + """ + Threading-related functionality tests. + + jsonschema doesn't promise thread safety, and its validation behavior + across multiple threads may change at any time, but that means it isn't + safe to share *validators* across threads, not that anytime one has + multiple threads that jsonschema won't work (it certainly is intended to). + + These tests ensure that this minimal level of functionality continues to + work. + """ + + def test_validation_across_a_second_thread(self): + failed = [] + + def validate(): + try: + validators.validate(instance=37, schema=True) + except: # pragma: no cover # noqa: E722 + failed.append(sys.exc_info()) + + validate() # just verify it succeeds + + from threading import Thread + thread = Thread(target=validate) + thread.start() + thread.join() + self.assertEqual((thread.is_alive(), failed), (False, [])) + + +class TestReferencing(TestCase): + def test_registry_with_retrieve(self): + def retrieve(uri): + return DRAFT202012.create_resource({"type": "integer"}) + + registry = referencing.Registry(retrieve=retrieve) + schema = {"$ref": "https://example.com/"} + validator = validators.Draft202012Validator(schema, registry=registry) + + self.assertEqual( + (validator.is_valid(12), validator.is_valid("foo")), + (True, False), + ) + + def test_custom_registries_do_not_autoretrieve_remote_resources(self): + registry = referencing.Registry() + schema = {"$ref": "https://example.com/"} + validator = validators.Draft202012Validator(schema, registry=registry) + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + with self.assertRaises(referencing.exceptions.Unresolvable): + validator.validate(12) + self.assertFalse(w) + + +class TestRefResolver(TestCase): + + base_uri = "" + stored_uri = "foo://stored" + stored_schema = {"stored": "schema"} + + def setUp(self): + self.referrer = {} + self.store = {self.stored_uri: self.stored_schema} + self.resolver = validators._RefResolver( + self.base_uri, self.referrer, self.store, + ) + + def test_it_does_not_retrieve_schema_urls_from_the_network(self): + ref = validators.Draft3Validator.META_SCHEMA["id"] + with mock.patch.object(self.resolver, "resolve_remote") as patched: # noqa: SIM117 + with self.resolver.resolving(ref) as resolved: + pass + self.assertEqual(resolved, validators.Draft3Validator.META_SCHEMA) + self.assertFalse(patched.called) + + def test_it_resolves_local_refs(self): + ref = "#/properties/foo" + self.referrer["properties"] = {"foo": object()} + with self.resolver.resolving(ref) as resolved: + self.assertEqual(resolved, self.referrer["properties"]["foo"]) + + def test_it_resolves_local_refs_with_id(self): + schema = {"id": "http://bar/schema#", "a": {"foo": "bar"}} + resolver = validators._RefResolver.from_schema( + schema, + id_of=lambda schema: schema.get("id", ""), + ) + with resolver.resolving("#/a") as resolved: + self.assertEqual(resolved, schema["a"]) + with resolver.resolving("http://bar/schema#/a") as resolved: + self.assertEqual(resolved, schema["a"]) + + def test_it_retrieves_stored_refs(self): + with self.resolver.resolving(self.stored_uri) as resolved: + self.assertIs(resolved, self.stored_schema) + + self.resolver.store["cached_ref"] = {"foo": 12} + with self.resolver.resolving("cached_ref#/foo") as resolved: + self.assertEqual(resolved, 12) + + def test_it_retrieves_unstored_refs_via_requests(self): + ref = "http://bar#baz" + schema = {"baz": 12} + + if "requests" in sys.modules: # pragma: no cover + self.addCleanup( + sys.modules.__setitem__, "requests", sys.modules["requests"], + ) + sys.modules["requests"] = ReallyFakeRequests({"http://bar": schema}) + + with self.resolver.resolving(ref) as resolved: + self.assertEqual(resolved, 12) + + def test_it_retrieves_unstored_refs_via_urlopen(self): + ref = "http://bar#baz" + schema = {"baz": 12} + + if "requests" in sys.modules: # pragma: no cover + self.addCleanup( + sys.modules.__setitem__, "requests", sys.modules["requests"], + ) + sys.modules["requests"] = None + + @contextmanager + def fake_urlopen(url): + self.assertEqual(url, "http://bar") + yield BytesIO(json.dumps(schema).encode("utf8")) + + self.addCleanup(setattr, validators, "urlopen", validators.urlopen) + validators.urlopen = fake_urlopen + + with self.resolver.resolving(ref) as resolved: + pass + self.assertEqual(resolved, 12) + + def test_it_retrieves_local_refs_via_urlopen(self): + with tempfile.NamedTemporaryFile(delete=False, mode="wt") as tempf: + self.addCleanup(os.remove, tempf.name) + json.dump({"foo": "bar"}, tempf) + + ref = f"file://{pathname2url(tempf.name)}#foo" + with self.resolver.resolving(ref) as resolved: + self.assertEqual(resolved, "bar") + + def test_it_can_construct_a_base_uri_from_a_schema(self): + schema = {"id": "foo"} + resolver = validators._RefResolver.from_schema( + schema, + id_of=lambda schema: schema.get("id", ""), + ) + self.assertEqual(resolver.base_uri, "foo") + self.assertEqual(resolver.resolution_scope, "foo") + with resolver.resolving("") as resolved: + self.assertEqual(resolved, schema) + with resolver.resolving("#") as resolved: + self.assertEqual(resolved, schema) + with resolver.resolving("foo") as resolved: + self.assertEqual(resolved, schema) + with resolver.resolving("foo#") as resolved: + self.assertEqual(resolved, schema) + + def test_it_can_construct_a_base_uri_from_a_schema_without_id(self): + schema = {} + resolver = validators._RefResolver.from_schema(schema) + self.assertEqual(resolver.base_uri, "") + self.assertEqual(resolver.resolution_scope, "") + with resolver.resolving("") as resolved: + self.assertEqual(resolved, schema) + with resolver.resolving("#") as resolved: + self.assertEqual(resolved, schema) + + def test_custom_uri_scheme_handlers(self): + def handler(url): + self.assertEqual(url, ref) + return schema + + schema = {"foo": "bar"} + ref = "foo://bar" + resolver = validators._RefResolver("", {}, handlers={"foo": handler}) + with resolver.resolving(ref) as resolved: + self.assertEqual(resolved, schema) + + def test_cache_remote_on(self): + response = [object()] + + def handler(url): + try: + return response.pop() + except IndexError: # pragma: no cover + self.fail("Response must not have been cached!") + + ref = "foo://bar" + resolver = validators._RefResolver( + "", {}, cache_remote=True, handlers={"foo": handler}, + ) + with resolver.resolving(ref): + pass + with resolver.resolving(ref): + pass + + def test_cache_remote_off(self): + response = [object()] + + def handler(url): + try: + return response.pop() + except IndexError: # pragma: no cover + self.fail("Handler called twice!") + + ref = "foo://bar" + resolver = validators._RefResolver( + "", {}, cache_remote=False, handlers={"foo": handler}, + ) + with resolver.resolving(ref): + pass + + def test_if_you_give_it_junk_you_get_a_resolution_error(self): + error = ValueError("Oh no! What's this?") + + def handler(url): + raise error + + ref = "foo://bar" + resolver = validators._RefResolver("", {}, handlers={"foo": handler}) + with self.assertRaises(exceptions._RefResolutionError) as err: # noqa: SIM117 + with resolver.resolving(ref): + self.fail("Shouldn't get this far!") # pragma: no cover + self.assertEqual(err.exception, exceptions._RefResolutionError(error)) + + def test_helpful_error_message_on_failed_pop_scope(self): + resolver = validators._RefResolver("", {}) + resolver.pop_scope() + with self.assertRaises(exceptions._RefResolutionError) as exc: + resolver.pop_scope() + self.assertIn("Failed to pop the scope", str(exc.exception)) + + def test_pointer_within_schema_with_different_id(self): + """ + See #1085. + """ + schema = validators.Draft7Validator.META_SCHEMA + one = validators._RefResolver("", schema) + validator = validators.Draft7Validator(schema, resolver=one) + self.assertFalse(validator.is_valid({"maxLength": "foo"})) + + another = { + "allOf": [{"$ref": validators.Draft7Validator.META_SCHEMA["$id"]}], + } + two = validators._RefResolver("", another) + validator = validators.Draft7Validator(another, resolver=two) + self.assertFalse(validator.is_valid({"maxLength": "foo"})) + + def test_newly_created_validator_with_ref_resolver(self): + """ + See https://github.com/python-jsonschema/jsonschema/issues/1061#issuecomment-1624266555. + """ + + def handle(uri): + self.assertEqual(uri, "http://example.com/foo") + return {"type": "integer"} + + resolver = validators._RefResolver("", {}, handlers={"http": handle}) + Validator = validators.create( + meta_schema={}, + validators=validators.Draft4Validator.VALIDATORS, + ) + schema = {"$id": "http://example.com/bar", "$ref": "foo"} + validator = Validator(schema, resolver=resolver) + self.assertEqual( + (validator.is_valid({}), validator.is_valid(37)), + (False, True), + ) + + def test_refresolver_with_pointer_in_schema_with_no_id(self): + """ + See https://github.com/python-jsonschema/jsonschema/issues/1124#issuecomment-1632574249. + """ + + schema = { + "properties": {"x": {"$ref": "#/definitions/x"}}, + "definitions": {"x": {"type": "integer"}}, + } + + validator = validators.Draft202012Validator( + schema, + resolver=validators._RefResolver("", schema), + ) + self.assertEqual( + (validator.is_valid({"x": "y"}), validator.is_valid({"x": 37})), + (False, True), + ) + + + +def sorted_errors(errors): + def key(error): + return ( + [str(e) for e in error.path], + [str(e) for e in error.schema_path], + ) + return sorted(errors, key=key) + + +@define +class ReallyFakeRequests: + + _responses: dict[str, Any] + + def get(self, url): + response = self._responses.get(url) + if url is None: # pragma: no cover + raise ValueError("Unknown URL: " + repr(url)) + return _ReallyFakeJSONResponse(json.dumps(response)) + + +@define +class _ReallyFakeJSONResponse: + + _response: str + + def json(self): + return json.loads(self._response) diff --git a/.venv/lib/python3.10/site-packages/jsonschema/validators.py b/.venv/lib/python3.10/site-packages/jsonschema/validators.py new file mode 100644 index 0000000..85c3916 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema/validators.py @@ -0,0 +1,1410 @@ +""" +Creation and extension of validators, with implementations for existing drafts. +""" +from __future__ import annotations + +from collections import deque +from collections.abc import Iterable, Mapping, Sequence +from functools import lru_cache +from operator import methodcaller +from typing import TYPE_CHECKING +from urllib.parse import unquote, urldefrag, urljoin, urlsplit +from urllib.request import urlopen +from warnings import warn +import contextlib +import json +import reprlib +import warnings + +from attrs import define, field, fields +from jsonschema_specifications import REGISTRY as SPECIFICATIONS +from rpds import HashTrieMap +import referencing.exceptions +import referencing.jsonschema + +from jsonschema import ( + _format, + _keywords, + _legacy_keywords, + _types, + _typing, + _utils, + exceptions, +) + +if TYPE_CHECKING: + from jsonschema.protocols import Validator + +_UNSET = _utils.Unset() + +_VALIDATORS: dict[str, Validator] = {} +_META_SCHEMAS = _utils.URIDict() + + +def __getattr__(name): + if name == "ErrorTree": + warnings.warn( + "Importing ErrorTree from jsonschema.validators is deprecated. " + "Instead import it from jsonschema.exceptions.", + DeprecationWarning, + stacklevel=2, + ) + from jsonschema.exceptions import ErrorTree + return ErrorTree + elif name == "validators": + warnings.warn( + "Accessing jsonschema.validators.validators is deprecated. " + "Use jsonschema.validators.validator_for with a given schema.", + DeprecationWarning, + stacklevel=2, + ) + return _VALIDATORS + elif name == "meta_schemas": + warnings.warn( + "Accessing jsonschema.validators.meta_schemas is deprecated. " + "Use jsonschema.validators.validator_for with a given schema.", + DeprecationWarning, + stacklevel=2, + ) + return _META_SCHEMAS + elif name == "RefResolver": + warnings.warn( + _RefResolver._DEPRECATION_MESSAGE, + DeprecationWarning, + stacklevel=2, + ) + return _RefResolver + raise AttributeError(f"module {__name__} has no attribute {name}") + + +def validates(version): + """ + Register the decorated validator for a ``version`` of the specification. + + Registered validators and their meta schemas will be considered when + parsing :kw:`$schema` keywords' URIs. + + Arguments: + + version (str): + + An identifier to use as the version's name + + Returns: + + collections.abc.Callable: + + a class decorator to decorate the validator with the version + + """ + + def _validates(cls): + _VALIDATORS[version] = cls + meta_schema_id = cls.ID_OF(cls.META_SCHEMA) + _META_SCHEMAS[meta_schema_id] = cls + return cls + return _validates + + +def _warn_for_remote_retrieve(uri: str): + from urllib.request import Request, urlopen + headers = {"User-Agent": "python-jsonschema (deprecated $ref resolution)"} + request = Request(uri, headers=headers) # noqa: S310 + with urlopen(request) as response: # noqa: S310 + warnings.warn( + "Automatically retrieving remote references can be a security " + "vulnerability and is discouraged by the JSON Schema " + "specifications. Relying on this behavior is deprecated " + "and will shortly become an error. If you are sure you want to " + "remotely retrieve your reference and that it is safe to do so, " + "you can find instructions for doing so via referencing.Registry " + "in the referencing documentation " + "(https://referencing.readthedocs.org).", + DeprecationWarning, + stacklevel=9, # Ha ha ha ha magic numbers :/ + ) + return referencing.Resource.from_contents( + json.load(response), + default_specification=referencing.jsonschema.DRAFT202012, + ) + + +_REMOTE_WARNING_REGISTRY = SPECIFICATIONS.combine( + referencing.Registry(retrieve=_warn_for_remote_retrieve), # type: ignore[call-arg] +) + + +def create( + meta_schema: referencing.jsonschema.ObjectSchema, + validators: ( + Mapping[str, _typing.SchemaKeywordValidator] + | Iterable[tuple[str, _typing.SchemaKeywordValidator]] + ) = (), + version: str | None = None, + type_checker: _types.TypeChecker = _types.draft202012_type_checker, + format_checker: _format.FormatChecker = _format.draft202012_format_checker, + id_of: _typing.id_of = referencing.jsonschema.DRAFT202012.id_of, + applicable_validators: _typing.ApplicableValidators = methodcaller( + "items", + ), +): + """ + Create a new validator class. + + Arguments: + + meta_schema: + + the meta schema for the new validator class + + validators: + + a mapping from names to callables, where each callable will + validate the schema property with the given name. + + Each callable should take 4 arguments: + + 1. a validator instance, + 2. the value of the property being validated within the + instance + 3. the instance + 4. the schema + + version: + + an identifier for the version that this validator class will + validate. If provided, the returned validator class will + have its ``__name__`` set to include the version, and also + will have `jsonschema.validators.validates` automatically + called for the given version. + + type_checker: + + a type checker, used when applying the :kw:`type` keyword. + + If unprovided, a `jsonschema.TypeChecker` will be created + with a set of default types typical of JSON Schema drafts. + + format_checker: + + a format checker, used when applying the :kw:`format` keyword. + + If unprovided, a `jsonschema.FormatChecker` will be created + with a set of default formats typical of JSON Schema drafts. + + id_of: + + A function that given a schema, returns its ID. + + applicable_validators: + + A function that, given a schema, returns the list of + applicable schema keywords and associated values + which will be used to validate the instance. + This is mostly used to support pre-draft 7 versions of JSON Schema + which specified behavior around ignoring keywords if they were + siblings of a ``$ref`` keyword. If you're not attempting to + implement similar behavior, you can typically ignore this argument + and leave it at its default. + + Returns: + + a new `jsonschema.protocols.Validator` class + + """ + # preemptively don't shadow the `Validator.format_checker` local + format_checker_arg = format_checker + + specification = referencing.jsonschema.specification_with( + dialect_id=id_of(meta_schema) or "urn:unknown-dialect", + default=referencing.Specification.OPAQUE, + ) + + @define + class Validator: + + VALIDATORS = dict(validators) # noqa: RUF012 + META_SCHEMA = dict(meta_schema) # noqa: RUF012 + TYPE_CHECKER = type_checker + FORMAT_CHECKER = format_checker_arg + ID_OF = staticmethod(id_of) + + _APPLICABLE_VALIDATORS = applicable_validators + _validators = field(init=False, repr=False, eq=False) + + schema: referencing.jsonschema.Schema = field(repr=reprlib.repr) + _ref_resolver = field(default=None, repr=False, alias="resolver") + format_checker: _format.FormatChecker | None = field(default=None) + # TODO: include new meta-schemas added at runtime + _registry: referencing.jsonschema.SchemaRegistry = field( + default=_REMOTE_WARNING_REGISTRY, + kw_only=True, + repr=False, + ) + _resolver = field( + alias="_resolver", + default=None, + kw_only=True, + repr=False, + ) + + def __init_subclass__(cls): + warnings.warn( + ( + "Subclassing validator classes is not intended to " + "be part of their public API. A future version " + "will make doing so an error, as the behavior of " + "subclasses isn't guaranteed to stay the same " + "between releases of jsonschema. Instead, prefer " + "composition of validators, wrapping them in an object " + "owned entirely by the downstream library." + ), + DeprecationWarning, + stacklevel=2, + ) + + def evolve(self, **changes): + cls = self.__class__ + schema = changes.setdefault("schema", self.schema) + NewValidator = validator_for(schema, default=cls) + + for field in fields(cls): # noqa: F402 + if not field.init: + continue + attr_name = field.name + init_name = field.alias + if init_name not in changes: + changes[init_name] = getattr(self, attr_name) + + return NewValidator(**changes) + + cls.evolve = evolve + + def __attrs_post_init__(self): + if self._resolver is None: + registry = self._registry + if registry is not _REMOTE_WARNING_REGISTRY: + registry = SPECIFICATIONS.combine(registry) + resource = specification.create_resource(self.schema) + self._resolver = registry.resolver_with_root(resource) + + if self.schema is True or self.schema is False: + self._validators = [] + else: + self._validators = [ + (self.VALIDATORS[k], k, v) + for k, v in applicable_validators(self.schema) + if k in self.VALIDATORS + ] + + # REMOVEME: Legacy ref resolution state management. + push_scope = getattr(self._ref_resolver, "push_scope", None) + if push_scope is not None: + id = id_of(self.schema) + if id is not None: + push_scope(id) + + @classmethod + def check_schema(cls, schema, format_checker=_UNSET): + Validator = validator_for(cls.META_SCHEMA, default=cls) + if format_checker is _UNSET: + format_checker = Validator.FORMAT_CHECKER + validator = Validator( + schema=cls.META_SCHEMA, + format_checker=format_checker, + ) + for error in validator.iter_errors(schema): + raise exceptions.SchemaError.create_from(error) + + @property + def resolver(self): + warnings.warn( + ( + f"Accessing {self.__class__.__name__}.resolver is " + "deprecated as of v4.18.0, in favor of the " + "https://github.com/python-jsonschema/referencing " + "library, which provides more compliant referencing " + "behavior as well as more flexible APIs for " + "customization." + ), + DeprecationWarning, + stacklevel=2, + ) + if self._ref_resolver is None: + self._ref_resolver = _RefResolver.from_schema( + self.schema, + id_of=id_of, + ) + return self._ref_resolver + + def evolve(self, **changes): + schema = changes.setdefault("schema", self.schema) + NewValidator = validator_for(schema, default=self.__class__) + + for (attr_name, init_name) in evolve_fields: + if init_name not in changes: + changes[init_name] = getattr(self, attr_name) + + return NewValidator(**changes) + + def iter_errors(self, instance, _schema=None): + if _schema is not None: + warnings.warn( + ( + "Passing a schema to Validator.iter_errors " + "is deprecated and will be removed in a future " + "release. Call validator.evolve(schema=new_schema)." + "iter_errors(...) instead." + ), + DeprecationWarning, + stacklevel=2, + ) + validators = [ + (self.VALIDATORS[k], k, v) + for k, v in applicable_validators(_schema) + if k in self.VALIDATORS + ] + else: + _schema, validators = self.schema, self._validators + + if _schema is True: + return + elif _schema is False: + yield exceptions.ValidationError( + f"False schema does not allow {instance!r}", + validator=None, + validator_value=None, + instance=instance, + schema=_schema, + ) + return + + for validator, k, v in validators: + errors = validator(self, v, instance, _schema) or () + for error in errors: + # set details if not already set by the called fn + error._set( + validator=k, + validator_value=v, + instance=instance, + schema=_schema, + type_checker=self.TYPE_CHECKER, + ) + if k not in {"if", "$ref"}: + error.schema_path.appendleft(k) + yield error + + def descend( + self, + instance, + schema, + path=None, + schema_path=None, + resolver=None, + ): + if schema is True: + return + elif schema is False: + yield exceptions.ValidationError( + f"False schema does not allow {instance!r}", + validator=None, + validator_value=None, + instance=instance, + schema=schema, + ) + return + + if self._ref_resolver is not None: + evolved = self.evolve(schema=schema) + else: + if resolver is None: + resolver = self._resolver.in_subresource( + specification.create_resource(schema), + ) + evolved = self.evolve(schema=schema, _resolver=resolver) + + for k, v in applicable_validators(schema): + validator = evolved.VALIDATORS.get(k) + if validator is None: + continue + + errors = validator(evolved, v, instance, schema) or () + for error in errors: + # set details if not already set by the called fn + error._set( + validator=k, + validator_value=v, + instance=instance, + schema=schema, + type_checker=evolved.TYPE_CHECKER, + ) + if k not in {"if", "$ref"}: + error.schema_path.appendleft(k) + if path is not None: + error.path.appendleft(path) + if schema_path is not None: + error.schema_path.appendleft(schema_path) + yield error + + def validate(self, *args, **kwargs): + for error in self.iter_errors(*args, **kwargs): + raise error + + def is_type(self, instance, type): + try: + return self.TYPE_CHECKER.is_type(instance, type) + except exceptions.UndefinedTypeCheck: + exc = exceptions.UnknownType(type, instance, self.schema) + raise exc from None + + def _validate_reference(self, ref, instance): + if self._ref_resolver is None: + try: + resolved = self._resolver.lookup(ref) + except referencing.exceptions.Unresolvable as err: + raise exceptions._WrappedReferencingError(err) from err + + return self.descend( + instance, + resolved.contents, + resolver=resolved.resolver, + ) + else: + resolve = getattr(self._ref_resolver, "resolve", None) + if resolve is None: + with self._ref_resolver.resolving(ref) as resolved: + return self.descend(instance, resolved) + else: + scope, resolved = resolve(ref) + self._ref_resolver.push_scope(scope) + + try: + return list(self.descend(instance, resolved)) + finally: + self._ref_resolver.pop_scope() + + def is_valid(self, instance, _schema=None): + if _schema is not None: + warnings.warn( + ( + "Passing a schema to Validator.is_valid is deprecated " + "and will be removed in a future release. Call " + "validator.evolve(schema=new_schema).is_valid(...) " + "instead." + ), + DeprecationWarning, + stacklevel=2, + ) + self = self.evolve(schema=_schema) + + error = next(self.iter_errors(instance), None) + return error is None + + evolve_fields = [ + (field.name, field.alias) + for field in fields(Validator) + if field.init + ] + + if version is not None: + safe = version.title().replace(" ", "").replace("-", "") + Validator.__name__ = Validator.__qualname__ = f"{safe}Validator" + Validator = validates(version)(Validator) # type: ignore[misc] + + return Validator + + +def extend( + validator, + validators=(), + version=None, + type_checker=None, + format_checker=None, +): + """ + Create a new validator class by extending an existing one. + + Arguments: + + validator (jsonschema.protocols.Validator): + + an existing validator class + + validators (collections.abc.Mapping): + + a mapping of new validator callables to extend with, whose + structure is as in `create`. + + .. note:: + + Any validator callables with the same name as an + existing one will (silently) replace the old validator + callable entirely, effectively overriding any validation + done in the "parent" validator class. + + If you wish to instead extend the behavior of a parent's + validator callable, delegate and call it directly in + the new validator function by retrieving it using + ``OldValidator.VALIDATORS["validation_keyword_name"]``. + + version (str): + + a version for the new validator class + + type_checker (jsonschema.TypeChecker): + + a type checker, used when applying the :kw:`type` keyword. + + If unprovided, the type checker of the extended + `jsonschema.protocols.Validator` will be carried along. + + format_checker (jsonschema.FormatChecker): + + a format checker, used when applying the :kw:`format` keyword. + + If unprovided, the format checker of the extended + `jsonschema.protocols.Validator` will be carried along. + + Returns: + + a new `jsonschema.protocols.Validator` class extending the one + provided + + .. note:: Meta Schemas + + The new validator class will have its parent's meta schema. + + If you wish to change or extend the meta schema in the new + validator class, modify ``META_SCHEMA`` directly on the returned + class. Note that no implicit copying is done, so a copy should + likely be made before modifying it, in order to not affect the + old validator. + + """ + all_validators = dict(validator.VALIDATORS) + all_validators.update(validators) + + if type_checker is None: + type_checker = validator.TYPE_CHECKER + if format_checker is None: + format_checker = validator.FORMAT_CHECKER + return create( + meta_schema=validator.META_SCHEMA, + validators=all_validators, + version=version, + type_checker=type_checker, + format_checker=format_checker, + id_of=validator.ID_OF, + applicable_validators=validator._APPLICABLE_VALIDATORS, + ) + + +Draft3Validator = create( + meta_schema=SPECIFICATIONS.contents( + "http://json-schema.org/draft-03/schema#", + ), + validators={ + "$ref": _keywords.ref, + "additionalItems": _legacy_keywords.additionalItems, + "additionalProperties": _keywords.additionalProperties, + "dependencies": _legacy_keywords.dependencies_draft3, + "disallow": _legacy_keywords.disallow_draft3, + "divisibleBy": _keywords.multipleOf, + "enum": _keywords.enum, + "extends": _legacy_keywords.extends_draft3, + "format": _keywords.format, + "items": _legacy_keywords.items_draft3_draft4, + "maxItems": _keywords.maxItems, + "maxLength": _keywords.maxLength, + "maximum": _legacy_keywords.maximum_draft3_draft4, + "minItems": _keywords.minItems, + "minLength": _keywords.minLength, + "minimum": _legacy_keywords.minimum_draft3_draft4, + "pattern": _keywords.pattern, + "patternProperties": _keywords.patternProperties, + "properties": _legacy_keywords.properties_draft3, + "type": _legacy_keywords.type_draft3, + "uniqueItems": _keywords.uniqueItems, + }, + type_checker=_types.draft3_type_checker, + format_checker=_format.draft3_format_checker, + version="draft3", + id_of=referencing.jsonschema.DRAFT3.id_of, + applicable_validators=_legacy_keywords.ignore_ref_siblings, +) + +Draft4Validator = create( + meta_schema=SPECIFICATIONS.contents( + "http://json-schema.org/draft-04/schema#", + ), + validators={ + "$ref": _keywords.ref, + "additionalItems": _legacy_keywords.additionalItems, + "additionalProperties": _keywords.additionalProperties, + "allOf": _keywords.allOf, + "anyOf": _keywords.anyOf, + "dependencies": _legacy_keywords.dependencies_draft4_draft6_draft7, + "enum": _keywords.enum, + "format": _keywords.format, + "items": _legacy_keywords.items_draft3_draft4, + "maxItems": _keywords.maxItems, + "maxLength": _keywords.maxLength, + "maxProperties": _keywords.maxProperties, + "maximum": _legacy_keywords.maximum_draft3_draft4, + "minItems": _keywords.minItems, + "minLength": _keywords.minLength, + "minProperties": _keywords.minProperties, + "minimum": _legacy_keywords.minimum_draft3_draft4, + "multipleOf": _keywords.multipleOf, + "not": _keywords.not_, + "oneOf": _keywords.oneOf, + "pattern": _keywords.pattern, + "patternProperties": _keywords.patternProperties, + "properties": _keywords.properties, + "required": _keywords.required, + "type": _keywords.type, + "uniqueItems": _keywords.uniqueItems, + }, + type_checker=_types.draft4_type_checker, + format_checker=_format.draft4_format_checker, + version="draft4", + id_of=referencing.jsonschema.DRAFT4.id_of, + applicable_validators=_legacy_keywords.ignore_ref_siblings, +) + +Draft6Validator = create( + meta_schema=SPECIFICATIONS.contents( + "http://json-schema.org/draft-06/schema#", + ), + validators={ + "$ref": _keywords.ref, + "additionalItems": _legacy_keywords.additionalItems, + "additionalProperties": _keywords.additionalProperties, + "allOf": _keywords.allOf, + "anyOf": _keywords.anyOf, + "const": _keywords.const, + "contains": _legacy_keywords.contains_draft6_draft7, + "dependencies": _legacy_keywords.dependencies_draft4_draft6_draft7, + "enum": _keywords.enum, + "exclusiveMaximum": _keywords.exclusiveMaximum, + "exclusiveMinimum": _keywords.exclusiveMinimum, + "format": _keywords.format, + "items": _legacy_keywords.items_draft6_draft7_draft201909, + "maxItems": _keywords.maxItems, + "maxLength": _keywords.maxLength, + "maxProperties": _keywords.maxProperties, + "maximum": _keywords.maximum, + "minItems": _keywords.minItems, + "minLength": _keywords.minLength, + "minProperties": _keywords.minProperties, + "minimum": _keywords.minimum, + "multipleOf": _keywords.multipleOf, + "not": _keywords.not_, + "oneOf": _keywords.oneOf, + "pattern": _keywords.pattern, + "patternProperties": _keywords.patternProperties, + "properties": _keywords.properties, + "propertyNames": _keywords.propertyNames, + "required": _keywords.required, + "type": _keywords.type, + "uniqueItems": _keywords.uniqueItems, + }, + type_checker=_types.draft6_type_checker, + format_checker=_format.draft6_format_checker, + version="draft6", + id_of=referencing.jsonschema.DRAFT6.id_of, + applicable_validators=_legacy_keywords.ignore_ref_siblings, +) + +Draft7Validator = create( + meta_schema=SPECIFICATIONS.contents( + "http://json-schema.org/draft-07/schema#", + ), + validators={ + "$ref": _keywords.ref, + "additionalItems": _legacy_keywords.additionalItems, + "additionalProperties": _keywords.additionalProperties, + "allOf": _keywords.allOf, + "anyOf": _keywords.anyOf, + "const": _keywords.const, + "contains": _legacy_keywords.contains_draft6_draft7, + "dependencies": _legacy_keywords.dependencies_draft4_draft6_draft7, + "enum": _keywords.enum, + "exclusiveMaximum": _keywords.exclusiveMaximum, + "exclusiveMinimum": _keywords.exclusiveMinimum, + "format": _keywords.format, + "if": _keywords.if_, + "items": _legacy_keywords.items_draft6_draft7_draft201909, + "maxItems": _keywords.maxItems, + "maxLength": _keywords.maxLength, + "maxProperties": _keywords.maxProperties, + "maximum": _keywords.maximum, + "minItems": _keywords.minItems, + "minLength": _keywords.minLength, + "minProperties": _keywords.minProperties, + "minimum": _keywords.minimum, + "multipleOf": _keywords.multipleOf, + "not": _keywords.not_, + "oneOf": _keywords.oneOf, + "pattern": _keywords.pattern, + "patternProperties": _keywords.patternProperties, + "properties": _keywords.properties, + "propertyNames": _keywords.propertyNames, + "required": _keywords.required, + "type": _keywords.type, + "uniqueItems": _keywords.uniqueItems, + }, + type_checker=_types.draft7_type_checker, + format_checker=_format.draft7_format_checker, + version="draft7", + id_of=referencing.jsonschema.DRAFT7.id_of, + applicable_validators=_legacy_keywords.ignore_ref_siblings, +) + +Draft201909Validator = create( + meta_schema=SPECIFICATIONS.contents( + "https://json-schema.org/draft/2019-09/schema", + ), + validators={ + "$recursiveRef": _legacy_keywords.recursiveRef, + "$ref": _keywords.ref, + "additionalItems": _legacy_keywords.additionalItems, + "additionalProperties": _keywords.additionalProperties, + "allOf": _keywords.allOf, + "anyOf": _keywords.anyOf, + "const": _keywords.const, + "contains": _keywords.contains, + "dependentRequired": _keywords.dependentRequired, + "dependentSchemas": _keywords.dependentSchemas, + "enum": _keywords.enum, + "exclusiveMaximum": _keywords.exclusiveMaximum, + "exclusiveMinimum": _keywords.exclusiveMinimum, + "format": _keywords.format, + "if": _keywords.if_, + "items": _legacy_keywords.items_draft6_draft7_draft201909, + "maxItems": _keywords.maxItems, + "maxLength": _keywords.maxLength, + "maxProperties": _keywords.maxProperties, + "maximum": _keywords.maximum, + "minItems": _keywords.minItems, + "minLength": _keywords.minLength, + "minProperties": _keywords.minProperties, + "minimum": _keywords.minimum, + "multipleOf": _keywords.multipleOf, + "not": _keywords.not_, + "oneOf": _keywords.oneOf, + "pattern": _keywords.pattern, + "patternProperties": _keywords.patternProperties, + "properties": _keywords.properties, + "propertyNames": _keywords.propertyNames, + "required": _keywords.required, + "type": _keywords.type, + "unevaluatedItems": _legacy_keywords.unevaluatedItems_draft2019, + "unevaluatedProperties": ( + _legacy_keywords.unevaluatedProperties_draft2019 + ), + "uniqueItems": _keywords.uniqueItems, + }, + type_checker=_types.draft201909_type_checker, + format_checker=_format.draft201909_format_checker, + version="draft2019-09", +) + +Draft202012Validator = create( + meta_schema=SPECIFICATIONS.contents( + "https://json-schema.org/draft/2020-12/schema", + ), + validators={ + "$dynamicRef": _keywords.dynamicRef, + "$ref": _keywords.ref, + "additionalProperties": _keywords.additionalProperties, + "allOf": _keywords.allOf, + "anyOf": _keywords.anyOf, + "const": _keywords.const, + "contains": _keywords.contains, + "dependentRequired": _keywords.dependentRequired, + "dependentSchemas": _keywords.dependentSchemas, + "enum": _keywords.enum, + "exclusiveMaximum": _keywords.exclusiveMaximum, + "exclusiveMinimum": _keywords.exclusiveMinimum, + "format": _keywords.format, + "if": _keywords.if_, + "items": _keywords.items, + "maxItems": _keywords.maxItems, + "maxLength": _keywords.maxLength, + "maxProperties": _keywords.maxProperties, + "maximum": _keywords.maximum, + "minItems": _keywords.minItems, + "minLength": _keywords.minLength, + "minProperties": _keywords.minProperties, + "minimum": _keywords.minimum, + "multipleOf": _keywords.multipleOf, + "not": _keywords.not_, + "oneOf": _keywords.oneOf, + "pattern": _keywords.pattern, + "patternProperties": _keywords.patternProperties, + "prefixItems": _keywords.prefixItems, + "properties": _keywords.properties, + "propertyNames": _keywords.propertyNames, + "required": _keywords.required, + "type": _keywords.type, + "unevaluatedItems": _keywords.unevaluatedItems, + "unevaluatedProperties": _keywords.unevaluatedProperties, + "uniqueItems": _keywords.uniqueItems, + }, + type_checker=_types.draft202012_type_checker, + format_checker=_format.draft202012_format_checker, + version="draft2020-12", +) + +_LATEST_VERSION = Draft202012Validator + + +class _RefResolver: + """ + Resolve JSON References. + + Arguments: + + base_uri (str): + + The URI of the referring document + + referrer: + + The actual referring document + + store (dict): + + A mapping from URIs to documents to cache + + cache_remote (bool): + + Whether remote refs should be cached after first resolution + + handlers (dict): + + A mapping from URI schemes to functions that should be used + to retrieve them + + urljoin_cache (:func:`functools.lru_cache`): + + A cache that will be used for caching the results of joining + the resolution scope to subscopes. + + remote_cache (:func:`functools.lru_cache`): + + A cache that will be used for caching the results of + resolved remote URLs. + + Attributes: + + cache_remote (bool): + + Whether remote refs should be cached after first resolution + + .. deprecated:: v4.18.0 + + ``RefResolver`` has been deprecated in favor of `referencing`. + + """ + + _DEPRECATION_MESSAGE = ( + "jsonschema.RefResolver is deprecated as of v4.18.0, in favor of the " + "https://github.com/python-jsonschema/referencing library, which " + "provides more compliant referencing behavior as well as more " + "flexible APIs for customization. A future release will remove " + "RefResolver. Please file a feature request (on referencing) if you " + "are missing an API for the kind of customization you need." + ) + + def __init__( + self, + base_uri, + referrer, + store=HashTrieMap(), + cache_remote=True, + handlers=(), + urljoin_cache=None, + remote_cache=None, + ): + if urljoin_cache is None: + urljoin_cache = lru_cache(1024)(urljoin) + if remote_cache is None: + remote_cache = lru_cache(1024)(self.resolve_from_url) + + self.referrer = referrer + self.cache_remote = cache_remote + self.handlers = dict(handlers) + + self._scopes_stack = [base_uri] + + self.store = _utils.URIDict( + (uri, each.contents) for uri, each in SPECIFICATIONS.items() + ) + self.store.update( + (id, each.META_SCHEMA) for id, each in _META_SCHEMAS.items() + ) + self.store.update(store) + self.store.update( + (schema["$id"], schema) + for schema in store.values() + if isinstance(schema, Mapping) and "$id" in schema + ) + self.store[base_uri] = referrer + + self._urljoin_cache = urljoin_cache + self._remote_cache = remote_cache + + @classmethod + def from_schema( # noqa: D417 + cls, + schema, + id_of=referencing.jsonschema.DRAFT202012.id_of, + *args, + **kwargs, + ): + """ + Construct a resolver from a JSON schema object. + + Arguments: + + schema: + + the referring schema + + Returns: + + `_RefResolver` + + """ + return cls(base_uri=id_of(schema) or "", referrer=schema, *args, **kwargs) # noqa: B026, E501 + + def push_scope(self, scope): + """ + Enter a given sub-scope. + + Treats further dereferences as being performed underneath the + given scope. + """ + self._scopes_stack.append( + self._urljoin_cache(self.resolution_scope, scope), + ) + + def pop_scope(self): + """ + Exit the most recent entered scope. + + Treats further dereferences as being performed underneath the + original scope. + + Don't call this method more times than `push_scope` has been + called. + """ + try: + self._scopes_stack.pop() + except IndexError: + raise exceptions._RefResolutionError( + "Failed to pop the scope from an empty stack. " + "`pop_scope()` should only be called once for every " + "`push_scope()`", + ) from None + + @property + def resolution_scope(self): + """ + Retrieve the current resolution scope. + """ + return self._scopes_stack[-1] + + @property + def base_uri(self): + """ + Retrieve the current base URI, not including any fragment. + """ + uri, _ = urldefrag(self.resolution_scope) + return uri + + @contextlib.contextmanager + def in_scope(self, scope): + """ + Temporarily enter the given scope for the duration of the context. + + .. deprecated:: v4.0.0 + """ + warnings.warn( + "jsonschema.RefResolver.in_scope is deprecated and will be " + "removed in a future release.", + DeprecationWarning, + stacklevel=3, + ) + self.push_scope(scope) + try: + yield + finally: + self.pop_scope() + + @contextlib.contextmanager + def resolving(self, ref): + """ + Resolve the given ``ref`` and enter its resolution scope. + + Exits the scope on exit of this context manager. + + Arguments: + + ref (str): + + The reference to resolve + + """ + url, resolved = self.resolve(ref) + self.push_scope(url) + try: + yield resolved + finally: + self.pop_scope() + + def _find_in_referrer(self, key): + return self._get_subschemas_cache()[key] + + @lru_cache # noqa: B019 + def _get_subschemas_cache(self): + cache = {key: [] for key in _SUBSCHEMAS_KEYWORDS} + for keyword, subschema in _search_schema( + self.referrer, _match_subschema_keywords, + ): + cache[keyword].append(subschema) + return cache + + @lru_cache # noqa: B019 + def _find_in_subschemas(self, url): + subschemas = self._get_subschemas_cache()["$id"] + if not subschemas: + return None + uri, fragment = urldefrag(url) + for subschema in subschemas: + id = subschema["$id"] + if not isinstance(id, str): + continue + target_uri = self._urljoin_cache(self.resolution_scope, id) + if target_uri.rstrip("/") == uri.rstrip("/"): + if fragment: + subschema = self.resolve_fragment(subschema, fragment) + self.store[url] = subschema + return url, subschema + return None + + def resolve(self, ref): + """ + Resolve the given reference. + """ + url = self._urljoin_cache(self.resolution_scope, ref).rstrip("/") + + match = self._find_in_subschemas(url) + if match is not None: + return match + + return url, self._remote_cache(url) + + def resolve_from_url(self, url): + """ + Resolve the given URL. + """ + url, fragment = urldefrag(url) + if not url: + url = self.base_uri + + try: + document = self.store[url] + except KeyError: + try: + document = self.resolve_remote(url) + except Exception as exc: + raise exceptions._RefResolutionError(exc) from exc + + return self.resolve_fragment(document, fragment) + + def resolve_fragment(self, document, fragment): + """ + Resolve a ``fragment`` within the referenced ``document``. + + Arguments: + + document: + + The referent document + + fragment (str): + + a URI fragment to resolve within it + + """ + fragment = fragment.lstrip("/") + + if not fragment: + return document + + if document is self.referrer: + find = self._find_in_referrer + else: + + def find(key): + yield from _search_schema(document, _match_keyword(key)) + + for keyword in ["$anchor", "$dynamicAnchor"]: + for subschema in find(keyword): + if fragment == subschema[keyword]: + return subschema + for keyword in ["id", "$id"]: + for subschema in find(keyword): + if "#" + fragment == subschema[keyword]: + return subschema + + # Resolve via path + parts = unquote(fragment).split("/") if fragment else [] + for part in parts: + part = part.replace("~1", "/").replace("~0", "~") + + if isinstance(document, Sequence): + try: # noqa: SIM105 + part = int(part) + except ValueError: + pass + try: + document = document[part] + except (TypeError, LookupError) as err: + raise exceptions._RefResolutionError( + f"Unresolvable JSON pointer: {fragment!r}", + ) from err + + return document + + def resolve_remote(self, uri): + """ + Resolve a remote ``uri``. + + If called directly, does not check the store first, but after + retrieving the document at the specified URI it will be saved in + the store if :attr:`cache_remote` is True. + + .. note:: + + If the requests_ library is present, ``jsonschema`` will use it to + request the remote ``uri``, so that the correct encoding is + detected and used. + + If it isn't, or if the scheme of the ``uri`` is not ``http`` or + ``https``, UTF-8 is assumed. + + Arguments: + + uri (str): + + The URI to resolve + + Returns: + + The retrieved document + + .. _requests: https://pypi.org/project/requests/ + + """ + try: + import requests + except ImportError: + requests = None + + scheme = urlsplit(uri).scheme + + if scheme in self.handlers: + result = self.handlers[scheme](uri) + elif scheme in ["http", "https"] and requests: + # Requests has support for detecting the correct encoding of + # json over http + result = requests.get(uri).json() + else: + # Otherwise, pass off to urllib and assume utf-8 + with urlopen(uri) as url: # noqa: S310 + result = json.loads(url.read().decode("utf-8")) + + if self.cache_remote: + self.store[uri] = result + return result + + +_SUBSCHEMAS_KEYWORDS = ("$id", "id", "$anchor", "$dynamicAnchor") + + +def _match_keyword(keyword): + + def matcher(value): + if keyword in value: + yield value + + return matcher + + +def _match_subschema_keywords(value): + for keyword in _SUBSCHEMAS_KEYWORDS: + if keyword in value: + yield keyword, value + + +def _search_schema(schema, matcher): + """Breadth-first search routine.""" + values = deque([schema]) + while values: + value = values.pop() + if not isinstance(value, dict): + continue + yield from matcher(value) + values.extendleft(value.values()) + + +def validate(instance, schema, cls=None, *args, **kwargs): # noqa: D417 + """ + Validate an instance under the given schema. + + >>> validate([2, 3, 4], {"maxItems": 2}) + Traceback (most recent call last): + ... + ValidationError: [2, 3, 4] is too long + + :func:`~jsonschema.validators.validate` will first verify that the + provided schema is itself valid, since not doing so can lead to less + obvious error messages and fail in less obvious or consistent ways. + + If you know you have a valid schema already, especially + if you intend to validate multiple instances with + the same schema, you likely would prefer using the + `jsonschema.protocols.Validator.validate` method directly on a + specific validator (e.g. ``Draft202012Validator.validate``). + + + Arguments: + + instance: + + The instance to validate + + schema: + + The schema to validate with + + cls (jsonschema.protocols.Validator): + + The class that will be used to validate the instance. + + If the ``cls`` argument is not provided, two things will happen + in accordance with the specification. First, if the schema has a + :kw:`$schema` keyword containing a known meta-schema [#]_ then the + proper validator will be used. The specification recommends that + all schemas contain :kw:`$schema` properties for this reason. If no + :kw:`$schema` property is found, the default validator class is the + latest released draft. + + Any other provided positional and keyword arguments will be passed + on when instantiating the ``cls``. + + Raises: + + `jsonschema.exceptions.ValidationError`: + + if the instance is invalid + + `jsonschema.exceptions.SchemaError`: + + if the schema itself is invalid + + .. rubric:: Footnotes + .. [#] known by a validator registered with + `jsonschema.validators.validates` + + """ + if cls is None: + cls = validator_for(schema) + + cls.check_schema(schema) + validator = cls(schema, *args, **kwargs) + error = exceptions.best_match(validator.iter_errors(instance)) + if error is not None: + raise error + + +def validator_for( + schema, + default: Validator | _utils.Unset = _UNSET, +) -> type[Validator]: + """ + Retrieve the validator class appropriate for validating the given schema. + + Uses the :kw:`$schema` keyword that should be present in the given + schema to look up the appropriate validator class. + + Arguments: + + schema (collections.abc.Mapping or bool): + + the schema to look at + + default: + + the default to return if the appropriate validator class + cannot be determined. + + If unprovided, the default is to return the latest supported + draft. + + Examples: + + The :kw:`$schema` JSON Schema keyword will control which validator + class is returned: + + >>> schema = { + ... "$schema": "https://json-schema.org/draft/2020-12/schema", + ... "type": "integer", + ... } + >>> jsonschema.validators.validator_for(schema) + + + + Here, a draft 7 schema instead will return the draft 7 validator: + + >>> schema = { + ... "$schema": "http://json-schema.org/draft-07/schema#", + ... "type": "integer", + ... } + >>> jsonschema.validators.validator_for(schema) + + + + Schemas with no ``$schema`` keyword will fallback to the default + argument: + + >>> schema = {"type": "integer"} + >>> jsonschema.validators.validator_for( + ... schema, default=Draft7Validator, + ... ) + + + or if none is provided, to the latest version supported. + Always including the keyword when authoring schemas is highly + recommended. + + """ + DefaultValidator = _LATEST_VERSION if default is _UNSET else default + + if schema is True or schema is False or "$schema" not in schema: + return DefaultValidator + if schema["$schema"] not in _META_SCHEMAS and default is _UNSET: + warn( + ( + "The metaschema specified by $schema was not found. " + "Using the latest draft to validate, but this will raise " + "an error in the future." + ), + DeprecationWarning, + stacklevel=2, + ) + return _META_SCHEMAS.get(schema["$schema"], DefaultValidator) diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/INSTALLER b/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/METADATA b/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/METADATA new file mode 100644 index 0000000..0437aaa --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/METADATA @@ -0,0 +1,54 @@ +Metadata-Version: 2.4 +Name: jsonschema-specifications +Version: 2025.4.1 +Summary: The JSON Schema meta-schemas and vocabularies, exposed as a Registry +Project-URL: Documentation, https://jsonschema-specifications.readthedocs.io/ +Project-URL: Homepage, https://github.com/python-jsonschema/jsonschema-specifications +Project-URL: Issues, https://github.com/python-jsonschema/jsonschema-specifications/issues/ +Project-URL: Funding, https://github.com/sponsors/Julian +Project-URL: Tidelift, https://tidelift.com/subscription/pkg/pypi-jsonschema-specifications?utm_source=pypi-jsonschema-specifications&utm_medium=referral&utm_campaign=pypi-link +Project-URL: Source, https://github.com/python-jsonschema/jsonschema-specifications +Author-email: Julian Berman +License-Expression: MIT +License-File: COPYING +Keywords: data validation,json,json schema,jsonschema,validation +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: File Formats :: JSON +Classifier: Topic :: File Formats :: JSON :: JSON Schema +Requires-Python: >=3.9 +Requires-Dist: referencing>=0.31.0 +Description-Content-Type: text/x-rst + +============================= +``jsonschema-specifications`` +============================= + +|PyPI| |Pythons| |CI| |ReadTheDocs| + +JSON support files from the `JSON Schema Specifications `_ (metaschemas, vocabularies, etc.), packaged for runtime access from Python as a `referencing-based Schema Registry `_. + +.. |PyPI| image:: https://img.shields.io/pypi/v/jsonschema-specifications.svg + :alt: PyPI version + :target: https://pypi.org/project/jsonschema-specifications/ + +.. |Pythons| image:: https://img.shields.io/pypi/pyversions/jsonschema-specifications.svg + :alt: Supported Python versions + :target: https://pypi.org/project/jsonschema-specifications/ + +.. |CI| image:: https://github.com/python-jsonschema/jsonschema-specifications/workflows/CI/badge.svg + :alt: Build status + :target: https://github.com/python-jsonschema/jsonschema-specifications/actions?query=workflow%3ACI + +.. |ReadTheDocs| image:: https://readthedocs.org/projects/jsonschema-specifications/badge/?version=stable&style=flat + :alt: ReadTheDocs status + :target: https://jsonschema-specifications.readthedocs.io/en/stable/ diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/RECORD b/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/RECORD new file mode 100644 index 0000000..2132791 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/RECORD @@ -0,0 +1,33 @@ +jsonschema_specifications-2025.4.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +jsonschema_specifications-2025.4.1.dist-info/METADATA,sha256=O5aSPJh5x5sRBhPXC-mW3OVQ7F8cSiVjwv7ZPOSOKcA,2907 +jsonschema_specifications-2025.4.1.dist-info/RECORD,, +jsonschema_specifications-2025.4.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87 +jsonschema_specifications-2025.4.1.dist-info/licenses/COPYING,sha256=QtzWNJX4e063x3V6-jebtVpT-Ur9el9lfZrfVyNuUVw,1057 +jsonschema_specifications/__init__.py,sha256=qoTB2DKY7qvNrGhMPH6gtmAJRLilmVQ-fFZwT6ryqw0,386 +jsonschema_specifications/__pycache__/__init__.cpython-310.pyc,, +jsonschema_specifications/__pycache__/_core.cpython-310.pyc,, +jsonschema_specifications/_core.py,sha256=tFhc1CMleJ3AJOK_bjxOpFQTdrsUClFGfFxPBU_CebM,1140 +jsonschema_specifications/schemas/draft201909/metaschema.json,sha256=e3YbPhIfCgyh6ioLjizIVrz4AWBLgmjXG6yqICvAwTs,1785 +jsonschema_specifications/schemas/draft201909/vocabularies/applicator,sha256=aJUQDplyb7sQcFhRK77D7P1LJOj9L6zuPlBe5ysNTDE,1860 +jsonschema_specifications/schemas/draft201909/vocabularies/content,sha256=m31PVaTi_bAsQwBo_f-rxzKt3OI42j8d8mkCScM1MnQ,517 +jsonschema_specifications/schemas/draft201909/vocabularies/core,sha256=taLElX9kldClCB8ECevooU5BOayyA_x0hHH47eKvWyw,1531 +jsonschema_specifications/schemas/draft201909/vocabularies/meta-data,sha256=1H4kRd1qgicaKY2DzGxsuNSuHhXg3Fa-zTehY-zwEoY,892 +jsonschema_specifications/schemas/draft201909/vocabularies/validation,sha256=HlJsHTNac0gF_ILPV5jBK5YK19olF8Zs2lobCTWcPBw,2834 +jsonschema_specifications/schemas/draft202012/metaschema.json,sha256=Qdp29a-3zgYtJI92JGOpL3ykfk4PkFsiS6av7vkd7Q8,2452 +jsonschema_specifications/schemas/draft202012/vocabularies/applicator,sha256=xKbkFHuR_vf-ptwFjLG_k0AvdBS3ZXiosWqvHa1qrO8,1659 +jsonschema_specifications/schemas/draft202012/vocabularies/content,sha256=CDQ3R3ZOSlgUJieTz01lIFenkThjxZUNQyl-jh_axbY,519 +jsonschema_specifications/schemas/draft202012/vocabularies/core,sha256=wtEqjk3RHTNt_IOj9mOqTGnwtJs76wlP_rJbUxb0gD0,1564 +jsonschema_specifications/schemas/draft202012/vocabularies/format,sha256=UOu_55BhGoSbjMQAoJwdDg-2q1wNQ6DyIgH9NiUFa_Q,403 +jsonschema_specifications/schemas/draft202012/vocabularies/format-annotation,sha256=q8d1rf79idIjWBcNm_k_Tr0jSVY7u-3WDwK-98gSvMA,448 +jsonschema_specifications/schemas/draft202012/vocabularies/format-assertion,sha256=xSJCuaG7eGsmw-gset1CjDH5yW5XXc6Z5W6l_qptogw,445 +jsonschema_specifications/schemas/draft202012/vocabularies/meta-data,sha256=j3bW4U9Bubku-TO3CM3FFEyLUmhlGtEZGEhfsXVPHHY,892 +jsonschema_specifications/schemas/draft202012/vocabularies/unevaluated,sha256=Lb-8tzmUtnCwl2SSre4f_7RsIWgnhNL1pMpWH54tDLQ,506 +jsonschema_specifications/schemas/draft202012/vocabularies/validation,sha256=cBCjHlQfMtK-ch4t40jfdcmzaHaj7TBId_wKvaHTelg,2834 +jsonschema_specifications/schemas/draft3/metaschema.json,sha256=LPdfZENvtb43Si6qJ6uLfh_WUcm0ba6mxnsC_WTiRYs,2600 +jsonschema_specifications/schemas/draft4/metaschema.json,sha256=4UidC0dV8CeTMCWR0_y48Htok6gqlPJIlfjk7fEbguI,4357 +jsonschema_specifications/schemas/draft6/metaschema.json,sha256=wp386fVINcOgbAOzxdXsDtp3cGVo-cTffPvHVmpRAG0,4437 +jsonschema_specifications/schemas/draft7/metaschema.json,sha256=PVOSCIJhYGxVm2A_OFMpyfGrRbXWZ-uZBodFOwVdQF4,4819 +jsonschema_specifications/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +jsonschema_specifications/tests/__pycache__/__init__.cpython-310.pyc,, +jsonschema_specifications/tests/__pycache__/test_jsonschema_specifications.cpython-310.pyc,, +jsonschema_specifications/tests/test_jsonschema_specifications.py,sha256=WkbYRW6A6FoZ0rivShfqVLSCsAiHJ2x8TxqECJTXPTY,1106 diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/WHEEL b/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/WHEEL new file mode 100644 index 0000000..12228d4 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: hatchling 1.27.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/licenses/COPYING b/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/licenses/COPYING new file mode 100644 index 0000000..a9f853e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications-2025.4.1.dist-info/licenses/COPYING @@ -0,0 +1,19 @@ +Copyright (c) 2022 Julian Berman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/__init__.py b/.venv/lib/python3.10/site-packages/jsonschema_specifications/__init__.py new file mode 100644 index 0000000..a423574 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/__init__.py @@ -0,0 +1,12 @@ +""" +The JSON Schema meta-schemas and vocabularies, exposed as a Registry. +""" + +from referencing.jsonschema import EMPTY_REGISTRY as _EMPTY_REGISTRY + +from jsonschema_specifications._core import _schemas + +#: A `referencing.jsonschema.SchemaRegistry` containing all of the official +#: meta-schemas and vocabularies. +REGISTRY = (_schemas() @ _EMPTY_REGISTRY).crawl() +__all__ = ["REGISTRY"] diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/_core.py b/.venv/lib/python3.10/site-packages/jsonschema_specifications/_core.py new file mode 100644 index 0000000..e67bd71 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/_core.py @@ -0,0 +1,38 @@ +""" +Load all the JSON Schema specification's official schemas. +""" + +import json + +try: + from importlib.resources import files +except ImportError: + from importlib_resources import ( # type: ignore[import-not-found, no-redef] + files, + ) + +from referencing import Resource + + +def _schemas(): + """ + All schemas we ship. + """ + # importlib.resources.abc.Traversal doesn't have nice ways to do this that + # I'm aware of... + # + # It can't recurse arbitrarily, e.g. no ``.glob()``. + # + # So this takes some liberties given the real layout of what we ship + # (only 2 levels of nesting, no directories within the second level). + + for version in files(__package__).joinpath("schemas").iterdir(): + if version.name.startswith("."): + continue + for child in version.iterdir(): + children = [child] if child.is_file() else child.iterdir() + for path in children: + if path.name.startswith("."): + continue + contents = json.loads(path.read_text(encoding="utf-8")) + yield Resource.from_contents(contents) diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/metaschema.json b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/metaschema.json new file mode 100644 index 0000000..2248a0c --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/metaschema.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://json-schema.org/draft/2019-09/schema", + "$vocabulary": { + "https://json-schema.org/draft/2019-09/vocab/core": true, + "https://json-schema.org/draft/2019-09/vocab/applicator": true, + "https://json-schema.org/draft/2019-09/vocab/validation": true, + "https://json-schema.org/draft/2019-09/vocab/meta-data": true, + "https://json-schema.org/draft/2019-09/vocab/format": false, + "https://json-schema.org/draft/2019-09/vocab/content": true + }, + "$recursiveAnchor": true, + + "title": "Core and Validation specifications meta-schema", + "allOf": [ + {"$ref": "meta/core"}, + {"$ref": "meta/applicator"}, + {"$ref": "meta/validation"}, + {"$ref": "meta/meta-data"}, + {"$ref": "meta/format"}, + {"$ref": "meta/content"} + ], + "type": ["object", "boolean"], + "properties": { + "definitions": { + "$comment": "While no longer an official keyword as it is replaced by $defs, this keyword is retained in the meta-schema to prevent incompatible extensions as it remains in common use.", + "type": "object", + "additionalProperties": { "$recursiveRef": "#" }, + "default": {} + }, + "dependencies": { + "$comment": "\"dependencies\" is no longer a keyword, but schema authors should avoid redefining it to facilitate a smooth transition to \"dependentSchemas\" and \"dependentRequired\"", + "type": "object", + "additionalProperties": { + "anyOf": [ + { "$recursiveRef": "#" }, + { "$ref": "meta/validation#/$defs/stringArray" } + ] + } + } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/applicator b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/applicator new file mode 100644 index 0000000..24a1cc4 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/applicator @@ -0,0 +1,56 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://json-schema.org/draft/2019-09/meta/applicator", + "$vocabulary": { + "https://json-schema.org/draft/2019-09/vocab/applicator": true + }, + "$recursiveAnchor": true, + + "title": "Applicator vocabulary meta-schema", + "type": ["object", "boolean"], + "properties": { + "additionalItems": { "$recursiveRef": "#" }, + "unevaluatedItems": { "$recursiveRef": "#" }, + "items": { + "anyOf": [ + { "$recursiveRef": "#" }, + { "$ref": "#/$defs/schemaArray" } + ] + }, + "contains": { "$recursiveRef": "#" }, + "additionalProperties": { "$recursiveRef": "#" }, + "unevaluatedProperties": { "$recursiveRef": "#" }, + "properties": { + "type": "object", + "additionalProperties": { "$recursiveRef": "#" }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { "$recursiveRef": "#" }, + "propertyNames": { "format": "regex" }, + "default": {} + }, + "dependentSchemas": { + "type": "object", + "additionalProperties": { + "$recursiveRef": "#" + } + }, + "propertyNames": { "$recursiveRef": "#" }, + "if": { "$recursiveRef": "#" }, + "then": { "$recursiveRef": "#" }, + "else": { "$recursiveRef": "#" }, + "allOf": { "$ref": "#/$defs/schemaArray" }, + "anyOf": { "$ref": "#/$defs/schemaArray" }, + "oneOf": { "$ref": "#/$defs/schemaArray" }, + "not": { "$recursiveRef": "#" } + }, + "$defs": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { "$recursiveRef": "#" } + } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/content b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/content new file mode 100644 index 0000000..f6752a8 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/content @@ -0,0 +1,17 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://json-schema.org/draft/2019-09/meta/content", + "$vocabulary": { + "https://json-schema.org/draft/2019-09/vocab/content": true + }, + "$recursiveAnchor": true, + + "title": "Content vocabulary meta-schema", + + "type": ["object", "boolean"], + "properties": { + "contentMediaType": { "type": "string" }, + "contentEncoding": { "type": "string" }, + "contentSchema": { "$recursiveRef": "#" } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/core b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/core new file mode 100644 index 0000000..eb708a5 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/core @@ -0,0 +1,57 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://json-schema.org/draft/2019-09/meta/core", + "$vocabulary": { + "https://json-schema.org/draft/2019-09/vocab/core": true + }, + "$recursiveAnchor": true, + + "title": "Core vocabulary meta-schema", + "type": ["object", "boolean"], + "properties": { + "$id": { + "type": "string", + "format": "uri-reference", + "$comment": "Non-empty fragments not allowed.", + "pattern": "^[^#]*#?$" + }, + "$schema": { + "type": "string", + "format": "uri" + }, + "$anchor": { + "type": "string", + "pattern": "^[A-Za-z][-A-Za-z0-9.:_]*$" + }, + "$ref": { + "type": "string", + "format": "uri-reference" + }, + "$recursiveRef": { + "type": "string", + "format": "uri-reference" + }, + "$recursiveAnchor": { + "type": "boolean", + "default": false + }, + "$vocabulary": { + "type": "object", + "propertyNames": { + "type": "string", + "format": "uri" + }, + "additionalProperties": { + "type": "boolean" + } + }, + "$comment": { + "type": "string" + }, + "$defs": { + "type": "object", + "additionalProperties": { "$recursiveRef": "#" }, + "default": {} + } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/meta-data b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/meta-data new file mode 100644 index 0000000..da04cff --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/meta-data @@ -0,0 +1,37 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://json-schema.org/draft/2019-09/meta/meta-data", + "$vocabulary": { + "https://json-schema.org/draft/2019-09/vocab/meta-data": true + }, + "$recursiveAnchor": true, + + "title": "Meta-data vocabulary meta-schema", + + "type": ["object", "boolean"], + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": true, + "deprecated": { + "type": "boolean", + "default": false + }, + "readOnly": { + "type": "boolean", + "default": false + }, + "writeOnly": { + "type": "boolean", + "default": false + }, + "examples": { + "type": "array", + "items": true + } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/validation b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/validation new file mode 100644 index 0000000..9f59677 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft201909/vocabularies/validation @@ -0,0 +1,98 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://json-schema.org/draft/2019-09/meta/validation", + "$vocabulary": { + "https://json-schema.org/draft/2019-09/vocab/validation": true + }, + "$recursiveAnchor": true, + + "title": "Validation vocabulary meta-schema", + "type": ["object", "boolean"], + "properties": { + "multipleOf": { + "type": "number", + "exclusiveMinimum": 0 + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "number" + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "number" + }, + "maxLength": { "$ref": "#/$defs/nonNegativeInteger" }, + "minLength": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, + "pattern": { + "type": "string", + "format": "regex" + }, + "maxItems": { "$ref": "#/$defs/nonNegativeInteger" }, + "minItems": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "maxContains": { "$ref": "#/$defs/nonNegativeInteger" }, + "minContains": { + "$ref": "#/$defs/nonNegativeInteger", + "default": 1 + }, + "maxProperties": { "$ref": "#/$defs/nonNegativeInteger" }, + "minProperties": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, + "required": { "$ref": "#/$defs/stringArray" }, + "dependentRequired": { + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/stringArray" + } + }, + "const": true, + "enum": { + "type": "array", + "items": true + }, + "type": { + "anyOf": [ + { "$ref": "#/$defs/simpleTypes" }, + { + "type": "array", + "items": { "$ref": "#/$defs/simpleTypes" }, + "minItems": 1, + "uniqueItems": true + } + ] + } + }, + "$defs": { + "nonNegativeInteger": { + "type": "integer", + "minimum": 0 + }, + "nonNegativeIntegerDefault0": { + "$ref": "#/$defs/nonNegativeInteger", + "default": 0 + }, + "simpleTypes": { + "enum": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ] + }, + "stringArray": { + "type": "array", + "items": { "type": "string" }, + "uniqueItems": true, + "default": [] + } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/metaschema.json b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/metaschema.json new file mode 100644 index 0000000..d5e2d31 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/metaschema.json @@ -0,0 +1,58 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://json-schema.org/draft/2020-12/schema", + "$vocabulary": { + "https://json-schema.org/draft/2020-12/vocab/core": true, + "https://json-schema.org/draft/2020-12/vocab/applicator": true, + "https://json-schema.org/draft/2020-12/vocab/unevaluated": true, + "https://json-schema.org/draft/2020-12/vocab/validation": true, + "https://json-schema.org/draft/2020-12/vocab/meta-data": true, + "https://json-schema.org/draft/2020-12/vocab/format-annotation": true, + "https://json-schema.org/draft/2020-12/vocab/content": true + }, + "$dynamicAnchor": "meta", + + "title": "Core and Validation specifications meta-schema", + "allOf": [ + {"$ref": "meta/core"}, + {"$ref": "meta/applicator"}, + {"$ref": "meta/unevaluated"}, + {"$ref": "meta/validation"}, + {"$ref": "meta/meta-data"}, + {"$ref": "meta/format-annotation"}, + {"$ref": "meta/content"} + ], + "type": ["object", "boolean"], + "$comment": "This meta-schema also defines keywords that have appeared in previous drafts in order to prevent incompatible extensions as they remain in common use.", + "properties": { + "definitions": { + "$comment": "\"definitions\" has been replaced by \"$defs\".", + "type": "object", + "additionalProperties": { "$dynamicRef": "#meta" }, + "deprecated": true, + "default": {} + }, + "dependencies": { + "$comment": "\"dependencies\" has been split and replaced by \"dependentSchemas\" and \"dependentRequired\" in order to serve their differing semantics.", + "type": "object", + "additionalProperties": { + "anyOf": [ + { "$dynamicRef": "#meta" }, + { "$ref": "meta/validation#/$defs/stringArray" } + ] + }, + "deprecated": true, + "default": {} + }, + "$recursiveAnchor": { + "$comment": "\"$recursiveAnchor\" has been replaced by \"$dynamicAnchor\".", + "$ref": "meta/core#/$defs/anchorString", + "deprecated": true + }, + "$recursiveRef": { + "$comment": "\"$recursiveRef\" has been replaced by \"$dynamicRef\".", + "$ref": "meta/core#/$defs/uriReferenceString", + "deprecated": true + } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/applicator b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/applicator new file mode 100644 index 0000000..ca69923 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/applicator @@ -0,0 +1,48 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://json-schema.org/draft/2020-12/meta/applicator", + "$vocabulary": { + "https://json-schema.org/draft/2020-12/vocab/applicator": true + }, + "$dynamicAnchor": "meta", + + "title": "Applicator vocabulary meta-schema", + "type": ["object", "boolean"], + "properties": { + "prefixItems": { "$ref": "#/$defs/schemaArray" }, + "items": { "$dynamicRef": "#meta" }, + "contains": { "$dynamicRef": "#meta" }, + "additionalProperties": { "$dynamicRef": "#meta" }, + "properties": { + "type": "object", + "additionalProperties": { "$dynamicRef": "#meta" }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { "$dynamicRef": "#meta" }, + "propertyNames": { "format": "regex" }, + "default": {} + }, + "dependentSchemas": { + "type": "object", + "additionalProperties": { "$dynamicRef": "#meta" }, + "default": {} + }, + "propertyNames": { "$dynamicRef": "#meta" }, + "if": { "$dynamicRef": "#meta" }, + "then": { "$dynamicRef": "#meta" }, + "else": { "$dynamicRef": "#meta" }, + "allOf": { "$ref": "#/$defs/schemaArray" }, + "anyOf": { "$ref": "#/$defs/schemaArray" }, + "oneOf": { "$ref": "#/$defs/schemaArray" }, + "not": { "$dynamicRef": "#meta" } + }, + "$defs": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { "$dynamicRef": "#meta" } + } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/content b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/content new file mode 100644 index 0000000..2f6e056 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/content @@ -0,0 +1,17 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://json-schema.org/draft/2020-12/meta/content", + "$vocabulary": { + "https://json-schema.org/draft/2020-12/vocab/content": true + }, + "$dynamicAnchor": "meta", + + "title": "Content vocabulary meta-schema", + + "type": ["object", "boolean"], + "properties": { + "contentEncoding": { "type": "string" }, + "contentMediaType": { "type": "string" }, + "contentSchema": { "$dynamicRef": "#meta" } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/core b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/core new file mode 100644 index 0000000..dfc092d --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/core @@ -0,0 +1,51 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://json-schema.org/draft/2020-12/meta/core", + "$vocabulary": { + "https://json-schema.org/draft/2020-12/vocab/core": true + }, + "$dynamicAnchor": "meta", + + "title": "Core vocabulary meta-schema", + "type": ["object", "boolean"], + "properties": { + "$id": { + "$ref": "#/$defs/uriReferenceString", + "$comment": "Non-empty fragments not allowed.", + "pattern": "^[^#]*#?$" + }, + "$schema": { "$ref": "#/$defs/uriString" }, + "$ref": { "$ref": "#/$defs/uriReferenceString" }, + "$anchor": { "$ref": "#/$defs/anchorString" }, + "$dynamicRef": { "$ref": "#/$defs/uriReferenceString" }, + "$dynamicAnchor": { "$ref": "#/$defs/anchorString" }, + "$vocabulary": { + "type": "object", + "propertyNames": { "$ref": "#/$defs/uriString" }, + "additionalProperties": { + "type": "boolean" + } + }, + "$comment": { + "type": "string" + }, + "$defs": { + "type": "object", + "additionalProperties": { "$dynamicRef": "#meta" } + } + }, + "$defs": { + "anchorString": { + "type": "string", + "pattern": "^[A-Za-z_][-A-Za-z0-9._]*$" + }, + "uriString": { + "type": "string", + "format": "uri" + }, + "uriReferenceString": { + "type": "string", + "format": "uri-reference" + } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format new file mode 100644 index 0000000..09bbfdd --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format @@ -0,0 +1,14 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://json-schema.org/draft/2019-09/meta/format", + "$vocabulary": { + "https://json-schema.org/draft/2019-09/vocab/format": true + }, + "$recursiveAnchor": true, + + "title": "Format vocabulary meta-schema", + "type": ["object", "boolean"], + "properties": { + "format": { "type": "string" } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format-annotation b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format-annotation new file mode 100644 index 0000000..51ef7ea --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format-annotation @@ -0,0 +1,14 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://json-schema.org/draft/2020-12/meta/format-annotation", + "$vocabulary": { + "https://json-schema.org/draft/2020-12/vocab/format-annotation": true + }, + "$dynamicAnchor": "meta", + + "title": "Format vocabulary meta-schema for annotation results", + "type": ["object", "boolean"], + "properties": { + "format": { "type": "string" } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format-assertion b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format-assertion new file mode 100644 index 0000000..5e73fd7 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/format-assertion @@ -0,0 +1,14 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://json-schema.org/draft/2020-12/meta/format-assertion", + "$vocabulary": { + "https://json-schema.org/draft/2020-12/vocab/format-assertion": true + }, + "$dynamicAnchor": "meta", + + "title": "Format vocabulary meta-schema for assertion results", + "type": ["object", "boolean"], + "properties": { + "format": { "type": "string" } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/meta-data b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/meta-data new file mode 100644 index 0000000..05cbc22 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/meta-data @@ -0,0 +1,37 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://json-schema.org/draft/2020-12/meta/meta-data", + "$vocabulary": { + "https://json-schema.org/draft/2020-12/vocab/meta-data": true + }, + "$dynamicAnchor": "meta", + + "title": "Meta-data vocabulary meta-schema", + + "type": ["object", "boolean"], + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": true, + "deprecated": { + "type": "boolean", + "default": false + }, + "readOnly": { + "type": "boolean", + "default": false + }, + "writeOnly": { + "type": "boolean", + "default": false + }, + "examples": { + "type": "array", + "items": true + } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/unevaluated b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/unevaluated new file mode 100644 index 0000000..5f62a3f --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/unevaluated @@ -0,0 +1,15 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://json-schema.org/draft/2020-12/meta/unevaluated", + "$vocabulary": { + "https://json-schema.org/draft/2020-12/vocab/unevaluated": true + }, + "$dynamicAnchor": "meta", + + "title": "Unevaluated applicator vocabulary meta-schema", + "type": ["object", "boolean"], + "properties": { + "unevaluatedItems": { "$dynamicRef": "#meta" }, + "unevaluatedProperties": { "$dynamicRef": "#meta" } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/validation b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/validation new file mode 100644 index 0000000..606b87b --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft202012/vocabularies/validation @@ -0,0 +1,98 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://json-schema.org/draft/2020-12/meta/validation", + "$vocabulary": { + "https://json-schema.org/draft/2020-12/vocab/validation": true + }, + "$dynamicAnchor": "meta", + + "title": "Validation vocabulary meta-schema", + "type": ["object", "boolean"], + "properties": { + "type": { + "anyOf": [ + { "$ref": "#/$defs/simpleTypes" }, + { + "type": "array", + "items": { "$ref": "#/$defs/simpleTypes" }, + "minItems": 1, + "uniqueItems": true + } + ] + }, + "const": true, + "enum": { + "type": "array", + "items": true + }, + "multipleOf": { + "type": "number", + "exclusiveMinimum": 0 + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "number" + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "number" + }, + "maxLength": { "$ref": "#/$defs/nonNegativeInteger" }, + "minLength": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, + "pattern": { + "type": "string", + "format": "regex" + }, + "maxItems": { "$ref": "#/$defs/nonNegativeInteger" }, + "minItems": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "maxContains": { "$ref": "#/$defs/nonNegativeInteger" }, + "minContains": { + "$ref": "#/$defs/nonNegativeInteger", + "default": 1 + }, + "maxProperties": { "$ref": "#/$defs/nonNegativeInteger" }, + "minProperties": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, + "required": { "$ref": "#/$defs/stringArray" }, + "dependentRequired": { + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/stringArray" + } + } + }, + "$defs": { + "nonNegativeInteger": { + "type": "integer", + "minimum": 0 + }, + "nonNegativeIntegerDefault0": { + "$ref": "#/$defs/nonNegativeInteger", + "default": 0 + }, + "simpleTypes": { + "enum": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ] + }, + "stringArray": { + "type": "array", + "items": { "type": "string" }, + "uniqueItems": true, + "default": [] + } + } +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft3/metaschema.json b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft3/metaschema.json new file mode 100644 index 0000000..8b26b1f --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft3/metaschema.json @@ -0,0 +1,172 @@ +{ + "$schema" : "http://json-schema.org/draft-03/schema#", + "id" : "http://json-schema.org/draft-03/schema#", + "type" : "object", + + "properties" : { + "type" : { + "type" : ["string", "array"], + "items" : { + "type" : ["string", {"$ref" : "#"}] + }, + "uniqueItems" : true, + "default" : "any" + }, + + "properties" : { + "type" : "object", + "additionalProperties" : {"$ref" : "#"}, + "default" : {} + }, + + "patternProperties" : { + "type" : "object", + "additionalProperties" : {"$ref" : "#"}, + "default" : {} + }, + + "additionalProperties" : { + "type" : [{"$ref" : "#"}, "boolean"], + "default" : {} + }, + + "items" : { + "type" : [{"$ref" : "#"}, "array"], + "items" : {"$ref" : "#"}, + "default" : {} + }, + + "additionalItems" : { + "type" : [{"$ref" : "#"}, "boolean"], + "default" : {} + }, + + "required" : { + "type" : "boolean", + "default" : false + }, + + "dependencies" : { + "type" : "object", + "additionalProperties" : { + "type" : ["string", "array", {"$ref" : "#"}], + "items" : { + "type" : "string" + } + }, + "default" : {} + }, + + "minimum" : { + "type" : "number" + }, + + "maximum" : { + "type" : "number" + }, + + "exclusiveMinimum" : { + "type" : "boolean", + "default" : false + }, + + "exclusiveMaximum" : { + "type" : "boolean", + "default" : false + }, + + "minItems" : { + "type" : "integer", + "minimum" : 0, + "default" : 0 + }, + + "maxItems" : { + "type" : "integer", + "minimum" : 0 + }, + + "uniqueItems" : { + "type" : "boolean", + "default" : false + }, + + "pattern" : { + "type" : "string", + "format" : "regex" + }, + + "minLength" : { + "type" : "integer", + "minimum" : 0, + "default" : 0 + }, + + "maxLength" : { + "type" : "integer" + }, + + "enum" : { + "type" : "array", + "minItems" : 1, + "uniqueItems" : true + }, + + "default" : { + "type" : "any" + }, + + "title" : { + "type" : "string" + }, + + "description" : { + "type" : "string" + }, + + "format" : { + "type" : "string" + }, + + "divisibleBy" : { + "type" : "number", + "minimum" : 0, + "exclusiveMinimum" : true, + "default" : 1 + }, + + "disallow" : { + "type" : ["string", "array"], + "items" : { + "type" : ["string", {"$ref" : "#"}] + }, + "uniqueItems" : true + }, + + "extends" : { + "type" : [{"$ref" : "#"}, "array"], + "items" : {"$ref" : "#"}, + "default" : {} + }, + + "id" : { + "type" : "string" + }, + + "$ref" : { + "type" : "string" + }, + + "$schema" : { + "type" : "string", + "format" : "uri" + } + }, + + "dependencies" : { + "exclusiveMinimum" : "minimum", + "exclusiveMaximum" : "maximum" + }, + + "default" : {} +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft4/metaschema.json b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft4/metaschema.json new file mode 100644 index 0000000..bcbb847 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft4/metaschema.json @@ -0,0 +1,149 @@ +{ + "id": "http://json-schema.org/draft-04/schema#", + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "Core schema meta-schema", + "definitions": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#" } + }, + "positiveInteger": { + "type": "integer", + "minimum": 0 + }, + "positiveIntegerDefault0": { + "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ] + }, + "simpleTypes": { + "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ] + }, + "stringArray": { + "type": "array", + "items": { "type": "string" }, + "minItems": 1, + "uniqueItems": true + } + }, + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "$schema": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": {}, + "multipleOf": { + "type": "number", + "minimum": 0, + "exclusiveMinimum": true + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "boolean", + "default": false + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "boolean", + "default": false + }, + "maxLength": { "$ref": "#/definitions/positiveInteger" }, + "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" }, + "pattern": { + "type": "string", + "format": "regex" + }, + "additionalItems": { + "anyOf": [ + { "type": "boolean" }, + { "$ref": "#" } + ], + "default": {} + }, + "items": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/schemaArray" } + ], + "default": {} + }, + "maxItems": { "$ref": "#/definitions/positiveInteger" }, + "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "maxProperties": { "$ref": "#/definitions/positiveInteger" }, + "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" }, + "required": { "$ref": "#/definitions/stringArray" }, + "additionalProperties": { + "anyOf": [ + { "type": "boolean" }, + { "$ref": "#" } + ], + "default": {} + }, + "definitions": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "properties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "dependencies": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/stringArray" } + ] + } + }, + "enum": { + "type": "array", + "minItems": 1, + "uniqueItems": true + }, + "type": { + "anyOf": [ + { "$ref": "#/definitions/simpleTypes" }, + { + "type": "array", + "items": { "$ref": "#/definitions/simpleTypes" }, + "minItems": 1, + "uniqueItems": true + } + ] + }, + "format": { "type": "string" }, + "allOf": { "$ref": "#/definitions/schemaArray" }, + "anyOf": { "$ref": "#/definitions/schemaArray" }, + "oneOf": { "$ref": "#/definitions/schemaArray" }, + "not": { "$ref": "#" } + }, + "dependencies": { + "exclusiveMaximum": [ "maximum" ], + "exclusiveMinimum": [ "minimum" ] + }, + "default": {} +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft6/metaschema.json b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft6/metaschema.json new file mode 100644 index 0000000..a0d2bf7 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft6/metaschema.json @@ -0,0 +1,153 @@ +{ + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "http://json-schema.org/draft-06/schema#", + "title": "Core schema meta-schema", + "definitions": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#" } + }, + "nonNegativeInteger": { + "type": "integer", + "minimum": 0 + }, + "nonNegativeIntegerDefault0": { + "allOf": [ + { "$ref": "#/definitions/nonNegativeInteger" }, + { "default": 0 } + ] + }, + "simpleTypes": { + "enum": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ] + }, + "stringArray": { + "type": "array", + "items": { "type": "string" }, + "uniqueItems": true, + "default": [] + } + }, + "type": ["object", "boolean"], + "properties": { + "$id": { + "type": "string", + "format": "uri-reference" + }, + "$schema": { + "type": "string", + "format": "uri" + }, + "$ref": { + "type": "string", + "format": "uri-reference" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": {}, + "examples": { + "type": "array", + "items": {} + }, + "multipleOf": { + "type": "number", + "exclusiveMinimum": 0 + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "number" + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "number" + }, + "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, + "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "pattern": { + "type": "string", + "format": "regex" + }, + "additionalItems": { "$ref": "#" }, + "items": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/schemaArray" } + ], + "default": {} + }, + "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, + "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "contains": { "$ref": "#" }, + "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, + "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "required": { "$ref": "#/definitions/stringArray" }, + "additionalProperties": { "$ref": "#" }, + "definitions": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "properties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "propertyNames": { "format": "regex" }, + "default": {} + }, + "dependencies": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/stringArray" } + ] + } + }, + "propertyNames": { "$ref": "#" }, + "const": {}, + "enum": { + "type": "array" + }, + "type": { + "anyOf": [ + { "$ref": "#/definitions/simpleTypes" }, + { + "type": "array", + "items": { "$ref": "#/definitions/simpleTypes" }, + "minItems": 1, + "uniqueItems": true + } + ] + }, + "format": { "type": "string" }, + "allOf": { "$ref": "#/definitions/schemaArray" }, + "anyOf": { "$ref": "#/definitions/schemaArray" }, + "oneOf": { "$ref": "#/definitions/schemaArray" }, + "not": { "$ref": "#" } + }, + "default": {} +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft7/metaschema.json b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft7/metaschema.json new file mode 100644 index 0000000..746cde9 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/schemas/draft7/metaschema.json @@ -0,0 +1,166 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://json-schema.org/draft-07/schema#", + "title": "Core schema meta-schema", + "definitions": { + "schemaArray": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#" } + }, + "nonNegativeInteger": { + "type": "integer", + "minimum": 0 + }, + "nonNegativeIntegerDefault0": { + "allOf": [ + { "$ref": "#/definitions/nonNegativeInteger" }, + { "default": 0 } + ] + }, + "simpleTypes": { + "enum": [ + "array", + "boolean", + "integer", + "null", + "number", + "object", + "string" + ] + }, + "stringArray": { + "type": "array", + "items": { "type": "string" }, + "uniqueItems": true, + "default": [] + } + }, + "type": ["object", "boolean"], + "properties": { + "$id": { + "type": "string", + "format": "uri-reference" + }, + "$schema": { + "type": "string", + "format": "uri" + }, + "$ref": { + "type": "string", + "format": "uri-reference" + }, + "$comment": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "default": true, + "readOnly": { + "type": "boolean", + "default": false + }, + "examples": { + "type": "array", + "items": true + }, + "multipleOf": { + "type": "number", + "exclusiveMinimum": 0 + }, + "maximum": { + "type": "number" + }, + "exclusiveMaximum": { + "type": "number" + }, + "minimum": { + "type": "number" + }, + "exclusiveMinimum": { + "type": "number" + }, + "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, + "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "pattern": { + "type": "string", + "format": "regex" + }, + "additionalItems": { "$ref": "#" }, + "items": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/schemaArray" } + ], + "default": true + }, + "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, + "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "uniqueItems": { + "type": "boolean", + "default": false + }, + "contains": { "$ref": "#" }, + "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, + "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, + "required": { "$ref": "#/definitions/stringArray" }, + "additionalProperties": { "$ref": "#" }, + "definitions": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "properties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "default": {} + }, + "patternProperties": { + "type": "object", + "additionalProperties": { "$ref": "#" }, + "propertyNames": { "format": "regex" }, + "default": {} + }, + "dependencies": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { "$ref": "#" }, + { "$ref": "#/definitions/stringArray" } + ] + } + }, + "propertyNames": { "$ref": "#" }, + "const": true, + "enum": { + "type": "array", + "items": true + }, + "type": { + "anyOf": [ + { "$ref": "#/definitions/simpleTypes" }, + { + "type": "array", + "items": { "$ref": "#/definitions/simpleTypes" }, + "minItems": 1, + "uniqueItems": true + } + ] + }, + "format": { "type": "string" }, + "contentMediaType": { "type": "string" }, + "contentEncoding": { "type": "string" }, + "if": {"$ref": "#"}, + "then": {"$ref": "#"}, + "else": {"$ref": "#"}, + "allOf": { "$ref": "#/definitions/schemaArray" }, + "anyOf": { "$ref": "#/definitions/schemaArray" }, + "oneOf": { "$ref": "#/definitions/schemaArray" }, + "not": { "$ref": "#" } + }, + "default": true +} diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/tests/__init__.py b/.venv/lib/python3.10/site-packages/jsonschema_specifications/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/.venv/lib/python3.10/site-packages/jsonschema_specifications/tests/test_jsonschema_specifications.py b/.venv/lib/python3.10/site-packages/jsonschema_specifications/tests/test_jsonschema_specifications.py new file mode 100644 index 0000000..fd2927e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/jsonschema_specifications/tests/test_jsonschema_specifications.py @@ -0,0 +1,41 @@ +from collections.abc import Mapping +from pathlib import Path + +import pytest + +from jsonschema_specifications import REGISTRY + + +def test_it_contains_metaschemas(): + schema = REGISTRY.contents("http://json-schema.org/draft-07/schema#") + assert isinstance(schema, Mapping) + assert schema["$id"] == "http://json-schema.org/draft-07/schema#" + assert schema["title"] == "Core schema meta-schema" + + +def test_it_is_crawled(): + assert REGISTRY.crawl() == REGISTRY + + +@pytest.mark.parametrize( + "ignored_relative_path", + ["schemas/.DS_Store", "schemas/draft7/.DS_Store"], +) +def test_it_copes_with_dotfiles(ignored_relative_path): + """ + Ignore files like .DS_Store if someone has actually caused one to exist. + + We test here through the private interface as of course the global has + already loaded our schemas. + """ + + import jsonschema_specifications + + package = Path(jsonschema_specifications.__file__).parent + + ignored = package / ignored_relative_path + ignored.touch() + try: + list(jsonschema_specifications._schemas()) + finally: + ignored.unlink() diff --git a/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/INSTALLER b/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/METADATA b/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/METADATA new file mode 100644 index 0000000..78cde34 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/METADATA @@ -0,0 +1,64 @@ +Metadata-Version: 2.4 +Name: referencing +Version: 0.36.2 +Summary: JSON Referencing + Python +Project-URL: Documentation, https://referencing.readthedocs.io/ +Project-URL: Homepage, https://github.com/python-jsonschema/referencing +Project-URL: Issues, https://github.com/python-jsonschema/referencing/issues/ +Project-URL: Funding, https://github.com/sponsors/Julian +Project-URL: Tidelift, https://tidelift.com/subscription/pkg/pypi-referencing?utm_source=pypi-referencing&utm_medium=referral&utm_campaign=pypi-link +Project-URL: Changelog, https://referencing.readthedocs.io/en/stable/changes/ +Project-URL: Source, https://github.com/python-jsonschema/referencing +Author-email: Julian Berman +License-Expression: MIT +License-File: COPYING +Keywords: asyncapi,json,jsonschema,openapi,referencing +Classifier: Development Status :: 3 - Alpha +Classifier: Intended Audience :: Developers +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: File Formats :: JSON +Classifier: Topic :: File Formats :: JSON :: JSON Schema +Requires-Python: >=3.9 +Requires-Dist: attrs>=22.2.0 +Requires-Dist: rpds-py>=0.7.0 +Requires-Dist: typing-extensions>=4.4.0; python_version < '3.13' +Description-Content-Type: text/x-rst + +=============== +``referencing`` +=============== + +|PyPI| |Pythons| |CI| |ReadTheDocs| |pre-commit| + +.. |PyPI| image:: https://img.shields.io/pypi/v/referencing.svg + :alt: PyPI version + :target: https://pypi.org/project/referencing/ + +.. |Pythons| image:: https://img.shields.io/pypi/pyversions/referencing.svg + :alt: Supported Python versions + :target: https://pypi.org/project/referencing/ + +.. |CI| image:: https://github.com/python-jsonschema/referencing/workflows/CI/badge.svg + :alt: Build status + :target: https://github.com/python-jsonschema/referencing/actions?query=workflow%3ACI + +.. |ReadTheDocs| image:: https://readthedocs.org/projects/referencing/badge/?version=stable&style=flat + :alt: ReadTheDocs status + :target: https://referencing.readthedocs.io/en/stable/ + +.. |pre-commit| image:: https://results.pre-commit.ci/badge/github/python-jsonschema/referencing/main.svg + :alt: pre-commit.ci status + :target: https://results.pre-commit.ci/latest/github/python-jsonschema/referencing/main + + +An implementation-agnostic implementation of JSON reference resolution. + +See `the documentation `_ for more details. diff --git a/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/RECORD b/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/RECORD new file mode 100644 index 0000000..b42f48d --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/RECORD @@ -0,0 +1,33 @@ +referencing-0.36.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +referencing-0.36.2.dist-info/METADATA,sha256=8eyM93pT0UngPkNw0ZxSgXU8d_JKvDRo0nxhSwW9cgY,2843 +referencing-0.36.2.dist-info/RECORD,, +referencing-0.36.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87 +referencing-0.36.2.dist-info/licenses/COPYING,sha256=QtzWNJX4e063x3V6-jebtVpT-Ur9el9lfZrfVyNuUVw,1057 +referencing/__init__.py,sha256=5IZKXaAH_FWyCJRkaTn1XcptLfg9cveLb9u5nYUxJKs,207 +referencing/__pycache__/__init__.cpython-310.pyc,, +referencing/__pycache__/_attrs.cpython-310.pyc,, +referencing/__pycache__/_core.cpython-310.pyc,, +referencing/__pycache__/exceptions.cpython-310.pyc,, +referencing/__pycache__/jsonschema.cpython-310.pyc,, +referencing/__pycache__/retrieval.cpython-310.pyc,, +referencing/__pycache__/typing.cpython-310.pyc,, +referencing/_attrs.py,sha256=bgT-KMhDVLeGtWxM_SGKYeLaZBFzT2kUVFdAkOcXi8g,791 +referencing/_attrs.pyi,sha256=J6StMUKqixO4H7Eii9-TXNfCOfS8aHm-1ewimOA-8oo,559 +referencing/_core.py,sha256=0SJfZW68dOrLMaFdhMyuyYzb0Bi9d0BcPjGwijesf9E,24830 +referencing/exceptions.py,sha256=zFgaEg6WiKeT58MQuKNsgGDnHszp26c4oReC6sF9gHM,4176 +referencing/jsonschema.py,sha256=jFURIFOnuxtE4doPL1xSDeuQ4OhdxNzSn8MRRbTeVyk,18628 +referencing/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +referencing/retrieval.py,sha256=QYlOvhiQeDI12XKwezhZ3XOUzqBTFE8b5TpfATamA7I,2697 +referencing/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +referencing/tests/__pycache__/__init__.cpython-310.pyc,, +referencing/tests/__pycache__/test_core.cpython-310.pyc,, +referencing/tests/__pycache__/test_exceptions.cpython-310.pyc,, +referencing/tests/__pycache__/test_jsonschema.cpython-310.pyc,, +referencing/tests/__pycache__/test_referencing_suite.cpython-310.pyc,, +referencing/tests/__pycache__/test_retrieval.cpython-310.pyc,, +referencing/tests/test_core.py,sha256=eap0CAaI23vjMIbVyEj92qLddp3iHH3AxC55CKUN4LU,37854 +referencing/tests/test_exceptions.py,sha256=7eOdHyobXMt7-h5AnnH7u8iw2uHPaH7U4Bs9JhLgjWo,934 +referencing/tests/test_jsonschema.py,sha256=4QnjUWOAMAn5yeA8ZtldJkhI54vwKWJWB0LDzNdx5xc,11687 +referencing/tests/test_referencing_suite.py,sha256=wD6veMfLsUu0s4MLjm7pS8cg4cIfL7FMBENngk73zCI,2335 +referencing/tests/test_retrieval.py,sha256=vcbnfA4TqVeqUzW073wO-nLeqVIv0rQZWNWv0z9km48,3719 +referencing/typing.py,sha256=WjUbnZ6jPAd31cnCFAaeWIVENzyHtHdJyOlelv1GY70,1445 diff --git a/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/WHEEL b/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/WHEEL new file mode 100644 index 0000000..12228d4 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: hatchling 1.27.0 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/licenses/COPYING b/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/licenses/COPYING new file mode 100644 index 0000000..a9f853e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing-0.36.2.dist-info/licenses/COPYING @@ -0,0 +1,19 @@ +Copyright (c) 2022 Julian Berman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/.venv/lib/python3.10/site-packages/referencing/__init__.py b/.venv/lib/python3.10/site-packages/referencing/__init__.py new file mode 100644 index 0000000..e09207d --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing/__init__.py @@ -0,0 +1,7 @@ +""" +Cross-specification, implementation-agnostic JSON referencing. +""" + +from referencing._core import Anchor, Registry, Resource, Specification + +__all__ = ["Anchor", "Registry", "Resource", "Specification"] diff --git a/.venv/lib/python3.10/site-packages/referencing/_attrs.py b/.venv/lib/python3.10/site-packages/referencing/_attrs.py new file mode 100644 index 0000000..ae85b86 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing/_attrs.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +from typing import NoReturn, TypeVar + +from attrs import define as _define, frozen as _frozen + +_T = TypeVar("_T") + + +def define(cls: type[_T]) -> type[_T]: # pragma: no cover + cls.__init_subclass__ = _do_not_subclass + return _define(cls) + + +def frozen(cls: type[_T]) -> type[_T]: + cls.__init_subclass__ = _do_not_subclass + return _frozen(cls) + + +class UnsupportedSubclassing(Exception): + def __str__(self): + return ( + "Subclassing is not part of referencing's public API. " + "If no other suitable API exists for what you're trying to do, " + "feel free to file an issue asking for one." + ) + + +@staticmethod +def _do_not_subclass() -> NoReturn: # pragma: no cover + raise UnsupportedSubclassing() diff --git a/.venv/lib/python3.10/site-packages/referencing/_attrs.pyi b/.venv/lib/python3.10/site-packages/referencing/_attrs.pyi new file mode 100644 index 0000000..278e410 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing/_attrs.pyi @@ -0,0 +1,20 @@ +from typing import Any, Callable, TypeVar, Union + +from attr import attrib, field + +class UnsupportedSubclassing(Exception): ... + +_T = TypeVar("_T") + +def __dataclass_transform__( + *, + frozen_default: bool = False, + field_descriptors: tuple[Union[type, Callable[..., Any]], ...] = ..., +) -> Callable[[_T], _T]: ... +@__dataclass_transform__(field_descriptors=(attrib, field)) +def define(cls: type[_T]) -> type[_T]: ... +@__dataclass_transform__( + frozen_default=True, + field_descriptors=(attrib, field), +) +def frozen(cls: type[_T]) -> type[_T]: ... diff --git a/.venv/lib/python3.10/site-packages/referencing/_core.py b/.venv/lib/python3.10/site-packages/referencing/_core.py new file mode 100644 index 0000000..ec2d51b --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing/_core.py @@ -0,0 +1,739 @@ +from __future__ import annotations + +from collections.abc import Iterable, Iterator, Sequence +from enum import Enum +from typing import Any, Callable, ClassVar, Generic, Protocol +from urllib.parse import unquote, urldefrag, urljoin + +from attrs import evolve, field +from rpds import HashTrieMap, HashTrieSet, List + +try: + from typing_extensions import TypeVar +except ImportError: # pragma: no cover + from typing import TypeVar + +from referencing import exceptions +from referencing._attrs import frozen +from referencing.typing import URI, Anchor as AnchorType, D, Mapping, Retrieve + +EMPTY_UNCRAWLED: HashTrieSet[URI] = HashTrieSet() +EMPTY_PREVIOUS_RESOLVERS: List[URI] = List() + + +class _Unset(Enum): + """ + What sillyness... + """ + + SENTINEL = 1 + + +_UNSET = _Unset.SENTINEL + + +class _MaybeInSubresource(Protocol[D]): + def __call__( + self, + segments: Sequence[int | str], + resolver: Resolver[D], + subresource: Resource[D], + ) -> Resolver[D]: ... + + +def _detect_or_error(contents: D) -> Specification[D]: + if not isinstance(contents, Mapping): + raise exceptions.CannotDetermineSpecification(contents) + + jsonschema_dialect_id = contents.get("$schema") # type: ignore[reportUnknownMemberType] + if not isinstance(jsonschema_dialect_id, str): + raise exceptions.CannotDetermineSpecification(contents) + + from referencing.jsonschema import specification_with + + return specification_with(jsonschema_dialect_id) + + +def _detect_or_default( + default: Specification[D], +) -> Callable[[D], Specification[D]]: + def _detect(contents: D) -> Specification[D]: + if not isinstance(contents, Mapping): + return default + + jsonschema_dialect_id = contents.get("$schema") # type: ignore[reportUnknownMemberType] + if jsonschema_dialect_id is None: + return default + + from referencing.jsonschema import specification_with + + return specification_with( + jsonschema_dialect_id, # type: ignore[reportUnknownArgumentType] + default=default, + ) + + return _detect + + +class _SpecificationDetector: + def __get__( + self, + instance: Specification[D] | None, + cls: type[Specification[D]], + ) -> Callable[[D], Specification[D]]: + if instance is None: + return _detect_or_error + else: + return _detect_or_default(instance) + + +@frozen +class Specification(Generic[D]): + """ + A specification which defines referencing behavior. + + The various methods of a `Specification` allow for varying referencing + behavior across JSON Schema specification versions, etc. + """ + + #: A short human-readable name for the specification, used for debugging. + name: str + + #: Find the ID of a given document. + id_of: Callable[[D], URI | None] + + #: Retrieve the subresources of the given document (without traversing into + #: the subresources themselves). + subresources_of: Callable[[D], Iterable[D]] + + #: While resolving a JSON pointer, conditionally enter a subresource + #: (if e.g. we have just entered a keyword whose value is a subresource) + maybe_in_subresource: _MaybeInSubresource[D] + + #: Retrieve the anchors contained in the given document. + _anchors_in: Callable[ + [Specification[D], D], + Iterable[AnchorType[D]], + ] = field(alias="anchors_in") + + #: An opaque specification where resources have no subresources + #: nor internal identifiers. + OPAQUE: ClassVar[Specification[Any]] + + #: Attempt to discern which specification applies to the given contents. + #: + #: May be called either as an instance method or as a class method, with + #: slightly different behavior in the following case: + #: + #: Recall that not all contents contains enough internal information about + #: which specification it is written for -- the JSON Schema ``{}``, + #: for instance, is valid under many different dialects and may be + #: interpreted as any one of them. + #: + #: When this method is used as an instance method (i.e. called on a + #: specific specification), that specification is used as the default + #: if the given contents are unidentifiable. + #: + #: On the other hand when called as a class method, an error is raised. + #: + #: To reiterate, ``DRAFT202012.detect({})`` will return ``DRAFT202012`` + #: whereas the class method ``Specification.detect({})`` will raise an + #: error. + #: + #: (Note that of course ``DRAFT202012.detect(...)`` may return some other + #: specification when given a schema which *does* identify as being for + #: another version). + #: + #: Raises: + #: + #: `CannotDetermineSpecification` + #: + #: if the given contents don't have any discernible + #: information which could be used to guess which + #: specification they identify as + detect = _SpecificationDetector() + + def __repr__(self) -> str: + return f"" + + def anchors_in(self, contents: D): + """ + Retrieve the anchors contained in the given document. + """ + return self._anchors_in(self, contents) + + def create_resource(self, contents: D) -> Resource[D]: + """ + Create a resource which is interpreted using this specification. + """ + return Resource(contents=contents, specification=self) + + +Specification.OPAQUE = Specification( + name="opaque", + id_of=lambda contents: None, + subresources_of=lambda contents: [], + anchors_in=lambda specification, contents: [], + maybe_in_subresource=lambda segments, resolver, subresource: resolver, +) + + +@frozen +class Resource(Generic[D]): + r""" + A document (deserialized JSON) with a concrete interpretation under a spec. + + In other words, a Python object, along with an instance of `Specification` + which describes how the document interacts with referencing -- both + internally (how it refers to other `Resource`\ s) and externally (how it + should be identified such that it is referenceable by other documents). + """ + + contents: D + _specification: Specification[D] = field(alias="specification") + + @classmethod + def from_contents( + cls, + contents: D, + default_specification: ( + type[Specification[D]] | Specification[D] + ) = Specification, + ) -> Resource[D]: + """ + Create a resource guessing which specification applies to the contents. + + Raises: + + `CannotDetermineSpecification` + + if the given contents don't have any discernible + information which could be used to guess which + specification they identify as + + """ + specification = default_specification.detect(contents) + return specification.create_resource(contents=contents) + + @classmethod + def opaque(cls, contents: D) -> Resource[D]: + """ + Create an opaque `Resource` -- i.e. one with opaque specification. + + See `Specification.OPAQUE` for details. + """ + return Specification.OPAQUE.create_resource(contents=contents) + + def id(self) -> URI | None: + """ + Retrieve this resource's (specification-specific) identifier. + """ + id = self._specification.id_of(self.contents) + if id is None: + return + return id.rstrip("#") + + def subresources(self) -> Iterable[Resource[D]]: + """ + Retrieve this resource's subresources. + """ + return ( + Resource.from_contents( + each, + default_specification=self._specification, + ) + for each in self._specification.subresources_of(self.contents) + ) + + def anchors(self) -> Iterable[AnchorType[D]]: + """ + Retrieve this resource's (specification-specific) identifier. + """ + return self._specification.anchors_in(self.contents) + + def pointer(self, pointer: str, resolver: Resolver[D]) -> Resolved[D]: + """ + Resolve the given JSON pointer. + + Raises: + + `exceptions.PointerToNowhere` + + if the pointer points to a location not present in the document + + """ + if not pointer: + return Resolved(contents=self.contents, resolver=resolver) + + contents = self.contents + segments: list[int | str] = [] + for segment in unquote(pointer[1:]).split("/"): + if isinstance(contents, Sequence): + segment = int(segment) + else: + segment = segment.replace("~1", "/").replace("~0", "~") + try: + contents = contents[segment] # type: ignore[reportUnknownArgumentType] + except LookupError as lookup_error: + error = exceptions.PointerToNowhere(ref=pointer, resource=self) + raise error from lookup_error + + segments.append(segment) + last = resolver + resolver = self._specification.maybe_in_subresource( + segments=segments, + resolver=resolver, + subresource=self._specification.create_resource(contents), + ) + if resolver is not last: + segments = [] + return Resolved(contents=contents, resolver=resolver) # type: ignore[reportUnknownArgumentType] + + +def _fail_to_retrieve(uri: URI): + raise exceptions.NoSuchResource(ref=uri) + + +@frozen +class Registry(Mapping[URI, Resource[D]]): + r""" + A registry of `Resource`\ s, each identified by their canonical URIs. + + Registries store a collection of in-memory resources, and optionally + enable additional resources which may be stored elsewhere (e.g. in a + database, a separate set of files, over the network, etc.). + + They also lazily walk their known resources, looking for subresources + within them. In other words, subresources contained within any added + resources will be retrievable via their own IDs (though this discovery of + subresources will be delayed until necessary). + + Registries are immutable, and their methods return new instances of the + registry with the additional resources added to them. + + The ``retrieve`` argument can be used to configure retrieval of resources + dynamically, either over the network, from a database, or the like. + Pass it a callable which will be called if any URI not present in the + registry is accessed. It must either return a `Resource` or else raise a + `NoSuchResource` exception indicating that the resource does not exist + even according to the retrieval logic. + """ + + _resources: HashTrieMap[URI, Resource[D]] = field( + default=HashTrieMap(), + converter=HashTrieMap.convert, # type: ignore[reportGeneralTypeIssues] + alias="resources", + ) + _anchors: HashTrieMap[tuple[URI, str], AnchorType[D]] = HashTrieMap() + _uncrawled: HashTrieSet[URI] = EMPTY_UNCRAWLED + _retrieve: Retrieve[D] = field(default=_fail_to_retrieve, alias="retrieve") + + def __getitem__(self, uri: URI) -> Resource[D]: + """ + Return the (already crawled) `Resource` identified by the given URI. + """ + try: + return self._resources[uri.rstrip("#")] + except KeyError: + raise exceptions.NoSuchResource(ref=uri) from None + + def __iter__(self) -> Iterator[URI]: + """ + Iterate over all crawled URIs in the registry. + """ + return iter(self._resources) + + def __len__(self) -> int: + """ + Count the total number of fully crawled resources in this registry. + """ + return len(self._resources) + + def __rmatmul__( + self, + new: Resource[D] | Iterable[Resource[D]], + ) -> Registry[D]: + """ + Create a new registry with resource(s) added using their internal IDs. + + Resources must have a internal IDs (e.g. the :kw:`$id` keyword in + modern JSON Schema versions), otherwise an error will be raised. + + Both a single resource as well as an iterable of resources works, i.e.: + + * ``resource @ registry`` or + + * ``[iterable, of, multiple, resources] @ registry`` + + which -- again, assuming the resources have internal IDs -- is + equivalent to calling `Registry.with_resources` as such: + + .. code:: python + + registry.with_resources( + (resource.id(), resource) for resource in new_resources + ) + + Raises: + + `NoInternalID` + + if the resource(s) in fact do not have IDs + + """ + if isinstance(new, Resource): + new = (new,) + + resources = self._resources + uncrawled = self._uncrawled + for resource in new: + id = resource.id() + if id is None: + raise exceptions.NoInternalID(resource=resource) + uncrawled = uncrawled.insert(id) + resources = resources.insert(id, resource) + return evolve(self, resources=resources, uncrawled=uncrawled) + + def __repr__(self) -> str: + size = len(self) + pluralized = "resource" if size == 1 else "resources" + if self._uncrawled: + uncrawled = len(self._uncrawled) + if uncrawled == size: + summary = f"uncrawled {pluralized}" + else: + summary = f"{pluralized}, {uncrawled} uncrawled" + else: + summary = f"{pluralized}" + return f"" + + def get_or_retrieve(self, uri: URI) -> Retrieved[D, Resource[D]]: + """ + Get a resource from the registry, crawling or retrieving if necessary. + + May involve crawling to find the given URI if it is not already known, + so the returned object is a `Retrieved` object which contains both the + resource value as well as the registry which ultimately contained it. + """ + resource = self._resources.get(uri) + if resource is not None: + return Retrieved(registry=self, value=resource) + + registry = self.crawl() + resource = registry._resources.get(uri) + if resource is not None: + return Retrieved(registry=registry, value=resource) + + try: + resource = registry._retrieve(uri) + except ( + exceptions.CannotDetermineSpecification, + exceptions.NoSuchResource, + ): + raise + except Exception as error: + raise exceptions.Unretrievable(ref=uri) from error + else: + registry = registry.with_resource(uri, resource) + return Retrieved(registry=registry, value=resource) + + def remove(self, uri: URI): + """ + Return a registry with the resource identified by a given URI removed. + """ + if uri not in self._resources: + raise exceptions.NoSuchResource(ref=uri) + + return evolve( + self, + resources=self._resources.remove(uri), + uncrawled=self._uncrawled.discard(uri), + anchors=HashTrieMap( + (k, v) for k, v in self._anchors.items() if k[0] != uri + ), + ) + + def anchor(self, uri: URI, name: str): + """ + Retrieve a given anchor from a resource which must already be crawled. + """ + value = self._anchors.get((uri, name)) + if value is not None: + return Retrieved(value=value, registry=self) + + registry = self.crawl() + value = registry._anchors.get((uri, name)) + if value is not None: + return Retrieved(value=value, registry=registry) + + resource = self[uri] + canonical_uri = resource.id() + if canonical_uri is not None: + value = registry._anchors.get((canonical_uri, name)) + if value is not None: + return Retrieved(value=value, registry=registry) + + if "/" in name: + raise exceptions.InvalidAnchor( + ref=uri, + resource=resource, + anchor=name, + ) + raise exceptions.NoSuchAnchor(ref=uri, resource=resource, anchor=name) + + def contents(self, uri: URI) -> D: + """ + Retrieve the (already crawled) contents identified by the given URI. + """ + return self[uri].contents + + def crawl(self) -> Registry[D]: + """ + Crawl all added resources, discovering subresources. + """ + resources = self._resources + anchors = self._anchors + uncrawled = [(uri, resources[uri]) for uri in self._uncrawled] + while uncrawled: + uri, resource = uncrawled.pop() + + id = resource.id() + if id is not None: + uri = urljoin(uri, id) + resources = resources.insert(uri, resource) + for each in resource.anchors(): + anchors = anchors.insert((uri, each.name), each) + uncrawled.extend((uri, each) for each in resource.subresources()) + return evolve( + self, + resources=resources, + anchors=anchors, + uncrawled=EMPTY_UNCRAWLED, + ) + + def with_resource(self, uri: URI, resource: Resource[D]): + """ + Add the given `Resource` to the registry, without crawling it. + """ + return self.with_resources([(uri, resource)]) + + def with_resources( + self, + pairs: Iterable[tuple[URI, Resource[D]]], + ) -> Registry[D]: + r""" + Add the given `Resource`\ s to the registry, without crawling them. + """ + resources = self._resources + uncrawled = self._uncrawled + for uri, resource in pairs: + # Empty fragment URIs are equivalent to URIs without the fragment. + # TODO: Is this true for non JSON Schema resources? Probably not. + uri = uri.rstrip("#") + uncrawled = uncrawled.insert(uri) + resources = resources.insert(uri, resource) + return evolve(self, resources=resources, uncrawled=uncrawled) + + def with_contents( + self, + pairs: Iterable[tuple[URI, D]], + **kwargs: Any, + ) -> Registry[D]: + r""" + Add the given contents to the registry, autodetecting when necessary. + """ + return self.with_resources( + (uri, Resource.from_contents(each, **kwargs)) + for uri, each in pairs + ) + + def combine(self, *registries: Registry[D]) -> Registry[D]: + """ + Combine together one or more other registries, producing a unified one. + """ + if registries == (self,): + return self + resources = self._resources + anchors = self._anchors + uncrawled = self._uncrawled + retrieve = self._retrieve + for registry in registries: + resources = resources.update(registry._resources) + anchors = anchors.update(registry._anchors) + uncrawled = uncrawled.update(registry._uncrawled) + + if registry._retrieve is not _fail_to_retrieve: # type: ignore[reportUnnecessaryComparison] ??? + if registry._retrieve is not retrieve is not _fail_to_retrieve: # type: ignore[reportUnnecessaryComparison] ??? + raise ValueError( # noqa: TRY003 + "Cannot combine registries with conflicting retrieval " + "functions.", + ) + retrieve = registry._retrieve + return evolve( + self, + anchors=anchors, + resources=resources, + uncrawled=uncrawled, + retrieve=retrieve, + ) + + def resolver(self, base_uri: URI = "") -> Resolver[D]: + """ + Return a `Resolver` which resolves references against this registry. + """ + return Resolver(base_uri=base_uri, registry=self) + + def resolver_with_root(self, resource: Resource[D]) -> Resolver[D]: + """ + Return a `Resolver` with a specific root resource. + """ + uri = resource.id() or "" + return Resolver( + base_uri=uri, + registry=self.with_resource(uri, resource), + ) + + +#: An anchor or resource. +AnchorOrResource = TypeVar( + "AnchorOrResource", + AnchorType[Any], + Resource[Any], + default=Resource[Any], +) + + +@frozen +class Retrieved(Generic[D, AnchorOrResource]): + """ + A value retrieved from a `Registry`. + """ + + value: AnchorOrResource + registry: Registry[D] + + +@frozen +class Resolved(Generic[D]): + """ + A reference resolved to its contents by a `Resolver`. + """ + + contents: D + resolver: Resolver[D] + + +@frozen +class Resolver(Generic[D]): + """ + A reference resolver. + + Resolvers help resolve references (including relative ones) by + pairing a fixed base URI with a `Registry`. + + This object, under normal circumstances, is expected to be used by + *implementers of libraries* built on top of `referencing` (e.g. JSON Schema + implementations or other libraries resolving JSON references), + not directly by end-users populating registries or while writing + schemas or other resources. + + References are resolved against the base URI, and the combined URI + is then looked up within the registry. + + The process of resolving a reference may itself involve calculating + a *new* base URI for future reference resolution (e.g. if an + intermediate resource sets a new base URI), or may involve encountering + additional subresources and adding them to a new registry. + """ + + _base_uri: URI = field(alias="base_uri") + _registry: Registry[D] = field(alias="registry") + _previous: List[URI] = field(default=List(), repr=False, alias="previous") + + def lookup(self, ref: URI) -> Resolved[D]: + """ + Resolve the given reference to the resource it points to. + + Raises: + + `exceptions.Unresolvable` + + or a subclass thereof (see below) if the reference isn't + resolvable + + `exceptions.NoSuchAnchor` + + if the reference is to a URI where a resource exists but + contains a plain name fragment which does not exist within + the resource + + `exceptions.PointerToNowhere` + + if the reference is to a URI where a resource exists but + contains a JSON pointer to a location within the resource + that does not exist + + """ + if ref.startswith("#"): + uri, fragment = self._base_uri, ref[1:] + else: + uri, fragment = urldefrag(urljoin(self._base_uri, ref)) + try: + retrieved = self._registry.get_or_retrieve(uri) + except exceptions.NoSuchResource: + raise exceptions.Unresolvable(ref=ref) from None + except exceptions.Unretrievable as error: + raise exceptions.Unresolvable(ref=ref) from error + + if fragment.startswith("/"): + resolver = self._evolve(registry=retrieved.registry, base_uri=uri) + return retrieved.value.pointer(pointer=fragment, resolver=resolver) + + if fragment: + retrieved = retrieved.registry.anchor(uri, fragment) + resolver = self._evolve(registry=retrieved.registry, base_uri=uri) + return retrieved.value.resolve(resolver=resolver) + + resolver = self._evolve(registry=retrieved.registry, base_uri=uri) + return Resolved(contents=retrieved.value.contents, resolver=resolver) + + def in_subresource(self, subresource: Resource[D]) -> Resolver[D]: + """ + Create a resolver for a subresource (which may have a new base URI). + """ + id = subresource.id() + if id is None: + return self + return evolve(self, base_uri=urljoin(self._base_uri, id)) + + def dynamic_scope(self) -> Iterable[tuple[URI, Registry[D]]]: + """ + In specs with such a notion, return the URIs in the dynamic scope. + """ + for uri in self._previous: + yield uri, self._registry + + def _evolve(self, base_uri: URI, **kwargs: Any): + """ + Evolve, appending to the dynamic scope. + """ + previous = self._previous + if self._base_uri and (not previous or base_uri != self._base_uri): + previous = previous.push_front(self._base_uri) + return evolve(self, base_uri=base_uri, previous=previous, **kwargs) + + +@frozen +class Anchor(Generic[D]): + """ + A simple anchor in a `Resource`. + """ + + name: str + resource: Resource[D] + + def resolve(self, resolver: Resolver[D]): + """ + Return the resource for this anchor. + """ + return Resolved(contents=self.resource.contents, resolver=resolver) diff --git a/.venv/lib/python3.10/site-packages/referencing/exceptions.py b/.venv/lib/python3.10/site-packages/referencing/exceptions.py new file mode 100644 index 0000000..3267fc7 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing/exceptions.py @@ -0,0 +1,165 @@ +""" +Errors, oh no! +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +import attrs + +from referencing._attrs import frozen + +if TYPE_CHECKING: + from referencing import Resource + from referencing.typing import URI + + +@frozen +class NoSuchResource(KeyError): + """ + The given URI is not present in a registry. + + Unlike most exceptions, this class *is* intended to be publicly + instantiable and *is* part of the public API of the package. + """ + + ref: URI + + def __eq__(self, other: object) -> bool: + if self.__class__ is not other.__class__: + return NotImplemented + return attrs.astuple(self) == attrs.astuple(other) + + def __hash__(self) -> int: + return hash(attrs.astuple(self)) + + +@frozen +class NoInternalID(Exception): + """ + A resource has no internal ID, but one is needed. + + E.g. in modern JSON Schema drafts, this is the :kw:`$id` keyword. + + One might be needed if a resource was to-be added to a registry but no + other URI is available, and the resource doesn't declare its canonical URI. + """ + + resource: Resource[Any] + + def __eq__(self, other: object) -> bool: + if self.__class__ is not other.__class__: + return NotImplemented + return attrs.astuple(self) == attrs.astuple(other) + + def __hash__(self) -> int: + return hash(attrs.astuple(self)) + + +@frozen +class Unretrievable(KeyError): + """ + The given URI is not present in a registry, and retrieving it failed. + """ + + ref: URI + + def __eq__(self, other: object) -> bool: + if self.__class__ is not other.__class__: + return NotImplemented + return attrs.astuple(self) == attrs.astuple(other) + + def __hash__(self) -> int: + return hash(attrs.astuple(self)) + + +@frozen +class CannotDetermineSpecification(Exception): + """ + Attempting to detect the appropriate `Specification` failed. + + This happens if no discernible information is found in the contents of the + new resource which would help identify it. + """ + + contents: Any + + def __eq__(self, other: object) -> bool: + if self.__class__ is not other.__class__: + return NotImplemented + return attrs.astuple(self) == attrs.astuple(other) + + def __hash__(self) -> int: + return hash(attrs.astuple(self)) + + +@attrs.frozen # Because here we allow subclassing below. +class Unresolvable(Exception): + """ + A reference was unresolvable. + """ + + ref: URI + + def __eq__(self, other: object) -> bool: + if self.__class__ is not other.__class__: + return NotImplemented + return attrs.astuple(self) == attrs.astuple(other) + + def __hash__(self) -> int: + return hash(attrs.astuple(self)) + + +@frozen +class PointerToNowhere(Unresolvable): + """ + A JSON Pointer leads to a part of a document that does not exist. + """ + + resource: Resource[Any] + + def __str__(self) -> str: + msg = f"{self.ref!r} does not exist within {self.resource.contents!r}" + if self.ref == "/": + msg += ( + ". The pointer '/' is a valid JSON Pointer but it points to " + "an empty string property ''. If you intended to point " + "to the entire resource, you should use '#'." + ) + return msg + + +@frozen +class NoSuchAnchor(Unresolvable): + """ + An anchor does not exist within a particular resource. + """ + + resource: Resource[Any] + anchor: str + + def __str__(self) -> str: + return ( + f"{self.anchor!r} does not exist within {self.resource.contents!r}" + ) + + +@frozen +class InvalidAnchor(Unresolvable): + """ + An anchor which could never exist in a resource was dereferenced. + + It is somehow syntactically invalid. + """ + + resource: Resource[Any] + anchor: str + + def __str__(self) -> str: + return ( + f"'#{self.anchor}' is not a valid anchor, neither as a " + "plain name anchor nor as a JSON Pointer. You may have intended " + f"to use '#/{self.anchor}', as the slash is required *before each " + "segment* of a JSON pointer." + ) diff --git a/.venv/lib/python3.10/site-packages/referencing/jsonschema.py b/.venv/lib/python3.10/site-packages/referencing/jsonschema.py new file mode 100644 index 0000000..169e109 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing/jsonschema.py @@ -0,0 +1,642 @@ +""" +Referencing implementations for JSON Schema specs (historic & current). +""" + +from __future__ import annotations + +from collections.abc import Iterable, Sequence, Set +from typing import Any, Union + +from referencing import Anchor, Registry, Resource, Specification, exceptions +from referencing._attrs import frozen +from referencing._core import ( + _UNSET, # type: ignore[reportPrivateUsage] + Resolved as _Resolved, + Resolver as _Resolver, + _Unset, # type: ignore[reportPrivateUsage] +) +from referencing.typing import URI, Anchor as AnchorType, Mapping + +#: A JSON Schema which is a JSON object +ObjectSchema = Mapping[str, Any] + +#: A JSON Schema of any kind +Schema = Union[bool, ObjectSchema] + +#: A Resource whose contents are JSON Schemas +SchemaResource = Resource[Schema] + +#: A JSON Schema Registry +SchemaRegistry = Registry[Schema] + +#: The empty JSON Schema Registry +EMPTY_REGISTRY: SchemaRegistry = Registry() + + +@frozen +class UnknownDialect(Exception): + """ + A dialect identifier was found for a dialect unknown by this library. + + If it's a custom ("unofficial") dialect, be sure you've registered it. + """ + + uri: URI + + +def _dollar_id(contents: Schema) -> URI | None: + if isinstance(contents, bool): + return + return contents.get("$id") + + +def _legacy_dollar_id(contents: Schema) -> URI | None: + if isinstance(contents, bool) or "$ref" in contents: + return + id = contents.get("$id") + if id is not None and not id.startswith("#"): + return id + + +def _legacy_id(contents: ObjectSchema) -> URI | None: + if "$ref" in contents: + return + id = contents.get("id") + if id is not None and not id.startswith("#"): + return id + + +def _anchor( + specification: Specification[Schema], + contents: Schema, +) -> Iterable[AnchorType[Schema]]: + if isinstance(contents, bool): + return + anchor = contents.get("$anchor") + if anchor is not None: + yield Anchor( + name=anchor, + resource=specification.create_resource(contents), + ) + + dynamic_anchor = contents.get("$dynamicAnchor") + if dynamic_anchor is not None: + yield DynamicAnchor( + name=dynamic_anchor, + resource=specification.create_resource(contents), + ) + + +def _anchor_2019( + specification: Specification[Schema], + contents: Schema, +) -> Iterable[Anchor[Schema]]: + if isinstance(contents, bool): + return [] + anchor = contents.get("$anchor") + if anchor is None: + return [] + return [ + Anchor( + name=anchor, + resource=specification.create_resource(contents), + ), + ] + + +def _legacy_anchor_in_dollar_id( + specification: Specification[Schema], + contents: Schema, +) -> Iterable[Anchor[Schema]]: + if isinstance(contents, bool): + return [] + id = contents.get("$id", "") + if not id.startswith("#"): + return [] + return [ + Anchor( + name=id[1:], + resource=specification.create_resource(contents), + ), + ] + + +def _legacy_anchor_in_id( + specification: Specification[ObjectSchema], + contents: ObjectSchema, +) -> Iterable[Anchor[ObjectSchema]]: + id = contents.get("id", "") + if not id.startswith("#"): + return [] + return [ + Anchor( + name=id[1:], + resource=specification.create_resource(contents), + ), + ] + + +def _subresources_of( + in_value: Set[str] = frozenset(), + in_subvalues: Set[str] = frozenset(), + in_subarray: Set[str] = frozenset(), +): + """ + Create a callable returning JSON Schema specification-style subschemas. + + Relies on specifying the set of keywords containing subschemas in their + values, in a subobject's values, or in a subarray. + """ + + def subresources_of(contents: Schema) -> Iterable[ObjectSchema]: + if isinstance(contents, bool): + return + for each in in_value: + if each in contents: + yield contents[each] + for each in in_subarray: + if each in contents: + yield from contents[each] + for each in in_subvalues: + if each in contents: + yield from contents[each].values() + + return subresources_of + + +def _subresources_of_with_crazy_items( + in_value: Set[str] = frozenset(), + in_subvalues: Set[str] = frozenset(), + in_subarray: Set[str] = frozenset(), +): + """ + Specifically handle older drafts where there are some funky keywords. + """ + + def subresources_of(contents: Schema) -> Iterable[ObjectSchema]: + if isinstance(contents, bool): + return + for each in in_value: + if each in contents: + yield contents[each] + for each in in_subarray: + if each in contents: + yield from contents[each] + for each in in_subvalues: + if each in contents: + yield from contents[each].values() + + items = contents.get("items") + if items is not None: + if isinstance(items, Sequence): + yield from items + else: + yield items + + return subresources_of + + +def _subresources_of_with_crazy_items_dependencies( + in_value: Set[str] = frozenset(), + in_subvalues: Set[str] = frozenset(), + in_subarray: Set[str] = frozenset(), +): + """ + Specifically handle older drafts where there are some funky keywords. + """ + + def subresources_of(contents: Schema) -> Iterable[ObjectSchema]: + if isinstance(contents, bool): + return + for each in in_value: + if each in contents: + yield contents[each] + for each in in_subarray: + if each in contents: + yield from contents[each] + for each in in_subvalues: + if each in contents: + yield from contents[each].values() + + items = contents.get("items") + if items is not None: + if isinstance(items, Sequence): + yield from items + else: + yield items + dependencies = contents.get("dependencies") + if dependencies is not None: + values = iter(dependencies.values()) + value = next(values, None) + if isinstance(value, Mapping): + yield value + yield from values + + return subresources_of + + +def _subresources_of_with_crazy_aP_items_dependencies( + in_value: Set[str] = frozenset(), + in_subvalues: Set[str] = frozenset(), + in_subarray: Set[str] = frozenset(), +): + """ + Specifically handle even older drafts where there are some funky keywords. + """ + + def subresources_of(contents: ObjectSchema) -> Iterable[ObjectSchema]: + for each in in_value: + if each in contents: + yield contents[each] + for each in in_subarray: + if each in contents: + yield from contents[each] + for each in in_subvalues: + if each in contents: + yield from contents[each].values() + + items = contents.get("items") + if items is not None: + if isinstance(items, Sequence): + yield from items + else: + yield items + dependencies = contents.get("dependencies") + if dependencies is not None: + values = iter(dependencies.values()) + value = next(values, None) + if isinstance(value, Mapping): + yield value + yield from values + + for each in "additionalItems", "additionalProperties": + value = contents.get(each) + if isinstance(value, Mapping): + yield value + + return subresources_of + + +def _maybe_in_subresource( + in_value: Set[str] = frozenset(), + in_subvalues: Set[str] = frozenset(), + in_subarray: Set[str] = frozenset(), +): + in_child = in_subvalues | in_subarray + + def maybe_in_subresource( + segments: Sequence[int | str], + resolver: _Resolver[Any], + subresource: Resource[Any], + ) -> _Resolver[Any]: + _segments = iter(segments) + for segment in _segments: + if segment not in in_value and ( + segment not in in_child or next(_segments, None) is None + ): + return resolver + return resolver.in_subresource(subresource) + + return maybe_in_subresource + + +def _maybe_in_subresource_crazy_items( + in_value: Set[str] = frozenset(), + in_subvalues: Set[str] = frozenset(), + in_subarray: Set[str] = frozenset(), +): + in_child = in_subvalues | in_subarray + + def maybe_in_subresource( + segments: Sequence[int | str], + resolver: _Resolver[Any], + subresource: Resource[Any], + ) -> _Resolver[Any]: + _segments = iter(segments) + for segment in _segments: + if segment == "items" and isinstance( + subresource.contents, + Mapping, + ): + return resolver.in_subresource(subresource) + if segment not in in_value and ( + segment not in in_child or next(_segments, None) is None + ): + return resolver + return resolver.in_subresource(subresource) + + return maybe_in_subresource + + +def _maybe_in_subresource_crazy_items_dependencies( + in_value: Set[str] = frozenset(), + in_subvalues: Set[str] = frozenset(), + in_subarray: Set[str] = frozenset(), +): + in_child = in_subvalues | in_subarray + + def maybe_in_subresource( + segments: Sequence[int | str], + resolver: _Resolver[Any], + subresource: Resource[Any], + ) -> _Resolver[Any]: + _segments = iter(segments) + for segment in _segments: + if segment in {"items", "dependencies"} and isinstance( + subresource.contents, + Mapping, + ): + return resolver.in_subresource(subresource) + if segment not in in_value and ( + segment not in in_child or next(_segments, None) is None + ): + return resolver + return resolver.in_subresource(subresource) + + return maybe_in_subresource + + +#: JSON Schema draft 2020-12 +DRAFT202012 = Specification( + name="draft2020-12", + id_of=_dollar_id, + subresources_of=_subresources_of( + in_value={ + "additionalProperties", + "contains", + "contentSchema", + "else", + "if", + "items", + "not", + "propertyNames", + "then", + "unevaluatedItems", + "unevaluatedProperties", + }, + in_subarray={"allOf", "anyOf", "oneOf", "prefixItems"}, + in_subvalues={ + "$defs", + "definitions", + "dependentSchemas", + "patternProperties", + "properties", + }, + ), + anchors_in=_anchor, + maybe_in_subresource=_maybe_in_subresource( + in_value={ + "additionalProperties", + "contains", + "contentSchema", + "else", + "if", + "items", + "not", + "propertyNames", + "then", + "unevaluatedItems", + "unevaluatedProperties", + }, + in_subarray={"allOf", "anyOf", "oneOf", "prefixItems"}, + in_subvalues={ + "$defs", + "definitions", + "dependentSchemas", + "patternProperties", + "properties", + }, + ), +) +#: JSON Schema draft 2019-09 +DRAFT201909 = Specification( + name="draft2019-09", + id_of=_dollar_id, + subresources_of=_subresources_of_with_crazy_items( + in_value={ + "additionalItems", + "additionalProperties", + "contains", + "contentSchema", + "else", + "if", + "not", + "propertyNames", + "then", + "unevaluatedItems", + "unevaluatedProperties", + }, + in_subarray={"allOf", "anyOf", "oneOf"}, + in_subvalues={ + "$defs", + "definitions", + "dependentSchemas", + "patternProperties", + "properties", + }, + ), + anchors_in=_anchor_2019, + maybe_in_subresource=_maybe_in_subresource_crazy_items( + in_value={ + "additionalItems", + "additionalProperties", + "contains", + "contentSchema", + "else", + "if", + "not", + "propertyNames", + "then", + "unevaluatedItems", + "unevaluatedProperties", + }, + in_subarray={"allOf", "anyOf", "oneOf"}, + in_subvalues={ + "$defs", + "definitions", + "dependentSchemas", + "patternProperties", + "properties", + }, + ), +) +#: JSON Schema draft 7 +DRAFT7 = Specification( + name="draft-07", + id_of=_legacy_dollar_id, + subresources_of=_subresources_of_with_crazy_items_dependencies( + in_value={ + "additionalItems", + "additionalProperties", + "contains", + "else", + "if", + "not", + "propertyNames", + "then", + }, + in_subarray={"allOf", "anyOf", "oneOf"}, + in_subvalues={"definitions", "patternProperties", "properties"}, + ), + anchors_in=_legacy_anchor_in_dollar_id, + maybe_in_subresource=_maybe_in_subresource_crazy_items_dependencies( + in_value={ + "additionalItems", + "additionalProperties", + "contains", + "else", + "if", + "not", + "propertyNames", + "then", + }, + in_subarray={"allOf", "anyOf", "oneOf"}, + in_subvalues={"definitions", "patternProperties", "properties"}, + ), +) +#: JSON Schema draft 6 +DRAFT6 = Specification( + name="draft-06", + id_of=_legacy_dollar_id, + subresources_of=_subresources_of_with_crazy_items_dependencies( + in_value={ + "additionalItems", + "additionalProperties", + "contains", + "not", + "propertyNames", + }, + in_subarray={"allOf", "anyOf", "oneOf"}, + in_subvalues={"definitions", "patternProperties", "properties"}, + ), + anchors_in=_legacy_anchor_in_dollar_id, + maybe_in_subresource=_maybe_in_subresource_crazy_items_dependencies( + in_value={ + "additionalItems", + "additionalProperties", + "contains", + "not", + "propertyNames", + }, + in_subarray={"allOf", "anyOf", "oneOf"}, + in_subvalues={"definitions", "patternProperties", "properties"}, + ), +) +#: JSON Schema draft 4 +DRAFT4 = Specification( + name="draft-04", + id_of=_legacy_id, + subresources_of=_subresources_of_with_crazy_aP_items_dependencies( + in_value={"not"}, + in_subarray={"allOf", "anyOf", "oneOf"}, + in_subvalues={"definitions", "patternProperties", "properties"}, + ), + anchors_in=_legacy_anchor_in_id, + maybe_in_subresource=_maybe_in_subresource_crazy_items_dependencies( + in_value={"additionalItems", "additionalProperties", "not"}, + in_subarray={"allOf", "anyOf", "oneOf"}, + in_subvalues={"definitions", "patternProperties", "properties"}, + ), +) +#: JSON Schema draft 3 +DRAFT3 = Specification( + name="draft-03", + id_of=_legacy_id, + subresources_of=_subresources_of_with_crazy_aP_items_dependencies( + in_subarray={"extends"}, + in_subvalues={"definitions", "patternProperties", "properties"}, + ), + anchors_in=_legacy_anchor_in_id, + maybe_in_subresource=_maybe_in_subresource_crazy_items_dependencies( + in_value={"additionalItems", "additionalProperties"}, + in_subarray={"extends"}, + in_subvalues={"definitions", "patternProperties", "properties"}, + ), +) + + +_SPECIFICATIONS: Registry[Specification[Schema]] = Registry( + { + dialect_id: Resource.opaque(specification) + for dialect_id, specification in [ + ("https://json-schema.org/draft/2020-12/schema", DRAFT202012), + ("https://json-schema.org/draft/2019-09/schema", DRAFT201909), + ("http://json-schema.org/draft-07/schema", DRAFT7), + ("http://json-schema.org/draft-06/schema", DRAFT6), + ("http://json-schema.org/draft-04/schema", DRAFT4), + ("http://json-schema.org/draft-03/schema", DRAFT3), + ] + }, +) + + +def specification_with( + dialect_id: URI, + default: Specification[Any] | _Unset = _UNSET, +) -> Specification[Any]: + """ + Retrieve the `Specification` with the given dialect identifier. + + Raises: + + `UnknownDialect` + + if the given ``dialect_id`` isn't known + + """ + resource = _SPECIFICATIONS.get(dialect_id.rstrip("#")) + if resource is not None: + return resource.contents + if default is _UNSET: + raise UnknownDialect(dialect_id) + return default + + +@frozen +class DynamicAnchor: + """ + Dynamic anchors, introduced in draft 2020. + """ + + name: str + resource: SchemaResource + + def resolve(self, resolver: _Resolver[Schema]) -> _Resolved[Schema]: + """ + Resolve this anchor dynamically. + """ + last = self.resource + for uri, registry in resolver.dynamic_scope(): + try: + anchor = registry.anchor(uri, self.name).value + except exceptions.NoSuchAnchor: + continue + if isinstance(anchor, DynamicAnchor): + last = anchor.resource + return _Resolved( + contents=last.contents, + resolver=resolver.in_subresource(last), + ) + + +def lookup_recursive_ref(resolver: _Resolver[Schema]) -> _Resolved[Schema]: + """ + Recursive references (via recursive anchors), present only in draft 2019. + + As per the 2019 specification (§ 8.2.4.2.1), only the ``#`` recursive + reference is supported (and is therefore assumed to be the relevant + reference). + """ + resolved = resolver.lookup("#") + if isinstance(resolved.contents, Mapping) and resolved.contents.get( + "$recursiveAnchor", + ): + for uri, _ in resolver.dynamic_scope(): + next_resolved = resolver.lookup(uri) + if not isinstance( + next_resolved.contents, + Mapping, + ) or not next_resolved.contents.get("$recursiveAnchor"): + break + resolved = next_resolved + return resolved diff --git a/.venv/lib/python3.10/site-packages/referencing/py.typed b/.venv/lib/python3.10/site-packages/referencing/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/.venv/lib/python3.10/site-packages/referencing/retrieval.py b/.venv/lib/python3.10/site-packages/referencing/retrieval.py new file mode 100644 index 0000000..53e0512 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing/retrieval.py @@ -0,0 +1,92 @@ +""" +Helpers related to (dynamic) resource retrieval. +""" + +from __future__ import annotations + +from functools import lru_cache +from typing import TYPE_CHECKING, Callable +import json + +try: + from typing_extensions import TypeVar +except ImportError: # pragma: no cover + from typing import TypeVar + +from referencing import Resource + +if TYPE_CHECKING: + from referencing.typing import URI, D, Retrieve + +#: A serialized document (e.g. a JSON string) +_T = TypeVar("_T", default=str) + + +def to_cached_resource( + cache: Callable[[Retrieve[D]], Retrieve[D]] | None = None, + loads: Callable[[_T], D] = json.loads, + from_contents: Callable[[D], Resource[D]] = Resource.from_contents, +) -> Callable[[Callable[[URI], _T]], Retrieve[D]]: + """ + Create a retriever which caches its return values from a simpler callable. + + Takes a function which returns things like serialized JSON (strings) and + returns something suitable for passing to `Registry` as a retrieve + function. + + This decorator both reduces a small bit of boilerplate for a common case + (deserializing JSON from strings and creating `Resource` objects from the + result) as well as makes the probable need for caching a bit easier. + Retrievers which otherwise do expensive operations (like hitting the + network) might otherwise be called repeatedly. + + Examples + -------- + + .. testcode:: + + from referencing import Registry + from referencing.typing import URI + import referencing.retrieval + + + @referencing.retrieval.to_cached_resource() + def retrieve(uri: URI): + print(f"Retrieved {uri}") + + # Normally, go get some expensive JSON from the network, a file ... + return ''' + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "foo": "bar" + } + ''' + + one = Registry(retrieve=retrieve).get_or_retrieve("urn:example:foo") + print(one.value.contents["foo"]) + + # Retrieving the same URI again reuses the same value (and thus doesn't + # print another retrieval message here) + two = Registry(retrieve=retrieve).get_or_retrieve("urn:example:foo") + print(two.value.contents["foo"]) + + .. testoutput:: + + Retrieved urn:example:foo + bar + bar + + """ + if cache is None: + cache = lru_cache(maxsize=None) + + def decorator(retrieve: Callable[[URI], _T]): + @cache + def cached_retrieve(uri: URI): + response = retrieve(uri) + contents = loads(response) + return from_contents(contents) + + return cached_retrieve + + return decorator diff --git a/.venv/lib/python3.10/site-packages/referencing/tests/__init__.py b/.venv/lib/python3.10/site-packages/referencing/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/.venv/lib/python3.10/site-packages/referencing/tests/test_core.py b/.venv/lib/python3.10/site-packages/referencing/tests/test_core.py new file mode 100644 index 0000000..3edddbc --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing/tests/test_core.py @@ -0,0 +1,1057 @@ +from rpds import HashTrieMap +import pytest + +from referencing import Anchor, Registry, Resource, Specification, exceptions +from referencing.jsonschema import DRAFT202012 + +ID_AND_CHILDREN = Specification( + name="id-and-children", + id_of=lambda contents: contents.get("ID"), + subresources_of=lambda contents: contents.get("children", []), + anchors_in=lambda specification, contents: [ + Anchor( + name=name, + resource=specification.create_resource(contents=each), + ) + for name, each in contents.get("anchors", {}).items() + ], + maybe_in_subresource=lambda segments, resolver, subresource: ( + resolver.in_subresource(subresource) + if not len(segments) % 2 + and all(each == "children" for each in segments[::2]) + else resolver + ), +) + + +def blow_up(uri): # pragma: no cover + """ + A retriever suitable for use in tests which expect it never to be used. + """ + raise RuntimeError("This retrieve function expects to never be called!") + + +class TestRegistry: + def test_with_resource(self): + """ + Adding a resource to the registry then allows re-retrieving it. + """ + + resource = Resource.opaque(contents={"foo": "bar"}) + uri = "urn:example" + registry = Registry().with_resource(uri=uri, resource=resource) + assert registry[uri] is resource + + def test_with_resources(self): + """ + Adding multiple resources to the registry is like adding each one. + """ + + one = Resource.opaque(contents={}) + two = Resource(contents={"foo": "bar"}, specification=ID_AND_CHILDREN) + registry = Registry().with_resources( + [ + ("http://example.com/1", one), + ("http://example.com/foo/bar", two), + ], + ) + assert registry == Registry().with_resource( + uri="http://example.com/1", + resource=one, + ).with_resource( + uri="http://example.com/foo/bar", + resource=two, + ) + + def test_matmul_resource(self): + uri = "urn:example:resource" + resource = ID_AND_CHILDREN.create_resource({"ID": uri, "foo": 12}) + registry = resource @ Registry() + assert registry == Registry().with_resource(uri, resource) + + def test_matmul_many_resources(self): + one_uri = "urn:example:one" + one = ID_AND_CHILDREN.create_resource({"ID": one_uri, "foo": 12}) + + two_uri = "urn:example:two" + two = ID_AND_CHILDREN.create_resource({"ID": two_uri, "foo": 12}) + + registry = [one, two] @ Registry() + assert registry == Registry().with_resources( + [(one_uri, one), (two_uri, two)], + ) + + def test_matmul_resource_without_id(self): + resource = Resource.opaque(contents={"foo": "bar"}) + with pytest.raises(exceptions.NoInternalID) as e: + resource @ Registry() + assert e.value == exceptions.NoInternalID(resource=resource) + + def test_with_contents_from_json_schema(self): + uri = "urn:example" + schema = {"$schema": "https://json-schema.org/draft/2020-12/schema"} + registry = Registry().with_contents([(uri, schema)]) + + expected = Resource(contents=schema, specification=DRAFT202012) + assert registry[uri] == expected + + def test_with_contents_and_default_specification(self): + uri = "urn:example" + registry = Registry().with_contents( + [(uri, {"foo": "bar"})], + default_specification=Specification.OPAQUE, + ) + assert registry[uri] == Resource.opaque({"foo": "bar"}) + + def test_len(self): + total = 5 + registry = Registry().with_contents( + [(str(i), {"foo": "bar"}) for i in range(total)], + default_specification=Specification.OPAQUE, + ) + assert len(registry) == total + + def test_bool_empty(self): + assert not Registry() + + def test_bool_not_empty(self): + registry = Registry().with_contents( + [(str(i), {"foo": "bar"}) for i in range(3)], + default_specification=Specification.OPAQUE, + ) + assert registry + + def test_iter(self): + registry = Registry().with_contents( + [(str(i), {"foo": "bar"}) for i in range(8)], + default_specification=Specification.OPAQUE, + ) + assert set(registry) == {str(i) for i in range(8)} + + def test_crawl_still_has_top_level_resource(self): + resource = Resource.opaque({"foo": "bar"}) + uri = "urn:example" + registry = Registry({uri: resource}).crawl() + assert registry[uri] is resource + + def test_crawl_finds_a_subresource(self): + child_id = "urn:child" + root = ID_AND_CHILDREN.create_resource( + {"ID": "urn:root", "children": [{"ID": child_id, "foo": 12}]}, + ) + registry = root @ Registry() + with pytest.raises(LookupError): + registry[child_id] + + expected = ID_AND_CHILDREN.create_resource({"ID": child_id, "foo": 12}) + assert registry.crawl()[child_id] == expected + + def test_crawl_finds_anchors_with_id(self): + resource = ID_AND_CHILDREN.create_resource( + {"ID": "urn:bar", "anchors": {"foo": 12}}, + ) + registry = resource @ Registry() + + assert registry.crawl().anchor(resource.id(), "foo").value == Anchor( + name="foo", + resource=ID_AND_CHILDREN.create_resource(12), + ) + + def test_crawl_finds_anchors_no_id(self): + resource = ID_AND_CHILDREN.create_resource({"anchors": {"foo": 12}}) + registry = Registry().with_resource("urn:root", resource) + + assert registry.crawl().anchor("urn:root", "foo").value == Anchor( + name="foo", + resource=ID_AND_CHILDREN.create_resource(12), + ) + + def test_contents(self): + resource = Resource.opaque({"foo": "bar"}) + uri = "urn:example" + registry = Registry().with_resource(uri, resource) + assert registry.contents(uri) == {"foo": "bar"} + + def test_getitem_strips_empty_fragments(self): + uri = "http://example.com/" + resource = ID_AND_CHILDREN.create_resource({"ID": uri + "#"}) + registry = resource @ Registry() + assert registry[uri] == registry[uri + "#"] == resource + + def test_contents_strips_empty_fragments(self): + uri = "http://example.com/" + resource = ID_AND_CHILDREN.create_resource({"ID": uri + "#"}) + registry = resource @ Registry() + assert ( + registry.contents(uri) + == registry.contents(uri + "#") + == {"ID": uri + "#"} + ) + + def test_contents_nonexistent_resource(self): + registry = Registry() + with pytest.raises(exceptions.NoSuchResource) as e: + registry.contents("urn:example") + assert e.value == exceptions.NoSuchResource(ref="urn:example") + + def test_crawled_anchor(self): + resource = ID_AND_CHILDREN.create_resource({"anchors": {"foo": "bar"}}) + registry = Registry().with_resource("urn:example", resource) + retrieved = registry.anchor("urn:example", "foo") + assert retrieved.value == Anchor( + name="foo", + resource=ID_AND_CHILDREN.create_resource("bar"), + ) + assert retrieved.registry == registry.crawl() + + def test_anchor_in_nonexistent_resource(self): + registry = Registry() + with pytest.raises(exceptions.NoSuchResource) as e: + registry.anchor("urn:example", "foo") + assert e.value == exceptions.NoSuchResource(ref="urn:example") + + def test_init(self): + one = Resource.opaque(contents={}) + two = ID_AND_CHILDREN.create_resource({"foo": "bar"}) + registry = Registry( + { + "http://example.com/1": one, + "http://example.com/foo/bar": two, + }, + ) + assert ( + registry + == Registry() + .with_resources( + [ + ("http://example.com/1", one), + ("http://example.com/foo/bar", two), + ], + ) + .crawl() + ) + + def test_dict_conversion(self): + """ + Passing a `dict` to `Registry` gets converted to a `HashTrieMap`. + + So continuing to use the registry works. + """ + + one = Resource.opaque(contents={}) + two = ID_AND_CHILDREN.create_resource({"foo": "bar"}) + registry = Registry( + {"http://example.com/1": one}, + ).with_resource("http://example.com/foo/bar", two) + assert ( + registry.crawl() + == Registry() + .with_resources( + [ + ("http://example.com/1", one), + ("http://example.com/foo/bar", two), + ], + ) + .crawl() + ) + + def test_no_such_resource(self): + registry = Registry() + with pytest.raises(exceptions.NoSuchResource) as e: + registry["urn:bigboom"] + assert e.value == exceptions.NoSuchResource(ref="urn:bigboom") + + def test_combine(self): + one = Resource.opaque(contents={}) + two = ID_AND_CHILDREN.create_resource({"foo": "bar"}) + three = ID_AND_CHILDREN.create_resource({"baz": "quux"}) + four = ID_AND_CHILDREN.create_resource({"anchors": {"foo": 12}}) + + first = Registry({"http://example.com/1": one}) + second = Registry().with_resource("http://example.com/foo/bar", two) + third = Registry( + { + "http://example.com/1": one, + "http://example.com/baz": three, + }, + ) + fourth = ( + Registry() + .with_resource( + "http://example.com/foo/quux", + four, + ) + .crawl() + ) + assert first.combine(second, third, fourth) == Registry( + [ + ("http://example.com/1", one), + ("http://example.com/baz", three), + ("http://example.com/foo/quux", four), + ], + anchors=HashTrieMap( + { + ("http://example.com/foo/quux", "foo"): Anchor( + name="foo", + resource=ID_AND_CHILDREN.create_resource(12), + ), + }, + ), + ).with_resource("http://example.com/foo/bar", two) + + def test_combine_self(self): + """ + Combining a registry with itself short-circuits. + + This is a performance optimization -- otherwise we do lots more work + (in jsonschema this seems to correspond to making the test suite take + *3x* longer). + """ + + registry = Registry({"urn:foo": "bar"}) + assert registry.combine(registry) is registry + + def test_combine_with_uncrawled_resources(self): + one = Resource.opaque(contents={}) + two = ID_AND_CHILDREN.create_resource({"foo": "bar"}) + three = ID_AND_CHILDREN.create_resource({"baz": "quux"}) + + first = Registry().with_resource("http://example.com/1", one) + second = Registry().with_resource("http://example.com/foo/bar", two) + third = Registry( + { + "http://example.com/1": one, + "http://example.com/baz": three, + }, + ) + expected = Registry( + [ + ("http://example.com/1", one), + ("http://example.com/foo/bar", two), + ("http://example.com/baz", three), + ], + ) + combined = first.combine(second, third) + assert combined != expected + assert combined.crawl() == expected + + def test_combine_with_single_retrieve(self): + one = Resource.opaque(contents={}) + two = ID_AND_CHILDREN.create_resource({"foo": "bar"}) + three = ID_AND_CHILDREN.create_resource({"baz": "quux"}) + + def retrieve(uri): # pragma: no cover + pass + + first = Registry().with_resource("http://example.com/1", one) + second = Registry( + retrieve=retrieve, + ).with_resource("http://example.com/2", two) + third = Registry().with_resource("http://example.com/3", three) + + assert first.combine(second, third) == Registry( + retrieve=retrieve, + ).with_resources( + [ + ("http://example.com/1", one), + ("http://example.com/2", two), + ("http://example.com/3", three), + ], + ) + assert second.combine(first, third) == Registry( + retrieve=retrieve, + ).with_resources( + [ + ("http://example.com/1", one), + ("http://example.com/2", two), + ("http://example.com/3", three), + ], + ) + + def test_combine_with_common_retrieve(self): + one = Resource.opaque(contents={}) + two = ID_AND_CHILDREN.create_resource({"foo": "bar"}) + three = ID_AND_CHILDREN.create_resource({"baz": "quux"}) + + def retrieve(uri): # pragma: no cover + pass + + first = Registry(retrieve=retrieve).with_resource( + "http://example.com/1", + one, + ) + second = Registry( + retrieve=retrieve, + ).with_resource("http://example.com/2", two) + third = Registry(retrieve=retrieve).with_resource( + "http://example.com/3", + three, + ) + + assert first.combine(second, third) == Registry( + retrieve=retrieve, + ).with_resources( + [ + ("http://example.com/1", one), + ("http://example.com/2", two), + ("http://example.com/3", three), + ], + ) + assert second.combine(first, third) == Registry( + retrieve=retrieve, + ).with_resources( + [ + ("http://example.com/1", one), + ("http://example.com/2", two), + ("http://example.com/3", three), + ], + ) + + def test_combine_conflicting_retrieve(self): + one = Resource.opaque(contents={}) + two = ID_AND_CHILDREN.create_resource({"foo": "bar"}) + three = ID_AND_CHILDREN.create_resource({"baz": "quux"}) + + def foo_retrieve(uri): # pragma: no cover + pass + + def bar_retrieve(uri): # pragma: no cover + pass + + first = Registry(retrieve=foo_retrieve).with_resource( + "http://example.com/1", + one, + ) + second = Registry().with_resource("http://example.com/2", two) + third = Registry(retrieve=bar_retrieve).with_resource( + "http://example.com/3", + three, + ) + + with pytest.raises(Exception, match="conflict.*retriev"): + first.combine(second, third) + + def test_remove(self): + one = Resource.opaque(contents={}) + two = ID_AND_CHILDREN.create_resource({"foo": "bar"}) + registry = Registry({"urn:foo": one, "urn:bar": two}) + assert registry.remove("urn:foo") == Registry({"urn:bar": two}) + + def test_remove_uncrawled(self): + one = Resource.opaque(contents={}) + two = ID_AND_CHILDREN.create_resource({"foo": "bar"}) + registry = Registry().with_resources( + [("urn:foo", one), ("urn:bar", two)], + ) + assert registry.remove("urn:foo") == Registry().with_resource( + "urn:bar", + two, + ) + + def test_remove_with_anchors(self): + one = Resource.opaque(contents={}) + two = ID_AND_CHILDREN.create_resource({"anchors": {"foo": "bar"}}) + registry = ( + Registry() + .with_resources( + [("urn:foo", one), ("urn:bar", two)], + ) + .crawl() + ) + assert ( + registry.remove("urn:bar") + == Registry() + .with_resource( + "urn:foo", + one, + ) + .crawl() + ) + + def test_remove_nonexistent_uri(self): + with pytest.raises(exceptions.NoSuchResource) as e: + Registry().remove("urn:doesNotExist") + assert e.value == exceptions.NoSuchResource(ref="urn:doesNotExist") + + def test_retrieve(self): + foo = Resource.opaque({"foo": "bar"}) + registry = Registry(retrieve=lambda uri: foo) + assert registry.get_or_retrieve("urn:example").value == foo + + def test_retrieve_arbitrary_exception(self): + foo = Resource.opaque({"foo": "bar"}) + + def retrieve(uri): + if uri == "urn:succeed": + return foo + raise Exception("Oh no!") + + registry = Registry(retrieve=retrieve) + assert registry.get_or_retrieve("urn:succeed").value == foo + with pytest.raises(exceptions.Unretrievable): + registry.get_or_retrieve("urn:uhoh") + + def test_retrieve_no_such_resource(self): + foo = Resource.opaque({"foo": "bar"}) + + def retrieve(uri): + if uri == "urn:succeed": + return foo + raise exceptions.NoSuchResource(ref=uri) + + registry = Registry(retrieve=retrieve) + assert registry.get_or_retrieve("urn:succeed").value == foo + with pytest.raises(exceptions.NoSuchResource): + registry.get_or_retrieve("urn:uhoh") + + def test_retrieve_cannot_determine_specification(self): + def retrieve(uri): + return Resource.from_contents({}) + + registry = Registry(retrieve=retrieve) + with pytest.raises(exceptions.CannotDetermineSpecification): + registry.get_or_retrieve("urn:uhoh") + + def test_retrieve_already_available_resource(self): + foo = Resource.opaque({"foo": "bar"}) + registry = Registry({"urn:example": foo}, retrieve=blow_up) + assert registry["urn:example"] == foo + assert registry.get_or_retrieve("urn:example").value == foo + + def test_retrieve_first_checks_crawlable_resource(self): + child = ID_AND_CHILDREN.create_resource({"ID": "urn:child", "foo": 12}) + root = ID_AND_CHILDREN.create_resource({"children": [child.contents]}) + registry = Registry(retrieve=blow_up).with_resource("urn:root", root) + assert registry.crawl()["urn:child"] == child + + def test_resolver(self): + one = Resource.opaque(contents={}) + registry = Registry({"http://example.com": one}) + resolver = registry.resolver(base_uri="http://example.com") + assert resolver.lookup("#").contents == {} + + def test_resolver_with_root_identified(self): + root = ID_AND_CHILDREN.create_resource({"ID": "http://example.com"}) + resolver = Registry().resolver_with_root(root) + assert resolver.lookup("http://example.com").contents == root.contents + assert resolver.lookup("#").contents == root.contents + + def test_resolver_with_root_unidentified(self): + root = Resource.opaque(contents={}) + resolver = Registry().resolver_with_root(root) + assert resolver.lookup("#").contents == root.contents + + def test_repr(self): + one = Resource.opaque(contents={}) + two = ID_AND_CHILDREN.create_resource({"foo": "bar"}) + registry = Registry().with_resources( + [ + ("http://example.com/1", one), + ("http://example.com/foo/bar", two), + ], + ) + assert repr(registry) == "" + assert repr(registry.crawl()) == "" + + def test_repr_mixed_crawled(self): + one = Resource.opaque(contents={}) + two = ID_AND_CHILDREN.create_resource({"foo": "bar"}) + registry = ( + Registry( + {"http://example.com/1": one}, + ) + .crawl() + .with_resource(uri="http://example.com/foo/bar", resource=two) + ) + assert repr(registry) == "" + + def test_repr_one_resource(self): + registry = Registry().with_resource( + uri="http://example.com/1", + resource=Resource.opaque(contents={}), + ) + assert repr(registry) == "" + + def test_repr_empty(self): + assert repr(Registry()) == "" + + +class TestResource: + def test_from_contents_from_json_schema(self): + schema = {"$schema": "https://json-schema.org/draft/2020-12/schema"} + resource = Resource.from_contents(schema) + assert resource == Resource(contents=schema, specification=DRAFT202012) + + def test_from_contents_with_no_discernible_information(self): + """ + Creating a resource with no discernible way to see what + specification it belongs to (e.g. no ``$schema`` keyword for JSON + Schema) raises an error. + """ + + with pytest.raises(exceptions.CannotDetermineSpecification): + Resource.from_contents({"foo": "bar"}) + + def test_from_contents_with_no_discernible_information_and_default(self): + resource = Resource.from_contents( + {"foo": "bar"}, + default_specification=Specification.OPAQUE, + ) + assert resource == Resource.opaque(contents={"foo": "bar"}) + + def test_from_contents_unneeded_default(self): + schema = {"$schema": "https://json-schema.org/draft/2020-12/schema"} + resource = Resource.from_contents( + schema, + default_specification=Specification.OPAQUE, + ) + assert resource == Resource( + contents=schema, + specification=DRAFT202012, + ) + + def test_non_mapping_from_contents(self): + resource = Resource.from_contents( + True, + default_specification=ID_AND_CHILDREN, + ) + assert resource == Resource( + contents=True, + specification=ID_AND_CHILDREN, + ) + + def test_from_contents_with_fallback(self): + resource = Resource.from_contents( + {"foo": "bar"}, + default_specification=Specification.OPAQUE, + ) + assert resource == Resource.opaque(contents={"foo": "bar"}) + + def test_id_delegates_to_specification(self): + specification = Specification( + name="", + id_of=lambda contents: "urn:fixedID", + subresources_of=lambda contents: [], + anchors_in=lambda specification, contents: [], + maybe_in_subresource=( + lambda segments, resolver, subresource: resolver + ), + ) + resource = Resource( + contents={"foo": "baz"}, + specification=specification, + ) + assert resource.id() == "urn:fixedID" + + def test_id_strips_empty_fragment(self): + uri = "http://example.com/" + root = ID_AND_CHILDREN.create_resource({"ID": uri + "#"}) + assert root.id() == uri + + def test_subresources_delegates_to_specification(self): + resource = ID_AND_CHILDREN.create_resource({"children": [{}, 12]}) + assert list(resource.subresources()) == [ + ID_AND_CHILDREN.create_resource(each) for each in [{}, 12] + ] + + def test_subresource_with_different_specification(self): + schema = {"$schema": "https://json-schema.org/draft/2020-12/schema"} + resource = ID_AND_CHILDREN.create_resource({"children": [schema]}) + assert list(resource.subresources()) == [ + DRAFT202012.create_resource(schema), + ] + + def test_anchors_delegates_to_specification(self): + resource = ID_AND_CHILDREN.create_resource( + {"anchors": {"foo": {}, "bar": 1, "baz": ""}}, + ) + assert list(resource.anchors()) == [ + Anchor(name="foo", resource=ID_AND_CHILDREN.create_resource({})), + Anchor(name="bar", resource=ID_AND_CHILDREN.create_resource(1)), + Anchor(name="baz", resource=ID_AND_CHILDREN.create_resource("")), + ] + + def test_pointer_to_mapping(self): + resource = Resource.opaque(contents={"foo": "baz"}) + resolver = Registry().resolver() + assert resource.pointer("/foo", resolver=resolver).contents == "baz" + + def test_pointer_to_array(self): + resource = Resource.opaque(contents={"foo": {"bar": [3]}}) + resolver = Registry().resolver() + assert resource.pointer("/foo/bar/0", resolver=resolver).contents == 3 + + def test_root_pointer(self): + contents = {"foo": "baz"} + resource = Resource.opaque(contents=contents) + resolver = Registry().resolver() + assert resource.pointer("", resolver=resolver).contents == contents + + def test_opaque(self): + contents = {"foo": "bar"} + assert Resource.opaque(contents) == Resource( + contents=contents, + specification=Specification.OPAQUE, + ) + + +class TestResolver: + def test_lookup_exact_uri(self): + resource = Resource.opaque(contents={"foo": "baz"}) + resolver = Registry({"http://example.com/1": resource}).resolver() + resolved = resolver.lookup("http://example.com/1") + assert resolved.contents == resource.contents + + def test_lookup_subresource(self): + root = ID_AND_CHILDREN.create_resource( + { + "ID": "http://example.com/", + "children": [ + {"ID": "http://example.com/a", "foo": 12}, + ], + }, + ) + registry = root @ Registry() + resolved = registry.resolver().lookup("http://example.com/a") + assert resolved.contents == {"ID": "http://example.com/a", "foo": 12} + + def test_lookup_anchor_with_id(self): + root = ID_AND_CHILDREN.create_resource( + { + "ID": "http://example.com/", + "anchors": {"foo": 12}, + }, + ) + registry = root @ Registry() + resolved = registry.resolver().lookup("http://example.com/#foo") + assert resolved.contents == 12 + + def test_lookup_anchor_without_id(self): + root = ID_AND_CHILDREN.create_resource({"anchors": {"foo": 12}}) + resolver = Registry().with_resource("urn:example", root).resolver() + resolved = resolver.lookup("urn:example#foo") + assert resolved.contents == 12 + + def test_lookup_unknown_reference(self): + resolver = Registry().resolver() + ref = "http://example.com/does/not/exist" + with pytest.raises(exceptions.Unresolvable) as e: + resolver.lookup(ref) + assert e.value == exceptions.Unresolvable(ref=ref) + + def test_lookup_non_existent_pointer(self): + resource = Resource.opaque({"foo": {}}) + resolver = Registry({"http://example.com/1": resource}).resolver() + ref = "http://example.com/1#/foo/bar" + with pytest.raises(exceptions.Unresolvable) as e: + resolver.lookup(ref) + assert e.value == exceptions.PointerToNowhere( + ref="/foo/bar", + resource=resource, + ) + assert str(e.value) == "'/foo/bar' does not exist within {'foo': {}}" + + def test_lookup_non_existent_pointer_to_array_index(self): + resource = Resource.opaque([1, 2, 4, 8]) + resolver = Registry({"http://example.com/1": resource}).resolver() + ref = "http://example.com/1#/10" + with pytest.raises(exceptions.Unresolvable) as e: + resolver.lookup(ref) + assert e.value == exceptions.PointerToNowhere( + ref="/10", + resource=resource, + ) + + def test_lookup_pointer_to_empty_string(self): + resolver = Registry().resolver_with_root(Resource.opaque({"": {}})) + assert resolver.lookup("#/").contents == {} + + def test_lookup_non_existent_pointer_to_empty_string(self): + resource = Resource.opaque({"foo": {}}) + resolver = Registry().resolver_with_root(resource) + with pytest.raises( + exceptions.Unresolvable, + match="^'/' does not exist within {'foo': {}}.*'#'", + ) as e: + resolver.lookup("#/") + assert e.value == exceptions.PointerToNowhere( + ref="/", + resource=resource, + ) + + def test_lookup_non_existent_anchor(self): + root = ID_AND_CHILDREN.create_resource({"anchors": {}}) + resolver = Registry().with_resource("urn:example", root).resolver() + resolved = resolver.lookup("urn:example") + assert resolved.contents == root.contents + + ref = "urn:example#noSuchAnchor" + with pytest.raises(exceptions.Unresolvable) as e: + resolver.lookup(ref) + assert "'noSuchAnchor' does not exist" in str(e.value) + assert e.value == exceptions.NoSuchAnchor( + ref="urn:example", + resource=root, + anchor="noSuchAnchor", + ) + + def test_lookup_invalid_JSON_pointerish_anchor(self): + resolver = Registry().resolver_with_root( + ID_AND_CHILDREN.create_resource( + { + "ID": "http://example.com/", + "foo": {"bar": 12}, + }, + ), + ) + + valid = resolver.lookup("#/foo/bar") + assert valid.contents == 12 + + with pytest.raises(exceptions.InvalidAnchor) as e: + resolver.lookup("#foo/bar") + assert " '#/foo/bar'" in str(e.value) + + def test_lookup_retrieved_resource(self): + resource = Resource.opaque(contents={"foo": "baz"}) + resolver = Registry(retrieve=lambda uri: resource).resolver() + resolved = resolver.lookup("http://example.com/") + assert resolved.contents == resource.contents + + def test_lookup_failed_retrieved_resource(self): + """ + Unretrievable exceptions are also wrapped in Unresolvable. + """ + + uri = "http://example.com/" + + registry = Registry(retrieve=blow_up) + with pytest.raises(exceptions.Unretrievable): + registry.get_or_retrieve(uri) + + resolver = registry.resolver() + with pytest.raises(exceptions.Unresolvable): + resolver.lookup(uri) + + def test_repeated_lookup_from_retrieved_resource(self): + """ + A (custom-)retrieved resource is added to the registry returned by + looking it up. + """ + resource = Resource.opaque(contents={"foo": "baz"}) + once = [resource] + + def retrieve(uri): + return once.pop() + + resolver = Registry(retrieve=retrieve).resolver() + resolved = resolver.lookup("http://example.com/") + assert resolved.contents == resource.contents + + resolved = resolved.resolver.lookup("http://example.com/") + assert resolved.contents == resource.contents + + def test_repeated_anchor_lookup_from_retrieved_resource(self): + resource = Resource.opaque(contents={"foo": "baz"}) + once = [resource] + + def retrieve(uri): + return once.pop() + + resolver = Registry(retrieve=retrieve).resolver() + resolved = resolver.lookup("http://example.com/") + assert resolved.contents == resource.contents + + resolved = resolved.resolver.lookup("#") + assert resolved.contents == resource.contents + + # FIXME: The tests below aren't really representable in the current + # suite, though we should probably think of ways to do so. + + def test_in_subresource(self): + root = ID_AND_CHILDREN.create_resource( + { + "ID": "http://example.com/", + "children": [ + { + "ID": "child/", + "children": [{"ID": "grandchild"}], + }, + ], + }, + ) + registry = root @ Registry() + + resolver = registry.resolver() + first = resolver.lookup("http://example.com/") + assert first.contents == root.contents + + with pytest.raises(exceptions.Unresolvable): + first.resolver.lookup("grandchild") + + sub = first.resolver.in_subresource( + ID_AND_CHILDREN.create_resource(first.contents["children"][0]), + ) + second = sub.lookup("grandchild") + assert second.contents == {"ID": "grandchild"} + + def test_in_pointer_subresource(self): + root = ID_AND_CHILDREN.create_resource( + { + "ID": "http://example.com/", + "children": [ + { + "ID": "child/", + "children": [{"ID": "grandchild"}], + }, + ], + }, + ) + registry = root @ Registry() + + resolver = registry.resolver() + first = resolver.lookup("http://example.com/") + assert first.contents == root.contents + + with pytest.raises(exceptions.Unresolvable): + first.resolver.lookup("grandchild") + + second = first.resolver.lookup("#/children/0") + third = second.resolver.lookup("grandchild") + assert third.contents == {"ID": "grandchild"} + + def test_dynamic_scope(self): + one = ID_AND_CHILDREN.create_resource( + { + "ID": "http://example.com/", + "children": [ + { + "ID": "child/", + "children": [{"ID": "grandchild"}], + }, + ], + }, + ) + two = ID_AND_CHILDREN.create_resource( + { + "ID": "http://example.com/two", + "children": [{"ID": "two-child/"}], + }, + ) + registry = [one, two] @ Registry() + + resolver = registry.resolver() + first = resolver.lookup("http://example.com/") + second = first.resolver.lookup("#/children/0") + third = second.resolver.lookup("grandchild") + fourth = third.resolver.lookup("http://example.com/two") + assert list(fourth.resolver.dynamic_scope()) == [ + ("http://example.com/child/grandchild", fourth.resolver._registry), + ("http://example.com/child/", fourth.resolver._registry), + ("http://example.com/", fourth.resolver._registry), + ] + assert list(third.resolver.dynamic_scope()) == [ + ("http://example.com/child/", third.resolver._registry), + ("http://example.com/", third.resolver._registry), + ] + assert list(second.resolver.dynamic_scope()) == [ + ("http://example.com/", second.resolver._registry), + ] + assert list(first.resolver.dynamic_scope()) == [] + + +class TestSpecification: + def test_create_resource(self): + specification = Specification( + name="", + id_of=lambda contents: "urn:fixedID", + subresources_of=lambda contents: [], + anchors_in=lambda specification, contents: [], + maybe_in_subresource=( + lambda segments, resolver, subresource: resolver + ), + ) + resource = specification.create_resource(contents={"foo": "baz"}) + assert resource == Resource( + contents={"foo": "baz"}, + specification=specification, + ) + assert resource.id() == "urn:fixedID" + + def test_detect_from_json_schema(self): + schema = {"$schema": "https://json-schema.org/draft/2020-12/schema"} + specification = Specification.detect(schema) + assert specification == DRAFT202012 + + def test_detect_with_no_discernible_information(self): + with pytest.raises(exceptions.CannotDetermineSpecification): + Specification.detect({"foo": "bar"}) + + def test_detect_with_non_URI_schema(self): + with pytest.raises(exceptions.CannotDetermineSpecification): + Specification.detect({"$schema": 37}) + + def test_detect_with_no_discernible_information_and_default(self): + specification = Specification.OPAQUE.detect({"foo": "bar"}) + assert specification is Specification.OPAQUE + + def test_detect_unneeded_default(self): + schema = {"$schema": "https://json-schema.org/draft/2020-12/schema"} + specification = Specification.OPAQUE.detect(schema) + assert specification == DRAFT202012 + + def test_non_mapping_detect(self): + with pytest.raises(exceptions.CannotDetermineSpecification): + Specification.detect(True) + + def test_non_mapping_detect_with_default(self): + specification = ID_AND_CHILDREN.detect(True) + assert specification is ID_AND_CHILDREN + + def test_detect_with_fallback(self): + specification = Specification.OPAQUE.detect({"foo": "bar"}) + assert specification is Specification.OPAQUE + + def test_repr(self): + assert ( + repr(ID_AND_CHILDREN) == "" + ) + + +class TestOpaqueSpecification: + THINGS = [{"foo": "bar"}, True, 37, "foo", object()] + + @pytest.mark.parametrize("thing", THINGS) + def test_no_id(self, thing): + """ + An arbitrary thing has no ID. + """ + + assert Specification.OPAQUE.id_of(thing) is None + + @pytest.mark.parametrize("thing", THINGS) + def test_no_subresources(self, thing): + """ + An arbitrary thing has no subresources. + """ + + assert list(Specification.OPAQUE.subresources_of(thing)) == [] + + @pytest.mark.parametrize("thing", THINGS) + def test_no_anchors(self, thing): + """ + An arbitrary thing has no anchors. + """ + + assert list(Specification.OPAQUE.anchors_in(thing)) == [] + + +@pytest.mark.parametrize( + "cls", + [Anchor, Registry, Resource, Specification, exceptions.PointerToNowhere], +) +def test_nonsubclassable(cls): + with pytest.raises(Exception, match="(?i)subclassing"): + + class Boom(cls): # pragma: no cover + pass diff --git a/.venv/lib/python3.10/site-packages/referencing/tests/test_exceptions.py b/.venv/lib/python3.10/site-packages/referencing/tests/test_exceptions.py new file mode 100644 index 0000000..85cf99e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing/tests/test_exceptions.py @@ -0,0 +1,34 @@ +import itertools + +import pytest + +from referencing import Resource, exceptions + + +def pairs(choices): + return itertools.combinations(choices, 2) + + +TRUE = Resource.opaque(True) + + +thunks = ( + lambda: exceptions.CannotDetermineSpecification(TRUE), + lambda: exceptions.NoSuchResource("urn:example:foo"), + lambda: exceptions.NoInternalID(TRUE), + lambda: exceptions.InvalidAnchor(resource=TRUE, anchor="foo", ref="a#b"), + lambda: exceptions.NoSuchAnchor(resource=TRUE, anchor="foo", ref="a#b"), + lambda: exceptions.PointerToNowhere(resource=TRUE, ref="urn:example:foo"), + lambda: exceptions.Unresolvable("urn:example:foo"), + lambda: exceptions.Unretrievable("urn:example:foo"), +) + + +@pytest.mark.parametrize("one, two", pairs(each() for each in thunks)) +def test_eq_incompatible_types(one, two): + assert one != two + + +@pytest.mark.parametrize("thunk", thunks) +def test_hash(thunk): + assert thunk() in {thunk()} diff --git a/.venv/lib/python3.10/site-packages/referencing/tests/test_jsonschema.py b/.venv/lib/python3.10/site-packages/referencing/tests/test_jsonschema.py new file mode 100644 index 0000000..c80714d --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing/tests/test_jsonschema.py @@ -0,0 +1,382 @@ +import pytest + +from referencing import Registry, Resource, Specification +import referencing.jsonschema + + +@pytest.mark.parametrize( + "uri, expected", + [ + ( + "https://json-schema.org/draft/2020-12/schema", + referencing.jsonschema.DRAFT202012, + ), + ( + "https://json-schema.org/draft/2019-09/schema", + referencing.jsonschema.DRAFT201909, + ), + ( + "http://json-schema.org/draft-07/schema#", + referencing.jsonschema.DRAFT7, + ), + ( + "http://json-schema.org/draft-06/schema#", + referencing.jsonschema.DRAFT6, + ), + ( + "http://json-schema.org/draft-04/schema#", + referencing.jsonschema.DRAFT4, + ), + ( + "http://json-schema.org/draft-03/schema#", + referencing.jsonschema.DRAFT3, + ), + ], +) +def test_schemas_with_explicit_schema_keywords_are_detected(uri, expected): + """ + The $schema keyword in JSON Schema is a dialect identifier. + """ + contents = {"$schema": uri} + resource = Resource.from_contents(contents) + assert resource == Resource(contents=contents, specification=expected) + + +def test_unknown_dialect(): + dialect_id = "http://example.com/unknown-json-schema-dialect-id" + with pytest.raises(referencing.jsonschema.UnknownDialect) as excinfo: + Resource.from_contents({"$schema": dialect_id}) + assert excinfo.value.uri == dialect_id + + +@pytest.mark.parametrize( + "id, specification", + [ + ("$id", referencing.jsonschema.DRAFT202012), + ("$id", referencing.jsonschema.DRAFT201909), + ("$id", referencing.jsonschema.DRAFT7), + ("$id", referencing.jsonschema.DRAFT6), + ("id", referencing.jsonschema.DRAFT4), + ("id", referencing.jsonschema.DRAFT3), + ], +) +def test_id_of_mapping(id, specification): + uri = "http://example.com/some-schema" + assert specification.id_of({id: uri}) == uri + + +@pytest.mark.parametrize( + "specification", + [ + referencing.jsonschema.DRAFT202012, + referencing.jsonschema.DRAFT201909, + referencing.jsonschema.DRAFT7, + referencing.jsonschema.DRAFT6, + ], +) +@pytest.mark.parametrize("value", [True, False]) +def test_id_of_bool(specification, value): + assert specification.id_of(value) is None + + +@pytest.mark.parametrize( + "specification", + [ + referencing.jsonschema.DRAFT202012, + referencing.jsonschema.DRAFT201909, + referencing.jsonschema.DRAFT7, + referencing.jsonschema.DRAFT6, + ], +) +@pytest.mark.parametrize("value", [True, False]) +def test_anchors_in_bool(specification, value): + assert list(specification.anchors_in(value)) == [] + + +@pytest.mark.parametrize( + "specification", + [ + referencing.jsonschema.DRAFT202012, + referencing.jsonschema.DRAFT201909, + referencing.jsonschema.DRAFT7, + referencing.jsonschema.DRAFT6, + ], +) +@pytest.mark.parametrize("value", [True, False]) +def test_subresources_of_bool(specification, value): + assert list(specification.subresources_of(value)) == [] + + +@pytest.mark.parametrize( + "uri, expected", + [ + ( + "https://json-schema.org/draft/2020-12/schema", + referencing.jsonschema.DRAFT202012, + ), + ( + "https://json-schema.org/draft/2019-09/schema", + referencing.jsonschema.DRAFT201909, + ), + ( + "http://json-schema.org/draft-07/schema#", + referencing.jsonschema.DRAFT7, + ), + ( + "http://json-schema.org/draft-06/schema#", + referencing.jsonschema.DRAFT6, + ), + ( + "http://json-schema.org/draft-04/schema#", + referencing.jsonschema.DRAFT4, + ), + ( + "http://json-schema.org/draft-03/schema#", + referencing.jsonschema.DRAFT3, + ), + ], +) +def test_specification_with(uri, expected): + assert referencing.jsonschema.specification_with(uri) == expected + + +@pytest.mark.parametrize( + "uri, expected", + [ + ( + "http://json-schema.org/draft-07/schema", + referencing.jsonschema.DRAFT7, + ), + ( + "http://json-schema.org/draft-06/schema", + referencing.jsonschema.DRAFT6, + ), + ( + "http://json-schema.org/draft-04/schema", + referencing.jsonschema.DRAFT4, + ), + ( + "http://json-schema.org/draft-03/schema", + referencing.jsonschema.DRAFT3, + ), + ], +) +def test_specification_with_no_empty_fragment(uri, expected): + assert referencing.jsonschema.specification_with(uri) == expected + + +def test_specification_with_unknown_dialect(): + dialect_id = "http://example.com/unknown-json-schema-dialect-id" + with pytest.raises(referencing.jsonschema.UnknownDialect) as excinfo: + referencing.jsonschema.specification_with(dialect_id) + assert excinfo.value.uri == dialect_id + + +def test_specification_with_default(): + dialect_id = "http://example.com/unknown-json-schema-dialect-id" + specification = referencing.jsonschema.specification_with( + dialect_id, + default=Specification.OPAQUE, + ) + assert specification is Specification.OPAQUE + + +# FIXME: The tests below should move to the referencing suite but I haven't yet +# figured out how to represent dynamic (& recursive) ref lookups in it. +def test_lookup_trivial_dynamic_ref(): + one = referencing.jsonschema.DRAFT202012.create_resource( + {"$dynamicAnchor": "foo"}, + ) + resolver = Registry().with_resource("http://example.com", one).resolver() + resolved = resolver.lookup("http://example.com#foo") + assert resolved.contents == one.contents + + +def test_multiple_lookup_trivial_dynamic_ref(): + TRUE = referencing.jsonschema.DRAFT202012.create_resource(True) + root = referencing.jsonschema.DRAFT202012.create_resource( + { + "$id": "http://example.com", + "$dynamicAnchor": "fooAnchor", + "$defs": { + "foo": { + "$id": "foo", + "$dynamicAnchor": "fooAnchor", + "$defs": { + "bar": True, + "baz": { + "$dynamicAnchor": "fooAnchor", + }, + }, + }, + }, + }, + ) + resolver = ( + Registry() + .with_resources( + [ + ("http://example.com", root), + ("http://example.com/foo/", TRUE), + ("http://example.com/foo/bar", root), + ], + ) + .resolver() + ) + + first = resolver.lookup("http://example.com") + second = first.resolver.lookup("foo/") + resolver = second.resolver.lookup("bar").resolver + fourth = resolver.lookup("#fooAnchor") + assert fourth.contents == root.contents + + +def test_multiple_lookup_dynamic_ref_to_nondynamic_ref(): + one = referencing.jsonschema.DRAFT202012.create_resource( + {"$anchor": "fooAnchor"}, + ) + two = referencing.jsonschema.DRAFT202012.create_resource( + { + "$id": "http://example.com", + "$dynamicAnchor": "fooAnchor", + "$defs": { + "foo": { + "$id": "foo", + "$dynamicAnchor": "fooAnchor", + "$defs": { + "bar": True, + "baz": { + "$dynamicAnchor": "fooAnchor", + }, + }, + }, + }, + }, + ) + resolver = ( + Registry() + .with_resources( + [ + ("http://example.com", two), + ("http://example.com/foo/", one), + ("http://example.com/foo/bar", two), + ], + ) + .resolver() + ) + + first = resolver.lookup("http://example.com") + second = first.resolver.lookup("foo/") + resolver = second.resolver.lookup("bar").resolver + fourth = resolver.lookup("#fooAnchor") + assert fourth.contents == two.contents + + +def test_lookup_trivial_recursive_ref(): + one = referencing.jsonschema.DRAFT201909.create_resource( + {"$recursiveAnchor": True}, + ) + resolver = Registry().with_resource("http://example.com", one).resolver() + first = resolver.lookup("http://example.com") + resolved = referencing.jsonschema.lookup_recursive_ref( + resolver=first.resolver, + ) + assert resolved.contents == one.contents + + +def test_lookup_recursive_ref_to_bool(): + TRUE = referencing.jsonschema.DRAFT201909.create_resource(True) + registry = Registry({"http://example.com": TRUE}) + resolved = referencing.jsonschema.lookup_recursive_ref( + resolver=registry.resolver(base_uri="http://example.com"), + ) + assert resolved.contents == TRUE.contents + + +def test_multiple_lookup_recursive_ref_to_bool(): + TRUE = referencing.jsonschema.DRAFT201909.create_resource(True) + root = referencing.jsonschema.DRAFT201909.create_resource( + { + "$id": "http://example.com", + "$recursiveAnchor": True, + "$defs": { + "foo": { + "$id": "foo", + "$recursiveAnchor": True, + "$defs": { + "bar": True, + "baz": { + "$recursiveAnchor": True, + "$anchor": "fooAnchor", + }, + }, + }, + }, + }, + ) + resolver = ( + Registry() + .with_resources( + [ + ("http://example.com", root), + ("http://example.com/foo/", TRUE), + ("http://example.com/foo/bar", root), + ], + ) + .resolver() + ) + + first = resolver.lookup("http://example.com") + second = first.resolver.lookup("foo/") + resolver = second.resolver.lookup("bar").resolver + fourth = referencing.jsonschema.lookup_recursive_ref(resolver=resolver) + assert fourth.contents == root.contents + + +def test_multiple_lookup_recursive_ref_with_nonrecursive_ref(): + one = referencing.jsonschema.DRAFT201909.create_resource( + {"$recursiveAnchor": True}, + ) + two = referencing.jsonschema.DRAFT201909.create_resource( + { + "$id": "http://example.com", + "$recursiveAnchor": True, + "$defs": { + "foo": { + "$id": "foo", + "$recursiveAnchor": True, + "$defs": { + "bar": True, + "baz": { + "$recursiveAnchor": True, + "$anchor": "fooAnchor", + }, + }, + }, + }, + }, + ) + three = referencing.jsonschema.DRAFT201909.create_resource( + {"$recursiveAnchor": False}, + ) + resolver = ( + Registry() + .with_resources( + [ + ("http://example.com", three), + ("http://example.com/foo/", two), + ("http://example.com/foo/bar", one), + ], + ) + .resolver() + ) + + first = resolver.lookup("http://example.com") + second = first.resolver.lookup("foo/") + resolver = second.resolver.lookup("bar").resolver + fourth = referencing.jsonschema.lookup_recursive_ref(resolver=resolver) + assert fourth.contents == two.contents + + +def test_empty_registry(): + assert referencing.jsonschema.EMPTY_REGISTRY == Registry() diff --git a/.venv/lib/python3.10/site-packages/referencing/tests/test_referencing_suite.py b/.venv/lib/python3.10/site-packages/referencing/tests/test_referencing_suite.py new file mode 100644 index 0000000..4b8ae91 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing/tests/test_referencing_suite.py @@ -0,0 +1,66 @@ +from pathlib import Path +import json +import os + +import pytest + +from referencing import Registry +from referencing.exceptions import Unresolvable +import referencing.jsonschema + + +class SuiteNotFound(Exception): + def __str__(self): # pragma: no cover + return ( + "Cannot find the referencing suite. " + "Set the REFERENCING_SUITE environment variable to the path to " + "the suite, or run the test suite from alongside a full checkout " + "of the git repository." + ) + + +if "REFERENCING_SUITE" in os.environ: # pragma: no cover + SUITE = Path(os.environ["REFERENCING_SUITE"]) / "tests" +else: + SUITE = Path(__file__).parent.parent.parent / "suite/tests" +if not SUITE.is_dir(): # pragma: no cover + raise SuiteNotFound() +DIALECT_IDS = json.loads(SUITE.joinpath("specifications.json").read_text()) + + +@pytest.mark.parametrize( + "test_path", + [ + pytest.param(each, id=f"{each.parent.name}-{each.stem}") + for each in SUITE.glob("*/**/*.json") + ], +) +def test_referencing_suite(test_path, subtests): + dialect_id = DIALECT_IDS[test_path.relative_to(SUITE).parts[0]] + specification = referencing.jsonschema.specification_with(dialect_id) + loaded = json.loads(test_path.read_text()) + registry = loaded["registry"] + registry = Registry().with_resources( + (uri, specification.create_resource(contents)) + for uri, contents in loaded["registry"].items() + ) + for test in loaded["tests"]: + with subtests.test(test=test): + if "normalization" in test_path.stem: + pytest.xfail("APIs need to change for proper URL support.") + + resolver = registry.resolver(base_uri=test.get("base_uri", "")) + + if test.get("error"): + with pytest.raises(Unresolvable): + resolver.lookup(test["ref"]) + else: + resolved = resolver.lookup(test["ref"]) + assert resolved.contents == test["target"] + + then = test.get("then") + while then: # pragma: no cover + with subtests.test(test=test, then=then): + resolved = resolved.resolver.lookup(then["ref"]) + assert resolved.contents == then["target"] + then = then.get("then") diff --git a/.venv/lib/python3.10/site-packages/referencing/tests/test_retrieval.py b/.venv/lib/python3.10/site-packages/referencing/tests/test_retrieval.py new file mode 100644 index 0000000..d0a8f8a --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing/tests/test_retrieval.py @@ -0,0 +1,106 @@ +from functools import lru_cache +import json + +import pytest + +from referencing import Registry, Resource, exceptions +from referencing.jsonschema import DRAFT202012 +from referencing.retrieval import to_cached_resource + + +class TestToCachedResource: + def test_it_caches_retrieved_resources(self): + contents = {"$schema": "https://json-schema.org/draft/2020-12/schema"} + stack = [json.dumps(contents)] + + @to_cached_resource() + def retrieve(uri): + return stack.pop() + + registry = Registry(retrieve=retrieve) + + expected = Resource.from_contents(contents) + + got = registry.get_or_retrieve("urn:example:schema") + assert got.value == expected + + # And a second time we get the same value. + again = registry.get_or_retrieve("urn:example:schema") + assert again.value is got.value + + def test_custom_loader(self): + contents = {"$schema": "https://json-schema.org/draft/2020-12/schema"} + stack = [json.dumps(contents)[::-1]] + + @to_cached_resource(loads=lambda s: json.loads(s[::-1])) + def retrieve(uri): + return stack.pop() + + registry = Registry(retrieve=retrieve) + + expected = Resource.from_contents(contents) + + got = registry.get_or_retrieve("urn:example:schema") + assert got.value == expected + + # And a second time we get the same value. + again = registry.get_or_retrieve("urn:example:schema") + assert again.value is got.value + + def test_custom_from_contents(self): + contents = {} + stack = [json.dumps(contents)] + + @to_cached_resource(from_contents=DRAFT202012.create_resource) + def retrieve(uri): + return stack.pop() + + registry = Registry(retrieve=retrieve) + + expected = DRAFT202012.create_resource(contents) + + got = registry.get_or_retrieve("urn:example:schema") + assert got.value == expected + + # And a second time we get the same value. + again = registry.get_or_retrieve("urn:example:schema") + assert again.value is got.value + + def test_custom_cache(self): + schema = {"$schema": "https://json-schema.org/draft/2020-12/schema"} + mapping = { + "urn:example:1": dict(schema, foo=1), + "urn:example:2": dict(schema, foo=2), + "urn:example:3": dict(schema, foo=3), + } + + resources = { + uri: Resource.from_contents(contents) + for uri, contents in mapping.items() + } + + @to_cached_resource(cache=lru_cache(maxsize=2)) + def retrieve(uri): + return json.dumps(mapping.pop(uri)) + + registry = Registry(retrieve=retrieve) + + got = registry.get_or_retrieve("urn:example:1") + assert got.value == resources["urn:example:1"] + assert registry.get_or_retrieve("urn:example:1").value is got.value + assert registry.get_or_retrieve("urn:example:1").value is got.value + + got = registry.get_or_retrieve("urn:example:2") + assert got.value == resources["urn:example:2"] + assert registry.get_or_retrieve("urn:example:2").value is got.value + assert registry.get_or_retrieve("urn:example:2").value is got.value + + # This still succeeds, but evicts the first URI + got = registry.get_or_retrieve("urn:example:3") + assert got.value == resources["urn:example:3"] + assert registry.get_or_retrieve("urn:example:3").value is got.value + assert registry.get_or_retrieve("urn:example:3").value is got.value + + # And now this fails (as we popped the value out of `mapping`) + with pytest.raises(exceptions.Unretrievable): + registry.get_or_retrieve("urn:example:1") diff --git a/.venv/lib/python3.10/site-packages/referencing/typing.py b/.venv/lib/python3.10/site-packages/referencing/typing.py new file mode 100644 index 0000000..a614464 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/referencing/typing.py @@ -0,0 +1,61 @@ +""" +Type-annotation related support for the referencing library. +""" + +from __future__ import annotations + +from collections.abc import Mapping as Mapping +from typing import TYPE_CHECKING, Any, Protocol + +try: + from typing_extensions import TypeVar +except ImportError: # pragma: no cover + from typing import TypeVar + +if TYPE_CHECKING: + from referencing._core import Resolved, Resolver, Resource + +#: A URI which identifies a `Resource`. +URI = str + +#: The type of documents within a registry. +D = TypeVar("D", default=Any) + + +class Retrieve(Protocol[D]): + """ + A retrieval callable, usable within a `Registry` for resource retrieval. + + Does not make assumptions about where the resource might be coming from. + """ + + def __call__(self, uri: URI) -> Resource[D]: + """ + Retrieve the resource with the given URI. + + Raise `referencing.exceptions.NoSuchResource` if you wish to indicate + the retriever cannot lookup the given URI. + """ + ... + + +class Anchor(Protocol[D]): + """ + An anchor within a `Resource`. + + Beyond "simple" anchors, some specifications like JSON Schema's 2020 + version have dynamic anchors. + """ + + @property + def name(self) -> str: + """ + Return the name of this anchor. + """ + ... + + def resolve(self, resolver: Resolver[D]) -> Resolved[D]: + """ + Return the resource for this anchor. + """ + ... diff --git a/.venv/lib/python3.10/site-packages/rpds/__init__.py b/.venv/lib/python3.10/site-packages/rpds/__init__.py new file mode 100644 index 0000000..257da6a --- /dev/null +++ b/.venv/lib/python3.10/site-packages/rpds/__init__.py @@ -0,0 +1,5 @@ +from .rpds import * + +__doc__ = rpds.__doc__ +if hasattr(rpds, "__all__"): + __all__ = rpds.__all__ \ No newline at end of file diff --git a/.venv/lib/python3.10/site-packages/rpds/__init__.pyi b/.venv/lib/python3.10/site-packages/rpds/__init__.pyi new file mode 100644 index 0000000..5af0e32 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/rpds/__init__.pyi @@ -0,0 +1,77 @@ +from typing import ( + ItemsView, + Iterable, + Iterator, + KeysView, + Mapping, + TypeVar, + ValuesView, +) + +_T = TypeVar("_T") +_KT_co = TypeVar("_KT_co", covariant=True) +_VT_co = TypeVar("_VT_co", covariant=True) +_KU_co = TypeVar("_KU_co", covariant=True) +_VU_co = TypeVar("_VU_co", covariant=True) + +class HashTrieMap(Mapping[_KT_co, _VT_co]): + def __init__( + self, + value: Mapping[_KT_co, _VT_co] | Iterable[tuple[_KT_co, _VT_co]] = {}, + **kwds: Mapping[_KT_co, _VT_co], + ): ... + def __getitem__(self, key: _KT_co) -> _VT_co: ... + def __iter__(self) -> Iterator[_KT_co]: ... + def __len__(self) -> int: ... + def discard(self, key: _KT_co) -> HashTrieMap[_KT_co, _VT_co]: ... + def items(self) -> ItemsView[_KT_co, _VT_co]: ... + def keys(self) -> KeysView[_KT_co]: ... + def values(self) -> ValuesView[_VT_co]: ... + def remove(self, key: _KT_co) -> HashTrieMap[_KT_co, _VT_co]: ... + def insert( + self, + key: _KT_co, + val: _VT_co, + ) -> HashTrieMap[_KT_co, _VT_co]: ... + def update( + self, + *args: Mapping[_KU_co, _VU_co] | Iterable[tuple[_KU_co, _VU_co]], + ) -> HashTrieMap[_KT_co | _KU_co, _VT_co | _VU_co]: ... + @classmethod + def convert( + cls, + value: Mapping[_KT_co, _VT_co] | Iterable[tuple[_KT_co, _VT_co]], + ) -> HashTrieMap[_KT_co, _VT_co]: ... + @classmethod + def fromkeys( + cls, + keys: Iterable[_KT_co], + value: _VT_co = None, + ) -> HashTrieMap[_KT_co, _VT_co]: ... + +class HashTrieSet(frozenset[_T]): + def __init__(self, value: Iterable[_T] = ()): ... + def __iter__(self) -> Iterator[_T]: ... + def __len__(self) -> int: ... + def discard(self, value: _T) -> HashTrieSet[_T]: ... + def remove(self, value: _T) -> HashTrieSet[_T]: ... + def insert(self, value: _T) -> HashTrieSet[_T]: ... + def update(self, *args: Iterable[_T]) -> HashTrieSet[_T]: ... + +class List(Iterable[_T]): + def __init__(self, value: Iterable[_T] = (), *more: _T): ... + def __iter__(self) -> Iterator[_T]: ... + def __len__(self) -> int: ... + def push_front(self, value: _T) -> List[_T]: ... + def drop_first(self) -> List[_T]: ... + +class Queue(Iterable[_T]): + def __init__(self, value: Iterable[_T] = (), *more: _T): ... + def __iter__(self) -> Iterator[_T]: ... + def __len__(self) -> int: ... + def enqueue(self, value: _T) -> Queue[_T]: ... + def dequeue(self, value: _T) -> Queue[_T]: ... + @property + def is_empty(self) -> _T: ... + @property + def peek(self) -> _T: ... diff --git a/.venv/lib/python3.10/site-packages/rpds/py.typed b/.venv/lib/python3.10/site-packages/rpds/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/.venv/lib/python3.10/site-packages/rpds/rpds.cpython-310-x86_64-linux-gnu.so b/.venv/lib/python3.10/site-packages/rpds/rpds.cpython-310-x86_64-linux-gnu.so new file mode 100755 index 0000000000000000000000000000000000000000..7569799880fd739012f833cde92592e181e70ee1 GIT binary patch literal 1047104 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≠c*oPkbbnWrM&S0v?W0E}{lIk(FzNWuEz8kEpaFy(D zv-y*K^K1Le8r#SBV1BY&xq`iJ`_gUSuHD|(`J$-W@Vb<5HqZrPS~o#5L47T+s!Y1O z#B*+R^YdmobjtB;y(BsUiH@#)ER0{F4jL|jmWcU1%UYLW(*1kEVgI=Dy5l3KmLt
      k|f?qu0rvPRv{-9k14mYj~ZJua`<YU&khSEt!{AJ~6EFFjdp!F6^AAtXu@247rsXkJ@9XhZyVWO0 zd^-v zzCk$frg+o5wol>9;<_*&8uF2{8^>ojIGP-mWqW{(r~*FThUH#0P}ch(wc`U`{AqNY}@b*WE(J)D90Y3rM%dlT-`KJO7szTKU*){+P$ZW5bWM1cw&23 z#kO_^LsrxDNy?|#=Xri}!R3!XP3+=_C(dNNYi`%3AUJ;2%UdzN>U_;3eId;rX9B(; z6*doQ@EByV?|A^U5_gspV_%%OI7M?iyC;d!`}!4UVV~rNg}nRV>{(flY0nUIFLG4d z#@=WBE9*;guicBXFR{0pPqZ$^{{ELboFiMn)GW-6@8bsJRkH zOfbK8M$FzZU1u-0uW!n06Lh%0Ki&S~9 z)Vl-1*z;k{Gr?uQ*>R9-iJE3&CUsO2hgm6ey!f$ZROxi-7x*6Zp+0S257K2~6N?dZ+ZYs0#aAHa7T0A}L6-I+Y&Bjn`Y@jF>8 zIsx*Fi!0(F4F}yB$PyS?FE!%!X%VJK7s7nOq|3=!Pmc-wfcKL0_Q{jg_Vyg58@^s& znXhl%cNd%MX7%RcW>pHs!9PB&pXg6Qa`0qT-(K)e^A!`Tf5C8Xv2CLt*8J_NIVnAI1Xs$RDz89P&f7?(TE1s+x`2P_~ZPo)96Prxgd=@VVyg`tE9TE-~Gc$N1lWz(M{F|NTvSuuJ=m z`}(t;5Bb|WKd<=t|NZN~-njSwnf=Cnb?^UM_I-b_^ZtyV|84$r@Bf|s#(n*Zf7iT0 zKKF0%pL_ownqNQpW4_9<-TVLP-!p%3U;p{PX?}M9$}xuj`#C@S_2B%!`G@AO?(09Y zZ*b@DKF59i1uy?sgZF=s8_NIO*Zws_(k{>SG1?&}BrYyXb%-FWikzu$TP+m-C5Cr{khfB8;- z?EcyP{Qrf&$mjnp`-i{yAIcvxo22zx)0F$shFk-3$IFbKOt= z+{ZIbLyzj~1GhhF(+t}tH?tSi%f0H-M@7($S;XktP z`}fV)4{l-FH|)Ou@9=*4e9s-we*HuH{(rjjdwH$=Z}@fRBlPcoZr}fB_LX85|0A}B w`+R5rWVgC=*EiaKvVUM4$Myd)KDzr{_u9Wd^Zx(g|B+S2e&2b+&W}(2f8{}|tN;K2 literal 0 HcmV?d00001 diff --git a/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/INSTALLER b/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/METADATA b/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/METADATA new file mode 100644 index 0000000..e5e37d8 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/METADATA @@ -0,0 +1,99 @@ +Metadata-Version: 2.4 +Name: rpds-py +Version: 0.24.0 +Classifier: Development Status :: 3 - Alpha +Classifier: Intended Audience :: Developers +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Rust +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +License-File: LICENSE +Summary: Python bindings to Rust's persistent data structures (rpds) +Keywords: data structures,rust,persistent +Author-email: Julian Berman +License: MIT +Requires-Python: >=3.9 +Description-Content-Type: text/x-rst; charset=UTF-8 +Project-URL: Documentation, https://rpds.readthedocs.io/ +Project-URL: Homepage, https://github.com/crate-py/rpds +Project-URL: Issues, https://github.com/crate-py/rpds/issues/ +Project-URL: Funding, https://github.com/sponsors/Julian +Project-URL: Tidelift, https://tidelift.com/subscription/pkg/pypi-rpds-py?utm_source=pypi-rpds-py&utm_medium=referral&utm_campaign=pypi-link +Project-URL: Source, https://github.com/crate-py/rpds +Project-URL: Upstream, https://github.com/orium/rpds + +=========== +``rpds.py`` +=========== + +|PyPI| |Pythons| |CI| + +.. |PyPI| image:: https://img.shields.io/pypi/v/rpds-py.svg + :alt: PyPI version + :target: https://pypi.org/project/rpds-py/ + +.. |Pythons| image:: https://img.shields.io/pypi/pyversions/rpds-py.svg + :alt: Supported Python versions + :target: https://pypi.org/project/rpds-py/ + +.. |CI| image:: https://github.com/crate-py/rpds/workflows/CI/badge.svg + :alt: Build status + :target: https://github.com/crate-py/rpds/actions?query=workflow%3ACI + +.. |ReadTheDocs| image:: https://readthedocs.org/projects/referencing/badge/?version=stable&style=flat + :alt: ReadTheDocs status + :target: https://referencing.readthedocs.io/en/stable/ + + +Python bindings to the `Rust rpds crate `_ for persistent data structures. + +What's here is quite minimal (in transparency, it was written initially to support replacing ``pyrsistent`` in the `referencing library `_). +If you see something missing (which is very likely), a PR is definitely welcome to add it. + +Installation +------------ + +The distribution on PyPI is named ``rpds.py`` (equivalently ``rpds-py``), and thus can be installed via e.g.: + +.. code:: sh + + $ pip install rpds-py + +Note that if you install ``rpds-py`` from source, you will need a Rust toolchain installed, as it is a build-time dependency. +An example of how to do so in a ``Dockerfile`` can be found `here `_. + +If you believe you are on a common platform which should have wheels built (i.e. and not need to compile from source), feel free to file an issue or pull request modifying the GitHub action used here to build wheels via ``maturin``. + +Usage +----- + +Methods in general are named similarly to their ``rpds`` counterparts (rather than ``pyrsistent``\ 's conventions, though probably a full drop-in ``pyrsistent``\ -compatible wrapper module is a good addition at some point). + +.. code:: python + + >>> from rpds import HashTrieMap, HashTrieSet, List + + >>> m = HashTrieMap({"foo": "bar", "baz": "quux"}) + >>> m.insert("spam", 37) == HashTrieMap({"foo": "bar", "baz": "quux", "spam": 37}) + True + >>> m.remove("foo") == HashTrieMap({"baz": "quux"}) + True + + >>> s = HashTrieSet({"foo", "bar", "baz", "quux"}) + >>> s.insert("spam") == HashTrieSet({"foo", "bar", "baz", "quux", "spam"}) + True + >>> s.remove("foo") == HashTrieSet({"bar", "baz", "quux"}) + True + + >>> L = List([1, 3, 5]) + >>> L.push_front(-1) == List([-1, 1, 3, 5]) + True + >>> L.rest == List([3, 5]) + True + diff --git a/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/RECORD b/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/RECORD new file mode 100644 index 0000000..d3b796b --- /dev/null +++ b/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/RECORD @@ -0,0 +1,10 @@ +rpds/__init__.py,sha256=w3MgXW7lpTCICw0KXbw20QX573_kbsEnWIeMsCAugvM,99 +rpds/__init__.pyi,sha256=-hd1A1d1BqGxL3XZGI9SpW1-xZe2iJcDMU6CpiejgV4,2570 +rpds/__pycache__/__init__.cpython-310.pyc,, +rpds/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +rpds/rpds.cpython-310-x86_64-linux-gnu.so,sha256=XIPWS-BQZ8bACZaFsCzbrUzj7pYyibHsU_vUSrzGCMo,1047104 +rpds_py-0.24.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +rpds_py-0.24.0.dist-info/METADATA,sha256=JNbgNTYB-2pVCxTzVZSgjNCcXemjwKKvhR7CcVvWh0c,4132 +rpds_py-0.24.0.dist-info/RECORD,, +rpds_py-0.24.0.dist-info/WHEEL,sha256=vZCrFUqux3RT3x-5MYcfGpyb4lW1eii-LV1Nx1Zs4nE,129 +rpds_py-0.24.0.dist-info/licenses/LICENSE,sha256=MU5Okb47qpPA-0vMyeTpfNZD64ObBlr5IXgsIXX-mQk,1057 diff --git a/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/WHEEL b/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/WHEEL new file mode 100644 index 0000000..1ccdf65 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: maturin (1.8.3) +Root-Is-Purelib: false +Tag: cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64 diff --git a/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/licenses/LICENSE b/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/licenses/LICENSE new file mode 100644 index 0000000..119a1f2 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/rpds_py-0.24.0.dist-info/licenses/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2023 Julian Berman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/INSTALLER b/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/LICENSE b/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/LICENSE new file mode 100644 index 0000000..41c87e7 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/LICENSE @@ -0,0 +1,3 @@ +This software is made available under the terms of *either* of the licenses +found in LICENSE.APACHE or LICENSE.BSD. Contributions to uritemplate are +made under the terms of *both* these licenses. diff --git a/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/METADATA b/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/METADATA new file mode 100644 index 0000000..97001a2 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/METADATA @@ -0,0 +1,92 @@ +Metadata-Version: 2.1 +Name: uritemplate +Version: 4.1.1 +Summary: Implementation of RFC 6570 URI Templates +Home-page: https://uritemplate.readthedocs.org +Author: Ian Stapleton Cordasco +Author-email: graffatcolmingov@gmail.com +License: BSD 3-Clause License or Apache License, Version 2.0 +Keywords: rfc 6570 uri template +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved +Classifier: License :: OSI Approved :: Apache Software License +Classifier: License :: OSI Approved :: BSD License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: Implementation :: CPython +Requires-Python: >=3.6 +Description-Content-Type: text/x-rst +License-File: LICENSE + +uritemplate +=========== + +Documentation_ -- GitHub_ -- Travis-CI_ + +Simple python library to deal with `URI Templates`_. The API looks like + +.. code-block:: python + + from uritemplate import URITemplate, expand + + # NOTE: URI params must be strings not integers + + gist_uri = 'https://api.github.com/users/sigmavirus24/gists{/gist_id}' + t = URITemplate(gist_uri) + print(t.expand(gist_id='123456')) + # => https://api.github.com/users/sigmavirus24/gists/123456 + + # or + print(expand(gist_uri, gist_id='123456')) + + # also + t.expand({'gist_id': '123456'}) + print(expand(gist_uri, {'gist_id': '123456'})) + +Where it might be useful to have a class + +.. code-block:: python + + import requests + + class GitHubUser(object): + url = URITemplate('https://api.github.com/user{/login}') + def __init__(self, name): + self.api_url = url.expand(login=name) + response = requests.get(self.api_url) + if response.status_code == 200: + self.__dict__.update(response.json()) + +When the module containing this class is loaded, ``GitHubUser.url`` is +evaluated and so the template is created once. It's often hard to notice in +Python, but object creation can consume a great deal of time and so can the +``re`` module which uritemplate relies on. Constructing the object once should +reduce the amount of time your code takes to run. + +Installing +---------- + +:: + + pip install uritemplate + +License +------- + +Modified BSD license_ + + +.. _Documentation: https://uritemplate.readthedocs.io/ +.. _GitHub: https://github.com/python-hyper/uritemplate +.. _Travis-CI: https://travis-ci.org/python-hyper/uritemplate +.. _URI Templates: https://tools.ietf.org/html/rfc6570 +.. _license: https://github.com/python-hyper/uritemplate/blob/master/LICENSE + + diff --git a/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/RECORD b/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/RECORD new file mode 100644 index 0000000..8e2393e --- /dev/null +++ b/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/RECORD @@ -0,0 +1,17 @@ +uritemplate-4.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +uritemplate-4.1.1.dist-info/LICENSE,sha256=PPyfAc3uySkA8ijPVnf_pX5-0wTEJjUyvK2cvZlp5Gw,196 +uritemplate-4.1.1.dist-info/METADATA,sha256=rotEEWL5rUie3gKyYHhxXqjdpYw16kLCT0Aw0bvta9o,2882 +uritemplate-4.1.1.dist-info/RECORD,, +uritemplate-4.1.1.dist-info/WHEEL,sha256=WzZ8cwjh8l0jtULNjYq1Hpr-WCqCRgPr--TX4P5I1Wo,110 +uritemplate-4.1.1.dist-info/top_level.txt,sha256=WJzkFEINWbgwuzuUEP8kD8Sk2fFHYQzBgrjO3viyubE,12 +uritemplate/__init__.py,sha256=toWdtJeaNWsftVzhDASD_2wwxkd84HdXg22rFwMkVkc,816 +uritemplate/__pycache__/__init__.cpython-310.pyc,, +uritemplate/__pycache__/api.cpython-310.pyc,, +uritemplate/__pycache__/orderedset.cpython-310.pyc,, +uritemplate/__pycache__/template.cpython-310.pyc,, +uritemplate/__pycache__/variable.cpython-310.pyc,, +uritemplate/api.py,sha256=eQ3DdgNNDlnoedSE-rQ5AQv8JvMzdljPX8l-187myfI,2305 +uritemplate/orderedset.py,sha256=4Z8u8uw339D_RWvbUslv5d6EnA2wxQC66317oTLzp0o,3367 +uritemplate/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +uritemplate/template.py,sha256=qXcNZxcGPGxgQnaRDIafaKsrTnvBzplOBBPAM8Hbq7g,4774 +uritemplate/variable.py,sha256=HixfLuF7R3f7zwIQohB9cFVRVZsN_8Y2RIZDRHpNg40,12870 diff --git a/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/WHEEL b/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/WHEEL new file mode 100644 index 0000000..b733a60 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/top_level.txt b/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/top_level.txt new file mode 100644 index 0000000..2d76f01 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/uritemplate-4.1.1.dist-info/top_level.txt @@ -0,0 +1 @@ +uritemplate diff --git a/.venv/lib/python3.10/site-packages/uritemplate/__init__.py b/.venv/lib/python3.10/site-packages/uritemplate/__init__.py new file mode 100644 index 0000000..65015c1 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/uritemplate/__init__.py @@ -0,0 +1,35 @@ +""" + +uritemplate +=========== + +URI templates implemented as close to :rfc:`6570` as possible + +See http://uritemplate.rtfd.org/ for documentation + +:copyright: + (c) 2013 Ian Stapleton Cordasco +:license: + Modified BSD Apache License (Version 2.0), see LICENSE for more details + and either LICENSE.BSD or LICENSE.APACHE for the details of those specific + licenses + +""" + +__title__ = "uritemplate" +__author__ = "Ian Stapleton Cordasco" +__license__ = "Modified BSD or Apache License, Version 2.0" +__copyright__ = "Copyright 2013 Ian Stapleton Cordasco" +__version__ = "4.1.1" +__version_info__ = tuple( + int(i) for i in __version__.split(".") if i.isdigit() +) + +from uritemplate.api import ( + URITemplate, + expand, + partial, + variables, +) + +__all__ = ("URITemplate", "expand", "partial", "variables") diff --git a/.venv/lib/python3.10/site-packages/uritemplate/api.py b/.venv/lib/python3.10/site-packages/uritemplate/api.py new file mode 100644 index 0000000..ac75473 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/uritemplate/api.py @@ -0,0 +1,85 @@ +""" + +uritemplate.api +=============== + +This module contains the very simple API provided by uritemplate. + +""" +import typing as t + +from uritemplate import variable +from uritemplate.orderedset import OrderedSet +from uritemplate.template import URITemplate + +__all__ = ("OrderedSet", "URITemplate", "expand", "partial", "variables") + + +def expand( + uri: str, + var_dict: t.Optional[variable.VariableValueDict] = None, + **kwargs: variable.VariableValue, +) -> str: + """Expand the template with the given parameters. + + :param str uri: The templated URI to expand + :param dict var_dict: Optional dictionary with variables and values + :param kwargs: Alternative way to pass arguments + :returns: str + + Example:: + + expand('https://api.github.com{/end}', {'end': 'users'}) + expand('https://api.github.com{/end}', end='gists') + + .. note:: Passing values by both parts, may override values in + ``var_dict``. For example:: + + expand('https://{var}', {'var': 'val1'}, var='val2') + + ``val2`` will be used instead of ``val1``. + + """ + return URITemplate(uri).expand(var_dict, **kwargs) + + +def partial( + uri: str, + var_dict: t.Optional[variable.VariableValueDict] = None, + **kwargs: variable.VariableValue, +) -> URITemplate: + """Partially expand the template with the given parameters. + + If all of the parameters for the template are not given, return a + partially expanded template. + + :param dict var_dict: Optional dictionary with variables and values + :param kwargs: Alternative way to pass arguments + :returns: :class:`URITemplate` + + Example:: + + t = URITemplate('https://api.github.com{/end}') + t.partial() # => URITemplate('https://api.github.com{/end}') + + """ + return URITemplate(uri).partial(var_dict, **kwargs) + + +def variables(uri: str) -> OrderedSet: + """Parse the variables of the template. + + This returns all of the variable names in the URI Template. + + :returns: Set of variable names + :rtype: set + + Example:: + + variables('https://api.github.com{/end}) + # => {'end'} + variables('https://api.github.com/repos{/username}{/repository}') + # => {'username', 'repository'} + + """ + return OrderedSet(URITemplate(uri).variable_names) diff --git a/.venv/lib/python3.10/site-packages/uritemplate/orderedset.py b/.venv/lib/python3.10/site-packages/uritemplate/orderedset.py new file mode 100644 index 0000000..dd7cd1a --- /dev/null +++ b/.venv/lib/python3.10/site-packages/uritemplate/orderedset.py @@ -0,0 +1,92 @@ +# From: https://github.com/ActiveState/code/blob/master/recipes/Python/576696_OrderedSet_with_Weakrefs/ # noqa +import typing as t +import weakref + + +class Link: + """Representation of one item in a doubly-linked list.""" + + __slots__ = ("prev", "next", "key", "__weakref__") + prev: "Link" + next: "Link" + key: str + + +class OrderedSet(t.MutableSet[str]): + """A set that remembers the order in which items were added.""" + + # Big-O running times for all methods are the same as for regular sets. + # The internal self.__map dictionary maps keys to links in a doubly linked + # list. The circular doubly linked list starts and ends with a sentinel + # element. The sentinel element never gets deleted (this simplifies the + # algorithm). The prev/next links are weakref proxies (to prevent circular + # references). Individual links are kept alive by the hard reference in + # self.__map. Those hard references disappear when a key is deleted from + # an OrderedSet. + + def __init__(self, iterable: t.Optional[t.Iterable[str]] = None): + self.__root = root = Link() # sentinel node for doubly linked list + root.prev = root.next = root + self.__map: t.MutableMapping[str, Link] = {} # key --> link + if iterable is not None: + self |= iterable # type: ignore + + def __len__(self) -> int: + return len(self.__map) + + def __contains__(self, key: object) -> bool: + return key in self.__map + + def add(self, key: str) -> None: + # Store new key in a new link at the end of the linked list + if key not in self.__map: + self.__map[key] = link = Link() + root = self.__root + last = root.prev + link.prev, link.next, link.key = last, root, key + last.next = root.prev = weakref.proxy(link) + + def discard(self, key: str) -> None: + # Remove an existing item using self.__map to find the link which is + # then removed by updating the links in the predecessor and successors. + if key in self.__map: + link = self.__map.pop(key) + link.prev.next = link.next + link.next.prev = link.prev + + def __iter__(self) -> t.Generator[str, None, None]: + # Traverse the linked list in order. + root = self.__root + curr = root.next + while curr is not root: + yield curr.key + curr = curr.next + + def __reversed__(self) -> t.Generator[str, None, None]: + # Traverse the linked list in reverse order. + root = self.__root + curr = root.prev + while curr is not root: + yield curr.key + curr = curr.prev + + def pop(self, last: bool = True) -> str: + if not self: + raise KeyError("set is empty") + key = next(reversed(self)) if last else next(iter(self)) + self.discard(key) + return key + + def __repr__(self) -> str: + if not self: + return f"{self.__class__.__name__}()" + return f"{self.__class__.__name__}({list(self)!r})" + + def __str__(self) -> str: + return self.__repr__() + + def __eq__(self, other: object) -> bool: + if isinstance(other, OrderedSet): + return len(self) == len(other) and list(self) == list(other) + other = t.cast(t.Iterable[str], other) + return not self.isdisjoint(other) diff --git a/.venv/lib/python3.10/site-packages/uritemplate/py.typed b/.venv/lib/python3.10/site-packages/uritemplate/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/.venv/lib/python3.10/site-packages/uritemplate/template.py b/.venv/lib/python3.10/site-packages/uritemplate/template.py new file mode 100644 index 0000000..73ef89c --- /dev/null +++ b/.venv/lib/python3.10/site-packages/uritemplate/template.py @@ -0,0 +1,169 @@ +""" + +uritemplate.template +==================== + +This module contains the essential inner workings of uritemplate. + +What treasures await you: + +- URITemplate class + +You see a treasure chest of knowledge in front of you. +What do you do? +> + +""" +import re +import typing as t + +from uritemplate import orderedset +from uritemplate import variable + +template_re = re.compile("{([^}]+)}") + + +def _merge( + var_dict: t.Optional[variable.VariableValueDict], + overrides: variable.VariableValueDict, +) -> variable.VariableValueDict: + if var_dict: + opts = var_dict.copy() + opts.update(overrides) + return opts + return overrides + + +class URITemplate: + + """This parses the template and will be used to expand it. + + This is the most important object as the center of the API. + + Example:: + + from uritemplate import URITemplate + import requests + + + t = URITemplate( + 'https://api.github.com/users/sigmavirus24/gists{/gist_id}' + ) + uri = t.expand(gist_id=123456) + resp = requests.get(uri) + for gist in resp.json(): + print(gist['html_url']) + + Please note:: + + str(t) + # 'https://api.github.com/users/sigmavirus24/gists{/gistid}' + repr(t) # is equivalent to + # URITemplate(str(t)) + # Where str(t) is interpreted as the URI string. + + Also, ``URITemplates`` are hashable so they can be used as keys in + dictionaries. + + """ + + def __init__(self, uri: str): + #: The original URI to be parsed. + self.uri: str = uri + #: A list of the variables in the URI. They are stored as + #: :class:`~uritemplate.variable.URIVariable`\ s + self.variables: t.List[variable.URIVariable] = [ + variable.URIVariable(m.groups()[0]) + for m in template_re.finditer(self.uri) + ] + #: A set of variable names in the URI. + self.variable_names = orderedset.OrderedSet() + for var in self.variables: + for name in var.variable_names: + self.variable_names.add(name) + + def __repr__(self) -> str: + return 'URITemplate("%s")' % self + + def __str__(self) -> str: + return self.uri + + def __eq__(self, other: object) -> bool: + if not isinstance(other, URITemplate): + return NotImplemented + return self.uri == other.uri + + def __hash__(self) -> int: + return hash(self.uri) + + def _expand( + self, var_dict: variable.VariableValueDict, replace: bool + ) -> str: + if not self.variables: + return self.uri + + expansion = var_dict + expanded: t.Dict[str, str] = {} + for v in self.variables: + expanded.update(v.expand(expansion)) + + def replace_all(match: "re.Match[str]") -> str: + return expanded.get(match.groups()[0], "") + + def replace_partial(match: "re.Match[str]") -> str: + match_group = match.groups()[0] + var = "{%s}" % match_group + return expanded.get(match_group) or var + + replace_func = replace_partial if replace else replace_all + + return template_re.sub(replace_func, self.uri) + + def expand( + self, + var_dict: t.Optional[variable.VariableValueDict] = None, + **kwargs: variable.VariableValue, + ) -> str: + """Expand the template with the given parameters. + + :param dict var_dict: Optional dictionary with variables and values + :param kwargs: Alternative way to pass arguments + :returns: str + + Example:: + + t = URITemplate('https://api.github.com{/end}') + t.expand({'end': 'users'}) + t.expand(end='gists') + + .. note:: Passing values by both parts, may override values in + ``var_dict``. For example:: + + expand('https://{var}', {'var': 'val1'}, var='val2') + + ``val2`` will be used instead of ``val1``. + + """ + return self._expand(_merge(var_dict, kwargs), False) + + def partial( + self, + var_dict: t.Optional[variable.VariableValueDict] = None, + **kwargs: variable.VariableValue, + ) -> "URITemplate": + """Partially expand the template with the given parameters. + + If all of the parameters for the template are not given, return a + partially expanded template. + + :param dict var_dict: Optional dictionary with variables and values + :param kwargs: Alternative way to pass arguments + :returns: :class:`URITemplate` + + Example:: + + t = URITemplate('https://api.github.com{/end}') + t.partial() # => URITemplate('https://api.github.com{/end}') + + """ + return URITemplate(self._expand(_merge(var_dict, kwargs), True)) diff --git a/.venv/lib/python3.10/site-packages/uritemplate/variable.py b/.venv/lib/python3.10/site-packages/uritemplate/variable.py new file mode 100644 index 0000000..da406ca --- /dev/null +++ b/.venv/lib/python3.10/site-packages/uritemplate/variable.py @@ -0,0 +1,419 @@ +""" + +uritemplate.variable +==================== + +This module contains the URIVariable class which powers the URITemplate class. + +What treasures await you: + +- URIVariable class + +You see a hammer in front of you. +What do you do? +> + +""" +import collections.abc +import typing as t +import urllib.parse + +ScalarVariableValue = t.Union[int, float, complex, str] +VariableValue = t.Union[ + t.Sequence[ScalarVariableValue], + t.Mapping[str, ScalarVariableValue], + t.Tuple[str, ScalarVariableValue], + ScalarVariableValue, +] +VariableValueDict = t.Dict[str, VariableValue] + + +class URIVariable: + + """This object validates everything inside the URITemplate object. + + It validates template expansions and will truncate length as decided by + the template. + + Please note that just like the :class:`URITemplate `, this + object's ``__str__`` and ``__repr__`` methods do not return the same + information. Calling ``str(var)`` will return the original variable. + + This object does the majority of the heavy lifting. The ``URITemplate`` + object finds the variables in the URI and then creates ``URIVariable`` + objects. Expansions of the URI are handled by each ``URIVariable`` + object. ``URIVariable.expand()`` returns a dictionary of the original + variable and the expanded value. Check that method's documentation for + more information. + + """ + + operators = ("+", "#", ".", "/", ";", "?", "&", "|", "!", "@") + reserved = ":/?#[]@!$&'()*+,;=" + + def __init__(self, var: str): + #: The original string that comes through with the variable + self.original: str = var + #: The operator for the variable + self.operator: str = "" + #: List of safe characters when quoting the string + self.safe: str = "" + #: List of variables in this variable + self.variables: t.List[ + t.Tuple[str, t.MutableMapping[str, t.Any]] + ] = [] + #: List of variable names + self.variable_names: t.List[str] = [] + #: List of defaults passed in + self.defaults: t.MutableMapping[str, ScalarVariableValue] = {} + # Parse the variable itself. + self.parse() + self.post_parse() + + def __repr__(self) -> str: + return "URIVariable(%s)" % self + + def __str__(self) -> str: + return self.original + + def parse(self) -> None: + """Parse the variable. + + This finds the: + - operator, + - set of safe characters, + - variables, and + - defaults. + + """ + var_list_str = self.original + if self.original[0] in URIVariable.operators: + self.operator = self.original[0] + var_list_str = self.original[1:] + + if self.operator in URIVariable.operators[:2]: + self.safe = URIVariable.reserved + + var_list = var_list_str.split(",") + + for var in var_list: + default_val = None + name = var + if "=" in var: + name, default_val = tuple(var.split("=", 1)) + + explode = False + if name.endswith("*"): + explode = True + name = name[:-1] + + prefix: t.Optional[int] = None + if ":" in name: + name, prefix_str = tuple(name.split(":", 1)) + prefix = int(prefix_str) + + if default_val: + self.defaults[name] = default_val + + self.variables.append( + (name, {"explode": explode, "prefix": prefix}) + ) + + self.variable_names = [varname for (varname, _) in self.variables] + + def post_parse(self) -> None: + """Set ``start``, ``join_str`` and ``safe`` attributes. + + After parsing the variable, we need to set up these attributes and it + only makes sense to do it in a more easily testable way. + """ + self.safe = "" + self.start = self.join_str = self.operator + if self.operator == "+": + self.start = "" + if self.operator in ("+", "#", ""): + self.join_str = "," + if self.operator == "#": + self.start = "#" + if self.operator == "?": + self.start = "?" + self.join_str = "&" + + if self.operator in ("+", "#"): + self.safe = URIVariable.reserved + + def _query_expansion( + self, + name: str, + value: VariableValue, + explode: bool, + prefix: t.Optional[int], + ) -> t.Optional[str]: + """Expansion method for the '?' and '&' operators.""" + if value is None: + return None + + tuples, items = is_list_of_tuples(value) + + safe = self.safe + if list_test(value) and not tuples: + if not value: + return None + value = t.cast(t.Sequence[ScalarVariableValue], value) + if explode: + return self.join_str.join( + f"{name}={quote(v, safe)}" for v in value + ) + else: + value = ",".join(quote(v, safe) for v in value) + return f"{name}={value}" + + if dict_test(value) or tuples: + if not value: + return None + value = t.cast(t.Mapping[str, ScalarVariableValue], value) + items = items or sorted(value.items()) + if explode: + return self.join_str.join( + f"{quote(k, safe)}={quote(v, safe)}" for k, v in items + ) + else: + value = ",".join( + f"{quote(k, safe)},{quote(v, safe)}" for k, v in items + ) + return f"{name}={value}" + + if value: + value = t.cast(t.Text, value) + value = value[:prefix] if prefix else value + return f"{name}={quote(value, safe)}" + return name + "=" + + def _label_path_expansion( + self, + name: str, + value: VariableValue, + explode: bool, + prefix: t.Optional[int], + ) -> t.Optional[str]: + """Label and path expansion method. + + Expands for operators: '/', '.' + + """ + join_str = self.join_str + safe = self.safe + + if value is None or ( + not isinstance(value, (str, int, float, complex)) + and len(value) == 0 + ): + return None + + tuples, items = is_list_of_tuples(value) + + if list_test(value) and not tuples: + if not explode: + join_str = "," + + value = t.cast(t.Sequence[ScalarVariableValue], value) + fragments = [quote(v, safe) for v in value if v is not None] + return join_str.join(fragments) if fragments else None + + if dict_test(value) or tuples: + value = t.cast(t.Mapping[str, ScalarVariableValue], value) + items = items or sorted(value.items()) + format_str = "%s=%s" + if not explode: + format_str = "%s,%s" + join_str = "," + + expanded = join_str.join( + format_str % (quote(k, safe), quote(v, safe)) + for k, v in items + if v is not None + ) + return expanded if expanded else None + + value = t.cast(t.Text, value) + value = value[:prefix] if prefix else value + return quote(value, safe) + + def _semi_path_expansion( + self, + name: str, + value: VariableValue, + explode: bool, + prefix: t.Optional[int], + ) -> t.Optional[str]: + """Expansion method for ';' operator.""" + join_str = self.join_str + safe = self.safe + + if value is None: + return None + + if self.operator == "?": + join_str = "&" + + tuples, items = is_list_of_tuples(value) + + if list_test(value) and not tuples: + value = t.cast(t.Sequence[ScalarVariableValue], value) + if explode: + expanded = join_str.join( + f"{name}={quote(v, safe)}" for v in value if v is not None + ) + return expanded if expanded else None + else: + value = ",".join(quote(v, safe) for v in value) + return f"{name}={value}" + + if dict_test(value) or tuples: + value = t.cast(t.Mapping[str, ScalarVariableValue], value) + items = items or sorted(value.items()) + + if explode: + return join_str.join( + f"{quote(k, safe)}={quote(v, safe)}" + for k, v in items + if v is not None + ) + else: + expanded = ",".join( + f"{quote(k, safe)},{quote(v, safe)}" + for k, v in items + if v is not None + ) + return f"{name}={expanded}" + + value = t.cast(t.Text, value) + value = value[:prefix] if prefix else value + if value: + return f"{name}={quote(value, safe)}" + + return name + + def _string_expansion( + self, + name: str, + value: VariableValue, + explode: bool, + prefix: t.Optional[int], + ) -> t.Optional[str]: + if value is None: + return None + + tuples, items = is_list_of_tuples(value) + + if list_test(value) and not tuples: + value = t.cast(t.Sequence[ScalarVariableValue], value) + return ",".join(quote(v, self.safe) for v in value) + + if dict_test(value) or tuples: + value = t.cast(t.Mapping[str, ScalarVariableValue], value) + items = items or sorted(value.items()) + format_str = "%s=%s" if explode else "%s,%s" + + return ",".join( + format_str % (quote(k, self.safe), quote(v, self.safe)) + for k, v in items + ) + + value = t.cast(t.Text, value) + value = value[:prefix] if prefix else value + return quote(value, self.safe) + + def expand( + self, var_dict: t.Optional[VariableValueDict] = None + ) -> t.Mapping[str, str]: + """Expand the variable in question. + + Using ``var_dict`` and the previously parsed defaults, expand this + variable and subvariables. + + :param dict var_dict: dictionary of key-value pairs to be used during + expansion + :returns: dict(variable=value) + + Examples:: + + # (1) + v = URIVariable('/var') + expansion = v.expand({'var': 'value'}) + print(expansion) + # => {'/var': '/value'} + + # (2) + v = URIVariable('?var,hello,x,y') + expansion = v.expand({'var': 'value', 'hello': 'Hello World!', + 'x': '1024', 'y': '768'}) + print(expansion) + # => {'?var,hello,x,y': + # '?var=value&hello=Hello%20World%21&x=1024&y=768'} + + """ + return_values = [] + if var_dict is None: + return {self.original: self.original} + + for name, opts in self.variables: + value = var_dict.get(name, None) + if not value and value != "" and name in self.defaults: + value = self.defaults[name] + + if value is None: + continue + + expanded = None + if self.operator in ("/", "."): + expansion = self._label_path_expansion + elif self.operator in ("?", "&"): + expansion = self._query_expansion + elif self.operator == ";": + expansion = self._semi_path_expansion + else: + expansion = self._string_expansion + + expanded = expansion(name, value, opts["explode"], opts["prefix"]) + + if expanded is not None: + return_values.append(expanded) + + value = "" + if return_values: + value = self.start + self.join_str.join(return_values) + return {self.original: value} + + +def is_list_of_tuples( + value: t.Any, +) -> t.Tuple[bool, t.Optional[t.Sequence[t.Tuple[str, ScalarVariableValue]]]]: + if ( + not value + or not isinstance(value, (list, tuple)) + or not all(isinstance(t, tuple) and len(t) == 2 for t in value) + ): + return False, None + + return True, value + + +def list_test(value: t.Any) -> bool: + return isinstance(value, (list, tuple)) + + +def dict_test(value: t.Any) -> bool: + return isinstance(value, (dict, collections.abc.MutableMapping)) + + +def _encode(value: t.AnyStr, encoding: str = "utf-8") -> bytes: + if isinstance(value, str): + return value.encode(encoding) + return value + + +def quote(value: t.Any, safe: str) -> str: + if not isinstance(value, (str, bytes)): + value = str(value) + return urllib.parse.quote(_encode(value), safe) diff --git a/.venv/lib/python3.10/site-packages/yaml/__init__.py b/.venv/lib/python3.10/site-packages/yaml/__init__.py new file mode 100644 index 0000000..2ec4f20 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/__init__.py @@ -0,0 +1,390 @@ + +from .error import * + +from .tokens import * +from .events import * +from .nodes import * + +from .loader import * +from .dumper import * + +__version__ = '6.0.2' +try: + from .cyaml import * + __with_libyaml__ = True +except ImportError: + __with_libyaml__ = False + +import io + +#------------------------------------------------------------------------------ +# XXX "Warnings control" is now deprecated. Leaving in the API function to not +# break code that uses it. +#------------------------------------------------------------------------------ +def warnings(settings=None): + if settings is None: + return {} + +#------------------------------------------------------------------------------ +def scan(stream, Loader=Loader): + """ + Scan a YAML stream and produce scanning tokens. + """ + loader = Loader(stream) + try: + while loader.check_token(): + yield loader.get_token() + finally: + loader.dispose() + +def parse(stream, Loader=Loader): + """ + Parse a YAML stream and produce parsing events. + """ + loader = Loader(stream) + try: + while loader.check_event(): + yield loader.get_event() + finally: + loader.dispose() + +def compose(stream, Loader=Loader): + """ + Parse the first YAML document in a stream + and produce the corresponding representation tree. + """ + loader = Loader(stream) + try: + return loader.get_single_node() + finally: + loader.dispose() + +def compose_all(stream, Loader=Loader): + """ + Parse all YAML documents in a stream + and produce corresponding representation trees. + """ + loader = Loader(stream) + try: + while loader.check_node(): + yield loader.get_node() + finally: + loader.dispose() + +def load(stream, Loader): + """ + Parse the first YAML document in a stream + and produce the corresponding Python object. + """ + loader = Loader(stream) + try: + return loader.get_single_data() + finally: + loader.dispose() + +def load_all(stream, Loader): + """ + Parse all YAML documents in a stream + and produce corresponding Python objects. + """ + loader = Loader(stream) + try: + while loader.check_data(): + yield loader.get_data() + finally: + loader.dispose() + +def full_load(stream): + """ + Parse the first YAML document in a stream + and produce the corresponding Python object. + + Resolve all tags except those known to be + unsafe on untrusted input. + """ + return load(stream, FullLoader) + +def full_load_all(stream): + """ + Parse all YAML documents in a stream + and produce corresponding Python objects. + + Resolve all tags except those known to be + unsafe on untrusted input. + """ + return load_all(stream, FullLoader) + +def safe_load(stream): + """ + Parse the first YAML document in a stream + and produce the corresponding Python object. + + Resolve only basic YAML tags. This is known + to be safe for untrusted input. + """ + return load(stream, SafeLoader) + +def safe_load_all(stream): + """ + Parse all YAML documents in a stream + and produce corresponding Python objects. + + Resolve only basic YAML tags. This is known + to be safe for untrusted input. + """ + return load_all(stream, SafeLoader) + +def unsafe_load(stream): + """ + Parse the first YAML document in a stream + and produce the corresponding Python object. + + Resolve all tags, even those known to be + unsafe on untrusted input. + """ + return load(stream, UnsafeLoader) + +def unsafe_load_all(stream): + """ + Parse all YAML documents in a stream + and produce corresponding Python objects. + + Resolve all tags, even those known to be + unsafe on untrusted input. + """ + return load_all(stream, UnsafeLoader) + +def emit(events, stream=None, Dumper=Dumper, + canonical=None, indent=None, width=None, + allow_unicode=None, line_break=None): + """ + Emit YAML parsing events into a stream. + If stream is None, return the produced string instead. + """ + getvalue = None + if stream is None: + stream = io.StringIO() + getvalue = stream.getvalue + dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, + allow_unicode=allow_unicode, line_break=line_break) + try: + for event in events: + dumper.emit(event) + finally: + dumper.dispose() + if getvalue: + return getvalue() + +def serialize_all(nodes, stream=None, Dumper=Dumper, + canonical=None, indent=None, width=None, + allow_unicode=None, line_break=None, + encoding=None, explicit_start=None, explicit_end=None, + version=None, tags=None): + """ + Serialize a sequence of representation trees into a YAML stream. + If stream is None, return the produced string instead. + """ + getvalue = None + if stream is None: + if encoding is None: + stream = io.StringIO() + else: + stream = io.BytesIO() + getvalue = stream.getvalue + dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, + allow_unicode=allow_unicode, line_break=line_break, + encoding=encoding, version=version, tags=tags, + explicit_start=explicit_start, explicit_end=explicit_end) + try: + dumper.open() + for node in nodes: + dumper.serialize(node) + dumper.close() + finally: + dumper.dispose() + if getvalue: + return getvalue() + +def serialize(node, stream=None, Dumper=Dumper, **kwds): + """ + Serialize a representation tree into a YAML stream. + If stream is None, return the produced string instead. + """ + return serialize_all([node], stream, Dumper=Dumper, **kwds) + +def dump_all(documents, stream=None, Dumper=Dumper, + default_style=None, default_flow_style=False, + canonical=None, indent=None, width=None, + allow_unicode=None, line_break=None, + encoding=None, explicit_start=None, explicit_end=None, + version=None, tags=None, sort_keys=True): + """ + Serialize a sequence of Python objects into a YAML stream. + If stream is None, return the produced string instead. + """ + getvalue = None + if stream is None: + if encoding is None: + stream = io.StringIO() + else: + stream = io.BytesIO() + getvalue = stream.getvalue + dumper = Dumper(stream, default_style=default_style, + default_flow_style=default_flow_style, + canonical=canonical, indent=indent, width=width, + allow_unicode=allow_unicode, line_break=line_break, + encoding=encoding, version=version, tags=tags, + explicit_start=explicit_start, explicit_end=explicit_end, sort_keys=sort_keys) + try: + dumper.open() + for data in documents: + dumper.represent(data) + dumper.close() + finally: + dumper.dispose() + if getvalue: + return getvalue() + +def dump(data, stream=None, Dumper=Dumper, **kwds): + """ + Serialize a Python object into a YAML stream. + If stream is None, return the produced string instead. + """ + return dump_all([data], stream, Dumper=Dumper, **kwds) + +def safe_dump_all(documents, stream=None, **kwds): + """ + Serialize a sequence of Python objects into a YAML stream. + Produce only basic YAML tags. + If stream is None, return the produced string instead. + """ + return dump_all(documents, stream, Dumper=SafeDumper, **kwds) + +def safe_dump(data, stream=None, **kwds): + """ + Serialize a Python object into a YAML stream. + Produce only basic YAML tags. + If stream is None, return the produced string instead. + """ + return dump_all([data], stream, Dumper=SafeDumper, **kwds) + +def add_implicit_resolver(tag, regexp, first=None, + Loader=None, Dumper=Dumper): + """ + Add an implicit scalar detector. + If an implicit scalar value matches the given regexp, + the corresponding tag is assigned to the scalar. + first is a sequence of possible initial characters or None. + """ + if Loader is None: + loader.Loader.add_implicit_resolver(tag, regexp, first) + loader.FullLoader.add_implicit_resolver(tag, regexp, first) + loader.UnsafeLoader.add_implicit_resolver(tag, regexp, first) + else: + Loader.add_implicit_resolver(tag, regexp, first) + Dumper.add_implicit_resolver(tag, regexp, first) + +def add_path_resolver(tag, path, kind=None, Loader=None, Dumper=Dumper): + """ + Add a path based resolver for the given tag. + A path is a list of keys that forms a path + to a node in the representation tree. + Keys can be string values, integers, or None. + """ + if Loader is None: + loader.Loader.add_path_resolver(tag, path, kind) + loader.FullLoader.add_path_resolver(tag, path, kind) + loader.UnsafeLoader.add_path_resolver(tag, path, kind) + else: + Loader.add_path_resolver(tag, path, kind) + Dumper.add_path_resolver(tag, path, kind) + +def add_constructor(tag, constructor, Loader=None): + """ + Add a constructor for the given tag. + Constructor is a function that accepts a Loader instance + and a node object and produces the corresponding Python object. + """ + if Loader is None: + loader.Loader.add_constructor(tag, constructor) + loader.FullLoader.add_constructor(tag, constructor) + loader.UnsafeLoader.add_constructor(tag, constructor) + else: + Loader.add_constructor(tag, constructor) + +def add_multi_constructor(tag_prefix, multi_constructor, Loader=None): + """ + Add a multi-constructor for the given tag prefix. + Multi-constructor is called for a node if its tag starts with tag_prefix. + Multi-constructor accepts a Loader instance, a tag suffix, + and a node object and produces the corresponding Python object. + """ + if Loader is None: + loader.Loader.add_multi_constructor(tag_prefix, multi_constructor) + loader.FullLoader.add_multi_constructor(tag_prefix, multi_constructor) + loader.UnsafeLoader.add_multi_constructor(tag_prefix, multi_constructor) + else: + Loader.add_multi_constructor(tag_prefix, multi_constructor) + +def add_representer(data_type, representer, Dumper=Dumper): + """ + Add a representer for the given type. + Representer is a function accepting a Dumper instance + and an instance of the given data type + and producing the corresponding representation node. + """ + Dumper.add_representer(data_type, representer) + +def add_multi_representer(data_type, multi_representer, Dumper=Dumper): + """ + Add a representer for the given type. + Multi-representer is a function accepting a Dumper instance + and an instance of the given data type or subtype + and producing the corresponding representation node. + """ + Dumper.add_multi_representer(data_type, multi_representer) + +class YAMLObjectMetaclass(type): + """ + The metaclass for YAMLObject. + """ + def __init__(cls, name, bases, kwds): + super(YAMLObjectMetaclass, cls).__init__(name, bases, kwds) + if 'yaml_tag' in kwds and kwds['yaml_tag'] is not None: + if isinstance(cls.yaml_loader, list): + for loader in cls.yaml_loader: + loader.add_constructor(cls.yaml_tag, cls.from_yaml) + else: + cls.yaml_loader.add_constructor(cls.yaml_tag, cls.from_yaml) + + cls.yaml_dumper.add_representer(cls, cls.to_yaml) + +class YAMLObject(metaclass=YAMLObjectMetaclass): + """ + An object that can dump itself to a YAML stream + and load itself from a YAML stream. + """ + + __slots__ = () # no direct instantiation, so allow immutable subclasses + + yaml_loader = [Loader, FullLoader, UnsafeLoader] + yaml_dumper = Dumper + + yaml_tag = None + yaml_flow_style = None + + @classmethod + def from_yaml(cls, loader, node): + """ + Convert a representation node to a Python object. + """ + return loader.construct_yaml_object(node, cls) + + @classmethod + def to_yaml(cls, dumper, data): + """ + Convert a Python object to a representation node. + """ + return dumper.represent_yaml_object(cls.yaml_tag, data, cls, + flow_style=cls.yaml_flow_style) + diff --git a/.venv/lib/python3.10/site-packages/yaml/_yaml.cpython-310-x86_64-linux-gnu.so b/.venv/lib/python3.10/site-packages/yaml/_yaml.cpython-310-x86_64-linux-gnu.so new file mode 100755 index 0000000000000000000000000000000000000000..c6514b684bb84eae4fb6893ef4b0cfc79d7d112a GIT binary patch literal 2383664 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

      r@c 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�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�jWEv~kT+hKrGb7A#Si6Oa}%&HUB)E(Q57 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

      NfHWdT~(g6K2-I-oPA=tIOUexw?% zu)O|wU4>;V6qfN=HE42=Q&_$N6M{c=>qdTEO2TXTRgc25Of%gZmgyc%z;q9gM)3-Z zVY*rh%UnG;IqJ3Al)!|!Q791-o;PdyD)p|VZ%rNgVwqe+`o<|Ne&h8hEUPUVSBKbO zHx-r_K#*N1Ecen$Kcuj{L}J%bSmxSZeu>w1-I!xDx3NwFg~gxLVTEP7qh@g8{rw8d ztvDF~t1I<3juC~`*H~#6Qdnw0lX?`Eu{f+q$dw;FQkN@dlD38`eTC)6M?wnAvvT;V zZRXeW>?dwX(V^R*u)Hd#xCo`mB93}%8*a>-MPyeB%k-ToEZ13bYy}>Fzryl`9Hg0@ zs8Lw1LQB5FvN>G9C@j~KB*FG%n=VpYVY!T@G-(qmEH{2;>RU%yF%n9Yl~*72m6f}RT3A{68*vFVm6!YaippIj@p{UOeYt*% zN&Rkm1H|!^ucoXP=K&n^un6u*e_25_<&oJqfj6m!sVQWzdexLUW*D~hjaO1;2(2*^ z6V!8ecV2YkI{oCNTdizfr2f1;aMpm47DuW2i6$`QJ<=hfh1MyD!)m+Tb_mkFMw5`}7U?et&Nc!4(V{<|1^XFN|%n7nQG|a2-HTH+k z61<#&m-r{b>L>j^Sa{LwC3r6_W-W9xhPqksbrttY_7|0+>d)sTeqolHd@nj?J*}S> zQYK(`uBdGgFqdG(M1U>p?`Rjt3^llg@>Tw@Bmbt2SN8t!FG|mxbXC2jE44~T$nr=Dj7E5w|AwGn?QLKydCawR>H*=9N9|3xt1BvzU%IgF}YBE|4xMA0?dJi zYtD7t3q3W8a z7LUWd%0uKRP9n-e;7fR1dmy#9k^XJf=e)rP=W0~=5m7w~v2iOvlw-B^O$WY22jhk^ zuR|W@kDl9BeQK)U&fz?~MATRH*_%!&qFWrQa}WvFN^wffYRHgcmu{0qxQYr!KoU1d^#kMF;G;lfCmjpz1k6=2 z{k<_rY+@&>+W;XS6U#8qGlMwfR>vu&2*yTYximwT6iJRLF!v12EMK-1xIPm z7YL`o7tR3wg9Q?cJV#wxP+lov(s8bOMx{M5djhS74(;y)H==VqJoC%q3rQNoCI5RE zl3&1$PYdyLROJ~7I)arNrAC6946YGXZwwkn(xKWjKr97U^~uFy-v~_)lmQdhw6PZ1 zOV5CFFEUS2Gf@xA2wW@;0VN=F0s=yKPecuTGGumv&_!( zP{$GGst;m0K-RV~>q7@DAOHfukHir}H@~4xnfY?awn2Ja5@Dd!hP#}a1YWgU0au)A z52nWqd4<9eQ65BjF;2CJwk6)9(3yY-ELGq#?L2xH=(Rh(qsOo^rqrPNy+&CABn!Ka z7Qkascn~h5+Yv}E(8!?*=RRGw%-4Y+c56DX`-

      *9I|hB*cx;<5JV^`aNg7>8N76;UBPr$6^@}D&OaFc$bIIn&Uy?H07Ve&h`hUd?110XRnEC2` zp84;toVj`t^om-7=CSu9|CKbDlzVe42&2e<;#dFwPSRY?k*p(Xetcj1(}!fuyk8kT zmWxv@Su^u$YY}aztbrF)^>Y>Qdw_~9o;dyf3+G8d5e$is9O20Hj ztJ3#Cr9m7|e*dVpJ8m`Iao^yVlHh)co!M<0VL-yR=}ml9iTX%^s!CK1dkxfk%huCs zJ_^rBR2V@TsV0p+0|-D}&?!xd2j zZFg6g?rv=9L>HnraJ6k|NYfD z&vT!9`}RWKk)xl#Tx;Y46I=m=ATL+gFV<5uZy zFWH%2z^^}$DLLutak}2*1noZD3ZZJM%F+_e*e0w4b?l?C{1<+5(>tRiy8cQJ#R;39 zw(26JgB$%+s~#+tGb=PO+{`ZNl7l*Frb#7$lyjeG2 z@B(+sD8~JFp7@2yFKOB2`~K2T{u7QJoqbL+CQm<`{N%^^$#=u5t;wHllb<-sCckwn zlfSgl$$u0ke|z(jpQ_1o@{1-vzGai26(;|(O@2p!JpHWmlfTDL9uw7FnmmuypqQn8 z@(VS2GEX-GdF%k%5U&2DW+DHkCJ(u8`Lo{moTF18Pc8pj25h3PIv#7uVjg>@KtN_u zJFd`z0T29wzb@}k3b$nM%fxHx@kokv9aD(Y<1L|}k#uT_r?cswV)lrxo*I_`lRwStz8tO#8wS`#oTJfhwH@#a?lZ@Xh9l-ZN5@V85~`G4Pb z|Fp*Z_WG=Er44U?wPeRn-@>!A|DU(~Kf6_Lq4VI^)+zPR3M2G=^hh7#&F8H@hIp3$ zY%kbvv}k7*VQR;5IN1l^dN|G$LPaT_>0cCKPxMG1EsO#sZJydk5@FBud31VGVzzfA z`&Abl%`6X7W6@^qMB;NbNgi?km6f$B&f+w|1X6CSS?&`wOCRSpC**8GF2x~dmHP_K z1c){fa+Zf=>Q?XjkLC5WepQ50b3DMpJtY}>R(U5kph9zW*?SzJbSx%oxf^JoE+K+T z-wK9PAlew$aY(O3;HwZKF@)9e7p{q*OT;PHMBFR;?e4pvnPg8L+>k3dfiS0GkdI$W zluRnbU**1zDIVoU;vUQI?Y(E~xKWj)6X2i{uKkQw{mClalibO9B;3Nu>w49`R?;v^ z+=F*krmHnewAj6T%=men=xPeM891Lv++@9}AOiZ6+>ScMUPRQ_6b!%IK9}ld*yEc@{H36U%ca6b_|B_uE8E-P};o z-{NEi72=a>6aAUW)m_2`?fd<8OU`$c+5r?ut>tYCqXOR#`d3!jEfqUu4Q{bEmqYzy zAmIt%zm~YZ11jxBJnr9zDy|%QeQC?llc@KHyaCk>tFV3xZbp;p(7c zSnW8XHNmOzxzXLYIoTgc=DlfP03?(WWm6pXet`1EJcYw4jNEee`tpoh4j1$N zD7O(iO-Oa@lj?MFs^euT{eGFv!Jo&A+(!d>IhB_8M<;jN`@8^Y8zLb-W#pfS$^_BQ zL`78pZ9PS9OOCH{AbW=|x5fIG-nPyyd8!Vis-e47TZw9&+?^hTVkE(DZ?EW4lne$> zt+Ps-?hwoj&e;Ax%#@#~a_(#+u<4wzpF#Lq;sy-#KIE+7ea$gLoI`Tw#!wqof$%RvoZc1>Kcd77h>Hh!&P67a?O8 zEhe!D^DOZbJ<1)tqq3$#8=d*T_!=|~L379U2iFIZH_kJrwM=X&_XPWidd@xV_Z=R3 z(U)hmsoFDbF1hjDO#KTXM#JsR$~(!cneA>=q5GZ-3wxF;Ydf&-!<_s-n!+7FWfsQZ zQtqi}geU!&r8Xuk&$oO6ND!Zpb;;2YP}ol1wju0f?XpZZ={yMpd@|{3xrz-K4+XXD zRQS{129V#MgdW4SbuYi)%3to!)J`e-gTj_kz>IJ49MZs~DT@Feue3Z=+5`XQ#;`=Y zx*M^PjfHTnD^tqM;Tlvv{a2Th%=*I(7^<&!{l`~w&3C;1WE3(6Kt>wmg&Hci04`U$ zS<94nDhh9wO2^DhyYc!3;4&GE|H?vi#4gxN{!2G~QQ9EL;Y8bI1O@+$h~wATxIJyK zI0&!hVWWQzTnhg02-05-`_D}iY8sRokNA~w?K$Y}aX~;2)hJY2 zNMCd{TC9EYO?~^X`2Y9`u-k2Dw*xmcTadXJTO)HI5!3X2xZ#AO@FPT@CZq~|O)0&{ z)m<}w@&{DTZ{RX#X>kG3O{Se%lrxN8jPaf~qPD2z}vg`s&8o-?}2ZAcZ zBsxOsp9liIGIh!KU~5FoAo;fpD5c9}Z4058I0E=MU^Ue7ahnE8~+S|@diI-xM& zdwR^!F1VMgoVzV9d;W#xBy_GB20E`D2JP%gK=&nEG?~6^A)lyHa@9T}Q%0x6*LjHm z?p3~zo2srssQzN6`r+oP6BV+GWY|utE-iG+6|wpxH*GqnD4l~y-s5CeXjg$AeY{&gH6OY4{Hu~%AfUeqxoH=HrDwk=aw`Jxg>L#of!L09%T{_~ zoBB{gVk?IjDJLuo#P(x=auTPR&V+^)Ng6fHxJ)}S13(D*DFAp1brmI6`%QrKq<2`* zZjAIqOPvXPOY3mjIMjmbFK4QM)KqmT$bZipQ_kGtBsTY@Kgkfv!~f(7rT!<;f%YM) z@=iKzgSV`1W}OhqC@Lrhy(q5&MrO?HbM6o1c;y&Tt3VCqkvroMV)A?b85r$cUK4os z*^*$GXO*PRGrsBOyw=;eY~w$&JsN#5%-=H6L@>;>`{-4!0xX=|JZ&W1#4+hd%ukiP z;y>n3%c>a2a^hF~kqlIR!ymaeT`Ihr=Q1DfvOAd)xARhi-d8Zve97Kc1x)U_lnxVA zLX$pJ=*+N37hXqEI1P@nfn`49t|5%cyuvYWw)Ntz1J8sJ7hM`{?5F53v$3Df8BwdF zf;Kk4at9?-vF2tfB`6A@rpGaLy1ksrwQW@8BtE z^rbSqoak16NqPiB8qHOQAR=-sC{C&3DqwVKFWsIHbM)693snc*tJ}<$X=ZuM0NOcJK4{P=b+0s1jqUEAWgxfq zGNj$V1L_SoVJ0N7q+&!Q-Act7I`+WRk2=py*Bxw&B(?4WB`tSN{ zSQrgi3`*trQ=KZgHPzvwY;U1WER&WmUv8)K=m*`M;ttyGKg!+z;|jgV`KjB@3OJOl zZXJ75*I$ZFpef!3jP?Z>t!P2r_e0&+TTu4{X478JMzY@m1&m=UsV1NfZDilY){ogo8+{%_1?DHgz)bX<>X{e73_}EC?&>6%ZPnR#0CY)-=$>zku z#im^b-u96RYIc7xJHmnwpDGO4=I@`-9D^-sE83}*t%bN6rF`h%qe3&jb}n@5LE4uY zzHNv|wWh@_H{`T@yTvUx(vmyu*Qaq0^<`K4YHwLKl@gY>DJRI*j}@2l#|eX3t1u;h zg4W>o92xvQRrg?lRt{9yVK)d^`JMieWkAYBG6|KsPvkb&C=6tP`IQF(O`eI)03SEm zC{@%83t@0ze>Q4!IBuiIR(a0u4{&y8$JK@Z>mZ-{j;r_Vim;`Dnb!v{4NE`^u|4X4 zP#w(Ip}H6YmM)Ew$70Ve3nz()Bqk&@oYxA&OLQhhkEZLWAO%3ZNH!kDdzK$-^S5;`eWeFCBiGww6FO^^~|z{F&!eEZywM%-ODQ&f%CQyT2&! zw^J^IzO z0&S#IBnnQFC}?YkgF*luEvJoFQ;h9s9exRJ83CwVdReL@ln^r$%| zzRPrFNafGFchH|p{MRv;p;ULl+F4HWm8>89g%H$@V~q)PU#|1=G`aZc?g`<%PD?t* z-2fPhg|WB^uNMGuR8Td zdSOBIO^TNz>3XQdlzfD~rlXsb{Y*Z@)~9CDx%iy9sq)mZo6y-5V4}cu14m{TPBC5q z`>uQKRHUN^<5Yo9D%SVh$}a|)IrTwq!;W~IpoG{+9{lurU7_1`xK$lGSL9j}2Na>` zKcN~|N~uK@UDiqu1Lbzo&V2QaT3=q(_*G^Fm-Q?$HyJw6c|ZnR7YMa~mD#NQiC=0O zr`GpB=DIXoC9a^HucV3KBTz}X*P<`eRIPm>MpfPGCSpvyY<=ny7P6YHTBr~sD$_jw zb#wZvKlkF{;IZ&hl|>`)=L*p=RUf7as9{yTvYH!;R3F4D@&7IvX>dLet=y|pWS3CFO#~|wj%xFPhy3bk!9-%w${BNqg zQ3SLZR?L~)m@~(v?^k<90sz1oqBj?3wM@hoyxh+&C(aoP9RTmFndxPCT666w9AJw0 z&^K*}?uJj*18y32j)xPGL(GIA69GK%IeKNbSFxD5_i_)vj8J1s}t*) zE@~C)VTng876UU)xtJ_-m&iDOB(8@rz$!|#?;5V5LDrmj37mJl@6xZ_z3M|3RIObx z2>|p9hRQdzujC=dLx&bBUlo*jSV>0wo#Dks9#UL% zEW=^XC}5(ew#@k*dRyUfT+S|E%%!B&o_O$%u6Vk4BWM(3Qb$s4eb+j7p=l zn_E>WTI%E$f6UXZ$Xh7vlZM2?OqH6?NYc5xN8%rcEBM#5o_%mUZ4i(&Vx16F6ngwK z%*vSu*J;&a6+l>QrO3RwxQf_>&lW1)kHuIqlL*KZf3Z5Y?hQ8*S3g*;&@m{`%|XSRPU%+p*tnrLu`mw%Ygjg+5W)WAp1HTXzxh+MLSFLnz>DJGW;fJ1fD0KJhE_%wO&{Y|(wR zG=P+PP3BOtj&Khhuh8l=Wc&gMlDnoinn@pR zB){F{RF_G_#YrF!Q8&7K@ca6 zcPi5r3sS?`rjJi2Z~|R5_^0=q;a}i3|&g+TI^rerErmqEYobyd0~ zSqT^6O!Op|7Jn^q{pVMjBy$I!Z&hVqZl7PN>&mw7(DMlSuezgTyXCp+JgeBz)vXjo zxY@gV_qc?E%i`*S9`+nz+HOMh2D|Ae^Guz#d(AJq1IpXD^#oWkq3pNbQvkxS#rK}V;+G5E+!#0osozJzuT%*=i$xl$AAiA6 z-Oi(WUJk0?2eTIuWi1Mvl?Q8ca#8YR1FX%=t@2E$!h^V5L6mM^4hjR8kxn?m;3t-1 zs>K-mAc4V!c`!J~4;kF1i`)zID$}(lyGS4nb_e65-1WlLFWqKd){}U$vUUjnQm5W2 zX|TMw-bmw(S`l|McbI!#3ulg%P1ZI&%I%|a;YK>=aV^zBiF1?rhSX?qs$8Dc-(rq& zvEz~XOW&!K+yS=F#j>mxxep;^oTK)^sP-!@sr^w@dudkf z+}Whkmbsbk4@C`LZefGNQG=IS*x=)+!HX?y@JZBQNedf%8Z}tl!Ungz9;l`+t3e|e z=o8g`AyeB-N)3p@fLh@C(SXzF32tFuRP*C&MB_Vm^^VBCms@INKO-i4NV3RnC$W~U zy1j=!zv`}ADqr-A{gv;B)qq+MXu`jL10EUe+^w}7GSej-3H;Bb^$jb}Z?N%cJ6{*os&I$zWZ}^>NoCl__DeyqCGr>KaNhHG_sq!q3p{91L&Ii zwd3JRvAevS-%b@U%6t0lK190Uvm|>j(K$7Uoi{U3X4G7qNQy$XyCamZ%BtP)9!d{1 z3)2hqGs*xe4wPKL74BP_-VbvY5SY|iuB)c}?Mx~9-WZZGTaqsiz)vCo7P|ukBZhr#eetjN`w}=~+q*98zV7DZ0!6Q0U)cw3AJy)IAc_p*t4nN`aXBPkX2ZaGs}0 zq`p7lYaVS9+xJEfX}5HGrM(dW#BWj^JI#AGD>u|P#$Lj)TUWz!IEF-Tn_jusEG;f_ zId+BegLCGk=IiXHZR&ga9jl^U{&#lw;#tdHur%qN3&-2^H}qqN#zp~U|LDr4lNzfP z=nlvD`L-LPCtlBr862IKtC2gpi#MNaPIc^->U6n(Z-qCwz3oY_v?adA66v~=o4Tx( zp7i*9>B|ftksLlf$@HKtNmdTh2Q-&pYCJH_@R8B!IOiYqLZVBz%6u7xG;a@PoX3(&%ws|y+ z5TJAz`mEmrBO6jZRKNq!D^O<(yW0+Ohh`Z7ZzHBO|9}E?tec%c$3tf|55P@| zN1X&9=c%dquw>}Ck2-YObj&m%<1K1y#2=vk(u^e3XDp>SAJki)Vh-{ozYa$6jjY34 zqyYQf>eYkYMjmK|0nmZUY-Ep?RA*avwSG3?tZL5=z|f8Kt*UNesyg*${nj;j%072v znf|nIFnnL+>(-@U>(=Ut8_Prcr)clLJ$_?Pl?}=KFubMGB{C|C-o9U0Z|Mv($+n?| z$360%@yIKzkTuvYngaG-pV>V2CcXr$&ZA)t`47!P#Lh+$@x>fOJd{MliVPymRGfGK zuykf(=Zk0|{z=RwN&Nk86!8lb0}9i+iZN_H=v!ig$s++@p$kdCuUJ0~Bw*wmo-L0i z#&gLp0XNdA4gHA{wMVQtNWcS4kNABg;E$M0_J{|3N3cmdP#|!*L^BPN#oqZcC=t?$ z#Eo~Hh2qZOoz*cH1mlbJA-Vq*H(L$7P)w{n5|N)8Cc`t8;3fSbEvV|oyVjpChyc6P z^X~kBedtvW*stdY>}4$Trwx`_7fXZufPIWk4Y2peLuXWrSDPO3-xyKZ2eJV>p_vgk z`%XOsKQZZ%>f#<+j%xAs9Mxi_mrXvBG@)bR<$x?(wRk3~lUKEv>BW+*aJjD;sTS&u z?`d9a#Hz&$_RaNW32>KBm}$(C6RO3Ssm*Wd)%29QD6y$w$+I6!vg9UIi#2MTty;X4 zB@1Ur79N3Wv4tfkyKnoH0X21XE+S{pdV7GG}6#Tad2b6nh* zbK!3zj(ttz9J@oru@_wvaqMS0L>&9EYdpsmbE+yfJ`F=2#}q-GX3f6_>d2!lP)DAT zI-(1?9Dcmpk_blX$l!Xxr3LE9Z63-3KgKmdE2EAancUlUbtLyjacJ{$YnKO~JJ`EX zFy2=jfpH^mi@h)$A9t|f>U@Il`PLCY-D5TH{`P(=V; zE=koAfIiKPVnt&i^ZJVcdOr_sysGeK>jVQw)mzlasdVdK@ZQ6rh!v7`{xX|Xt8eOGiT3nD$5+jqeJ+c5S)P7 z@DP5Io1^nxZcJ738unCzT8??Yj|7@JILXyEsLn2aTorjcIJuw)_HJ6*hpd*INNR9r zEK?K+6ObpGMNbz+B6a-q|*R zJC+2&y~@||7h*vp8c(6-e}Tc;zkUFekrm>r2yST+*@FAEc(7cJh^964XjcN^;!eF6 zfkRCG7)#!}Y13)C@xHrFojsrZ0oU&TLWy1g7R9USZ`g|DO|EH4Q>Tk3qJiKGJX`gN z-n0Ap*e2RoKaxxI^J3JG^qvlOA77+*4my*$f8%Z^p1(yhA2i53z1+54z3UaiqsZMe z6zgHJTeFL>y1iVz8HMInmJj5Q$bcw2+7Qv`eQ9qrA3Gy*aAF2{OJn4)H*QpU3;jJp z>%(3j^hfk8#Z$G|_PeQo6dUH-XuoIKHu}wIp6R})^TPQVrYnSXc4MZrL?$?uTs)P9$EaXApBBPcnnYIi#GxA zYZQ2b>^DX3zm<8FAe@%?CUB|;Os$NB#Y$8&0lq_xsp*|!yUKXJwl1?1k?pT1X9UgX z$)&9_n$IFbKtw@}7*z&h1B*1D&9S`<%}12VS?Nw+o_nm?kf-VpssfGJrZDDuoBeHp zY^FzKW6qu0ZAJ#Ln3cID1EP{0xh0QACC|hqRZNtaQ<*EDU%TCA@2t)kH;dg-^|7t> zpq1X1T?)b9f!V0|Cs%g0eD74#@Ue?DqEVIk2m^xNeb7aQB*l_V{vI znd#l#R#4qdA{C4Dg02_PZm@cEdwR>R3!>OATjp2pwQFkhxh1Gz$N=Hid>`xk@?Xfo zke$N+P-fLsVV;}L&34gQkCUJqe^^$#PMeLB4vQ^4FgL)Ga_e4e<>N))Q(I|ol8Rle zu0D@()kAG^yLR!``A_cAVi}NMygFk*ro$4qgz3`Hu?}I=qYP9nZ7Xk|68FY5yFxB? zoY#7|2XE37*b+BmX86kSxQE->+JAlSk?<9>F}IRf+8(LIKP;RSYjtVg(diUseN6W~ z+ZTDXx-XWqt5t-7+VoydP*uybMPz)2()mcHOWK8lREkRuKjo>F3o6)rr53Rf`g;^L zm6B37-D~__xY&g`!DqZ~ZRL;q^5{&Z;}+l3xYa8xj?%x&U4rX$Hh>K^&ab$m!)%?q zhG1tt!;M&$y@uGtoLED!GwWrmb^P4)oHaa$&C}*ME@^xYYmf~&;>J_5P0q4L+Zq;N zj}2?EJ0L|M;8Hlo4h#F7yX&KZ0(<0)!7s~7oGFER?$f1tiQDWfYU)-Io|D{$$3KLe z;$MT4%I+4}{bVyt+OIv2@5=+(jO9f8(_ee7H+3}IOlZ?=s9mnfQ*}69CE4tV zo6s(=?Q)^1mV4WnHy+GoR&tNUcq$V&0L6`DJVRzzGwp=aaVNN-@1ibN?Jj;b7y=-ybB zHq~qaj`?KT^G@va`5;xTpGV_<=pbAFcs9}9Q*n3Vqh|P$)lgNKE&(NoDHEBGVYR<&>vo}dod2V2gHPBmMV73uCAV^TT6KAY#l${lB?}j zPcRhsC&sXclsd2ChxpoW%efAtQy-bXvA@ihRP+CBd8&j9U*919+a4_!yT_kzRSr3% ze&=f1NVVI2Q#rp6ZKJttzX@ed1VYn|^LYoE7@uWXW9}S(=O(m~IM{eo?ZE8%Oql6Y z)%HLgS-Vg-i`@#w_?eqxjaJ^&(_K>yHCBtSxN$?d5JVZ>g9z;g2&zq_7U!ygd$uiHo`WyY_ukYs7*7EVs zbR)Y0-N@9YUW?uQo3p$5rF%(db2szmWH*C~v%8VKhi-Hk=)3v&>g;ZQI_ zSk&4M+1)f))Rb$oyZNWF;5ADrjF{xySj7W_($U%fPg3qr2w9>_$+s|QD9C2oJ%Rpb`}V2V z629xfY?s&dQoif7@X&k>eSzg=DAH&Muf!OfFI^kJd4-$XPROsj7H~4Vm96V-a`L3- zY8IxD?Z>}4Hg9Ca!cc4*wktO!3j;WYQ5b<^pD*`^%m9vCWr@?dEQJ3Ik~|9>hvo!u z^h2>_mi`(#7~PrzhqwN^L4cg4x8NRc)HNJQRn={at-9kX%#PWV`E7q}79JX#g?Gmt zR0p%L`t`SYfgJr-g$gNY?e4rG8)@h9mHmIA{$p%p0(mr!b}NkoJ$R$%NI!F1?C&vt zhyKYeD6S7CT=#KBjfQM|>E2{W*7VruSR306SLHW42I$O-?Ts(rT&qD6x0Lp$XlZgY zv^3ny{H(3DF_QMfl7)emHYF5>iAjYa&{93+d1xs;HC75IV=l3cwX%+LWkgBAa+r^j z*jHYs(avh)7BPZ;N$WihmL*pCbhwOdY{z&%#KcV-3}iyYK6i%s%?7vsCu3=fzR-G(kn76!c4QW)`oRq?fIh9%ZS zBgzd$5oYl?kJR|}GXusZa7v9a7A};VT8T$kKe{%Al|{RvwDJ8wMf60oqw^3nzS937 zzLKxLsaaN_D1P1&-!Hz?KNNS+H+iQo>Y0;jn%~~$&lFjEc0yI^cwXRLg>=D$ znI<|Vls`%u=AY2&51RtH>}nLqjPjjP3EH^%?SfPXE3I803mcY^Xfh+h9KWsq7;{{9 zy_n-hvQ!tlVK#t@+3ya$|O$+;y_u&EEeZ3{7)a}hv zc&ooHHd^TunG|HGs?(`}5#K;DZ*r@9l_M~(FywoYHs3F4iHXRM!kGLbOH4c@HWv0H z&V=sy8zjG6`!bFnsF`n=s`khYwS&;rI=ZI|6%p!a_hl(?)l@AmlRDbXJ#ToNe?7_y zOKw-Mu0~#)=;}}I4&vq)yIas_q_V13bvZV#a#h`(9Q8lkbQ^UQ3Zkz%hG8*;S=GMR zCwjfwjm7z~*u8sQRJC6bC#GW8@A~rSfPmd?oRgNjzE_1Ndkfj(cspI}Uhd_!{LVr+ zu8V2WbyHF~o3ut=?|Dvp{~y3*9l2d1Z=<16*C#|U(3@6daC!5(#0viCp0yP`dtCtW zG%WxUn1)43?4U96wJz!38IU~Eo6btz+B}7$D2ymzSJLoYXGwV6B8XDBc()=ky+61a zhPIUzVR~cR8+>qX#Kjq+k*+$-yaeHwXFf*AG1s9kUGV>-ZAzW$7PsA0k$Qlwbns|Gz;id5d4r2R{-49^ zFIDJSkh+` z;oGA%1S9j94S`@*=PA6K!f5C2@a6ufCQBSP`a3DN5j$Rej-P0a1!Od2) zE;%7_5(2{vrKKUD)T*pWR?(4w8<*kg+)(p*)vT&s!0{c`pP{NeVm=9oxuq$@{F)pH zLdUyh?#wN5;1j~TY{L~;}VDwz+l6-6Kuj3u`5{^uy%)!cxB}u`|>Qre56Ho zgr1K66sWHh6;LyC9r) zA8$ZOOyFs6a()3%pJwCfy=0Yur#=>J!`~gH+>?G(=bqABw5f<>Zp&Yh1dm|HMw>`m z8S9JOA}uYO$o2}=(s{E#i=+$OgEnfRTiPql1+5>)eX~6Jb*Q#@cN@L0E{EeS&St=I z0Wf3Ff}MyePIaTPZr$XzV(H>qh1gBZY`ZH%Se2`rvqLvYPLb&5H*}+2f2vzXH@(~= z)(t=gZSKpa7s{8i41Wxx>penf?8b19kNll6tPrbowUU8r#(p(^tmE7Z=C!9hKibp# z!~m<5)pV}>_qYa^HVr+pyw0w_Uj6$lGIf>_V!wg{C?kZqY52RHPe&&!VPC&Rfd^u@ zPhaVStV);TyQ@n7p6scCdrI)|tE;Jmm!N`zF8aC zr~@my^BDe7E0AE9YfSIrltNtaUr#R3ioFM0EGdTa{IBH5?Z<2{jnIpr<3?yVy&uz; z%ZN9sD=j?y{kwxGOoWH8Nd1swNj0tiHEwMie@dP;KOfdC_TR~^O327|?mo##hV?OX zxD_Xu_osYl{kcw(qq^?!5#Zjlj`cR<*g`i*J)WXCy#DrYbaGVjjFX9?tU4;^Dv4q~ zc5rX52R_~<$Ywht*-m%nv|CL(*3`BzM79`~tV5NyZXJ|J^R&CCrm{wH!azz5EGm6@ zBL2dIjj?Z5^gtZ!hL?Zi#N6V5J@i}THjLxtA6YHJBd!5!r~wzNMC?{Ou zXgj|(WEJLL8(0Nw<^5JYT@e?~ZrVh7`QY?H>UmY!v05i))6~Nf!Z}& z_Vq;E2($S%Kq+=x-)^M~Zfe|fZ)I6wfYjZrm#@_K5Gs^|9uQoG46*O`2gt$V{0-jY zm1vq&LQfbdL6guEpl)|kweh-=a>Wl=kQyoM;gNAub?Ve^si_5SMVpY042i06#Cn^_ z4-AI9)yzP-MqP_(($P?LbeHewY2VS50`~-`3C8;he*K}|Fx4C3>y7mFY75+sXuvrP zSQ5Ph4I`asd*0p7X!@=3A6`)hE;k`=RJB{m+Pa6@bkUzRLfinDdU$?0t#N{Tps=R_ z5GW6ipg+}D7wp|@=p6?7DH+g%wp>3uDS{EHlYkFF>vvy7>L4tNrxM{Z;Ml~K^yh3U zVT|-~ybfV{(k~_!xDVeJezCl!YV`6m&xSIlPK`HmhR_1B@@msd+wOR=*M04!oS5KL zTVPOfvFJP^T`Q_No(ghR%~TB97qjA?wdQT|E%kE4IX!{@{kvMhM{!>y!`031lOb${ zQ{91HrUDGu*Q!1g-Q*4ott_h%OF5a4z;4w6rp6vS6_vIMxHTw}b=#z|Ap!QzX%~JX(6KM^^+A(C8}%G%|U5Gu`a7?&Slmlri83cA!aj zlWINH1VLFj(;uMFO%?6{u8bw_(wfvYZcXn6tgZt)@KpCbi-7nPOY7|39Glc5$_b3P zsiCs5EUOaA#&lK6Q8u2>s)VvJUzNn(I+4ji2M270v2^xB1t<2 zmX>vfLfd#-{LQot1f;v6JW@GssBqW!XhiGS0*;`Qgx0ZPO|I6li8>Xi9pk`KQthaY z<`AhJTfzh~YR915D%;{YW~&`MF7~zM=(m7W9Q5w@Z zKDwt7ox{#Nuo`yTA$5_^Iim1Wb4@t<18+NLf<6fIV>#z^+5?pZNzQLRH|J8Dp#=FU z?h$p%fm3-raL7zZ=J)-{KC=$C(Z|%LVl0{WB$ z@3nLzSp{{m4Q6?4CG${7GVwMSl&5~LoSAYn z9Js$#g?W$L-@gYY9eEVvp6FGU!o>Crwlmn&tdH36;!Jk{{F7_9NpKp|+P}MwSW8bOoXfQcq>3a_%Hg;$ihi)%1(@mDDL5d=pEUu{ zXY={mAmXL!7#j|~YdReKETKTH_Ye{qA-UG>5xUhcv5has&*E2Ry1iyos^hq@^i#V9 zyiB|oFC1xe>ZwiC6PJNhe56-F>Ob9^fanDG$p=74Hy{;u1A>b&hl;KJ36gb7!P!h} zZv5mVE#S29;MWQ6vBfflspP`C;?0d#PCEkF$xz3 z6c)MLCk7NAl+1}x7}#ZA6e>zT{l<5B#FqjSq?}A{vL>{HQ^<|WgfP5zaGQvO3X33K zuh;?|Fx$!Z$z@Rtt{lY<0nL@6!tpZ7o6#siF<~paIh9?+5-1%tykIY38NZelmXZCJ zCoW^cD4gOwvg!7j$c%kjr%%G2n}6)bK2Nr4ZHcz>hi2Wb*nphX{V{W~#Z~l@DeY#- zuz|fKD>Q4`qEPbL3#N73Q9nXp#2WS0&~@}StCBz|C;A;!1)+H8`$&j=bL&9ppQyV` zEVmb_B0#yh))rvHuNOxj=c#hONQlo^&yt+rV)HO+(d=MBy3T`VTGQZJq;6yI?9T$v z?JWS$pdA_T?754+8iHqL?$QCz>Mcpk~E^VbKD8!#M+B+D7c>xpOAE6QR}q=p0Q zPHxf^E#+9ExEJWw0w})qy7Apk?%qt1gce2bQe>@*3irt<#QqTfpC)d{e=nD!T7AB( z3-5L3!mMyoscrCLO0?073x8;4n18BBovu5CZPxDCt5U~YmOA$I)G?=}j_sa01}{#m z8Im5jC>0fwXNbeEZsL{1mmFHDqsH*Z`SeEmY3S1R4{Bxd?7Hbh%yi75+Oa1o)s>E%a6Eyx=HwF(%5 zw3VJ-+q>$Km}!o4W3U#fb&b<)wUaS5L`L2011koD9PDAJqAF&>q6WG)MWCmTmWe*K zSN{hE*hptDr+z7OI=aG#p=5b~7a@48qFLrguvlM1-1@JE)((ysi>zfl;KD0`<4k#ia zjCA|uo+UpxRfHG#hmO-%z)6R*xSk9IU>@WVqiO=jBVh*}+y}2hl$>TE4cd;%4<0)H zteZTgw+`vldh>OA3mR{S{Ls=Sk&vN5v=d|jy((-4{r*_k3K!>Yg&EOS@Qk*&@aOrq z0?C4}Y;G%@#4vs zhuOt}p8gL8SQEVCaR3&0hwIDc`m7s#K0&tGCbyYF^BI}f-aLm&4TIO7!%6F0Pb}wf zVet=ADcxOs`L5J5T{*W_pcAfK6@t#F@H=?V*d98ik~RvpE|BAbxuM8K=#ij$sSSiS@(|?hP1vr zEHuO3s;cPv+`k!rLlnI({&tn;Z&Uv={-)>NuOehRRHeREmpZeGHx0;zD#iJB+b=-- zI&zlzt@aNE}O3%hGcsjydo(C2>BDB+dyu8uz^Li&{3;N2r9008AXU+VA_% zffdGqqBnC6XgW|d7%D74-Qp%4@!vBR_@jQ^-FnADXKf!}zv{ z0ZJR|bgg%}wTNYg^D)~)2Isr9Q_cS`bbXHS<%sB#5J^RhV-&P#t!X?=;(_1LU>0# zw?QrpIfpw>emzwd*8K#(-lB>!UZ0CGO-mYye1%sbCUa!Um6MFgh$;!Am6 zl_cQQ*1R}`h8R4Hr-`gs#kSsQY@sbCtd4Fnr>#B8fRlF1IIpy4M~cN=GEW*j>&HBS68>-s5<$HlbNdP5mdr^W6{X$1z8 z|7op&=@Em?`X%`Nv#5NHh>_f+nLpW;xG<7CFtNB^YU6ea;UPYDep56K%qfx}6 z?-K#|ZLe2)6Ix0~ITE1XzSK*4WaQTj0&OgH*Q5>$D#3u z_=<68{P9C8Ej0f6UD!DpY2;As>%k5@a+IAhLS+1PTWy!OEHeI}sHwCpWnteIT4y5T z56G>uGgQfqjK4xohq2#JlNWF-phiB2VFAPZ5E;WgUJGmeC}LpzuagMN`!jE927NiZ6}j2(Z~=X`yJK{vMLu{5=pMtye}_qSbgzx}emW1oBP|IkGyf!= zP9lHRpYe8VG*c8`^{yjGAI@L$J(8>$v9pPcSM}Qr6j0D(N*CY*+(H2U!8@n0@a#a& zDqYc+Rh`+#md3Y+3!{-C_THTo^K!@s#+nibpd4Pb88-CpZ1kIEqX4U*j8 z6K-GcP7WQC>&vgV|}b25kaagMag*6h>a23%}+XY7DYY{Qac|#*1a4zlOT&?E?dekWXxpR zMW9~oYkE+NHPi1R%8hB9z&roWbPybInJoW8vgYb^@gYBs^h!Q<#MfCKdfu|X)21oIITw6G)$@s*x4n%c=@dIG zxg2?}Tu{s5)_q^se&89XK~$#`G_@2xDno@TNOk4<93*g9|74ISdmPpTD)D zJZwR}Tw)bpR(k7B0ElXj9#znTER6)B#h0GzuV^}t=b6q-n~um9K*@)ylYB8sl!3Q5 z@am%#O(Mat=xB4RTE@? ztlC)~NrufRzrrI?gV9+H8tHyURC`oQYCjs)9@%7VQDA|aL*?o&UBcb=^5K=l1u+*k zN|7xqo0KiM2NQF@x}eI|z9AWBW`TKqyVva*V71hz<=kj@>xQG#%NDZiQC>nQVwu{O zIE46K;{^=M-g{_!E4>vd#Y7kJ7??#c6pID$&&unPdkT6XuuqT3y3c>b)Y$G*SY);n zBqD3LlI*EYv|I>!N<=~InU8j~vJ8NG;e77F><1Y(c9tx*ctXtlUA7uJQ?2OrInnEd z5Z&*p6~hH;uD=VP4qZDGy8%EJaQwmXJhE8vLH^+WK|1VzrBCYi&2C-$rvA%)9^VQM zo$om))^Eal14bLXqDU24Mgu_za-0xRz{IFNCaB7SbSSR3?4Qo2PNJN(#+jjpa*!aCc_k?A9nxo<^T4?IatB!`B-^$a%C#1PJ(6*NL{fnC8UfTjtT z6O|U~=^eXOsB1&ETm1*E6<<-JXJ}aW#^zR>xY*M8V;1XFqFsBfn{GiEmyvYqTK5Qd z5ykGc-Zhlm;5HOM3Wjy}Ly!=1b`IG2H=+fN1T8F+9(;j*_nvgxk;U%S-nGo>=Wa$c zr#OMFQO7i{UCNVG@%h@9ZWdD{&TGr%F1D;@*3@ zuVm-Qn$*#C@j24kd$zfExUS*+>yfY8fdndcH&j4qC62-eLKag3d$Q{WxX39d>d<4 zVU@BdiC6sC9p2HZOuP5Sa=9(Kxk2c&aj$eQ3O>iU*?hBCnfABdXED|nynYe{EM0-* z=f&9m)18w(sXX;RT)UcbWVn7({aN!IEp?&3Ih>v4CNVfB7{Ju;J&xdFGD@wx6rX$? z2f33jOv}9u$%H=Z=1RsCyTv!xXiGn$EnV!E_Aalh0wP83;Hb*#G=7tjGh2QofLA*1 z&*_sCaFLeOr)?QyVtkQxWxKZ!gBbySpZCEfWjd|Bj1SRer|0UkcuZ@7_ zJG!acF(B^{SWK)_DT4#3u z>$z3#4OMb&N)tqUP1uxlq`W+nZSi#p<}i)bevHh~j=ev^50f-1`8SX)H7fDkvj)H2 z$H!$El|JMV0l@4(-W!$P*Zbbaj7n5$+^Dqn9iB-TCm8rJlogqYq@OVRJH3Go(Q(_I z5K?nir9rBmv?|@NXBV+m>5ca&Zq}-_R!4+r9@4a7C!^@tCb=e0;b;n@bIiNGJc9z1 ztO1&p>2M2E9s9)Dne>tbqmtYK)9wS_Ei+UnH&ALS5z%e5#|)v38ew5S%Tqdux1wr0(`@H*~(KgSFQ z0sn_YfO5(V(CvvGtSn`AFv2rbB8kE8*;=vJ8TqR_=Oa{$`Z%-NQr+&xX7=>F91d$x~;2w54rPI*Fh4b#MRO%pJR#ti7rAi>U*4USKKI} zyFVOJMI^mn3L|Hv_k+1rUI|su77uJ;o^4&fF{~(=HhHhU$Aa7*h0CXkvC-p?PM-oP zRRmq$zYOQR3bW}mhW#G|`t)2{KqNjLMuzSuqeQ2U;nG|7C>^w9G6{0H6S9R4j~Uv< zy!11QJYba~?@iuQlLN@o=L{7Rz2Ra{fCazQld6e%mEmJ`{(U~%*Fk)>tuVlM2+N0e zi#0%sJ1NXo=ijngrRw?KO1w%8t+CEu17rxS_41+ledX>;}@|F~dsMA`St z`h)vNTh(uRrcNC!P(Rd0H}WaBK0?erqL%gqw8t90FkuakFkmN490(J(x`g^bkGmqw zz8P@lTjXXOuFB*;-W|1A)ntoIj^g*C25)3FXvBuTC#t=&$=bpz)88A_u5U^0eNpWd zP1e@2nn%b~UeKkBSP%3&6y6h=sYUR)X6j)>f|)vFsy2JIe#npvnQaax=W^Mc2T3Gg zbFNSQj`QIc-Pp>W=DaZf<^s&hUmn(tGwBy(aVE6df4ML6irxLhT$?5lz$&nhjbRlH ztjt;fz}XTlcSDoQ4cqvgsJ4i!S!?swsP?+7+WD-_SbP;jip0poi7HQ5@kX-TOxy&P zgVNoNW$fY9AKh2&p!`E3bDcVvi-@OeXP@P|*%r7^TOh>Oeqp$*^Rf@fHo=qpv72E`hPKbbWlH=kNRwf^78~$#KSSj{f(^6gC$_j^%h1mG{Sadji~OH`l*}OnkgZWu{(2ErbIzJ6DgX~ zNSi|cf+-wM+K?r47e_=H?iw>aukt#rmkPo3JRbIFe9q#7MCYwgSVLjNaoS|MRqZLfgLw6@k&p`)o%=9d~LNGlKWE2@j8~+hmQ)l07 zb)wh{FSRx+tQk`4^Vp;b(Jwlzy18e!2}Z?#cAE-}jPL2a$v#|*sn01(q8y zZEuX-K}5CqN{twb-Svo*{n#yhPaF8h-BLe3KlOzxF$})HrBxL?yiN)}?DR@EKwIP( zw|`43RA9uj{he(v3@nol;SC?7h*g1~|8y_7GVT{J8tOk-4cX~1+Gm4u5gG-n;Ra(d z9o+LfTGf`Pi6@e<7^Y7zZ2ft?M2784V7nvYk2tDEO-fAe0z_Sd6a0U);WDRnWM7~|dx-Y;z1yxypa-V8V> zv=#}LrM`<~RekPgy~^S%_03cwZ`t>74p5~_sD!(ixtis=iz#DPmb=*cOC-75x`|(x zHMGR7y~J38oAmXBtJo`6Dc1Afeyex+C8+%q?5`y)Yz%e4L-aTJO@U_sW z_i|_$oeC!VwwXi0lAH>)zJfRCecvMl|BVs%8QkNOcb=p|>C-a?y)|zEvLL{h+X((B zD9(p=Ji!LB!*OT##`E#XtvdA`)c^Uk{hr|@w%;yI*15>dP?ZkumFH!@{Wh*2`uiel z5})p#O*ZM_7WyX7SragCe|yY_Cefu$2Ahea-l$9BI~xScwy*nx-l$8WbKcqrY`Uu{ zPnm61sK;UM5`W6uWVr7jAzk9CvvGg->fSozg?6c&GhR#ugL81TH5Zu!b1Llc6*%9m zo&=B~$kl9y%L;!VH9dCa3J^9&ql-4>eWS zK*h7+Q1`)P-Q2TL=A?6PsQy3;su#Ei&MBxZ?}Ajgdo&j-$5+YuW+>btkb}G-bO4wO zIT+E*`93}~b%kjqic!!i>AyN%=ogp==7F)GHamvc#&d(Z9aS`Cyga=?I(h4pc|(wU zRDDPMDd(t~U6E@Qfz zbe&J@x>B6eJq%O%tl#(VUYuzYbm;zPNO$Qd=hNrf>JCmOeM_2p*Y%>Y^O+R!t;v`A z)Sqja7&KPuRyFKr{26A)Kh1iG6U(l-STmS(hSYfJZdvgQ-|w;46vZYI%Jw-kZ$8-> z7ctMsOZcU4!kE43Jvyo=-+(=SN_D&})hT_t4l_QXY@KFa3d%e2?trEHB+1%1h3?ZH zVsY(UA6`r(63p)EA)tBjs|y7n)%Q%9v|~t-UUpEo)6SvRY$cZERlDHi9 zctT>M837oR?n)neDhK}hTNCce89>)x2N?pMRQr}MtCL^iAb zEH2y?&ATwOcwn>)moPv8sm(dlr;~S8w#rZQqj+>9t2C3EmWI(QdzDflPjZhfDqxfx zZ&#E_Zl|X`&E`@*c)L;X)gNuV`n;%mN9ms4qG>jC(aPsqk~j2ch3S(e;TbA;7*GB# zlZ(jj^>4`)1p2E5;@tD-nB2OHh1JY}|4Gr1$gZ<{ob?9aZv7r#17%6{L0SF35lW%Q z{onKSIN%#u^td_E%1|Pv;W%<`C#%z46!a0Y;sh6UB ztB$|$Q6bbjL{#DSo~f;ChsI!S^;o~(CtOuE)^ zGc(ba*51sUtpc*16Edh&JLSn>;UBrtaK~Zx}W#{JMqS^2pe7QM1Sx0-sRe`y5^}DG8c4&tm%7 zj5IGVS&#tAGfAMZ>^&EGnjP}Zs&LY`vv~8iljkgNTY)1r8`CVXlfL`VyQiJ5FJ1K` z@=<##j!pjz@%sI-e^DEM>?c?v?w_p#ds_D$0dC@1c>%Zo+sy**Q-Gr6aXEmSc|n4v zmXx&&a7zU3Kut60H>M^4*GKb2_fz-JbnN?^0U$(7%RP)GpOohSSeS>eI7%awXqi)sWvDkEHmZfz+5byktYm9 z7&!b4a;+OBslvtn{+7L1kUB?I080y*{D#D00+YXsUK%p_wTX)MsswQ` zDz|13$z#u@hlqSOaKHgcC^OitjmMj0&d1;%73jj2d=biww`8e%(}vI7z{B7*dc@$j zp6}^vboVU!TA64S82sJcv*>HiwP=f9fxMQrE5o`$PDRreZ#72saehX1ck_(ut*)`S zP5M6Bd?LU+p!v6e!|(cb1}a17H--v~>i%#0b-&g12pQGE>yLy{4I(;`XH*}O?Wwbo zZ2xqEQE}8UxILu#xK&;AGWf?YY?dF*g>RhaDL4tYLrH#A)fhj@(Xxjn;I<rax*1G05>r{v%M957NT|aT7XtN$@p;j^OJDJV8K1Zu~Eo|1QN4i-b zJR+@PZLC$?A8QqFCAEq}HwVCtmVW5AeKYTFo%Y>kck2t^^4T+yH%Y+l5TQhX8wRDc zgv(XwART!BA@t)Umz)1xzgu7U))DU3K{qx|T@CfvgG$9Kaw9ci#N|j$s4qw_C@$i1 zk7+*cxo_o#+w$);3%5xShBEKwz>Q6mf!nSY!tDVae*@fBf{!HJ-VSQ)q$5>hXIQ4x zmg@g2I6Hc{O($5lmkzHMCg5gV4t6%!;I=P6-0o{0Zm$BjOB%v$eR89YYvD#ckl3jG zayIJp0Jm3<6mETw2yT7jjoK%M+owsmjVTBlwcf<)6cei=$1Ka;&gR8He~2k4hRKaO zS?W==QD1MNI`U*ftS-tCs~-k2(Emuqz>7yDRxR&E#Yu$5*%(q4u=~NPU<_3^rXJ+h&bH%n8UpjbGR`{ z4mYzh0PbEhajea6;+WSw;1;n!MGnkiaUUcBcSj2WcW1)Hu_wpG@k{{Rq9X;|s3S6Q z?2b(wBVrTBj--hr-m2S;$BoL*<8EnQrhWhq|9(TjElSFUCtD~RUQft|$vLuNV34UF z9H~rQdqh0$!B{rD9rL(JNghWCdw+Cz-nQz({9AQ(^MD(ZA8=!m6t}5`6!%DCtG=AG zRo@AK8*`+9TX;lU^~HFr&X2e13x2CAa;tlYfLbz;RKL}`UN5Wn+(#s$VmJ7$-c{bW z7MaXFq+H+@^A62C?8K&CZqM^B)O_TyJG>?u_TAj#2)-z<>x)p%i1qJ5ed9 z8*R7u?c7#Ev?h#UW^@b2F!_DcYWvw)#)?hX6b#1ifXEsI5@ju9A1riV4A`8Oh0O|E z!=mn5Q;Ex<6J$l`TolbRpcAx?_Q@9rJb|iv#R9u~5Os_{U;Q2H-VEe1?0mtft^2UM znZ$@y76u1~CJYZ49T>(2MK&0QsnESU;~W=_GX=0f#5EOiu{)pp=IutScU9J=OS*MC z?L1ve<7RP|J7m|g1EA-#+iR=+@ zUhk64;RP^vJ5O7j_D-7(2=B@w7Pbx$O1XaL$aN;|4xL*r&)@%ceK3<1yJgq(^s7FX zvOAwIs4oj{un*r(K>s@J+RN44-^%c|Myw$C>8ISs+KKRjzUL`sgYMEHlDp2p)4v^- z1!@+BcYO;l_WnP55g@A{MGNiD&?dV?*OT!+=biItbJ_FVy>f=eD0Ks(E@)fI9g+J_ zyZ2_motd7-L_M()Qbodkc4rJ~oz;ZS3WTEjy;W6A zPx0Phg7oj+yU!vAj9%TljtXVxfzUe)|NDC@B2AH-^Zj}O#seqgMX{H6GVVp;OVMzI zg=*Z2|JyyvHY51JHRb$1l^Z*r3tywR3Ym^@lk$vS<^2ANr8u763&V%? zzcMF{vQ#bl*WHNk|Dl`I|F7MfQe4~=l$KwUPEAXgd{flP5W5G@Oj2qGo%|^76j|s=7Yv|HIbV38TO5`@bmk@4>OXbsc|aCSjv{1=LTX=0;88 z7jBcJs+)*J{e@eb5;!K@2)Iwfk?W(@DjG;~&|kU_TC1r4&Cw+KrLrfXBLR^5moSN9 z_mTDgJ9mfm|1tgl&h@qa58W7b@bcwH^`q|Z-~Fb)f(bgf%q%jgNFE(G2$2HAYQfzmSd|j>U`P|f2DiU5dR#AztSx< z#6J@w{)L?7feH*>=HI?lId1ORm!{ zo5MTOVpn&av4Shzek-b`=t}pV6%D>FqKKI}wAo-6zhtyYpGKRnK$};&8Ah8g-)KYM zSKv0b6Uj}wwmiijZ{wT6Cb>2m;luXXglpLG_Zxn3w^vl3hWqnJmSMhsMXmVPm9EPA zywxUsm`MxVZQN{2U#^VoW+>w7%vfa$9Qt3oxghmr`Y3Rs<(OdM|aa^F&?6l zuE7rVXlt_=d-b!8J5IW3V(?PaRU7}|hvA+j9{bIB>?zq}H?$|N7s1#xCqXo}T=#Zs zvy0VAGGDE0I?3pZgM1z;B@|)o!xt_xS0^v&rEVc;=b!22)|!tsb|X9!fU+VMJextjF5iHqjTd~5kwi~j+>fZ(T;}G9vD`% zylbFnnB2Y-XJ{S8{eR_s+Ao^8#hqHXEVo|(G09bxm zo6qpe(qoP`CR^OYZS^T5V;by&`PbPlsI$Gg=(@mQ+Bna$+qk=0r$vjRK47IR(M@6h zex2Qeo)@tH>bE@h?`v4J-0Tg8{h3ypxhZ9=XE_=-iv5M(^>BLbTN&(oV|+e1MajqL zbr4q5rdF`{I}KJa^(?=Fx`sv5?E1!5u+mDiR&Y-kOL+GFgbDgx`yIc6iDzY2;LYMq zt-vGtsWTJw`*iE3SM*v#z)uP|S>CYdz6?&*H^j-vrf{+?;AB(+C*CH})QZ5#3XBy^ z;iS(+4RG?oH$6^nX;`%1j4_6jAy%4&ldWN_yf_(kk;lolZ)R}f4WLb}z~f}fw+tt4 z3rTVOhS5*A+FpLKeeACdCN|o*_cFVx*bTd(-~zX&cbPf({=xM#4f<0w=s&nVXwbg< z`T~0k<>tlRYd_xI4DL5x*Z^|e%NlGpG%UKyu57JzkCkRY?l$aqjqb;T7kbFu-Yo+; zZ*y-7a;#u&ps2>=$%hR$-KT+i_ctuMC9@ypZL*bS5#G|K*yxPFMqf#=QGZL; z%nC+fRc#6fPsjwDEz0J0^;_rhhDG!2mdm!z%T}7Tf``Lcd6~|NZ~Lt?rE6yE_zU@_ zR`B2MAXX@mUu(CzmmWf9g#3B@mG+n1Ue(pKkvxX%nBZCM)FN>xZ7U{j9^;BqPh$tSk#aaENF@mJQo0UfQsH~ zhKdg9qCT4u912wQQNyCc87k`Ekc#9VVKQ`c6cv6vTag6GksW_%prqXiO7bpDP2s^y zp%q>VnFwm_*4o8QYYXG)wGHutZ+q4d8KST`_o~K9u)}23=w7vh-Qa?HQ%10H{lN{f z?;rAA9OFg8kT=CLpK1t>*=3$(KH0EnPR9H66)VkRnGfL+(Ili+Uf|j0WL`!`CnfL9 z+dQO(nB%I>G$**pW4W(69+NchUCbt15nW8-+lJwG_*=cxCk@7yIvrc82lPdIfudSp z=7wW_Ep{JV%j+yz{X0{D(f92l8FX4;9hiJXj%06pN3y-b#k6KLzkYU4l64N>V}|xp zcWa_3*wOc9E?9;~7c7uVoo;l(nzo)T9j66r+Dn2DZ}GUZJyt6XC{Ia$`S26nglYq6GH?xwVpwQSY3 zwGqO$Iz>=uqg>5xh?7%{%WTTR?~ z7+K&Q{*9nmH!R}aM|6L+$4Wh^>kbZ7-iCL8k$T9vmAuzG_`RT4eSj$^7#1%1G*yar!egR88)ykf z1zV1rqg`O%>bOJ!NpsspWSQUkw!*G0v&eFy-KLhh*Bchyo4N1YXr&nr+|kLQzEdQo z+Vb+sbN+;^+F|#po!p4-8QS#D@GZeqb@vux>alCBqHa9{UwN!3g64v24Vq@fJSzZg zNjuL{P{uJnzIQ&iUA#;?;vW|8qtRwon)yLJU0j~(>d4u28;C!=t`(cihtfzy(cm`r zt09htYF%NEskiSWAOLR{^koF;%DQkbxnpPVT0W9^;!8;Fj&9*_0$~4?;3~>sZ&`e} z@O_#qWxEEqOkhP-TJM~HR`n%6=%Fj%S^un#6>pFThTW1unahaK;THdZ>l3>7ffe;= zkAFtEgj}Jo5#LY{uw?f0w$v`^QN>cZE3TI_2i;qpsq2u0$yYHv0)5t32p7);9U!4k z)W3$YK^{I+!Il~wwA~+Oa(s;UffL#jw0*UsPj^D2H^XI==)m#-B!^sCxSQ{wYNvL*ECrhsQ$sc2*BQs z8dg@~HlXN$eA&ts`ELl>O>kyq=d;90xCs1!dt_9lf63s?KzAq!dkGa_zhAx6 zuav$5x4(5=0M44;#KlsaFu2JKfet)BN>aQ|Zs`w=W*+%!<23VqJaK-gRNWea08T=E zC%08^)k$xD6xZ_1UCtC=g?JRzf>bY`PyKyC>hrWXzp$1#A@UFzD*nKNE#jGbd~I*< z_wn>Sv_F@aHnws3te!4#_PNtw`Z}CC$&1+gJsl9OlZj(aVI4GT>!z*kT^%%Cn3TdHS4>ST8U04lZNW+p&LtqyL9Mr^NV zTz_Y?x>(Rf9lhTOq&N^t`@$dE%GMjv1>r0Jkjr>PM3J7ZvkS*Xh1-0~j6U)?+y71# zQbqb*&+?LzP6O(bd)St0RV@0GoPP4}4@j(r{yKFk2wUwTYZ|#GN7k? zZBH^Lps8SN6L=p?fTqh+C-c3S@4Tf0yY?o>0su{^$A!mlqw3VpN$fS5h;VRrcF*e} z?AWX%2$iELH)n~lXtr@rHgme33WQ&jKmt!})Ln^cUG(5#M$}AOM-!jY?tGU6g*CI)3gY@D=<$QSNt)5jz40jaW+hpI#{ysYT zz9swnnCSav|6TglYj3fiduk9lJ6rOmZdu8j!n_+{=Hi{S-5T{AL_(v)^AT%Cn-N|kA(t2zY(i+aY0coAX zd0%_G0q1SUCEdMr4i{IRt%ze*d!)8!moNiH-ogyXYw=lw_~<0c1%%rQ+)F|k73UW$ zunibC+Ylniu;=bni02{nCU--3F`)|~BrgtL@RPEEj&t)gnWHXZQ{B@D%RC&hO!;*M z9(hpk=^69LfWmNT%@vd~w{-B_S1rmm&JVgXOutdbMVz-2A8by?nVI*t?&qDK9nF2M% z3PzxJQIk2L8nsqwLLBFzkQ}8Y#MWFN5o6dEjgW58LpDUU!)9rucIbO!R6A^;MhSfu z$&rZTLxv>c`IG>-YNcQzxkO0BFO-HDvP^{3w!1( zR1`Oo#CPk7iDlh|G)8z#=oZOQ_+O~EB3W&Uu$saY-(ShKKnOnYn4ayR?(=mI^RO7z=be*S^4R~d>{1i$Vx#dG@ z=8_!`UGpegHAl_8aQS#yb9 z{m7{{X$i@16QbtYnK;V(gu?D@kufD7rJJ9)k(Z@vsg`jh1vL+d&-Js(L(;5vR42Os|L%J!QX|R%15F{mksBrHJXSREjL(_`zQ4K_?^h6PMv{jk;teCY9x7u7A zhu5&!peTTNpwg(xwCIfW^yq--drWfU?e;A7$_`{0@jEYCYZwqC0Cy-o@M&RUJYajd zv8h%jdGr{h!TlxG5@k{%P28bg(*Z*vN2EfS%_Yl+ucDpi4myr|kM{&ROHH!;Y@rr> z$f=rb)pk|TlioCgIK5-45O8_n*~44xok`Cbchx(5UuucxD&6x19q_#-e2um3>1NWF zf#~Ilvq=K35fX1egohymzp^Qm_Tkqb>R0ez*V8C{VvzlY`3oWLoJOCdY2`XBQq?a# zJKBk#eaNB3H*hp}>siB7EtK42zo6gLe}5Nkie^bNDE4xb>aY&+ zM-M1PZ?v<01-6uX+?E#4xYAv%byuATgNB2!3>b$SPY3MlE`|F_4NUjK?hIU-eu-6U z+!{C5H{Mbt_;E)_z&=5gF5e|nNBQLat0LDIz0>ikXV;s&-09mxVf6`7#SY*D|7DfF z(cam_$tzoh4W?)!5#4@icgZYJ;_m^EuhtL^bSn}~khffuTI_Ev9u}evbT1@Ze9ui& zgP!ii))asplJ(63YInyY-Yx6Z@IMXM}zh%7bLSu z4SQ@-4YJsgR{rE4+;ZA_y*rB_6`b{k{N|NKx*wt&deJ(J1&zkIjffHrK)&g_!7jJr zb~5uwHqkx1D{bk+-7q)R?aSKDq+UH-uhHD!x?7lNDk`$Fc}HZif~>{&@8+@M_9HB~ z@<6b{f32A|q->Ek&@D%BElTV)_;Xj>vd=$8+QX2e@5Un-KC~3kMr6F#x2#Fbt07yg zX(ys2E2G0xk^iMM-5XPgWmL3*XUE-vic)^E6OYCNt6m)OqCy=pwNiI3K+HD|v;gx$ zl^qZk!%w-<>;SJXd^*K7#uJxjDE4!(Pm#zSsUWPiAX@|$Gc3nqNOBB_u;Iiq#xa4q z_+n297DHdfl%Qy)oWkzN{?DssTA@~P zujr6?HhGZvg}!?jg2=D@Hg((VyZ*LgJ)x62uxY(^`_`mS@W}eX5kl56y9Hz&JvWsp zG&F?}zjF5qJJ~NiKAa>=w^_#yx6AuDE)Qwj0@9wFMcP+$7?DKUv)Uu=8@ZMVoIN8( zvT%xY+;a_onLX=8X4okd*l_bu$}d`nkx6W<`8SY+6$3sq{yMB{Ys^4 zt$-O4%DYl(MM{7?z%zeu4b0%=;>}8f5SY`t=V%l4tSsEjNAi~!swYv5gd?;=ywMZF zhF`#mO1TH;dit9uj%3{21)@ahYmqeG-km9M2|>>O%%ac|#%wPNB_$nAszVuQNmpc` z2{{?4kJf;OL5WYBlHw1NiCN_+1&uoJqj^RKw&Nn=W(;JtI{+@-AQ4_NtE%hj>PVI4 z9{MG3(5Mb1oVOoZCH!KZ0Co!c>L%~*Zgr7j0J}A)%k>DJfjKVr`%ZW5aKu+r1V>&E zIP$c$HNlUkv%}M;@}4$_r;GBQ&e<)MNmh1RU~jiFW70LC`p?~L%CR!DCph<;nOSBK z`iY`sRf01Udna#V0rv{&lrHSFeK&8q9kdPozQ-c|kSI^(7ol(5&Gn74Gxl)r@8)$3 zq#-zhkYi;dE_ZVw^oP4I#g~e!k8DMY?C!(#k`Hql4{=xSCb2c+mK`DXrN1%m*|l`# z5#GAm1L^<>zT@T$H{HkR>)CTKiG##VyB{b8AZzhYs^s3wllZ88bjtr7HNewQ?5H7L zp!DGk?dT@|O++nwqu+tDJ-W^h<2utH>1zk2K|f|Qw^(5p9eyqxwm2~!fWo{%7}EZH z+6D1*IiT@TpBqkzXA)dN!@wOM_GA$Te@@VbLpraD?I7sDP%nQ;6hLIK;7XTq^AD%+ z6#FpiDX19uJaeux4s2(h0DyKi%g<0HK#YaAMd|{@N_|`qBw66Id=PB`%Tpy@81WQJ z5Oi~PtI14lce2wQX^Fi!tPF8w)irKby_wul#U9y~Ji4OdnW2)a=^iS9T<-22PKGq+ z?o3tZm9z`606!$7XzCwam$$I>U0WEg8{pTAxs{=pj)q)=&~!TEGTmlxC0!&r%I>Wa zE#Ey#_vG1sBc&@}FJZ!Y=$=(zB&5rZP~LNNlouGgq&IEh|E54Sy;;YX^^9B0DP!-? z`5RZJp6<6C6i$|IdQtkv5w{e)Jfa>oFt?#fD8=PbOVuYfD;1e{C}unS691fzzx*bw z)s!b^?g0o4eSl<7_a2vns`Q93pa^NIsTV_kGdpzq@1z^>-)+)&LkDU1UwsOJ*>j-1K?#J*p z7u^=QSdaF@n3`gsYrDYjyx+G&IZv+w`Jd-+?wY(thj7zI6$?f5sB71nhAJFzt2V)wl-+7c-jCaHoL|kht-HxhPq94(>dFfz~y6L*~ zFs@tPNzSYJ>oywbW=sS*Icchh zJurQ#9h4jo`GBUbvT{ez;E@rF&;JHoWd>A0x2H`YK{e z(p?4p!Mo}=B;WeL&nq`BSNHc4?>A=O8$M(zB+1a`{cIZ+GKK+pytUi78ocU{P!oE8 zH~Y003C=c`EQDIoVn}dJWWxHBd&x3kU0QE`TDNVbveH%V8P$YD zJ&?lFz^z)zxNz$Gf~VLL|FVOtUl_UVm9WRHowgRGrt9@_>&0DZy}`GRocdM=ZZ=Pl zi`&&hUYOTiC-smw#uIoV?~4xZz#qh|7j&idhjHu2^I8|y6Klvx#2>|9Jl5$Kxe8<- z#~(bJ_d((Gh3Y9cf`i+L@YUblwXS4ds6e)HY<;z1N7=VXdG)9-t9@f!@%G6}>ha>@ zYovyE87sfs7+E_e$7QhFg38Nkl<`mO*F|YA)iBeI=9(qYI@JE?aB<3gTul6EkU3E! zJCB*?RUW$qTpZ#~sumtI)8pI@R!+5++-zg1=yeJ;fxd?0Kh~GBZ(gW&$GSae><&{o z<*!hD42Q?9Ky}ZJpAFDzr^^ZYi??F1hVu|mzWx331M^&~HoGzD)unj4j+rKAGnm-( zZx9?;<_^_di6l9bx9K%}FIZRFy5 zQqcsJuuj`dQ;wb_qU6~Rw014;%07Tvg-e31^XrKYhAcqt}DfFE1G4;<#4 z4fs@_>h2wfyn|_dy;Z#CFZl&gQF}ZS0UQtjso=a1lt=Cf`*5VJ<}QBTI$m#>nt;a0 z`}lHNmF_avypkUMX|=SAIs#|a*JcI^{Xc;b?cvs2_Qml^KKgTz^W!#4)W`&@m40z7 zSE{m4hPV%CH815RS$@8?RD$J?3-!*eAvI%vch-gy^dG*SVgp1)oey#E@a|MRv+U@- zJKV2F%RxEsX%nRpQ4FD?k?PTx?VbRPWBX8Pr`7YN;1kp;Z>62>gbMdJ z6BcIeEW%4F^OTjwme0R?2ufs9TFAEJ3vuzrm+cGE7(*eNyon5=EQ>>;6T|ktgiqj! zu8BNZob5|q)5dabqxN!{d*b|hIDnAh&mm%T295vhlvL~26ss12^A51*4VO89Xmg&g6gb}Ov0UFJRnfHe)cMCEPkw=9G+-bH3I>(|{AQj7URKOPAd z+Z71m>4x@d)3|za1)sV}6`8tgdt>CZqoaIy9h;z6-m61BLc6{si@c4d_%Gvxq z>(pjeJct#u+R?VA6|Bit&g&OXt8K&+@f&V^wdRag(MaPY=q;6A5i?Mbvef{M@o;{aDMb_n6Jh6${rHlUF z;El+CMV9<8vnE9@Hqh;?LF(nW!==8pbw@4QrOd9%ecN)nLb+eM!sIxn4x4&JFC%AW zw2R)?@9phqL-9Txqbb5ZX#%GdzPZJER>YFV0yg0-p)1AUZLc%D!NcJ_(i3XKA{kvrC9DMATM{dh@gUS?$bZe%UYH#N0N)MA+{w4nptWg$>V z+9aiZUA}_jD!l8LUINg#a}9JCCfn4wHEKc`_NJiuv%jVJ>xV;l_~e}ACx^Q>|H--b z$ziC`^|x+**-u1ccf;MYAu3{qfAR91wu#*p0Dyf3DURzcGH);ZTm=*pdf4%`>Iav8F*JF)u*vk$q!d~`-!bPp*874GegmiZawdKABnwM+G8pY8)eV|(}#0)Bi z8xkSBo^gho-bb5i!-y>YTzh9KW@+>GDBtf1HYi=6Q8U z#%J~h9iP{XgOK}@O`$lIo52GAJ?&O5EAigymtIldtQ!Qgd?B9Y3jcjfMw{a290e9y zC0m=?8zsWDCbhS%t~2Vo5a#GVD+T1Zq# zZFtmekbF6P|109@7E(==q4Wh3HeFudY$hd`iQUwT!%yA0_KQ~!@~SmcRD3^gi+;}@ z=;ZtXWH{dagrJN+yQ((vhPSw$c423T0P_nd+=uoE5w6^8;*|#Iba>^)zb5ou2po>D zjBG;tA?`h$ipULY(X3~0)Y05hlc-fLzxE8^Z~#nA9*XSZ!zEr*mfa8{@Rya;AiNx> zwC}XoKd(Xi1qVght1P$}2ZD=Y`ZaM9$p~5ieeoi7M+vsB@uxI*TVzvPVsM5docHo! zUhGn@rpR-PasI`R||%*VLC1YxtaKZ z85_i6Uv>vz{E~IIPrvBS^*ih{CQjR{%oWsQy?Fz@=;Qomj!SV$RFkW};DsetL z?qYN7kruS`x~kqHQ^c2>#m&4M(!^--=vX*pGN&q6Zmfu z4WrV&Rc0FQ$?dcU(_&7V&%s~F)9&d*#J3u$9|49|90piwDx;m;BJ-!)Zd=z&V{0q9 zsRJW#Vve$S7*J2 z8oR9pT|sxI(G@~epf!H1yspO6K#_RNsRwpHHRUg){wwRbb#0F|2ZwvE(}Y$13zvMU z9J{A4vzRf`CRw5a9uUVQNv$lZq=c|}l}vv!)uJhu$-m616H{{L*=yLA@6v^(A8L!N zAhtE1TTkblYk%HE{qad_f3QgXV!Z#V-{MKqoE}Obm%IMkz)UTSu^o?>z3mU&w9JLw%kD0y!hrUqHMWDVUdn!j{~s%>lkp_6vI{!+?wQF zk{t|i>mUZMs;UzD2Oe|CmY+F1wVf_A&P}yYEynXFQI>ov9i*iQ_5Q%RydMzaLMHNg zrTb_k+Yv)5h%AFh`NuH$haY{UczuWPQh1p|= z)g;L>{wS7ljAt2{3Q=g6O1popA+uZde@&t%_b8=|s6Bp`kRZYc zcv_x((ruTD!bk8!R=n!O&yG(L)rwL((`R_vhF+S{3WytzL_c7r9Z1DF3is*HqQBSy zzChu8JYSZ=rQM)dikO$KOQnJEPgC>wsrlCZ&j*evRbtp6Ca~%vuz@uF?*dHcY%zy4 zF<|slgoTj7#L+%a_ZX2IY*+=4d+Yg!rvdTYi`#XH6%-L=K>&wv;($N|Cl*?Wh;~Or@349~A zki}o5;!H6uLoI16@>7zj&%CgV7AD%inT08tRB~bY2kG-)SdcdTjz#Gigev_-UK}wQ z{$__8XLl#j;pEQY+!e1;?~8BV@^p>1xVPWEQc^S`FDlwz^rE+$v^9QB$=w`exO~yp z5+P&OB)^%LPsH`aP2u@CP~p<4_0l}ca1#E@nM@I5_u`hTd%2qaQaAQpWPw$-pw%TA z+{6&f3H|S-Rwy=EQw`<=49Se>UAAO3Q3tvWGx&SUQL=7@cr2y%3DH&|6;OAvCkywk z!57t?aT$uZ1NeeF66%^?yYsz^#+$=y_XNsrb)+Ockvsn-%dF(wo0r0Y&Bbp>UVO+o zG(d7Ms&Q2E3gDS>t?w(dB;B5+VId1ArC1infJb{{8cxpt+Ax19fAS_zP9)oo?_t$d zH{Yj$OOMP3r#Bb`qV$POyvog7t$8KXCJeY>3Tr^s))4Il1i#Mr#OYe=n|-KyDsknBZsA1WTPKK3F%GjF<@xk@XIO;?LAw$aUWCF3Ni zrOPvWX+D-$pI^M`>MpBo>P=U7P1ZN$Q=t9U^O)zb*pRjQWrL!Ji!|magvK#C4Y5w8 z55F~d_r8>D7h6qk!I)YUiO9t;MCzKHnI~Wo131?P{A^RkdDJqh45F-$pO4Ldz9D{o zcH();y{~QHv$~9eGOFBpognI|=pPuHotVJlIA;Z$aYHAYackaYe7G{X84Z_oZ8OeG zY{u(_n~^mY-kJom{2SPe+lp+)P04oPk`J9m&)+QTcF?}*VB5LHSW_3fIIq!Kgf;Yh z<~=gjYzyov-Br_VRf_5t87+6M&(m=0^g`o}fNeSrc)?A2x!#nf7m~+7Kgr#zYc?Un zW$E>XV7*U_29Dq_pI)>K+dBg)z%Ap}k>!hCO5MVx91&teZR4h0nZQArss0uFmnM2F z9eX1#am=fp#r#mHB;I&VzAE~YxA`n$a;5HjUI6KdpPeb7OWk)-?3Yy%55GzodpF6n z`z=O@NyH~bNW^--_pCq!_-pQDDM;`qM7#3g-I~wm3BEZ7KBZ}e3^Hr;Km$Uhf}6a? z%H4!zx_AY+y#O?`dJyS_f!oLJ;I`y*hTAw)wRv!Ry9nG)_oP)`pB`@Jyan8L_QDp` zs8=`JV};P6;y!X$d{rLR6Bm%(YV4;l0_r1 zh(jJaG&)3b1Zpfb`6*g)whS{7jlbMrJ)EK3XJ?7VsW1QR@H%-kU7Uh!qbZ8tpz4$` zDOXeV{gZTCbSOU$(Zeu+x^1+#d!oo2%v*77qPPZU72&H^h>Zk=RZ!sLa*~Ra8;w93 z!ARW~bdb}eFD}x-rJne5>Yu=Ah27u5&27RhB=pBgopTC~hVH4zpx2{`EQWU6u9c5V zl5w&EWu1$9Dw&Tp$x&+(>aFqQ7nXI=OE}Zzd+o%Ly|??>RJlOYji<`0mESxp{*JhH zp!A)$zB6te=znP4-b*}~tdWt#nQ}h#@I-gbsddrUJOJ8^pC%*+UXOySnoINe^P{bo zMdiQYoSzYUbCjn409eS=WF*xy;-2m)@t^IliF*G80g^P?WlEDR1nohZY#K=h@M*GN zhzDesevL~IW6@uQdv%ph;C+~X7X6+%D@9!QD%g{4#0)!Io%vNW_vxCua7eZk@L|^7 zBJ7g06I~sX;9f5q692;^-;D&dV_I_*1$v{xxBIgVAe-U0!5jxlHeT?S*Ux z{Jw`=rYqfjzL7D0p3YCS*tv~kU~Nn5tnHL`9j;0=-$RV0(zTH>Fcy*MaGa9Jg&}ut zv<`O>9oX76!7ui7&ytUeW<2TPF4dO|Xm*Wx7(hv(P2#Nq+QO*k;HVF|vbj%)%Mroc z1C$=Xi(dT5CD&%}2aC&DQofD2$q4*NmGWqGXI$ZvXhVe_4%>Q;2@!!H0Hs~rb5l}H z8Lg$%H3M@Ccc_u=T{79e?qSHf#TnmtPszMsGFyK&GspMpoW(4*j10`=wdAKSO#7_o z4LPGC^x)EEG(_qS$s0DfYZ4_zZ5rO3TmyWUzcygBQNo=EmADYa7UGmb`2bf9S-z?*!MOKxAho(m8K?G*NP_pJNRSOR>&Zm+}xI^4d~rG{HY-cs+0mwIE7rQVxZ>U~9)dSk~+ zeKcO`P06K(TT*9B?dL{|ij}4hwQENi7%1h;1gTCSZFSW~C67u48u?+Mk)!izq}L#< zC_*DI2sF|%r?XpELL=p9c&xkPVkuByuVA@^NN`nC}udX%Szg0{OISNt?hW3P1U+?xwX*VJdp#-w|B#O(okoVqI9bE}3A)g6z##{Mz1@MvYDb#LsC#l5flKrk~|0$}IE&1)7qgPXCi9Nbut zhK4uP>B`wMM1qOQSrGX-UXYu_ui7=}y>1DkO%%qRXg_l=Zq;|Q4*(XG>65Mw+K5qE zhT=by9f&d$9<0q9DEY+6cu8KJ8!?Z_q^G+6AUN6$+_3t?Cx~hCjKjFnVQY|e3hOwU&0awP* z?;9&dFZx51`9LSz!a7%cROAw!&nVvcd^&H)&I^5tXx9Do4Wy4#aGY+{uj@^K^|GAUgkMu#hjcC5i127Dx>l08=HSOrJYti}v98*XQt zN2T1QP#Yyze`$EYj+I=gr7kALo|%#y#D+ZxWFhQQAf;lJK^IHIimdbhVe{ zx7MLe0mJT}#+xGrAB8A2bPj0hzO}aihhxmTkP%)UCz)wIQ(zOz!D z(kHuJRKEu;&0erId{PXpJVN-1Sgj2K-m|_^Aw4=2qxrvg%8gm5`!;fIE+C*QfSRO4|7H{FCfb z=`Hq_>+}({AboS*NK8N|gDs|uxMW4Rk`9OCp!QuS5Fg_o@f6oruF?`5#u-%5+7B!XFk2D5dU-^(mZy z|CjC)b+10(Z8Cn<$H7JOx9MNqeP~p5KAzV3;M`1(8aOs(ZtW>GLntV5SvMWqn#0v( z`DwKnpoq*B^>S!ND|H?=N)rYw*F@e0|7OsjvsYLSh&c?1EWLhF-*4_BKG}eQz zcpL9qVfB5Ww^I)MG|t9+h_th{J7FkZq-BE!C^o|#)QX-G-1>gh??8~i;w`%OG3^Ul zKVJu#4@+%88rt;bi?3PZkMCDw#s8!RPOeUX(ChRWzR~vjK~@)gW`CF~HfjB_<~Q42 zrF;4^yDpU*a{j3~c$Q0}FSP=W<+QyYpq07X4;+M%$K9i=2yWHof;viMIDow3%N5GW z&r)gxiD7&l=Ss5S>)_8rIOr+$qYnfbiY@5;?=}v#+wR_y4UBs<5+Nxb;0@a6+u^)? zws=$@28q+CFMB#AVqfW|=U&O$h=BSAul%hny4m zR6;b8C$KK?`(K94!PWHZ>20I^_l^4MrhlY>`88nUe%@%}6~EgowrWGH}EsqqhrnE6iCJWL9?!`gwfJ zs6K#^OwKXh=JZyJOu6|+vW8penjv0iSdzpYiQ)x=Gl2+JP(Tx5v(7dw7QQgq{JHqt z9eHyJYP#H9F7$IDu3;y)ZXcG{#W_$%mxGu2%Pk3kQPMg3`>|Ri!?VtpY@JPh zom%GN0PoMf%xQ^bzWhZkb6r^G^F@|9F}F-I*kYKxD!0tXKDTAgN-XpFFKU_Zhh;up zWSN)dmbs8s^>^3hmU-W&U8eMPc?anF>;d{(_5eLnst|D`}L34r1!OjP|6Ljl1sPDE>wJ-SM(o^Gv9TZj&rG`k~v74!7ASfyKBAQru zrmrI;cx2o~OX)C5Kh8P%H-71ZQQ=KmS%gce8?Uzm+-s_ar7Ij=_J$c3)CGsiO+x|@ z!z@kf9$Dp9T%I_iL8b7d=FSdGK{HqGUaqy;(UW)ZTBBll2r%=mu1!$}Bx^uwmn0ET8aVV)i#65Ah~&6V_jrCF z*qbGixRtDBk1Z)?NELSf1A-B3z&7Hxc?^ju#Vd9@GNpW?ltr=MK_J8LGg({7$H|ug z-8b@*|Lpy^8fAXnTas>zS1#M#@s@q#AjP=p14Wx6m%mejTX*2+kN{RL|3l~Q z1`Y;+JBz`dCci^BN*k}~1>@tq593%pA4X0eT37ec%!l(MKv)1N(4m6Gfl*573g097 z3={dJBx|Dy^Js5WYL<{q#ua_e(@AhtKp%9q!a84A>Nbea4KIT2F>f#*^Abe1*P*|!9Xh#?=*XbR8tyo-X@^zXAGp@a5VFF(P$wSd5gk5Ev^MPelBsd|C<4+xY^^}`9gI(xJ`HT&OT;{ z`aj%+zI__pl==|~O7t7f`u3JZB>SjfxQ}Uhq~Cr`4&4M_}e=-=P)i;dZSE6 z`|6jpTWHmzm7+Z5t~<C-lC`}-Y2n>3=LIwOAEjB1%B#)63@i5GUImtRSF>E7PA%W)Jwwwb zyZWNxX7;{(4(^s+w|ir^bkDGWLc{kv&8epUO_uMkwzqtnV%A%}=V3Vf54L<;fa=g1 zyWV%v@IBIu2o_v|^Ut%>csEjl;l#;d|6N2GTRP6AZpRH4XLY}^gfC#-B9 zo-~Q?kTr?lb$C}S;*Cr+y$ky%TUcORb1V(^}j=gnW_x3s;om6Ge*DGRCn>D)0m zg}UvV2}^ayfat&Guim=<9M8%3&N&5CRjvbMDaF_29Q0N{!J^e|*KOl0qT75w-xG!d zTP|RgR{N}m1JiEZPI+gqXCru1=yr0R31-3VM8|I&dDZg`~aon$z1aGPkf%F)J=k-(IZu^9)dS6Or2%|ZbZYK-& zYsA=!m1O(FM6*b+>PgXMSct0rNqI<>=-wX!A`}?>A8pK!DR0J9 z0t)0}$|=vO%c8QH#zEzA*2(W-8Tf(ETtQel4kYeXg^BOrCf!v}^ho=BpcTf$K$h4O zBibi;VUU8|BFwj=N<*o?*j$ThHwvPTg;gu>JSFAirMZLeO27* z5PU7JX8J)(+5Cta1y&W@4<1mSLEI10^ak?o+i2zeaG607`C4CZ;j}=9WL3Ue+)0mC z`NVhz!7ez>ELh$yh?9zJSC(K`d(ly8m8B2cq;kv=)7~W*A2@hb?%5(QFXbiw+50vA zea@uDSsgFSg+?r&8f`NoDnBUN#>W)0`+SsfZ#`^w!E)Dlb0Q7FEe4zp?1BWcPf)i$ zt}|(aeLgt@v43o^6KQJTv_f+pwoI(l2di#;Pz%n6$Y$KA+YC+*n=x}nD%~2*(&q_7 z@BM{?uv2&0Af7ypW$qFy+`H_i0p_wS;3!WSM2^LLp%k=6*{s#O)(Sr-FO!@_1AG3C zf6hs9)9dm4hLk8{e!gCqZ}8r~Db<2O8!OnY)veTpGH0O{hqY|V7s`?%$zQUdL+o40_jHvD_tUf6*y-kx(AuxUPn@{7Us8D0cOTZ3DEq`Qq z2A6%=E65s)(E>mr6W)pdmkMVAlH$m?%g_sVndttkBi z+xcbY{m{WFVA^kDQ&A6T_Z%&emuK1ot6po9EMDTduSmT<=Pba3#|=q7Ni%+D2yO35Xzj!LH51Nqx(`LYd(q`C@vGPFtRnW`@~Y$0Pq!*i_B*G|O+qNlloM(+*GhOZr?q}g>0^E$BH+$Q zPD~SrAS_4_gpWADdg?~=Ft3t$IP&f7;f&}L$M!^t$r{9!ng4Pqf@(^*h7Ha}AXq7;6(LX47{<-R=5Q0L=UNgVF zD*b=$)gX|WBvU781TaJM6wi;P5Fa%%26QpG;aAXbc5 zS%+p7MTdNP^lB)EUS}6WukppvYk2~_9x0AqP3>KwJ3%kGLLZiMg~mjZ+1V!ide@wv z?G6ZftbgvSC8Sb7zE1OE2LV_+Ga?n*x(}y+zaz11dHjLOFlLm zc)>^-mt)=E=57A6GcFcr#5@Ri^m;s3y&J)0@tHBW&IIvTM3aj_d(tRA*(rfdR=C=X zOhs4uq|~qYwMTHhkfgvk55&~>Lq8!sb)!0>?nF42yA?a8{!5%3xnZWHB>#YK``8fuBH2Uj40CmJmMB z8ciXKzQVS7e#WEW+?BgoXjZ@-&d%MSzuZx(8+@Y+scT{GG&+ggfX)U5{eSE-csj&i z76O*GKQAsUbUWBTtU90H}0fJA*7YGY&}%HwZ(9DO!XsK zTej#Jc$oq4_kC-Kh!~Iw?k#V}?2MCt9}{SI^evcH>kWY6reA5n6GSd={GBa(S8B>J zFaXP!vXW)3HbVro1vl3dsjJCeuka1UXCSic$1pejcd1$>HKf&z2>m{5X}l^>LTeIY z^vw(ydKlkT*>^j+2hlk9)%D-))S&H%GFP%w2YPXs%V8+S)8U3OonN^naCt+ADU{U` zIy4Ynzv1_2;mX|O{rnW!{EL6z+3x40*G}o?{6vb#7-W72*HFa3R&_?oE&VMQ6kyR< zZSESYy0ZHoGVL(BV2uE&l$=1kmPUhuM*oLp>xWv7Ns(lb4`SJrto@D@!NB zhRto3>BmvSPoAqDf)<8#6;0Iq4nymH9Q-mKDj8G|kZO__z0L{M&hmN{0wboaQ948) z6O2GsBh}})-)r{ys?W=Ke$B7L(dJ@3u<%&Wo7%jnTL?owv3nC5tIA;^1>_t*QEp^V ze{GZ{%i`w*T{a~K<{qFLlJpfnKqVqET&V8arVkgvD0k;RZ@nDB(<*mMXZKO&a^CYn zWpVRn8lE3Fys5K>9GwejsOzLZf9t2~GT#Jg(f@0xVT^hQudtAku3__A%ARD4?M|#$u ze6`XJH--Mas}DPK4m$%DBNJW-9mI!1OP<5rv-5^PU> z8+{_!ZJ1jKrosfDhHz=5Wa8Wp~t@%B4NWDMmi++D~#Jn43)_sPZ^j z`C?~uihBg7C;ERyNeR>#5a)BWBK^1ThaTppI$()kL$8ddDZ=Qu{7x zF?`PNSalCcjJ^@H_q0GizO&mAymv~);%J$KE&FnjmZ*Zkhx|1)%4iA0n%yM9lQ zxTkBuLKSW$FCHw49ZzoBVE^gz+|!i1axksk<)>0yjxH9L%yX5#)hmaJ)5LnO@p~x` zw_(Ne;e~XBQXlczMfTQ*450TdZH@-IS0CdD^l zbZA-v^m1it^@HI!9vWO)(BRp4HrtRj@}FrXd>Y`^Fd6AT<5-SK5E%HAB(ykH){;<& z7wC*_6=c0~^GX{aXBt6xe$2*z(;E_8k!T>+3lhAz7w9KlYK#GsbKBEcEfjb~8{$!b z#MK@J&dqDYroXL5+H?z$@{L9%8fj-gjCVGROSYv=QDsB19bIxrc1KA{J8O`ZP~nyw z5^v_zL18niqQ7&!v|CtQbK80pr!n5&D+JOW?zvVBecAm}cO2_OL|w|AHk`VPZn@y8 zHUXv!4gpNzKxtQJ`cZSc`e;Fe+3~crt4CyabyD80mKNkdd(`w|=r2MFG&c76#Kt~l zWB85LzOk`QHcY&+i{b|2C8gEWMv(KfsEdKE%3T{~$ee#xQjQNtzf`VgJw^{C&9^iE^>8l_R(6++n{qH$d>deGU{EjEpyAsN@<6|u z$ILotYm37c9ojyh?6+`EQ7OWx#S;OpRV>v<2+BUkPRu)X6{rUno@`ur?bosh=JhL= z&*})ndb$fgNWlUzl%d+3K1;T+;yxfe^U#-@@jVdiH2 z+#;U*m%<$9QRzbEWA^C%Y(T?Tl4wXSko>a|l~VVOWMM`IVp`DGt=}^Ya?a1%Vl~(^ zp+j3lR?NFFZVV9!CtLtUT>86PmvCfuY_PI2(;$Y1v0Dx}`Z|v2K%<1S0=YcSEp~$-pI1W} z`@4r`W4K2B)t`T>YopUs5*9ds^73ULe7$qPlhre*rMfXQGzm06va{D9Msn-6HAhBC!BTUmWP^^)k^#?%BXF zkwx+t=BmyZ<``C=Wth!B0iR-q`Q+vq=6yMaIX}xVKL`x-3>fCFI%?^z9B48dNcq!n zh%KL;A&22LgSqdrLM~SJa>2piu;D8LnSl?uOh33S8=bAg-_6Yil|w@5$+N^?^>jP^ zgRhN#(5XF3ueQJB=lkjMTHh;V_yM0&CYXnjYi z7%ntw+`~LXBtQYq7mPGjxk-svB6+-eaZlluowX|yWL$?BEL;TCb9|+Hy4zRd8ul4C z=V$7o(ml1OQf+&+h-WYb6h;6nJr4Xg>jxO1gAUTSMR=M`6tw?Hi__u2ecjypHkSEf z3O)F7?hfMp%iKy;3+d}dqz3V5CmqXUO}jMrYK}48aKirRURF1~-IQ5kt8{CB(`_xu zozJLOSoDj-8z|sDguiFfQ(yNx>Qq*fK=T`V`Gg;1EN}kZ?V&M#S`+=oJ!*RKn@(%c z?@)w38u~bQ3zIB!6NWeN`#QN0xQofnRp#F1$$oCWJ^871zn>dYEjz#asW$T+Dr_9< zK1dP7|L<<=7E8VK622l5PLD%`*({E zO0$i|;MYD2%nzUw4$4332fO&oMp4hJsffjHw9O*dL|=E;;^Eb1N}k<~E4`2*LSCs`MO+ga6Rv`H27-D^`&V}j&SLI^_I4Z7>$$)}WA#}bRg$Xgpr~>s zkFCmhdDKT~Q8I49!Gc{Mcl}`H2=f^1uM0&nSkzla9RYhQ2fNl!%f-%}mfz9ZR&^-c zkYGgHX$^z<;~e8QAH!|>yZJ(ExD#MJyA?H*or!AWNnFxkQoS9btkCJs zr@<$hO{aEFnS0?h;n~@SPNi<-&l<#W>=-k(Zthh`d7z)q{s-X32;qiNPh?ppAl$(J z*FfiKodHemoM=o+7WuCxu^Y znk;J_Zl>dmTXl$z4OtJSy<3uLWn+80euL0B|DGyK;Ws<}{vlWM_$ie|T)zQoNo~gD zZ`Jm?`;zGNE zPzJ4OJYm4CFap%6Z!J+-ITnhb#{O>aX3e&O*(_`6)8rPG<~@;YI9L)2lMPFim6vBY zGY}3gJ|&Nv*eiE}F|M+-B^s8gAK{!?l%;=a>4v{jhm#@AbH2GhLSUynBw{>ic@-Y; z2kW5}8<{Srta*-pVKu!j;;$c=u&_59mq<5^(@xUgo6oRPJ#rNQLgOmwl-q9UJXhL6 zY}ybq?dfoSg~vLZI+5!>PQrV&-CL;2oY`bq`6e{bQ4H0g(bxQk6-@|(xh@{*w2Pbb zy9i^4({{a(F1{M+cscjrhvCG{8|7)wKmr+g7I8%n%Bs8kS9vGy1~rku;2eQ&J2`SY zYl*U+R=F#a!-SNRPwIm`vVDe`A4W`1JIM6p%VdgZ@ep4tR#;UhTX6Xx=;@?WxnX78 zTng_V-Bf}efzKL7ATOQKt~N?uw@JsPe5KqFs+g2{JGlH@3XR_ zOy-}EYC}rHvTQc57e7Kex0cmZ*icLPjURz?A46;`QBjJ9R4WxEtdh@4B=uY+9|%$F zNWSKwj`9SY+zNJyG@ih90QF>wgNc&A8i6;hvPxra}@`2#9f4S`&rIKL@ zdY>79A(sx^ho@q@_IuS9jZZb8I5B(CeP^P%7rp%fj*(v2D|K_n)HnO!Kc8+j&O}I? zhc96OqrRo?y1Zue?n3c0NQFWv0sDtKkBM?w3(PUdI52M?gBmk5<+4`4X9U(QURff~ z?>?Es0SCh^&~V4d4Kt*cn5^NwRO{_y=YeTn{7%$!h_*GscDpF*_U-M|&$27(yM0O8 zH2#Y!PUdP&#&UWhOF1S)?~kqdzVi&;WZH|G21C5@_>cp><1Cs3l5~|MJ{CF}dMu8T zagU7+Eo2vj0^J{4tN{t7y>;UR0tqpdlmci3`+4@){3jXLL>qQ#qcYHP#w0NI%Z85I zUsB-Ny?P7Z<@e(MLbbVZxS9XoQ^mD-K>6dJSZxuP$m)OlcOey2W z)n^7}26P)#!9Tml|4`Zmqf%Q*H^LaHPY~_YxJpD}!_qvWpn?7aslr`_Q~}C#(-K3s z|G-&{E|^6tDh;&}0!q~-+OMru(|t-c&dVo)Pu-Vfaq+%vanlPS$D{aZfv zw8JOE%f%dQzF7{z)TXoi>5gtc;3@`Gd0_Wy z{!mQfIta~pAFZITaqs8HzVegYyP<(Xm`i375karBme@ix?WXZHjjU%Awf(dOU|?pb zoZ`Ni(qSx*gWXv+(Sl-Pz>lbqb0kCM0s=mf(|s~uMAQ@eQ92P2K=CFc1#v(?K?S54 z={k$}NN2Ok8OM*y9_2y;aI;<|=?qCZzJFRoUw%bL;C4|kl@|;YJgZ}>+{camFj<_+ zJOwC}@|giHY5Ra6K2HQ@*@{t}0=!uDw*MIbkC|K__vQ!r06)$(N{lXZFF#YlNs5n& z6>#AXu=9i6#XeEyDrCQdM3u1DP%DZY1S%P2_k|CYH|L8wI=a?FOLTU8YSn_1!s(UL zfUAEORV!UTE;nxGxBv}bb`Rrh?yOMDuiaVctt#erC9>m0_0`Yq2y`Xd=!}2Lfh~N+&TTzVD1(NcH}m|M|My|WSqq$Wh>SV28Y|1 zeOz8ZuIHI4J5;IDp}jrQ4I_DIAoOF7eXbjg(zT%?d?`BDj_C@ZZ0LJ4axSUMI{ZW+7`^Iw{k1jEt38bU71MF^G2v$D#aW+2R`*OG5*6bBgM)@c_oDh$)4q2dZ zlm_1*9;IKgL2lX1AU7rld7{W5)AI+Jv{kWDE`74|r7RegSjtT>n!=^r?i<8Qxxb{? zD2o?%KFXxgiBaD8p#3PLe1mwDaYeV~fhRg2WyTqaQJ&w}ew2y6K|IRpq7ZxTkyfmE7jDE_A*6Hj>uRzmP%+)+Q&{a^SCC2flb?qncl$z$UkF~?`-1u+5+2!#^ zO`ubG9p#Vz$(!xRU!NEs?FHeeQX}cNCiiQxFE{Vl)Pz01142JiAs?DskF6c@U1kLV zzpkOa&{bH@GyvchCSb$^pwU~E>CmKoNI2D^Rtui(x5lj-J8d2MzAbJ&zALTg#jVfn zO6&P?>vOu&`u4c>xV+Y+y>q&+8O=oOBUUN+2Hz2XFgEXlVqi(RyJ_4!V9-zx>y|e| zdJL%V-3jVzdnPSD`_Z@vvR&@p3jE^Sm|qmD&-Dw!Ma3pm9wek_3QFq9Pvy*9Aj0{K zpJ&&Sb1tJ6DyhlVlG6Q{S4E0wN_TlXw_?pRE}}VCMKpzCv2E+94s2UTTN%y0IxVI- z-!z?rqFza5HHiw7%1+B>6!oo+zW(>o{@J9WUzZ(%kge&>+A~io&QJ0@rcCH6OC!vt zRiF>r(f;X&^ebfxtAy-qzy%}fgHJB{OC@y?J?Q2x6pIOtWzCBPT|NGs9CPi!azEBk zNLtri%__{(Fcl58M?lz(7~aSk{`wGnG#k2ATPg^*b`#}gaMx3+wveZd+mcV)rqyDn zzZn!1al)TL3v>^^NwFF!gz={zz?bnKezEMlz(dO_w>bb(o(*`7@d&#yAnfSPAng0a z5qA7$5VixWiV#-o{O^gdho;@^1j3%(5yGxWAS^5GXE)*1Pa2`P_!=)*u6!~GmK_j^ zDc2Mw6mQsed3$&z&O%QARNHRaAfy}rR$cyp7% z6(bYhjsE2N6ZQcof4{=V#a!q)mZ>>-yauts4*I0`rLV2Q4Ly%r8uF^%MTYUKdX66P-*E(lF&Zrug&Z6cxbe3FnD!(7iAk(+C&Tk%9m1M~Qw_V86^;*6nxyfG+_Atp z2HLqLfJwr{E-1CW#7|$BQa4}mnMq7yD6@Q3L(;{>&cMgi*5*%*sZ_eh>{h3o`CH=- zz;%wNz1$NY4zH7$U)sO$Jo>sUubF|-0DnTx@@p`ExJnXZGJQVn?#}yUc%yuTnBN;b zGXMy37uw1vBv&p{Z>Q9fd%SykjNGm1lIr$7e~J104>r-e{X}g_1QzJx z+3TP1M|hcJ+44&)OZSnSH59KW$(B{_9kfo+B%9!G)9&;Jn_z`I{gdHCW!D|%pGCER z*Y#(@RjF|JZ?{QyB;5;NSll@J(?$?1xd2?~<7UtGNc_}-PLLS+^y<0nmgG|(eN1fM z9nTsvnb;U1HnI$0e^5X!)WfnJ0x_H=GKn>;k?9=dCO4p*NQ5&l@r(Dq zHiGjmoE~NjXyaAR>2#I4!!W?bVU@N8pV-~p5*!PFygpqwb8c3q7}-N=kxJL#v=J_exvP>rFhjPP5z zCG{Q_?J|PDsCv&|+oT6;lj@{Q8vhQ~EKl1S$t2+3IvZyoa#&!z4`?*)qXd=F^en0MSBe8KQ*MgB?am#`cZB3@D4A#E(Ek25%Zco0Rk?=bM1|fJZmiB1JooolqSz-A z`05(P%uAK0N3!=hr(_20IpllB-nMdI%1A2TYE=-;3&KCj+z~-g|CRf)7_c~;o0mcp z99ZIGU&#Fd_bH~l7y%QK|1Yr+a?l%}qd%7J5VQM)VR~EOU6_ff%pAdchaCCd&x6mVkNG3UILsP zM5}i3wt^p`+T2*_5JWi8QYp!bDIJ`yP2X-G}L zockX!%(?w0k2&`~(g~4=)y}^O6p$2<%#fkIf zWAcdi5_}+>{J&SA-OsR-MR;>7%0)_15g$mh@f(`IGMb0DE!2VS>OR;x!t%-00vaIl|6X)Um z|0q@L{tc>~p@2*sD7g?r9X=MVjjzM$%pUq3y*D5M$A{zJ=tdGIO?1%7+>~QTRl1K) zBUXb~=679+A=dN!mJ>3KL-taT=fXu$t4g;-7yaJuYTfhwWtAtotX?HWK>N$;VNeC# z`Q=fXB_KEAiueT*kTMhqP!E~Sy+~cg#RiD#>R^;Z6o?fqCXhCKeLj<2l~?zhUeT& z*Cy=cmTQwF1gI9Zo1%wE0@r#jePOJkG4qNpRk8V-y`oXUUR}|CuSAl>`#u#(3Y(+b z&u7}4r;BXP#YyOh39>n@+0EJ1_W5qks>02=C^>xCoM*!D1MLXzJOF7`qpU;5?Z4}-NhDyzv{G*i298Y_z7ndn3(wP&cd>s6yN{e zi|;1Ii$1vVe+kzk5;Av3d?!Mstz@35%g!Qn&d@7Q6)rN@*Icjnb>q!%lS#=xyFm^R z$Pbnd8&d|^h0U&!v)gQCb{kEHt0hEq9lo$$o%FP_|CGDt8@-6T=+VF%i(QToacAEM zK=MUg#;$ayzn>>AGQ=liID|pU3S#XFlZk>9cB%M#o)jh)QN@O+CK>~ZsBP3ODLnOJd zNCDQ)5%sGQ*tikBgU3eydJMV=d(Dn*;<^-w!LkR87+g8e6N6_T=$sf_F|Qpl$i-HM z`|ihY=Me^I?TB+Z`1$w9<-SpTkDL~_h%dS(1Z6L}uieiq?V>wzzGtCp?++8r)1GnB zrNQPdy63c;;M?)=Og2!iH{Y^V#1m{BAC?f`aPuel;eGK0N8RqP92@UzKS8@Y(ja+v zL}YpGH9n5*FRQ)%k9Hd@iL^CbJ8t??-klKS}xqg{$ZK zam*MT0X5#!?6!3u&9BD=DDA#HRGW`j^0c1A3Br`0EIMUwNi^`cq^!y4zQmLh_L$zp zK4vHTZ8uMI?d=|Xtpt}!=5Bv`g_*z0wHD61!rda5CTS$Q?XKw;Q%Syfd}hFeuMQbR z_yViBFZfX9+3ZD?*~>e1WTfAvT}4x{BPuJ;ePn~$3wyw`q~#evna#jwCQ1h%i0?eJ zvV7jex490*G0`sn*(y4S&dXBK{T$%@*%;NhZQ24&cC5wL`Ug+sMmRLs+aahe^)1Me)L32RlgwA@{Im!I;>cejVBX-;TRKog!>lbdqK zG~vn%`L4HHwkFU7`#VV!UNg0AV%{Xl6s~ke6WF3s*zFD=OPPD)*xIjPpqz}q-wx>- z%wYTnM|Q6qtJv|2DwJ4j?Xflc^T)&rnbh4`_m<#-^q+ks(WIOydi4udk<*$_s`qMh z&&9cRy=X=J2@wxBh3C5bG7e%=7 zta>8|#^)0oiMo+$MeN75xJ`H$ujAeKvX-N>x5-(KUN-I17q`3((mnr>{*i@$q#uS$ z^N$b9`?YJ?#>>KU{v2fCLP2dtno!aVC8I;sp+ymN5_LEL9_25N&%^T!KuQz{zrGx{ z7`yDno;WCwMiLvz>qAXTTL$Jz_cTE%5kTEK^vP*=R7#3dxZQ_xTIZY5iw*hbm<6;f zeWHmAE4+@@Cyy zJyJu15ze(ip!{a29bt~riT88YJwilRN5F52fsZuzfrSfb8~PPO-&+a03jGG0bPW7Z zw<~1~SDy#AD8K#>Fk2tUU;RU* zvi;n7O@rmhAPf@he7pod6~$xsJTlt(es(i1#CZ(+HgWeX!_8*fArdwr(Z&nTnn7Fb zhV(*D7{uRFC3HPi41m{{*l)fmiu=E5Ddl>J zRqlK{-XdbZ;z>_@nSN_OW8)@*@;)2=qL2oEX|e(DjdCFytV>D(5VZU zQ6PEi1IarlpX4266M41>$-6X3^4um`WQj-4nJ_xuT_3a{(;sU`Gw7R1Sh-7%Yal&` zx`$=-FLMk2nyDBvWXLzij`4)=-`v_jeqMVbOZf7c-$NyyKAj_7zo(4EG%ngTF1$n? zFmh0Fl7MwCSIjqY%sQJV-v%%#c3^M)RF)UFe!T+xEgmvcjRJr@d5Lc|Z};lP;jPek z3fm}4*+M}hBKwB)fSIF}ZefnyI*qmw+b!*STY|W4Ih;|WZn~0bmbnW~Ym!p+byKRI ze_Cw-(D80; zy|p`kSvK{|K*O+)PtcB-8yYC_5x*#(`>491!Q;t4!G-qDKU?wWQg?5!RQkvE?c;ye z2#m~^*Y`>dO&>((lnz+vOaAfEYtVMK#J$u_Y}vM~+?^qXE1%p(Y6`AR(Lc6CeHx+z zSmZzQ*8mooa|4^1425dSF$ZvD;(K(HMG-@Lwz=5NT31~Qu-n@c=NM2v`+8P_(W_+;TYXWJ@ny!<42H?#>d%N11I@YQtU zqAR}OMk_afbERPHpS~0pscgVi~MoW{xJ;oxD;%1Nw;fWf97wkDh=%)tkYd%W#@y-F!2} zuqWe|cI%>W+M-dBJKm7o;jdNAf3a)Tv)v1>RWtsgYt>RTRpgfVOU-`#vADYq=*+*= z@cT2o=;Q8%8p%}+EUk$SfHJj^Gpia@Ekx5>&8iT#$gs3&C?Z-O;#azHvLtlJ5lE!} zfCjk<#NFkKM9Z>18JOCrf6!=MHp)w{%zc1ih|M<&GA`rk?jw(6DF~ePvREQ*FY7Dz z0%jH~W#PzU>uWrj|FgR?kojw4DN}cx`*!vIlOO4}zPaOiS2CtBKCby-z_PY{DR78l zA+>^vxfD_6ka!~tMQ;dFQ`+*E$dIPeq~-2`+Zeo`T#99OOkO3bTn~A1P=hwyC`fC= zr>9?D58#e>?>c2_Kl{{%!}#MpYNF{66Q!SARMHw)6?i&s>zE&Zwkt?{1EB~AlWOPXpdDgk->S_u<6 zM19<3DPp^X{7jMvGQ&cBFr2n0Bh4U^tTsM%VOAjV-$T6UXNQ`jp`i=Mmbd8&P{`@Wst*r-~r8&YjEzWj^v)P3my#d>>teX z!{qFnN80SypJKB=H`44koI)*_liU?}!<4yaB@&+GW_BACE_U~C8jeWK8N#CmI`^5S ze8#v?nC1`d>M~pE+xHukDqNeKm^#0jf#CgAb6(f7RmHAl@VV2l#RE0T-lT*yMt3+c zI?C`v@|cednVe*E@uA98GdBp$ouziF?m4Lj&UdJL%3w8DfIHMJv_Gx~aPGaQbl4hN zN#6L0Bpqm&KzO9vXj1hVr`5U(pDt-I!XMH!As@O8GUjxN9IZ-fkdx%7(w!rRN~%xQ z83#VX9QA5gr*~46Qo^ruewP2jl2~VVcgvZ$g9}$*J+X$Js6NW`%;U+H#$!PIQdaUe zKaFPjW+QaKDD=t?EcgwbB~7$B=wdu+x$oVA0$<%mrpR8(?)0h+@MfM&xI&p*r~8{N=jmRy zoDn*TCUayd)_0?7ca3BGa`y_%ID75$M|fdx-t=^5+^ZwZN-|E_3cG$8In=!>)?DUh z|G9a{H#uC3dTE4Nf37`q&mlv&R^IAr1@=cz71eeLIj4_XfSI{VC;i$aPmlNd|5NuK z@KqMs|3CK*&%+HQ1d@P|wP0@$u(J|$SJxKQUCX)wbyrsb-L(NXfGEX)brk~^u!Sa8 zu&p(yU=O-B)ZkjM#jdMjcP+p7=gf0&ZbF`ruYURc|36-u`#kf^oH=vm%sFSy%$&)L z^lR1f0{7x5JSaWfoNiJQYvrEXa}`nsV#Gc3yBWaOPL@K>H+`H#Qm8%JeNUaf+do~c zL-|rJS#t*FTG~DHeetLIE+Z!2z5fi6p{#QrfMl{I4|eZqGeCix8d2{%quv>#M& zD{4|9%=}q(G+lE}7vt$4)8gsTZk6ZhuOCxqO6+~4HL(J>>?Gee_jOm_+<%hc&XF^5 zESNDzsn;B(z&$(Oe|k5=?ia)Ehdnm4ppe6KnkZwTqY!K>amwAYaFRR^wk1*r zJpE?sxp?8T6ISxF7o;(onLVI&az8VB@f4exEiP;!7gwC3nb}Q+5}nVVVhdi^7itG) zo?E(lQls2eNcGx@sC1I#S!mQ`u@)T`?YzBb6_uC_bu+7?{)QN4rlt+h~3t(b~9fDF~f89;l_WU#Ra7#?+GOGCShY zw~a?HJ!wQntJyKAS~}q}+zD{+m=XQNu@4bZuy@YN*GSe#9dip#mjmll!02i)iOS_x*DnuzvqF7GVH%yZ9vt#EQ~#n}pT=N=ntxU#X}jLGU^d?%=! zL_f<4cIBR>PEZ4QKLPt-tW1-`-8cUA{IRv=R}G#{ zx4dcHGB?{Te{ol80iwJ624SHPxrq2pe1{q{Tq5tbNyXcjNHdLUze$C`&16CtATAGix{1&)dX-PJKX@xf$ zA{C(JqRrgRXE6Og!PQJ|l=VP7gwHiS_`eXJ6u%wSDL$!>@`%-cz6Hm(D33BbT95LG z?PT&|-nVoCBM0sUP88))Jah|79MRag2QI0_>GO1<3ghF+^BFK3*KYhr8iD)FgkxAdwDG4{zmqLv1Iss2kD8|u9;k3Q_I2L zD-1;AY4sy`xw50i)mx{H*sTF7(8lPPgAP7KZLIS{>G84lez^O@&sQ!z*-rvyN%24u zJgJ`f+<*KkAHa@w+F(RAGso9*nJ&}W(;Are(}z!e*`eY8W!9^5^_NUG8^z@9*^-gx z;?JvcKWR3|t)pY4_{X}BjTtU6*5D-UjQ@6kIgqSP!GuS`KN5lyZbyMhb5aXME$)E~o;xB+J)V zX%bGrlfxGz(>19HhX+_Jg&7WcV!n^2kF1~ z1P*ORdPCs3v%nk##=6CtUa&~5p0iJHGh@}KdofwQp2vaNm@uokF;;c6(hgCWRh1*m zYM~pD;sOF9rTtnbTFw2|b}W&y@?ihaJ-K%x_&u!B6jPPWzD?Ie`9tWhzNG19c9$;Z z<-CP7!>=Y~HpbuYGs${lRYKocPuYlEI;UQu^WQuvUNYy@ap2E+PcVz+HdT~{!NE4# z*M1CVa%WLA3LQyJgl?2)73J+Wx{&lMLf?mpI`)>7DIP3g?zG4-!%v=Bs-09lT?S@k zJ3q3D*dWa(JaTP-#|^hekveLh7A|cCd?ELZncP=3%N-vUaZ#qgmCXvYj8G6EvpAFc zil*F}>om)bSD>1$=uzCon=(Z%Zz|HV1brm`0r=mX$$eRyxg&IL$>g5hEO&fsZ_N~# z)t&+gcRTqTD$3|McmHUc)P38RuI%p4<}PX+C13aTC$rZ)eO9R{%~|APM#G+>CGwm2 z9qKR}PFyh!I*E9ty29FBd5DD>elr$cd2lSYDey)bycvR5!q_Z!v;J*-Zxe!)d*>P$ z6W_MqYY=w__p>jnjAE(6wz5`1WZ~5jqdk-RG1~ue4IlYOg&dOi-}qD7nJc+(dd0K#8WVmUzu%bEe?jJO ztoG9T1HgvF^DU8}H?AV9jY1Ko#I0zVg%$5Pf~I53{Il&wECSH>o3@LO$;>{~`>a$H zlljqHuo8-Zz0qgL2%EP$E@}?{vA%7>zxsM%6~TY4!TP2tDiZK#`V1NPFS{1--`lE9 z_){0>z@PHmn(#jZp5&Z_CHk#uk;x|c(_Uwul8Kr39fFd5J4YF-euJ!(FK|uPFPDHk z^QZ*(oM*PvMXb8`U#gmg45*fJ&-{~0*UGBzK4s`OW7P{Y!}y)tj}fcZ@R5JU0$=*? z%~-XX?`R$dNNOXhUnwm_=9K&4sfa(P-kQUo4@Z(Bjz6af+?xFPLCc!q&$G#z!=LZv zW(o3AM`>!kT46vT57{O8b0UB$h8H0~Ekia~sNVell;t2Th3#T(ZEIR%Til?gZE>bn zAK%-nRqj$@O}l208(p^Dpn<^%w~6fRV=H-DUlY2cE2m2~*A^<&N{PF=ne1#P`kMs# zLXfxI3)Y_7T_eI^9Ce{r2w#{R>t;?(*T;5U&|>xc8r%Lqc3yo%qio*vKiJI@}o8p$H#Z(@-kfk86p{->aL zrB)>UChkb)lE0XPz_eZ+o98}3vf7`&=+27M=zt3R#&6Bh>UkgrI>Yo z8=4DE_;REPo5u#6Z4ln`y6@69AP~CjT_7AqQ#=H^ITGJuG9Ka2^Ix8{x+zGw4weuk zTz|zkoqV46MVvkL3?y#DvlE6FgGRSGwB^G?Ea1w_2$P)CnT^2#P#+ZjU??o1WF*rb zQ`jX#9P))&RV|h68inTXLuFTB-6TZWfz#)fSHo}QK<9rD?Vm8 z`@&rPBSQ#oc+dAai^OjS#hmpesxy0F!qn#`Y$e=gdF9)~K>;z8U!qxMuu9hSwoCbL zs(X~w93LU*td{k%@#Djs?`LMe8{4OfWB`)qBcDerF_C}SnpvIAj?hpu$odIc$<--%TZMWnuz$>Q^*>yntxbJ ztfb%650xw_YmrD=)TSRCUtyBNJ&&kTWnx44Bam|=?VQ3e`qpt@Eh)??O574w##B9K zP1KTK*^b}3;9%q#$0RF*KMFxS0(jhSJ~eS6A@Wv)GSP&yR9(-CUIFB_0N1sw7Y(pH=liwU@69#9 z<33MI4RCcfdy@uulB_Vv+O3v(Eeq3Y&!`^L0Ou=Ocdpfvjbfgw1U}PNz^u{YmB5@< z;I8m+TUP?}eedTefmg%<&6U8^92TLo{+r3sLJ35}s%8rft51j8u$sO_{IEJ0GjFIr zN9l(ZZq_LZP94Py$R1ym^78>}>sj9YLFb{mxv9jhRzyYrE;?jP!i!#zVry;^uDZd9 zE6YvtyqBAAUe;9!_L7)vCM>Cekhc~_tUxwnb9&*d=@P;@%CMCJYf64xzPTFu&M<4} z?9JmFdH{zChh>JI6rL%&XP#}+zlciB_6CG*@lE1b-I*N)F2CS;YmFVq!bAPRjW&!r zxl5nV1}=Y}H0;|jp}^&P+912cmuhkymADtlr3mFE1TI(H@*`#ItD`d^%OCa#878G} zi4d`n<*Ab9XB8?qtl(pof9oAch8s@F?>%mu7JEK>SV3vQaS39SY)HGZG0T@3er>t1 zA@Dgcn#ue=?uSR=3&P=gK+L+ZFtsUxM;^pq%N<+jZhTasNu*3+(wgE zJhn}O2LW)2$vbuE`s755EG1Zoj)is#xx;&HvA6rP7=?-=G7HAWoM4lt0He8~w=a64 zdFbtrZl7F>JptQo=_TUwmWXwAw}O}Pm7=@}J*+g9z*8(Sc`zp+6<+~k>#%BXJ&g1W z%K7xFntLvw!Fg`Vs!6E|?-qc$Hb!f()Nv7W7(K=R3G6~{#`#3cGbq?r`Q4e?j%`n$ zPSjOfi9z}^(8G0?Y6Z@|el}6(S`!!Q&js=pU0#SoLhhn#nmjmkN=tWk`3M}S zU1(NNsU2v=tPxDs(C#`g5&Tw<{<1H$0Y*^c#G0&4#ny{Cwm$jR#M%q2R7W>A*+3D+ zw4+m>OJ%}Xy}PMI%4O`cL?OJrX}n0mB$<6gYbMFd24Ue5ep1>71WihT(6&kP^oq5c zB-hBL99?skb)>8W4L>P8!cR&gOj?>G*MY(sCdqlvm}E3T)Y*N0Gw|1Hl03X35|f#A z416WGftfMhL%AO_lTtorOp+D;dy`~9_$*Yj+B8XCT9KKQF3vGY=GkD5H%YD)+{~o3 zWxbk|=6tWues6A)T<`Ok^v=0O;gM|iCX-|lS>edFng}Tl4Y&Hz172Q-6VO)#(j1YNLMVm1vHwQB;NDvtyXfpl*!S$NpkBZ8dgtpjzx{y zBz{<7l00=}3zKA?f(5i~lDwjj0o~lygsw4@#NKmFlG{zSHaAJ`lY%AK^Z$xT!T@m( zZ>(0{%MJ-z`QXO!t;8N#^5@LB%i1H~J!zxPOu;65Wa@2TnQM>SWrNcn5XT-_#^_{> zb#lv|$=V}JNz2+J{vws7zErL~aud0jPVQ(1NxjT4yGbS2BKeO;$pk@HccD-zy*DU2 zf?c5#6nXeKAAh1CyvQHp%Gf0fa&W{hS>bUkayNmahCiDNm6l_d(1c?5NDc+amGACW zja|a!icn}iTT{aY;lk+Xp1=E~OZa<}GM^jcMoX!Yl$i=++Q-$oAGOYkd^#`l@xT6K zll<8X<$$hMh9FPRa%|_SY{66#0btZ?mL*8(2SnG@t&wy1eBc#l7e?x==vr*B=_(=v zL=-rxQl5w#Y=vgAuSph3WOCh+z^b`h$!z~-n^mXqo+cC1Z8XA&1~rX{o6O);Sg!fh z+RY_+tM6C5q+<8r-IEoa+TBNBiD-G!t}#)%zsBVG=+3)GThfxjaHHth%#0%Z40uLn zRFnTjCVt?ymd|7Us9J^VVAT_)uMnBf7acBYqck8SzC~g7kk3uIDt}u z`(b>JJ#nNv%Z{mkKOTDm`{BE;4SvO)wf4727^=oKt?@+bmhc>FJoi9~MUfG5{&*R9 z7$Mfe*KjFB7SpR+t%DY_`lVJeVZ+U4VOpcmOV+^Js+!duNU_-XC#elvZqas`<&sz~T4e%d9H!cV!RB&RHwRCC6LHiX z9Ooey)B8vUyVCk%6Ck^AWVbrl5zpx^FpiIaVz9qzIq)}Q3L`1s#f$Gvh6Fv&KnQ>Z$2WEyS1;P6GS^OQafOoAjrD9<&4`dZ2R(SWdF&< zhW1|*mS;OX;(;dmMl|LK2y4lMTvZus@59}LHfeZdV(o>@8sthvbTF>{9)5ooEz<`P zr?59k&YpI3MC3U09q|KR{iq`zz=0G2gBx9#R^B$!h*+!nB6GdthSCpfXnlvmWXGWfkA0iffK&8rQQEcz`vqAHu!c zf@!I)pIZhkRtJ5L>qnktESlQh5 zf}_J9n))!u^D-Pm0e1l;C~{vt=RGfn`!ubV5;pC>n^kfS-g=;;YdpkDeaZTc5&#cO zEO#7`7#NInD~!~4KB*&$&R{00iz`o!hz*=+~AMUx`WZt^g4 zA{@E?6Y)ISQ`)cdMWtb&>R?llNAB#iHVNI&^8GsKtKZ%9hsNl~&1vSuFnI1gH9z`V z>FaQBB$11j#(_fpUf{YmL}PRuyK2ROFR#)0#*a2eH3Y!ibN`L7BrsZV|6U}a?f2CW zJi^}d@fq&_i@U*U__u1P!4P_FDq(VkMoD%sv^tW9yPvEN z&#_UED_F3|v=Q5V#^j(IVzDUncW4E!u5V3h1gkU~YnsSD+NjL9^RyeD97(#$e ztEvgMb<-?T1#Y}S9Pv2UTK%0`twFyG2J=H6{5@+uZhdy2F*&oOE)8zV_-bRaB`>iL z4Vka`h3D||SaKFVZOZq4uCgZRJ2covA*)$l6e33wp+GO+sev_>t}84vg8E0g3k|_< zK(HoahqImN)G-yYL%w@$Th=l&0?tz+`?a5Yk%(*CxX#*Zuc{2D)%DHkmB2s8$@2O7 zba2Yy$k!_qjmS24e^_1iDBph=C2XEfxQn`$XSieL#76a7ybx;69fOrQVga&XkA)pp5n#~bO0JBT23UqM5&xo=i6T#_^OT@S-d2GDSw!76fdpP6Jq z+|Ug^nNf2*?&~hDmi65>2Gg0%TsS#{iE;R_b_BFlw%N9XoU(}jc`{b;;nZdav3F)= z2Jv;apIKfL++S=Yukm585++ci0XmKPe|{gF-bx>cGkhPw9Z?^MLoDr$(|sT4MIs5S zyV#xGHJ3$RO1LXwk$s>X~oJ3Sgn*BjfdvN7Dx%^^}%R^0iacD?cXDic8(iy0xX zY`lcP39bPy=TzIcHH5&SI;1X>|?EMdF5JGBP+eJCeo8u&QQOZIK{0R5LCN7HAB057~Uv61@^Vwx%6>4OIDQ6pc`kFKqLdAkKb z#BmpQ!8M6m7UeoMw$Y()XC0HiLw&)U7?Ov&{*9`5L87sx`^$CaxHv>zPl1~U3p!DU zM_VjUXnRugj(l|j9chZp^YBRbFC*9z2-bXFL)-7f49NECE_>3e)da&q_)hS#a5A0h z&Bs~TDUt8#f7Xo``EI0hf&JxZ>&EjjSkMBatsBqdl=e6`eSD>it!YTd9HcI+@pIN6 zUX51Q5NhaXsldQ}Mx=>4LTCI6Gvg3WjYMV=(!8ImIVjsWW9gA@zSa3Qb($aN-2kEf zGiM8M{F7UGj;|JnzxXH2w9I%K&9xEU3$b`*ZorIMe+;_u>ICu$ldZbeH|=Va2+SIV z)nK~?=7>!Tqo&GGlrcp;x5R|86V2dV;%m?mNgS28?rznYLG+Yy{T>B+y zOS+B)@b&qTefi|9 zOhaa=%qlZI=ADk4tEEWWozr(e*yn2hxw$gX=UNL#@y0k`+LTE~U|MNe4z4;~dw~S- zGK@Gs4wsH+)poSI!)5_1m<4c@V|778Wpy>(7oLQ_ga(wj4|6>jx`+gS%2{%xcHyjt zTp?ZYo4HH+vfVt`%5RDOmD2`ld?RJJD-KCjGXuE1Z@F+{PC(|1iRP1-$IaI-vsIkH zi=#D1xPnB@AZig=KiRBdR$s*6X!Z*}} z=V)selcUwvlIgpa`;Qxu9_niu6YET)HgVq-lph9=%hi%0?gQpbfxA>M9Dd(RNng`~ z?pH$d8WPJER=O&EyKr>*pz_MDG=5sw@*uaSW95EMyO-?q!ss)egXlBT z&<2C?>%12HN{j!SRMn4BH81y2cY%Afsxo)TkbXb-jd!H%-#4jwNY6= zXB*CPr%y+?7fjvVCi_4x6cNY|B%SAJK)OfeiA6tLO_({uVj%aH})u#!^S0n#I!o5|1SuO9C3 z3JPo=P6)blb849`cleEu@~6U%`z}jZw4!Ra85ZF#>~A|-2M_wY_4yF2$0I<71$j4w zyJcz`0=5a)6P3AJ=&s=hX}TMCD3=TkcI!t(=Z*Q%-^?9@c}Ma{UwZS6=QB-s-(8y# zXncSp@?G5<7EdST9<80E{n{smX0hO-d?Q+-Jb#YLwA{I1fE5y(z!L`O4)O~1!Fae|U!QXHCSXLsnLU;}mk zj9>%c*%8l?_Lv82ZLe^Q`NTk%Hlx4tD#LX6F15HmKw+!5wLQ&`H``};r?=I7Su z*p99yfO47#`Lza}Yfz$Pb_H>v(8nsoJcQ?=QQ?a%vV9QFGzCby z6`qn?SY1fruPAIEUu_e=sH(436)Vw11@7f0a4cz{RjTcS0f)Pb*gIG{3xPUbY_|lS z>`h9qyLp+(ODRK{o?(#Zh4*46iSIZO9&XF;s?7T~nTH)R4+Ely83R(j9jj-x948u_ zG-j6Orf~2Zrx~}o`6Nq*Srr-?Q%0I!~Jb}1eqodUeh5MttZ zcEx=`IF$mutsusA1fY9F+AXKzQ>zQMB+J%wg3YhuZ78-oZ-gsgIBd*gNhP=r6EFgH ziWso7S@rZI1L%ezn1)TC+CSL5nD$S#9*yo-!R+ZtjY$EtUpLnF5BSSi)Lz#$G1M2~ zTuIpom~CI=Hzv43h45S$6pmv;?C6pZD4oJT4-K4`5Z`$fLy8DkLPC^)fkfdBDq4e)#gEL^-(xq2ZpU(KShlkD^_f|M zanaDAdohPS1r=O0PQ@H>Nsv~3<1Ar_5}5P-jrvX`r5E>eD2up(inj1S1*X2--nC~A z>bGmz_Pg@`pnk&!iMDw4wEhV|#$idAlCHucGZDNXvO!XibIol`ByltzPM|<-#%!6N zEkbK`*-H)|m;whcDr%1#V?$2c$ zHLJ3<^2HCu2Hgg3YS>FK7AUnGpp;``JJozRh+SXCJm9_@|p(#vlsR4 z>+1t#!!H8a%UvswSa(!Y92`CdWZCuzbcGtglI&b9McC7wvmIFWG^*#_5)^M6Y}gMH z4i=fE`HDk!fG6DD*qAKA{A;^1lck$i2Za*OeiRf84vLxH+08e3;Q$*M-Nnl$&G|hp zx_}3r*o8aUp?E%iB|4~w1d|EsR83mse3N=Kkb9&N=4k~S65r3=4nfqT7y^|tsK+y3 zIZD43!CqV0FRe-LBojbml$ld?gnOLCN`Nn4%Z`n^47d;H`hT-e~i3YKWi67Y(InB9XLxfp`Xxp zC^<2#2_W6b<;AG%9hAX?sA<@Q;InVg8YTqCA~t&Rt=PR`8XVik>H49P^^jZSOu4Hy zmN?)Urpv>Wgc$}z2B@X6^rRu;df5@vbb!MO%bJM`c`aB&#>(zPy1(J*x+|kWBDRmB z3qPfqs}J}v)|mYcpUH3M1X^~gbr(4;$GKMtOzTFu7a!f--DF00ZtFh!s|NSd$@E{T zJAVtId=rBU{}MA*h*YC)eVm1j4c!Z;(|0<&0&7>&M>lW|wUfI}MY&V@rit*C4+m73 zhSS7X>TAS4zlF8UlBE86)}kNNb|tHFwI|74<7()V(-Uq14jDs43iU|iupKbRb|%6T z30*yv@n8~Sxwo587gYS2B!Yx3Q~Py9gmn98z9Y2ty5eH z%P;0DBL8p6j~AS~`#9d!;@j`|woi+1FlbOrxr{LEL%EHka+z-jQ0@=p)6!|nZ+r4> z@0f4D;oF`u-wx#4K|kYLhG?zfvJWsTVqosaH2Y&_V z@HK%NL3iQXt~uY3XS~f#Cd-S09u>h=NxsjOi3>O3|MIk6jaMOUySOr__+po3ie0K= zm$fXWxmFrXo0{i~U7k$tZne!)vCDn2S-!61Rz<-mQqyacqB379x3bw0hBa_;+RV`A z7+#qv1aj%%$|ejq0sgFHav#IvVtoXeX01;4FA7d2{q!|3nVn4TVdXASx!EnsF|b?q zc$QkeSZ)JEWZ?o$JTAF3$@YM#GMc)o*1+YO3@!_V%QY=P483#;g~qJWOP6F&nJJ(&qdBKh?gY{`t7*=@ZI{E%Ez9okHHuxDsqP|GM;mji zTbfJ`D+-D$f_wFGsXjKZ6bg9O$fdx~qg!TBGn8g0sO<{bxy@_4Dl#f&Hl`=t_RcW=aiOH5=vQt&CWd;*=f)@sxr&a|!x$)^>^V$B_g{hN% zW-VC!Y}8<33Hq`K6494;=$n1N(%#?CzR%^o5X_iEOr0bTw@y{*SbUO*!HKCb4Zp3$c)MO5qvH7tFUaG5z`oeV|T2JrhX8lbD zBOZtea$HwX{&7@k1gFUo7#D3&gG4+Df0SP&X zd=xYDHgE{VjCpf;xyPPP*eGmEN31ctuun&MRXP#$$c{20u0cmDcX%r9}@tVDal znOise{R#l+zNK089su_-Zv7y_%yrQ*_Njj6oin?TM}*jv@2H^Jn<7kIB24xx3htAv ziGlR>-8Pw76VmEtkQRAJH@5-l!#GGkW*{Z}Ha*>!LNCyx48Ik3Px6O?oO$ytQJeWJ zOq=t07Cc6yeywNP#!ttvjK4|S`q^~dwlc7TT70B|5w%xj*jpaF{jzD+4Xfg?{f8=J zhNOZVEbn7801wRfUtGcIQ9&=wn)>SBaRq9u0CS1f=(4OGbh+af(q$htPxg3D^Zpfw z?NvE+*{GlQWuBq%{g>AKm|1s z%PDwQT*2F7=yFF~f!o`n%a!e*%fEjiU0UOp>*BC|Acrok@yo)vf)B^gWkFnlN86&y zdF`Ofhrf_6`>ESCcg^YcOXIM8E{84$s-Py>IR!6@E7%Z2ml<&dUTljl-`ur!x%|J{Uung>eNQZi_DGw}US4uLHWwj>GoZwb12~xPs5e(B-1I0u61^<-0rAuBZRI z4(M`L9JX)e(B%;E%VEv=Wolf(cVg&rMqGjS+M>&Q?V!sA%YT`kZcV;?ac7KG@nsHO zT9dn<#TEP}hAyAP75J_#x-_(dE_2oaUEYkt_H0!a>FG-Gi=4DMcHL`n1<#8Lw$#(F z#uYf<3dHE?hucAyTh{?yo{7WuvK+enNpu<3oGwqs6}&QrE>FZ2sBMcbx3z;V53K{b z+#iSSjX88_ZGN;QuHa2Ebh#(4z%6ajWo|p@^1?cx%c3}J@5`Y}Yy5J3T)|~Abh$RJ zz=LhkWqLd4^6omI%jI#{KAl6C!!(ZM@y(Ghv*HS_h@s0RaRr`li!R^av35QE?K+^# zIdRy&kwce1iZ0q=ltY&@;|ey$&}C{|fp^-X%LnbC%Re6f-`CS$DHM3-G#3tfzoP~Z z`R6%wIaGA{Q**j}9#`a zEQ`bT`W(8n=6|^_uHd2=x-5w+a8p}!ncoh&Jhu+$a#I|(OLFMa+I;%PxPte`(B=BL z0?XQ>OHDiI^7cBQ%aw81KAA(8*2d9gaRr}=q06ke0xR00%a6COT~B|#4(M`T9Ja6J z(4{p;-`Q~m-;ANlnQ;Xg+oH=y?V!uKPyFxe>2Ge2(bJ#h(4{qf^krPZFJkEOd0c_7 z+M>%#?V!sQ>wqrr#9=#Cl|_2GHGX+3uHacw!IpaZjkp5mSb-QlUEdD6EM5n6c|H!? zOLFMan*Zh5xPr4|=<;-2fy>*X%bo3@%hGi~mj~mpy*7s~t?8qsaRqOPq04=71s1hM zm#f=BmuJ@jU2ciP_MRNNwC2ZL99Qt(7`ogTSK$7(=rXe%ba`tX(4{sG+b449(%Lw> zBCg<5F?6{suD~;G(Pc_I=|7G3Uc z2VL%42XuKj4%>w}bm88qK6Yd&$6xnAT*2#N=(04fzzuED<(hWT<>_@mm)qj7y(@<< zt@#;ljw@IfLzl&I1@3K&E*H0hE^quoy0o@Wb#5HC%X8?`nm)QJuHe67=yF9|fv4J{ zOLaTw^7%TT%k(&GU(TURYx|}C5m#_k3|-EREAV<-bounQwd?6KpZsNdx;1|J{v53I6|G(Ig9hnk4{23fke-i&bcu)L^6CuM6CT!6ZNYjh4%YnUu-Zebx;R)j zH;47K$7@AfcrA{Db#HT608t;l&=#z@aj=#*hxNRNMQ3J~qjb8VIX_$!2dkkuESO4o zJ=Yejv*KXA^*@L8?X59`>(l12+C#68;$Z#I99Dbi^;#UP^PV!U&+uw{@LCZEYgThu zFuZ90Y+JN{Bo5Zq&0)RbVZGKCth?i2-Rfa^8NrYiR&O+i)J)hcjstYB0V=go{icWW zb{lZ!$H95b;9!p%r1p&IOXEO2*PKp|d8{69j#cxqb8Z~0*Z=3RzPB@2QAo_(MbwX* z!vY~uouaFHjHRFYqae!tTAkPbp9?rXM z!1-4koU05@Z{vh^oW^=E4$ieX`1B=$LjPuzZq}x|TEMs_)QPp--P<~bbpSz*hzDSQ zkFvkNOHBxl_NhGm)t>fgmUfJ#?MvDSdm7R#-*8K-X!g~^Q$GK+Un@@sWYe1R9h^-& zDEp*(J(Q-jKV;K>pM5$o`?P2FX|L>)@N0=n)7QPTUz^G{r8VK#)Q;A$Zw+2+`S#D& zCaiofsH}ey?fsK57-iHQ+fj$JI4N|n^M+D^*MZ*@%D9JgIHmI zeH|w$-M*d7--2lKd}8?47Yc|2U9YC5?+cs$zeuE*cj;zDncyGKC*0OLlX`$X?ob&#nsE7bB>c8ckGod}hxqq9CfD)! zM2AXOq|XcN_0`Pl414_~^ZFC!{2`7z>3!yp?e(I}>&y1KF!Q?HUhm4hYHRZ$Zh7W) zp}oGGdA-P9KhC_KVXr@BUO$Q+sx~i1e7_%{UeAf zddps~%Dg^nuQz92m)h$Cnb*bk`dsGq3VVG!^Lnnmew}&!nlLYixO2m(qPOk!ip=YC z_PUr@Jntqv^E^Nb&r3=AEaAF{`R*i%=f_FrMcuZVNQ^LfO-`A?MeK1n>!BI$!D=@pWAzPeMTukLC8ek)lr zfFAUK?#}^qhX?dTPOj^Gt`|vqFM@pqNj$$z(pOQ^bdq>pP0}|J8K#oN^A99_A0>S= zu1?SAFkOUZHjqCeiRX(+dLx4M8c96QOGT)!@b5Q~r7_C#2uVCIAt}?EyGi1?o}}-h z>K2p4^K&Hq7$waoiRV=$AzM1DBW9Dt^Lr%i?K|)SQucPAldy|h$a8OZoW&vfA?1&p zpY4Stns}Gc&6G4e)(xyfqZXx#xZ*&6{qu45{P&#nzcr=U)A9OiPbW5gK^F+dDEsSS z_~%nB)UH$HnK#t&#iNF#0pI26E1qg4LWq- z1bCtY&;RXOz+aA(^TL1qPd+8xfAn$vj~zZXee%gCj2WKpx7~pLqfb6L-M?zg=>8`h z|JVK_k2$9Q_<=kBW#=9HjUImNaYv{7opAg~Rpa}U@A#9BIic#<;T(GJ9Gmobpec}lu zcGUOL$DcIPXE=JynBk+-{@JH*&x;2_VgI50uT{sNknVT>xqt?78y*&p)T& z{DfpvcrN0Xl_*qQ-cUj|l$hzM=o5YUlouXIEH{Os%ICTcLaLpjm=SJ6!mx8}KH-kn zwe8%hvWtGUw?wy%f4kUXH!I?%veKQz!YWZ%o;+ee8pIJqOyE;8yd_XXNyRVG<(LE& zSJda^uPw}J@_?X^ecU$ap^HG1kAFXl{gbCGf?#YGNA@GHl!B1gYdg zS>irp2JAuwgnHd&FA@lIqSzOG-8kLN6X;r=Kt<28TzzT7-;@i8U!LA5LJ_eVLS4jf zVR^8@romvsLn=takp!(E-f1|0s>Q%jl;s5Rjk_t*njVY$^f8piaBV@Tco-#aOd8Nt zdd=tm%MzYt2@C@4V9Wc0%`1W}D}v35^}lBN{8or=Tn z^dRyE1USt7CEu#(TOB!F9yb$_bpWAcqB!k|@J&K&ml(0~>h)3Myer+qH5wFI?13vW z2oJYNiHXGkTCJ?=qk~fYgWs2P=_|J>apOx6?gj*fzZ({8r$XtVCvTO!DsWAy;>=Z9 z@W!5cRCLu6b=_`iNM)ZgE~V(K{wJ(Sf|$AlUQg^A$-Evv!Z-^xf*&2dP_X`G8 zFhmp_mk4b1MR`zMuBgW_$xy4Jo2uB~D5AbAD=SmDma0B*S(nPnvha2)GA;ng-Gg4` zLC31%oBH9g zJ$W`!(D^Ehn$l-t83?=e8OKpi2OH1izL|-;xMI+ z^#SGUqKuZLKXkb-vRkIeFUWXPF2u3%03Tm_KD#)q9q=q)d*JyS4pNL{RZgetr;p*7 zbSFb@-jj@4ks}%Q3e(}xF=6WSroYL)#Z51{A5x#wtwhi68>YU{;K=|z8cxXpng|b7 zl|*l%H$Uw_SVuo@iJvjFig-MPG%ejH*kpXL`H-M=7Z`JhF&X2Api-N|6Nw>Fl%KJN zd!3+JtRVX{Os_4{{?sB(HFwVnjHu#LKyOqPl$t0kF};|r$=|S;QVLh=3-_&9#8_3EyuCPvItXhYIl=^tdx6Q+ACpR1^)3Xh6J^ zVPAo;A%xV^b4`>_&->fQsKkqz5^Ij2_A>I=TzIM0hosT2Jpfy9e10>IA4ObTD$C{g zig5XU;pgGieVkdqOuDU+<0WBO8Nq(fx3%!Jy0!l_yq2h>4Zy=7N+Ku zq=uw6Gs{XLr=NU&SVXc_Duxzk4mvY(aC&?P6#P#|qrRmeRlhH+t? ze|KDnU{^U{3)vS<1<1inO1JMim#(mM=khVol@i{ozg)awpNUzm;)FMo^m23^ml7>m zZn5?hW4ItZv)MC4aH_7D7_3=@;?((2f*VmdsR;iwEH@#Jg-mi$Y7vCzDdCPya03Bt zg1bYvQJLbxCwJ^AVs*tRbff7OY>0}o1`*9wCAbVk6Epf&)LLma_J-E|Td4boHtT+s zIW-(Q2xo`$UsHu)XI)uhud9N@A@;g(uyf0=X`rYG76 zX({gbl#~QW>O)eJ(?9uF>SRjX?Ve~#JQz9kbJ@-8_O1aJ94wh8?*mg0ZVyQ4LaII7 zIFTu@jM*AQI+X~;5Gdf%foK-PO$zzR%}W9zBkV6SR7QM_#Sg-{!mOp8(M#NGllF*x zgFlB$Fnc{0+I>PGlD~+MjHg!EJqnwaO`STniPkm=p<~?9BTS0wDg-}aJ3JQ%p%Tl0 zF$N|lZ`T@|zqgjxf?U&ej0A`f*tJ7bjk$Esjc@Oa@ZUi%ZVUNSIJhLN3zOxViIl=k z#G_9fWf)=OtL5%UBS0&inrKzIsf;FxbZUotqfRYTr^>C7;L4Za>@a2F&&7)xq8aLN zCl6h-URj1VOq2R^<&9cPZ&M?Bh1y&%o@j%>V{~?4D!a#ernSbJ*6OM&i&JypmKlxVh_5vI zq_7aN8WiEoAZ5SeQPXDp&WWbsIl8R>|Kqw$s?Fc!)uhYPh^|uiXJ&V9f@!Ip%jYy# zQ>o&grKhTqQtreNxTT0K`xkuaf!jD8basD{vf3EG#Fjn1EIkzIUtC$sy$q%9ca>bJ zXtJ%BT&IcD3-&jo#ZG947SrrD(q~@Q4R|CPN6R{xz#z3S2oAs(buaWl7sG8xU)kY3 zOo9*LxjQ!55N@gry3d}fJa(l~lp9glz4G30-!J$q2QfF3*nJLxbojps3c#<%P61;l z0MeEx@KXW9YUt^1BR7iMGcs*D#oFXqcT2ewhd~y+PQUg(WIUZB0T<2sA2ZeJsA!}O zmBisnmM_ydd1Jlh*m_+(Ky7cx$EmU0XO0x8&un&HH<^;yd8P=6Obv3nx^GF!-!Ieo zV)GT^Kmri=2Nb!nUSDohHZ{jIkr+2kar`24N;N5Q?}U>g$g05Y3|NsnX#`ABgeOmW z(SOg}R6-Qul{kxgy~&qhWXF-bUzpsanAQ`qn6|hP=KXfb{w4l>U;mDcp|8=K_j9>p zjYNu-EsDEP?l&h%=A?0)jQ*B?7%*;lC0xt5BojmS2zVv+_Zm{77|huxlR<0KywB7} z+_;sP5t6Sboutc#hz?yFrZzD%pe4aO$w(@azsLQm1<8%z+|s7l$+-lltC+nr*o0qb zE*XtQy-o9p`}((C{Tl?c_UDOysyETZ0eG6ef-#?)5BQ?34073Zt~IT``P6_by2@q*Jr|V!>db70gU}#(Rr|1+#Pna;&9* z3Knx!TB!7JS4^xxlXKk?=#+95W$`2`8fmmxD=sDOb;IRK;Zow>^tj+s0FTb8UM%~0 zGi(mT)qJoEwy9>EUFsq3e9?ic74saC_#s(04Ulf!Se0+TW~Pi`wygYG8oF4IST`qz zqs;-Hw|`JLg>-XBhkm3kqG%wG0roL#Z}t$aDAIGhChF;qF}m|Joq>!NDymrzl8ER{ z(`CPA$E*BP4$4v=(?6-eVx_I<7+I|Iw7uQ;)u@l3QW_pyegqU!* zbg9tFA_4|LewifU#;g`9nC$+iOSDcXvfzmfAEewfxiz)y6tNBUQq>ZFiyqhOikdg! zkjX3smuoq5T9RH4I^WFtZ*@>S2SW(2PUMo9DS-nH)m~LH)e<&g>cH&uAqZI!pghKm zW)fURv23*3v5Y$vsBOt;O-;l#C8+!VkXY(29$gs}Ursf;V^joX(iIlNe?zC}C4=oS zzA?O(vP2HlrK1yC<8&VtXgQis3H(AL8EKUWYg^M}#Si>?VOk2$USVp!;VF|f|2X=S zb{VTM15m$fVGu%k=ZMR%wz0~B_j>wP9hCBu)C^({w4OaW+p9Jhr-BrN@d{xq^n=nR z!v5`C?BR$vJoZ;ny1>1KBT`a2;V}BGU(xGsJ5kR46`b%t@U^2gB2QXHEm1yN!sN^z zB2LAI;1y1lJF#=BAAbv^&ARDNkpz1Y*YeoUmNc4&L~{FXR5UlLC6OvmEh0HTB?VBZ zTaiqGxZ{)9X{H_V%o?_#E+g~k;+AZP05s8B+c0`L9H+vimpj=eRo&@#KU}66&GpT> z6S*Ev4}dlms!Mr&iu+q+s<~5yP{)+o(Af<80u9z~`covGR+KzZ4J%Cc)lWV*_XsvS zJyIGm9j#SS!6u5RsYS`ZTZv?ul}|M!H=)t)6x{Qnt8=#XKnl8$OMo{|)8~gHNfrl* zenH`xbZzRrAkR|&F&7fyV5d=2%Nv}a9u*0dhbXhYj@o*J}XP% zgyxVP#nxJ_@Qm%3;WZP{?dAD!4g*hn9sHh?^@1*b=ZK&S2OK4u9;8O_$As$N47|Lz zoWe~&;u6oteYo*N(==V1(#3w=(Fg>wT_4nipys(!mFg-f?M_PW!M>MpYdv=! z5w*RGD==Fmxu+2+H6qxC0*-AB+u1MoSn`WtToll1`KS}_wUe@=vUFTa35bdurd!3K zv6nN88ME+x#4lGv*PKD*QmU@|`}`>u6?<|;8b3BGFV*!sTvBu%yY3`FL_vYCuH2v6W?q%xP==YFpAJKcJ zt)zk1desI1YiUF69P5vdAvv&kKQ6OQ4k*5d<`!sb%yH%fXo3GuA0&~2K-FT;gsru#}HqPH|HML zeN8m-GZs^J5}9g+Ri5iZ8@nfe(;dNdSn@aUUwzPviONn|O&E~+=gO5ZbsnVo?6c25 z`(pKoTBC1gcg`uQZTC*)CtL*i&BeH z&nsloTI#+z1v}C`i-WP$EoR-yK48~;aY`A_=NDG1y`NE{UG3#6b!v9*0h+AQ$OT0i z)qv`>6gS4JhNQb|a%D@^)GMQ!#9beBsMqDw9_cBNyqBBek*?;#vF1qg0i=I4q^mvB z|7}0g1@2l9)|wl>h5q`{a-Um|j_^`5ryg9%p0j=39(<+*xT11kM4zJ&_{xpBfXH3Ybz zR!sgEk6zkSADhxh|AdKbN1qGpju#mHJ7VeE=nq|Q`;`FbC>7DM0!#8pTH-eKVm&2k z-|J4`{|%9Gc#taa!%HD!=66A7tampS z5+4plu&VshThjxIjOGVnax=LGp)1|h()u0ZWik28Dr$@bH8p#Gzh-6E0w@x4ur40i8 zL2MR;=b9?$@p;fYwaE~6K@Q*p5fFi5G50CxG-?3#$Y%7GDC~($PL*J8V>bkT9!=o zZ#0ZMx;G~Y)rB5aS6uIX%nZBKrolkLujlin_SqUQWrJSs;Yu|L;ZP7pr$?mPb|168 zZD>8_-=u#294X7Zr0Rp7K<>pj(9dZ7sn8!8$odUa)AYj@VS7^_xH~7;8oL+P zHJCzpzC*dEf!m@%-;Zc893lMH6iP6!>C11@dMwcRc76SE*;YG_3>I)_}1U-7% zPHqHeZ)_;-s$5@p4bQOI&&D;u2ITI@vTr~8O_=qCN!dHx1LLyQSS!5*d@q? z5Bmbn!V>s+|!h~bv;c~ z@ha%_3`F9&8+#jyBz;QKB6p1uIdnrs&y={?jOn@D3&<=+>%HB>m+ZGkI9u$Z9La5j zRG|hy3A;Wn0-OQ!xMB_QAyFT?5?TnzfZehg*xB5s zd1`uuF=N;F09lGOP!kd^o%}V+JXVW+&f^eZ8Ltd@OLZqF4_2K{tqK|~Pv_JHysXiu zzxQnB+$qWJGUKt^>g47^B@YoTuw6x$Qu=Z;{l0DBN{92DV2a64_vBVG<0BK>4-qS} zno)Lg@+>TDji~%j_#@F^bjo)}C3h5(MU18`_~mxT$q*#i?xJA8j5$`Ki<=_bUe$KN z522so9HO~=a`J$L2_sJ4)EHC4HWE(V$Zg8m4Pw*_XuTEd?l!hLWN~dUz+F8#xrOxz z_cyy|I-pGixlq{kbcM+Q`sSwytHmf}AL}o5?CnM|ltQ<8qaRmDgJ2U?QternMOVFD z<=+q-)}PFWZ*BBBM@J7vT;@$Y@gc5 zzIILNxPzN^GHZ)n?8Zl6uyHKms<5?OcQgYNlR@j5xbDSiDrP%XSSLqlLyhK5d84u7 zd90^MUUGZp1UCIGhwN^gd=^+cVQD4rwl^L_I3Z&mV>IC&;u6=ueE2uv(=2o=CRPWq zgyuh5Of6(P)fv38>z3Ie&Mz``!y@Xlf>zH*;dV<6=cy`8E!``u>WOvHGvJov7vXB>~oLF|4RipFMh4bF)?%>8sjTJPhiiG1x2Z)O|XUNl!S|SMi+yxNeEC zSI}*A(B~As%r6Nmk~=c#s=}keq>G=;dbtS|;n>(V!6UYf$(^z&`I{2WW(JyMeS0G2 z(Jyr|ceBGwrS81ba4{#``2p@!a2{3p`KM4Ue|1E_s?>=Thn`WYW zuXIQr&fY-Dw4G3akg+hqG8YCOrgro*jN;wg_2U?EiBgOjBbWFsbE+z@a~{sw_qS*1yZDnn0L8-lHA_hIXSRrkXL^oa%B*=HOmzFrUL@m-8G4x zb5Gjy?UU2)S1K}EDmBkN*g-=NS0k)M{Ew6y$36ufYmBs=DXtkKjvjNvDywbB1XsT^ z>wA{s|l!UQDrXXQLR&rc7wst$VE zq>I_BHZOEf4x%e2dcfsxzqhvGRVGNt+b6*NAjqm^>mFLdxhB{MF zfv&EhgM5STp2^95=~BR|6N}uk4$0l16F&UZPGrTRsT7a)TU{IUDhoFKtw!75Xfb0# z^N<;~qSZq-QFnZ?T36gc(AU>M(PEjqcd`~X1mAqM?vW13KO~X|6}c}aC6^$^E!Q-l zLL;%@w#*b99LS?_rdafn$zpDOO1R57+!;@k9*{)Kl0(>J(bY|-?Z7W`qnK#aPYF6d z2<&50^=?Z#)ZH;T*`LkBHSTRZG%5FN2Xjbxrj{(WA(-5)NIaFA7Ic-_G0l@I>>qvI z)V{*;rzU45dNxUn(A~zx@+J{!iMGxTSug1PUxN#=xrl~s6Zshju&zLCm#)(`&4+6rS${cbQzkO=l&>FWTlnUM1 zI%gbd;>)CHOO^WXB+6iYcP(Z@!N{N|u6MD|ZPu`XuGa`iaa>y5<6cGaCfxI;qLCW( z5XJyri0#+2%o@X}=Y`~2kE`Yz&@l6`@qz`szBExjj_^3jNcWQ^a7BrpUMZlP+cq{L z#SHgMpI9qL$*zomlx94;x)UmBHz{L+-b13ln`+6s3MDCnC@ArprSeb;Vmo~DS!Mn| zlhw5CN|b1+dvih=dvzF1S{a2dA0$`HNCdsV!tS`)Yh(oVWtv!+`a7G@-HpkFA_sML z&pS5`Q@gA?Z(}9^Lw$)SiyLc;K2x29gV+Am(*D+KpMgn%tC;|g z_JkqSWml^gSlkWW`x#xYwGOZ0ry!_J!*|9;D)y_{O%A0sTui9D60xgyESUz!p`=El znQE3x!{a#8I}W2}?=2Mmizs|NvWyhWv7IG7yX(!3L6&D6J#u^JIC{1y)07EnBHF#6 zIM05&r~XForM5Tf6yXiRBm;vDXG!4R%FLHL>65!s1)I^#=U)q4cju(EiKjx`E8Jbr zS!vl+y>N}pP#sU74IZC4 z7y_ZIWqCU@tYsN9tV`W>U664_t`BzpPFh6_U9Z+WKY{=YT%0yjq6XJj=+2l>pJDLc zsl~yrFJR*p!Q$@ZbP&VWwx6IGUk9b*m^rX(Uws}~a#{;6Hr>$8-OdIaCPm}4Fg=9f z1Ru9x=!O;y-5~Lc8@HV1K>BZ)A)*rk=Hqw=m}1CUb zmbwjU)Fs1ftq(YKyEOu-FaJ|`Q-1vTJj>i`XeOzXZGcw7Y>!903PEqCxM*G-soYvK z#XYEwJt$1&(Fgz4q4daG(gXgafY<46JuMS>?}+;=c21a@3ED^pHM7Yfa-P*ul-#2S zSt1VzY*SC2?u1mC>%v4Q@^1v>Dm8~jQ2H;b?}-m%7bc2K&*i%?KY=u5a$sR{oY@UM z-SFhj36^*9MR0__gn4;T`YrSGfeFfQ#wpG}0p+md4iYij=<8;0la}1S2yX<71oI|| zx;CmP>n z&6La*ij0}!*E%)eGDgaR5*aD4{#{d<{S|qn7~Del&It-}ba^o@f?jSlb4SdqVb*3u zfA?@sl7I+#?(Rf#OIQvpvpmO=ftx-F+X{8s-EB#K3~+ye`nV$IhN*YJan?z{495cZ z0ZX&scrkzq+()dE^>py81}&^OJ<0l(cuT%m%cjjQx_^A$wupvzDE!rc3BJbTy=7U;9>cNy?V@{nj+$(|& zPYO0Dr`!T9xt0e5IM=VG(~bUs57kX5Q%1>5IaTpv2J5SirM5gfpd7XWkvk@H&eIS% zSctHBr3sOp)g2Y-U~{**9J8*XHp==}W!*40>!a-I?u}nH%_@!uH%xhu?M>h?EPJ~> z(kO$?Nrz-QZRnoARjbsZ&vc8#I70R`9Zmu$cI=G4S2P((* zxjAry^>zn}`?juh~fhHg#aYAB<;na9Gl>|Da&U z!NCT*0(yx#DYh;TcGR#KY?RoV4PR7N>W%}p=L)Nr<5CZnH*tT`x>9-#`?7 zh?I+FFr}QFb_+`?B4LP+vvf#Mtck`{X=w}cvD`+m_LNH@dPgVFrWY&L2y@27j2c{z z$Z`|mnr8N_9-6ukK{C`QNwH2%O%2^QlT!6FumL4b4E=t0vfy zjR4)`DufytqI-`hQ zaMj7=rigp@`yHZh)Gf_}CkFBkhFXdV00aBG+7HOXe^E~t5 zkkFIf(o|dPo?YGXa+Trdmrcr4>n(mRmWzYL+fP$ByMKXHXI?;p=QK}PG3FdD*YW^4 zUYn5kC8n%x2cFfmy;ysv?gW9BTY8shJeV;dW3HQf0bgdRyM8=7#c()xN>m%xQ%|dF zVbW@jc01H4XY*Fzwom9r)o$)aS{JzMI?^mQ>-3g2t7!|fvZ~0$P;j8apc^MYx=v3X zW7b@LasVfj*n+9tdl$><2;64X(DCp^tSD*U;%2Ial@_czcQ{)`{)pEt$e#uSa=aSo zf7bw9H3m0Ho|{k4V7;%zxt=xOiB)u0z8dy8I;n>beZ)wS!6YL}ULPJaGT|NCLJuq; zR1avdbTs#!ncAUTD|cB>j$CQhILO`7u_lKb21s<2u+G`j<`SQbNi_m>d+bhI z7*D5h0k9zK?Jk}Ez;O!g{08YDeA%EPpS!yG7-B(qdDDc?`!Kg|2)57~XAwIxybGi- zJl{$&GuWmw*kVbr_iAjWnaM+0m7wk-<{I_bQmKBT*aw-akux@N@a*}>IDR!FgB|^v z!dLP(u;{?-I8{;UrpbT7b}?T0eHl12eyZ^lIe6vrG~fdy8#4Gcm2Xe zM+hg6@L|drdp+u>Flw+I*{LtXv72HSy-f@Owg;>2-NVmqMVx96Vn*es&RrqT|6%T3 z;Pk4>d;fW7vB#N^gj^<&aE*Wn3L%q(kU&sFGJzzMOOpTz*1nz0B^l?+%sZ0=6eNIR zFE$|cv{eI&J*^ecQ)~anphena4_4cr)6+t$r`lHRRjsAkp7!+e|Nfq5t-bgA&P>qO z|Nm1l^WOGed#z_Z_uF!RkpM71%p;vqjk>N_A;^LN(SlxrNrG##^`~&Wr_o8+(PT zGvxITiV0#}-2jpi(nS!x^9WuZTaZk&2Q0mF2`0o^2Aem*vJM+?mL0O7cctZDvMmJE zD*S4JU%~_yTx_urw1|?P0}vN;S;U!s(Ink*5mYe2_MJV27PHC1w61& zra>kAEX@b9b`)pv0y##sCaMbL#|rZl%bM607SzI+_(}7t&!NJ5c{nOy=wk1A^0C%S zp#Qe-a8vX4MIylP4{zZaHsX6;=JhAz@9DMi`t<$GuPaVum)5eY#ah~0|0vrT+Mds@ zdMLZXnDv}f%mB9W4+@NVGCO=iT=U16BjzPoEY~m^#gaStCK~=0YPgrkH`G2ae495N zQiI-i7lKfHFZ^#7R|y|A$T@M#kAEJcU2reIKbd9c@cR>(4T;E3$ztIN3g~?V)go)R zFhq<}31IU`CeS%Y=Y~(*t;tWxmGW77A<|rA4z37dc>l!LA8UOK4_n)}#jJ3b$(F*g zC$2Xq{4LH6ws=7h7H@+nzuJ5vdv*B2TWi^+ym^T$@8kI|N_J|;wLj{Vr=7RPV7LK^ z$ddg|Z-WT0#W(ZN!KCod0QB5&9}Fih|NruZFl@o9?2_Nf7Q7+5WGu@zX3M|91xFVXfI6p> zcx(#{*&u|q-_FCy2biN+s-Yrt`D3&Un1TG`#PS-0mLA?qE41YtZ&$cmtpLLHVuYQV ze3B!!&~w5^*eYC%)WOcfNsYB_%YM&MCaXuy4NtNAtHKW-X9M0PCkzw$d$QxFLnWMf zTv5y?z^Mknw4tqti-8@4F7dT~!2tA2YS8ES@#~?|LWPVQ2TgaF<%L5t07z^kd|l33RCZATq!hmO7BNCY+jnYO*@AoZ!}6cw+m9`7 zIr$Fl72KsAT*jl=E;PRXx%~+LCrs#CIOn}m^@N+S^DFHjg02bItp4ch=q$?$n<0 z!S{?HT+6fOBGA6D@{6Rnbc3wq`L;|r^of)qift2qQtMT6xOQ+nYinMO`}n!mZ6pQE zS6h^Mf)$CzAAxG;h1Wj^z5Yq_NgUVV=OLa2kMcO?FJ66VSOEgP8nME3d!<$UoU6aW zn|Dig*ArAd-ndD`vw-!A@FkcJ3{#vyLo?u3#*S~hd0PqpLp!RBgz)1f4)$F5M$W;0 zY&r*vHC!ycF3jG7wP}z0yQst#3hYqo)sDCF zMCBC!0S(RTS9toDfErJ4g%>P(D}#D>qKw~6@_ZhiY7cFBm%j?XUubE5Bi{7C0mIC4 z5I#gZgBlc6yGvW{Whhdb-R=Gtcf*{+f2wStaR}OJ_)Bi2MnA*vievu3=fuPxozfS7 z+~(Kdw>S~~&lo8%p_XskqqgDUX!%T9_niN%2TMWvI5s@1$X&Nm8~B*#T4hT<7Yp{b zTbduEbQuW3uTvL+3G-j&1PIT~*-wqAa;~2KHxKwLKHz6;z|YJ<=D(?V0}!G;y+q7> zfsG7mB~gQ|pJb~l;hn_G3 z|F)g}U6P2{>0hXs^%=f%X64b(89M$q7!c5I3%^h~&JJB1o{#uRTAkxx2N=-JOsB$qgkn$p|HwEMuIMZRS^THh@hXN}}y*yck z%xwLJTx6zaHQx@9!?+?{W`vTGz*;Gegu#c8-P797wOn`qG4tolCn0e0`fN=tBND&_ z@tUDXx5a=dm8r^KxQ<-;3pZxhjh@_)UABu?{k`N9*<~BEOYr*536J0@*(hrM*JjO* zWyCxzWs-%-=G$1LX;u<>!q@&?TNt)nlm@8KQzILG`W@`54r0TXz^ZJ2d;SAL5zZ_={n$uQNkxaRe| zxIWkVDtnWKPo06+V*R3UL!92T%p(iWWG8H(Z`rKEWg18~W-VWET0vk(#ZdK57_R!! z6vNMG09Smd_$yK^O#S&~6mHbx-$1)r9)4L}w@l&t44+X{TX7&PxI0@U{+$$phtL4+ z!P2YeXRTl0x5KO@x+%iNF(E--!#1RaOcJPy7TFvavs$XO&SG#R0RHn@o_RDon`_#Y z-9V)-Z&i1Cj=fUN$?G{-t1UlZUs+h)8+$7tAT*4x@SJ5#1qT@4Wds#PcFLttBF!IB z8$PSFu*&i$#n%!ZoYQ}TEl6Veq`v`2- z0e8hBtkYMAPl|E0gew#oH#M!mg1@7Kx?L-Y=>?+lAqkwc*l%gxZIN&U|EsXywq*0) z0DG2bGe>~#dB)#*5AsTQuX+j1rdiDn!7tq*%gN{(2k^Ry59i=n;}=w9;3}%O)@8P~7jIRrgQi2}U~} zj3=`5nqLk6-k)8to{Jt8Duafr)c&Kb%}ql zZOxju{QZS$-tsU1A)2?0b&qo<#lNd}OSx0a^gb@-GcRW9-SXHSXQ?`G zq0{kra?`CghrC-dJM{%=_Wsom>61#YW^U#cOP;7`Ku~-$cC4hd7FF#&oOdiibq`m^ z?wWH{`T$D*)7{vJ5v9+)I;%`T3uh_sgrZcOo0Zm2X4Lesq(Kru?Q&usaR9N_WgpF!;5ngo>Xm$&M^6D~xQ{6D z4-YgT;*Ch-EJ=5A%&u=~zG5+N4MtF`puwXIP+Un&?lvXYkj!uAF0^r62T~8R3N%Wc z#}cmLleW}fyPPX2z<`x44n^vTDp7)(QG}QDN9-q%-m`*Vy^*c;F{Y8Nwt9ZKks!@% zQ}sLb2pXrE2=}7a69gvh!|j5|uBwWY zC1bioR8%p97J6<_^Lv6vYoTD2N7+>_K@BVHe#d3aCJ`kgr<`$|RX z!O^+5WaqyTG{=X)i6TPn%GI26!mytt4{8Zn;PbAhL$jqdFa{;pLOhX(YE1*zpVe{; z*YQfbLr2PEr~GMF;u|iviZklVczPhya&dN!An|DP4=kqNw-IRDZNPtCKhNcoAI3&! zI5asU#xGbcTR=_I^LF@`fKi{e_?JiOzFg;@S`OR%+WnHNtn){p$)tVzsQ#*xMrgi; zwh_DmbjNCRbCGK`^v8&SJ~+Xo*?is~e2xo@wR#LOQN2J*4z}ja z?f#7`NMc`Pxx#m@XL3WFygsz3_hMPbQty&a*>Gkk^0 zJuR$-S%_t}uyL>C6)F)E7W2izXAmLCBD&0!U#-PSJf(-9>|^P&g#lG(Nf^f}*ZRVL ze#;5HsxY1SzY%r#dJwvw;UW%tf7e@(gZhRpYkC3M?B?x$ll4v^pkhBw>Tmp=$J+Hc zob)X<33ds7SbKHqIs@vppSjw9|5W_dIZXI-d8;3M=swzeIw2)4{o8k2MI~Ts2|tGR zwanm9Eby|2-~}g5G_@bdF1wdcH(1PJA=Mkw0F>RiIC~}ig(tID5|_nGdwsT$RHo~* zizLV<)%5x`ONe|fZC<&A$5Kv!Tjgx{*3w(}bbvQx>nvTT_lu<_?8l1%13bI=Rq9pD zckGNn8`wF$ln7k*igxmnpJUreJ6syBI-Xr}g9zm;{6Jc2x@2L?hZf@&MG$lU8#Hlp zCOA2185kuQu}m$Jl@5UzU4}lilvA3n+TPFijfXzWmbGW+-^yFTeHk-fr}x@Pz^(+Z(tF-& z5BP2|llMJfl(+{XZ82GS4&VABq2iYs0bh5goy> zjMfh~=r6H9MSsD=8`}~1UvI*|_dY5M#oceH?U&y6`MdkCx}NP1@2fmvo4AB~PJ~^R zs|;z6>YTH)-=&(kvu_6a0O~xRHjgv9PPQ~}RiLiDixfj8Oe_gUDP3U7Tisv72~vQ1 z>3Y7h(5ZuZCh(FSZ(yA?&MEL-qSD``w+X8ma3OgTi*de%SIW8rXC4Yaq@+LU7Z-(- z_q-&@9sa55ICDMsT{^kyT;{4x1yy-vu73p`5@TC3FItQ zVw8OdYh#pGZU)i^f0SKcoW1sX-cRzBv$6|1NN#Hh>jbY^=8&mHL?s*|G_vGf*`=$< zD8U*%%?)YNH|LYycbd@`g>T%Athplm5l7!H3Xf3?C3#>cYJH{|?~93_v$BOc@}dvi zP~{zR!NtX-$vBA%aT`=bljlkQZhguaY-nCZsz1MraG`*o;>c5y+rN!drxMOz!J!U( z30k3T$qDEN0zN*MY07f*R3@qCVqgpD%c0t&CE@LNKB4NQf5aRyJN#ZX>$gqm$`&jA zB6sIo{u*BxO1Yf;C!X(2PwfCq#|Hw!sOKD^cKD}z{L>Nt^xDW*2Vy5>n38TWo@+MP z3coy1_rXRTejYlb?;7^WB?V)cj=AD)K8d;N{-+PJRx+foq0y8!|IEp3$-Nony^DMK z<K_2{dGF`_qs_NVB%y@dcQ<$C81cpL9U&f@5h4EmE^{!3U%;PNS>>G^-zZ1h z%=mzAjw*5%JbB)S#msOh!-@XqT{;dDZ&DJR)T=<0Z z$Ej@DyNpXx?Z#y0{K6Ib4GsLwPnVt;b8$1O3*L@#DZU%TTh7V;Nx`#jj+Q~eP&*2XzRROy)b`Os?w5nZI#?y zH<%%nwfrCqXTAdPuWP|s(fVgPoTvF3A#!{8D2x-xe2(5t@}4TT0oaV+yq&b7?>~0^ zXvD7nBz_aI>-N)PSNnAAdXZT90xA=8?E1=g&1xLG{-%sw7kz)QtNL%ou8ynK>1iZc%1p7UV-|rE@-ba8G1pD9E$&Cnhf-2sKV9#d@ zSAFmNYX*VFqyDt%l#xDNv0@+EU2+`F%)MrkX6sFw{q<3#+4}I%E21>}OHRE>(u|~m zSI}#M2-b2G_aA?S+6VvjQAy51#38A@i|{YL;<&S)Zt~BKX2me;C7g2$j`%b-VY;<3 z7jyryLjemjG7C8b{Tt&Nxqy?B9KgYUlYk@M{PF@0Ml0PRyP(Wub6J;*x~->#QZR1h z7F8fiaB~#ij?-8}QuUXtWFD=QWa~X;zFH`S3VLY)IwlfX<%>Coe2pWpBq>|}83o)x zGqRA0zoS(%h5yz>y52<;ph;E13nX#zI=0gJqmaAz_pj); zPb*{qSoW?qTyaVG&VX)tNk9Ar0Z5KgRw&N_r08DK0UtJjB9fU^j53q28I~u>IRkH# zM$`I0{>VQd)>sM8F>lqaL#XwST!UuOO6dR&QQ1i6n7SzcCu-_nu$ioyB=F~@WXwyG z&eRp)lU$KR;F~1^rKXt({AiZ-v^3u&h|LWHIL2A{XUXiWgs<8xu?ENQ|R2ZlcZ}3DJ@R`N;GSs6jPpBWGky0;i zbcQ3jjFc>{WZz zl^j4*3A;BK+N`uR{X1Xeo8M8!*-ZN+X!u+(1>SK_qnj0FSqpKMpI14g7lglS!VSSv zl}fFL^LEioaT=kI&?@O`1wAUQCb*p-*15C4&P7M!hXva_KR_0 zDtRmx_F%m93A^+Kzx2cL(iiN~7b6TFWKMrqaEtzWN2GH$olEU;0T`fM^Wp!HOIQgH zGsBs13u>8rU$(f11wMvZBg`~U!k==Nui^bRu|M^R{Y;$LpVqBGoAdQq9`-)pKI ze=eN7TYvx7-ak>%`)&$i0%hO4{nc+VprW>Ea;{J=6#gcZsY~1m4Y_DWGw#A~Y`>FNRn|t}?0NpYxqy~PPJ(3ee!Lev_ z@N2;=bvpgr+t?e*^tDNgo>Tf&3+=+b*ZYLTOPJO9;jdXfdl)`JCd}gdugvD|%oca^ z#iPx;sl~TKCZ+%UA{M*SKNp3cBH2s4hdNUD9oYckL4DKOAMPg|jB6;M^lRm-B@5}8 zbdhrC`?k_&3w^(8jY8jl`yV3o-8Vc?tNlA;-_zsW6VLFN@<1PgX& zOCHH8>u|Wef&Dl@A|Ac(S_yZxwfvQ_64DW*6oNTkO2ygoP)U2JSv>d~Q?UAWqs0vI zEOp7VQrpA3@XK=XisfeV9<6DR7TJ$MKFW-2XI@C(;Yp-M$G5H6c4`|55T;+_;t3oMu^W!KuXMT*zpDp$~ZO77rx zxy>~zbs#kP&Oy?Z@Y~8U@Lf0?FSo$vs;losC482ZF9?UEfh}9nk7?3O=rhJbvz1vz zwKqE%l$5ATv&zAY_PlvCldNl2Vvgmk^#^&I$%S;r@1SfDn)5c+GO5@eEVoR@_gcOd;@2x{6ls*t`a77rm#ehX${AO9j&_OOx&Y-vG-CwiGj#j zrX%D&YD!8)=d0L#M3c=Sinfpbu@JvsHH_JezlIws50v-o?Eilx)xk-4PVO%jg2~uzOEhgb;1| za<2Z&w?77xm-NvN^H9B)KG_Ksaq%mQ#Y+*TY3<5NvHTo^mTxeNL$b=!pN!49r}NSNH3Z4Q6u$ohcwBkVAgilYpM49iaCWTeEXyF>W{BLG`_! zS~)3TR35RvJ+vpGFuO%vKMiX|v-9c1@^<)Ewsa@35!-S#*gEuzFzhS}lBxX23Sx-j zHfPAQk^LYVF@RK2nIF?McV)KXR_XCZnD|Ob!V#>paBPEKv{~)X+X(F~umU>>)<7+A zd^b3+Wci5h+78g&kMoHruLsP4@_fsU6q>U57w;kqK`zFH*?F&2-VIeunL4OrPiWsy zvF07dXRN@^&$O&S3Ca>36^$)Co?W6516BW7%LnjMk`ZY4BH!En$YFS+_=I}9Eh8lb zsZXy5zedBW`YKSp zWte^!pNJ(xI@I_kIAJ>cDvP z&uD0?Mb;|du3uGA0s!~e4CyAQ=j-faBd9PgYOr?b*0PrN$}s+;ts98^a?et4^c!e% zjV8pEB(ezoZC+=dWP^^O7-^*Du;i4D-K-G0e=`of({Af6=7%>VX#+_B_kCIG;jB#t z=TipTS2F+(C~J-_z7Z3K;2MU?YVm9b3oSSSgX9DW%|yMvBlY}*w8^-A2IGFLrf>ME zAo4nWIWZ`CkN}gn&V@BGOcq%*sUlFoOT?BY6D`>9XZq>YXRG(XlE%9Zp}3#c;SeKT!=^&&iJu4ymi_!ibFD`SDZLJXvkt>9Ts0_EhvYxM0z zR1cn@x6htDsDLbjU5wJC`h8Kux}C8}Eo>?h2K)d2P8d|+Q(?cCNf`V&%$&ry z=F=;XG(`e6e@gLy;n_Z}L!g1TcqU707*twNhcMIo**}1p4b+ne1*=3}bfhXU> zxP&yH;mh;Gv&R%!#ae>#nmJ=z{(cl>0>088Wu2)k6cMyNsgFPDBf<_U;Up2PX_sX<}MHwL}64Y3&ai&{#)N4 zYzL0aW%P$mGy2k?X4x$I8P2sovw7V-V5(dshQ9#u#T3ove}-+5VY>i7Y|A|{8jlsu z#sCXiH|U7s%OOi-$6|AE$|q;MSSKCX58A`0d=%L1yzon8?6!Sy+etGg22U~3$G@A2 z{u(VjD&a@In@i8Enb*SA8Z2>5<7WT#I_CZXL&>dAY0J)hadDiQT-Nu~4hUB-vF-P> zzQ*GmTS;)mY{;FycM5yd#13#*<0yzp|phu{NrtW6e2(1<0wKDj-U{5 z`x3HtIM19PKj1&MZaeN=EBuhW<82=5e>$y$t=|t% zk>S~Hhj1NxE*}fOQU(GcMug^--^=EZL;uVAn}KOo*#rqxc4rIDCj^K+NxL9r6KM|6 z)h{6+AaV%%G2!<7maiR032Z?DER3F$bR|CieCu+Z6nAC|D&-?d0!9lZJbTxEGg87Q z&)DBuJC03r{CRc2S`eO*i~EPw!r%!WDD6ku-J-wD&bxw7r1{#nhobRF%8q@WB6;;Q zVBf2Zt-xQ*Q%qjf;uYDld%5uj%eBf{Mx3va**akBr;Q+6cK%BUinFrTH>zharDO}< z2=ub>AkH1O2=`niSOW>m+0I(`OIHlPWA3)_$9Rq^tBn{Zv9rQ@n}Wen)Y|1Bm14KU zo_GQ1`Z+;zm3E=s79z`xXf&0~X1?z5?4G$FMYQt#Pb2Rt;b(ARm070w75su1GzIcZ z^?Ux{`|W8uu{^0JdPwWl>|8iUd2--}q>$fjo<;5z?Hylb?P3G132k7B%@1T3^NcH~=p`czgDE=_6UL_m-lxEu z9Cr6ldy5VSrBfR$Uv)bM{G#kN;e%|lYN54^E7SOCp_^Aq)qr;lxAVohxi12w(A^pLL#8x+gje>@1;C)mVKNVvSFD@sphK?q|V<3*gdo!XHR%;`e1C7ffaCHzRo@kWHx|rjf4) zp0ZIB#H6_}e5*-i5p%;&13#>adEz;|UP7n!gMaib(K*S+TiEhZ zwS{lrm@Ons1L=Oqc!YN8Q5JVW_^KAyK5i>}kFRX;%uBmok6-3xbqo7}AlNMI_HGgL zNG27}$Fa2#Ic~(vi!wD@R~Bo1E?;Z=_1SVIF+91LZF*y|P1*um85M46Wy;KbvJfR& zTI;TCVYjX5w_!s9U2FLI8Js#4-a|_Xw&?{I3yb*)hUp|op$DxF>%0!?_$C92ELwc% z45LyJ*a|CqDdO0>i|H3QRyX}0E~YOmyI(gl{X-c4#E=^%zM6?Eb`#!Me$ee$?A?EW%I0H5%~hLJ`^ z^7cQhHd|JnKyxKSV_FE%u$YLziJ7R%{9;d`hKXCrkb-x}kMl*1lYxJcx6r{UP9(<{8c!ra6+_vzF{iIXPOGj4Qlaj_(@A*Ex7%D ziz!k@FKhJda3}da8gQUIAXvfLM5y%~WBPzkFd)L330l+Dvr%}@=F_(J0*y4vN^~2v zyVvUslCW9N4mX@K2MY&cUi75AFzPC~M2BfgUw}iTnq7cufqEi~>U{d#_P+$Ppyhndb)leav`< zCx6!NJ~hjeZ_vFr&UWu_+P%N%_p&j+ERbE_eAzUhEzvMtCE533r*;qK0#nAo` z8KubL5}w~4K2|wJOFX4FG{4&QT>O~K@sFF-j-Y+94qYWs3D!NrG=x#tb38qte>ftg z(XSyTaw)v+p3*o}rB_;C3jfS1&ThVBe)Em_11>?-(aaxe;!*Qn%C2r%%D8tDNZbq_ zZs7z^1Tk~GdP8;&Im#_pQf&Z4E(@Hi!5#nF1m)*Ku=O}S6jo3zugoG!nnl{MM<{Ml zxJuWzK2uzbal(vGLylUk1r)i8&Ir{U9YCBVyiTQ{IS zaiG9#pE^OVNaZ-Y`Dz;mEJ7hXo4y)X;J|q5gg!9I*5kSi z4HvE;bZ;PbInu+yMC@mCq6NoZ3zK#IZJ zBlW7r&r~EF$j;#?9I8{E<}Zal;l;Z*plnfytI4w^^TXp{0gR{eQft2^2OBRZ9X`$;XcZ#J z#|pAXC2x6&@=OH%e`mEb&1s>kVlNCmoV1CxFeg0DNZSlVVZVb4z%LA+gv#fK$&;e$ z3)NLirbYO)9>rk>E68628cIniu+4Shjy`}k&(-B@{@LO8 z?yj5&HxVp4H~eF>KU0sPZ2}g3OL%sIR7yNGa)GpdPMbjcC>LE1lLCS-Niq0IWrLud z$QgXdWPt2pv-(j<+Eq7S374+eZ$8vFs$`<_9A18@=3Rc7d_-Nw!EuXRa0?H5w>^dj za{P`SXqAeJc3B9~J2mexbVxx6I@I77BjH|Qg7D-1>4<-NZwycj#0*+1LyhMVt95P| z<%CF{vJ`+TI>yogz=FWZ(iP4yAW{J>5`cpy3g>Mk5bl;$#G-1Tx%yG?{N~ony<(JK zJUHRSyUNPvhC@2KRqqa2HrXrxSv9Sb7fb{ z%O~nc;J|nm9B}{Wq{-vUhBc38_sxNK5eR(YPNIZ#G|Ci+xns$K(u;JUU2%JV$tjxbWsf_x3rkoG{(UEPoPS`( z3=7-oOZhQh*irxVGjU;Wo^fFSetdr&z#I0Q&LRtfjz9`?wdc0b?uLEjygnA8ePr?L zp_TIDEer<|*oHtV-?w?wY}n{YVVODGd_RtoJHRw-maRulH_eYI8myKv@=%ewBh1Z& z)2+WPqEpNh9jImT3zNLVnWTepAv)ZSq#uO?LcFk4kG{p+QnEOfhGjLl(V-PG=%VkC z3)YYe5Dv&#d_d=y#^Ek1hGV1wjkK#Y(yKMnf$~Ts!=MFfMjD~T3Qit;YZ=i_&x)2m zYDJPcH+s;a2RBkoSW#S9lE0%vx1~~qarRwbh515Ok2xCN@Aw`$){+v(dLmm+8>S27 z)XR(76?P5u>D9|l3$liTMs0!4OHPn#>1@B>>|cD!KV9gb;FP-eN^z2d2wZJP!MH9I z5+4*2UlXSB{Ys8pykr0j3K2bOAb!pl<(m}kz8K4%}jJRBG zIN8jpUHYO`+~5rLoZ=BgsApz?U$19?SVR`s;TnE4Tf^b+H zwp1I&Q@?VT%CjpcJvpd3JmmFAt=p7+`sMF+bC_cI!@HiS)o`dvSkn^oer7f&{NKBt zc**duIXp_fm9g`$-C6MSIXJYEIC;*J4MI!vt>-urh9v++XlSWLCPC~E(N=v6IDpb6 z9v)c{cfChpg8T9A0!@#bJZUHGsPI-yMX#QWH~q6rOa1QmJ%#;pIr#Y+zO@2yKgq*7 ze(g-(UcEotBKz{;XebC_!mrWbYCfti-1`B!rSL7j6yAZ2JdeB`6X~s-F4i8t$#s=$ z_%@uYY!KR=X@=HuN{4Q5?^9@a5%rM>Af{QTj}} z4jIV6??5ZVBlr?NyI+@zct1nZKfm<~phQCf8X*(Oc0SA@CZ4uo-hoT{<770-ovkOB z-Z^P{GHAm$S&yQKji7mZ`u6hu87+tBp{8lcz~ZMkZHa7U^B?dBF9QE?J#?8qht$Xe zUBYOo8!=V~uYZ8g?_8`2G_P8O0gPork3bx6&%xKvTyaWNqJ}yCLGjPfB2>n9#mK+g$cv?%A}3m!Sjrh`kY>l24j8? zQ!7yk{|sQcx!_fEQHbx!=AsCHm~9%6Kh^x*|Ag}?xs~Eidj|1^KMas^pvLB*FgjH{>Ip_IX#`VEs1Xf zVX2E+J}r+rE!pW4mR&%UPIR(7jJumjnlX1%1I?VoKn|%I>^1J}zU-mqcUBh3OY+*V zvH4OOMUcUUFz(l)k7t*CQ@8SIo*W78?4oG~Tgagy_&k?|1?qG5CgwojU80@}R4>;M zzi(GxKtqw+n9sRb521epCNrLX713nYoVT@QS$0)twvtSR>yBiXhGS~fJ0&I{6p&Q9 zdU4i)8K`cKLJDOWUCFDme*N>KH~>2c;;nizT_jjt%@}-rR<=g5y>u@#uOI9HpUZsGC%}nYFo;hzzhTjH{3A?{^?Gp+=I||usq+y5oX{42NVN$ZqIof?vt$|a8~cW2 zBTm`8@*I9!#7RFeovo(~UfC<}%`SVLV0-OzYy_vS0+Epo+49dnpI!8la>*|OQ-WM_ zuVyTrs5Spy9&}k)p}wyd|F4%$@>3gufs4Y($@|%m0U8H9YIER+d6-qDQ7?Lky$kKc zD_`tCaguVrb{cvxo&JXiMO+WE&so7u7lq$$;6yDkP03$n}K zm#um#yK)MEJ_VfShiA#vVnQz(wa_Q1E$p)?{p2HxxZo*15m4s>jZ_I=B*O!aA-;uJ zSMsUEE!3;j3HdDv=FRZwb^LOEcoJsM3ciCpkBKgF`CJ%YdW9sC!Da&=uiOCq`_*gr z=Z~55W|``D1;@+xpFDX&2P6LUJ&ImEZcK@tn(8-l|5d!ZrV;CtHyWDX@^Mf~vv-w5 z88!JO52R^iXGtxfPnQ_U=Y-PP#elafTXi#EOdUX0okiBPUjiM6pQfIe-ERs1iQSlI zNvM*W?`XxxM6)6|ANE49`q zNM-;D30nc^7f;}{Yds0Uz6fsr`4MqDD>iKp7t{ZkxOVON*5mS;vDVx6!!OUu=05OT zlW9avZOv!Ssdy8}4~NPMD-`-ln+k=#{2!uFXuPkx_upA3RIUmtcf@Q$yKZZKtTprH ze;FTibTFLvj_g{5)EM~rNEFLI6kk6mhNFOMK&;YX>JmvEc~Lm|1!=JShHTDJLggH2 zarq`*kI7=6QZr^Lw7lPC#+XWBoRd?}#!rT&~c(f2*keZf;VR8O=jyXkbjh)X zALBlnPTT#dbNg@VvnKvdQ>a(evTG-^R=Qr&(oA9NGkLYt!Y^3wsS01+1m?mXWUTN4 zowU6q<_bGH59YM~AYZ+i=io{Glcp1k14gts2_NBg6gA=a*nTM6wl&+nJ-ar%W?Q!Q zfQ|#iy}x{wGQ*a%tTsj2j#+#bW*IJ)kA#ysdDPldlJ^Rj^Wn_r&Ez@%hU_(WQV4QP z0%P(V$at|%s9K<2U8b32ud!(^S)slC7c{Ro)Zlc-n`>|kKEsJXyv_82G0sd{H@R*|sjt38Du*4(CWC+R+kjI)$|&F3E)QD`4!X zO;siQ8hEI4$)u4zWS$*5P|+Kyt>uOT3O8oU<(u{1tgrhSIlZ5$oKP%Wxi#h!#^Oie z_#BGiyx(*NCEoX-L58KlA-U=QQG878f;RMJn-2NGt*gu=JYTH~p0#4H9UC&rW;W3l z&%!QJiOva#4}jiP$zEskUAx~~ZCW~i+o{umd=UmbkL2*mjvLhVMY$&(%$u^W4)wb7 z!zp9C5$SGuKsD5mZK#J+DjVKX1sh3|Kn=UNF5CLV27P&Zj4o zOG$Kq37!`|OkPl;n2(2w?cm>Y&f^LWl_n~1(5vA@egF8DmmAcn?=Z6p|AKKrOnAw0 z1M^0DvtFNFSIauA;myL9yZE}2-FQRRvGoR_;?-vMvG@-4KP!Wx@l!Z*!oWu7GIaM} zxtrczjI>GgL;u(n9NJAe#HMgAdbM__WmC4!UPDz12^>Mm|IIC71x(7`RkCaKx*?N0 zt~pF_X0N^BXsavjf-phfG`)jP?F+>dA2vm08Ctu8{&U)ppFlpL)BX*B1ztbuo8aEi zf>iFCG$DIr97$SjU zhKuQ*2yA~ASlCXp1+QSY^}=r3r+#+a-e}i3GOCHaWmNXy$(LQ?op+eDmRI-XS_ z!t>QH+aPyo_);^^kk_yhe)4Xkduvo%shNuRP>_oEJO3e6yd&cS|K3vY>1y5oSQyp1 z<*i5MsVyB?rp6SXTz7L4M&WavTVX-m$@ z+N4M5iw|b=+RZwbCFgON`^|DYFHmBNy`xIoK&nyOW2it9o?>ThEw9r}+8+7py&_!w zc)wIP_)Z=&Umk%l^&EpQLm{Gw>y=>+Igl-#)}UJq?X{GciVt0x;VEu=Q=Hk(GKs8Vpj z8n@~E>~u&b z^_MP__5tCeR}5XfT<71?98sTuq+J6v^~z-JBlh3prDvGR_@)Y3gKlWXg$WBpy%qYi zP(ZqXWN+1;epw%!8h_><3o*C;9-~&`-xEfZ)#})>qt&TuZFI12q{%;xR41yNcH2P# z)tNp}v~`Ff=-HXu16v7^#)U7#JC-4Rj9;+&M6EsJOe++b~qC z)$zXG$)3Jy&#~I!(e&)vs*S)_Jt2y0RUcXh>_KXfq4v$njsy5wfe8f$CwT-pf z`0CAl{oSlGK0ts!+&$7eWWet3?a=q#y{r6XwZE+Kmuq;@WVZt3P2Fr$?~RiKL$!gC ziKgD}T6YKVt4)rNR7Z-98yM;BvklUHdu!ut%f9Y|og=mJV;Yk$2df+oVO!QW9>3C@ zHV=&V0rIK7eI+d6+8UPfa1+z0?(N)H-MjVn&SIQecP%~H@F{Kk=ool5F?n#bzki~y zHW6=#+rH+SrokiKK&I0_q&eAv2h$weM(YlJRMKYu)2D2N|>k z0>?{+d;1z_a^0qc2OS+fL!%RMF}pYJ+1pvYv1`|+?fJsCcOIzj-M4XHS{*a!K2n|N z>4sG>U$KR*(b2)lF=l^j_xP@ZZw5zsf72%Lb)x$qL}c(wxB$8`%W9u?wpxOwWBwFh zMe1-u7#W51bXH2Wue9A$3F&PQy0-4?+_SN(x_8sYu8n(`?SU@MR^$~4-1n+;$JTvu zb$dI1;Fivvn>wr9x+AV{_pw_>280FGE#srZTSmu+yAwwkjPnIQw7O~h=~liS9q)lW zs#`Yh-N!t-ssQe`U3)g~jhir79UJfKA2`}HJXVG7CVIvP#?tUP>aAH9ub!%P9|VY- z2YPDNoqaTrnSzhxBbglN7bJ7yZe)AcI6NDPh>py8^^)h0(?h^oZu5?j_0dUDnm4JTh~$% zXx-z-68$>&7sskjl-}3u{ne%-ats#YANEt`J0*?xVARHvu)|zc69F8wdX*! zbI+b#dwiKWm6XJ@WQX%jO}T-iMf&3!n0fa&mmYI1kV~~+rc5@f%sr!MFd%ZF9pBtN zA#J1y)vBA<28}7_AXQYFnr~H|_Kh7-uT*i(c%tS;zPiTdbdBWZQM7rnPN}!TXLhH$ ze(g1@SFc+yJyl;7I+(PPgRsyhGZ}hECnc&~vh68tgK5o_a03~3W2+6|}N zwRxcH1stAy zno5jX-110YVy>uL#daTLA9^Q@qcjbhu3|D@vW?*#n@p44!xkJ%9I}qZ`dmt|%~|lK zT|4(hR*aIIqd8JirfnR5Pxrt?-^TGn29~WOz5_?2OcwcWOQWc7-pHHRe@$vQ{veY|4|V8x~f};$419%n@3^gy{?Ny&gd-P z_~LN4Z@!s(!ff!kXV5H=sDkd*Jh3T~EInFhcwq~SqB-XnJ~M|}+rT!BO9}P^6MFnW zFQdc4%;em^b?2r%or#>?@^dE98#QsBIWlT03Ya;SgDiIxXy6jB6IYZ<6)$WshjP^v ziUnQ})3Dob^&Xc7g-@F#6*`W2I&IT+yFyvmIC0CqE$d*bBG_Uh_jMmi=IOq}Vh7Gp ziu+dGcwk>=b^F$xo11!$nN%4bj;f(^nH>Kc^-Px%YY$HL_hUxs)sIy*iS0PVAb3Y1EV~8d~_0r z4L{|4tk*Vvf|=fUjC;%=^xfJx(rd)v6PSUzs*@vdV|NzW(vsOTUD!jf@G$JV0uDGO zz&#vf5in!b$!c}gHB2NoB&s(G?)mSzPL1^5v2ok3J=GmsccTCJ1-1=QagWZ3wBfVQ z%lCGm$GB55PDwV}p5~frQY8G+2HGkNoTO3KS@Ml|nqyi=M~Q(KlSs2p=9~XASlwvq zyidu$n|0(>9j;rN3!kW;mLJkgLJYl%1LeM*3yxIi?sI9_hwz zzN0!}R+8U7RqaPS)#;Oiru;JeZt#QwO}nXABFqXb*t?^fw6cf|1xG7M<9g5t1H?+2 zAe$)T6MeFOaGUJfjLR!dyu@Us0S+EXDuCo#|4=th zMBGH<$IQ|}Kk!E)Kc*>mm-lK8%W)Vrz zD_pNNYs{Pz_%x#n$~Z_h5ntn&IqI%jRWe@2CHWEXhpMA&q>uo3NXYJ#gGpY`T#t-% z)$=z;&nZf%JM;|v(N1$?-vKb}b2>CMdXVMo!$42d$mDQ!7zdA|R%wUirA`oOu(Jy~ z?O0u`9^9<%-`r`!xTO4;Vwp6_TQ_#y(phinzr4npsG@9O<$j8_tK%dQ3>NrsQcd@i zMAfW&&=L2bX0Gx=g37h$oV=-b;Lre`?FiH;_-JuFtX?(4iXs=+s>WU z9tDP~D3YPejo0eKpo%~Ta@9Xus42@qZo)Hvz$rB(Pwms$w?4@ zZ={)m@>f-p*9qmE=XcA|Gs|7BP_B`qv%%|781M}me;f&6-5A@Mu5lKV>bQ2A=9D`) zrchh!LQGQ*_$qi+xb?I{XmM#JgJtfT^lgZ&daGQYPCLH!x>1pik=%}Rb~FL9VTqf{ z?XER=`p!wYQ{a5NATi|EXSqd(J1mJml@D2s@|xcP;*KRY%7a%dZ-)O^)>4KqwD|yoZn7<2{FOIJ$1_RcqHQ zzv|HPt9GqkepUaG@$RuHUUzTZlw*R>rwIqdxS~PMs}qqH>OizLQuuicf*CYFS6M6^ zjAQmX=g3(lB5|g0Q^A{V+jKKQBeSVu_#-)QeI|{1D6l0rEh=Zjq| z>%QZFc0AGcG=5p4>#l36uq_X#I7FX78^&MO3sy@<8}Ca@UHGm6 z4Y(5{17l+Zom}(Sx2JRC4s^fGG1Op6S1BuCvS(sd6MxqD^`%f-QWLgp-LrR}qGC~1 zD7h1g`4n_#dmC+Aty;3Oi~(J%R?Pxnt-``3S_baw1n|MKL0YyH8Y~v9!Li9&^2Ft+ zYD#oO33*{8ImFP#ol7c~q#pu5w<-aCwX2U{)t)}^e1hn`=>!HCFQQ+=>=UC+ILKBK@+K>Dq~fZq(0#r1)+R?@ckGr%z0uNmxks#dKmWmb1R(HzK|^ZJxOHPz~yQ zdjrGf;v`@k4O30r@LCU+%~t1tOV+~P!qsBbC3o7;fQJ>e0VN?-+chp{;cesm@iYiQ zL)j`woM|kSAP8m;Can}tx!T1zqKOsZJc6epSH#@I6B*77s9rdq9oioKsKV+b5NCXR z4R`7AP}4+*s4MA$1#+6g=^vBPQ2J{6_T;#}UIZH@PjpOyr*eK)w~ve-86lKY=#j3v z`(ql=Hy^Men4z63J97QzMjb3_Q)oJbT2gkB2&Pc}yC-@E24p*;IqZb@logd+yEh+? z0ld+N<~b3X4Jy9;bp7a(CF~-_A?l>EB8fJcZcrD8%Hw>d!S5R#-O)Wl&Id}ba zB-=eYr=bh7HtD6T7UCK?6Q~ym<yD_aXiqi8>MZtCU7OZmzg=7RN$Db5d~UO%cDie5 zPoGky_9>kxLUCrq%h7iA%GuRyCNgQE`{H>%s4&z>g}e`(m|J(5gLg9ehD+?m9Q)Cn zs>7+6FouxC-@nPiJpyi5M@LCl?e8YMn)GRtW-%=i_$J!5!N-o_v;vX)daB8}W}~fM zYmO`u*9`R|uum6d^}I1la7n6y0Idf`E|oZW+7M*bG!JLo8+2P)ZZa6+hLx~YUb8zU zyN60Ma}7q8)xe0w_4>?j?$g$fDPthFN#o|4l2n%&8Eua^N!`oypg%|s3vzFDVq}aU zM6Ewwa2iIrYJGz_2cI%2gG3W^?ooi4K^0M#Py4ok+Tq=!6T7gKH_Dn$%87oI;tr)HCLIlYv>Y>5G=cW*4xW-^EKHg7 z^q9JX>kInm8SF*3Jq*@L-bPDZ*TI`*ihtVPELNsRUsqPu* zIlM_h{9Gm(9ph{29`Cd)SDRaI3^YzpSDTg+O(LK4L43>j@8vj+E|1*BBxzyz>VIK_ zahi?xY%T%HnvikRn8fCfvS*khi*ZD@B^D-&#*@h$MK|u;bTfe{_ftcH5FNnEF{e%d zOdm}Q(W1MS79Nw{6nVH28+5x#8LJyHBz2M$0eiYuBGTfUq>3ntjQZMJ9qn<4L&oh6j(DpzXQRoapl$tbS2a)zj0wSvT`FfpIM8uxq{#uhlxt0U( z19h!$NMC8tHT|l(+)fkTJ|7&)u7GKmwvH%VNHV&}lgX7*kqSSZCT)`hUrVX1J2&pR zX>VM`pr@+E+?c)65M3@B+U9vyb%`5N2PPHsEypV-tA~1!7WnO&CKO$h6kxY8>s8ytSmV$+Lz;nDN;tGh@f(x>jk&Dz><9)m^-qIeXAA!@Mp}RpJ^NOm}UWX z(%bt|N|#^}t7!7P{K4oHk&cAwLFQ>m7a8|D7o|_GU1MpQ+B9^82^SZ@xPirL7GBFT>E}l*BEmdgvyVtaNs5k#`{`1NR|uT}3T6x1lPb9CLI%1uZg% zo#;Q;)O>ERX5>V^qf?2NudLnJ6%c~9{52ES_lM=o>D2D)9fXB zf7;|yqnP%2Y}wbliyLU5%sVkM!Zn5B60| zXZFVC8?i^@M%8h8T-HaDq+`ztb6Op?VAl_9RJ z(tORntX#<~dz>L;OPDALV>kOFuDbGB^1}?`jIFL*U8r@*Acz7YcXcXvadgaMp!h)e zh#H)WD00OWY6WLuU9fhF(iE#ryr4ui{mSC3_TthY*ASf`X7Kl8nboA!l?2n?6tRuA zJENOfGlnn5@^IYlGgnVeZz7YurjVN#Eun30;%TdPAGoP=C$5Tpx9r)OuhR@x!L90P z7)kiZC0fFStro&{3aBHLI1t~(*l&a2b!SJ@=i4Q5cmukm5CnAPAOd{51hx%DI2M~E%LQdQx^1){T!(`&ChA%(Z<7qG zsyRxFJuf0qq}Ey1>hAH;o{6T&r;JV65=?JKoOKp?X~KRjWdeB`A$A&uxthJxAuACPTUuJwtme z>5GFHc(tlCW|F{bIPV)XGRnlw-jVWdxf3Rs1cyd>le8>nB?-Yjs$K06QEPY8XDiJv zeNM!ieor)`}QsD7FBo^YXy#>M^k1sp~bH4Oeu!hoXLYs~W(!ssVhflIV!wS+$yg zphc~z!%Y4#85%e!OO{5ux&gSW65pH-o(^F`RGR8-`&mUx%FItbK=-pA>ZvN(mf9;y zV|pX=t1IC2jGAfnj3r}ijIxo$ShYQ-=|qnsYB@=*zPW7Cj??G;pn;naCrJ{2H>han-)Lz}N*Q-~TR%K4& z8ODf4YfJ)>3Q47PG_&0^y7$-w^4OIce_qKiDAftiy$JxL^Af{}0;$f|lB-%dhl?hX zSHDg(is9N`)nTL9W+YcZ<2T8>LGl>^xw0OgBp;5m%jY(n3dc!d5tPIUcpW`oM#{`|EXw_}?MAH!zOhBvISB(bJ z6s2mK`@9Kde8@To_)kQKtrFXa#Vg!A%B?DC?c>SPmiRm<%|oI>*2lo(l)G3 zvM5y=OhZ&%JXl3SJAW}SH~`#GEi;SQu^?^)sZTLLw+Hg^)$$*3xX{AjakE<^AZIc!enouPw*e890O* zv)p5*wsgDOZO(pYDrQh5f-M+NQg#i?XO$?#Vk|TNXmWlhEHeenSl%QNdpzYBal0iqpOl$VB!)#^kpBu3g?bun zr|DasL#3{2Lej8G-r1JuRrM_qF6R1PiJ8!)W*mRnFlE;RV^k%GOPF$Q+kI>2p1oUl z?W}Izx~Fr~zOA=*#;7b}GOtXCfYSpkL14P?x)J5o*g#YxPra4Dku(n1hM6~2C+x2w zfku?tGiyK&&BW@tMbb1P=o=|ngSt8LG28n(t7&FcFpqucUbZ05EAvEJHew&)VW}~*839Q$(~2VIR@%n7eq*X)NxeDPuLv^` zri!<;Z3UGyxF8kYp%5&Wragzr(P7%wqonNVX{6T~+}Z-F9#jT`zS~0XS6T!KNoC_l zKO1NEl+`km)K7_AN-K#=GZ46Lll$aTUnj94W7H+paJG#DgK+mD=3~~5(S9mw_uMtu zxBO&IWHB|$9zR14`(AZm>8#dApQ1!5Wq3$6e|apa+eI@|3*RnqE=eUZ_Qpn7$}yC` zuY@d=g`)^|b?)6uL@l-lnjXSH7c?igD}klk>&=qsH)_Wkycq;BN~&a6$I2Pv@)DVw zU^cbBO|V-B78bfmvsezk&$^!NR!rTk%FWVgaEQ@dqdw=xz$ArFqk_K!=vkiIgWaxC z7{Ej9jW$Io3A<~}`ciVCRTD<^Fs&_xxup8VB50(bSy2WpmF^ebMha?VI~4UK+m)MC zuxzV!N;F}xsPCL8k!Hhg+O=c%uD!W=9p!LCLWu^zJ!NK9togL}Cdmj)M(=Iy&T8*O z&2p*BLd~K+Z9%@&5R`iC|sMm zQIyk2#&A(w)pl{%i%1 znyotK_Sd@wDfBB0DkLfs5u!DC)@+mNxx4X$Vf-Y-Q4N4m@o@#sxR)V#O5%(<^CoSW z(Mf>H!_vMAUv^u&#3x^BgP&^?KiH z{X=Jl8wID0))!GADq#o7+C{Z4x(sQ(F{d`_J%dNwmh}lJGVIaI-nzIN4NnyX&9gRh zvM8(GE}-i&^0q`aRe0LuB%qX|uP-9fnB*cu6PwFRca4hmy=PgMj4s8CAf>Dn&CJC=H9%RiQ91w#sNJIpmCYbnjyq+sQyKx&z zMrFxrZrJ@)CoOwW9<0Q(8V7S)z@lb_d1;L>*BNmW4IsTu1;k+WFgZsg)lXW=plS!A zq)Mx?O-}@6zKkT|eFHpln^R4>%Ym8Lq9}?9S<@jg=@_BXln)WXq#$Ba4 zbxV6I+kTDsP#{;{%*bIDUAe2TaY5m7FHSBlO_XHnM68WYJ2t$u_iKugQ{0~mQplgTDIm?; zRJnGO8~uWVQXb+6jXWZE{B*1@VMvj-$SAw(!a#ZAd7a`AM~{qU4KX5o*jA0AkcWdJ z{U|)v9+f6|lc#n&7Uv4PU$&_W(rYlIBbF5KkIs+eDS}zftT*Rw#k4!6MN9F7|E3gt zlFh~nFR3OhZ{W9bLj?Jv_UezAQp_Y52+<2aY(8MF4Qpy=I^Ro$^ph%RhD+AljEhXL*8U6Z!lG0K-$?nt^p1pZoNYk ziMvRLoU%Ea*v-zCaKlAgG&@s&(B3@N z)~s16yk(OnNr4%1^pIKHo{fl@<4j|skP@v*=^VCWmT1+~P0Yzvi(CaHSdd~7 zIN_R()cF$V`(h@Z4u^#%Xc5;jQSAn4&NyX>p%%9FCX zI#$ORrUR(l5*qK1RZqbw(LUlXj)B*Pm>8DwNP0)2WbXU=>iWgS)x50pd;~Z}H$0e#nH)-+i0M&sghU4x`ku5?lx9mx80j5Iifd|%;dY-&IAl3V^rqui zn$+^Gsh!U$cv7AA*j4S)@biq-v$yc>XR*~DHtPKfcakYW0(h8;V=Z$Dm;;-$VB@&b~cvaOr)bC!_ zw4X{3Dm6Fmr&^+}M9X4&w$RuSG8MOIYRv3L_wL)IN>3H{(iJ6@sZ^=Ab62U{Q;SF> z-k{3}(2x_xd{gXms;vC_UZ;kF(;l`nk1!xp8!9y1>kXtm^D9YFc_))vy#0vTm-z`R z5jkew$ZKPoR^FSA6KTka@2hRj>$Mw2adZ?}oT1bqSv($BbB>Bq&+JsA5=zF7l!lPd zqT@um#b`ufvWBV%d3EsbOpH#B>o5&FImONqNKJ)wqgN}$hsQ_=DtY>1MuWaysp?wY zr1AI|*xdyXPl!K$mxp4j&xoEBAAbP5Ydw`R;VBnjY>mT8l9QEF2Lg zB8pNCCM@XWvQfsD$XpydE{1|43-OE{Yw+nNVNr4~&Y6kQ`;^<0_9-_h?Nd^T3~U&d9|8LHS6sO<&%`TgrOf?mN1ll+PmZy%8A52CJ9h6oP#0!`goIH^vyVbVuPNHAC!qD!^+vULQKD;}H=9lo`QI2AU!=U@7<89@ z8e5sTw)`!-x;D>z3`^r`wZ?=|&OSbof; zH--KS7Oz#5)OLN$E#gM8W~(dPnV$2fu9e+%h{q;!iMucFgy>QixAnkCM{JHJ&!1hk zX-{5S1;xl@8#SW#L@_K}?|JDLg9y_Sv>Zt^e1Bg~Wii}-$K!f-noGNwB>WasHb zfcoYwta55#bTXD47P5=DP@&2Q90k#p3A}6d`stpqJS5}_P~Dyi)l0fr^3}yvcCDIz zV4y>^QIW}6VtuFwkCKR$CXuv%a~qfl_I)b(?e+RZ^7e zR2QWc37hidhaOYmhM|pU%oKN)Kq{;$w_%WSQtuiQ$erWXA+0UO<{AyY=v8Pa1c77E zkaTEc&J6!z>*^A8{o>?6Ms1JAXDPLVIEi*6Zq5viIHOwA@2^m4-a4gm&>op#QsRk82v+`msoIQC3BQOI#!;iI%JIR&@(eN%uwWR$|C5J29(!XnX937Kd!ago1?Em0}SlS-mY=xvYdN z#FCb#O-!b1No5wlD*se)1`8D&Z1Q94qULRzf*+%%lW*C(eccB+`K9b1vbnh4nmfLw z*|^)gz?yyXO+*0bFh1`DXwd}U!c_4Y?Ic{+_1Zn>K$S9TVpulq1e}27%7s-emDSta zP*XPNJ`jJDu5EBlK#nBc*$sF?%TTR9Ik$w{Ib-%>Di;}DFs32rc=_B)BCaeKH46_p zlsR+k#pl5;L-#}h=G{!)xs)G>nN@W1v#IBS!^Tb@dX`V4LHmwjx7AFRn71|INt+b; z_TId@qsiUfjXfh82v-PII{m~uMbx>L8|ui*9;dv00B(Zufjq`OnBxA?S5Qcmt@3;2 zWsw{lcGIq1n)DDZf*jV<#D^os?Buu7$gj?<%7s7<(h@Dqlti4eBFnL^ z0wJe0Xp-y_gSSx&(>{$-&aF&DEyEiS72RM@lbck>$?EE?g)APwjeyh_bt<;9?+Ja0 z;%YTmU$F|!q}*!Aso5N5R)6Y09#uf-*96h*BT_^IK+YsXSz&FxYsA>X=dUq zuK5Eo6B|CAXzZ2qF1m-zXP#OE#Ovx0MMykTc_77{-lL~W@FN`|TdX`6u^x|;IYy$B#$PenU$!2>PK12W#-7p1_@D~E}vV7q}P z_Kle(GNG23abIVpin?<$zy{KYofIk080VA}0y_=K{Rz0v_Z+;)$x^z>>pnACN2){V(tpYWgqISd{UvJ}ER;$SnX=GE?EZOCp@iIF%1@|&v| ziW(nx3+1t_TVkE2#k9}_yww*`>oKdqDR7!%$2u@JB2TU) zteT-UEe&bWL|~X3bsKzEc6l4pXqV(hUObOi3SxZ`bV-8bN#-I@+lvCDIvRbL zvs%2=yp+3=#0)gf&Gr3J4jKu{cse?DM4s@=Ov(t1sf6A|R+KwM1ntB-q)l5{MVWUv zHn;*72P=6!5{K~3m^P5dL!1fuCDx37XP=HY9q%*zicOYfmlT$gBt*VR$_Bu~A>d0* ziPL!wLEn8DM$zcfg1BZ6Rvb^LKcG*eDpijXvzQ-JP(?%e+O&v7K^1wYDA&d(Rw-99 zC8S_+D+@9=9n^BCi)-t=X*6a>JdaCzEa-OxzdxoBBiG9k4du_+!d zCS;0aIg3!ppurk4M&bNspv65a$04XoHQO%VA&*G(lof+P3RQvZ3>`Te?1_BNEwKR6z6=DQcjG<~2T*>sNw+JR&4tB{ot* zusi@Ydv`g3IMIBrc>KTYy$6_NMY;cfx@R_$R)l+zpeS7Ns)Qknq9~FPdO|n5Fw2mZ zpe{Lx0;__80R=(9IG~82sE8n3K@kB(z(5cY^ojxo5Cs9V@PFS^@29G|s(Q9})ce=x z`3(eQ(|-QDLk!+f1!sV@W6XZHsjv%g;!KEy3lI2&{aH~G;Eja=pA zJ(jYdcZ9DIKW6BXy=j;vP_O zV(T!n24KIrD1+8gItBhtjxyFSHGb_2#^f}#=Uc5K*U!iejizb0#jmL#wUjdkE#cx26 z;Z`20Z&}svuvmP!Ei7rvE0`Nyo5rPUJnt1S>)gRrEPAfqh5LF@wP=~W2qx{ zsdv32OUp3oH|o3Vp=+{HgN`r$s^H!OC$|;yTW?y!>dnvQb~jB@X%K&M~@nCqI>BB;Eg{ zKSd*tE2T%dxw2hjC)k4_w~$diX}I+hG${tt66x@|ZOXC4&GvF_PW^DRCtSIth1cD= zVCCYd_aU0D((8zJJ?ya8)mt^ns4?CC-RjBxuEP{f3H`+4k($COO^aPT0e{1K`xfB zmOaL@_`r`~$~ztq=>57(UUhiRX5(_}c;JNGLCRC*YCqX;E{lscz}Pg5uU z@V7>*VHck-=|sb0L+v@~wnq-9uVUT^+gsA#T+g$Sb>kQC(}L?&13NA-UxywOR;2 zMXFyxYERq9O+C31wlfgTisHwpvT*Lc53ehT!MMDZZ}DMA>eo!=%I`+CdLNxFZP#7P z-}&qIF`3=TOR1eav<04SY0HtFNEUi{eth)ACSJzk$I<>*xMXjY|CFs?N7vsca`yE7 zfO@BFHN9>9%VnnFe$vKom8sV#?ITUGn=Z(zom|Qe)hm;fR({AuUtlLcdE_sqGK}h7 zj$F<3DPp*W>y2mqdonTe)zSi6{zbt$(j6wR51rU}OPT3Kx5K+`;%EI-t=tMr<&G*z zcm0Yt-9|2#0bQ`BI$v!Yoa^T4dW1B47C^NK68gRe$;HXtz(o%(Wj9Iv;y1J9L)&Dd zxNht99xm*G!?XS%p{9a_dJ2*)T=VW4XV@#NwI>aEf;aam9?BxohE9U&ug*nJ?(!j2 zzGbXt(-%{yOm6k~#+dBW*?y;8x3fIRR5O_()zfKb$roi)nr)Df64|&?chz2BE({u3 z$~MhXw&@nqz$V(;jt<#TCyjcJuH1UX4_oS@=`y0W7r&X+1)q*W{swj9dS6C7HL5$e zmYdgF)VOYiI(KkWL_b+bF7`YbN*_zqMp^&%olx3#{ekVo!Xc+eSGs#jZkpY%KgkFr zFMtg@%93lc+pT18i*${xdogrOe|OOjkoMrmJqU{jTwh0<(Hw&$tNG2S`M{xef`lEc zL6X(=W?NJT93#7eSZQ*#cC7pwUA=9~?~l?A0y>qKDwbK9u4Np0n9HHga4o^IxX%My zYuE?Mmk{>#KdS0Fk&aHRp~!e9ZL1zGZ9kQA>II`wc^Ar}1GYV0o?{;R%2)058n@SX zLumlImw3a&kJlQkpYF)l9m0&smvwXN$o5*F?ib<)R+gj9vm9;CkRP;O;_5kB-jnIe z$e3T?txHu;f?cAz0?{$W4GGDc-c4%Xk8q@&}@w6159Mb_7e1NB!Q>mB-&(88@gQ8JMIk% zZaAuc-&ns|<42?*u_4PX7RIj=5081Q_*xE)y?hC(Ux=?sqtm)JHbp_Zz5q?L?dZN~ zckxH$*64i2#0w$%O-BEs3mz)T!lAzT$*F75g{tH|Le7(nK6>+5C(G72wC?TepmzOn zANz+XGIJ5m5y$B4sya-5TgMXVE>_Y~{wkp0y5hDRN_f3?GI?X|ZZ+G6dYjW*bL zgQ2xI-e}{YjfOVaXzdq_$g6jE-1lhvVEv(?|6Y6j#Yf9e(Qhp~AY`d%e>vS(R(`gA z!+int+UplAYzaarq?54W>LZ ztUX6Lc9;M9I|lW%xhBbM-rujpcI(G2sCP-h9wr&l-mbhgKefz1jtd{(=jePB5`}S_zj_GSdC!9+$ zAg`T`wc;eXFJ!xwY+d8m9c8s?-;s1-)Ap;%?g;(SBl*U_zK7ZdS4-%Di;mv^V66$A z@o8d?J6M+5j*{OBlG}>fo)M3fyF&Rz&!cpLQvd3szDMSeddVZVDxF52mC0+4Vhgp< z&0}4ka&yrxjti&0Bdae8-7&aZex8A5wvRdTkO_J0vhU#%x;=)fN11{Lx2??jc5KK6 z;O3 z=}Yr`E2e8`&hzfrD+9&a@$+?gEo{_cx@(~>if6hjt){+y&FLYB$}0>P>vBR@>Gj88 zqo&jKS>0CT!LPJ*n+e1py9(*?p)`AGjKQ!jKgf^O`%6}wnnIn{CDBWXgx?*n#uV4q zME$*#?mW22Tz z?z|1y7Na_?HdrO~Q`bTK{aM>TuIUVIL4)q{cfcZjVWmuM>c;6-jPuG%TW&O1S=oE_ z8kgd@BD&oB`g6U#k`023j+AMkEQjlRe_Yk*4=r1Vl&_@8TeEZrVv9SAA~HH6&`(6R-T)#y3Ri?B&J}*T4i`KKss!@dZ>*tnboRtZBZ8+{e-Be zb@cK<+!-&}lBz2Q;xAqGdkWJ5I!UKY%w^UmFEh-uE& z=~|WUg|6F2z5RmesMT2^TfItMs2|^OolZSS7GigGMpm^p>KAr(Gv)U%v~p~q&3j}N zX^-BchIMLrT=?O{?n{R=;WL?D%5`^{hTxmNX*2)RqkoTg-B;c9z?B1*BwW6lM=y}t zIaI4h??!bWj$W@ zJ1jEs>}JUqg7jAhofTUZS5-?$&Z(1{dnR*oUt~INVmAVm}Ghv4Wjy>v&*#$(k^z~pms6pO6+dz zu4B{}wh0*)ld5ngOBtz6`Ibsny1a#?*>$+}!<`s=8;m%RRQc#^P>@v)cXTVY7Om z+->NKca!3Fd8iBM+ecx*aQ4NN=FJRuS%~|B4Lp@>dXSK{6Syw}yRU_JRbO{0>M*SG zxFpMLaB+dvefg+KeqQdzpZZ@n<&W-i!|ay|sh!e&<9l!j41rpft}-9^`eWqfVf7Bh z-ZkBIGti|TCY$wR*B%3JY2cwj)Oy;9+|XSd;#|!Yt+)l9rM4<>zp6`F8s43g{p5$b zx=I+;Cl{lvD3b{xvvYGcpRWxXJkW&EYR>ODBXT4xAN)YlPy2!r}iy_ zgAY0AV7HRFas6tnMMugQBo`RDd(d|2!sUj4LA1-FXsM9g*n?Xyy& z7QDxfjj9bi--|lHk9$!Ic&!(;f#36@4)8V;4OWjg+LN3;5QyDT#b-o#iYJc&i9xN7 zO>%ZkAOdgnqG2Guoo?(9{CZP5+bhq<1x6axeApZtGtlEWSZ(v_btn0pW6o<-Ek5Kp zm>CV4O+*b0;mFEcOLyV>}!&A4?YgR|h#udkznYEe1nz>Hi%BsPKtOOjz@6Ng3oL4GD zW^AB3BKO&7JZ?T;-BqwS0Qb3M5tI#F~`|(#IW#d5Acsh%GgjhIg^PFu3dxjk~ zcJK>*p|hbOC5D*=bE#bBc2G{%|wpK*~x(j{Ad@E zvp0--iy=$>pgfafWO6m1$#LLXCURFN&Ta}sk~?lGZ&c&J1(t88%NeN`BKh9J=X?AH zgLecG$-XnHg0V@?$h(-!lRciNb({p=;WIrBB&ROm=_PZRWUk;7G74NXYL>&3oV_p* zfh1J}8J^_qM?NQ`z?Vlk8J^@U<+=}~ z2wI>KU!cl*pAdmG2}k5?XJ7ITkcQ%joRI;s2&DNqB4=bkh(MZ;BXUM}6(W#E<%pco zU4;mwsW~ENA?ckoyUnJXL6t^8<&t#LszWrGMkXC0Z&~A1!27IEswO>=EQ@BET@ld} zIjUxwTcMFy`lZrlS)-#7sw~a6sHUk_TAFL2rHNKrnrWe>X;xaA=a64A`hbmS$_78~ zN4XX-B)O9&SvAQrRb28-ET`F(?EU_V)&f4uj|h9?W%D3PoiwVwu{qW80;~Cp{8g|8 zqyY?6XP&X-7VDJX^_{Z?oMod;%}d)rExg|tzp$fBWq~w?n)iNd8B~2OOzXTBrZrp( zrz)rW>@q9mmqKZQQEAUz@Ku?B(0i%MQyM(4573|z4g@T>C zq)@PPmlO*&XO0(NZ^gMa6bl#?>%1ioS#dZ@JpiL(owuZE^*|YfS17@Gr4pQ1D#3YK z39PF%+-$`cq@wvV(U6`CWR{`B=9uqO=cU;@FU{V0 zY4*-bvp1z7^y0vx^?1JxSj%!-EJ8n9gQlx z=`WEAYgSs=pPRK``#iU34j20DwSZBUFUl@BA$Kn`W7`Fzz}>v44P@}ItB&S*SX`gD zrCw`ha2KPz!HunIF1Pfq$1oHcNR~rqG&k2?F*DcB%@wk(SDw^dvpQyW8lK8hgDQ(l z2~O=vTS!$4%|o?w&HhTUi*@ArzC&k4EfuuCz{;Ba1U92kq-9BDRWZxi-xsU}e9()s zNrucjs0)rdn!nC8-ji!?>z9u*O|^jL>0Wa_6Pw3;f6T7tx?YfLwsXy_vKljvF;5(2 zNq75vNjK*;t2bnAaxk+tQ&^>?> zjykCVhiYg6*YKW(4;ioMi-1O+(IjxPxb3-|N$&D7v1KMuCjiGj2l(e3)vBIP%urTKH0 znw-R%(d|x;8-+f#&+xYyT{lZpX@^;V>83N))bszan=_)8v~Y8Csb5CPGUY6-p6TwH z>+Xq}Ys0cIk$( z$)l=ZsxaZX*!*4P7c>eFC$;jnHUbLb@`ULHCjB}$wkO6yk+S;K5h2$c%Qdrm39Zio zuX~UcMK7Y@kNNVCr1nbJS~aMDQyV?r8*Kqki+qEF@7A*U4z;qanH{L!xMY%(bG`dE zFmeS9723x8TdiViYn+6N$p)@Q)kj-vNbNmAnEnz~dSc^J8~z=v2B)dntOm?e^!Oqe zc4$UFq~?JBM-EtwmL-el=<)(9(5y5gXQh?JX5?uIJ+05}VZD|Ytk?3stv~s$a_qId zV7-?2XI)lK(xiwewOLqSnK7WZk~1n&{3Ac=b;vG{>g0JNPd|A?Cn9pqGM9+bkbCnGM38*p9sK^M%I1Q19H06U8xtfC1 ztO|jpmS*%r(iwvOJ!rjkOM41eFBE>DxXP%W3SQ1#f|p1; zpTPFeKBJ_a&!{WtgHB1#{ri%25u`kTt}MDBPZcRZ0hp2!_% zS3-?qFB=|@^TTAeRj80%gC$F#y4;9uXZzp?yZSuC4ze#LQWFfRj<#J&y1-O!l=2Qc3ct|HhRW;8< z1TL3HU}yww>f-IeCh(lxW^Fk8XOFCmzHLy4a_2`GxAA2x)_PUt=7vdGFgKi=>ro%M zIbQ?8oUefpT{f!H88CRV6a;84vY#Jsyzv(nO_RhFg`H!7dX)rZWz^a0?fqlmyE zBEK1MStE)gTxc#Ru&iYRzw86r6F7x)Q6!E~4SS{uDlC;ZsxMnc8S$Fc8{-fSx3UhD zUF{mxW=SV$R)-f%r9Gm!V)+g;MYk!Es*35{@2wCrVL4+78@#yA7Iv8G)#In8v#h$> zq|jN#(jtDt{ww_V@LQSAvg$S~G^p1e)3fK9gDGiL%$qmWTvXL%c9cW|uQZXn7vb#D zKm0vNj=$=owa;hY-y=T$~kk^3urLC1iUZie23t}~BfJrbBeT7W!g zo(HDLrkyqe*W7}C$|@$d1a}9pB>~_;so-vJTc+N0`cnTdA5f1M_;L&baVSq5arV8y z0^aULBfy_~(J+vRicc@ADtEc(O=bk6vbdg>qu#XFpakccf?n~6_r^$up+7{jqQxjH z*p%5>YEnd4q>v&4PEp=EYRP{Zx3ufrM;jkht+0R;#0^DhQR*pL=H%~5PV8ZAOX5rI zC}9C#VImh6XFCQWaIA~S+2Mf*JgJKqhmm5!dbu|;1|$#-YiyFU(Le+e$V?@!GkcQr z#eoWp11k@{1hk=79tOtBQw_dVg%OG(od`%d+*r#QMG+#9QaB=K$NI2FfN@y82W3q> zVNvn_zqf%GT4_j*Tx#-+%+Jf7Jua)8RlP%+$_gfjF}bVH-7v6aBKgK*W0DhUKt=~# z9~e~A7OdwaG&pV3XM(Zp=E04I1iXd0&<;<;+eI=$IWCf=vAB^cwJ7CC4fa2 zJ2%)SKn4M6T|i=XBTO2#8~9Que@`A76)g*^QsC5Wet!7c?y`Qi9i;@oPnpP-fV1lY z5%^>mk+Ww$*I5>ez%@-+0?i($YM6v~vX5mLh^E?`dc1Yz#ngq~)CiCgtErJm&h80BAbD^^ z&YtB9I|3vRj>y?ofe0iIj>s8hD@?DLMu$qIU^K>m`*wMfC7$Y$ai2PQ#MjCEJp1$W zJkQTFnqM9CnQ=w4B8w|&vzqs`{ViGDH;Zps2pNHZsJx62sw^Pfg|fC8D}Le2TD~?^ z8g?A|8D3$8e0?>D2#+QzZ40=%wacZp)|Yk>^W0`z8Qn#!6l9j2G~|px0f;suQ2j)i z5z>G&LZ}yqxWx6!b2|-M`W|62l1GC&k!zmi!KWpYkz9yCO5liT*g{MLbql!VF!fSN zoL5+TP#Ksu(yWFi3I6GbN1Ozux@kzNo5s{=V1;roHQ&;py%LSHXFE;(Y3cE})a0ki zjfzo+fuOHBLA9B?a<6MgsT$yBCUSMi*>-^lJf@4t*;#=I{74s(v&#b!_?0dqXWtIQ zwDi(J8?GSsiBTzwEUM-O7^48Y7<-^PdiEsopW(fY0f|^MGB(NC7XlGT#E!^Wh`%^h zpeml}?F|FbRD1nQ6)?4_H#Gtz4Qgs+lCwPn5l9{!k+Tm5B9J^dB4=L?L?C%^M9wH% zUsDAN7V7oiv$^{AyP~Cu>XE4eb+XuJaDJZs`FWn_=NTWHG%Yfj4Q+%$C&>tW zu#?3pH$CzT8fVXTnpT#adu1{%sR9y&%W10Is2HJ0Umw$o)(Y-g{0=*cH{j`BGzvV^ zL@of%z7~kU8@h;`t+k?aCJ*v}&oPm+$k_vdn3l41P9gU2fs6s)<3%0d8D7)|QWA|~ zY?8Ch=d$un@2T0)@k+V?LY|~PysIiP?;=$l0pCWG|e7Kp%|P1LN;oDbe7(12%0H1I`%2K-7y z1CwqSN}SE5VX{p=rBegr)Q%KVJ5oyR$Yh?{ky2_$CiB#elu|n~nWuInO|2GuWHL|g zNSa(n%+otUdgD}1z1pv-C4G!8|CR&ILDu4_c$orH_f)Zn@_L=0*WmoTuI8t8CEcKv z*VO#9rj(Y~(|qcQrmwWLk$2sQ`41`PYpuAl?_?f$u^$IoK&o_xJhYy<&OA=JXw0aN zQZc9GZnn-K*3nPW6q-VsMiZy0G;x|v6Q}7jahfg@`wVn}Pg{|%@P!7^P*v3+eF%F+u7;}Mz>kZ+1$~NViS0P z7j=LKdr=#Bh>6N>objEEgBjTY2E>f`1x{^|z|UCS+5WH{#Q^Z&HQh%trvM&mA{QlR zTlwOY-j7#d@3P?Hg{HBo*Uau>)b~ZEv22=Jv@evNT9X{yiX zndVD^&wI?*15^9la9Wz`b8FKa3qEf)Uw2OJbLVMks?YhRd06oIW%G5z)IJwYOH+Lw zWt#5{K0j@~E}z=xo2IS#=4okav}c;;XF{|evM4W@I@k>K+<^L5J9KJTBFruuxsH0K5fjPXYYkuu{y9eD=r<7LxSE6+5|=h{&h z5WstQr-eJX&F#bOJgG3|ymaX#4dT+}-SGK+JIYlM_^63wj(4z9)4yDGELGL3WqBjg zm6_kxT_(b>Y~N2^>XXiEjP^A<3hfsL9}c2alk-PyQZq2mUp9cxG?BZ+bGBX}0*~;b z;#J?d${mfB9F0xl=mp;D81R57qOnQNg8TAw1j&*9J!K_b+1nil;!;uvd`V#KXApk_ z)lug)I5{lvfW%YtT;apNjfzsw4w~U(hZ+^B-OH1*)DCzOv1o@$P3ifI&B$inSPQtP z7Ztk9HumAGJ*m(Dcd-v!o>ce_5g$(Bj=)=+yXxBCj?w{vN14bqNX||TMBr^+lw}P! zaxJI%pP%elt5n;oS-_AodeL}|A4t7mAwCeYB_D~M9fs#@1R ze8E(ts^Xfkg1R77knsXYQUTpqkSCqfmaiBWpYt@?Oacw)!kPGC@ zb+$?M-T6ElhF@ey>EFPYd(kNH6((|BzGM-58+zq2V62>9b+tIpGNrZbD8;#{dWoHE z?S)6(RPrpcd8@kiv4tI_Fu-k1og9wAW2N4h-|>t4VSk#>pQa{>Bf!F!$=pVX6EAcD zPufu`68Jx#av#Z;V}V~YQMpy>j=n#eou}+LyE^ldC1($=)0jk3nGN|q)Fn%thv;8< zDt)`Da+I+Lc%=_1n+-Rsar^KzJI<_5cyn{+I)x>$bIrrm-dz6uIH@;iBt%E`&ztJy zc9f3OD9k-jxz=b>hNzGpK4~A5HKkchbA4=?rZ%ZYH9H|{bSUlNl}A5n@Z&+`-FE@( zz1R~+fIFK=s_fDwxxs8HGT7Z~FNYV|QJNRMGWp@gzJO7 z`WSGr7qx-0#eB$AyN8<6yS;J?c&!&@&9YIw-#(-`g)eS5D?XgU(u{scE&=~}kvnc; zN69+y&!2W5$x9c2e=||f`cmsaNi$+P=EMM?ZGWLuhN^?>8 z8t}}tC~{8p_|ve!Kk_lOfKPhSC~&}6ZVO1n5(AJ5Rr_FSRI&pM?RPXSkZR`bH@kA9+V6rP7fb=FU z1$h0Cd|=y)CV=~SQ42^}<)scl>Ok#-DZS9rvX|>)A}#5hL_nb#6Vwd&Jt0mY!O6u2 z$N-?4;1FkLsyKh_`%4QLhQjQUH#Z4A^p^82Pz?cmbqF5Fh%OUP;Ddn$q+G%RQmk?j z$EPYHqwQT=J>HHo2m)WUgZoIPFu>hR5jku7-+0RAMo}RnNO=$T8MYHL zwv#tD4kT@bUhV4MnIIf2Ni`4-$rBNf%q?Rc)6$fa=EBMYnr41nAO3)4p7QCCKmp0O z%F+;3mS)@qm|C1$eQdU6^v$W|__NeQ{8@jVj-rmu;)_et@^K;GOgQr_f z^A0;|s{sdV*=4n=PzH$%gPsgc5-)(ui1wog&C<)t!jhFdVVm; zNCOQ5hFln!<`hU--kXi(%?*~C)e&1}IcV@H$HH(ncSVBYI9ScCW@p_u=M^RrD`dvx z>y{VABW4|=3Vv%zWl)SeblTkG&(cDcZ1p=NsjW1Q{<^Ol9?@lh?>W||1u75WY7~>C zrN3~rAWtO;m8S)%+rs;nRg>`7@)znBa6>OD-UOyIqQcy#xR`_UR%L;yu-+7L~Q2m)>Etvcj9gkC%;CMWDJWla~{ZsX+}3=Ir7F)?zxjXsAgp(sncEZ zAHU3b`rD$ZwYizKnZhdl_+>SCrBy0N@w;>GH|G@!F_0OPJv0~9l^sXen015s$g9EcT3j4^<$}*Smg3Kh4OAx-av>wv|K{B)Z}eG$B(0gI z&fQYg9=DU3uGD9$TBu?f^a`4#5j3sPvSvR%#Zu$JEJwq6wAoZ&o8IqC^DlPPe1OA1 zmfddz#Xu_D1O3s)_i*XREa`PSAN%{c!jv`pxn3Vz6NmXt=dLsktLX<(3b=xuCer7*TugM7%be94ncEYsgUFLRgR%j_twfzRC9 zeIyq!;ImDnx7qDU&R*q-ZQ!^UjRPmTbUAxRAOhd*MQz~eUAmlIdFy0`=3ArQdf@18Pz2>uD~av zDju8U>@Hsiqd@AyS>$XtpQKSBiFZWK&JIK%xpzd)NWa7gq$V6OO}-9Sr9Z0RUdy*$ zfJiMJOJ!v7gO&-Er3q6RxoKE#RJO9=wIUh#MLvfu`UJUDRWdlw5~DKkbA7T}}Yj3VmJp*uU=jGY*27|6ILr7CIeWf}(sO<>T>=5Vv; zQX-CpZ=y6R!kWSoeFX~jBilY!%UWbDOjA+|(+aDFX?f$#-1rOW&svM@^_WMMEa%&Q z2mkvA5s+F^%`_sFr2)wg^U7RR8_6{`Byb_t4n$v|ORMbpR!y`Xl~Dv@RT+^mP^oNL zybl$;4;8%24i}3kc$e4dS!#m!!rOPH{k5(G zWLhJgA|1=68}>PPrBz*jvw>{WP5K_u7~Htj)z-dX^+a3kZ{*Y8BFz8d9Fjp=vy6;1 zX0CHG4+S!T6c%tIngg^aIb#ATL}1ADKXEQe2Nb_)rHCl6lG4PHE)h~a&6(bSj28pd zj9KLPIzM^yIbPSd$TsnYOTUkoxJx%9^+?HFaJDx$N=+OPM8L%+l8sJ}X01af%b5F} z1uVp0Rv3)5f0=1l1BAe_w16kehQBw{vwV0hV9?AigN=gujHE$bY~AGwKk~Pj5Z)X_ zdH6S3IQROn3g#jCNnO4ys+O_w8*i%x44MV==mk=C58*D4Br5dX7IURvhdBZ;jQVHp zm=;{``EzR>tf5+*m@qcbJ_-}C#sDOaviO@_Vslo(l)OB_(i!|^OL@}fj5HQu7{?p%^0RbQG^XK6&O%ICf15g{5n_6ukEsJB3UxK&V;c1_b$~?Sh@6F(3Ijz| zz0(|C;2pQ`G5A0b#nFSw**83GoJu5QxnRPMkCf~Nui42pvuL%go@yE)+TlFf?BPIF zz0&k{_8zlE=ti~u(n(ddyOHL5ONFsxZ0V$`T4N7DP=?R(@#li)K=CIdZi_Vqy( zytT=M27GNq1E1z;E#RaVb%3`xhjE)Mb8F!*0~)KY=h3p8LmqJd8hG~fp# z8u;^`)&l;>i#ovS#*iY9O(x+s4Q>?C!21On@aTvJey69kfLD4^2Y7F!3I1`Q0hjwm z2p7Dy$+Sid?jF&=i#)9be4iI}fM1FO2O=8y5>IOZf9ORW;NK!m@Y8_?T>q93E_lLZ5-#wFhz35@(^|mGy{H4cJJJN- z6KKHMw}v>tTbWGa0PY&m!25Yx3;13y>HxnOX@ai^G~oRa4ZP~NeQN`*XCiHF;H^Ea z1$?a+b%5`QG{I*C8t|(T4g6@J0h`|mX#=ljGU>O#?YyW1JS5Ttzb?>#AB465kI--Fe2{ho-5e>ZRorK#0zRHU_zynRBB>*2BXuuCd zH1JJ<2D~Stfgkm>7I3Za6IuuON)u@u;B5m9ctk`4eGLJG`g^{6nM({!^d<*ZV;T7rek^5-#v{5e@tn zPip}`=S3ah?U5$<&Oie;?+$T*H#M2W0o*>KfyX_q1$>7Wb%39ZG{K(_G~kaT8hE82 z`ql<~u8Fj@fw%Cq7VrQs>HtrRG{Nr-G~iVc4g64`0sk7&z$@QFxGmr-yr=`*-$Ysh z@S;Eio)yu+HwGH;2N4bYh^MuHtKUm#9pKANq;Y_^2{hoL5e#lk z;K30Me3GZNfS>WA4)D8?Ciu2M13n$mz(fD*YZ7)&l-TL&8ObrB8x(Le)! zKB9qd^t2Z6cV5&1{>RT;Xc`B2HIqrW!0jU%_zi&ud}l-hpXX^U;J3Y~1AHvf1V0{V zz~|l{!Ud0-Ou_{&ifG_Bd0Gp2kr#D-a?*tm~uMrKr!2`aQf!ml!vkUHcS_^ox z7j=N2iZsC&2O97P5e+=&K_3Tj4HIb`;2}?I0r&Qz4)Cp!Cis*<16~% z!6*1RCKI2)UA(9RJT=k;pW|sQ;PqbA0X`jRf>(NoYH0yq>O~#kaVF9Xflu|c7VwK+ z)B*lB(gZ*4X)WN39wv+q@E{YZPw;V`)&hRQi#oucM4I5=dRhy(#;?6k;2tJYpWuT$ ztpz;Gi#ovXMw;NCcv=g%+#}v6a0e5qPw*a|)&idFMIGR^ktX=Np4I~X#fv(?Eq>#| zP@mu(OeU=lc$61)fS->v!Pk0P3;3`Xb%5*rHuwZ@XEN~#9QUFQ@ZFIn_|u-&0$%4u z9pGb;Cb;n^RnP*i??oNpAturcfsgmJ7Vwi^)B*l9(gZ)|X)WMdj}b-(xWGi}6MTrL zwSe#Uq7Lx3NE7^1Pip~J_?`C&+{r}h6MT@TwSXsiQ3v?BNE3Xkr?r6hdr=2C@A1$Q zz#EuMS^{u8FX{ka6KR59=V>hhWLaiShqsBq169(un8gVb@A{ZhrU;E_CfF;J2GhDjj&K7mWjV zxiM&h_cfVl0^j9D)aYN!7nkHXae{5qH*9;ktTSRZ#!$E34FO1jRSvZBF!!M zx1QDlKI=Oe8wXx)BGm-n>}f6F6J9h9eD8NdIl-SanM4cxt{061U;DkF34XK5L=*UF zFB%7KcU#Z|?`1O41isCS#(`_!9yGz5n@lu;`*_hf@Gp@j_!)ONYoZB!sTYj{?=q3* z7W`{ZYXSemKQuv!TdeJ!WkC7&LMZfIa0&eL=)Lx4dW^ctEtu3Vx$s zWo-d3@S<_xE20HYaNDnowt!2#XdJkDv_uKs$ggC!fO~q;IPl3x6TF;XRBQn^^P+L! z_e`W20{`68TEKbt(ecKCpD~eYg0J(m7Vu#&8V9~TTFV1}#4p^nfZy<O@B>eT|C;6>xW|BM!(!0Ve##v$MyUNjE;U8D(~{UC{K0XO!d zap1R2q`3v(?`bXI3O~o#IPfA9sV4ZVp4I~X(u>A{C;!43Q%&#(O(x|8UhhTYz&jof zn&5{`CYr#3Cjt$;hRK8m+$5rbcL_A${t*rQra%Lp716+-2{hpK5en2{hm{e;+Cf{34S{ zWdXO1XyCm94R};U1HUWKfS-tH;Hv`-ct=D7KOAVlfj@*IfY&gYwl{;DL^SX&fd9qaaH_@#jc9F1t;*998z;Lo85;5AI9?akmO5e>XcpaJ)fXy7*m8t|-$2L4Q-0k4l};CllN_;^GE zFZY+w-VCl|$GW{4erccqM4bwrX>Nh zI3+(i37pEes(N1rW_iK%oli{H`Rspy^M%uO?tNGHf6n3G*ipK`e}CSIwy>j!fGc0> zK9VKA4Gn(g3tq%`k60rVMfX|!?{jZ(XMFiUOvN8N{8uCK&44252RAx0+xCm3%f8`A z?5Qu3PXDGOvEjW)I@p$8*o|H!ZELG6Y!xq(o^1;%?Bgzy{$wOJSr z-|9-o_T(bzowgpr-r*u?k*#yEvA0Ot#+EeLbz3B@VXGHxi7k?TZzT4s7D>0+Y6hE0 zi=<0zm4cm~MbfFZ_`o*IB5A)nT{77tStM=!eMe#gW0ADlU5>==!XoK$BeC_bNczqX zoTc0CSR`G1wu1GrNhmORKwjycb9!FxkS&_8Wy^h3Qup((yyDw*>R+03mk=R95 zB;8{7>1=T-k}kCSZ}uM*NpG>+YBmQIN#pmq((Pl%B54b|GiF;&k+ibi1heO*NP5Ib zY)C1RZnB$Vc8e5ApRk)oIL@gC&Uk2slO_MkSJ{oc$c}}pRkO*5#~W#GHL!TdS(8Ty5ih{$?fd?V~M;jfAmku zh88K+FBMZNQU1~h8qlmb=N(@*;^=Q0^aeumvOJYrva zM;?{2hK=fv=6c|>?z1VzjTxRi+h)u%B)s{?9z%k($m*G9^!av_ZUDqYkN1+SXBry? zO<>Smm=?$1Sk%v`DcZ};hSnB%B-jOh$cs9_^S!7A{D~KJfIl};oDF0%{k=st)nBej zfTT$boZov8n`Lfb7YDJvNb~xzBtP*=VvY?(euKetgD9;7&e2}vsl&iyOeAgXJZnA} zJ~gm`=j3dBq(^-2=dHAW_-t0ku8p%(0u6{WrKQ$od@kf(-=V8l=c?MoqFvf65=!qw2xai7U{O|e(swS1D77ad zZ^VGuvcH#GkZn84Pyr-vnU3P+CO`S?0B`l87Vs%A%0{wggRJ1V5M9;aLym<3i~=mM zzz+`v0N&$8b-Hqz2=J{41L17%> z!;tB$QRy6vk7=}8oA+4)c)3WahMNUlX_BdGp_R&_Y-1{~m?(MGiO^KKQ$<|T?Jr_k z$!%yAP31X`ntnX%deu_p7LWi7x2nvn@bWXOUCjfSS`v#m{C#Mxz~Cfn7jq;W95B<3 ztNa-jaw++Zih@nyV6Y!jquS8?Z0%E&wNB{__95@3DI~2?J&pxi)Gd&j)$#TrZ;mOJ6e*FLx=Deq|(fNfzC$YOD3U?4@Yw!$#sAE=AG}Mq+Da(cPm)ddiMPOUK%} zKd)*jk|vGBe$1k~Ta3i3TZ)#3Z*d)gH?kB-Z!{8{IE(HsG!k!UDO!5*t-%8Qa&y4h_9gC#p>>&z!OpETe zFcPm-DO&o9k#4bLk@R!>kd3KDcPra78{VE$v~;eKcqvMebe)md&02K#h>>_nO3~6$ z_VkB$pA<qybk z;di+~jF*WNNgp&4yN-+QZZr}v7b#lW#hxPa&X6MMXd}JVKXNS0RnD^yd51{R((~=P zB(DZ3l6E%|`eaLG&ilnQJ#GdV_acQ8#NNI*eF{1p^IK z&sFd|I~Lt-U?0BBld>DrW_7uJ`1PqsKei7a_N2lfHs_~R{l^P4ih;k^NW2H5NV>{M zY?CjR?g1n5UW}rp*Z$1K#Op4Kq_d24z8#D1uC)(&{YBBzcK17Xyw##eI@CyP$S=D4 zkdb)HMbXmQ4>)(cyrM|j$w=(tFSO?#6y44Ig>%OnD2kTeZ6sbS zQ6ybqB)*wYboWyu@uG=>rAGCdU%Hrhr$mu-qmg)hM3J=hubd^`6j3ByVI*D(Q6#PZ zkh8@5ABv<;8i`ju6iI76>@4wCha&0yM&bnyMbZktc9wWoLy`10Bk@{>BI$2N;tdQ% z(lL)Xcf4$&NP5IbyjP(}TJ#%diB~8TNk29cZ%ZhWcKfZf#ETJ%q%RtYcOVo=&w12Y z;&lf_(m6)r%?3r%N{=~9yu_eLI@L(Lub@bJ+DN>bph!CWcg`JeAt;i*ZzNtgP$X^f zxUR;hUy;NAL;6XyM_Ln%K`Yjt`nA8hl3(bvcuhMsH=A-e!=-SBvo_~Sk(Xu!^&NdUdjsQeMtWE*2Q?q7fAQrW1wPvxY1-yba<;X1 zKMIW9&+p;>0kc2XtG9qymXQniUxDTF5&mt|5OXUUQF|m9BQgj9iM0GUFIUW(VPjyR zasDS=6dY$%XWo73l1WZiywH7I`2AkS5hYw{R<5_>iq%=O+h@%lJ8Sk)tDQCbtl2l4 z{I(vSBma?ozLL{FY90pew-0{Ni|`x!;4wR<5g>oEmjPGK_+JV&+vgz5U`*d;Lp%Fx1y5p}qd&mE_wnOb`DJU6s`$d2M4 z_~~c3k7Q^Ae#VR1z)MWzMmx^tuIzPzt9VfxxPupUfIFI~JonLz#ee@^(KiOZWLf4| zxcM2V`0#2Y&#aEEX0Fr7CMr3zV6M@`%niPVvuoXq3KEr7nt06gtSL+l&g4Umg`j3u zeE6-nj6-W?Wz3lcbJ`*vFhfuIQnvq0%k-_R9k(6D+DM<6mZoaYFbB^Gz2YH*PXv)N z<3IJe>a;Y~%JWTgo8aIF1|JBb*q>tcx%sp-ReJ~1To@dD)8L&!q|EqFeeN+WO|^1> zX}&QyxYFPaK@|H_tUiyPmZoaI#Wc?e4j9ia4AAAxsPO6 z0-kCjS7)4kG!TIw>mqXYP#~)BrT-DiH$!x{8T?HU{n6m6-hBHx2Dc2NR~g(Zh!z<< zJBSGNf*|^o!OMf_%LZ=Tnr2XaJ}@m!^*Ph3CTco`x-I!!Zd#h^bA8i{+Ge4Nm3(eIElu^=GR>&* z7g~DBXM0+j>hmbmJjsqSv@l{s9j@f_4b#$0EwyZN^x7~<0>1s3VQ4dWsu#6^rS@?}+R=L&2F9KW^ZyyoGL;RyYH|Mmq!kvwGTGnFH1JTE z|2OAWrZ?LsD_cL9F>6+p(sbxVWsXuaulTR#b-Py5nl62)R6AD!zO z*dOg!2to^)(liKE{^V5)g-jI-_O*~Htxx;1dXvSU1))jZ=S{Ad2isA?0A6CE@{A)^ ze!W*71IEgEXOPO9J%#5_P3d{Yj2T`TrltkVu~4mZWNm8Ne&;qCUKt;K`dv=5)xh&& zE1oKY&-W>80fUb-4_5v7Z~1`%Uv(dd%z;V&KsEc7+1lX>Q9)49Sim@zFaNK;;f&gC zW@E(}Gx`c(u$uee%9-{v#VFaJxiza}UI3;Q&5)6>z0M2bl7la`QeWj0*9QL8M7 z%GY@1F<`7*Zn!ApPPz>64^w*9hKn*x%{!Q5kA{mX&ieMN4Hsp6^y$|%T$I0J#ZzVQ zV?Ko~VDM3HxS0ESWDZRFrQvRqH5+ZXQz_$kX$^NO8w4N?_wsVXMVoq%hPyVHR^%G) z+BDX#;|XrWooz>{M&Pa{>fLZFV=V8L$AGbNx#6OWyU6nnQ+n2hi!w}Y17MCl8ZN5K z>{lBu%J}HhuWPs{uVBSfW$-I~3R}S7qug*Yw|Qg^O!}qazM|N0r&7l8(i-kmHV8l( z?#bnbi#GKj4R9jP}=dPx?haIH>(ypSqE%_XtmS$>cBU^9W-Y-SAfgkpw4)7CR z)COK)BG)H4`=%#$fOmRP8#rK_Tx3lPIB25swNWz`|NVPKuaS>f78ZqUTxsxzAd1VV zSligdv@})w5Ys#%IQYE5%Y#Un@t^uUc3PTh<;|vfR&YSuxFm>Te~Q)T>C@805-S=9 z_%)F>@LeWyO^dTn1|smHE+UrGBc3L_fiWPq)zjD{XCDhhVC*TM%;6DF6hzjNfY??~ z!`{<*-qSEJ_EcI+I>J=m?p2G|%|-Sxeq}0np^5NNm>pJwgOuf;czpCyH$1HO1$UI8 z6!@$!B3cMs-HY15-Mwfbu;oQ<;OD()A#ktDoq5-?IQx$)yi?#VCUQj1h653Ja2JuY zmA~XI0yp!bHt-cDa!xpVRUiV7^P+{ow|41rc3mI>Z|x#-Hs?woAaE5Exo9{$A`pQm zbP+kbClG-Tb`d!nxyri+E;NyI&Dm!I5%`rZB4^(SMBu9bbB67C= zHNFCX8=J_bi?b~Q5x8|1k+b!_;w=Illz>!0B?feINo)^rCSf!+_J} z?3;lIWEgNn&Q|hWcpS(u;E0?Z7l=TH0Y~KQzCZ*r3^*cZ^L-Z{2QmyeB4>;Ql0+cG zfFp8tYp@7p7;r?+7zxB8kYT_PIeV+`iQ_j1wJ(ZJ8Rj4`PLe36ON8hA;d0nd$S z;7dJi6nJe!1K$;B!2gKq1iYrnWU2f~08nmgUII=~Nk(I{}PAE!FN=bA{%$#AxJ zpfPZLB8Y&OdC@5F7BA`m@A0BhAS0iI58TSeCyj#f?%+rUKEjV zSu0#*HT+s%`$Lm!Sq*TN(>$fR@hT$&)02LzY5}sm~U7gfps6`*H3qSL`~>iBgbq`s}&0Vn4jl%fR{%!@Or*oF9dRN zP-|c=6xso;*>jyx8W)PvNKQ*v9(dI-{s0-llm@0{$sG-l;Yw*>1|p#W<0cMfAQBpo zDpPAz8*?)$D)5SE=mKA3GFiI-QrDsh9Eb)uFoT}NQ5y3Y;260yHtL+CY?~My)cKt3 zxk2WSG?Qc^_2#Jd!9VehWCFOAZxEwEDqka^_7AjHpt9-L{zQMZKT7RC=tr}SCc#v> zd^;RSjcagVs=QH6086$1{iv$Jp~5Cg6~@JhqXa@7a%Iv$z+9Om5a3i*Jy+^As%Wj; zsONJFs}8_S6y;t4`1jNxy-ZzzNwl~CmXb;0RJD{j(lk~1Y0dJrU~8L%Y?s2X#wdi#rl^wmu1HKEy9befo*0-xi4ZZ z@@#)gk?kOJO+8=49h%Hn_=YA~%sA2C2IO77m&J_=7B?zb%)5NqqV(G|L=mMC7JB!L zx_AF0i#%%%);N|HQA(^leN}U3t3X!K3r$vj&bA*?RizoyQ6WuHuaP3x?XLl7ulPsm z_E)Q}FTUTp&jn#n0J1tQ^M^D8g(-!a!&uPlr+K+RF0lZDZVRu+`L&l8kp5Jx>Z;0( z^;3kI+Rk--wd;>ob*>*K{8Nmh{4mkskp&B~5*TarEVYV=ndBB%*Ii0nb-1HuMO8#B zl|EogrXt$>t4^W1)+=89H3xrYM`3MzofGY4M-lDzbthWwdau}3IysR^y#J%H421QH zAZ6n=u@-V4w6fJ(E#&D1HCGF%E3PcHkWrmmwp!@JFfdhQ+6mLZRF=l2vNSA}rBSIY z4N7HcOtO&W|I%#fBrlI?s1VaoA*P{1Ohbj33Pa%Fs5MTG?njt?pn!~5*ibc)kp`;6 z3qSNJk0Rb;Ug;VG)v>Gj1ke*|Ap!Vf6CI9)%X`(t2FF6UjYgrLc{c{!W0TwLKJJ%x z6qhfuju<-R=+4&b=#a&hnL2o1W_se!CYt5@dJ7o5`2{t+$;g`b^@+T%Pvm`lBJb%ysrrcKkQ9ei%XH2y5Mu9&4bd>j+`0KX%|4aBWfM(V9_jQ&>}_j&ukmr`zQ&K1k~MtAZft0kTAQR1*U=4%(NNT!n7gR!n7&Z z!nAg$4p`e!8n4RIa8;H@tFkm$m8G$&EDcp)jtc{c`{)n{xn_H{cJ-KA<(b*Rx%Z&VBJG|~ThOD*89yl4UNaT5(x zXP&o&lQ1J(K#RTG&j=R)nIzV#wAjOKZYY5OPdAb9E?V+cJGmzorsZ;16gm)Pl%b03 zP(~4@-A6>JxvJXAO1ZO7K(<@lT{!SLYDDdLVB&}`4rxH~XK5H*IPkGo_d*FHtFW=kuFZ6cJ%MoXc)OE3dyR6c?v_zu7$Mi(2!-n3JsZ? zn<=jnsV{9VsVkMGo>Z1PQdv|ZHDrv>{R|cSlt=B{Pd-9dgGXAc;aDD_b6%l!4P?f8 z4bW1?513yX-avKyYQAU;Qnip12B}#(V$EDBVn&llB#;jNVJ=R zrAFi1Ha7myj`e_;R;8YQ+y=eN?IiFK1b^Q5-}bC*8MiTTl6}arko-oW6=aqM{e0jWYk*QaX_*GALD}NQ z{De8RT>qGjFryX`bC2kjFgMq%xN&Bqu-vh+9>wa7h*HgFeL4B8-MF)%SZAOtlKj~g zbX3M7$>~!pU-z;YmR*9yu>CZhuWm8*Q%JUsacM z`>R#etg0Vd^Z&ISWmo{xj-`*L87R(VgR!95PxEqtJYfL@-4vUWogP(mS#+4X~I;N z=1XO1x@vpfDXHRT3Edy%*%~TjYp9T|p+dHX3fT%z7DBd$3fUSeWNWC9ExA##u1NdR z2}GW)p+dHX3fU^%_*`e#HIBV*eE6JWVQM!p$cG$z-S{+rYhD@e>IWJ$T}HefPdU)x zSh{6sVuNEL+(x4?cy>1#eRQcy%-7kP+1>uR!{{0|x`t79^f-IU!6@rSh}2?o{?^R& z#6u?fgZI_~25%E|IK1iQ(ppOxz$fwnd?FvfC-MP2TSRg?>|W-9aS=qU#dXpv&|PiBJ_DI(eiEmD2|6Waz$PcDgsNCN6^K#(-xT1c2( zUv5eRt(j>vu7znsu7zn+u7zpsP93neqcmQXrQz0>pCqj+OM_Ke8mr3EP-}ZhsH}jM zQ>&MQJkoG^A+gF!^Qy8uQh92U%`q>ToRBkpoZUCN8ythKz`jzxEgmYi;Bbkt=r`+D#rHxVtwCr!tO1X+pK#!*!_*~0~+VQ}|5nmkAfa1^6D7bLo zPls)CzYj+RF?W-j8Ds?BX91fJZk5D@)5cke3`Wx zj^zGc$NbXp>IWJWjX|mwa>5`r#ZwN9aV!m{)z#)1dxerz)lEjC z-4rY}8W-Bwc$ppR0WqygJ-^!qzlZ!F*#a^y792QBjH0)A-8S&&CaV3eXag$)Y@t|g zc%@x1Ow0HJ{Aw_G(GnuVaB;-e7*8{;bA5y@Acm)W%0WOMHGS<6U?Pgg*EF#BGncdQ zFJmu0E{lACuL^MkaVt+b@HSxi6;UwnP-Eb7Gr_Tt{6?V_WR?c~eBkZY0Htf&Y*u+;tLF2Q>Mg9~Hmbfz@?$FYl8a@nL|q!sb^B{ln(th< zzp5_j_E)Q_SykIvdB^N1!vc^LNFU7`Nns`%j0MepnwJY?JW0F+g4c7xQw|{gsaVxj zl^g4)2<2`63>rs=ryPaX2Jw!dhr?LJYjSvRio}|~bgskQF0V%s7AsIJ+KY&bJhL?s zv7*XdhKN{x=29Y}boE(8F5ltb-cLEIio$n2=SaUTUe8z=gn8Uk3wh?#_3(q2%5**a zphB1a@Pjw}bv^tbi(L;t(md87rJ1aSX)bGFn$236=Cc-tTspKY8P%yonoyOc`BYh& zPL-wER9Tu#m6aZeq^VS1nn{(ViBwsdN0p^%R9Tuum8D5kS(?M%k3{lTsn_m2hw_No zIwNgTd3g?p3OO7q|#G@qJYq zY5ZAQ+?gi8$D+sw`1lYv5Vw-R)LS8^@}R^_pkHXFGF6Wsl$gSG-uJ|x4ALUS5p9DO zDWZR7+h9e><%}GVfVvwHBn`M05@y#mISsUCrp>q(rVY6krcJpPrnNhDz}k+|cvY5$ ztFkm&m8HR|ER9uVX{ahoBV`e-oLU|F^GM5=mpsyc?4?8=fLKH1SiY3xydDoq5^FuL zC6^eHF5w=O*jP-b==Go^(Jfv}u)(p=NgE9sN7Uugx@=ajutm0x9gFT#HF;WZbkt=% z>6nn{;bDu_{iYcJ%MoXc)OE3dyR6c?v_z zu7y9dG=_#O4@zjrQ|?gfPls)CzYj+R2El>V#fHiOgg&fe#)bE?x*yiWTxeU zV|j$G2Kk(0p>+*pq+SEGl<uu0G$&TU@$hcT=;4CqUPI%om@QqXL<=Z+-zc<#%+jEr545ap^?p!d^AzUP za{XgA!i-u(%srx8!ZbxXrg7uUo8IO2EL{gF+_AaK$vf=Eoj1bk7{vk;F9KH?3rwF~ z>VuNpVpy^Y7Q>QNu$Ygey<*(75aXtW7&pzv=CVauKTiuSqO{CCAC%-po_>HcXJd_H z`9TSva%@(4VXNlZN%a;6sz%ipsjAWpX-`j6RJt7MgOXggzb2*4J=g88s!O{4)v9V% z)o1Pb#5LhT36ORy-73vMp{K>hf@VL>tB#|((E!?-rlBhX=@~Mnq#5Wj%wQ~N z_S3vvAX_K>QKmt7-6Fgw2gpm9i&b4!xv_qWaJ{vqZ--N_pf>^;o5B2?95rp0e6 z$cr<14tA`6!Q>c_pLdv34Q%v)yKTGCSp1@y7{GRR)GJ&44LQ8>D}eIySzrjn{~+Ly zfAQ|Zg_iS0zViLA0`LPEVv7=-;7hO&$a|snhn3osdGP+1*}flivvSmeXIoSux;D`r z;G=8vPTw`XxqQT*MLIajZRw8d=3`{WYgR{R4^n4lteL`^xlZA=WKxW#6(VGPEYC?+ zp>-YBNkE_4o4O)NnXqy%{bXKmaB#V7A#-aK^#6}Sc28*u8mGbN<$IB##$yiOP)?TSq zYpT@IRC}u7P)pVdPu?hLxXRN~>vb`0gykzAGO*RdHhs0EIcr3Bj3=c9Bz1#wC0(ha zDQ8+%@3v_8DvhMB;j=JhQs!3W*@TASdO<%zb3%ooosUZBO!-zTSU%LEJX{AHlu=%p zw%KCbsUgPtcR-pZUbDrxdqa%7H>7d*KGP_Zsxs5UD)Zbhdk&|(s(K-Ad;%A2LTo&n zX3tGh^~_d-eD9a)mEK*}+CbHZkhYbwgtWrSB5JC{=CJ)WDNSr$Z+}(Y6t=%w)sR*7 zBkKnDx}9kO=^4`Z$`WYkj(KD$WIxR-q@&_{Il3Vn1)qFHXd3-p9WsVdV%NpK{ zZ&=<8R*$yjP!=vFEkg|-3Et^nf<>?X*`DG=0shUu#-HL;9%_woMG*M+U4l?wNrJ%h zzLv)bb%SvwM&JqG$OWM;Gp+~%ue~J~g!-0oMG&~z_j19kOcK=6DZa^CFP+h*(ixqp zm(FNY>5R@$IyZXhi~=c-_)S_UibQ5@K*}QuLQy0l2&6osAQVL+g223VMr*@gD58ea zNkz9|s9vhWWvPnEtrzKVS)?LWFVA7h^ZQ=J9Uz6O1u{GXMY#@C!@y_!TWl_(0eI)v zQwtiNf%*$?lN}%x5|uzvC!z#++qYZ^@GfJ;uu$uhAaL`n;SbM1?cfc+1Ekhtj8Ig( zqz3qv|M1iRZ#7m73w37_1a`iimkrbk<4Pd{-`OPy^}Qqr{B4&Y)FW^6Gy-2>te8fq zb`k_0+$9KgYZ3(R@tr&~P_HzuWCnObmmt)sNf7wXE<%uzu#E@2*F$ z8*xj&1i0yq6zdr9kjzvsnSr7&$Z!gzBWU?AY3LSXbc>f}Hhswq6b)Zu1k&nbj8HUu z5d_khqaYNGR|J8y+$ab|;}t<5EjJ26(Rf7=NXw0aP&8f<1k!S&AQX*P1c9{NCN8tI^T;&YGs+BZNjCo)}&`32j4VCt&JX#?}Is}HGJ*r^Y3YAwjIOUaXOL=88 zQeN3&lvg$m<(2I~d1aL=udH3=l@+Nx>g;1yXCcF7WyIRS5^Uwhp)+P(czGK1o^(f) zUTn`kj>DGfdebz7Cs;Bx7vKYY<~U9>c!>?%DmHBR8XwHZn;HQP;)R~8aoR=R1i&-} zSt%lQlN6Sn*}Ooy(thjk{NFn2o}b16P*NG zD&R5yO%cMulx7jaqEqD&!lQF#!C+x$^I-6pBByk~p&Moq!lFCo5yGQeX2D?5J@a7j zcChZ51%pL*&4a;XPMwkuhbc)GAuPs@JVJQ%`79VLI(i-q-U_n^Suj|PKzT5DOkT2J zuo$HBVDK;-Suj|bk31MWCN^0xSPXS}FnCOJvS6?n4f9~|nDk`9U@>6k!Qe3k%7VdS zOwEJAV`85LgN0$rgOwI)K&=!1haa&qPszqPa2oq|_Ob8vHz&ghKH7OZ&wzKZC8io( z@E*?Fc?P`NCJrhGCbR0^2a`LMD{~d*e>w;Bd0;=el7pH4?od}CeZ!@pCV8K@WgTxPVNLXg03==4>|B01UVtC~gf zq)uNIt-jsvKQjEXtof3U+s(nEmBaAyv24opDZ~4lQBye#-N826E01}>`!XIAgD+=1 zW(YsXcxw&MH+P}N*PVk(E>G9L_;2~!Z1lA@HF%8sq{e}h#*(S{+Gz-!UovYcrvbvc z$mYF2Nb_F`jKMX;_FkLOGIol?AIO*~v6Vw)2+BzI`G1f0L*#&uv3X~ZgIJm-qrd}l zIf%oP9PsR14uU~Z^p;~_&`ZTLoQYgHdI^h>Y0$kq<3L8H5F10$-boI~P!#0Ku}4&t zxDIWgOwWtaKk>&17{{1Bg;%>Kb4uwekwDW{ZwW)`>D)y_EVYp?5DC2vY*Pr z$bPC9LdmJu@K{+G;*co|L0Dzxg;i!+SY>8~Rc2CHW#)ucW=dFP(wi(I*}2UctlCp> zYQ%1puJ9#z>(d5*(%CJh`VEOpEciGnGEU`CuK5DNPrbA&d&a16ph;6Xi#fNXA zQ(oCHlvlP4{D8!YYeMSfq&(5>{D2!Ya#0SY`1Dt4wF4Zz&r6Jn zX&9|XH(HNwmcwvS$<`L>U)fW%11VXl(?w;eDzD6*^2!7$uS}8h${Z#GNP-r7f?B}i zjU`8S7lEe|uT@Xvah}NE`@-V5n)0gpqQ&yhNohTW*I5^%BRBN)!HOU0k7C=(nBrXS zNbBxcDmAN^Dl($H(pEK_Ut*)1H>f2UbmGOp36|lr-c&>R@zE(X|MBgb&9p z;EFUH&u;Qhw9+~|jiEraNy{bCPxqN{8%U9c83RSZlh(KDVb!AA%0y#T%9O(=g*>(G zkl|Fk?RxRfVnc{WpO3S}>E6C>9bu)pm3fimL=x^57N5c@7nQ;)*N?&~mw>`5S9`)L zmu$k?+ZG(G&V-dGyBU|6$tLDyrm~;P%w<27naqAFGn@TXW;*++%zXA!SqRxrWnpAL zH5WwAEek~^_GMuRt1JXzm6;b-nQ38_nH5%-iq9=ey>|kbw1kkJt0v;5ghENu)R{NGz?5t|M=6c^DcuWTpED+^3{Wr-=TY%0nt z%S?G?p(&4amQT|C94iGG21)kiULd32G{4sm-TyTT{BL75t_^3?Mk$G*LK}r7tg?)R zRTh!3$`TS*SwO-n%STvc@d&F-XQa2ZGNEi(Pmtt`X(qNVDN70Y=GY%!i#@I?p;D!=N^Qa_6$z_Z$2Bz#qxI-U>(SLFz1%BkT=s@>@VM*3;yF#G<^~o)RVS$Ifa4NkE9Q zo|9VtqV;|1Vb!7)P$n9yQYI2UmBv%s4!KLU)vgzBEsw+ypC7Q@El!}wT9RF<)4hr& z|G^;9ixf^JHll>Z#?1}B!82LkxS6bP+|1&qO9?F#nNEC=R!)ATU*M37Y`$LRCi|(( zRrXVvyX>bjm)TEcZnK|K{+dvkXPKIlS+XRoGAqI=vmmT8>B1_LEUYrA!YUJ1Uks4U zk6Sy^g#b9UsTN89nxDjLl@%mbq@J6RdTvJQxf!YFW~82*1|yy4kDR1b`(eRU;N$fq zj@OeoUQgmiZeeNy*WMZjieK7OOy0Eh$CR+1D~UU-)QL%ljzNopsFYXcM0sUalvftF z^2+j7US7O8COunwjz&q&E^c&2Pck#|Ha91uzzdAk=tOGLM9#%Zp^1$DQEb`0Rs-ai zIXsEk-m(q9%sc!%ZwcRDi#^WaiJd}aFsaA>Ky&`ZR#V^g8XE?F&sgG3-r_S>FKGlA zF58MM0?MW$tdy5-bc98Y5^_)~f?sNbU#f)Ptu0aSEcD837?of4=GZQ^iBzd*)=B(7 z)HICNqZ_S9*JBdDyG41RJw-Q=@>7>T8KIJtSE^QCsatuegd$?XR8=V7%ayl)Gse;> zH~52z*CIh*u##0dN;xI6X}bP>i{(d2X+4EMw%$P>ln!4C4OaX}S8A9yM=QMJ2HH*f zTC+VQHhO4-TGCn>?`~1P+@2C8@J-HY z14%%LvK)*WdJ?Vg1rMthEu1pZ*pD)i@ToMO+IGlYs;zdtcx%)3f$CYd7~$+?Q%h=+ zs((YNNveKXL|sZwVIH?jyeX+Rrq69iUtROu`SV?l{79^q5Gy?LD8GGj$5}KERQKBM z;10G;)O6)VlT((08oS)N>M44pqo6mK?!7n3+@il;m<*|kdgroBJfjcEvKrE zHp7T5lDExE1=S#LX7X&va-0y(x0malr4qK6iOujEstF>mI58TKCM;({N(`5c_p`y`bk|>@{U7)(dUO>Lj zo=q`XwO&>e9iMMzG`0R#z4ecOv3Q}m;oXopv8J7&NjekhLX)s)c|B#L_nV|f)G8tSDijH$L9bj}w?GW{lm6x!9Df_jPF#|&v zS+qQxDmvIYbW!P25gS)s(SQ)0r@N9xL>XZ)KvWg4vG=e_Wu#gkWt_?@qf}m5{?YzC zlrdIwF1Nzw*=%X*at)O-REum@LvyWZrRIjJsYNp{w|0^S0AZG8FsDLn%)}Q}Q<S<^WEmSm_hd~m>vmvXRs$W}Nf3T;B0q5E)h)vN;$RAjUBsTF_3$cxdto83`Q)nl| zA#I*$h(lOUvuJ3b4JJyn@MTNLjVTMjTS%kaipGY-+-$JMa#3HvIo4XQ8G}~Vw%%1^wezIoJv2` z$N-@x4TD=`V;}JO;ce9J!^>AaYBuLFATxgUBsC2a#L)4kEYo9z-tl zAV$H+#b_~_TMX73dAB)o%eR{&w|u`ja?3ZIBe#6VIdaQ-XKhmQm8Lyp_wV4u$nM&q zC1m&Nl+8d)OW6j5MFYt0#-T><^Hcjxcixn>CUH^V**!DZHOf__xIczh#)Vauov_M+ z6INL|y-F=Fxu^K0N^Rh&&gvXvZ^xhLXOlZ8+fLCt>?xx|+4hA+F|G4r>QG`_5hPM& zM-Ub*d%16>bZFL3@C9gRTZ1?oB_QQWgBDiVnuS#_@=n=eMXFxpHRp#cP!=xCPU5l6 zB4xV(9G+poi<|+GkN?qbv12;q&~RU9Wvx8$6<+>h*BivxiIJs!W9c+x*}#=ows7Uq z#LuRpq`mG!Q2R6MnWpJ|MFJwKviB2mm0R5_bIO&LzPz!qRJ~LF3KxwbW>%-YM+a* z(m8{J0|T=)iEf{vSuh&K)3RF|!7ucQP765VtTEuaEF}0hF4h8K3#CH=cg`9jcrR~= zEllO4-=x$6VlgE$;NeLMvkSi5#ah74(|iKRR70x-{K_N-WG1L$;J3I~ z3y58p$yC|5Bu~A}^$FPo1I(OLmbF0UD-v5dH4#?X|AfWFWUjwkz0(XBlP+Rqj}#UY zj-UAJz#ZT(vdF;fpG(&3CcahLbBVv#3?%Q!nC=Jav}K3truVj{+p*`SddI?(7w@#a zUhe?&1ODT5`jKY0(%Ms3NSL4VAG45@JrluAtL#T?40fgKM+^pM1-gFh&RA7#u2)W)q?^lGF(AW?hNOGbfkg~>ch*b6J9;OY1U}nY zZQ!u8CV?GesZQ{*F4h9Ban>Y|PO2g6y>zndrIGB81FBfr-6UJg_n&SPdO1c1WZExMK>DOuBf2D0D2*RX zHKd8!E>;BZqN3?V65?hu?2(G?lrrhat~KK`h@KPs}3**VX%6B%{ZuBKke;NWsMIG z)@$6>_kW5Smpu@_6Sb`R{I`v519=?1Yz6h-)E4qMXdizJ+d?~NY7=>yXeS$LiymFJ zjd}CxZDT=X{VCdpOcKf_A*_vU33BP{|8_Ro9!ThKcm8ZFf~02a@r||#TS~oCpZM-& z<^p7uD`j0akgZEbjV4|k)ZuIZLs;XXWt`7JvYbr@W;xmgCc_=xlfW$7Mqn~jbZpHP zn58WUOeTkP?!d(2<3b6{a_SJ6%pI5~1ZL?)3Cwc#5SXPokHO7n%Q_}7%TnL)YEhF? z){63Qn^GytE9*pgWtAwetP$mv6{5VdK9pBhhw{qWP+nOX$}8(ad1X~7udE5>l@+19 zvK~U%q8gM}*1}^;MvX2zhsN@MweZl^g06*jv?(<%i@|Ew8K%WdIh9vd(4dFJttX!` zU%NJQCT1bxq6<|7khL8U?c%8^l?yA2$>B?ibZ2fWk}WJ3H=uKNbm4mx1$bTX@Xez0 zjiz&@J>?}iI_NKa54Q2W$OCI3+x3vOSFW_!N}c+x;4)~__k-umW6{L3VT_8U@(D{E zD=Aqy)6-bJ3ad0@4eRTHim3k4OQ?4IWw7E$d^`;?#ibttDPf&@!aDVY)y86Nl|;t6 zQHrCFkm}(csOm21iF!gNN>6H&;nUs0{$h)Dlm6Al@CPeaTwzjj<%rWzm;=?L%^|+E zJH~5g88rGm?B~pXP6Nn1<0(lI&8?7UBdDSK%$+|}4b9E|S86T+cxs8UL-`%|rHx%- z?rNSYwy(`l*y$0S?CkMWv2uG(#Ml<*sbU+tEzI_?hGkorr}D}&npZVss}x#T4NCKv z@BdLM+0HM8!c%oI56QM~DX4r4jZ$H5mX!o&V>C8$wxJu}+J10{Y^hAtfJVU{@#UTKYizn@AEnDmaLHz}!^fH}>Bx0fhQSe1Uo#=BeXsl3vyth`dK z@|q^A4`yQ8@0y;?56*vSTG&)&BUO22+t3QG*JNKMy3rxEJ5^=@**%nITNZm$OV;Bg z_P5AlV6Raegv|CiiX$w1wz%VES_8x#FH&VG3#**{3k%I%&xRDS{UU80$o7jYuYoDu zll64>xuZ}|cRyPNp$xqoV{Ue>m8Nei{=!evjRARTiy{rrw8QLDZNQzK)q0V^5qpN) z2M#gfup|e>hZW?gi<9k?vZ#2cK@OTWwe8T(D%uG-?7LBPRkIK=I^_~2wcER*lj1&W zwN%WhE7Wf5vxgRtl*siV3&1oqok5q~plMdEErQCtF>^zMziqsRrAI0nBDg(^0DMo1 z0GL|H1dV~3mu;wez1K#lIGNTGL-T)Un!%f-1_n%;N9vkK>Y8g8TTv^qw$T0v)1>VY z{N$t^NDq1#JC8t!`E zZjiEQxB*cI^^FUuItMDWVV$JSVW7}1EX)ozM_8#eBGQD+c?hGM&*;FjVKCf8bn-K& zYecN!OiGzr?KFho6oA+;<~YRAI9Efy<3^~yBK5fz!pyFM*Rq@<1tx>>1N%(NnNFi8 zG#&gZlb{{5Oo8&s1Sqe`Q&_53xw3rc%~}9|4DEw+Hj%cd4V<&qJXJfJqPzMWeUj-C zgM`#OIUn@{4U=WY8(PQavb@u*Kb$%=U#D8z;~a`4rQDBeNSzwO_ghFduEkM8V_@g6 z!Ih*shpNpgoNsBHy6Nl~5s@SUSyCr6gyw-la6ZFU<>U zQWEE^woM;#VN+m-f|VH^1N!{bk4p@C-^E55b_wbh$kkZ9{q6rJLVMuC?&s||e7 z5iv?tG&%$I*T$7Z0?{1>>uTYk9tCo_AduKKiecCFO4l_EM5nCCfVukNnpF)STa^@` z{2a@u_9ZYy`_Pm!bw|-kQh{Vw3J;j){6Um5^GdCMKbU>YcvqU*;pHaV%nFR8iUuUHVreVuE3D~R1G!2wl@4}equP`Pk405Cz zQqm(zM&Y}bg~wP`sx+ANt63^5N9D?zP&ta7hTo)J-ciZS5{21RN;EKy1x#a;<3GpD z?OAqBt%my67{QcOjIk`M&158EC`yCThNe~~P>*|dTp2y2Y0l#dCnMc1iE*QrNWU)D?Vh>ZRrGy8_f z%6v)Nu{_POXM+o6u;NFQG-N4Git2;uL_PfzcbKi~)em*x=`Xf2PihWdZMk7!kOVgv z`g+KQsYNNI^ykemechfi{k+HW^gB1{jYl#*Sqs^&hip8OQR-AjaT&D9c|2zxW|U{c zqEAbEPDN>D^B&B9HlZnpN120^Wh6W9;XfjxTgyz1Dde}ky^Rq!H6&6@anJJ7tnHo7 zldJ9YzlT#t%-3K=`d4_O$4Ng0Br|D-Ncx?yNI#vRX~fYhSL9Yki+Y1qlw~hNLRAh& z()`Quq@fExa-&0rH26E{Rdw@GaZq~V(eWv3G2lCl6_?gf7bQX9e{=~#J?$8e5%@x5 z#TcRXOM<|?j*nrZU|DVtoQKh-JdDoN^Dx?!htZjO9!8t;FgjDu!)Q|;Mr%_i%Tv#q z7$z4hyv#>{WF@)?pvaB*5`bhy`aY1Xh!l`~h!l`~h!l`&X|N;pI;yv{LL<|c>J_f2KK=L6r3P?Ug3YfA~Gh6b?Vt8wjj2v%?QOiIMNR{%y zpEWtzT>8*T5{RBAvtrl8WNqPBMXyX>3!(^V2MeoXt6dk1OKRI0Sfp(e^&Z)8@Msk& zLO3Keix3tingYS0V6#B5DBu(b4n>g#DqGKhtUV)-k{HVhADk*=SFeyWkBgQ=%NhJG z=j}QJCJ{~bAx^Rl&@NMFf9r-~Msrgta`}EzGi2|OX?gT2jd3d>nHIlj`3%%?#+7+b zKZ%pTyDaakkkZ<(s%S&>0O?=9GriAs<30(bg@_bz!fHr{I^eXkmXxK`FdzyV+%%qs=~-&YrIyqYP)3JHzrZ0GSr;jjll@dCEBh%W zr$lA)vf3aOnVBR(Vob|~2&+thuxjc`MnwW1X|M3!qJYO(;?lii)W8(;VkmbVQ@PvV4?Rrn2d? z9wZw*scJ@1Lw$%Psu%cZLxI=7@K9vi?OI4nP zmL@DkwC9EqYp~)+nx*tm^2jrqx-XeZI@tqR4BBn8#UM6XdxKik*G1ceA}zf;JSl0& zzv@_M7BodRfz?YPYsQt-U1!De9ec{Y4)A_wwSnkr9FL?q5-U%d*^LjY7S&cJnl4=$ zQuw5hr#2FDmrAltNxt8QsahU~D%Lg3?Hi_Vbs^m;KsnF4luWokzLWXPk>WYOrno82 zg*7RObJl|l3+FHozSXDXdP6Qcc`mGw>sm4LGtW(2jP+R4nq^bj3L(1BnOcv->mI7k=zvrK030!$VTZ~^KFOPO9;GV{cN};BcAn+qyf>8gN1c93z6P3gmp|&)xG$P=R&Kd*m-xU_>j3fxW zxl0i0@yB}pfZI5$4gBeeE(M%_Ql4h0t&A(p1Nf6JL8wFC>@fn@7%P?n)ICWMc(1eC zz|&TGbig}|6{CYXWR(j7e`>5K2=%{75V+G@^DIN{XI#lLu+t?7b&w0Tfk!xN40u{s zSg37I@ni#^X{?xRsDqOr@H<_CP|tX~#|T_*tQaHI;&-?paDQV(L8#>}*ai-r=3#-m z8!Lu|+A9eHkLVJFx;zO2Z!wm9TI|y4d3$d&1LNtdqxPr@>Y2us`T|aL2|{i1x1M<5 zZpMl+LhYLbfhQQt(*$F;(>+q)8;unsg*q|`0x#Wz{9!(p&om#=Lh%_ zW5xVHy(S3)r@I89E>D8M+qwjy{xb;z7o3-82C8FR$qaC{vD~J?xFyK~@9l~d>dtq2 z#(`U&A6XtLjHlZVk^ta-#)^dmb!rj>emq4QEe?z?C0XEiyCQ{p-UXgg;9|f7{5rez{gw^Re8KHjwsC|_%{9&AwWPu+mWno;KWP$6GY)r2+F7@=zH@KZWJ-smAo@9X^D`jE)N0J3@{{EtE z!Pv=uklF=~C)t=@7zZR-;Dx2^pQDH6|I+lwEde}Q_Z&d`9tD2TJz5HxXyi+kcs8_nLssr5LS);($IjaLa(pjUx^PSZJ;^~S?p>TFd z9)Nhdq97E`E)fLc>576-Pk$pN+5zI}ih@u$yCg;+o~|eeb<<%UBk*QtwSg0dyA*KJ zS#987zsaS5`#P%)y!S|#0^aAWHt;n^xfHPFtTu4eSsmb>N5_CMn^2?1mGS^~oYe-t z!&x059=I4C)Tdo=6u8b=9UxA*7#3=G^QlQvfOz1dAk_PkAP^5+6ok4v2?EzSs|}n! z)=Lz)(phcb&d0kHa2IE_fm@v5Qou(!s|{S?tPXHja|-JA+%yD^z?dtjC%Rj(1H=&+ z1)+{~*IoyRBQOd=U7rMjH#n;e9D9rB4YZ~?!|0$0P zxcSP+l5)Cq8scnYO3MM_qKp}ZI&zgq2*gDh1)=7>)dhjLD5D_MUP%y$n=uMP{bLdY zUTdsS=MZ-$Ip8mIIS4$Ll4l@p%cvL%&!q?gaa%?~sBfI=c?Q1cZCPnU?C8$U4iNWd zj1X$l1>3;Cbhl;)h{rRAg*qn*0cVcG%WON~09E_T5-@LSI60CBIzuu%KCFS7&0aT*1o&Pakl z9H&tb>YtJz5XWg0gnEH{I6FYRq)`y+*dz$VOBw~C7PyDA1H?-j1)*M=1c7)-O|=P} zngoHTIjar)nzK4Ue5o-ysC!+o4P0d2QZbW2e5;`~KpdFlfVftp4yaF=UV#SG!&lI5E|mf6dH(QHHLP6toAP}c)6ok4W2?BA-MnR|_CP5%h*(eCLnY&%vz{fhP1AM%*+Q37c z)dAwljT)eSkOYCaa-$&B``oeH0e;?Cp*2AKB*_8s_r?gJ7MWL8_P&8naaIS23pj>_ z8g{`puPeaUiuW<*stFb~cK z7iJo%HJqZFYF;++-#D|j{5Py2q40T@;1maJRf>3|yF76Hxe|i*znoNQ~{OM5; z>bxWf#77X%6nh+8@eLOssi#2w&!GJo>u4AkEzK_KqqkZ_1Qk{l4%agc*}jr)5$ zK-|VLg-~xzf)2x za72FF9g)MpzjH_A1Q6GwmdLO>BH!yS#t9%!#V81M?x9RZCV)5sqaYN%K)GQ6h$Aox zLjC(2JVqdnz$gfXi%((%;@^vcP#3$?ZUTshEDA!M>fWpgAil3C2z6Hy1mft5f>662 z1lU zQ)B{&111VW;c$^E1makUf>4{gPh|p#!z2nqeJu$BahOCwsAJrHG6BS45(S|?o&$hGJV4wdQ4s1FcX&(yagRhns81$AAij_& z2(_vEF(!ZsuJn1s2r!>FEb)26 zn%6Uyi~yM_XwH_*K(QYw@8kg4X%xM{H9or-0WzP6(Lph#km!KSC!!z}JB=a;-0F=n z%~23)XXA<>aQ7+jNr?fkPGNyJ z87qc``hF4wGHHo|P&@g|WCX}y8wH^%A9_cCd1GBtdqYQWfE<+nAKpJEPCqy?n+kpLx3{ng@$}5K%<(1fFU$)g81FkW7j1@CSy zT4ZtX;=+ZG^Y+o^L4}VC_MOJpxWRu{$l^9#Y_3n@c!_x~ac{!E!T7h^6MpFugukb` z%y6~A{|oa-;W2|>`pV$r@_N68gO5LIe{(az$Nh9>!N=+HX!DUEUs|t+)1onM{Ob|P zK7pTX27RIWSX{}DSqA_2}E4Q7MhxuZ4qdYc~F=xudOktvwhe^U5Wl6#^ zvBb%Kf`!4-m@rxxtV|r+#fl~S2^JOCOJY_7iS+j8*m%=cMsOXFuU_#$;tb zaTJ*~OZF3oWAU?QKb1Ca=wY9=Vd*YEGFdwCtw(jw2L4>koOVm>TQ4J~a#*h>6V=NO zY1q;LF%tE%J`aV7QQf6&L3e3bRJODz$}3HY@~|NDou&X zVnc2(W;1LRV_S#=!}85ymcxE71_ybp&0^d2gwK{MRtP>O=<|hqX@8K%_}pxJmhj8H zO!%cmf?t{=_@ym^k0H9Nm_@Puw{0<7Dyao|351_$j(r2PkmhO=t$VLk;k-&uD z%(aFFvkemj*?qzN5ttB|_n_PSBJ0hp2SI!x7uc*eF!5;oHfQ3ec$N7nf+X82pU;_i z0$zGTRzz%eGAotPlCyO5QJb>uYzD44M7l3!+z#L2u!vfUS+O} zZ)1I6GN}J7XR>T~n)x(>B#w^poQaoX7aP-qB!mA^Ig>@jjX9Gk!H^B{Avp7aQ*$Ph zfluU2W&-#-LU4|8%}a-$)=zO{Yww)N#NZ=2lUc#P=giVk5(~uU0ps=zOePPkPy&;g z0REJ~HCR= zT{_eJtr|ZVTO}c}R6jH^VPU7XH|rxTtkfBag^gn6B2uM=Qk9(Ke1RXboWMM>hLMov z@5F{2?U984#+#dK@I`~ zFLFR^eUO8|>Wdr@k5iC?;G~Mk0T(Ct&zfl*MR-s|4u~Hm#0SAi5s?G3Itg+R?45`l z5N}J6gGeiaNgykOAP2!vCGi0nwSpW3Z*_?raB*@`teIw6fQv%pfXw?td=Sj|MGnXi z8RQ@sBSj9#a2ezv(qw)T$fQ2VK`_IY_<%3734W9_g4usyLhy=_1O~o1IWX2tbA=Y` zgb)~leO(D$zE>3FST?XA5IG>z(jW(c^FriG*M+cfTriOk7LbdZLTud3^lY141m>Pb zv~woY5QgI*32~vXGA7GWL%&1EUzp;>A;$-v@LSHyam8Tp)od^Tf8BWUAr}S%MgX;? zzqip~Ge2~?6!=(UNgh^Dv#HWFM6kCK1R*$)s!A9owze${<$<>|o{R}VmQ*1=h_~9N zhK2>7Z9EAJywO+^cI^~<9}EB*_BtC3uzAV@FI>%7w-ksYUgG=EG{oNKaL};eW$uJ% z0r5|Sd_Wv&3l0qnUS&MV2atJW2n%tzt&BA+c*d9-t|&o$A$;*(TKVfY~JsS|HdaR6#KFp&$ss0bBS4egvD%1YXMtO#7EZ_+{%C7HuEPEi7QK zmM>zx+C39}O$V46zXS!|VKaRd1Jiy*4EX!ZsDoGdtbPQT&FU|lhG2Ft(E*$6JTra~ z1Kw&I+?qJ>YkWa40%Q#!&G16Mn27~}h6S@S5EVcc2`UC=X&_=i76w5D1WN;v1F|p( zau9S%kpt2vRV|n6!AXowh)Wk%2n!GTqg1LnuRz^q3^49IFEL<2JH|X1S7P_0S~i5U84iDx)CwpjV2bNgJ5+dazNHLK@KAAw2S~*@Tgkw z=4tVBp)Y=(WINiT1Gv4jS{%@4T_jRKRz)Et5Uh(t4#=t~$U$7chN;d7@Egu*aX9T) z&Kd#U@2nQPK&-JuCy*6Z&)CLqf$ky|$fu_&#< zF7!1R9&%9v{JHPew16znLVOS`&q87#*rk#9fcw~1vP|oMEaO6a5G>EaQS41PeKl1F~WZauBT9L=MQ}EXYBmmD&i9sb-LaV0k9-0a=^{If%5K zGXiAsrdQM;h$ztDKX%4owbyW`Q(VNpBN4**pO#=sw%*2rUyZYd>8a1exG3r7XPn9Lvufyq=sHpAHg4}uWbOcexUG=m@nwo3)U?9K*32#lKw zme%Sq&gj>=d4O3#FB|r5U;T72XIL#w9vGt~H{t+$*)I{>SnDN0v0dyIYC^!+CJ_T- znp6yoWfC!9FC!&l{g@~b>&HNeSU=`T#QHH#B8F+|Wne@M^MV1;0s+(iMGV->6sXcZ z41tJY2I#)36in|GF(92+#lW0~5HTQKSH-~eToD7(A5{!YcN8%oy-~%$bVd;a_Ue~g zdhhanshpwt&fgf&t7pE)d*(!cJ#(VJo;k7cJ#&Jd$w7xu?&d;R;jV;X;6FHPDRA&a zmO>ri*3McAJlR-cHb2zhgP7>APfzsMrziUB(-ZV*{0W+QFzy6tO+efUDh9@zAYwpP z*eV9T;xsQLAeKT-WB{=W8WPM}S~ehntff^9yu?qCbbzd`MF9{)p&`L62Sovp6_bjw zP-4}iJTB2=k4brqzN}J|M+atGM|og+ZDz544`-W|L8t8**)^6Q`KuUD_9t4l`H z8#j!?S|VUNdk}=^H6{najqUp(Fuk8aR+9s!M+QNNUPEpWq=RxjyT%9}cPC*B_(f+; z0Ke(1N#LZNEs&NBJjhv-z|7&ex-W-gNN_)#Kp{9-By{+7L7BJlyg?W{>4CkG_D)$U2dF{aUhU*ztp2_UYr zkQ4}A*>;KhD6c@oI6grF4SgGmmE|0~ErF!@s*V8)gp2!R_* z1;Kc+f*=HLEENRf#R`HD_^ebAe7*1MP69d4AO!XqDa@Gj&f1EV|%m%bo{SIiWru!VwR!#RB&=|7BTMJ~w(gFa_ z*o&MZ24oZ)sK$W|Vj2?67#7MHfAhG`r>SyGXo3 zp}^z6;cSeYm#O%_lz%`v#3P}H<`9Q+_+NuN9vslgLN;NDVFOq7|NrJM>!tP$XkjHMyL zzjCpqz#Z+i0u=-A;jbDj1)i9Rflp0hz`g9~p2h~=$9OVBVK#QGol8|Q@CxIJ7!b#U z6efM+nfBs>h6Fdf%)lL~Dt3`#o$>|dNVKR09+HWH zc_l{FuAPE7IXg)Q=9sj^2fQ~E19R|BN*(yr<5KFt+Z#_}TVwEf=1kYTg70(??^R-M2%)vg14S4@sQm()QC(}q;hZ@|% zRzR9IFxTGH52SJI(BTYRu&O?5XjAKVUqGk2M^ZY^oR+ZT`r8mo4CZ#tLdVrpVK&=dz+8GKVS!xLDYInY(OF3FDaMnKK-R4xV=Pa( zG(uC{bggH3uu|fypR1f;VauBj1J!btwOl+TB?n}8M|C!B>#$+-FSf0ta$qh8m2?2N zK0OwkCRIJxc8duphL=qIpnrhOiLa zL#Sc7))Ys%@^A{QH6MfWzzyd{O~4Taul49qz#5d-GC%3$8(7cn5m zLo_xpP7|qFApQ{*1LGeNG2lNsswWxi^LDaNh0wVD{CX8Uty@y|LT94*TH`r$b1nwc7Y8BuRbv9 zKGdF@S4Zi^2`|}q@%DNjIqWz1&+^%Y^fT-g_VcDO^iCn{8e@Lge>^ta$q;_T9q{+& z4k+}(-r1Jzo9pKulHPJvziD-nt|#V&sLQo{*N^22zU#+wf!p=tRkluLb-TF^Z1Y@e zxt#3^TP|#iu&h~Gn|6hT$r`l?`!QQQUX#|9XV?<&B6~^${H!hJzG2Ufh)H~{ zJtaLrE(wwJoN2#aXwRbgkfbX&kQo0Ij zSDPTU?b)TWyedT^i4Doq&35Uc(oGv>G1Q>1{{ciDL178)$H1T4+1#%1R4HhXGZ2C_8$hH=b0%@I_GHgmq}YRIr6??}Yr-f=K-OQ_A7Pc& zMp&hd5msqggjL!TVU<=ySX|r4vP@W|#Sm6$CxpeZ)35q&@px%4M5;6s!YYk}uu794 ztkMt&i$%gGFNytBSfxb}R%r)>RrY>im3>}VWltAY*}sKVcGAZyLtmjEl0@kSq~QnL z0!&+sVXIMM$vANfQ+Xk)^_TveWHlul{P%$A+~61=k^nK^DXNlAzic#O!?I~7@-eoy z&}AI>mBy3R9`F=rEd#P0874mvY)Fci9r$4j8ss2uIXJd#RSRC=8-+`OyE|(ckZnbY zZuK-o+GAWcZb44Br)pr|@rAy}xD3cuA|Z7UY&>dMb{?BxUW{KPy-x{nAPt^f_j`1Yy+dq^0m&k?KBhMw3XLlyY30u<`$SCSz06T$;YPTg4@QEXnkI879m@s`VF znHcyBK6&T>|2Y!_f78WUz%=a`0d8y44owI6g=s1RG(deCJ+ zHZ3LSs%c)Y_=(H4fkSDF^2%w5vyG|s!1gA4nWC1R%zWDteB9eT7eID2LoOiL(v;}f zwfwaQT?S;QGUNh+y-H0Tn2(=mTQ@&R{&g?5GTFBjtw7u>8XNu;b}y9&{)M|=mH~G@ zE#@_3jMWEQni>{7ZGzI-fxOTrVb@GUu=go)z_bmz49Iq<1ijSng1g%8jZw8=HbkYh z|ImKE*Pc>Nz(Ly@4Y^>!^h#q&cLILVS<8TIn@Uh=WcK@Fb1`X3z-*#Q#@IsTi!YKA zAWkX`iC5~s++np0xSegZh6Fc#c!1qmu7DP;Y`*3@t>Eqa7<3!BgR_6W#y>J@$ z*zc1ZkWUkL_KyZKU656u3vqy@;1vx?!Ec(Hj)l?UG2c#<<98_6m*_U>5RN7z%ufb27e z6hq+fkg5RU@X+YMcswM*z=O|E6$?Jnc%l`^wzS3u=29gQ1F~x!5(lx}1yO}04!DD} zmI3jzNYHc(6EFNrf`ROAYf8Xua*GBao7*Y|=9VQ%Fp%x;kYETrHyRdvvhP|i172(_ z3A=uZ&2L;h8Wwz83Jcsk?NG0u!fnhY1R*gHTtlD{g1Lqu2tu$su7cpRlbS21%N=tm z1~$yu5ZAC^JX0bD};kA_BzA)UnUm`T);K{BV#XIT6Tth7rD4IWXJpL|WI3Z^ zV3saH1q6#16$G<-8K_R=HAPbsMFc2(dG%T1EO%Q}&KS%|^ ztWiQvAby@LX22{tq-20B4m3V6Uz!YxAujd>!%`qy?m-SBpMQgyhld10Fu_*MV7>?$ z1R;2@Uj@O;;iRnt^P_6u&EJQKYXQ$TmZ*>;az-!&s|xV5E+Xs%aJ8{QSY819T#^I+ zFqdN}XS`J%;LqBCEZG3EVI-{$$nh@?31*}YNrB+BmkO4{m}VwsDEHfehYJ=LtI8c~!_|kfVGGP#5*ilYBECZn zTMj+S`W!FZu^*l^6Y%9Z9?<*>}yUFDVbR>PJCQhBAR(Xe?tQT)Wf=$gi* z>07q5_@|r3^_sr@+FG#Y3{1-%sK$V&dt*-fTK&$|XuzrhOk)-mz$3G^4Bo-!V!<#% zY@0P^@V>?q6Az?)OV|siE1S5Toi%Xqel`~iN+6mhX0&=qG?4uS%^P@sHWp;-2$-gC ztEV?L;>($DAH2?ZGKU3nTY;(oGmQ&LhM+U4Aed=f5QNCx;9%xXHAE~r{Cvp5l4Jq>}e zP(d)WxDX=*)WPD5Z;G&K0lHdPC1n9||Hmb?HlKN=Q%yt$!+l3sH)CT7wyflQ|~ zJ}|SXkP`@OoC<>9pIpqV-B0|x#Jq5t`4*EW4Gm`Q6x2X0J}VBDDhS5MDZLi>%S;T+ zd`iTC%%(!ALgfBV@M-SvTnfY$8p1*_71QK_nTd(uh0_rCrU-%fN`oB4r_DpB5rUbs zNwou+cBvTn`98H82TrG{)hhoI(zPzv0y4wW=)nK#v#oI;Q!HsOKxSAP63nNHBxCX- zi1|T!&9%i z1PfdFx=O8-e-Ru*X*_6fESV?m}o@ZZ^Q5+Cp;XDtQdSe3*9F(VpT zlU-=)@%=2NdUsg;^>91*x-uPrJn#S)Ppk_Jek8HjuX%Ucn>pX$Cll*a z2Cqvjt_kK#s#1Pz5xm)V7g}#Icz$ACVDKY}Rr=Z`F1+dorRsjY!IKgTuQm7ENWk({ zEn$`ZWMP$s9PFU1B7!9?-N4!Eq70YY-tOP_vU5C~4$@`9KD;gd6Jo`=B|N5y5jo>*@jRN10pG#pnn+}MK*H43tGkL`J1Qm34=2U@6 z*Zw=3Oi7w~3HdAD+{S^|87pKL0=Jd~W!AKhZ?2ECYt5FmNU>ABLhq^sYRsVTSqLX5mg$`+lZkzKfKe{KB~8)sYRTUh1x zSBR1QFZQ>Fs)c`O_~>%&XmgOmW@ZL*{S=1r*YC}8gEjn;nZBSK3%7lm6|JAbG4=7B z$#xKPp`ab&rmlS_UOr(1})0H*})ae&FTCv?5tQMK_{*ggEISN2k@o`l+&u1W7u{&FOf^>gk3~ zvU-|M!g+rQzIvKYLVpNMdIYZl1ZG2zSUp|#h>#>&`fF43Up>us?uUK1wgpU$U;6j` z_WKrT7yz=78Q_31)I8jh}r`u^2Rc<^Ul^ zPUf>~*)R-gTb8$CeE{0pR^HqAI(-T7Fk?y7pPN3#i2Q&WS!MDQ1R=<>4kP50NlXxg zz`v}5tXG)D1i`ZVElv#02LE?|qK`KX^jF164*71*!?rGIx=ZRA_AX}_Vh!_-=$vYk zXU&~~dU+-Z=7mv_{KK3Xs5Qq#6Qgm0`R1cY4$k#2K+ZoYNrG9(h~&Jv?j6pLdxG&? ziR8g^-H*i-TeXAPY?2o=flRxlUf1}(6CMZ+3+AkvXxVh`3=}7_R1(b5ERo!4uHV;z zfl)~?c19%ko9pME@{>wnjE_ieKG)ALags>mX0x61_G%BLwEw z3Xy#2T>t9Mzhw>wFz0(ja`{|8?eo^`Xb+fKvq(FT*WJbJmxgX!bBJUsfk%7f|mxja02yvl>={kc3m`n}47u>rX}ybZMkc^p^= zY=G(nV-Iq9cvu3J2V)g-d3e|Zl?P)Ra(Q?gY9aDC`mqzayxWc*)*_e3g7mT(Pfs>O zKcm6_dMA0hmt0Z)OQPU*bN+0shS<)@vA*nuNM10~@2ub}BmK?_=8yI}D>(YKea;F- z8)gL;_B$(BHrns3;Im`>&I-<7+V8C3{Lu$9D>!NYerE-j?ceXLVE<+P&I;bT?7_?m zo-@|(tYFWj{mu$r`r5u`1v&@W?G14z@^X91-LBl}!X=}6cW&{g!|ld}j1lcwoFb9K z%Kg3*TBIZ#Vd1UVVT)F_!|Ks3EkkN1HZJ5qMF#%LHP+tG9<2BgC6dcB4SJu_KvjQR zcf33UBW@|~m*u2@4n$>qx-jc6wlbu;QD-bSycH}7o@;N#KGL2Id8n%YwrLI*ipo&4 z_w6<%EA=!=xB8csf~ZHSoOy4KEqQZ$%32+`v$K{0NvbTI)=iZW4piT@lHg7!X;F2d z9V}Ynl5EeKk%6i~xd4nj#W$TaUl64{w8Ow*~Laq7*76#X3Xm0Tn{}8B;v;Au3dk3J5R)WDF zG(o~}*grHa&Xj-BLyrQ9c-AKPR6B{rJ>pV&o4q|YcV5$NC{PvnmF)%%+HQ}$>dCD# zY}*K{EC6i|8y7Mr>ItUph4u^?<7Fyt43)h+An#N)7C;;=AJQnR>aiiQaGf?eU&-SbtX_W3! zNM+oO*&epTE^T`@q%xMx)h5947ir)1!zL5;6C;gA@j8o)!5^XKijaSn(rD8v1Y?m+RN!kJocPUS0w|n^EjDwpb7TuND)P!J9}@d%WxO zYMPB#aWKXex z>~XWfJ&RG?xR6?j@3K=8m-uOk7LWrHgVo9{M6&B|pkl+6a|KOOG01+l^E+lwF(<$S zoYm%=Kv(&mb-PQW5z8z@3OQO2Ioe;yest>h{3r-+l#%Ae7W7)5Y1Nw7f{hNT^>U@v z$A;;wsy~<|NyrIaY?pk%}Aqkk3uTrZp`-fcI1(R^9`xglBue97su$u7Ss<8 zPSj8TH4Y%$`{VDZRLh9$44a6}GJtGc$N^9Od&x$9aX(n`BT5?VT^vB_UmzK;=X|{U zX2NU(NPn@#YDoWTQ{_Y|uQN#Pak~FHABbx`JT`K|@Fr_$#=Il&aSuHTB;v;At^>%9 zC&!4n!AVMwI;qj0C$Q~ElPBXNV( ziiQD%ohQz`G)cu;I@L}DooP=|0pu1axfFo|69--zi%(cFc=x~OStKdsXgy@(08$Ux zk4|mq`p2`XK5Qk$g;$bLjt^~TXY7OpD1NdXJQ7x^ za-ibPqJQ$XRM43_j4$Tz7znJ8PKZO6i1_L|2|$ z(l-e?w)8zape46SlxMM2jFU{fY@s|bT~2})B@#{t|JI5n9n5c^{+`%^Igj4lGR1z5 zSg9T5rMHXc;vh@0R#H8A^@<~H#CfDUNm@YENN4=qG^O=oFPRo6j6AiJ70|I-4buco?T<~@hJ}=X^7jXu$Ma6P3_%>W z;p$6a0e@l}RMM?hPsa$-zuNe?;5J3Kv>sh;%BBUkaUlmh19R;CVR_*!B`Ko8iXTxT zSt^CJAP1`Y#k*r{6Y>_ZC@4RTH`~;=zu3x@Xzv@b+;Ho!B$(Sve|KW+(fLxiVn?Ly344_&R5GfJZuO6v(GeB`!Yt`01lPE+DtkHw-Q@-SyPA zNgA4Dc&TfcWiIsXTIPrA(GAz5tIcpI)!Qw?pL%JwfRyS`b@aNb)DoDbp1>q#o^dvc zo-ER}O_8px8X{dwT>c!WHa{>{#-r@na1dc&=!y0t&n6*>b2k&?(?U9Cf6&f6q!Y#U zF?+y6zRY46s!muN)8$Ex^YK!JG?-GuEN$o&MdD;hQV&@h=vDnt!#Axb>)*7VEWc?z zODTQT67qF>idaKrS-u0*j!%d?JmgY7slA=|yqW>khVv~8v0))qXH^mAcNT}(_q9`3 zn+>|&E$b5CzZomYg&4AbVk`cMMfH$Gsi`EQO%KAfjF5~wJcYH9HJEh^v0))qCn5gQ zVvziLtt`p4SfAXh#iQK=b-+3$bA#RVN`{Q$hz$#=I;)B>hguv`!t1Bd_gU9F47}P{K`z9Q{S#Z>h(+~~L>W^_RHvm>u9`mG zl5&BkatZLll*(1Lc~VT}F&5QB5~Y^G6&B$&_LRY%W7(ZF8fT?dK*E37!*_rw$~KU% zyGt{yYiXm94?{OJ)>yD9*`IN>EgwX{*lR{$EPtKDkny4n^H^@G(33&7~tQYaNS zmCT%Z+(E^&VI`mx?U zhV>q{ZjsPj#mIN~gazcbs~!=ufpKbzkeNOo=aUG5oat_p&Fh$u0@`({?MRhH06!NA-kG6)|>s)OMhx( z;BhmXE8U{j&K{}pXy`PltmbrB(r?(Tub&y zJ=r7mWRIZbTu*kx^mL`gj#->FDOcIIac=f+Os#umwcDj_+Xfs}(5~H(3^~thE;P?_9;`{_lt-vfQ3M$9KZt z@8QRQDatmm^24)ZbuDca@~Md)HW#(OcC{@a>ec3g(XXXYDxR%mUTtaR8e%C1UZv;O z)E*^M58WmruFn$#P>--p++4ycQe~%#%>xZ>FVhwfO`5e*MN@X?%;U;Ro(&E%wZ{kB z3ElKHr{#PDhOfOeoO#veM2L@C459$Yhk9q77p%501ejMHSLrvHp^0FjdREUH(4Wd8 z)5Kq6(eV8#Ndi~tz0R#n&9|vB-D)9!>WLp+_s-Z!?zLx+rjWv~_3&fB6lEKDSCXo0 zX`_%YRrKg2B>Q_FVGD?Q?Id9IYYQnAH?ceq_1@L{rGFT^mQdP1&6@kNaAAHZ*l@XCrooc-)@S&bT$}GPn7) zcBajV5T|>{1NJxeD!)IuOOPrp<>OF!W2*OwRQ?;KY zAnJ8M2BTk_Q>nPIiB)rsie_bjJ!KN6#g+dJ3~gmU@@#Aq+7kCL!IsB1x}V)HFl^6; zQr3|1uO7ZlRHGhcrygaS*xRn91LRw+bEgcJoQBOTLMT z)v-tquxCS#V{Y^CcYF8_Fh$u0-kYTATG}W)%oWcvlBZ<<*duHKQLpU^jD9VJQt@mh zv%t{&8|f4qku1Ewh3K)%2zqf=c=8-;wKs>c|H+DE(E77+D1 zhJn$qrBEuKtz_P0QS&JXDF&`Z~LK#1!t22lXK!B~y_=|WYp7wZ9qzasOL1{6-N|RrnQGAw z46QJEo{gKzd`p+t9vXVboQn4n_@ZvZiDW$(rGJPnu;V1*jAQ*`KRIm3^_Ez_Xm&{jT-%wGC^Qs^Utd<#zl^+TXhkej>571oA&kZQFj{u#kfl@~3$8ug#-Y zJWw5EKlTt(!B5-k{WtjS0i$2C?r^Pliyo$j@Yj3z4lqU827WC`)wQ%y$cgBNUWDTk zwO{fGTR_yS=>el(%}lAd$@FN+eBYwJ*Hw%@$9yr*w`Y%8TMB=VhaUr`DBD23P%Sgn zx|TKy`N(LG`7Fu)nX7F9QLpn^F#5F=O2xC4%q#3g7XQ3OHCn%Kf7Uir58WmrK6fS+ zUyra|Uf@4#^FYIX{=!WQh$hWisiG;nbLR1V8=kWaFBA3#O8QRta{TXnS9zBCEFoqr z22lXK)L663XWwE!Bi3s^`w5ff7unxhupQ;O)Ax0b=-mj$lF6CbYUoAsiK z_4F5fL0_9OX-v18_MduYMn7)ve0<8DJxwR!*LwI4Fh$u0-j$^4TG}YQ$`#K#pGEEW zJi-Mj)xfMTNh-0=M5_Yit1 zkdFv78u1wAXUzKDZBG$hKQ(1hy)8uvETzTD1m$`p)pEHaJ*nSOZguUUb#=Sx;NTW+Bfjdzm7l27zUiX zZ)B-Qxjh5*8smx}@Nc>Vq5l2V9wYEBW5pPu-uoIC1pd-kQ4nhGunPjWGFB9X+9L@9 zU)m)IwIm4w_wN#fx;6;{ukR9s`c4uAe((RW_a1PX6;=BG?d}EKZ>4De7>#lj%{DiMMA z^bwIh+4UHKUousU5ovhbiNJMC6^Te&BqDHe9}(&4i3of~9}(%fi3mKQkBD?-A_8yf zBO?7I5rIGNBO>i^l$RQ~tEpnCkq%2l;AkHa>7_?|jKEV(6=OuYA`yX)T^7SeBGNld zE1e5?K_3z6%40lf;3rKLV???>5rJRnBO=|Bh`=BB5s`kIh`?7Z&kKX}Nz+PUfYB=~5rYyFf;G2@7N_kBK0i z>;v{B@XTz$9-Bpa$e7m^kO4Kuh_t+dfd3^lI`k{7Lo4lc!)JIW9|xY7(LQCEt}d|w>BJfvcsK7t<3ReH(!lgM zi492iQX2T@DYmoBpSsen5|Xa>Oz(Q*K)Rqt=Ga^CIIa#|O(Fx*uQVi>UL`c(2^N{s zz?Y>2fb=P)(UTUrxgW;^I6bMb^&fPrH%^nJrAao*hBM-g%$nGmyoo58?U@Kojb^2J z9i&|;Z@z{#e=C}x6xJC!Q!H4z<;9agd2FUm>Q(PboMr=_jP;ip|kg1bGcF<-o4ddwcn1&fASZn zafyUiPl+pM=TaVT!%_PyVx7+JRHvb&haSA;~(gdq#bL;z!!-70Nbb_+B1X)|Zp ztaqywKRAWit+I#6>G=4?yY_eQO1=JA z-Q0ik-<><$9Cz?B=~rs9!B<&dlj#PKaY||Qw_UA6sSbRQFT#xjYcuwfoi+h{XBHdy zQSPz!o@EfvRZji_H!zP>^Kp>j<#v^W5J0?G35lV;$64dRt+K%syr&PQ9pI6!8V9DK zIW0NlGsAMo(Cp&&GG0jDfbYm=i(rOwp_Rjks2Dz;oO!xnh7_4m0~tm%AK-sW{sJ)h z$i232&|}bHRME)5OfDr&Aft@r7Wi!&a5NUynH3@vJt9ncoE=ww4 zZPNW+qiJTrjIxqhU_OZePx<`12YimJx=b+`mnAabTaBe@g3tGm9Uv1DSxkJc&C7Xr zB#{9JovJgHk=TIDXfz+-i)=_28W0;Hi2|_=^6Y?2i-ZMymDvD|AB=qv8t^~;P0u8d zsgtmPSPzX13&IRabzs(AWf%ssFs8I}U|(DOHF4K+J5#qAIirkZetF)ISd>Sa_0T+m zSxS7((fLtX7;0;;GpBYXT#a9-$cN?$_h-HyQ zfiqViU`Mpxa80ksOb-~_BF`Sk`ilkyCp)tYJ9DwGfG-2GC?0Zx@!2IaA>e(I2`N2a zO%)q8+^lvg&rR(HI*cj|Pa1P#PGEAk7AdMUX_xVP90G zYpszn#PjM&(gZTnD~-XMRal_`xk>`SuVq6#i?sKpAs)ygtb_!v>r1p9;6bjMC|!BU z1ta%mK5|dAhv^=}G_JesqysWsOD!@a-{3=X56Czy0a?sqNS54}qp#LjIVui?DeL%8}gOa|(l50?wPEk;nJu5s{Jf1gM z+Yd}$MI2(wvO!sPi4YtY=V0p;fjMEq^K&JAgsk4TMn)rv}^UA2Nni?!0{S80r^R#Y0}sufrrW;D{gX`eJkjgYqZ z^3?1ktO;2gTeYIn##XJUwXyb4K2>RUt5(qL?lYqy&tuh!O0!$FqSEYEt+>cqYjU%v zDvfT{ib|tfwW4fvQad!ceNyXMwSp%1%v{Nc{XtVo;P&vmls0&?kHu3!TH;9a!rO)r zvSztz#hk4y+_=>S#yj0%>-^dv3;Ajc%-dn06BUgD_oFhNh^lyHz&HR~`65pZIrxO!g%OAbnOt@*v-vO_ITQR}vIhn_n|c)#$*d zyFb$bGK-bi=x=G$!&KSZG%~syok>Ch8OoIgepTv4Kst`nz;q&s4aj6uX<*zPp#hm} zDh!8-7l|hD_@nha_~*w^(TRUo>o3NUn|GbXeEJZ+OpyR9JG~R zm9=v4=Tj>O(zGQ7V6By3oV9W=O6MVC+BO@ySrVO1Y$=t z0Wi&7@&=?CD-BFL78;OtskHv4)ifLWevI;t%SEGI-R3xGJF5+ogSLz%S<3()ms$pp z<{&c|V6A1;9yvaR)*<-BG{Xbp+)4^SybKKqW@r?<2t3zE$q8VsnWZ+>njC5Z?O}3a zu*NbmNMng_Iitr*^ElnAc^z{CWs16yL9b)U7{$Z_2#sRWgEar(J-s*e+P$gQ?h@5S z$a47B1j?~mbrgl`L+0!gf6ca!)1^5C(;s9{d+82{3U6T0Ha%ba(o`9=<{LjA`k=2X z`EkcBc8eQpT0T^M?{86i8_ijJ@|&KvJ77@f_D>mSXc9`Jhf4>E9KJ{?%%Yz;q7)6y9H$NYq&XeQCUDa3T%02VXMZ9p-wP& zEUoBv)-#j1i<`y{#_UY@nOYM|jc)r^$gy_F>Sr3-AqPn_?$=Yp=+)sb2##SE&C*Kf zD&@*?P`0=79#bwI2VShP^zT}_Pq3Es1C4MfY{>n!J?-ICmj5=Fhiu7SXdo-v)f_g> z+pQ(=`dV7?b#wQ-3j4;v*_BqTmBqH5%Y4DL10+|~4tT!xQnr3nN!PW@H)oFJ+Y)W| zJhf4>E9H}3Ii}8%9&TP%>7^{-`C@T}6kGgG~?Ex`0uN&j@Ta~Ra&m9iV6>w3KCVhHYqArCb#nW zK(Abv6jrRj`oFJh-1ltsfH`YFH{b z&s$Gx6=S&J=J`%){ql~!$>H|=wOiK3aKkH(tb}b6?;WV_)%y)qjc+fTvoLoF>-`At z&gPO}YF>AgGW%nG7Xp_PyPz!RJnCIB|9MoJ;4tUG-PS~y$FU%wIxw>zX;VOqo6_1# zV7{q>IiAwW$&tiX&W$RKRy)uCm~m~q2upy>C@LYfSsZ0m%SI%jm9<$3DFN;6;5RKi z6HI;bOb=gVxltXpx3hT(s%ux(<63JbwU#8Q%O5HK%5oqM5DD{kN>rpVGq-ml6(~MG zlVu7bA7LQR-}GATKHPR7Z{>%-s>7(}uN`5B2(R!6J3#71D!aXGR2`^3ZjoH;k&U%; zR~@R`AqOd!KJcN2)X1-PATmtys@uydD7EkQq`n?wRs%#RsxrPxql^A@lkWy}82jF9}V{0S}LF`Vj;qgqivu@I{la=3xN z*av}D4GlGau*l~lN%k3I^1+QkCXM;+U$xXqAnfXmPdbNrU?GQ_7g(Y4+-gqpzmbM9 z51U%?ruD&LC|M;GTH64&rqp>-;7^#ny4I(WU2Nn-QYQs&;;M<8t%2~)M@H#W?V}R2 z{&9&e@O`eD0AB8@F7P|9ngD*!RbAj>`%p!tZYWjL@EMU*t`6l|=!NJ2U+JpRw&`zu zAwyOZQ$iUE&huIp6;&q7LG7v=up`t-^$u&_m1&>VQ! z_N@i?Hm~*(xwTrcts$SETVuP6y;?l|1$S82(u!=PIjK?? z;=FBUsiwiR))ivz)4%d4TOrlMD+d$RrBD&o!e&EuHWZX0#UpQ}Dy1(ItyD-oWUVun zX^K3wRjZDcw9~9QCy%j^JKI(31DtBS-544ICeqSY&W296SW}g?Vj5b=c*<3p)!((d zSesXC$qQPs$!x03SA18ZOOrd80m7zf=`m^yN2+5&OQovrYgRT4kLuPlb35OQuDMee zTUjP9sxoa+l}U@LOj%TAv7?Nw-NVgzmqb77er$J9QIN`TM)Z#?>QMFz5Fu44s&*+R zH*2NQS^{D~Zl^KPPQ%Y_@RY>q!T;fbRQwOWMO>T9PVNtfV?#>KYk!8&QEbw zv&Od%zMRhCvdM~#;S!Q#9en3NRH+CN=~0e2rVo~x_6HWmA6UY}3x*rY%~eZAi8upR zsluV=>sIV}NIHhC=_%ahjb)0>6m0*MEuGXX4_@=puBfK@vBfffY-Pyd20kapD{XtI z`L#tp56NZ(ApvNdJeN4B4Zh5%$=E9=}va+JQo<&Ba`tHjfIZ=wLj8Ihd=$eL)U~Fj-%g6^LjgjU> zcQs`yL0P5~lx0e>6Om39=^eF5?`SHK-ciOGPN4AJ4!$QKotUP}q5Vp~)~H@%h2?Xg z@>n@G$Cn-F9JKTBd|^~t3NS_K9~6$n6qAH)WX8S&ye$1b- zGUUQFH7o_>ss$yUjlEPyv)%H>q$=an&cBY`UcHcOuRB*xh-WKLcFCazmnT&%C!5>t z)eE`4IGohP`>fSyjSvfoSH_*8<}sG!JS5HOa`Sp-e1pvx2f_IU@w|qQ@O+b6j1@3N z>7S?OD+I!7r&9aqaao!AX!MU{pY7T107+gAADFDDkt-9f8@^Xs#HV`#?O}TXhfTRw z9)vDebDM+ILfgeU9|K(_mx{y1J6@w^A|AtJWL4vApd94S+R{h$*!_^2z-mH#)1D~D*YmMcNXdM{~Y6x z@gMl_uId7>e`{pLut+zXR?-EYdv;Dldg0qV5#Xt&iZLSH{B|b-AF(Qr5$T`Kbt3Rw zQ>`h-jHlN)bnz^TPuY!_6w)8x=`jF*_O3iBq@&;MMBoZj#Tb!RCL(ZE9}(#pvmPVx zo2H5}BCUD86M<)#DiV?Y`vNBd?=w{-B0cgwP6Y00sz^jSBoTp2P30Ag;`NCOytgk> zq|Gn%)PXyg$|FT_QsM&NZK{}4qze-f_@OdV6hBQ|;IB(Aia#bUaQ*kj{KpI+ZDm^N zLckqO<)uRLs>B7JRdP{$HF1I8D!C|rp18on-j`<~ z;EtJP9h*hEClP@d-54X%PHruGK#XoAA{~~9KrC(~BE2OMfmqx~MB2(tS`Uc1jYOoE zCn6AY8;M9CNJJpEHWHEUN<<)rHWHCW+>-Tx7}`ig+9DBwSlLKKIxZ1`nAk`}x*-vP z*w;uzx;qhp*w;uz8h6{+17cqz5$V!I1Y%z!5$T#l1Y%z!5$Q~~pgkbQH4>4|PedTb zH4>4quQJL2F|Lt_beh;WE0H5o8N zb|50$ml44X*@1|_psg`7RDaxtYSn=mokL)R&1_&*BAC%R5E+3PV1trD^iUh}G&J}H zrVB)b*Jeb<%O7PrhDL_DP!=147|}w6fHU=fH2|7Zh(5*Z}u@TvpT z-9ummyl5rT&FP$hh_I{mR3(DxoPmfyPgP>s(S{ySC#9PmZ_c8|45sTzkNV7v_o#ES zz6bsn)5-hEvX8~Ubf}-%N<-8l;izfiWsi!?vP&tm>^+fLc9p0t`$g2!;D6v=j25(P z-I^AS`xVv;Vt6E)yfVwy9hs&5joPw}MlB6;xtX`9MZ!vITHt&7m`FQhZ5K?tj&YW) zSK}-jYGjtJGHS~vD8CSgY9zibMoiZ~cY|9>gFD(6$Mhj0ooQP6Lg8WWh`Bq;uA-VY zIFnSsb4(@uZ`E|Ip$^g{C5c*VsG^N7|8Pe-52(4z7lGE-5kbZGl# zm7ix<*;xR@h|9wCC+seRhNyrqv-zb)cAjCbs$(9Cbypo2t1i(2G3`nNW6^~M#I7q1 z%s?YFAXZ&z;FtRxYl5eYU6PPM{C*7y-rJX8Ca?mG*%Fdk=DK#+n3O$@ku_5f`iuO` zHqVy_r+Mee;f2X|A>g1-4m+UHf$5hL9dN02Mx}x2s6)-sz|?1#1L?aG8IZm!zkdci zGxgc?r`IqikMpeY&<)=Ft$TsDWWN7<|jeN=Xm;^F-2@7~<8pl39y?bjMo1AYP z!_$^`^?$ICXZbib3B1Tvo!U6YbT*A+lY@<8M-MiRO%67WO%67WP0lxtF(^rW02!0C zErW6Jg$6v{e0}kEfDBz>1Vmu$(&)epUJ@OUu}f)#4O)|f4O)})4O&bwBqQZIo~Q;J zv?gnV*1K)a!Qdsaecn_IUZMgrc4^_k3|>M5GIl8q%-|(7;OdWKleKY-F^%y|p6bV^ z5pdfyEBI?%*X$#RH~MJ7gBH_RV=Xqso{EU_o(gpO0<6bWgnW6mMVT*JbhtYo0d1P zCa(49zYl2D$EvOWlF~})_cIEKT7O!$Yzt-rDOCr|=NvqV$7jn<;G_J#WH3~c{3kkl&X&vBI zt{Mf>cQk8s8m_qx_eTm3WHm;%RRM8+gau@JFOLPtv`*s(zt;RAp#k6Ms!<@_Sy*&k z)(Rv^;NJFPSK|jC;xBtUz{6ZM0lXy(3I37OIzZMUZa#8_b z=Bh3OJ?|s50N`t!HVR~_sx&Y@o>T|$@!2~FFwUFMfEU}VW{nNZyi{nw?bF;7$aGU! zK-@Wv42(M`G$8Jr(!jWGLIZyFJ*hW>e{4G0rGsO)MrI$u*hy(Iz}(pb7;D{nVZYn2#}RV4GCt}E;Jz4N+vQuY>kG**etTCx$3~#N+fV) zMgwQFdf*YZrAcE0FY|3qJ$62QDx-m~Pqc3u{9RH3F>CUyfUnFf9Qa(fa6KSqO+o@$ zKMlDxV>IeUX|i0FP#X5^UZbfFjCGQS0Q_KPsKB2woj4gl)+c02xN;idxXgNiU+SBu zx@T%H1KcJ zPKD~I^LJ@z!X+_Wr1orjTt7h ztFu+&)i$}s)JkK$)l|I77S)z!bPq_AQs%DAMAvRkYt}k_r?u|e!e4G);#RZs8k^Da z_DtgZn5nL@>$=Sgo3*yy{;@k~6hAiQQ8wLLSGPxdK}louzDmqN3S7(k*STY;2N|vWbc68yCgN>UZoK^7aq*{HE<1 zlx3rk!0m?>77^oAMt z6_X9z!yE(RkV;+gp8qAr3PE|RzpFLZprqL`wgx5bjs*{i5igNpHt-M_b0yQ|(nR2u ziw;3qt{ns=o+2(_P~rsQ@C9Y*@&#o%JgO&RULvoO0mG^SC+aS3SSENIsGzye=r7}WKqw`z=F9B3IT@p=BshJB@hS#p$wuV3H` zkSrN06HjLQY|Rji10$htSTKw9W~*ck4W{P_^QHy9hR0f)GQqeR!n}NeZw_5ur+!l& z8Q1E&ra$MS%YVp>$NA@YfO))wJjtBT(_P)?na456Q_cB2X`W~8+2(wn_v$|3&3Lk0 z^?hp7=)VyK{h#v*ON;!#k$>jSIX=iEm4r{~{3)ID-JL-@=MOrAcFsMY@qjyL)0|?9 z1+3CZgShTn;rTVK`FWLnZKyR7n@N%Qt6^ zhnfm|p4uqcbCmCwmIW3ggm#t<;rR8Hkm^{p7e#yRkSzyXpB^Du2$8xOAmmU(UVrV+ zqVm--ZjwkP_d~K_pY<)SI{xr(Gu1^a{sqkdBz3rsuy+Z(Z;)(MR{Zmp7V(-^HrB7D z$$xzAMqFWkW^i_;YBUoMvn*`s)!YG+t7>cJJT>cJRnp$=^39p!p{Bx~r#4FV9OXO9 z*4S8A6B^5EG{Z_rZSw8a{9Zd`waF8bH9e`D0YVNn_{6vaOp}chTL(FY zoAwN%&5AX3xy^?^mELjzuXk0Ksm7Ci$-VXcX^rkP79xclYlm$8ra(R9AZhB?PpJsr z^vOPY-oI_*8#`KGQ`T=gJ+P2^cIF&=9;=t8_7wI2^TJU!{PJq>DW2Qb&+Vvjcwiwl zw?DVsu3nm9jx3=$2+{MEkEwD6LKg8@FF4v~h*QiEFYuQ>QxaX@pO%aGd8a9nRpRdp zCIY!*FZ0(tcfNI(r4AVyaH>D+xtnCm>gArhRtMMI5kId|C9-l|r84wrZkO2$f>+s9 zUM#ZVjdus4QfB$b!74(op=+FKtd&NJJ~RR_B3ZRwP`mTWaD z<6A>^Syp0Wg>{~g8q=?={EK}Nu*>^=-gnGV4}UB|Qr-D#zJ;5aJNkud;^=a%TK{Q#GAwx1p2AvcOL%l#^%3#_e&MU& zQ@mlk%*T{g-_wHs$U>}M$aU76D<{Nrujgcv9I&cd=`EU*yDh}(h1_6~d}XoHsEK8B zx0|h}H`J_YH|He{H^U9PgV_!v#+v0Jrk}w}wzn}Hs!^SktnY6@EwVm_2n*N5Q{-B0 zGcPf>;#K|vvDI@&B=`EacKC0kDc8$1i>!F9_9nt|4NM~|SGH7Fu3@Q;)eTlJR2OoZ z{iDNgBdfu&2&dZgLV9+;3$=UijP*KK;GSrG%vYjga@** z?*moaP;r<+ksj|vR^TH%g;<~=BIHOtAnx}t%H*0$>1E6?H2PH8|nYu zu9bYtk8au6&*)YqHO?;1# zmkeT*szX`3YMKU{_aQ64{3gSXtsvWY^vi&x9Q?{DyZ;Z)>i{ou)v~s2T*lC_(AIH7 zY>W-(_~Py|;FUS=b`!9oA#hnToiLNvr>4A6OSdFd8M2X({eOQ#4Lw+@qiK>Aqc}J@ zp{4N1X;DE*?(u4Zvif;eWc8o>dJhnuFRI|Xi?-!b!Dbh z*Z;UxN;ashE#?1B^0eTm)+@QrHA-`zYh@rCX+<{IC~Z}<(E1C*z)175&1MnkXYv_t z*~_@yX0vA)n?WG3%V8iW%ctg1v>(ZNMWmHtHO*c0Yd?b58j3aMZH-3GB`$JuyX{!5 zL_gF(V%(}V9+{vFU2XASOLm%Nz|WehI%;X&uD9XsTRseSfQ)?A>9U6X7Yp+V58DOa zVyckty(Z8xDus=2Ht0bN#9|zPm*o+XGa{a|bSGM<*Vt831`_eY=4G;!aIBUm|63#M z{USqew($A{z~o5Y$$w?n*n?-wjOF+8*cIzfn>Gz8T#%&zCI!hg5&w58NC=+&Gc@uhMy)p%TpDMqJYcb!Lr2r-csZb(b?tQJ*<%dSTVR3M+K8U8_ zgaF?=km@XF78Q>y_ZMDo?jc`C&}v~Bf@!zvnD}u(U3E0P(e7^Y_0rb5)QD&8O(|<-JB;!Nie4cGj55$EL{+xyikXX# zi|D>+(S{XiBK*8nN>C#Fz?AbWQ#TDYOy8A3f-L`^Z9ATx)r+v1)lQdr39#kSrzj=IMYM^(U-< z{+svH4v_dO-6(~-pXj;$-4s1AMc*13h8n^pQtNF+uu%E%+x*Tt3WxKgip#Z7QL*gF zSvXO>!j>+WtBHz*P!7b2ij@}@kVVC^CCAl7#fi1Ed>$~0m(0{rSmjeqbJ%!?qV%oF z)6wpKrJXWTpfGc$NPUayWuXF-V)ZS6m!+uA#_z8j>XMYjP+j?)R96;4b!8b;R~A8a zWeHSQ7C?37b4c^{`g71Q59a(g3+}Z}z;&)!KKHp+Jlc^~WOL2(!(?wuJL^jK3yY~d zM0#6Lmi;X#%f~p!TI~MTR}c5)#+JJ-TOwN>x5brC|lMZ-Imd^EojMW@%kAc3-f_8;6 z2dXPGpt>@B)s@MsuKiRQrvE0XFLl6P-^A5YDO=xkbM1B zXuQkk%bk^w!wnxH;zJ9Sj17(OaRsh5Qp1P;IMFlb@bZ4!^UWs!g~-NqK9nyi_8g{< zb+#ta@c|LtO}@{(OLRZ+?R#CKTjq25)_aEhd4JF%yTKzJ1CoyZ?mY?J>IsbjNn2?o zewZgd1|&a9%QMi%AF`}`!n4!?k~R76%3Tct`CKS5ud&?=%d7@&nOWnO`3>AM$Hpx) znlEaQWwIpk+%ZS~o?FS^9Zfxd&#mO|j;5Z!)~4JA4M(v4;1$_wSwkc1*(o}%mDW7e zY-glL`ysv7`K6(e$J$MvICL>FR{%if3WatBCp^)Z6EhQ~>jK{@*C_5gucilWGElBx{wz4mJ1MtCqEW z{k}c6geu{ep!xKvIzF|Jds4OEwj+|Yxk8ArDPxrLN@awiBEJ9hBbTis;W4^rSP96W z9Jp#nH%@e4@#v}_s%VlNO|X+0!WXvs9x?-E(MZW2u-#ZdLEa? zBBp`w5pZ%H!l4 zUqmP>;@ig;0q1zaYg$>zpgiGrbmK&~hetQZ6Mlw8H)>buL_ksqwMB%Kw_1hq(QIx} zJKCEn}1iP(~;!;@j3| z7u9F-dRzJYoUee6w| zYCCVW$oPhnWQ0%7aR^aVW!0M8_l5Rj?Zn7O?J9E`;6pEq^II90ft#C3e`UKni?p*7 zyTC(SH32-lFD%kIPV53Nb=3s$ldkFlfAkU0-5llYQ@6`GMmZ@){ONF{?L5gbAbE~N zq+TKdk2h5$B2hkZCV`YM5|JpP5P_6768lP)g!_50ODOP$p5sv$_M zwm+%ac9!bkDX-m}D0hA}G`8(5Dr#ySeeiY<9qm3vh=%H0J0uk%L`AE}(n3Ws^R&>> zby8Yr=ssCmsLruUOo7l`YIm|+prW0nKxnA`ED&|fb;xR;I{%5)y*@E8)hAzQn_b|I z?=~B+lnExm$RrJ}u@N=RAZf|6-4?sqCRNfWm0F59pY*tntU+6wFXg+et~BLv6ONWo}Z}Dl?VtlzGcKU75M;R++o( zRy$i!Q)W&aBXUK(h^kCeRApKfk1B6i{i&_62c*proE}z(99-`0t3!qS(N)Xt{!nac zdwTm?2AnaKy6Y=$DxPLgKHgg35#AD)0sp~N!dtbXthbnC)3obtid?69n`+nFRJ-0< zT|m?Pu@&x4yRMdLA> zCY|(X#z=!pABVzOq%}q@ve$N=w@*EhW(tt*r7KPp>tC(^s_fw6v0^)91+3 zx2%3C_Zs?x1@ef<(hinB`Z6{2c?lE#K`Zw7MJQsYlza)P9ed=b7<06)HLIKKDjp{A z>!uoRUcBf6>k15aLd#lPx0nsQ1$DwXG~w->kf?71>xj zWNYO$W@t+b`*gcXMu3!1DrYk?N9CxlzeMsj)fGg#lSkSCzR^^}%}JYq|2gS8By_12 zU3t_9g;JfT<=|$Eg(0B2()bl?X|!iCjUIu4;f9+uOX<;Vl4^Ec%@KxnTOVPFjn-aC zHfEzu>=New$APjWD!-v9hrCB&P$bKhS1ZKyL<@a{U8UlIr?{#MB(3U5Re6s}t2*E> znu?aC%rrf?v>E6rKUX!Eln$FC1)?S&nff&$xQ;Z;&zLz>T)sA`w!yp25(oeA$JvB{ z1i7x+O1Kv1+AWsE`7fM=BQC!#STKy|;5q@PkH$xNn_Z=9fai|ITjEy%KWr+Udv|A% z7Iq;3L|V_Z6%R453&qsO z&0Zg4K#Hqzk9py*@>&`LUYFI<*enuNBLfJKN{BHcQ4c}{Qh-P-^K45F13up+Jl}_S z&PRcJXE|Roi^S8H<`2y4Vu{xUGLZj(0$>P##X@aNt_CV+XZEcIIXw%7Ag;9_s}6F}-gGrZJmg>uUp zFOWhcaZR%X$^?^OWR_`3rx-Y`eASMJODeS# zbAFj_TIHLslq-C|Ug!5upGA6yk2qt4WJ3ym*V9{FOsY6^F_Nc3wIIa$T^pfQ2j=n1 zNCc#YmDVa}pMnm^KqISv|7nHU)W^&zAft=0XvH*4*}g>TzjQM)1#H}NIQr2BX_}RN zPx|}`30*8m*UZqG&}aC-0^GIhAO=?)cmj;ofvc|1C^U$Lv~A_s10jX@0X#iy0E7?g)w zyMDGe^<}_UnJVzgGP(V4C`-!s6!}h-In}PrTE}Zw=2V%m%BNXLUu##^9QUx|?q}D^ zyf;==)AX$Vh)QSm=UQ|`qq?%vR9EJ*z9JAaPCDs%jgbrwNgVk0Qy8l}g^!6+tJEt61PbG*}HBPe+)gQM>+DbgZKm{?>2 zP6XF`*X@3zm8I&M8TIdYR`Sy}vxzi-ph%W0V=pn>WcmG(=eq;k)JN_v zkhH`MwMQyxeZeqzex>ked+c(AL zHdjA6A+O>Iz$8=_x$ujb_K6CJ1=mG^?kv6}>uf><;?75+_x8T^HL}BXT>CgIo;IZ{hdXB88ab@xhGaC( zLDC^TP3!lz9GirzYRMx#Jlabhewzb4aVO`mCBjnbzmO8lpaXwYfqyxFc;gN^5$Sf*O47hncFc)Lckkpe z0vGR`6Onc?t;7g?^R77&=?c>d5xDDaIT7g#rWGP^|HtJ-q+3iYMBqpE$cae*&$L1W zp7Qvdi1Z253K969eMF@1B_id5)t^^r{yss zooHH#5%`uqBGNk(5%`rpBGS!?2t4rVdD2KHn^uwrUU^tfM7q|rLIiGecuqvx(X>JY zPW2IyUY>}+Cmor`h;*1~B}U-B&&Y{LhniN1!0ndiM5J9!D@5RHk&k z+W!^i|7zetUjxi3Ht`9>7;q<7b%BqzIfWc!1v0Tv&wOka>3u5eWs_(xaufcLtp3w-hBUMAp)uId86?W!K|JFe;i$F}gefPe3*4)9u6O#wga zsxI)FhZENn@J3g4fcq|n)dTM5sxEM6pT_lo%H=4~st0_7tGd8@UDX5L=c+DnbQ@0* zIOeJ@u(z$VfRnE30-v>=vw+9DstbJA_Ra$S-c+&5kRI_!Cjz%}RTsF^qnriY*;QTO zGi(Mfy&rf~HYp#QMY=o@fuHUpA~9u`7=g3<|5U7U!(54freJaT7G7x)ZUb%Fotsvhu4S9O7p*u~=lZsn>j@C&Z$ z0l(;~E^r%Pc<2FHlZeGc`mrxO^nka!stY{wv7R;HGhEdL{;R8cz$;zV1@?CLxPX(c z>H@EFRS(D#NGt%-*L^{x2mFz#A`$6iUl8d5SC}dikyt^ICIY!XjOph`_J7Y6|%Cy*w+xdrTFxg7mJvoe11!pQwsNq&rP3RRFxN zkBBt&M2`{p52lJSBAwvGF7V~9>H$~ug++REA_6aT)fDh@SM`85_C<$uXCeZB(?>-5 zofEsjt@icu0$DDLs(Vq26uB+56C)OOaW;$5rM3;MIzEOo!A9l z=&By@GE>E{NFQ}#7kIU+dceo{D%=$CnkRWh0sq}pF$JWrCnAtFJK4$!eBJ>b9q?>Z z#psZ3N<`qV`iMwV2YQUae=t>y5$Oacc7Y#oRS)>FzOYDFINJM&VA_7^zk3^(@c48O!0ax{aEa}IvNUZ9MMF-yM zVY|Rxe09GEWZ^$Xhje2i0&g=_BqIGG5rJ!D?+eCekv8)81wG)FeMF>foY)2K@2Vc~ z*?nP=-kylS^ZJNLHzy+SdwoQtA33oL-1Kno0YKh$#JWK`I1zzIm?{#HmN>Bse21%g zzzh1qB3+S)!0Y;mNH;jK3*7GrFA4BzrivLvx*!pOAMGO|UE#zo@H?*R0q^Jwi}X7u zP5~GBo1PwUi|m!q*euec6A`$RtGYnm7D*=ozPK+sq?e?yz&E(62Yj2WrhxBtRS)f9^&u6dO%){#oQo$I1z!L?28d;amQN> zaMV;WMx=KoBJhK*ngV{vRbAlCuId55XR4S2(r*$GxaE?VyGTUZ#kBI&fqV54k%t!J<)(^6q|=<(1zzQ<9&p{!Jljaym{zh4n#=JQIH#AkuBhu1D1o8qj5|Q4Nh`@9DVnn(*5rMoZjWHte zvQ+93$eYqgMB-(s5P^qwDc=-u!c{%sjHzODNM|G>@Z3Hk(nk^zctsx(>CQw1{-%$J zwAnb>?g6(nRm>yOPKgNY_7RaL6A}2jJ|fcl6A^fQ9}(&1LM&*bU`8l zf7VAt`fVZtPhFPRAkte+D>Vqbu#bpzRU!gE*GELUF%f~^>?0zreGJtz1$?BddcfUG z6)OVi1&IiJTOSeWy@?3?S|8D+<>aQfz~BaUjY%Wzn25l~_Ysj!O+?_U`-n&zO?cA4 zElm}ZM%p|p)V}bYZ4K7MjsLB z!bAjK)<;CTIuU`N?;|4JnTWvO^bwIBGey--0nc|;54g^;dEFo#YFZgNfb8Ijm56j) zA_D)uFGi$O6A}38J|fbpLb@+ibSNpOGF_1mLd`9pAr#xMPH0aUr$8ft$jqK4UY3X0v~Uxm^9J>i3ogJ9}(%a zLDk|*Gkw#q^yuq_~lMtbyPGAaV^ks}pp-N$8A1YRjdD$?<`!X8SB zz>0jNA{}qbp^<6=Yo(Ej^g~mn6t6I;p(R0P)7A{FWUoQl9IS)?M}VJjjb zRs@zjA{A*}n+*pl0<-5xMOvOy5tu(mD$+JKg$=PHFoTX%q)D4L1}Xy6%t%GLE2knb ztBh2nWj3n|u_7>Cj8r6MjDd>4gfUW)9%-(9pdv7nh*YF^L;#kFLAw8tU8KJu$7VoJJ{5#j}F$?AZk$fkFgEm{+z^XyZGc~F!kI$%%%`tcH zl#*>9ikV<@$?UF)2L6cYBq!zJ7fpdtmt7mGV;2THDnd>kAEV~Tit5UPDyn18#Fw5B z`I0P<{SQhj51OcsGbNl4Q62B6IpLwY@?3}N$|D@A<8?1bG*nj}%uro<219kcpy7;# z>UbB!aSGL82sjX-I!1h6ji`=S9UOB|-Icc5f300r$7()@7gSdsSx{YhIze^V1Wq5Q zj%7Q}52%i1vc(J$)v<3M?_6~ZA^5JUWA8jp zrRvIF9X_=17aIY})CQF~^*%~>CxnMFDw zV_v&M48@2MqP)WT`B&{4lx(p&V~-djC@(O9ZXT4JFgwuttscUq!?H^$5D^aFGiCjy zhS^r6fx+x63V{)B%>uKZXyM)|LbeVauusx$^u&mFwyP!rKG<|25qA2pmnSIMufre{ zl#DbN?VFM*chdyo(0-AygeN*cVq=|W(H zoigIr4Ku<8A_vUAbYO~c@slHFh|`qWD8jyv5V+j&5tMB3VE;x?BCrcXqZ~dsCbOYk zRdEADXYuP#lym zwy~F2wVKX7reiD)MBadYExGZh&y+6{1G9W#7nJ2|si4F$W{}pz@qlq}1CiGdjL1P* zzBUL--UqPUuTkRuvT7bf+X6GI+)4zqfE|b*Gf$X>;Gis5T!Zq-<_J&PRioqt*9&Z& zG7u4dXG$fqh=*4kh^)i0%%((qVV2JVv0Q!%%5nipLx0>BqrPd^Kx6?51EoZa6bnCr zh?QaiB`8^`c(J**8oD$XLw|8og_*f@^VIvn8!e7Hu_&LJnMJzQw6YXg8Wb%;X-`yF zniJKP)c}hy;ixS~ z+^8*w(x@%R(x@#5)2L-cWSJsrk$&piy{6dMwMp7K1!OeUGL?gAjISIywUTY;5#y!? zX4t&YMoN8@#h|IQa(s+wlmlecmLp`;mP2IJmSd!GZPkDQF>1>ZF>1>pF>1^4Ps>ma zb&*+)bx~Umc2Qf7Y*AYdW13buVnt>-WJPT`K1FRg7)5P48bxh6^zg$}rG9RCzM+I8 zQ!%Z#JUk98XWLaio5tvpxx05v|2fAO8FTNLE=P@^tc@GB5u!F0)O$Vske(KjLCCvZ z*}-Cd=ILUYXL85%pW4aj3~Wt^52x1bYt6IXxXR`+B;WBG9?{3G%Py6 z)PcWkx^`UCH$y$VA+O5zqZ=5;M*qBN@ z&1Mlgq?EhSCFt+X?Z@R;8a_IEqlH#BX-%PQy{f|&Tw(^G@7b_ofhEwi_=*B{Ky_@? z!wN|HY_?-BozmDu$D)Sn*fMv*k@1m8&~F)J!Gl6?Pba<-)g&J-*^{SMhnUU7>i%38@1UTZiwob z)!~GwZhPB@e!Oo{A7wN8&ytF%))TWSSGgZrGRGF%$NQ?4e3#8ID_TNhb0el+RBT&( zr$5qBHYoCFHMhL4;L)n?=l1Smd*3uS%04=ttt9X?d%WZRm`8a{aaK|RKW!?FALnAo z_j!%7eQRys2Q|v1iY-zal1UY>6I91S*wHq1lB}`c=8~l1{lOFMt%9%)GRR&UQSD}v zDJEBGTd!4q7vfHU{ zuzoi&NWatQ+8u9#jz@2k;SV@y$76e|1O>8dRTBlL&NxA5qz6h!AnP6)lAgz+wCd=3 zEH+Ef)$MxpHwg+n#k!uR0LI}L8r?DVy@__;n`rmFiTU~-3m6iAyQ59e(Qx{OMMq;v zLR9oB))_=auVU|msLKALy=vH29Tcy=$5zJp;FZ~raL-n$&x2WM7mxh(nb+Eeg`4cE zO#ytX=|-AYY(0zcLsQB(mw~@G)tb#&w@k0G-PW^wk?yVLYigw6m${GWpPAdqd`+c+ zH+md{?|9pH9A~kdcV-&09KS;G+79J7E87fi8WxOu5yF=KMNsm&G*(J9bm@-Dx03Ko zk1`K6ghgQSJCxVftyxV`9dGAee?Y7QuU9sC;OmB15jc1$sRIu-2RQH$c;BZfu`rIO ztU54Wv&6^u*YK`H1;o(`NtB*eP?pCeHI23xK8{1q!g&bG>NzXtk}!+scyJmW7;i3w zMZmx)5sZ%)hzS4fj^8+twI~hC=W!g zfT%cF#d}&&F&X;D#Nx%l?tbuSoc%sblQh5J|41~ZObgv_9%uH%%t=FnnMFx9m_&`I zkfnPNijISTHxQHvx2M3&ym-^B$?~@Oy?&}^y!7Bhbhz_7m@6;YW4jRxe}TvJ?S{l- zCdVv5lLg~(gs=!}y0<@$8-mXfc)Sf?Vrz?%7a;FnG>y_X31N4(DFScIl~_6~fmpgM zLCMsC!xI{s^ARlAsE%m``;kImgh%;#fpLxy@D5(XGX22031NAC^Lw9wjF%oy;NkwT zOJ5@dvk)4HrE?UNy!v6YyoLt9-)1sW+3bg62fWfs&nm>n8zOuxC4!mj1R}yyYyu>S zEHlWOmxkr-(r*%tX%enlh>jOdEZu6@6KsaWUaCMuSmo2Fakf=4qYAvz)eFkf*$YZG z5VPe%qxcTX6RYAotemO% z4l8Hy9qvql@e^--62M7 zHizhx2+r*I%9)BCmxpS$8bht2D+YSyOvMwwtT`YC0BVT9M3Jc{E-f~XwH_8dS z-zY7I-zdjyzfq3cexn?K{YE(m`;BsZ^&91Q>Nm<^(QlMPqu(e;9KTVHI)0-ZQv60a z4)~37hTu2Kj_xhT8)YZ=8)c{V8)bj>8)g6W8)YB$8)g6V8|7N1 z-zfW>-zfW?-zfc0zftxzzp*-fX%H@N1n6%vJg%B4`&v+z{VXWUJ{FW^{|d^oZv|!9 zuY$7dQ$bnwr=TqRQc#xtC@9N56qIHE3CgnX1ZCN8g0k#0L0R^fpe*}JP?r59D9b() zlx6=2%Cc_+W!W!+vg{K#E8+-77_*dFVII-U}*SyWfPUQu27 z;8a&WH`SGoO?Bl1QeF9cR98M8)s;_2b>+iRUHNQOS3U>b1e5;QNOF|TAT8Bv~dcDDS&cf0I93x0@A zbMv^$d90>gPW4oW^UZRd>TtCAn2qYnygk%vH7ztGRC524G6!|{UO&A?0)KiD%h8jZ z&*j&ktJ9JW;l^Ex|)%TZgQ0sm;Xlm=#FozQ@6nF^x>`{{PHcU;0d$si|hMa6O3 z3+#x8s5s@prd&}0Im!_dKwz7$@PM4!2t0(HZTFJ!IDPTvqyn;`DFj8}#ghbexL>T_ zz~i*V)ut34@GI4b8Q}qWuM>C(Z0Qvq zkkb)?hro*!;Q`r(6?p6@*>M+G93>|ATYfa9+1z`1RerAh=m8_WJKU0 zum~+YV0QRn)eHhViiHQ{2tex zpYiI}AEHgRl1Ce}dtkZ!jng%oiABKL&7qlQ4lvxF$Qc0sfrnO&2v{N|f-y;wFc6cZG%yw^#D{=QQX&|W6o?2IB_)D019hew zD0Y`C5zM(h$srKq6%uY6vNKzTOo-#`*~jnD0mivs5lLAVyMS17`;F%ozl% zq!Pgx$xsXg%%l>*Sjj*{z+@`1w3#85;tWg(TpCR!Vl_DtpgJ(-Q;H14c!u~8FrOM0 zjP(pe1Wc(COIxbCiZMO2WlWV=v8HGGN;f7{iC`>f$PNNFREc0rXdohBM3o4}h6W-6 zR#b^#jA$StU`CY)#)<|a0%t9h2#7WqoI$fJW<a<}=Sfu@e(Q1K#7R zF^4{%oS4sq-;!v+AGoRm#L$b^3!Kk>OU}w^sCHVc_q**VhtPohdV}nu2Qonw77(kh zk%2Ml(oBKabftlxa}ZOZ2_RNp(gb4UH6(a{KbJZI#KucVASPZzg5U4QS0{iNeF+J~ z=4(hWMqg+^Y`)UK7=57uG3H7G|H5B~cYv68d7wb7yM_c~+~pYnvF%C&Uto)JvU3=S zwU>~>THG5=Cf-~#`6OY#IT^_n*@mR^DaG4x6UW9KEmz(Gy^xbIL~2Ap)& z6!7`3ngBA_maGBs4m4|ErrJUS;u|Ope7hg5nE>J~NJt>gf`**WN7%&oc#Q%d>#9j0 z&VwWX#COmHz-vr-=L6zRNJt>ggoXs;O9%~!kDxR#E`sy!6h5T>i?o$WvB$+YAUI?+otDp8g8>?+(1OYeUJ!& zcn@0XU}o<^18(eYLl3yUtCl^>;46{}c!R5Yz+ak5vUbljivs-kq@)SN?+82uRtG|B zvNh%%ec5?g>4b#h&*z3L_CplQfGi(K*juIt@l8So2lGyPgLx;tLA;ZY?0o*oDqr$m z2EvQ4}^9#2U7I^AoBQ1p8-?k~R6<@>hwGEC-st$a+eQ!|W1OC=jAwC!OiiwC_9WltM zOX>-{UW7l(t`Z;c zU249QTm4aEz<~F z_ySW0hKaG|4awCkE^DD2bn6=G{;!k z+Nsg;-3_+ts*Z!J*ZSvhmIJ?Kst_LsTWc$YhuGemK;*P5TYohXj=ylKRdwKNd}^>9 z_)SxV_z?K5tW=9={+QD_Fw6GUkdz&+VNRhs4%NKQmJ(xHChT@h9Cnq+2YMzm9r$&o z3xPRPb9b)fBrLmMHAcSg!y#DJfk!5?0e_hZ$K^@{es3w&2bz^R{XHgJk}DA|bER}c z&eL+DN3+EV9?s3G4*c?7mQ@7ayQW;B;rx$A!FeC{^{TF%W~q*^rEqpub>JJ0&5}p> ziYui+91G$|t%e3)l4fbQOe1jSHf0_SCvY_i@Q%l28Q{1PyN#8|S6t?s{B4@eoaUYU zWjurRiCSHoLf_y0#QY1Q!KQ4-3^rvurZQ!_YtSj%U6m=@F#}H7?(!+yu3N{ZpidqA z2Gb2S#{fTJDj6>BnRm)|eKzd^Z?#KIL*fG-Z7PZHu4$%S&$RiJ<^_DE=_D-ht~Bks zYkIzE*PxRkCP13*1Dyd${+RzTgV5-}@3Yy2(14%JCm0C-=DZG&{rFkV=O*=%V0rFrra9}xdLR22f} zO|+_NJ~sX~zIMnA0$#QT2Jhs~_%T2{@DLW^{@igsH

      L;N$&sGsgfq!WIh0k@2bI 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[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 z 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%0D{1-C6FPw^B#c}`tM0Y-%eO}0?2D*M0y7yom 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

      bR}>f4RK zm~o4nCgYX^*FanUQ|f8`Url}MSKof><(YM`c!jikKeYA#pkB)>SqC=?{jdm@KwG~F z^|XF{Q{Vd4*O7X5owmD2+V28w{qEG83N^2|Y^fK0ldu=G^(UG7hsam!Tfeq5oqAd9 zn;f`>aoz41-^Zx;6np`G2ouS3k|W=P_-b=r7O)<4UD$|2huJ>Rh+|wf!t_d{;bMUwx<0{tCuj=fnEd*8;!JpVqVf z_V{$Z?fhE*mH7Sed-BnBY5n>5-h?AqCwh)pzxv+AzZHH5i*J|t{1e*x2k@PlD!$iQ z2j9bF*1>egdeC}psox2XgvHdWo+I&X`!n$^hhdx(jU4C8f(rUIZn5SATck-ok$g@% z3r4|n;p$t&_aUswxp@|xbgNvS2e)vpHDNz0bsu-1Fa9_<0$u^f!HIAKd=>UtAoT~s zZSZsW-a_()jqjH7+3;ETBHX)JuKxfVEs=5)_{?%CzW{f_J#Y%of!8{o2X`{w-&NuVa^uDIgLAA+4&)Hwthlkg_-VdPOC-mH1%lX@u^LHS;hH;z$=fMSV8N3%J z&y&0-!8UhFIR@5VAm#dSFzb96ybO+npWP+?9dHHb>?$~vb9MyW2w#H-mP!4Ca0=({ zG`IvVgFQKi`$2uL(3|%Q8Sq;8ey+s-1lswpmnqjHq0Xn}Ib65%=QHzG-uTXVCV=|d z(EcT6eHpt?ef{z4denN>KOCQ~U%Otde{_^$ z{qO*^@kS75qKUV`;n#L&;MaM1$1y)~S+b5Uhl`-TceMEotDs-sdp|r)+IbSb4PRtk z6+zqHR(#uF5iEha?=NBh+xnHRk#<`^{T$eY``fZR2@7JncA^H@+*Lt*^cswErCQtn+RC>T8N$ z*N4`#{+9T3J=yhR{a4^mQL^53-CO@-_@0OQURB4@`nTazZed+*hkX~x{H8%$e=qfa zfCpf$>!hB3Zfmko%C>%ee0||yI27u0ygv8X`j_Dw3-xo7eh#w!H}Jg+x5DqVKKtMW zXzPbxFa1z9pnN*C{wVaeFpqOm-;15NSmHH+w*GkPWx#3hW@!Dlp(__sUgYqvMSmaa zeWMTOQGY#`U_2ZLm)<4$KMVCaQO_0q+#kmJITB?uc$;Xa|=F^1v zRBC?Kuj8Qnoc*uQ(RVOU`nl^n&dJ23G7e+lWS9kShBM%6@IANVW_ zSi^~w)8Oqe2X2F3z+LcbsGk!b;d9+5un6vj&3JA~a6CW##`sm?bBG;3JN`rP`Qd+R zJjT%a5{IZqyfI?l6L-}7OvW4+I%-h8+at~Bw+I_hh?PvehWF8TC_wtpLVPpaHV`8CJ; z(?)zw(f1a`JlE=b3mbn0&o#>XDX)dr|2n!p7wLOseJ-;8{rL4g_!r!F^gX!sH{|(U z-&^Z_QQuoz|8G3!hw*%`&kbigo*$m(x$9MUJw82$ZTvI2kGF;&;Q!PSKNa8gurt1% z4u8=Jm4Zz!;`2eyWs|A1Uq)?XuK z<)7=MtUOd*@>bTMAL2UlXLY`90Hfe6m;;ZOaFmW`TQs?OJ zzKN7labwi8guNi@VdSBI2Gg3zrFrnMk#ADqJ@8(*7FrY`oJM~e!luyrv-#h|J_VnF z8=>|8R7I2$c*1c~J_*)=y$uIaw(;sz73DI+M9S8GR}E2=H=QWuLTLT1PZp*1DZ=(J z%FK5(^L!0l3UlFCuo3GZ7IufXIo5}^e*t;)f?aA$K7HWFun7LQ@~z7FoB$)>x$r!w z`E{i1hj#pLVBDs|`OuE<{pb(CN8uAt$KS?3i*eWe*`BhUpFZgQ;7}M3UGuk#>)*hG z&=(<@RE6E4&9CS@QND*i!S*ezQ_7vtd&2>6j>8|_O6nbI+bQlKku+}oUN*9n)jxs!roit_{p)&&zfDh}E8bt7<$9-BVOQAGupeb{ z9r-hoJe4gdC&Jv`;ytsEunBAnV__mZ5?Q_*M4b44DBc6)_aH1PXTF-Z&G$eV^{rpW z=|TGUEPMfOhdZH;Qx4;m4_|YPUwPx^khhInK-|`SZRS#rMOVgCo&gKu#1}tEco|HC zSuhvcR{o-XRj!``%ZjIQZM+s`)VF@^$J6AYc@~bhPATWm?-c{398SF_P5t6Aay@#i zaQT(O=b$To*a-3YVIQ8$SHcJ2dU)sx@oRf2w0AYU6Yhg;lEr^9>+KWVL!?@jFY-gz$205yCUXISwgwlRdW4%SOR?$MZXLF3oeCuumIZj zTB5guU13@AG_H-8R7QR4FRNdgcedZwlyYmwxZF5Ft}Ab$d>gzEYWz>hy9h2!llrg1 zU9b{)xbo?ZZx9>?FNcZn4rqI|hWOu2mMc}K2$wz}2wHHR9b1dlNSfUP|1t@C3%I9$ZKNAA?6)mhWtP7t+oM zM|(EDjh95d$#5FXhBjYY|2O)r^H6_=IG%^~?v(Pm@b`sM&b!M-lCmpaYvO7BG)H}1 z$I4#Ja}Knv_GDe8Wyuxw*>$4xYU}GfpJ~=nH8an1D4&}x5z^qI#ZrD1HdrF%=CA;M z3FYdMKhL^OzV84phTWmAGi|@DcvsVpXJO0@62IP!!mUe%m6r)?z=lxNBY#e%ehyp# z?}ta6@}0J;`*KCL=z6}KFki}-!FBLyc;+IxehK5b-i)JMJ@Th*??UR2fk&M3ozAQ7 z3ti{yXUg@f83%iwty&@1bzdj)f^Q9Uop&1lJmR;388Daj^5FB1_H$|f7x)KkMEm8< zrw;W784jmx$7@-xDBBD_rz}^G{Hf!o{nEVc___LVB$9lm>)zhKo?}1ix~`Wk{$;Fh zUFX`ap38qX{$=c+@z4(|8m|NOG@h-W!F}X@sQbX)Z}r@9)nD*8>lae*2JZWNSf}>> zU)DY@>%O7;+~yxiyX{~sEGwVib0m_UD>s{SKc6^z4QujzraYOlt*`sYKHne5^O?)P zjD7eBEN}f%d>=+t5#0~O!Pt3g(D%g z4rBER@@*b`3H}NX8~J8z4f!UjrZ6{LmP#twYXo+wgLEnzXtuPx=6Qw~=t^-T-v zY5hoiF2BZCYJ9C%D!5nBJT{*sSGv-V>rB7$DaV~GzL7ASeC~4O->|Oum18Jh1!u#2 zDDESF7DdSS%Cj0s`CQlqX2Byh<-533g}dQ*umnb(CfEOhwthPLK3H6aKlgNrpxjA$ zFRav1uE#*zUicZJJP4nF`LGzi*2vbBa!2$h;CkrtPl%LylVHwSQqDDenDXW_zMa2g!lTCUqawSQUkV^|AuTm_r8l=4(KE?UZW zK^srwlr>&=(O&V{5+SFVa2EOI!`if~dAvyZqE_NRo_@7;^sj{YClFtGD`lI%=2bv` zG0e|4_%?aB%bDB>wibP zX^#5VpNr4OylTHRZyk5tN4EYV=CJ^-B|ptm*S(Iru6x)1);Ni*TU`el*S5d@K6w!O z9ERU7?a5=mO=E2*a zk+{lR)`!k#F?pw?C+c~L*YX8nA215bmC^F{Cbk?<3^=3^;G z779DTkKp;+L{ElGzL4@3cvg{=&}kfK*sUwGRD)6-x;jG6tfO>ymWl}Fg{sjjMpb-yzKh5 z-;YGAgsAb{Qk|Q$N4nY{{WcFI`3}Q`3lMh;7qgbPi4J7 z!g|+ruk&Effmy8Y*Wst|FF5iO$+H^s<=O`|w~Oy;ct89acKKYcr$U`KUFUY)>N*|o zSg)rtj*VdyOng<^(Q{kJSg_E!F7Ml zU>z=n>!IeeYPYN-Jy%`vUv`Xl>*u9@EKGbs%KBXL)CMURLVJF!!2b+Xf4;-7?I;Uq zw;0;^@#yN)=OS&#`j_B;0;)gPk&m{k&wct_rO!n+{)}&BJm$iAa5=R8eDv4h8?eyf zk1dw?Q{i>+W>^4=VB&u9&wx2F7utLZ(3gi*4PMfJM^fAI?@0#yDDkg{IX_AH0hkB( zz^I?)dTZDV&Vn`{jT=qEvzb-d`E;V8HQ7Qt^}&1&NB0#9Z9n?XAtIxlv--ew%b|9{fo&SqV> z)?EocT?aK;2NCcYm=E8Fx(@PL2d~5bt#uJq#=6jT;M$*dJaSBb%j#cQ>$nX4tgCR=QCaK4_Wu&bzdsxZ6QT9@LAVCq0B6D+ z*oJ-30d|Jja2C}4QcRiZg8p|2SVbKkO{6SM|Nw z>}W;4ui`u2r!UcuzFNgs&9_EhdLMP6iZ9HU*ZC-cZ>#vcof;QPKfxCnQm^6Df0TT5 ztt!5nz8L-2p+{Y);ycmji)0s<(rfvi934tO$rpK5C_UU4wIP&#vM)NMUfUNFQa{BP z8&a?13x6q8eD5dI`JwcBzQk8U>GgfFg`xBilk1H~6<_F|Tvze&6Y8VJEbwg=A3uRU zM&~EY$LOJd(p<&IPm+)E^AqEv^uXRY&bR;2QBv^Rz!_iJSHq|OXkE|zz|XP*dNB{} zs$Yukt0B8h^=$NTqpv`ZH2U-C(dae3a^S1b`!CRLEV_=!kLZc$Spl>6Ro6?SlCQom zd#}uwo^cnTM;3`5b%OYZdU~+G#PN&ln}UCqiL)4gTutvA?<*evdh|T>SoCe^#pvzO ze?pHwQR3)~p6Hz~fqdf77s_SdIq1c;M9`IYA$s^pqVqFH-*EI;bp5*+6VY|QzePSb zq9@|N1^of^V)UEPUq{almv%P`eBYzT)fS-;y^eP?3G^$vjtCzTrvrL;VB);5F6eRS ziRhORXEJ(zJrQ0<5B#pVK>VBt5!C-MdT|5M`MYesch!HY=vnYgB_VJ05dASvujJjwdv)^$%KP$0B>1%n zJ;vxCqsMm@zn;(g(8IcjeiCsidkZ@de+_yq^ayl+toXyxqtS~m5WPNn;9)ut$B(Y( zUK;wI?&3du-$5^k5nb=B_i7w;J#ROmmynO<|0#M-XNkk#jr0ACzR2|J1TTR=p0kV| zi5`BD#L>S~*9kqQhv;6|;8$PtIQpwk3=`0E$Y1Y+x1;+58_@fz6a3TXTZ>+NVd-`^ zX?)`^LQgdFQlfFlpTFDatL@!CgY#m>r#X7GnXkU+1tw0i>L$-@^gN?4Ro%pS3O&x` z^DcUpnU`JY(Z>HL`W~|$>UbL@(BE+5Z-HKXv5d2>lOE_fCjTUKztOKl?{$g9@t&}Q zU-QumO+IVTqs=^SQoWGM5^UQECAeAtYhNB;Wc{WW@lnHR51!G6Vz7qXY)`R!B68w4u zeY07IFQJE_d)qnqwFN!GjOQ-(8~s=GXU#f1&bvVb#-{|o#;=FI4L`Si-5_l-UXy};>`VHv2j6NIvOQSDD&*j`` z%J^?Uk2Ck>BJ>nOC+7&tY?aX^I|g*5^g4oAn%z{+5Y9PW>j& zIp~G#7jJn4zgD34VH~{2x!~7B=zGjMc@cfH*}w0jmvC-)$8zv%H~ML2qpITQt5I|3&B#=-zE2`1LUQT9fAs z=!xw2bMWs*&oX%)Ko2wVYj_XFf$>~p?iXjGuONRNpH}F5%zn89J<{Ye0X^J27tKch zg7|t4FGMdi`*$^Zis{!g=#l39c@KS-8Rwnon@#**(6fxcy7yoo7@uOE-#lCJs|k8M z`RIJLLtkm;s~h@KqYpvvW%@N1JqN#@OBv_|jOQ8TlY>6n#J>mqG_wvLMlUhv|I6q; z#?#w|!LLuy_Za^V={2FXnTKcbf=)+>UrFeN ztRL?&BltB1eGU2OKANpM>q?)`1HU{mkbeyOMfb%+=zc!ec*`>Q^&0vj;%mFxR5$B( zA9|G8kAI*~G4oR0`#==PXN(z#2=sV#&9fPLw7KtJgg%RW^f_lBdWt!h#-N9pdC5Tc z8GSl>ocY|h9Q|t3uXX78?PTZj`pWkKdX^ct-RQH-x++00;PaZk|7qyGPzsD&9_N_1 zT!UX7Rp&WSKUZFk9%0VgiRx#)>Ac^9oaI1c81bS8S98MlknZ}fQd zSkvw}^!2o>=g)QMDQ2C|LytFlF8V$*4v(PkHu?+bIp+P(r|2cDb3JeOp+}qjTh)8f z8W^8q=G|LP!LO$1Uzm2=pl>sJ7xXwY?*q_N%zjBi&o`#J@G;j^moc{Mla@XQJlqtZ!vl#12cmc z8CAUlGtjTR?h+@H{3Fq$dx+kY1LZ>W#6F@&FrWiHJ@E5cf1#Y`x~|5erx^VP_49Kv zeV)04_}N1w{#+jHo4ABV zGe6&4jX!R3Y5%7hXPW5R-@nkquNA$YPrjlWOP+~Fk3-Kh`V@5Eb*1AhM~_3#V;r`q z|3>kve%zVTZr)9z-z@OeMUR~>LImqG20d|>=#7a#0$qPO|E2V6GP?ef{;%-QLjQA} z7%L|T@A34&&zG}bl?E4)&$B_jzAw>?{|D&tMlVM1W%TN2N&MU`rQ@F+)a(25zYsm1 z`~$y)Kd_#|zo;Bk{@}qk6Fs}G=&jmGg;m6le7AJ`SMVpUk`5heE&d-h&UlFvc#j$Q zYTAVLuvPql_kDq{LFoC%iT`Qz8R-54;_t_U?{l6WShu4|x=i83ow@m!QtH^~K zO{Lx9nj*Y7O!Q9Zd3~hanS6jBr}}8|@3~m~cYAtp9^a}O6m%Y+L678|j1;?XC%Vt* zVP{MJe)8Azwh?-Y(L13h8htQ&ywOw9_1JEOkeieGS(QiTzGx~CLpV6O0FWFvt{THAY8~tnaJw~t6T>4vN^i$Cbjou!; z!07$aHyeFCdcM)K(bpS&8G4@4pFm$@^!Lznjs6w-BBNJ6Px_l<^akj&jNT4C+vxq! zvy7gC?l=04=qW~Dik@in$I;`B{w{i)(RZWwGJ2&J(%)F4N1(?Ty)AmQ(fguD8GRgj zq|t9ck1+ZY^l+m;h8|}0chG%C--TZCS?TrfYbpILHhO*ZJw|VXUS#w>=!HhVGN{+{ z6@4u2>hr*S^n9bgjGk-sU(mCS-l$a|fA8-r8odvCtkI{SM;iS;bf3{bKri~JbpF0* zX*b{KEzom~emQ!!(dVEi8ht%_tkHL&M;g7p_q-Vx2cOaVp%-l}o&R+7e4{^to@?}v z(6f#H7kZ-6qt2InVvRl=J<{lN(S1hWgkJPv>HPP5df>S|XO2AIPC8j0G*4|4Xt%yE z@>B7L@%$P1pT7k32&4D)^gx_MK3M<6b8_H+Ruk~&ne{veeT~sqqep*Iy4@Ghqm2GB zdbrWQLk}~0SX;>_(dcKO#~b|u^f;prMDJzvtI#8jo{b)1^rh%Nqd$gTvaR$uyp5i1 z{9mGH8U0W69HXD&eGUuE%Pga}M2|IkH}n{zC!qU{J{dj5=sD=QMqiD-$mko<^Njv6 z`WmDE=;?uVn7>=r^Zntna3k7Fe{;-wYlS|`=zY<1jXoNEkTg2(AOLN_!#MLp3zT7Ut{zR=+Qy7>)-V2JoGh2?}1)q&WBOxg+`x-USRYb^vyFb?kLW2zuXUmHE79mp(c_KY1--zWZo6b51dN{CXOF{v(e|G z=No+$`g)_kn!<){~&o5HIzKh_w+!X`DQ)$ zMqh9AWb{0vUx&WN=!?*Ejs7V5BBQ^Bo@4Yc(PtSw@IM_4j2H+Lo1({=^?xCHFQdn! zM;bj1J;La>q5F)!61~La^CEhz@oz9^OOp)L)vzZQs|-(?hL?^YKTXK!UW}7Cp}BJ<)TFKFZSr z=XosmFO4=ns2}_L6LN@CVB#zb`j7oR49|OdsQfn)Czt=3{qZ!s1wC(Nm0*ts(XYMe z;j2U+fqq<188<(=_ZT1iIt@J!{Vepr|5P{d_lx2NRt+lk(fgo>qjS6VC7~A&5I>Jg zzAW?t^m@d(13eGD0s3n69P|kE4d`*`jnF?tk4D#g_MwNHIF)-zzl!@yo~IJ00eS(t z<{yoohpzebM9)Fj@wo!skFNcij2>tFbJ3&Gd93rTQk`)=g*=}__u<$1+Jc_nPx{pu z{~q*g^rq;C&|}dxPQBhTKH=!6<8Ogp+*ji3ICn$ON7wk5qi3UQ{B-nK^d`igjqXD~ z6Fu-hR}QShfRM9)FzaoG2p#zEJ4JgE=sA6>_xDSEVt z-w8b&UDwYb^y1!<@bpmU!*Wj#-0%E>U$EePtz#UXM~{3@ z^eO1u&~wqx<6N!MSK<_G5r4gEQlSxgaiQq9%W>@MhMv7$bp4;ij6yH^N_74EY?IOb z--xcCUlyqThv@usdf$`ixqphjlyh$fdh8+5FBkZZ?;C?R7pIc%B;Uxj5?@9~ z{tT7p$3g$Gzt?D2P(Swf8hz*KK3|C6vos*kZoR|L1KMuQpzfV6`K9wY)6;7Q-dDUJ z17D5t>FMd=TKOoBbm)^b&Vv$X4s~WZ{0kiVeGdI;;)g#Z@kbK>J=Iwt(I?7<9ga8$ zg8rjA#J6DsL-)6irw7KTnCB3k_ofd2#SXn+FwU{un zpCx`S8_WA~K=5lTdVY0T4}ss)5%~JS5$E{0(BpHarw7I-+b~qrJ z7x5=K{8JtJbca4K7+?Bw^q(t(y7%`F?~``*oP5L)=VeEnt;9)OCvongkslp#s(TN> zf$_vs~!Fg_;VkX{_4K|#Nq$i zq5tI2j~^`g_}SNUxbL6g>7mA_g+sr{q4#&_S32}8PYwdry z=LP(6Z;C&Qb^ejVzcc7R_V?_4L!9E5B+gFa{2A1bT|g%f2|aF64!xtN2m8wnS*xR3n6I&ALgq2}=dhu()cd3h3lI4O^H_-8uw1rGh*VEkjp z;Tebj&7j|#7xsG;RRh0VH&nkq#-C{JBRd@N_XqvQ=2O+{c&PaG9C|B<9_!HiIrPgs zJ=D5Q4eH*%H(4$7@-iuBJK`*G=&L+E^4RYB9(VX(bm$*B^gRy!4~Jgk($M`qBdB}p zoDV1oJetvl$J&yA#_;Jar_>Cj}Uk?4m5%lX~dA_~1wY1*c(?hM3P7b|~L!aQ# zr#bZ7JU!I@&2{)64f?&Gvp*&i;{El2;MeQu#czwwKXdYZ4E(o&bo?bd>(c9H#qdSJ^f_w=NF0m{DRj!zVC=% z#B*s?o;MCT;+*I`sD#>&XE^lc4n5Y>L#?-=4*yt(o*j(iJy&o(PiK7Ybof_!dL*8s zvBBYg*P(BB=-+#KV7~I1uQoJNZB*!Si}3V--^b^^#rQj*=kT6K?_d2LajtOa6CC<= z#Lp(r_O!de)6YD5VEF#gpuhStzvuiZ;^gsOMgLviC!QW^oqX-kD_s%Vf09FQS1NA=96bnmo01Kf89HG(J<3@_R{5$xIsU z&rJUxJ(DsrlQNSNB&CEvVZ07y$QI&~(lZVZPv{0pSwaN~%tq+`C8egO1yV>$b&Sr~ z@nbTn8aHj==&O>)WG3`X&g_zznLZ>lFl%Pex+YDW*grWlC2j2CT2f3HkUaHRdtmND z&s%!3U&F^u8#>LOoG>^!Y3#JaQ3p((G&(swp?7NL!1R7;spBq9_x>21oH2P~X22b~ zsR>iZCSRH4SpvNc%$PS?W0Sp<)5iRdljgM9p${1>^zdhRT_2lv)ZCAmn4IKZJArWy zjC}X3G0FbGgdOQYsERhR5T4L!1&zm!9v$PtkmSta-ddli!#pOMT+Ju>&yNTls0}W4yJJF!0!`fpsjCX#xiJLzj$FJL0J3 z0&C!Z+=2l^sYPqT2N%(iB^~POkqvAbcAuGnsG)bIw~1Sh@eYgNnID`x)8tXZG+1s{Sx|iA93lx!QF-=^zS~j*T8NStAu-S()f(z5ZT2|80`ZPZ+z-F8^s@3>*nqtcfmG+wULoJ z-tSKioTQf^oC?6rDuk?JS6$*$;qi>l0#fKx7rB_DkLN%q$iJ^JSI6| z%rx)5bEGFn8N3B8w_TSd@DQLk`lCW0nU27;9d#kuyYC+!*uxE_`HvdN!>V`t9-lOE z{540#FLg|LVWsTu$>HnHj^G#*Sf~lfr6yUU%eB-aPc%mwmP?tX7J^ngW(;U5u&hHj z6u1(yncz705@Oq<$0^_YDZklA*}?A4>Lg=i&kRd-~_s(LX*-QKBVyb<-DEWL+>gy8bZm^>*X zAv!C;drbCtct*Tqt@MZ-$+h%wpbt2D{T_XsSaGA55nIXpOlM_#)o z2YV03$r;`vvloVV4<||KrH4VZQe!4k=`r`T)YN0*aTp)7n04Aqhduh}Hc99KXf}~| zgGx@CbZmH)O^!i1#6FQQA=co~E6`uxLJ6I!=9>if1wzCX%xe!HXO_D8-y%6*jMC_{%M-k8JRCIwbga9yPb zzVk-cd))R<&P*7e;oT&!o_wrvN}$t$%gI^Z<9lXu;A5L?n!u-`sR@(i(dmd9d^|A4 zgh`V#G80B8CusXeu4jx%P95vDosl-td!|21pO*UnI=gll$(E#A4gv>wh|eOB(4bvu z7lWp6{~L$t>EE=N>1lQM>|?F_s;jEI>rGYNR(;-^cEDK=gB3`Ci3KYp#EPF-V}*o- zv|1rpkHtW&g@q6}&%oeuA|fMyH*U^@mS%3<%!tg4$jFROe(qr0)PrW;td`^1NFA~_ zbrKJt*JXX%tWZcFuIfFU2H4p=$@;=>9^p_6;XZB9$D|Xz%^DEWpM(@cQ5p);QjD;V z#)GJAehuv(O!|xLjY1UTPhYmstJTmGC8SIJVevH?*zTPqXAvVHe zQ5(-N`=JRUF@d3&4gI_nN`T5G$qf}!Lwq*3>IO4z7|9gv@cGmJhmq%$2>5h7i?X7i zsYFntVTt&oFL2h>ZfMo%2tfwhyz^GN4`rfYSW$uC#BUK~Uk_}!$RIK7aKrw7V3Q{l z;Ul*)qG7+>jziy2A{#`R@}+dO979=1gf>A4FG)(Jj4+oH1avhbVKtLx)nw5n$P`tL zgtF~5w7doMbC3giiKb+6MtudgZ|YJb38i?aGwUK;R-68PA!b^5A0ZYqq^V*xpOfDl zbfJ=EQCrieNeoEXtJeRD=m*eK}f$p_5MT{FZ4`PK&S`#CQ9%#~Ss9RA(gSv;S)L zX4ZT>bMtF5AT>*>OtT(_vBp>-4y@hp*|u8V*3}Ly&O9X=#sm{A#8f*Kn%c zeE0imTRC-F(Z}QAGFTHI&tV06Tv{+oUTR)EGm^+OMDhh@u~Ut_uZ7&>!&12zaXErK1J+e=GPKl(j-4xT*DNh_Pqma4Ju;k1NV8~H@c5%8pVK=hIb0{Bo-qV&Pfb5+_2x|^xk z+jQ;6H&oOZ7GmF~hHe?&ajg@G^s0mDY~e;FgvaJ}CvdgjGL*VucZv6(tystWc-rnR zw`y5tov{1Vgt*j9^-NFAbn^e1iOyl?- z>qdrVode$ah^AiHo6U@jSV%CvRZV($*85;H*2ZX zd9YA4`kvNO709nNjGv(t$oIoT-{(6CYT<|K^ zZc6@of&6uw{Pk|~t9_IFYQLNOYTqQk+V3X6+BeCsaHnfTVruH|o8(vf-Q-vMCi&HV zf&4w2{JjGCdp7xd1@iZ7^7jhl@7d(<70BPS$=@rGziX3^J2^Z1W!ENuw?O``P5y3y z{9T*;-2(Z$Hu<{+@^@_VcM9b1*yQgN$ltNa-zkv4W0SvAAb-auf2TnHwoU$af&6Wo z{Otny+cx>z1@gCT^0y1*Z`?m(WwHMT^Xyu1ew*du$pi z@|!Wap{ajuH>sNjJF--W5>@6bT!;~MgowI{-Y|#IW;cR8<~F;1gbmY0*yz?h8z#{k z-8Iy;f|uL|My$_}qrh46Z1hu5n@c)ha2>s2AV zZb#P(!F4;fUI?w*k@Z4g-Hxjl!s>QZy%1FIh^ZIMoyuMut4ey)R-9GIzOW69YNLA) zRkn#y6_((t4nwJADRr1iC40{=j>&OztZTaQ9+v)briv~iSXdc+*s7g@4Hgvqa~UbV zuc%&3nj9uwRMjnTX*n5;92P5qL^}yw!_p!+-|Yg&g&ceXhkM0gg8t+YJLzOi+0Mfz z&NPEJDAL|ex7DXB7rTa+wAntXQIN3@g-$bIM|+ZqO)!JeVnJo68G>~~M~Ue~ChZ`& z$Hu;e1x0&Y@><6;x?BL8M6FD08KCndL{QkfnY4@8BulCR$OXfMeGS3}6X5C#NJ z$IQlce?IR&Vhc77yY_D9*dbI8SJUYu3XR?*EEj|JAI3UNgd5l+yeE8+O^;hbX*XM`VXRprddX3!}Bbf{fBblaXBbgjP zBbiKBBbj`Nb~0P>Ml#t-Mlu;nMlzX7MzT!~Ya9dGCWn=c0o_3kd4g?dcHi2`tVNAv zn|Rh!2DD8)t6Kxw?n_o^2DIImywSsewuvWyvklCyT|3z(-R^dqaJ$oOvOBumY_Q$o z>pgcaM#r{0{)EXK12jx{PNlfqIgW3C6lcpkpt#r(>^F3J)ltv*(xEnFt})|M64k~h z#L|XP<5@$k=HsN~d4s!VVyzaJ`Y@rpbVOk$SgTotr#tm|zH;cdBkc8;;{ewM<&WWDKVxqX^~xFq-v95L~pVoV3gvtuwZ2U-L33h1**z@f2JM5P^K-Q z_;i(oY`2RUDtM{B7uD2;a!gWPUIuGv;-np1VGJVY&@!g1_%uyT+w0xIYF15ifYtTM z<-yD2`uO~a7q5nkM$NwZ=qu+3FV7AEb9(-|K7Q^%pC4T!>H6iNBAvc?_3Yq9{p#f8 z>iD|8K6v)xxR!47TQ9kz-5DT%40F^AxAL6Ko9Rh2pZ1qXbf+|~MoT(1kw^dxa|{RC zht3CUFCJgOrjTpJLSdJ58V%*(XiI(d2%BRnn~USFpo09l<2Zx)3*;j@4egq6#RuwP zWsF8opPs%rdv;iFtZm@q)CxuyyKo^e(RIp@2FN{KR8TnXaq;M`L!*7kJs20W!So?5 zmKJbM=`tmlDtxv`{5$aBMxDiF-@_v7ggJIOc^^shShZ=<# z8f?M}AzllLWK%@$ypiqoz@#G428ZUGb$W=>saGlgoJK$0kmL`fA%iaU6ZXh~Fl9H+ z%S-KEl-96d`*|*!TllKMbjDr{UKd7z!y@XK5CI(dq7S`O5$)tZV3(8$!M0! zj_-7Il#_GmCY74Qn#TVdDNtu@b7X@Zn71x*f5Uj{PD4Agfggm7cxE2p3;cFshF%P< zkfEdRZibaAqhk$Rq4q32iRk&@J{x3$cSNU_;qJqPAi1GoAsHl`XeJ+Q$L$OwoXoxL zk0&k8(LhHL_+KUx@bK&?>tDxvZkX@%MCSBHni>~2Enyff&x!P z2sDP9DTu9J0^N~FX^Iyuv)9swkyJUm49vg6)o%|tXS}?nCef+CXVjI?F?**1MuX8S zCEsf__2GyO4~{v_6=6uaemrj?waHT=qVdZ)MoCU=7*OtrCAS-MA(PK9q~*{~4@p0W zbuAs`U=9{nt}Nf;Xt+IV8XDnl?m$oQ`AEnI_{`dbsv;eJz+oDavsOjiEL;kQOKS2t z)(~ub6 zE)}Z5!(-qx;+3f^nBwA9(&dP*h=3xe+UXb(I5oZ<e2N)W>uQm+hQbh zde#&cOJ{cyZRmqna&LgE&S^h4*n9`G2ylCJPPm<{=){-fg&Sb?uhLQP=Y8Zral9De z2G3l7yJm;$A6c7m(XQ@fO#AVBh3ipBD%mP?)uE$hu2Ei)<`k75x`V7VE?(!{4pWq2 z{KRsHfyg#d(A-D3XJI%Z?aiWg4r|LvTHJc^b8smb&YRJtDKrVW=AA9B=PR77cK!UK zY2HAKdBq_{gN&0GF!v^c7VsTk)sj$k=EiPHF)41UEpDN99ZfQ^N9l=nDpVQu&>xdf zGRI}q&{#O5bJIEy9A(g&XA7O7$N=KG1E$VwF}}l%5G+2vq_=FnAX@9N*@VITLaum9 zMPR;|O#S&PHZxMza;JQRoled31-)FDJ54DC)8$EUIM@QZcs%Ss;Qo~n zdtQMJGDfI*m|46#r?42d7w#6ATXsP6-X@|*Jt)JpnSrlrA9IuB#G`LgP%*^l9y>@K z?vWM@O96HZ+UxxTx-ZCc3k|j>*Oj{v4Seu7kO!fR`@osjkW=q1gGNZM-*=mhW>kfZ$JnZq?J!z%2;o}UL^2Ctm9OpD8 zFE#S!qe-6-+^+}RHnc{{skgR-71CQ{|6pz2;HHv(Z*7Ed8vCaAL*VM0V8~L1VCZkc zqAE}TH>W?v74U0!Fy!dJHLguczQIj$SWcPJouU98-K_3VNPl*R1r+x>p50O@l63=S zf241GZrtU7Lp~W^u}gI&86P|Ne8Fk2 zf8c)T^Y7hvIpnJ(Tcr319i&d*Z%->z;qEjCG|vaZi2xHh#qTf8oCWtIvu19<{>f z_5VSJ|KvldU!PB1e=5HApT7Swe*6gjseF9tTY~?kKapn+ukZT&E8vodDE_*`U;m8w ze+yiqU-9=G{@y$Afx>_Pi2q6U6#uEif9mkRONHZ4`KIkwIrtv(;`-nF8=?EXKb7Zy zGIsb+@%8yH8NUDi@izqjxjcLUil@(i%kV$=J3;v1FXj3D>|;Ssd`a@--|?WbJpJxF zM^C>k_`miJ{Qm+j(Z7y=@t@-VQk;n2j-CGb-%(l&+PM0k_<[0-9][0-9][0-9][0-9]) + -(?P[0-9][0-9]?) + -(?P[0-9][0-9]?) + (?:(?:[Tt]|[ \t]+) + (?P[0-9][0-9]?) + :(?P[0-9][0-9]) + :(?P[0-9][0-9]) + (?:\.(?P[0-9]*))? + (?:[ \t]*(?PZ|(?P[-+])(?P[0-9][0-9]?) + (?::(?P[0-9][0-9]))?))?)?$''', re.X) + + def construct_yaml_timestamp(self, node): + value = self.construct_scalar(node) + match = self.timestamp_regexp.match(node.value) + values = match.groupdict() + year = int(values['year']) + month = int(values['month']) + day = int(values['day']) + if not values['hour']: + return datetime.date(year, month, day) + hour = int(values['hour']) + minute = int(values['minute']) + second = int(values['second']) + fraction = 0 + tzinfo = None + if values['fraction']: + fraction = values['fraction'][:6] + while len(fraction) < 6: + fraction += '0' + fraction = int(fraction) + if values['tz_sign']: + tz_hour = int(values['tz_hour']) + tz_minute = int(values['tz_minute'] or 0) + delta = datetime.timedelta(hours=tz_hour, minutes=tz_minute) + if values['tz_sign'] == '-': + delta = -delta + tzinfo = datetime.timezone(delta) + elif values['tz']: + tzinfo = datetime.timezone.utc + return datetime.datetime(year, month, day, hour, minute, second, fraction, + tzinfo=tzinfo) + + def construct_yaml_omap(self, node): + # Note: we do not check for duplicate keys, because it's too + # CPU-expensive. + omap = [] + yield omap + if not isinstance(node, SequenceNode): + raise ConstructorError("while constructing an ordered map", node.start_mark, + "expected a sequence, but found %s" % node.id, node.start_mark) + for subnode in node.value: + if not isinstance(subnode, MappingNode): + raise ConstructorError("while constructing an ordered map", node.start_mark, + "expected a mapping of length 1, but found %s" % subnode.id, + subnode.start_mark) + if len(subnode.value) != 1: + raise ConstructorError("while constructing an ordered map", node.start_mark, + "expected a single mapping item, but found %d items" % len(subnode.value), + subnode.start_mark) + key_node, value_node = subnode.value[0] + key = self.construct_object(key_node) + value = self.construct_object(value_node) + omap.append((key, value)) + + def construct_yaml_pairs(self, node): + # Note: the same code as `construct_yaml_omap`. + pairs = [] + yield pairs + if not isinstance(node, SequenceNode): + raise ConstructorError("while constructing pairs", node.start_mark, + "expected a sequence, but found %s" % node.id, node.start_mark) + for subnode in node.value: + if not isinstance(subnode, MappingNode): + raise ConstructorError("while constructing pairs", node.start_mark, + "expected a mapping of length 1, but found %s" % subnode.id, + subnode.start_mark) + if len(subnode.value) != 1: + raise ConstructorError("while constructing pairs", node.start_mark, + "expected a single mapping item, but found %d items" % len(subnode.value), + subnode.start_mark) + key_node, value_node = subnode.value[0] + key = self.construct_object(key_node) + value = self.construct_object(value_node) + pairs.append((key, value)) + + def construct_yaml_set(self, node): + data = set() + yield data + value = self.construct_mapping(node) + data.update(value) + + def construct_yaml_str(self, node): + return self.construct_scalar(node) + + def construct_yaml_seq(self, node): + data = [] + yield data + data.extend(self.construct_sequence(node)) + + def construct_yaml_map(self, node): + data = {} + yield data + value = self.construct_mapping(node) + data.update(value) + + def construct_yaml_object(self, node, cls): + data = cls.__new__(cls) + yield data + if hasattr(data, '__setstate__'): + state = self.construct_mapping(node, deep=True) + data.__setstate__(state) + else: + state = self.construct_mapping(node) + data.__dict__.update(state) + + def construct_undefined(self, node): + raise ConstructorError(None, None, + "could not determine a constructor for the tag %r" % node.tag, + node.start_mark) + +SafeConstructor.add_constructor( + 'tag:yaml.org,2002:null', + SafeConstructor.construct_yaml_null) + +SafeConstructor.add_constructor( + 'tag:yaml.org,2002:bool', + SafeConstructor.construct_yaml_bool) + +SafeConstructor.add_constructor( + 'tag:yaml.org,2002:int', + SafeConstructor.construct_yaml_int) + +SafeConstructor.add_constructor( + 'tag:yaml.org,2002:float', + SafeConstructor.construct_yaml_float) + +SafeConstructor.add_constructor( + 'tag:yaml.org,2002:binary', + SafeConstructor.construct_yaml_binary) + +SafeConstructor.add_constructor( + 'tag:yaml.org,2002:timestamp', + SafeConstructor.construct_yaml_timestamp) + +SafeConstructor.add_constructor( + 'tag:yaml.org,2002:omap', + SafeConstructor.construct_yaml_omap) + +SafeConstructor.add_constructor( + 'tag:yaml.org,2002:pairs', + SafeConstructor.construct_yaml_pairs) + +SafeConstructor.add_constructor( + 'tag:yaml.org,2002:set', + SafeConstructor.construct_yaml_set) + +SafeConstructor.add_constructor( + 'tag:yaml.org,2002:str', + SafeConstructor.construct_yaml_str) + +SafeConstructor.add_constructor( + 'tag:yaml.org,2002:seq', + SafeConstructor.construct_yaml_seq) + +SafeConstructor.add_constructor( + 'tag:yaml.org,2002:map', + SafeConstructor.construct_yaml_map) + +SafeConstructor.add_constructor(None, + SafeConstructor.construct_undefined) + +class FullConstructor(SafeConstructor): + # 'extend' is blacklisted because it is used by + # construct_python_object_apply to add `listitems` to a newly generate + # python instance + def get_state_keys_blacklist(self): + return ['^extend$', '^__.*__$'] + + def get_state_keys_blacklist_regexp(self): + if not hasattr(self, 'state_keys_blacklist_regexp'): + self.state_keys_blacklist_regexp = re.compile('(' + '|'.join(self.get_state_keys_blacklist()) + ')') + return self.state_keys_blacklist_regexp + + def construct_python_str(self, node): + return self.construct_scalar(node) + + def construct_python_unicode(self, node): + return self.construct_scalar(node) + + def construct_python_bytes(self, node): + try: + value = self.construct_scalar(node).encode('ascii') + except UnicodeEncodeError as exc: + raise ConstructorError(None, None, + "failed to convert base64 data into ascii: %s" % exc, + node.start_mark) + try: + if hasattr(base64, 'decodebytes'): + return base64.decodebytes(value) + else: + return base64.decodestring(value) + except binascii.Error as exc: + raise ConstructorError(None, None, + "failed to decode base64 data: %s" % exc, node.start_mark) + + def construct_python_long(self, node): + return self.construct_yaml_int(node) + + def construct_python_complex(self, node): + return complex(self.construct_scalar(node)) + + def construct_python_tuple(self, node): + return tuple(self.construct_sequence(node)) + + def find_python_module(self, name, mark, unsafe=False): + if not name: + raise ConstructorError("while constructing a Python module", mark, + "expected non-empty name appended to the tag", mark) + if unsafe: + try: + __import__(name) + except ImportError as exc: + raise ConstructorError("while constructing a Python module", mark, + "cannot find module %r (%s)" % (name, exc), mark) + if name not in sys.modules: + raise ConstructorError("while constructing a Python module", mark, + "module %r is not imported" % name, mark) + return sys.modules[name] + + def find_python_name(self, name, mark, unsafe=False): + if not name: + raise ConstructorError("while constructing a Python object", mark, + "expected non-empty name appended to the tag", mark) + if '.' in name: + module_name, object_name = name.rsplit('.', 1) + else: + module_name = 'builtins' + object_name = name + if unsafe: + try: + __import__(module_name) + except ImportError as exc: + raise ConstructorError("while constructing a Python object", mark, + "cannot find module %r (%s)" % (module_name, exc), mark) + if module_name not in sys.modules: + raise ConstructorError("while constructing a Python object", mark, + "module %r is not imported" % module_name, mark) + module = sys.modules[module_name] + if not hasattr(module, object_name): + raise ConstructorError("while constructing a Python object", mark, + "cannot find %r in the module %r" + % (object_name, module.__name__), mark) + return getattr(module, object_name) + + def construct_python_name(self, suffix, node): + value = self.construct_scalar(node) + if value: + raise ConstructorError("while constructing a Python name", node.start_mark, + "expected the empty value, but found %r" % value, node.start_mark) + return self.find_python_name(suffix, node.start_mark) + + def construct_python_module(self, suffix, node): + value = self.construct_scalar(node) + if value: + raise ConstructorError("while constructing a Python module", node.start_mark, + "expected the empty value, but found %r" % value, node.start_mark) + return self.find_python_module(suffix, node.start_mark) + + def make_python_instance(self, suffix, node, + args=None, kwds=None, newobj=False, unsafe=False): + if not args: + args = [] + if not kwds: + kwds = {} + cls = self.find_python_name(suffix, node.start_mark) + if not (unsafe or isinstance(cls, type)): + raise ConstructorError("while constructing a Python instance", node.start_mark, + "expected a class, but found %r" % type(cls), + node.start_mark) + if newobj and isinstance(cls, type): + return cls.__new__(cls, *args, **kwds) + else: + return cls(*args, **kwds) + + def set_python_instance_state(self, instance, state, unsafe=False): + if hasattr(instance, '__setstate__'): + instance.__setstate__(state) + else: + slotstate = {} + if isinstance(state, tuple) and len(state) == 2: + state, slotstate = state + if hasattr(instance, '__dict__'): + if not unsafe and state: + for key in state.keys(): + self.check_state_key(key) + instance.__dict__.update(state) + elif state: + slotstate.update(state) + for key, value in slotstate.items(): + if not unsafe: + self.check_state_key(key) + setattr(instance, key, value) + + def construct_python_object(self, suffix, node): + # Format: + # !!python/object:module.name { ... state ... } + instance = self.make_python_instance(suffix, node, newobj=True) + yield instance + deep = hasattr(instance, '__setstate__') + state = self.construct_mapping(node, deep=deep) + self.set_python_instance_state(instance, state) + + def construct_python_object_apply(self, suffix, node, newobj=False): + # Format: + # !!python/object/apply # (or !!python/object/new) + # args: [ ... arguments ... ] + # kwds: { ... keywords ... } + # state: ... state ... + # listitems: [ ... listitems ... ] + # dictitems: { ... dictitems ... } + # or short format: + # !!python/object/apply [ ... arguments ... ] + # The difference between !!python/object/apply and !!python/object/new + # is how an object is created, check make_python_instance for details. + if isinstance(node, SequenceNode): + args = self.construct_sequence(node, deep=True) + kwds = {} + state = {} + listitems = [] + dictitems = {} + else: + value = self.construct_mapping(node, deep=True) + args = value.get('args', []) + kwds = value.get('kwds', {}) + state = value.get('state', {}) + listitems = value.get('listitems', []) + dictitems = value.get('dictitems', {}) + instance = self.make_python_instance(suffix, node, args, kwds, newobj) + if state: + self.set_python_instance_state(instance, state) + if listitems: + instance.extend(listitems) + if dictitems: + for key in dictitems: + instance[key] = dictitems[key] + return instance + + def construct_python_object_new(self, suffix, node): + return self.construct_python_object_apply(suffix, node, newobj=True) + +FullConstructor.add_constructor( + 'tag:yaml.org,2002:python/none', + FullConstructor.construct_yaml_null) + +FullConstructor.add_constructor( + 'tag:yaml.org,2002:python/bool', + FullConstructor.construct_yaml_bool) + +FullConstructor.add_constructor( + 'tag:yaml.org,2002:python/str', + FullConstructor.construct_python_str) + +FullConstructor.add_constructor( + 'tag:yaml.org,2002:python/unicode', + FullConstructor.construct_python_unicode) + +FullConstructor.add_constructor( + 'tag:yaml.org,2002:python/bytes', + FullConstructor.construct_python_bytes) + +FullConstructor.add_constructor( + 'tag:yaml.org,2002:python/int', + FullConstructor.construct_yaml_int) + +FullConstructor.add_constructor( + 'tag:yaml.org,2002:python/long', + FullConstructor.construct_python_long) + +FullConstructor.add_constructor( + 'tag:yaml.org,2002:python/float', + FullConstructor.construct_yaml_float) + +FullConstructor.add_constructor( + 'tag:yaml.org,2002:python/complex', + FullConstructor.construct_python_complex) + +FullConstructor.add_constructor( + 'tag:yaml.org,2002:python/list', + FullConstructor.construct_yaml_seq) + +FullConstructor.add_constructor( + 'tag:yaml.org,2002:python/tuple', + FullConstructor.construct_python_tuple) + +FullConstructor.add_constructor( + 'tag:yaml.org,2002:python/dict', + FullConstructor.construct_yaml_map) + +FullConstructor.add_multi_constructor( + 'tag:yaml.org,2002:python/name:', + FullConstructor.construct_python_name) + +class UnsafeConstructor(FullConstructor): + + def find_python_module(self, name, mark): + return super(UnsafeConstructor, self).find_python_module(name, mark, unsafe=True) + + def find_python_name(self, name, mark): + return super(UnsafeConstructor, self).find_python_name(name, mark, unsafe=True) + + def make_python_instance(self, suffix, node, args=None, kwds=None, newobj=False): + return super(UnsafeConstructor, self).make_python_instance( + suffix, node, args, kwds, newobj, unsafe=True) + + def set_python_instance_state(self, instance, state): + return super(UnsafeConstructor, self).set_python_instance_state( + instance, state, unsafe=True) + +UnsafeConstructor.add_multi_constructor( + 'tag:yaml.org,2002:python/module:', + UnsafeConstructor.construct_python_module) + +UnsafeConstructor.add_multi_constructor( + 'tag:yaml.org,2002:python/object:', + UnsafeConstructor.construct_python_object) + +UnsafeConstructor.add_multi_constructor( + 'tag:yaml.org,2002:python/object/new:', + UnsafeConstructor.construct_python_object_new) + +UnsafeConstructor.add_multi_constructor( + 'tag:yaml.org,2002:python/object/apply:', + UnsafeConstructor.construct_python_object_apply) + +# Constructor is same as UnsafeConstructor. Need to leave this in place in case +# people have extended it directly. +class Constructor(UnsafeConstructor): + pass diff --git a/.venv/lib/python3.10/site-packages/yaml/cyaml.py b/.venv/lib/python3.10/site-packages/yaml/cyaml.py new file mode 100644 index 0000000..0c21345 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/cyaml.py @@ -0,0 +1,101 @@ + +__all__ = [ + 'CBaseLoader', 'CSafeLoader', 'CFullLoader', 'CUnsafeLoader', 'CLoader', + 'CBaseDumper', 'CSafeDumper', 'CDumper' +] + +from yaml._yaml import CParser, CEmitter + +from .constructor import * + +from .serializer import * +from .representer import * + +from .resolver import * + +class CBaseLoader(CParser, BaseConstructor, BaseResolver): + + def __init__(self, stream): + CParser.__init__(self, stream) + BaseConstructor.__init__(self) + BaseResolver.__init__(self) + +class CSafeLoader(CParser, SafeConstructor, Resolver): + + def __init__(self, stream): + CParser.__init__(self, stream) + SafeConstructor.__init__(self) + Resolver.__init__(self) + +class CFullLoader(CParser, FullConstructor, Resolver): + + def __init__(self, stream): + CParser.__init__(self, stream) + FullConstructor.__init__(self) + Resolver.__init__(self) + +class CUnsafeLoader(CParser, UnsafeConstructor, Resolver): + + def __init__(self, stream): + CParser.__init__(self, stream) + UnsafeConstructor.__init__(self) + Resolver.__init__(self) + +class CLoader(CParser, Constructor, Resolver): + + def __init__(self, stream): + CParser.__init__(self, stream) + Constructor.__init__(self) + Resolver.__init__(self) + +class CBaseDumper(CEmitter, BaseRepresenter, BaseResolver): + + def __init__(self, stream, + default_style=None, default_flow_style=False, + canonical=None, indent=None, width=None, + allow_unicode=None, line_break=None, + encoding=None, explicit_start=None, explicit_end=None, + version=None, tags=None, sort_keys=True): + CEmitter.__init__(self, stream, canonical=canonical, + indent=indent, width=width, encoding=encoding, + allow_unicode=allow_unicode, line_break=line_break, + explicit_start=explicit_start, explicit_end=explicit_end, + version=version, tags=tags) + Representer.__init__(self, default_style=default_style, + default_flow_style=default_flow_style, sort_keys=sort_keys) + Resolver.__init__(self) + +class CSafeDumper(CEmitter, SafeRepresenter, Resolver): + + def __init__(self, stream, + default_style=None, default_flow_style=False, + canonical=None, indent=None, width=None, + allow_unicode=None, line_break=None, + encoding=None, explicit_start=None, explicit_end=None, + version=None, tags=None, sort_keys=True): + CEmitter.__init__(self, stream, canonical=canonical, + indent=indent, width=width, encoding=encoding, + allow_unicode=allow_unicode, line_break=line_break, + explicit_start=explicit_start, explicit_end=explicit_end, + version=version, tags=tags) + SafeRepresenter.__init__(self, default_style=default_style, + default_flow_style=default_flow_style, sort_keys=sort_keys) + Resolver.__init__(self) + +class CDumper(CEmitter, Serializer, Representer, Resolver): + + def __init__(self, stream, + default_style=None, default_flow_style=False, + canonical=None, indent=None, width=None, + allow_unicode=None, line_break=None, + encoding=None, explicit_start=None, explicit_end=None, + version=None, tags=None, sort_keys=True): + CEmitter.__init__(self, stream, canonical=canonical, + indent=indent, width=width, encoding=encoding, + allow_unicode=allow_unicode, line_break=line_break, + explicit_start=explicit_start, explicit_end=explicit_end, + version=version, tags=tags) + Representer.__init__(self, default_style=default_style, + default_flow_style=default_flow_style, sort_keys=sort_keys) + Resolver.__init__(self) + diff --git a/.venv/lib/python3.10/site-packages/yaml/dumper.py b/.venv/lib/python3.10/site-packages/yaml/dumper.py new file mode 100644 index 0000000..6aadba5 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/dumper.py @@ -0,0 +1,62 @@ + +__all__ = ['BaseDumper', 'SafeDumper', 'Dumper'] + +from .emitter import * +from .serializer import * +from .representer import * +from .resolver import * + +class BaseDumper(Emitter, Serializer, BaseRepresenter, BaseResolver): + + def __init__(self, stream, + default_style=None, default_flow_style=False, + canonical=None, indent=None, width=None, + allow_unicode=None, line_break=None, + encoding=None, explicit_start=None, explicit_end=None, + version=None, tags=None, sort_keys=True): + Emitter.__init__(self, stream, canonical=canonical, + indent=indent, width=width, + allow_unicode=allow_unicode, line_break=line_break) + Serializer.__init__(self, encoding=encoding, + explicit_start=explicit_start, explicit_end=explicit_end, + version=version, tags=tags) + Representer.__init__(self, default_style=default_style, + default_flow_style=default_flow_style, sort_keys=sort_keys) + Resolver.__init__(self) + +class SafeDumper(Emitter, Serializer, SafeRepresenter, Resolver): + + def __init__(self, stream, + default_style=None, default_flow_style=False, + canonical=None, indent=None, width=None, + allow_unicode=None, line_break=None, + encoding=None, explicit_start=None, explicit_end=None, + version=None, tags=None, sort_keys=True): + Emitter.__init__(self, stream, canonical=canonical, + indent=indent, width=width, + allow_unicode=allow_unicode, line_break=line_break) + Serializer.__init__(self, encoding=encoding, + explicit_start=explicit_start, explicit_end=explicit_end, + version=version, tags=tags) + SafeRepresenter.__init__(self, default_style=default_style, + default_flow_style=default_flow_style, sort_keys=sort_keys) + Resolver.__init__(self) + +class Dumper(Emitter, Serializer, Representer, Resolver): + + def __init__(self, stream, + default_style=None, default_flow_style=False, + canonical=None, indent=None, width=None, + allow_unicode=None, line_break=None, + encoding=None, explicit_start=None, explicit_end=None, + version=None, tags=None, sort_keys=True): + Emitter.__init__(self, stream, canonical=canonical, + indent=indent, width=width, + allow_unicode=allow_unicode, line_break=line_break) + Serializer.__init__(self, encoding=encoding, + explicit_start=explicit_start, explicit_end=explicit_end, + version=version, tags=tags) + Representer.__init__(self, default_style=default_style, + default_flow_style=default_flow_style, sort_keys=sort_keys) + Resolver.__init__(self) + diff --git a/.venv/lib/python3.10/site-packages/yaml/emitter.py b/.venv/lib/python3.10/site-packages/yaml/emitter.py new file mode 100644 index 0000000..a664d01 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/emitter.py @@ -0,0 +1,1137 @@ + +# Emitter expects events obeying the following grammar: +# stream ::= STREAM-START document* STREAM-END +# document ::= DOCUMENT-START node DOCUMENT-END +# node ::= SCALAR | sequence | mapping +# sequence ::= SEQUENCE-START node* SEQUENCE-END +# mapping ::= MAPPING-START (node node)* MAPPING-END + +__all__ = ['Emitter', 'EmitterError'] + +from .error import YAMLError +from .events import * + +class EmitterError(YAMLError): + pass + +class ScalarAnalysis: + def __init__(self, scalar, empty, multiline, + allow_flow_plain, allow_block_plain, + allow_single_quoted, allow_double_quoted, + allow_block): + self.scalar = scalar + self.empty = empty + self.multiline = multiline + self.allow_flow_plain = allow_flow_plain + self.allow_block_plain = allow_block_plain + self.allow_single_quoted = allow_single_quoted + self.allow_double_quoted = allow_double_quoted + self.allow_block = allow_block + +class Emitter: + + DEFAULT_TAG_PREFIXES = { + '!' : '!', + 'tag:yaml.org,2002:' : '!!', + } + + def __init__(self, stream, canonical=None, indent=None, width=None, + allow_unicode=None, line_break=None): + + # The stream should have the methods `write` and possibly `flush`. + self.stream = stream + + # Encoding can be overridden by STREAM-START. + self.encoding = None + + # Emitter is a state machine with a stack of states to handle nested + # structures. + self.states = [] + self.state = self.expect_stream_start + + # Current event and the event queue. + self.events = [] + self.event = None + + # The current indentation level and the stack of previous indents. + self.indents = [] + self.indent = None + + # Flow level. + self.flow_level = 0 + + # Contexts. + self.root_context = False + self.sequence_context = False + self.mapping_context = False + self.simple_key_context = False + + # Characteristics of the last emitted character: + # - current position. + # - is it a whitespace? + # - is it an indention character + # (indentation space, '-', '?', or ':')? + self.line = 0 + self.column = 0 + self.whitespace = True + self.indention = True + + # Whether the document requires an explicit document indicator + self.open_ended = False + + # Formatting details. + self.canonical = canonical + self.allow_unicode = allow_unicode + self.best_indent = 2 + if indent and 1 < indent < 10: + self.best_indent = indent + self.best_width = 80 + if width and width > self.best_indent*2: + self.best_width = width + self.best_line_break = '\n' + if line_break in ['\r', '\n', '\r\n']: + self.best_line_break = line_break + + # Tag prefixes. + self.tag_prefixes = None + + # Prepared anchor and tag. + self.prepared_anchor = None + self.prepared_tag = None + + # Scalar analysis and style. + self.analysis = None + self.style = None + + def dispose(self): + # Reset the state attributes (to clear self-references) + self.states = [] + self.state = None + + def emit(self, event): + self.events.append(event) + while not self.need_more_events(): + self.event = self.events.pop(0) + self.state() + self.event = None + + # In some cases, we wait for a few next events before emitting. + + def need_more_events(self): + if not self.events: + return True + event = self.events[0] + if isinstance(event, DocumentStartEvent): + return self.need_events(1) + elif isinstance(event, SequenceStartEvent): + return self.need_events(2) + elif isinstance(event, MappingStartEvent): + return self.need_events(3) + else: + return False + + def need_events(self, count): + level = 0 + for event in self.events[1:]: + if isinstance(event, (DocumentStartEvent, CollectionStartEvent)): + level += 1 + elif isinstance(event, (DocumentEndEvent, CollectionEndEvent)): + level -= 1 + elif isinstance(event, StreamEndEvent): + level = -1 + if level < 0: + return False + return (len(self.events) < count+1) + + def increase_indent(self, flow=False, indentless=False): + self.indents.append(self.indent) + if self.indent is None: + if flow: + self.indent = self.best_indent + else: + self.indent = 0 + elif not indentless: + self.indent += self.best_indent + + # States. + + # Stream handlers. + + def expect_stream_start(self): + if isinstance(self.event, StreamStartEvent): + if self.event.encoding and not hasattr(self.stream, 'encoding'): + self.encoding = self.event.encoding + self.write_stream_start() + self.state = self.expect_first_document_start + else: + raise EmitterError("expected StreamStartEvent, but got %s" + % self.event) + + def expect_nothing(self): + raise EmitterError("expected nothing, but got %s" % self.event) + + # Document handlers. + + def expect_first_document_start(self): + return self.expect_document_start(first=True) + + def expect_document_start(self, first=False): + if isinstance(self.event, DocumentStartEvent): + if (self.event.version or self.event.tags) and self.open_ended: + self.write_indicator('...', True) + self.write_indent() + if self.event.version: + version_text = self.prepare_version(self.event.version) + self.write_version_directive(version_text) + self.tag_prefixes = self.DEFAULT_TAG_PREFIXES.copy() + if self.event.tags: + handles = sorted(self.event.tags.keys()) + for handle in handles: + prefix = self.event.tags[handle] + self.tag_prefixes[prefix] = handle + handle_text = self.prepare_tag_handle(handle) + prefix_text = self.prepare_tag_prefix(prefix) + self.write_tag_directive(handle_text, prefix_text) + implicit = (first and not self.event.explicit and not self.canonical + and not self.event.version and not self.event.tags + and not self.check_empty_document()) + if not implicit: + self.write_indent() + self.write_indicator('---', True) + if self.canonical: + self.write_indent() + self.state = self.expect_document_root + elif isinstance(self.event, StreamEndEvent): + if self.open_ended: + self.write_indicator('...', True) + self.write_indent() + self.write_stream_end() + self.state = self.expect_nothing + else: + raise EmitterError("expected DocumentStartEvent, but got %s" + % self.event) + + def expect_document_end(self): + if isinstance(self.event, DocumentEndEvent): + self.write_indent() + if self.event.explicit: + self.write_indicator('...', True) + self.write_indent() + self.flush_stream() + self.state = self.expect_document_start + else: + raise EmitterError("expected DocumentEndEvent, but got %s" + % self.event) + + def expect_document_root(self): + self.states.append(self.expect_document_end) + self.expect_node(root=True) + + # Node handlers. + + def expect_node(self, root=False, sequence=False, mapping=False, + simple_key=False): + self.root_context = root + self.sequence_context = sequence + self.mapping_context = mapping + self.simple_key_context = simple_key + if isinstance(self.event, AliasEvent): + self.expect_alias() + elif isinstance(self.event, (ScalarEvent, CollectionStartEvent)): + self.process_anchor('&') + self.process_tag() + if isinstance(self.event, ScalarEvent): + self.expect_scalar() + elif isinstance(self.event, SequenceStartEvent): + if self.flow_level or self.canonical or self.event.flow_style \ + or self.check_empty_sequence(): + self.expect_flow_sequence() + else: + self.expect_block_sequence() + elif isinstance(self.event, MappingStartEvent): + if self.flow_level or self.canonical or self.event.flow_style \ + or self.check_empty_mapping(): + self.expect_flow_mapping() + else: + self.expect_block_mapping() + else: + raise EmitterError("expected NodeEvent, but got %s" % self.event) + + def expect_alias(self): + if self.event.anchor is None: + raise EmitterError("anchor is not specified for alias") + self.process_anchor('*') + self.state = self.states.pop() + + def expect_scalar(self): + self.increase_indent(flow=True) + self.process_scalar() + self.indent = self.indents.pop() + self.state = self.states.pop() + + # Flow sequence handlers. + + def expect_flow_sequence(self): + self.write_indicator('[', True, whitespace=True) + self.flow_level += 1 + self.increase_indent(flow=True) + self.state = self.expect_first_flow_sequence_item + + def expect_first_flow_sequence_item(self): + if isinstance(self.event, SequenceEndEvent): + self.indent = self.indents.pop() + self.flow_level -= 1 + self.write_indicator(']', False) + self.state = self.states.pop() + else: + if self.canonical or self.column > self.best_width: + self.write_indent() + self.states.append(self.expect_flow_sequence_item) + self.expect_node(sequence=True) + + def expect_flow_sequence_item(self): + if isinstance(self.event, SequenceEndEvent): + self.indent = self.indents.pop() + self.flow_level -= 1 + if self.canonical: + self.write_indicator(',', False) + self.write_indent() + self.write_indicator(']', False) + self.state = self.states.pop() + else: + self.write_indicator(',', False) + if self.canonical or self.column > self.best_width: + self.write_indent() + self.states.append(self.expect_flow_sequence_item) + self.expect_node(sequence=True) + + # Flow mapping handlers. + + def expect_flow_mapping(self): + self.write_indicator('{', True, whitespace=True) + self.flow_level += 1 + self.increase_indent(flow=True) + self.state = self.expect_first_flow_mapping_key + + def expect_first_flow_mapping_key(self): + if isinstance(self.event, MappingEndEvent): + self.indent = self.indents.pop() + self.flow_level -= 1 + self.write_indicator('}', False) + self.state = self.states.pop() + else: + if self.canonical or self.column > self.best_width: + self.write_indent() + if not self.canonical and self.check_simple_key(): + self.states.append(self.expect_flow_mapping_simple_value) + self.expect_node(mapping=True, simple_key=True) + else: + self.write_indicator('?', True) + self.states.append(self.expect_flow_mapping_value) + self.expect_node(mapping=True) + + def expect_flow_mapping_key(self): + if isinstance(self.event, MappingEndEvent): + self.indent = self.indents.pop() + self.flow_level -= 1 + if self.canonical: + self.write_indicator(',', False) + self.write_indent() + self.write_indicator('}', False) + self.state = self.states.pop() + else: + self.write_indicator(',', False) + if self.canonical or self.column > self.best_width: + self.write_indent() + if not self.canonical and self.check_simple_key(): + self.states.append(self.expect_flow_mapping_simple_value) + self.expect_node(mapping=True, simple_key=True) + else: + self.write_indicator('?', True) + self.states.append(self.expect_flow_mapping_value) + self.expect_node(mapping=True) + + def expect_flow_mapping_simple_value(self): + self.write_indicator(':', False) + self.states.append(self.expect_flow_mapping_key) + self.expect_node(mapping=True) + + def expect_flow_mapping_value(self): + if self.canonical or self.column > self.best_width: + self.write_indent() + self.write_indicator(':', True) + self.states.append(self.expect_flow_mapping_key) + self.expect_node(mapping=True) + + # Block sequence handlers. + + def expect_block_sequence(self): + indentless = (self.mapping_context and not self.indention) + self.increase_indent(flow=False, indentless=indentless) + self.state = self.expect_first_block_sequence_item + + def expect_first_block_sequence_item(self): + return self.expect_block_sequence_item(first=True) + + def expect_block_sequence_item(self, first=False): + if not first and isinstance(self.event, SequenceEndEvent): + self.indent = self.indents.pop() + self.state = self.states.pop() + else: + self.write_indent() + self.write_indicator('-', True, indention=True) + self.states.append(self.expect_block_sequence_item) + self.expect_node(sequence=True) + + # Block mapping handlers. + + def expect_block_mapping(self): + self.increase_indent(flow=False) + self.state = self.expect_first_block_mapping_key + + def expect_first_block_mapping_key(self): + return self.expect_block_mapping_key(first=True) + + def expect_block_mapping_key(self, first=False): + if not first and isinstance(self.event, MappingEndEvent): + self.indent = self.indents.pop() + self.state = self.states.pop() + else: + self.write_indent() + if self.check_simple_key(): + self.states.append(self.expect_block_mapping_simple_value) + self.expect_node(mapping=True, simple_key=True) + else: + self.write_indicator('?', True, indention=True) + self.states.append(self.expect_block_mapping_value) + self.expect_node(mapping=True) + + def expect_block_mapping_simple_value(self): + self.write_indicator(':', False) + self.states.append(self.expect_block_mapping_key) + self.expect_node(mapping=True) + + def expect_block_mapping_value(self): + self.write_indent() + self.write_indicator(':', True, indention=True) + self.states.append(self.expect_block_mapping_key) + self.expect_node(mapping=True) + + # Checkers. + + def check_empty_sequence(self): + return (isinstance(self.event, SequenceStartEvent) and self.events + and isinstance(self.events[0], SequenceEndEvent)) + + def check_empty_mapping(self): + return (isinstance(self.event, MappingStartEvent) and self.events + and isinstance(self.events[0], MappingEndEvent)) + + def check_empty_document(self): + if not isinstance(self.event, DocumentStartEvent) or not self.events: + return False + event = self.events[0] + return (isinstance(event, ScalarEvent) and event.anchor is None + and event.tag is None and event.implicit and event.value == '') + + def check_simple_key(self): + length = 0 + if isinstance(self.event, NodeEvent) and self.event.anchor is not None: + if self.prepared_anchor is None: + self.prepared_anchor = self.prepare_anchor(self.event.anchor) + length += len(self.prepared_anchor) + if isinstance(self.event, (ScalarEvent, CollectionStartEvent)) \ + and self.event.tag is not None: + if self.prepared_tag is None: + self.prepared_tag = self.prepare_tag(self.event.tag) + length += len(self.prepared_tag) + if isinstance(self.event, ScalarEvent): + if self.analysis is None: + self.analysis = self.analyze_scalar(self.event.value) + length += len(self.analysis.scalar) + return (length < 128 and (isinstance(self.event, AliasEvent) + or (isinstance(self.event, ScalarEvent) + and not self.analysis.empty and not self.analysis.multiline) + or self.check_empty_sequence() or self.check_empty_mapping())) + + # Anchor, Tag, and Scalar processors. + + def process_anchor(self, indicator): + if self.event.anchor is None: + self.prepared_anchor = None + return + if self.prepared_anchor is None: + self.prepared_anchor = self.prepare_anchor(self.event.anchor) + if self.prepared_anchor: + self.write_indicator(indicator+self.prepared_anchor, True) + self.prepared_anchor = None + + def process_tag(self): + tag = self.event.tag + if isinstance(self.event, ScalarEvent): + if self.style is None: + self.style = self.choose_scalar_style() + if ((not self.canonical or tag is None) and + ((self.style == '' and self.event.implicit[0]) + or (self.style != '' and self.event.implicit[1]))): + self.prepared_tag = None + return + if self.event.implicit[0] and tag is None: + tag = '!' + self.prepared_tag = None + else: + if (not self.canonical or tag is None) and self.event.implicit: + self.prepared_tag = None + return + if tag is None: + raise EmitterError("tag is not specified") + if self.prepared_tag is None: + self.prepared_tag = self.prepare_tag(tag) + if self.prepared_tag: + self.write_indicator(self.prepared_tag, True) + self.prepared_tag = None + + def choose_scalar_style(self): + if self.analysis is None: + self.analysis = self.analyze_scalar(self.event.value) + if self.event.style == '"' or self.canonical: + return '"' + if not self.event.style and self.event.implicit[0]: + if (not (self.simple_key_context and + (self.analysis.empty or self.analysis.multiline)) + and (self.flow_level and self.analysis.allow_flow_plain + or (not self.flow_level and self.analysis.allow_block_plain))): + return '' + if self.event.style and self.event.style in '|>': + if (not self.flow_level and not self.simple_key_context + and self.analysis.allow_block): + return self.event.style + if not self.event.style or self.event.style == '\'': + if (self.analysis.allow_single_quoted and + not (self.simple_key_context and self.analysis.multiline)): + return '\'' + return '"' + + def process_scalar(self): + if self.analysis is None: + self.analysis = self.analyze_scalar(self.event.value) + if self.style is None: + self.style = self.choose_scalar_style() + split = (not self.simple_key_context) + #if self.analysis.multiline and split \ + # and (not self.style or self.style in '\'\"'): + # self.write_indent() + if self.style == '"': + self.write_double_quoted(self.analysis.scalar, split) + elif self.style == '\'': + self.write_single_quoted(self.analysis.scalar, split) + elif self.style == '>': + self.write_folded(self.analysis.scalar) + elif self.style == '|': + self.write_literal(self.analysis.scalar) + else: + self.write_plain(self.analysis.scalar, split) + self.analysis = None + self.style = None + + # Analyzers. + + def prepare_version(self, version): + major, minor = version + if major != 1: + raise EmitterError("unsupported YAML version: %d.%d" % (major, minor)) + return '%d.%d' % (major, minor) + + def prepare_tag_handle(self, handle): + if not handle: + raise EmitterError("tag handle must not be empty") + if handle[0] != '!' or handle[-1] != '!': + raise EmitterError("tag handle must start and end with '!': %r" % handle) + for ch in handle[1:-1]: + if not ('0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ + or ch in '-_'): + raise EmitterError("invalid character %r in the tag handle: %r" + % (ch, handle)) + return handle + + def prepare_tag_prefix(self, prefix): + if not prefix: + raise EmitterError("tag prefix must not be empty") + chunks = [] + start = end = 0 + if prefix[0] == '!': + end = 1 + while end < len(prefix): + ch = prefix[end] + if '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ + or ch in '-;/?!:@&=+$,_.~*\'()[]': + end += 1 + else: + if start < end: + chunks.append(prefix[start:end]) + start = end = end+1 + data = ch.encode('utf-8') + for ch in data: + chunks.append('%%%02X' % ord(ch)) + if start < end: + chunks.append(prefix[start:end]) + return ''.join(chunks) + + def prepare_tag(self, tag): + if not tag: + raise EmitterError("tag must not be empty") + if tag == '!': + return tag + handle = None + suffix = tag + prefixes = sorted(self.tag_prefixes.keys()) + for prefix in prefixes: + if tag.startswith(prefix) \ + and (prefix == '!' or len(prefix) < len(tag)): + handle = self.tag_prefixes[prefix] + suffix = tag[len(prefix):] + chunks = [] + start = end = 0 + while end < len(suffix): + ch = suffix[end] + if '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ + or ch in '-;/?:@&=+$,_.~*\'()[]' \ + or (ch == '!' and handle != '!'): + end += 1 + else: + if start < end: + chunks.append(suffix[start:end]) + start = end = end+1 + data = ch.encode('utf-8') + for ch in data: + chunks.append('%%%02X' % ch) + if start < end: + chunks.append(suffix[start:end]) + suffix_text = ''.join(chunks) + if handle: + return '%s%s' % (handle, suffix_text) + else: + return '!<%s>' % suffix_text + + def prepare_anchor(self, anchor): + if not anchor: + raise EmitterError("anchor must not be empty") + for ch in anchor: + if not ('0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ + or ch in '-_'): + raise EmitterError("invalid character %r in the anchor: %r" + % (ch, anchor)) + return anchor + + def analyze_scalar(self, scalar): + + # Empty scalar is a special case. + if not scalar: + return ScalarAnalysis(scalar=scalar, empty=True, multiline=False, + allow_flow_plain=False, allow_block_plain=True, + allow_single_quoted=True, allow_double_quoted=True, + allow_block=False) + + # Indicators and special characters. + block_indicators = False + flow_indicators = False + line_breaks = False + special_characters = False + + # Important whitespace combinations. + leading_space = False + leading_break = False + trailing_space = False + trailing_break = False + break_space = False + space_break = False + + # Check document indicators. + if scalar.startswith('---') or scalar.startswith('...'): + block_indicators = True + flow_indicators = True + + # First character or preceded by a whitespace. + preceded_by_whitespace = True + + # Last character or followed by a whitespace. + followed_by_whitespace = (len(scalar) == 1 or + scalar[1] in '\0 \t\r\n\x85\u2028\u2029') + + # The previous character is a space. + previous_space = False + + # The previous character is a break. + previous_break = False + + index = 0 + while index < len(scalar): + ch = scalar[index] + + # Check for indicators. + if index == 0: + # Leading indicators are special characters. + if ch in '#,[]{}&*!|>\'\"%@`': + flow_indicators = True + block_indicators = True + if ch in '?:': + flow_indicators = True + if followed_by_whitespace: + block_indicators = True + if ch == '-' and followed_by_whitespace: + flow_indicators = True + block_indicators = True + else: + # Some indicators cannot appear within a scalar as well. + if ch in ',?[]{}': + flow_indicators = True + if ch == ':': + flow_indicators = True + if followed_by_whitespace: + block_indicators = True + if ch == '#' and preceded_by_whitespace: + flow_indicators = True + block_indicators = True + + # Check for line breaks, special, and unicode characters. + if ch in '\n\x85\u2028\u2029': + line_breaks = True + if not (ch == '\n' or '\x20' <= ch <= '\x7E'): + if (ch == '\x85' or '\xA0' <= ch <= '\uD7FF' + or '\uE000' <= ch <= '\uFFFD' + or '\U00010000' <= ch < '\U0010ffff') and ch != '\uFEFF': + unicode_characters = True + if not self.allow_unicode: + special_characters = True + else: + special_characters = True + + # Detect important whitespace combinations. + if ch == ' ': + if index == 0: + leading_space = True + if index == len(scalar)-1: + trailing_space = True + if previous_break: + break_space = True + previous_space = True + previous_break = False + elif ch in '\n\x85\u2028\u2029': + if index == 0: + leading_break = True + if index == len(scalar)-1: + trailing_break = True + if previous_space: + space_break = True + previous_space = False + previous_break = True + else: + previous_space = False + previous_break = False + + # Prepare for the next character. + index += 1 + preceded_by_whitespace = (ch in '\0 \t\r\n\x85\u2028\u2029') + followed_by_whitespace = (index+1 >= len(scalar) or + scalar[index+1] in '\0 \t\r\n\x85\u2028\u2029') + + # Let's decide what styles are allowed. + allow_flow_plain = True + allow_block_plain = True + allow_single_quoted = True + allow_double_quoted = True + allow_block = True + + # Leading and trailing whitespaces are bad for plain scalars. + if (leading_space or leading_break + or trailing_space or trailing_break): + allow_flow_plain = allow_block_plain = False + + # We do not permit trailing spaces for block scalars. + if trailing_space: + allow_block = False + + # Spaces at the beginning of a new line are only acceptable for block + # scalars. + if break_space: + allow_flow_plain = allow_block_plain = allow_single_quoted = False + + # Spaces followed by breaks, as well as special character are only + # allowed for double quoted scalars. + if space_break or special_characters: + allow_flow_plain = allow_block_plain = \ + allow_single_quoted = allow_block = False + + # Although the plain scalar writer supports breaks, we never emit + # multiline plain scalars. + if line_breaks: + allow_flow_plain = allow_block_plain = False + + # Flow indicators are forbidden for flow plain scalars. + if flow_indicators: + allow_flow_plain = False + + # Block indicators are forbidden for block plain scalars. + if block_indicators: + allow_block_plain = False + + return ScalarAnalysis(scalar=scalar, + empty=False, multiline=line_breaks, + allow_flow_plain=allow_flow_plain, + allow_block_plain=allow_block_plain, + allow_single_quoted=allow_single_quoted, + allow_double_quoted=allow_double_quoted, + allow_block=allow_block) + + # Writers. + + def flush_stream(self): + if hasattr(self.stream, 'flush'): + self.stream.flush() + + def write_stream_start(self): + # Write BOM if needed. + if self.encoding and self.encoding.startswith('utf-16'): + self.stream.write('\uFEFF'.encode(self.encoding)) + + def write_stream_end(self): + self.flush_stream() + + def write_indicator(self, indicator, need_whitespace, + whitespace=False, indention=False): + if self.whitespace or not need_whitespace: + data = indicator + else: + data = ' '+indicator + self.whitespace = whitespace + self.indention = self.indention and indention + self.column += len(data) + self.open_ended = False + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + + def write_indent(self): + indent = self.indent or 0 + if not self.indention or self.column > indent \ + or (self.column == indent and not self.whitespace): + self.write_line_break() + if self.column < indent: + self.whitespace = True + data = ' '*(indent-self.column) + self.column = indent + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + + def write_line_break(self, data=None): + if data is None: + data = self.best_line_break + self.whitespace = True + self.indention = True + self.line += 1 + self.column = 0 + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + + def write_version_directive(self, version_text): + data = '%%YAML %s' % version_text + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + self.write_line_break() + + def write_tag_directive(self, handle_text, prefix_text): + data = '%%TAG %s %s' % (handle_text, prefix_text) + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + self.write_line_break() + + # Scalar streams. + + def write_single_quoted(self, text, split=True): + self.write_indicator('\'', True) + spaces = False + breaks = False + start = end = 0 + while end <= len(text): + ch = None + if end < len(text): + ch = text[end] + if spaces: + if ch is None or ch != ' ': + if start+1 == end and self.column > self.best_width and split \ + and start != 0 and end != len(text): + self.write_indent() + else: + data = text[start:end] + self.column += len(data) + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + start = end + elif breaks: + if ch is None or ch not in '\n\x85\u2028\u2029': + if text[start] == '\n': + self.write_line_break() + for br in text[start:end]: + if br == '\n': + self.write_line_break() + else: + self.write_line_break(br) + self.write_indent() + start = end + else: + if ch is None or ch in ' \n\x85\u2028\u2029' or ch == '\'': + if start < end: + data = text[start:end] + self.column += len(data) + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + start = end + if ch == '\'': + data = '\'\'' + self.column += 2 + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + start = end + 1 + if ch is not None: + spaces = (ch == ' ') + breaks = (ch in '\n\x85\u2028\u2029') + end += 1 + self.write_indicator('\'', False) + + ESCAPE_REPLACEMENTS = { + '\0': '0', + '\x07': 'a', + '\x08': 'b', + '\x09': 't', + '\x0A': 'n', + '\x0B': 'v', + '\x0C': 'f', + '\x0D': 'r', + '\x1B': 'e', + '\"': '\"', + '\\': '\\', + '\x85': 'N', + '\xA0': '_', + '\u2028': 'L', + '\u2029': 'P', + } + + def write_double_quoted(self, text, split=True): + self.write_indicator('"', True) + start = end = 0 + while end <= len(text): + ch = None + if end < len(text): + ch = text[end] + if ch is None or ch in '"\\\x85\u2028\u2029\uFEFF' \ + or not ('\x20' <= ch <= '\x7E' + or (self.allow_unicode + and ('\xA0' <= ch <= '\uD7FF' + or '\uE000' <= ch <= '\uFFFD'))): + if start < end: + data = text[start:end] + self.column += len(data) + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + start = end + if ch is not None: + if ch in self.ESCAPE_REPLACEMENTS: + data = '\\'+self.ESCAPE_REPLACEMENTS[ch] + elif ch <= '\xFF': + data = '\\x%02X' % ord(ch) + elif ch <= '\uFFFF': + data = '\\u%04X' % ord(ch) + else: + data = '\\U%08X' % ord(ch) + self.column += len(data) + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + start = end+1 + if 0 < end < len(text)-1 and (ch == ' ' or start >= end) \ + and self.column+(end-start) > self.best_width and split: + data = text[start:end]+'\\' + if start < end: + start = end + self.column += len(data) + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + self.write_indent() + self.whitespace = False + self.indention = False + if text[start] == ' ': + data = '\\' + self.column += len(data) + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + end += 1 + self.write_indicator('"', False) + + def determine_block_hints(self, text): + hints = '' + if text: + if text[0] in ' \n\x85\u2028\u2029': + hints += str(self.best_indent) + if text[-1] not in '\n\x85\u2028\u2029': + hints += '-' + elif len(text) == 1 or text[-2] in '\n\x85\u2028\u2029': + hints += '+' + return hints + + def write_folded(self, text): + hints = self.determine_block_hints(text) + self.write_indicator('>'+hints, True) + if hints[-1:] == '+': + self.open_ended = True + self.write_line_break() + leading_space = True + spaces = False + breaks = True + start = end = 0 + while end <= len(text): + ch = None + if end < len(text): + ch = text[end] + if breaks: + if ch is None or ch not in '\n\x85\u2028\u2029': + if not leading_space and ch is not None and ch != ' ' \ + and text[start] == '\n': + self.write_line_break() + leading_space = (ch == ' ') + for br in text[start:end]: + if br == '\n': + self.write_line_break() + else: + self.write_line_break(br) + if ch is not None: + self.write_indent() + start = end + elif spaces: + if ch != ' ': + if start+1 == end and self.column > self.best_width: + self.write_indent() + else: + data = text[start:end] + self.column += len(data) + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + start = end + else: + if ch is None or ch in ' \n\x85\u2028\u2029': + data = text[start:end] + self.column += len(data) + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + if ch is None: + self.write_line_break() + start = end + if ch is not None: + breaks = (ch in '\n\x85\u2028\u2029') + spaces = (ch == ' ') + end += 1 + + def write_literal(self, text): + hints = self.determine_block_hints(text) + self.write_indicator('|'+hints, True) + if hints[-1:] == '+': + self.open_ended = True + self.write_line_break() + breaks = True + start = end = 0 + while end <= len(text): + ch = None + if end < len(text): + ch = text[end] + if breaks: + if ch is None or ch not in '\n\x85\u2028\u2029': + for br in text[start:end]: + if br == '\n': + self.write_line_break() + else: + self.write_line_break(br) + if ch is not None: + self.write_indent() + start = end + else: + if ch is None or ch in '\n\x85\u2028\u2029': + data = text[start:end] + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + if ch is None: + self.write_line_break() + start = end + if ch is not None: + breaks = (ch in '\n\x85\u2028\u2029') + end += 1 + + def write_plain(self, text, split=True): + if self.root_context: + self.open_ended = True + if not text: + return + if not self.whitespace: + data = ' ' + self.column += len(data) + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + self.whitespace = False + self.indention = False + spaces = False + breaks = False + start = end = 0 + while end <= len(text): + ch = None + if end < len(text): + ch = text[end] + if spaces: + if ch != ' ': + if start+1 == end and self.column > self.best_width and split: + self.write_indent() + self.whitespace = False + self.indention = False + else: + data = text[start:end] + self.column += len(data) + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + start = end + elif breaks: + if ch not in '\n\x85\u2028\u2029': + if text[start] == '\n': + self.write_line_break() + for br in text[start:end]: + if br == '\n': + self.write_line_break() + else: + self.write_line_break(br) + self.write_indent() + self.whitespace = False + self.indention = False + start = end + else: + if ch is None or ch in ' \n\x85\u2028\u2029': + data = text[start:end] + self.column += len(data) + if self.encoding: + data = data.encode(self.encoding) + self.stream.write(data) + start = end + if ch is not None: + spaces = (ch == ' ') + breaks = (ch in '\n\x85\u2028\u2029') + end += 1 diff --git a/.venv/lib/python3.10/site-packages/yaml/error.py b/.venv/lib/python3.10/site-packages/yaml/error.py new file mode 100644 index 0000000..b796b4d --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/error.py @@ -0,0 +1,75 @@ + +__all__ = ['Mark', 'YAMLError', 'MarkedYAMLError'] + +class Mark: + + def __init__(self, name, index, line, column, buffer, pointer): + self.name = name + self.index = index + self.line = line + self.column = column + self.buffer = buffer + self.pointer = pointer + + def get_snippet(self, indent=4, max_length=75): + if self.buffer is None: + return None + head = '' + start = self.pointer + while start > 0 and self.buffer[start-1] not in '\0\r\n\x85\u2028\u2029': + start -= 1 + if self.pointer-start > max_length/2-1: + head = ' ... ' + start += 5 + break + tail = '' + end = self.pointer + while end < len(self.buffer) and self.buffer[end] not in '\0\r\n\x85\u2028\u2029': + end += 1 + if end-self.pointer > max_length/2-1: + tail = ' ... ' + end -= 5 + break + snippet = self.buffer[start:end] + return ' '*indent + head + snippet + tail + '\n' \ + + ' '*(indent+self.pointer-start+len(head)) + '^' + + def __str__(self): + snippet = self.get_snippet() + where = " in \"%s\", line %d, column %d" \ + % (self.name, self.line+1, self.column+1) + if snippet is not None: + where += ":\n"+snippet + return where + +class YAMLError(Exception): + pass + +class MarkedYAMLError(YAMLError): + + def __init__(self, context=None, context_mark=None, + problem=None, problem_mark=None, note=None): + self.context = context + self.context_mark = context_mark + self.problem = problem + self.problem_mark = problem_mark + self.note = note + + def __str__(self): + lines = [] + if self.context is not None: + lines.append(self.context) + if self.context_mark is not None \ + and (self.problem is None or self.problem_mark is None + or self.context_mark.name != self.problem_mark.name + or self.context_mark.line != self.problem_mark.line + or self.context_mark.column != self.problem_mark.column): + lines.append(str(self.context_mark)) + if self.problem is not None: + lines.append(self.problem) + if self.problem_mark is not None: + lines.append(str(self.problem_mark)) + if self.note is not None: + lines.append(self.note) + return '\n'.join(lines) + diff --git a/.venv/lib/python3.10/site-packages/yaml/events.py b/.venv/lib/python3.10/site-packages/yaml/events.py new file mode 100644 index 0000000..f79ad38 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/events.py @@ -0,0 +1,86 @@ + +# Abstract classes. + +class Event(object): + def __init__(self, start_mark=None, end_mark=None): + self.start_mark = start_mark + self.end_mark = end_mark + def __repr__(self): + attributes = [key for key in ['anchor', 'tag', 'implicit', 'value'] + if hasattr(self, key)] + arguments = ', '.join(['%s=%r' % (key, getattr(self, key)) + for key in attributes]) + return '%s(%s)' % (self.__class__.__name__, arguments) + +class NodeEvent(Event): + def __init__(self, anchor, start_mark=None, end_mark=None): + self.anchor = anchor + self.start_mark = start_mark + self.end_mark = end_mark + +class CollectionStartEvent(NodeEvent): + def __init__(self, anchor, tag, implicit, start_mark=None, end_mark=None, + flow_style=None): + self.anchor = anchor + self.tag = tag + self.implicit = implicit + self.start_mark = start_mark + self.end_mark = end_mark + self.flow_style = flow_style + +class CollectionEndEvent(Event): + pass + +# Implementations. + +class StreamStartEvent(Event): + def __init__(self, start_mark=None, end_mark=None, encoding=None): + self.start_mark = start_mark + self.end_mark = end_mark + self.encoding = encoding + +class StreamEndEvent(Event): + pass + +class DocumentStartEvent(Event): + def __init__(self, start_mark=None, end_mark=None, + explicit=None, version=None, tags=None): + self.start_mark = start_mark + self.end_mark = end_mark + self.explicit = explicit + self.version = version + self.tags = tags + +class DocumentEndEvent(Event): + def __init__(self, start_mark=None, end_mark=None, + explicit=None): + self.start_mark = start_mark + self.end_mark = end_mark + self.explicit = explicit + +class AliasEvent(NodeEvent): + pass + +class ScalarEvent(NodeEvent): + def __init__(self, anchor, tag, implicit, value, + start_mark=None, end_mark=None, style=None): + self.anchor = anchor + self.tag = tag + self.implicit = implicit + self.value = value + self.start_mark = start_mark + self.end_mark = end_mark + self.style = style + +class SequenceStartEvent(CollectionStartEvent): + pass + +class SequenceEndEvent(CollectionEndEvent): + pass + +class MappingStartEvent(CollectionStartEvent): + pass + +class MappingEndEvent(CollectionEndEvent): + pass + diff --git a/.venv/lib/python3.10/site-packages/yaml/loader.py b/.venv/lib/python3.10/site-packages/yaml/loader.py new file mode 100644 index 0000000..e90c112 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/loader.py @@ -0,0 +1,63 @@ + +__all__ = ['BaseLoader', 'FullLoader', 'SafeLoader', 'Loader', 'UnsafeLoader'] + +from .reader import * +from .scanner import * +from .parser import * +from .composer import * +from .constructor import * +from .resolver import * + +class BaseLoader(Reader, Scanner, Parser, Composer, BaseConstructor, BaseResolver): + + def __init__(self, stream): + Reader.__init__(self, stream) + Scanner.__init__(self) + Parser.__init__(self) + Composer.__init__(self) + BaseConstructor.__init__(self) + BaseResolver.__init__(self) + +class FullLoader(Reader, Scanner, Parser, Composer, FullConstructor, Resolver): + + def __init__(self, stream): + Reader.__init__(self, stream) + Scanner.__init__(self) + Parser.__init__(self) + Composer.__init__(self) + FullConstructor.__init__(self) + Resolver.__init__(self) + +class SafeLoader(Reader, Scanner, Parser, Composer, SafeConstructor, Resolver): + + def __init__(self, stream): + Reader.__init__(self, stream) + Scanner.__init__(self) + Parser.__init__(self) + Composer.__init__(self) + SafeConstructor.__init__(self) + Resolver.__init__(self) + +class Loader(Reader, Scanner, Parser, Composer, Constructor, Resolver): + + def __init__(self, stream): + Reader.__init__(self, stream) + Scanner.__init__(self) + Parser.__init__(self) + Composer.__init__(self) + Constructor.__init__(self) + Resolver.__init__(self) + +# UnsafeLoader is the same as Loader (which is and was always unsafe on +# untrusted input). Use of either Loader or UnsafeLoader should be rare, since +# FullLoad should be able to load almost all YAML safely. Loader is left intact +# to ensure backwards compatibility. +class UnsafeLoader(Reader, Scanner, Parser, Composer, Constructor, Resolver): + + def __init__(self, stream): + Reader.__init__(self, stream) + Scanner.__init__(self) + Parser.__init__(self) + Composer.__init__(self) + Constructor.__init__(self) + Resolver.__init__(self) diff --git a/.venv/lib/python3.10/site-packages/yaml/nodes.py b/.venv/lib/python3.10/site-packages/yaml/nodes.py new file mode 100644 index 0000000..c4f070c --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/nodes.py @@ -0,0 +1,49 @@ + +class Node(object): + def __init__(self, tag, value, start_mark, end_mark): + self.tag = tag + self.value = value + self.start_mark = start_mark + self.end_mark = end_mark + def __repr__(self): + value = self.value + #if isinstance(value, list): + # if len(value) == 0: + # value = '' + # elif len(value) == 1: + # value = '<1 item>' + # else: + # value = '<%d items>' % len(value) + #else: + # if len(value) > 75: + # value = repr(value[:70]+u' ... ') + # else: + # value = repr(value) + value = repr(value) + return '%s(tag=%r, value=%s)' % (self.__class__.__name__, self.tag, value) + +class ScalarNode(Node): + id = 'scalar' + def __init__(self, tag, value, + start_mark=None, end_mark=None, style=None): + self.tag = tag + self.value = value + self.start_mark = start_mark + self.end_mark = end_mark + self.style = style + +class CollectionNode(Node): + def __init__(self, tag, value, + start_mark=None, end_mark=None, flow_style=None): + self.tag = tag + self.value = value + self.start_mark = start_mark + self.end_mark = end_mark + self.flow_style = flow_style + +class SequenceNode(CollectionNode): + id = 'sequence' + +class MappingNode(CollectionNode): + id = 'mapping' + diff --git a/.venv/lib/python3.10/site-packages/yaml/parser.py b/.venv/lib/python3.10/site-packages/yaml/parser.py new file mode 100644 index 0000000..13a5995 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/parser.py @@ -0,0 +1,589 @@ + +# The following YAML grammar is LL(1) and is parsed by a recursive descent +# parser. +# +# stream ::= STREAM-START implicit_document? explicit_document* STREAM-END +# implicit_document ::= block_node DOCUMENT-END* +# explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +# block_node_or_indentless_sequence ::= +# ALIAS +# | properties (block_content | indentless_block_sequence)? +# | block_content +# | indentless_block_sequence +# block_node ::= ALIAS +# | properties block_content? +# | block_content +# flow_node ::= ALIAS +# | properties flow_content? +# | flow_content +# properties ::= TAG ANCHOR? | ANCHOR TAG? +# block_content ::= block_collection | flow_collection | SCALAR +# flow_content ::= flow_collection | SCALAR +# block_collection ::= block_sequence | block_mapping +# flow_collection ::= flow_sequence | flow_mapping +# block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END +# indentless_sequence ::= (BLOCK-ENTRY block_node?)+ +# block_mapping ::= BLOCK-MAPPING_START +# ((KEY block_node_or_indentless_sequence?)? +# (VALUE block_node_or_indentless_sequence?)?)* +# BLOCK-END +# flow_sequence ::= FLOW-SEQUENCE-START +# (flow_sequence_entry FLOW-ENTRY)* +# flow_sequence_entry? +# FLOW-SEQUENCE-END +# flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +# flow_mapping ::= FLOW-MAPPING-START +# (flow_mapping_entry FLOW-ENTRY)* +# flow_mapping_entry? +# FLOW-MAPPING-END +# flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +# +# FIRST sets: +# +# stream: { STREAM-START } +# explicit_document: { DIRECTIVE DOCUMENT-START } +# implicit_document: FIRST(block_node) +# block_node: { ALIAS TAG ANCHOR SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START } +# flow_node: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START } +# block_content: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR } +# flow_content: { FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR } +# block_collection: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START } +# flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START } +# block_sequence: { BLOCK-SEQUENCE-START } +# block_mapping: { BLOCK-MAPPING-START } +# block_node_or_indentless_sequence: { ALIAS ANCHOR TAG SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START BLOCK-ENTRY } +# indentless_sequence: { ENTRY } +# flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START } +# flow_sequence: { FLOW-SEQUENCE-START } +# flow_mapping: { FLOW-MAPPING-START } +# flow_sequence_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY } +# flow_mapping_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY } + +__all__ = ['Parser', 'ParserError'] + +from .error import MarkedYAMLError +from .tokens import * +from .events import * +from .scanner import * + +class ParserError(MarkedYAMLError): + pass + +class Parser: + # Since writing a recursive-descendant parser is a straightforward task, we + # do not give many comments here. + + DEFAULT_TAGS = { + '!': '!', + '!!': 'tag:yaml.org,2002:', + } + + def __init__(self): + self.current_event = None + self.yaml_version = None + self.tag_handles = {} + self.states = [] + self.marks = [] + self.state = self.parse_stream_start + + def dispose(self): + # Reset the state attributes (to clear self-references) + self.states = [] + self.state = None + + def check_event(self, *choices): + # Check the type of the next event. + if self.current_event is None: + if self.state: + self.current_event = self.state() + if self.current_event is not None: + if not choices: + return True + for choice in choices: + if isinstance(self.current_event, choice): + return True + return False + + def peek_event(self): + # Get the next event. + if self.current_event is None: + if self.state: + self.current_event = self.state() + return self.current_event + + def get_event(self): + # Get the next event and proceed further. + if self.current_event is None: + if self.state: + self.current_event = self.state() + value = self.current_event + self.current_event = None + return value + + # stream ::= STREAM-START implicit_document? explicit_document* STREAM-END + # implicit_document ::= block_node DOCUMENT-END* + # explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* + + def parse_stream_start(self): + + # Parse the stream start. + token = self.get_token() + event = StreamStartEvent(token.start_mark, token.end_mark, + encoding=token.encoding) + + # Prepare the next state. + self.state = self.parse_implicit_document_start + + return event + + def parse_implicit_document_start(self): + + # Parse an implicit document. + if not self.check_token(DirectiveToken, DocumentStartToken, + StreamEndToken): + self.tag_handles = self.DEFAULT_TAGS + token = self.peek_token() + start_mark = end_mark = token.start_mark + event = DocumentStartEvent(start_mark, end_mark, + explicit=False) + + # Prepare the next state. + self.states.append(self.parse_document_end) + self.state = self.parse_block_node + + return event + + else: + return self.parse_document_start() + + def parse_document_start(self): + + # Parse any extra document end indicators. + while self.check_token(DocumentEndToken): + self.get_token() + + # Parse an explicit document. + if not self.check_token(StreamEndToken): + token = self.peek_token() + start_mark = token.start_mark + version, tags = self.process_directives() + if not self.check_token(DocumentStartToken): + raise ParserError(None, None, + "expected '', but found %r" + % self.peek_token().id, + self.peek_token().start_mark) + token = self.get_token() + end_mark = token.end_mark + event = DocumentStartEvent(start_mark, end_mark, + explicit=True, version=version, tags=tags) + self.states.append(self.parse_document_end) + self.state = self.parse_document_content + else: + # Parse the end of the stream. + token = self.get_token() + event = StreamEndEvent(token.start_mark, token.end_mark) + assert not self.states + assert not self.marks + self.state = None + return event + + def parse_document_end(self): + + # Parse the document end. + token = self.peek_token() + start_mark = end_mark = token.start_mark + explicit = False + if self.check_token(DocumentEndToken): + token = self.get_token() + end_mark = token.end_mark + explicit = True + event = DocumentEndEvent(start_mark, end_mark, + explicit=explicit) + + # Prepare the next state. + self.state = self.parse_document_start + + return event + + def parse_document_content(self): + if self.check_token(DirectiveToken, + DocumentStartToken, DocumentEndToken, StreamEndToken): + event = self.process_empty_scalar(self.peek_token().start_mark) + self.state = self.states.pop() + return event + else: + return self.parse_block_node() + + def process_directives(self): + self.yaml_version = None + self.tag_handles = {} + while self.check_token(DirectiveToken): + token = self.get_token() + if token.name == 'YAML': + if self.yaml_version is not None: + raise ParserError(None, None, + "found duplicate YAML directive", token.start_mark) + major, minor = token.value + if major != 1: + raise ParserError(None, None, + "found incompatible YAML document (version 1.* is required)", + token.start_mark) + self.yaml_version = token.value + elif token.name == 'TAG': + handle, prefix = token.value + if handle in self.tag_handles: + raise ParserError(None, None, + "duplicate tag handle %r" % handle, + token.start_mark) + self.tag_handles[handle] = prefix + if self.tag_handles: + value = self.yaml_version, self.tag_handles.copy() + else: + value = self.yaml_version, None + for key in self.DEFAULT_TAGS: + if key not in self.tag_handles: + self.tag_handles[key] = self.DEFAULT_TAGS[key] + return value + + # block_node_or_indentless_sequence ::= ALIAS + # | properties (block_content | indentless_block_sequence)? + # | block_content + # | indentless_block_sequence + # block_node ::= ALIAS + # | properties block_content? + # | block_content + # flow_node ::= ALIAS + # | properties flow_content? + # | flow_content + # properties ::= TAG ANCHOR? | ANCHOR TAG? + # block_content ::= block_collection | flow_collection | SCALAR + # flow_content ::= flow_collection | SCALAR + # block_collection ::= block_sequence | block_mapping + # flow_collection ::= flow_sequence | flow_mapping + + def parse_block_node(self): + return self.parse_node(block=True) + + def parse_flow_node(self): + return self.parse_node() + + def parse_block_node_or_indentless_sequence(self): + return self.parse_node(block=True, indentless_sequence=True) + + def parse_node(self, block=False, indentless_sequence=False): + if self.check_token(AliasToken): + token = self.get_token() + event = AliasEvent(token.value, token.start_mark, token.end_mark) + self.state = self.states.pop() + else: + anchor = None + tag = None + start_mark = end_mark = tag_mark = None + if self.check_token(AnchorToken): + token = self.get_token() + start_mark = token.start_mark + end_mark = token.end_mark + anchor = token.value + if self.check_token(TagToken): + token = self.get_token() + tag_mark = token.start_mark + end_mark = token.end_mark + tag = token.value + elif self.check_token(TagToken): + token = self.get_token() + start_mark = tag_mark = token.start_mark + end_mark = token.end_mark + tag = token.value + if self.check_token(AnchorToken): + token = self.get_token() + end_mark = token.end_mark + anchor = token.value + if tag is not None: + handle, suffix = tag + if handle is not None: + if handle not in self.tag_handles: + raise ParserError("while parsing a node", start_mark, + "found undefined tag handle %r" % handle, + tag_mark) + tag = self.tag_handles[handle]+suffix + else: + tag = suffix + #if tag == '!': + # raise ParserError("while parsing a node", start_mark, + # "found non-specific tag '!'", tag_mark, + # "Please check 'http://pyyaml.org/wiki/YAMLNonSpecificTag' and share your opinion.") + if start_mark is None: + start_mark = end_mark = self.peek_token().start_mark + event = None + implicit = (tag is None or tag == '!') + if indentless_sequence and self.check_token(BlockEntryToken): + end_mark = self.peek_token().end_mark + event = SequenceStartEvent(anchor, tag, implicit, + start_mark, end_mark) + self.state = self.parse_indentless_sequence_entry + else: + if self.check_token(ScalarToken): + token = self.get_token() + end_mark = token.end_mark + if (token.plain and tag is None) or tag == '!': + implicit = (True, False) + elif tag is None: + implicit = (False, True) + else: + implicit = (False, False) + event = ScalarEvent(anchor, tag, implicit, token.value, + start_mark, end_mark, style=token.style) + self.state = self.states.pop() + elif self.check_token(FlowSequenceStartToken): + end_mark = self.peek_token().end_mark + event = SequenceStartEvent(anchor, tag, implicit, + start_mark, end_mark, flow_style=True) + self.state = self.parse_flow_sequence_first_entry + elif self.check_token(FlowMappingStartToken): + end_mark = self.peek_token().end_mark + event = MappingStartEvent(anchor, tag, implicit, + start_mark, end_mark, flow_style=True) + self.state = self.parse_flow_mapping_first_key + elif block and self.check_token(BlockSequenceStartToken): + end_mark = self.peek_token().start_mark + event = SequenceStartEvent(anchor, tag, implicit, + start_mark, end_mark, flow_style=False) + self.state = self.parse_block_sequence_first_entry + elif block and self.check_token(BlockMappingStartToken): + end_mark = self.peek_token().start_mark + event = MappingStartEvent(anchor, tag, implicit, + start_mark, end_mark, flow_style=False) + self.state = self.parse_block_mapping_first_key + elif anchor is not None or tag is not None: + # Empty scalars are allowed even if a tag or an anchor is + # specified. + event = ScalarEvent(anchor, tag, (implicit, False), '', + start_mark, end_mark) + self.state = self.states.pop() + else: + if block: + node = 'block' + else: + node = 'flow' + token = self.peek_token() + raise ParserError("while parsing a %s node" % node, start_mark, + "expected the node content, but found %r" % token.id, + token.start_mark) + return event + + # block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END + + def parse_block_sequence_first_entry(self): + token = self.get_token() + self.marks.append(token.start_mark) + return self.parse_block_sequence_entry() + + def parse_block_sequence_entry(self): + if self.check_token(BlockEntryToken): + token = self.get_token() + if not self.check_token(BlockEntryToken, BlockEndToken): + self.states.append(self.parse_block_sequence_entry) + return self.parse_block_node() + else: + self.state = self.parse_block_sequence_entry + return self.process_empty_scalar(token.end_mark) + if not self.check_token(BlockEndToken): + token = self.peek_token() + raise ParserError("while parsing a block collection", self.marks[-1], + "expected , but found %r" % token.id, token.start_mark) + token = self.get_token() + event = SequenceEndEvent(token.start_mark, token.end_mark) + self.state = self.states.pop() + self.marks.pop() + return event + + # indentless_sequence ::= (BLOCK-ENTRY block_node?)+ + + def parse_indentless_sequence_entry(self): + if self.check_token(BlockEntryToken): + token = self.get_token() + if not self.check_token(BlockEntryToken, + KeyToken, ValueToken, BlockEndToken): + self.states.append(self.parse_indentless_sequence_entry) + return self.parse_block_node() + else: + self.state = self.parse_indentless_sequence_entry + return self.process_empty_scalar(token.end_mark) + token = self.peek_token() + event = SequenceEndEvent(token.start_mark, token.start_mark) + self.state = self.states.pop() + return event + + # block_mapping ::= BLOCK-MAPPING_START + # ((KEY block_node_or_indentless_sequence?)? + # (VALUE block_node_or_indentless_sequence?)?)* + # BLOCK-END + + def parse_block_mapping_first_key(self): + token = self.get_token() + self.marks.append(token.start_mark) + return self.parse_block_mapping_key() + + def parse_block_mapping_key(self): + if self.check_token(KeyToken): + token = self.get_token() + if not self.check_token(KeyToken, ValueToken, BlockEndToken): + self.states.append(self.parse_block_mapping_value) + return self.parse_block_node_or_indentless_sequence() + else: + self.state = self.parse_block_mapping_value + return self.process_empty_scalar(token.end_mark) + if not self.check_token(BlockEndToken): + token = self.peek_token() + raise ParserError("while parsing a block mapping", self.marks[-1], + "expected , but found %r" % token.id, token.start_mark) + token = self.get_token() + event = MappingEndEvent(token.start_mark, token.end_mark) + self.state = self.states.pop() + self.marks.pop() + return event + + def parse_block_mapping_value(self): + if self.check_token(ValueToken): + token = self.get_token() + if not self.check_token(KeyToken, ValueToken, BlockEndToken): + self.states.append(self.parse_block_mapping_key) + return self.parse_block_node_or_indentless_sequence() + else: + self.state = self.parse_block_mapping_key + return self.process_empty_scalar(token.end_mark) + else: + self.state = self.parse_block_mapping_key + token = self.peek_token() + return self.process_empty_scalar(token.start_mark) + + # flow_sequence ::= FLOW-SEQUENCE-START + # (flow_sequence_entry FLOW-ENTRY)* + # flow_sequence_entry? + # FLOW-SEQUENCE-END + # flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + # + # Note that while production rules for both flow_sequence_entry and + # flow_mapping_entry are equal, their interpretations are different. + # For `flow_sequence_entry`, the part `KEY flow_node? (VALUE flow_node?)?` + # generate an inline mapping (set syntax). + + def parse_flow_sequence_first_entry(self): + token = self.get_token() + self.marks.append(token.start_mark) + return self.parse_flow_sequence_entry(first=True) + + def parse_flow_sequence_entry(self, first=False): + if not self.check_token(FlowSequenceEndToken): + if not first: + if self.check_token(FlowEntryToken): + self.get_token() + else: + token = self.peek_token() + raise ParserError("while parsing a flow sequence", self.marks[-1], + "expected ',' or ']', but got %r" % token.id, token.start_mark) + + if self.check_token(KeyToken): + token = self.peek_token() + event = MappingStartEvent(None, None, True, + token.start_mark, token.end_mark, + flow_style=True) + self.state = self.parse_flow_sequence_entry_mapping_key + return event + elif not self.check_token(FlowSequenceEndToken): + self.states.append(self.parse_flow_sequence_entry) + return self.parse_flow_node() + token = self.get_token() + event = SequenceEndEvent(token.start_mark, token.end_mark) + self.state = self.states.pop() + self.marks.pop() + return event + + def parse_flow_sequence_entry_mapping_key(self): + token = self.get_token() + if not self.check_token(ValueToken, + FlowEntryToken, FlowSequenceEndToken): + self.states.append(self.parse_flow_sequence_entry_mapping_value) + return self.parse_flow_node() + else: + self.state = self.parse_flow_sequence_entry_mapping_value + return self.process_empty_scalar(token.end_mark) + + def parse_flow_sequence_entry_mapping_value(self): + if self.check_token(ValueToken): + token = self.get_token() + if not self.check_token(FlowEntryToken, FlowSequenceEndToken): + self.states.append(self.parse_flow_sequence_entry_mapping_end) + return self.parse_flow_node() + else: + self.state = self.parse_flow_sequence_entry_mapping_end + return self.process_empty_scalar(token.end_mark) + else: + self.state = self.parse_flow_sequence_entry_mapping_end + token = self.peek_token() + return self.process_empty_scalar(token.start_mark) + + def parse_flow_sequence_entry_mapping_end(self): + self.state = self.parse_flow_sequence_entry + token = self.peek_token() + return MappingEndEvent(token.start_mark, token.start_mark) + + # flow_mapping ::= FLOW-MAPPING-START + # (flow_mapping_entry FLOW-ENTRY)* + # flow_mapping_entry? + # FLOW-MAPPING-END + # flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + + def parse_flow_mapping_first_key(self): + token = self.get_token() + self.marks.append(token.start_mark) + return self.parse_flow_mapping_key(first=True) + + def parse_flow_mapping_key(self, first=False): + if not self.check_token(FlowMappingEndToken): + if not first: + if self.check_token(FlowEntryToken): + self.get_token() + else: + token = self.peek_token() + raise ParserError("while parsing a flow mapping", self.marks[-1], + "expected ',' or '}', but got %r" % token.id, token.start_mark) + if self.check_token(KeyToken): + token = self.get_token() + if not self.check_token(ValueToken, + FlowEntryToken, FlowMappingEndToken): + self.states.append(self.parse_flow_mapping_value) + return self.parse_flow_node() + else: + self.state = self.parse_flow_mapping_value + return self.process_empty_scalar(token.end_mark) + elif not self.check_token(FlowMappingEndToken): + self.states.append(self.parse_flow_mapping_empty_value) + return self.parse_flow_node() + token = self.get_token() + event = MappingEndEvent(token.start_mark, token.end_mark) + self.state = self.states.pop() + self.marks.pop() + return event + + def parse_flow_mapping_value(self): + if self.check_token(ValueToken): + token = self.get_token() + if not self.check_token(FlowEntryToken, FlowMappingEndToken): + self.states.append(self.parse_flow_mapping_key) + return self.parse_flow_node() + else: + self.state = self.parse_flow_mapping_key + return self.process_empty_scalar(token.end_mark) + else: + self.state = self.parse_flow_mapping_key + token = self.peek_token() + return self.process_empty_scalar(token.start_mark) + + def parse_flow_mapping_empty_value(self): + self.state = self.parse_flow_mapping_key + return self.process_empty_scalar(self.peek_token().start_mark) + + def process_empty_scalar(self, mark): + return ScalarEvent(None, None, (True, False), '', mark, mark) + diff --git a/.venv/lib/python3.10/site-packages/yaml/reader.py b/.venv/lib/python3.10/site-packages/yaml/reader.py new file mode 100644 index 0000000..774b021 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/reader.py @@ -0,0 +1,185 @@ +# This module contains abstractions for the input stream. You don't have to +# looks further, there are no pretty code. +# +# We define two classes here. +# +# Mark(source, line, column) +# It's just a record and its only use is producing nice error messages. +# Parser does not use it for any other purposes. +# +# Reader(source, data) +# Reader determines the encoding of `data` and converts it to unicode. +# Reader provides the following methods and attributes: +# reader.peek(length=1) - return the next `length` characters +# reader.forward(length=1) - move the current position to `length` characters. +# reader.index - the number of the current character. +# reader.line, stream.column - the line and the column of the current character. + +__all__ = ['Reader', 'ReaderError'] + +from .error import YAMLError, Mark + +import codecs, re + +class ReaderError(YAMLError): + + def __init__(self, name, position, character, encoding, reason): + self.name = name + self.character = character + self.position = position + self.encoding = encoding + self.reason = reason + + def __str__(self): + if isinstance(self.character, bytes): + return "'%s' codec can't decode byte #x%02x: %s\n" \ + " in \"%s\", position %d" \ + % (self.encoding, ord(self.character), self.reason, + self.name, self.position) + else: + return "unacceptable character #x%04x: %s\n" \ + " in \"%s\", position %d" \ + % (self.character, self.reason, + self.name, self.position) + +class Reader(object): + # Reader: + # - determines the data encoding and converts it to a unicode string, + # - checks if characters are in allowed range, + # - adds '\0' to the end. + + # Reader accepts + # - a `bytes` object, + # - a `str` object, + # - a file-like object with its `read` method returning `str`, + # - a file-like object with its `read` method returning `unicode`. + + # Yeah, it's ugly and slow. + + def __init__(self, stream): + self.name = None + self.stream = None + self.stream_pointer = 0 + self.eof = True + self.buffer = '' + self.pointer = 0 + self.raw_buffer = None + self.raw_decode = None + self.encoding = None + self.index = 0 + self.line = 0 + self.column = 0 + if isinstance(stream, str): + self.name = "" + self.check_printable(stream) + self.buffer = stream+'\0' + elif isinstance(stream, bytes): + self.name = "" + self.raw_buffer = stream + self.determine_encoding() + else: + self.stream = stream + self.name = getattr(stream, 'name', "") + self.eof = False + self.raw_buffer = None + self.determine_encoding() + + def peek(self, index=0): + try: + return self.buffer[self.pointer+index] + except IndexError: + self.update(index+1) + return self.buffer[self.pointer+index] + + def prefix(self, length=1): + if self.pointer+length >= len(self.buffer): + self.update(length) + return self.buffer[self.pointer:self.pointer+length] + + def forward(self, length=1): + if self.pointer+length+1 >= len(self.buffer): + self.update(length+1) + while length: + ch = self.buffer[self.pointer] + self.pointer += 1 + self.index += 1 + if ch in '\n\x85\u2028\u2029' \ + or (ch == '\r' and self.buffer[self.pointer] != '\n'): + self.line += 1 + self.column = 0 + elif ch != '\uFEFF': + self.column += 1 + length -= 1 + + def get_mark(self): + if self.stream is None: + return Mark(self.name, self.index, self.line, self.column, + self.buffer, self.pointer) + else: + return Mark(self.name, self.index, self.line, self.column, + None, None) + + def determine_encoding(self): + while not self.eof and (self.raw_buffer is None or len(self.raw_buffer) < 2): + self.update_raw() + if isinstance(self.raw_buffer, bytes): + if self.raw_buffer.startswith(codecs.BOM_UTF16_LE): + self.raw_decode = codecs.utf_16_le_decode + self.encoding = 'utf-16-le' + elif self.raw_buffer.startswith(codecs.BOM_UTF16_BE): + self.raw_decode = codecs.utf_16_be_decode + self.encoding = 'utf-16-be' + else: + self.raw_decode = codecs.utf_8_decode + self.encoding = 'utf-8' + self.update(1) + + NON_PRINTABLE = re.compile('[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\uD7FF\uE000-\uFFFD\U00010000-\U0010ffff]') + def check_printable(self, data): + match = self.NON_PRINTABLE.search(data) + if match: + character = match.group() + position = self.index+(len(self.buffer)-self.pointer)+match.start() + raise ReaderError(self.name, position, ord(character), + 'unicode', "special characters are not allowed") + + def update(self, length): + if self.raw_buffer is None: + return + self.buffer = self.buffer[self.pointer:] + self.pointer = 0 + while len(self.buffer) < length: + if not self.eof: + self.update_raw() + if self.raw_decode is not None: + try: + data, converted = self.raw_decode(self.raw_buffer, + 'strict', self.eof) + except UnicodeDecodeError as exc: + character = self.raw_buffer[exc.start] + if self.stream is not None: + position = self.stream_pointer-len(self.raw_buffer)+exc.start + else: + position = exc.start + raise ReaderError(self.name, position, character, + exc.encoding, exc.reason) + else: + data = self.raw_buffer + converted = len(data) + self.check_printable(data) + self.buffer += data + self.raw_buffer = self.raw_buffer[converted:] + if self.eof: + self.buffer += '\0' + self.raw_buffer = None + break + + def update_raw(self, size=4096): + data = self.stream.read(size) + if self.raw_buffer is None: + self.raw_buffer = data + else: + self.raw_buffer += data + self.stream_pointer += len(data) + if not data: + self.eof = True diff --git a/.venv/lib/python3.10/site-packages/yaml/representer.py b/.venv/lib/python3.10/site-packages/yaml/representer.py new file mode 100644 index 0000000..808ca06 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/representer.py @@ -0,0 +1,389 @@ + +__all__ = ['BaseRepresenter', 'SafeRepresenter', 'Representer', + 'RepresenterError'] + +from .error import * +from .nodes import * + +import datetime, copyreg, types, base64, collections + +class RepresenterError(YAMLError): + pass + +class BaseRepresenter: + + yaml_representers = {} + yaml_multi_representers = {} + + def __init__(self, default_style=None, default_flow_style=False, sort_keys=True): + self.default_style = default_style + self.sort_keys = sort_keys + self.default_flow_style = default_flow_style + self.represented_objects = {} + self.object_keeper = [] + self.alias_key = None + + def represent(self, data): + node = self.represent_data(data) + self.serialize(node) + self.represented_objects = {} + self.object_keeper = [] + self.alias_key = None + + def represent_data(self, data): + if self.ignore_aliases(data): + self.alias_key = None + else: + self.alias_key = id(data) + if self.alias_key is not None: + if self.alias_key in self.represented_objects: + node = self.represented_objects[self.alias_key] + #if node is None: + # raise RepresenterError("recursive objects are not allowed: %r" % data) + return node + #self.represented_objects[alias_key] = None + self.object_keeper.append(data) + data_types = type(data).__mro__ + if data_types[0] in self.yaml_representers: + node = self.yaml_representers[data_types[0]](self, data) + else: + for data_type in data_types: + if data_type in self.yaml_multi_representers: + node = self.yaml_multi_representers[data_type](self, data) + break + else: + if None in self.yaml_multi_representers: + node = self.yaml_multi_representers[None](self, data) + elif None in self.yaml_representers: + node = self.yaml_representers[None](self, data) + else: + node = ScalarNode(None, str(data)) + #if alias_key is not None: + # self.represented_objects[alias_key] = node + return node + + @classmethod + def add_representer(cls, data_type, representer): + if not 'yaml_representers' in cls.__dict__: + cls.yaml_representers = cls.yaml_representers.copy() + cls.yaml_representers[data_type] = representer + + @classmethod + def add_multi_representer(cls, data_type, representer): + if not 'yaml_multi_representers' in cls.__dict__: + cls.yaml_multi_representers = cls.yaml_multi_representers.copy() + cls.yaml_multi_representers[data_type] = representer + + def represent_scalar(self, tag, value, style=None): + if style is None: + style = self.default_style + node = ScalarNode(tag, value, style=style) + if self.alias_key is not None: + self.represented_objects[self.alias_key] = node + return node + + def represent_sequence(self, tag, sequence, flow_style=None): + value = [] + node = SequenceNode(tag, value, flow_style=flow_style) + if self.alias_key is not None: + self.represented_objects[self.alias_key] = node + best_style = True + for item in sequence: + node_item = self.represent_data(item) + if not (isinstance(node_item, ScalarNode) and not node_item.style): + best_style = False + value.append(node_item) + if flow_style is None: + if self.default_flow_style is not None: + node.flow_style = self.default_flow_style + else: + node.flow_style = best_style + return node + + def represent_mapping(self, tag, mapping, flow_style=None): + value = [] + node = MappingNode(tag, value, flow_style=flow_style) + if self.alias_key is not None: + self.represented_objects[self.alias_key] = node + best_style = True + if hasattr(mapping, 'items'): + mapping = list(mapping.items()) + if self.sort_keys: + try: + mapping = sorted(mapping) + except TypeError: + pass + for item_key, item_value in mapping: + node_key = self.represent_data(item_key) + node_value = self.represent_data(item_value) + if not (isinstance(node_key, ScalarNode) and not node_key.style): + best_style = False + if not (isinstance(node_value, ScalarNode) and not node_value.style): + best_style = False + value.append((node_key, node_value)) + if flow_style is None: + if self.default_flow_style is not None: + node.flow_style = self.default_flow_style + else: + node.flow_style = best_style + return node + + def ignore_aliases(self, data): + return False + +class SafeRepresenter(BaseRepresenter): + + def ignore_aliases(self, data): + if data is None: + return True + if isinstance(data, tuple) and data == (): + return True + if isinstance(data, (str, bytes, bool, int, float)): + return True + + def represent_none(self, data): + return self.represent_scalar('tag:yaml.org,2002:null', 'null') + + def represent_str(self, data): + return self.represent_scalar('tag:yaml.org,2002:str', data) + + def represent_binary(self, data): + if hasattr(base64, 'encodebytes'): + data = base64.encodebytes(data).decode('ascii') + else: + data = base64.encodestring(data).decode('ascii') + return self.represent_scalar('tag:yaml.org,2002:binary', data, style='|') + + def represent_bool(self, data): + if data: + value = 'true' + else: + value = 'false' + return self.represent_scalar('tag:yaml.org,2002:bool', value) + + def represent_int(self, data): + return self.represent_scalar('tag:yaml.org,2002:int', str(data)) + + inf_value = 1e300 + while repr(inf_value) != repr(inf_value*inf_value): + inf_value *= inf_value + + def represent_float(self, data): + if data != data or (data == 0.0 and data == 1.0): + value = '.nan' + elif data == self.inf_value: + value = '.inf' + elif data == -self.inf_value: + value = '-.inf' + else: + value = repr(data).lower() + # Note that in some cases `repr(data)` represents a float number + # without the decimal parts. For instance: + # >>> repr(1e17) + # '1e17' + # Unfortunately, this is not a valid float representation according + # to the definition of the `!!float` tag. We fix this by adding + # '.0' before the 'e' symbol. + if '.' not in value and 'e' in value: + value = value.replace('e', '.0e', 1) + return self.represent_scalar('tag:yaml.org,2002:float', value) + + def represent_list(self, data): + #pairs = (len(data) > 0 and isinstance(data, list)) + #if pairs: + # for item in data: + # if not isinstance(item, tuple) or len(item) != 2: + # pairs = False + # break + #if not pairs: + return self.represent_sequence('tag:yaml.org,2002:seq', data) + #value = [] + #for item_key, item_value in data: + # value.append(self.represent_mapping(u'tag:yaml.org,2002:map', + # [(item_key, item_value)])) + #return SequenceNode(u'tag:yaml.org,2002:pairs', value) + + def represent_dict(self, data): + return self.represent_mapping('tag:yaml.org,2002:map', data) + + def represent_set(self, data): + value = {} + for key in data: + value[key] = None + return self.represent_mapping('tag:yaml.org,2002:set', value) + + def represent_date(self, data): + value = data.isoformat() + return self.represent_scalar('tag:yaml.org,2002:timestamp', value) + + def represent_datetime(self, data): + value = data.isoformat(' ') + return self.represent_scalar('tag:yaml.org,2002:timestamp', value) + + def represent_yaml_object(self, tag, data, cls, flow_style=None): + if hasattr(data, '__getstate__'): + state = data.__getstate__() + else: + state = data.__dict__.copy() + return self.represent_mapping(tag, state, flow_style=flow_style) + + def represent_undefined(self, data): + raise RepresenterError("cannot represent an object", data) + +SafeRepresenter.add_representer(type(None), + SafeRepresenter.represent_none) + +SafeRepresenter.add_representer(str, + SafeRepresenter.represent_str) + +SafeRepresenter.add_representer(bytes, + SafeRepresenter.represent_binary) + +SafeRepresenter.add_representer(bool, + SafeRepresenter.represent_bool) + +SafeRepresenter.add_representer(int, + SafeRepresenter.represent_int) + +SafeRepresenter.add_representer(float, + SafeRepresenter.represent_float) + +SafeRepresenter.add_representer(list, + SafeRepresenter.represent_list) + +SafeRepresenter.add_representer(tuple, + SafeRepresenter.represent_list) + +SafeRepresenter.add_representer(dict, + SafeRepresenter.represent_dict) + +SafeRepresenter.add_representer(set, + SafeRepresenter.represent_set) + +SafeRepresenter.add_representer(datetime.date, + SafeRepresenter.represent_date) + +SafeRepresenter.add_representer(datetime.datetime, + SafeRepresenter.represent_datetime) + +SafeRepresenter.add_representer(None, + SafeRepresenter.represent_undefined) + +class Representer(SafeRepresenter): + + def represent_complex(self, data): + if data.imag == 0.0: + data = '%r' % data.real + elif data.real == 0.0: + data = '%rj' % data.imag + elif data.imag > 0: + data = '%r+%rj' % (data.real, data.imag) + else: + data = '%r%rj' % (data.real, data.imag) + return self.represent_scalar('tag:yaml.org,2002:python/complex', data) + + def represent_tuple(self, data): + return self.represent_sequence('tag:yaml.org,2002:python/tuple', data) + + def represent_name(self, data): + name = '%s.%s' % (data.__module__, data.__name__) + return self.represent_scalar('tag:yaml.org,2002:python/name:'+name, '') + + def represent_module(self, data): + return self.represent_scalar( + 'tag:yaml.org,2002:python/module:'+data.__name__, '') + + def represent_object(self, data): + # We use __reduce__ API to save the data. data.__reduce__ returns + # a tuple of length 2-5: + # (function, args, state, listitems, dictitems) + + # For reconstructing, we calls function(*args), then set its state, + # listitems, and dictitems if they are not None. + + # A special case is when function.__name__ == '__newobj__'. In this + # case we create the object with args[0].__new__(*args). + + # Another special case is when __reduce__ returns a string - we don't + # support it. + + # We produce a !!python/object, !!python/object/new or + # !!python/object/apply node. + + cls = type(data) + if cls in copyreg.dispatch_table: + reduce = copyreg.dispatch_table[cls](data) + elif hasattr(data, '__reduce_ex__'): + reduce = data.__reduce_ex__(2) + elif hasattr(data, '__reduce__'): + reduce = data.__reduce__() + else: + raise RepresenterError("cannot represent an object", data) + reduce = (list(reduce)+[None]*5)[:5] + function, args, state, listitems, dictitems = reduce + args = list(args) + if state is None: + state = {} + if listitems is not None: + listitems = list(listitems) + if dictitems is not None: + dictitems = dict(dictitems) + if function.__name__ == '__newobj__': + function = args[0] + args = args[1:] + tag = 'tag:yaml.org,2002:python/object/new:' + newobj = True + else: + tag = 'tag:yaml.org,2002:python/object/apply:' + newobj = False + function_name = '%s.%s' % (function.__module__, function.__name__) + if not args and not listitems and not dictitems \ + and isinstance(state, dict) and newobj: + return self.represent_mapping( + 'tag:yaml.org,2002:python/object:'+function_name, state) + if not listitems and not dictitems \ + and isinstance(state, dict) and not state: + return self.represent_sequence(tag+function_name, args) + value = {} + if args: + value['args'] = args + if state or not isinstance(state, dict): + value['state'] = state + if listitems: + value['listitems'] = listitems + if dictitems: + value['dictitems'] = dictitems + return self.represent_mapping(tag+function_name, value) + + def represent_ordered_dict(self, data): + # Provide uniform representation across different Python versions. + data_type = type(data) + tag = 'tag:yaml.org,2002:python/object/apply:%s.%s' \ + % (data_type.__module__, data_type.__name__) + items = [[key, value] for key, value in data.items()] + return self.represent_sequence(tag, [items]) + +Representer.add_representer(complex, + Representer.represent_complex) + +Representer.add_representer(tuple, + Representer.represent_tuple) + +Representer.add_multi_representer(type, + Representer.represent_name) + +Representer.add_representer(collections.OrderedDict, + Representer.represent_ordered_dict) + +Representer.add_representer(types.FunctionType, + Representer.represent_name) + +Representer.add_representer(types.BuiltinFunctionType, + Representer.represent_name) + +Representer.add_representer(types.ModuleType, + Representer.represent_module) + +Representer.add_multi_representer(object, + Representer.represent_object) + diff --git a/.venv/lib/python3.10/site-packages/yaml/resolver.py b/.venv/lib/python3.10/site-packages/yaml/resolver.py new file mode 100644 index 0000000..3522bda --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/resolver.py @@ -0,0 +1,227 @@ + +__all__ = ['BaseResolver', 'Resolver'] + +from .error import * +from .nodes import * + +import re + +class ResolverError(YAMLError): + pass + +class BaseResolver: + + DEFAULT_SCALAR_TAG = 'tag:yaml.org,2002:str' + DEFAULT_SEQUENCE_TAG = 'tag:yaml.org,2002:seq' + DEFAULT_MAPPING_TAG = 'tag:yaml.org,2002:map' + + yaml_implicit_resolvers = {} + yaml_path_resolvers = {} + + def __init__(self): + self.resolver_exact_paths = [] + self.resolver_prefix_paths = [] + + @classmethod + def add_implicit_resolver(cls, tag, regexp, first): + if not 'yaml_implicit_resolvers' in cls.__dict__: + implicit_resolvers = {} + for key in cls.yaml_implicit_resolvers: + implicit_resolvers[key] = cls.yaml_implicit_resolvers[key][:] + cls.yaml_implicit_resolvers = implicit_resolvers + if first is None: + first = [None] + for ch in first: + cls.yaml_implicit_resolvers.setdefault(ch, []).append((tag, regexp)) + + @classmethod + def add_path_resolver(cls, tag, path, kind=None): + # Note: `add_path_resolver` is experimental. The API could be changed. + # `new_path` is a pattern that is matched against the path from the + # root to the node that is being considered. `node_path` elements are + # tuples `(node_check, index_check)`. `node_check` is a node class: + # `ScalarNode`, `SequenceNode`, `MappingNode` or `None`. `None` + # matches any kind of a node. `index_check` could be `None`, a boolean + # value, a string value, or a number. `None` and `False` match against + # any _value_ of sequence and mapping nodes. `True` matches against + # any _key_ of a mapping node. A string `index_check` matches against + # a mapping value that corresponds to a scalar key which content is + # equal to the `index_check` value. An integer `index_check` matches + # against a sequence value with the index equal to `index_check`. + if not 'yaml_path_resolvers' in cls.__dict__: + cls.yaml_path_resolvers = cls.yaml_path_resolvers.copy() + new_path = [] + for element in path: + if isinstance(element, (list, tuple)): + if len(element) == 2: + node_check, index_check = element + elif len(element) == 1: + node_check = element[0] + index_check = True + else: + raise ResolverError("Invalid path element: %s" % element) + else: + node_check = None + index_check = element + if node_check is str: + node_check = ScalarNode + elif node_check is list: + node_check = SequenceNode + elif node_check is dict: + node_check = MappingNode + elif node_check not in [ScalarNode, SequenceNode, MappingNode] \ + and not isinstance(node_check, str) \ + and node_check is not None: + raise ResolverError("Invalid node checker: %s" % node_check) + if not isinstance(index_check, (str, int)) \ + and index_check is not None: + raise ResolverError("Invalid index checker: %s" % index_check) + new_path.append((node_check, index_check)) + if kind is str: + kind = ScalarNode + elif kind is list: + kind = SequenceNode + elif kind is dict: + kind = MappingNode + elif kind not in [ScalarNode, SequenceNode, MappingNode] \ + and kind is not None: + raise ResolverError("Invalid node kind: %s" % kind) + cls.yaml_path_resolvers[tuple(new_path), kind] = tag + + def descend_resolver(self, current_node, current_index): + if not self.yaml_path_resolvers: + return + exact_paths = {} + prefix_paths = [] + if current_node: + depth = len(self.resolver_prefix_paths) + for path, kind in self.resolver_prefix_paths[-1]: + if self.check_resolver_prefix(depth, path, kind, + current_node, current_index): + if len(path) > depth: + prefix_paths.append((path, kind)) + else: + exact_paths[kind] = self.yaml_path_resolvers[path, kind] + else: + for path, kind in self.yaml_path_resolvers: + if not path: + exact_paths[kind] = self.yaml_path_resolvers[path, kind] + else: + prefix_paths.append((path, kind)) + self.resolver_exact_paths.append(exact_paths) + self.resolver_prefix_paths.append(prefix_paths) + + def ascend_resolver(self): + if not self.yaml_path_resolvers: + return + self.resolver_exact_paths.pop() + self.resolver_prefix_paths.pop() + + def check_resolver_prefix(self, depth, path, kind, + current_node, current_index): + node_check, index_check = path[depth-1] + if isinstance(node_check, str): + if current_node.tag != node_check: + return + elif node_check is not None: + if not isinstance(current_node, node_check): + return + if index_check is True and current_index is not None: + return + if (index_check is False or index_check is None) \ + and current_index is None: + return + if isinstance(index_check, str): + if not (isinstance(current_index, ScalarNode) + and index_check == current_index.value): + return + elif isinstance(index_check, int) and not isinstance(index_check, bool): + if index_check != current_index: + return + return True + + def resolve(self, kind, value, implicit): + if kind is ScalarNode and implicit[0]: + if value == '': + resolvers = self.yaml_implicit_resolvers.get('', []) + else: + resolvers = self.yaml_implicit_resolvers.get(value[0], []) + wildcard_resolvers = self.yaml_implicit_resolvers.get(None, []) + for tag, regexp in resolvers + wildcard_resolvers: + if regexp.match(value): + return tag + implicit = implicit[1] + if self.yaml_path_resolvers: + exact_paths = self.resolver_exact_paths[-1] + if kind in exact_paths: + return exact_paths[kind] + if None in exact_paths: + return exact_paths[None] + if kind is ScalarNode: + return self.DEFAULT_SCALAR_TAG + elif kind is SequenceNode: + return self.DEFAULT_SEQUENCE_TAG + elif kind is MappingNode: + return self.DEFAULT_MAPPING_TAG + +class Resolver(BaseResolver): + pass + +Resolver.add_implicit_resolver( + 'tag:yaml.org,2002:bool', + re.compile(r'''^(?:yes|Yes|YES|no|No|NO + |true|True|TRUE|false|False|FALSE + |on|On|ON|off|Off|OFF)$''', re.X), + list('yYnNtTfFoO')) + +Resolver.add_implicit_resolver( + 'tag:yaml.org,2002:float', + re.compile(r'''^(?:[-+]?(?:[0-9][0-9_]*)\.[0-9_]*(?:[eE][-+][0-9]+)? + |\.[0-9][0-9_]*(?:[eE][-+][0-9]+)? + |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]* + |[-+]?\.(?:inf|Inf|INF) + |\.(?:nan|NaN|NAN))$''', re.X), + list('-+0123456789.')) + +Resolver.add_implicit_resolver( + 'tag:yaml.org,2002:int', + re.compile(r'''^(?:[-+]?0b[0-1_]+ + |[-+]?0[0-7_]+ + |[-+]?(?:0|[1-9][0-9_]*) + |[-+]?0x[0-9a-fA-F_]+ + |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$''', re.X), + list('-+0123456789')) + +Resolver.add_implicit_resolver( + 'tag:yaml.org,2002:merge', + re.compile(r'^(?:<<)$'), + ['<']) + +Resolver.add_implicit_resolver( + 'tag:yaml.org,2002:null', + re.compile(r'''^(?: ~ + |null|Null|NULL + | )$''', re.X), + ['~', 'n', 'N', '']) + +Resolver.add_implicit_resolver( + 'tag:yaml.org,2002:timestamp', + re.compile(r'''^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] + |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]? + (?:[Tt]|[ \t]+)[0-9][0-9]? + :[0-9][0-9] :[0-9][0-9] (?:\.[0-9]*)? + (?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$''', re.X), + list('0123456789')) + +Resolver.add_implicit_resolver( + 'tag:yaml.org,2002:value', + re.compile(r'^(?:=)$'), + ['=']) + +# The following resolver is only for documentation purposes. It cannot work +# because plain scalars cannot start with '!', '&', or '*'. +Resolver.add_implicit_resolver( + 'tag:yaml.org,2002:yaml', + re.compile(r'^(?:!|&|\*)$'), + list('!&*')) + diff --git a/.venv/lib/python3.10/site-packages/yaml/scanner.py b/.venv/lib/python3.10/site-packages/yaml/scanner.py new file mode 100644 index 0000000..de925b0 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/scanner.py @@ -0,0 +1,1435 @@ + +# Scanner produces tokens of the following types: +# STREAM-START +# STREAM-END +# DIRECTIVE(name, value) +# DOCUMENT-START +# DOCUMENT-END +# BLOCK-SEQUENCE-START +# BLOCK-MAPPING-START +# BLOCK-END +# FLOW-SEQUENCE-START +# FLOW-MAPPING-START +# FLOW-SEQUENCE-END +# FLOW-MAPPING-END +# BLOCK-ENTRY +# FLOW-ENTRY +# KEY +# VALUE +# ALIAS(value) +# ANCHOR(value) +# TAG(value) +# SCALAR(value, plain, style) +# +# Read comments in the Scanner code for more details. +# + +__all__ = ['Scanner', 'ScannerError'] + +from .error import MarkedYAMLError +from .tokens import * + +class ScannerError(MarkedYAMLError): + pass + +class SimpleKey: + # See below simple keys treatment. + + def __init__(self, token_number, required, index, line, column, mark): + self.token_number = token_number + self.required = required + self.index = index + self.line = line + self.column = column + self.mark = mark + +class Scanner: + + def __init__(self): + """Initialize the scanner.""" + # It is assumed that Scanner and Reader will have a common descendant. + # Reader do the dirty work of checking for BOM and converting the + # input data to Unicode. It also adds NUL to the end. + # + # Reader supports the following methods + # self.peek(i=0) # peek the next i-th character + # self.prefix(l=1) # peek the next l characters + # self.forward(l=1) # read the next l characters and move the pointer. + + # Had we reached the end of the stream? + self.done = False + + # The number of unclosed '{' and '['. `flow_level == 0` means block + # context. + self.flow_level = 0 + + # List of processed tokens that are not yet emitted. + self.tokens = [] + + # Add the STREAM-START token. + self.fetch_stream_start() + + # Number of tokens that were emitted through the `get_token` method. + self.tokens_taken = 0 + + # The current indentation level. + self.indent = -1 + + # Past indentation levels. + self.indents = [] + + # Variables related to simple keys treatment. + + # A simple key is a key that is not denoted by the '?' indicator. + # Example of simple keys: + # --- + # block simple key: value + # ? not a simple key: + # : { flow simple key: value } + # We emit the KEY token before all keys, so when we find a potential + # simple key, we try to locate the corresponding ':' indicator. + # Simple keys should be limited to a single line and 1024 characters. + + # Can a simple key start at the current position? A simple key may + # start: + # - at the beginning of the line, not counting indentation spaces + # (in block context), + # - after '{', '[', ',' (in the flow context), + # - after '?', ':', '-' (in the block context). + # In the block context, this flag also signifies if a block collection + # may start at the current position. + self.allow_simple_key = True + + # Keep track of possible simple keys. This is a dictionary. The key + # is `flow_level`; there can be no more that one possible simple key + # for each level. The value is a SimpleKey record: + # (token_number, required, index, line, column, mark) + # A simple key may start with ALIAS, ANCHOR, TAG, SCALAR(flow), + # '[', or '{' tokens. + self.possible_simple_keys = {} + + # Public methods. + + def check_token(self, *choices): + # Check if the next token is one of the given types. + while self.need_more_tokens(): + self.fetch_more_tokens() + if self.tokens: + if not choices: + return True + for choice in choices: + if isinstance(self.tokens[0], choice): + return True + return False + + def peek_token(self): + # Return the next token, but do not delete if from the queue. + # Return None if no more tokens. + while self.need_more_tokens(): + self.fetch_more_tokens() + if self.tokens: + return self.tokens[0] + else: + return None + + def get_token(self): + # Return the next token. + while self.need_more_tokens(): + self.fetch_more_tokens() + if self.tokens: + self.tokens_taken += 1 + return self.tokens.pop(0) + + # Private methods. + + def need_more_tokens(self): + if self.done: + return False + if not self.tokens: + return True + # The current token may be a potential simple key, so we + # need to look further. + self.stale_possible_simple_keys() + if self.next_possible_simple_key() == self.tokens_taken: + return True + + def fetch_more_tokens(self): + + # Eat whitespaces and comments until we reach the next token. + self.scan_to_next_token() + + # Remove obsolete possible simple keys. + self.stale_possible_simple_keys() + + # Compare the current indentation and column. It may add some tokens + # and decrease the current indentation level. + self.unwind_indent(self.column) + + # Peek the next character. + ch = self.peek() + + # Is it the end of stream? + if ch == '\0': + return self.fetch_stream_end() + + # Is it a directive? + if ch == '%' and self.check_directive(): + return self.fetch_directive() + + # Is it the document start? + if ch == '-' and self.check_document_start(): + return self.fetch_document_start() + + # Is it the document end? + if ch == '.' and self.check_document_end(): + return self.fetch_document_end() + + # TODO: support for BOM within a stream. + #if ch == '\uFEFF': + # return self.fetch_bom() <-- issue BOMToken + + # Note: the order of the following checks is NOT significant. + + # Is it the flow sequence start indicator? + if ch == '[': + return self.fetch_flow_sequence_start() + + # Is it the flow mapping start indicator? + if ch == '{': + return self.fetch_flow_mapping_start() + + # Is it the flow sequence end indicator? + if ch == ']': + return self.fetch_flow_sequence_end() + + # Is it the flow mapping end indicator? + if ch == '}': + return self.fetch_flow_mapping_end() + + # Is it the flow entry indicator? + if ch == ',': + return self.fetch_flow_entry() + + # Is it the block entry indicator? + if ch == '-' and self.check_block_entry(): + return self.fetch_block_entry() + + # Is it the key indicator? + if ch == '?' and self.check_key(): + return self.fetch_key() + + # Is it the value indicator? + if ch == ':' and self.check_value(): + return self.fetch_value() + + # Is it an alias? + if ch == '*': + return self.fetch_alias() + + # Is it an anchor? + if ch == '&': + return self.fetch_anchor() + + # Is it a tag? + if ch == '!': + return self.fetch_tag() + + # Is it a literal scalar? + if ch == '|' and not self.flow_level: + return self.fetch_literal() + + # Is it a folded scalar? + if ch == '>' and not self.flow_level: + return self.fetch_folded() + + # Is it a single quoted scalar? + if ch == '\'': + return self.fetch_single() + + # Is it a double quoted scalar? + if ch == '\"': + return self.fetch_double() + + # It must be a plain scalar then. + if self.check_plain(): + return self.fetch_plain() + + # No? It's an error. Let's produce a nice error message. + raise ScannerError("while scanning for the next token", None, + "found character %r that cannot start any token" % ch, + self.get_mark()) + + # Simple keys treatment. + + def next_possible_simple_key(self): + # Return the number of the nearest possible simple key. Actually we + # don't need to loop through the whole dictionary. We may replace it + # with the following code: + # if not self.possible_simple_keys: + # return None + # return self.possible_simple_keys[ + # min(self.possible_simple_keys.keys())].token_number + min_token_number = None + for level in self.possible_simple_keys: + key = self.possible_simple_keys[level] + if min_token_number is None or key.token_number < min_token_number: + min_token_number = key.token_number + return min_token_number + + def stale_possible_simple_keys(self): + # Remove entries that are no longer possible simple keys. According to + # the YAML specification, simple keys + # - should be limited to a single line, + # - should be no longer than 1024 characters. + # Disabling this procedure will allow simple keys of any length and + # height (may cause problems if indentation is broken though). + for level in list(self.possible_simple_keys): + key = self.possible_simple_keys[level] + if key.line != self.line \ + or self.index-key.index > 1024: + if key.required: + raise ScannerError("while scanning a simple key", key.mark, + "could not find expected ':'", self.get_mark()) + del self.possible_simple_keys[level] + + def save_possible_simple_key(self): + # The next token may start a simple key. We check if it's possible + # and save its position. This function is called for + # ALIAS, ANCHOR, TAG, SCALAR(flow), '[', and '{'. + + # Check if a simple key is required at the current position. + required = not self.flow_level and self.indent == self.column + + # The next token might be a simple key. Let's save it's number and + # position. + if self.allow_simple_key: + self.remove_possible_simple_key() + token_number = self.tokens_taken+len(self.tokens) + key = SimpleKey(token_number, required, + self.index, self.line, self.column, self.get_mark()) + self.possible_simple_keys[self.flow_level] = key + + def remove_possible_simple_key(self): + # Remove the saved possible key position at the current flow level. + if self.flow_level in self.possible_simple_keys: + key = self.possible_simple_keys[self.flow_level] + + if key.required: + raise ScannerError("while scanning a simple key", key.mark, + "could not find expected ':'", self.get_mark()) + + del self.possible_simple_keys[self.flow_level] + + # Indentation functions. + + def unwind_indent(self, column): + + ## In flow context, tokens should respect indentation. + ## Actually the condition should be `self.indent >= column` according to + ## the spec. But this condition will prohibit intuitively correct + ## constructions such as + ## key : { + ## } + #if self.flow_level and self.indent > column: + # raise ScannerError(None, None, + # "invalid indentation or unclosed '[' or '{'", + # self.get_mark()) + + # In the flow context, indentation is ignored. We make the scanner less + # restrictive then specification requires. + if self.flow_level: + return + + # In block context, we may need to issue the BLOCK-END tokens. + while self.indent > column: + mark = self.get_mark() + self.indent = self.indents.pop() + self.tokens.append(BlockEndToken(mark, mark)) + + def add_indent(self, column): + # Check if we need to increase indentation. + if self.indent < column: + self.indents.append(self.indent) + self.indent = column + return True + return False + + # Fetchers. + + def fetch_stream_start(self): + # We always add STREAM-START as the first token and STREAM-END as the + # last token. + + # Read the token. + mark = self.get_mark() + + # Add STREAM-START. + self.tokens.append(StreamStartToken(mark, mark, + encoding=self.encoding)) + + + def fetch_stream_end(self): + + # Set the current indentation to -1. + self.unwind_indent(-1) + + # Reset simple keys. + self.remove_possible_simple_key() + self.allow_simple_key = False + self.possible_simple_keys = {} + + # Read the token. + mark = self.get_mark() + + # Add STREAM-END. + self.tokens.append(StreamEndToken(mark, mark)) + + # The steam is finished. + self.done = True + + def fetch_directive(self): + + # Set the current indentation to -1. + self.unwind_indent(-1) + + # Reset simple keys. + self.remove_possible_simple_key() + self.allow_simple_key = False + + # Scan and add DIRECTIVE. + self.tokens.append(self.scan_directive()) + + def fetch_document_start(self): + self.fetch_document_indicator(DocumentStartToken) + + def fetch_document_end(self): + self.fetch_document_indicator(DocumentEndToken) + + def fetch_document_indicator(self, TokenClass): + + # Set the current indentation to -1. + self.unwind_indent(-1) + + # Reset simple keys. Note that there could not be a block collection + # after '---'. + self.remove_possible_simple_key() + self.allow_simple_key = False + + # Add DOCUMENT-START or DOCUMENT-END. + start_mark = self.get_mark() + self.forward(3) + end_mark = self.get_mark() + self.tokens.append(TokenClass(start_mark, end_mark)) + + def fetch_flow_sequence_start(self): + self.fetch_flow_collection_start(FlowSequenceStartToken) + + def fetch_flow_mapping_start(self): + self.fetch_flow_collection_start(FlowMappingStartToken) + + def fetch_flow_collection_start(self, TokenClass): + + # '[' and '{' may start a simple key. + self.save_possible_simple_key() + + # Increase the flow level. + self.flow_level += 1 + + # Simple keys are allowed after '[' and '{'. + self.allow_simple_key = True + + # Add FLOW-SEQUENCE-START or FLOW-MAPPING-START. + start_mark = self.get_mark() + self.forward() + end_mark = self.get_mark() + self.tokens.append(TokenClass(start_mark, end_mark)) + + def fetch_flow_sequence_end(self): + self.fetch_flow_collection_end(FlowSequenceEndToken) + + def fetch_flow_mapping_end(self): + self.fetch_flow_collection_end(FlowMappingEndToken) + + def fetch_flow_collection_end(self, TokenClass): + + # Reset possible simple key on the current level. + self.remove_possible_simple_key() + + # Decrease the flow level. + self.flow_level -= 1 + + # No simple keys after ']' or '}'. + self.allow_simple_key = False + + # Add FLOW-SEQUENCE-END or FLOW-MAPPING-END. + start_mark = self.get_mark() + self.forward() + end_mark = self.get_mark() + self.tokens.append(TokenClass(start_mark, end_mark)) + + def fetch_flow_entry(self): + + # Simple keys are allowed after ','. + self.allow_simple_key = True + + # Reset possible simple key on the current level. + self.remove_possible_simple_key() + + # Add FLOW-ENTRY. + start_mark = self.get_mark() + self.forward() + end_mark = self.get_mark() + self.tokens.append(FlowEntryToken(start_mark, end_mark)) + + def fetch_block_entry(self): + + # Block context needs additional checks. + if not self.flow_level: + + # Are we allowed to start a new entry? + if not self.allow_simple_key: + raise ScannerError(None, None, + "sequence entries are not allowed here", + self.get_mark()) + + # We may need to add BLOCK-SEQUENCE-START. + if self.add_indent(self.column): + mark = self.get_mark() + self.tokens.append(BlockSequenceStartToken(mark, mark)) + + # It's an error for the block entry to occur in the flow context, + # but we let the parser detect this. + else: + pass + + # Simple keys are allowed after '-'. + self.allow_simple_key = True + + # Reset possible simple key on the current level. + self.remove_possible_simple_key() + + # Add BLOCK-ENTRY. + start_mark = self.get_mark() + self.forward() + end_mark = self.get_mark() + self.tokens.append(BlockEntryToken(start_mark, end_mark)) + + def fetch_key(self): + + # Block context needs additional checks. + if not self.flow_level: + + # Are we allowed to start a key (not necessary a simple)? + if not self.allow_simple_key: + raise ScannerError(None, None, + "mapping keys are not allowed here", + self.get_mark()) + + # We may need to add BLOCK-MAPPING-START. + if self.add_indent(self.column): + mark = self.get_mark() + self.tokens.append(BlockMappingStartToken(mark, mark)) + + # Simple keys are allowed after '?' in the block context. + self.allow_simple_key = not self.flow_level + + # Reset possible simple key on the current level. + self.remove_possible_simple_key() + + # Add KEY. + start_mark = self.get_mark() + self.forward() + end_mark = self.get_mark() + self.tokens.append(KeyToken(start_mark, end_mark)) + + def fetch_value(self): + + # Do we determine a simple key? + if self.flow_level in self.possible_simple_keys: + + # Add KEY. + key = self.possible_simple_keys[self.flow_level] + del self.possible_simple_keys[self.flow_level] + self.tokens.insert(key.token_number-self.tokens_taken, + KeyToken(key.mark, key.mark)) + + # If this key starts a new block mapping, we need to add + # BLOCK-MAPPING-START. + if not self.flow_level: + if self.add_indent(key.column): + self.tokens.insert(key.token_number-self.tokens_taken, + BlockMappingStartToken(key.mark, key.mark)) + + # There cannot be two simple keys one after another. + self.allow_simple_key = False + + # It must be a part of a complex key. + else: + + # Block context needs additional checks. + # (Do we really need them? They will be caught by the parser + # anyway.) + if not self.flow_level: + + # We are allowed to start a complex value if and only if + # we can start a simple key. + if not self.allow_simple_key: + raise ScannerError(None, None, + "mapping values are not allowed here", + self.get_mark()) + + # If this value starts a new block mapping, we need to add + # BLOCK-MAPPING-START. It will be detected as an error later by + # the parser. + if not self.flow_level: + if self.add_indent(self.column): + mark = self.get_mark() + self.tokens.append(BlockMappingStartToken(mark, mark)) + + # Simple keys are allowed after ':' in the block context. + self.allow_simple_key = not self.flow_level + + # Reset possible simple key on the current level. + self.remove_possible_simple_key() + + # Add VALUE. + start_mark = self.get_mark() + self.forward() + end_mark = self.get_mark() + self.tokens.append(ValueToken(start_mark, end_mark)) + + def fetch_alias(self): + + # ALIAS could be a simple key. + self.save_possible_simple_key() + + # No simple keys after ALIAS. + self.allow_simple_key = False + + # Scan and add ALIAS. + self.tokens.append(self.scan_anchor(AliasToken)) + + def fetch_anchor(self): + + # ANCHOR could start a simple key. + self.save_possible_simple_key() + + # No simple keys after ANCHOR. + self.allow_simple_key = False + + # Scan and add ANCHOR. + self.tokens.append(self.scan_anchor(AnchorToken)) + + def fetch_tag(self): + + # TAG could start a simple key. + self.save_possible_simple_key() + + # No simple keys after TAG. + self.allow_simple_key = False + + # Scan and add TAG. + self.tokens.append(self.scan_tag()) + + def fetch_literal(self): + self.fetch_block_scalar(style='|') + + def fetch_folded(self): + self.fetch_block_scalar(style='>') + + def fetch_block_scalar(self, style): + + # A simple key may follow a block scalar. + self.allow_simple_key = True + + # Reset possible simple key on the current level. + self.remove_possible_simple_key() + + # Scan and add SCALAR. + self.tokens.append(self.scan_block_scalar(style)) + + def fetch_single(self): + self.fetch_flow_scalar(style='\'') + + def fetch_double(self): + self.fetch_flow_scalar(style='"') + + def fetch_flow_scalar(self, style): + + # A flow scalar could be a simple key. + self.save_possible_simple_key() + + # No simple keys after flow scalars. + self.allow_simple_key = False + + # Scan and add SCALAR. + self.tokens.append(self.scan_flow_scalar(style)) + + def fetch_plain(self): + + # A plain scalar could be a simple key. + self.save_possible_simple_key() + + # No simple keys after plain scalars. But note that `scan_plain` will + # change this flag if the scan is finished at the beginning of the + # line. + self.allow_simple_key = False + + # Scan and add SCALAR. May change `allow_simple_key`. + self.tokens.append(self.scan_plain()) + + # Checkers. + + def check_directive(self): + + # DIRECTIVE: ^ '%' ... + # The '%' indicator is already checked. + if self.column == 0: + return True + + def check_document_start(self): + + # DOCUMENT-START: ^ '---' (' '|'\n') + if self.column == 0: + if self.prefix(3) == '---' \ + and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': + return True + + def check_document_end(self): + + # DOCUMENT-END: ^ '...' (' '|'\n') + if self.column == 0: + if self.prefix(3) == '...' \ + and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': + return True + + def check_block_entry(self): + + # BLOCK-ENTRY: '-' (' '|'\n') + return self.peek(1) in '\0 \t\r\n\x85\u2028\u2029' + + def check_key(self): + + # KEY(flow context): '?' + if self.flow_level: + return True + + # KEY(block context): '?' (' '|'\n') + else: + return self.peek(1) in '\0 \t\r\n\x85\u2028\u2029' + + def check_value(self): + + # VALUE(flow context): ':' + if self.flow_level: + return True + + # VALUE(block context): ':' (' '|'\n') + else: + return self.peek(1) in '\0 \t\r\n\x85\u2028\u2029' + + def check_plain(self): + + # A plain scalar may start with any non-space character except: + # '-', '?', ':', ',', '[', ']', '{', '}', + # '#', '&', '*', '!', '|', '>', '\'', '\"', + # '%', '@', '`'. + # + # It may also start with + # '-', '?', ':' + # if it is followed by a non-space character. + # + # Note that we limit the last rule to the block context (except the + # '-' character) because we want the flow context to be space + # independent. + ch = self.peek() + return ch not in '\0 \t\r\n\x85\u2028\u2029-?:,[]{}#&*!|>\'\"%@`' \ + or (self.peek(1) not in '\0 \t\r\n\x85\u2028\u2029' + and (ch == '-' or (not self.flow_level and ch in '?:'))) + + # Scanners. + + def scan_to_next_token(self): + # We ignore spaces, line breaks and comments. + # If we find a line break in the block context, we set the flag + # `allow_simple_key` on. + # The byte order mark is stripped if it's the first character in the + # stream. We do not yet support BOM inside the stream as the + # specification requires. Any such mark will be considered as a part + # of the document. + # + # TODO: We need to make tab handling rules more sane. A good rule is + # Tabs cannot precede tokens + # BLOCK-SEQUENCE-START, BLOCK-MAPPING-START, BLOCK-END, + # KEY(block), VALUE(block), BLOCK-ENTRY + # So the checking code is + # if : + # self.allow_simple_keys = False + # We also need to add the check for `allow_simple_keys == True` to + # `unwind_indent` before issuing BLOCK-END. + # Scanners for block, flow, and plain scalars need to be modified. + + if self.index == 0 and self.peek() == '\uFEFF': + self.forward() + found = False + while not found: + while self.peek() == ' ': + self.forward() + if self.peek() == '#': + while self.peek() not in '\0\r\n\x85\u2028\u2029': + self.forward() + if self.scan_line_break(): + if not self.flow_level: + self.allow_simple_key = True + else: + found = True + + def scan_directive(self): + # See the specification for details. + start_mark = self.get_mark() + self.forward() + name = self.scan_directive_name(start_mark) + value = None + if name == 'YAML': + value = self.scan_yaml_directive_value(start_mark) + end_mark = self.get_mark() + elif name == 'TAG': + value = self.scan_tag_directive_value(start_mark) + end_mark = self.get_mark() + else: + end_mark = self.get_mark() + while self.peek() not in '\0\r\n\x85\u2028\u2029': + self.forward() + self.scan_directive_ignored_line(start_mark) + return DirectiveToken(name, value, start_mark, end_mark) + + def scan_directive_name(self, start_mark): + # See the specification for details. + length = 0 + ch = self.peek(length) + while '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ + or ch in '-_': + length += 1 + ch = self.peek(length) + if not length: + raise ScannerError("while scanning a directive", start_mark, + "expected alphabetic or numeric character, but found %r" + % ch, self.get_mark()) + value = self.prefix(length) + self.forward(length) + ch = self.peek() + if ch not in '\0 \r\n\x85\u2028\u2029': + raise ScannerError("while scanning a directive", start_mark, + "expected alphabetic or numeric character, but found %r" + % ch, self.get_mark()) + return value + + def scan_yaml_directive_value(self, start_mark): + # See the specification for details. + while self.peek() == ' ': + self.forward() + major = self.scan_yaml_directive_number(start_mark) + if self.peek() != '.': + raise ScannerError("while scanning a directive", start_mark, + "expected a digit or '.', but found %r" % self.peek(), + self.get_mark()) + self.forward() + minor = self.scan_yaml_directive_number(start_mark) + if self.peek() not in '\0 \r\n\x85\u2028\u2029': + raise ScannerError("while scanning a directive", start_mark, + "expected a digit or ' ', but found %r" % self.peek(), + self.get_mark()) + return (major, minor) + + def scan_yaml_directive_number(self, start_mark): + # See the specification for details. + ch = self.peek() + if not ('0' <= ch <= '9'): + raise ScannerError("while scanning a directive", start_mark, + "expected a digit, but found %r" % ch, self.get_mark()) + length = 0 + while '0' <= self.peek(length) <= '9': + length += 1 + value = int(self.prefix(length)) + self.forward(length) + return value + + def scan_tag_directive_value(self, start_mark): + # See the specification for details. + while self.peek() == ' ': + self.forward() + handle = self.scan_tag_directive_handle(start_mark) + while self.peek() == ' ': + self.forward() + prefix = self.scan_tag_directive_prefix(start_mark) + return (handle, prefix) + + def scan_tag_directive_handle(self, start_mark): + # See the specification for details. + value = self.scan_tag_handle('directive', start_mark) + ch = self.peek() + if ch != ' ': + raise ScannerError("while scanning a directive", start_mark, + "expected ' ', but found %r" % ch, self.get_mark()) + return value + + def scan_tag_directive_prefix(self, start_mark): + # See the specification for details. + value = self.scan_tag_uri('directive', start_mark) + ch = self.peek() + if ch not in '\0 \r\n\x85\u2028\u2029': + raise ScannerError("while scanning a directive", start_mark, + "expected ' ', but found %r" % ch, self.get_mark()) + return value + + def scan_directive_ignored_line(self, start_mark): + # See the specification for details. + while self.peek() == ' ': + self.forward() + if self.peek() == '#': + while self.peek() not in '\0\r\n\x85\u2028\u2029': + self.forward() + ch = self.peek() + if ch not in '\0\r\n\x85\u2028\u2029': + raise ScannerError("while scanning a directive", start_mark, + "expected a comment or a line break, but found %r" + % ch, self.get_mark()) + self.scan_line_break() + + def scan_anchor(self, TokenClass): + # The specification does not restrict characters for anchors and + # aliases. This may lead to problems, for instance, the document: + # [ *alias, value ] + # can be interpreted in two ways, as + # [ "value" ] + # and + # [ *alias , "value" ] + # Therefore we restrict aliases to numbers and ASCII letters. + start_mark = self.get_mark() + indicator = self.peek() + if indicator == '*': + name = 'alias' + else: + name = 'anchor' + self.forward() + length = 0 + ch = self.peek(length) + while '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ + or ch in '-_': + length += 1 + ch = self.peek(length) + if not length: + raise ScannerError("while scanning an %s" % name, start_mark, + "expected alphabetic or numeric character, but found %r" + % ch, self.get_mark()) + value = self.prefix(length) + self.forward(length) + ch = self.peek() + if ch not in '\0 \t\r\n\x85\u2028\u2029?:,]}%@`': + raise ScannerError("while scanning an %s" % name, start_mark, + "expected alphabetic or numeric character, but found %r" + % ch, self.get_mark()) + end_mark = self.get_mark() + return TokenClass(value, start_mark, end_mark) + + def scan_tag(self): + # See the specification for details. + start_mark = self.get_mark() + ch = self.peek(1) + if ch == '<': + handle = None + self.forward(2) + suffix = self.scan_tag_uri('tag', start_mark) + if self.peek() != '>': + raise ScannerError("while parsing a tag", start_mark, + "expected '>', but found %r" % self.peek(), + self.get_mark()) + self.forward() + elif ch in '\0 \t\r\n\x85\u2028\u2029': + handle = None + suffix = '!' + self.forward() + else: + length = 1 + use_handle = False + while ch not in '\0 \r\n\x85\u2028\u2029': + if ch == '!': + use_handle = True + break + length += 1 + ch = self.peek(length) + handle = '!' + if use_handle: + handle = self.scan_tag_handle('tag', start_mark) + else: + handle = '!' + self.forward() + suffix = self.scan_tag_uri('tag', start_mark) + ch = self.peek() + if ch not in '\0 \r\n\x85\u2028\u2029': + raise ScannerError("while scanning a tag", start_mark, + "expected ' ', but found %r" % ch, self.get_mark()) + value = (handle, suffix) + end_mark = self.get_mark() + return TagToken(value, start_mark, end_mark) + + def scan_block_scalar(self, style): + # See the specification for details. + + if style == '>': + folded = True + else: + folded = False + + chunks = [] + start_mark = self.get_mark() + + # Scan the header. + self.forward() + chomping, increment = self.scan_block_scalar_indicators(start_mark) + self.scan_block_scalar_ignored_line(start_mark) + + # Determine the indentation level and go to the first non-empty line. + min_indent = self.indent+1 + if min_indent < 1: + min_indent = 1 + if increment is None: + breaks, max_indent, end_mark = self.scan_block_scalar_indentation() + indent = max(min_indent, max_indent) + else: + indent = min_indent+increment-1 + breaks, end_mark = self.scan_block_scalar_breaks(indent) + line_break = '' + + # Scan the inner part of the block scalar. + while self.column == indent and self.peek() != '\0': + chunks.extend(breaks) + leading_non_space = self.peek() not in ' \t' + length = 0 + while self.peek(length) not in '\0\r\n\x85\u2028\u2029': + length += 1 + chunks.append(self.prefix(length)) + self.forward(length) + line_break = self.scan_line_break() + breaks, end_mark = self.scan_block_scalar_breaks(indent) + if self.column == indent and self.peek() != '\0': + + # Unfortunately, folding rules are ambiguous. + # + # This is the folding according to the specification: + + if folded and line_break == '\n' \ + and leading_non_space and self.peek() not in ' \t': + if not breaks: + chunks.append(' ') + else: + chunks.append(line_break) + + # This is Clark Evans's interpretation (also in the spec + # examples): + # + #if folded and line_break == '\n': + # if not breaks: + # if self.peek() not in ' \t': + # chunks.append(' ') + # else: + # chunks.append(line_break) + #else: + # chunks.append(line_break) + else: + break + + # Chomp the tail. + if chomping is not False: + chunks.append(line_break) + if chomping is True: + chunks.extend(breaks) + + # We are done. + return ScalarToken(''.join(chunks), False, start_mark, end_mark, + style) + + def scan_block_scalar_indicators(self, start_mark): + # See the specification for details. + chomping = None + increment = None + ch = self.peek() + if ch in '+-': + if ch == '+': + chomping = True + else: + chomping = False + self.forward() + ch = self.peek() + if ch in '0123456789': + increment = int(ch) + if increment == 0: + raise ScannerError("while scanning a block scalar", start_mark, + "expected indentation indicator in the range 1-9, but found 0", + self.get_mark()) + self.forward() + elif ch in '0123456789': + increment = int(ch) + if increment == 0: + raise ScannerError("while scanning a block scalar", start_mark, + "expected indentation indicator in the range 1-9, but found 0", + self.get_mark()) + self.forward() + ch = self.peek() + if ch in '+-': + if ch == '+': + chomping = True + else: + chomping = False + self.forward() + ch = self.peek() + if ch not in '\0 \r\n\x85\u2028\u2029': + raise ScannerError("while scanning a block scalar", start_mark, + "expected chomping or indentation indicators, but found %r" + % ch, self.get_mark()) + return chomping, increment + + def scan_block_scalar_ignored_line(self, start_mark): + # See the specification for details. + while self.peek() == ' ': + self.forward() + if self.peek() == '#': + while self.peek() not in '\0\r\n\x85\u2028\u2029': + self.forward() + ch = self.peek() + if ch not in '\0\r\n\x85\u2028\u2029': + raise ScannerError("while scanning a block scalar", start_mark, + "expected a comment or a line break, but found %r" % ch, + self.get_mark()) + self.scan_line_break() + + def scan_block_scalar_indentation(self): + # See the specification for details. + chunks = [] + max_indent = 0 + end_mark = self.get_mark() + while self.peek() in ' \r\n\x85\u2028\u2029': + if self.peek() != ' ': + chunks.append(self.scan_line_break()) + end_mark = self.get_mark() + else: + self.forward() + if self.column > max_indent: + max_indent = self.column + return chunks, max_indent, end_mark + + def scan_block_scalar_breaks(self, indent): + # See the specification for details. + chunks = [] + end_mark = self.get_mark() + while self.column < indent and self.peek() == ' ': + self.forward() + while self.peek() in '\r\n\x85\u2028\u2029': + chunks.append(self.scan_line_break()) + end_mark = self.get_mark() + while self.column < indent and self.peek() == ' ': + self.forward() + return chunks, end_mark + + def scan_flow_scalar(self, style): + # See the specification for details. + # Note that we loose indentation rules for quoted scalars. Quoted + # scalars don't need to adhere indentation because " and ' clearly + # mark the beginning and the end of them. Therefore we are less + # restrictive then the specification requires. We only need to check + # that document separators are not included in scalars. + if style == '"': + double = True + else: + double = False + chunks = [] + start_mark = self.get_mark() + quote = self.peek() + self.forward() + chunks.extend(self.scan_flow_scalar_non_spaces(double, start_mark)) + while self.peek() != quote: + chunks.extend(self.scan_flow_scalar_spaces(double, start_mark)) + chunks.extend(self.scan_flow_scalar_non_spaces(double, start_mark)) + self.forward() + end_mark = self.get_mark() + return ScalarToken(''.join(chunks), False, start_mark, end_mark, + style) + + ESCAPE_REPLACEMENTS = { + '0': '\0', + 'a': '\x07', + 'b': '\x08', + 't': '\x09', + '\t': '\x09', + 'n': '\x0A', + 'v': '\x0B', + 'f': '\x0C', + 'r': '\x0D', + 'e': '\x1B', + ' ': '\x20', + '\"': '\"', + '\\': '\\', + '/': '/', + 'N': '\x85', + '_': '\xA0', + 'L': '\u2028', + 'P': '\u2029', + } + + ESCAPE_CODES = { + 'x': 2, + 'u': 4, + 'U': 8, + } + + def scan_flow_scalar_non_spaces(self, double, start_mark): + # See the specification for details. + chunks = [] + while True: + length = 0 + while self.peek(length) not in '\'\"\\\0 \t\r\n\x85\u2028\u2029': + length += 1 + if length: + chunks.append(self.prefix(length)) + self.forward(length) + ch = self.peek() + if not double and ch == '\'' and self.peek(1) == '\'': + chunks.append('\'') + self.forward(2) + elif (double and ch == '\'') or (not double and ch in '\"\\'): + chunks.append(ch) + self.forward() + elif double and ch == '\\': + self.forward() + ch = self.peek() + if ch in self.ESCAPE_REPLACEMENTS: + chunks.append(self.ESCAPE_REPLACEMENTS[ch]) + self.forward() + elif ch in self.ESCAPE_CODES: + length = self.ESCAPE_CODES[ch] + self.forward() + for k in range(length): + if self.peek(k) not in '0123456789ABCDEFabcdef': + raise ScannerError("while scanning a double-quoted scalar", start_mark, + "expected escape sequence of %d hexadecimal numbers, but found %r" % + (length, self.peek(k)), self.get_mark()) + code = int(self.prefix(length), 16) + chunks.append(chr(code)) + self.forward(length) + elif ch in '\r\n\x85\u2028\u2029': + self.scan_line_break() + chunks.extend(self.scan_flow_scalar_breaks(double, start_mark)) + else: + raise ScannerError("while scanning a double-quoted scalar", start_mark, + "found unknown escape character %r" % ch, self.get_mark()) + else: + return chunks + + def scan_flow_scalar_spaces(self, double, start_mark): + # See the specification for details. + chunks = [] + length = 0 + while self.peek(length) in ' \t': + length += 1 + whitespaces = self.prefix(length) + self.forward(length) + ch = self.peek() + if ch == '\0': + raise ScannerError("while scanning a quoted scalar", start_mark, + "found unexpected end of stream", self.get_mark()) + elif ch in '\r\n\x85\u2028\u2029': + line_break = self.scan_line_break() + breaks = self.scan_flow_scalar_breaks(double, start_mark) + if line_break != '\n': + chunks.append(line_break) + elif not breaks: + chunks.append(' ') + chunks.extend(breaks) + else: + chunks.append(whitespaces) + return chunks + + def scan_flow_scalar_breaks(self, double, start_mark): + # See the specification for details. + chunks = [] + while True: + # Instead of checking indentation, we check for document + # separators. + prefix = self.prefix(3) + if (prefix == '---' or prefix == '...') \ + and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': + raise ScannerError("while scanning a quoted scalar", start_mark, + "found unexpected document separator", self.get_mark()) + while self.peek() in ' \t': + self.forward() + if self.peek() in '\r\n\x85\u2028\u2029': + chunks.append(self.scan_line_break()) + else: + return chunks + + def scan_plain(self): + # See the specification for details. + # We add an additional restriction for the flow context: + # plain scalars in the flow context cannot contain ',' or '?'. + # We also keep track of the `allow_simple_key` flag here. + # Indentation rules are loosed for the flow context. + chunks = [] + start_mark = self.get_mark() + end_mark = start_mark + indent = self.indent+1 + # We allow zero indentation for scalars, but then we need to check for + # document separators at the beginning of the line. + #if indent == 0: + # indent = 1 + spaces = [] + while True: + length = 0 + if self.peek() == '#': + break + while True: + ch = self.peek(length) + if ch in '\0 \t\r\n\x85\u2028\u2029' \ + or (ch == ':' and + self.peek(length+1) in '\0 \t\r\n\x85\u2028\u2029' + + (u',[]{}' if self.flow_level else u''))\ + or (self.flow_level and ch in ',?[]{}'): + break + length += 1 + if length == 0: + break + self.allow_simple_key = False + chunks.extend(spaces) + chunks.append(self.prefix(length)) + self.forward(length) + end_mark = self.get_mark() + spaces = self.scan_plain_spaces(indent, start_mark) + if not spaces or self.peek() == '#' \ + or (not self.flow_level and self.column < indent): + break + return ScalarToken(''.join(chunks), True, start_mark, end_mark) + + def scan_plain_spaces(self, indent, start_mark): + # See the specification for details. + # The specification is really confusing about tabs in plain scalars. + # We just forbid them completely. Do not use tabs in YAML! + chunks = [] + length = 0 + while self.peek(length) in ' ': + length += 1 + whitespaces = self.prefix(length) + self.forward(length) + ch = self.peek() + if ch in '\r\n\x85\u2028\u2029': + line_break = self.scan_line_break() + self.allow_simple_key = True + prefix = self.prefix(3) + if (prefix == '---' or prefix == '...') \ + and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': + return + breaks = [] + while self.peek() in ' \r\n\x85\u2028\u2029': + if self.peek() == ' ': + self.forward() + else: + breaks.append(self.scan_line_break()) + prefix = self.prefix(3) + if (prefix == '---' or prefix == '...') \ + and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': + return + if line_break != '\n': + chunks.append(line_break) + elif not breaks: + chunks.append(' ') + chunks.extend(breaks) + elif whitespaces: + chunks.append(whitespaces) + return chunks + + def scan_tag_handle(self, name, start_mark): + # See the specification for details. + # For some strange reasons, the specification does not allow '_' in + # tag handles. I have allowed it anyway. + ch = self.peek() + if ch != '!': + raise ScannerError("while scanning a %s" % name, start_mark, + "expected '!', but found %r" % ch, self.get_mark()) + length = 1 + ch = self.peek(length) + if ch != ' ': + while '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ + or ch in '-_': + length += 1 + ch = self.peek(length) + if ch != '!': + self.forward(length) + raise ScannerError("while scanning a %s" % name, start_mark, + "expected '!', but found %r" % ch, self.get_mark()) + length += 1 + value = self.prefix(length) + self.forward(length) + return value + + def scan_tag_uri(self, name, start_mark): + # See the specification for details. + # Note: we do not check if URI is well-formed. + chunks = [] + length = 0 + ch = self.peek(length) + while '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ + or ch in '-;/?:@&=+$,_.!~*\'()[]%': + if ch == '%': + chunks.append(self.prefix(length)) + self.forward(length) + length = 0 + chunks.append(self.scan_uri_escapes(name, start_mark)) + else: + length += 1 + ch = self.peek(length) + if length: + chunks.append(self.prefix(length)) + self.forward(length) + length = 0 + if not chunks: + raise ScannerError("while parsing a %s" % name, start_mark, + "expected URI, but found %r" % ch, self.get_mark()) + return ''.join(chunks) + + def scan_uri_escapes(self, name, start_mark): + # See the specification for details. + codes = [] + mark = self.get_mark() + while self.peek() == '%': + self.forward() + for k in range(2): + if self.peek(k) not in '0123456789ABCDEFabcdef': + raise ScannerError("while scanning a %s" % name, start_mark, + "expected URI escape sequence of 2 hexadecimal numbers, but found %r" + % self.peek(k), self.get_mark()) + codes.append(int(self.prefix(2), 16)) + self.forward(2) + try: + value = bytes(codes).decode('utf-8') + except UnicodeDecodeError as exc: + raise ScannerError("while scanning a %s" % name, start_mark, str(exc), mark) + return value + + def scan_line_break(self): + # Transforms: + # '\r\n' : '\n' + # '\r' : '\n' + # '\n' : '\n' + # '\x85' : '\n' + # '\u2028' : '\u2028' + # '\u2029 : '\u2029' + # default : '' + ch = self.peek() + if ch in '\r\n\x85': + if self.prefix(2) == '\r\n': + self.forward(2) + else: + self.forward() + return '\n' + elif ch in '\u2028\u2029': + self.forward() + return ch + return '' diff --git a/.venv/lib/python3.10/site-packages/yaml/serializer.py b/.venv/lib/python3.10/site-packages/yaml/serializer.py new file mode 100644 index 0000000..fe911e6 --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/serializer.py @@ -0,0 +1,111 @@ + +__all__ = ['Serializer', 'SerializerError'] + +from .error import YAMLError +from .events import * +from .nodes import * + +class SerializerError(YAMLError): + pass + +class Serializer: + + ANCHOR_TEMPLATE = 'id%03d' + + def __init__(self, encoding=None, + explicit_start=None, explicit_end=None, version=None, tags=None): + self.use_encoding = encoding + self.use_explicit_start = explicit_start + self.use_explicit_end = explicit_end + self.use_version = version + self.use_tags = tags + self.serialized_nodes = {} + self.anchors = {} + self.last_anchor_id = 0 + self.closed = None + + def open(self): + if self.closed is None: + self.emit(StreamStartEvent(encoding=self.use_encoding)) + self.closed = False + elif self.closed: + raise SerializerError("serializer is closed") + else: + raise SerializerError("serializer is already opened") + + def close(self): + if self.closed is None: + raise SerializerError("serializer is not opened") + elif not self.closed: + self.emit(StreamEndEvent()) + self.closed = True + + #def __del__(self): + # self.close() + + def serialize(self, node): + if self.closed is None: + raise SerializerError("serializer is not opened") + elif self.closed: + raise SerializerError("serializer is closed") + self.emit(DocumentStartEvent(explicit=self.use_explicit_start, + version=self.use_version, tags=self.use_tags)) + self.anchor_node(node) + self.serialize_node(node, None, None) + self.emit(DocumentEndEvent(explicit=self.use_explicit_end)) + self.serialized_nodes = {} + self.anchors = {} + self.last_anchor_id = 0 + + def anchor_node(self, node): + if node in self.anchors: + if self.anchors[node] is None: + self.anchors[node] = self.generate_anchor(node) + else: + self.anchors[node] = None + if isinstance(node, SequenceNode): + for item in node.value: + self.anchor_node(item) + elif isinstance(node, MappingNode): + for key, value in node.value: + self.anchor_node(key) + self.anchor_node(value) + + def generate_anchor(self, node): + self.last_anchor_id += 1 + return self.ANCHOR_TEMPLATE % self.last_anchor_id + + def serialize_node(self, node, parent, index): + alias = self.anchors[node] + if node in self.serialized_nodes: + self.emit(AliasEvent(alias)) + else: + self.serialized_nodes[node] = True + self.descend_resolver(parent, index) + if isinstance(node, ScalarNode): + detected_tag = self.resolve(ScalarNode, node.value, (True, False)) + default_tag = self.resolve(ScalarNode, node.value, (False, True)) + implicit = (node.tag == detected_tag), (node.tag == default_tag) + self.emit(ScalarEvent(alias, node.tag, implicit, node.value, + style=node.style)) + elif isinstance(node, SequenceNode): + implicit = (node.tag + == self.resolve(SequenceNode, node.value, True)) + self.emit(SequenceStartEvent(alias, node.tag, implicit, + flow_style=node.flow_style)) + index = 0 + for item in node.value: + self.serialize_node(item, node, index) + index += 1 + self.emit(SequenceEndEvent()) + elif isinstance(node, MappingNode): + implicit = (node.tag + == self.resolve(MappingNode, node.value, True)) + self.emit(MappingStartEvent(alias, node.tag, implicit, + flow_style=node.flow_style)) + for key, value in node.value: + self.serialize_node(key, node, None) + self.serialize_node(value, node, key) + self.emit(MappingEndEvent()) + self.ascend_resolver() + diff --git a/.venv/lib/python3.10/site-packages/yaml/tokens.py b/.venv/lib/python3.10/site-packages/yaml/tokens.py new file mode 100644 index 0000000..4d0b48a --- /dev/null +++ b/.venv/lib/python3.10/site-packages/yaml/tokens.py @@ -0,0 +1,104 @@ + +class Token(object): + def __init__(self, start_mark, end_mark): + self.start_mark = start_mark + self.end_mark = end_mark + def __repr__(self): + attributes = [key for key in self.__dict__ + if not key.endswith('_mark')] + attributes.sort() + arguments = ', '.join(['%s=%r' % (key, getattr(self, key)) + for key in attributes]) + return '%s(%s)' % (self.__class__.__name__, arguments) + +#class BOMToken(Token): +# id = '' + +class DirectiveToken(Token): + id = '' + def __init__(self, name, value, start_mark, end_mark): + self.name = name + self.value = value + self.start_mark = start_mark + self.end_mark = end_mark + +class DocumentStartToken(Token): + id = '' + +class DocumentEndToken(Token): + id = '' + +class StreamStartToken(Token): + id = '' + def __init__(self, start_mark=None, end_mark=None, + encoding=None): + self.start_mark = start_mark + self.end_mark = end_mark + self.encoding = encoding + +class StreamEndToken(Token): + id = '' + +class BlockSequenceStartToken(Token): + id = '' + +class BlockMappingStartToken(Token): + id = '' + +class BlockEndToken(Token): + id = '' + +class FlowSequenceStartToken(Token): + id = '[' + +class FlowMappingStartToken(Token): + id = '{' + +class FlowSequenceEndToken(Token): + id = ']' + +class FlowMappingEndToken(Token): + id = '}' + +class KeyToken(Token): + id = '?' + +class ValueToken(Token): + id = ':' + +class BlockEntryToken(Token): + id = '-' + +class FlowEntryToken(Token): + id = ',' + +class AliasToken(Token): + id = '' + def __init__(self, value, start_mark, end_mark): + self.value = value + self.start_mark = start_mark + self.end_mark = end_mark + +class AnchorToken(Token): + id = '' + def __init__(self, value, start_mark, end_mark): + self.value = value + self.start_mark = start_mark + self.end_mark = end_mark + +class TagToken(Token): + id = '' + def __init__(self, value, start_mark, end_mark): + self.value = value + self.start_mark = start_mark + self.end_mark = end_mark + +class ScalarToken(Token): + id = '' + def __init__(self, value, plain, start_mark, end_mark, style=None): + self.value = value + self.plain = plain + self.start_mark = start_mark + self.end_mark = end_mark + self.style = style + diff --git a/backend/api/migrations/0002_linkgroup_description.py b/backend/api/migrations/0002_linkgroup_description.py new file mode 100644 index 0000000..b2405c0 --- /dev/null +++ b/backend/api/migrations/0002_linkgroup_description.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2 on 2025-05-07 04:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='linkgroup', + name='description', + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/backend/api/migrations/0003_linkgroup_icon.py b/backend/api/migrations/0003_linkgroup_icon.py new file mode 100644 index 0000000..59a0ab2 --- /dev/null +++ b/backend/api/migrations/0003_linkgroup_icon.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2 on 2025-05-07 04:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0002_linkgroup_description'), + ] + + operations = [ + migrations.AddField( + model_name='linkgroup', + name='icon', + field=models.ImageField(blank=True, help_text='Иконка группы ссылок', null=True, upload_to='link_groups/'), + ), + ] diff --git a/backend/api/migrations/0004_linkgroup_created_at_linkgroup_is_favorite_and_more.py b/backend/api/migrations/0004_linkgroup_created_at_linkgroup_is_favorite_and_more.py new file mode 100644 index 0000000..c552ffd --- /dev/null +++ b/backend/api/migrations/0004_linkgroup_created_at_linkgroup_is_favorite_and_more.py @@ -0,0 +1,35 @@ +# Generated by Django 5.2 on 2025-05-07 05:00 + +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0003_linkgroup_icon'), + ] + + operations = [ + migrations.AddField( + model_name='linkgroup', + name='created_at', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name='linkgroup', + name='is_favorite', + field=models.BooleanField(default=False, help_text='Избранная группа ссылок'), + ), + migrations.AddField( + model_name='linkgroup', + name='is_public', + field=models.BooleanField(default=False, help_text='Публичная группа ссылок'), + ), + migrations.AddField( + model_name='linkgroup', + name='updated_at', + field=models.DateTimeField(auto_now=True), + ), + ] diff --git a/backend/api/migrations/0005_alter_link_icon_alter_linkgroup_is_favorite_and_more.py b/backend/api/migrations/0005_alter_link_icon_alter_linkgroup_is_favorite_and_more.py new file mode 100644 index 0000000..b68be26 --- /dev/null +++ b/backend/api/migrations/0005_alter_link_icon_alter_linkgroup_is_favorite_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 5.2 on 2025-05-07 05:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0004_linkgroup_created_at_linkgroup_is_favorite_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='link', + name='icon', + field=models.ImageField(blank=True, help_text='Иконка для этой ссылки', null=True, upload_to='links/'), + ), + migrations.AlterField( + model_name='linkgroup', + name='is_favorite', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='linkgroup', + name='is_public', + field=models.BooleanField(default=False), + ), + ] diff --git a/backend/api/models.py b/backend/api/models.py index 8765159..1c0863e 100644 --- a/backend/api/models.py +++ b/backend/api/models.py @@ -1,3 +1,5 @@ +# backend/api/models.py + from django.db import models from django.conf import settings @@ -5,13 +7,25 @@ class LinkGroup(models.Model): owner = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, - related_name='api_link_groups' # уникальное имя, чтобы не конфликтовать с links app + related_name='api_link_groups' ) name = models.CharField(max_length=100) order = models.PositiveIntegerField(default=0) + description = models.TextField(blank=True, null=True) + icon = models.ImageField( + upload_to='link_groups/', + null=True, + blank=True, + help_text='Иконка группы ссылок' + ) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + is_public = models.BooleanField(default=False) + is_favorite = models.BooleanField(default=False) def __str__(self): - return f"{self.owner.username} - {self.name}" + return f"{self.owner.username} — {self.name}" + class Link(models.Model): owner = models.ForeignKey( @@ -28,8 +42,13 @@ class Link(models.Model): ) title = models.CharField(max_length=200) url = models.URLField() - icon = models.URLField(blank=True, null=True) + icon = models.ImageField( + upload_to='links/', + null=True, + blank=True, + help_text='Иконка для этой ссылки' + ) order = models.PositiveIntegerField(default=0) def __str__(self): - return self.title \ No newline at end of file + return self.title diff --git a/backend/api/serializers.py b/backend/api/serializers.py index 71af5a8..0be3437 100644 --- a/backend/api/serializers.py +++ b/backend/api/serializers.py @@ -2,54 +2,47 @@ from rest_framework import serializers from django.contrib.auth import get_user_model from .models import Link, LinkGroup - +from django.conf import settings +from .models import Link, LinkGroup User = get_user_model() class RegisterSerializer(serializers.ModelSerializer): - password = serializers.CharField(write_only=True) - + password2 = serializers.CharField(write_only=True) class Meta: model = User - fields = ('username', 'email', 'password') + fields = ['username', 'email', 'first_name', 'last_name', 'password', 'password2'] + extra_kwargs = {'password': {'write_only': True}} + + def validate(self, attrs): + if attrs['password'] != attrs.pop('password2'): + raise serializers.ValidationError("Пароли не совпадают") + return attrs def create(self, validated_data): - user = User( - username=validated_data['username'], - email=validated_data.get('email', '') - ) - user.set_password(validated_data['password']) - user.save() - return user -# api/serializers.py -from rest_framework import serializers -from django.conf import settings -from .models import Link, LinkGroup + return User.objects.create_user(**validated_data) + + + # сериализатор для ссылок -class LinkSerializer(serializers.ModelSerializer): - class Meta: - model = Link - fields = ['id', 'title', 'url', 'icon', 'order', 'group'] - -# сериализатор для групп со вложенными ссылками -class LinkGroupSerializer(serializers.ModelSerializer): - # related_name у вас в модели LinkGroup.owner = 'api_link_groups', - # а у модели Link.group = 'links', так что у группы obj.links — это QuerySet ссылок - links = LinkSerializer(many=True, read_only=True) - - class Meta: - model = LinkGroup - fields = ['id', 'name', 'order', 'links'] - - - -from django.contrib.auth import get_user_model -from rest_framework import serializers - -User = get_user_model() - class UserSerializer(serializers.ModelSerializer): class Meta: model = User - # поля, которые хотите отдавать на фронт: fields = ['id', 'username', 'email', 'full_name', 'bio', 'avatar', 'last_login', 'date_joined'] + + +class LinkGroupSerializer(serializers.ModelSerializer): + icon = serializers.ImageField(required=False, allow_null=True) + class Meta: + model = LinkGroup + fields = ['id', 'name', 'description', 'icon', 'order', 'is_public', 'is_favorite', + 'created_at', 'updated_at'] + read_only_fields = ['id', 'created_at', 'updated_at'] + + +class LinkSerializer(serializers.ModelSerializer): + icon = serializers.ImageField(required=False, allow_null=True) + class Meta: + model = Link + fields = ['id', 'title', 'url', 'icon', 'group', 'order'] + read_only_fields = ['id'] \ No newline at end of file diff --git a/backend/api/urls.py b/backend/api/urls.py index 84b5a0a..03f19eb 100644 --- a/backend/api/urls.py +++ b/backend/api/urls.py @@ -4,9 +4,11 @@ from .views import ( RegisterView, UserProfileView, LinkViewSet, - LinkGroupViewSet + LinkGroupViewSet, + PublicUserGroupsView ) from rest_framework.routers import DefaultRouter +from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView router = DefaultRouter() router.register('links', LinkViewSet, basename='link') @@ -17,4 +19,17 @@ urlpatterns = [ path('auth/login/', TokenObtainPairView.as_view(), name='token_obtain_pair'), path('auth/refresh/', TokenRefreshView.as_view(), name='token_refresh'), path('auth/user/', UserProfileView.as_view(), name='user-profile'), # ← новый + path('users//public/', + PublicUserGroupsView.as_view(), + name='public-user-groups' + ), + # схема OpenAPI + path('schema/', SpectacularAPIView.as_view(), name='schema'), + # Swagger UI, берёт шаблон из drf_spectacular_sidecar + path( + 'swagger/', + SpectacularSwaggerView.as_view(url_name='schema'), + name='swagger-ui' + ), + ] + router.urls \ No newline at end of file diff --git a/backend/api/views.py b/backend/api/views.py index 4bb2c6d..f655d7d 100644 --- a/backend/api/views.py +++ b/backend/api/views.py @@ -1,32 +1,52 @@ -# api/views.py -from rest_framework import generics, viewsets, permissions -from django.contrib.auth import get_user_model +# coding: utf-8 +from rest_framework import generics, viewsets, permissions, status +from rest_framework.parsers import MultiPartParser, FormParser, JSONParser from rest_framework_simplejwt.views import TokenObtainPairView -from .serializers import RegisterSerializer, LinkSerializer, LinkGroupSerializer +from rest_framework.views import APIView +from rest_framework.response import Response +from django.shortcuts import get_object_or_404 +from drf_spectacular.utils import extend_schema, OpenApiParameter +from django.contrib.auth import get_user_model + from .models import Link, LinkGroup +from .serializers import ( + RegisterSerializer, + UserSerializer, + LinkSerializer, + LinkGroupSerializer, +) User = get_user_model() + class RegisterView(generics.CreateAPIView): queryset = User.objects.all() - permission_classes = (permissions.AllowAny,) + permission_classes = [permissions.AllowAny] serializer_class = RegisterSerializer + class LoginView(TokenObtainPairView): - permission_classes = (permissions.AllowAny,) + permission_classes = [permissions.AllowAny] + class LinkGroupViewSet(viewsets.ModelViewSet): queryset = LinkGroup.objects.all() serializer_class = LinkGroupSerializer permission_classes = [permissions.IsAuthenticated] + parser_classes = [MultiPartParser, FormParser, JSONParser] def get_queryset(self): - # возвращаем только группы текущего пользователя return self.queryset.filter(owner=self.request.user).order_by('order') + def perform_create(self, serializer): + serializer.save(owner=self.request.user) + + class LinkViewSet(viewsets.ModelViewSet): + queryset = Link.objects.all() serializer_class = LinkSerializer - permission_classes = (permissions.IsAuthenticated,) + permission_classes = [permissions.IsAuthenticated] + parser_classes = [MultiPartParser, FormParser, JSONParser] def get_queryset(self): return Link.objects.filter(owner=self.request.user).order_by('order') @@ -34,26 +54,66 @@ class LinkViewSet(viewsets.ModelViewSet): def perform_create(self, serializer): serializer.save(owner=self.request.user) + +class UserProfileView(generics.RetrieveAPIView): + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + def get_object(self): + return self.request.user + + class UserLinksListView(generics.ListAPIView): serializer_class = LinkSerializer - permission_classes = (permissions.AllowAny,) - + permission_classes = [permissions.AllowAny] def get_queryset(self): username = self.kwargs['username'] return Link.objects.filter(owner__username=username).order_by('order') - - -from .serializers import UserSerializer # нужно завести сериализатор для пользователя -User = get_user_model() -class UserProfileView(generics.RetrieveAPIView): +class PublicUserGroupsView(APIView): """ - Возвращает данные авторизованного пользователя. - GET /api/auth/user/ + GET /api/users/{username}/public/ """ - serializer_class = UserSerializer - permission_classes = [permissions.IsAuthenticated] + permission_classes = [permissions.AllowAny] - def get_object(self): - return self.request.user \ No newline at end of file + def get(self, request, username): + # 1. Ищем пользователя + user = get_object_or_404(User, username=username) + + # 2. Берём его группы со ссылками + groups_qs = LinkGroup.objects.filter(owner=user).prefetch_related('links') + + result = { + "username": user.username, + "groups": [] + } + + for grp in groups_qs: + # icon у группы (абсолютный URL) + grp_icon_url = None + if grp.icon: + grp_icon_url = request.build_absolute_uri(grp.icon.url) + + grp_data = { + "id": grp.id, + "name": grp.name, + "icon": grp_icon_url, + "links": [], + } + + for ln in grp.links.all(): + # icon у ссылки + ln_icon_url = None + if ln.icon: + ln_icon_url = request.build_absolute_uri(ln.icon.url) + + grp_data["links"].append({ + "id": ln.id, + "title": ln.title, + "url": ln.url, + "icon": ln_icon_url, + }) + + result["groups"].append(grp_data) + + return Response(result, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/backend/backend/settings.py b/backend/backend/settings.py index 7234939..8ed99f0 100644 --- a/backend/backend/settings.py +++ b/backend/backend/settings.py @@ -40,6 +40,8 @@ CORS_ALLOWED_ORIGINS = [ INSTALLED_APPS = [ "corsheaders", + 'drf_spectacular', + "drf_spectacular_sidecar", 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -52,6 +54,7 @@ INSTALLED_APPS = [ 'api', 'rest_framework', 'rest_framework_simplejwt', + 'django_extensions', ] MIDDLEWARE = [ @@ -91,6 +94,7 @@ REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticatedOrReadOnly', ), + 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', } from datetime import timedelta @@ -151,8 +155,10 @@ USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/5.2/howto/static-files/ -STATIC_URL = 'static/' +STATIC_ROOT = BASE_DIR / 'staticfiles' +# URL, по которому статика будет доступна +STATIC_URL = '/static/' # Default primary key field type # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field diff --git a/backend/backend/urls.py b/backend/backend/urls.py index 85a4f03..0f6228d 100644 --- a/backend/backend/urls.py +++ b/backend/backend/urls.py @@ -3,6 +3,7 @@ from django.urls import path, include from django.conf import settings from django.conf.urls.static import static + urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('api.urls')), # API endpoints diff --git a/backend/staticfiles/admin/css/autocomplete.css b/backend/staticfiles/admin/css/autocomplete.css new file mode 100644 index 0000000..7478c2c --- /dev/null +++ b/backend/staticfiles/admin/css/autocomplete.css @@ -0,0 +1,279 @@ +select.admin-autocomplete { + width: 20em; +} + +.select2-container--admin-autocomplete.select2-container { + min-height: 30px; +} + +.select2-container--admin-autocomplete .select2-selection--single, +.select2-container--admin-autocomplete .select2-selection--multiple { + min-height: 30px; + padding: 0; +} + +.select2-container--admin-autocomplete.select2-container--focus .select2-selection, +.select2-container--admin-autocomplete.select2-container--open .select2-selection { + border-color: var(--body-quiet-color); + min-height: 30px; +} + +.select2-container--admin-autocomplete.select2-container--focus .select2-selection.select2-selection--single, +.select2-container--admin-autocomplete.select2-container--open .select2-selection.select2-selection--single { + padding: 0; +} + +.select2-container--admin-autocomplete.select2-container--focus .select2-selection.select2-selection--multiple, +.select2-container--admin-autocomplete.select2-container--open .select2-selection.select2-selection--multiple { + padding: 0; +} + +.select2-container--admin-autocomplete .select2-selection--single { + background-color: var(--body-bg); + border: 1px solid var(--border-color); + border-radius: 4px; +} + +.select2-container--admin-autocomplete .select2-selection--single .select2-selection__rendered { + color: var(--body-fg); + line-height: 30px; +} + +.select2-container--admin-autocomplete .select2-selection--single .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; +} + +.select2-container--admin-autocomplete .select2-selection--single .select2-selection__placeholder { + color: var(--body-quiet-color); +} + +.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow { + height: 26px; + position: absolute; + top: 1px; + right: 1px; + width: 20px; +} + +.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow b { + border-color: #888 transparent transparent transparent; + border-style: solid; + border-width: 5px 4px 0 4px; + height: 0; + left: 50%; + margin-left: -4px; + margin-top: -2px; + position: absolute; + top: 50%; + width: 0; +} + +.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--single .select2-selection__clear { + float: left; +} + +.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--single .select2-selection__arrow { + left: 1px; + right: auto; +} + +.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--single { + background-color: var(--darkened-bg); + cursor: default; +} + +.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--single .select2-selection__clear { + display: none; +} + +.select2-container--admin-autocomplete.select2-container--open .select2-selection--single .select2-selection__arrow b { + border-color: transparent transparent #888 transparent; + border-width: 0 4px 5px 4px; +} + +.select2-container--admin-autocomplete .select2-selection--multiple { + background-color: var(--body-bg); + border: 1px solid var(--border-color); + border-radius: 4px; + cursor: text; +} + +.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered { + box-sizing: border-box; + list-style: none; + margin: 0; + padding: 0 10px 5px 5px; + width: 100%; + display: flex; + flex-wrap: wrap; +} + +.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered li { + list-style: none; +} + +.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__placeholder { + color: var(--body-quiet-color); + margin-top: 5px; + float: left; +} + +.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; + margin: 5px; + position: absolute; + right: 0; +} + +.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice { + background-color: var(--darkened-bg); + border: 1px solid var(--border-color); + border-radius: 4px; + cursor: default; + float: left; + margin-right: 5px; + margin-top: 5px; + padding: 0 5px; +} + +.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove { + color: var(--body-quiet-color); + cursor: pointer; + display: inline-block; + font-weight: bold; + margin-right: 2px; +} + +.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove:hover { + color: var(--body-fg); +} + +.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-search--inline { + float: right; +} + +.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice { + margin-left: 5px; + margin-right: auto; +} + +.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { + margin-left: 2px; + margin-right: auto; +} + +.select2-container--admin-autocomplete.select2-container--focus .select2-selection--multiple { + border: solid var(--body-quiet-color) 1px; + outline: 0; +} + +.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--multiple { + background-color: var(--darkened-bg); + cursor: default; +} + +.select2-container--admin-autocomplete.select2-container--disabled .select2-selection__choice__remove { + display: none; +} + +.select2-container--admin-autocomplete.select2-container--open.select2-container--above .select2-selection--single, .select2-container--admin-autocomplete.select2-container--open.select2-container--above .select2-selection--multiple { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.select2-container--admin-autocomplete.select2-container--open.select2-container--below .select2-selection--single, .select2-container--admin-autocomplete.select2-container--open.select2-container--below .select2-selection--multiple { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +.select2-container--admin-autocomplete .select2-search--dropdown { + background: var(--darkened-bg); +} + +.select2-container--admin-autocomplete .select2-search--dropdown .select2-search__field { + background: var(--body-bg); + color: var(--body-fg); + border: 1px solid var(--border-color); + border-radius: 4px; +} + +.select2-container--admin-autocomplete .select2-search--inline .select2-search__field { + background: transparent; + color: var(--body-fg); + border: none; + outline: 0; + box-shadow: none; + -webkit-appearance: textfield; +} + +.select2-container--admin-autocomplete .select2-results > .select2-results__options { + max-height: 200px; + overflow-y: auto; + color: var(--body-fg); + background: var(--body-bg); +} + +.select2-container--admin-autocomplete .select2-results__option[role=group] { + padding: 0; +} + +.select2-container--admin-autocomplete .select2-results__option[aria-disabled=true] { + color: var(--body-quiet-color); +} + +.select2-container--admin-autocomplete .select2-results__option[aria-selected=true] { + background-color: var(--selected-bg); + color: var(--body-fg); +} + +.select2-container--admin-autocomplete .select2-results__option .select2-results__option { + padding-left: 1em; +} + +.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__group { + padding-left: 0; +} + +.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option { + margin-left: -1em; + padding-left: 2em; +} + +.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -2em; + padding-left: 3em; +} + +.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -3em; + padding-left: 4em; +} + +.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -4em; + padding-left: 5em; +} + +.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -5em; + padding-left: 6em; +} + +.select2-container--admin-autocomplete .select2-results__option--highlighted[aria-selected] { + background-color: var(--primary); + color: var(--primary-fg); +} + +.select2-container--admin-autocomplete .select2-results__group { + cursor: default; + display: block; + padding: 6px; +} + +.errors .select2-selection { + border: 1px solid var(--error-fg); +} diff --git a/backend/staticfiles/admin/css/base.css b/backend/staticfiles/admin/css/base.css new file mode 100644 index 0000000..4f47732 --- /dev/null +++ b/backend/staticfiles/admin/css/base.css @@ -0,0 +1,1183 @@ +/* + DJANGO Admin styles +*/ + +/* VARIABLE DEFINITIONS */ +html[data-theme="light"], +:root { + --primary: #79aec8; + --secondary: #417690; + --accent: #f5dd5d; + --primary-fg: #fff; + + --body-fg: #333; + --body-bg: #fff; + --body-quiet-color: #666; + --body-medium-color: #444; + --body-loud-color: #000; + + --header-color: #ffc; + --header-branding-color: var(--accent); + --header-bg: var(--secondary); + --header-link-color: var(--primary-fg); + + --breadcrumbs-fg: #c4dce8; + --breadcrumbs-link-fg: var(--body-bg); + --breadcrumbs-bg: #264b5d; + + --link-fg: #417893; + --link-hover-color: #036; + --link-selected-fg: var(--secondary); + + --hairline-color: #e8e8e8; + --border-color: #ccc; + + --error-fg: #ba2121; + + --message-success-bg: #dfd; + --message-warning-bg: #ffc; + --message-error-bg: #ffefef; + + --darkened-bg: #f8f8f8; /* A bit darker than --body-bg */ + --selected-bg: #e4e4e4; /* E.g. selected table cells */ + --selected-row: #ffc; + + --button-fg: #fff; + --button-bg: var(--secondary); + --button-hover-bg: #205067; + --default-button-bg: #205067; + --default-button-hover-bg: var(--secondary); + --close-button-bg: #747474; + --close-button-hover-bg: #333; + --delete-button-bg: #ba2121; + --delete-button-hover-bg: #a41515; + + --object-tools-fg: var(--button-fg); + --object-tools-bg: var(--close-button-bg); + --object-tools-hover-bg: var(--close-button-hover-bg); + + --font-family-primary: + "Segoe UI", + system-ui, + Roboto, + "Helvetica Neue", + Arial, + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + "Segoe UI Symbol", + "Noto Color Emoji"; + --font-family-monospace: + ui-monospace, + Menlo, + Monaco, + "Cascadia Mono", + "Segoe UI Mono", + "Roboto Mono", + "Oxygen Mono", + "Ubuntu Monospace", + "Source Code Pro", + "Fira Mono", + "Droid Sans Mono", + "Courier New", + monospace, + "Apple Color Emoji", + "Segoe UI Emoji", + "Segoe UI Symbol", + "Noto Color Emoji"; + + color-scheme: light; +} + +html, body { + height: 100%; +} + +body { + margin: 0; + padding: 0; + font-size: 0.875rem; + font-family: var(--font-family-primary); + color: var(--body-fg); + background: var(--body-bg); +} + +/* LINKS */ + +a:link, a:visited { + color: var(--link-fg); + text-decoration: none; + transition: color 0.15s, background 0.15s; +} + +a:focus, a:hover { + color: var(--link-hover-color); +} + +a:focus { + text-decoration: underline; +} + +a img { + border: none; +} + +a.section:link, a.section:visited { + color: var(--header-link-color); + text-decoration: none; +} + +a.section:focus, a.section:hover { + text-decoration: underline; +} + +/* GLOBAL DEFAULTS */ + +p, ol, ul, dl { + margin: .2em 0 .8em 0; +} + +p { + padding: 0; + line-height: 140%; +} + +h1,h2,h3,h4,h5 { + font-weight: bold; +} + +h1 { + margin: 0 0 20px; + font-weight: 300; + font-size: 1.25rem; +} + +h2 { + font-size: 1rem; + margin: 1em 0 .5em 0; +} + +h2.subhead { + font-weight: normal; + margin-top: 0; +} + +h3 { + font-size: 0.875rem; + margin: .8em 0 .3em 0; + color: var(--body-medium-color); + font-weight: bold; +} + +h4 { + font-size: 0.75rem; + margin: 1em 0 .8em 0; + padding-bottom: 3px; + color: var(--body-medium-color); +} + +h5 { + font-size: 0.625rem; + margin: 1.5em 0 .5em 0; + color: var(--body-quiet-color); + text-transform: uppercase; + letter-spacing: 1px; +} + +ul > li { + list-style-type: square; + padding: 1px 0; +} + +li ul { + margin-bottom: 0; +} + +li, dt, dd { + font-size: 0.8125rem; + line-height: 1.25rem; +} + +dt { + font-weight: bold; + margin-top: 4px; +} + +dd { + margin-left: 0; +} + +form { + margin: 0; + padding: 0; +} + +fieldset { + margin: 0; + min-width: 0; + padding: 0; + border: none; + border-top: 1px solid var(--hairline-color); +} + +details summary { + cursor: pointer; +} + +blockquote { + font-size: 0.6875rem; + color: #777; + margin-left: 2px; + padding-left: 10px; + border-left: 5px solid #ddd; +} + +code, pre { + font-family: var(--font-family-monospace); + color: var(--body-quiet-color); + font-size: 0.75rem; + overflow-x: auto; +} + +pre.literal-block { + margin: 10px; + background: var(--darkened-bg); + padding: 6px 8px; +} + +code strong { + color: #930; +} + +hr { + clear: both; + color: var(--hairline-color); + background-color: var(--hairline-color); + height: 1px; + border: none; + margin: 0; + padding: 0; + line-height: 1px; +} + +/* TEXT STYLES & MODIFIERS */ + +.small { + font-size: 0.6875rem; +} + +.mini { + font-size: 0.625rem; +} + +.help, p.help, form p.help, div.help, form div.help, div.help li { + font-size: 0.6875rem; + color: var(--body-quiet-color); +} + +div.help ul { + margin-bottom: 0; +} + +.help-tooltip { + cursor: help; +} + +p img, h1 img, h2 img, h3 img, h4 img, td img { + vertical-align: middle; +} + +.quiet, a.quiet:link, a.quiet:visited { + color: var(--body-quiet-color); + font-weight: normal; +} + +.clear { + clear: both; +} + +.nowrap { + white-space: nowrap; +} + +.hidden { + display: none !important; +} + +/* TABLES */ + +table { + border-collapse: collapse; + border-color: var(--border-color); +} + +td, th { + font-size: 0.8125rem; + line-height: 1rem; + border-bottom: 1px solid var(--hairline-color); + vertical-align: top; + padding: 8px; +} + +th { + font-weight: 500; + text-align: left; +} + +thead th, +tfoot td { + color: var(--body-quiet-color); + padding: 5px 10px; + font-size: 0.6875rem; + background: var(--body-bg); + border: none; + border-top: 1px solid var(--hairline-color); + border-bottom: 1px solid var(--hairline-color); +} + +tfoot td { + border-bottom: none; + border-top: 1px solid var(--hairline-color); +} + +thead th.required { + font-weight: bold; +} + +tr.alt { + background: var(--darkened-bg); +} + +tr:nth-child(odd), .row-form-errors { + background: var(--body-bg); +} + +tr:nth-child(even), +tr:nth-child(even) .errorlist, +tr:nth-child(odd) + .row-form-errors, +tr:nth-child(odd) + .row-form-errors .errorlist { + background: var(--darkened-bg); +} + +/* SORTABLE TABLES */ + +thead th { + padding: 5px 10px; + line-height: normal; + text-transform: uppercase; + background: var(--darkened-bg); +} + +thead th a:link, thead th a:visited { + color: var(--body-quiet-color); +} + +thead th.sorted { + background: var(--selected-bg); +} + +thead th.sorted .text { + padding-right: 42px; +} + +table thead th .text span { + padding: 8px 10px; + display: block; +} + +table thead th .text a { + display: block; + cursor: pointer; + padding: 8px 10px; +} + +table thead th .text a:focus, table thead th .text a:hover { + background: var(--selected-bg); +} + +thead th.sorted a.sortremove { + visibility: hidden; +} + +table thead th.sorted:hover a.sortremove { + visibility: visible; +} + +table thead th.sorted .sortoptions { + display: block; + padding: 9px 5px 0 5px; + float: right; + text-align: right; +} + +table thead th.sorted .sortpriority { + font-size: .8em; + min-width: 12px; + text-align: center; + vertical-align: 3px; + margin-left: 2px; + margin-right: 2px; +} + +table thead th.sorted .sortoptions a { + position: relative; + width: 14px; + height: 14px; + display: inline-block; + background: url(../img/sorting-icons.svg) 0 0 no-repeat; + background-size: 14px auto; +} + +table thead th.sorted .sortoptions a.sortremove { + background-position: 0 0; +} + +table thead th.sorted .sortoptions a.sortremove:after { + content: '\\'; + position: absolute; + top: -6px; + left: 3px; + font-weight: 200; + font-size: 1.125rem; + color: var(--body-quiet-color); +} + +table thead th.sorted .sortoptions a.sortremove:focus:after, +table thead th.sorted .sortoptions a.sortremove:hover:after { + color: var(--link-fg); +} + +table thead th.sorted .sortoptions a.sortremove:focus, +table thead th.sorted .sortoptions a.sortremove:hover { + background-position: 0 -14px; +} + +table thead th.sorted .sortoptions a.ascending { + background-position: 0 -28px; +} + +table thead th.sorted .sortoptions a.ascending:focus, +table thead th.sorted .sortoptions a.ascending:hover { + background-position: 0 -42px; +} + +table thead th.sorted .sortoptions a.descending { + top: 1px; + background-position: 0 -56px; +} + +table thead th.sorted .sortoptions a.descending:focus, +table thead th.sorted .sortoptions a.descending:hover { + background-position: 0 -70px; +} + +/* FORM DEFAULTS */ + +input, textarea, select, .form-row p, form .button { + margin: 2px 0; + padding: 2px 3px; + vertical-align: middle; + font-family: var(--font-family-primary); + font-weight: normal; + font-size: 0.8125rem; +} +.form-row div.help { + padding: 2px 3px; +} + +textarea { + vertical-align: top; +} + +/* +Minifiers remove the default (text) "type" attribute from "input" HTML tags. +Add input:not([type]) to make the CSS stylesheet work the same. +*/ +input:not([type]), input[type=text], input[type=password], input[type=email], +input[type=url], input[type=number], input[type=tel], textarea, select, +.vTextField { + border: 1px solid var(--border-color); + border-radius: 4px; + padding: 5px 6px; + margin-top: 0; + color: var(--body-fg); + background-color: var(--body-bg); +} + +/* +Minifiers remove the default (text) "type" attribute from "input" HTML tags. +Add input:not([type]) to make the CSS stylesheet work the same. +*/ +input:not([type]):focus, input[type=text]:focus, input[type=password]:focus, +input[type=email]:focus, input[type=url]:focus, input[type=number]:focus, +input[type=tel]:focus, textarea:focus, select:focus, .vTextField:focus { + border-color: var(--body-quiet-color); +} + +select { + height: 1.875rem; +} + +select[multiple] { + /* Allow HTML size attribute to override the height in the rule above. */ + height: auto; + min-height: 150px; +} + +/* FORM BUTTONS */ + +.button, input[type=submit], input[type=button], .submit-row input, a.button { + background: var(--button-bg); + padding: 10px 15px; + border: none; + border-radius: 4px; + color: var(--button-fg); + cursor: pointer; + transition: background 0.15s; +} + +a.button { + padding: 4px 5px; +} + +.button:active, input[type=submit]:active, input[type=button]:active, +.button:focus, input[type=submit]:focus, input[type=button]:focus, +.button:hover, input[type=submit]:hover, input[type=button]:hover { + background: var(--button-hover-bg); +} + +.button[disabled], input[type=submit][disabled], input[type=button][disabled] { + opacity: 0.4; +} + +.button.default, input[type=submit].default, .submit-row input.default { + border: none; + font-weight: 400; + background: var(--default-button-bg); +} + +.button.default:active, input[type=submit].default:active, +.button.default:focus, input[type=submit].default:focus, +.button.default:hover, input[type=submit].default:hover { + background: var(--default-button-hover-bg); +} + +.button[disabled].default, +input[type=submit][disabled].default, +input[type=button][disabled].default { + opacity: 0.4; +} + + +/* MODULES */ + +.module { + border: none; + margin-bottom: 30px; + background: var(--body-bg); +} + +.module p, .module ul, .module h3, .module h4, .module dl, .module pre { + padding-left: 10px; + padding-right: 10px; +} + +.module blockquote { + margin-left: 12px; +} + +.module ul, .module ol { + margin-left: 1.5em; +} + +.module h3 { + margin-top: .6em; +} + +.module h2, .module caption, .inline-group h2 { + margin: 0; + padding: 8px; + font-weight: 400; + font-size: 0.8125rem; + text-align: left; + background: var(--header-bg); + color: var(--header-link-color); +} + +.module caption, +.inline-group h2 { + font-size: 0.75rem; + letter-spacing: 0.5px; + text-transform: uppercase; +} + +.module table { + border-collapse: collapse; +} + +/* MESSAGES & ERRORS */ + +ul.messagelist { + padding: 0; + margin: 0; +} + +ul.messagelist li { + display: block; + font-weight: 400; + font-size: 0.8125rem; + padding: 10px 10px 10px 65px; + margin: 0 0 10px 0; + background: var(--message-success-bg) url(../img/icon-yes.svg) 40px 12px no-repeat; + background-size: 16px auto; + color: var(--body-fg); + word-break: break-word; +} + +ul.messagelist li.warning { + background: var(--message-warning-bg) url(../img/icon-alert.svg) 40px 14px no-repeat; + background-size: 14px auto; +} + +ul.messagelist li.error { + background: var(--message-error-bg) url(../img/icon-no.svg) 40px 12px no-repeat; + background-size: 16px auto; +} + +.errornote { + font-size: 0.875rem; + font-weight: 700; + display: block; + padding: 10px 12px; + margin: 0 0 10px 0; + color: var(--error-fg); + border: 1px solid var(--error-fg); + border-radius: 4px; + background-color: var(--body-bg); + background-position: 5px 12px; + overflow-wrap: break-word; +} + +ul.errorlist { + margin: 0 0 4px; + padding: 0; + color: var(--error-fg); + background: var(--body-bg); +} + +ul.errorlist li { + font-size: 0.8125rem; + display: block; + margin-bottom: 4px; + overflow-wrap: break-word; +} + +ul.errorlist li:first-child { + margin-top: 0; +} + +ul.errorlist li a { + color: inherit; + text-decoration: underline; +} + +td ul.errorlist { + margin: 0; + padding: 0; +} + +td ul.errorlist li { + margin: 0; +} + +.form-row.errors { + margin: 0; + border: none; + border-bottom: 1px solid var(--hairline-color); + background: none; +} + +.form-row.errors ul.errorlist li { + padding-left: 0; +} + +.errors input, .errors select, .errors textarea, +td ul.errorlist + input, td ul.errorlist + select, td ul.errorlist + textarea { + border: 1px solid var(--error-fg); +} + +.description { + font-size: 0.75rem; + padding: 5px 0 0 12px; +} + +/* BREADCRUMBS */ + +div.breadcrumbs { + background: var(--breadcrumbs-bg); + padding: 10px 40px; + border: none; + color: var(--breadcrumbs-fg); + text-align: left; +} + +div.breadcrumbs a { + color: var(--breadcrumbs-link-fg); +} + +div.breadcrumbs a:focus, div.breadcrumbs a:hover { + color: var(--breadcrumbs-fg); +} + +/* ACTION ICONS */ + +.viewlink, .inlineviewlink { + padding-left: 16px; + background: url(../img/icon-viewlink.svg) 0 1px no-repeat; +} + +.hidelink { + padding-left: 16px; + background: url(../img/icon-hidelink.svg) 0 1px no-repeat; +} + +.addlink { + padding-left: 16px; + background: url(../img/icon-addlink.svg) 0 1px no-repeat; +} + +.changelink, .inlinechangelink { + padding-left: 16px; + background: url(../img/icon-changelink.svg) 0 1px no-repeat; +} + +.deletelink { + padding-left: 16px; + background: url(../img/icon-deletelink.svg) 0 1px no-repeat; +} + +a.deletelink:link, a.deletelink:visited { + color: #CC3434; /* XXX Probably unused? */ +} + +a.deletelink:focus, a.deletelink:hover { + color: #993333; /* XXX Probably unused? */ + text-decoration: none; +} + +/* OBJECT TOOLS */ + +.object-tools { + font-size: 0.625rem; + font-weight: bold; + padding-left: 0; + float: right; + position: relative; +} + +.object-tools li { + display: block; + float: left; + margin-left: 5px; + height: 1rem; +} + +.object-tools a { + border-radius: 15px; +} + +.object-tools a:link, .object-tools a:visited { + display: block; + float: left; + padding: 3px 12px; + background: var(--object-tools-bg); + color: var(--object-tools-fg); + font-weight: 400; + font-size: 0.6875rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.object-tools a:focus, .object-tools a:hover { + background-color: var(--object-tools-hover-bg); +} + +.object-tools a:focus{ + text-decoration: none; +} + +.object-tools a.viewsitelink, .object-tools a.addlink { + background-repeat: no-repeat; + background-position: right 7px center; + padding-right: 26px; +} + +.object-tools a.viewsitelink { + background-image: url(../img/tooltag-arrowright.svg); +} + +.object-tools a.addlink { + background-image: url(../img/tooltag-add.svg); +} + +.object-tools:has(a.addlink) { + margin-top: -48px; +} + +/* OBJECT HISTORY */ + +#change-history table { + width: 100%; +} + +#change-history table tbody th { + width: 16em; +} + +#change-history .paginator { + color: var(--body-quiet-color); + border-bottom: 1px solid var(--hairline-color); + background: var(--body-bg); + overflow: hidden; +} + +/* PAGE STRUCTURE */ + +#container { + position: relative; + width: 100%; + min-width: 980px; + padding: 0; + display: flex; + flex-direction: column; + height: 100%; +} + +#container > .main { + display: flex; + flex: 1 0 auto; +} + +.main > .content { + flex: 1 0; + max-width: 100%; +} + +.skip-to-content-link { + position: absolute; + top: -999px; + margin: 5px; + padding: 5px; + background: var(--body-bg); + z-index: 1; +} + +.skip-to-content-link:focus { + left: 0px; + top: 0px; +} + +#content { + padding: 20px 40px; +} + +.dashboard #content { + width: 600px; +} + +#content-main { + float: left; + width: 100%; +} + +#content-related { + float: right; + width: 260px; + position: relative; + margin-right: -300px; +} + +@media (forced-colors: active) { + #content-related { + border: 1px solid; + } +} + +/* COLUMN TYPES */ + +.colMS { + margin-right: 300px; +} + +.colSM { + margin-left: 300px; +} + +.colSM #content-related { + float: left; + margin-right: 0; + margin-left: -300px; +} + +.colSM #content-main { + float: right; +} + +.popup .colM { + width: auto; +} + +/* HEADER */ + +#header { + width: auto; + height: auto; + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px 40px; + background: var(--header-bg); + color: var(--header-color); +} + +#header a:link, #header a:visited, #logout-form button { + color: var(--header-link-color); +} + +#header a:focus , #header a:hover { + text-decoration: underline; +} + +@media (forced-colors: active) { + #header { + border-bottom: 1px solid; + } +} + +#branding { + display: flex; +} + +#site-name { + padding: 0; + margin: 0; + margin-inline-end: 20px; + font-weight: 300; + font-size: 1.5rem; + color: var(--header-branding-color); +} + +#site-name a:link, #site-name a:visited { + color: var(--accent); +} + +#branding h2 { + padding: 0 10px; + font-size: 0.875rem; + margin: -8px 0 8px 0; + font-weight: normal; + color: var(--header-color); +} + +#branding a:hover { + text-decoration: none; +} + +#logout-form { + display: inline; +} + +#logout-form button { + background: none; + border: 0; + cursor: pointer; + font-family: var(--font-family-primary); +} + +#user-tools { + float: right; + margin: 0 0 0 20px; + text-align: right; +} + +#user-tools, #logout-form button{ + padding: 0; + font-weight: 300; + font-size: 0.6875rem; + letter-spacing: 0.5px; + text-transform: uppercase; +} + +#user-tools a, #logout-form button { + border-bottom: 1px solid rgba(255, 255, 255, 0.25); +} + +#user-tools a:focus, #user-tools a:hover, +#logout-form button:active, #logout-form button:hover { + text-decoration: none; + border-bottom: 0; +} + +#logout-form button:active, #logout-form button:hover { + margin-bottom: 1px; +} + +/* SIDEBAR */ + +#content-related { + background: var(--darkened-bg); +} + +#content-related .module { + background: none; +} + +#content-related h3 { + color: var(--body-quiet-color); + padding: 0 16px; + margin: 0 0 16px; +} + +#content-related h4 { + font-size: 0.8125rem; +} + +#content-related p { + padding-left: 16px; + padding-right: 16px; +} + +#content-related .actionlist { + padding: 0; + margin: 16px; +} + +#content-related .actionlist li { + line-height: 1.2; + margin-bottom: 10px; + padding-left: 18px; +} + +#content-related .module h2 { + background: none; + padding: 16px; + margin-bottom: 16px; + border-bottom: 1px solid var(--hairline-color); + font-size: 1.125rem; + color: var(--body-fg); +} + +.delete-confirmation form input[type="submit"] { + background: var(--delete-button-bg); + border-radius: 4px; + padding: 10px 15px; + color: var(--button-fg); +} + +.delete-confirmation form input[type="submit"]:active, +.delete-confirmation form input[type="submit"]:focus, +.delete-confirmation form input[type="submit"]:hover { + background: var(--delete-button-hover-bg); +} + +.delete-confirmation form .cancel-link { + display: inline-block; + vertical-align: middle; + height: 0.9375rem; + line-height: 0.9375rem; + border-radius: 4px; + padding: 10px 15px; + color: var(--button-fg); + background: var(--close-button-bg); + margin: 0 0 0 10px; +} + +.delete-confirmation form .cancel-link:active, +.delete-confirmation form .cancel-link:focus, +.delete-confirmation form .cancel-link:hover { + background: var(--close-button-hover-bg); +} + +/* POPUP */ +.popup #content { + padding: 20px; +} + +.popup #container { + min-width: 0; +} + +.popup #header { + padding: 10px 20px; +} + +/* PAGINATOR */ + +.paginator { + display: flex; + align-items: center; + gap: 4px; + font-size: 0.8125rem; + padding-top: 10px; + padding-bottom: 10px; + line-height: 22px; + margin: 0; + border-top: 1px solid var(--hairline-color); + width: 100%; + box-sizing: border-box; +} + +.paginator a:link, .paginator a:visited { + padding: 2px 6px; + background: var(--button-bg); + text-decoration: none; + color: var(--button-fg); +} + +.paginator a.showall { + border: none; + background: none; + color: var(--link-fg); +} + +.paginator a.showall:focus, .paginator a.showall:hover { + background: none; + color: var(--link-hover-color); +} + +.paginator .end { + margin-right: 6px; +} + +.paginator .this-page { + padding: 2px 6px; + font-weight: bold; + font-size: 0.8125rem; + vertical-align: top; +} + +.paginator a:focus, .paginator a:hover { + color: white; + background: var(--link-hover-color); +} + +.paginator input { + margin-left: auto; +} + +.base-svgs { + display: none; +} + +.visually-hidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + overflow: hidden; + clip: rect(0,0,0,0); + white-space: nowrap; + border: 0; + color: var(--body-fg); + background-color: var(--body-bg); +} diff --git a/backend/staticfiles/admin/css/changelists.css b/backend/staticfiles/admin/css/changelists.css new file mode 100644 index 0000000..005b776 --- /dev/null +++ b/backend/staticfiles/admin/css/changelists.css @@ -0,0 +1,343 @@ +/* CHANGELISTS */ + +#changelist { + display: flex; + align-items: flex-start; + justify-content: space-between; +} + +#changelist .changelist-form-container { + flex: 1 1 auto; + min-width: 0; +} + +#changelist table { + width: 100%; +} + +.change-list .hiddenfields { display:none; } + +.change-list .filtered table { + border-right: none; +} + +.change-list .filtered { + min-height: 400px; +} + +.change-list .filtered .results, .change-list .filtered .paginator, +.filtered #toolbar, .filtered div.xfull { + width: auto; +} + +.change-list .filtered table tbody th { + padding-right: 1em; +} + +#changelist-form .results { + overflow-x: auto; + width: 100%; +} + +#changelist .toplinks { + border-bottom: 1px solid var(--hairline-color); +} + +#changelist .paginator { + color: var(--body-quiet-color); + border-bottom: 1px solid var(--hairline-color); + background: var(--body-bg); + overflow: hidden; +} + +/* CHANGELIST TABLES */ + +#changelist table thead th { + padding: 0; + white-space: nowrap; + vertical-align: middle; +} + +#changelist table thead th.action-checkbox-column { + width: 1.5em; + text-align: center; +} + +#changelist table tbody td.action-checkbox { + text-align: center; +} + +#changelist table tfoot { + color: var(--body-quiet-color); +} + +/* TOOLBAR */ + +#toolbar { + padding: 8px 10px; + margin-bottom: 15px; + border-top: 1px solid var(--hairline-color); + border-bottom: 1px solid var(--hairline-color); + background: var(--darkened-bg); + color: var(--body-quiet-color); +} + +#toolbar form input { + border-radius: 4px; + font-size: 0.875rem; + padding: 5px; + color: var(--body-fg); +} + +#toolbar #searchbar { + height: 1.1875rem; + border: 1px solid var(--border-color); + padding: 2px 5px; + margin: 0; + vertical-align: top; + font-size: 0.8125rem; + max-width: 100%; +} + +#toolbar #searchbar:focus { + border-color: var(--body-quiet-color); +} + +#toolbar form input[type="submit"] { + border: 1px solid var(--border-color); + font-size: 0.8125rem; + padding: 4px 8px; + margin: 0; + vertical-align: middle; + background: var(--body-bg); + box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset; + cursor: pointer; + color: var(--body-fg); +} + +#toolbar form input[type="submit"]:focus, +#toolbar form input[type="submit"]:hover { + border-color: var(--body-quiet-color); +} + +#changelist-search img { + vertical-align: middle; + margin-right: 4px; +} + +#changelist-search .help { + word-break: break-word; +} + +/* FILTER COLUMN */ + +#changelist-filter { + flex: 0 0 240px; + order: 1; + background: var(--darkened-bg); + border-left: none; + margin: 0 0 0 30px; +} + +@media (forced-colors: active) { + #changelist-filter { + border: 1px solid; + } +} + +#changelist-filter h2 { + font-size: 0.875rem; + text-transform: uppercase; + letter-spacing: 0.5px; + padding: 5px 15px; + margin-bottom: 12px; + border-bottom: none; +} + +#changelist-filter h3, +#changelist-filter details summary { + font-weight: 400; + padding: 0 15px; + margin-bottom: 10px; +} + +#changelist-filter details summary > * { + display: inline; +} + +#changelist-filter details > summary { + list-style-type: none; +} + +#changelist-filter details > summary::-webkit-details-marker { + display: none; +} + +#changelist-filter details > summary::before { + content: '→'; + font-weight: bold; + color: var(--link-hover-color); +} + +#changelist-filter details[open] > summary::before { + content: '↓'; +} + +#changelist-filter ul { + margin: 5px 0; + padding: 0 15px 15px; + border-bottom: 1px solid var(--hairline-color); +} + +#changelist-filter ul:last-child { + border-bottom: none; +} + +#changelist-filter li { + list-style-type: none; + margin-left: 0; + padding-left: 0; +} + +#changelist-filter a { + display: block; + color: var(--body-quiet-color); + word-break: break-word; +} + +#changelist-filter li.selected { + border-left: 5px solid var(--hairline-color); + padding-left: 10px; + margin-left: -15px; +} + +#changelist-filter li.selected a { + color: var(--link-selected-fg); +} + +#changelist-filter a:focus, #changelist-filter a:hover, +#changelist-filter li.selected a:focus, +#changelist-filter li.selected a:hover { + color: var(--link-hover-color); +} + +#changelist-filter #changelist-filter-extra-actions { + font-size: 0.8125rem; + margin-bottom: 10px; + border-bottom: 1px solid var(--hairline-color); +} + +/* DATE DRILLDOWN */ + +.change-list .toplinks { + display: flex; + padding-bottom: 5px; + flex-wrap: wrap; + gap: 3px 17px; + font-weight: bold; +} + +.change-list .toplinks a { + font-size: 0.8125rem; +} + +.change-list .toplinks .date-back { + color: var(--body-quiet-color); +} + +.change-list .toplinks .date-back:focus, +.change-list .toplinks .date-back:hover { + color: var(--link-hover-color); +} + +/* ACTIONS */ + +.filtered .actions { + border-right: none; +} + +#changelist table input { + margin: 0; + vertical-align: baseline; +} + +/* Once the :has() pseudo-class is supported by all browsers, the tr.selected + selector and the JS adding the class can be removed. */ +#changelist tbody tr.selected { + background-color: var(--selected-row); +} + +#changelist tbody tr:has(.action-select:checked) { + background-color: var(--selected-row); +} + +@media (forced-colors: active) { + #changelist tbody tr.selected { + background-color: SelectedItem; + } + #changelist tbody tr:has(.action-select:checked) { + background-color: SelectedItem; + } +} + +#changelist .actions { + padding: 10px; + background: var(--body-bg); + border-top: none; + border-bottom: none; + line-height: 1.5rem; + color: var(--body-quiet-color); + width: 100%; +} + +#changelist .actions span.all, +#changelist .actions span.action-counter, +#changelist .actions span.clear, +#changelist .actions span.question { + font-size: 0.8125rem; + margin: 0 0.5em; +} + +#changelist .actions:last-child { + border-bottom: none; +} + +#changelist .actions select { + vertical-align: top; + height: 1.5rem; + color: var(--body-fg); + border: 1px solid var(--border-color); + border-radius: 4px; + font-size: 0.875rem; + padding: 0 0 0 4px; + margin: 0; + margin-left: 10px; +} + +#changelist .actions select:focus { + border-color: var(--body-quiet-color); +} + +#changelist .actions label { + display: inline-block; + vertical-align: middle; + font-size: 0.8125rem; +} + +#changelist .actions .button { + font-size: 0.8125rem; + border: 1px solid var(--border-color); + border-radius: 4px; + background: var(--body-bg); + box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset; + cursor: pointer; + height: 1.5rem; + line-height: 1; + padding: 4px 8px; + margin: 0; + color: var(--body-fg); +} + +#changelist .actions .button:focus, #changelist .actions .button:hover { + border-color: var(--body-quiet-color); +} diff --git a/backend/staticfiles/admin/css/dark_mode.css b/backend/staticfiles/admin/css/dark_mode.css new file mode 100644 index 0000000..65b58d0 --- /dev/null +++ b/backend/staticfiles/admin/css/dark_mode.css @@ -0,0 +1,130 @@ +@media (prefers-color-scheme: dark) { + :root { + --primary: #264b5d; + --primary-fg: #f7f7f7; + + --body-fg: #eeeeee; + --body-bg: #121212; + --body-quiet-color: #d0d0d0; + --body-medium-color: #e0e0e0; + --body-loud-color: #ffffff; + + --breadcrumbs-link-fg: #e0e0e0; + --breadcrumbs-bg: var(--primary); + + --link-fg: #81d4fa; + --link-hover-color: #4ac1f7; + --link-selected-fg: #6f94c6; + + --hairline-color: #272727; + --border-color: #353535; + + --error-fg: #e35f5f; + --message-success-bg: #006b1b; + --message-warning-bg: #583305; + --message-error-bg: #570808; + + --darkened-bg: #212121; + --selected-bg: #1b1b1b; + --selected-row: #00363a; + + --close-button-bg: #333333; + --close-button-hover-bg: #666666; + + color-scheme: dark; + } + } + + +html[data-theme="dark"] { + --primary: #264b5d; + --primary-fg: #f7f7f7; + + --body-fg: #eeeeee; + --body-bg: #121212; + --body-quiet-color: #d0d0d0; + --body-medium-color: #e0e0e0; + --body-loud-color: #ffffff; + + --breadcrumbs-link-fg: #e0e0e0; + --breadcrumbs-bg: var(--primary); + + --link-fg: #81d4fa; + --link-hover-color: #4ac1f7; + --link-selected-fg: #6f94c6; + + --hairline-color: #272727; + --border-color: #353535; + + --error-fg: #e35f5f; + --message-success-bg: #006b1b; + --message-warning-bg: #583305; + --message-error-bg: #570808; + + --darkened-bg: #212121; + --selected-bg: #1b1b1b; + --selected-row: #00363a; + + --close-button-bg: #333333; + --close-button-hover-bg: #666666; + + color-scheme: dark; +} + +/* THEME SWITCH */ +.theme-toggle { + cursor: pointer; + border: none; + padding: 0; + background: transparent; + vertical-align: middle; + margin-inline-start: 5px; + margin-top: -1px; +} + +.theme-toggle svg { + vertical-align: middle; + height: 1.5rem; + width: 1.5rem; + display: none; +} + +/* +Fully hide screen reader text so we only show the one matching the current +theme. +*/ +.theme-toggle .visually-hidden { + display: none; +} + +html[data-theme="auto"] .theme-toggle .theme-label-when-auto { + display: block; +} + +html[data-theme="dark"] .theme-toggle .theme-label-when-dark { + display: block; +} + +html[data-theme="light"] .theme-toggle .theme-label-when-light { + display: block; +} + +/* ICONS */ +.theme-toggle svg.theme-icon-when-auto, +.theme-toggle svg.theme-icon-when-dark, +.theme-toggle svg.theme-icon-when-light { + fill: var(--header-link-color); + color: var(--header-bg); +} + +html[data-theme="auto"] .theme-toggle svg.theme-icon-when-auto { + display: block; +} + +html[data-theme="dark"] .theme-toggle svg.theme-icon-when-dark { + display: block; +} + +html[data-theme="light"] .theme-toggle svg.theme-icon-when-light { + display: block; +} diff --git a/backend/staticfiles/admin/css/dashboard.css b/backend/staticfiles/admin/css/dashboard.css new file mode 100644 index 0000000..242b81a --- /dev/null +++ b/backend/staticfiles/admin/css/dashboard.css @@ -0,0 +1,29 @@ +/* DASHBOARD */ +.dashboard td, .dashboard th { + word-break: break-word; +} + +.dashboard .module table th { + width: 100%; +} + +.dashboard .module table td { + white-space: nowrap; +} + +.dashboard .module table td a { + display: block; + padding-right: .6em; +} + +/* RECENT ACTIONS MODULE */ + +.module ul.actionlist { + margin-left: 0; +} + +ul.actionlist li { + list-style-type: none; + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/backend/staticfiles/admin/css/forms.css b/backend/staticfiles/admin/css/forms.css new file mode 100644 index 0000000..c6ce788 --- /dev/null +++ b/backend/staticfiles/admin/css/forms.css @@ -0,0 +1,498 @@ +@import url('widgets.css'); + +/* FORM ROWS */ + +.form-row { + overflow: hidden; + padding: 10px; + font-size: 0.8125rem; + border-bottom: 1px solid var(--hairline-color); +} + +.form-row img, .form-row input { + vertical-align: middle; +} + +.form-row label input[type="checkbox"] { + margin-top: 0; + vertical-align: 0; +} + +form .form-row p { + padding-left: 0; +} + +.flex-container { + display: flex; +} + +.form-multiline { + flex-wrap: wrap; +} + +.form-multiline > div { + padding-bottom: 10px; +} + +/* FORM LABELS */ + +label { + font-weight: normal; + color: var(--body-quiet-color); + font-size: 0.8125rem; +} + +.required label, label.required { + font-weight: bold; +} + +/* RADIO BUTTONS */ + +form div.radiolist div { + padding-right: 7px; +} + +form div.radiolist.inline div { + display: inline-block; +} + +form div.radiolist label { + width: auto; +} + +form div.radiolist input[type="radio"] { + margin: -2px 4px 0 0; + padding: 0; +} + +form ul.inline { + margin-left: 0; + padding: 0; +} + +form ul.inline li { + float: left; + padding-right: 7px; +} + +/* FIELDSETS */ + +fieldset .fieldset-heading, +fieldset .inline-heading, +:not(.inline-related) .collapse summary { + border: 1px solid var(--header-bg); + margin: 0; + padding: 8px; + font-weight: 400; + font-size: 0.8125rem; + background: var(--header-bg); + color: var(--header-link-color); +} + +/* ALIGNED FIELDSETS */ + +.aligned label { + display: block; + padding: 4px 10px 0 0; + min-width: 160px; + width: 160px; + word-wrap: break-word; +} + +.aligned label:not(.vCheckboxLabel):after { + content: ''; + display: inline-block; + vertical-align: middle; +} + +.aligned label + p, .aligned .checkbox-row + div.help, .aligned label + div.readonly { + padding: 6px 0; + margin-top: 0; + margin-bottom: 0; + margin-left: 0; + overflow-wrap: break-word; +} + +.aligned ul label { + display: inline; + float: none; + width: auto; +} + +.aligned .form-row input { + margin-bottom: 0; +} + +.colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField { + width: 350px; +} + +form .aligned ul { + margin-left: 160px; + padding-left: 10px; +} + +form .aligned div.radiolist { + display: inline-block; + margin: 0; + padding: 0; +} + +form .aligned p.help, +form .aligned div.help { + margin-top: 0; + margin-left: 160px; + padding-left: 10px; +} + +form .aligned p.date div.help.timezonewarning, +form .aligned p.datetime div.help.timezonewarning, +form .aligned p.time div.help.timezonewarning { + margin-left: 0; + padding-left: 0; + font-weight: normal; +} + +form .aligned p.help:last-child, +form .aligned div.help:last-child { + margin-bottom: 0; + padding-bottom: 0; +} + +form .aligned input + p.help, +form .aligned textarea + p.help, +form .aligned select + p.help, +form .aligned input + div.help, +form .aligned textarea + div.help, +form .aligned select + div.help { + margin-left: 160px; + padding-left: 10px; +} + +form .aligned select option:checked { + background-color: var(--selected-row); +} + +form .aligned ul li { + list-style: none; +} + +form .aligned table p { + margin-left: 0; + padding-left: 0; +} + +.aligned .vCheckboxLabel { + padding: 1px 0 0 5px; +} + +.aligned .vCheckboxLabel + p.help, +.aligned .vCheckboxLabel + div.help { + margin-top: -4px; +} + +.colM .aligned .vLargeTextField, .colM .aligned .vXMLLargeTextField { + width: 610px; +} + +fieldset .fieldBox { + margin-right: 20px; +} + +/* WIDE FIELDSETS */ + +.wide label { + width: 200px; +} + +form .wide p.help, +form .wide ul.errorlist, +form .wide div.help { + padding-left: 50px; +} + +form div.help ul { + padding-left: 0; + margin-left: 0; +} + +.colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField { + width: 450px; +} + +/* COLLAPSIBLE FIELDSETS */ + +.collapse summary .fieldset-heading, +.collapse summary .inline-heading { + background: transparent; + border: none; + color: currentColor; + display: inline; + margin: 0; + padding: 0; +} + +/* MONOSPACE TEXTAREAS */ + +fieldset.monospace textarea { + font-family: var(--font-family-monospace); +} + +/* SUBMIT ROW */ + +.submit-row { + padding: 12px 14px 12px; + margin: 0 0 20px; + background: var(--darkened-bg); + border: 1px solid var(--hairline-color); + border-radius: 4px; + overflow: hidden; + display: flex; + gap: 10px; + flex-wrap: wrap; +} + +body.popup .submit-row { + overflow: auto; +} + +.submit-row input { + height: 2.1875rem; + line-height: 0.9375rem; +} + +.submit-row input, .submit-row a { + margin: 0; +} + +.submit-row input.default { + text-transform: uppercase; +} + +.submit-row a.deletelink { + margin-left: auto; +} + +.submit-row a.deletelink { + display: block; + background: var(--delete-button-bg); + border-radius: 4px; + padding: 0.625rem 0.9375rem; + height: 0.9375rem; + line-height: 0.9375rem; + color: var(--button-fg); +} + +.submit-row a.closelink { + display: inline-block; + background: var(--close-button-bg); + border-radius: 4px; + padding: 10px 15px; + height: 0.9375rem; + line-height: 0.9375rem; + color: var(--button-fg); +} + +.submit-row a.deletelink:focus, +.submit-row a.deletelink:hover, +.submit-row a.deletelink:active { + background: var(--delete-button-hover-bg); + text-decoration: none; +} + +.submit-row a.closelink:focus, +.submit-row a.closelink:hover, +.submit-row a.closelink:active { + background: var(--close-button-hover-bg); + text-decoration: none; +} + +/* CUSTOM FORM FIELDS */ + +.vSelectMultipleField { + vertical-align: top; +} + +.vCheckboxField { + border: none; +} + +.vDateField, .vTimeField { + margin-right: 2px; + margin-bottom: 4px; +} + +.vDateField { + min-width: 6.85em; +} + +.vTimeField { + min-width: 4.7em; +} + +.vURLField { + width: 30em; +} + +.vLargeTextField, .vXMLLargeTextField { + width: 48em; +} + +.flatpages-flatpage #id_content { + height: 40.2em; +} + +.module table .vPositiveSmallIntegerField { + width: 2.2em; +} + +.vIntegerField { + width: 5em; +} + +.vBigIntegerField { + width: 10em; +} + +.vForeignKeyRawIdAdminField { + width: 5em; +} + +.vTextField, .vUUIDField { + width: 20em; +} + +/* INLINES */ + +.inline-group { + padding: 0; + margin: 0 0 30px; +} + +.inline-group thead th { + padding: 8px 10px; +} + +.inline-group .aligned label { + width: 160px; +} + +.inline-related { + position: relative; +} + +.inline-related h4, +.inline-related:not(.tabular) .collapse summary { + margin: 0; + color: var(--body-medium-color); + padding: 5px; + font-size: 0.8125rem; + background: var(--darkened-bg); + border: 1px solid var(--hairline-color); + border-left-color: var(--darkened-bg); + border-right-color: var(--darkened-bg); +} + +.inline-related h3 span.delete { + float: right; +} + +.inline-related h3 span.delete label { + margin-left: 2px; + font-size: 0.6875rem; +} + +.inline-related fieldset { + margin: 0; + background: var(--body-bg); + border: none; + width: 100%; +} + +.inline-group .tabular fieldset.module { + border: none; +} + +.inline-related.tabular fieldset.module table { + width: 100%; + overflow-x: scroll; +} + +.last-related fieldset { + border: none; +} + +.inline-group .tabular tr.has_original td { + padding-top: 2em; +} + +.inline-group .tabular tr td.original { + padding: 2px 0 0 0; + width: 0; + _position: relative; +} + +.inline-group .tabular th.original { + width: 0px; + padding: 0; +} + +.inline-group .tabular td.original p { + position: absolute; + left: 0; + height: 1.1em; + padding: 2px 9px; + overflow: hidden; + font-size: 0.5625rem; + font-weight: bold; + color: var(--body-quiet-color); + _width: 700px; +} + +.inline-group div.add-row, +.inline-group .tabular tr.add-row td { + color: var(--body-quiet-color); + background: var(--darkened-bg); + padding: 8px 10px; + border-bottom: 1px solid var(--hairline-color); +} + +.inline-group .tabular tr.add-row td { + padding: 8px 10px; + border-bottom: 1px solid var(--hairline-color); +} + +.inline-group div.add-row a, +.inline-group .tabular tr.add-row td a { + font-size: 0.75rem; +} + +.empty-form { + display: none; +} + +/* RELATED FIELD ADD ONE / LOOKUP */ + +.related-lookup { + margin-left: 5px; + display: inline-block; + vertical-align: middle; + background-repeat: no-repeat; + background-size: 14px; +} + +.related-lookup { + width: 1rem; + height: 1rem; + background-image: url(../img/search.svg); +} + +form .related-widget-wrapper ul { + display: inline-block; + margin-left: 0; + padding-left: 0; +} + +.clearable-file-input input { + margin-top: 0; +} diff --git a/backend/staticfiles/admin/css/login.css b/backend/staticfiles/admin/css/login.css new file mode 100644 index 0000000..805a34b --- /dev/null +++ b/backend/staticfiles/admin/css/login.css @@ -0,0 +1,61 @@ +/* LOGIN FORM */ + +.login { + background: var(--darkened-bg); + height: auto; +} + +.login #header { + height: auto; + padding: 15px 16px; + justify-content: center; +} + +.login #header h1 { + font-size: 1.125rem; + margin: 0; +} + +.login #header h1 a { + color: var(--header-link-color); +} + +.login #content { + padding: 20px; +} + +.login #container { + background: var(--body-bg); + border: 1px solid var(--hairline-color); + border-radius: 4px; + overflow: hidden; + width: 28em; + min-width: 300px; + margin: 100px auto; + height: auto; +} + +.login .form-row { + padding: 4px 0; +} + +.login .form-row label { + display: block; + line-height: 2em; +} + +.login .form-row #id_username, .login .form-row #id_password { + padding: 8px; + width: 100%; + box-sizing: border-box; +} + +.login .submit-row { + padding: 1em 0 0 0; + margin: 0; + text-align: center; +} + +.login .password-reset-link { + text-align: center; +} diff --git a/backend/staticfiles/admin/css/nav_sidebar.css b/backend/staticfiles/admin/css/nav_sidebar.css new file mode 100644 index 0000000..7eb0de9 --- /dev/null +++ b/backend/staticfiles/admin/css/nav_sidebar.css @@ -0,0 +1,150 @@ +.sticky { + position: sticky; + top: 0; + max-height: 100vh; +} + +.toggle-nav-sidebar { + z-index: 20; + left: 0; + display: flex; + align-items: center; + justify-content: center; + flex: 0 0 23px; + width: 23px; + border: 0; + border-right: 1px solid var(--hairline-color); + background-color: var(--body-bg); + cursor: pointer; + font-size: 1.25rem; + color: var(--link-fg); + padding: 0; +} + +[dir="rtl"] .toggle-nav-sidebar { + border-left: 1px solid var(--hairline-color); + border-right: 0; +} + +.toggle-nav-sidebar:hover, +.toggle-nav-sidebar:focus { + background-color: var(--darkened-bg); +} + +#nav-sidebar { + z-index: 15; + flex: 0 0 275px; + left: -276px; + margin-left: -276px; + border-top: 1px solid transparent; + border-right: 1px solid var(--hairline-color); + background-color: var(--body-bg); + overflow: auto; +} + +[dir="rtl"] #nav-sidebar { + border-left: 1px solid var(--hairline-color); + border-right: 0; + left: 0; + margin-left: 0; + right: -276px; + margin-right: -276px; +} + +.toggle-nav-sidebar::before { + content: '\00BB'; +} + +.main.shifted .toggle-nav-sidebar::before { + content: '\00AB'; +} + +.main > #nav-sidebar { + visibility: hidden; +} + +.main.shifted > #nav-sidebar { + margin-left: 0; + visibility: visible; +} + +[dir="rtl"] .main.shifted > #nav-sidebar { + margin-right: 0; +} + +#nav-sidebar .module th { + width: 100%; + overflow-wrap: anywhere; +} + +#nav-sidebar .module th, +#nav-sidebar .module caption { + padding-left: 16px; +} + +#nav-sidebar .module td { + white-space: nowrap; +} + +[dir="rtl"] #nav-sidebar .module th, +[dir="rtl"] #nav-sidebar .module caption { + padding-left: 8px; + padding-right: 16px; +} + +#nav-sidebar .current-app .section:link, +#nav-sidebar .current-app .section:visited { + color: var(--header-color); + font-weight: bold; +} + +#nav-sidebar .current-model { + background: var(--selected-row); +} + +@media (forced-colors: active) { + #nav-sidebar .current-model { + background-color: SelectedItem; + } +} + +.main > #nav-sidebar + .content { + max-width: calc(100% - 23px); +} + +.main.shifted > #nav-sidebar + .content { + max-width: calc(100% - 299px); +} + +@media (max-width: 767px) { + #nav-sidebar, #toggle-nav-sidebar { + display: none; + } + + .main > #nav-sidebar + .content, + .main.shifted > #nav-sidebar + .content { + max-width: 100%; + } +} + +#nav-filter { + width: 100%; + box-sizing: border-box; + padding: 2px 5px; + margin: 5px 0; + border: 1px solid var(--border-color); + background-color: var(--darkened-bg); + color: var(--body-fg); +} + +#nav-filter:focus { + border-color: var(--body-quiet-color); +} + +#nav-filter.no-results { + background: var(--message-error-bg); +} + +#nav-sidebar table { + width: 100%; +} diff --git a/backend/staticfiles/admin/css/responsive.css b/backend/staticfiles/admin/css/responsive.css new file mode 100644 index 0000000..0ca125d --- /dev/null +++ b/backend/staticfiles/admin/css/responsive.css @@ -0,0 +1,908 @@ +/* Tablets */ + +input[type="submit"], button { + -webkit-appearance: none; + appearance: none; +} + +@media (max-width: 1024px) { + /* Basic */ + + html { + -webkit-text-size-adjust: 100%; + } + + td, th { + padding: 10px; + font-size: 0.875rem; + } + + .small { + font-size: 0.75rem; + } + + /* Layout */ + + #container { + min-width: 0; + } + + #content { + padding: 15px 20px 20px; + } + + div.breadcrumbs { + padding: 10px 30px; + } + + /* Header */ + + #header { + flex-direction: column; + padding: 15px 30px; + justify-content: flex-start; + } + + #site-name { + margin: 0 0 8px; + line-height: 1.2; + } + + #user-tools { + margin: 0; + font-weight: 400; + line-height: 1.85; + text-align: left; + } + + #user-tools a { + display: inline-block; + line-height: 1.4; + } + + /* Dashboard */ + + .dashboard #content { + width: auto; + } + + #content-related { + margin-right: -290px; + } + + .colSM #content-related { + margin-left: -290px; + } + + .colMS { + margin-right: 290px; + } + + .colSM { + margin-left: 290px; + } + + .dashboard .module table td a { + padding-right: 0; + } + + td .changelink, td .addlink { + font-size: 0.8125rem; + } + + /* Changelist */ + + #toolbar { + border: none; + padding: 15px; + } + + #changelist-search > div { + display: flex; + flex-wrap: nowrap; + max-width: 480px; + } + + #changelist-search label { + line-height: 1.375rem; + } + + #toolbar form #searchbar { + flex: 1 0 auto; + width: 0; + height: 1.375rem; + margin: 0 10px 0 6px; + } + + #toolbar form input[type=submit] { + flex: 0 1 auto; + } + + #changelist-search .quiet { + width: 0; + flex: 1 0 auto; + margin: 5px 0 0 25px; + } + + #changelist .actions { + display: flex; + flex-wrap: wrap; + padding: 15px 0; + } + + #changelist .actions label { + display: flex; + } + + #changelist .actions select { + background: var(--body-bg); + } + + #changelist .actions .button { + min-width: 48px; + margin: 0 10px; + } + + #changelist .actions span.all, + #changelist .actions span.clear, + #changelist .actions span.question, + #changelist .actions span.action-counter { + font-size: 0.6875rem; + margin: 0 10px 0 0; + } + + #changelist-filter { + flex-basis: 200px; + } + + .change-list .filtered .results, + .change-list .filtered .paginator, + .filtered #toolbar, + .filtered .actions, + + #changelist .paginator { + border-top-color: var(--hairline-color); /* XXX Is this used at all? */ + } + + #changelist .results + .paginator { + border-top: none; + } + + /* Forms */ + + label { + font-size: 1rem; + } + + /* + Minifiers remove the default (text) "type" attribute from "input" HTML + tags. Add input:not([type]) to make the CSS stylesheet work the same. + */ + .form-row input:not([type]), + .form-row input[type=text], + .form-row input[type=password], + .form-row input[type=email], + .form-row input[type=url], + .form-row input[type=tel], + .form-row input[type=number], + .form-row textarea, + .form-row select, + .form-row .vTextField { + box-sizing: border-box; + margin: 0; + padding: 6px 8px; + min-height: 2.25rem; + font-size: 1rem; + } + + .form-row select { + height: 2.25rem; + } + + .form-row select[multiple] { + height: auto; + min-height: 0; + } + + fieldset .fieldBox + .fieldBox { + margin-top: 10px; + padding-top: 10px; + border-top: 1px solid var(--hairline-color); + } + + textarea { + max-width: 100%; + max-height: 120px; + } + + .aligned label { + padding-top: 6px; + } + + .aligned .related-lookup, + .aligned .datetimeshortcuts, + .aligned .related-lookup + strong { + align-self: center; + margin-left: 15px; + } + + form .aligned div.radiolist { + margin-left: 2px; + } + + .submit-row { + padding: 8px; + } + + .submit-row a.deletelink { + padding: 10px 7px; + } + + .button, input[type=submit], input[type=button], .submit-row input, a.button { + padding: 7px; + } + + /* Selector */ + + .selector { + display: flex; + width: 100%; + } + + .selector .selector-filter { + display: flex; + align-items: center; + } + + .selector .selector-filter input { + width: 100%; + min-height: 0; + flex: 1 1; + } + + .selector-available, .selector-chosen { + width: auto; + flex: 1 1; + display: flex; + flex-direction: column; + } + + .selector select { + width: 100%; + flex: 1 0 auto; + margin-bottom: 5px; + } + + .selector-chooseall, .selector-clearall { + align-self: center; + } + + .stacked { + flex-direction: column; + max-width: 480px; + } + + .stacked > * { + flex: 0 1 auto; + } + + .stacked select { + margin-bottom: 0; + } + + .stacked .selector-available, .stacked .selector-chosen { + width: auto; + } + + .stacked ul.selector-chooser { + padding: 0 2px; + transform: none; + } + + .stacked .selector-chooser li { + padding: 3px; + } + + .help-tooltip, .selector .help-icon { + display: none; + } + + .datetime input { + width: 50%; + max-width: 120px; + } + + .datetime span { + font-size: 0.8125rem; + } + + .datetime .timezonewarning { + display: block; + font-size: 0.6875rem; + color: var(--body-quiet-color); + } + + .datetimeshortcuts { + color: var(--border-color); /* XXX Redundant, .datetime span also sets #ccc */ + } + + .form-row .datetime input.vDateField, .form-row .datetime input.vTimeField { + width: 75%; + } + + .inline-group { + overflow: auto; + } + + /* Messages */ + + ul.messagelist li { + padding-left: 55px; + background-position: 30px 12px; + } + + ul.messagelist li.error { + background-position: 30px 12px; + } + + ul.messagelist li.warning { + background-position: 30px 14px; + } + + /* Login */ + + .login #header { + padding: 15px 20px; + } + + .login #site-name { + margin: 0; + } + + /* GIS */ + + div.olMap { + max-width: calc(100vw - 30px); + max-height: 300px; + } + + .olMap + .clear_features { + display: block; + margin-top: 10px; + } + + /* Docs */ + + .module table.xfull { + width: 100%; + } + + pre.literal-block { + overflow: auto; + } +} + +/* Mobile */ + +@media (max-width: 767px) { + /* Layout */ + + #header, #content { + padding: 15px; + } + + div.breadcrumbs { + padding: 10px 15px; + } + + /* Dashboard */ + + .colMS, .colSM { + margin: 0; + } + + #content-related, .colSM #content-related { + width: 100%; + margin: 0; + } + + #content-related .module { + margin-bottom: 0; + } + + #content-related .module h2 { + padding: 10px 15px; + font-size: 1rem; + } + + /* Changelist */ + + #changelist { + align-items: stretch; + flex-direction: column; + } + + #toolbar { + padding: 10px; + } + + #changelist-filter { + margin-left: 0; + } + + #changelist .actions label { + flex: 1 1; + } + + #changelist .actions select { + flex: 1 0; + width: 100%; + } + + #changelist .actions span { + flex: 1 0 100%; + } + + #changelist-filter { + position: static; + width: auto; + margin-top: 30px; + } + + .object-tools { + float: none; + margin: 0 0 15px; + padding: 0; + overflow: hidden; + } + + .object-tools li { + height: auto; + margin-left: 0; + } + + .object-tools li + li { + margin-left: 15px; + } + + .object-tools:has(a.addlink) { + margin-top: 0px; + } + + /* Forms */ + + .form-row { + padding: 15px 0; + } + + .aligned .form-row, + .aligned .form-row > div { + max-width: 100vw; + } + + .aligned .form-row > div { + width: calc(100vw - 30px); + } + + .flex-container { + flex-flow: column; + } + + .flex-container.checkbox-row { + flex-flow: row; + } + + textarea { + max-width: none; + } + + .vURLField { + width: auto; + } + + fieldset .fieldBox + .fieldBox { + margin-top: 15px; + padding-top: 15px; + } + + .aligned label { + width: 100%; + min-width: auto; + padding: 0 0 10px; + } + + .aligned label:after { + max-height: 0; + } + + .aligned .form-row input, + .aligned .form-row select, + .aligned .form-row textarea { + flex: 1 1 auto; + max-width: 100%; + } + + .aligned .checkbox-row input { + flex: 0 1 auto; + margin: 0; + } + + .aligned .vCheckboxLabel { + flex: 1 0; + padding: 1px 0 0 5px; + } + + .aligned label + p, + .aligned label + div.help, + .aligned label + div.readonly { + padding: 0; + margin-left: 0; + } + + .aligned p.file-upload { + font-size: 0.8125rem; + } + + span.clearable-file-input { + margin-left: 15px; + } + + span.clearable-file-input label { + font-size: 0.8125rem; + padding-bottom: 0; + } + + .aligned .timezonewarning { + flex: 1 0 100%; + margin-top: 5px; + } + + form .aligned .form-row div.help { + width: 100%; + margin: 5px 0 0; + padding: 0; + } + + form .aligned ul, + form .aligned ul.errorlist { + margin-left: 0; + padding-left: 0; + } + + form .aligned div.radiolist { + margin-top: 5px; + margin-right: 15px; + margin-bottom: -3px; + } + + form .aligned div.radiolist:not(.inline) div + div { + margin-top: 5px; + } + + /* Related widget */ + + .related-widget-wrapper { + width: 100%; + display: flex; + align-items: flex-start; + } + + .related-widget-wrapper .selector { + order: 1; + flex: 1 0 auto; + } + + .related-widget-wrapper > a { + order: 2; + } + + .related-widget-wrapper .radiolist ~ a { + align-self: flex-end; + } + + .related-widget-wrapper > select ~ a { + align-self: center; + } + + /* Selector */ + + .selector { + flex-direction: column; + gap: 10px 0; + } + + .selector-available, .selector-chosen { + flex: 1 1 auto; + } + + .selector select { + max-height: 96px; + } + + .selector ul.selector-chooser { + display: flex; + width: 60px; + height: 30px; + padding: 0 2px; + transform: none; + } + + .selector ul.selector-chooser li { + float: left; + } + + .selector-remove { + background-position: 0 0; + } + + :enabled.selector-remove:focus, :enabled.selector-remove:hover { + background-position: 0 -24px; + } + + .selector-add { + background-position: 0 -48px; + } + + :enabled.selector-add:focus, :enabled.selector-add:hover { + background-position: 0 -72px; + } + + /* Inlines */ + + .inline-group[data-inline-type="stacked"] .inline-related { + border: 1px solid var(--hairline-color); + border-radius: 4px; + margin-top: 15px; + overflow: auto; + } + + .inline-group[data-inline-type="stacked"] .inline-related > * { + box-sizing: border-box; + } + + .inline-group[data-inline-type="stacked"] .inline-related .module { + padding: 0 10px; + } + + .inline-group[data-inline-type="stacked"] .inline-related .module .form-row { + border-top: 1px solid var(--hairline-color); + border-bottom: none; + } + + .inline-group[data-inline-type="stacked"] .inline-related .module .form-row:first-child { + border-top: none; + } + + .inline-group[data-inline-type="stacked"] .inline-related h3 { + padding: 10px; + border-top-width: 0; + border-bottom-width: 2px; + display: flex; + flex-wrap: wrap; + align-items: center; + } + + .inline-group[data-inline-type="stacked"] .inline-related h3 .inline_label { + margin-right: auto; + } + + .inline-group[data-inline-type="stacked"] .inline-related h3 span.delete { + float: none; + flex: 1 1 100%; + margin-top: 5px; + } + + .inline-group[data-inline-type="stacked"] .aligned .form-row > div:not([class]) { + width: 100%; + } + + .inline-group[data-inline-type="stacked"] .aligned label { + width: 100%; + } + + .inline-group[data-inline-type="stacked"] div.add-row { + margin-top: 15px; + border: 1px solid var(--hairline-color); + border-radius: 4px; + } + + .inline-group div.add-row, + .inline-group .tabular tr.add-row td { + padding: 0; + } + + .inline-group div.add-row a, + .inline-group .tabular tr.add-row td a { + display: block; + padding: 8px 10px 8px 26px; + background-position: 8px 9px; + } + + /* Submit row */ + + .submit-row { + padding: 10px; + margin: 0 0 15px; + flex-direction: column; + gap: 8px; + } + + .submit-row input, .submit-row input.default, .submit-row a { + text-align: center; + } + + .submit-row a.closelink { + padding: 10px 0; + text-align: center; + } + + .submit-row a.deletelink { + margin: 0; + } + + /* Messages */ + + ul.messagelist li { + padding-left: 40px; + background-position: 15px 12px; + } + + ul.messagelist li.error { + background-position: 15px 12px; + } + + ul.messagelist li.warning { + background-position: 15px 14px; + } + + /* Paginator */ + + .paginator .this-page, .paginator a:link, .paginator a:visited { + padding: 4px 10px; + } + + /* Login */ + + body.login { + padding: 0 15px; + } + + .login #container { + width: auto; + max-width: 480px; + margin: 50px auto; + } + + .login #header, + .login #content { + padding: 15px; + } + + .login #content-main { + float: none; + } + + .login .form-row { + padding: 0; + } + + .login .form-row + .form-row { + margin-top: 15px; + } + + .login .form-row label { + margin: 0 0 5px; + line-height: 1.2; + } + + .login .submit-row { + padding: 15px 0 0; + } + + .login br { + display: none; + } + + .login .submit-row input { + margin: 0; + text-transform: uppercase; + } + + .errornote { + margin: 0 0 20px; + padding: 8px 12px; + font-size: 0.8125rem; + } + + /* Calendar and clock */ + + .calendarbox, .clockbox { + position: fixed !important; + top: 50% !important; + left: 50% !important; + transform: translate(-50%, -50%); + margin: 0; + border: none; + overflow: visible; + } + + .calendarbox:before, .clockbox:before { + content: ''; + position: fixed; + top: 50%; + left: 50%; + width: 100vw; + height: 100vh; + background: rgba(0, 0, 0, 0.75); + transform: translate(-50%, -50%); + } + + .calendarbox > *, .clockbox > * { + position: relative; + z-index: 1; + } + + .calendarbox > div:first-child { + z-index: 2; + } + + .calendarbox .calendar, .clockbox h2 { + border-radius: 4px 4px 0 0; + overflow: hidden; + } + + .calendarbox .calendar-cancel, .clockbox .calendar-cancel { + border-radius: 0 0 4px 4px; + overflow: hidden; + } + + .calendar-shortcuts { + padding: 10px 0; + font-size: 0.75rem; + line-height: 0.75rem; + } + + .calendar-shortcuts a { + margin: 0 4px; + } + + .timelist a { + background: var(--body-bg); + padding: 4px; + } + + .calendar-cancel { + padding: 8px 10px; + } + + .clockbox h2 { + padding: 8px 15px; + } + + .calendar caption { + padding: 10px; + } + + .calendarbox .calendarnav-previous, .calendarbox .calendarnav-next { + z-index: 1; + top: 10px; + } + + /* History */ + + table#change-history tbody th, table#change-history tbody td { + font-size: 0.8125rem; + word-break: break-word; + } + + table#change-history tbody th { + width: auto; + } + + /* Docs */ + + table.model tbody th, table.model tbody td { + font-size: 0.8125rem; + word-break: break-word; + } +} diff --git a/backend/staticfiles/admin/css/responsive_rtl.css b/backend/staticfiles/admin/css/responsive_rtl.css new file mode 100644 index 0000000..5e8f5c5 --- /dev/null +++ b/backend/staticfiles/admin/css/responsive_rtl.css @@ -0,0 +1,89 @@ +/* TABLETS */ + +@media (max-width: 1024px) { + [dir="rtl"] .colMS { + margin-right: 0; + } + + [dir="rtl"] #user-tools { + text-align: right; + } + + [dir="rtl"] #changelist .actions label { + padding-left: 10px; + padding-right: 0; + } + + [dir="rtl"] #changelist .actions select { + margin-left: 0; + margin-right: 15px; + } + + [dir="rtl"] .change-list .filtered .results, + [dir="rtl"] .change-list .filtered .paginator, + [dir="rtl"] .filtered #toolbar, + [dir="rtl"] .filtered div.xfull, + [dir="rtl"] .filtered .actions, + [dir="rtl"] #changelist-filter { + margin-left: 0; + } + + [dir="rtl"] .inline-group div.add-row a, + [dir="rtl"] .inline-group .tabular tr.add-row td a { + padding: 8px 26px 8px 10px; + background-position: calc(100% - 8px) 9px; + } + + [dir="rtl"] .object-tools li { + float: right; + } + + [dir="rtl"] .object-tools li + li { + margin-left: 0; + margin-right: 15px; + } + + [dir="rtl"] .dashboard .module table td a { + padding-left: 0; + padding-right: 16px; + } +} + +/* MOBILE */ + +@media (max-width: 767px) { + [dir="rtl"] .aligned .related-lookup, + [dir="rtl"] .aligned .datetimeshortcuts { + margin-left: 0; + margin-right: 15px; + } + + [dir="rtl"] .aligned ul, + [dir="rtl"] form .aligned ul.errorlist { + margin-right: 0; + } + + [dir="rtl"] #changelist-filter { + margin-left: 0; + margin-right: 0; + } + [dir="rtl"] .aligned .vCheckboxLabel { + padding: 1px 5px 0 0; + } + + [dir="rtl"] .selector-remove { + background-position: 0 0; + } + + [dir="rtl"] :enabled.selector-remove:focus, :enabled.selector-remove:hover { + background-position: 0 -24px; + } + + [dir="rtl"] .selector-add { + background-position: 0 -48px; + } + + [dir="rtl"] :enabled.selector-add:focus, :enabled.selector-add:hover { + background-position: 0 -72px; + } +} diff --git a/backend/staticfiles/admin/css/rtl.css b/backend/staticfiles/admin/css/rtl.css new file mode 100644 index 0000000..a2556d0 --- /dev/null +++ b/backend/staticfiles/admin/css/rtl.css @@ -0,0 +1,293 @@ +/* GLOBAL */ + +th { + text-align: right; +} + +.module h2, .module caption { + text-align: right; +} + +.module ul, .module ol { + margin-left: 0; + margin-right: 1.5em; +} + +.viewlink, .addlink, .changelink, .hidelink { + padding-left: 0; + padding-right: 16px; + background-position: 100% 1px; +} + +.deletelink { + padding-left: 0; + padding-right: 16px; + background-position: 100% 1px; +} + +.object-tools { + float: left; +} + +thead th:first-child, +tfoot td:first-child { + border-left: none; +} + +/* LAYOUT */ + +#user-tools { + right: auto; + left: 0; + text-align: left; +} + +div.breadcrumbs { + text-align: right; +} + +#content-main { + float: right; +} + +#content-related { + float: left; + margin-left: -300px; + margin-right: auto; +} + +.colMS { + margin-left: 300px; + margin-right: 0; +} + +/* SORTABLE TABLES */ + +table thead th.sorted .sortoptions { + float: left; +} + +thead th.sorted .text { + padding-right: 0; + padding-left: 42px; +} + +/* dashboard styles */ + +.dashboard .module table td a { + padding-left: .6em; + padding-right: 16px; +} + +/* changelists styles */ + +.change-list .filtered table { + border-left: none; + border-right: 0px none; +} + +#changelist-filter { + border-left: none; + border-right: none; + margin-left: 0; + margin-right: 30px; +} + +#changelist-filter li.selected { + border-left: none; + padding-left: 10px; + margin-left: 0; + border-right: 5px solid var(--hairline-color); + padding-right: 10px; + margin-right: -15px; +} + +#changelist table tbody td:first-child, #changelist table tbody th:first-child { + border-right: none; + border-left: none; +} + +.paginator .end { + margin-left: 6px; + margin-right: 0; +} + +.paginator input { + margin-left: 0; + margin-right: auto; +} + +/* FORMS */ + +.aligned label { + padding: 0 0 3px 1em; +} + +.submit-row a.deletelink { + margin-left: 0; + margin-right: auto; +} + +.vDateField, .vTimeField { + margin-left: 2px; +} + +.aligned .form-row input { + margin-left: 5px; +} + +form .aligned ul { + margin-right: 163px; + padding-right: 10px; + margin-left: 0; + padding-left: 0; +} + +form ul.inline li { + float: right; + padding-right: 0; + padding-left: 7px; +} + +form .aligned p.help, +form .aligned div.help { + margin-left: 0; + margin-right: 160px; + padding-right: 10px; +} + +form div.help ul, +form .aligned .checkbox-row + .help, +form .aligned p.date div.help.timezonewarning, +form .aligned p.datetime div.help.timezonewarning, +form .aligned p.time div.help.timezonewarning { + margin-right: 0; + padding-right: 0; +} + +form .wide p.help, +form .wide ul.errorlist, +form .wide div.help { + padding-left: 0; + padding-right: 50px; +} + +.submit-row { + text-align: right; +} + +fieldset .fieldBox { + margin-left: 20px; + margin-right: 0; +} + +.errorlist li { + background-position: 100% 12px; + padding: 0; +} + +.errornote { + background-position: 100% 12px; + padding: 10px 12px; +} + +/* WIDGETS */ + +.calendarnav-previous { + top: 0; + left: auto; + right: 10px; + background: url(../img/calendar-icons.svg) 0 -15px no-repeat; +} + +.calendarnav-next { + top: 0; + right: auto; + left: 10px; + background: url(../img/calendar-icons.svg) 0 0 no-repeat; +} + +.calendar caption, .calendarbox h2 { + text-align: center; +} + +.selector { + float: right; +} + +.selector .selector-filter { + text-align: right; +} + +.selector-add { + background: url(../img/selector-icons.svg) 0 -96px no-repeat; + background-size: 24px auto; +} + +:enabled.selector-add:focus, :enabled.selector-add:hover { + background-position: 0 -120px; +} + +.selector-remove { + background: url(../img/selector-icons.svg) 0 -144px no-repeat; + background-size: 24px auto; +} + +:enabled.selector-remove:focus, :enabled.selector-remove:hover { + background-position: 0 -168px; +} + +.selector-chooseall { + background: url(../img/selector-icons.svg) right -128px no-repeat; +} + +:enabled.selector-chooseall:focus, :enabled.selector-chooseall:hover { + background-position: 100% -144px; +} + +.selector-clearall { + background: url(../img/selector-icons.svg) 0 -160px no-repeat; +} + +:enabled.selector-clearall:focus, :enabled.selector-clearall:hover { + background-position: 0 -176px; +} + +.inline-deletelink { + float: left; +} + +form .form-row p.datetime { + overflow: hidden; +} + +.related-widget-wrapper { + float: right; +} + +/* MISC */ + +.inline-related h2, .inline-group h2 { + text-align: right +} + +.inline-related h3 span.delete { + padding-right: 20px; + padding-left: inherit; + left: 10px; + right: inherit; + float:left; +} + +.inline-related h3 span.delete label { + margin-left: inherit; + margin-right: 2px; +} + +.inline-group .tabular td.original p { + right: 0; +} + +.selector .selector-chooser { + margin: 0; +} diff --git a/backend/staticfiles/admin/css/unusable_password_field.css b/backend/staticfiles/admin/css/unusable_password_field.css new file mode 100644 index 0000000..d46eb03 --- /dev/null +++ b/backend/staticfiles/admin/css/unusable_password_field.css @@ -0,0 +1,19 @@ +/* Hide warnings fields if usable password is selected */ +form:has(#id_usable_password input[value="true"]:checked) .messagelist { + display: none; +} + +/* Hide password fields if unusable password is selected */ +form:has(#id_usable_password input[value="false"]:checked) .field-password1, +form:has(#id_usable_password input[value="false"]:checked) .field-password2 { + display: none; +} + +/* Select appropriate submit button */ +form:has(#id_usable_password input[value="true"]:checked) input[type="submit"].unset-password { + display: none; +} + +form:has(#id_usable_password input[value="false"]:checked) input[type="submit"].set-password { + display: none; +} diff --git a/backend/staticfiles/admin/css/vendor/select2/LICENSE-SELECT2.md b/backend/staticfiles/admin/css/vendor/select2/LICENSE-SELECT2.md new file mode 100644 index 0000000..8cb8a2b --- /dev/null +++ b/backend/staticfiles/admin/css/vendor/select2/LICENSE-SELECT2.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/backend/staticfiles/admin/css/vendor/select2/select2.css b/backend/staticfiles/admin/css/vendor/select2/select2.css new file mode 100644 index 0000000..750b320 --- /dev/null +++ b/backend/staticfiles/admin/css/vendor/select2/select2.css @@ -0,0 +1,481 @@ +.select2-container { + box-sizing: border-box; + display: inline-block; + margin: 0; + position: relative; + vertical-align: middle; } + .select2-container .select2-selection--single { + box-sizing: border-box; + cursor: pointer; + display: block; + height: 28px; + user-select: none; + -webkit-user-select: none; } + .select2-container .select2-selection--single .select2-selection__rendered { + display: block; + padding-left: 8px; + padding-right: 20px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } + .select2-container .select2-selection--single .select2-selection__clear { + position: relative; } + .select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered { + padding-right: 8px; + padding-left: 20px; } + .select2-container .select2-selection--multiple { + box-sizing: border-box; + cursor: pointer; + display: block; + min-height: 32px; + user-select: none; + -webkit-user-select: none; } + .select2-container .select2-selection--multiple .select2-selection__rendered { + display: inline-block; + overflow: hidden; + padding-left: 8px; + text-overflow: ellipsis; + white-space: nowrap; } + .select2-container .select2-search--inline { + float: left; } + .select2-container .select2-search--inline .select2-search__field { + box-sizing: border-box; + border: none; + font-size: 100%; + margin-top: 5px; + padding: 0; } + .select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button { + -webkit-appearance: none; } + +.select2-dropdown { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + box-sizing: border-box; + display: block; + position: absolute; + left: -100000px; + width: 100%; + z-index: 1051; } + +.select2-results { + display: block; } + +.select2-results__options { + list-style: none; + margin: 0; + padding: 0; } + +.select2-results__option { + padding: 6px; + user-select: none; + -webkit-user-select: none; } + .select2-results__option[aria-selected] { + cursor: pointer; } + +.select2-container--open .select2-dropdown { + left: 0; } + +.select2-container--open .select2-dropdown--above { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } + +.select2-container--open .select2-dropdown--below { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; } + +.select2-search--dropdown { + display: block; + padding: 4px; } + .select2-search--dropdown .select2-search__field { + padding: 4px; + width: 100%; + box-sizing: border-box; } + .select2-search--dropdown .select2-search__field::-webkit-search-cancel-button { + -webkit-appearance: none; } + .select2-search--dropdown.select2-search--hide { + display: none; } + +.select2-close-mask { + border: 0; + margin: 0; + padding: 0; + display: block; + position: fixed; + left: 0; + top: 0; + min-height: 100%; + min-width: 100%; + height: auto; + width: auto; + opacity: 0; + z-index: 99; + background-color: #fff; + filter: alpha(opacity=0); } + +.select2-hidden-accessible { + border: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(50%) !important; + clip-path: inset(50%) !important; + height: 1px !important; + overflow: hidden !important; + padding: 0 !important; + position: absolute !important; + width: 1px !important; + white-space: nowrap !important; } + +.select2-container--default .select2-selection--single { + background-color: #fff; + border: 1px solid #aaa; + border-radius: 4px; } + .select2-container--default .select2-selection--single .select2-selection__rendered { + color: #444; + line-height: 28px; } + .select2-container--default .select2-selection--single .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; } + .select2-container--default .select2-selection--single .select2-selection__placeholder { + color: #999; } + .select2-container--default .select2-selection--single .select2-selection__arrow { + height: 26px; + position: absolute; + top: 1px; + right: 1px; + width: 20px; } + .select2-container--default .select2-selection--single .select2-selection__arrow b { + border-color: #888 transparent transparent transparent; + border-style: solid; + border-width: 5px 4px 0 4px; + height: 0; + left: 50%; + margin-left: -4px; + margin-top: -2px; + position: absolute; + top: 50%; + width: 0; } + +.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear { + float: left; } + +.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow { + left: 1px; + right: auto; } + +.select2-container--default.select2-container--disabled .select2-selection--single { + background-color: #eee; + cursor: default; } + .select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear { + display: none; } + +.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b { + border-color: transparent transparent #888 transparent; + border-width: 0 4px 5px 4px; } + +.select2-container--default .select2-selection--multiple { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + cursor: text; } + .select2-container--default .select2-selection--multiple .select2-selection__rendered { + box-sizing: border-box; + list-style: none; + margin: 0; + padding: 0 5px; + width: 100%; } + .select2-container--default .select2-selection--multiple .select2-selection__rendered li { + list-style: none; } + .select2-container--default .select2-selection--multiple .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; + margin-top: 5px; + margin-right: 10px; + padding: 1px; } + .select2-container--default .select2-selection--multiple .select2-selection__choice { + background-color: #e4e4e4; + border: 1px solid #aaa; + border-radius: 4px; + cursor: default; + float: left; + margin-right: 5px; + margin-top: 5px; + padding: 0 5px; } + .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { + color: #999; + cursor: pointer; + display: inline-block; + font-weight: bold; + margin-right: 2px; } + .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { + color: #333; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline { + float: right; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice { + margin-left: 5px; + margin-right: auto; } + +.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { + margin-left: 2px; + margin-right: auto; } + +.select2-container--default.select2-container--focus .select2-selection--multiple { + border: solid black 1px; + outline: 0; } + +.select2-container--default.select2-container--disabled .select2-selection--multiple { + background-color: #eee; + cursor: default; } + +.select2-container--default.select2-container--disabled .select2-selection__choice__remove { + display: none; } + +.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple { + border-top-left-radius: 0; + border-top-right-radius: 0; } + +.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } + +.select2-container--default .select2-search--dropdown .select2-search__field { + border: 1px solid #aaa; } + +.select2-container--default .select2-search--inline .select2-search__field { + background: transparent; + border: none; + outline: 0; + box-shadow: none; + -webkit-appearance: textfield; } + +.select2-container--default .select2-results > .select2-results__options { + max-height: 200px; + overflow-y: auto; } + +.select2-container--default .select2-results__option[role=group] { + padding: 0; } + +.select2-container--default .select2-results__option[aria-disabled=true] { + color: #999; } + +.select2-container--default .select2-results__option[aria-selected=true] { + background-color: #ddd; } + +.select2-container--default .select2-results__option .select2-results__option { + padding-left: 1em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__group { + padding-left: 0; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option { + margin-left: -1em; + padding-left: 2em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -2em; + padding-left: 3em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -3em; + padding-left: 4em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -4em; + padding-left: 5em; } + .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { + margin-left: -5em; + padding-left: 6em; } + +.select2-container--default .select2-results__option--highlighted[aria-selected] { + background-color: #5897fb; + color: white; } + +.select2-container--default .select2-results__group { + cursor: default; + display: block; + padding: 6px; } + +.select2-container--classic .select2-selection--single { + background-color: #f7f7f7; + border: 1px solid #aaa; + border-radius: 4px; + outline: 0; + background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%); + background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%); + background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } + .select2-container--classic .select2-selection--single:focus { + border: 1px solid #5897fb; } + .select2-container--classic .select2-selection--single .select2-selection__rendered { + color: #444; + line-height: 28px; } + .select2-container--classic .select2-selection--single .select2-selection__clear { + cursor: pointer; + float: right; + font-weight: bold; + margin-right: 10px; } + .select2-container--classic .select2-selection--single .select2-selection__placeholder { + color: #999; } + .select2-container--classic .select2-selection--single .select2-selection__arrow { + background-color: #ddd; + border: none; + border-left: 1px solid #aaa; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + height: 26px; + position: absolute; + top: 1px; + right: 1px; + width: 20px; + background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%); + background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%); + background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); } + .select2-container--classic .select2-selection--single .select2-selection__arrow b { + border-color: #888 transparent transparent transparent; + border-style: solid; + border-width: 5px 4px 0 4px; + height: 0; + left: 50%; + margin-left: -4px; + margin-top: -2px; + position: absolute; + top: 50%; + width: 0; } + +.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear { + float: left; } + +.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow { + border: none; + border-right: 1px solid #aaa; + border-radius: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + left: 1px; + right: auto; } + +.select2-container--classic.select2-container--open .select2-selection--single { + border: 1px solid #5897fb; } + .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow { + background: transparent; + border: none; } + .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b { + border-color: transparent transparent #888 transparent; + border-width: 0 4px 5px 4px; } + +.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; + background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%); + background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%); + background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } + +.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%); + background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%); + background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); } + +.select2-container--classic .select2-selection--multiple { + background-color: white; + border: 1px solid #aaa; + border-radius: 4px; + cursor: text; + outline: 0; } + .select2-container--classic .select2-selection--multiple:focus { + border: 1px solid #5897fb; } + .select2-container--classic .select2-selection--multiple .select2-selection__rendered { + list-style: none; + margin: 0; + padding: 0 5px; } + .select2-container--classic .select2-selection--multiple .select2-selection__clear { + display: none; } + .select2-container--classic .select2-selection--multiple .select2-selection__choice { + background-color: #e4e4e4; + border: 1px solid #aaa; + border-radius: 4px; + cursor: default; + float: left; + margin-right: 5px; + margin-top: 5px; + padding: 0 5px; } + .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove { + color: #888; + cursor: pointer; + display: inline-block; + font-weight: bold; + margin-right: 2px; } + .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover { + color: #555; } + +.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { + float: right; + margin-left: 5px; + margin-right: auto; } + +.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { + margin-left: 2px; + margin-right: auto; } + +.select2-container--classic.select2-container--open .select2-selection--multiple { + border: 1px solid #5897fb; } + +.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple { + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; } + +.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple { + border-bottom: none; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; } + +.select2-container--classic .select2-search--dropdown .select2-search__field { + border: 1px solid #aaa; + outline: 0; } + +.select2-container--classic .select2-search--inline .select2-search__field { + outline: 0; + box-shadow: none; } + +.select2-container--classic .select2-dropdown { + background-color: white; + border: 1px solid transparent; } + +.select2-container--classic .select2-dropdown--above { + border-bottom: none; } + +.select2-container--classic .select2-dropdown--below { + border-top: none; } + +.select2-container--classic .select2-results > .select2-results__options { + max-height: 200px; + overflow-y: auto; } + +.select2-container--classic .select2-results__option[role=group] { + padding: 0; } + +.select2-container--classic .select2-results__option[aria-disabled=true] { + color: grey; } + +.select2-container--classic .select2-results__option--highlighted[aria-selected] { + background-color: #3875d7; + color: white; } + +.select2-container--classic .select2-results__group { + cursor: default; + display: block; + padding: 6px; } + +.select2-container--classic.select2-container--open .select2-dropdown { + border-color: #5897fb; } diff --git a/backend/staticfiles/admin/css/vendor/select2/select2.min.css b/backend/staticfiles/admin/css/vendor/select2/select2.min.css new file mode 100644 index 0000000..7c18ad5 --- /dev/null +++ b/backend/staticfiles/admin/css/vendor/select2/select2.min.css @@ -0,0 +1 @@ +.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px;padding:1px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right;margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb} diff --git a/backend/staticfiles/admin/css/widgets.css b/backend/staticfiles/admin/css/widgets.css new file mode 100644 index 0000000..538af2e --- /dev/null +++ b/backend/staticfiles/admin/css/widgets.css @@ -0,0 +1,613 @@ +/* SELECTOR (FILTER INTERFACE) */ + +.selector { + display: flex; + flex: 1; + gap: 0 10px; +} + +.selector select { + height: 17.2em; + flex: 1 0 auto; + overflow: scroll; + width: 100%; +} + +.selector-available, .selector-chosen { + display: flex; + flex-direction: column; + flex: 1 1; +} + +.selector-available-title, .selector-chosen-title { + border: 1px solid var(--border-color); + border-radius: 4px 4px 0 0; +} + +.selector .helptext { + font-size: 0.6875rem; +} + +.selector-chosen .list-footer-display { + border: 1px solid var(--border-color); + border-top: none; + border-radius: 0 0 4px 4px; + margin: 0 0 10px; + padding: 8px; + text-align: center; + background: var(--primary); + color: var(--header-link-color); + cursor: pointer; +} +.selector-chosen .list-footer-display__clear { + color: var(--breadcrumbs-fg); +} + +.selector-chosen-title { + background: var(--secondary); + color: var(--header-link-color); + padding: 8px; +} + +.aligned .selector-chosen-title label { + color: var(--header-link-color); + width: 100%; +} + +.selector-available-title { + background: var(--darkened-bg); + color: var(--body-quiet-color); + padding: 8px; +} + +.aligned .selector-available-title label { + width: 100%; +} + +.selector .selector-filter { + border: 1px solid var(--border-color); + border-width: 0 1px; + padding: 8px; + color: var(--body-quiet-color); + font-size: 0.625rem; + margin: 0; + text-align: left; + display: flex; + gap: 8px; +} + +.selector .selector-filter label, +.inline-group .aligned .selector .selector-filter label { + float: left; + margin: 7px 0 0; + width: 18px; + height: 18px; + padding: 0; + overflow: hidden; + line-height: 1; + min-width: auto; +} + +.selector-filter input { + flex-grow: 1; +} + +.selector ul.selector-chooser { + align-self: center; + width: 30px; + background-color: var(--selected-bg); + border-radius: 10px; + margin: 0; + padding: 0; + transform: translateY(-17px); +} + +.selector-chooser li { + margin: 0; + padding: 3px; + list-style-type: none; +} + +.selector select { + padding: 0 10px; + margin: 0 0 10px; + border-radius: 0 0 4px 4px; +} +.selector .selector-chosen--with-filtered select { + margin: 0; + border-radius: 0; + height: 14em; +} + +.selector .selector-chosen:not(.selector-chosen--with-filtered) .list-footer-display { + display: none; +} + +.selector-add, .selector-remove { + width: 24px; + height: 24px; + display: block; + text-indent: -3000px; + overflow: hidden; + cursor: default; + opacity: 0.55; + border: none; +} + +:enabled.selector-add, :enabled.selector-remove { + opacity: 1; +} + +:enabled.selector-add:hover, :enabled.selector-remove:hover { + cursor: pointer; +} + +.selector-add { + background: url(../img/selector-icons.svg) 0 -144px no-repeat; + background-size: 24px auto; +} + +:enabled.selector-add:focus, :enabled.selector-add:hover { + background-position: 0 -168px; +} + +.selector-remove { + background: url(../img/selector-icons.svg) 0 -96px no-repeat; + background-size: 24px auto; +} + +:enabled.selector-remove:focus, :enabled.selector-remove:hover { + background-position: 0 -120px; +} + +.selector-chooseall, .selector-clearall { + display: inline-block; + height: 16px; + text-align: left; + margin: 0 auto; + overflow: hidden; + font-weight: bold; + line-height: 16px; + color: var(--body-quiet-color); + text-decoration: none; + opacity: 0.55; + border: none; +} + +:enabled.selector-chooseall:focus, :enabled.selector-clearall:focus, +:enabled.selector-chooseall:hover, :enabled.selector-clearall:hover { + color: var(--link-fg); +} + +:enabled.selector-chooseall, :enabled.selector-clearall { + opacity: 1; +} + +:enabled.selector-chooseall:hover, :enabled.selector-clearall:hover { + cursor: pointer; +} + +.selector-chooseall { + padding: 0 18px 0 0; + background: url(../img/selector-icons.svg) right -160px no-repeat; + cursor: default; +} + +:enabled.selector-chooseall:focus, :enabled.selector-chooseall:hover { + background-position: 100% -176px; +} + +.selector-clearall { + padding: 0 0 0 18px; + background: url(../img/selector-icons.svg) 0 -128px no-repeat; + cursor: default; +} + +:enabled.selector-clearall:focus, :enabled.selector-clearall:hover { + background-position: 0 -144px; +} + +/* STACKED SELECTORS */ + +.stacked { + float: left; + width: 490px; + display: block; +} + +.stacked select { + width: 480px; + height: 10.1em; +} + +.stacked .selector-available, .stacked .selector-chosen { + width: 480px; +} + +.stacked .selector-available { + margin-bottom: 0; +} + +.stacked .selector-available input { + width: 422px; +} + +.stacked ul.selector-chooser { + display: flex; + height: 30px; + width: 64px; + margin: 0 0 10px 40%; + background-color: #eee; + border-radius: 10px; + transform: none; +} + +.stacked .selector-chooser li { + float: left; + padding: 3px 3px 3px 5px; +} + +.stacked .selector-chooseall, .stacked .selector-clearall { + display: none; +} + +.stacked .selector-add { + background: url(../img/selector-icons.svg) 0 -48px no-repeat; + background-size: 24px auto; + cursor: default; +} + +.stacked :enabled.selector-add { + background-position: 0 -48px; + cursor: pointer; +} + +.stacked :enabled.selector-add:focus, .stacked :enabled.selector-add:hover { + background-position: 0 -72px; + cursor: pointer; +} + +.stacked .selector-remove { + background: url(../img/selector-icons.svg) 0 0 no-repeat; + background-size: 24px auto; + cursor: default; +} + +.stacked :enabled.selector-remove { + background-position: 0 0px; + cursor: pointer; +} + +.stacked :enabled.selector-remove:focus, .stacked :enabled.selector-remove:hover { + background-position: 0 -24px; + cursor: pointer; +} + +.selector .help-icon { + background: url(../img/icon-unknown.svg) 0 0 no-repeat; + display: inline-block; + vertical-align: middle; + margin: -2px 0 0 2px; + width: 13px; + height: 13px; +} + +.selector .selector-chosen .help-icon { + background: url(../img/icon-unknown-alt.svg) 0 0 no-repeat; +} + +.selector .search-label-icon { + background: url(../img/search.svg) 0 0 no-repeat; + display: inline-block; + height: 1.125rem; + width: 1.125rem; +} + +/* DATE AND TIME */ + +p.datetime { + line-height: 20px; + margin: 0; + padding: 0; + color: var(--body-quiet-color); + font-weight: bold; +} + +.datetime span { + white-space: nowrap; + font-weight: normal; + font-size: 0.6875rem; + color: var(--body-quiet-color); +} + +.datetime input, .form-row .datetime input.vDateField, .form-row .datetime input.vTimeField { + margin-left: 5px; + margin-bottom: 4px; +} + +table p.datetime { + font-size: 0.6875rem; + margin-left: 0; + padding-left: 0; +} + +.datetimeshortcuts .clock-icon, .datetimeshortcuts .date-icon { + position: relative; + display: inline-block; + vertical-align: middle; + height: 24px; + width: 24px; + overflow: hidden; +} + +.datetimeshortcuts .clock-icon { + background: url(../img/icon-clock.svg) 0 0 no-repeat; + background-size: 24px auto; +} + +.datetimeshortcuts a:focus .clock-icon, +.datetimeshortcuts a:hover .clock-icon { + background-position: 0 -24px; +} + +.datetimeshortcuts .date-icon { + background: url(../img/icon-calendar.svg) 0 0 no-repeat; + background-size: 24px auto; + top: -1px; +} + +.datetimeshortcuts a:focus .date-icon, +.datetimeshortcuts a:hover .date-icon { + background-position: 0 -24px; +} + +.timezonewarning { + font-size: 0.6875rem; + color: var(--body-quiet-color); +} + +/* URL */ + +p.url { + line-height: 20px; + margin: 0; + padding: 0; + color: var(--body-quiet-color); + font-size: 0.6875rem; + font-weight: bold; +} + +.url a { + font-weight: normal; +} + +/* FILE UPLOADS */ + +p.file-upload { + line-height: 20px; + margin: 0; + padding: 0; + color: var(--body-quiet-color); + font-size: 0.6875rem; + font-weight: bold; +} + +.file-upload a { + font-weight: normal; +} + +.file-upload .deletelink { + margin-left: 5px; +} + +span.clearable-file-input label { + color: var(--body-fg); + font-size: 0.6875rem; + display: inline; + float: none; +} + +/* CALENDARS & CLOCKS */ + +.calendarbox, .clockbox { + margin: 5px auto; + font-size: 0.75rem; + width: 19em; + text-align: center; + background: var(--body-bg); + color: var(--body-fg); + border: 1px solid var(--hairline-color); + border-radius: 4px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15); + overflow: hidden; + position: relative; +} + +.clockbox { + width: auto; +} + +.calendar { + margin: 0; + padding: 0; +} + +.calendar table { + margin: 0; + padding: 0; + border-collapse: collapse; + background: white; + width: 100%; +} + +.calendar caption, .calendarbox h2 { + margin: 0; + text-align: center; + border-top: none; + font-weight: 700; + font-size: 0.75rem; + color: #333; + background: var(--accent); +} + +.calendar th { + padding: 8px 5px; + background: var(--darkened-bg); + border-bottom: 1px solid var(--border-color); + font-weight: 400; + font-size: 0.75rem; + text-align: center; + color: var(--body-quiet-color); +} + +.calendar td { + font-weight: 400; + font-size: 0.75rem; + text-align: center; + padding: 0; + border-top: 1px solid var(--hairline-color); + border-bottom: none; +} + +.calendar td.selected a { + background: var(--secondary); + color: var(--button-fg); +} + +.calendar td.nonday { + background: var(--darkened-bg); +} + +.calendar td.today a { + font-weight: 700; +} + +.calendar td a, .timelist a { + display: block; + font-weight: 400; + padding: 6px; + text-decoration: none; + color: var(--body-quiet-color); +} + +.calendar td a:focus, .timelist a:focus, +.calendar td a:hover, .timelist a:hover { + background: var(--primary); + color: white; +} + +.calendar td a:active, .timelist a:active { + background: var(--header-bg); + color: white; +} + +.calendarnav { + font-size: 0.625rem; + text-align: center; + color: #ccc; + margin: 0; + padding: 1px 3px; +} + +.calendarnav a:link, #calendarnav a:visited, +#calendarnav a:focus, #calendarnav a:hover { + color: var(--body-quiet-color); +} + +.calendar-shortcuts { + background: var(--body-bg); + color: var(--body-quiet-color); + font-size: 0.6875rem; + line-height: 0.6875rem; + border-top: 1px solid var(--hairline-color); + padding: 8px 0; +} + +.calendarbox .calendarnav-previous, .calendarbox .calendarnav-next { + display: block; + position: absolute; + top: 8px; + width: 15px; + height: 15px; + text-indent: -9999px; + padding: 0; +} + +.calendarnav-previous { + left: 10px; + background: url(../img/calendar-icons.svg) 0 0 no-repeat; +} + +.calendarnav-next { + right: 10px; + background: url(../img/calendar-icons.svg) 0 -15px no-repeat; +} + +.calendar-cancel { + margin: 0; + padding: 4px 0; + font-size: 0.75rem; + background: var(--close-button-bg); + border-top: 1px solid var(--border-color); + color: var(--button-fg); +} + +.calendar-cancel:focus, .calendar-cancel:hover { + background: var(--close-button-hover-bg); +} + +.calendar-cancel a { + color: var(--button-fg); + display: block; +} + +ul.timelist, .timelist li { + list-style-type: none; + margin: 0; + padding: 0; +} + +.timelist a { + padding: 2px; +} + +/* EDIT INLINE */ + +.inline-deletelink { + float: right; + text-indent: -9999px; + background: url(../img/inline-delete.svg) 0 0 no-repeat; + width: 1.5rem; + height: 1.5rem; + border: 0px none; + margin-bottom: .25rem; +} + +.inline-deletelink:focus, .inline-deletelink:hover { + cursor: pointer; +} + +/* RELATED WIDGET WRAPPER */ +.related-widget-wrapper { + display: flex; + gap: 0 10px; + flex-grow: 1; + flex-wrap: wrap; + margin-bottom: 5px; +} + +.related-widget-wrapper-link { + opacity: .6; + filter: grayscale(1); +} + +.related-widget-wrapper-link:link { + opacity: 1; + filter: grayscale(0); +} + +/* GIS MAPS */ +.dj_map { + width: 600px; + height: 400px; +} diff --git a/backend/staticfiles/admin/img/LICENSE b/backend/staticfiles/admin/img/LICENSE new file mode 100644 index 0000000..a4faaa1 --- /dev/null +++ b/backend/staticfiles/admin/img/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Code Charm Ltd + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/backend/staticfiles/admin/img/README.txt b/backend/staticfiles/admin/img/README.txt new file mode 100644 index 0000000..bf81f35 --- /dev/null +++ b/backend/staticfiles/admin/img/README.txt @@ -0,0 +1,7 @@ +All icons are taken from Font Awesome (https://fontawesome.com/) project. +The Font Awesome font is licensed under the SIL OFL 1.1: +- https://scripts.sil.org/OFL + +SVG icons source: https://github.com/encharm/Font-Awesome-SVG-PNG +Font-Awesome-SVG-PNG is licensed under the MIT license (see file license +in current folder). diff --git a/backend/staticfiles/admin/img/calendar-icons.svg b/backend/staticfiles/admin/img/calendar-icons.svg new file mode 100644 index 0000000..04c0274 --- /dev/null +++ b/backend/staticfiles/admin/img/calendar-icons.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + diff --git a/backend/staticfiles/admin/img/gis/move_vertex_off.svg b/backend/staticfiles/admin/img/gis/move_vertex_off.svg new file mode 100644 index 0000000..228854f --- /dev/null +++ b/backend/staticfiles/admin/img/gis/move_vertex_off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/backend/staticfiles/admin/img/gis/move_vertex_on.svg b/backend/staticfiles/admin/img/gis/move_vertex_on.svg new file mode 100644 index 0000000..96b87fd --- /dev/null +++ b/backend/staticfiles/admin/img/gis/move_vertex_on.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/backend/staticfiles/admin/img/icon-addlink.svg b/backend/staticfiles/admin/img/icon-addlink.svg new file mode 100644 index 0000000..8d5c6a3 --- /dev/null +++ b/backend/staticfiles/admin/img/icon-addlink.svg @@ -0,0 +1,3 @@ + + + diff --git a/backend/staticfiles/admin/img/icon-alert.svg b/backend/staticfiles/admin/img/icon-alert.svg new file mode 100644 index 0000000..e51ea83 --- /dev/null +++ b/backend/staticfiles/admin/img/icon-alert.svg @@ -0,0 +1,3 @@ + + + diff --git a/backend/staticfiles/admin/img/icon-calendar.svg b/backend/staticfiles/admin/img/icon-calendar.svg new file mode 100644 index 0000000..97910a9 --- /dev/null +++ b/backend/staticfiles/admin/img/icon-calendar.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/backend/staticfiles/admin/img/icon-changelink.svg b/backend/staticfiles/admin/img/icon-changelink.svg new file mode 100644 index 0000000..592b093 --- /dev/null +++ b/backend/staticfiles/admin/img/icon-changelink.svg @@ -0,0 +1,3 @@ + + + diff --git a/backend/staticfiles/admin/img/icon-clock.svg b/backend/staticfiles/admin/img/icon-clock.svg new file mode 100644 index 0000000..bf9985d --- /dev/null +++ b/backend/staticfiles/admin/img/icon-clock.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/backend/staticfiles/admin/img/icon-deletelink.svg b/backend/staticfiles/admin/img/icon-deletelink.svg new file mode 100644 index 0000000..4059b15 --- /dev/null +++ b/backend/staticfiles/admin/img/icon-deletelink.svg @@ -0,0 +1,3 @@ + + + diff --git a/backend/staticfiles/admin/img/icon-hidelink.svg b/backend/staticfiles/admin/img/icon-hidelink.svg new file mode 100644 index 0000000..2a8b404 --- /dev/null +++ b/backend/staticfiles/admin/img/icon-hidelink.svg @@ -0,0 +1,3 @@ + + + diff --git a/backend/staticfiles/admin/img/icon-no.svg b/backend/staticfiles/admin/img/icon-no.svg new file mode 100644 index 0000000..2e0d383 --- /dev/null +++ b/backend/staticfiles/admin/img/icon-no.svg @@ -0,0 +1,3 @@ + + + diff --git a/backend/staticfiles/admin/img/icon-unknown-alt.svg b/backend/staticfiles/admin/img/icon-unknown-alt.svg new file mode 100644 index 0000000..1c6b99f --- /dev/null +++ b/backend/staticfiles/admin/img/icon-unknown-alt.svg @@ -0,0 +1,3 @@ + + + diff --git a/backend/staticfiles/admin/img/icon-unknown.svg b/backend/staticfiles/admin/img/icon-unknown.svg new file mode 100644 index 0000000..50b4f97 --- /dev/null +++ b/backend/staticfiles/admin/img/icon-unknown.svg @@ -0,0 +1,3 @@ + + + diff --git a/backend/staticfiles/admin/img/icon-viewlink.svg b/backend/staticfiles/admin/img/icon-viewlink.svg new file mode 100644 index 0000000..a1ca1d3 --- /dev/null +++ b/backend/staticfiles/admin/img/icon-viewlink.svg @@ -0,0 +1,3 @@ + + + diff --git a/backend/staticfiles/admin/img/icon-yes.svg b/backend/staticfiles/admin/img/icon-yes.svg new file mode 100644 index 0000000..5883d87 --- /dev/null +++ b/backend/staticfiles/admin/img/icon-yes.svg @@ -0,0 +1,3 @@ + + + diff --git a/backend/staticfiles/admin/img/inline-delete.svg b/backend/staticfiles/admin/img/inline-delete.svg new file mode 100644 index 0000000..8751150 --- /dev/null +++ b/backend/staticfiles/admin/img/inline-delete.svg @@ -0,0 +1,3 @@ + + + diff --git a/backend/staticfiles/admin/img/search.svg b/backend/staticfiles/admin/img/search.svg new file mode 100644 index 0000000..c8c69b2 --- /dev/null +++ b/backend/staticfiles/admin/img/search.svg @@ -0,0 +1,3 @@ + + + diff --git a/backend/staticfiles/admin/img/selector-icons.svg b/backend/staticfiles/admin/img/selector-icons.svg new file mode 100644 index 0000000..926b8e2 --- /dev/null +++ b/backend/staticfiles/admin/img/selector-icons.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/backend/staticfiles/admin/img/sorting-icons.svg b/backend/staticfiles/admin/img/sorting-icons.svg new file mode 100644 index 0000000..7c31ec9 --- /dev/null +++ b/backend/staticfiles/admin/img/sorting-icons.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/backend/staticfiles/admin/img/tooltag-add.svg b/backend/staticfiles/admin/img/tooltag-add.svg new file mode 100644 index 0000000..1ca64ae --- /dev/null +++ b/backend/staticfiles/admin/img/tooltag-add.svg @@ -0,0 +1,3 @@ + + + diff --git a/backend/staticfiles/admin/img/tooltag-arrowright.svg b/backend/staticfiles/admin/img/tooltag-arrowright.svg new file mode 100644 index 0000000..b664d61 --- /dev/null +++ b/backend/staticfiles/admin/img/tooltag-arrowright.svg @@ -0,0 +1,3 @@ + + + diff --git a/backend/staticfiles/admin/js/SelectBox.js b/backend/staticfiles/admin/js/SelectBox.js new file mode 100644 index 0000000..3db4ec7 --- /dev/null +++ b/backend/staticfiles/admin/js/SelectBox.js @@ -0,0 +1,116 @@ +'use strict'; +{ + const SelectBox = { + cache: {}, + init: function(id) { + const box = document.getElementById(id); + SelectBox.cache[id] = []; + const cache = SelectBox.cache[id]; + for (const node of box.options) { + cache.push({value: node.value, text: node.text, displayed: 1}); + } + }, + redisplay: function(id) { + // Repopulate HTML select box from cache + const box = document.getElementById(id); + const scroll_value_from_top = box.scrollTop; + box.innerHTML = ''; + for (const node of SelectBox.cache[id]) { + if (node.displayed) { + const new_option = new Option(node.text, node.value, false, false); + // Shows a tooltip when hovering over the option + new_option.title = node.text; + box.appendChild(new_option); + } + } + box.scrollTop = scroll_value_from_top; + }, + filter: function(id, text) { + // Redisplay the HTML select box, displaying only the choices containing ALL + // the words in text. (It's an AND search.) + const tokens = text.toLowerCase().split(/\s+/); + for (const node of SelectBox.cache[id]) { + node.displayed = 1; + const node_text = node.text.toLowerCase(); + for (const token of tokens) { + if (!node_text.includes(token)) { + node.displayed = 0; + break; // Once the first token isn't found we're done + } + } + } + SelectBox.redisplay(id); + }, + get_hidden_node_count(id) { + const cache = SelectBox.cache[id] || []; + return cache.filter(node => node.displayed === 0).length; + }, + delete_from_cache: function(id, value) { + let delete_index = null; + const cache = SelectBox.cache[id]; + for (const [i, node] of cache.entries()) { + if (node.value === value) { + delete_index = i; + break; + } + } + cache.splice(delete_index, 1); + }, + add_to_cache: function(id, option) { + SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1}); + }, + cache_contains: function(id, value) { + // Check if an item is contained in the cache + for (const node of SelectBox.cache[id]) { + if (node.value === value) { + return true; + } + } + return false; + }, + move: function(from, to) { + const from_box = document.getElementById(from); + for (const option of from_box.options) { + const option_value = option.value; + if (option.selected && SelectBox.cache_contains(from, option_value)) { + SelectBox.add_to_cache(to, {value: option_value, text: option.text, displayed: 1}); + SelectBox.delete_from_cache(from, option_value); + } + } + SelectBox.redisplay(from); + SelectBox.redisplay(to); + }, + move_all: function(from, to) { + const from_box = document.getElementById(from); + for (const option of from_box.options) { + const option_value = option.value; + if (SelectBox.cache_contains(from, option_value)) { + SelectBox.add_to_cache(to, {value: option_value, text: option.text, displayed: 1}); + SelectBox.delete_from_cache(from, option_value); + } + } + SelectBox.redisplay(from); + SelectBox.redisplay(to); + }, + sort: function(id) { + SelectBox.cache[id].sort(function(a, b) { + a = a.text.toLowerCase(); + b = b.text.toLowerCase(); + if (a > b) { + return 1; + } + if (a < b) { + return -1; + } + return 0; + } ); + }, + select_all: function(id) { + const box = document.getElementById(id); + for (const option of box.options) { + option.selected = true; + } + } + }; + window.SelectBox = SelectBox; +} diff --git a/backend/staticfiles/admin/js/SelectFilter2.js b/backend/staticfiles/admin/js/SelectFilter2.js new file mode 100644 index 0000000..08d47fc --- /dev/null +++ b/backend/staticfiles/admin/js/SelectFilter2.js @@ -0,0 +1,307 @@ +/*global SelectBox, gettext, ngettext, interpolate, quickElement, SelectFilter*/ +/* +SelectFilter2 - Turns a multiple-select box into a filter interface. + +Requires core.js and SelectBox.js. +*/ +'use strict'; +{ + window.SelectFilter = { + init: function(field_id, field_name, is_stacked) { + if (field_id.match(/__prefix__/)) { + // Don't initialize on empty forms. + return; + } + const from_box = document.getElementById(field_id); + from_box.id += '_from'; // change its ID + from_box.className = 'filtered'; + from_box.setAttribute('aria-labelledby', field_id + '_from_title'); + + for (const p of from_box.parentNode.getElementsByTagName('p')) { + if (p.classList.contains("info")) { + // Remove

      , because it just gets in the way. + from_box.parentNode.removeChild(p); + } else if (p.classList.contains("help")) { + // Move help text up to the top so it isn't below the select + // boxes or wrapped off on the side to the right of the add + // button: + from_box.parentNode.insertBefore(p, from_box.parentNode.firstChild); + } + } + + //

      or
      + const selector_div = quickElement('div', from_box.parentNode); + // Make sure the selector div is at the beginning so that the + // add link would be displayed to the right of the widget. + from_box.parentNode.prepend(selector_div); + selector_div.className = is_stacked ? 'selector stacked' : 'selector'; + + //
      + const selector_available = quickElement('div', selector_div); + selector_available.className = 'selector-available'; + const selector_available_title = quickElement('div', selector_available); + selector_available_title.id = field_id + '_from_title'; + selector_available_title.className = 'selector-available-title'; + quickElement('label', selector_available_title, interpolate(gettext('Available %s') + ' ', [field_name]), 'for', field_id + '_from'); + quickElement( + 'p', + selector_available_title, + interpolate(gettext('Choose %s by selecting them and then select the "Choose" arrow button.'), [field_name]), + 'class', 'helptext' + ); + + const filter_p = quickElement('p', selector_available, '', 'id', field_id + '_filter'); + filter_p.className = 'selector-filter'; + + const search_filter_label = quickElement('label', filter_p, '', 'for', field_id + '_input'); + + quickElement( + 'span', search_filter_label, '', + 'class', 'help-tooltip search-label-icon', + 'aria-label', interpolate(gettext("Type into this box to filter down the list of available %s."), [field_name]) + ); + + filter_p.appendChild(document.createTextNode(' ')); + + const filter_input = quickElement('input', filter_p, '', 'type', 'text', 'placeholder', gettext("Filter")); + filter_input.id = field_id + '_input'; + + selector_available.appendChild(from_box); + const choose_all = quickElement( + 'button', + selector_available, + interpolate(gettext('Choose all %s'), [field_name]), + 'id', field_id + '_add_all', + 'class', 'selector-chooseall' + ); + + //

      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Ã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 z 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