From 45962e9886f2423cb3fed0027968fec4b109b819 Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sun, 6 Oct 2024 22:49:57 +0200 Subject: [PATCH 01/53] Update pyodide, pyodide-worker-runner, python, selenium, snoop, and other dependencies (#481) --- .github/workflows/workflow.yml | 2 +- README.md | 2 +- core/core_imports.txt | 2 - core/utils.py | 8 +- frontend/craco.config.js | 8 +- frontend/package-lock.json | 912 ++++++++++++++++++++- frontend/package.json | 5 +- poetry.lock | 476 ++++++++--- pyproject.toml | 4 +- tests/golden_files/en/test_transcript.json | 28 +- tests/test_frontend.py | 124 ++- tests/test_steps.py | 2 - 12 files changed, 1336 insertions(+), 237 deletions(-) diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index c397f07c..11cb1cf2 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.11.2' + python-version: '3.12.1' - name: Set up Node uses: actions/setup-node@v4 with: diff --git a/README.md b/README.md index a7a8134c..a06089f3 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ Several debuggers are provided, including [snoop](https://github.com/alexmojaki/ ## Running locally 1. Fork this repo, `git clone` it, and enter the top-level `futurecoder` folder. -2. Install Python 3.11.2 and [poetry](https://python-poetry.org/docs/#installation). +2. Install Python 3.12.1 and [poetry](https://python-poetry.org/docs/#installation). 3. Run `poetry install` to install Python dependencies. 4. Run `./scripts/generate.sh`. This will generate various static files from Python used by the frontend and run some tests. Repeat this step whenever you change Python files. 5. In the `frontend` folder: diff --git a/core/core_imports.txt b/core/core_imports.txt index 66cf3097..52944d9d 100644 --- a/core/core_imports.txt +++ b/core/core_imports.txt @@ -8,8 +8,6 @@ executing friendly_traceback littleutils markdown -packaging -pkg_resources pure_eval pyflakes pygments diff --git a/core/utils.py b/core/utils.py index 16381b81..b680c42f 100644 --- a/core/utils.py +++ b/core/utils.py @@ -8,7 +8,7 @@ from itertools import combinations from random import shuffle from textwrap import dedent -from tokenize import generate_tokens +from tokenize import generate_tokens, TokenError from types import ModuleType from typing import Union @@ -32,9 +32,10 @@ def qa_error(message, cls=AssertionError): def stub_module(name): - assert name not in sys.modules sys.modules[name] = ModuleType(name) + +assert "selenium" in sys.modules or not ("urllib3" in sys.modules or "certifi" in sys.modules) stub_module("urllib3") stub_module("certifi") @@ -309,6 +310,7 @@ def wrapper(*args, **kwargs): if TESTING: raise return internal_error_result(e) + return wrapper @@ -324,7 +326,7 @@ def split_into_tokens_gen(s): linenos = asttokens.LineNumbers(s) try: tokens = list(generate_tokens(StringIO(s).readline)) - except SyntaxError: + except (SyntaxError, TokenError): yield from s return for t1, t2 in zip(tokens, tokens[1:]): diff --git a/frontend/craco.config.js b/frontend/craco.config.js index 96b665a0..ecd1075f 100644 --- a/frontend/craco.config.js +++ b/frontend/craco.config.js @@ -1,8 +1,14 @@ const path = require('path'); +const {PyodidePlugin} = require("@pyodide/webpack-plugin"); module.exports = { - // Output to ./course (instead of ./build) webpack: { + plugins: { + add: [ + new PyodidePlugin(), + ] + }, + // Output to ./course (instead of ./build) configure: (webpackConfig, {env, paths}) => { paths.appBuild = webpackConfig.output.path = path.resolve('course'); return webpackConfig; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a4ab426a..e63f491a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -24,8 +24,8 @@ "lodash": "^4.17.21", "p-retry": "^5.0.0", "prop-types": "^15.7.2", - "pyodide": "^0.23.2", - "pyodide-worker-runner": "^1.3.3", + "pyodide": "^0.26.2", + "pyodide-worker-runner": "^1.4.0", "react": "^17.0.2", "react-ace": "^10.0.0", "react-beautiful-dnd": "^13.1.0", @@ -47,6 +47,7 @@ "sync-message": "^0.0.10" }, "devDependencies": { + "@pyodide/webpack-plugin": "^1.3.2", "raw-loader": "^4.0.2", "worker-loader": "^3.0.8" }, @@ -2214,6 +2215,374 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", @@ -3681,6 +4050,32 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" }, + "node_modules/@pyodide/webpack-plugin": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@pyodide/webpack-plugin/-/webpack-plugin-1.3.2.tgz", + "integrity": "sha512-Kz6GRcgBO/xounBCVD9aztxqcO+BVFPh8zp6rcQIH0xoKPjG8s38AJJdSC2Ai8yhFCaYPGAP3NcT7qMlO44+VQ==", + "dev": true, + "dependencies": { + "acorn-walk": "^8.2.0", + "copy-webpack-plugin": "^11.0.0", + "esbuild": "^0.19.5" + }, + "peerDependencies": { + "pyodide": ">=0.21.3" + } + }, + "node_modules/@pyodide/webpack-plugin/node_modules/acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -4762,9 +5157,9 @@ "integrity": "sha512-NBOQlm9+7RBqRqZwimpgquaLeTJFayqb9UEPtTkpC3TkkwDnlsT/TwsCC0svjt9kEZ6G9mH5AEOHSz6Q/HrzQQ==" }, "node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "bin": { "acorn": "bin/acorn" }, @@ -5503,11 +5898,6 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "node_modules/base-64": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", - "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==" - }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -6143,6 +6533,114 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/copy-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/copy-webpack-plugin/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/core-js": { "version": "3.27.1", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.27.1.tgz", @@ -7178,6 +7676,44 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -8091,9 +8627,9 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -8126,6 +8662,12 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "dev": true + }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -14309,25 +14851,26 @@ } }, "node_modules/pyodide": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/pyodide/-/pyodide-0.23.2.tgz", - "integrity": "sha512-GK4YDZVgzfAXK/7X0IiCI+142k0Ah/HwYTzDHtG8zC47dflWYuPozeFbOngShuL1M9Un5sCmHFqiH3boxJv0pQ==", + "version": "0.26.2", + "resolved": "https://registry.npmjs.org/pyodide/-/pyodide-0.26.2.tgz", + "integrity": "sha512-8VCRdFX83gBsWs6XP2rhG8HMaB+JaVyyav4q/EMzoV8fXH8HN6T5IISC92SNma6i1DRA3SVXA61S1rJcB8efgA==", "dependencies": { - "base-64": "^1.0.0", - "node-fetch": "^2.6.1", "ws": "^8.5.0" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/pyodide-worker-runner": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/pyodide-worker-runner/-/pyodide-worker-runner-1.3.3.tgz", - "integrity": "sha512-6SyvbsfSis5u4dgcnOo5Xzr9shp2Mc3f2NtoL9B1xWWwKRQqYHNqAvQkf2S0ZfyRd43FS4M/Kp797unKirR98A==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pyodide-worker-runner/-/pyodide-worker-runner-1.4.0.tgz", + "integrity": "sha512-t9v49q4sWSlywNMoMPw1Zs9FBpCP70wkHB5zzzmOErIxPS3w3HVxiwSI/ldpT1GH1exLEPGz16YHGVa65XqdHw==", "dependencies": { "p-retry": "^5.0.0" }, "peerDependencies": { "comsync": "*", - "pyodide": "^0.23.2" + "pyodide": "*" } }, "node_modules/pyodide/node_modules/ws": { @@ -19247,6 +19790,167 @@ "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==", "requires": {} }, + "@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "dev": true, + "optional": true + }, "@eslint/eslintrc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", @@ -20396,6 +21100,28 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" }, + "@pyodide/webpack-plugin": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@pyodide/webpack-plugin/-/webpack-plugin-1.3.2.tgz", + "integrity": "sha512-Kz6GRcgBO/xounBCVD9aztxqcO+BVFPh8zp6rcQIH0xoKPjG8s38AJJdSC2Ai8yhFCaYPGAP3NcT7qMlO44+VQ==", + "dev": true, + "requires": { + "acorn-walk": "^8.2.0", + "copy-webpack-plugin": "^11.0.0", + "esbuild": "^0.19.5" + }, + "dependencies": { + "acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "dev": true, + "requires": { + "acorn": "^8.11.0" + } + } + } + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -21223,9 +21949,9 @@ "integrity": "sha512-NBOQlm9+7RBqRqZwimpgquaLeTJFayqb9UEPtTkpC3TkkwDnlsT/TwsCC0svjt9kEZ6G9mH5AEOHSz6Q/HrzQQ==" }, "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==" + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==" }, "acorn-globals": { "version": "6.0.0", @@ -21764,11 +22490,6 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "base-64": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", - "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==" - }, "batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -22247,6 +22968,80 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "dev": true, + "requires": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "requires": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + } + }, + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true + } + } + }, "core-js": { "version": "3.27.1", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.27.1.tgz", @@ -22992,6 +23787,37 @@ "is-symbol": "^1.0.2" } }, + "esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "requires": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -23647,9 +24473,9 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -23678,6 +24504,12 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, + "fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "dev": true + }, "fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -27984,12 +28816,10 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "pyodide": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/pyodide/-/pyodide-0.23.2.tgz", - "integrity": "sha512-GK4YDZVgzfAXK/7X0IiCI+142k0Ah/HwYTzDHtG8zC47dflWYuPozeFbOngShuL1M9Un5sCmHFqiH3boxJv0pQ==", + "version": "0.26.2", + "resolved": "https://registry.npmjs.org/pyodide/-/pyodide-0.26.2.tgz", + "integrity": "sha512-8VCRdFX83gBsWs6XP2rhG8HMaB+JaVyyav4q/EMzoV8fXH8HN6T5IISC92SNma6i1DRA3SVXA61S1rJcB8efgA==", "requires": { - "base-64": "^1.0.0", - "node-fetch": "^2.6.1", "ws": "^8.5.0" }, "dependencies": { @@ -28002,9 +28832,9 @@ } }, "pyodide-worker-runner": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/pyodide-worker-runner/-/pyodide-worker-runner-1.3.3.tgz", - "integrity": "sha512-6SyvbsfSis5u4dgcnOo5Xzr9shp2Mc3f2NtoL9B1xWWwKRQqYHNqAvQkf2S0ZfyRd43FS4M/Kp797unKirR98A==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pyodide-worker-runner/-/pyodide-worker-runner-1.4.0.tgz", + "integrity": "sha512-t9v49q4sWSlywNMoMPw1Zs9FBpCP70wkHB5zzzmOErIxPS3w3HVxiwSI/ldpT1GH1exLEPGz16YHGVa65XqdHw==", "requires": { "p-retry": "^5.0.0" } diff --git a/frontend/package.json b/frontend/package.json index fa14b951..85fa52c4 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -24,8 +24,8 @@ "lodash": "^4.17.21", "p-retry": "^5.0.0", "prop-types": "^15.7.2", - "pyodide": "^0.23.2", - "pyodide-worker-runner": "^1.3.3", + "pyodide": "^0.26.2", + "pyodide-worker-runner": "^1.4.0", "react": "^17.0.2", "react-ace": "^10.0.0", "react-beautiful-dnd": "^13.1.0", @@ -67,6 +67,7 @@ ] }, "devDependencies": { + "@pyodide/webpack-plugin": "^1.3.2", "raw-loader": "^4.0.2", "worker-loader": "^3.0.8" } diff --git a/poetry.lock b/poetry.lock index b690958b..242a3e3d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -13,20 +13,40 @@ files = [ [[package]] name = "asttokens" -version = "2.1.0" +version = "2.4.1" description = "Annotate AST trees with source code positions" optional = false python-versions = "*" files = [ - {file = "asttokens-2.1.0-py2.py3-none-any.whl", hash = "sha256:1b28ed85e254b724439afc783d4bee767f780b936c3fe8b3275332f42cf5f561"}, - {file = "asttokens-2.1.0.tar.gz", hash = "sha256:4aa76401a151c8cc572d906aad7aea2a841780834a19d780f4321c0fe1b54635"}, + {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, + {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, ] [package.dependencies] -six = "*" +six = ">=1.12.0" + +[package.extras] +astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] +test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] + +[[package]] +name = "attrs" +version = "24.2.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, + {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, +] [package.extras] -test = ["astroid (<=2.5.3)", "pytest"] +benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "bettererrormessages" @@ -50,7 +70,7 @@ develop = false [package.dependencies] asttokens = "*" -cheap-repr = "*" +cheap_repr = "*" littleutils = ">=0.2" [package.extras] @@ -64,28 +84,107 @@ resolved_reference = "81273e689c5460a0b44ec28840e6adcf7fd6dad4" [[package]] name = "certifi" -version = "2023.7.22" +version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, +] + +[[package]] +name = "cffi" +version = "1.17.0" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb"}, + {file = "cffi-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a"}, + {file = "cffi-1.17.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42"}, + {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d"}, + {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2"}, + {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab"}, + {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b"}, + {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206"}, + {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa"}, + {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f"}, + {file = "cffi-1.17.0-cp310-cp310-win32.whl", hash = "sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc"}, + {file = "cffi-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2"}, + {file = "cffi-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720"}, + {file = "cffi-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9"}, + {file = "cffi-1.17.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb"}, + {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424"}, + {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d"}, + {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8"}, + {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6"}, + {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91"}, + {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8"}, + {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb"}, + {file = "cffi-1.17.0-cp311-cp311-win32.whl", hash = "sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9"}, + {file = "cffi-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0"}, + {file = "cffi-1.17.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc"}, + {file = "cffi-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59"}, + {file = "cffi-1.17.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb"}, + {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195"}, + {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e"}, + {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828"}, + {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150"}, + {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a"}, + {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885"}, + {file = "cffi-1.17.0-cp312-cp312-win32.whl", hash = "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492"}, + {file = "cffi-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2"}, + {file = "cffi-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118"}, + {file = "cffi-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7"}, + {file = "cffi-1.17.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377"}, + {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb"}, + {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555"}, + {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204"}, + {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f"}, + {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0"}, + {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4"}, + {file = "cffi-1.17.0-cp313-cp313-win32.whl", hash = "sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a"}, + {file = "cffi-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7"}, + {file = "cffi-1.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c"}, + {file = "cffi-1.17.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e"}, + {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b"}, + {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e"}, + {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401"}, + {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c"}, + {file = "cffi-1.17.0-cp38-cp38-win32.whl", hash = "sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499"}, + {file = "cffi-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c"}, + {file = "cffi-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2"}, + {file = "cffi-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759"}, + {file = "cffi-1.17.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4"}, + {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82"}, + {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf"}, + {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058"}, + {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932"}, + {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693"}, + {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3"}, + {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4"}, + {file = "cffi-1.17.0-cp39-cp39-win32.whl", hash = "sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb"}, + {file = "cffi-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29"}, + {file = "cffi-1.17.0.tar.gz", hash = "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76"}, ] +[package.dependencies] +pycparser = "*" + [[package]] name = "cheap-repr" -version = "0.5.1" +version = "0.5.2" description = "Better version of repr/reprlib for short, cheap string representations." optional = false python-versions = "*" files = [ - {file = "cheap_repr-0.5.1-py2.py3-none-any.whl", hash = "sha256:30096998aeb49367a4a153988d7a99dce9dc59bbdd4b19740da6b4f3f97cf2ff"}, - {file = "cheap_repr-0.5.1.tar.gz", hash = "sha256:31ec63b9d8394aa23d746c8376c8307f75f9fca0b983566b8bcf13cc661fe6dd"}, + {file = "cheap_repr-0.5.2-py2.py3-none-any.whl", hash = "sha256:537ec1991bfee885c13c6d473afd110a408e039cde26882e95bf92761556ab6e"}, + {file = "cheap_repr-0.5.2.tar.gz", hash = "sha256:001a5cf8adb0305c7ad3152c5f776040ac2a559d97f85770cebcb28c6ca5a30f"}, ] [package.extras] -tests = ["Django", "Django (<2)", "Django (<3)", "chainmap", "numpy (>=1.16.3)", "numpy (>=1.16.3,<1.17)", "numpy (>=1.16.3,<1.19)", "pandas (>=0.24.2)", "pandas (>=0.24.2,<0.25)", "pandas (>=0.24.2,<0.26)", "pytest"] +tests = ["Django", "numpy (>=1.16.3)", "pandas (>=0.24.2)", "pytest"] [[package]] name = "colorama" @@ -100,43 +199,43 @@ files = [ [[package]] name = "executing" -version = "1.2.0" +version = "2.1.0" description = "Get the currently executing AST node of a frame, and other information" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "executing-1.2.0-py2.py3-none-any.whl", hash = "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc"}, - {file = "executing-1.2.0.tar.gz", hash = "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107"}, + {file = "executing-2.1.0-py2.py3-none-any.whl", hash = "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf"}, + {file = "executing-2.1.0.tar.gz", hash = "sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab"}, ] [package.extras] -tests = ["asttokens", "littleutils", "pytest", "rich"] +tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] [[package]] name = "flake8" -version = "3.8.3" +version = "3.9.2" description = "the modular source code checker: pep8 pyflakes and co" optional = true -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ - {file = "flake8-3.8.3-py2.py3-none-any.whl", hash = "sha256:15e351d19611c887e482fb960eae4d44845013cc142d42896e9862f775d8cf5c"}, - {file = "flake8-3.8.3.tar.gz", hash = "sha256:f04b9fcbac03b0a3e58c0ab3a0ecc462e023a9faf046d57794184028123aa208"}, + {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, + {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, ] [package.dependencies] mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.6.0a1,<2.7.0" -pyflakes = ">=2.2.0,<2.3.0" +pycodestyle = ">=2.7.0,<2.8.0" +pyflakes = ">=2.3.0,<2.4.0" [[package]] name = "friendly-traceback" -version = "0.7.48" +version = "0.7.61" description = "Friendlier tracebacks in any language." optional = false python-versions = ">=3.6" files = [ - {file = "friendly-traceback-0.7.48.tar.gz", hash = "sha256:0384c49eee16df41b3356bf3071b031eaa85cda5b4b41420cbbe09d9ff8270a0"}, - {file = "friendly_traceback-0.7.48-py3-none-any.whl", hash = "sha256:5b0a917ef4a1e750e92015757870f50cab83c90002863f77bbbf41a3d26e67af"}, + {file = "friendly-traceback-0.7.61.tar.gz", hash = "sha256:8ca149ea4effa114a9d4354078d0252dbc53e291cdcc63f23e34b8fb65ba15f3"}, + {file = "friendly_traceback-0.7.61-py3-none-any.whl", hash = "sha256:6945346e49a4ef72c855723f09a6d9b1b4fbf43759d4529f779f29259efab9f7"}, ] [package.dependencies] @@ -144,7 +243,29 @@ asttokens = ">=2.0.4" executing = ">=1.1.0" pure-eval = ">=0.2.1" six = ">=1.16" -stack-data = ">=0.5.1" +stack-data = ">=0.6.2" + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "idna" +version = "3.8" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, + {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, +] [[package]] name = "iniconfig" @@ -159,44 +280,42 @@ files = [ [[package]] name = "isort" -version = "5.1.4" +version = "5.13.2" description = "A Python utility / library to sort Python imports." optional = false -python-versions = ">=3.6,<4.0" +python-versions = ">=3.8.0" files = [ - {file = "isort-5.1.4-py3-none-any.whl", hash = "sha256:ae3007f72a2e9da36febd3454d8be4b175d6ca17eb765841d5fe3d038aede79d"}, - {file = "isort-5.1.4.tar.gz", hash = "sha256:145072eedc4927cc9c1f9478f2d83b2fc1e6469df4129c02ef4e8c742207a46c"}, + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, ] [package.extras] -pipfile-deprecated-finder = ["pipreqs", "requirementslib", "tomlkit (>=0.5.3)"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] +colors = ["colorama (>=0.4.6)"] [[package]] name = "littleutils" -version = "0.2.2" +version = "0.2.4" description = "Small personal collection of python utility functions" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "littleutils-0.2.2.tar.gz", hash = "sha256:e6cae3a4203e530d51c9667ed310ffe3b1948f2876e3d69605b3de4b7d96916f"}, + {file = "littleutils-0.2.4-py3-none-any.whl", hash = "sha256:d10d5fe2e107c49fe2fc2904a08d6e5a302b41f8405921835ffcc323782d5dbc"}, + {file = "littleutils-0.2.4.tar.gz", hash = "sha256:c7835b01020ced42e291118b7d78fb16bc2d9a1b4f3f42f3cb3787bb4da53d19"}, ] [[package]] name = "markdown" -version = "3.2.1" -description = "Python implementation of Markdown." +version = "3.7" +description = "Python implementation of John Gruber's Markdown." optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "Markdown-3.2.1-py2.py3-none-any.whl", hash = "sha256:e4795399163109457d4c5af2183fbe6b60326c17cfdf25ce6e7474c6624f725d"}, - {file = "Markdown-3.2.1.tar.gz", hash = "sha256:90fee683eeabe1a92e149f7ba74e5ccdc81cd397bd6c516d93a8da0ef90b6902"}, + {file = "Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"}, + {file = "markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2"}, ] -[package.dependencies] -setuptools = ">=36" - [package.extras] +docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] testing = ["coverage", "pyyaml"] [[package]] @@ -210,26 +329,40 @@ files = [ {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] +[[package]] +name = "outcome" +version = "1.3.0.post0" +description = "Capture the outcome of Python function calls." +optional = false +python-versions = ">=3.7" +files = [ + {file = "outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b"}, + {file = "outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8"}, +] + +[package.dependencies] +attrs = ">=19.2.0" + [[package]] name = "packaging" -version = "23.1" +version = "24.1" description = "Core utilities for Python packages" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, - {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, + {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, + {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] [package.extras] @@ -238,24 +371,24 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "polib" -version = "1.1.1" +version = "1.2.0" description = "A library to manipulate gettext files (po and mo files)." optional = false python-versions = "*" files = [ - {file = "polib-1.1.1-py2.py3-none-any.whl", hash = "sha256:d3ee85e0c6788f789353416b1612c6c92d75fe6ccfac0029711974d6abd0f86d"}, - {file = "polib-1.1.1.tar.gz", hash = "sha256:e02c355ae5e054912e3b0d16febc56510eff7e49d60bf22aecb463bd2f2a2dfa"}, + {file = "polib-1.2.0-py2.py3-none-any.whl", hash = "sha256:1c77ee1b81feb31df9bca258cbc58db1bbb32d10214b173882452c73af06d62d"}, + {file = "polib-1.2.0.tar.gz", hash = "sha256:f3ef94aefed6e183e342a8a269ae1fc4742ba193186ad76f175938621dbfc26b"}, ] [[package]] name = "pure-eval" -version = "0.2.2" +version = "0.2.3" description = "Safely evaluate AST nodes without side effects" optional = false python-versions = "*" files = [ - {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, - {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, + {file = "pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0"}, + {file = "pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42"}, ] [package.extras] @@ -263,39 +396,62 @@ tests = ["pytest"] [[package]] name = "pycodestyle" -version = "2.6.0" +version = "2.7.0" description = "Python style guide checker" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ - {file = "pycodestyle-2.6.0-py2.py3-none-any.whl", hash = "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367"}, - {file = "pycodestyle-2.6.0.tar.gz", hash = "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"}, + {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, + {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, +] + +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] [[package]] name = "pyflakes" -version = "2.2.0" +version = "2.3.1" description = "passive checker of Python programs" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ - {file = "pyflakes-2.2.0-py2.py3-none-any.whl", hash = "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92"}, - {file = "pyflakes-2.2.0.tar.gz", hash = "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"}, + {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, + {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, ] [[package]] name = "pygments" -version = "2.15.0" +version = "2.18.0" description = "Pygments is a syntax highlighting package written in Python." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "Pygments-2.15.0-py3-none-any.whl", hash = "sha256:77a3299119af881904cd5ecd1ac6a66214b6e9bed1f2db16993b54adede64094"}, - {file = "Pygments-2.15.0.tar.gz", hash = "sha256:f7e36cffc4c517fbc252861b9a6e4644ca0e5abadf9a113c72d1358ad09b9500"}, + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, ] [package.extras] -plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pysocks" +version = "1.7.1" +description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "PySocks-1.7.1-py27-none-any.whl", hash = "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299"}, + {file = "PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5"}, + {file = "PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"}, +] [[package]] name = "pytest" @@ -333,27 +489,32 @@ tests = ["pytest", "snoop"] [[package]] name = "selenium" -version = "3.141.0" -description = "Python bindings for Selenium" +version = "4.24.0" +description = "Official Python bindings for Selenium WebDriver" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "selenium-3.141.0-py2.py3-none-any.whl", hash = "sha256:2d7131d7bc5a5b99a2d9b04aaf2612c411b03b8ca1b1ee8d3de5845a9be2cb3c"}, - {file = "selenium-3.141.0.tar.gz", hash = "sha256:deaf32b60ad91a4611b98d8002757f29e6f2c2d5fcaf202e1c9ad06d6772300d"}, + {file = "selenium-4.24.0-py3-none-any.whl", hash = "sha256:42c23f60753d5415b261b236cecbd69bd4eb5271e1563915f546b443cb6b71c6"}, + {file = "selenium-4.24.0.tar.gz", hash = "sha256:88281e5b5b90fe231868905d5ea745b9ee5e30db280b33498cc73fb0fa06d571"}, ] [package.dependencies] -urllib3 = "*" +certifi = ">=2021.10.8" +trio = ">=0.17,<1.0" +trio-websocket = ">=0.9,<1.0" +typing_extensions = ">=4.9,<5.0" +urllib3 = {version = ">=1.26,<3", extras = ["socks"]} +websocket-client = ">=1.8,<2.0" [[package]] name = "sentry-sdk" -version = "2.8.0" +version = "2.13.0" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = ">=3.6" files = [ - {file = "sentry_sdk-2.8.0-py2.py3-none-any.whl", hash = "sha256:6051562d2cfa8087bb8b4b8b79dc44690f8a054762a29c07e22588b1f619bfb5"}, - {file = "sentry_sdk-2.8.0.tar.gz", hash = "sha256:aa4314f877d9cd9add5a0c9ba18e3f27f99f7de835ce36bd150e48a41c7c646f"}, + {file = "sentry_sdk-2.13.0-py2.py3-none-any.whl", hash = "sha256:6beede8fc2ab4043da7f69d95534e320944690680dd9a963178a49de71d726c6"}, + {file = "sentry_sdk-2.13.0.tar.gz", hash = "sha256:8d4a576f7a98eb2fdb40e13106e41f330e5c79d72a68be1316e7852cf4995260"}, ] [package.dependencies] @@ -380,10 +541,11 @@ httpx = ["httpx (>=0.16.0)"] huey = ["huey (>=2)"] huggingface-hub = ["huggingface-hub (>=0.22)"] langchain = ["langchain (>=0.0.210)"] +litestar = ["litestar (>=2.0.0)"] loguru = ["loguru (>=0.5)"] openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"] opentelemetry = ["opentelemetry-distro (>=0.35b0)"] -opentelemetry-experimental = ["opentelemetry-instrumentation-aio-pika (==0.46b0)", "opentelemetry-instrumentation-aiohttp-client (==0.46b0)", "opentelemetry-instrumentation-aiopg (==0.46b0)", "opentelemetry-instrumentation-asgi (==0.46b0)", "opentelemetry-instrumentation-asyncio (==0.46b0)", "opentelemetry-instrumentation-asyncpg (==0.46b0)", "opentelemetry-instrumentation-aws-lambda (==0.46b0)", "opentelemetry-instrumentation-boto (==0.46b0)", "opentelemetry-instrumentation-boto3sqs (==0.46b0)", "opentelemetry-instrumentation-botocore (==0.46b0)", "opentelemetry-instrumentation-cassandra (==0.46b0)", "opentelemetry-instrumentation-celery (==0.46b0)", "opentelemetry-instrumentation-confluent-kafka (==0.46b0)", "opentelemetry-instrumentation-dbapi (==0.46b0)", "opentelemetry-instrumentation-django (==0.46b0)", "opentelemetry-instrumentation-elasticsearch (==0.46b0)", "opentelemetry-instrumentation-falcon (==0.46b0)", "opentelemetry-instrumentation-fastapi (==0.46b0)", "opentelemetry-instrumentation-flask (==0.46b0)", "opentelemetry-instrumentation-grpc (==0.46b0)", "opentelemetry-instrumentation-httpx (==0.46b0)", "opentelemetry-instrumentation-jinja2 (==0.46b0)", "opentelemetry-instrumentation-kafka-python (==0.46b0)", "opentelemetry-instrumentation-logging (==0.46b0)", "opentelemetry-instrumentation-mysql (==0.46b0)", "opentelemetry-instrumentation-mysqlclient (==0.46b0)", "opentelemetry-instrumentation-pika (==0.46b0)", "opentelemetry-instrumentation-psycopg (==0.46b0)", "opentelemetry-instrumentation-psycopg2 (==0.46b0)", "opentelemetry-instrumentation-pymemcache (==0.46b0)", "opentelemetry-instrumentation-pymongo (==0.46b0)", "opentelemetry-instrumentation-pymysql (==0.46b0)", "opentelemetry-instrumentation-pyramid (==0.46b0)", "opentelemetry-instrumentation-redis (==0.46b0)", "opentelemetry-instrumentation-remoulade (==0.46b0)", "opentelemetry-instrumentation-requests (==0.46b0)", "opentelemetry-instrumentation-sklearn (==0.46b0)", "opentelemetry-instrumentation-sqlalchemy (==0.46b0)", "opentelemetry-instrumentation-sqlite3 (==0.46b0)", "opentelemetry-instrumentation-starlette (==0.46b0)", "opentelemetry-instrumentation-system-metrics (==0.46b0)", "opentelemetry-instrumentation-threading (==0.46b0)", "opentelemetry-instrumentation-tornado (==0.46b0)", "opentelemetry-instrumentation-tortoiseorm (==0.46b0)", "opentelemetry-instrumentation-urllib (==0.46b0)", "opentelemetry-instrumentation-urllib3 (==0.46b0)", "opentelemetry-instrumentation-wsgi (==0.46b0)"] +opentelemetry-experimental = ["opentelemetry-distro"] pure-eval = ["asttokens", "executing", "pure-eval"] pymongo = ["pymongo (>=3.1)"] pyspark = ["pyspark (>=2.4.4)"] @@ -397,19 +559,23 @@ tornado = ["tornado (>=6)"] [[package]] name = "setuptools" -version = "67.8.0" +version = "74.0.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "setuptools-67.8.0-py3-none-any.whl", hash = "sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f"}, - {file = "setuptools-67.8.0.tar.gz", hash = "sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102"}, + {file = "setuptools-74.0.0-py3-none-any.whl", hash = "sha256:0274581a0037b638b9fc1c6883cc71c0210865aaa76073f7882376b641b84e8f"}, + {file = "setuptools-74.0.0.tar.gz", hash = "sha256:a85e96b8be2b906f3e3e789adec6a9323abf79758ecfa3065bd740d81158b11e"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"] [[package]] name = "six" @@ -422,15 +588,26 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] +[[package]] +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] + [[package]] name = "snoop" -version = "0.4.2" +version = "0.6.0" description = "Powerful debugging tools for Python" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "snoop-0.4.2-py2.py3-none-any.whl", hash = "sha256:0c5d7e472adb4cb37b8ed6631bea3aa8d128a8e9749229d11efe1823a637d282"}, - {file = "snoop-0.4.2.tar.gz", hash = "sha256:3ee2f843f64066b1963d830db66de0257a75b5104a7c83782afaaebca74c758c"}, + {file = "snoop-0.6.0-py3-none-any.whl", hash = "sha256:f5ea9060e65594bf404e6841086b4a964cc27bc30569109c91a470f948b0f729"}, + {file = "snoop-0.6.0.tar.gz", hash = "sha256:c615eddf84d8907f893dec7fde38768aa4b1d88d92d63055b6cfc07e5cde37ec"}, ] [package.dependencies] @@ -438,20 +615,30 @@ asttokens = "*" cheap-repr = ">=0.4.0" executing = "*" pygments = "*" -six = "*" [package.extras] -tests = ["Django", "birdseye", "littleutils", "numpy (>=1.16.5)", "pandas (>=0.24.2)", "pprintpp", "prettyprinter", "pytest", "pytest-order", "pytest-order (<=0.11.0)"] +tests = ["Django", "birdseye", "littleutils", "numpy (>=1.16.5)", "pandas (>=0.24.2)", "pprintpp", "prettyprinter", "pytest", "pytest-order"] + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +optional = false +python-versions = "*" +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] [[package]] name = "stack-data" -version = "0.6.1" +version = "0.6.3" description = "Extract data from python stack frames and tracebacks for informative displays" optional = false python-versions = "*" files = [ - {file = "stack_data-0.6.1-py3-none-any.whl", hash = "sha256:960cb054d6a1b2fdd9cbd529e365b3c163e8dabf1272e02cfe36b58403cff5c6"}, - {file = "stack_data-0.6.1.tar.gz", hash = "sha256:6c9a10eb5f342415fe085db551d673955611afb821551f554d91772415464315"}, + {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, + {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, ] [package.dependencies] @@ -462,23 +649,102 @@ pure-eval = "*" [package.extras] tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] +[[package]] +name = "trio" +version = "0.26.2" +description = "A friendly Python library for async concurrency and I/O" +optional = false +python-versions = ">=3.8" +files = [ + {file = "trio-0.26.2-py3-none-any.whl", hash = "sha256:c5237e8133eb0a1d72f09a971a55c28ebe69e351c783fc64bc37db8db8bbe1d0"}, + {file = "trio-0.26.2.tar.gz", hash = "sha256:0346c3852c15e5c7d40ea15972c4805689ef2cb8b5206f794c9c19450119f3a4"}, +] + +[package.dependencies] +attrs = ">=23.2.0" +cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""} +idna = "*" +outcome = "*" +sniffio = ">=1.3.0" +sortedcontainers = "*" + +[[package]] +name = "trio-websocket" +version = "0.11.1" +description = "WebSocket library for Trio" +optional = false +python-versions = ">=3.7" +files = [ + {file = "trio-websocket-0.11.1.tar.gz", hash = "sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f"}, + {file = "trio_websocket-0.11.1-py3-none-any.whl", hash = "sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638"}, +] + +[package.dependencies] +trio = ">=0.11" +wsproto = ">=0.14" + +[[package]] +name = "typing-extensions" +version = "4.12.2" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, +] + [[package]] name = "urllib3" -version = "1.26.18" +version = "2.2.2" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.8" files = [ - {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, - {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, ] +[package.dependencies] +pysocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""} + [package.extras] -brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "websocket-client" +version = "1.8.0" +description = "WebSocket client for Python with low level API options" +optional = false +python-versions = ">=3.8" +files = [ + {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, + {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, +] + +[package.extras] +docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"] +optional = ["python-socks", "wsaccel"] +test = ["websockets"] + +[[package]] +name = "wsproto" +version = "1.2.0" +description = "WebSockets state-machine based protocol implementation" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"}, + {file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"}, +] + +[package.dependencies] +h11 = ">=0.9.0,<1" [metadata] lock-version = "2.0" -python-versions = "3.11.2" -content-hash = "d6bbb5839e569d323a39807c794029247b5ab3cd2a630aad97f053b649e106e7" +python-versions = "3.12.1" +content-hash = "100a6c0c63a1867705570052caaaaec920c9c9b8b633d80ba4505048eb9448ea" diff --git a/pyproject.toml b/pyproject.toml index 578309d8..7f7f8f4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ authors = ["Alex Hall "] package-mode = false [tool.poetry.dependencies] -python = "3.11.2" +python = "3.12.1" birdseye = {git = "https://github.com/alexmojaki/birdseye.git", branch = "futurecoder"} snoop = "*" asttokens = "*" @@ -27,11 +27,11 @@ setuptools = "*" [tool.poetry.dev-dependencies] flake8 = {version = "^3.8.3", optional = true} isort = "^5.1.4" -selenium = "^3.141.0" polib = "^1.1.1" [tool.poetry.group.dev.dependencies] pytest = "7.3.1" +selenium = "^4.24.0" [build-system] requires = ["poetry>=0.12"] diff --git a/tests/golden_files/en/test_transcript.json b/tests/golden_files/en/test_transcript.json index 49a59b85..4ba82422 100644 --- a/tests/golden_files/en/test_transcript.json +++ b/tests/golden_files/en/test_transcript.json @@ -1247,27 +1247,27 @@ "passed": true, "result": [ { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | sentence \u001b[38;5;197m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mFalse\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 4\u001b[0m | new_sentence \u001b[38;5;197m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mH\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | sentence \u001b[38;5;204m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mFalse\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 4\u001b[0m | new_sentence \u001b[38;5;204m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mH\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mel\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mell\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mel\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mell\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mW\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello W\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mW\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello W\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mr\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wor\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Worl\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mr\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wor\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Worl\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186md\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 10\u001b[0m | print(new_sentence)\n", + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186md\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 10\u001b[0m | print(new_sentence)\n", "type": "snoop" }, { @@ -2786,7 +2786,7 @@ ] } ], - "friendly": "

A TypeError is usually caused by trying\nto combine two incompatible types of objects,\nby calling a function with the wrong type of object,\nor by trying to do an operation not allowed on a given type of object.

\n

The parenthesis () following f are interpreted\nby Python as a function call for f.\nHowever, f is not a function but an object of type str.

", + "friendly": "

A TypeError is usually caused by trying\nto combine two incompatible types of objects,\nby calling a function with the wrong type of object,\nor by trying to do an operation not allowed on a given type of object.

\n

Because of the surrounding parenthesis, ` \nis interpreted by Python as indicating a function call forf, which is an object of typestr`\nwhich cannot be called.

", "tail": "" } ], @@ -3811,7 +3811,7 @@ "passed": true, "result": [ { - "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

I suspect that you were trying to use a quote character inside a string\nthat was enclosed in quotes of the same kind.\nPerhaps you should have escaped the inner quote character:

\n
print('Alice\\'s Diner')\n            ^^\n
", + "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

You started writing a string with a single or double quote\nbut never ended the string with another quote on that line.

", "text": " print('Alice's Diner')\n ^\nSyntaxError: unterminated string literal (detected at line 1)\nat line 1\n", "type": "syntax_error" } @@ -4978,11 +4978,11 @@ "passed": true, "result": [ { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n\u001b[38;5;242m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_twice in File \"/my_program.py\", line 5\u001b[0m\n\u001b[38;5;242m \u001b[0m...... x = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;242m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_many in File \"/my_program.py\", line 1\u001b[0m\n\u001b[38;5;242m \u001b[0m...... n = \u001b[38;5;141m2\u001b[39m\n\u001b[38;5;242m \u001b[0m...... thing = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n\u001b[38;5;245m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_twice in File \"/my_program.py\", line 5\u001b[0m\n\u001b[38;5;245m \u001b[0m...... x = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;245m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_many in File \"/my_program.py\", line 1\u001b[0m\n\u001b[38;5;245m \u001b[0m...... n = \u001b[38;5;141m2\u001b[39m\n\u001b[38;5;245m \u001b[0m...... thing = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.......... _ = \u001b[38;5;141m0\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | print(thing)\n", + "text": "\u001b[38;5;245m \u001b[0m.......... _ = \u001b[38;5;141m0\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | print(thing)\n", "type": "snoop" }, { @@ -4994,11 +4994,11 @@ "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.......... _ = \u001b[38;5;141m1\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | print(thing)\n", + "text": "\u001b[38;5;245m \u001b[0m.......... _ = \u001b[38;5;141m1\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | print(thing)\n", "type": "snoop" }, { @@ -5010,11 +5010,11 @@ "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_many: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;242m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_twice: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_many: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;245m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_twice: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n", "type": "snoop" } ] diff --git a/tests/test_frontend.py b/tests/test_frontend.py index 1b131463..bafff8e2 100644 --- a/tests/test_frontend.py +++ b/tests/test_frontend.py @@ -5,7 +5,6 @@ import pytest from selenium import webdriver -from selenium.webdriver import DesiredCapabilities from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys @@ -41,11 +40,8 @@ def get_driver(caps): options = Options() options.add_argument("--headless") options.add_argument("--disable-gpu") - desired_capabilities = DesiredCapabilities.CHROME - desired_capabilities["goog:loggingPrefs"] = {"browser": "ALL"} - driver = webdriver.Chrome( - options=options, desired_capabilities=desired_capabilities - ) + options.set_capability("goog:loggingPrefs", {"browser": "ALL"}) + driver = webdriver.Chrome(options=options) driver.set_window_size(1024, 768) driver.implicitly_wait(5) return driver @@ -100,7 +96,7 @@ def _tests(driver): driver.get("http://localhost:3000/course/#toc") # Go to page - driver.find_element_by_partial_link_text("Getting elements at a position").click() + driver.find_element(By.PARTIAL_LINK_TEXT, "Getting elements at a position").click() # Wait for page to load locator = (By.CSS_SELECTOR, ".book-text h1") @@ -110,19 +106,19 @@ def _tests(driver): assert driver.find_element(*locator).text.startswith( "Getting elements at a position" ) - assert driver.find_element_by_css_selector(".book-text p").text.startswith( + assert driver.find_element(By.CSS_SELECTOR, ".book-text p").text.startswith( "Looping is great" ) # Reverse buttons don't exist (developer mode is off) - assert not driver.find_elements_by_class_name("button-reverse-step"), "Is developer mode on?" + assert not driver.find_elements(By.CLASS_NAME, "button-reverse-step"), "Is developer mode on?" - assert driver.find_element_by_class_name("navbar").text.strip() == "Login / Sign up\nTable of Contents" + assert driver.find_element(By.CLASS_NAME, "navbar").text.strip() == "Login / Sign up\nTable of Contents" # Click on menu - driver.find_element_by_css_selector(".nav-item.custom-popup").click() + driver.find_element(By.CSS_SELECTOR, ".nav-item.custom-popup").click() assert ( - driver.find_element_by_class_name("menu-popup").text + driver.find_element(By.CLASS_NAME, "menu-popup").text == """\ Sign out Settings @@ -133,26 +129,26 @@ def _tests(driver): ) # Open settings - settings_button = driver.find_element_by_css_selector(".menu-popup .btn.btn-primary") + settings_button = driver.find_element(By.CSS_SELECTOR, ".menu-popup .btn.btn-primary") assert settings_button.text.strip() == "Settings" settings_button.click() # Turn on developer mode - developer_mode_togle = driver.find_element_by_css_selector(".settings-modal label") + developer_mode_togle = driver.find_element(By.CSS_SELECTOR, ".settings-modal label") developer_mode_togle.click() # Reverse buttons exist now - reverse_button = driver.find_element_by_class_name("button-reverse-step") - skip_button = driver.find_element_by_class_name("button-skip-step") + reverse_button = driver.find_element(By.CLASS_NAME, "button-reverse-step") + skip_button = driver.find_element(By.CLASS_NAME, "button-skip-step") # Escape settings - driver.find_element_by_tag_name("html").send_keys(Keys.ESCAPE) + driver.find_element(By.TAG_NAME, "html").send_keys(Keys.ESCAPE) # Empty shell await_result(driver, "", ">>> ") # Run code in shell, check result - driver.find_element_by_css_selector(".terminal input").send_keys("12345\n") + driver.find_element(By.CSS_SELECTOR, ".terminal input").send_keys("12345\n") await_result( driver, "12345\n12345", @@ -162,9 +158,9 @@ def _tests(driver): >>> """, ) - editor = driver.find_element_by_css_selector("#editor textarea") - run_button = driver.find_element_by_css_selector(".editor-buttons .btn-primary") - snoop_button = driver.find_element_by_css_selector(".editor-buttons .btn-success") + editor = driver.find_element(By.CSS_SELECTOR, "#editor textarea") + run_button = driver.find_element(By.CSS_SELECTOR, ".editor-buttons .btn-primary") + snoop_button = driver.find_element(By.CSS_SELECTOR, ".editor-buttons .btn-success") # Run test_steps within futurecoder! run_code(editor, run_button, get_test_steps_code()) @@ -175,7 +171,7 @@ def _tests(driver): reverse_button.click() if ( "In general, you can get the element" - not in driver.find_element_by_css_selector(".book-text").text + not in driver.find_element(By.CSS_SELECTOR, ".book-text").text ): break sleep(0.1) @@ -183,7 +179,7 @@ def _tests(driver): pytest.fail() # Get code from instructions - code = driver.find_element_by_css_selector("#step-text-0 pre").text + code = driver.find_element(By.CSS_SELECTOR, "#step-text-0 pre").text assert ( code == """\ @@ -213,7 +209,7 @@ def _tests(driver): # Passed onto next step assert ( "In general, you can get the element" - in driver.find_element_by_css_selector(".book-text").text + in driver.find_element(By.CSS_SELECTOR, ".book-text").text ) # Run with snoop @@ -242,7 +238,7 @@ def _tests(driver): assert ( "As you can see, the result is the same" - in driver.find_element_by_css_selector(".book-text").text + in driver.find_element(By.CSS_SELECTOR, ".book-text").text ) # Correct answer first time @@ -261,7 +257,7 @@ def _tests(driver): predict_output(driver, editor, run_button, 1, 2) # Click OK - driver.find_element_by_css_selector(".submit-prediction button").click() + driver.find_element(By.CSS_SELECTOR, ".submit-prediction button").click() # Course has moved on to next step: indices_out_of_bounds # Let's skip to the end of this page @@ -270,15 +266,15 @@ def _tests(driver): skip_button.click() sleep(0.1) - force_click(driver, driver.find_element_by_class_name("next-button")) + force_click(driver, driver.find_element(By.CLASS_NAME, "next-button")) - assert "Given a list" in driver.find_element_by_css_selector(".book-text").text + assert "Given a list" in driver.find_element(By.CSS_SELECTOR, ".book-text").text - driver.find_element_by_css_selector(".assistant-hints .card-header").click() + driver.find_element(By.CSS_SELECTOR, ".assistant-hints .card-header").click() show_hints_and_solution(driver, num_hints=9, parsons=False) # Hidden solution contains correct text - code = driver.find_element_by_css_selector(".gradual-solution code") + code = driver.find_element(By.CSS_SELECTOR, ".gradual-solution code") assert ( code.text == """\ @@ -289,26 +285,26 @@ def _tests(driver): ) # Click button repeatedly to reveal solution - get_hint_button = driver.find_element_by_css_selector(".hints-popup .btn-primary") + get_hint_button = driver.find_element(By.CSS_SELECTOR, ".hints-popup .btn-primary") assert get_hint_button.text == "Reveal" scroll_to_bottom(driver) for i in range(24): - assert len(code.find_elements_by_class_name("solution-token-hidden")) == 24 - i - assert len(code.find_elements_by_class_name("solution-token-visible")) == 12 + i + assert len(code.find_elements(By.CLASS_NAME, "solution-token-hidden")) == 24 - i + assert len(code.find_elements(By.CLASS_NAME, "solution-token-visible")) == 12 + i get_hint_button.click() # Open assessment - force_click(driver, driver.find_element_by_css_selector(".assistant-assessment .card-header")) + force_click(driver, driver.find_element(By.CSS_SELECTOR, ".assistant-assessment .card-header")) # No messages visible - assert not driver.find_elements_by_class_name("assistant-messages-message") + assert not driver.find_elements(By.CLASS_NAME, "assistant-messages-message") # Run code which triggers a message run_code(editor, run_button, "12345") # Now we have a message assert ( - driver.find_element_by_css_selector(".assistant-messages-message").text + driver.find_element(By.CSS_SELECTOR, ".assistant-messages-message").text == """\ Your code should start like this: things = '...' @@ -330,7 +326,7 @@ def _tests(driver): # Now we have a message assert ( - driver.find_element_by_css_selector(".assistant-messages-message").text + driver.find_element(By.CSS_SELECTOR, ".assistant-messages-message").text == "You're almost there! However, this prints all the indices, not just the first one." ) @@ -340,7 +336,7 @@ def _tests(driver): sleep(0.2) # Step has passed, message has disappeared - assert not driver.find_elements_by_class_name("assistant-messages-message") + assert not driver.find_elements(By.CLASS_NAME, "assistant-messages-message") # Skip to zip_longest exercise skip_button.click() @@ -349,9 +345,9 @@ def _tests(driver): show_hints_and_solution(driver, num_hints=10, parsons=True) assert { - node.text - for node in driver.find_elements_by_css_selector(".parsons-droppable code") - } == set( + node.text + for node in driver.find_elements(By.CSS_SELECTOR, ".parsons-droppable code") + } == set( """\ length1 = len(string1) length2 = len(string2) @@ -372,7 +368,7 @@ def _tests(driver): ) # Cannot go to next page yet - assert not driver.find_elements_by_class_name("next-button") + assert not driver.find_elements(By.CLASS_NAME, "next-button") # Next button appears after completing last step # Scroll to end of page to get skip button out of the way @@ -380,19 +376,19 @@ def _tests(driver): sleep(0.1) driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") sleep(0.1) - driver.find_element_by_class_name("next-button").click() + driver.find_element(By.CLASS_NAME, "next-button").click() # On next page sleep(0.1) assert ( - driver.find_element_by_css_selector(".book-text h1").text + driver.find_element(By.CSS_SELECTOR, ".book-text h1").text == "Terminology: Calling functions and methods" ) # Back to previous page - driver.find_element_by_class_name("previous-button").click() + driver.find_element(By.CLASS_NAME, "previous-button").click() sleep(0.1) - assert driver.find_element_by_css_selector(".book-text h1").text.startswith( + assert driver.find_element(By.CSS_SELECTOR, ".book-text h1").text.startswith( "Exercises with" ) @@ -404,8 +400,8 @@ def scroll_to_bottom(driver): def show_hints_and_solution(driver, *, num_hints, parsons): # Show all hints for hint_num in range(num_hints): - assert len(driver.find_elements_by_class_name("hint-body")) == hint_num - get_hint_button = driver.find_element_by_css_selector( + assert len(driver.find_elements(By.CLASS_NAME, "hint-body")) == hint_num + get_hint_button = driver.find_element(By.CSS_SELECTOR, ".hints-popup .btn-primary" ) assert get_hint_button.text == ( @@ -414,38 +410,40 @@ def show_hints_and_solution(driver, *, num_hints, parsons): scroll_to_bottom(driver) get_hint_button.click() if hint_num < num_hints - 1: - hints_progress = driver.find_element_by_css_selector( + hints_progress = driver.find_element(By.CSS_SELECTOR, ".hints-popup .hints-progress" ) assert hints_progress.text == f"Shown {hint_num + 1} of {num_hints} hints" # All hints are shown - assert len(driver.find_elements_by_class_name("hint-body")) == num_hints + assert len(driver.find_elements(By.CLASS_NAME, "hint-body")) == num_hints # Click 'Show solution' - get_hint_button = driver.find_element_by_css_selector(".hints-popup .btn-primary") + get_hint_button = driver.find_element(By.CSS_SELECTOR, ".hints-popup .btn-primary") assert get_hint_button.text == ("Show shuffled solution" if parsons else "Show solution") scroll_to_bottom(driver) get_hint_button.click() # Solution not yet visible - assert not driver.find_elements_by_css_selector(".gradual-solution") - assert not driver.find_elements_by_css_selector(".parsons-droppable") + assert not driver.find_elements(By.CSS_SELECTOR, ".gradual-solution") + assert not driver.find_elements(By.CSS_SELECTOR, ".parsons-droppable") # Are you sure? Click 'Yes' - get_hint_button = driver.find_element_by_css_selector(".hints-popup .btn-primary") + get_hint_button = driver.find_element(By.CSS_SELECTOR, ".hints-popup .btn-primary") assert get_hint_button.text == "Yes" scroll_to_bottom(driver) get_hint_button.click() # Exactly one kind of solution visible - assert bool(driver.find_elements_by_css_selector(".gradual-solution")) == (not parsons) - assert bool(driver.find_elements_by_css_selector(".parsons-droppable")) == parsons + assert bool(driver.find_elements(By.CSS_SELECTOR, ".gradual-solution")) == (not parsons) + assert bool(driver.find_elements(By.CSS_SELECTOR, ".parsons-droppable")) == parsons def run_code(editor, run_button, text): editor.send_keys(Keys.CONTROL + "a") editor.send_keys(Keys.BACK_SPACE) + editor.send_keys(Keys.COMMAND + "a") + editor.send_keys(Keys.BACK_SPACE) editor.send_keys(text) run_button.click() @@ -487,7 +485,7 @@ def predict_output(driver, editor, run_button, first_choice, second_choice): sleep(2) # Check the choices - choices = driver.find_elements_by_class_name("prediction-choice") + choices = driver.find_elements(By.CLASS_NAME, "prediction-choice") assert len(choices) == 6 # Click first choice @@ -498,7 +496,7 @@ def predict_output(driver, editor, run_button, first_choice, second_choice): check_choice_status(driver, first_choice, "selected") # Click Submit - driver.find_element_by_css_selector(".submit-prediction button").click() + driver.find_element(By.CSS_SELECTOR, ".submit-prediction button").click() sleep(0.1) check_choice_status(driver, first_choice, "correct" if is_correct else "wrong") @@ -507,7 +505,7 @@ def predict_output(driver, editor, run_button, first_choice, second_choice): bottom_text = "Correct!" else: bottom_text = "Oops, that's not right. You can try one more time!\nSubmit" - assert driver.find_element_by_css_selector(".submit-prediction").text == bottom_text + assert driver.find_element(By.CSS_SELECTOR, ".submit-prediction").text == bottom_text if is_correct: return @@ -523,7 +521,7 @@ def predict_output(driver, editor, run_button, first_choice, second_choice): check_choice_status(driver, second_choice, "selected") # Click Submit - driver.find_element_by_css_selector(".submit-prediction button").click() + driver.find_element(By.CSS_SELECTOR, ".submit-prediction button").click() sleep(0.1) check_choice_status(driver, first_choice, "wrong") @@ -533,17 +531,17 @@ def predict_output(driver, editor, run_button, first_choice, second_choice): bottom_text = "Correct!" else: bottom_text = "Sorry, wrong answer. Try again next time!\nOK" - assert driver.find_element_by_css_selector(".submit-prediction").text == bottom_text + assert driver.find_element(By.CSS_SELECTOR, ".submit-prediction").text == bottom_text def check_choice_status(driver, choice_index, status): - choices = driver.find_elements_by_class_name("prediction-choice") + choices = driver.find_elements(By.CLASS_NAME, "prediction-choice") choice = choices[choice_index] assert choice.get_attribute("class") == ( f"prediction-choice prediction-{status}" ), [ choice.get_attribute("class") - for choice in driver.find_elements_by_class_name("prediction-choice") + for choice in driver.find_elements(By.CLASS_NAME, "prediction-choice") ] diff --git a/tests/test_steps.py b/tests/test_steps.py index fb3bd426..7f1443ad 100644 --- a/tests/test_steps.py +++ b/tests/test_steps.py @@ -4,8 +4,6 @@ import re from pathlib import Path -from littleutils import only - import core.utils from core import translation as t from core.checker import check_entry, FullRunner From 426966f7ad0bc6cbae05c73db8da730c87911968 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 6 Oct 2024 22:56:18 +0200 Subject: [PATCH 02/53] Bump rollup from 2.79.1 to 2.79.2 in /frontend (#487) Bumps [rollup](https://github.com/rollup/rollup) from 2.79.1 to 2.79.2. - [Release notes](https://github.com/rollup/rollup/releases) - [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md) - [Commits](https://github.com/rollup/rollup/compare/v2.79.1...v2.79.2) --- updated-dependencies: - dependency-name: rollup dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e63f491a..f988e486 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -15766,9 +15766,9 @@ } }, "node_modules/rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "version": "2.79.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", + "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", "bin": { "rollup": "dist/bin/rollup" }, @@ -29470,9 +29470,9 @@ } }, "rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "version": "2.79.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", + "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", "requires": { "fsevents": "~2.3.2" } From f8cd25df12638d46e37ed9d739b951972f1760cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 6 Oct 2024 23:16:35 +0200 Subject: [PATCH 03/53] Bump send and express in /frontend (#485) Bumps [send](https://github.com/pillarjs/send) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together. Updates `send` from 0.18.0 to 0.19.0 - [Release notes](https://github.com/pillarjs/send/releases) - [Changelog](https://github.com/pillarjs/send/blob/master/HISTORY.md) - [Commits](https://github.com/pillarjs/send/compare/0.18.0...0.19.0) Updates `express` from 4.19.2 to 4.21.0 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md) - [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0) --- updated-dependencies: - dependency-name: send dependency-type: indirect - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 417 +++++++++++++++++++++++++------------ 1 file changed, 283 insertions(+), 134 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f988e486..f217671f 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -5939,9 +5939,9 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -5951,7 +5951,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -6094,12 +6094,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7181,6 +7187,22 @@ "clone": "^1.0.2" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -7541,9 +7563,9 @@ } }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "engines": { "node": ">= 0.8" } @@ -7634,6 +7656,25 @@ "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", @@ -8544,36 +8585,36 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -8772,12 +8813,12 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -9147,9 +9188,12 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -9193,13 +9237,18 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9428,11 +9477,11 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9474,6 +9523,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -12683,9 +12743,12 @@ "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==" }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -13022,9 +13085,12 @@ } }, "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13356,9 +13422,9 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, "node_modules/path-type": { "version": "4.0.0", @@ -14903,11 +14969,11 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -16015,9 +16081,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -16050,6 +16116,14 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -16134,19 +16208,35 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -16191,13 +16281,17 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -22522,9 +22616,9 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "requires": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -22534,7 +22628,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -22641,12 +22735,15 @@ "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" }, "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" } }, "callsites": { @@ -23408,6 +23505,16 @@ "clone": "^1.0.2" } }, + "define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, "define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -23676,9 +23783,9 @@ "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" }, "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" }, "enhanced-resolve": { "version": "5.12.0", @@ -23754,6 +23861,19 @@ "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" }, + "es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "requires": { + "get-intrinsic": "^1.2.4" + } + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, "es-module-lexer": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", @@ -24405,36 +24525,36 @@ } }, "express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -24591,12 +24711,12 @@ } }, "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "requires": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -24851,9 +24971,9 @@ "optional": true }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, "function.prototype.name": { "version": "1.1.5", @@ -24882,13 +25002,15 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" } }, "get-own-enumerable-property-symbols": { @@ -25050,11 +25172,11 @@ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" }, "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "requires": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" } }, "has-proto": { @@ -25075,6 +25197,14 @@ "has-symbols": "^1.0.2" } }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -27429,9 +27559,9 @@ "integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==" }, "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==" }, "merge-stream": { "version": "2.0.0", @@ -27673,9 +27803,9 @@ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==" }, "object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==" }, "object-keys": { "version": "1.1.1", @@ -27912,9 +28042,9 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, "path-type": { "version": "4.0.0", @@ -28845,11 +28975,11 @@ "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" }, "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "requires": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" } }, "querystringify": { @@ -29631,9 +29761,9 @@ } }, "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "requires": { "debug": "2.6.9", "depd": "2.0.0", @@ -29665,6 +29795,11 @@ } } }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -29741,14 +29876,27 @@ } }, "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "requires": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" + } + }, + "set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" } }, "setprototypeof": { @@ -29783,13 +29931,14 @@ "integrity": "sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw==" }, "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" } }, "signal-exit": { From 967c0fb00f5ec83aaeb29f699584f3fee49b5526 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 6 Oct 2024 23:16:48 +0200 Subject: [PATCH 04/53] Bump @sentry/browser and @sentry/react in /frontend (#491) Bumps [@sentry/browser](https://github.com/getsentry/sentry-javascript) to 7.119.1 and updates ancestor dependency [@sentry/react](https://github.com/getsentry/sentry-javascript). These dependencies need to be updated together. Updates `@sentry/browser` from 7.16.0 to 7.119.1 - [Release notes](https://github.com/getsentry/sentry-javascript/releases) - [Changelog](https://github.com/getsentry/sentry-javascript/blob/7.119.1/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-javascript/compare/7.16.0...7.119.1) Updates `@sentry/react` from 7.16.0 to 7.119.1 - [Release notes](https://github.com/getsentry/sentry-javascript/releases) - [Changelog](https://github.com/getsentry/sentry-javascript/blob/7.119.1/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-javascript/compare/7.16.0...7.119.1) --- updated-dependencies: - dependency-name: "@sentry/browser" dependency-type: indirect - dependency-name: "@sentry/react" dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 243 ++++++++++++++++++++++++++++--------- frontend/package.json | 2 +- 2 files changed, 185 insertions(+), 60 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f217671f..7555251c 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,7 +12,7 @@ "@fortawesome/fontawesome-svg-core": "^6.2.0", "@fortawesome/free-solid-svg-icons": "^6.2.0", "@fortawesome/react-fontawesome": "^0.2.0", - "@sentry/react": "^7.16.0", + "@sentry/react": "^7.119.1", "ansi_up": "^5.0.0", "axios": "^1.6.0", "comlink": "^4.3.1", @@ -4155,43 +4155,100 @@ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==" }, + "node_modules/@sentry-internal/feedback": { + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.119.1.tgz", + "integrity": "sha512-EPyW6EKZmhKpw/OQUPRkTynXecZdYl4uhZwdZuGqnGMAzswPOgQvFrkwsOuPYvoMfXqCH7YuRqyJrox3uBOrTA==", + "dependencies": { + "@sentry/core": "7.119.1", + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.119.1.tgz", + "integrity": "sha512-O/lrzENbMhP/UDr7LwmfOWTjD9PLNmdaCF408Wx8SDuj7Iwc+VasGfHg7fPH4Pdr4nJON6oh+UqoV4IoG05u+A==", + "dependencies": { + "@sentry/core": "7.119.1", + "@sentry/replay": "7.119.1", + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@sentry-internal/tracing": { + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.119.1.tgz", + "integrity": "sha512-cI0YraPd6qBwvUA3wQdPGTy8PzAoK0NZiaTN1LM3IczdPegehWOaEG5GVTnpGnTsmBAzn1xnBXNBhgiU4dgcrQ==", + "dependencies": { + "@sentry/core": "7.119.1", + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@sentry/browser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.16.0.tgz", - "integrity": "sha512-tJ063zvoF8Raw7mzQEXupOFPSN6v36WIbsDVGeFdToPCwViaBuATaxvWCrudGzsnBkMyItmTLJkzn9SEIXUOiw==", + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.119.1.tgz", + "integrity": "sha512-aMwAnFU4iAPeLyZvqmOQaEDHt/Dkf8rpgYeJ0OEi50dmP6AjG+KIAMCXU7CYCCQDn70ITJo8QD5+KzCoZPYz0A==", "dependencies": { - "@sentry/core": "7.16.0", - "@sentry/types": "7.16.0", - "@sentry/utils": "7.16.0", - "tslib": "^1.9.3" + "@sentry-internal/feedback": "7.119.1", + "@sentry-internal/replay-canvas": "7.119.1", + "@sentry-internal/tracing": "7.119.1", + "@sentry/core": "7.119.1", + "@sentry/integrations": "7.119.1", + "@sentry/replay": "7.119.1", + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/core": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.16.0.tgz", - "integrity": "sha512-vq6H1b/IPTvzDD9coQ3wIudvSjkAYuUlXb1dv69dRlq4v3st9dcKBps1Zf0lQ1i4TVlDLoe1iGMmNFglMF1Q5w==", + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.119.1.tgz", + "integrity": "sha512-YUNnH7O7paVd+UmpArWCPH4Phlb5LwrkWVqzFWqL3xPyCcTSof2RL8UmvpkTjgYJjJ+NDfq5mPFkqv3aOEn5Sw==", + "dependencies": { + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/integrations": { + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.119.1.tgz", + "integrity": "sha512-CGmLEPnaBqbUleVqrmGYjRjf5/OwjUXo57I9t0KKWViq81mWnYhaUhRZWFNoCNQHns+3+GPCOMvl0zlawt+evw==", "dependencies": { - "@sentry/types": "7.16.0", - "@sentry/utils": "7.16.0", - "tslib": "^1.9.3" + "@sentry/core": "7.119.1", + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1", + "localforage": "^1.8.1" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/react": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.16.0.tgz", - "integrity": "sha512-tJH5zO4MPopzqZgi7Yd4iIB9Am5uGVefgkHaoeCGXffveEVWqEdjj8TqPL36SBb76gCmtpa01NBDsUSDZ1w/yw==", + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.119.1.tgz", + "integrity": "sha512-Bri314LnSVm16K3JATgn3Zsq6Uj3M/nIjdUb3nggBw0BMlFWMsyFjUCfmCio5d80KJK/lUjOIxRjzu79M6jOzQ==", "dependencies": { - "@sentry/browser": "7.16.0", - "@sentry/types": "7.16.0", - "@sentry/utils": "7.16.0", - "hoist-non-react-statics": "^3.3.2", - "tslib": "^1.9.3" + "@sentry/browser": "7.119.1", + "@sentry/core": "7.119.1", + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1", + "hoist-non-react-statics": "^3.3.2" }, "engines": { "node": ">=8" @@ -4200,21 +4257,34 @@ "react": "15.x || 16.x || 17.x || 18.x" } }, + "node_modules/@sentry/replay": { + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.119.1.tgz", + "integrity": "sha512-4da+ruMEipuAZf35Ybt2StBdV1S+oJbSVccGpnl9w6RoeQoloT4ztR6ML3UcFDTXeTPT1FnHWDCyOfST0O7XMw==", + "dependencies": { + "@sentry-internal/tracing": "7.119.1", + "@sentry/core": "7.119.1", + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@sentry/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.16.0.tgz", - "integrity": "sha512-i6D+OK6d0l/k+VQvRp/Pt21WkDEgVBUIZq+sOkEZJczbcfexVdXKeXXoYTD2vYuFq8Yy28fzlsZaKI+NoH94yQ==", + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.119.1.tgz", + "integrity": "sha512-4G2mcZNnYzK3pa2PuTq+M2GcwBRY/yy1rF+HfZU+LAPZr98nzq2X3+mJHNJoobeHRkvVh7YZMPi4ogXiIS5VNQ==", "engines": { "node": ">=8" } }, "node_modules/@sentry/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-3Zh1txg7IRp4kZAdG27YF7K6lD1IZyuAo9KjoPg1Xzqa4DOZyASJuEkbf+rK2a9T4HrtVHHXJUsNbKg8WM3VHg==", + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.119.1.tgz", + "integrity": "sha512-ju/Cvyeu/vkfC5/XBV30UNet5kLEicZmXSyuLwZu95hEbL+foPdxN+re7pCI/eNqfe3B2vz7lvz5afLVOlQ2Hg==", "dependencies": { - "@sentry/types": "7.16.0", - "tslib": "^1.9.3" + "@sentry/types": "7.119.1" }, "engines": { "node": ">=8" @@ -21269,51 +21339,106 @@ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==" }, + "@sentry-internal/feedback": { + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.119.1.tgz", + "integrity": "sha512-EPyW6EKZmhKpw/OQUPRkTynXecZdYl4uhZwdZuGqnGMAzswPOgQvFrkwsOuPYvoMfXqCH7YuRqyJrox3uBOrTA==", + "requires": { + "@sentry/core": "7.119.1", + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1" + } + }, + "@sentry-internal/replay-canvas": { + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.119.1.tgz", + "integrity": "sha512-O/lrzENbMhP/UDr7LwmfOWTjD9PLNmdaCF408Wx8SDuj7Iwc+VasGfHg7fPH4Pdr4nJON6oh+UqoV4IoG05u+A==", + "requires": { + "@sentry/core": "7.119.1", + "@sentry/replay": "7.119.1", + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1" + } + }, + "@sentry-internal/tracing": { + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.119.1.tgz", + "integrity": "sha512-cI0YraPd6qBwvUA3wQdPGTy8PzAoK0NZiaTN1LM3IczdPegehWOaEG5GVTnpGnTsmBAzn1xnBXNBhgiU4dgcrQ==", + "requires": { + "@sentry/core": "7.119.1", + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1" + } + }, "@sentry/browser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.16.0.tgz", - "integrity": "sha512-tJ063zvoF8Raw7mzQEXupOFPSN6v36WIbsDVGeFdToPCwViaBuATaxvWCrudGzsnBkMyItmTLJkzn9SEIXUOiw==", + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.119.1.tgz", + "integrity": "sha512-aMwAnFU4iAPeLyZvqmOQaEDHt/Dkf8rpgYeJ0OEi50dmP6AjG+KIAMCXU7CYCCQDn70ITJo8QD5+KzCoZPYz0A==", "requires": { - "@sentry/core": "7.16.0", - "@sentry/types": "7.16.0", - "@sentry/utils": "7.16.0", - "tslib": "^1.9.3" + "@sentry-internal/feedback": "7.119.1", + "@sentry-internal/replay-canvas": "7.119.1", + "@sentry-internal/tracing": "7.119.1", + "@sentry/core": "7.119.1", + "@sentry/integrations": "7.119.1", + "@sentry/replay": "7.119.1", + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1" } }, "@sentry/core": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.16.0.tgz", - "integrity": "sha512-vq6H1b/IPTvzDD9coQ3wIudvSjkAYuUlXb1dv69dRlq4v3st9dcKBps1Zf0lQ1i4TVlDLoe1iGMmNFglMF1Q5w==", + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.119.1.tgz", + "integrity": "sha512-YUNnH7O7paVd+UmpArWCPH4Phlb5LwrkWVqzFWqL3xPyCcTSof2RL8UmvpkTjgYJjJ+NDfq5mPFkqv3aOEn5Sw==", "requires": { - "@sentry/types": "7.16.0", - "@sentry/utils": "7.16.0", - "tslib": "^1.9.3" + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1" + } + }, + "@sentry/integrations": { + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.119.1.tgz", + "integrity": "sha512-CGmLEPnaBqbUleVqrmGYjRjf5/OwjUXo57I9t0KKWViq81mWnYhaUhRZWFNoCNQHns+3+GPCOMvl0zlawt+evw==", + "requires": { + "@sentry/core": "7.119.1", + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1", + "localforage": "^1.8.1" } }, "@sentry/react": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.16.0.tgz", - "integrity": "sha512-tJH5zO4MPopzqZgi7Yd4iIB9Am5uGVefgkHaoeCGXffveEVWqEdjj8TqPL36SBb76gCmtpa01NBDsUSDZ1w/yw==", + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.119.1.tgz", + "integrity": "sha512-Bri314LnSVm16K3JATgn3Zsq6Uj3M/nIjdUb3nggBw0BMlFWMsyFjUCfmCio5d80KJK/lUjOIxRjzu79M6jOzQ==", "requires": { - "@sentry/browser": "7.16.0", - "@sentry/types": "7.16.0", - "@sentry/utils": "7.16.0", - "hoist-non-react-statics": "^3.3.2", - "tslib": "^1.9.3" + "@sentry/browser": "7.119.1", + "@sentry/core": "7.119.1", + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1", + "hoist-non-react-statics": "^3.3.2" + } + }, + "@sentry/replay": { + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.119.1.tgz", + "integrity": "sha512-4da+ruMEipuAZf35Ybt2StBdV1S+oJbSVccGpnl9w6RoeQoloT4ztR6ML3UcFDTXeTPT1FnHWDCyOfST0O7XMw==", + "requires": { + "@sentry-internal/tracing": "7.119.1", + "@sentry/core": "7.119.1", + "@sentry/types": "7.119.1", + "@sentry/utils": "7.119.1" } }, "@sentry/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.16.0.tgz", - "integrity": "sha512-i6D+OK6d0l/k+VQvRp/Pt21WkDEgVBUIZq+sOkEZJczbcfexVdXKeXXoYTD2vYuFq8Yy28fzlsZaKI+NoH94yQ==" + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.119.1.tgz", + "integrity": "sha512-4G2mcZNnYzK3pa2PuTq+M2GcwBRY/yy1rF+HfZU+LAPZr98nzq2X3+mJHNJoobeHRkvVh7YZMPi4ogXiIS5VNQ==" }, "@sentry/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-3Zh1txg7IRp4kZAdG27YF7K6lD1IZyuAo9KjoPg1Xzqa4DOZyASJuEkbf+rK2a9T4HrtVHHXJUsNbKg8WM3VHg==", + "version": "7.119.1", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.119.1.tgz", + "integrity": "sha512-ju/Cvyeu/vkfC5/XBV30UNet5kLEicZmXSyuLwZu95hEbL+foPdxN+re7pCI/eNqfe3B2vz7lvz5afLVOlQ2Hg==", "requires": { - "@sentry/types": "7.16.0", - "tslib": "^1.9.3" + "@sentry/types": "7.119.1" } }, "@sinclair/typebox": { diff --git a/frontend/package.json b/frontend/package.json index 85fa52c4..ed56b8be 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,7 +12,7 @@ "@fortawesome/fontawesome-svg-core": "^6.2.0", "@fortawesome/free-solid-svg-icons": "^6.2.0", "@fortawesome/react-fontawesome": "^0.2.0", - "@sentry/react": "^7.16.0", + "@sentry/react": "^7.119.1", "ansi_up": "^5.0.0", "axios": "^1.6.0", "comlink": "^4.3.1", From 520bd6e1c30b3ee83c9046c0514c10421b564805 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 6 Oct 2024 23:17:01 +0200 Subject: [PATCH 05/53] Bump body-parser and express in /frontend (#486) Bumps [body-parser](https://github.com/expressjs/body-parser) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together. Updates `body-parser` from 1.20.2 to 1.20.3 - [Release notes](https://github.com/expressjs/body-parser/releases) - [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md) - [Commits](https://github.com/expressjs/body-parser/compare/1.20.2...1.20.3) Updates `express` from 4.19.2 to 4.21.0 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md) - [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0) --- updated-dependencies: - dependency-name: body-parser dependency-type: indirect - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From 2c3b0fe02a6ea347d972193bebbd953e181f38ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 6 Oct 2024 23:17:11 +0200 Subject: [PATCH 06/53] Bump @grpc/grpc-js from 1.3.2 to 1.12.0 in /frontend (#490) Bumps [@grpc/grpc-js](https://github.com/grpc/grpc-node) from 1.3.2 to 1.12.0. - [Release notes](https://github.com/grpc/grpc-node/releases) - [Commits](https://github.com/grpc/grpc-node/compare/@grpc/grpc-js@1.3.2...@grpc/grpc-js@1.12.0) --- updated-dependencies: - dependency-name: "@grpc/grpc-js" dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 183 +++++++++++++++++++++++++++++++++++-- 1 file changed, 174 insertions(+), 9 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 7555251c..80ef5d7a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -3098,14 +3098,98 @@ } }, "node_modules/@grpc/grpc-js": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.3.2.tgz", - "integrity": "sha512-UXepkOKCATJrhHGsxt+CGfpZy9zUn1q9mop5kfcXq1fBkTePxVNPOdnISlCbJFlCtld+pSLGyZCzr9/zVprFKA==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.0.tgz", + "integrity": "sha512-eWdP97A6xKtZXVP/ze9y8zYRB2t6ugQAuLXFuZXAsyqmyltaAjl4yPkmIfc0wuTFJMOUF1AdvIFQCL7fMtaX6g==", "dependencies": { - "@types/node": ">=12.12.47" + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" }, "engines": { - "node": "^8.13.0 || >=10.10.0" + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/grpc-js/node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/grpc-js/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/grpc-js/node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "node_modules/@grpc/grpc-js/node_modules/protobufjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@grpc/grpc-js/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@grpc/grpc-js/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" } }, "node_modules/@grpc/proto-loader": { @@ -3861,6 +3945,15 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", @@ -20560,11 +20653,78 @@ } }, "@grpc/grpc-js": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.3.2.tgz", - "integrity": "sha512-UXepkOKCATJrhHGsxt+CGfpZy9zUn1q9mop5kfcXq1fBkTePxVNPOdnISlCbJFlCtld+pSLGyZCzr9/zVprFKA==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.0.tgz", + "integrity": "sha512-eWdP97A6xKtZXVP/ze9y8zYRB2t6ugQAuLXFuZXAsyqmyltaAjl4yPkmIfc0wuTFJMOUF1AdvIFQCL7fMtaX6g==", "requires": { - "@types/node": ">=12.12.47" + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "dependencies": { + "@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "requires": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + } + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "protobufjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + } + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + } } }, "@grpc/proto-loader": { @@ -21125,6 +21285,11 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==" + }, "@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", From e129d38e067bf65ebaccce1c7a2f601a34842009 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 6 Oct 2024 23:28:41 +0200 Subject: [PATCH 07/53] Bump braces from 3.0.2 to 3.0.3 in /frontend (#472) Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3. - [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3) --- updated-dependencies: - dependency-name: braces dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 80ef5d7a..b5616524 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -6182,11 +6182,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -8965,9 +8965,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -22978,11 +22978,11 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "browser-process-hrtime": { @@ -24993,9 +24993,9 @@ "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==" }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "requires": { "to-regex-range": "^5.0.1" } From c29121f4b9bd5a0881d4c5102d84423b6edb7ccf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 6 Oct 2024 23:28:55 +0200 Subject: [PATCH 08/53] Bump micromatch from 4.0.5 to 4.0.8 in /frontend (#479) Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.5 to 4.0.8. - [Release notes](https://github.com/micromatch/micromatch/releases) - [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/micromatch/compare/4.0.5...4.0.8) --- updated-dependencies: - dependency-name: micromatch dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b5616524..6baeac20 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12935,11 +12935,11 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -27869,11 +27869,11 @@ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "requires": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" } }, From c07e2d518e249d0f23b7f6b2f7100add9942f2e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 6 Oct 2024 23:29:03 +0200 Subject: [PATCH 09/53] Bump axios from 1.6.0 to 1.7.4 in /frontend (#478) Bumps [axios](https://github.com/axios/axios) from 1.6.0 to 1.7.4. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.6.0...v1.7.4) --- updated-dependencies: - dependency-name: axios dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 18 +++++++++--------- frontend/package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 6baeac20..c56cde8d 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -14,7 +14,7 @@ "@fortawesome/react-fontawesome": "^0.2.0", "@sentry/react": "^7.119.1", "ansi_up": "^5.0.0", - "axios": "^1.6.0", + "axios": "^1.7.4", "comlink": "^4.3.1", "comsync": "^0.0.8", "defaults": "^1.0.3", @@ -5749,11 +5749,11 @@ } }, "node_modules/axios": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", - "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -22631,11 +22631,11 @@ "integrity": "sha512-b1WlTV8+XKLj9gZy2DZXgQiyDp9xkkoe2a6U6UbYccScq2wgH/YwCeI2/Jq2mgo0HzQxqJOjWZBLeA/mqsk5Mg==" }, "axios": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", - "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", "requires": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" }, diff --git a/frontend/package.json b/frontend/package.json index ed56b8be..1411934a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,7 +14,7 @@ "@fortawesome/react-fontawesome": "^0.2.0", "@sentry/react": "^7.119.1", "ansi_up": "^5.0.0", - "axios": "^1.6.0", + "axios": "^1.7.4", "comlink": "^4.3.1", "comsync": "^0.0.8", "defaults": "^1.0.3", From fd90166fd7cc4d70e1714a94b403669829a2aba4 Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sun, 27 Oct 2024 17:14:45 +0200 Subject: [PATCH 10/53] Update birdseye for 3.12 (#492) And use secret google service account key --- .github/workflows/workflow.yml | 2 +- poetry.lock | 186 +++++++++++++++++---------------- 2 files changed, 96 insertions(+), 92 deletions(-) diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 11cb1cf2..1125143a 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -47,6 +47,6 @@ jobs: if: steps.build.outcome == 'success' && github.ref != 'refs/heads/master' with: repoToken: '${{ secrets.GITHUB_TOKEN }}' - firebaseServiceAccount: '{ "type": "service_account", "project_id": "futurecoder-staging", "private_key_id": "22b14cd951860ff430e5dbc8f594fb4bc8f6cdab", "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCfOtcinbvJ5t9J\nh1N3yA37BUBlm0UdibbcZkQhI2YI5oUogF//F8Q9giEGzKcGexM5Yz2mLKhkwGVl\n+j5H+C3EFqUUqtAHk7Lf/F7KnS54fjMz76MgxG80xFCxrZcD6jJerxKUroukIEsK\n7VO28oY16i2kWF8gFwCIeTPGbRcSi3Y+V9JbOaIkIafx7kOU4u0o6X/KymKmws6G\nW462VBfaOwF81cObDMDBUl2RvbDK7vw2XhyTd5ua/EGNv0gGNdnl3XNVYI+a81Ct\nM1GIxV0r77wHTpEHWkC6bUh+e5D5mom6NQkZo64jcQSKAtkUzSaVdeXkHdEJjEZC\no/xBGRjPAgMBAAECggEADn2ATnokOL912m8iPWhLPWjA734tz/5UUcJMuOdLxcuU\nmpb0JXa4ORC6iK/fE0vn9/T8Cz9NI74OfDVFra78GzgkVbklrUrXoGKLDc04CWcS\nqctJARZfOGIVJdYyQ/zwEIXGHxmzQ4Bc0+W9FI0FgaqJ9MbGAVmWhtTgzVHoI5vA\npPgDBYX6NTKUwcGcIAloapvGUSmBuNE2nt46TA8zR8UFCxSHogY030WQZJJrQhGY\nmwlmWcj4+yVP9DSzGKo4M6eEkfx/uoPT0SHED91Fev3lMre5j4Jcsw5DaAECnyS4\n6osyXDverxmoqHtDjULt8qZR6cpD1lj8j1rukX/ZYQKBgQDRt/UeiqeoGDiQMuii\nG8A6WKc8Ajt/H0NQTHiRxuK0KJWXQoo29rVIRTWYdhiryXn5Ox6IqHyzdR8n/45M\nS2MchwJ5flztePZAfAL1bT5VZ4wS9XvXmg6kqPVDztEM0b/tc8pYbu7vFaa3t1KZ\nWg5OHQG4ujSzB1ov3kZk1rNzIwKBgQDCXoYShoaoAsbXWGrZ5Alwia7ovm+EI0XT\nukeNZ+jrNPs6feBLSZtWmNpWcYtFtudrLJxn/5zesxJdT35y1C2HuH4//9UHpd7q\njKKonUXmRmP+5EirCYr08kO3fzrM8tPpZgEOx/hw+dvS04zgwjGSsZ4L2YyAtT13\nYteV2hFkZQKBgQC8dgHS1mtfxZRfEUC5HRMb27s9VAw/asrFCFN5PS9REv+LFIK8\nbevu7DMDtWzqQ35XGGeSC0c0xdWfzioEKeMBKdpxb7r2tLMms8q83tUbTpg0GWKX\nF5x9IFB4BQ0b5goBywJVgis5s01E33tcz+73B14asUrWb47+YVMFH2PX3QKBgQCx\nX0z+TuFHJPGLxtYLbPvoRNzm7BIcBYxNQOrW8gIt0jWJFSG/0rX8+pQU2pz7y4O3\n3AgHJ85htAyINmjwJQw/lG8xvCcNSaL5a8lsEcmd8JKEIpLl8llqWkLNiz9/lAEq\nNrm0YWwovPqLlB41ZUGT2p6dtbNwKPSkpACUcWH5uQKBgGO1hVeWdVgKESi4eDZF\nRiY7i/RvsVSz6FY4vOB8gjGFuPkucPnDQEczFU64HbqiVqqv50ceGm7CkYWekCbh\nWlqvH/ptmKt71taSi2hbNoinFqWoU2Wqs2n2JFAzFNrS8m2KYjshVK9/ycllGIFr\nYXCZv1gcS+vONiEt5lzPK/We\n-----END PRIVATE KEY-----\n", "client_email": "firebase-adminsdk-r0lzu@futurecoder-staging.iam.gserviceaccount.com", "client_id": "109050011633679213214", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-r0lzu%40futurecoder-staging.iam.gserviceaccount.com" }' + firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT }}' projectId: futurecoder-staging channelId: ${{ github.ref }} diff --git a/poetry.lock b/poetry.lock index 242a3e3d..3a461600 100644 --- a/poetry.lock +++ b/poetry.lock @@ -61,10 +61,10 @@ files = [ [[package]] name = "birdseye" -version = "0.9.1.dev6+g81273e6" +version = "0.9.6.dev23+g8aa06c7" description = "Minimal version of birdseye for futurecoder" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [] develop = false @@ -74,13 +74,13 @@ cheap_repr = "*" littleutils = ">=0.2" [package.extras] -tests = ["bs4", "pytest", "requests", "selenium"] +tests = ["bs4", "pytest", "selenium"] [package.source] type = "git" url = "https://github.com/alexmojaki/birdseye.git" reference = "futurecoder" -resolved_reference = "81273e689c5460a0b44ec28840e6adcf7fd6dad4" +resolved_reference = "8aa06c7e6854d22ecd9fcef05edca2acabb043a1" [[package]] name = "certifi" @@ -95,78 +95,78 @@ files = [ [[package]] name = "cffi" -version = "1.17.0" +version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" files = [ - {file = "cffi-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb"}, - {file = "cffi-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f"}, - {file = "cffi-1.17.0-cp310-cp310-win32.whl", hash = "sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc"}, - {file = "cffi-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb"}, - {file = "cffi-1.17.0-cp311-cp311-win32.whl", hash = "sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9"}, - {file = "cffi-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885"}, - {file = "cffi-1.17.0-cp312-cp312-win32.whl", hash = "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492"}, - {file = "cffi-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4"}, - {file = "cffi-1.17.0-cp313-cp313-win32.whl", hash = "sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a"}, - {file = "cffi-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7"}, - {file = "cffi-1.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c"}, - {file = "cffi-1.17.0-cp38-cp38-win32.whl", hash = "sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499"}, - {file = "cffi-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4"}, - {file = "cffi-1.17.0-cp39-cp39-win32.whl", hash = "sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb"}, - {file = "cffi-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29"}, - {file = "cffi-1.17.0.tar.gz", hash = "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, ] [package.dependencies] @@ -258,15 +258,18 @@ files = [ [[package]] name = "idna" -version = "3.8" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" files = [ - {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, - {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + [[package]] name = "iniconfig" version = "2.0.0" @@ -489,13 +492,13 @@ tests = ["pytest", "snoop"] [[package]] name = "selenium" -version = "4.24.0" +version = "4.25.0" description = "Official Python bindings for Selenium WebDriver" optional = false python-versions = ">=3.8" files = [ - {file = "selenium-4.24.0-py3-none-any.whl", hash = "sha256:42c23f60753d5415b261b236cecbd69bd4eb5271e1563915f546b443cb6b71c6"}, - {file = "selenium-4.24.0.tar.gz", hash = "sha256:88281e5b5b90fe231868905d5ea745b9ee5e30db280b33498cc73fb0fa06d571"}, + {file = "selenium-4.25.0-py3-none-any.whl", hash = "sha256:3798d2d12b4a570bc5790163ba57fef10b2afee958bf1d80f2a3cf07c4141f33"}, + {file = "selenium-4.25.0.tar.gz", hash = "sha256:95d08d3b82fb353f3c474895154516604c7f0e6a9a565ae6498ef36c9bac6921"}, ] [package.dependencies] @@ -508,13 +511,13 @@ websocket-client = ">=1.8,<2.0" [[package]] name = "sentry-sdk" -version = "2.13.0" +version = "2.17.0" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = ">=3.6" files = [ - {file = "sentry_sdk-2.13.0-py2.py3-none-any.whl", hash = "sha256:6beede8fc2ab4043da7f69d95534e320944690680dd9a963178a49de71d726c6"}, - {file = "sentry_sdk-2.13.0.tar.gz", hash = "sha256:8d4a576f7a98eb2fdb40e13106e41f330e5c79d72a68be1316e7852cf4995260"}, + {file = "sentry_sdk-2.17.0-py2.py3-none-any.whl", hash = "sha256:625955884b862cc58748920f9e21efdfb8e0d4f98cca4ab0d3918576d5b606ad"}, + {file = "sentry_sdk-2.17.0.tar.gz", hash = "sha256:dd0a05352b78ffeacced73a94e86f38b32e2eae15fff5f30ca5abb568a72eacf"}, ] [package.dependencies] @@ -537,6 +540,7 @@ falcon = ["falcon (>=1.4)"] fastapi = ["fastapi (>=0.79.0)"] flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"] grpcio = ["grpcio (>=1.21.1)", "protobuf (>=3.8.0)"] +http2 = ["httpcore[http2] (==1.*)"] httpx = ["httpx (>=0.16.0)"] huey = ["huey (>=2)"] huggingface-hub = ["huggingface-hub (>=0.22)"] @@ -559,18 +563,18 @@ tornado = ["tornado (>=6)"] [[package]] name = "setuptools" -version = "74.0.0" +version = "75.2.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-74.0.0-py3-none-any.whl", hash = "sha256:0274581a0037b638b9fc1c6883cc71c0210865aaa76073f7882376b641b84e8f"}, - {file = "setuptools-74.0.0.tar.gz", hash = "sha256:a85e96b8be2b906f3e3e789adec6a9323abf79758ecfa3065bd740d81158b11e"}, + {file = "setuptools-75.2.0-py3-none-any.whl", hash = "sha256:a7fcb66f68b4d9e8e66b42f9876150a3371558f98fa32222ffaa5bced76406f8"}, + {file = "setuptools-75.2.0.tar.gz", hash = "sha256:753bb6ebf1f465a1912e19ed1d41f403a79173a9acf66a42e7e6aec45c3c16ec"}, ] [package.extras] check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] -core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] @@ -651,13 +655,13 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] [[package]] name = "trio" -version = "0.26.2" +version = "0.27.0" description = "A friendly Python library for async concurrency and I/O" optional = false python-versions = ">=3.8" files = [ - {file = "trio-0.26.2-py3-none-any.whl", hash = "sha256:c5237e8133eb0a1d72f09a971a55c28ebe69e351c783fc64bc37db8db8bbe1d0"}, - {file = "trio-0.26.2.tar.gz", hash = "sha256:0346c3852c15e5c7d40ea15972c4805689ef2cb8b5206f794c9c19450119f3a4"}, + {file = "trio-0.27.0-py3-none-any.whl", hash = "sha256:68eabbcf8f457d925df62da780eff15ff5dc68fd6b367e2dde59f7aaf2a0b884"}, + {file = "trio-0.27.0.tar.gz", hash = "sha256:1dcc95ab1726b2da054afea8fd761af74bad79bd52381b84eae408e983c76831"}, ] [package.dependencies] @@ -696,13 +700,13 @@ files = [ [[package]] name = "urllib3" -version = "2.2.2" +version = "2.2.3" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, - {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, + {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, + {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, ] [package.dependencies] From 1b1e402e266181092adffcfc18eb958047572bbf Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sun, 27 Oct 2024 19:01:51 +0200 Subject: [PATCH 11/53] assistant section arrows without font awesome font --- frontend/src/css/main.scss | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/src/css/main.scss b/frontend/src/css/main.scss index e4156cb4..da5d1daa 100644 --- a/frontend/src/css/main.scss +++ b/frontend/src/css/main.scss @@ -478,8 +478,9 @@ } &:after { - font-family: 'FontAwesome'; - content: '\f107'; + transform: translatey(-3px) rotate(180deg) scalex(1.2); + font-family: 'Tahoma', sans-serif; + content: '^'; position: absolute; right: 20px; top: 10px; @@ -489,7 +490,7 @@ &.is-open { &:after { - transform: rotateZ(180deg); + transform: translatey(3px) rotate(0deg) scalex(1.2); } } } From 44f6186b257a3a94c9f8f558c5064dcb97a9475b Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sun, 27 Oct 2024 22:52:50 +0200 Subject: [PATCH 12/53] workaround a specific unicode bug in 3.12.1 in one step in spanish --- core/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/core/utils.py b/core/utils.py index b680c42f..d6a32817 100644 --- a/core/utils.py +++ b/core/utils.py @@ -332,6 +332,7 @@ def split_into_tokens_gen(s): for t1, t2 in zip(tokens, tokens[1:]): start1, end1 = token_text_range(t1, linenos) start2, end2 = token_text_range(t2, linenos) + end1 = min(end1, start2) # workaround a specific unicode bug in 3.12.1 assert start1 <= end1 <= start2 <= end2 yield s[start1:end1] yield s[end1:start2] From b64d20cf86470645aa43ec5d43805f9a43ad482e Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sun, 27 Oct 2024 23:21:54 +0200 Subject: [PATCH 13/53] update french translation --- core/chapters/c12_dictionaries.py | 2 +- tests/golden_files/fr/test_transcript.json | 783 +++++------------- translations/english.po | 2 +- .../locales/en/LC_MESSAGES/futurecoder.mo | Bin 297004 -> 297003 bytes .../locales/fr/LC_MESSAGES/futurecoder.mo | Bin 324407 -> 331872 bytes 5 files changed, 232 insertions(+), 555 deletions(-) diff --git a/core/chapters/c12_dictionaries.py b/core/chapters/c12_dictionaries.py index c4ecd336..6b70b08c 100644 --- a/core/chapters/c12_dictionaries.py +++ b/core/chapters/c12_dictionaries.py @@ -450,7 +450,7 @@ class keys_are_iterable2(VerbatimStep): program_in_text = False requirements = ( - "Run the same code as the previous step, but without `.keys()`. after `quantities`, " + "Run the same code as the previous step, but without `.keys()` after `quantities`, " "so the middle line is `for key in quantities:`" ) diff --git a/tests/golden_files/fr/test_transcript.json b/tests/golden_files/fr/test_transcript.json index bfdfb16b..d4e74041 100644 --- a/tests/golden_files/fr/test_transcript.json +++ b/tests/golden_files/fr/test_transcript.json @@ -17,12 +17,12 @@ "step": "first_expression" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de la console", "program": [ "1+2" ], "response": { - "message": "", "passed": true, "result": [ { @@ -52,12 +52,12 @@ "step": "more_calculation" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de la console", "program": [ "5 - 6" ], "response": { - "message": "", "passed": true, "result": [ { @@ -69,12 +69,12 @@ "step": "more_calculation" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des chaines", "program": [ "'hello'" ], "response": { - "message": "", "passed": true, "result": [ { @@ -86,12 +86,12 @@ "step": "hello_string" }, { + "get_solution": "program", "page": "Concat\u00e9nation de chaines", "program": [ "'hello' + 'world'" ], "response": { - "message": "", "passed": true, "result": [ { @@ -120,15 +120,12 @@ "step": "hello_world_space" }, { - "get_solution": [ - "'hello ' + 'world'" - ], + "get_solution": "program", "page": "Concat\u00e9nation de chaines", "program": [ "'hello ' + 'world'" ], "response": { - "message": "", "passed": true, "result": [ { @@ -140,12 +137,12 @@ "step": "hello_world_space" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des variables", "program": [ "mot = 'Hello'" ], "response": { - "message": "", "passed": true, "result": [] }, @@ -164,12 +161,12 @@ "step": "word_check" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des variables", "program": [ "mot" ], "response": { - "message": "", "passed": true, "result": [ { @@ -181,12 +178,12 @@ "step": "word_check" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des variables", "program": [ "'mot'" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "'mot'", @@ -208,12 +205,12 @@ "step": "word_string_check" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des variables", "program": [ "soleil" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Erreur", @@ -311,31 +308,31 @@ "votre_nom = ' Alex'" ], "response": { - "message": "

Pour cet exercice, choisissez un nom qui ne commence pas par une espace.

", + "message": "

Pour cet exercice, choisissez un nom qui ne commence pas par un espace.

", "passed": false, "result": [] }, "step": "name_assign" }, { + "get_solution": "program", "page": "Utilisation de variables et de print()", "program": [ "votre_nom = 'Alex'" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "name_assign" }, { + "get_solution": "program", "page": "Utilisation de variables et de print()", "program": [ "'Hello ' + votre_nom" ], "response": { - "message": "", "passed": true, "result": [ { @@ -359,12 +356,12 @@ "step": "word_plus_name" }, { + "get_solution": "program", "page": "Utilisation de variables et de print()", "program": [ "mot + votre_nom" ], "response": { - "message": "", "passed": true, "result": [ { @@ -388,15 +385,12 @@ "step": "word_plus_name_with_space" }, { - "get_solution": [ - "mot + ' ' + votre_nom" - ], + "get_solution": "program", "page": "Utilisation de variables et de print()", "program": [ "mot + ' ' + votre_nom" ], "response": { - "message": "", "passed": true, "result": [ { @@ -408,24 +402,24 @@ "step": "word_plus_name_with_space" }, { + "get_solution": "program", "page": "Utilisation de variables et de print()", "program": [ "mot = 'Goodbye'" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "word_assign_goodbye" }, { + "get_solution": "program", "page": "Utilisation de variables et de print()", "program": [ "mot + ' ' + votre_nom" ], "response": { - "message": "", "passed": true, "result": [ { @@ -437,12 +431,12 @@ "step": "goodbye_plus_name" }, { + "get_solution": "program", "page": "Utilisation de variables et de print()", "program": [ "print(mot + ' ' + votre_nom)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -454,6 +448,7 @@ "step": "first_print" }, { + "get_solution": "program", "page": "\u00c9criture de scripts", "program": [ "mot = 'Hello'", @@ -463,7 +458,6 @@ "print(mot + ' ' + nom)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -475,6 +469,7 @@ "step": "editor_hello_world" }, { + "get_solution": "program", "page": "Stockage de r\u00e9sultats avec des variables", "program": [ "mot = 'Hello'", @@ -483,7 +478,6 @@ "print(phrase)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello World", @@ -507,6 +501,7 @@ "step": "sentence_equals_word_plus_name" }, { + "get_solution": "program", "page": "Stockage de r\u00e9sultats avec des variables", "program": [ "mot = 'Hello'", @@ -517,7 +512,6 @@ "print(phrase)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello World\nHello World", @@ -538,13 +532,13 @@ "step": "sentence_doesnt_change" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des boucles for", "program": [ "nom = 'World'", "for caractere in nom: print(caractere)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -556,13 +550,13 @@ "step": "first_for_loop" }, { + "get_solution": "program", "page": "Indentation", "program": [ "for caractere in nom:", "print(caractere)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -575,6 +569,7 @@ "step": "missing_indentation" }, { + "get_solution": "program", "page": "Indentation", "program": [ "nom = 'World'", @@ -584,7 +579,6 @@ " print('---')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -596,6 +590,7 @@ "step": "two_indented_lines" }, { + "get_solution": "program", "page": "Indentation", "program": [ "nom = 'World'", @@ -605,7 +600,6 @@ "print('---')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -617,6 +611,7 @@ "step": "one_indented_line" }, { + "get_solution": "program", "page": "Indentation", "program": [ "for caractere in nom:", @@ -624,7 +619,6 @@ " print('---')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -648,7 +642,6 @@ " print('---' + caractere)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -671,7 +664,6 @@ " print(nom)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -683,6 +675,7 @@ "step": "loop_exercise_2" }, { + "get_solution": "program", "page": "Construction de chaines", "program": [ "hello = 'Hello'", @@ -691,7 +684,6 @@ "print(hello)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello\nHello!", @@ -712,6 +704,7 @@ "step": "hello_plus_equals" }, { + "get_solution": "program", "page": "Construction de chaines", "program": [ "nom = 'World'", @@ -721,7 +714,6 @@ " print(ligne)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "-W\n-Wo\n-Wor\n-Worl\n-World", @@ -747,6 +739,7 @@ "step": "name_triangle" }, { + "get_solution": "program", "page": "Construction de chaines", "program": [ "nom = 'World'", @@ -756,7 +749,6 @@ " ligne = ligne + caractere" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "-\n-W\n-Wo\n-Wor\n-Worl", @@ -777,12 +769,12 @@ "step": "name_triangle_missing_last_line" }, { + "get_solution": "program", "page": "Construction de chaines", "program": [ "'' + '' + ''" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "''", @@ -824,7 +816,6 @@ " print(ligne)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -851,7 +842,6 @@ " print(ligne)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -878,7 +868,6 @@ " print(ligne)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -907,7 +896,6 @@ "print(ligne)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -940,7 +928,6 @@ "print(ligne)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -977,7 +964,6 @@ "print(ligne)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -998,7 +984,7 @@ " print(espaces + caractere)" ], "response": { - "message": "

On y est presque ! Vous avez une espace de trop avant chaque lettre.\nAssurez-vous que la premi\u00e8re fois que votre boucle appelle print votre variable qui contiendra les espaces soit une cha\u00eene vide.\nV\u00e9rifiez l'agencement de votre code.

", + "message": "

On y est presque ! Vous avez un espace de trop avant chaque lettre.\nAssurez-vous que la premi\u00e8re fois que votre boucle appelle print votre variable qui contiendra les espaces soit une cha\u00eene vide.\nV\u00e9rifiez l'agencement de votre code.

", "passed": false, "result": [ { @@ -1025,7 +1011,6 @@ " espaces += ' '" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1037,6 +1022,7 @@ "step": "diagonal_name_bonus_challenge" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des structures conditionnelles", "program": [ "condition = True", @@ -1045,7 +1031,6 @@ "print(condition)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1057,6 +1042,7 @@ "step": "introducing_booleans" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des structures conditionnelles", "program": [ "if True:", @@ -1066,7 +1052,6 @@ " print('Ceci non')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1078,6 +1063,7 @@ "step": "first_if_statements" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des structures conditionnelles", "program": [ "phrase = 'Hello World'", @@ -1087,7 +1073,6 @@ "print(phrase)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello World!", @@ -1107,6 +1092,7 @@ "step": "excited_example" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des structures conditionnelles", "program": [ "phrase = 'Hello World'", @@ -1116,7 +1102,6 @@ "print(phrase)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello World", @@ -1155,7 +1140,6 @@ "print(phrase)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1167,6 +1151,7 @@ "step": "excited_confused_exercise" }, { + "get_solution": "program", "page": "Structures imbriqu\u00e9es", "program": [ "phrase = 'Hello World'", @@ -1181,7 +1166,6 @@ "print(phrase)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "H!e!l!l!o! !W!o!r!l!d!", @@ -1208,6 +1192,7 @@ "step": "for_inside_if" }, { + "get_solution": "program", "page": "Observation des programmes avec snoop", "program": [ "phrase = 'Hello World'", @@ -1222,7 +1207,6 @@ "print(nouvelle_phrase)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "ello World", @@ -1245,6 +1229,7 @@ "step": "print_tail" }, { + "get_solution": "program", "page": "Observation des programmes avec snoop", "program": [ "phrase = 'Hello World'", @@ -1259,31 +1244,30 @@ "print(nouvelle_phrase)" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | phrase \u001b[38;5;197m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | inclus \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mFalse\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 4\u001b[0m | nouvelle_phrase \u001b[38;5;197m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;197min\u001b[39m phrase:\n\u001b[38;5;242m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mH\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | inclus \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;197min\u001b[39m phrase:\n\u001b[38;5;242m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | nouvelle_phrase \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m caractere\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | phrase \u001b[38;5;204m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | inclus \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mFalse\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 4\u001b[0m | nouvelle_phrase \u001b[38;5;204m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;204min\u001b[39m phrase:\n\u001b[38;5;245m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mH\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | inclus \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;204min\u001b[39m phrase:\n\u001b[38;5;245m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | nouvelle_phrase \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m caractere\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | inclus \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;197min\u001b[39m phrase:\n\u001b[38;5;242m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | nouvelle_phrase \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m caractere\n\u001b[38;5;242m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mel\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | inclus \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;197min\u001b[39m phrase:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | nouvelle_phrase \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m caractere\n", + "text": "\u001b[38;5;245m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | inclus \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;204min\u001b[39m phrase:\n\u001b[38;5;245m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | nouvelle_phrase \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m caractere\n\u001b[38;5;245m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mel\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | inclus \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;204min\u001b[39m phrase:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | nouvelle_phrase \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m caractere\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mell\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | inclus \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;197min\u001b[39m phrase:\n\u001b[38;5;242m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | nouvelle_phrase \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m caractere\n\u001b[38;5;242m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | inclus \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;197min\u001b[39m phrase:\n\u001b[38;5;242m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | nouvelle_phrase \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m caractere\n", + "text": "\u001b[38;5;245m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mell\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | inclus \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;204min\u001b[39m phrase:\n\u001b[38;5;245m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | nouvelle_phrase \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m caractere\n\u001b[38;5;245m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | inclus \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;204min\u001b[39m phrase:\n\u001b[38;5;245m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | nouvelle_phrase \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m caractere\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | inclus \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;197min\u001b[39m phrase:\n\u001b[38;5;242m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mW\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | nouvelle_phrase \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m caractere\n\u001b[38;5;242m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello W\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | inclus \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;197min\u001b[39m phrase:\n\u001b[38;5;242m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | nouvelle_phrase \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m caractere\n", + "text": "\u001b[38;5;245m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | inclus \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;204min\u001b[39m phrase:\n\u001b[38;5;245m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mW\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | nouvelle_phrase \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m caractere\n\u001b[38;5;245m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello W\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | inclus \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;204min\u001b[39m phrase:\n\u001b[38;5;245m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | nouvelle_phrase \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m caractere\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | inclus \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;197min\u001b[39m phrase:\n\u001b[38;5;242m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mr\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | nouvelle_phrase \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m caractere\n\u001b[38;5;242m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wor\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | inclus \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;197min\u001b[39m phrase:\n\u001b[38;5;242m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | nouvelle_phrase \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m caractere\n", + "text": "\u001b[38;5;245m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | inclus \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;204min\u001b[39m phrase:\n\u001b[38;5;245m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mr\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | nouvelle_phrase \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m caractere\n\u001b[38;5;245m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wor\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | inclus \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;204min\u001b[39m phrase:\n\u001b[38;5;245m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | nouvelle_phrase \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m caractere\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Worl\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | inclus \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;197min\u001b[39m phrase:\n\u001b[38;5;242m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186md\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | nouvelle_phrase \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m caractere\n\u001b[38;5;242m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | inclus \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;197min\u001b[39m phrase:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 10\u001b[0m | print(nouvelle_phrase)\n", + "text": "\u001b[38;5;245m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Worl\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | inclus \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;204min\u001b[39m phrase:\n\u001b[38;5;245m \u001b[0m...... caractere = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186md\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m inclus:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | nouvelle_phrase \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m caractere\n\u001b[38;5;245m \u001b[0m.............. nouvelle_phrase = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | inclus \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m caractere \u001b[38;5;204min\u001b[39m phrase:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 10\u001b[0m | print(nouvelle_phrase)\n", "type": "snoop" }, { @@ -1326,7 +1310,6 @@ "print(nouvelle_phrase)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1338,6 +1321,7 @@ "step": "print_first_character" }, { + "get_solution": "program", "page": "if et else, le bloc sinon", "program": [ "condition = True", @@ -1347,7 +1331,6 @@ " print('Non')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1359,6 +1342,7 @@ "step": "first_if_else" }, { + "get_solution": "program", "page": "if et else, le bloc sinon", "program": [ "condition = False", @@ -1368,7 +1352,6 @@ " print('Non')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1380,6 +1363,7 @@ "step": "first_if_else_false" }, { + "get_solution": "program", "page": "if et else, le bloc sinon", "program": [ "phrase = 'Hello World'", @@ -1391,7 +1375,6 @@ "print(phrase)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1403,6 +1386,7 @@ "step": "if_upper_else_lower" }, { + "get_solution": "program", "page": "if et else, le bloc sinon", "program": [ "phrase = 'Hello World'", @@ -1414,7 +1398,6 @@ "print(phrase)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1426,6 +1409,7 @@ "step": "if_upper_else_lower_false" }, { + "get_solution": "program", "page": "if et else, le bloc sinon", "program": [ "phrase = 'Hello World'", @@ -1438,7 +1422,6 @@ "print(phrase)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Erreur", @@ -1527,7 +1510,6 @@ "print(phrase)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1568,7 +1550,6 @@ "print(nouvelle_phrase)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1611,7 +1592,6 @@ "print(nouvelle_phrase)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1623,6 +1603,7 @@ "step": "spongebob" }, { + "get_solution": "program", "page": "L'op\u00e9rateur d'\u00e9galit\u00e9", "program": [ "print(1 + 2 == 3)", @@ -1630,7 +1611,6 @@ "print('ab' + 'c' == 'a' + 'bc')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1642,12 +1622,12 @@ "step": "introducing_equality" }, { + "get_solution": "program", "page": "L'op\u00e9rateur d'\u00e9galit\u00e9", "program": [ "print(1 + 2 = 3)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1660,6 +1640,7 @@ "step": "equality_vs_assignment" }, { + "get_solution": "program", "page": "L'op\u00e9rateur d'\u00e9galit\u00e9", "program": [ "nom = 'Melissa'", @@ -1672,7 +1653,6 @@ "print(nouveau_nom)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1713,7 +1693,6 @@ "print(nouveau_nom)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1725,6 +1704,7 @@ "step": "if_equals_replacing_characters_exercise" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de elif, le bloc sinon si", "program": [ "adn = 'AGTAGCGTC'", @@ -1743,7 +1723,6 @@ "print(adn_inverse)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1792,7 +1771,6 @@ "print(adn_inverse)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1804,6 +1782,7 @@ "step": "dna_example_with_else" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de elif, le bloc sinon si", "program": [ "adn = 'AGTAGCGTC'", @@ -1822,7 +1801,6 @@ "print(adn_inverse)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1834,12 +1812,12 @@ "step": "dna_example_with_elif" }, { + "get_solution": "program", "page": "Autres op\u00e9rateurs de comparaison", "program": [ "1 != 2" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", @@ -1859,6 +1837,7 @@ "step": "try_not_equals" }, { + "get_solution": "program", "page": "Autres op\u00e9rateurs de comparaison", "program": [ "phrase = 'La touche e de mon clavier est cass\u00e9e'", @@ -1869,7 +1848,6 @@ "print(nouvelle_phrase)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1881,15 +1859,12 @@ "step": "brokn_kyboard" }, { - "get_solution": [ - "1 < 2" - ], + "get_solution": "program", "page": "Autres op\u00e9rateurs de comparaison", "program": [ "1 < 2" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1901,15 +1876,12 @@ "step": "introducing_less_than" }, { - "get_solution": [ - "'1' < '2'" - ], + "get_solution": "program", "page": "Autres op\u00e9rateurs de comparaison", "program": [ "'1' < '2'" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1921,6 +1893,7 @@ "step": "comparing_strings" }, { + "get_solution": "program", "page": "Autres op\u00e9rateurs de comparaison", "program": [ "pourcentage = 73", @@ -1937,7 +1910,6 @@ "print(note)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "B", @@ -1990,7 +1962,6 @@ "print(premier)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2002,6 +1973,7 @@ "step": "min_three_exercise" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des listes", "program": [ "mots = ['Ceci', 'est', 'une', 'liste']", @@ -2010,7 +1982,6 @@ " print(mot)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2022,6 +1993,7 @@ "step": "first_list" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des listes", "program": [ "x = 1", @@ -2029,7 +2001,6 @@ "print(choses)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2041,6 +2012,7 @@ "step": "can_contain_anything" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des listes", "program": [ "nombres = [3, 1, 4, 1, 5, 9]", @@ -2052,7 +2024,6 @@ "print(total)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2081,7 +2052,6 @@ "print(total)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2121,7 +2091,6 @@ "print(total)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2148,7 +2117,6 @@ "print(double)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2177,7 +2145,6 @@ "print(grands_nombres)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2209,7 +2176,6 @@ "print(trouve)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2221,6 +2187,7 @@ "step": "list_contains_exercise" }, { + "get_solution": "program", "page": "Lecture d'\u00e9l\u00e9ments \u00e0 une position, range() et len()", "program": [ "mots = ['Ceci', 'est', 'une', 'liste']", @@ -2231,7 +2198,6 @@ "print(mots[3])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2243,12 +2209,12 @@ "step": "introducing_subscripting" }, { + "get_solution": "program", "page": "Lecture d'\u00e9l\u00e9ments \u00e0 une position, range() et len()", "program": [ "mots[4]" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2301,6 +2267,7 @@ "step": "index_error" }, { + "get_solution": "program", "page": "Lecture d'\u00e9l\u00e9ments \u00e0 une position, range() et len()", "program": [ "mots = ['Ceci', 'est', 'une', 'liste']", @@ -2311,7 +2278,6 @@ " print(mots[i])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "0\nCeci\n1\nest\n2\nune\n3\nliste", @@ -2335,6 +2301,7 @@ "step": "introducing_len_and_range" }, { + "get_solution": "program", "page": "Lecture d'\u00e9l\u00e9ments \u00e0 une position, range() et len()", "program": [ "mots = ['Ceci', 'est', 'une', 'liste']", @@ -2345,7 +2312,6 @@ " print(mots[i])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2357,6 +2323,7 @@ "step": "range_len" }, { + "get_solution": "program", "page": "Lecture d'\u00e9l\u00e9ments \u00e0 une position, range() et len()", "program": [ "indices = range(4)", @@ -2367,7 +2334,6 @@ "print(indices[3])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "0\n1\n2\n3", @@ -2390,12 +2356,12 @@ "step": "printing_the_range" }, { + "get_solution": "program", "page": "Lecture d'\u00e9l\u00e9ments \u00e0 une position, range() et len()", "program": [ "indices[4]" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Erreur", @@ -2459,12 +2425,12 @@ "step": "indices_out_of_bounds" }, { + "get_solution": "program", "page": "Lecture d'\u00e9l\u00e9ments \u00e0 une position, range() et len()", "program": [ "range(4)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2476,12 +2442,12 @@ "step": "range_almost_the_same_as_list" }, { + "get_solution": "program", "page": "Lecture d'\u00e9l\u00e9ments \u00e0 une position, range() et len()", "program": [ "list(range(4))" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[0, 1, 2, 3]", @@ -2506,13 +2472,13 @@ "step": "range_versus_list" }, { + "get_solution": "program", "page": "Lecture d'\u00e9l\u00e9ments \u00e0 une position, range() et len()", "program": [ "mots = ['Ceci', 'est', 'une', 'liste']", "print(len(mots))" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "4", @@ -2545,7 +2511,6 @@ "print(mots[len(mots) - 1])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2570,7 +2535,6 @@ " print(mots[indice])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2642,7 +2606,6 @@ " break" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2670,7 +2633,6 @@ " print(caractere_1 + ' ' + caractere_2)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2730,7 +2692,6 @@ " print(caractere_1 + ' ' + caractere_2)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2742,13 +2703,13 @@ "step": "zip_longest_exercise" }, { + "get_solution": "program", "page": "Vocabulaire sur les appels de fonctions et les m\u00e9thodes", "program": [ "print(len)", "print(print)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2760,12 +2721,12 @@ "step": "print_functions" }, { + "get_solution": "program", "page": "Vocabulaire sur les appels de fonctions et les m\u00e9thodes", "program": [ "print(callable(len))" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2777,6 +2738,7 @@ "step": "introducing_callable" }, { + "get_solution": "program", "page": "Vocabulaire sur les appels de fonctions et les m\u00e9thodes", "program": [ "f = 'une chaine'", @@ -2784,7 +2746,6 @@ "f()" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2823,7 +2784,7 @@ ] } ], - "friendly": "

Une exception TypeError est g\u00e9n\u00e9ralement caus\u00e9e par une tentative\nde combiner deux types d\u2019objets incompatibles,\nen invoquant une fonction avec le mauvais type d\u2019objet,\nou en tentant d'effectuer une op\u00e9ration non permise sur un type d'objet donn\u00e9.

\n

En raison des parenth\u00e8ses, f est interpr\u00e9t\u00e9 par Python\ncomme indiquant une invocation de fonction pour f.\nCelui-ci n'est pas une fonction mais plut\u00f4t un objet de type str\nne pouvant pas \u00eatre invoqu\u00e9.

", + "friendly": "

Une exception TypeError est g\u00e9n\u00e9ralement caus\u00e9e par une tentative\nde combiner deux types d\u2019objets incompatibles,\nen invoquant une fonction avec le mauvais type d\u2019objet,\nou en tentant d'effectuer une op\u00e9ration non permise sur un type d'objet donn\u00e9.

\n

En raison des parenthees, ` est interpr\u00e9t\u00e9 par Python\ncomme indiquant une invocation de fonction pourf, qui est un objet de typestr`\nne pouvant pas \u00eatre invoqu\u00e9.

", "tail": "" } ], @@ -2844,6 +2805,7 @@ "step": "not_callable" }, { + "get_solution": "program", "page": "Vocabulaire sur les appels de fonctions et les m\u00e9thodes", "program": [ "choses = [1, 2, 3]", @@ -2852,7 +2814,6 @@ "print(affichage)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2864,13 +2825,13 @@ "step": "print_returns_none" }, { + "get_solution": "program", "page": "Vocabulaire sur les appels de fonctions et les m\u00e9thodes", "program": [ "choses = print([1, 2, 3])", "longueur = len(choses)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2930,6 +2891,7 @@ "step": "len_of_none" }, { + "get_solution": "program", "page": "Vocabulaire sur les appels de fonctions et les m\u00e9thodes", "program": [ "mot = 'Hello'", @@ -2937,7 +2899,6 @@ "print(mot.upper())" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2949,13 +2910,13 @@ "step": "methods_of_str" }, { + "get_solution": "program", "page": "Vocabulaire sur les appels de fonctions et les m\u00e9thodes", "program": [ "mot = 'Hello'", "mot.append('!')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3009,6 +2970,7 @@ "step": "no_append_for_str" }, { + "get_solution": "program", "page": "Fonctions et m\u00e9thodes sur les listes", "program": [ "nombres = [1, 2, 3]", @@ -3019,7 +2981,6 @@ "print(nombres)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3031,6 +2992,7 @@ "step": "append_vs_concatenate" }, { + "get_solution": "program", "page": "Fonctions et m\u00e9thodes sur les listes", "program": [ "nombres = [1, 2, 3]", @@ -3038,7 +3000,6 @@ "print(nombres)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[1, 9, 3]", @@ -3062,12 +3023,12 @@ "step": "subscript_assignment_predict" }, { + "get_solution": "program", "page": "Fonctions et m\u00e9thodes sur les listes", "program": [ "[7, 8, 9, 8].index(8)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "1", @@ -3091,6 +3052,7 @@ "step": "index_predict_exercise" }, { + "get_solution": "program", "page": "Fonctions et m\u00e9thodes sur les listes", "program": [ "nombres = [1, 2, 3]", @@ -3098,7 +3060,6 @@ "print(nombres)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "2\n[1, 3]", @@ -3122,6 +3083,7 @@ "step": "pop_predict_exercise" }, { + "get_solution": "program", "page": "Fonctions et m\u00e9thodes sur les listes", "program": [ "nombres = [1, 2, 3]", @@ -3129,7 +3091,6 @@ "print(nombres)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[2, 3]", @@ -3153,11 +3114,7 @@ "step": "remove_predict_exercise" }, { - "get_solution": [ - "x = ['a', 'b', 'c']", - "x.append(x.pop(0))", - "print(x)" - ], + "get_solution": "program", "page": "Fonctions et m\u00e9thodes sur les listes", "program": [ "x = ['a', 'b', 'c']", @@ -3165,7 +3122,6 @@ "print(x)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3177,11 +3133,7 @@ "step": "pop_remove_index_subscript_assignment" }, { - "get_solution": [ - "x = ['a', 'b', 'c']", - "x[len(x) - 1] = x[0]", - "print(x)" - ], + "get_solution": "program", "page": "Fonctions et m\u00e9thodes sur les listes", "program": [ "x = ['a', 'b', 'c']", @@ -3189,7 +3141,6 @@ "print(x)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3201,11 +3152,7 @@ "step": "subscript_assignment_exercise" }, { - "get_solution": [ - "x = ['a', 'b', 'c']", - "y = x + [x[0]]", - "print(y)" - ], + "get_solution": "program", "page": "Fonctions et m\u00e9thodes sur les listes", "program": [ "x = ['a', 'b', 'c']", @@ -3213,7 +3160,6 @@ "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3225,11 +3171,7 @@ "step": "negative_index_concatenation_exercise" }, { - "get_solution": [ - "x = [1, 2, 0, 3]", - "x.pop(x.index(0))", - "print(x)" - ], + "get_solution": "program", "page": "Fonctions et m\u00e9thodes sur les listes", "program": [ "x = [1, 2, 0, 3]", @@ -3237,7 +3179,6 @@ "print(x)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3249,12 +3190,12 @@ "step": "remove_exercise" }, { + "get_solution": "program", "page": "Plus de fonctions et de m\u00e9thodes sur les listes", "program": [ "sorted([2, 9, 1, 8, 5, 6])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[1, 2, 5, 6, 8, 9]", @@ -3276,6 +3217,7 @@ "step": "sorted_predict_exercise" }, { + "get_solution": "program", "page": "Plus de fonctions et de m\u00e9thodes sur les listes", "program": [ "nombres = [2, 9, 1, 8, 5, 64]", @@ -3283,7 +3225,6 @@ "print(2 in nombres)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False\nTrue", @@ -3305,12 +3246,12 @@ "step": "in_predict_exercise" }, { + "get_solution": "program", "page": "Plus de fonctions et de m\u00e9thodes sur les listes", "program": [ "sum([5, 3, 4])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "12", @@ -3331,12 +3272,12 @@ "step": "sum_predict_exercise" }, { + "get_solution": "program", "page": "Plus de fonctions et de m\u00e9thodes sur les listes", "program": [ "[1, 2, 3, 2, 7, 2, 5].count(2)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "3", @@ -3358,11 +3299,7 @@ "step": "count_predict_exercise" }, { - "get_solution": [ - "x = [1, 2, 0, 3]", - "y = x.count(1) > 0", - "print(y)" - ], + "get_solution": "program", "page": "Plus de fonctions et de m\u00e9thodes sur les listes", "program": [ "x = [1, 2, 0, 3]", @@ -3370,7 +3307,6 @@ "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3382,11 +3318,7 @@ "step": "count_in_sorted_sum" }, { - "get_solution": [ - "x = [15, 12, -6, 3]", - "y = sum(x) / len(x)", - "print(y)" - ], + "get_solution": "program", "page": "Plus de fonctions et de m\u00e9thodes sur les listes", "program": [ "x = [15, 12, -6, 3]", @@ -3394,7 +3326,6 @@ "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3406,11 +3337,7 @@ "step": "average_exercise" }, { - "get_solution": [ - "x = 100", - "y = sum(range(x + 1))", - "print(y)" - ], + "get_solution": "program", "page": "Plus de fonctions et de m\u00e9thodes sur les listes", "program": [ "x = 100", @@ -3418,7 +3345,6 @@ "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3430,11 +3356,7 @@ "step": "sum_range_exercise" }, { - "get_solution": [ - "x = [12, -6, 2, -1, 3]", - "y = sorted(x)[1]", - "print(y)" - ], + "get_solution": "program", "page": "Plus de fonctions et de m\u00e9thodes sur les listes", "program": [ "x = [12, -6, 2, -1, 3]", @@ -3442,7 +3364,6 @@ "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3454,12 +3375,12 @@ "step": "second_smallest_in_list_exercise" }, { + "get_solution": "program", "page": "M\u00e9thodes sur les chaines et immuabilit\u00e9", "program": [ "print('tes' in 'fait tes devoirs et apprend tes le\u00e7ons')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3471,6 +3392,7 @@ "step": "string_in_step" }, { + "get_solution": "program", "page": "M\u00e9thodes sur les chaines et immuabilit\u00e9", "program": [ "chaine = 'fait tes devoirs et apprend tes le\u00e7ons'", @@ -3478,7 +3400,6 @@ "print(chaine.index('tes'))" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3490,12 +3411,12 @@ "step": "string_count_index" }, { + "get_solution": "program", "page": "M\u00e9thodes sur les chaines et immuabilit\u00e9", "program": [ "'Python'.append(' est sympa !')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3542,6 +3463,7 @@ "step": "mutation_string_append" }, { + "get_solution": "program", "page": "M\u00e9thodes sur les chaines et immuabilit\u00e9", "program": [ "phrase = \"Python brille !\"", @@ -3550,7 +3472,6 @@ "print(nouvelle_phrase)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3562,15 +3483,12 @@ "step": "string_lower_upper" }, { - "get_solution": [ - "max([21, 55, 4, 91, 62, 49])" - ], + "get_solution": "program", "page": "Recherche d'informations sur le web", "program": [ "max([21, 55, 4, 91, 62, 49])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3582,11 +3500,7 @@ "step": "sum_list" }, { - "get_solution": [ - "nombres = [1, 2, 3, 4, 5]", - "nombres.insert(2, 9)", - "print(nombres)" - ], + "get_solution": "program", "page": "Recherche d'informations sur le web", "program": [ "nombres = [1, 2, 3, 4, 5]", @@ -3594,7 +3508,6 @@ "print(nombres)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3606,16 +3519,16 @@ "step": "list_insert" }, { + "get_solution": "program", "page": "Recherche d'informations sur le web", "program": [ "dir([])" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']\n", + "text": "['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']\n", "type": "stdout" } ] @@ -3623,6 +3536,7 @@ "step": "dir_list" }, { + "get_solution": "program", "page": "Observation des programmes avec Python Tutor", "program": [ "des_nombres = [2, 4, 8, 1, 9, 7]", @@ -3640,7 +3554,6 @@ "print(grands_nombres)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3652,6 +3565,7 @@ "step": "run_with_python_tutor" }, { + "get_solution": "program", "page": "== ou is, test d'\u00e9galit\u00e9 ou d'identit\u00e9", "program": [ "liste_1 = [1, 2, 3]", @@ -3669,7 +3583,6 @@ "print(liste_2)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3681,6 +3594,7 @@ "step": "two_separate_lists" }, { + "get_solution": "program", "page": "== ou is, test d'\u00e9galit\u00e9 ou d'identit\u00e9", "program": [ "liste_1 = [1, 2, 3]", @@ -3698,7 +3612,6 @@ "print(liste_2)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3710,6 +3623,7 @@ "step": "same_list" }, { + "get_solution": "program", "page": "Modifications pendant l'it\u00e9ration", "program": [ "nombres = [10, 7, 8, 3, 12, 15]", @@ -3720,7 +3634,6 @@ "print(nombres)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3799,6 +3712,7 @@ "step": "run_broken_with_python_tutor" }, { + "get_solution": "program", "page": "Modifications pendant l'it\u00e9ration", "program": [ "nombres = [10, 7, 8, 3, 12, 15]", @@ -3808,7 +3722,6 @@ "print(nombres)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3820,6 +3733,7 @@ "step": "remove_instead_of_pop" }, { + "get_solution": "program", "page": "Modifications pendant l'it\u00e9ration", "program": [ "nombres = [10, 7, 8, 3, 12, 15]", @@ -3829,7 +3743,6 @@ "print(nombres)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3841,6 +3754,7 @@ "step": "make_copy" }, { + "get_solution": "program", "page": "Modifications pendant l'it\u00e9ration", "program": [ "nombres = [10, 7, 8, 3, 12, 15]", @@ -3852,7 +3766,6 @@ "print(grands_nombres)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3864,6 +3777,7 @@ "step": "make_copy2" }, { + "get_solution": "program", "page": "Modifications pendant l'it\u00e9ration", "program": [ "nombres = [10, 7, 8, 3, 12, 15]", @@ -3875,7 +3789,6 @@ "print(grands_nombres)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3887,17 +3800,17 @@ "step": "make_new_list" }, { + "get_solution": "program", "page": "Guillemets simples et doubles dans les chaines", "program": [ "print('Alice s'en va diner')" ], "response": { - "message": "", "passed": true, "result": [ { - "friendly": "

Une exception de type SyntaxError se produit lorsque Python ne peut pas comprendre votre code.

\n

Pr\u00e9sentement, je ne peux pas deviner la cause probable de cette erreur.\nEssayez d\u2019examiner attentivement la ligne indiqu\u00e9e ainsi que celle\nimm\u00e9diatement au dessus pour voir si vous pouvez identifier\nun mot mal orthographi\u00e9, ou des symboles manquants, comme (,), [,],:, etc.

\n

Si votre code n'utilise pas d'annotations de type,\net que vous pensez que friendly devrait\npouvoir l'analyser correctement, SVP rapporter ce cas au site suivant:\nhttps://github.com/friendly-traceback/friendly-traceback/issues

", - "text": " print('Alice s'en va diner')\n ^^^^^^^^^^^\nSyntaxError: invalid syntax. Perhaps you forgot a comma?\nat line 1\n", + "friendly": "

Une exception de type SyntaxError se produit lorsque Python ne peut pas comprendre votre code.

\n

Vous aviez commenc\u00e9 \u00e0 \u00e9crire une cha\u00eene de caract\u00e8res\navec un guillemet simple ou double, mais n'avez jamais\ntermin\u00e9 la cha\u00eene avec un autre guillemet sur cette ligne.

", + "text": " print('Alice s'en va diner')\n ^\nSyntaxError: unterminated string literal (detected at line 1)\nat line 1\n", "type": "syntax_error" } ] @@ -3905,12 +3818,12 @@ "step": "single_quotes_apostrophe" }, { + "get_solution": "program", "page": "Guillemets simples et doubles dans les chaines", "program": [ "print(\"Alice s'en va diner\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3922,12 +3835,12 @@ "step": "double_quotes" }, { + "get_solution": "program", "page": "Guillemets simples et doubles dans les chaines", "program": [ "'Alice' == \"Alice\"" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", @@ -3947,15 +3860,12 @@ "step": "single_double_quotes_equal" }, { - "get_solution": [ - "print(\"Un cas n\u2019est jamais assez particulier pour autoriser de briser une r\u00e8gle.\")" - ], + "get_solution": "program", "page": "Guillemets simples et doubles dans les chaines", "program": [ "print(\"Un cas n\u2019est jamais assez particulier pour autoriser de briser une r\u00e8gle.\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3967,15 +3877,12 @@ "step": "double_quote_exercise" }, { - "get_solution": [ - "print('\"Parler est facile. Montre-moi le code.\" - Linus Torvalds')" - ], + "get_solution": "program", "page": "Guillemets simples et doubles dans les chaines", "program": [ "print('\"Parler est facile. Montre-moi le code.\" - Linus Torvalds')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3987,6 +3894,7 @@ "step": "single_quote_exercise" }, { + "get_solution": "program", "page": "Les f-string", "program": [ "nom = \"Alice\"", @@ -3995,7 +3903,6 @@ "print(f\"{nom} est all\u00e9(e) {repas} avec {ami}.\")" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Alice est all\u00e9(e) d\u00e9jeuner avec Bob.", @@ -4022,6 +3929,7 @@ "step": "introduce_f_strings" }, { + "get_solution": "program", "page": "Les f-string", "program": [ "nom = \"Alice\"", @@ -4029,7 +3937,6 @@ "print(\"Bonjour \" + nom + \". Vous avez \" + age + \" ans.\")" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Erreur", @@ -4108,11 +4015,7 @@ "step": "concatenate_string_number" }, { - "get_solution": [ - "nom = \"Alice\"", - "age = 20", - "print(f'Bonjour {nom}. Vous avez {age} ans.')" - ], + "get_solution": "program", "page": "Les f-string", "program": [ "nom = \"Alice\"", @@ -4120,7 +4023,6 @@ "print(f'Bonjour {nom}. Vous avez {age} ans.')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4132,12 +4034,12 @@ "step": "basic_f_string_exercise" }, { + "get_solution": "program", "page": "Les f-string", "program": [ "f\"2 * 3 + 4 est \u00e9gal \u00e0 {2 * 3 + 4}\"" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4154,15 +4056,14 @@ ], "page": "Les f-string", "program": [ - "personnes = ['eODoUwNzS', 'ofHBEzZxs', 'zwTrQA', 'LDaOKmpHU', 'HCMLTt', 'NbRmEjaoyD']", + "personnes = ['Alice', 'Bob', 'Charlie']", "print(f\"Il y a {len(personnes)} personnes qui attendent, la premi\u00e8re personne s'appelle {personnes[0]}.\")" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "Il y a 6 personnes qui attendent, la premi\u00e8re personne s'appelle eODoUwNzS.\n", + "text": "Il y a 3 personnes qui attendent, la premi\u00e8re personne s'appelle Alice.\n", "type": "stdout" } ] @@ -4170,6 +4071,7 @@ "step": "fix_broken_program" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des boucles imbriqu\u00e9es", "program": [ "for lettre in \"ABC\":", @@ -4179,7 +4081,6 @@ " print('---')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "A\nA 0\nA 1\nA 2\nA 3\n---\nB\nB 0\nB 1\nB 2\nB 3\n---\nC\nC 0\nC 1\nC 2\nC 3\n---", @@ -4360,14 +4261,7 @@ "step": "times_table_exercise" }, { - "get_solution": [ - "for gauche in range(12):", - " gauche += 1", - " for droite in range(12):", - " droite += 1", - " print(f'{gauche} x {droite} = {gauche * droite}')", - " print('---')" - ], + "get_solution": "program", "page": "Pr\u00e9sentation des boucles imbriqu\u00e9es", "program": [ "for gauche in range(12):", @@ -4378,7 +4272,6 @@ " print('---')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4402,18 +4295,17 @@ ], "page": "Pr\u00e9sentation des boucles imbriqu\u00e9es", "program": [ - "joueurs = ['OUumHyG', 'ocUyWBh', 'DbNQe', 'XjItgGJ', 'iOuKYyzZt', 'iySpdUX', 'EZkLNo']", + "joueurs = ['Alice', 'Bob', 'Charlie']", "for joueur_1 in joueurs:", " for joueur_2 in joueurs:", " if joueur_1 != joueur_2:", " print(f'{joueur_1} contre {joueur_2}')" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "OUumHyG contre ocUyWBh\nOUumHyG contre DbNQe\nOUumHyG contre XjItgGJ\nOUumHyG contre iOuKYyzZt\nOUumHyG contre iySpdUX\nOUumHyG contre EZkLNo\nocUyWBh contre OUumHyG\nocUyWBh contre DbNQe\nocUyWBh contre XjItgGJ\nocUyWBh contre iOuKYyzZt\nocUyWBh contre iySpdUX\nocUyWBh contre EZkLNo\nDbNQe contre OUumHyG\nDbNQe contre ocUyWBh\nDbNQe contre XjItgGJ\nDbNQe contre iOuKYyzZt\nDbNQe contre iySpdUX\nDbNQe contre EZkLNo\nXjItgGJ contre OUumHyG\nXjItgGJ contre ocUyWBh\nXjItgGJ contre DbNQe\nXjItgGJ contre iOuKYyzZt\nXjItgGJ contre iySpdUX\nXjItgGJ contre EZkLNo\niOuKYyzZt contre OUumHyG\niOuKYyzZt contre ocUyWBh\niOuKYyzZt contre DbNQe\niOuKYyzZt contre XjItgGJ\niOuKYyzZt contre iySpdUX\niOuKYyzZt contre EZkLNo\niySpdUX contre OUumHyG\niySpdUX contre ocUyWBh\niySpdUX contre DbNQe\niySpdUX contre XjItgGJ\niySpdUX contre iOuKYyzZt\niySpdUX contre EZkLNo\nEZkLNo contre OUumHyG\nEZkLNo contre ocUyWBh\nEZkLNo contre DbNQe\nEZkLNo contre XjItgGJ\nEZkLNo contre iOuKYyzZt\nEZkLNo contre iySpdUX\n", + "text": "Alice contre Bob\nAlice contre Charlie\nBob contre Alice\nBob contre Charlie\nCharlie contre Alice\nCharlie contre Bob\n", "type": "stdout" } ] @@ -4438,7 +4330,6 @@ " print(c_1 + c_2 + c_3 + c_4)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4469,7 +4360,6 @@ " print(ligne)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4489,18 +4379,17 @@ ], "page": "Pr\u00e9sentation des boucles imbriqu\u00e9es", "program": [ - "joueurs = ['JwsUZyHWXS', 'UepKEbOB', 'uTRiPVo', 'VWkbqMa', 'BwdsYFWHh', 'XmgDJ', 'WRoYNxvLF']", + "joueurs = ['Alice', 'Bob', 'Charlie']", "for i in range(len(joueurs)):", " for j in range(len(joueurs)):", " if i < j:", " print(f'{joueurs[i]} contre {joueurs[j]}')" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "JwsUZyHWXS contre UepKEbOB\nJwsUZyHWXS contre uTRiPVo\nJwsUZyHWXS contre VWkbqMa\nJwsUZyHWXS contre BwdsYFWHh\nJwsUZyHWXS contre XmgDJ\nJwsUZyHWXS contre WRoYNxvLF\nUepKEbOB contre uTRiPVo\nUepKEbOB contre VWkbqMa\nUepKEbOB contre BwdsYFWHh\nUepKEbOB contre XmgDJ\nUepKEbOB contre WRoYNxvLF\nuTRiPVo contre VWkbqMa\nuTRiPVo contre BwdsYFWHh\nuTRiPVo contre XmgDJ\nuTRiPVo contre WRoYNxvLF\nVWkbqMa contre BwdsYFWHh\nVWkbqMa contre XmgDJ\nVWkbqMa contre WRoYNxvLF\nBwdsYFWHh contre XmgDJ\nBwdsYFWHh contre WRoYNxvLF\nXmgDJ contre WRoYNxvLF\n", + "text": "Alice contre Bob\nAlice contre Charlie\nBob contre Charlie\n", "type": "stdout" } ] @@ -4508,6 +4397,7 @@ "step": "player_vs_player_bonus" }, { + "get_solution": "program", "page": "Observation des programmes avec birdseye", "program": [ "a = 2", @@ -4517,7 +4407,6 @@ "print(a * b + c * d)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4529,6 +4418,7 @@ "step": "first_birdseye_example" }, { + "get_solution": "program", "page": "Observation des programmes avec birdseye", "program": [ "mot = 'Fabuleux'", @@ -4543,7 +4433,6 @@ "print(consonnes)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4566,7 +4455,6 @@ "print(chaine[0])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4578,13 +4466,13 @@ "step": "string_list_exercise" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des listes imbriqu\u00e9es", "program": [ "chaines = [\"abc\", \"def\", \"ghi\"]", "print(chaines[1][0])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4605,7 +4493,6 @@ "print(chaines[-2][-1])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4617,13 +4504,13 @@ "step": "double_subscripting_exercise" }, { + "get_solution": "program", "page": "Pr\u00e9sentation des listes imbriqu\u00e9es", "program": [ "chaines = [['hello', 'there'], ['comment', 'allez', 'vous']]", "print(chaines[1][0])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "comment", @@ -4661,7 +4548,6 @@ "print(chaines[1][2][0])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4673,6 +4559,7 @@ "step": "triple_subscripting" }, { + "get_solution": "program", "page": "Faire des boucles avec des listes imbriqu\u00e9es", "program": [ "nombres = [[1, 2, 3], [4, 5], [6], []]", @@ -4682,7 +4569,6 @@ " print('---')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "1\n2\n3\n---\n4\n5\n---\n6\n---\n---", @@ -4705,6 +4591,7 @@ "step": "nested_list_nested_loop_example" }, { + "get_solution": "program", "page": "Faire des boucles avec des listes imbriqu\u00e9es", "program": [ "nombres = [[1, 2, 3], [4, 5], [6], []]", @@ -4714,7 +4601,6 @@ " print('---')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4742,7 +4628,6 @@ " print(chaine)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4774,7 +4659,6 @@ " print(cadeau)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4806,7 +4690,6 @@ "print(cadeau)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4835,7 +4718,6 @@ " print(ligne)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4880,7 +4762,6 @@ " print(ligne)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4892,6 +4773,7 @@ "step": "zip_longest_strings_exercise" }, { + "get_solution": "program", "page": "D\u00e9finitions de fonctions", "program": [ "def salutation(nom):", @@ -4901,7 +4783,6 @@ "salutation(\"Bob\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4913,6 +4794,7 @@ "step": "define_greet" }, { + "get_solution": "program", "page": "D\u00e9finitions de fonctions", "program": [ "def salutation(nom):", @@ -4923,7 +4805,6 @@ "salutation(\"Bob\")" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Bonjour Alice !\nComment allez-vous ?\nBonjour Bob !\nComment allez-vous ?", @@ -4944,14 +4825,7 @@ "step": "how_are_you" }, { - "get_solution": [ - "def dit_bonjour(nom):", - " print(f\"Bonjour {nom} !\")", - " print(\"Comment allez-vous ?\")", - "", - "dit_bonjour(\"Alice\")", - "dit_bonjour(\"Bob\")" - ], + "get_solution": "program", "page": "D\u00e9finitions de fonctions", "program": [ "def dit_bonjour(nom):", @@ -4962,7 +4836,6 @@ "dit_bonjour(\"Bob\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4974,14 +4847,7 @@ "step": "change_function_name" }, { - "get_solution": [ - "def dit_bonjour(nom_personne):", - " print(f\"Bonjour {nom_personne} !\")", - " print(\"Comment allez-vous ?\")", - "", - "dit_bonjour(\"Alice\")", - "dit_bonjour(\"Bob\")" - ], + "get_solution": "program", "page": "D\u00e9finitions de fonctions", "program": [ "def dit_bonjour(nom_personne):", @@ -4992,7 +4858,6 @@ "dit_bonjour(\"Bob\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5004,11 +4869,7 @@ "step": "change_parameter_name" }, { - "get_solution": [ - "def affiche_deux_fois(x):", - " print(x)", - " print(x)" - ], + "get_solution": "program", "page": "D\u00e9finitions de fonctions", "program": [ "def affiche_deux_fois(x):", @@ -5016,13 +4877,13 @@ " print(x)" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "print_twice_exercise" }, { + "get_solution": "program", "page": "D\u00e9finitions de fonctions", "program": [ "def affiche_plusieurs(chose, n):", @@ -5032,7 +4893,6 @@ "affiche_plusieurs(\"Hello\", 3)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello\nHello\nHello", @@ -5055,13 +4915,7 @@ "step": "print_many" }, { - "get_solution": [ - "def affiche_plusieurs(n, chose):", - " for _ in range(n):", - " print(chose)", - "", - "affiche_plusieurs(3, \"Hello\")" - ], + "get_solution": "program", "page": "D\u00e9finitions de fonctions", "program": [ "def affiche_plusieurs(n, chose):", @@ -5071,7 +4925,6 @@ "affiche_plusieurs(3, \"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5083,6 +4936,7 @@ "step": "swap_parameters" }, { + "get_solution": "program", "page": "Appels de fonctions dans des fonctions", "program": [ "def affiche_plusieurs(n, chose):", @@ -5095,7 +4949,6 @@ "affiche_deux_fois(\"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5107,6 +4960,7 @@ "step": "print_twice_call_print_many" }, { + "get_solution": "program", "page": "Appels de fonctions dans des fonctions", "program": [ "def affiche_plusieurs(n, chose):", @@ -5119,15 +4973,14 @@ "affiche_deux_fois(\"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148maffiche_plusieurs\u001b[39m(n, chose):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148maffiche_deux_fois\u001b[39m(x):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | affiche_deux_fois(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n\u001b[38;5;242m \u001b[0m\u001b[36m\u001b[1m>>> Call to affiche_deux_fois in File \"/my_program.py\", line 5\u001b[0m\n\u001b[38;5;242m \u001b[0m...... x = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148maffiche_deux_fois\u001b[39m(x):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | affiche_plusieurs(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;242m \u001b[0m\u001b[36m\u001b[1m>>> Call to affiche_plusieurs in File \"/my_program.py\", line 1\u001b[0m\n\u001b[38;5;242m \u001b[0m...... n = \u001b[38;5;141m2\u001b[39m\n\u001b[38;5;242m \u001b[0m...... chose = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148maffiche_plusieurs\u001b[39m(n, chose):\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148maffiche_plusieurs\u001b[39m(n, chose):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148maffiche_deux_fois\u001b[39m(x):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | affiche_deux_fois(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n\u001b[38;5;245m \u001b[0m\u001b[36m\u001b[1m>>> Call to affiche_deux_fois in File \"/my_program.py\", line 5\u001b[0m\n\u001b[38;5;245m \u001b[0m...... x = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148maffiche_deux_fois\u001b[39m(x):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | affiche_plusieurs(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;245m \u001b[0m\u001b[36m\u001b[1m>>> Call to affiche_plusieurs in File \"/my_program.py\", line 1\u001b[0m\n\u001b[38;5;245m \u001b[0m...... n = \u001b[38;5;141m2\u001b[39m\n\u001b[38;5;245m \u001b[0m...... chose = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148maffiche_plusieurs\u001b[39m(n, chose):\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n\u001b[38;5;242m \u001b[0m.......... _ = \u001b[38;5;141m0\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | print(chose)\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n\u001b[38;5;245m \u001b[0m.......... _ = \u001b[38;5;141m0\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | print(chose)\n", "type": "snoop" }, { @@ -5139,11 +4992,11 @@ "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.......... _ = \u001b[38;5;141m1\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | print(chose)\n", + "text": "\u001b[38;5;245m \u001b[0m.......... _ = \u001b[38;5;141m1\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | print(chose)\n", "type": "snoop" }, { @@ -5155,11 +5008,11 @@ "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[32m\u001b[1m<<< Return value from affiche_plusieurs: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | affiche_plusieurs(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;242m \u001b[0m\u001b[32m\u001b[1m<<< Return value from affiche_deux_fois: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | affiche_deux_fois(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[32m\u001b[1m<<< Return value from affiche_plusieurs: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | affiche_plusieurs(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;245m \u001b[0m\u001b[32m\u001b[1m<<< Return value from affiche_deux_fois: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | affiche_deux_fois(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n", "type": "snoop" } ] @@ -5167,6 +5020,7 @@ "step": "see_stack_in_snoop" }, { + "get_solution": "program", "page": "Appels de fonctions dans des fonctions", "program": [ "def affiche_plusieurs(n, chose):", @@ -5179,7 +5033,6 @@ "affiche_deux_fois(\"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5191,6 +5044,7 @@ "step": "see_stack_in_pythontutor" }, { + "get_solution": "program", "page": "Appels de fonctions dans des fonctions", "program": [ "def affiche_plusieurs(n, chose):", @@ -5203,7 +5057,6 @@ "affiche_deux_fois(\"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5215,6 +5068,7 @@ "step": "see_stack_in_birdseye" }, { + "get_solution": "program", "page": "Renvoi de valeurs par des fonctions", "program": [ "def double(x):", @@ -5226,7 +5080,6 @@ "print(deux_fois)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "5\n10", @@ -5247,6 +5100,7 @@ "step": "first_return" }, { + "get_solution": "program", "page": "Renvoi de valeurs par des fonctions", "program": [ "def double(x):", @@ -5257,7 +5111,6 @@ "print(nombre)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "5", @@ -5303,13 +5156,13 @@ " return double(double(x))" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "quadruple_exercise" }, { + "get_solution": "program", "page": "Fonctions de tests", "program": [ "def double(x):", @@ -5319,7 +5172,6 @@ "assert_equal(double(5), 10)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "OK\nOK", @@ -5342,6 +5194,7 @@ "step": "introducing_assert_equal" }, { + "get_solution": "program", "page": "Fonctions de tests", "program": [ "def double(x):", @@ -5351,7 +5204,6 @@ "assert_equal(double(5), 10)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Error! 6 != 4\nError! 15 != 10", @@ -5373,6 +5225,7 @@ "step": "make_tests_fail" }, { + "get_solution": "program", "page": "Fonctions de tests", "program": [ "def double(x):", @@ -5385,7 +5238,6 @@ "assert_equal(quadruple(5), 20)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5397,17 +5249,13 @@ "step": "complete_quadruple_tests" }, { - "get_solution": [ - "def entoure(chaine, balise):", - " return balise + chaine + balise" - ], + "get_solution": "program", "page": "Fonctions de tests", "program": [ "def entoure(chaine, balise):", " return balise + chaine + balise" ], "response": { - "message": "", "passed": true, "result": [] }, @@ -5466,13 +5314,13 @@ " return chaine" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "alert_exercise" }, { + "get_solution": "program", "page": "return termine l'appel de la fonction", "program": [ "def foo():", @@ -5482,7 +5330,6 @@ "print(foo())" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "1", @@ -5505,6 +5352,7 @@ "step": "double_return_in_one_function" }, { + "get_solution": "program", "page": "return termine l'appel de la fonction", "program": [ "def nombres_doubles(nombres):", @@ -5514,7 +5362,6 @@ "assert_equal(nombres_doubles([1, 2, 3]), [2, 4, 6])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5526,6 +5373,7 @@ "step": "cannot_return_multiple_values" }, { + "get_solution": "program", "page": "return termine l'appel de la fonction", "program": [ "def foo():", @@ -5538,7 +5386,6 @@ "foo()" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "a 0\na 1\na 2\nb 0", @@ -5561,6 +5408,7 @@ "step": "return_ends_whole_function" }, { + "get_solution": "program", "page": "return termine l'appel de la fonction", "program": [ "def foo():", @@ -5573,7 +5421,6 @@ "foo()" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "a 0\na 1\na 2\nb 0\nc 0\nc 1\nc 2", @@ -5596,6 +5443,7 @@ "step": "break_vs_return" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de or", "program": [ "def est_ami(nom):", @@ -5611,7 +5459,6 @@ "assert_equal(est_ami(\"Carole\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5623,12 +5470,12 @@ "step": "InputAliceBob" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de or", "program": [ "True or True" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", @@ -5648,12 +5495,12 @@ "step": "TrueOrTrue" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de or", "program": [ "True or False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", @@ -5673,12 +5520,12 @@ "step": "TrueOrFalse" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de or", "program": [ "False or False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False", @@ -5698,6 +5545,7 @@ "step": "FalseOrFalse" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de or", "program": [ "def est_ami(nom):", @@ -5711,7 +5559,6 @@ "assert_equal(est_ami(\"Carole\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5723,6 +5570,7 @@ "step": "ImprovingWithOr" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de or", "program": [ "def est_ami(nom):", @@ -5733,7 +5581,6 @@ "assert_equal(est_ami(\"Carole\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5745,6 +5592,7 @@ "step": "FurtherImprovement" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de or", "program": [ "def est_ami(nom):", @@ -5755,7 +5603,6 @@ "assert_equal(est_ami(\"Carole\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5767,6 +5614,7 @@ "step": "ACommonMistake" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de or", "program": [ "def est_ami(nom):", @@ -5777,7 +5625,6 @@ "assert_equal(est_ami(\"Carole\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5789,13 +5636,7 @@ "step": "InspectWithBirdseye" }, { - "get_solution": [ - "def est_pourcentage_valide(x):", - " if x < 0 or x > 100:", - " return False", - " else:", - " return True" - ], + "get_solution": "program", "page": "Pr\u00e9sentation de or", "program": [ "def est_pourcentage_valide(x):", @@ -5805,19 +5646,18 @@ " return True" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "AnExercise" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de and", "program": [ "True and True" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", @@ -5837,12 +5677,12 @@ "step": "TrueAndTrue" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de and", "program": [ "True and False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False", @@ -5862,12 +5702,12 @@ "step": "TrueAndFalse" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de and", "program": [ "False and False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False", @@ -5887,13 +5727,7 @@ "step": "FalseAndFalse" }, { - "get_solution": [ - "def est_pourcentage_valide(x):", - " if 0 <= x and x <= 100:", - " return True", - " else:", - " return False" - ], + "get_solution": "program", "page": "Pr\u00e9sentation de and", "program": [ "def est_pourcentage_valide(x):", @@ -5903,37 +5737,32 @@ " return False" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "AndExercise" }, { - "get_solution": [ - "def tous_egaux(ligne):", - " return ligne[0] == ligne[1] and ligne[0] == ligne[2]" - ], + "get_solution": "program", "page": "Pr\u00e9sentation de and", "program": [ "def tous_egaux(ligne):", " return ligne[0] == ligne[1] and ligne[0] == ligne[2]" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "TicTacToeWinningRow" }, { + "get_solution": "program", "page": "Instructions sur plusieurs lignes", "program": [ "est_ami = nom == \"Alice\" or", " nom == \"Bob\"" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5946,6 +5775,7 @@ "step": "invalid_multiline" }, { + "get_solution": "program", "page": "Instructions sur plusieurs lignes", "program": [ "nom = \"Bob\"", @@ -5966,7 +5796,6 @@ " nom == \"Bob\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5978,12 +5807,12 @@ "step": "valid_multiline" }, { + "get_solution": "program", "page": "M\u00e9langes de and et or", "program": [ "True or False and False" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5995,14 +5824,7 @@ "step": "CombiningAndOr" }, { - "get_solution": [ - "def victoire_en_diagonale(plateau):", - " milieu = plateau[1][1]", - " return (", - " (milieu == plateau[0][0] and milieu == plateau[2][2]) or", - " (milieu == plateau[0][2] and milieu == plateau[2][0])", - " )" - ], + "get_solution": "program", "page": "M\u00e9langes de and et or", "program": [ "def victoire_en_diagonale(plateau):", @@ -6013,19 +5835,18 @@ " )" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "AndHasHigherPriority" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de not", "program": [ "not True" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False", @@ -6045,12 +5866,12 @@ "step": "IntroducingNot" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de not", "program": [ "not False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", @@ -6070,13 +5891,13 @@ "step": "NotFalse" }, { + "get_solution": "program", "page": "Pr\u00e9sentation de not", "program": [ "b = True", "print(not b or b)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6088,17 +5909,13 @@ "step": "NotTrueOrTrue" }, { - "get_solution": [ - "def est_image_invalide(nom_fichier):", - " return not (nom_fichier.endswith(\".png\") or nom_fichier.endswith(\".jpg\"))" - ], + "get_solution": "program", "page": "Pr\u00e9sentation de not", "program": [ "def est_image_invalide(nom_fichier):", " return not (nom_fichier.endswith(\".png\") or nom_fichier.endswith(\".jpg\"))" ], "response": { - "message": "", "passed": true, "result": [] }, @@ -6127,19 +5944,7 @@ "step": "intro_row_winner" }, { - "get_solution": [ - "def victoire_en_ligne(plateau):", - " for ligne in plateau:", - " tous_egaux = True", - " marque = ligne[0]", - " for valeur in ligne:", - " if valeur == ' ' or marque != valeur:", - " tous_egaux = False", - " break", - " if tous_egaux:", - " return True", - " return False" - ], + "get_solution": "program", "page": "V\u00e9rification du plateau pour un gagnant", "program": [ "def victoire_en_ligne(plateau):", @@ -6155,26 +5960,13 @@ " return False" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "intro_row_winner" }, { - "get_solution": [ - "def victoire_en_colonne(plateau):", - " for i_colonne in range(len(plateau[0])):", - " tous_egaux = True", - " marque = plateau[0][i_colonne]", - " for ligne in plateau:", - " if ligne[i_colonne] == ' ' or ligne[i_colonne] != marque:", - " tous_egaux = False", - " break", - " if tous_egaux:", - " return True", - " return False" - ], + "get_solution": "program", "page": "V\u00e9rification du plateau pour un gagnant", "program": [ "def victoire_en_colonne(plateau):", @@ -6190,26 +5982,13 @@ " return False" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "column_winner" }, { - "get_solution": [ - "def victoire_en_diagonale(plateau):", - " tous_egaux_1 = True", - " tous_egaux_2 = True", - " haut_gauche = plateau[0][0]", - " haut_droite = plateau[0][-1]", - " for i in range(len(plateau)):", - " if plateau[i][i] == ' ' or plateau[i][i] != haut_gauche:", - " tous_egaux_1 = False", - " if plateau[i][-i - 1] == ' ' or plateau[i][-i - 1] != haut_droite:", - " tous_egaux_2 = False", - " return tous_egaux_1 or tous_egaux_2" - ], + "get_solution": "program", "page": "V\u00e9rification du plateau pour un gagnant", "program": [ "def victoire_en_diagonale(plateau):", @@ -6225,7 +6004,6 @@ " return tous_egaux_1 or tous_egaux_2" ], "response": { - "message": "", "passed": true, "result": [] }, @@ -6274,13 +6052,13 @@ " return victoire_en_ligne(plateau) or victoire_en_colonne(plateau) or victoire_en_diagonale(plateau)" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "winner" }, { + "get_solution": "program", "page": "Le caract\u00e8re saut de ligne, representation", "program": [ "def affiche_plateau(plateau):", @@ -6294,7 +6072,6 @@ "])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6306,6 +6083,7 @@ "step": "one_way_to_print_board" }, { + "get_solution": "program", "page": "Le caract\u00e8re saut de ligne, representation", "program": [ "assert_equal(", @@ -6320,7 +6098,6 @@ ")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6333,6 +6110,7 @@ "step": "invalid_multi_line_string" }, { + "get_solution": "program", "page": "Le caract\u00e8re saut de ligne, representation", "program": [ "chaine = \"\"\"Premi\u00e8re ligne", @@ -6340,7 +6118,6 @@ "print(chaine)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6364,12 +6141,12 @@ "step": "discovering_newline" }, { + "get_solution": "program", "page": "Le caract\u00e8re saut de ligne, representation", "program": [ "chaine" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6381,12 +6158,12 @@ "step": "discovering_newline" }, { + "get_solution": "program", "page": "Le caract\u00e8re saut de ligne, representation", "program": [ "len('\\n')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "1", @@ -6406,16 +6183,7 @@ "step": "introducing_newline" }, { - "get_solution": [ - "def representation(plateau):", - " resultat = ''", - " for i in range(len(plateau)):", - " for caractere in plateau[i]:", - " resultat += caractere", - " if i != len(plateau) - 1:", - " resultat += '\\n'", - " return resultat" - ], + "get_solution": "program", "page": "Le caract\u00e8re saut de ligne, representation", "program": [ "def representation(plateau):", @@ -6428,24 +6196,13 @@ " return resultat" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "format_board_simple" }, { - "get_solution": [ - "def representation(plateau):", - " liste_de_lignes = []", - " for ligne in plateau:", - " liste_de_lignes.append(\"|\".join(ligne))", - " lignes = []", - " for _ in plateau[0]:", - " lignes.append(\"-\")", - " ligne = f'\\n{\"+\".join(lignes)}\\n'", - " return ligne.join(liste_de_lignes)" - ], + "get_solution": "program", "page": "Le caract\u00e8re saut de ligne, representation", "program": [ "def representation(plateau):", @@ -6459,13 +6216,13 @@ " return ligne.join(liste_de_lignes)" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "format_board_bonus_challenge" }, { + "get_solution": "program", "page": "Les types", "program": [ "print(type('Hello World'))", @@ -6475,7 +6232,6 @@ "print(type(4.56))" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6487,12 +6243,12 @@ "step": "five_different_types" }, { + "get_solution": "program", "page": "Les types", "program": [ "type(3) == int" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6504,6 +6260,7 @@ "step": "check_type_manually" }, { + "get_solution": "program", "page": "Les types", "program": [ "print('123')", @@ -6511,7 +6268,6 @@ "print(123 == '123')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6523,13 +6279,13 @@ "step": "different_types_look_same" }, { + "get_solution": "program", "page": "Les types", "program": [ "print(123 + 456)", "print('123' + '456')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "579\n123456", @@ -6553,13 +6309,13 @@ "step": "plus_has_two_meanings" }, { + "get_solution": "program", "page": "Les types", "program": [ "print(13 < 120)", "print('13' < '120')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True\nFalse", @@ -6581,13 +6337,13 @@ "step": "less_than_has_two_meanings" }, { + "get_solution": "program", "page": "Les types", "program": [ "print(sorted([120, 13, 0]))", "print(sorted(['120', '13', '0']))" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[0, 13, 120]\n['0', '120', '13']", @@ -6611,12 +6367,12 @@ "step": "less_than_sorting_strings" }, { + "get_solution": "program", "page": "Les types", "program": [ "12 + '34'" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Erreur", @@ -6680,17 +6436,16 @@ ], "page": "Les types", "program": [ - "nombre = '2'", + "nombre = '1'", "for i in range(int(nombre)):", " print('\u00c0 la... ' + str(i + 1))", "print('Et hop !')" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "\u00c0 la... 1\n\u00c0 la... 2\nEt hop !\n", + "text": "\u00c0 la... 1\nEt hop !\n", "type": "stdout" } ] @@ -6698,17 +6453,7 @@ "step": "fixing_type_errors_with_conversion" }, { - "get_solution": [ - "def representation(plateau):", - " premiere_ligne = ' '", - " for i in range(len(plateau)):", - " premiere_ligne += str(i + 1)", - " liste_de_lignes = [premiere_ligne]", - " for i in range(len(plateau)):", - " ligne = str(i + 1) + ''.join(plateau[i])", - " liste_de_lignes.append(ligne)", - " return \"\\n\".join(liste_de_lignes)" - ], + "get_solution": "program", "page": "Les types", "program": [ "def representation(plateau):", @@ -6722,13 +6467,13 @@ " return \"\\n\".join(liste_de_lignes)" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "format_board_with_numbers" }, { + "get_solution": "program", "page": "Programmes interactifs avec input()", "program": [ "print('Tapez votre nom, puis appuyez sur \"Entr\u00e9e\" :')", @@ -6736,7 +6481,6 @@ "print(f'Bonjour {nom} !')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6761,7 +6505,6 @@ }, { "get_solution": [ - "nombre_super_secret = 7", "print(\"Quel est le nombre auquel je pense ?\")", "reponse = input()", "if int(reponse) == nombre_super_secret:", @@ -6780,7 +6523,6 @@ " print(\"Perdu !\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6792,11 +6534,11 @@ "type": "input_prompt" }, { - "text": "\n", + "text": "\n", "type": "stdout" }, { - "text": "Perdu !\n", + "text": "Incroyable ! \u00cates-vous devin ?\n", "type": "stdout" } ] @@ -6804,6 +6546,7 @@ "step": "convert_input_to_int" }, { + "get_solution": "program", "page": "Affectation avec liste imbriqu\u00e9e : Jouer un coup sur un plateau", "program": [ "def joue_un_coup(plateau, joueur):", @@ -6817,7 +6560,6 @@ "lance_jeu()" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[' ', 'X', ' ']", @@ -6844,6 +6586,7 @@ "step": "modify_list_in_function" }, { + "get_solution": "program", "page": "Affectation avec liste imbriqu\u00e9e : Jouer un coup sur un plateau", "program": [ "def joue_un_coup(plateau, joueur):", @@ -6862,7 +6605,6 @@ "lance_jeu()" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6874,12 +6616,7 @@ "step": "nested_assignment_two_lines" }, { - "get_solution": [ - "def joue_un_coup(plateau, joueur):", - " ligne = int(input()) - 1", - " i_colonne = int(input()) - 1", - " plateau[ligne][i_colonne] = joueur" - ], + "get_solution": "program", "page": "Affectation avec liste imbriqu\u00e9e : Jouer un coup sur un plateau", "program": [ "def joue_un_coup(plateau, joueur):", @@ -6888,13 +6625,13 @@ " plateau[ligne][i_colonne] = joueur" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "nested_assignment_input" }, { + "get_solution": "program", "page": "Fabrication du plateau", "program": [ "def fabrique_plateau(taille):", @@ -6923,7 +6660,6 @@ "test()" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6941,23 +6677,14 @@ "def fabrique_plateau(taille): return [[' '] * taille] * taille" ], "response": { - "message": "

Les sous-listes dans le r\u00e9sultat sont des objets identiques.

", + "message": "

Avec ces valeurs :

\n
taille = 2\n
\n

votre code affiche :

\n
[[' ', ' '], [' ', ' ']]\n
\n

ce qui est exact !

\n

N\u00e9anmoins, les sous-listes dans le r\u00e9sultat sont des objets identiques.

", "passed": false, "result": [] }, "step": "fix_make_board" }, { - "get_solution": [ - "def fabrique_plateau(taille):", - " plateau = []", - " for _ in range(taille):", - " ligne = []", - " for _ in range(taille):", - " ligne.append(' ')", - " plateau.append(ligne)", - " return plateau" - ], + "get_solution": "program", "page": "Fabrication du plateau", "program": [ "def fabrique_plateau(taille):", @@ -6970,7 +6697,6 @@ " return plateau" ], "response": { - "message": "", "passed": true, "result": [] }, @@ -7060,19 +6786,18 @@ " affiche_egalite()" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "the_full_game" }, { + "get_solution": "program", "page": "Introduction aux Dictionnaires", "program": [ "anglais = {'pomme': 'apple', 'boite': 'box'}" ], "response": { - "message": "", "passed": true, "result": [] }, @@ -7091,12 +6816,12 @@ "step": "dict_access" }, { + "get_solution": "program", "page": "Introduction aux Dictionnaires", "program": [ "anglais[0]" ], "response": { - "message": "", "passed": true, "result": [ { @@ -7161,12 +6886,12 @@ "step": "dict_access2" }, { + "get_solution": "program", "page": "Introduction aux Dictionnaires", "program": [ "anglais['pomme']" ], "response": { - "message": "", "passed": true, "result": [ { @@ -7190,12 +6915,12 @@ "step": "dict_access3" }, { + "get_solution": "program", "page": "Introduction aux Dictionnaires", "program": [ "anglais['boite']" ], "response": { - "message": "", "passed": true, "result": [ { @@ -7219,12 +6944,12 @@ "step": "dict_access4" }, { + "get_solution": "program", "page": "Introduction aux Dictionnaires", "program": [ "anglais['apple']" ], "response": { - "message": "", "passed": true, "result": [ { @@ -7277,14 +7002,7 @@ "step": "dict_access4" }, { - "get_solution": [ - "def cout_total(panier, prix):", - " resultat = 0", - " for element in panier:", - " tarif = prix[element]", - " resultat += tarif", - " return resultat" - ], + "get_solution": "program", "page": "Utiliser les Dictionnaires sur un exemple pratique", "program": [ "def cout_total(panier, prix):", @@ -7295,22 +7013,13 @@ " return resultat" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "shopping_cart1" }, { - "get_solution": [ - "def cout_total(panier, quantites, prix):", - " resultat = 0", - " for element in panier:", - " tarif = prix[element]", - " quantite = quantites[element]", - " resultat += tarif * quantite", - " return resultat" - ], + "get_solution": "program", "page": "Utiliser les Dictionnaires sur un exemple pratique", "program": [ "def cout_total(panier, quantites, prix):", @@ -7322,13 +7031,13 @@ " return resultat" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "shopping_cart4" }, { + "get_solution": "program", "page": "Utiliser les Dictionnaires sur un exemple pratique", "program": [ "def substitution(chaine):", @@ -7350,7 +7059,6 @@ "assert_equal(substitution(original), attendu)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -7362,13 +7070,7 @@ "step": "dna_part1" }, { - "get_solution": [ - "def substitution(chaine, d):", - " resultat = \"\"", - " for lettre in chaine:", - " resultat += d[lettre]", - " return resultat" - ], + "get_solution": "program", "page": "Utiliser les Dictionnaires sur un exemple pratique", "program": [ "def substitution(chaine, d):", @@ -7378,20 +7080,19 @@ " return resultat" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "dna_part2" }, { + "get_solution": "program", "page": "It\u00e9rer sur les clefs d'un dictionnaire", "program": [ "quantites = {'pomme': 1, 'chat': 10}", "print(quantites.keys())" ], "response": { - "message": "", "passed": true, "result": [ { @@ -7403,6 +7104,7 @@ "step": "introducing_keys" }, { + "get_solution": "program", "page": "It\u00e9rer sur les clefs d'un dictionnaire", "program": [ "quantites = {'pomme': 1, 'chat': 10}", @@ -7410,7 +7112,6 @@ " print(clef)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -7422,6 +7123,7 @@ "step": "keys_are_iterable" }, { + "get_solution": "program", "page": "It\u00e9rer sur les clefs d'un dictionnaire", "program": [ "quantites = {'pomme': 1, 'chat': 10}", @@ -7429,7 +7131,6 @@ " print(clef)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -7441,15 +7142,7 @@ "step": "keys_are_iterable2" }, { - "get_solution": [ - "def cout_total(quantites, prix):", - " resultat = 0", - " for element in quantites:", - " tarif = prix[element]", - " quantite = quantites[element]", - " resultat += tarif * quantite", - " return resultat" - ], + "get_solution": "program", "page": "It\u00e9rer sur les clefs d'un dictionnaire", "program": [ "def cout_total(quantites, prix):", @@ -7461,20 +7154,13 @@ " return resultat" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "cleanup_shopping_cart" }, { - "get_solution": [ - "def affiche_mots(anglais):", - " for mot in anglais:", - " print(\"Francais: \" + mot)", - " print(\"Anglais: \" + anglais[mot])", - " print(\"---\")" - ], + "get_solution": "program", "page": "It\u00e9rer sur les clefs d'un dictionnaire", "program": [ "def affiche_mots(anglais):", @@ -7484,21 +7170,13 @@ " print(\"---\")" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "english_to_french" }, { - "get_solution": [ - "def affiche_mots(anglais, allemand):", - " for mot in anglais:", - " print(\"Francais: \" + mot)", - " print(\"Anglais: \" + anglais[mot])", - " print(\"Allemand: \" + allemand[mot])", - " print(\"---\")" - ], + "get_solution": "program", "page": "It\u00e9rer sur les clefs d'un dictionnaire", "program": [ "def affiche_mots(anglais, allemand):", @@ -7509,13 +7187,13 @@ " print(\"---\")" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "english_to_german" }, { + "get_solution": "program", "page": "It\u00e9rer sur les clefs d'un dictionnaire", "program": [ "def affiche_mots(mots):", @@ -7539,7 +7217,6 @@ "})" ], "response": { - "message": "", "passed": true, "result": [ { diff --git a/translations/english.po b/translations/english.po index efd5978c..2b9a43b3 100644 --- a/translations/english.po +++ b/translations/english.po @@ -22115,7 +22115,7 @@ msgstr "" #. https://futurecoder.io/course/#DictionaryKeysAndValues msgid "pages.DictionaryKeysAndValues.steps.keys_are_iterable2.requirements" msgstr "" -"Run the same code as the previous step, but without `.keys()`. after `quantities`, so the middle line is `for key in " +"Run the same code as the previous step, but without `.keys()` after `quantities`, so the middle line is `for key in " "quantities:`" #. https://futurecoder.io/course/#DictionaryKeysAndValues diff --git a/translations/locales/en/LC_MESSAGES/futurecoder.mo b/translations/locales/en/LC_MESSAGES/futurecoder.mo index 582919860527ed093584c6ca24889db81c1737f3..b2b991debdea073344f61be22a57157c6dabae1f 100644 GIT binary patch delta 7520 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 Cr0E?1 delta 7522 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 F{|CmX=kEXj diff --git a/translations/locales/fr/LC_MESSAGES/futurecoder.mo b/translations/locales/fr/LC_MESSAGES/futurecoder.mo index ec7107f24e89259c3209884c1c27aa3cb81682d9..0ae6e9016f0d09c57d7401dd630bb848c87fba3b 100644 GIT binary patch delta 37633 zcmd_zcXU+M-uVABXC{=;Yv>F$)S-j)-iuOHijWzSAq3KxNkV4=C>=!u4j>{bDhMJN zbU^H(2_k|DiXu%>v0}x7e&3(HcS5<|XMOK;e`|gJ_&sag`#O7{bN1P1_p>M5Cvvge z*$w4GpOkg2viLtwAfh$!Vj46VJ2y-?2IWx{F3 zg(wet1SLZ|ur0oZa{aF;RTMp0XRr=>2oFIix!IE`|LPosiIAK>k4c75lI|trpCNNlGR3?(O2W-iF6?UJhZ=q6 z{1g+;Hm*QDSln3WwNqo=5UoifRl1||?eSZwfbq$gDkaY_Ol0ZL{2aM7utjWfi#-&(;^ADk1 z|00&a!{+>lC~x>BN)=o+mQB}d zitst(Wt0p!rs#}Sz|w^4pfuvvDCY;El%N;OOaBjYAPFxr7le&lQ0neglsEklCBe^8 zTJ;qygJlBRIw%=xW5T_$Ea5v*?wf=joQX1EJ&hshE(bV}R{R&%!pcFa0Xt#~T!m8f z2Tb@P4klbFL*F+6TM?d%4e@!D@#75EMLSbJI2I+HJFpIBW>Wuh!y0oU4`tFgk7e;M zls77qrHif>N=dZAir5q7{Ag5fXq<`ViC<>IkD^@nobe6g@hr+;PMjw~it-0@!ZlTg z%cHzOeUv&Jh~+RIW!#vGQgy3P9=H)J;BJ(R9z}VP(2P$gqiR4;~-v5_X6hLZk0SdQmgVGbmRTTpWT z8cM?NqCDtRlsEqg1rJ^u9zHX@8qT`O85eib0g+ zkQAvKyfk>O1k~A9>!&JfkfOx zguMAfC`Gm%WrRA2a{g;{qdiwASO=>U?u2svXq2K2pxk#iR>4hJ6Z5b#UO>6-DoRF6 zh34sm>!aM*7bRztu`1q=@_=Vh9=H!BLl;mI{0&vf&DV|8jm3!fpxocVcn8)X95Cna zN6BF5VGe3@unS}HBdmkYyLColu|DC!#tf7N z4qFiZ7;nLn%e8&6AK`2heiNG$w(q6<<;_~%t8W~PT?mJauV7okS53I}efoUR_#Ddl z%P2+MV1;Eh!2u{4or;o?mBu5+Lig+VuJ=>^a=|ncu>+eEzJ%Sd>I3@xUB*?$w~d8! z^!43P9y|r*!RxUZ?!l(`6%NG8E46;(jt~c}IdK*HV#`(98OAq^(GTkQVaBz_^TtMD zosj@a<9yusrLoy+9iM63gVK0Ijx~C%*VVYj_#^hwON|WBDg_2@JumgqLD09!9z0M;wIBo}v%q zEbJraQL3iwCSBACC~v$Cd*bid7`trN=}s~}jUjo^B@@x;X>)<`Y2zhhqb>T4CSeQi zdkm#@zlYV)-m1^LQ8F~r__Xm)QadB~a&Cow0$& zrN+a?V%yDm<5J^cW3e4NV*{}p>CHFp-9hxqjoVNf;ZNwn#?R~4Kic?6$Q*o%l2F4J^qbsi3>!}xVE|(jM-(* z8^gwv*pBpLcI%S8)fif04)z(X7xgUH5v5L3Q5xAYCA!`Z;a=}h)h2NocmpZTLUg1YM{|HKJK7}2z#;dxwjK(^I!&o2p zpp@i!tcRsv(?#DFD-!mjWONp`lllKu4kY1UaWr;(UHhQ%vT@KGI{qo6oySbb^hLC`bDs{6Gwv37zEys|PACm~5q`s1_<#-%GTv`IVXS&kpZ6M{z)swM z$%JFy)afQ0Up1CJq~rYLff4`{QPe#UHT^R((rX$x!SvBB7t@Cua1_YO)){etpBZBA;ljfX?#pyCJmgwMFu_^YwUhx+_-ypx1J zz&o({DgEGu*pKibW4VuX_%7oU#&3=7KGx?$+2-I)W7*UC#2D;Gf*bKR{LI+)6CGY? z{J_}ojE!9pUqQ)esdK7ZhOChsNRcf>=|%@oimK>&?Fi!|#!JRF7xbHF zqco;GW3f+lc)0N);{}xGH2zFaUX!t@^#6y|0n@1QH)HHYJ&@dPoR9TLUu^V7it!QSF>J{7&M)-+O|b#t;nQXE1i+fSb=aNhGIFG%|SbS0;Tnz##UJNYrUxKgOb6iD6`&^ z7=tHp0Dfz1|BVjcZ9HnM@~w{d8@C((_?GgQ1p0iZ>+*iQh46dW9!q?$i>fb5hSH52 zjUO0`U)JZlVPme#z^1qXJL22M=pS^rk8$1)l)qf?3K8;v-?0gLe$)w#!A67^VikN2 zJKzzNk|^?%zW)}iNjL+gTdu^`_!UZbb^okK&}rD2@HUkAuS4cUuU~Y;3~a-R9Um~hVJvGo)b-1r2T1?_S{?9E+o2|xc_7t>_d2f%c0)tdL!lAxwMj4+p z{%Gu0QlDRLJY|e6rQKcSS!Ein$Y zEti3P35ShmVsb{;?4Z8dYF5!N8;9+=-fROmBx>-3-{NqL9O-Yz*obe++zG0Wd`qBQy0oy<9=f?w~oKfxXO6SShJQspJ3c< z{1)#d-Bz_7);L^Rn_3&f!6hQbV*5JUFiJcA83$v_y4q~x+s113bo?aaE@PqkI(~%l zG3-q`-(ziT8>>rvREPuV!ppE7?lxXFHf*5dea1D$W5%Kl_4)27gXDB0lu%mjjs?FQOz^#-r_sl?nS%5(r^)+=lW-XHeewFC2uPX8H|h zVrRlT@DBXW#P?~gN9$QA{bHSxQS$>1q^`@i&<-`;Ydnl{Ly?x+UdC+WOU5h4)~)n) z>Bg-nW7Zca8LQS>I~vul&1w^I(paI5zF@fVe&bPNiMIOuK;vSRQT_l*30+0$UY>T^ z6zocPs|kN?YB&DN5b8?x0I-GRhidlkv2%Y)4(^ zebLSN43rG6LYe>ecclNzLA6dgB49j-lA#)%bz>TfvbwtuC4o~Y-L_a4?P%j>;}w+F z-M6cLa0q2I-+%-0U1QB|AssQfn>J!}cGsiottkCJ2c`d>Ln(pS9(qKaigNx{V~L(R zJjS@$_$$i&y?f~lFEySDnS+MC^@(Z51ICJdbiCiV)9CE0ht^>zt$&U2qOny!9iMGH zf-=2S>90rHIAdtDIr!1od4RrPq4Aip>OdXuH$ICpME`~|qIDdkyYV=bwz1gwn(w3 zmIk9#!7`LZ)NvK2|Nml6bQ-EJm}fj_EICZak3i|aYq1}GV5~J7; zdr@ZaqbQBD-0j56s%;<#(hHUu&l_*KL&x81{M6XtPTj~>pw#InC{lfz_`5pRw0eQZFu%ox3X?SPdC2T`hI8A=trjPhnz zPzI#tcR5tQpMX*|3sKt2izxSiD_Fea4~_b^KuC{l@o= zm6P;~j5V%7X*;3!IgrLvWs)8N??P$an^1<}%P4i$e6p_F;V2nfYCLKzm#pLOG(KcJ zW2}>+GmwZfS3HhAG=dV_i9K z!k?ft&X_6sMTeoh;7TR^?=%Op2(2H`rlVZ&qR|=D;X%e##!rl~8Tx#>aW_iau`_l2 zXzWJ#ag<*4DaxEtA`7MekC6l1Z2T3~WHD7Y&ZQ`C@FvPE=$fXlzt#A#@hg=3+E3S2 z8A5rH!ze4P@-uWgU2!bo85oj-4@^YcnR>EWiPHTppdTB}(ylQ6V!Ug%j(@}0V2-~3 zUX%x(MrlJu=w*`ez9=RA0808Fhv@&3<2u>;gEs-V^9{ED~)d( zi_FvUJ&dzZ?t8)bow31u9q%))olj2W!gozX@w;`nHx46y4oU`(p^R8D_vnoFL#dLb z*aY{R@Q)}N^eoT|mx(AN>009nW7&l|en`k1EJ0Z$?nn8s{T-#~VixIcbqA`1P*%Ms zOnjlm4z(XW0A=8L1SJDsV@<5TL}$DY%KcM~xhTCR^qo0qvQ$ST8J{#>FuIrN^J9%` zjVF!em+J=%MM-$M@sP3by*j>^ajrIGy<#H%Fy3;XzA)4H97@i=GvUT7ba3|9@yA%08$wG7#kxYL*FaLuq7ZunZOt>j9+(%4#+a z)UTE8*Z=vZUM4-84`ewc%yc){3atqw0VerRm`kbb~yl!0Xzc0opJfcga3Cd(L z%6P9a&v?bybc4QbJW5H1Q5HITH-vQE{Xm3tnzW;r=K^J{x6Z z+>esL&&GC7>hN?NPW&E}7b^9XUM=@WNjCu{-PKqXLwh-Rl!LPPEFWVb{1eNebF+R>3`P@fiRG~~%6-GIG~R_pFa-vHne`gMgabkdq zVAmZb1Mw&crlK^uEUbjfQA*}XlsDUnE_?;$Me7OuuV!Viw?zbTh}Qj`a+G8a6AlECBU{8khH0;)GP;l1YkTPSaI!kqsIC8Ot1 z()q%~Uq;EmuR0vE{^md~jM}afE{>A3vMBMf=tPeRw?wJa_9#`*%QzIJ4U9A4Nhpna zD#`;FnDD(Q={>BZ|2=9Vo-l4kdGIqRC9@MH;a7}@O#BJsS(FD{LKz8vF!6 zq!WWuLbXuRt1n9bZ^?m-SY1$ZHUcFBBT?!!4&?!9#;N9f2qnP&ebE>Z74(QRIH3^P!_GZ z*a+W2N#_r&iKTbyUez4sMMt2N)TEvCe<_MNM93R1L8-F`P)g!a6Mh1vM0TQFx5u2% zL%II|N+Ww0r9?hPX(Q)QuKyaP(f)*z&hJLY^QQk7d0sCFN~64K7nB=^qKy5cOgJ4S zp=l^pGY92?_o5`6V_b`pp+`|N^0e`Jl(z61%Jqjr9LR%?nG+wPJm7-4;7fD0Pp36d`gb#w`#Pf}+!Lh)2cVSD5R~b6v~e=Z3xsBwgJmceu0u&+lkr)U48CA| z1?9T^C~tTi<&8cv@t>h|%gZR~{AJEZMRa^Al=y1M{UNK4KCqggJgAMipfk!F^+GA) z0Vp}X)fk5|B&QkYqP$@aN(MHfWNe3Vk8vML#*ZrLe;;rlIXZ{(z%Nh|{?^1>yYw3u zM!BvWN}X0Q;d;gXyJZL#eH(802 z&?c0U*lv6tCBrWoUqiWXzX=~fsj7F4XH5K8D9^i$A-UjB4kX7#c5BO`WTYBOf(=n} z-rU&U*uyvw<;_Q+G`e_{j3%0JvN7G5f%3d*yXpT@)bogtZnqL8Lr>won2Q6k$BTL( zx)-G+PNH0Y24nFDlx|vOk6z`rKvrFrAG;D?`eofVZbM1mhw|K%m+AlVfDjQfVjadB zcot=3`y1C|x`tKG{yxeB^gHfoZpD;xc&l8 z!m6P>hx!AU1$%YQ*Q1vUkE8VKR{Qk%?kIIO3Z(=RP>MPkAH#HPgyr@#){}4-vQl+b~K8DtD(1L?Jl)c-ZaXASzJ*bOn&zlY_iTDF3Mcm?$!8k0C>$rX-%7cGKY0Q6{aJl2EjfAY~9LNQ=QHs6^N>vOrVK1tY z3Z<^^LrExt(kKt3l*oG~{$rG0@jd#<=r1TGbJu%%UvMF|CVneAW&MBdeTVfk7kq|s zocQR3!x}@`b^O3#{X~5Dlz!u7A33bQ2w(Y_2XNi5r*%DdGxe z^)y=z7Zbh(d*B<`2cyn8^j~cb;y_yIQ`i$f$I00Eyk6yo@eaa=P~N201&8$v4#F2` z1ixb&!aF{9SljV)Y>lhG(AOQo;$(Q{mkukN_(hi-)*3AO75!g|?r{#J=(nJBt3xPN za2jPt;|G*CYW%hSSZ#?r2+u=#lh)tpH=Bv_(fJDAjaP6651#$4?oC&|b67KpFZ;d2 zO2B)+r~lXD;71}J#|oDzdfaWS@PorjAv^_Xm)04SHt^I>?0S)-qbS|9?jO2)b;0$7 zXQOOvR{K-G*bKa#@EVl(?~tLz8hkaRb5i(k-FlO8I2Wu%Sic`s}rp~7GsD=C}mr7aTdx0{=!6@R9ZjaIF2G*y^L+m$Eo-&{(-%C(514r z+FEH=-nPCZek?A+z7=e1Hok)yIHaO2YfJvs1_yp3ipSXM_qqTMC85pO5C5oStDk6k zRk5w*TsIGgVd<*2^)SX`G}k$*+3KH(6t8ZpHj{>NoIj02uyYODnuN>n5&RW9NdFJl zv@IVI$8ig`cH3(8dlse9MAx#_9N|T|ZYwU}fhB9(YMH&Nj&0Q-ya(&ysk*kc1g-kE z<-w(~w)HZ>7aQm|pVrWpe<)^sgC|22eP$zDb+f@uZL20XEI@g{lOEgZ#)VCr+txg; zOU0gqFSoR9&opb__2>|#dBeFU)|_ZQR?sn-imGe+3LH00d^(4 z8zp1I`(g z#xi)QZAI~>yHJMUSBC5ER$+wB$XMeF+{*bp?8*zJ-)^e~#`Zh7pZGUWCb@%{hR0Dd z)+2PMtwy|ESd)nIBXym(#-W5WQR@5vN=A!~vemC!15t+Fbi5xUC_`%h(PW$qY{P8A zmG83EzTa955`G(Hn(r~zw*KbDLNhp!A#{eQQo*NZA1F;I9x|UUuH8N5MFS%ZEfQG$M-Py z<2?&>)g46{LBB)!1*GsoJ!JPnoBO69W094y$hJ0c{(&V7$vod`wbWMMS__x2@lB;JrFSz3;Qtw%xZVFVJWOLoy~{58R9;$jH~|z~Aqu z|1aX;&j<8KcF#%%5^}f&DPe0$*j7I-O-CBO^)|{{vG!W307qaIOf=3jK5X2D(x%?U z{n+av-Mx!ZUr!NETSxzwjmDUV^`tW#W##fdvf8qu*V~qt@Wn@T|LwcMR=;dKg>8uc z8U5J!QQJC<_oHNN>|;7U9i`u=ScveKSOdQ|;ZmWkI;RzJ zASY&FT|9`=jlMw{c=|nKTVYD%5tIkCdsfe48*nn=ZrgPgZpB)Jk7ITG3DsWD4&BW? z*q8WzDARCg1qY9iaMW|QTE#w*YpZ{yk-byD!7-G{qSf(*IkWVBn!>w%}^Q?LV~D$K-L8{$2Bwtrnq`Khim$j}=JZ zJQm~pm5=pw>pE@AzooUxpe#t9L1_bTeL~3*zJxL^)H`ciQwYbQ`um?_=a~J7_zjP8 z!K@3m^&SrTR6n5BXL`D9iv5UBK$#<+K^dT|i+adyk9QGF#8ljivYc=Ax%NI>#z^`V zKF;%|eMSE-#G6<9Mz`KN-|0nVf0Uv+f-(u!`Chk;UB)Z;J@L0(w$;vN!yj~8xE&=! zGf;X{E=ryMjWVr|{gF9>=N(3=vT482|KH-^z%RD-3$FZCuV9v5q3B%=(MsiE5@m&-Cr@l8x5@Fv}niH zD^;9o@w&9S(`v^3&*Lv-=rgxd|7=&=seV8F6RVL3zF|7L z39rH0_#$2+!P6*X_`&*4D+kkKoocdiHE^o=zCX4i{yrRmc_`hxQbVU&(2T?q^8LMz zgNB@Vx`|W$X7e7_Cw$ddx2ev+Kx{&MvT+SIAiN*t`tMLiw2B_5l|}}aVsXNMPz=+s zNOS$*xyXmGwGWF)|9`fnzHkrHldOX%-Rg-pI(`SrEcOcSz-Dco);v6iFJnSGr&<@( zzC~wnT6-toh1`#0c~Fy1vrnj%kFyK`Gj?-JDiD zMs;^ug-9p~69}jGaH{YB_fclI`8{=G`xa%EOYWuH%!jy-@Uh+$HTQ@6=tlcQUu{%B zG9cZ<&w&(O9{TW>{`!Ko7$*EX&cFu-I92~IG0>^{_Z_&2_FU}!W-w`Lzon|J|V#MsfgTb)PgJ!Qt|aCeL)oQ`#HHMYc;&`F7W7vi8U z5kHP~sxiLOIQl)|c{l+3#5t|Kct6%9BX@Xp8=2|TjqNM!#Q93&o$3?pcJy*xGD>$l z67RH55-yQIVjR7oiP_aiKUr6%eJSI2n5%TZ>v z%Qzm>lbqH@-soLSB0Mcwr*|GF5^kKreVkv3G9Fw>QzaF$2B$Of5iuKOO?L$QpmT~Y zvH>XLLn=zqu11+&52932oq!$*Gx0vcZ{k@T71WKhLx#Tp0=^kVNo4Bhot)uhlB55{ z&eS8@pD1rubC%Qk6z8MN{}X5HH`$G{Y_{h()hCpTwi8Xb6V~IpzS(+UNx|lX@0>?f z;38azU*ZEeWxiAGkht!qDy09nu!3WkhRn4>_gTjzno}n-)9O)@QpP4S8yL0slLpq=KBlFo$BM#aj#RYj;Er$$Z6b+p8Is8`~X9;{I*s&)dxiCr^Y|RPi2WaST6}j}&DZNjwPb_Sx|fW+k5U2&kI~vWzX}Tz zKDg1THlN->cJBD!v!MSk=HR0zo$4dhze$g9A$*P-KE*bi4{z3E_>rfbYC+Lwi_=;| z!jGY>ZaZz$Bj8AsR(=AdBwIi0RO^5ZDA#?B^1?;7JFQ&owVk??H@ZT^7@V_1_w!S@ zmT;Npoa(cAD=s4J&ee0kW~@TS#_ZG&$a>zX78Gyb61ndMr}ZSRLuu_jBa{@bMp>Zz zfU-hr9NMKXT#NmQ=)T*jR;x>qT~{mSMg2z3m-NEHhiW4NdvSe*m-PcjqrAXpI6=~R z#i_PnH=zvOO<&b7unC_a+~PIes6!_?@Dt&Foqk`8p%Z2Lyz&;a8u1g~)?@f9C?(bA zD3cRKzXux-jz6x)fn`{TaItrt>Wiu@MiH)xQunnmNV*NN7(V=-8lXbf=J%cIWWBs#w?Y9UA5zfWGB**7;YybOG zz4B@PnbYbu^=~i;MLRJ&rcv}&dn!P@Xc3J1R;0N4_?-g@djW|EIxJzxXZ!PIkZ@8h9 z%X)}6Z&%u-RyOaJbE(DYx$-X6x?L4qDuYj>l)xpFD(hI$rAm4cenj|4#gI#FscepM zS&tF%R3(>M7!0WFQY)B5>_>byR>n867LDfu=8>_esxE7%#8=l3np4ANJx=&2F2`U^ zm#TY*Tbqc<#2-P)P=`=0os)&Qhlu#vF3ZUSYSwY7&FDIHUFx@*qu7`8N%dT6cHDu| zn699_$)Nf!t2FmDh;^xMknS9^zTiL>kG(tVqF#@~2!D<;mUrmlQk&ANaRA|W(Tg>@ z>Y@x`N5WsD4;yr&Eis8LK|T+yNBg;~Zp7ydbg3ctJ>*Z0te%5h)?5eu??;;aGA_tu zt{sQ=Z7$V%eK?o!4)kKHp)R#guoCAH{u8B2Lc?@M51{(I9_~_GvT=AX=PzSAC6_(I zrH1Cqck1g$j^u@<|G&V26ye{PgpEeI)Iww>_91))$79#gx&$6WdC)hQhp}T^)&<_^ zE0hJs(Xo^u-FW;sm-^-8`SC8b#q%TX<$O+pOLgy&ewP)J*1dp(g>obI!aFCptaor7 zO8-qs)EV51cM|>%r(@rVF6#ikj!X~M;v|>#BpDf*qSN_1)umQSz0zEko9kww-2X7j zxbbru{a@V;FQFv#C9c9+GhJ%696^~S zV`jP3$hdH}&cGIwk@GAz#FBIL`CD){*WZO}@D$Jeg7X=nxi0G<2V>{yZc%@}F4~bO zRdXD_$EtVhfvNaCE~_XBG(->atrob{R?T>fA>3}E9;j}`s)Um;5${16SH3}+rY|pY z>0i~aa8QnjB8znb)sSU?)f!7+H+&X{puEvv_%b$F!W+}bF5*PORqrFf1MWs?ocFA7 z@jsBjzl_9^bi?5f==;a7)YmW5hOD1Ckh&bVO4m`*2X(8x110AxaVGwWb#Yo)m(;_U zP53BEx4mt(9{HX{nRd@&H!QbCj~^rO5aIh!o;P}}%lcU6|EPx;8i_cMPmts1*6Fc) zMzlko7zU1}N)qhu@(d*K&28=G!)S-GUQ17uTOV+g;Gw_%ITE^8Cl%|rRDZoEa8KrfU%p)7m}2W{1JLeXb* ziH${BM|_BqUW08eD*^AudiW)V7I0ANSv}A^h|=gzqs;I1x9bEaU~|GRq8q*S01mV9>hUVd~F=SI>Comn`y}=vfraYHgoW8x+ zrM|FE?xi2f5c?Mq^5(tw>Hd2!#!~k$;c9unLER{4zo{puJt!-gl85w=JrV~Hegh|A ziNh|nTAqfLc<^611Y?dcVBv(fX{2~4bd>(g4OicBSs!5GW6aldm$N7X(1mw(V=Mih zo&!c;7V#03D)PLq8)qs?U4Mja3Nw(M(B0U3+NJ)kAlWz-d9F3j7`mGSSuQWYM{ys1 zjftP=^}vWT%mv&r3u_WT_?(VUL1_c4P+Io^?2D&RR=c&&>k?XoIfRd+RMmtFx(c(A z5(!zyIgmH0^_k0Jo7VE7yy1v1coRH~gVFJ&?$5WPRM`sbjVDodKC541;lj{%>1#bQ zuKrPH=m2))x>7%}REuJ#6s4-I-z8m|Wq%HO5DsHEJcX5LOjZBT14-+@DH%#25v9(H zI-*qn9gf=xZ$nv%#o1A6;K{|sgfF6$NV+phb-!IGyX@s%QR?eC92I4ClIe9$p(v|6 z?!nG@6{lgx!cpq$btlRmk5wc}b)(MMfZ)rRO@bHk0&kWW9i{(rs&rKDOy9?j+&S?} zissZzc_jD!l^yfX{j0h)CAA9xSZ@z z#pc(7amh*ld|h0+T$B)(;SXj6b5rN^a+I0q3&xH2`%~ir{`9m!hCd6Uvkdn(3qmU zN=h7QXXaGTj>#FA-LtqaH6bpTmYgYR<;=;hU7k1b2U2~>asEIcEf5#X@C7n*9?b6K zn3}UcyYArBw77{}5{&a@`I3@-6uM@eJCpn)Pl(Pv*6DIfrRCe6>K-$!xKXC1$EPr6U zFC!@>x6<7eoVk4$o^X_!Ix#7JVq8*?L<0eTd~WH*PdJL-kcBCWtLD72qEL=^N%7q0 zm#nCKw%Ko!lcEzbba)8OQd`6+Lna z?>l+ZWB0Yn`DC9bx6PXe3*}5dcFT=tcN}k;`^>TBcCLMDe(@Vm9lO{n$8)iG?mZX1 zH$Csz#ZI}OectV+H$Qf%ZcdG_Cf}Hdx{hMut7(qv5qH3G^rkB=Pj|ElAIPF`znkh9bz}1gmznE0 zc4Ov_&34p?9G~kba?|U5GT%`veD{1uOoaYfr`(MSn2FWxOHR() z?B+=s0UyJ4&|?jV^(7HX%go|LvcEyFp_^G|d~)8V6ctF!+nk!WIUq^NxnO2e7Wt6F z1Yc^97s&`n?nttOHOTKCpO)&5&)b=yo)UD&PfQE?TLj5l-jqx0&P>fr zneCRjUsA3Wxqqi4+FAW}%7VGopBZrb+!O>?27KwV7RcM|53h+hs)c&0(lCW2kH}2r z)n$bc@AtUxkYeUVXSm1vgK0^r^5zL#><^?QrBXEHCs}8na^$rWWI;hGNJ$1WlQVo7 zoRx_y!{hGdcc-SMj3+lNcjSWfwA5gTLzxjNA*MtEK^8#n^fYQgCUuW>hbkX4Z>RWq zk83$0U4K>@)s?`FNvRXk0x7DEkR+Lq!U<%k!&ufF$w@(9hLl8Bl21-fNRw4fc*gV2 z5+S#4R203Gpg-V~Y)}k7uE@wtpwSRarfnsprSjUo8?#Ktc^i3=>z;c3BdO)2Kn6v{ z`*hDrqTyz^1O5zJWY8L%w<$UNX2el4)XP61DK&{T+zjf#Z}P`;rA<@jDL%^4JR-%H znv}PRplMD14$;wdXHN9{68wSL(a}BAQqpOr(lLC=X#sixEo@&7?@m7%pPUv?VI`33 zyv?5I=s~6^LUb;A1usVn@pC(6o#l_e?p0|Cfy7K%E~-~8$ON557aLiP^(XT%UA9tI zx{=HC>5Qf;_>xV-N~hCE9;MH@L+Y`#se-y8Kh&V=>P=Jfo~H7-A@DyuE5%3I#`{Si zHP*)}D_&J){xDE5gt!xv)5iOf{rQc{w1lS@JIi|N&P)%m=8R)GN)2TOQfGU0G5lkj z4xflP+IH!knw2(P)taeQcS0YP^g_yp-Q9YhkxP)jiRdnIQvAqAxRkqTdrK zw#%{6j_IG8kQ8rPFU=!=ogCiwqN9!X*35K<0O@Qp0H`s+EqzrQIE|xVG;-HsBuMd1 zAMfuiE9zlp**}|poD`o#(MTG4>@;OR!AFPf5I+B+BQ`Wds)NksZMKH%QOX*^fP2FT zL5;@KLwPaA!pwMSsI(=MbC0`sFzAz_ke(nT0k4^=Q+4|ob-6K1eQ&67Ih7tr6V!uD zdRj;|hJZiO7oZtSGsrIlH_by0_<2vu5Rnz|B}pqJCrOe5y^1^*j9OCpI&TH-RVqYx z()>DC18$>)w4{tiB$GmNjPe0hReVMzCCcC?qY90NF@u($IjtZyT7Q0WP1GHXmvlJY z3Ds9gkWM)0y1Uh&HYt;#MI~ykr%KgZnW_lUHmKSpnST;usRuqvq;Lx62h};Hr!kCk zI!y*U>QfcPOjb^%%G>6q9;;*k7Jx&Vvtlj zm8yosaMx$;nBFvTJ^Kb!Q%s>%FbWp*cRsIp+jOF+AsK9%NZV&}3HmdW-6?5-c$%6g zGUa8*_Cjrj`Qs-tw)kf>3-~5byYUnCI7k~v_a*XJYS*-^Yb`2VbFZU$sHbnDyq46J zP9tdbPgXf%){U3Dq#a6!)VVEKDg^z>GN^N3Qfe?Gkg1jf5=fv>)o`Ak%;YD%)#L8Y z`ho#0EpN9OUt|G6Ml+g|L0X3zwd0d{mei^AHPcziRWe_w6Y~3Zhsdyfj)``tpraII zOf5R{JIl3IfycUbsh-7nTh%z+slKeFL^Y?W4nT36Y22qK5GiOi5z9O)^{3`xJ*mgY z2rgr9ez7pD2J$uq!>>1Wl@Iw6eCaf@4(|MBLx-lX(jTQ`Fny~gry7=&-vqJ)G!N>I zxx?cgE{|3h6%>Q48u*G2x*MqOrV8F4O!rYmGD^hz1Ds|(#OBAS0NqlSQGP}Qx;ed` zD&)~=w5FgtJu@k&T5(X8dU{5dMS~fR3RV-0c4~!1A>=O~B9Q}*!Nnux-gA6kq(uJH z$#+&-*m2rXrMT*+rl7*TPCI6mRYPWyYEP=|v$T5kv}3d*T;+`8jmo#HWd+6PZS2*P zlW$TQg%Jq5x7gK(xErKpx}_C0QDk`rRR;g8NZevBMF>sVRM*{D%!B=M?aVpRAY+wL8%=(KBu+c@q1k&x3) zE?Ow4=AQ87;&zK7JWhoo4NKUgTv4k3g%_8xyGIU}vEMA!t#`p9n#`DKR_~H9;mULo zpVXAz70hI~QWLBiYP{o<0trF?biX%}Q_H^F?(x4%=C6X}H`7|jBa3U%$(j?VwP zguKDjw6t_@WJ^8!gNl*6JJ}bC6zZ<(B7CmB?JneFB%*mw>SkAuS1&+0>zCC_AvN52 zSUFKofh<|VN`sa`Ulv2EiF$*4gRr7yo#bT^lB~Ko=OtmOHd?qW;N-j~GNHG9$`vki z)>)-Ueth`bMb4P;$bNR&%6iI?JK_V>xf*E3`+^>Cr0W2?bjhLxWe|RPq+PY73_IQ_ zeD|;#^#{XePq<)?$*jxF{JA(D4!bCuh%o#KRwu>A&VNF z?`z3=Z)%w=lBKuHc$vcD*`LYzEarV_n5?wjB*b7zA((7+@LIi784Hpa>D9ExG@Rv+ zlpJjrEgC9#A<4uIjZC+(f_Xw_;tZW5*pfb|AWS&$RR;m0nOj*jOv7H)M#u z*1~0QVHL-8t{&}e5dQR8N7EJ*m^?}i0eWDQm5(VPwd!XwNu;x=yiihMUtw1T+v5&D zQpi;+)Wpr4n;JWvuNOuxxm6F&eC%<|sHTQ!k9!1Ps=RN0(O-L<$32AW3bLh^wEFud ziRzf{?(Fu;`cOVlXit1u(DYfg=#ewMyNsKZtKY5HAnd17$OVs)POfT9K9pxP;iE#W zzH~LIcl1Oyq}YoK{qGB~%YRsa@+!JbY)W80QKi`Pzb{2A{MvSBOr%?e9pg&k7mp5n23FwRECOtbqr|M%7C`OjWE+_{yjibL04kN>{*B9G0qv!e=|u_S!V z=d9EwB`qU3Mn(cPHC^i=-d4KDvf$L44tkJf^PeAABDLn)x7(4E3+krB_>hl@?P_Ea*ghH!>0e)EvEt9*L=yW#5Q zx7P0(^vJB0n$V!VsV^Fn>??&wzi3zK8Lbv>YJdy4+vg7nW*TF>&mU=7O|lE1#^VMp z%~FchstiKm?Gx+@jB2f$xZ8~NHYAG-d}@YJ<2zeQ`rD5ohAGh#&5HaVM!)=VuV85^ z3qfw7X9Q&yRTGl#4d%;L^$$I$CHwm2kH7g7lqdQQ*{;$HTlHbfv5e;Qg#iDN#ihAN z6+uv^JtbUonq8@8!Qz_UroRXoBF!$2Kj4Yf*ll;RYy3|YMbmJ+Zr3zZZb92{dxM!N zx=m0I)DT}IG6m>GeEwF6JIIDXJRb_Y{eM?rE!FrzGS~0K=!roWoqkh3am=STgHw7> zXQlD~SUSl*os!B^FxHpI{G#(;kaPA+@-`<@oAQytE~}oy3!WmSuGe{<$f!MbsZ#$@ zA8T}7IgSWq`c3ER<4X?une(n+O@~(;vdcR>k;Fsx9>;(5kPiR%4{>|h_)Vfy>l`qa zyk#dAYEv+o6ntx3w{T`(B!8jSlqQhBc5D)Ut%0*5CsWzRlbz}7a$z2F-5Z;j@cnPw z^3R(NQpT|TnzxP88OdwP)GwUEN`>JcF>n3?Y97gm2fyINj%18+N)d$J~E zGh9|RvVGAoJok*%M@s`MP$HjrKSe@-onmQ4Rl{quTa&GL_04NGyQA4K%I~{+(^vflAT62yxQFT;H1%VF+E$nKRKZLkzYwUklnfH8 z5Y%U!kFPl0f6QQ{mQ4ItvVVpra_Ou+vuc%sYQDD2HS6(k*H*5W?vw{p0mFK5Ol-RB zI>pN9ng5jSecrlKib*-iPE zC&;%>Yqc*NbbFH~=m!nm;Vc)Dy9z#5py_(L4No9lPT7%k`V) zKWc{Z4mZ2ttWeaeHgfsY2^U-LtQkplJNf^yqf>Asgi8%}RaSHOf7A6Jjdji}6fWJ& zSuW!7I1iLzamRiyy8-&qlmb7J1jn=(JEr+qX5zHW@R&?z)ed}!FAFkTNStI;l zc~@!vd2#sBgRTmZV%?lo+f|H?j#Gb0&?+u2n)aNSD*JctaM!8M#?9o%oJ4je)#OY; zrv(z|G}JN=PUDM`eK_?^$qepi4=1vCs&k8@hi=pWl;rrz>4ZBw;C^_i8D#u$+QLB;?h9lxM! z7kr%Q+X^NdHFFot)!wv#SI^dbwIn7+vD3lpez(lo(^>uBcg7nQaiwqC&+tTAtZ@Ez z?UOZs#*!k<*E+k`j0AQ&&lZV_Wtkfrx&002hlTFsVQLHY+H#+a@PnD` zz2=Xa>URMG1s}GO+3`v2h_a;|-J6Ah`Js)wxK^UWEpD~T@k6H?)%bLmU3?i9ul?F4 zL#X;N)T!rB2C~2%=RIzRSZtLpzhmQJOAS32R6 z+nklc!a#RW*eaJ2pu5sR3 zC=&CLvt`*5L-IEJQd9Vqh0#4ZGTy4;}N}r#Cdb9lVk5SDZusi;bSp zfA)c^TDa_zUDwsF`^3L)>+FVY8U1;|mbcne(%U!e^G}QSM{;ae+v|qW|ND)q7P1*P zO|Oox?Hj2@(f_bbr9X#m&V9(-k^fao69xX^iZ4j6N zClDU$aaCx}T2(%T#Q2y+S7K|W!;q!$mH`ce;t+oqeQ{l!4n<%+~-Ow*5X<&nPsna%o~;; zW*Mgjkf7}URj$sDg-)|)Bm7fCw8FBp4voD!(QkEKW zfvkn(M|FN!lq*s*Jkjj6=TBOy&8Q!PuKl{B-$b>!D7LABp2)ztt|k1jr20I${^O$U zwPx>~=5EAtP_=1w+{(*LA)EU0R{`>K1%Jyhk*`DkA|mqM0@ug?v=Fa*Ej_xC{G!7b zRp-t+RViL?XBzOcOI%;H{g3uP#+wDT`mKe9S_YeM<`=bVdwcxpkUkSTEHgFME z{NGcqtFZh()nFATzc1@@ly`dYbyxp-rSg{@mikl*s1Ks{s(M)BvXYGL$2V|VZ2nsE k+WUGrZ%R-7I37on_C`Lx=-TBBZ@A<-8cF}kb)fM70WawYr2qf` delta 28763 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 g^tOx2sZULRsE{|ub`Q_eL*Y5T;;e-^bL Date: Sat, 2 Nov 2024 19:22:44 +0200 Subject: [PATCH 14/53] add more testimonials --- homepage/index.html | 22 +++++++++++++++++++++- translations/locales/es/index.html | 2 +- translations/locales/fr/index.html | 2 +- translations/locales/ta/index.html | 2 +- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/homepage/index.html b/homepage/index.html index cd99f20e..019fa1ae 100644 --- a/homepage/index.html +++ b/homepage/index.html @@ -197,7 +197,7 @@

See what others think

GitHub
- 1000+ + 1300+
@@ -240,6 +240,26 @@

See what others think

A lot of courses could use this treatment. + + +
- 1000+ + 1300+
diff --git a/translations/locales/fr/index.html b/translations/locales/fr/index.html index 310b16e3..01a73cba 100644 --- a/translations/locales/fr/index.html +++ b/translations/locales/fr/index.html @@ -253,7 +253,7 @@

Ce qu'en disent les autres

GitHub
- 1000+ + 1300+
diff --git a/translations/locales/ta/index.html b/translations/locales/ta/index.html index 95e49baf..70ca8769 100644 --- a/translations/locales/ta/index.html +++ b/translations/locales/ta/index.html @@ -201,7 +201,7 @@

மற்றவர்கள் என்ன நினை GitHub
- 1000+ + 1300+
From a4e4b94fac0277a68e26a0eba3c5d7400c67421e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 11:30:44 +0200 Subject: [PATCH 15/53] Bump cookie and express in /frontend (#494) Bumps [cookie](https://github.com/jshttp/cookie) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together. Updates `cookie` from 0.6.0 to 0.7.1 - [Release notes](https://github.com/jshttp/cookie/releases) - [Commits](https://github.com/jshttp/cookie/compare/v0.6.0...v0.7.1) Updates `express` from 4.21.0 to 4.21.1 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.1/History.md) - [Commits](https://github.com/expressjs/express/compare/4.21.0...4.21.1) --- updated-dependencies: - dependency-name: cookie dependency-type: indirect - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c56cde8d..59b7ac29 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -6690,9 +6690,9 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "engines": { "node": ">= 0.6" } @@ -8748,16 +8748,16 @@ } }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -23346,9 +23346,9 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==" + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==" }, "cookie-signature": { "version": "1.0.6", @@ -24815,16 +24815,16 @@ } }, "express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", From 99dda573a8e6c3f25769d2593635dfef07f48bf2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 11:30:52 +0200 Subject: [PATCH 16/53] Bump cross-spawn from 7.0.3 to 7.0.6 in /frontend (#495) Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from 7.0.3 to 7.0.6. - [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md) - [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.6) --- updated-dependencies: - dependency-name: cross-spawn dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 59b7ac29..de424ffc 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -6886,9 +6886,9 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -23479,9 +23479,9 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", From 893cafb24e2ce382e5f65ad06b27e3328fe5f265 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Dec 2024 11:49:48 +0200 Subject: [PATCH 17/53] Bump path-to-regexp and express in /frontend (#497) Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together. Updates `path-to-regexp` from 0.1.10 to 0.1.12 - [Release notes](https://github.com/pillarjs/path-to-regexp/releases) - [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md) - [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.10...v0.1.12) Updates `express` from 4.21.1 to 4.21.2 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.2/History.md) - [Commits](https://github.com/expressjs/express/compare/4.21.1...4.21.2) --- updated-dependencies: - dependency-name: path-to-regexp dependency-type: indirect - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index de424ffc..ce00b2fc 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8748,9 +8748,9 @@ } }, "node_modules/express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -8771,7 +8771,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -8786,6 +8786,10 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/array-flatten": { @@ -13585,9 +13589,9 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" }, "node_modules/path-type": { "version": "4.0.0", @@ -24815,9 +24819,9 @@ } }, "express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -24838,7 +24842,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -28332,9 +28336,9 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" }, "path-type": { "version": "4.0.0", From 3b606b23187e60e322f6e603003ed12d0b1a8f44 Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sat, 7 Dec 2024 12:36:34 +0200 Subject: [PATCH 18/53] Upgrade to asttokens 3.0, no longer need six (#498) Also make assistant headers more obviously clickable --- core/core_imports.txt | 1 - frontend/src/App.js | 6 +++--- frontend/src/css/main.scss | 16 ++++++++++++++-- poetry.lock | 15 ++++++--------- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/core/core_imports.txt b/core/core_imports.txt index 52944d9d..3f32002a 100644 --- a/core/core_imports.txt +++ b/core/core_imports.txt @@ -13,6 +13,5 @@ pyflakes pygments python_runner sentry_sdk -six.py snoop stack_data \ No newline at end of file diff --git a/frontend/src/App.js b/frontend/src/App.js index 56e54f9a..51131bb7 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -250,7 +250,7 @@ const Assistant = (assistant) => { - {terms.requirements} + {terms.requirements} } >

@@ -269,7 +269,7 @@ const Assistant = (assistant) => { classParentString="assistant-assessment card" contentInnerClassName="assistant-content card-body" trigger={

- {terms.assessment}   + {terms.assessment}   {newMessages && {terms.new}}
} > @@ -278,7 +278,7 @@ const Assistant = (assistant) => { - {terms.hints_and_solution} + {terms.hints_and_solution} } > diff --git a/frontend/src/css/main.scss b/frontend/src/css/main.scss index da5d1daa..7be386ac 100644 --- a/frontend/src/css/main.scss +++ b/frontend/src/css/main.scss @@ -468,10 +468,22 @@ .assistant { margin-top: 1em; + .card-header { + padding: .75rem 3.25rem; + background: rgba(0,0,0,0); + } + .card__trigger { font-size: larger; position: relative; + cursor: pointer; + background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.1)); + + :hover { + background: linear-gradient(rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.15)); + } + // Font awesome icons svg { width: 2em; @@ -482,8 +494,8 @@ font-family: 'Tahoma', sans-serif; content: '^'; position: absolute; - right: 20px; - top: 10px; + left: 20px; + top: 12px; display: block; transition: transform 300ms; } diff --git a/poetry.lock b/poetry.lock index 3a461600..31c7d088 100644 --- a/poetry.lock +++ b/poetry.lock @@ -13,21 +13,18 @@ files = [ [[package]] name = "asttokens" -version = "2.4.1" +version = "3.0.0" description = "Annotate AST trees with source code positions" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, - {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, + {file = "asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"}, + {file = "asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7"}, ] -[package.dependencies] -six = ">=1.12.0" - [package.extras] -astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] -test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] +astroid = ["astroid (>=2,<4)"] +test = ["astroid (>=2,<4)", "pytest", "pytest-cov", "pytest-xdist"] [[package]] name = "attrs" From 11f0915044690e75b5a20befa92a3c37402e6f86 Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sat, 7 Dec 2024 12:40:57 +0200 Subject: [PATCH 19/53] Stop storing code entries --- frontend/src/RunCode.js | 18 +++++++++--------- frontend/src/book/store.js | 31 ++++++++++++++++--------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/frontend/src/RunCode.js b/frontend/src/RunCode.js index fa24049c..275fe365 100644 --- a/frontend/src/RunCode.js +++ b/frontend/src/RunCode.js @@ -171,15 +171,15 @@ export const _runCode = wrapAsync(async function runCode({code, source}) { finishedLastRunResolve(); postCodeEntry({ - entry, - result: { - passed: data.passed, - messageSections: data.message_sections?.map(section => ({ - type: section.type, - messages: section.messages?.map(m => _.truncate(m, {length: 1000})), - })), - output: _.truncate(data.output, {length: 1000}), - }, + // entry, + // result: { + // passed: data.passed, + // messageSections: data.message_sections?.map(section => ({ + // type: section.type, + // messages: section.messages?.map(m => _.truncate(m, {length: 1000})), + // })), + // output: _.truncate(data.output, {length: 1000}), + // }, }); }); diff --git a/frontend/src/book/store.js b/frontend/src/book/store.js index 473b5db3..b2feeeae 100644 --- a/frontend/src/book/store.js +++ b/frontend/src/book/store.js @@ -514,19 +514,20 @@ export function logEvent(name, data = {}) { } export function postCodeEntry(codeEntry) { - const {user: {developerMode}, route, assistant: {numHints, requestingSolution}} = localState; - codeEntry = { - ...codeEntry, - state: { - developerMode, - page_route: route, - num_hints: numHints, - requesting_solution: requestingSolution, - }, - timestamp: new Date().toISOString(), - }; - console.log("Posting code entry", codeEntry); - if (isProduction) { - databaseRequest("POST", codeEntry, "code_entries").catch(e => console.error(e)); - } + // Disabling for now because this data isn't used. + // const {user: {developerMode}, route, assistant: {numHints, requestingSolution}} = localState; + // codeEntry = { + // ...codeEntry, + // state: { + // developerMode, + // page_route: route, + // num_hints: numHints, + // requesting_solution: requestingSolution, + // }, + // timestamp: new Date().toISOString(), + // }; + // console.log("Posting code entry", codeEntry); + // if (isProduction) { + // databaseRequest("POST", codeEntry, "code_entries").catch(e => console.error(e)); + // } } From c86b99ca3883e0b1c91a021b845cbc436f9c74d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 16:34:16 +0200 Subject: [PATCH 20/53] Bump nanoid from 3.3.4 to 3.3.8 in /frontend (#499) Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.4 to 3.3.8. - [Release notes](https://github.com/ai/nanoid/releases) - [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md) - [Commits](https://github.com/ai/nanoid/compare/3.3.4...3.3.8) --- updated-dependencies: - dependency-name: nanoid dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index ce00b2fc..c2379f0d 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -13108,9 +13108,15 @@ } }, "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -27990,9 +27996,9 @@ } }, "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==" }, "natural-compare": { "version": "1.4.0", From 073338ee3a1bf9af8e43c40a7b1f8c0ca7caa637 Mon Sep 17 00:00:00 2001 From: Darp Na <18359392@student.curtin.edu.au> Date: Sun, 12 Jan 2025 22:39:23 +0800 Subject: [PATCH 21/53] Update c09_functions.py (#500) Verbose instruction --- core/chapters/c09_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/chapters/c09_functions.py b/core/chapters/c09_functions.py index a41cc552..b56af9ea 100644 --- a/core/chapters/c09_functions.py +++ b/core/chapters/c09_functions.py @@ -200,7 +200,7 @@ def print_twice(x: str): class print_many(VerbatimStep): """ -Functions can have many parameters. Here's an example: +Functions can have many parameters. Try the below example: __program_indented__ """ From 3d8d744ad8d954379166bacf36c167a4795670e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 23 Feb 2025 16:50:54 +0200 Subject: [PATCH 22/53] Bump serialize-javascript from 6.0.0 to 6.0.2 in /frontend (#502) Bumps [serialize-javascript](https://github.com/yahoo/serialize-javascript) from 6.0.0 to 6.0.2. - [Release notes](https://github.com/yahoo/serialize-javascript/releases) - [Commits](https://github.com/yahoo/serialize-javascript/compare/v6.0.0...v6.0.2) --- updated-dependencies: - dependency-name: serialize-javascript dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c2379f0d..9ed0b298 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -16303,9 +16303,10 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } @@ -30108,9 +30109,9 @@ } }, "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "requires": { "randombytes": "^2.1.0" } From 8cc3e3a72fdf7b0fd8a94df2a430ce148ca90f9a Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sat, 15 Mar 2025 23:35:21 +0200 Subject: [PATCH 23/53] update english.po --- translations/english.po | 2 +- .../locales/en/LC_MESSAGES/futurecoder.mo | Bin 297003 -> 297007 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/translations/english.po b/translations/english.po index 2b9a43b3..ea379858 100644 --- a/translations/english.po +++ b/translations/english.po @@ -21719,7 +21719,7 @@ msgstr "" #. https://futurecoder.io/course/#DefiningFunctions msgid "pages.DefiningFunctions.steps.print_many.text" msgstr "" -"Functions can have many parameters. Here's an example:\n" +"Functions can have many parameters. Try the below example:\n" "\n" "__program_indented__" diff --git a/translations/locales/en/LC_MESSAGES/futurecoder.mo b/translations/locales/en/LC_MESSAGES/futurecoder.mo index b2b991debdea073344f61be22a57157c6dabae1f..03910361628a1a71198bc484fa5bf0eba822d73f 100644 GIT binary patch delta 7834 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 VcDbBWhBS8k@9i1V*#ETk{{hcG6f6J$ delta 7805 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 Date: Sat, 5 Jul 2025 12:29:52 +0200 Subject: [PATCH 24/53] fix gha (#510) * fix gha * update node --- .github/workflows/workflow.yml | 4 ++-- frontend/package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 1125143a..901d287e 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -9,7 +9,7 @@ on: jobs: test: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python @@ -19,7 +19,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 with: - node-version: '18.17.1' + node-version: '22.17.0' - name: Install chromedriver uses: nanasess/setup-chromedriver@master - name: Install Python and JS dependencies diff --git a/frontend/package.json b/frontend/package.json index 1411934a..147d7d8c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -4,8 +4,8 @@ "homepage": "/course/", "private": true, "engines": { - "node": ">= 16.17.1", - "npm": ">= 8.15.0" + "node": ">= 22.17.0", + "npm": ">= 10.9.2" }, "dependencies": { "@craco/craco": "^7.0.0", From a9d26d6d95e212949fe3125dc094da153da3d158 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 12:47:33 +0200 Subject: [PATCH 25/53] Bump urllib3 from 2.2.3 to 2.5.0 (#509) Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.2.3 to 2.5.0. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.2.3...2.5.0) --- updated-dependencies: - dependency-name: urllib3 dependency-version: 2.5.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 86 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 19 deletions(-) diff --git a/poetry.lock b/poetry.lock index 31c7d088..55f8edc2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. [[package]] name = "astcheck" @@ -6,6 +6,7 @@ version = "0.2.5" description = "Check Python ASTs against templates" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "astcheck-0.2.5-py2.py3-none-any.whl", hash = "sha256:083d3f787e42f7707f4e9b3ea8ef4e08f50753e3612b494ebcb8cda763979f07"}, {file = "astcheck-0.2.5.tar.gz", hash = "sha256:ba9987e8dfe6c2b9ea6720ab8fbdb5aa00fdfa2908017be8a272b2a4b663397d"}, @@ -17,6 +18,7 @@ version = "3.0.0" description = "Annotate AST trees with source code positions" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"}, {file = "asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7"}, @@ -32,18 +34,19 @@ version = "24.2.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, ] [package.extras] -benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\" and python_version < \"3.13\"", "pytest-xdist[psutil]"] +cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\" and python_version < \"3.13\"", "pytest-xdist[psutil]"] +dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\"", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\" and python_version < \"3.13\"", "pytest-xdist[psutil]"] docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] +tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\" and python_version < \"3.13\"", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.9\" and python_version < \"3.13\""] [[package]] name = "bettererrormessages" @@ -51,6 +54,7 @@ version = "0.4" description = "Logic to have suggestions in case of errors (NameError, AttributeError, ImportError, TypeError, etc)." optional = false python-versions = "*" +groups = ["main"] files = [ {file = "BetterErrorMessages-0.4-py2-none-any.whl", hash = "sha256:1ec7e7e1614668ace08811f0aeefda50317e5a3e000b50162f86590a9bcdc720"}, {file = "BetterErrorMessages-0.4.tar.gz", hash = "sha256:f565984d39c18bfbd5175792f9f1c0d2bf30333a66c48247e7dd9fb2d2030f70"}, @@ -62,6 +66,7 @@ version = "0.9.6.dev23+g8aa06c7" description = "Minimal version of birdseye for futurecoder" optional = false python-versions = ">=3.8" +groups = ["main"] files = [] develop = false @@ -85,6 +90,7 @@ version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" +groups = ["main", "dev"] files = [ {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, @@ -96,6 +102,8 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "os_name == \"nt\" and implementation_name != \"pypy\"" files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -175,13 +183,14 @@ version = "0.5.2" description = "Better version of repr/reprlib for short, cheap string representations." optional = false python-versions = "*" +groups = ["main"] files = [ {file = "cheap_repr-0.5.2-py2.py3-none-any.whl", hash = "sha256:537ec1991bfee885c13c6d473afd110a408e039cde26882e95bf92761556ab6e"}, {file = "cheap_repr-0.5.2.tar.gz", hash = "sha256:001a5cf8adb0305c7ad3152c5f776040ac2a559d97f85770cebcb28c6ca5a30f"}, ] [package.extras] -tests = ["Django", "numpy (>=1.16.3)", "pandas (>=0.24.2)", "pytest"] +tests = ["Django", "numpy (>=1.16.3) ; platform_python_implementation != \"PyPy\"", "pandas (>=0.24.2) ; platform_python_implementation != \"PyPy\"", "pytest"] [[package]] name = "colorama" @@ -189,6 +198,8 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] +markers = "sys_platform == \"win32\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -200,13 +211,14 @@ version = "2.1.0" description = "Get the currently executing AST node of a frame, and other information" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "executing-2.1.0-py2.py3-none-any.whl", hash = "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf"}, {file = "executing-2.1.0.tar.gz", hash = "sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab"}, ] [package.extras] -tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] +tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich ; python_version >= \"3.11\""] [[package]] name = "flake8" @@ -214,6 +226,7 @@ version = "3.9.2" description = "the modular source code checker: pep8 pyflakes and co" optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +groups = ["dev"] files = [ {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, @@ -230,6 +243,7 @@ version = "0.7.61" description = "Friendlier tracebacks in any language." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "friendly-traceback-0.7.61.tar.gz", hash = "sha256:8ca149ea4effa114a9d4354078d0252dbc53e291cdcc63f23e34b8fb65ba15f3"}, {file = "friendly_traceback-0.7.61-py3-none-any.whl", hash = "sha256:6945346e49a4ef72c855723f09a6d9b1b4fbf43759d4529f779f29259efab9f7"}, @@ -248,6 +262,7 @@ version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, @@ -259,6 +274,7 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" +groups = ["dev"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -273,6 +289,7 @@ version = "2.0.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, @@ -284,6 +301,7 @@ version = "5.13.2" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.8.0" +groups = ["dev"] files = [ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, @@ -298,6 +316,7 @@ version = "0.2.4" description = "Small personal collection of python utility functions" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "littleutils-0.2.4-py3-none-any.whl", hash = "sha256:d10d5fe2e107c49fe2fc2904a08d6e5a302b41f8405921835ffcc323782d5dbc"}, {file = "littleutils-0.2.4.tar.gz", hash = "sha256:c7835b01020ced42e291118b7d78fb16bc2d9a1b4f3f42f3cb3787bb4da53d19"}, @@ -309,6 +328,7 @@ version = "3.7" description = "Python implementation of John Gruber's Markdown." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"}, {file = "markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2"}, @@ -324,6 +344,7 @@ version = "0.6.1" description = "McCabe checker, plugin for flake8" optional = true python-versions = "*" +groups = ["dev"] files = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, @@ -335,6 +356,7 @@ version = "1.3.0.post0" description = "Capture the outcome of Python function calls." optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b"}, {file = "outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8"}, @@ -349,6 +371,7 @@ version = "24.1" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, @@ -360,6 +383,7 @@ version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -375,6 +399,7 @@ version = "1.2.0" description = "A library to manipulate gettext files (po and mo files)." optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "polib-1.2.0-py2.py3-none-any.whl", hash = "sha256:1c77ee1b81feb31df9bca258cbc58db1bbb32d10214b173882452c73af06d62d"}, {file = "polib-1.2.0.tar.gz", hash = "sha256:f3ef94aefed6e183e342a8a269ae1fc4742ba193186ad76f175938621dbfc26b"}, @@ -386,6 +411,7 @@ version = "0.2.3" description = "Safely evaluate AST nodes without side effects" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0"}, {file = "pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42"}, @@ -400,6 +426,7 @@ version = "2.7.0" description = "Python style guide checker" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["dev"] files = [ {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, @@ -411,6 +438,8 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "os_name == \"nt\" and implementation_name != \"pypy\"" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -422,6 +451,7 @@ version = "2.3.1" description = "passive checker of Python programs" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["main", "dev"] files = [ {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, @@ -433,6 +463,7 @@ version = "2.18.0" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, @@ -447,6 +478,7 @@ version = "1.7.1" description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information." optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["dev"] files = [ {file = "PySocks-1.7.1-py27-none-any.whl", hash = "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299"}, {file = "PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5"}, @@ -459,6 +491,7 @@ version = "7.3.1" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"}, {file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"}, @@ -479,6 +512,7 @@ version = "0.6.1" description = "Helper for running python code indirectly" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "python_runner-0.6.1-py3-none-any.whl", hash = "sha256:0f8ab76bec0fa9be907e85ef8eb837051b4e15d434d991069a3da7dc33d1e349"}, {file = "python_runner-0.6.1.tar.gz", hash = "sha256:a65368abc006613c9dae064cac012da11ff9e324db2280b9a27712f980414e93"}, @@ -493,6 +527,7 @@ version = "4.25.0" description = "Official Python bindings for Selenium WebDriver" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "selenium-4.25.0-py3-none-any.whl", hash = "sha256:3798d2d12b4a570bc5790163ba57fef10b2afee958bf1d80f2a3cf07c4141f33"}, {file = "selenium-4.25.0.tar.gz", hash = "sha256:95d08d3b82fb353f3c474895154516604c7f0e6a9a565ae6498ef36c9bac6921"}, @@ -512,6 +547,7 @@ version = "2.17.0" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "sentry_sdk-2.17.0-py2.py3-none-any.whl", hash = "sha256:625955884b862cc58748920f9e21efdfb8e0d4f98cca4ab0d3918576d5b606ad"}, {file = "sentry_sdk-2.17.0.tar.gz", hash = "sha256:dd0a05352b78ffeacced73a94e86f38b32e2eae15fff5f30ca5abb568a72eacf"}, @@ -564,19 +600,20 @@ version = "75.2.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "setuptools-75.2.0-py3-none-any.whl", hash = "sha256:a7fcb66f68b4d9e8e66b42f9876150a3371558f98fa32222ffaa5bced76406f8"}, {file = "setuptools-75.2.0.tar.gz", hash = "sha256:753bb6ebf1f465a1912e19ed1d41f403a79173a9acf66a42e7e6aec45c3c16ec"}, ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] -core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.5.2) ; sys_platform != \"cygwin\""] +core = ["importlib-metadata (>=6) ; python_version < \"3.10\"", "importlib-resources (>=5.10.2) ; python_version < \"3.9\"", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib-metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.11.*)", "pytest-mypy"] [[package]] name = "six" @@ -584,6 +621,7 @@ version = "1.16.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +groups = ["main"] files = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, @@ -595,6 +633,7 @@ version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -606,6 +645,7 @@ version = "0.6.0" description = "Powerful debugging tools for Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "snoop-0.6.0-py3-none-any.whl", hash = "sha256:f5ea9060e65594bf404e6841086b4a964cc27bc30569109c91a470f948b0f729"}, {file = "snoop-0.6.0.tar.gz", hash = "sha256:c615eddf84d8907f893dec7fde38768aa4b1d88d92d63055b6cfc07e5cde37ec"}, @@ -618,7 +658,7 @@ executing = "*" pygments = "*" [package.extras] -tests = ["Django", "birdseye", "littleutils", "numpy (>=1.16.5)", "pandas (>=0.24.2)", "pprintpp", "prettyprinter", "pytest", "pytest-order"] +tests = ["Django", "birdseye ; platform_python_implementation != \"PyPy\"", "littleutils", "numpy (>=1.16.5) ; platform_python_implementation != \"PyPy\"", "pandas (>=0.24.2) ; platform_python_implementation != \"PyPy\"", "pprintpp", "prettyprinter", "pytest", "pytest-order"] [[package]] name = "sortedcontainers" @@ -626,6 +666,7 @@ version = "2.4.0" description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, @@ -637,6 +678,7 @@ version = "0.6.3" description = "Extract data from python stack frames and tracebacks for informative displays" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, @@ -656,6 +698,7 @@ version = "0.27.0" description = "A friendly Python library for async concurrency and I/O" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "trio-0.27.0-py3-none-any.whl", hash = "sha256:68eabbcf8f457d925df62da780eff15ff5dc68fd6b367e2dde59f7aaf2a0b884"}, {file = "trio-0.27.0.tar.gz", hash = "sha256:1dcc95ab1726b2da054afea8fd761af74bad79bd52381b84eae408e983c76831"}, @@ -675,6 +718,7 @@ version = "0.11.1" description = "WebSocket library for Trio" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "trio-websocket-0.11.1.tar.gz", hash = "sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f"}, {file = "trio_websocket-0.11.1-py3-none-any.whl", hash = "sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638"}, @@ -690,6 +734,7 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -697,20 +742,21 @@ files = [ [[package]] name = "urllib3" -version = "2.2.3" +version = "2.5.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main", "dev"] files = [ - {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, - {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, + {file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"}, + {file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"}, ] [package.dependencies] pysocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""} [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] @@ -721,6 +767,7 @@ version = "1.8.0" description = "WebSocket client for Python with low level API options" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, @@ -737,6 +784,7 @@ version = "1.2.0" description = "WebSockets state-machine based protocol implementation" optional = false python-versions = ">=3.7.0" +groups = ["dev"] files = [ {file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"}, {file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"}, @@ -746,6 +794,6 @@ files = [ h11 = ">=0.9.0,<1" [metadata] -lock-version = "2.0" +lock-version = "2.1" python-versions = "3.12.1" content-hash = "100a6c0c63a1867705570052caaaaec920c9c9b8b633d80ba4505048eb9448ea" From 50161e5b2ebf7fb4a86f6d162718f00993b620c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 12:48:06 +0200 Subject: [PATCH 26/53] Bump @babel/helpers from 7.20.7 to 7.26.10 in /frontend (#503) Bumps [@babel/helpers](https://github.com/babel/babel/tree/HEAD/packages/babel-helpers) from 7.20.7 to 7.26.10. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.26.10/packages/babel-helpers) --- updated-dependencies: - dependency-name: "@babel/helpers" dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 180 +++++++++++++++---------------------- 1 file changed, 74 insertions(+), 106 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 9ed0b298..4926a3ad 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -52,8 +52,8 @@ "worker-loader": "^3.0.8" }, "engines": { - "node": ">= 16.17.1", - "npm": ">= 8.15.0" + "node": ">= 22.17.0", + "npm": ">= 10.9.2" } }, "node_modules/@ampproject/remapping": { @@ -69,12 +69,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -462,17 +463,17 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "engines": { "node": ">=6.9.0" } @@ -500,35 +501,24 @@ } }, "node_modules/@babel/helpers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz", - "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "node_modules/@babel/parser": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@babel/types": "^7.28.0" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", "bin": { "parser": "bin/babel-parser.js" }, @@ -1851,13 +1841,13 @@ } }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1884,13 +1874,12 @@ } }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", + "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -13613,9 +13602,9 @@ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -17174,14 +17163,6 @@ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -18667,12 +18648,13 @@ } }, "@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "requires": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" } }, "@babel/compat-data": { @@ -18957,14 +18939,14 @@ } }, "@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==" + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==" }, "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==" }, "@babel/helper-validator-option": { "version": "7.18.6", @@ -18983,30 +18965,22 @@ } }, "@babel/helpers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz", - "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "requires": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" } }, - "@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "@babel/parser": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@babel/types": "^7.28.0" } }, - "@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==" - }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", @@ -19858,13 +19832,13 @@ } }, "@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "requires": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" } }, "@babel/traverse": { @@ -19885,13 +19859,12 @@ } }, "@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", + "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", "requires": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" } }, "@bcoe/v8-coverage": { @@ -28358,9 +28331,9 @@ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "picomatch": { "version": "2.3.1", @@ -30767,11 +30740,6 @@ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", From 413fcf350d746b79a1e6d5d034f8ecb6ce37d1a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 12:51:51 +0200 Subject: [PATCH 27/53] Bump axios from 1.7.4 to 1.8.2 in /frontend (#511) Bumps [axios](https://github.com/axios/axios) from 1.7.4 to 1.8.2. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.7.4...v1.8.2) --- updated-dependencies: - dependency-name: axios dependency-version: 1.8.2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 14 +++++++------- frontend/package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 4926a3ad..7f8bc1f7 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -14,7 +14,7 @@ "@fortawesome/react-fontawesome": "^0.2.0", "@sentry/react": "^7.119.1", "ansi_up": "^5.0.0", - "axios": "^1.7.4", + "axios": "^1.8.2", "comlink": "^4.3.1", "comsync": "^0.0.8", "defaults": "^1.0.3", @@ -5738,9 +5738,9 @@ } }, "node_modules/axios": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", - "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.2.tgz", + "integrity": "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -22615,9 +22615,9 @@ "integrity": "sha512-b1WlTV8+XKLj9gZy2DZXgQiyDp9xkkoe2a6U6UbYccScq2wgH/YwCeI2/Jq2mgo0HzQxqJOjWZBLeA/mqsk5Mg==" }, "axios": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", - "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.2.tgz", + "integrity": "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==", "requires": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", diff --git a/frontend/package.json b/frontend/package.json index 147d7d8c..904eb902 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,7 +14,7 @@ "@fortawesome/react-fontawesome": "^0.2.0", "@sentry/react": "^7.119.1", "ansi_up": "^5.0.0", - "axios": "^1.7.4", + "axios": "^1.8.2", "comlink": "^4.3.1", "comsync": "^0.0.8", "defaults": "^1.0.3", From 40d2a17c27ca28e5774d61174f924b396ca78811 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 12:54:41 +0200 Subject: [PATCH 28/53] Bump setuptools from 75.2.0 to 78.1.1 (#506) Bumps [setuptools](https://github.com/pypa/setuptools) from 75.2.0 to 78.1.1. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst) - [Commits](https://github.com/pypa/setuptools/compare/v75.2.0...v78.1.1) --- updated-dependencies: - dependency-name: setuptools dependency-version: 78.1.1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/poetry.lock b/poetry.lock index 55f8edc2..036fc6af 100644 --- a/poetry.lock +++ b/poetry.lock @@ -596,24 +596,24 @@ tornado = ["tornado (>=6)"] [[package]] name = "setuptools" -version = "75.2.0" +version = "78.1.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] files = [ - {file = "setuptools-75.2.0-py3-none-any.whl", hash = "sha256:a7fcb66f68b4d9e8e66b42f9876150a3371558f98fa32222ffaa5bced76406f8"}, - {file = "setuptools-75.2.0.tar.gz", hash = "sha256:753bb6ebf1f465a1912e19ed1d41f403a79173a9acf66a42e7e6aec45c3c16ec"}, + {file = "setuptools-78.1.1-py3-none-any.whl", hash = "sha256:c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561"}, + {file = "setuptools-78.1.1.tar.gz", hash = "sha256:fcc17fd9cd898242f6b4adfaca46137a9edef687f43e6f78469692a5e70d851d"}, ] [package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.5.2) ; sys_platform != \"cygwin\""] -core = ["importlib-metadata (>=6) ; python_version < \"3.10\"", "importlib-resources (>=5.10.2) ; python_version < \"3.9\"", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""] +core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] -test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib-metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.11.*)", "pytest-mypy"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] [[package]] name = "six" From 0604ef952fb1eb5681a186708ea6f196a38768dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 12:55:02 +0200 Subject: [PATCH 29/53] Bump @babel/runtime from 7.20.7 to 7.27.6 in /frontend (#512) Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.20.7 to 7.27.6. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.27.6/packages/babel-runtime) --- updated-dependencies: - dependency-name: "@babel/runtime" dependency-version: 7.27.6 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 7f8bc1f7..5fd6ac13 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1818,12 +1818,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", - "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", "engines": { "node": ">=6.9.0" } @@ -19815,12 +19812,9 @@ } }, "@babel/runtime": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", - "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", - "requires": { - "regenerator-runtime": "^0.13.11" - } + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==" }, "@babel/runtime-corejs3": { "version": "7.20.7", From 15538065cda14c16163b4cc786fbbee35a636906 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 13:03:22 +0200 Subject: [PATCH 30/53] Bump h11 from 0.14.0 to 0.16.0 (#505) Bumps [h11](https://github.com/python-hyper/h11) from 0.14.0 to 0.16.0. - [Commits](https://github.com/python-hyper/h11/compare/v0.14.0...v0.16.0) --- updated-dependencies: - dependency-name: h11 dependency-version: 0.16.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- poetry.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index 036fc6af..708c1d5b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -258,14 +258,14 @@ stack-data = ">=0.6.2" [[package]] name = "h11" -version = "0.14.0" +version = "0.16.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" groups = ["dev"] files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, + {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, + {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, ] [[package]] From 14ce94a23a16d3b5f94381af2b7e9b0d8515b0e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 13:05:09 +0200 Subject: [PATCH 31/53] Bump @babel/runtime-corejs3 from 7.20.7 to 7.28.0 in /frontend (#513) Bumps [@babel/runtime-corejs3](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime-corejs3) from 7.20.7 to 7.28.0. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.28.0/packages/babel-runtime-corejs3) --- updated-dependencies: - dependency-name: "@babel/runtime-corejs3" dependency-version: 7.28.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5fd6ac13..823fdd1f 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1826,12 +1826,11 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.20.7.tgz", - "integrity": "sha512-jr9lCZ4RbRQmCR28Q8U8Fu49zvFqLxTY9AMOUz+iyMohMoAgpEcVxY+wJNay99oXOpOcCTODkk70NDN2aaJEeg==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.28.0.tgz", + "integrity": "sha512-nlIXnSqLcBij8K8TtkxbBJgfzfvi75V1pAKSM7dUXejGw12vJAqez74jZrHTsJ3Z+Aczc5Q/6JgNjKRMsVU44g==", "dependencies": { - "core-js-pure": "^3.25.1", - "regenerator-runtime": "^0.13.11" + "core-js-pure": "^3.43.0" }, "engines": { "node": ">=6.9.0" @@ -6819,9 +6818,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.27.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.27.1.tgz", - "integrity": "sha512-BS2NHgwwUppfeoqOXqi08mUqS5FiZpuRuJJpKsaME7kJz0xxuk0xkhDdfMIlP/zLa80krBqss1LtD7f889heAw==", + "version": "3.43.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.43.0.tgz", + "integrity": "sha512-i/AgxU2+A+BbJdMxh3v7/vxi2SbFqxiFmg6VsDwYB4jkucrd1BZNA9a9gphC0fYMG5IBSgQcbQnk865VCLe7xA==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -19817,12 +19816,11 @@ "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==" }, "@babel/runtime-corejs3": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.20.7.tgz", - "integrity": "sha512-jr9lCZ4RbRQmCR28Q8U8Fu49zvFqLxTY9AMOUz+iyMohMoAgpEcVxY+wJNay99oXOpOcCTODkk70NDN2aaJEeg==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.28.0.tgz", + "integrity": "sha512-nlIXnSqLcBij8K8TtkxbBJgfzfvi75V1pAKSM7dUXejGw12vJAqez74jZrHTsJ3Z+Aczc5Q/6JgNjKRMsVU44g==", "requires": { - "core-js-pure": "^3.25.1", - "regenerator-runtime": "^0.13.11" + "core-js-pure": "^3.43.0" } }, "@babel/template": { @@ -23421,9 +23419,9 @@ } }, "core-js-pure": { - "version": "3.27.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.27.1.tgz", - "integrity": "sha512-BS2NHgwwUppfeoqOXqi08mUqS5FiZpuRuJJpKsaME7kJz0xxuk0xkhDdfMIlP/zLa80krBqss1LtD7f889heAw==" + "version": "3.43.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.43.0.tgz", + "integrity": "sha512-i/AgxU2+A+BbJdMxh3v7/vxi2SbFqxiFmg6VsDwYB4jkucrd1BZNA9a9gphC0fYMG5IBSgQcbQnk865VCLe7xA==" }, "core-util-is": { "version": "1.0.3", From df9aa150513208bb57098c96a930e49ac97f48d3 Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sat, 5 Jul 2025 19:12:10 +0200 Subject: [PATCH 32/53] update node version in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a06089f3..a5342157 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ Several debuggers are provided, including [snoop](https://github.com/alexmojaki/ 3. Run `poetry install` to install Python dependencies. 4. Run `./scripts/generate.sh`. This will generate various static files from Python used by the frontend and run some tests. Repeat this step whenever you change Python files. 5. In the `frontend` folder: - 1. Install `node`. We recommend using version 16.17.1 (lts/gallium) but there are no known issues with other versions. + 1. Install `node >= 22.17.0`. 2. Run `npm ci` to download dependencies. From 54283e98b51a8fa2798abca45e0829630143f82f Mon Sep 17 00:00:00 2001 From: Conner Mo Date: Sun, 6 Jul 2025 01:28:02 +0800 Subject: [PATCH 33/53] Add Chinese support and AI translation script (#508) --- .gitignore | 1 + tests/golden_files/pl/test_transcript.json | 28 +- tests/golden_files/ta/test_transcript.json | 28 +- tests/golden_files/zh/test_transcript.json | 2156 +++++++++-------- .../locales/zh/LC_MESSAGES/futurecoder.mo | Bin 103009 -> 290765 bytes translations/translate_futurecoder.py | 983 ++++++++ 6 files changed, 2099 insertions(+), 1097 deletions(-) create mode 100644 translations/translate_futurecoder.py diff --git a/.gitignore b/.gitignore index 659cf51c..7b6cfdd7 100644 --- a/.gitignore +++ b/.gitignore @@ -145,3 +145,4 @@ homepage/static/css/**/*.css translations/codes.json .DS_Store +translations/chunks/ diff --git a/tests/golden_files/pl/test_transcript.json b/tests/golden_files/pl/test_transcript.json index e7d5dd3b..909e8122 100644 --- a/tests/golden_files/pl/test_transcript.json +++ b/tests/golden_files/pl/test_transcript.json @@ -1247,27 +1247,27 @@ "passed": true, "result": [ { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | sentence \u001b[38;5;197m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mFalse\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 4\u001b[0m | new_sentence \u001b[38;5;197m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mH\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | sentence \u001b[38;5;204m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mFalse\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 4\u001b[0m | new_sentence \u001b[38;5;204m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mH\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mel\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mell\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mel\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mell\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mW\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello W\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mW\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello W\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mr\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wor\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Worl\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mr\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wor\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Worl\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186md\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 10\u001b[0m | print(new_sentence)\n", + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186md\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 10\u001b[0m | print(new_sentence)\n", "type": "snoop" }, { @@ -2786,7 +2786,7 @@ ] } ], - "friendly": "

A TypeError is usually caused by trying\nto combine two incompatible types of objects,\nby calling a function with the wrong type of object,\nor by trying to do an operation not allowed on a given type of object.

\n

The parenthesis () following f are interpreted\nby Python as a function call for f.\nHowever, f is not a function but an object of type str.

", + "friendly": "

A TypeError is usually caused by trying\nto combine two incompatible types of objects,\nby calling a function with the wrong type of object,\nor by trying to do an operation not allowed on a given type of object.

\n

Because of the surrounding parenthesis, ` \nis interpreted by Python as indicating a function call forf, which is an object of typestr`\nwhich cannot be called.

", "tail": "" } ], @@ -3811,7 +3811,7 @@ "passed": true, "result": [ { - "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

I suspect that you were trying to use a quote character inside a string\nthat was enclosed in quotes of the same kind.\nPerhaps you should have escaped the inner quote character:

\n
print('Alice\\'s Diner')\n            ^^\n
", + "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

You started writing a string with a single or double quote\nbut never ended the string with another quote on that line.

", "text": " print('Alice's Diner')\n ^\nSyntaxError: unterminated string literal (detected at line 1)\nw linii 1\n", "type": "syntax_error" } @@ -4978,11 +4978,11 @@ "passed": true, "result": [ { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n\u001b[38;5;242m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_twice in File \"/my_program.py\", line 5\u001b[0m\n\u001b[38;5;242m \u001b[0m...... x = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;242m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_many in File \"/my_program.py\", line 1\u001b[0m\n\u001b[38;5;242m \u001b[0m...... n = \u001b[38;5;141m2\u001b[39m\n\u001b[38;5;242m \u001b[0m...... thing = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n\u001b[38;5;245m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_twice in File \"/my_program.py\", line 5\u001b[0m\n\u001b[38;5;245m \u001b[0m...... x = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;245m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_many in File \"/my_program.py\", line 1\u001b[0m\n\u001b[38;5;245m \u001b[0m...... n = \u001b[38;5;141m2\u001b[39m\n\u001b[38;5;245m \u001b[0m...... thing = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.......... _ = \u001b[38;5;141m0\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | print(thing)\n", + "text": "\u001b[38;5;245m \u001b[0m.......... _ = \u001b[38;5;141m0\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | print(thing)\n", "type": "snoop" }, { @@ -4994,11 +4994,11 @@ "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.......... _ = \u001b[38;5;141m1\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | print(thing)\n", + "text": "\u001b[38;5;245m \u001b[0m.......... _ = \u001b[38;5;141m1\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | print(thing)\n", "type": "snoop" }, { @@ -5010,11 +5010,11 @@ "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_many: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;242m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_twice: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_many: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;245m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_twice: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n", "type": "snoop" } ] diff --git a/tests/golden_files/ta/test_transcript.json b/tests/golden_files/ta/test_transcript.json index 7ea915be..2e5a43d6 100644 --- a/tests/golden_files/ta/test_transcript.json +++ b/tests/golden_files/ta/test_transcript.json @@ -1247,27 +1247,27 @@ "passed": true, "result": [ { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | sentence \u001b[38;5;197m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mFalse\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 4\u001b[0m | new_sentence \u001b[38;5;197m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mH\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | sentence \u001b[38;5;204m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mFalse\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 4\u001b[0m | new_sentence \u001b[38;5;204m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mH\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mel\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mell\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mel\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mell\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mW\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello W\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mW\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello W\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mr\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wor\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Worl\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mr\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wor\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Worl\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186md\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 10\u001b[0m | print(new_sentence)\n", + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186md\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 10\u001b[0m | print(new_sentence)\n", "type": "snoop" }, { @@ -2786,7 +2786,7 @@ ] } ], - "friendly": "

\u0b92\u0bb0\u0bc1 \u0bb5\u0b95\u0bc8\u0baa\u0bcd\u0baa\u0bbf\u0bb4\u0bc8 TypeError \u0b8e\u0ba9\u0bcd\u0baa\u0ba4\u0bc1 \u0baa\u0bca\u0ba4\u0bc1\u0bb5\u0bbe\u0b95 \u0baa\u0bca\u0bb0\u0bc1\u0ba8\u0bcd\u0ba4\u0bbe\u0ba4 \u0b87\u0bb0\u0ba3\u0bcd\u0b9f\u0bc1\n\u0bb5\u0b95\u0bc8\u0baf\u0bbe\u0ba9 \u0baa\u0bca\u0bb0\u0bc1\u0bb3\u0bcd\u0b95\u0bb3\u0bc8 \u0b87\u0ba3\u0bc8\u0b95\u0bcd\u0b95 \u0bae\u0bc1\u0baf\u0bb1\u0bcd\u0b9a\u0bbf\u0baa\u0bcd\u0baa\u0ba4\u0bbe\u0bb2\u0bcb, \u0b92\u0bb0\u0bc1 \u0b9a\u0bc6\u0baf\u0bb2\u0bcd\u0baa\u0bbe\u0b9f\u0bcd\u0b9f\u0bc8\n\u0ba4\u0bb5\u0bb1\u0bbe\u0ba9 \u0bb5\u0b95\u0bc8\u0baa\u0bcd \u0baa\u0bca\u0bb0\u0bc1\u0bb3\u0bc1\u0b9f\u0ba9\u0bcd \u0b85\u0bb4\u0bc8\u0baa\u0bcd\u0baa\u0ba4\u0bbe\u0bb2\u0bcb \u0b85\u0bb2\u0bcd\u0bb2\u0ba4\u0bc1 \u0b95\u0bca\u0b9f\u0bc1\u0b95\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0b9f\u0bcd\u0b9f\n\u0bb5\u0b95\u0bc8\u0baa\u0bcd \u0baa\u0bca\u0bb0\u0bc1\u0bb3\u0bbf\u0bb2\u0bcd \u0b85\u0ba9\u0bc1\u0bae\u0ba4\u0bbf\u0b95\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0b9f\u0bbe\u0ba4 \u0b9a\u0bc6\u0baf\u0bb2\u0bc8\u0b9a\u0bcd \u0b9a\u0bc6\u0baf\u0bcd\u0baf \u0bae\u0bc1\u0baf\u0bb1\u0bcd\u0b9a\u0bbf\u0baa\u0bcd\u0baa\u0ba4\u0bbe\u0bb2\u0bcb \u0b8f\u0bb1\u0bcd\u0baa\u0b9f\u0bc1\u0b95\u0bbf\u0bb1\u0ba4\u0bc1.

\n

f \u0b8e\u0ba9\u0bcd\u0baa\u0ba4\u0bb1\u0bcd\u0b95\u0bc1\u0baa\u0bcd \u0baa\u0bbf\u0ba9\u0bcd \u0bb5\u0bb0\u0bc1\u0bae\u0bcd () \u0b85\u0b9f\u0bc8\u0baa\u0bcd\u0baa\u0bc1\u0b95\u0bcd\u0b95\u0bc1\u0bb1\u0bbf\u0baf\u0bbe\u0ba9\u0ba4\u0bc1 \nf\u0b95\u0bcd\u0b95\u0bbe\u0ba9 \u0b9a\u0bc6\u0baf\u0bb2\u0bcd\u0baa\u0bbe\u0b9f\u0bcd\u0b9f\u0bc1 \u0b85\u0bb4\u0bc8\u0baa\u0bcd\u0baa\u0bbe\u0b95 \u0baa\u0bc8\u0ba4\u0bcd\u0ba4\u0bbe\u0ba9\u0bbe\u0bb2\u0bcd \u0bb5\u0bbf\u0bb3\u0b95\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0b9f\u0bc1\u0b95\u0bbf\u0bb1\u0ba4\u0bc1. \n\u0b87\u0bb0\u0bc1\u0baa\u0bcd\u0baa\u0bbf\u0ba9\u0bc1\u0bae\u0bcd, f \u0b8e\u0ba9\u0bcd\u0baa\u0ba4\u0bc1 \u0b92\u0bb0\u0bc1 \u0b9a\u0bc6\u0baf\u0bb2\u0bcd\u0baa\u0bbe\u0b9f\u0bc1 \u0b85\u0bb2\u0bcd\u0bb2, \u0bae\u0bbe\u0bb1\u0bbe\u0b95 str \u0bb5\u0b95\u0bc8\u0baf\u0bbf\u0ba9\u0bcd \u0baa\u0bca\u0bb0\u0bc1\u0bb3\u0bcd.

", + "friendly": "

\u0b92\u0bb0\u0bc1 \u0bb5\u0b95\u0bc8\u0baa\u0bcd\u0baa\u0bbf\u0bb4\u0bc8 TypeError \u0b8e\u0ba9\u0bcd\u0baa\u0ba4\u0bc1 \u0baa\u0bca\u0ba4\u0bc1\u0bb5\u0bbe\u0b95 \u0baa\u0bca\u0bb0\u0bc1\u0ba8\u0bcd\u0ba4\u0bbe\u0ba4 \u0b87\u0bb0\u0ba3\u0bcd\u0b9f\u0bc1\n\u0bb5\u0b95\u0bc8\u0baf\u0bbe\u0ba9 \u0baa\u0bca\u0bb0\u0bc1\u0bb3\u0bcd\u0b95\u0bb3\u0bc8 \u0b87\u0ba3\u0bc8\u0b95\u0bcd\u0b95 \u0bae\u0bc1\u0baf\u0bb1\u0bcd\u0b9a\u0bbf\u0baa\u0bcd\u0baa\u0ba4\u0bbe\u0bb2\u0bcb, \u0b92\u0bb0\u0bc1 \u0b9a\u0bc6\u0baf\u0bb2\u0bcd\u0baa\u0bbe\u0b9f\u0bcd\u0b9f\u0bc8\n\u0ba4\u0bb5\u0bb1\u0bbe\u0ba9 \u0bb5\u0b95\u0bc8\u0baa\u0bcd \u0baa\u0bca\u0bb0\u0bc1\u0bb3\u0bc1\u0b9f\u0ba9\u0bcd \u0b85\u0bb4\u0bc8\u0baa\u0bcd\u0baa\u0ba4\u0bbe\u0bb2\u0bcb \u0b85\u0bb2\u0bcd\u0bb2\u0ba4\u0bc1 \u0b95\u0bca\u0b9f\u0bc1\u0b95\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0b9f\u0bcd\u0b9f\n\u0bb5\u0b95\u0bc8\u0baa\u0bcd \u0baa\u0bca\u0bb0\u0bc1\u0bb3\u0bbf\u0bb2\u0bcd \u0b85\u0ba9\u0bc1\u0bae\u0ba4\u0bbf\u0b95\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0b9f\u0bbe\u0ba4 \u0b9a\u0bc6\u0baf\u0bb2\u0bc8\u0b9a\u0bcd \u0b9a\u0bc6\u0baf\u0bcd\u0baf \u0bae\u0bc1\u0baf\u0bb1\u0bcd\u0b9a\u0bbf\u0baa\u0bcd\u0baa\u0ba4\u0bbe\u0bb2\u0bcb \u0b8f\u0bb1\u0bcd\u0baa\u0b9f\u0bc1\u0b95\u0bbf\u0bb1\u0ba4\u0bc1.

\n

\u0b9a\u0bc1\u0bb1\u0bcd\u0bb1\u0bbf\u0baf\u0bc1\u0bb3\u0bcd\u0bb3 \u0b85\u0b9f\u0bc8\u0baa\u0bcd\u0baa\u0bc1\u0b95\u0bcd\u0b95\u0bc1\u0bb1\u0bbf\u0baf\u0bbf\u0ba9\u0bcd \u0b95\u0bbe\u0bb0\u0ba3\u0bae\u0bbe\u0b95, ` \u0b8e\u0ba9\u0bcd\u0baa\u0ba4\u0bc1f\u0b95\u0bcd\u0b95\u0bbe\u0ba9 \u0b9a\u0bc6\u0baf\u0bb2\u0bcd\u0baa\u0bbe\u0b9f\u0bcd\u0b9f\u0bc1 \u0b85\u0bb4\u0bc8\u0baa\u0bcd\u0baa\u0bc8\u0b95\u0bcd \u0b95\u0bc1\u0bb1\u0bbf\u0b95\u0bcd\u0b95\u0bc1\u0bae\u0bcd \u0b8e\u0ba9 \u0baa\u0bc8\u0ba4\u0bcd\u0ba4\u0bbe\u0ba9\u0bbe\u0bb2\u0bcd \n\u0bb5\u0bbf\u0bb3\u0b95\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0b9f\u0bc1\u0b95\u0bbf\u0bb1\u0ba4\u0bc1, \u0b87\u0ba4\u0bc1str` \u0bb5\u0b95\u0bc8\u0baf\u0bbf\u0ba9\u0bcd \u0b92\u0bb0\u0bc1 \u0baa\u0bca\u0bb0\u0bc1\u0bb3\u0bbe\u0b95\u0bc1\u0bae\u0bcd, \n\u0b87\u0ba4\u0bc1 \u0b85\u0bb4\u0bc8\u0b95\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0b9f \u0bae\u0bc1\u0b9f\u0bbf\u0baf\u0bbe\u0ba4\u0bc1.

", "tail": "" } ], @@ -3811,7 +3811,7 @@ "passed": true, "result": [ { - "friendly": "

\u0baa\u0bc8\u0ba4\u0bcd\u0ba4\u0bbe\u0ba9\u0bbe\u0bb2\u0bcd \u0b89\u0b99\u0bcd\u0b95\u0bb3\u0bcd \u0b95\u0bc1\u0bb1\u0bbf\u0baf\u0bc0\u0b9f\u0bcd\u0b9f\u0bc8\u0baa\u0bcd \u0baa\u0bc1\u0bb0\u0bbf\u0ba8\u0bcd\u0ba4\u0bc1 \u0b95\u0bca\u0bb3\u0bcd\u0bb3 \u0bae\u0bc1\u0b9f\u0bbf\u0baf\u0bbe\u0ba4\u0baa\u0bcb\u0ba4\u0bc1 \u0ba4\u0bca\u0b9f\u0bb0\u0bbf\u0baf\u0bb2\u0bcd\u0baa\u0bbf\u0bb4\u0bc8 SyntaxError \u0b8f\u0bb1\u0bcd\u0baa\u0b9f\u0bc1\u0b95\u0bbf\u0bb1\u0ba4\u0bc1.

\n

I suspect that you were trying to use a quote character inside a string\nthat was enclosed in quotes of the same kind.\nPerhaps you should have escaped the inner quote character:

\n
print('Alice\\'s Diner')\n            ^^\n
", + "friendly": "

\u0baa\u0bc8\u0ba4\u0bcd\u0ba4\u0bbe\u0ba9\u0bbe\u0bb2\u0bcd \u0b89\u0b99\u0bcd\u0b95\u0bb3\u0bcd \u0b95\u0bc1\u0bb1\u0bbf\u0baf\u0bc0\u0b9f\u0bcd\u0b9f\u0bc8\u0baa\u0bcd \u0baa\u0bc1\u0bb0\u0bbf\u0ba8\u0bcd\u0ba4\u0bc1 \u0b95\u0bca\u0bb3\u0bcd\u0bb3 \u0bae\u0bc1\u0b9f\u0bbf\u0baf\u0bbe\u0ba4\u0baa\u0bcb\u0ba4\u0bc1 \u0ba4\u0bca\u0b9f\u0bb0\u0bbf\u0baf\u0bb2\u0bcd\u0baa\u0bbf\u0bb4\u0bc8 SyntaxError \u0b8f\u0bb1\u0bcd\u0baa\u0b9f\u0bc1\u0b95\u0bbf\u0bb1\u0ba4\u0bc1.

\n

\u0ba8\u0bc0\u0b99\u0bcd\u0b95\u0bb3\u0bcd \u0b92\u0bb1\u0bcd\u0bb1\u0bc8 \u0b85\u0bb2\u0bcd\u0bb2\u0ba4\u0bc1 \u0b87\u0bb0\u0b9f\u0bcd\u0b9f\u0bc8 \u0bae\u0bc7\u0bb1\u0bcd\u0b95\u0bcb\u0bb3\u0bc1\u0b9f\u0ba9\u0bcd \u0b92\u0bb0\u0bc1 \u0b9a\u0bb0\u0ba4\u0bcd\u0ba4\u0bc8 \u0b8e\u0bb4\u0bc1\u0ba4\u0ba4\u0bcd \n\u0ba4\u0bca\u0b9f\u0b99\u0bcd\u0b95\u0bbf\u0baf\u0bc1\u0bb3\u0bcd\u0bb3\u0bc0\u0bb0\u0bcd\u0b95\u0bb3\u0bcd, \u0b86\u0ba9\u0bbe\u0bb2\u0bcd \u0b85\u0ba8\u0bcd\u0ba4 \u0bb5\u0bb0\u0bbf\u0baf\u0bbf\u0bb2\u0bcd \u0bae\u0bb1\u0bcd\u0bb1\u0bca\u0bb0\u0bc1 \u0bae\u0bc7\u0bb1\u0bcd\u0b95\u0bcb\u0bb3\u0bc1\u0b9f\u0ba9\u0bcd \u0b9a\u0bb0\u0ba4\u0bcd\u0ba4\u0bc8 \u0bae\u0bc1\u0b9f\u0bbf\u0b95\u0bcd\u0b95\u0bb5\u0bbf\u0bb2\u0bcd\u0bb2\u0bc8.

", "text": " print('Alice's Diner')\n ^\nSyntaxError: unterminated string literal (detected at line 1)\n\u0bb5\u0bb0\u0bbf\u0b9a\u0bc8\u0baf\u0bbf\u0bb2\u0bcd 1\n", "type": "syntax_error" } @@ -4978,11 +4978,11 @@ "passed": true, "result": [ { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n\u001b[38;5;242m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_twice in File \"/my_program.py\", line 5\u001b[0m\n\u001b[38;5;242m \u001b[0m...... x = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;242m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_many in File \"/my_program.py\", line 1\u001b[0m\n\u001b[38;5;242m \u001b[0m...... n = \u001b[38;5;141m2\u001b[39m\n\u001b[38;5;242m \u001b[0m...... thing = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n\u001b[38;5;245m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_twice in File \"/my_program.py\", line 5\u001b[0m\n\u001b[38;5;245m \u001b[0m...... x = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;245m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_many in File \"/my_program.py\", line 1\u001b[0m\n\u001b[38;5;245m \u001b[0m...... n = \u001b[38;5;141m2\u001b[39m\n\u001b[38;5;245m \u001b[0m...... thing = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.......... _ = \u001b[38;5;141m0\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | print(thing)\n", + "text": "\u001b[38;5;245m \u001b[0m.......... _ = \u001b[38;5;141m0\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | print(thing)\n", "type": "snoop" }, { @@ -4994,11 +4994,11 @@ "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.......... _ = \u001b[38;5;141m1\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | print(thing)\n", + "text": "\u001b[38;5;245m \u001b[0m.......... _ = \u001b[38;5;141m1\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | print(thing)\n", "type": "snoop" }, { @@ -5010,11 +5010,11 @@ "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_many: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;242m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_twice: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n", + "text": "\u001b[38;5;245m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_many: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;245m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_twice: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n", "type": "snoop" } ] diff --git a/tests/golden_files/zh/test_transcript.json b/tests/golden_files/zh/test_transcript.json index e032ca5d..a816e2c3 100644 --- a/tests/golden_files/zh/test_transcript.json +++ b/tests/golden_files/zh/test_transcript.json @@ -1,11 +1,11 @@ [ { - "page": "Introducing The Shell", + "page": "\u4ecb\u7ecd Shell", "program": [ "'literally anything'" ], "response": { - "message": "

Awesome, you're trying out your own experiments!\nThat's a great sign. Keep it up.\nJust letting you know that you do need to eventually type 1+2 for the book to move forward.

", + "message": "

\u5f88\u597d\uff0c\u4f60\u5728\u5c1d\u8bd5\u81ea\u5df1\u7684\u5b9e\u9a8c\uff01\n\u8fd9\u771f\u662f\u4e2a\u597d\u5146\u5934\u3002\u7ee7\u7eed\u4fdd\u6301\u3002\n\u6211\u53ea\u662f\u60f3\u8ba9\u4f60\u77e5\u9053\uff0c\u4f60\u6700\u7ec8\u9700\u8981\u8f93\u5165 1+2 \u624d\u80fd\u7ee7\u7eed\u8fdb\u884c\u3002

", "passed": false, "result": [ { @@ -17,12 +17,12 @@ "step": "first_expression" }, { - "page": "Introducing The Shell", + "get_solution": "program", + "page": "\u4ecb\u7ecd Shell", "program": [ "1+2" ], "response": { - "message": "", "passed": true, "result": [ { @@ -34,16 +34,17 @@ "step": "first_expression" }, { - "page": "Introducing The Shell", + "page": "\u4ecb\u7ecd Shell", "program": [ "3 x 4" ], "response": { - "message": "

I see an 'x'. If you're trying to multiply, use an asterisk, e.g:

\n
3 * 4\n
", + "message": "

\u6211\u770b\u5230\u4e00\u4e2a 'x'\u3002\u5982\u679c\u4f60\u60f3\u8fdb\u884c\u4e58\u6cd5\u8fd0\u7b97\uff0c\u8bf7\u4f7f\u7528\u661f\u53f7\uff0c\u4f8b\u5982\uff1a

\n
3 * 4\n
", "passed": false, "result": [ { - "text": " 3 x 4\n ^\nSyntaxError: invalid syntax\nat line 1\n\nA `SyntaxError` occurs when Python cannot understand your code.\n\nCurrently, I cannot guess the likely cause of this error.\nTry to examine closely the line indicated as well as the line\nimmediately above to see if you can identify some misspelled\nword, or missing symbols, like (, ), [, ], :, etc.\n\nUnless your code uses type annotations, which are beyond our scope,\nif you think that this is something which should be handled\nby friendly, please report this case to\nhttps://github.com/aroberge/friendly/issues\n\n\n\n", + "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

Currently, I cannot guess the likely cause of this error.\nTry to examine closely the line indicated as well as the line\nimmediately above to see if you can identify some misspelled\nword, or missing symbols, like (, ), [, ], :, etc.

\n

Unless your code uses type annotations, which are beyond our scope,\nif you think that this is something which should be handled\nby friendly, please report this case to\nhttps://github.com/friendly-traceback/friendly-traceback/issues

", + "text": " 3 x 4\n ^\nSyntaxError: invalid syntax\n\u5728\u7b2c 1\n", "type": "syntax_error" } ] @@ -51,12 +52,12 @@ "step": "more_calculation" }, { - "page": "Introducing The Shell", + "get_solution": "program", + "page": "\u4ecb\u7ecd Shell", "program": [ "5 - 6" ], "response": { - "message": "", "passed": true, "result": [ { @@ -68,12 +69,12 @@ "step": "more_calculation" }, { - "page": "Introducing Strings", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5b57\u7b26\u4e32", "program": [ "'hello'" ], "response": { - "message": "", "passed": true, "result": [ { @@ -85,12 +86,12 @@ "step": "hello_string" }, { - "page": "Adding Strings", + "get_solution": "program", + "page": "\u6dfb\u52a0\u5b57\u7b26\u4e32", "program": [ "'hello' + 'world'" ], "response": { - "message": "", "passed": true, "result": [ { @@ -102,12 +103,12 @@ "step": "hello_world_concat" }, { - "page": "Adding Strings", + "page": "\u6dfb\u52a0\u5b57\u7b26\u4e32", "program": [ "'hello world'" ], "response": { - "message": "

You must still add two or more strings together.

", + "message": "

\u4f60\u4ecd\u7136\u5fc5\u987b\u5c06\u4e24\u4e2a\u6216\u66f4\u591a\u5b57\u7b26\u4e32\u76f8\u52a0\u3002

", "passed": false, "result": [ { @@ -119,15 +120,12 @@ "step": "hello_world_space" }, { - "get_solution": [ - "'hello ' + 'world'" - ], - "page": "Adding Strings", + "get_solution": "program", + "page": "\u6dfb\u52a0\u5b57\u7b26\u4e32", "program": [ "'hello ' + 'world'" ], "response": { - "message": "", "passed": true, "result": [ { @@ -139,36 +137,36 @@ "step": "hello_world_space" }, { - "page": "Introducing Variables", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u53d8\u91cf", "program": [ "word = 'Hello'" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "word_assign" }, { - "page": "Introducing Variables", + "page": "\u4ecb\u7ecd\u53d8\u91cf", "program": [ "word = 2" ], "response": { - "message": "

Oops, you need to set word = 'Hello' before we can continue.

", + "message": "

\u54ce\u5440\uff0c\u4f60\u9700\u8981\u5148\u8bbe\u7f6e word = 'Hello'\uff0c\u7136\u540e\u6211\u4eec\u624d\u80fd\u7ee7\u7eed\u3002

", "passed": false, "result": [] }, "step": "word_check" }, { - "page": "Introducing Variables", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u53d8\u91cf", "program": [ "word" ], "response": { - "message": "", "passed": true, "result": [ { @@ -180,12 +178,12 @@ "step": "word_check" }, { - "page": "Introducing Variables", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u53d8\u91cf", "program": [ "'word'" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "'word'", @@ -194,7 +192,7 @@ "'word'", "Hello", "'Hello'", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -207,21 +205,21 @@ "step": "word_string_check" }, { - "page": "Introducing Variables", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u53d8\u91cf", "program": [ "sunshine" ], "response": { - "message": "", "passed": true, "prediction": { - "answer": "Error", + "answer": "\u9519\u8bef", "choices": [ "sunshine", "'sunshine'", "Hello", "'Hello'", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -235,11 +233,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 1, "lines": [ { - "content": "sunshine", "is_current": true, "lineno": 1, + "text": "sunshine", "type": "line" } ], @@ -254,7 +254,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 1, in ", + " File \"/my_program.py\", line 1, in ", "--> 1 | sunshine", " ^^^^^^^^", "", @@ -267,72 +267,72 @@ "step": "sunshine_undefined_check" }, { - "page": "Using Variables and print()", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "foo = 3" ], "response": { - "message": "

Put your_name before the = to create a variable called your_name.

", + "message": "

\u5728 = \u524d\u9762\u653e\u4e0a your_name \u6765\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a your_name \u7684\u53d8\u91cf\u3002

", "passed": false, "result": [] }, "step": "name_assign" }, { - "page": "Using Variables and print()", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "your_name = ''" ], "response": { - "message": "

For this exercise, choose a non-empty string

", + "message": "

\u5728\u8fd9\u4e2a\u7ec3\u4e60\u4e2d\uff0c\u9009\u62e9\u4e00\u4e2a\u975e\u7a7a\u5b57\u7b26\u4e32\u3002

", "passed": false, "result": [] }, "step": "name_assign" }, { - "page": "Using Variables and print()", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "your_name = 3" ], "response": { - "message": "

You've got the your_name = part right, now put a string (use quotes) on the right of the =.

", + "message": "

\u4f60\u5df2\u7ecf\u628a your_name = \u90e8\u5206\u5199\u5bf9\u4e86\uff0c\u73b0\u5728\u5728 = \u7684\u53f3\u8fb9\u653e\u4e00\u4e2a\u5b57\u7b26\u4e32\uff08\u4f7f\u7528\u5f15\u53f7\uff09\u3002

", "passed": false, "result": [] }, "step": "name_assign" }, { - "page": "Using Variables and print()", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "your_name = ' Alex'" ], "response": { - "message": "

For this exercise, choose a name that doesn't start with a space.

", + "message": "

\u5728\u8fd9\u4e2a\u7ec3\u4e60\u4e2d\uff0c\u9009\u62e9\u4e00\u4e2a\u4e0d\u4ee5\u7a7a\u683c\u5f00\u5934\u7684\u540d\u5b57\u3002

", "passed": false, "result": [] }, "step": "name_assign" }, { - "page": "Using Variables and print()", + "get_solution": "program", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "your_name = 'Alex'" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "name_assign" }, { - "page": "Using Variables and print()", + "get_solution": "program", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "'Hello ' + your_name" ], "response": { - "message": "", "passed": true, "result": [ { @@ -344,24 +344,24 @@ "step": "hello_plus_name" }, { - "page": "Using Variables and print()", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "word = 2" ], "response": { - "message": "

Oops, you need to set word = 'Hello' before we can continue.

", + "message": "

\u54ce\u5440\uff0c\u4f60\u9700\u8981\u5148\u8bbe\u7f6e word = 'Hello'\uff0c\u7136\u540e\u6211\u4eec\u624d\u80fd\u7ee7\u7eed\u3002

", "passed": false, "result": [] }, "step": "word_plus_name" }, { - "page": "Using Variables and print()", + "get_solution": "program", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "word + your_name" ], "response": { - "message": "", "passed": true, "result": [ { @@ -373,27 +373,24 @@ "step": "word_plus_name" }, { - "page": "Using Variables and print()", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "word = 2" ], "response": { - "message": "

Oops, you need to set word = 'Hello' before we can continue.

", + "message": "

\u54ce\u5440\uff0c\u4f60\u9700\u8981\u5148\u8bbe\u7f6e word = 'Hello'\uff0c\u7136\u540e\u6211\u4eec\u624d\u80fd\u7ee7\u7eed\u3002

", "passed": false, "result": [] }, "step": "word_plus_name_with_space" }, { - "get_solution": [ - "word + ' ' + your_name" - ], - "page": "Using Variables and print()", + "get_solution": "program", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "word + ' ' + your_name" ], "response": { - "message": "", "passed": true, "result": [ { @@ -405,24 +402,24 @@ "step": "word_plus_name_with_space" }, { - "page": "Using Variables and print()", + "get_solution": "program", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "word = 'Goodbye'" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "word_assign_goodbye" }, { - "page": "Using Variables and print()", + "get_solution": "program", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "word + ' ' + your_name" ], "response": { - "message": "", "passed": true, "result": [ { @@ -434,12 +431,12 @@ "step": "goodbye_plus_name" }, { - "page": "Using Variables and print()", + "get_solution": "program", + "page": "\u4f7f\u7528\u53d8\u91cf\u548c print()", "program": [ "print(word + ' ' + your_name)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -451,7 +448,8 @@ "step": "first_print" }, { - "page": "Writing Programs", + "get_solution": "program", + "page": "\u7f16\u5199\u7a0b\u5e8f", "program": [ "word = 'Hello'", "name = 'World'", @@ -460,7 +458,6 @@ "print(word + ' ' + name)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -472,7 +469,8 @@ "step": "editor_hello_world" }, { - "page": "Storing Calculations In Variables", + "get_solution": "program", + "page": "\u5728\u53d8\u91cf\u4e2d\u5b58\u50a8\u8ba1\u7b97\u7ed3\u679c", "program": [ "word = 'Hello'", "name = 'World'", @@ -480,7 +478,6 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello World", @@ -491,7 +488,7 @@ "'Hello' + ' ' + 'World'", "Hello World", "'Hello World'", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -504,7 +501,8 @@ "step": "sentence_equals_word_plus_name" }, { - "page": "Storing Calculations In Variables", + "get_solution": "program", + "page": "\u5728\u53d8\u91cf\u4e2d\u5b58\u50a8\u8ba1\u7b97\u7ed3\u679c", "program": [ "word = 'Hello'", "name = 'World'", @@ -514,7 +512,6 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello World\nHello World", @@ -522,7 +519,7 @@ "Hello World\nHello World", "Hello World\nGoodbye World", "Goodbye World\nGoodbye World", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -535,13 +532,13 @@ "step": "sentence_doesnt_change" }, { - "page": "Introducing For Loops", + "get_solution": "program", + "page": "\u4ecb\u7ecd For \u5faa\u73af", "program": [ "name = 'World'", "for character in name: print(character)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -553,17 +550,18 @@ "step": "first_for_loop" }, { - "page": "Indentation", + "get_solution": "program", + "page": "\u7f29\u8fdb", "program": [ "for character in name:", "print(character)" ], "response": { - "message": "", "passed": true, "result": [ { - "text": " print(character)\n ^\nIndentationError: expected an indented block\nat line 2\n\nAn `IndentationError` occurs when a given line of code is\nnot indented (aligned vertically with other lines) as expected.\n\nLine `2` identified above was expected to begin a new indented block.\n\n\n", + "friendly": "

An IndentationError occurs when a given line of code is\nnot indented (aligned vertically with other lines) as expected.

\n

Line 2 identified above was expected to begin a new indented block.

", + "text": " print(character)\n ^^^^^\nIndentationError: expected an indented block after 'for' statement on line 1\n\u5728\u7b2c 2\n", "type": "syntax_error" } ] @@ -571,7 +569,8 @@ "step": "missing_indentation" }, { - "page": "Indentation", + "get_solution": "program", + "page": "\u7f29\u8fdb", "program": [ "name = 'World'", "", @@ -580,7 +579,6 @@ " print('---')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -592,7 +590,8 @@ "step": "two_indented_lines" }, { - "page": "Indentation", + "get_solution": "program", + "page": "\u7f29\u8fdb", "program": [ "name = 'World'", "", @@ -601,7 +600,6 @@ "print('---')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -613,18 +611,19 @@ "step": "one_indented_line" }, { - "page": "Indentation", + "get_solution": "program", + "page": "\u7f29\u8fdb", "program": [ "for character in name:", " print(character)", " print('---')" ], "response": { - "message": "", "passed": true, "result": [ { - "text": " print('---')\n ^\nIndentationError: unindent does not match any outer indentation level\nat line 3\n\nAn `IndentationError` occurs when a given line of code is\nnot indented (aligned vertically with other lines) as expected.\n\nLine `3` identified above is less indented than expected.\n\n\n", + "friendly": "

An IndentationError occurs when a given line of code is\nnot indented (aligned vertically with other lines) as expected.

\n

Line 3 identified above is less indented than expected.

", + "text": " print('---')\n ^\nIndentationError: unindent does not match any outer indentation level\n\u5728\u7b2c 3\n", "type": "syntax_error" } ] @@ -636,14 +635,13 @@ "for character in name:", " print('---' + character)" ], - "page": "Basic For Loop Exercises", + "page": "\u57fa\u7840 for \u5faa\u73af\u7ec3\u4e60", "program": [ "name = 'World'", "for character in name:", " print('---' + character)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -659,14 +657,13 @@ "for _ in name:", " print(name)" ], - "page": "Basic For Loop Exercises", + "page": "\u57fa\u7840 for \u5faa\u73af\u7ec3\u4e60", "program": [ "name = 'World'", "for _ in name:", " print(name)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -678,7 +675,8 @@ "step": "loop_exercise_2" }, { - "page": "Building Up Strings", + "get_solution": "program", + "page": "\u6784\u5efa\u5b57\u7b26\u4e32", "program": [ "hello = 'Hello'", "print(hello)", @@ -686,7 +684,6 @@ "print(hello)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello\nHello!", @@ -694,7 +691,7 @@ "Hello\nHello", "Hello\nHello!", "Hello!\nHello!", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -707,7 +704,8 @@ "step": "hello_plus_equals" }, { - "page": "Building Up Strings", + "get_solution": "program", + "page": "\u6784\u5efa\u5b57\u7b26\u4e32", "program": [ "name = 'World'", "line = '-'", @@ -716,7 +714,6 @@ " print(line)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "-W\n-Wo\n-Wor\n-Worl\n-World", @@ -729,7 +726,7 @@ "-World\n-Worl\n-Wor\n-Wo\n-W", "-World\n-World\n-World\n-World\n-World", "-World\n--World\n---World\n----World\n-----World", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -742,7 +739,8 @@ "step": "name_triangle" }, { - "page": "Building Up Strings", + "get_solution": "program", + "page": "\u6784\u5efa\u5b57\u7b26\u4e32", "program": [ "name = 'World'", "line = '-'", @@ -751,7 +749,6 @@ " line = line + char" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "-\n-W\n-Wo\n-Wor\n-Worl", @@ -759,7 +756,7 @@ "-W\n-Wo\n-Wor\n-Worl\n-World", "-Wo\n-Wor\n-Worl\n-World", "-\n-W\n-Wo\n-Wor\n-Worl", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -772,12 +769,12 @@ "step": "name_triangle_missing_last_line" }, { - "page": "Building Up Strings", + "get_solution": "program", + "page": "\u6784\u5efa\u5b57\u7b26\u4e32", "program": [ "'' + '' + ''" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "''", @@ -791,7 +788,7 @@ "'' '' ''", "' '' '' '", "++", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -810,7 +807,7 @@ " line = line + char", " print(line)" ], - "page": "Building Up Strings", + "page": "\u6784\u5efa\u5b57\u7b26\u4e32", "program": [ "name = 'World'", "line = ''", @@ -819,7 +816,6 @@ " print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -837,7 +833,7 @@ " line = line + char + ' '", " print(line)" ], - "page": "Building Up Strings Exercises", + "page": "\u5b57\u7b26\u4e32\u6784\u5efa\u7ec3\u4e60", "program": [ "name = 'World'", "line = ''", @@ -846,7 +842,6 @@ " print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -864,7 +859,7 @@ " line = char + line", " print(line)" ], - "page": "Building Up Strings Exercises", + "page": "\u5b57\u7b26\u4e32\u6784\u5efa\u7ec3\u4e60", "program": [ "name = 'World'", "line = ''", @@ -873,7 +868,6 @@ " print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -892,7 +886,7 @@ "print(name)", "print(line)" ], - "page": "Building Up Strings Exercises", + "page": "\u5b57\u7b26\u4e32\u6784\u5efa\u7ec3\u4e60", "program": [ "name = 'World'", "line = ''", @@ -902,7 +896,6 @@ "print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -923,7 +916,7 @@ "print('|' + name + '|')", "print(line)" ], - "page": "Building Up Strings Exercises", + "page": "\u5b57\u7b26\u4e32\u6784\u5efa\u7ec3\u4e60", "program": [ "name = 'World'", "line = ''", @@ -935,7 +928,6 @@ "print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -958,7 +950,7 @@ " print(char + spaces + char)", "print(line)" ], - "page": "Building Up Strings Exercises", + "page": "\u5b57\u7b26\u4e32\u6784\u5efa\u7ec3\u4e60", "program": [ "name = 'World'", "line = '+' + name + '+'", @@ -972,7 +964,6 @@ "print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -984,7 +975,7 @@ "step": "name_box_2" }, { - "page": "Building Up Strings Exercises", + "page": "\u5b57\u7b26\u4e32\u6784\u5efa\u7ec3\u4e60", "program": [ "name = 'World'", "spaces = ''", @@ -993,7 +984,7 @@ " print(spaces + char)" ], "response": { - "message": "

Almost there! You have one space too many before each letter.\nMake sure that the first time your loop calls print\nyour variable which will contain the spaces is an empty string.\nCheck the order of your code.

", + "message": "

\u5feb\u5230\u4e86\uff01\u6bcf\u4e2a\u5b57\u6bcd\u524d\u9762\u591a\u4e86\u4e00\u4e2a\u7a7a\u683c\u3002\n\u786e\u4fdd\u4f60\u7684\u5faa\u73af\u7b2c\u4e00\u6b21\u8c03\u7528 print \u65f6\uff0c\n\u5305\u542b\u7a7a\u683c\u7684\u53d8\u91cf\u662f\u4e00\u4e2a\u7a7a\u5b57\u7b26\u4e32\u3002\n\u68c0\u67e5\u4f60\u7684\u4ee3\u7801\u987a\u5e8f\u3002

", "passed": false, "result": [ { @@ -1011,7 +1002,7 @@ " print(spaces + char)", " spaces += ' '" ], - "page": "Building Up Strings Exercises", + "page": "\u5b57\u7b26\u4e32\u6784\u5efa\u7ec3\u4e60", "program": [ "name = 'World'", "spaces = ''", @@ -1020,7 +1011,6 @@ " spaces += ' '" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1032,7 +1022,8 @@ "step": "diagonal_name_bonus_challenge" }, { - "page": "Introducing If Statements", + "get_solution": "program", + "page": "\u4ecb\u7ecd if \u8bed\u53e5", "program": [ "condition = True", "print(condition)", @@ -1040,7 +1031,6 @@ "print(condition)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1052,7 +1042,8 @@ "step": "introducing_booleans" }, { - "page": "Introducing If Statements", + "get_solution": "program", + "page": "\u4ecb\u7ecd if \u8bed\u53e5", "program": [ "if True:", " print('This gets printed')", @@ -1061,7 +1052,6 @@ " print('This does not')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1073,7 +1063,8 @@ "step": "first_if_statements" }, { - "page": "Introducing If Statements", + "get_solution": "program", + "page": "\u4ecb\u7ecd if \u8bed\u53e5", "program": [ "sentence = 'Hello World'", "excited = True", @@ -1082,14 +1073,13 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello World!", "choices": [ "Hello World", "Hello World!", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -1102,7 +1092,8 @@ "step": "excited_example" }, { - "page": "Introducing If Statements", + "get_solution": "program", + "page": "\u4ecb\u7ecd if \u8bed\u53e5", "program": [ "sentence = 'Hello World'", "excited = False", @@ -1111,14 +1102,13 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello World", "choices": [ "Hello World", "Hello World!", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -1138,7 +1128,7 @@ " sentence += '?'", "print(sentence)" ], - "page": "Introducing If Statements", + "page": "\u4ecb\u7ecd if \u8bed\u53e5", "program": [ "sentence = 'Hello'", "excited = True", @@ -1150,7 +1140,6 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1162,7 +1151,8 @@ "step": "excited_confused_exercise" }, { - "page": "Combining Compound Statements", + "get_solution": "program", + "page": "\u7ec4\u5408\u590d\u5408\u8bed\u53e5", "program": [ "sentence = 'Hello World'", "excited = True", @@ -1176,7 +1166,6 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "H!e!l!l!o! !W!o!r!l!d!", @@ -1190,7 +1179,7 @@ "!Hello World!", "H!e!l!l!o! !W!o!r!l!d!", "!H!e!l!l!o! !W!o!r!l!d", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -1203,7 +1192,8 @@ "step": "for_inside_if" }, { - "page": "Understanding Programs With snoop", + "get_solution": "program", + "page": "\u4f7f\u7528 snoop \u7406\u89e3\u7a0b\u5e8f", "program": [ "sentence = 'Hello World'", "", @@ -1217,7 +1207,6 @@ "print(new_sentence)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "ello World", @@ -1227,7 +1216,7 @@ "Hello Worl", "H", "d", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -1240,7 +1229,8 @@ "step": "print_tail" }, { - "page": "Understanding Programs With snoop", + "get_solution": "program", + "page": "\u4f7f\u7528 snoop \u7406\u89e3\u7a0b\u5e8f", "program": [ "sentence = 'Hello World'", "", @@ -1254,208 +1244,43 @@ "print(new_sentence)" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | sentence \u001b[38;5;197m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mFalse\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 4\u001b[0m | new_sentence \u001b[38;5;197m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m'\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mH\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mel\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mell\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mW\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello W\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mr\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wor\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | sentence \u001b[38;5;204m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mFalse\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 4\u001b[0m | new_sentence \u001b[38;5;204m=\u001b[39m \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mH\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186me\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Worl\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mel\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mell\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186m \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello \u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186md\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mW\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello W\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wo\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 7\u001b[0m | new_sentence \u001b[38;5;197m+\u001b[39m\u001b[38;5;197m=\u001b[39m char\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mr\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Wor\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186ml\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello Worl\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | include \u001b[38;5;197m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m...... char = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186md\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | \u001b[38;5;81mif\u001b[39m include:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 7\u001b[0m | new_sentence \u001b[38;5;204m+\u001b[39m\u001b[38;5;204m=\u001b[39m char\n\u001b[38;5;245m \u001b[0m.............. new_sentence = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mello World\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | include \u001b[38;5;204m=\u001b[39m \u001b[38;5;81mTrue\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;204min\u001b[39m sentence:\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 10\u001b[0m | print(new_sentence)\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mfor\u001b[39m char \u001b[38;5;197min\u001b[39m sentence:\n", + "text": "ello World", "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 10\u001b[0m | print(new_sentence)\n", + "text": "\n", "type": "stdout" }, { - "text": "ello World\n", - "type": "stdout" + "text": "", + "type": "snoop" } ] }, @@ -1472,7 +1297,7 @@ "", "print(new_sentence)" ], - "page": "Understanding Programs With snoop", + "page": "\u4f7f\u7528 snoop \u7406\u89e3\u7a0b\u5e8f", "program": [ "sentence = 'Hello there'", "include = True", @@ -1485,7 +1310,6 @@ "print(new_sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1497,7 +1321,8 @@ "step": "print_first_character" }, { - "page": "if and else", + "get_solution": "program", + "page": "if \u548c else", "program": [ "condition = True", "if condition:", @@ -1506,7 +1331,6 @@ " print('No')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1518,7 +1342,8 @@ "step": "first_if_else" }, { - "page": "if and else", + "get_solution": "program", + "page": "if \u548c else", "program": [ "condition = False", "if condition:", @@ -1527,7 +1352,6 @@ " print('No')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1539,7 +1363,8 @@ "step": "first_if_else_false" }, { - "page": "if and else", + "get_solution": "program", + "page": "if \u548c else", "program": [ "sentence = 'Hello World'", "excited = True", @@ -1550,7 +1375,6 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1562,7 +1386,8 @@ "step": "if_upper_else_lower" }, { - "page": "if and else", + "get_solution": "program", + "page": "if \u548c else", "program": [ "sentence = 'Hello World'", "excited = False", @@ -1573,7 +1398,6 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1585,7 +1409,8 @@ "step": "if_upper_else_lower_false" }, { - "page": "if and else", + "get_solution": "program", + "page": "if \u548c else", "program": [ "sentence = 'Hello World'", "excited = False", @@ -1597,14 +1422,13 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "prediction": { - "answer": "Error", + "answer": "\u9519\u8bef", "choices": [ "Hello World", "Hello World!", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -1620,11 +1444,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 6, "lines": [ { - "content": "sentence += char", "is_current": true, "lineno": 6, + "text": "sentence += char", "type": "line" } ], @@ -1648,7 +1474,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 6, in ", + " File \"/my_program.py\", line 6, in ", " 5 | char = '!'", "--> 6 | sentence += char", " ^^^^", @@ -1664,7 +1490,16 @@ "step": "undefined_char" }, { - "page": "if and else", + "get_solution": [ + "if excited:", + " char = '!'", + "else:", + " char = '.'", + "sentence += char", + "", + "print(sentence)" + ], + "page": "if \u548c else", "program": [ "sentence = 'Hello there'", "excited = True", @@ -1677,7 +1512,6 @@ "print(sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1702,7 +1536,7 @@ "", "print(new_sentence)" ], - "page": "if and else", + "page": "if \u548c else", "program": [ "sentence = 'HELLO THERE'", "upper = True", @@ -1718,7 +1552,6 @@ "print(new_sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1744,7 +1577,7 @@ "", "print(new_sentence)" ], - "page": "if and else", + "page": "if \u548c else", "program": [ "sentence = 'One more exercise, and then you can relax.'", "upper = True", @@ -1761,7 +1594,6 @@ "print(new_sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1773,14 +1605,14 @@ "step": "spongebob" }, { - "page": "The Equality Operator", + "get_solution": "program", + "page": "\u7b49\u53f7\u64cd\u4f5c\u7b26", "program": [ "print(1 + 2 == 3)", "print(4 + 5 == 6)", "print('ab' + 'c' == 'a' + 'bc')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1792,16 +1624,17 @@ "step": "introducing_equality" }, { - "page": "The Equality Operator", + "get_solution": "program", + "page": "\u7b49\u53f7\u64cd\u4f5c\u7b26", "program": [ "print(1 + 2 = 3)" ], "response": { - "message": "", "passed": true, "result": [ { - "text": " print(1 + 2 = 3)\n ^\nSyntaxError: expression cannot contain assignment, perhaps you meant \"==\"?\nat line 1\n\nA `SyntaxError` occurs when Python cannot understand your code.\n\nYou likely called a function with a named argument:\n\n a_function(invalid=something) \n\nwhere `invalid` is not a valid variable name in Python\neither because it starts with a number, or is a string,\nor contains a period, etc.\n\n\n", + "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

You likely called a function with a named argument:

\n
a_function(invalid=something)\n
\n

where invalid is not a valid variable name in Python\neither because it starts with a number, or is a string,\nor contains a period, etc.

", + "text": " print(1 + 2 = 3)\n ^^^^^^^\nSyntaxError: expression cannot contain assignment, perhaps you meant \"==\"?\n\u5728\u7b2c 1\n", "type": "syntax_error" } ] @@ -1809,7 +1642,8 @@ "step": "equality_vs_assignment" }, { - "page": "The Equality Operator", + "get_solution": "program", + "page": "\u7b49\u53f7\u64cd\u4f5c\u7b26", "program": [ "name = 'kesha'", "new_name = ''", @@ -1821,7 +1655,6 @@ "print(new_name)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1846,7 +1679,7 @@ "", "print(new_name)" ], - "page": "The Equality Operator", + "page": "\u7b49\u53f7\u64cd\u4f5c\u7b26", "program": [ "name = 'kesha'", "new_name = ''", @@ -1862,7 +1695,6 @@ "print(new_name)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1874,7 +1706,8 @@ "step": "if_equals_replacing_characters_exercise" }, { - "page": "Introducing elif", + "get_solution": "program", + "page": "\u4ecb\u7ecd elif", "program": [ "dna = 'AGTAGCGTC'", "opposite_dna = ''", @@ -1892,7 +1725,6 @@ "print(opposite_dna)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1921,7 +1753,7 @@ "", "print(opposite_dna)" ], - "page": "Introducing elif", + "page": "\u4ecb\u7ecd elif", "program": [ "dna = 'AGTAGCGTCCTTAGTTACAGGATGGCTTAT'", "opposite_dna = ''", @@ -1941,7 +1773,6 @@ "print(opposite_dna)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1953,7 +1784,8 @@ "step": "dna_example_with_else" }, { - "page": "Introducing elif", + "get_solution": "program", + "page": "\u4ecb\u7ecd elif", "program": [ "dna = 'AGTAGCGTC'", "opposite_dna = ''", @@ -1971,7 +1803,6 @@ "print(opposite_dna)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -1983,13 +1814,21 @@ "step": "dna_example_with_elif" }, { - "page": "Other Comparison Operators", + "get_solution": "program", + "page": "\u5176\u4ed6\u6bd4\u8f83\u8fd0\u7b97\u7b26", "program": [ "1 != 2" ], "response": { - "message": "", "passed": true, + "prediction": { + "answer": "True", + "choices": [ + "True", + "False", + "\u9519\u8bef" + ] + }, "result": [ { "text": "True\n", @@ -2000,7 +1839,8 @@ "step": "try_not_equals" }, { - "page": "Other Comparison Operators", + "get_solution": "program", + "page": "\u5176\u4ed6\u6bd4\u8f83\u8fd0\u7b97\u7b26", "program": [ "sentence = 'The e key on my keyboard is broken'", "new_sentence = ''", @@ -2010,7 +1850,6 @@ "print(new_sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2022,15 +1861,12 @@ "step": "brokn_kyboard" }, { - "get_solution": [ - "1 < 2" - ], - "page": "Other Comparison Operators", + "get_solution": "program", + "page": "\u5176\u4ed6\u6bd4\u8f83\u8fd0\u7b97\u7b26", "program": [ "1 < 2" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2042,15 +1878,12 @@ "step": "introducing_less_than" }, { - "get_solution": [ - "'1' < '2'" - ], - "page": "Other Comparison Operators", + "get_solution": "program", + "page": "\u5176\u4ed6\u6bd4\u8f83\u8fd0\u7b97\u7b26", "program": [ "'1' < '2'" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2062,7 +1895,8 @@ "step": "comparing_strings" }, { - "page": "Other Comparison Operators", + "get_solution": "program", + "page": "\u5176\u4ed6\u6bd4\u8f83\u8fd0\u7b97\u7b26", "program": [ "percentage = 73", "", @@ -2078,7 +1912,6 @@ "print(grade)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "B", @@ -2087,7 +1920,7 @@ "C", "B", "A", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -2113,7 +1946,7 @@ " first = x3", "print(first)" ], - "page": "Other Comparison Operators", + "page": "\u5176\u4ed6\u6bd4\u8f83\u8fd0\u7b97\u7b26", "program": [ "x1 = 1", "x2 = 2", @@ -2131,7 +1964,6 @@ "print(first)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2143,7 +1975,8 @@ "step": "min_three_exercise" }, { - "page": "Introducing Lists", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5217\u8868", "program": [ "words = ['This', 'is', 'a', 'list']", "", @@ -2151,7 +1984,6 @@ " print(word)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2163,14 +1995,14 @@ "step": "first_list" }, { - "page": "Introducing Lists", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5217\u8868", "program": [ "x = 1", "things = ['Hello', x, x + 3]", "print(things)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2182,7 +2014,8 @@ "step": "can_contain_anything" }, { - "page": "Introducing Lists", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5217\u8868", "program": [ "numbers = [3, 1, 4, 1, 5, 9]", "", @@ -2193,7 +2026,6 @@ "print(total)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2212,7 +2044,7 @@ "", "print(total)" ], - "page": "Introducing Lists", + "page": "\u4ecb\u7ecd\u5217\u8868", "program": [ "words = ['This', 'is', 'a', 'list']", "total = ''", @@ -2222,7 +2054,6 @@ "print(total)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2246,7 +2077,7 @@ "", "print(total)" ], - "page": "Introducing Lists", + "page": "\u4ecb\u7ecd\u5217\u8868", "program": [ "words = ['This', 'is', 'a', 'list']", "separator = ' - '", @@ -2262,7 +2093,6 @@ "print(total)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2280,7 +2110,7 @@ " double += [number * 2]", "print(double)" ], - "page": "Building New Lists", + "page": "\u521b\u5efa\u65b0\u5217\u8868", "program": [ "numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]", "double = []", @@ -2289,7 +2119,6 @@ "print(double)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2308,7 +2137,7 @@ " big_numbers.append(number)", "print(big_numbers)" ], - "page": "Building New Lists", + "page": "\u521b\u5efa\u65b0\u5217\u8868", "program": [ "numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5]", "big_numbers = []", @@ -2318,7 +2147,6 @@ "print(big_numbers)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2338,7 +2166,7 @@ "", "print(found)" ], - "page": "Using break to end a loop early", + "page": "\u4f7f\u7528 break \u63d0\u524d\u7ed3\u675f\u5faa\u73af", "program": [ "things = ['This', 'is', 'a', 'list']", "thing_to_find = 'is'", @@ -2350,7 +2178,6 @@ "print(found)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2362,7 +2189,8 @@ "step": "list_contains_exercise" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u4e0a\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "words = ['This', 'is', 'a', 'list']", "", @@ -2372,7 +2200,6 @@ "print(words[3])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2384,12 +2211,12 @@ "step": "introducing_subscripting" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u4e0a\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "words[4]" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2402,11 +2229,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 1, "lines": [ { - "content": "words[4]", "is_current": true, "lineno": 1, + "text": "words[4]", "type": "line" } ], @@ -2426,7 +2255,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 1, in ", + " File \"/my_program.py\", line 1, in ", "--> 1 | words[4]", " ^^^^^^^^", "words = ['This', 'is', 'a', 'list']", @@ -2440,7 +2269,8 @@ "step": "index_error" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u4e0a\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "words = ['This', 'is', 'a', 'list']", "indices = [0, 1, 2, 3]", @@ -2450,7 +2280,6 @@ " print(words[index])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "0\nThis\n1\nis\n2\na\n3\nlist", @@ -2461,7 +2290,7 @@ "This\n0\nis\n1\na\n2\nlist\n3", "0\n1\n2\n3\nThis\nis\na\nlist", "This\nis\na\nlist\n0\n1\n2\n3", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -2474,7 +2303,8 @@ "step": "introducing_len_and_range" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u4e0a\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "words = ['This', 'is', 'a', 'list']", "indices = range(4)", @@ -2484,7 +2314,6 @@ " print(words[index])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2496,7 +2325,8 @@ "step": "range_len" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u4e0a\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "indices = range(4)", "", @@ -2506,7 +2336,6 @@ "print(indices[3])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "0\n1\n2\n3", @@ -2516,7 +2345,7 @@ "[0]\n[1]\n[2]\n[3]", "[1]\n[2]\n[3]\n[4]", "This\nis\na\nlist", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -2529,22 +2358,22 @@ "step": "printing_the_range" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u4e0a\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "indices[4]" ], "response": { - "message": "", "passed": true, "prediction": { - "answer": "Error", + "answer": "\u9519\u8bef", "choices": [ "0", "1", "2", "3", "4", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -2558,11 +2387,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 1, "lines": [ { - "content": "indices[4]", "is_current": true, "lineno": 1, + "text": "indices[4]", "type": "line" } ], @@ -2576,13 +2407,13 @@ ] } ], - "friendly": "

An IndexError occurs when you try to get an item from a list,\na tuple, or a similar object (sequence), and use an index which\ndoes not exist; typically, this happens because the index you give\nis greater than the length of the sequence.

\n

You have tried to get the item with index 4 of indices,\nrange object of length 4.\nThe valid index values of indices are integers ranging from\n-4 to 3.

", + "friendly": "

An IndexError occurs when you try to get an item from a list,\na tuple, or a similar object (sequence), and use an index which\ndoes not exist; typically, this happens because the index you give\nis greater than the length of the sequence.

\n

You have tried to get the item with index 4 of indices,\nrange object of length 4.\nThe valid index values of indices are integers ranging from\n-4 to 3.

", "tail": "" } ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 1, in ", + " File \"/my_program.py\", line 1, in ", "--> 1 | indices[4]", " ^^^^^^^^^^", "indices = range(0, 4)", @@ -2596,12 +2427,12 @@ "step": "indices_out_of_bounds" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u4e0a\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "range(4)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2613,12 +2444,12 @@ "step": "range_almost_the_same_as_list" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u4e0a\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "list(range(4))" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[0, 1, 2, 3]", @@ -2630,7 +2461,7 @@ "range(0, 1, 2, 3)", "(0, 1, 2, 3)", "[0, 1, 2, 3]", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -2643,13 +2474,13 @@ "step": "range_versus_list" }, { - "page": "Getting elements at a position, range(), and len()", + "get_solution": "program", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u4e0a\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "words = ['This', 'is', 'a', 'list']", "print(len(words))" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "4", @@ -2660,7 +2491,7 @@ "3", "4", "5", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -2676,13 +2507,12 @@ "get_solution": [ "print(words[len(words) - 1])" ], - "page": "Getting elements at a position, range(), and len()", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u4e0a\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "words = ['Python']", "print(words[len(words) - 1])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2699,7 +2529,7 @@ " print(index)", " print(words[index])" ], - "page": "Getting elements at a position, range(), and len()", + "page": "\u83b7\u53d6\u4f4d\u7f6e\u4e0a\u7684\u5143\u7d20\uff0crange() \u548c len()", "program": [ "words = ['Python']", "for index in range(len(words)):", @@ -2707,7 +2537,6 @@ " print(words[index])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2719,7 +2548,7 @@ "step": "print_indices_and_words" }, { - "page": "Exercises with range() and len()", + "page": "\u4f7f\u7528 range() \u548c len() \u7684\u7ec3\u4e60", "program": [ "things = ['on', 'the', 'way', 'to', 'the', 'store']", "to_find = 'the'", @@ -2728,7 +2557,7 @@ " print(i)" ], "response": { - "message": "

You're almost there! However, this prints all the indices,\nnot just the first one.

", + "message": "

\u4f60\u5feb\u5230\u4e86\uff01\u4f46\u662f\uff0c\u8fd9\u4f1a\u6253\u5370\u6240\u6709\u7684\u7d22\u5f15\uff0c\n\u800c\u4e0d\u4ec5\u4ec5\u662f\u7b2c\u4e00\u4e2a\u3002

", "passed": false, "result": [ { @@ -2740,7 +2569,7 @@ "step": "index_exercise" }, { - "page": "Exercises with range() and len()", + "page": "\u4f7f\u7528 range() \u548c len() \u7684\u7ec3\u4e60", "program": [ "things = ['on', 'the', 'way', 'to', 'the', 'store']", "to_find = 'the'", @@ -2751,7 +2580,7 @@ "print(answer)" ], "response": { - "message": "

You're almost there! However, this prints the last index,\nnot the first one.

", + "message": "

\u4f60\u5feb\u5230\u4e86\uff01\u4f46\u662f\uff0c\u8fd9\u4f1a\u6253\u5370 \u6700\u540e \u4e00\u4e2a\u7d22\u5f15\uff0c\n\u800c\u4e0d\u662f\u7b2c\u4e00\u4e2a\u3002

", "passed": false, "result": [ { @@ -2769,7 +2598,7 @@ " print(i)", " break" ], - "page": "Exercises with range() and len()", + "page": "\u4f7f\u7528 range() \u548c len() \u7684\u7ec3\u4e60", "program": [ "things = ['on', 'the', 'way', 'to', 'the', 'store']", "to_find = 'the'", @@ -2779,7 +2608,6 @@ " break" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2797,7 +2625,7 @@ " char2 = string2[i]", " print(char1 + ' ' + char2)" ], - "page": "Exercises with range() and len()", + "page": "\u4f7f\u7528 range() \u548c len() \u7684\u7ec3\u4e60", "program": [ "string1 = 'Hello'", "string2 = 'World'", @@ -2807,7 +2635,6 @@ " print(char1 + ' ' + char2)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2841,7 +2668,7 @@ "", " print(char1 + ' ' + char2)" ], - "page": "Exercises with range() and len()", + "page": "\u4f7f\u7528 range() \u548c len() \u7684\u7ec3\u4e60", "program": [ "string1 = 'Goodbye'", "string2 = 'World'", @@ -2867,7 +2694,6 @@ " print(char1 + ' ' + char2)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2879,13 +2705,13 @@ "step": "zip_longest_exercise" }, { - "page": "Terminology: Calling functions and methods", + "get_solution": "program", + "page": "\u672f\u8bed\uff1a\u8c03\u7528\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "print(len)", "print(print)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2897,12 +2723,12 @@ "step": "print_functions" }, { - "page": "Terminology: Calling functions and methods", + "get_solution": "program", + "page": "\u672f\u8bed\uff1a\u8c03\u7528\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "print(callable(len))" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2914,14 +2740,14 @@ "step": "introducing_callable" }, { - "page": "Terminology: Calling functions and methods", + "get_solution": "program", + "page": "\u672f\u8bed\uff1a\u8c03\u7528\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "f = 'a string'", "print(callable(f))", "f()" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2940,11 +2766,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 3, "lines": [ { - "content": "f()", "is_current": true, "lineno": 3, + "text": "f()", "type": "line" } ], @@ -2958,13 +2786,13 @@ ] } ], - "friendly": "

A TypeError is usually caused by trying\nto combine two incompatible types of objects,\nby calling a function with the wrong type of object,\nor by trying to do an operation not allowed on a given type of object.

\n

The parenthesis () following f are interpreted\nby Python as a function call for f.\nHowever, f is not a function but an object of type str.

", + "friendly": "

A TypeError is usually caused by trying\nto combine two incompatible types of objects,\nby calling a function with the wrong type of object,\nor by trying to do an operation not allowed on a given type of object.

\n

Because of the surrounding parenthesis, ` \nis interpreted by Python as indicating a function call forf, which is an object of typestr`\nwhich cannot be called.

", "tail": "" } ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 3, in ", + " File \"/my_program.py\", line 3, in ", " 2 | print(callable(f))", "--> 3 | f()", " ^^^", @@ -2979,7 +2807,8 @@ "step": "not_callable" }, { - "page": "Terminology: Calling functions and methods", + "get_solution": "program", + "page": "\u672f\u8bed\uff1a\u8c03\u7528\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "things = [1, 2, 3]", "length = len(things)", @@ -2987,7 +2816,6 @@ "print(printed)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -2999,13 +2827,13 @@ "step": "print_returns_none" }, { - "page": "Terminology: Calling functions and methods", + "get_solution": "program", + "page": "\u672f\u8bed\uff1a\u8c03\u7528\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "things = print([1, 2, 3])", "length = len(things)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3024,11 +2852,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 2, "lines": [ { - "content": "length = len(things)", "is_current": true, "lineno": 2, + "text": "length = len(things)", "type": "line" } ], @@ -3048,7 +2878,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 2, in ", + " File \"/my_program.py\", line 2, in ", " 1 | things = print([1, 2, 3])", "--> 2 | length = len(things)", " ^^^^^^^^^^^", @@ -3063,14 +2893,14 @@ "step": "len_of_none" }, { - "page": "Terminology: Calling functions and methods", + "get_solution": "program", + "page": "\u672f\u8bed\uff1a\u8c03\u7528\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "word = 'Hello'", "print(word.upper)", "print(word.upper())" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3082,13 +2912,13 @@ "step": "methods_of_str" }, { - "page": "Terminology: Calling functions and methods", + "get_solution": "program", + "page": "\u672f\u8bed\uff1a\u8c03\u7528\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "word = 'Hello'", "word.append('!')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3101,11 +2931,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 2, "lines": [ { - "content": "word.append('!')", "is_current": true, "lineno": 2, + "text": "word.append('!')", "type": "line" } ], @@ -3125,7 +2957,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 2, in ", + " File \"/my_program.py\", line 2, in ", " 1 | word = 'Hello'", "--> 2 | word.append('!')", " ^^^^^^^^^^^", @@ -3140,7 +2972,8 @@ "step": "no_append_for_str" }, { - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "nums = [1, 2, 3]", "new_nums = nums + [4, 5]", @@ -3150,7 +2983,6 @@ "print(nums)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3162,14 +2994,14 @@ "step": "append_vs_concatenate" }, { - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "nums = [1, 2, 3]", "nums[1] = 9", "print(nums)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[1, 9, 3]", @@ -3180,7 +3012,7 @@ "[9, 2, 3]", "[1, 9, 3]", "[1, 2, 9]", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3193,12 +3025,12 @@ "step": "subscript_assignment_predict" }, { - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "[7, 8, 9, 8].index(8)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "1", @@ -3209,7 +3041,7 @@ "1", "2", "3", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3222,14 +3054,14 @@ "step": "index_predict_exercise" }, { - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "nums = [1, 2, 3]", "print(nums.pop(1))", "print(nums)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "2\n[1, 3]", @@ -3240,7 +3072,7 @@ "2\n[2, 3]", "1\n[2, 1, 3]", "2\n[2, 1, 3]", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3253,14 +3085,14 @@ "step": "pop_predict_exercise" }, { - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "nums = [1, 2, 3]", "nums.remove(1)", "print(nums)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[2, 3]", @@ -3271,7 +3103,7 @@ "1", "2", "3", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3284,19 +3116,14 @@ "step": "remove_predict_exercise" }, { - "get_solution": [ - "x = ['a', 'b', 'c']", - "x.append(x.pop(0))", - "print(x)" - ], - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = ['a', 'b', 'c']", "x.append(x.pop(0))", "print(x)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3308,19 +3135,14 @@ "step": "pop_remove_index_subscript_assignment" }, { - "get_solution": [ - "x = ['a', 'b', 'c']", - "x[len(x) - 1] = x[0]", - "print(x)" - ], - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = ['a', 'b', 'c']", "x[len(x) - 1] = x[0]", "print(x)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3332,19 +3154,14 @@ "step": "subscript_assignment_exercise" }, { - "get_solution": [ - "x = ['a', 'b', 'c']", - "y = x + [x[0]]", - "print(y)" - ], - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = ['a', 'b', 'c']", "y = x + [x[0]]", "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3356,19 +3173,14 @@ "step": "negative_index_concatenation_exercise" }, { - "get_solution": [ - "x = [1, 2, 0, 3]", - "x.pop(x.index(0))", - "print(x)" - ], - "page": "Functions and Methods for Lists", + "get_solution": "program", + "page": "\u5217\u8868\u7684\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = [1, 2, 0, 3]", "x.pop(x.index(0))", "print(x)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3380,12 +3192,12 @@ "step": "remove_exercise" }, { - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "sorted([2, 9, 1, 8, 5, 6])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[1, 2, 5, 6, 8, 9]", @@ -3394,7 +3206,7 @@ "[1, 8, 6, 2, 5, 9]", "[1, 2, 5, 6, 8, 9]", "[2, 9, 1, 8, 5, 6]", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3407,14 +3219,14 @@ "step": "sorted_predict_exercise" }, { - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "nums = [2, 9, 1, 8, 5, 64]", "print(7 in nums)", "print(2 in nums)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False\nTrue", @@ -3423,7 +3235,7 @@ "False\nTrue", "True\nTrue", "False\nFalse", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3436,12 +3248,12 @@ "step": "in_predict_exercise" }, { - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "sum([5, 3, 4])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "12", @@ -3449,7 +3261,7 @@ "10", "12", "7", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3462,12 +3274,12 @@ "step": "sum_predict_exercise" }, { - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "[1, 2, 3, 2, 7, 2, 5].count(2)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "3", @@ -3476,7 +3288,7 @@ "1", "2", "3", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -3489,19 +3301,14 @@ "step": "count_predict_exercise" }, { - "get_solution": [ - "x = [1, 2, 0, 3]", - "y = x.count(1) > 0", - "print(y)" - ], - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = [1, 2, 0, 3]", "y = x.count(1) > 0", "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3513,19 +3320,14 @@ "step": "count_in_sorted_sum" }, { - "get_solution": [ - "x = [15, 12, -6, 3]", - "y = sum(x) / len(x)", - "print(y)" - ], - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = [15, 12, -6, 3]", "y = sum(x) / len(x)", "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3537,19 +3339,14 @@ "step": "average_exercise" }, { - "get_solution": [ - "x = 100", - "y = sum(range(x + 1))", - "print(y)" - ], - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = 100", "y = sum(range(x + 1))", "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3561,19 +3358,14 @@ "step": "sum_range_exercise" }, { - "get_solution": [ - "x = [12, -6, 2, -1, 3]", - "y = sorted(x)[1]", - "print(y)" - ], - "page": "More List Functions and Methods", + "get_solution": "program", + "page": "\u66f4\u591a\u5217\u8868\u51fd\u6570\u548c\u65b9\u6cd5", "program": [ "x = [12, -6, 2, -1, 3]", "y = sorted(x)[1]", "print(y)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3585,12 +3377,12 @@ "step": "second_smallest_in_list_exercise" }, { - "page": "String Methods and Immutability", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u65b9\u6cd5\u4e0e\u4e0d\u53ef\u53d8\u6027", "program": [ "print('the' in 'feed the dog and the cat')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3602,14 +3394,14 @@ "step": "string_in_step" }, { - "page": "String Methods and Immutability", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u65b9\u6cd5\u4e0e\u4e0d\u53ef\u53d8\u6027", "program": [ "string = 'feed the dog and the cat'", "print(string.count('the'))", "print(string.index('the'))" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3621,12 +3413,12 @@ "step": "string_count_index" }, { - "page": "String Methods and Immutability", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u65b9\u6cd5\u4e0e\u4e0d\u53ef\u53d8\u6027", "program": [ "'Python'.append(' is cool!')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3639,11 +3431,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 1, "lines": [ { - "content": "'Python'.append(' is cool!')", "is_current": true, "lineno": 1, + "text": "'Python'.append(' is cool!')", "type": "line" } ], @@ -3658,7 +3452,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 1, in ", + " File \"/my_program.py\", line 1, in ", "--> 1 | 'Python'.append(' is cool!')", " ^^^^^^^^^^^^^^^", "", @@ -3671,7 +3465,8 @@ "step": "mutation_string_append" }, { - "page": "String Methods and Immutability", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u65b9\u6cd5\u4e0e\u4e0d\u53ef\u53d8\u6027", "program": [ "sentence = \"Python rocks!\"", "new_sentence = sentence.upper()", @@ -3679,7 +3474,6 @@ "print(new_sentence)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3691,15 +3485,12 @@ "step": "string_lower_upper" }, { - "get_solution": [ - "max([21, 55, 4, 91, 62, 49])" - ], - "page": "How to Find Information with Google, and more", + "get_solution": "program", + "page": "\u5982\u4f55\u4f7f\u7528 Google \u67e5\u627e\u4fe1\u606f\uff0c\u4ee5\u53ca\u66f4\u591a", "program": [ "max([21, 55, 4, 91, 62, 49])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3711,19 +3502,14 @@ "step": "sum_list" }, { - "get_solution": [ - "nums = [1, 2, 3, 4, 5]", - "nums.insert(2, 9)", - "print(nums)" - ], - "page": "How to Find Information with Google, and more", + "get_solution": "program", + "page": "\u5982\u4f55\u4f7f\u7528 Google \u67e5\u627e\u4fe1\u606f\uff0c\u4ee5\u53ca\u66f4\u591a", "program": [ "nums = [1, 2, 3, 4, 5]", "nums.insert(2, 9)", "print(nums)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3735,16 +3521,16 @@ "step": "list_insert" }, { - "page": "How to Find Information with Google, and more", + "get_solution": "program", + "page": "\u5982\u4f55\u4f7f\u7528 Google \u67e5\u627e\u4fe1\u606f\uff0c\u4ee5\u53ca\u66f4\u591a", "program": [ "dir([])" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']\n", + "text": "['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']\n", "type": "stdout" } ] @@ -3752,7 +3538,8 @@ "step": "dir_list" }, { - "page": "Understanding Programs With Python Tutor", + "get_solution": "program", + "page": "\u4f7f\u7528 Python Tutor \u7406\u89e3\u7a0b\u5e8f", "program": [ "all_numbers = [2, 4, 8, 1, 9, 7]", "", @@ -3769,7 +3556,6 @@ "print(big_numbers)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3781,7 +3567,8 @@ "step": "run_with_python_tutor" }, { - "page": "== vs is, and Having Multiple Names for One Value", + "get_solution": "program", + "page": "== \u4e0e is\uff0c\u4ee5\u53ca\u4e00\u4e2a\u503c\u7684\u591a\u4e2a\u540d\u79f0", "program": [ "list1 = [1, 2, 3]", "list2 = [1, 2, 3]", @@ -3798,7 +3585,6 @@ "print(list2)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3810,7 +3596,8 @@ "step": "two_separate_lists" }, { - "page": "== vs is, and Having Multiple Names for One Value", + "get_solution": "program", + "page": "== \u4e0e is\uff0c\u4ee5\u53ca\u4e00\u4e2a\u503c\u7684\u591a\u4e2a\u540d\u79f0", "program": [ "list1 = [1, 2, 3]", "list2 = list1", @@ -3827,7 +3614,6 @@ "print(list2)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3839,7 +3625,8 @@ "step": "same_list" }, { - "page": "Modifying While Iterating", + "get_solution": "program", + "page": "\u5728\u8fed\u4ee3\u65f6\u4fee\u6539", "program": [ "numbers = [10, 7, 8, 3, 12, 15]", "for i in range(len(numbers)):", @@ -3849,7 +3636,6 @@ "print(numbers)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3862,11 +3648,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 3, "lines": [ { - "content": "number = numbers[i]", "is_current": true, "lineno": 3, + "text": "number = numbers[i]", "type": "line" } ], @@ -3906,7 +3694,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 3, in ", + " File \"/my_program.py\", line 3, in ", " 2 | for i in range(len(numbers)):", "--> 3 | number = numbers[i]", " ^^^^^^^^^^", @@ -3926,7 +3714,8 @@ "step": "run_broken_with_python_tutor" }, { - "page": "Modifying While Iterating", + "get_solution": "program", + "page": "\u5728\u8fed\u4ee3\u65f6\u4fee\u6539", "program": [ "numbers = [10, 7, 8, 3, 12, 15]", "for number in numbers:", @@ -3935,7 +3724,6 @@ "print(numbers)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3947,7 +3735,8 @@ "step": "remove_instead_of_pop" }, { - "page": "Modifying While Iterating", + "get_solution": "program", + "page": "\u5728\u8fed\u4ee3\u65f6\u4fee\u6539", "program": [ "numbers = [10, 7, 8, 3, 12, 15]", "for number in numbers.copy():", @@ -3956,7 +3745,6 @@ "print(numbers)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3968,7 +3756,8 @@ "step": "make_copy" }, { - "page": "Modifying While Iterating", + "get_solution": "program", + "page": "\u5728\u8fed\u4ee3\u65f6\u4fee\u6539", "program": [ "numbers = [10, 7, 8, 3, 12, 15]", "big_numbers = numbers.copy()", @@ -3979,7 +3768,6 @@ "print(big_numbers)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -3991,7 +3779,8 @@ "step": "make_copy2" }, { - "page": "Modifying While Iterating", + "get_solution": "program", + "page": "\u5728\u8fed\u4ee3\u65f6\u4fee\u6539", "program": [ "numbers = [10, 7, 8, 3, 12, 15]", "big_numbers = []", @@ -4002,7 +3791,6 @@ "print(big_numbers)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4014,16 +3802,17 @@ "step": "make_new_list" }, { - "page": "Single and Double Quotes in Strings", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u4e2d\u7684\u5355\u5f15\u53f7\u548c\u53cc\u5f15\u53f7", "program": [ "print('Alice's Diner')" ], "response": { - "message": "", "passed": true, "result": [ { - "text": " print('Alice's Diner')\n ^\nSyntaxError: invalid syntax\nat line 1\n\nA `SyntaxError` occurs when Python cannot understand your code.\n\nI suspect that you were trying to use a quote character inside a string\nthat was enclosed in quotes of the same kind.\nPerhaps you should have escaped the inner quote character:\n\n print('Alice\\'s Diner')\n ^^\n\n\n", + "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

You started writing a string with a single or double quote\nbut never ended the string with another quote on that line.

", + "text": " print('Alice's Diner')\n ^\nSyntaxError: unterminated string literal (detected at line 1)\n\u5728\u7b2c 1\n", "type": "syntax_error" } ] @@ -4031,12 +3820,12 @@ "step": "single_quotes_apostrophe" }, { - "page": "Single and Double Quotes in Strings", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u4e2d\u7684\u5355\u5f15\u53f7\u548c\u53cc\u5f15\u53f7", "program": [ "print(\"Alice's Diner\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4048,19 +3837,19 @@ "step": "double_quotes" }, { - "page": "Single and Double Quotes in Strings", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u4e2d\u7684\u5355\u5f15\u53f7\u548c\u53cc\u5f15\u53f7", "program": [ "'Alice' == \"Alice\"" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -4073,15 +3862,12 @@ "step": "single_double_quotes_equal" }, { - "get_solution": [ - "print(\"Special cases aren't special enough to break the rules.\")" - ], - "page": "Single and Double Quotes in Strings", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u4e2d\u7684\u5355\u5f15\u53f7\u548c\u53cc\u5f15\u53f7", "program": [ "print(\"Special cases aren't special enough to break the rules.\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4093,15 +3879,12 @@ "step": "double_quote_exercise" }, { - "get_solution": [ - "print('\"Talk is cheap. Show me the code.\" - Linus Torvalds')" - ], - "page": "Single and Double Quotes in Strings", + "get_solution": "program", + "page": "\u5b57\u7b26\u4e32\u4e2d\u7684\u5355\u5f15\u53f7\u548c\u53cc\u5f15\u53f7", "program": [ "print('\"Talk is cheap. Show me the code.\" - Linus Torvalds')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4113,6 +3896,7 @@ "step": "single_quote_exercise" }, { + "get_solution": "program", "page": "f-strings", "program": [ "name = \"Alice\"", @@ -4121,7 +3905,6 @@ "print(f\"{name} went to {meal} with {friend}.\")" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Alice went to lunch with Bob.", @@ -4135,7 +3918,7 @@ "'Alice' went to 'lunch' with 'Bob'.", "\"Alice went to lunch with Bob.\"", "Alice went to lunch with Bob.", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -4148,6 +3931,7 @@ "step": "introduce_f_strings" }, { + "get_solution": "program", "page": "f-strings", "program": [ "name = \"Alice\"", @@ -4155,16 +3939,15 @@ "print(\"Hello \" + name + \". You are \" + age + \" years old.\")" ], "response": { - "message": "", "passed": true, "prediction": { - "answer": "Error", + "answer": "\u9519\u8bef", "choices": [ "\"Hello \" + name + \". You are \" + age + \" years old.\"", "Hello name. You are age years old.", "Hello Alice. You are 20 years old.", "Hello 'Alice'. You are 20 years old.", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -4178,11 +3961,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 3, "lines": [ { - "content": "print("Hello " + name + ". You are " + age + " years old.")", "is_current": true, "lineno": 3, + "text": "print("Hello " + name + ". You are " + age + " years old.")", "type": "line" } ], @@ -4214,7 +3999,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 3, in ", + " File \"/my_program.py\", line 3, in ", " 2 | age = 20", "--> 3 | print(\"Hello \" + name + \". You are \" + age + \" years old.\")", " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^", @@ -4232,11 +4017,7 @@ "step": "concatenate_string_number" }, { - "get_solution": [ - "name = \"Alice\"", - "age = 20", - "print(f'Hello {name}. You are {age} years old.')" - ], + "get_solution": "program", "page": "f-strings", "program": [ "name = \"Alice\"", @@ -4244,7 +4025,6 @@ "print(f'Hello {name}. You are {age} years old.')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4256,12 +4036,12 @@ "step": "basic_f_string_exercise" }, { + "get_solution": "program", "page": "f-strings", "program": [ "f\"2 * 3 + 4 is equal to {2 * 3 + 4}\"" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4278,15 +4058,14 @@ ], "page": "f-strings", "program": [ - "people = ['eODoUwNzS', 'ofHBEzZxs', 'zwTrQA', 'LDaOKmpHU', 'HCMLTt', 'NbRmEjaoyD']", + "people = ['Alice', 'Bob', 'Charlie']", "print(f\"There are {len(people)} people waiting, the first one's name is {people[0]}.\")" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "There are 6 people waiting, the first one's name is eODoUwNzS.\n", + "text": "There are 3 people waiting, the first one's name is Alice.\n", "type": "stdout" } ] @@ -4294,7 +4073,8 @@ "step": "fix_broken_program" }, { - "page": "Introducing Nested Loops", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "for letter in \"ABC\":", " print(letter)", @@ -4303,7 +4083,6 @@ " print('---')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "A\nA 0\nA 1\nA 2\nA 3\n---\nB\nB 0\nB 1\nB 2\nB 3\n---\nC\nC 0\nC 1\nC 2\nC 3\n---", @@ -4312,7 +4091,7 @@ "A\nA 0\nA 1\nA 2\nA 3\n---\nB\nB 0\nB 1\nB 2\nB 3\n---\nC\nC 0\nC 1\nC 2\nC 3\n---", "A 1\nA 2\nA 3\nA 4\n---\nB 1\nB 2\nB 3\nB 4\n---\nC 1\nC 2\nC 3\nC 4\n---", "A\nB\nC\n---\nA 0\nB 0\nC 0\n---\nA 1\nB 1\nC 1\n---\nA 2\nB 2\nC 2\n---\nA 3\nB 3\nC 3", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -4325,12 +4104,12 @@ "step": "first_nested_loop" }, { - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "print(1 + \"x\")" ], "response": { - "message": "

You can't add together strings and numbers. Use an f-string.

", + "message": "

\u4f60\u4e0d\u80fd\u5c06\u5b57\u7b26\u4e32\u548c\u6570\u5b57\u76f8\u52a0\u3002\u4f7f\u7528 f-string\u3002

", "passed": false, "result": [ { @@ -4343,11 +4122,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 1, "lines": [ { - "content": "print(1 + "x")", "is_current": true, "lineno": 1, + "text": "print(1 + "x")", "type": "line" } ], @@ -4362,7 +4143,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 1, in ", + " File \"/my_program.py\", line 1, in ", "--> 1 | print(1 + \"x\")", " ^^^^^^^", "", @@ -4375,25 +4156,25 @@ "step": "times_table_exercise" }, { - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "for left in range(12):", " for right in range(12):", " left += 1", " right += 1", " print(f'{left} x {right} = {left * right}')", - " print('----------')" + " print('---')" ], "response": { - "message": "

You added 1 to your outer loop variable at the wrong place!\nWhere should you do that instead to fix it?

", + "message": "

\u4f60\u5728\u9519\u8bef\u7684\u5730\u65b9\u5c06 1 \u52a0\u5230\u4e86\u5916\u90e8\u5faa\u73af\u53d8\u91cf\u4e0a\uff01\n\u4f60\u5e94\u8be5\u5728\u54ea\u91cc\u505a\u8fd9\u4e2a\u4ee5\u4fee\u590d\u5b83\uff1f

", "passed": false, "result": [ { - "text": "1 x 1 = 1\n2 x 2 = 4\n3 x 3 = 9\n4 x 4 = 16\n5 x 5 = 25\n6 x 6 = 36\n7 x 7 = 49\n8 x 8 = 64\n9 x 9 = 81\n10 x 10 = 100\n11 x 11 = 121\n12 x 12 = 144\n----------\n2 x 1 = 2\n3 x 2 = 6\n4 x 3 = 12\n5 x 4 = 20\n6 x 5 = 30\n7 x 6 = 42\n8 x 7 = 56\n9 x 8 = 72\n10 x 9 = 90\n11 x 10 = 110\n12 x 11 = 132\n13 x 12 = 156\n----------\n3 x 1 = 3\n4 x 2 = 8\n5 x 3 = 15\n6 x 4 = 24\n7 x 5 = 35\n8 x 6 = 48\n9 x 7 = 63\n10 x 8 = 80\n11 x 9 = 99\n12 x 10 = 120\n13 x 11 = 143\n14 x 12 = 168\n----------\n4 x 1 = 4\n5 x 2 = 10\n6 x 3 = 18\n7 x 4 = 28\n8 x 5 = 40\n9 x 6 = 54\n10 x 7 = 70\n11 x 8 = 88\n12 x 9 = 108\n13 x 10 = 130\n14 x 11 = 154\n15 x 12 = 180\n----------\n5 x 1 = 5\n6 x 2 = 12\n7 x 3 = 21\n8 x 4 = 32\n9 x 5 = 45\n10 x 6 = 60\n11 x 7 = 77\n12 x 8 = 96\n13 x 9 = 117\n14 x 10 = 140\n15 x 11 = 165\n16 x 12 = 192\n----------\n6 x 1 = 6\n7 x 2 = 14\n8 x 3 = 24\n9 x 4 = 36\n10 x 5 = 50\n11 x 6 = 66\n12 x 7 = 84\n13 x 8 = 104\n14 x 9 = 126\n15 x 10 = 150\n16 x 11 = 176\n17 x 12 = 204\n----------\n7 x 1 = 7\n8 x 2 = 16\n9 x 3 = 27\n10 x 4 = 40\n11 x 5 = 55\n12 x 6 = 72\n13 x 7 = 91", + "text": "1 x 1 = 1\n2 x 2 = 4\n3 x 3 = 9\n4 x 4 = 16\n5 x 5 = 25\n6 x 6 = 36\n7 x 7 = 49\n8 x 8 = 64\n9 x 9 = 81\n10 x 10 = 100\n11 x 11 = 121\n12 x 12 = 144\n---\n2 x 1 = 2\n3 x 2 = 6\n4 x 3 = 12\n5 x 4 = 20\n6 x 5 = 30\n7 x 6 = 42\n8 x 7 = 56\n9 x 8 = 72\n10 x 9 = 90\n11 x 10 = 110\n12 x 11 = 132\n13 x 12 = 156\n---\n3 x 1 = 3\n4 x 2 = 8\n5 x 3 = 15\n6 x 4 = 24\n7 x 5 = 35\n8 x 6 = 48\n9 x 7 = 63\n10 x 8 = 80\n11 x 9 = 99\n12 x 10 = 120\n13 x 11 = 143\n14 x 12 = 168\n---\n4 x 1 = 4\n5 x 2 = 10\n6 x 3 = 18\n7 x 4 = 28\n8 x 5 = 40\n9 x 6 = 54\n10 x 7 = 70\n11 x 8 = 88\n12 x 9 = 108\n13 x 10 = 130\n14 x 11 = 154\n15 x 12 = 180\n---\n5 x 1 = 5\n6 x 2 = 12\n7 x 3 = 21\n8 x 4 = 32\n9 x 5 = 45\n10 x 6 = 60\n11 x 7 = 77\n12 x 8 = 96\n13 x 9 = 117\n14 x 10 = 140\n15 x 11 = 165\n16 x 12 = 192\n---\n6 x 1 = 6\n7 x 2 = 14\n8 x 3 = 24\n9 x 4 = 36\n10 x 5 = 50\n11 x 6 = 66\n12 x 7 = 84\n13 x 8 = 104\n14 x 9 = 126\n15 x 10 = 150\n16 x 11 = 176\n17 x 12 = 204\n---\n7 x 1 = 7\n8 x 2 = 16\n9 x 3 = 27\n10 x 4 = 40\n11 x 5 = 55\n12 x 6 = 72\n13 x 7 = 91\n14 x 8 = 112\n15 x 9 = 135\n16 x 10 = 160\n17 x 11 = 187", "type": "stdout" }, { - "text": "\n14 x 8 = 112\n15 x 9 = 135\n16 x 10 = 160\n17 x 11 = 187\n18 x 12 = 216\n----------\n8 x 1 = 8\n9 x 2 = 18\n10 x 3 = 30\n11 x 4 = 44\n12 x 5 = 60\n13 x 6 = 78\n14 x 7 = 98\n15 x 8 = 120\n16 x 9 = 144\n17 x 10 = 170\n18 x 11 = 198\n19 x 12 = 228\n----------\n9 x 1 = 9\n10 x 2 = 20\n11 x 3 = 33\n12 x 4 = 48\n13 x 5 = 65\n14 x 6 = 84\n15 x 7 = 105\n16 x 8 = 128\n17 x 9 = 153\n18 x 10 = 180\n19 x 11 = 209\n20 x 12 = 240\n----------\n10 x 1 = 10\n11 x 2 = 22\n12 x 3 = 36\n13 x 4 = 52\n14 x 5 = 70\n15 x 6 = 90\n16 x 7 = 112\n17 x 8 = 136\n18 x 9 = 162\n19 x 10 = 190\n20 x 11 = 220\n21 x 12 = 252\n----------\n11 x 1 = 11\n12 x 2 = 24\n13 x 3 = 39\n14 x 4 = 56\n15 x 5 = 75\n16 x 6 = 96\n17 x 7 = 119\n18 x 8 = 144\n19 x 9 = 171\n20 x 10 = 200\n21 x 11 = 231\n22 x 12 = 264\n----------\n12 x 1 = 12\n13 x 2 = 26\n14 x 3 = 42\n15 x 4 = 60\n16 x 5 = 80\n17 x 6 = 102\n18 x 7 = 126\n19 x 8 = 152\n20 x 9 = 180\n21 x 10 = 210\n22 x 11 = 242\n23 x 12 = 276\n----------\n", + "text": "\n18 x 12 = 216\n---\n8 x 1 = 8\n9 x 2 = 18\n10 x 3 = 30\n11 x 4 = 44\n12 x 5 = 60\n13 x 6 = 78\n14 x 7 = 98\n15 x 8 = 120\n16 x 9 = 144\n17 x 10 = 170\n18 x 11 = 198\n19 x 12 = 228\n---\n9 x 1 = 9\n10 x 2 = 20\n11 x 3 = 33\n12 x 4 = 48\n13 x 5 = 65\n14 x 6 = 84\n15 x 7 = 105\n16 x 8 = 128\n17 x 9 = 153\n18 x 10 = 180\n19 x 11 = 209\n20 x 12 = 240\n---\n10 x 1 = 10\n11 x 2 = 22\n12 x 3 = 36\n13 x 4 = 52\n14 x 5 = 70\n15 x 6 = 90\n16 x 7 = 112\n17 x 8 = 136\n18 x 9 = 162\n19 x 10 = 190\n20 x 11 = 220\n21 x 12 = 252\n---\n11 x 1 = 11\n12 x 2 = 24\n13 x 3 = 39\n14 x 4 = 56\n15 x 5 = 75\n16 x 6 = 96\n17 x 7 = 119\n18 x 8 = 144\n19 x 9 = 171\n20 x 10 = 200\n21 x 11 = 231\n22 x 12 = 264\n---\n12 x 1 = 12\n13 x 2 = 26\n14 x 3 = 42\n15 x 4 = 60\n16 x 5 = 80\n17 x 6 = 102\n18 x 7 = 126\n19 x 8 = 152\n20 x 9 = 180\n21 x 10 = 210\n22 x 11 = 242\n23 x 12 = 276\n---\n", "type": "stdout" } ] @@ -4401,7 +4182,7 @@ "step": "times_table_exercise" }, { - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "for left in range(12):", " left += 1", @@ -4417,18 +4198,18 @@ " print(left, 'x 10 =', left * 10)", " print(left, 'x 11 =', left * 11)", " print(left, 'x 12 =', left * 12)", - " print('----------')" + " print('---')" ], "response": { - "message": "

Your solution is too long. You only need a few lines of code for this problem.\nUse a nested loop so that you don't need to repeat yourself.\nThe computer will do the repetition for you!

", + "message": "

\u4f60\u7684\u89e3\u51b3\u65b9\u6848\u592a\u957f\u4e86\u3002\u5bf9\u4e8e\u8fd9\u4e2a\u95ee\u9898\uff0c\u4f60\u53ea\u9700\u8981\u51e0\u884c\u4ee3\u7801\u3002\n\u4f7f\u7528\u5d4c\u5957\u5faa\u73af\uff0c\u8fd9\u6837\u4f60\u5c31\u4e0d\u9700\u8981\u91cd\u590d\u81ea\u5df1\u3002\n\u8ba1\u7b97\u673a\u4f1a\u4e3a\u4f60\u5b8c\u6210\u91cd\u590d\u7684\u5de5\u4f5c\uff01

", "passed": false, "result": [ { - "text": "1 x 1 = 1\n1 x 2 = 2\n1 x 3 = 3\n1 x 4 = 4\n1 x 5 = 5\n1 x 6 = 6\n1 x 7 = 7\n1 x 8 = 8\n1 x 9 = 9\n1 x 10 = 10\n1 x 11 = 11\n1 x 12 = 12\n----------\n2 x 1 = 2\n2 x 2 = 4\n2 x 3 = 6\n2 x 4 = 8\n2 x 5 = 10\n2 x 6 = 12\n2 x 7 = 14\n2 x 8 = 16\n2 x 9 = 18\n2 x 10 = 20\n2 x 11 = 22\n2 x 12 = 24\n----------\n3 x 1 = 3\n3 x 2 = 6\n3 x 3 = 9\n3 x 4 = 12\n3 x 5 = 15\n3 x 6 = 18\n3 x 7 = 21\n3 x 8 = 24\n3 x 9 = 27\n3 x 10 = 30\n3 x 11 = 33\n3 x 12 = 36\n----------\n4 x 1 = 4\n4 x 2 = 8\n4 x 3 = 12\n4 x 4 = 16\n4 x 5 = 20\n4 x 6 = 24\n4 x 7 = 28\n4 x 8 = 32\n4 x 9 = 36\n4 x 10 = 40\n4 x 11 = 44\n4 x 12 = 48\n----------\n5 x 1 = 5\n5 x 2 = 10\n5 x 3 = 15\n5 x 4 = 20\n5 x 5 = 25\n5 x 6 = 30\n5 x 7 = 35\n5 x 8 = 40\n5 x 9 = 45\n5 x 10 = 50\n5 x 11 = 55\n5 x 12 = 60\n----------\n6 x 1 = 6\n6 x 2 = 12\n6 x 3 = 18\n6 x 4 = 24\n6 x 5 = 30\n6 x 6 = 36\n6 x 7 = 42\n6 x 8 = 48\n6 x 9 = 54\n6 x 10 = 60\n6 x 11 = 66\n6 x 12 = 72\n----------\n7 x 1 = 7\n7 x 2 = 14\n7 x 3 = 21\n7 x 4 = 28\n7 x 5 = 35\n7 x 6 = 42\n7 x 7 = 49\n7 x 8 = 56\n7 x 9 = 63\n7 x 10 = 70\n7 x 11 = 77\n7 x 12 = 84\n----------", + "text": "1 x 1 = 1\n1 x 2 = 2\n1 x 3 = 3\n1 x 4 = 4\n1 x 5 = 5\n1 x 6 = 6\n1 x 7 = 7\n1 x 8 = 8\n1 x 9 = 9\n1 x 10 = 10\n1 x 11 = 11\n1 x 12 = 12\n---\n2 x 1 = 2\n2 x 2 = 4\n2 x 3 = 6\n2 x 4 = 8\n2 x 5 = 10\n2 x 6 = 12\n2 x 7 = 14\n2 x 8 = 16\n2 x 9 = 18\n2 x 10 = 20\n2 x 11 = 22\n2 x 12 = 24\n---\n3 x 1 = 3\n3 x 2 = 6\n3 x 3 = 9\n3 x 4 = 12\n3 x 5 = 15\n3 x 6 = 18\n3 x 7 = 21\n3 x 8 = 24\n3 x 9 = 27\n3 x 10 = 30\n3 x 11 = 33\n3 x 12 = 36\n---\n4 x 1 = 4\n4 x 2 = 8\n4 x 3 = 12\n4 x 4 = 16\n4 x 5 = 20\n4 x 6 = 24\n4 x 7 = 28\n4 x 8 = 32\n4 x 9 = 36\n4 x 10 = 40\n4 x 11 = 44\n4 x 12 = 48\n---\n5 x 1 = 5\n5 x 2 = 10\n5 x 3 = 15\n5 x 4 = 20\n5 x 5 = 25\n5 x 6 = 30\n5 x 7 = 35\n5 x 8 = 40\n5 x 9 = 45\n5 x 10 = 50\n5 x 11 = 55\n5 x 12 = 60\n---\n6 x 1 = 6\n6 x 2 = 12\n6 x 3 = 18\n6 x 4 = 24\n6 x 5 = 30\n6 x 6 = 36\n6 x 7 = 42\n6 x 8 = 48\n6 x 9 = 54\n6 x 10 = 60\n6 x 11 = 66\n6 x 12 = 72\n---\n7 x 1 = 7\n7 x 2 = 14\n7 x 3 = 21\n7 x 4 = 28\n7 x 5 = 35\n7 x 6 = 42\n7 x 7 = 49\n7 x 8 = 56\n7 x 9 = 63\n7 x 10 = 70\n7 x 11 = 77\n7 x 12 = 84\n---\n8 x 1 = 8\n8 x 2 = 16\n8 x 3 = 24\n8 x 4 = 32\n8 x 5 =", "type": "stdout" }, { - "text": "\n8 x 1 = 8\n8 x 2 = 16\n8 x 3 = 24\n8 x 4 = 32\n8 x 5 = 40\n8 x 6 = 48\n8 x 7 = 56\n8 x 8 = 64\n8 x 9 = 72\n8 x 10 = 80\n8 x 11 = 88\n8 x 12 = 96\n----------\n9 x 1 = 9\n9 x 2 = 18\n9 x 3 = 27\n9 x 4 = 36\n9 x 5 = 45\n9 x 6 = 54\n9 x 7 = 63\n9 x 8 = 72\n9 x 9 = 81\n9 x 10 = 90\n9 x 11 = 99\n9 x 12 = 108\n----------\n10 x 1 = 10\n10 x 2 = 20\n10 x 3 = 30\n10 x 4 = 40\n10 x 5 = 50\n10 x 6 = 60\n10 x 7 = 70\n10 x 8 = 80\n10 x 9 = 90\n10 x 10 = 100\n10 x 11 = 110\n10 x 12 = 120\n----------\n11 x 1 = 11\n11 x 2 = 22\n11 x 3 = 33\n11 x 4 = 44\n11 x 5 = 55\n11 x 6 = 66\n11 x 7 = 77\n11 x 8 = 88\n11 x 9 = 99\n11 x 10 = 110\n11 x 11 = 121\n11 x 12 = 132\n----------\n12 x 1 = 12\n12 x 2 = 24\n12 x 3 = 36\n12 x 4 = 48\n12 x 5 = 60\n12 x 6 = 72\n12 x 7 = 84\n12 x 8 = 96\n12 x 9 = 108\n12 x 10 = 120\n12 x 11 = 132\n12 x 12 = 144\n----------\n", + "text": " 40\n8 x 6 = 48\n8 x 7 = 56\n8 x 8 = 64\n8 x 9 = 72\n8 x 10 = 80\n8 x 11 = 88\n8 x 12 = 96\n---\n9 x 1 = 9\n9 x 2 = 18\n9 x 3 = 27\n9 x 4 = 36\n9 x 5 = 45\n9 x 6 = 54\n9 x 7 = 63\n9 x 8 = 72\n9 x 9 = 81\n9 x 10 = 90\n9 x 11 = 99\n9 x 12 = 108\n---\n10 x 1 = 10\n10 x 2 = 20\n10 x 3 = 30\n10 x 4 = 40\n10 x 5 = 50\n10 x 6 = 60\n10 x 7 = 70\n10 x 8 = 80\n10 x 9 = 90\n10 x 10 = 100\n10 x 11 = 110\n10 x 12 = 120\n---\n11 x 1 = 11\n11 x 2 = 22\n11 x 3 = 33\n11 x 4 = 44\n11 x 5 = 55\n11 x 6 = 66\n11 x 7 = 77\n11 x 8 = 88\n11 x 9 = 99\n11 x 10 = 110\n11 x 11 = 121\n11 x 12 = 132\n---\n12 x 1 = 12\n12 x 2 = 24\n12 x 3 = 36\n12 x 4 = 48\n12 x 5 = 60\n12 x 6 = 72\n12 x 7 = 84\n12 x 8 = 96\n12 x 9 = 108\n12 x 10 = 120\n12 x 11 = 132\n12 x 12 = 144\n---\n", "type": "stdout" } ] @@ -4436,7 +4217,7 @@ "step": "times_table_exercise" }, { - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "for left in range(12):", " left += 1", @@ -4444,18 +4225,18 @@ " right += 1", " # for the sake of translation", " print(f'{left} x {right} = {left * right}'.replace('x', '*'))", - " print('----------')" + " print('---')" ], "response": { - "message": "

That's almost correct! Make sure to display the right character x in your table.\nFor example, your solution should display 3 x 4 = 12 and not 3 * 4 = 12.

", + "message": "

\u8fd9\u51e0\u4e4e\u662f\u6b63\u786e\u7684\uff01\u786e\u4fdd\u5728\u4f60\u7684\u8868\u4e2d\u663e\u793a\u6b63\u786e\u7684\u5b57\u7b26 x\u3002\n\u4f8b\u5982\uff0c\u4f60\u7684\u89e3\u51b3\u65b9\u6848\u5e94\u8be5\u663e\u793a 3 x 4 = 12 \u800c\u4e0d\u662f 3 * 4 = 12\u3002

", "passed": false, "result": [ { - "text": "1 * 1 = 1\n1 * 2 = 2\n1 * 3 = 3\n1 * 4 = 4\n1 * 5 = 5\n1 * 6 = 6\n1 * 7 = 7\n1 * 8 = 8\n1 * 9 = 9\n1 * 10 = 10\n1 * 11 = 11\n1 * 12 = 12\n----------\n2 * 1 = 2\n2 * 2 = 4\n2 * 3 = 6\n2 * 4 = 8\n2 * 5 = 10\n2 * 6 = 12\n2 * 7 = 14\n2 * 8 = 16\n2 * 9 = 18\n2 * 10 = 20\n2 * 11 = 22\n2 * 12 = 24\n----------\n3 * 1 = 3\n3 * 2 = 6\n3 * 3 = 9\n3 * 4 = 12\n3 * 5 = 15\n3 * 6 = 18\n3 * 7 = 21\n3 * 8 = 24\n3 * 9 = 27\n3 * 10 = 30\n3 * 11 = 33\n3 * 12 = 36\n----------\n4 * 1 = 4\n4 * 2 = 8\n4 * 3 = 12\n4 * 4 = 16\n4 * 5 = 20\n4 * 6 = 24\n4 * 7 = 28\n4 * 8 = 32\n4 * 9 = 36\n4 * 10 = 40\n4 * 11 = 44\n4 * 12 = 48\n----------\n5 * 1 = 5\n5 * 2 = 10\n5 * 3 = 15\n5 * 4 = 20\n5 * 5 = 25\n5 * 6 = 30\n5 * 7 = 35\n5 * 8 = 40\n5 * 9 = 45\n5 * 10 = 50\n5 * 11 = 55\n5 * 12 = 60\n----------\n6 * 1 = 6\n6 * 2 = 12\n6 * 3 = 18\n6 * 4 = 24\n6 * 5 = 30\n6 * 6 = 36\n6 * 7 = 42\n6 * 8 = 48\n6 * 9 = 54\n6 * 10 = 60\n6 * 11 = 66\n6 * 12 = 72\n----------\n7 * 1 = 7\n7 * 2 = 14\n7 * 3 = 21\n7 * 4 = 28\n7 * 5 = 35\n7 * 6 = 42\n7 * 7 = 49\n7 * 8 = 56\n7 * 9 = 63\n7 * 10 = 70\n7 * 11 = 77\n7 * 12 = 84\n----------", + "text": "1 * 1 = 1\n1 * 2 = 2\n1 * 3 = 3\n1 * 4 = 4\n1 * 5 = 5\n1 * 6 = 6\n1 * 7 = 7\n1 * 8 = 8\n1 * 9 = 9\n1 * 10 = 10\n1 * 11 = 11\n1 * 12 = 12\n---\n2 * 1 = 2\n2 * 2 = 4\n2 * 3 = 6\n2 * 4 = 8\n2 * 5 = 10\n2 * 6 = 12\n2 * 7 = 14\n2 * 8 = 16\n2 * 9 = 18\n2 * 10 = 20\n2 * 11 = 22\n2 * 12 = 24\n---\n3 * 1 = 3\n3 * 2 = 6\n3 * 3 = 9\n3 * 4 = 12\n3 * 5 = 15\n3 * 6 = 18\n3 * 7 = 21\n3 * 8 = 24\n3 * 9 = 27\n3 * 10 = 30\n3 * 11 = 33\n3 * 12 = 36\n---\n4 * 1 = 4\n4 * 2 = 8\n4 * 3 = 12\n4 * 4 = 16\n4 * 5 = 20\n4 * 6 = 24\n4 * 7 = 28\n4 * 8 = 32\n4 * 9 = 36\n4 * 10 = 40\n4 * 11 = 44\n4 * 12 = 48\n---\n5 * 1 = 5\n5 * 2 = 10\n5 * 3 = 15\n5 * 4 = 20\n5 * 5 = 25\n5 * 6 = 30\n5 * 7 = 35\n5 * 8 = 40\n5 * 9 = 45\n5 * 10 = 50\n5 * 11 = 55\n5 * 12 = 60\n---\n6 * 1 = 6\n6 * 2 = 12\n6 * 3 = 18\n6 * 4 = 24\n6 * 5 = 30\n6 * 6 = 36\n6 * 7 = 42\n6 * 8 = 48\n6 * 9 = 54\n6 * 10 = 60\n6 * 11 = 66\n6 * 12 = 72\n---\n7 * 1 = 7\n7 * 2 = 14\n7 * 3 = 21\n7 * 4 = 28\n7 * 5 = 35\n7 * 6 = 42\n7 * 7 = 49\n7 * 8 = 56\n7 * 9 = 63\n7 * 10 = 70\n7 * 11 = 77\n7 * 12 = 84\n---\n8 * 1 = 8\n8 * 2 = 16\n8 * 3 = 24\n8 * 4 = 32\n8 * 5 = 40", "type": "stdout" }, { - "text": "\n8 * 1 = 8\n8 * 2 = 16\n8 * 3 = 24\n8 * 4 = 32\n8 * 5 = 40\n8 * 6 = 48\n8 * 7 = 56\n8 * 8 = 64\n8 * 9 = 72\n8 * 10 = 80\n8 * 11 = 88\n8 * 12 = 96\n----------\n9 * 1 = 9\n9 * 2 = 18\n9 * 3 = 27\n9 * 4 = 36\n9 * 5 = 45\n9 * 6 = 54\n9 * 7 = 63\n9 * 8 = 72\n9 * 9 = 81\n9 * 10 = 90\n9 * 11 = 99\n9 * 12 = 108\n----------\n10 * 1 = 10\n10 * 2 = 20\n10 * 3 = 30\n10 * 4 = 40\n10 * 5 = 50\n10 * 6 = 60\n10 * 7 = 70\n10 * 8 = 80\n10 * 9 = 90\n10 * 10 = 100\n10 * 11 = 110\n10 * 12 = 120\n----------\n11 * 1 = 11\n11 * 2 = 22\n11 * 3 = 33\n11 * 4 = 44\n11 * 5 = 55\n11 * 6 = 66\n11 * 7 = 77\n11 * 8 = 88\n11 * 9 = 99\n11 * 10 = 110\n11 * 11 = 121\n11 * 12 = 132\n----------\n12 * 1 = 12\n12 * 2 = 24\n12 * 3 = 36\n12 * 4 = 48\n12 * 5 = 60\n12 * 6 = 72\n12 * 7 = 84\n12 * 8 = 96\n12 * 9 = 108\n12 * 10 = 120\n12 * 11 = 132\n12 * 12 = 144\n----------\n", + "text": "\n8 * 6 = 48\n8 * 7 = 56\n8 * 8 = 64\n8 * 9 = 72\n8 * 10 = 80\n8 * 11 = 88\n8 * 12 = 96\n---\n9 * 1 = 9\n9 * 2 = 18\n9 * 3 = 27\n9 * 4 = 36\n9 * 5 = 45\n9 * 6 = 54\n9 * 7 = 63\n9 * 8 = 72\n9 * 9 = 81\n9 * 10 = 90\n9 * 11 = 99\n9 * 12 = 108\n---\n10 * 1 = 10\n10 * 2 = 20\n10 * 3 = 30\n10 * 4 = 40\n10 * 5 = 50\n10 * 6 = 60\n10 * 7 = 70\n10 * 8 = 80\n10 * 9 = 90\n10 * 10 = 100\n10 * 11 = 110\n10 * 12 = 120\n---\n11 * 1 = 11\n11 * 2 = 22\n11 * 3 = 33\n11 * 4 = 44\n11 * 5 = 55\n11 * 6 = 66\n11 * 7 = 77\n11 * 8 = 88\n11 * 9 = 99\n11 * 10 = 110\n11 * 11 = 121\n11 * 12 = 132\n---\n12 * 1 = 12\n12 * 2 = 24\n12 * 3 = 36\n12 * 4 = 48\n12 * 5 = 60\n12 * 6 = 72\n12 * 7 = 84\n12 * 8 = 96\n12 * 9 = 108\n12 * 10 = 120\n12 * 11 = 132\n12 * 12 = 144\n---\n", "type": "stdout" } ] @@ -4463,17 +4244,18 @@ "step": "times_table_exercise" }, { - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "pass", "3 x 4" ], "response": { - "message": "

To multiply numbers, use *

", + "message": "

\u8981\u4e58\u6570\u5b57\uff0c\u4f7f\u7528 *

", "passed": false, "result": [ { - "text": " 3 x 4\n ^\nSyntaxError: invalid syntax\nat line 2\n\nA `SyntaxError` occurs when Python cannot understand your code.\n\nCurrently, I cannot guess the likely cause of this error.\nTry to examine closely the line indicated as well as the line\nimmediately above to see if you can identify some misspelled\nword, or missing symbols, like (, ), [, ], :, etc.\n\nUnless your code uses type annotations, which are beyond our scope,\nif you think that this is something which should be handled\nby friendly, please report this case to\nhttps://github.com/aroberge/friendly/issues\n\n\n\n", + "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

Currently, I cannot guess the likely cause of this error.\nTry to examine closely the line indicated as well as the line\nimmediately above to see if you can identify some misspelled\nword, or missing symbols, like (, ), [, ], :, etc.

\n

Unless your code uses type annotations, which are beyond our scope,\nif you think that this is something which should be handled\nby friendly, please report this case to\nhttps://github.com/friendly-traceback/friendly-traceback/issues

", + "text": " 3 x 4\n ^\nSyntaxError: invalid syntax\n\u5728\u7b2c 2\n", "type": "syntax_error" } ] @@ -4481,33 +4263,25 @@ "step": "times_table_exercise" }, { - "get_solution": [ - "for left in range(12):", - " left += 1", - " for right in range(12):", - " right += 1", - " print(f'{left} x {right} = {left * right}')", - " print('----------')" - ], - "page": "Introducing Nested Loops", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "for left in range(12):", " left += 1", " for right in range(12):", " right += 1", " print(f'{left} x {right} = {left * right}')", - " print('----------')" + " print('---')" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "1 x 1 = 1\n1 x 2 = 2\n1 x 3 = 3\n1 x 4 = 4\n1 x 5 = 5\n1 x 6 = 6\n1 x 7 = 7\n1 x 8 = 8\n1 x 9 = 9\n1 x 10 = 10\n1 x 11 = 11\n1 x 12 = 12\n----------\n2 x 1 = 2\n2 x 2 = 4\n2 x 3 = 6\n2 x 4 = 8\n2 x 5 = 10\n2 x 6 = 12\n2 x 7 = 14\n2 x 8 = 16\n2 x 9 = 18\n2 x 10 = 20\n2 x 11 = 22\n2 x 12 = 24\n----------\n3 x 1 = 3\n3 x 2 = 6\n3 x 3 = 9\n3 x 4 = 12\n3 x 5 = 15\n3 x 6 = 18\n3 x 7 = 21\n3 x 8 = 24\n3 x 9 = 27\n3 x 10 = 30\n3 x 11 = 33\n3 x 12 = 36\n----------\n4 x 1 = 4\n4 x 2 = 8\n4 x 3 = 12\n4 x 4 = 16\n4 x 5 = 20\n4 x 6 = 24\n4 x 7 = 28\n4 x 8 = 32\n4 x 9 = 36\n4 x 10 = 40\n4 x 11 = 44\n4 x 12 = 48\n----------\n5 x 1 = 5\n5 x 2 = 10\n5 x 3 = 15\n5 x 4 = 20\n5 x 5 = 25\n5 x 6 = 30\n5 x 7 = 35\n5 x 8 = 40\n5 x 9 = 45\n5 x 10 = 50\n5 x 11 = 55\n5 x 12 = 60\n----------\n6 x 1 = 6\n6 x 2 = 12\n6 x 3 = 18\n6 x 4 = 24\n6 x 5 = 30\n6 x 6 = 36\n6 x 7 = 42\n6 x 8 = 48\n6 x 9 = 54\n6 x 10 = 60\n6 x 11 = 66\n6 x 12 = 72\n----------\n7 x 1 = 7\n7 x 2 = 14\n7 x 3 = 21\n7 x 4 = 28\n7 x 5 = 35\n7 x 6 = 42\n7 x 7 = 49\n7 x 8 = 56\n7 x 9 = 63\n7 x 10 = 70\n7 x 11 = 77\n7 x 12 = 84\n----------", + "text": "1 x 1 = 1\n1 x 2 = 2\n1 x 3 = 3\n1 x 4 = 4\n1 x 5 = 5\n1 x 6 = 6\n1 x 7 = 7\n1 x 8 = 8\n1 x 9 = 9\n1 x 10 = 10\n1 x 11 = 11\n1 x 12 = 12\n---\n2 x 1 = 2\n2 x 2 = 4\n2 x 3 = 6\n2 x 4 = 8\n2 x 5 = 10\n2 x 6 = 12\n2 x 7 = 14\n2 x 8 = 16\n2 x 9 = 18\n2 x 10 = 20\n2 x 11 = 22\n2 x 12 = 24\n---\n3 x 1 = 3\n3 x 2 = 6\n3 x 3 = 9\n3 x 4 = 12\n3 x 5 = 15\n3 x 6 = 18\n3 x 7 = 21\n3 x 8 = 24\n3 x 9 = 27\n3 x 10 = 30\n3 x 11 = 33\n3 x 12 = 36\n---\n4 x 1 = 4\n4 x 2 = 8\n4 x 3 = 12\n4 x 4 = 16\n4 x 5 = 20\n4 x 6 = 24\n4 x 7 = 28\n4 x 8 = 32\n4 x 9 = 36\n4 x 10 = 40\n4 x 11 = 44\n4 x 12 = 48\n---\n5 x 1 = 5\n5 x 2 = 10\n5 x 3 = 15\n5 x 4 = 20\n5 x 5 = 25\n5 x 6 = 30\n5 x 7 = 35\n5 x 8 = 40\n5 x 9 = 45\n5 x 10 = 50\n5 x 11 = 55\n5 x 12 = 60\n---\n6 x 1 = 6\n6 x 2 = 12\n6 x 3 = 18\n6 x 4 = 24\n6 x 5 = 30\n6 x 6 = 36\n6 x 7 = 42\n6 x 8 = 48\n6 x 9 = 54\n6 x 10 = 60\n6 x 11 = 66\n6 x 12 = 72\n---\n7 x 1 = 7\n7 x 2 = 14\n7 x 3 = 21\n7 x 4 = 28\n7 x 5 = 35\n7 x 6 = 42\n7 x 7 = 49\n7 x 8 = 56\n7 x 9 = 63\n7 x 10 = 70\n7 x 11 = 77\n7 x 12 = 84\n---\n8 x 1 = 8\n8 x 2 = 16\n8 x 3 = 24\n8 x 4 = 32\n8 x 5 = 40", "type": "stdout" }, { - "text": "\n8 x 1 = 8\n8 x 2 = 16\n8 x 3 = 24\n8 x 4 = 32\n8 x 5 = 40\n8 x 6 = 48\n8 x 7 = 56\n8 x 8 = 64\n8 x 9 = 72\n8 x 10 = 80\n8 x 11 = 88\n8 x 12 = 96\n----------\n9 x 1 = 9\n9 x 2 = 18\n9 x 3 = 27\n9 x 4 = 36\n9 x 5 = 45\n9 x 6 = 54\n9 x 7 = 63\n9 x 8 = 72\n9 x 9 = 81\n9 x 10 = 90\n9 x 11 = 99\n9 x 12 = 108\n----------\n10 x 1 = 10\n10 x 2 = 20\n10 x 3 = 30\n10 x 4 = 40\n10 x 5 = 50\n10 x 6 = 60\n10 x 7 = 70\n10 x 8 = 80\n10 x 9 = 90\n10 x 10 = 100\n10 x 11 = 110\n10 x 12 = 120\n----------\n11 x 1 = 11\n11 x 2 = 22\n11 x 3 = 33\n11 x 4 = 44\n11 x 5 = 55\n11 x 6 = 66\n11 x 7 = 77\n11 x 8 = 88\n11 x 9 = 99\n11 x 10 = 110\n11 x 11 = 121\n11 x 12 = 132\n----------\n12 x 1 = 12\n12 x 2 = 24\n12 x 3 = 36\n12 x 4 = 48\n12 x 5 = 60\n12 x 6 = 72\n12 x 7 = 84\n12 x 8 = 96\n12 x 9 = 108\n12 x 10 = 120\n12 x 11 = 132\n12 x 12 = 144\n----------\n", + "text": "\n8 x 6 = 48\n8 x 7 = 56\n8 x 8 = 64\n8 x 9 = 72\n8 x 10 = 80\n8 x 11 = 88\n8 x 12 = 96\n---\n9 x 1 = 9\n9 x 2 = 18\n9 x 3 = 27\n9 x 4 = 36\n9 x 5 = 45\n9 x 6 = 54\n9 x 7 = 63\n9 x 8 = 72\n9 x 9 = 81\n9 x 10 = 90\n9 x 11 = 99\n9 x 12 = 108\n---\n10 x 1 = 10\n10 x 2 = 20\n10 x 3 = 30\n10 x 4 = 40\n10 x 5 = 50\n10 x 6 = 60\n10 x 7 = 70\n10 x 8 = 80\n10 x 9 = 90\n10 x 10 = 100\n10 x 11 = 110\n10 x 12 = 120\n---\n11 x 1 = 11\n11 x 2 = 22\n11 x 3 = 33\n11 x 4 = 44\n11 x 5 = 55\n11 x 6 = 66\n11 x 7 = 77\n11 x 8 = 88\n11 x 9 = 99\n11 x 10 = 110\n11 x 11 = 121\n11 x 12 = 132\n---\n12 x 1 = 12\n12 x 2 = 24\n12 x 3 = 36\n12 x 4 = 48\n12 x 5 = 60\n12 x 6 = 72\n12 x 7 = 84\n12 x 8 = 96\n12 x 9 = 108\n12 x 10 = 120\n12 x 11 = 132\n12 x 12 = 144\n---\n", "type": "stdout" } ] @@ -4521,7 +4295,7 @@ " if player1 != player2:", " print(f'{player1} vs {player2}')" ], - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "players = ['Alice', 'Bob', 'Charlie']", "for player1 in players:", @@ -4530,7 +4304,6 @@ " print(f'{player1} vs {player2}')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4549,7 +4322,7 @@ " for c4 in letters:", " print(c1 + c2 + c3 + c4)" ], - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "letters = 'AB'", "for c1 in letters:", @@ -4559,7 +4332,6 @@ " print(c1 + c2 + c3 + c4)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4579,7 +4351,7 @@ " line += '+'", " print(line)" ], - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "size = 3", "for i in range(size):", @@ -4590,7 +4362,6 @@ " print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4608,7 +4379,7 @@ " if i < j:", " print(f'{players[i]} vs {players[j]}')" ], - "page": "Introducing Nested Loops", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5faa\u73af", "program": [ "players = ['Alice', 'Bob', 'Charlie']", "for i in range(len(players)):", @@ -4617,7 +4388,6 @@ " print(f'{players[i]} vs {players[j]}')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4629,7 +4399,8 @@ "step": "player_vs_player_bonus" }, { - "page": "Understanding Programs with birdseye", + "get_solution": "program", + "page": "\u4f7f\u7528 birdseye \u7406\u89e3\u7a0b\u5e8f", "program": [ "a = 2", "b = 3", @@ -4638,7 +4409,6 @@ "print(a * b + c * d)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4650,7 +4420,8 @@ "step": "first_birdseye_example" }, { - "page": "Understanding Programs with birdseye", + "get_solution": "program", + "page": "\u4f7f\u7528 birdseye \u7406\u89e3\u7a0b\u5e8f", "program": [ "word = 'Amazing'", "vowels = []", @@ -4664,7 +4435,6 @@ "print(consonants)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4680,14 +4450,13 @@ "string = strings[1]", "print(string[0])" ], - "page": "Introducing Nested Lists", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5217\u8868", "program": [ "strings = ['abc', 'def', 'ghi']", "string = strings[1]", "print(string[0])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4699,13 +4468,13 @@ "step": "string_list_exercise" }, { - "page": "Introducing Nested Lists", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5217\u8868", "program": [ "strings = [\"abc\", \"def\", \"ghi\"]", "print(strings[1][0])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4720,13 +4489,12 @@ "get_solution": [ "print(strings[-2][-1])" ], - "page": "Introducing Nested Lists", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5217\u8868", "program": [ "strings = ['abc', 'de', 'fghi', 'jklmn', 'o']", "print(strings[-2][-1])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4738,13 +4506,13 @@ "step": "double_subscripting_exercise" }, { - "page": "Introducing Nested Lists", + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5217\u8868", "program": [ "strings = [['hello', 'there'], ['how', 'are', 'you']]", "print(strings[1][0])" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "how", @@ -4760,7 +4528,7 @@ "t", "e", "a", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -4776,13 +4544,12 @@ "get_solution": [ "print(strings[1][2][0])" ], - "page": "Introducing Nested Lists", + "page": "\u4ecb\u7ecd\u5d4c\u5957\u5217\u8868", "program": [ "strings = [['hello', 'there'], ['how', 'are', 'you']]", "print(strings[1][2][0])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4794,7 +4561,8 @@ "step": "triple_subscripting" }, { - "page": "Looping Over Nested Lists", + "get_solution": "program", + "page": "\u904d\u5386\u5d4c\u5957\u5217\u8868", "program": [ "numbers = [[1, 2, 3], [4, 5], [6], []]", "for sublist in numbers:", @@ -4803,7 +4571,6 @@ " print('---')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "1\n2\n3\n---\n4\n5\n---\n6\n---\n---", @@ -4813,7 +4580,7 @@ "1\n2\n3\n---\n4\n5\n---\n6\n---", "1 2 3\n---\n4 5\n---\n6\n---\n---", "1 2 3\n---\n4 5\n---\n6\n---", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -4826,7 +4593,8 @@ "step": "nested_list_nested_loop_example" }, { - "page": "Looping Over Nested Lists", + "get_solution": "program", + "page": "\u904d\u5386\u5d4c\u5957\u5217\u8868", "program": [ "numbers = [[1, 2, 3], [4, 5], [6], []]", "for sublist in numbers:", @@ -4835,7 +4603,6 @@ " print('---')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4853,7 +4620,7 @@ " if word in string:", " print(string)" ], - "page": "Looping Over Nested Lists", + "page": "\u904d\u5386\u5d4c\u5957\u5217\u8868", "program": [ "strings = [['hello there', 'how are you'], ['goodbye world', 'hello world']]", "word = 'hello'", @@ -4863,7 +4630,6 @@ " print(string)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4883,7 +4649,7 @@ " present = True", " print(present)" ], - "page": "Looping Over Nested Lists", + "page": "\u904d\u5386\u5d4c\u5957\u5217\u8868", "program": [ "strings = [['hello there', 'how are you'], ['goodbye world', 'hello world']]", "word = 'goodbye'", @@ -4895,7 +4661,6 @@ " print(present)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4915,7 +4680,7 @@ " present = True", "print(present)" ], - "page": "Looping Over Nested Lists", + "page": "\u904d\u5386\u5d4c\u5957\u5217\u8868", "program": [ "strings = [['hello there', 'how are you'], ['goodbye world', 'hello world']]", "word = 'are'", @@ -4927,7 +4692,6 @@ "print(present)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4946,7 +4710,7 @@ " line += string[i]", " print(line)" ], - "page": "Looping Over Nested Lists", + "page": "\u904d\u5386\u5d4c\u5957\u5217\u8868", "program": [ "strings = ['abc', 'def', 'ghi']", "for i in range(len(strings[0])):", @@ -4956,7 +4720,6 @@ " print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -4983,7 +4746,7 @@ " line += string[i]", " print(line)" ], - "page": "Looping Over Nested Lists", + "page": "\u904d\u5386\u5d4c\u5957\u5217\u8868", "program": [ "strings = ['abcqwe', 'def', 'ghiq']", "lengths = []", @@ -5001,7 +4764,6 @@ " print(line)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5013,7 +4775,8 @@ "step": "zip_longest_strings_exercise" }, { - "page": "Defining Functions", + "get_solution": "program", + "page": "\u5b9a\u4e49\u51fd\u6570", "program": [ "def greet(name):", " print(f\"Hello {name}!\")", @@ -5022,7 +4785,6 @@ "greet(\"Bob\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5034,7 +4796,8 @@ "step": "define_greet" }, { - "page": "Defining Functions", + "get_solution": "program", + "page": "\u5b9a\u4e49\u51fd\u6570", "program": [ "def greet(name):", " print(f\"Hello {name}!\")", @@ -5044,7 +4807,6 @@ "greet(\"Bob\")" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello Alice!\nHow are you?\nHello Bob!\nHow are you?", @@ -5052,7 +4814,7 @@ "Hello Alice!\nHow are you?\nHello Bob!\nHow are you?", "Hello Alice!\nHello Bob!\nHow are you?", "Hello Alice!\nHow are you?\nHello Bob!", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5065,15 +4827,8 @@ "step": "how_are_you" }, { - "get_solution": [ - "def say_hello(name):", - " print(f\"Hello {name}!\")", - " print(\"How are you?\")", - "", - "say_hello(\"Alice\")", - "say_hello(\"Bob\")" - ], - "page": "Defining Functions", + "get_solution": "program", + "page": "\u5b9a\u4e49\u51fd\u6570", "program": [ "def say_hello(name):", " print(f\"Hello {name}!\")", @@ -5083,7 +4838,6 @@ "say_hello(\"Bob\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5095,15 +4849,8 @@ "step": "change_function_name" }, { - "get_solution": [ - "def say_hello(person_name):", - " print(f\"Hello {person_name}!\")", - " print(\"How are you?\")", - "", - "say_hello(\"Alice\")", - "say_hello(\"Bob\")" - ], - "page": "Defining Functions", + "get_solution": "program", + "page": "\u5b9a\u4e49\u51fd\u6570", "program": [ "def say_hello(person_name):", " print(f\"Hello {person_name}!\")", @@ -5113,7 +4860,6 @@ "say_hello(\"Bob\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5125,26 +4871,22 @@ "step": "change_parameter_name" }, { - "get_solution": [ - "def print_twice(x):", - " print(x)", - " print(x)" - ], - "page": "Defining Functions", + "get_solution": "program", + "page": "\u5b9a\u4e49\u51fd\u6570", "program": [ "def print_twice(x):", " print(x)", " print(x)" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "print_twice_exercise" }, { - "page": "Defining Functions", + "get_solution": "program", + "page": "\u5b9a\u4e49\u51fd\u6570", "program": [ "def print_many(thing, n):", " for _ in range(n):", @@ -5153,7 +4895,6 @@ "print_many(\"Hello\", 3)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Hello\nHello\nHello", @@ -5163,7 +4904,7 @@ "Hello\nHello\nHello", "Hello", "H\ne\nl\nl\no", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5176,15 +4917,9 @@ "step": "print_many" }, { - "get_solution": [ - "def print_many(n, thing):", - " for _ in range(n):", - " print(thing)", - "", - "print_many(3, \"Hello\")" - ], - "page": "Defining Functions", - "program": [ + "get_solution": "program", + "page": "\u5b9a\u4e49\u51fd\u6570", + "program": [ "def print_many(n, thing):", " for _ in range(n):", " print(thing)", @@ -5192,7 +4927,6 @@ "print_many(3, \"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5204,7 +4938,8 @@ "step": "swap_parameters" }, { - "page": "Calling Functions Within Functions", + "get_solution": "program", + "page": "\u5728\u51fd\u6570\u4e2d\u8c03\u7528\u51fd\u6570", "program": [ "def print_many(n, thing):", " for _ in range(n):", @@ -5216,7 +4951,6 @@ "print_twice(\"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5228,7 +4962,8 @@ "step": "print_twice_call_print_many" }, { - "page": "Calling Functions Within Functions", + "get_solution": "program", + "page": "\u5728\u51fd\u6570\u4e2d\u8c03\u7528\u51fd\u6570", "program": [ "def print_many(n, thing):", " for _ in range(n):", @@ -5240,83 +4975,55 @@ "print_twice(\"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { - "text": "", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n\u001b[38;5;245m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_twice in File \"/my_program.py\", line 5\u001b[0m\n\u001b[38;5;245m \u001b[0m...... x = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;245m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_many in File \"/my_program.py\", line 1\u001b[0m\n\u001b[38;5;245m \u001b[0m...... n = \u001b[38;5;141m2\u001b[39m\n\u001b[38;5;245m \u001b[0m...... thing = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m.......... _ = \u001b[38;5;141m0\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | print(thing)\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n", + "text": "Hello", "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_twice in File \"my_program.py\", line 5\u001b[0m\n\u001b[38;5;242m \u001b[0m...... x = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 5\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_twice\u001b[39m(x):\n", + "text": "\n", "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[36m\u001b[1m>>> Call to print_many in File \"my_program.py\", line 1\u001b[0m\n\u001b[38;5;242m \u001b[0m...... n = \u001b[38;5;141m2\u001b[39m\n\u001b[38;5;242m \u001b[0m...... thing = \u001b[38;5;186m'\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m'\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 1\u001b[0m | \u001b[38;5;81mdef\u001b[39m \u001b[38;5;148mprint_many\u001b[39m(n, thing):\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m.......... _ = \u001b[38;5;141m1\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 3\u001b[0m | print(thing)\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", + "text": "Hello", "type": "stdout" }, { - "text": "\u001b[38;5;242m \u001b[0m.......... _ = \u001b[38;5;141m0\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | print(thing)\n", + "text": "\n", "type": "stdout" }, { - "text": "Hello\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;204min\u001b[39m range(n):\n", + "type": "snoop" }, { - "text": "\u001b[38;5;242m \u001b[0m.......... _ = \u001b[38;5;141m1\u001b[39m\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 3\u001b[0m | print(thing)\n", - "type": "stdout" - }, - { - "text": "Hello\n\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 2\u001b[0m | \u001b[38;5;81mfor\u001b[39m _ \u001b[38;5;197min\u001b[39m range(n):\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_many: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_twice: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n", - "type": "stdout" - }, - { - "text": "\u001b[38;5;242m \u001b[0m\u001b[38;5;242m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n", - "type": "stdout" - }, - { - "text": "", - "type": "stdout" + "text": "\u001b[38;5;245m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_many: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 6\u001b[0m | print_many(\u001b[38;5;141m2\u001b[39m, x)\n\u001b[38;5;245m \u001b[0m\u001b[32m\u001b[1m<<< Return value from print_twice: \u001b[0m\u001b[38;5;81mNone\u001b[39m\n\u001b[38;5;245m \u001b[0m\u001b[38;5;245m 8\u001b[0m | print_twice(\u001b[38;5;186m\"\u001b[39m\u001b[38;5;186mHello\u001b[39m\u001b[38;5;186m\"\u001b[39m)\n", + "type": "snoop" } ] }, "step": "see_stack_in_snoop" }, { - "page": "Calling Functions Within Functions", + "get_solution": "program", + "page": "\u5728\u51fd\u6570\u4e2d\u8c03\u7528\u51fd\u6570", "program": [ "def print_many(n, thing):", " for _ in range(n):", @@ -5328,7 +5035,6 @@ "print_twice(\"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5340,7 +5046,8 @@ "step": "see_stack_in_pythontutor" }, { - "page": "Calling Functions Within Functions", + "get_solution": "program", + "page": "\u5728\u51fd\u6570\u4e2d\u8c03\u7528\u51fd\u6570", "program": [ "def print_many(n, thing):", " for _ in range(n):", @@ -5352,7 +5059,6 @@ "print_twice(\"Hello\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5364,7 +5070,8 @@ "step": "see_stack_in_birdseye" }, { - "page": "Returning Values From Functions", + "get_solution": "program", + "page": "\u4ece\u51fd\u6570\u8fd4\u56de\u503c", "program": [ "def double(x):", " return x * 2", @@ -5375,7 +5082,6 @@ "print(twice)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "5\n10", @@ -5383,7 +5089,7 @@ "5\n5", "5\n10", "10\n10", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5396,7 +5102,8 @@ "step": "first_return" }, { - "page": "Returning Values From Functions", + "get_solution": "program", + "page": "\u4ece\u51fd\u6570\u8fd4\u56de\u503c", "program": [ "def double(x):", " return x * 2", @@ -5406,14 +5113,13 @@ "print(number)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "5", "choices": [ "5", "10", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5426,13 +5132,13 @@ "step": "losing_return_value" }, { - "page": "Returning Values From Functions", + "page": "\u4ece\u51fd\u6570\u8fd4\u56de\u503c", "program": [ "def quadruple(x):", " return x * 4" ], "response": { - "message": "

You cannot use *, +, or even any numbers inside quadruple.\nYou must call double to solve the problem.

", + "message": "

\u4f60\u4e0d\u80fd\u5728 quadruple \u5185\u90e8\u4f7f\u7528 *\u3001+\uff0c\u751a\u81f3\u4efb\u4f55\u6570\u5b57\u3002\n\u4f60\u5fc5\u987b\u8c03\u7528 double \u6765\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\u3002

", "passed": false, "result": [] }, @@ -5443,7 +5149,7 @@ "def quadruple(x):", " return double(double(x))" ], - "page": "Returning Values From Functions", + "page": "\u4ece\u51fd\u6570\u8fd4\u56de\u503c", "program": [ "def double(x):", " return x * 2", @@ -5452,14 +5158,14 @@ " return double(double(x))" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "quadruple_exercise" }, { - "page": "Testing Functions", + "get_solution": "program", + "page": "\u6d4b\u8bd5\u51fd\u6570", "program": [ "def double(x):", " return x * 2", @@ -5468,7 +5174,6 @@ "assert_equal(double(5), 10)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "OK\nOK", @@ -5478,7 +5183,7 @@ "Error! 2 != 4", "OK\nOK", "OK", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5491,7 +5196,8 @@ "step": "introducing_assert_equal" }, { - "page": "Testing Functions", + "get_solution": "program", + "page": "\u6d4b\u8bd5\u51fd\u6570", "program": [ "def double(x):", " return x * 3", @@ -5500,7 +5206,6 @@ "assert_equal(double(5), 10)" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "Error! 6 != 4\nError! 15 != 10", @@ -5509,7 +5214,7 @@ "Error! 6 != 4\nError! 15 != 10", "Error! 4 != 6\nError! 10 != 15", "OK\nOK", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5522,7 +5227,8 @@ "step": "make_tests_fail" }, { - "page": "Testing Functions", + "get_solution": "program", + "page": "\u6d4b\u8bd5\u51fd\u6570", "program": [ "def double(x):", " return x * 2", @@ -5534,7 +5240,6 @@ "assert_equal(quadruple(5), 20)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5546,24 +5251,20 @@ "step": "complete_quadruple_tests" }, { - "get_solution": [ - "def surround(string, sides):", - " return sides + string + sides" - ], - "page": "Testing Functions", + "get_solution": "program", + "page": "\u6d4b\u8bd5\u51fd\u6570", "program": [ "def surround(string, sides):", " return sides + string + sides" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "surround_exercise" }, { - "page": "Testing Functions", + "page": "\u6d4b\u8bd5\u51fd\u6570", "program": [ "def surround(string, sides):", " return sides + string + sides", @@ -5575,21 +5276,21 @@ " return string" ], "response": { - "message": "

In the alert function, you placed your return statement at the wrong place!\nPay attention to your indentations in alert. You might be ending a loop too early with return.

", + "message": "

\u5728 alert \u51fd\u6570\u4e2d\uff0c\u4f60\u628a return \u8bed\u53e5\u653e\u5728\u4e86\u9519\u8bef\u7684\u4f4d\u7f6e\uff01\n\u6ce8\u610f\u4f60\u5728 alert \u4e2d\u7684\u7f29\u8fdb\u3002\u4f60\u53ef\u80fd\u8fc7\u65e9\u5730\u7528 return \u7ed3\u675f\u4e86\u4e00\u4e2a\u5faa\u73af\u3002

", "passed": false, "result": [] }, "step": "alert_exercise" }, { - "page": "Testing Functions", + "page": "\u6d4b\u8bd5\u51fd\u6570", "program": [ "def alert(string, level):", " marks = '!' * level", " return marks + ' ' + string + ' ' + marks" ], "response": { - "message": "

You cannot use string concatenation/formatting/interpolation/multiplication or f-strings in alert.\nYou must call surround to solve the problem.

", + "message": "

\u4f60\u4e0d\u80fd\u5728 alert \u4e2d\u4f7f\u7528\u5b57\u7b26\u4e32\u8fde\u63a5/\u683c\u5f0f\u5316/\u63d2\u503c/\u4e58\u6cd5\u6216 f-strings\u3002\n\u4f60\u5fc5\u987b\u8c03\u7528 surround \u6765\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\u3002

", "passed": false, "result": [] }, @@ -5603,7 +5304,7 @@ " string = surround(string, '!')", " return string" ], - "page": "Testing Functions", + "page": "\u6d4b\u8bd5\u51fd\u6570", "program": [ "def surround(string, sides):", " return sides + string + sides", @@ -5615,14 +5316,14 @@ " return string" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "alert_exercise" }, { - "page": "return ends the function call", + "get_solution": "program", + "page": "return \u7ed3\u675f\u51fd\u6570\u8c03\u7528", "program": [ "def foo():", " return 1", @@ -5631,7 +5332,6 @@ "print(foo())" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "1", @@ -5641,7 +5341,7 @@ "[1, 2]", "1\n2", "1 2", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5654,7 +5354,8 @@ "step": "double_return_in_one_function" }, { - "page": "return ends the function call", + "get_solution": "program", + "page": "return \u7ed3\u675f\u51fd\u6570\u8c03\u7528", "program": [ "def double_numbers(numbers):", " for x in numbers:", @@ -5663,7 +5364,6 @@ "assert_equal(double_numbers([1, 2, 3]), [2, 4, 6])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5675,7 +5375,8 @@ "step": "cannot_return_multiple_values" }, { - "page": "return ends the function call", + "get_solution": "program", + "page": "return \u7ed3\u675f\u51fd\u6570\u8c03\u7528", "program": [ "def foo():", " for letter in 'abc':", @@ -5687,7 +5388,6 @@ "foo()" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "a 0\na 1\na 2\nb 0", @@ -5697,7 +5397,7 @@ "a 0\na 1\na 2\nb 0\nb 1\nb 2", "a 0\na 1\na 2\nb 0\nc 0\nc 1\nc 2", "a 0\na 1\na 2\nb 0\nb 1\nb 2\nc 0\nc 1\nc 2", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5710,7 +5410,8 @@ "step": "return_ends_whole_function" }, { - "page": "return ends the function call", + "get_solution": "program", + "page": "return \u7ed3\u675f\u51fd\u6570\u8c03\u7528", "program": [ "def foo():", " for letter in 'abc':", @@ -5722,7 +5423,6 @@ "foo()" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "a 0\na 1\na 2\nb 0\nc 0\nc 1\nc 2", @@ -5732,7 +5432,7 @@ "a 0\na 1\na 2\nb 0\nb 1\nb 2", "a 0\na 1\na 2\nb 0\nc 0\nc 1\nc 2", "a 0\na 1\na 2\nb 0\nb 1\nb 2\nc 0\nc 1\nc 2", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5745,7 +5445,8 @@ "step": "break_vs_return" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "def is_friend(name):", " if name == \"Alice\":", @@ -5760,7 +5461,6 @@ "assert_equal(is_friend(\"Charlie\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5772,19 +5472,19 @@ "step": "InputAliceBob" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "True or True" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5797,19 +5497,19 @@ "step": "TrueOrTrue" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "True or False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5822,19 +5522,19 @@ "step": "TrueOrFalse" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "False or False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5847,7 +5547,8 @@ "step": "FalseOrFalse" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "def is_friend(name):", " if name == \"Alice\" or name == \"Bob\":", @@ -5860,7 +5561,6 @@ "assert_equal(is_friend(\"Charlie\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5872,7 +5572,8 @@ "step": "ImprovingWithOr" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "def is_friend(name):", " return name == \"Alice\" or name == \"Bob\"", @@ -5882,7 +5583,6 @@ "assert_equal(is_friend(\"Charlie\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5894,7 +5594,8 @@ "step": "FurtherImprovement" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "def is_friend(name):", " return name == \"Alice\" or \"Bob\"", @@ -5904,7 +5605,6 @@ "assert_equal(is_friend(\"Charlie\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5916,7 +5616,8 @@ "step": "ACommonMistake" }, { - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "def is_friend(name):", " return name == \"Alice\" or \"Bob\"", @@ -5926,7 +5627,6 @@ "assert_equal(is_friend(\"Charlie\"), False)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -5938,14 +5638,8 @@ "step": "InspectWithBirdseye" }, { - "get_solution": [ - "def is_valid_percentage(x):", - " if x < 0 or x > 100:", - " return False", - " else:", - " return True" - ], - "page": "Introducing or", + "get_solution": "program", + "page": "\u4ecb\u7ecd or", "program": [ "def is_valid_percentage(x):", " if x < 0 or x > 100:", @@ -5954,26 +5648,25 @@ " return True" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "AnExercise" }, { - "page": "Introducing and", + "get_solution": "program", + "page": "\u4ecb\u7ecd and", "program": [ "True and True" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -5986,19 +5679,19 @@ "step": "TrueAndTrue" }, { - "page": "Introducing and", + "get_solution": "program", + "page": "\u4ecb\u7ecd and", "program": [ "True and False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6011,19 +5704,19 @@ "step": "TrueAndFalse" }, { - "page": "Introducing and", + "get_solution": "program", + "page": "\u4ecb\u7ecd and", "program": [ "False and False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6036,14 +5729,8 @@ "step": "FalseAndFalse" }, { - "get_solution": [ - "def is_valid_percentage(x):", - " if 0 <= x and x <= 100:", - " return True", - " else:", - " return False" - ], - "page": "Introducing and", + "get_solution": "program", + "page": "\u4ecb\u7ecd and", "program": [ "def is_valid_percentage(x):", " if 0 <= x and x <= 100:", @@ -6052,41 +5739,37 @@ " return False" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "AndExercise" }, { - "get_solution": [ - "def all_equal(row):", - " return row[0] == row[1] and row[0] == row[2]" - ], - "page": "Introducing and", + "get_solution": "program", + "page": "\u4ecb\u7ecd and", "program": [ "def all_equal(row):", " return row[0] == row[1] and row[0] == row[2]" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "TicTacToeWinningRow" }, { - "page": "Multi-line statements", + "get_solution": "program", + "page": "\u591a\u884c\u8bed\u53e5", "program": [ "is_friend = name == \"Alice\" or", " name == \"Bob\"" ], "response": { - "message": "", "passed": true, "result": [ { - "text": " is_friend = name == \"Alice\" or\n ^\nSyntaxError: invalid syntax\nat line 1\n\nA `SyntaxError` occurs when Python cannot understand your code.\n\nThe Python keyword `or` can only be used for boolean expressions.\nPerhaps you meant to write\n\n`is_friend = name == \"Alice\" ,`\n\n\n", + "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

The Python keyword or can only be used for boolean expressions.\nPerhaps you meant to write

\n

is_friend = name == \"Alice\" ,

", + "text": " is_friend = name == \"Alice\" or\n ^\nSyntaxError: invalid syntax\n\u5728\u7b2c 1\n", "type": "syntax_error" } ] @@ -6094,7 +5777,8 @@ "step": "invalid_multiline" }, { - "page": "Multi-line statements", + "get_solution": "program", + "page": "\u591a\u884c\u8bed\u53e5", "program": [ "name = \"Bob\"", "", @@ -6114,7 +5798,6 @@ " name == \"Bob\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6126,12 +5809,12 @@ "step": "valid_multiline" }, { - "page": "Combining and and or", + "get_solution": "program", + "page": "\u7ec4\u5408 and \u548c or", "program": [ "True or False and False" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6143,15 +5826,8 @@ "step": "CombiningAndOr" }, { - "get_solution": [ - "def diagonal_winner(board):", - " middle = board[1][1]", - " return (", - " (middle == board[0][0] and middle == board[2][2]) or", - " (middle == board[0][2] and middle == board[2][0])", - " )" - ], - "page": "Combining and and or", + "get_solution": "program", + "page": "\u7ec4\u5408 and \u548c or", "program": [ "def diagonal_winner(board):", " middle = board[1][1]", @@ -6161,26 +5837,25 @@ " )" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "AndHasHigherPriority" }, { - "page": "Introducing not", + "get_solution": "program", + "page": "\u4ecb\u7ecd not", "program": [ "not True" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "False", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6193,19 +5868,19 @@ "step": "IntroducingNot" }, { - "page": "Introducing not", + "get_solution": "program", + "page": "\u4ecb\u7ecd not", "program": [ "not False" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True", "choices": [ "True", "False", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6218,13 +5893,13 @@ "step": "NotFalse" }, { - "page": "Introducing not", + "get_solution": "program", + "page": "\u4ecb\u7ecd not", "program": [ "b = True", "print(not b or b)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6236,24 +5911,20 @@ "step": "NotTrueOrTrue" }, { - "get_solution": [ - "def invalid_image(filename):", - " return not (filename.endswith(\".png\") or filename.endswith(\".jpg\"))" - ], - "page": "Introducing not", + "get_solution": "program", + "page": "\u4ecb\u7ecd not", "program": [ "def invalid_image(filename):", " return not (filename.endswith(\".png\") or filename.endswith(\".jpg\"))" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "NotPriority" }, { - "page": "Checking the board for winners", + "page": "\u68c0\u67e5\u68cb\u76d8\u4e0a\u7684\u83b7\u80dc\u8005", "program": [ "def row_winner(board):", " for row in board:", @@ -6268,27 +5939,15 @@ " return False" ], "response": { - "message": "

Keep in mind that some entries might be ' '. An empty row is not a winning row.

", + "message": "

\u8bf7\u8bb0\u4f4f\uff0c\u6709\u4e9b\u6761\u76ee\u53ef\u80fd\u662f ' '\u3002\u7a7a\u884c\u4e0d\u662f\u83b7\u80dc\u884c\u3002

", "passed": false, "result": [] }, "step": "intro_row_winner" }, { - "get_solution": [ - "def row_winner(board):", - " for row in board:", - " all_equal = True", - " piece = row[0]", - " for entry in row:", - " if entry == ' ' or piece != entry:", - " all_equal = False", - " break", - " if all_equal:", - " return True", - " return False" - ], - "page": "Checking the board for winners", + "get_solution": "program", + "page": "\u68c0\u67e5\u68cb\u76d8\u4e0a\u7684\u83b7\u80dc\u8005", "program": [ "def row_winner(board):", " for row in board:", @@ -6303,27 +5962,14 @@ " return False" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "intro_row_winner" }, { - "get_solution": [ - "def column_winner(board):", - " for col in range(len(board[0])):", - " all_equal = True", - " piece = board[0][col]", - " for row in board:", - " if row[col] == ' ' or row[col] != piece:", - " all_equal = False", - " break", - " if all_equal:", - " return True", - " return False" - ], - "page": "Checking the board for winners", + "get_solution": "program", + "page": "\u68c0\u67e5\u68cb\u76d8\u4e0a\u7684\u83b7\u80dc\u8005", "program": [ "def column_winner(board):", " for col in range(len(board[0])):", @@ -6338,27 +5984,14 @@ " return False" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "column_winner" }, { - "get_solution": [ - "def diagonal_winner(board):", - " all_equal1 = True", - " all_equal2 = True", - " topleft = board[0][0]", - " topright = board[0][-1]", - " for i in range(len(board)):", - " if board[i][i] == ' ' or board[i][i] != topleft:", - " all_equal1 = False", - " if board[i][-i - 1] == ' ' or board[i][-i - 1] != topright:", - " all_equal2 = False", - " return all_equal1 or all_equal2" - ], - "page": "Checking the board for winners", + "get_solution": "program", + "page": "\u68c0\u67e5\u68cb\u76d8\u4e0a\u7684\u83b7\u80dc\u8005", "program": [ "def diagonal_winner(board):", " all_equal1 = True", @@ -6373,7 +6006,6 @@ " return all_equal1 or all_equal2" ], "response": { - "message": "", "passed": true, "result": [] }, @@ -6384,7 +6016,7 @@ "def winner(board):", " return row_winner(board) or column_winner(board) or diagonal_winner(board)" ], - "page": "Checking the board for winners", + "page": "\u68c0\u67e5\u68cb\u76d8\u4e0a\u7684\u83b7\u80dc\u8005", "program": [ "def winning_line(strings):", " piece = strings[0]", @@ -6422,14 +6054,14 @@ " return row_winner(board) or column_winner(board) or diagonal_winner(board)" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "winner" }, { - "page": "The newline character, format_board", + "get_solution": "program", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "def print_board(board):", " for row in board:", @@ -6442,7 +6074,6 @@ "])" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6454,7 +6085,8 @@ "step": "one_way_to_print_board" }, { - "page": "The newline character, format_board", + "get_solution": "program", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "assert_equal(", " format_board([", @@ -6468,11 +6100,11 @@ ")" ], "response": { - "message": "", "passed": true, "result": [ { - "text": " \"XOX\n ^\nSyntaxError: EOL while scanning string literal\nat line 7\n\nA `SyntaxError` occurs when Python cannot understand your code.\n\nYou started writing a string with a single or double quote\nbut never ended the string with another quote on that line.\n\n\n", + "friendly": "

A SyntaxError occurs when Python cannot understand your code.

\n

You started writing a string with a single or double quote\nbut never ended the string with another quote on that line.

", + "text": " \"XOX\n ^\nSyntaxError: unterminated string literal (detected at line 7)\n\u5728\u7b2c 7\n", "type": "syntax_error" } ] @@ -6480,14 +6112,14 @@ "step": "invalid_multi_line_string" }, { - "page": "The newline character, format_board", + "get_solution": "program", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "string = \"\"\"First line", "Second line\"\"\"", "print(string)" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6499,24 +6131,24 @@ "step": "multi_line_strings_triple_quotes" }, { - "page": "The newline character, format_board", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "string = 'a'" ], "response": { - "message": "

Oops, string doesn't have the right value. Run the program from the previous step again.

", + "message": "

\u54ce\u5440\uff0cstring \u7684\u503c\u4e0d\u6b63\u786e\u3002\u8bf7\u518d\u6b21\u8fd0\u884c\u4e0a\u4e00\u6b65\u7684\u7a0b\u5e8f\u3002

", "passed": false, "result": [] }, "step": "discovering_newline" }, { - "page": "The newline character, format_board", + "get_solution": "program", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "string" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6528,19 +6160,19 @@ "step": "discovering_newline" }, { - "page": "The newline character, format_board", + "get_solution": "program", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "len('\\n')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "1", "choices": [ "1", "2", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6553,17 +6185,8 @@ "step": "introducing_newline" }, { - "get_solution": [ - "def format_board(board):", - " result = ''", - " for i in range(len(board)):", - " for char in board[i]:", - " result += char", - " if i != len(board) - 1:", - " result += '\\n'", - " return result" - ], - "page": "The newline character, format_board", + "get_solution": "program", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "def format_board(board):", " result = ''", @@ -6575,25 +6198,14 @@ " return result" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "format_board_simple" }, { - "get_solution": [ - "def format_board(board):", - " joined_rows = []", - " for row in board:", - " joined_rows.append(\"|\".join(row))", - " lines = []", - " for _ in board[0]:", - " lines.append(\"-\")", - " line = f'\\n{\"+\".join(lines)}\\n'", - " return line.join(joined_rows)" - ], - "page": "The newline character, format_board", + "get_solution": "program", + "page": "\u6362\u884c\u7b26\uff0cformat_board", "program": [ "def format_board(board):", " joined_rows = []", @@ -6606,14 +6218,14 @@ " return line.join(joined_rows)" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "format_board_bonus_challenge" }, { - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "print(type('Hello World'))", "print(type(23))", @@ -6622,7 +6234,6 @@ "print(type(4.56))" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6634,12 +6245,12 @@ "step": "five_different_types" }, { - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "type(3) == int" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6651,14 +6262,14 @@ "step": "check_type_manually" }, { - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "print('123')", "print(123)", "print(123 == '123')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6670,13 +6281,13 @@ "step": "different_types_look_same" }, { - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "print(123 + 456)", "print('123' + '456')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "579\n123456", @@ -6687,7 +6298,7 @@ "123456\n'123456'", "579\n123456", "579\n'123456'", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6700,13 +6311,13 @@ "step": "plus_has_two_meanings" }, { - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "print(13 < 120)", "print('13' < '120')" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "True\nFalse", @@ -6715,7 +6326,7 @@ "True\nFalse", "False\nTrue", "False\nFalse", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6728,13 +6339,13 @@ "step": "less_than_has_two_meanings" }, { - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "print(sorted([120, 13, 0]))", "print(sorted(['120', '13', '0']))" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[0, 13, 120]\n['0', '120', '13']", @@ -6745,7 +6356,7 @@ "[120, 13, 0]\n['0', '120', '13']", "[120, 13, 0]\n['13', '120', '0']", "[120, 13, 0]\n['120', '13', '0']", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6758,21 +6369,21 @@ "step": "less_than_sorting_strings" }, { - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "12 + '34'" ], "response": { - "message": "", "passed": true, "prediction": { - "answer": "Error", + "answer": "\u9519\u8bef", "choices": [ "46", "'46'", "1234", "'1234'", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6786,11 +6397,13 @@ }, "frames": [ { + "filename": "/my_program.py", + "lineno": 1, "lines": [ { - "content": "12 + '34'", "is_current": true, "lineno": 1, + "text": "12 + '34'", "type": "line" } ], @@ -6805,7 +6418,7 @@ ], "text": [ "Traceback (most recent call last):", - " File \"my_program.py\", line 1, in ", + " File \"/my_program.py\", line 1, in ", "--> 1 | 12 + '34'", " ^^^^^^^^^", "", @@ -6823,7 +6436,7 @@ " print('Starting... ' + str(i + 1))", "print('Go!')" ], - "page": "Types", + "page": "\u7c7b\u578b", "program": [ "number = '1'", "for i in range(int(number)):", @@ -6831,7 +6444,6 @@ "print('Go!')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6843,18 +6455,8 @@ "step": "fixing_type_errors_with_conversion" }, { - "get_solution": [ - "def format_board(board):", - " first_row = ' '", - " for i in range(len(board)):", - " first_row += str(i + 1)", - " joined_rows = [first_row]", - " for i in range(len(board)):", - " joined_row = str(i + 1) + ''.join(board[i])", - " joined_rows.append(joined_row)", - " return \"\\n\".join(joined_rows)" - ], - "page": "Types", + "get_solution": "program", + "page": "\u7c7b\u578b", "program": [ "def format_board(board):", " first_row = ' '", @@ -6867,21 +6469,20 @@ " return \"\\n\".join(joined_rows)" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "format_board_with_numbers" }, { - "page": "Interactive Programs with input()", + "get_solution": "program", + "page": "\u4f7f\u7528 input() \u7684\u4e92\u52a8\u7a0b\u5e8f", "program": [ "print('Type your name, then press Enter:')", "name = input()", "print(f'Hello {name}!')" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6906,7 +6507,6 @@ }, { "get_solution": [ - "super_secret_number = 7", "print(\"What number am I thinking of?\")", "guess = input()", "if int(guess) == super_secret_number:", @@ -6914,7 +6514,7 @@ "else:", " print(\"Nope!\")" ], - "page": "Interactive Programs with input()", + "page": "\u4f7f\u7528 input() \u7684\u4e92\u52a8\u7a0b\u5e8f", "program": [ "super_secret_number = 7", "print(\"What number am I thinking of?\")", @@ -6925,7 +6525,6 @@ " print(\"Nope!\")" ], "response": { - "message": "", "passed": true, "result": [ { @@ -6949,7 +6548,8 @@ "step": "convert_input_to_int" }, { - "page": "Nested List Assignment: Playing Moves on the Board", + "get_solution": "program", + "page": "\u5d4c\u5957\u5217\u8868\u4f5c\u4e1a\uff1a\u5728\u68cb\u76d8\u4e0a\u8fdb\u884c\u79fb\u52a8", "program": [ "def play_move(board, player):", " board[1] = player", @@ -6962,7 +6562,6 @@ "play_game()" ], "response": { - "message": "", "passed": true, "prediction": { "answer": "[' ', 'X', ' ']", @@ -6976,7 +6575,7 @@ "['X', ' ', ' ']", "[' ', 'X', ' ']", "[' ', ' ', 'X']", - "Error" + "\u9519\u8bef" ] }, "result": [ @@ -6989,7 +6588,8 @@ "step": "modify_list_in_function" }, { - "page": "Nested List Assignment: Playing Moves on the Board", + "get_solution": "program", + "page": "\u5d4c\u5957\u5217\u8868\u4f5c\u4e1a\uff1a\u5728\u68cb\u76d8\u4e0a\u8fdb\u884c\u79fb\u52a8", "program": [ "def play_move(board, player):", " row = board[1]", @@ -7007,7 +6607,6 @@ "play_game()" ], "response": { - "message": "", "passed": true, "result": [ { @@ -7019,13 +6618,8 @@ "step": "nested_assignment_two_lines" }, { - "get_solution": [ - "def play_move(board, player):", - " row = int(input()) - 1", - " col = int(input()) - 1", - " board[row][col] = player" - ], - "page": "Nested List Assignment: Playing Moves on the Board", + "get_solution": "program", + "page": "\u5d4c\u5957\u5217\u8868\u4f5c\u4e1a\uff1a\u5728\u68cb\u76d8\u4e0a\u8fdb\u884c\u79fb\u52a8", "program": [ "def play_move(board, player):", " row = int(input()) - 1", @@ -7033,14 +6627,14 @@ " board[row][col] = player" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "nested_assignment_input" }, { - "page": "Making the Board", + "get_solution": "program", + "page": "\u5236\u4f5c\u68cb\u76d8", "program": [ "def make_board(size):", " row = []", @@ -7068,7 +6662,6 @@ "test()" ], "response": { - "message": "", "passed": true, "result": [ { @@ -7080,30 +6673,21 @@ "step": "naive_make_board" }, { - "page": "Making the Board", + "page": "\u5236\u4f5c\u68cb\u76d8", "program": [ "pass", "def make_board(size): return [[' '] * size] * size" ], "response": { - "message": "

The sublists in the result are not all separate objects.

", + "message": "

\u7ed9\u5b9a\u8fd9\u4e9b\u503c\uff1a

\n
size = 2\n
\n

\u4f60\u7684\u4ee3\u7801\u8f93\u51fa\uff1a

\n
[[' ', ' '], [' ', ' ']]\n
\n

\u54ea\u4e2a\u662f\u6b63\u786e\u7684\uff01

\n

\u7136\u800c\uff0c\u7ed3\u679c\u4e2d\u7684\u5b50\u5217\u8868\u5e76\u4e0d\u662f\u6240\u6709\u72ec\u7acb\u7684\u5bf9\u8c61\u3002

", "passed": false, "result": [] }, "step": "fix_make_board" }, { - "get_solution": [ - "def make_board(size):", - " board = []", - " for _ in range(size):", - " row = []", - " for _ in range(size):", - " row.append(' ')", - " board.append(row)", - " return board" - ], - "page": "Making the Board", + "get_solution": "program", + "page": "\u5236\u4f5c\u68cb\u76d8", "program": [ "def make_board(size):", " board = []", @@ -7115,7 +6699,6 @@ " return board" ], "response": { - "message": "", "passed": true, "result": [] }, @@ -7142,7 +6725,7 @@ "", " print_draw()" ], - "page": "The Full Tic-Tac-Toe Game", + "page": "\u5b8c\u6574\u7684\u4e95\u5b57\u68cb\u6e38\u620f", "program": [ "def winning_line(strings):", " strings = set(strings)", @@ -7205,10 +6788,445 @@ " print_draw()" ], "response": { - "message": "", "passed": true, "result": [] }, "step": "the_full_game" + }, + { + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french = {'apple': 'pomme', 'box': 'boite'}" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "first_dict" + }, + { + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french = {}" + ], + "response": { + "message": "

\u54ce\u5440\uff0c\u4f60\u9700\u8981\u5148\u8bbe\u7f6e french = {'apple': 'pomme', 'box': 'boite'}\uff0c\u624d\u80fd\u7ee7\u7eed\u3002

", + "passed": false, + "result": [] + }, + "step": "dict_access" + }, + { + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french[0]" + ], + "response": { + "passed": true, + "result": [ + { + "data": [ + { + "didyoumean": [], + "exception": { + "message": "0", + "type": "KeyError" + }, + "frames": [ + { + "filename": "/my_program.py", + "lineno": 1, + "lines": [ + { + "is_current": true, + "lineno": 1, + "text": "french[0]", + "type": "line" + } + ], + "name": "", + "type": "frame", + "variables": [ + { + "name": "french\n", + "value": "{'apple': 'pomme', 'box': 'boite'}\n" + } + ] + } + ], + "friendly": "

A KeyError is raised when a value is not found as a\nkey in a Python dict or in a similar object.

\n

The key 0 cannot be found in the dict french.

", + "tail": "" + } + ], + "text": [ + "Traceback (most recent call last):", + " File \"/my_program.py\", line 1, in ", + "--> 1 | french[0]", + " ^^^^^^^^^", + "french = {'apple': 'pomme', 'box': 'boite'}", + "", + "KeyError: 0" + ], + "type": "traceback" + } + ] + }, + "step": "dict_access" + }, + { + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french = {}" + ], + "response": { + "message": "

\u54ce\u5440\uff0c\u4f60\u9700\u8981\u5148\u8bbe\u7f6e french = {'apple': 'pomme', 'box': 'boite'}\uff0c\u624d\u80fd\u7ee7\u7eed\u3002

", + "passed": false, + "result": [] + }, + "step": "dict_access2" + }, + { + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french['apple']" + ], + "response": { + "passed": true, + "result": [ + { + "text": "'pomme'\n", + "type": "stdout" + } + ] + }, + "step": "dict_access2" + }, + { + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french = {}" + ], + "response": { + "message": "

\u54ce\u5440\uff0c\u4f60\u9700\u8981\u5148\u8bbe\u7f6e french = {'apple': 'pomme', 'box': 'boite'}\uff0c\u624d\u80fd\u7ee7\u7eed\u3002

", + "passed": false, + "result": [] + }, + "step": "dict_access3" + }, + { + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french['box']" + ], + "response": { + "passed": true, + "result": [ + { + "text": "'boite'\n", + "type": "stdout" + } + ] + }, + "step": "dict_access3" + }, + { + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french = {}" + ], + "response": { + "message": "

\u54ce\u5440\uff0c\u4f60\u9700\u8981\u5148\u8bbe\u7f6e french = {'apple': 'pomme', 'box': 'boite'}\uff0c\u624d\u80fd\u7ee7\u7eed\u3002

", + "passed": false, + "result": [] + }, + "step": "dict_access4" + }, + { + "get_solution": "program", + "page": "\u4ecb\u7ecd\u5b57\u5178", + "program": [ + "french['pomme']" + ], + "response": { + "passed": true, + "result": [ + { + "data": [ + { + "didyoumean": [], + "exception": { + "message": "'pomme'", + "type": "KeyError" + }, + "frames": [ + { + "filename": "/my_program.py", + "lineno": 1, + "lines": [ + { + "is_current": true, + "lineno": 1, + "text": "french['pomme']", + "type": "line" + } + ], + "name": "", + "type": "frame", + "variables": [ + { + "name": "french\n", + "value": "{'apple': 'pomme', 'box': 'boite'}\n" + } + ] + } + ], + "friendly": "

A KeyError is raised when a value is not found as a\nkey in a Python dict or in a similar object.

\n

The key 'pomme' cannot be found in the dict french.

", + "tail": "" + } + ], + "text": [ + "Traceback (most recent call last):", + " File \"/my_program.py\", line 1, in ", + "--> 1 | french['pomme']", + " ^^^^^^^^^^^^^^^", + "french = {'apple': 'pomme', 'box': 'boite'}", + "", + "KeyError: 'pomme'" + ], + "type": "traceback" + } + ] + }, + "step": "dict_access4" + }, + { + "get_solution": "program", + "page": "\u5728\u5b9e\u8df5\u4e2d\u4f7f\u7528\u5b57\u5178", + "program": [ + "def total_cost(cart, prices):", + " result = 0", + " for item in cart:", + " price = prices[item]", + " result += price", + " return result" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "shopping_cart1" + }, + { + "get_solution": "program", + "page": "\u5728\u5b9e\u8df5\u4e2d\u4f7f\u7528\u5b57\u5178", + "program": [ + "def total_cost(cart, quantities, prices):", + " result = 0", + " for item in cart:", + " price = prices[item]", + " quantity = quantities[item]", + " result += price * quantity", + " return result" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "shopping_cart4" + }, + { + "get_solution": "program", + "page": "\u5728\u5b9e\u8df5\u4e2d\u4f7f\u7528\u5b57\u5178", + "program": [ + "def substitute(string):", + " result = ''", + " for char in string:", + " if char == 'A':", + " char = 'T'", + " elif char == 'T':", + " char = 'A'", + " elif char == 'G':", + " char = 'C'", + " elif char == 'C':", + " char = 'G'", + " result += char", + " return result", + "", + "original = 'AGTAGCGTCCTTAGTTACAGGATGGCTTAT'", + "expected = 'TCATCGCAGGAATCAATGTCCTACCGAATA'", + "assert_equal(substitute(original), expected)" + ], + "response": { + "passed": true, + "result": [ + { + "text": "OK\n", + "type": "stdout" + } + ] + }, + "step": "dna_part1" + }, + { + "get_solution": "program", + "page": "\u5728\u5b9e\u8df5\u4e2d\u4f7f\u7528\u5b57\u5178", + "program": [ + "def substitute(string, d):", + " result = \"\"", + " for letter in string:", + " result += d[letter]", + " return result" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "dna_part2" + }, + { + "get_solution": "program", + "page": "\u904d\u5386\u5b57\u5178\u952e", + "program": [ + "quantities = {'apple': 1, 'cat': 10}", + "print(quantities.keys())" + ], + "response": { + "passed": true, + "result": [ + { + "text": "dict_keys(['apple', 'cat'])\n", + "type": "stdout" + } + ] + }, + "step": "introducing_keys" + }, + { + "get_solution": "program", + "page": "\u904d\u5386\u5b57\u5178\u952e", + "program": [ + "quantities = {'apple': 1, 'cat': 10}", + "for key in quantities.keys():", + " print(key)" + ], + "response": { + "passed": true, + "result": [ + { + "text": "apple\ncat\n", + "type": "stdout" + } + ] + }, + "step": "keys_are_iterable" + }, + { + "get_solution": "program", + "page": "\u904d\u5386\u5b57\u5178\u952e", + "program": [ + "quantities = {'apple': 1, 'cat': 10}", + "for key in quantities:", + " print(key)" + ], + "response": { + "passed": true, + "result": [ + { + "text": "apple\ncat\n", + "type": "stdout" + } + ] + }, + "step": "keys_are_iterable2" + }, + { + "get_solution": "program", + "page": "\u904d\u5386\u5b57\u5178\u952e", + "program": [ + "def total_cost(quantities, prices):", + " result = 0", + " for item in quantities:", + " price = prices[item]", + " quantity = quantities[item]", + " result += price * quantity", + " return result" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "cleanup_shopping_cart" + }, + { + "get_solution": "program", + "page": "\u904d\u5386\u5b57\u5178\u952e", + "program": [ + "def print_words(french):", + " for word in french:", + " print(\"English: \" + word)", + " print(\"French: \" + french[word])", + " print(\"---\")" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "english_to_french" + }, + { + "get_solution": "program", + "page": "\u904d\u5386\u5b57\u5178\u952e", + "program": [ + "def print_words(french, german):", + " for word in french:", + " print(\"English: \" + word)", + " print(\"French: \" + french[word])", + " print(\"German: \" + german[word])", + " print(\"---\")" + ], + "response": { + "passed": true, + "result": [] + }, + "step": "english_to_german" + }, + { + "get_solution": "program", + "page": "\u904d\u5386\u5b57\u5178\u952e", + "program": [ + "def print_words(words):", + " for word in words:", + " translations = words[word]", + "", + " print(f\"English: {word}\")", + " for language in translations:", + " print(f\"{language}: {translations[language]}\")", + " print(f\"---\")", + "", + "print_words({", + " 'apple': {", + " 'French': 'pomme',", + " 'German': 'apfel',", + " },", + " 'box': {", + " 'French': 'boite',", + " 'German': 'kasten',", + " },", + "})" + ], + "response": { + "passed": true, + "result": [ + { + "text": "English: apple\nFrench: pomme\nGerman: apfel\n---\nEnglish: box\nFrench: boite\nGerman: kasten\n---\n", + "type": "stdout" + } + ] + }, + "step": "nested_dictionaries" } ] \ No newline at end of file diff --git a/translations/locales/zh/LC_MESSAGES/futurecoder.mo b/translations/locales/zh/LC_MESSAGES/futurecoder.mo index e79c1c4806dd8520f7dd873878398fca2e79e183..2bae5cbd69909b0f27eb7bd2eb5e2b24f1bd9f55 100644 GIT binary patch literal 290765 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%0DT@FwI6Cp=S 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

qESgB08b)3htV57oF+hP& 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 by!dGGD;BmC*+3eXlIC(!%j!M@GxUD}L;vs# literal 103009 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 TranslationRules: + """Get translation rules for a language code.""" + try: + return cls[language_code.upper()].value + except KeyError: + raise ValueError(f"Unsupported language code: {language_code}") + + @classmethod + def add_language(cls, language_code: str, language_name: str, plural_forms: str) -> None: + """Add a new language to the supported languages. + + Args: + language_code: Two-letter language code (e.g., 'es' for Spanish) + language_name: Full name of the language + plural_forms: Plural forms expression for the language + """ + # Create new TranslationRules instance + rules = TranslationRules( + language_name=language_name, + language_code=language_code, + plural_forms=plural_forms, + context=BASE_TEACHING_CONTEXT.format(language_name=language_name) + ) + + # Add to enum + cls._member_map_[language_code.upper()] = rules + cls._member_names_.append(language_code.upper()) + cls._value2member_map_[rules] = rules + +class POFileSplitter: + def __init__(self, input_file: str, base_output_dir: str, chunk_size: int): + """Initialize the PO file splitter. + + Args: + input_file: Path to the input PO file + base_output_dir: Base directory for chunks (will create chunks/en/ subdirectory) + chunk_size: Maximum number of entries per chunk (for large chapters) + """ + self.input_file = input_file + self.base_output_dir = Path(base_output_dir) + self.en_chunks_dir = self.base_output_dir / "chunks" / "en" + self.chunk_size = chunk_size + self.logger = logging.getLogger(__name__) + self.logger.info(f"Initializing POFileSplitter with input: {input_file}, output: {self.en_chunks_dir}, max chunk size: {chunk_size}") + + def extract_chapter_name(self, msgid: str) -> str: + """Extract chapter name from msgid.""" + # Handle different msgid patterns + if msgid.startswith('pages.'): + # Extract chapter from patterns like: pages.IntroducingNestedLoops.steps.crack_password_exercise.hints.0.text + parts = msgid.split('.') + if len(parts) >= 2: + return parts[1] # IntroducingNestedLoops + elif msgid.startswith('frontend.'): + # Frontend UI elements + return 'frontend_ui' + elif 'hint' in msgid.lower(): + # Hint-related entries + return 'hints' + elif 'code_bits.' in msgid: + # Code bits + return 'code_bits' + elif any(marker in msgid for marker in ['__program__', '__code', '__copyable__']): + # Special markers + return 'special_markers' + else: + # General/uncategorized entries + return 'general' + + def split_entries(self) -> None: + """Split the PO file into chunks organized by chapters and save to chunks/en/.""" + try: + # Load the PO file + self.logger.info(f"Loading PO file: {self.input_file}") + po_file = polib.pofile(self.input_file) + total_entries = len(po_file) + self.logger.info(f"Found {total_entries} entries to split") + + # Group entries by chapter + chapters = defaultdict(list) + for entry in po_file: + chapter_name = self.extract_chapter_name(entry.msgid) + chapters[chapter_name].append(entry) + + self.logger.info(f"Organized entries into {len(chapters)} chapters:") + for chapter, entries in chapters.items(): + self.logger.info(f" - {chapter}: {len(entries)} entries") + + # Create English chunks directory + self.en_chunks_dir.mkdir(parents=True, exist_ok=True) + self.logger.info(f"Created English chunks directory: {self.en_chunks_dir}") + + # Save each chapter as one or more chunks to en/ directory + chunk_count = 0 + for chapter_name, entries in chapters.items(): + # If chapter has too many entries, split into multiple chunks + if len(entries) <= self.chunk_size: + # Single chunk for this chapter + chunk_count += 1 + chunk_file = self.en_chunks_dir / f"{chapter_name}.po" + self.save_chunk(entries, chunk_file, po_file.metadata) + self.logger.info(f"Saved chapter '{chapter_name}' to {chunk_file}") + else: + # Split large chapter into multiple chunks + num_chunks = (len(entries) + self.chunk_size - 1) // self.chunk_size + for i in range(num_chunks): + start_idx = i * self.chunk_size + end_idx = min((i + 1) * self.chunk_size, len(entries)) + chunk_entries = entries[start_idx:end_idx] + + chunk_count += 1 + chunk_file = self.en_chunks_dir / f"{chapter_name}_part{i+1:02d}.po" + self.save_chunk(chunk_entries, chunk_file, po_file.metadata) + self.logger.info(f"Saved chapter '{chapter_name}' part {i+1}/{num_chunks} to {chunk_file}") + + self.logger.info(f"Successfully split PO file into {chunk_count} chapter-based chunks in {self.en_chunks_dir}") + + except Exception as e: + self.logger.error(f"Error splitting PO file: {str(e)}") + raise + + def save_chunk(self, entries: List[polib.POEntry], chunk_file: Path, metadata: dict): + """Save a chunk of entries to a PO file.""" + chunk_po = polib.POFile() + chunk_po.metadata = metadata.copy() + chunk_po.extend(entries) + chunk_po.save(str(chunk_file)) + +class Translator: + def __init__(self, config: TranslationConfig, language_code: str): + """Initialize the translator. + + Args: + config: Translation configuration + language_code: Language code to translate to + """ + self.config = config + self.language_code = language_code + self.rules = Language.get_rules(language_code) + self.logger = logging.getLogger(__name__) + self.logger.info(f"Initialized translator for {self.rules.language_name}") + + # Initialize HTTP session + self.session = requests.Session() + self.session.headers.update({ + "Authorization": f"Bearer {config.api_key}", + "Content-Type": "application/json" + }) + + def is_chunk_translated(self, chunk_file: str) -> bool: + """Check if a chunk file is already translated.""" + try: + chunk = polib.pofile(chunk_file) + total_entries = len(chunk) + translated_entries = 0 + + for entry in chunk: + if entry.msgstr and entry.msgstr.strip(): + translated_entries += 1 + elif entry.msgstr_plural: + # Check if any plural form is translated + if any(msgstr.strip() for msgstr in entry.msgstr_plural.values()): + translated_entries += 1 + + # Consider chunk translated if at least 80% of entries are translated + translation_percentage = (translated_entries / total_entries) * 100 if total_entries > 0 else 0 + is_translated = translation_percentage >= 80 + + self.logger.debug(f"Chunk {os.path.basename(chunk_file)}: {translated_entries}/{total_entries} entries translated ({translation_percentage:.1f}%)") + + return is_translated + + except Exception as e: + self.logger.error(f"Error checking translation status of {chunk_file}: {str(e)}") + return False + + def prepare_translation_request(self, chunk: polib.POFile) -> Dict: + """Prepare the translation request payload.""" + # Convert PO entries to text format + entries_text = [] + for entry in chunk: + # Add special markers to help preserve special strings and formatting + entry_text = f"msgid: {entry.msgid}\n" + if entry.msgstr: + # Mark special strings with a unique marker + msgstr = entry.msgstr + + # Special handling for misc terms + if entry.msgid.startswith("misc_terms."): + # For misc terms, preserve all newlines and formatting exactly + msgstr = msgstr.replace('\n', '') + # Also preserve markdown formatting + msgstr = msgstr.replace('*', '') + msgstr = msgstr.replace('**', '') + msgstr = msgstr.replace('`', '') + msgstr = msgstr.replace('[', '') + msgstr = msgstr.replace(']', '') + msgstr = msgstr.replace('(', '') + msgstr = msgstr.replace(')', '') + else: + # For regular entries, just preserve newlines + msgstr = msgstr.replace('\n', '') + + # Mark special strings + msgstr = re.sub(r'(__\w+__)', r'\1', msgstr) + entry_text += f"msgstr: {msgstr}\n" + if entry.msgid_plural: + entry_text += f"msgid_plural: {entry.msgid_plural}\n" + for i, msgstr in enumerate(entry.msgstr_plural.values()): + # Mark newlines and special strings in plural forms too + msgstr = msgstr.replace('\n', '') + msgstr = re.sub(r'(__\w+__)', r'\1', msgstr) + entry_text += f"msgstr[{i}]: {msgstr}\n" + entries_text.append(entry_text) + + # Combine all entries + text_to_translate = "\n\n".join(entries_text) + self.logger.debug(f"Prepared text to translate (first 100 chars): {text_to_translate[:100]}") + + # Prepare the system message with rules + system_message = f"""You are a professional translator. Your task is to translate the following PO file entries from English to {self.rules.language_name}. + +{self.rules.context} + +The input will be in PO file format with msgid (English) and msgstr (translation) pairs. +Only translate the text in the msgstr fields, keeping all other formatting, markers, and structure exactly as is. + +Special formatting rules: +1. Special strings marked with tags must be preserved exactly as they are +2. Newlines marked with must be preserved exactly as they are, including their position and count +3. For misc_terms entries (starting with "misc_terms."): + - Preserve all newlines exactly as they appear in the original + - Preserve all markdown formatting: + * for italics (*) + * for bold (**) + * for code blocks (`) + * and for links ([ and ]) + * and for URLs (( and )) + - Keep all URLs and links unchanged + - Maintain the exact same number of newlines as the original + +Return the translated text in the same PO file format.""" + + return { + "model": self.config.model, + "messages": [ + {"role": "system", "content": system_message}, + {"role": "user", "content": text_to_translate} + ], + "temperature": 0.3 + } + + def translate_chunk(self, en_chunk_file: str, target_chunk_file: str) -> Optional[polib.POFile]: + """Translate a chunk from English to target language.""" + try: + # Check if target chunk already exists and is translated + if os.path.exists(target_chunk_file) and self.is_chunk_translated(target_chunk_file): + self.logger.info(f"Skipping already translated chunk: {os.path.basename(target_chunk_file)}") + return polib.pofile(target_chunk_file) + + self.logger.info(f"Translating {os.path.basename(en_chunk_file)} → {os.path.basename(target_chunk_file)}") + + # Load the English chunk + self.logger.debug(f"Loading English chunk: {en_chunk_file}") + chunk = polib.pofile(en_chunk_file) + self.logger.debug(f"Loaded chunk with {len(chunk)} entries") + + # Prepare translation request + payload = self.prepare_translation_request(chunk) + self.logger.debug("Prepared translation request") + + # Make API call + self.logger.debug(f"Making API call to {self.config.base_url}") + response = self.session.post(self.config.base_url, json=payload) + + if response.status_code == 200: + result = response.json() + translated_text = result['choices'][0]['message']['content'] + self.logger.debug(f"Received translation (first 100 chars): {translated_text[:100]}") + + # Parse the translated text and update the chunk + updated_chunk = self.parse_translated_text(translated_text, chunk) + + if updated_chunk: + # Ensure target directory exists + os.makedirs(os.path.dirname(target_chunk_file), exist_ok=True) + # Save to target language directory + updated_chunk.save(target_chunk_file) + self.logger.info(f"Successfully translated and saved: {os.path.basename(target_chunk_file)}") + return updated_chunk + else: + self.logger.error(f"Failed to parse translated text for {en_chunk_file}") + return None + else: + self.logger.error(f"API error {response.status_code}: {response.text}") + return None + + except Exception as e: + self.logger.error(f"Error translating chunk {en_chunk_file}: {str(e)}") + return None + + def parse_translated_text(self, translated_text: str, original_chunk: polib.POFile) -> Optional[polib.POFile]: + """Parse the translated text and update the original chunk with translations.""" + try: + self.logger.debug("Parsing translated text") + translated_lines = translated_text.split('\n') + current_entry = None + current_key = None + + for line in translated_lines: + line = line.strip() + if not line: + continue + + if line.startswith('msgid: '): + current_key = 'msgid' + msgid = line[7:].strip() + # Find the entry in the original chunk + current_entry = original_chunk.find(msgid) + if current_entry: + self.logger.debug(f"Found entry for msgid: {msgid[:50]}...") + else: + self.logger.warning(f"Could not find entry for msgid: {msgid[:50]}...") + + elif line.startswith('msgid_plural: '): + current_key = 'msgid_plural' + msgid_plural = line[14:].strip() + if current_entry and current_entry.msgid_plural == msgid_plural: + self.logger.debug(f"Found entry for msgid_plural: {msgid_plural[:50]}...") + + elif line.startswith('msgstr: '): + if current_entry and current_key == 'msgid': + translation = line[8:].strip() + + # Special handling for misc terms + if current_entry.msgid.startswith("misc_terms."): + # Restore markdown formatting + translation = translation.replace('', '*') + translation = translation.replace('', '**') + translation = translation.replace('', '`') + translation = translation.replace('', '[') + translation = translation.replace('', ']') + translation = translation.replace('', '(') + translation = translation.replace('', ')') + + # Restore newlines and special strings + translation = translation.replace('', '\n') + translation = re.sub(r'(__\w+__)', r'\1', translation) + + if translation and translation != current_entry.msgid: # Only update if actually translated + current_entry.msgstr = translation + self.logger.debug(f"Updated msgstr for entry: {current_entry.msgid[:50]}...") + + elif line.startswith('msgstr[0]: '): + if current_entry and current_key == 'msgid_plural': + translation = line[11:].strip() + # Restore newlines and special strings + translation = translation.replace('', '\n') + translation = re.sub(r'(__\w+__)', r'\1', translation) + if translation: + current_entry.msgstr_plural[0] = translation + self.logger.debug(f"Updated msgstr[0] for plural entry") + + elif line.startswith('msgstr[1]: '): + if current_entry and current_key == 'msgid_plural': + translation = line[11:].strip() + # Restore newlines and special strings + translation = translation.replace('', '\n') + translation = re.sub(r'(__\w+__)', r'\1', translation) + if translation: + current_entry.msgstr_plural[1] = translation + self.logger.debug(f"Updated msgstr[1] for plural entry") + + self.logger.debug(f"Successfully parsed translated text") + return original_chunk + + except Exception as e: + self.logger.error(f"Error parsing translated text: {str(e)}") + return None + +class TranslationMerger: + def __init__(self, chunks_dir: str, output_file: str, language_code: str): + self.chunks_dir = chunks_dir + self.output_file = output_file + self.language_code = language_code + self.logger = logging.getLogger(__name__) + # Define the locales directory path + self.locales_dir = Path(os.path.dirname(output_file)) / "locales" / language_code / "LC_MESSAGES" + self.locales_dir.mkdir(parents=True, exist_ok=True) + # Load English PO file for reference + self.english_po = polib.pofile(os.path.join(os.path.dirname(output_file), "english.po")) + + def validate_special_strings(self, entry: polib.POEntry, original_entry: polib.POEntry) -> bool: + """Validate that all special strings from the original entry are preserved in the translation.""" + try: + # Extract special strings from original entry with their positions + original_special_strings = [] + for match in re.finditer(r'(__\w+__)', original_entry.msgstr): + original_special_strings.append((match.group(1), match.start())) + + # Extract special strings from translated entry with their positions + translated_special_strings = [] + for match in re.finditer(r'(__\w+__)', entry.msgstr): + translated_special_strings.append((match.group(1), match.start())) + + # Check if we have the same number of special strings + if len(original_special_strings) != len(translated_special_strings): + self.logger.warning(f"Mismatched special strings count for {entry.msgid[:50]}...") + self.logger.warning(f"Original has {len(original_special_strings)} special strings: {[s[0] for s in original_special_strings]}") + self.logger.warning(f"Translation has {len(translated_special_strings)} special strings: {[s[0] for s in translated_special_strings]}") + return False + + # Check if each special string matches and is in a similar relative position + for (orig_str, orig_pos), (trans_str, trans_pos) in zip(original_special_strings, translated_special_strings): + if orig_str != trans_str: + self.logger.warning(f"Mismatched special string in {entry.msgid[:50]}...") + self.logger.warning(f"Original: {orig_str} at position {orig_pos}") + self.logger.warning(f"Translation: {trans_str} at position {trans_pos}") + return False + + # Calculate relative positions (as percentage of total length) + orig_rel_pos = orig_pos / len(original_entry.msgstr) + trans_rel_pos = trans_pos / len(entry.msgstr) + + # Allow some flexibility in position (within 20% of the text length) + if abs(orig_rel_pos - trans_rel_pos) > 0.2: + self.logger.warning(f"Special string {orig_str} is too far from expected position in {entry.msgid[:50]}...") + self.logger.warning(f"Original relative position: {orig_rel_pos:.2f}") + self.logger.warning(f"Translation relative position: {trans_rel_pos:.2f}") + return False + + return True + + except Exception as e: + self.logger.error(f"Error validating special strings: {str(e)}") + return False + + def fix_special_strings(self, entry: polib.POEntry, original_entry: polib.POEntry) -> polib.POEntry: + """Fix missing or misplaced special strings in the translation by copying them from the original entry.""" + try: + # Extract special strings from original entry with their context + original_special_strings = [] + original_text = original_entry.msgstr + translated_text = entry.msgstr + + # Find all special strings and their surrounding context + for match in re.finditer(r'(__\w+__)', original_text): + special_str = match.group(1) + start = max(0, match.start() - 20) # Get 20 chars before + end = min(len(original_text), match.end() + 20) # Get 20 chars after + context = original_text[start:end] + original_special_strings.append((special_str, context, match.start())) + + # For each special string in the original, ensure it exists in the translation + fixed_text = translated_text + for special_str, context, orig_pos in original_special_strings: + # Check if the special string exists in the translation + if special_str not in fixed_text: + # Find a good position to insert the special string + # Try to find similar context in the translation + context_words = set(re.findall(r'\w+', context)) + best_pos = 0 + best_match = 0 + + # Look for similar context in the translation + for i in range(len(fixed_text) - len(context) + 1): + trans_context = fixed_text[i:i + len(context)] + trans_words = set(re.findall(r'\w+', trans_context)) + common_words = len(context_words & trans_words) + if common_words > best_match: + best_match = common_words + best_pos = i + + # Insert the special string at the best position + if best_match > 0: + fixed_text = fixed_text[:best_pos] + special_str + fixed_text[best_pos:] + else: + # If no good context found, append at the end + fixed_text += f"\n{special_str}\n" + + self.logger.info(f"Added missing special string {special_str} to translation") + + # Create a new entry with the fixed translation + fixed_entry = polib.POEntry( + msgid=entry.msgid, + msgstr=fixed_text, + msgid_plural=entry.msgid_plural, + msgstr_plural=entry.msgstr_plural, + comment=entry.comment, + tcomment=entry.tcomment, + occurrences=entry.occurrences, + flags=entry.flags, + previous_msgid=entry.previous_msgid, + previous_msgid_plural=entry.previous_msgid_plural, + encoding=entry.encoding + ) + + # Validate the fix + if not self.validate_special_strings(fixed_entry, original_entry): + self.logger.warning(f"Failed to fix special strings for {entry.msgid[:50]}...") + # If validation fails, return the original entry's msgstr + fixed_entry.msgstr = original_entry.msgstr + self.logger.info(f"Using original English text for {entry.msgid[:50]}...") + + return fixed_entry + + except Exception as e: + self.logger.error(f"Error fixing special strings: {str(e)}") + return entry + + def normalize_po_file(self, po_file: str) -> bool: + """Normalize line endings and validate PO file format.""" + try: + # Read the PO file + with open(po_file, 'r', encoding='utf-8') as f: + content = f.read() + + # Normalize line endings to \n + content = content.replace('\r\n', '\n').replace('\r', '\n') + + # Parse the PO file using polib first to get proper structure + po = polib.pofile(po_file) + + # Create a new PO file with normalized entries + normalized_po = polib.POFile() + normalized_po.metadata = po.metadata.copy() + + for entry in po: + # Create a new entry + new_entry = polib.POEntry( + msgid=entry.msgid.strip(), + msgstr=entry.msgstr.strip(), + msgid_plural=entry.msgid_plural.strip() if entry.msgid_plural else None, + msgstr_plural=entry.msgstr_plural if entry.msgstr_plural else None, + comment=entry.comment, + tcomment=entry.tcomment, + occurrences=entry.occurrences, + flags=entry.flags, + previous_msgid=entry.previous_msgid, + previous_msgid_plural=entry.previous_msgid_plural, + encoding=entry.encoding + ) + normalized_po.append(new_entry) + + # Write back the normalized content + normalized_po.save(po_file) + + # Validate the normalized file + try: + polib.pofile(po_file) + self.logger.info(f"Successfully normalized and validated {po_file}") + return True + except Exception as e: + self.logger.error(f"PO file validation failed: {str(e)}") + return False + + except Exception as e: + self.logger.error(f"Error normalizing PO file: {str(e)}") + return False + + def compile_mo_file(self, po_file: str) -> bool: + """Compile PO file to MO file using msgfmt.""" + try: + # First normalize the PO file + if not self.normalize_po_file(po_file): + self.logger.error(f"Failed to normalize {po_file}") + return False + + # Always use futurecoder.mo as the output filename + mo_file = self.locales_dir / "futurecoder.mo" + + # Use msgfmt to compile the PO file to MO + result = subprocess.run( + ["msgfmt", "-o", str(mo_file), po_file], + capture_output=True, + text=True + ) + + if result.returncode == 0: + self.logger.info(f"Successfully compiled {po_file} to {mo_file}") + return True + else: + self.logger.error(f"Failed to compile {po_file}: {result.stderr}") + return False + + except Exception as e: + self.logger.error(f"Error compiling MO file: {str(e)}") + return False + + def merge_translations(self) -> None: + """Merge translated chunks into a single PO file and compile to MO.""" + self.logger.info(f"Starting merge process for {self.language_code}") + self.logger.info(f"Looking for chunks in: {self.chunks_dir}") + + # Create output directory if it doesn't exist + os.makedirs(os.path.dirname(os.path.abspath(self.output_file)), exist_ok=True) + + # Get all chunk files + chunk_files = sorted(glob.glob(os.path.join(self.chunks_dir, "*.po"))) + if not chunk_files: + self.logger.error(f"No chunk files found in {self.chunks_dir}") + all_files = glob.glob(os.path.join(self.chunks_dir, "*")) + self.logger.info(f"All files found: {all_files}") + raise FileNotFoundError(f"No chunk files found in {self.chunks_dir}") + + self.logger.info(f"Found {len(chunk_files)} chapter-based chunk files to merge") + for f in chunk_files: + self.logger.info(f" - {os.path.basename(f)}") + + # Create new PO file with metadata from english.po + try: + merged_po = polib.POFile() + merged_po.metadata = self.english_po.metadata.copy() + merged_po.metadata['Language'] = self.language_code + + # Get language rules for plural forms + language_rules = Language.get_rules(self.language_code) + merged_po.metadata['Plural-Forms'] = language_rules.plural_forms + except Exception as e: + self.logger.error(f"Failed to read english.po: {str(e)}") + raise + + # Track statistics + total_entries = 0 + translated_entries = 0 + skipped_entries = 0 + code_bits_kept = 0 + program_entries_kept = 0 + prediction_choices_kept = 0 + + # Process each translated chunk + for chunk_file in chunk_files: + self.logger.info(f"Processing translated chunk: {chunk_file}") + try: + chunk_po = polib.pofile(chunk_file) + total_entries += len(chunk_po) + + for entry in chunk_po: + if entry.msgstr and entry.msgstr.strip(): # Only include translated entries + # Find the corresponding English entry + original_entry = self.english_po.find(entry.msgid) + if original_entry: + # For Chinese and Tamil, keep certain entries in English + if self.language_code in ["zh", "ta"] and ( + entry.msgid.startswith("code_bits.") or + entry.msgid.endswith(".program") or + "output_prediction_choices" in entry.msgid + ): + entry.msgstr = original_entry.msgstr # Use English version + if entry.msgid.startswith("code_bits."): + code_bits_kept += 1 + self.logger.info(f"Keeping English code bit: {entry.msgid[:50]}...") + elif entry.msgid.endswith(".program"): + program_entries_kept += 1 + self.logger.info(f"Keeping English program entry: {entry.msgid[:50]}...") + else: + prediction_choices_kept += 1 + self.logger.info(f"Keeping English prediction choice: {entry.msgid[:50]}...") + + # Create a new entry with stripped content + new_entry = polib.POEntry( + msgid=entry.msgid.strip(), + msgstr=entry.msgstr.strip(), + msgid_plural=entry.msgid_plural.strip() if entry.msgid_plural else None, + msgstr_plural=entry.msgstr_plural if entry.msgstr_plural else None, + comment=entry.comment, + tcomment=entry.tcomment, + occurrences=entry.occurrences, + flags=entry.flags, + previous_msgid=entry.previous_msgid, + previous_msgid_plural=entry.previous_msgid_plural, + encoding=entry.encoding + ) + merged_po.append(new_entry) + translated_entries += 1 + else: + self.logger.warning(f"Skipping untranslated entry in {chunk_file}: {entry.msgid[:50]}...") + skipped_entries += 1 + + except Exception as e: + self.logger.error(f"Error processing chunk {chunk_file}: {str(e)}") + raise + + # Save the merged PO file + try: + # Save with proper formatting + merged_po.save(self.output_file) + self.logger.info(f"Successfully merged translations to {self.output_file}") + + # Normalize and compile the merged PO file to MO + if self.compile_mo_file(self.output_file): + self.logger.info(f"Successfully compiled MO file to {self.locales_dir}") + else: + self.logger.error("Failed to compile MO file") + + self.logger.info(f"Statistics:") + self.logger.info(f" Total entries: {total_entries}") + self.logger.info(f" Translated entries: {translated_entries}") + if self.language_code in ["zh", "ta"]: + self.logger.info(f" Code bits kept in English: {code_bits_kept}") + self.logger.info(f" Program entries kept in English: {program_entries_kept}") + self.logger.info(f" Prediction choices kept in English: {prediction_choices_kept}") + self.logger.info(f" Skipped entries: {skipped_entries}") + if total_entries > 0: + self.logger.info(f" Translation coverage: {(translated_entries/total_entries)*100:.1f}%") + except Exception as e: + self.logger.error(f"Failed to save merged file: {str(e)}") + raise + +def validate_language_code(language_code: str) -> bool: + """Validate if the language code is supported""" + try: + Language(language_code) + return True + except ValueError: + return False + +def translate_all_chunks(translator: Translator, base_chunks_dir: str, language_code: str, max_workers: int = 3): + """Translate all chunks from chunks/en/ to chunks/{lang}/, skipping already translated ones.""" + logger = logging.getLogger(__name__) + + en_chunks_dir = os.path.join(base_chunks_dir, "chunks", "en") + target_chunks_dir = os.path.join(base_chunks_dir, "chunks", language_code) + + # Get all English chunk files + en_chunk_files = sorted(glob.glob(os.path.join(en_chunks_dir, "*.po"))) + if not en_chunk_files: + logger.error(f"No English chunk files found in {en_chunks_dir}") + return + + logger.info(f"Found {len(en_chunk_files)} English chunk files in {en_chunks_dir}") + logger.info(f"Will translate to {target_chunks_dir}") + + # Create target directory + os.makedirs(target_chunks_dir, exist_ok=True) + + # Check which chunks need translation + chunks_to_translate = [] + already_translated = [] + + for en_chunk_file in en_chunk_files: + chunk_name = os.path.basename(en_chunk_file) + target_chunk_file = os.path.join(target_chunks_dir, chunk_name) + + if os.path.exists(target_chunk_file) and translator.is_chunk_translated(target_chunk_file): + already_translated.append((en_chunk_file, target_chunk_file)) + else: + chunks_to_translate.append((en_chunk_file, target_chunk_file)) + + logger.info(f"Translation status:") + logger.info(f" - Already translated: {len(already_translated)} chunks") + logger.info(f" - Need translation: {len(chunks_to_translate)} chunks") + + if already_translated: + logger.info("Already translated chunks:") + for en_file, target_file in already_translated: + logger.info(f" ✓ {os.path.basename(target_file)}") + + if not chunks_to_translate: + logger.info("All chunks are already translated! Skipping translation phase.") + return + + logger.info("Chunks to translate:") + for en_file, target_file in chunks_to_translate: + logger.info(f" → {os.path.basename(en_file)} → {os.path.basename(target_file)}") + + # Translate only the chunks that need translation + logger.info(f"Starting translation of {len(chunks_to_translate)} chunks using {max_workers} workers...") + + with ThreadPoolExecutor(max_workers=max_workers) as executor: + # Submit translation tasks + future_to_chunk = { + executor.submit(translator.translate_chunk, en_file, target_file): (en_file, target_file) + for en_file, target_file in chunks_to_translate + } + + completed = 0 + failed = 0 + + # Process completed tasks + for future in as_completed(future_to_chunk): + en_file, target_file = future_to_chunk[future] + try: + result = future.result() + if result is not None: + completed += 1 + logger.info(f"Progress: {completed + failed}/{len(chunks_to_translate)} - Completed: {os.path.basename(target_file)}") + else: + failed += 1 + logger.error(f"Progress: {completed + failed}/{len(chunks_to_translate)} - Failed: {os.path.basename(target_file)}") + except Exception as e: + failed += 1 + logger.error(f"Progress: {completed + failed}/{len(chunks_to_translate)} - Error: {str(e)}") + + logger.info(f"Translation completed: {completed} successful, {failed} failed") + +def main(): + parser = argparse.ArgumentParser(description="Translate Futurecoder PO files") + parser.add_argument("-l", "--language", required=True, help="Language code (e.g., zh, fr, es)") + parser.add_argument("-k", "--api-key", required=True, help="API key for translation service") + parser.add_argument("--base-url", default="https://api.openai.com/v1/chat/completions", + help="Base URL for the translation API") + parser.add_argument("-m", "--model", default="gpt-3.5-turbo", + help="Model to use for translation") + parser.add_argument("-i", "--input", default="./english.po", + help="Input PO file to translate") + parser.add_argument("-o", "--output-dir", default="./", + help="Output directory for translated files") + parser.add_argument("--max-workers", type=int, default=5, + help="Maximum number of parallel workers") + parser.add_argument("--chunk-size", type=int, default=50, + help="Number of entries per chunk") + parser.add_argument("--skip-mo", action="http://github.com/store_true", + help="Skip MO file compilation") + args = parser.parse_args() + + # Configure logging + logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + handlers=[ + logging.FileHandler(f"translation_{args.language}.log"), + logging.StreamHandler(sys.stdout) + ] + ) + logger = logging.getLogger(__name__) + + try: + # Validate language code + try: + rules = Language.get_rules(args.language) + logger.info(f"Using translation rules for {rules.language_name}") + except ValueError as e: + logger.error(str(e)) + logger.info("Supported languages: " + ", ".join(lang.value.language_name for lang in Language)) + sys.exit(1) + + # Create base chunks directory structure + base_chunks_dir = args.output_dir + en_chunks_dir = os.path.join(base_chunks_dir, "chunks", "en") + target_chunks_dir = os.path.join(base_chunks_dir, "chunks", args.language) + + logger.info(f"Directory structure:") + logger.info(f" - English chunks: {en_chunks_dir}") + logger.info(f" - Target chunks: {target_chunks_dir}") + + # Initialize components + config = TranslationConfig( + api_key=args.api_key, + base_url=args.base_url, + model=args.model + ) + + # Initialize splitter with base output directory + splitter = POFileSplitter( + input_file=args.input, + base_output_dir=base_chunks_dir, + chunk_size=args.chunk_size + ) + translator = Translator(config, args.language) + merger = TranslationMerger( + chunks_dir=target_chunks_dir, + output_file=os.path.join(args.output_dir, f"{args.language}.po"), + language_code=args.language + ) + + # Split the file into English chunks + logger.info(f"Splitting PO file from: {args.input}") + splitter.split_entries() + + # Translate chunks from en/ to {lang}/ + logger.info("Starting translation of chunks...") + translate_all_chunks(translator, base_chunks_dir, args.language, args.max_workers) + + # Merge translations and compile MO file + logger.info(f"Merging translated chunks to: {merger.output_file}") + merger.merge_translations() + + logger.info("Translation process completed successfully!") + logger.info(f"Final output files:") + logger.info(f" - PO file: {os.path.abspath(merger.output_file)}") + logger.info(f" - MO file: {os.path.abspath(merger.locales_dir / 'futurecoder.mo')}") + + except Exception as e: + logger.error(f"Translation process failed: {str(e)}", exc_info=True) + sys.exit(1) + +if __name__ == "__main__": + main() \ No newline at end of file From 2938b1c54267457c693ff6f05ecafbc61007175d Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sat, 5 Jul 2025 19:28:39 +0200 Subject: [PATCH 34/53] Add zh to languages.js --- frontend/src/languages.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/frontend/src/languages.js b/frontend/src/languages.js index 6929c5cc..a4b28b5f 100644 --- a/frontend/src/languages.js +++ b/frontend/src/languages.js @@ -95,6 +95,22 @@ const languages = [ measurementId: "G-XG7E3KF703" } }, + { + code: 'zh', + name: '中文', + url: 'https://zh.futurecoder.io/', + visible: false, + firebaseConfig: { + apiKey: "AIzaSyBqtDR34wsBxKB-QrnDY97uJ6uXSVkvb7o", + authDomain: "futurecoder-zh.firebaseapp.com", + databaseURL: "https://futurecoder-zh-default-rtdb.asia-southeast1.firebasedatabase.app/", + projectId: "futurecoder-zh", + storageBucket: "futurecoder-zh.firebasestorage.app", + messagingSenderId: "103387137175", + appId: "1:103387137175:web:a841284a28104ec4f1d5d2", + measurementId: "G-3LND5RGTWT" + }, + } ]; export let language = process.env.REACT_APP_LANGUAGE; From cef1622bbe0e535b1cec1a9ca9e8e42100bf9e6e Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sun, 6 Jul 2025 22:49:34 +0200 Subject: [PATCH 35/53] slack -> discord --- README.md | 2 +- frontend/src/Feedback.js | 4 ++-- frontend/src/english_terms.json | 2 +- homepage/index.html | 6 +++--- how_to_contribute.md | 4 ++-- translations/english.po | 4 ++-- translations/locales/es/index.html | 6 +++--- translations/locales/fr/index.html | 6 +++--- translations/locales/ta/index.html | 6 +++--- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index a5342157..a90aa76b 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ You can try it out here: https://futurecoder.io/ **Please consider [contributing](how_to_contribute.md) or [donating](https://opencollective.com/futurecoder)!** -Alternatively, [come have a chat on slack](https://join.slack.com/t/futurecoder/shared_invite/zt-tp8cmwra-CbdEeX9u3k1VyoMLDupAeQ). +Alternatively, [come have a chat on discord](https://discord.gg/KwWvQCPBjW). ## Features diff --git a/frontend/src/Feedback.js b/frontend/src/Feedback.js index 64000fe9..8e3fa86c 100644 --- a/frontend/src/Feedback.js +++ b/frontend/src/Feedback.js @@ -99,8 +99,8 @@ ${description.value.trim()}`;

  • - - {terms.chat_on_slack} + + {terms.chat_on_discord}
  • diff --git a/frontend/src/english_terms.json b/frontend/src/english_terms.json index 9cbe2504..fd4af741 100644 --- a/frontend/src/english_terms.json +++ b/frontend/src/english_terms.json @@ -34,7 +34,7 @@ "contact_directly": "Alternatively, you can contact us directly:", "send_email_to": "Email", "open_github_issue": "Open an issue on GitHub", - "chat_on_slack": "Chat on Slack", + "chat_on_discord": "Chat on Discord", "copying_solution_not_allowed": "Copying from the hints/solution area is not allowed!", "no_hints_available": "This step doesn't have any hints. Try reading the instructions and requirements again. You can still check the solution if you're really stuck.", "get_hint": "Get a hint", diff --git a/homepage/index.html b/homepage/index.html index 019fa1ae..c0bccf3a 100644 --- a/homepage/index.html +++ b/homepage/index.html @@ -467,9 +467,9 @@

    Interested in contributing code or course content?

    Contact Us

    -    - - Chat on Slack +    + + Chat on Discord

    diff --git a/how_to_contribute.md b/how_to_contribute.md index c90cd126..1877178a 100644 --- a/how_to_contribute.md +++ b/how_to_contribute.md @@ -10,7 +10,7 @@ For starters, try using the platform to see what it's like. From the [table of c Please [open an issue](https://github.com/alexmojaki/futurecoder/issues/new) about anything that's confusing, could be done better, or doesn't work. All suggestions and feedback are welcome. Tell me what interests you! -Consider adding your thoughts and ideas to [issues labeled 'discussion'](https://github.com/alexmojaki/futurecoder/issues?q=is%3Aissue+is%3Aopen+label%3Adiscussion). Or [come have a chat about anything on slack](https://join.slack.com/t/futurecoder/shared_invite/zt-tp8cmwra-CbdEeX9u3k1VyoMLDupAeQ). +Consider adding your thoughts and ideas to [issues labeled 'discussion'](https://github.com/alexmojaki/futurecoder/issues?q=is%3Aissue+is%3Aopen+label%3Adiscussion). Or [come have a chat about anything on discord](https://discord.gg/KwWvQCPBjW). The easiest way to contribute concretely is to write learning material for the course and participate in related discussions. This doesn't require any expertise beyond knowing how Python works. See [Helping with course content](#helping-with-course-content) for more information. @@ -28,7 +28,7 @@ It can be helpful to read through existing textbooks and such to find inspiratio If you want to contribute a solid bit of course with actual text, code, and exercises, open a new issue with a proposal draft just in markdown. Actually implementing course content in Python is trickier so I handle those details. If you're really curious, there's partial documentation [here](https://github.com/alexmojaki/futurecoder/wiki/How-course-content-works). -If you have some partial ideas you'd like to talk about but don't feel ready to open an issue, [come chat on slack](https://join.slack.com/t/futurecoder/shared_invite/zt-tp8cmwra-CbdEeX9u3k1VyoMLDupAeQ). +If you have some partial ideas you'd like to talk about but don't feel ready to open an issue, [come chat on discord](https://discord.gg/KwWvQCPBjW). ## Developing diff --git a/translations/english.po b/translations/english.po index ea379858..a792c24a 100644 --- a/translations/english.po +++ b/translations/english.po @@ -19655,8 +19655,8 @@ msgstr "On the bright side, your code passed ${num} test(s)!" msgid "frontend.cancel" msgstr "Cancel" -msgid "frontend.chat_on_slack" -msgstr "Chat on Slack" +msgid "frontend.chat_on_discord" +msgstr "Chat on Discord" msgid "frontend.click_for_error_details" msgstr "Click for error details" diff --git a/translations/locales/es/index.html b/translations/locales/es/index.html index 0fef0920..294f518b 100644 --- a/translations/locales/es/index.html +++ b/translations/locales/es/index.html @@ -447,9 +447,9 @@

    Interested in contributing code or course content?

    Contact Us

    -    - - Chat on Slack +    + + Chat on Discord

    diff --git a/translations/locales/fr/index.html b/translations/locales/fr/index.html index 01a73cba..39196310 100644 --- a/translations/locales/fr/index.html +++ b/translations/locales/fr/index.html @@ -523,10 +523,10 @@

    Vous souhaitez participer au développement ou proposer d

    Contacts

    -    +    - Discuter sur Slack + href="https://discord.gg/KwWvQCPBjW"> + Discuter sur Discord

    diff --git a/translations/locales/ta/index.html b/translations/locales/ta/index.html index 70ca8769..c93d6aa6 100644 --- a/translations/locales/ta/index.html +++ b/translations/locales/ta/index.html @@ -451,9 +451,9 @@

    குறியீடு அல்லது பாடந

    எங்களை தொடர்பு கொள்ள

    -    - - Slack சுலாக்கில் அரட்டை அடிக்கவும் +    + + Discord சுலாக்கில் அரட்டை அடிக்கவும்

    From 32b9973daf823bb216ae5387b97f9bbbdd2cd6fd Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Sun, 6 Jul 2025 22:50:03 +0200 Subject: [PATCH 36/53] slack -> discord --- .../locales/en/LC_MESSAGES/futurecoder.mo | Bin 297007 -> 297011 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/translations/locales/en/LC_MESSAGES/futurecoder.mo b/translations/locales/en/LC_MESSAGES/futurecoder.mo index 03910361628a1a71198bc484fa5bf0eba822d73f..35138154dc3d08816d2820fd482382644c292bd0 100644 GIT binary patch delta 22837 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 delta 22808 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 a@q{*&leAGdrPa0s{*7#HwJmz>`2PW_v|d60 From 98e3a5cb55cb53bc003c3c63a8a7d8e4ab2076ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Jul 2025 10:53:44 +0200 Subject: [PATCH 37/53] Bump on-headers and compression in /frontend (#515) Bumps [on-headers](https://github.com/jshttp/on-headers) and [compression](https://github.com/expressjs/compression). These dependencies needed to be updated together. Updates `on-headers` from 1.0.2 to 1.1.0 - [Release notes](https://github.com/jshttp/on-headers/releases) - [Changelog](https://github.com/jshttp/on-headers/blob/master/HISTORY.md) - [Commits](https://github.com/jshttp/on-headers/compare/v1.0.2...v1.1.0) Updates `compression` from 1.7.4 to 1.8.1 - [Release notes](https://github.com/expressjs/compression/releases) - [Changelog](https://github.com/expressjs/compression/blob/master/HISTORY.md) - [Commits](https://github.com/expressjs/compression/compare/1.7.4...v1.8.1) --- updated-dependencies: - dependency-name: on-headers dependency-version: 1.1.0 dependency-type: indirect - dependency-name: compression dependency-version: 1.8.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frontend/package-lock.json | 119 ++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 54 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 823fdd1f..d359ab68 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -6109,14 +6109,6 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/body-parser/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -6234,9 +6226,9 @@ } }, "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { "node": ">= 0.8" } @@ -6575,16 +6567,16 @@ } }, "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", + "bytes": "3.1.2", + "compressible": "~2.0.18", "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", "vary": "~1.1.2" }, "engines": { @@ -6604,6 +6596,33 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/comsync": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/comsync/-/comsync-0.0.8.tgz", @@ -13369,9 +13388,9 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "engines": { "node": ">= 0.8" } @@ -15218,14 +15237,6 @@ "node": ">= 0.8" } }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/raw-body/node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -22900,11 +22911,6 @@ "unpipe": "1.0.0" }, "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -22996,9 +23002,9 @@ "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==" }, "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, "call-bind": { "version": "1.0.7", @@ -23247,16 +23253,16 @@ } }, "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", + "bytes": "3.1.2", + "compressible": "~2.0.18", "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", "vary": "~1.1.2" }, "dependencies": { @@ -23272,6 +23278,16 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==" + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" } } }, @@ -28153,9 +28169,9 @@ } }, "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==" }, "once": { "version": "1.4.0", @@ -29300,11 +29316,6 @@ "unpipe": "1.0.0" }, "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", From 1125aec86f18bd428950a826e3f17567119d0da3 Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Fri, 18 Jul 2025 10:54:03 +0200 Subject: [PATCH 38/53] Warpslow (#514) * Slow down WarpSpeed, speed up AOS * translations --- homepage/index.html | 41 +++++++++++++++++------------- translations/locales/es/index.html | 41 +++++++++++++++++------------- translations/locales/fr/index.html | 41 +++++++++++++++++------------- translations/locales/ta/index.html | 41 +++++++++++++++++------------- 4 files changed, 96 insertions(+), 68 deletions(-) diff --git a/homepage/index.html b/homepage/index.html index c0bccf3a..4aec1a58 100644 --- a/homepage/index.html +++ b/homepage/index.html @@ -21,16 +21,15 @@

    -