From 507e2c929833e97075a94e94a42ef85f88fe66f8 Mon Sep 17 00:00:00 2001 From: Alex Hall Date: Wed, 1 Nov 2023 20:27:37 +0200 Subject: [PATCH 01/81] European Spanish translation (#441) --- core/runner/friendly_traceback.py | 5 +- frontend/src/languages.js | 20 +- homepage/index.html | 3 + scripts/deploy.sh | 2 - tests/golden_files/es/test_transcript.json | 1135 ++++++++++------- tests/test_frontend.py | 1 + .../es-latam/LC_MESSAGES/futurecoder.mo | Bin 0 -> 292732 bytes .../locales/es/LC_MESSAGES/futurecoder.mo | Bin 292732 -> 317107 bytes translations/locales/es/index.html | 541 ++++++++ translations/locales/fr/index.html | 3 + translations/locales/ta/index.html | 3 + translations/manual_programs.json | 84 ++ 12 files changed, 1305 insertions(+), 492 deletions(-) create mode 100644 translations/locales/es-latam/LC_MESSAGES/futurecoder.mo create mode 100644 translations/locales/es/index.html diff --git a/core/runner/friendly_traceback.py b/core/runner/friendly_traceback.py index 5fcbde2a..b3ce5808 100644 --- a/core/runner/friendly_traceback.py +++ b/core/runner/friendly_traceback.py @@ -15,7 +15,10 @@ linecache.getlines = old_getlines # undo friendly monkeypatching -friendly_traceback.set_lang(t.current_language or "en") +friendly_language = t.current_language or "en" +if friendly_language == "es-latam": + friendly_language = "es" +friendly_traceback.set_lang(friendly_language) def friendly_message(e, double_newline: bool): diff --git a/frontend/src/languages.js b/frontend/src/languages.js index 64eb5be7..cfbc6afc 100644 --- a/frontend/src/languages.js +++ b/frontend/src/languages.js @@ -15,6 +15,22 @@ const languages = [ measurementId: "G-ZKCE9KY52F", }, }, + { + code: 'es', + name: 'Español', + url: 'https://es.futurecoder.io/', + visible: true, + firebaseConfig: { + apiKey: "AIzaSyDkTwvLhDE53S5I-AjdKQQ4aFv305kSrfc", + authDomain: "futurecoder-es.firebaseapp.com", + databaseURL: "https://futurecoder-es-default-rtdb.europe-west1.firebasedatabase.app/", + projectId: "futurecoder-es", + storageBucket: "futurecoder-es.appspot.com", + messagingSenderId: "748547684459", + appId: "1:748547684459:web:10c851e2fe701d3234192e", + measurementId: "G-72RVB6YHN3" + } + }, { code: 'fr', name: 'Français', @@ -32,8 +48,8 @@ const languages = [ } }, { - code: 'es', - name: 'Español', + code: 'es-latam', + name: 'Español (Argentina)', url: 'https://es-latam.futurecoder.io/', visible: false, firebaseConfig: { diff --git a/homepage/index.html b/homepage/index.html index 52216bc2..cd99f20e 100644 --- a/homepage/index.html +++ b/homepage/index.html @@ -31,6 +31,9 @@
- 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 43/81] 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 44/81] 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 45/81] 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 46/81] 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 47/81] 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 48/81] 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 49/81] 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 50/81] 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 51/81] 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 52/81] 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 53/81] 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 54/81] 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 55/81] 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 56/81] 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 57/81] 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 58/81] 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 59/81] 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 60/81] 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 61/81] 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 62/81] 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 63/81] 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 64/81] 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 65/81] 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 66/81] 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 @@

    -