mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-14 10:35:11 +00:00
+33
-3
@@ -2,7 +2,35 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
## [2.0.0-beta.2]
|
||||
## [Unreleased]
|
||||
|
||||
## [2.0.0-beta.3] - 2022-07-06
|
||||
|
||||
### Changed
|
||||
- Updated dependencies.
|
||||
- Updated firmware to Pybricks v3.2.0b2:
|
||||
|
||||
### Added
|
||||
- Added `Motor.stalled()` method.
|
||||
|
||||
### Fixed
|
||||
- Fixed motor not stopping at the end of `run_until_stalled` ([support#662]).
|
||||
- Fixed incorrect battery current reading on Technic hub ([support#665]).
|
||||
- Fixed non-zero speed reported when motor stalled.
|
||||
- Fixed I/O devices not syncing at high baud rate.
|
||||
- Fixed `ENODEV` error while device connection manager is busy ([support#674]).
|
||||
|
||||
### Changed
|
||||
- Reworked internal motor model that is used to estimate speed.
|
||||
- Speed methods now use estimated speed instead of reported speed.
|
||||
- Changed drive base default speed to go a little slower.
|
||||
- Updated MicroPython to v1.19.
|
||||
|
||||
[support#662]: https://github.com/pybricks/support/issues/662
|
||||
[support#665]: https://github.com/pybricks/support/issues/665
|
||||
[support#674]: https://github.com/pybricks/support/issues/674
|
||||
|
||||
## [2.0.0-beta.2] - 2022-06-24
|
||||
|
||||
### Added
|
||||
- Added basic intellisense to the code editor.
|
||||
@@ -281,16 +309,18 @@
|
||||
- Updated hub firmware to [v3.0.0].
|
||||
- Updated documentation.
|
||||
|
||||
[v3.0.0]: https://github.com/pybricks/pybricks-micropython/blob/master/CHANGELOG.md#300---2021-06-08
|
||||
|
||||
## Prerelease
|
||||
|
||||
Prerelease changes are documented at [support#48].
|
||||
|
||||
[support#48]: https://github.com/pybricks/support/issues/48
|
||||
[v3.0.0]: https://github.com/pybricks/pybricks-micropython/blob/master/CHANGELOG.md#300---2021-06-08
|
||||
|
||||
<!-- links for version headings -->
|
||||
|
||||
[Unreleased]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.2...HEAD
|
||||
[Unreleased]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.3...HEAD
|
||||
[2.0.0-beta.3]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.2...v2.0.0-beta.3
|
||||
[2.0.0-beta.2]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.1...v2.0.0-beta.2
|
||||
[2.0.0-beta.1]: https://github.com/pybricks/pybricks-code/compare/v1.2.0-beta.1...v2.0.0-beta.1
|
||||
[1.2.0-beta.1]: https://github.com/pybricks/pybricks-code/compare/v1.1.0...v1.2.0-beta.1
|
||||
|
||||
@@ -601,8 +601,8 @@ module.exports = function (webpackEnv) {
|
||||
new CopyPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: 'node_modules/@pybricks/ide-docs/html',
|
||||
to: 'static/docs',
|
||||
from: `${path.dirname(require.resolve('@pybricks/ide-docs/package.json'))}/html`,
|
||||
to: `static/docs/v${require('@pybricks/ide-docs/package.json').version}/`,
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
||||
+3
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@pybricks/pybricks-code",
|
||||
"version": "2.0.0-beta.2",
|
||||
"version": "2.0.0-beta.3",
|
||||
"license": "MIT",
|
||||
"author": "The Pybricks Authors",
|
||||
"repository": {
|
||||
@@ -12,9 +12,10 @@
|
||||
"@blueprintjs/core": "^4.5.0",
|
||||
"@blueprintjs/popover2": "^1.4.1",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
|
||||
"@pybricks/firmware": "4.15.0",
|
||||
"@pybricks/firmware": "4.16.1",
|
||||
"@pybricks/ide-docs": "2.2.0",
|
||||
"@pybricks/mpy-cross-v5": "^2.0.0",
|
||||
"@pybricks/mpy-cross-v6": "^2.0.0",
|
||||
"@reduxjs/toolkit": "^1.8.3",
|
||||
"@shopify/react-i18n": "^7.1.3",
|
||||
"@svgr/webpack": "^6.2.1",
|
||||
|
||||
+4
-3
@@ -1,7 +1,10 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import 'react-splitter-layout/lib/index.css';
|
||||
import './app.scss';
|
||||
import { Classes } from '@blueprintjs/core';
|
||||
import docsPackage from '@pybricks/ide-docs/package.json';
|
||||
import { getFocusableTreeWalker } from '@react-aria/focus';
|
||||
import React, {
|
||||
FocusEventHandler,
|
||||
@@ -20,8 +23,6 @@ import StatusBar from '../status-bar/StatusBar';
|
||||
import Terminal from '../terminal/Terminal';
|
||||
import Toolbar from '../toolbar/Toolbar';
|
||||
import { isMacOS } from '../utils/os';
|
||||
import 'react-splitter-layout/lib/index.css';
|
||||
import './app.scss';
|
||||
|
||||
const Docs: React.VFC = () => {
|
||||
const { setIsSettingShowDocsEnabled } = useSettingIsShowDocsEnabled();
|
||||
@@ -119,7 +120,7 @@ const Docs: React.VFC = () => {
|
||||
contentWindow.document.documentElement.classList.add(Classes.DARK);
|
||||
}
|
||||
}}
|
||||
src="static/docs/index.html"
|
||||
src={`static/docs/v${docsPackage.version}/index.html`}
|
||||
allowFullScreen={true}
|
||||
role="documentation"
|
||||
width="100%"
|
||||
|
||||
@@ -392,10 +392,9 @@ const Editor: React.VFC = () => {
|
||||
() => ({
|
||||
id: 'pybricks.action.check',
|
||||
label: i18n.translate(I18nId.Check),
|
||||
// REVISIT: the compile options here might need to be changed - hopefully there is
|
||||
// one setting that works for all hub types for cases where we aren't connected.
|
||||
run: (e) => {
|
||||
dispatch(compile(e.getValue(), []));
|
||||
// for checking, use the most recent compiler
|
||||
dispatch(compile(e.getValue(), 6, []));
|
||||
},
|
||||
keybindings: [monaco.KeyCode.F2],
|
||||
}),
|
||||
|
||||
@@ -107,6 +107,7 @@ describe('flashFirmware', () => {
|
||||
action = await saga.take();
|
||||
expect(action).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"abiVersion": 5,
|
||||
"options": Array [
|
||||
"-mno-unicode",
|
||||
],
|
||||
@@ -622,6 +623,7 @@ describe('flashFirmware', () => {
|
||||
action = await saga.take();
|
||||
expect(action).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"abiVersion": 5,
|
||||
"options": Array [
|
||||
"-mno-unicode",
|
||||
],
|
||||
@@ -767,6 +769,7 @@ describe('flashFirmware', () => {
|
||||
action = await saga.take();
|
||||
expect(action).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"abiVersion": 5,
|
||||
"options": Array [
|
||||
"-mno-unicode",
|
||||
],
|
||||
@@ -861,6 +864,7 @@ describe('flashFirmware', () => {
|
||||
action = await saga.take();
|
||||
expect(action).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"abiVersion": 5,
|
||||
"options": Array [
|
||||
"-mno-unicode",
|
||||
],
|
||||
@@ -964,6 +968,7 @@ describe('flashFirmware', () => {
|
||||
action = await saga.take();
|
||||
expect(action).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"abiVersion": 5,
|
||||
"options": Array [
|
||||
"-mno-unicode",
|
||||
],
|
||||
@@ -1107,6 +1112,7 @@ describe('flashFirmware', () => {
|
||||
action = await saga.take();
|
||||
expect(action).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"abiVersion": 5,
|
||||
"options": Array [
|
||||
"-mno-unicode",
|
||||
],
|
||||
@@ -1236,6 +1242,7 @@ describe('flashFirmware', () => {
|
||||
let action = await saga.take();
|
||||
expect(action).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"abiVersion": 5,
|
||||
"options": Array [
|
||||
"-mno-unicode",
|
||||
],
|
||||
@@ -1477,6 +1484,7 @@ describe('flashFirmware', () => {
|
||||
let action = await saga.take();
|
||||
expect(action).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"abiVersion": 5,
|
||||
"options": Array [
|
||||
"-mno-unicode",
|
||||
],
|
||||
@@ -1536,6 +1544,7 @@ describe('flashFirmware', () => {
|
||||
let action = await saga.take();
|
||||
expect(action).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"abiVersion": 5,
|
||||
"options": Array [
|
||||
"-mno-unicode",
|
||||
],
|
||||
@@ -1596,6 +1605,7 @@ describe('flashFirmware', () => {
|
||||
let action = await saga.take();
|
||||
expect(action).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"abiVersion": 5,
|
||||
"options": Array [
|
||||
"-mno-unicode",
|
||||
],
|
||||
@@ -1659,6 +1669,7 @@ describe('flashFirmware', () => {
|
||||
let action = await saga.take();
|
||||
expect(action).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"abiVersion": 5,
|
||||
"options": Array [
|
||||
"-mno-unicode",
|
||||
],
|
||||
@@ -1759,6 +1770,7 @@ describe('flashFirmware', () => {
|
||||
action = await saga.take();
|
||||
expect(action).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"abiVersion": 5,
|
||||
"options": Array [
|
||||
"-mno-unicode",
|
||||
],
|
||||
|
||||
@@ -207,7 +207,9 @@ function* loadFirmware(
|
||||
yield* disconnectAndCancel();
|
||||
}
|
||||
|
||||
yield* put(compile(program, metadata['mpy-cross-options']));
|
||||
yield* put(
|
||||
compile(program, metadata['mpy-abi-version'], metadata['mpy-cross-options']),
|
||||
);
|
||||
const { mpy, mpyFail } = yield* race({
|
||||
mpy: take(didCompile),
|
||||
mpyFail: take(didFailToCompile),
|
||||
|
||||
+2
-1
@@ -13,8 +13,9 @@ export const checksum = createAction((checksum: number) => ({
|
||||
|
||||
// High-level hub actions.
|
||||
|
||||
export const downloadAndRun = createAction(() => ({
|
||||
export const downloadAndRun = createAction((abiVersion: number) => ({
|
||||
type: 'hub.action.downloadAndRun',
|
||||
abiVersion,
|
||||
}));
|
||||
|
||||
export const didStartDownload = createAction(() => ({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2021 The Pybricks Authors
|
||||
// Copyright (c) 2021-2022 The Pybricks Authors
|
||||
|
||||
import { AnyAction } from 'redux';
|
||||
import { didReceiveStatusReport } from '../ble-pybricks-service/actions';
|
||||
@@ -19,6 +19,7 @@ test('initial state', () => {
|
||||
expect(reducers(undefined, {} as AnyAction)).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"downloadProgress": null,
|
||||
"mpyAbiVersion": 6,
|
||||
"runtime": "hub.runtime.disconnected",
|
||||
}
|
||||
`);
|
||||
|
||||
+18
-1
@@ -2,9 +2,12 @@
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { Reducer, combineReducers } from 'redux';
|
||||
import * as semver from 'semver';
|
||||
import { bleDIServiceDidReceiveFirmwareRevision } from '../ble-device-info-service/actions';
|
||||
import { didReceiveStatusReport } from '../ble-pybricks-service/actions';
|
||||
import { Status, statusToFlag } from '../ble-pybricks-service/protocol';
|
||||
import { didConnect, didDisconnect } from '../ble/actions';
|
||||
import { pythonVersionToSemver } from '../utils/version';
|
||||
import {
|
||||
didFailToFinishDownload,
|
||||
didFinishDownload,
|
||||
@@ -118,4 +121,18 @@ const downloadProgress: Reducer<number | null> = (state = null, action) => {
|
||||
return state;
|
||||
};
|
||||
|
||||
export default combineReducers({ runtime, downloadProgress });
|
||||
const mpyAbiVersion: Reducer<number> = (state = 6, action) => {
|
||||
if (bleDIServiceDidReceiveFirmwareRevision.matches(action)) {
|
||||
// HACK: there is not a good way to get the supported MPY ABI version
|
||||
// from a running hub, so we use heuristics on the firmware version.
|
||||
if (semver.satisfies(pythonVersionToSemver(action.version), '>=3.2.0-beta.2')) {
|
||||
return 6;
|
||||
}
|
||||
|
||||
return 5;
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
export default combineReducers({ runtime, downloadProgress, mpyAbiVersion });
|
||||
|
||||
@@ -31,7 +31,7 @@ describe('downloadAndRun', () => {
|
||||
|
||||
saga.updateState({ editor: { isReady: true } });
|
||||
|
||||
saga.put(downloadAndRun());
|
||||
saga.put(downloadAndRun(5));
|
||||
|
||||
// first, it gets the value from the current editor
|
||||
const editorValueAction = await saga.take();
|
||||
@@ -41,7 +41,7 @@ describe('downloadAndRun', () => {
|
||||
|
||||
// then it tries to compile the program in the current editor
|
||||
const compileAction = await saga.take();
|
||||
expect(compileAction).toEqual(compile('', ['-mno-unicode']));
|
||||
expect(compileAction).toEqual(compile('', 5, ['-mno-unicode']));
|
||||
saga.put(didCompile(new Uint8Array(30)));
|
||||
|
||||
// then it notifies that loading has begun
|
||||
|
||||
+9
-2
@@ -46,10 +46,17 @@ function* waitForWrite(id: number): SagaGenerator<{
|
||||
});
|
||||
}
|
||||
|
||||
function* handleDownloadAndRun(): Generator {
|
||||
function* handleDownloadAndRun(action: ReturnType<typeof downloadAndRun>): Generator {
|
||||
const script = yield* editorGetValue();
|
||||
|
||||
yield* put(compile(script, ['-mno-unicode']));
|
||||
yield* put(
|
||||
compile(
|
||||
script,
|
||||
action.abiVersion,
|
||||
// no-unicode option was removed in MPY ABI v6
|
||||
action.abiVersion < 6 ? ['-mno-unicode'] : [],
|
||||
),
|
||||
);
|
||||
|
||||
const { mpy, mpyFail } = yield* race({
|
||||
mpy: take(didCompile),
|
||||
|
||||
+9
-6
@@ -1,14 +1,17 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020,2022 The Pybricks Authors
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { createAction } from '../actions';
|
||||
|
||||
/** Action that requests that a script is compiled. */
|
||||
export const compile = createAction((script: string, options: string[]) => ({
|
||||
type: 'mpy.action.compile',
|
||||
script,
|
||||
options,
|
||||
}));
|
||||
export const compile = createAction(
|
||||
(script: string, abiVersion: number, options: string[]) => ({
|
||||
type: 'mpy.action.compile',
|
||||
script,
|
||||
abiVersion,
|
||||
options,
|
||||
}),
|
||||
);
|
||||
|
||||
export const didCompile = createAction((data: Uint8Array) => ({
|
||||
type: 'mpy.action.didCompile',
|
||||
|
||||
+5
-10
@@ -1,33 +1,28 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020,2022 The Pybricks Authors
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { AsyncSaga } from '../../test';
|
||||
import { compile, didCompile, didFailToCompile } from './actions';
|
||||
import mpy from './sagas';
|
||||
|
||||
enum MpyFeatureFlags {
|
||||
MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE = 1 << 0,
|
||||
MICROPY_PY_BUILTINS_STR_UNICODE = 1 << 1,
|
||||
}
|
||||
|
||||
test('compiler works', async () => {
|
||||
const saga = new AsyncSaga(mpy);
|
||||
|
||||
saga.put(compile('print("hello!")', []));
|
||||
saga.put(compile('print("hello!")', 6, []));
|
||||
|
||||
const action = await saga.take();
|
||||
expect(didCompile.matches(action)).toBeTruthy();
|
||||
const { data } = action as ReturnType<typeof didCompile>;
|
||||
expect(data[0]).toBe('M'.charCodeAt(0));
|
||||
expect(data[1]).toBe(5); // ABI version
|
||||
expect(data[2]).toBe(MpyFeatureFlags.MICROPY_PY_BUILTINS_STR_UNICODE);
|
||||
expect(data[1]).toBe(6); // ABI version
|
||||
expect(data[2]).toBe(0); // flags
|
||||
expect(data[3]).toBe(31); // small int bits
|
||||
});
|
||||
|
||||
test('compiler error works', async () => {
|
||||
const saga = new AsyncSaga(mpy);
|
||||
|
||||
saga.put(compile('syntax error!', []));
|
||||
saga.put(compile('syntax error!', 6, []));
|
||||
|
||||
const action = await saga.take();
|
||||
expect(didFailToCompile.matches(action)).toBeTruthy();
|
||||
|
||||
+53
-16
@@ -1,8 +1,10 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020,2022 The Pybricks Authors
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { compile as mpyCrossCompile } from '@pybricks/mpy-cross-v5';
|
||||
import wasm from '@pybricks/mpy-cross-v5/build/mpy-cross.wasm';
|
||||
import { compile as mpyCrossCompileV5 } from '@pybricks/mpy-cross-v5';
|
||||
import wasmV5 from '@pybricks/mpy-cross-v5/build/mpy-cross.wasm';
|
||||
import { compile as mpyCrossCompileV6 } from '@pybricks/mpy-cross-v6';
|
||||
import wasmV6 from '@pybricks/mpy-cross-v6/build/mpy-cross-v6.wasm';
|
||||
import { call, put, takeEvery } from 'typed-redux-saga/macro';
|
||||
import { compile, didCompile, didFailToCompile } from './actions';
|
||||
|
||||
@@ -12,19 +14,54 @@ import { compile, didCompile, didFailToCompile } from './actions';
|
||||
* @param action A mpy compile action.
|
||||
*/
|
||||
function* handleCompile(action: ReturnType<typeof compile>): Generator {
|
||||
const result = yield* call(() =>
|
||||
mpyCrossCompile(
|
||||
'main.py',
|
||||
action.script,
|
||||
action.options,
|
||||
// HACK: testing user agent for jsdom is needed only for getting unit tests to work
|
||||
navigator.userAgent.includes('jsdom') ? undefined : wasm,
|
||||
),
|
||||
);
|
||||
if (result.status === 0 && result.mpy) {
|
||||
yield* put(didCompile(result.mpy));
|
||||
} else {
|
||||
yield* put(didFailToCompile(result.err));
|
||||
switch (action.abiVersion) {
|
||||
case 5:
|
||||
{
|
||||
const result = yield* call(() =>
|
||||
mpyCrossCompileV5(
|
||||
'main.py',
|
||||
action.script,
|
||||
action.options,
|
||||
// HACK: testing user agent for jsdom is needed only for getting unit tests to work
|
||||
navigator.userAgent.includes('jsdom') ? undefined : wasmV5,
|
||||
),
|
||||
);
|
||||
if (result.status === 0 && result.mpy) {
|
||||
yield* put(didCompile(result.mpy));
|
||||
} else {
|
||||
yield* put(didFailToCompile(result.err));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
{
|
||||
const result = yield* call(() =>
|
||||
mpyCrossCompileV6(
|
||||
'main.py',
|
||||
action.script,
|
||||
action.options,
|
||||
// HACK: testing user agent for jsdom is needed only for getting unit tests to work
|
||||
navigator.userAgent.includes('jsdom') ? undefined : wasmV6,
|
||||
),
|
||||
);
|
||||
if (result.status === 0 && result.mpy) {
|
||||
yield* put(didCompile(result.mpy));
|
||||
} else {
|
||||
yield* put(didFailToCompile(result.err));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
yield* put(
|
||||
didFailToCompile([
|
||||
`unsupported MPY ABI version: ${action.abiVersion}`,
|
||||
]),
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,5 +20,5 @@ it('should dispatch action when clicked', async () => {
|
||||
|
||||
await user.click(button.getByRole('button', { name: 'Run' }));
|
||||
|
||||
expect(dispatch).toHaveBeenCalledWith(downloadAndRun());
|
||||
expect(dispatch).toHaveBeenCalledWith(downloadAndRun(6));
|
||||
});
|
||||
|
||||
@@ -14,6 +14,7 @@ type RunButtonProps = Pick<ActionButtonProps, 'id'>;
|
||||
|
||||
const RunButton: React.VoidFunctionComponent<RunButtonProps> = ({ id }) => {
|
||||
const downloadProgress = useSelector((s) => s.hub.downloadProgress);
|
||||
const mpyAbiVersion = useSelector((s) => s.hub.mpyAbiVersion);
|
||||
const runtime = useSelector((s) => s.hub.runtime);
|
||||
const isEditorReady = useSelector((s) => s.editor.isReady);
|
||||
const keyboardShortcut = 'F5';
|
||||
@@ -37,7 +38,7 @@ const RunButton: React.VoidFunctionComponent<RunButtonProps> = ({ id }) => {
|
||||
enabled={isEditorReady && runtime === HubRuntimeState.Idle}
|
||||
showProgress={runtime === HubRuntimeState.Loading}
|
||||
progress={downloadProgress === null ? undefined : downloadProgress}
|
||||
onAction={() => dispatch(downloadAndRun())}
|
||||
onAction={() => dispatch(downloadAndRun(mpyAbiVersion))}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2260,12 +2260,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@pybricks/firmware@npm:4.15.0":
|
||||
version: 4.15.0
|
||||
resolution: "@pybricks/firmware@npm:4.15.0"
|
||||
"@pybricks/firmware@npm:4.16.1":
|
||||
version: 4.16.1
|
||||
resolution: "@pybricks/firmware@npm:4.16.1"
|
||||
dependencies:
|
||||
jszip: ^3.7.1
|
||||
checksum: 9aed7ff24b3d00103e4da9e6470cfb5246baa204551ed0e70c166d3206d5027dc5d6f322fe8d2d36d085ac7bb6895ad8d2ab819d514f2709dff4635efb25afbf
|
||||
checksum: 37c136f4d32dfac4938279ef7dc2eb9fcd1635a5f650161e54ba0f60050217be8f34bbc1632adec1b8bb566929db205e874c4eacb6fa2174b6d6dfa936b97a21
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -2283,6 +2283,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@pybricks/mpy-cross-v6@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "@pybricks/mpy-cross-v6@npm:2.0.0"
|
||||
checksum: 219f28d7d6f28252a13b65b29db436aa75d8d3cac14c852102a65e51e94b985ad1f2f3deb56cda83205d7125c4158264d463a2d6a13ea193fa4ac04590524f19
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@pybricks/pybricks-code@workspace:.":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@pybricks/pybricks-code@workspace:."
|
||||
@@ -2291,9 +2298,10 @@ __metadata:
|
||||
"@blueprintjs/core": ^4.5.0
|
||||
"@blueprintjs/popover2": ^1.4.1
|
||||
"@pmmmwh/react-refresh-webpack-plugin": ^0.5.7
|
||||
"@pybricks/firmware": 4.15.0
|
||||
"@pybricks/firmware": 4.16.1
|
||||
"@pybricks/ide-docs": 2.2.0
|
||||
"@pybricks/mpy-cross-v5": ^2.0.0
|
||||
"@pybricks/mpy-cross-v6": ^2.0.0
|
||||
"@reduxjs/toolkit": ^1.8.3
|
||||
"@shopify/react-i18n": ^7.1.3
|
||||
"@svgr/webpack": ^6.2.1
|
||||
|
||||
Reference in New Issue
Block a user