diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..70880ca --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,71 @@ +# Contributing to [Project Name] + +This document provides guidelines and instructions for contributing to the project. + + +## Getting Started + +1. Fork the repository +2. Clone your fork: + ```bash + git clone https://github.com/your-username/project-name.git + cd project-name + ``` +3. Create a new branch, be descriptive: + ```bash + git checkout -b feature/your-feature-name + + # OR + + git checkout -b bugfix/bug-this-pr-fixes + + # OR + + git checkout -b docs/documenting-something + ``` + +## Development Workflow + +### Testing + +- Implement your feature/changes +- Test any code changes thoroughly +- Make sure your PR contains all the information for any developer to checkout your branch and validate it + + +### Commit Guidelines (not enforced but nice) + +- Your commit message should be under 72 characters +- Your commit message should start with a topic (e.g.: "Docs: ") +- Sign-off your commits with `git commit -sm "Feature: Commit subject under 72 characters."` + +## Submitting Changes + +1. Push your changes to your fork +2. Submit a pull request towards the `development` branch of this repository +3. Ensure the PR description clearly describes the problem and solution +4. Include the relevant issue number if applicable + +### Pull Request Process + +1. Update documentation if needed: anyone should be able to checkout your branch and validate the changes +2. Add tests for new features +3. Wait for review +4. Upon approval, if you have write access you can merge your PR + +### New version/release (maintainers only) + +The branch `main` is always assumed to be stable, and new versions are created from there. +To create a new version of this module: + +1. Create a new branch from `main` and name it as the new version (e.g.: `v1.5.5`) +1. Update the `"version"` field in `package.json` +1. Run `npm install` to update `package-lock.json` +1. Validate the above +1. Commit and push these changes +1. Open a PR from this new branch to `main` to align version numbers + + +## License + +By contributing, you agree that your contributions will be licensed under the project's license. diff --git a/cli.js b/cli.js index 124d37a..7a13be2 100755 --- a/cli.js +++ b/cli.js @@ -82,7 +82,7 @@ const executeString = (args, port, dataConsumer) => { const code = args[0] || '' return board.open(port) .then(() => board.enter_raw_repl()) - .then(() => board.exec_raw({ command: code, data_consumer: dataConsumer })) + .then(() => board.exec_raw(code, dataConsumer)) .then(async (out) => { await board.exit_raw_repl() await board.close() @@ -140,7 +140,8 @@ const getFile = (args, port, dataConsumer) => { return board.open(port) .then(async () => { try { - let output = await board.fs_cat(boardFilename, consumer) + let output = await board.fs_cat_binary(boardFilename, consumer) + output = Buffer.from(output); fs.writeFileSync(diskFilename, output) log('output') log(output) diff --git a/examples/07_save_file.js b/examples/07_save_file.js index c0f806e..5729b0a 100644 --- a/examples/07_save_file.js +++ b/examples/07_save_file.js @@ -4,6 +4,7 @@ let content = ` """ Test """ +# Emoji TEST πŸ’©πŸ€―πŸ«ΆπŸΌ from time import sleep from machine import Pin diff --git a/examples/big_file.py b/examples/big_file.py index f9affdf..8994a6c 100644 --- a/examples/big_file.py +++ b/examples/big_file.py @@ -36,7 +36,7 @@ # When the following number is sampled at four consecutive # even-numbered bits it will have two bits set, but sampling at four # consecutive odd-numbered bits will only yield one bit set. - +# 😌πŸ₯²πŸ™πŸΌπŸ’© _WAVE_MAGIC = 0b0000011100000111 class Stepper: diff --git a/examples/test.py b/examples/test.py index 62f1fe9..a110c7e 100644 --- a/examples/test.py +++ b/examples/test.py @@ -1,7 +1,7 @@ """ Test """ - +# πŸ™πŸΌ from time import sleep print("start OK \r\n") diff --git a/micropython.js b/micropython.js index 1317687..5bec72b 100644 --- a/micropython.js +++ b/micropython.js @@ -25,6 +25,12 @@ function extract(out) { return out.slice(2, -3) } +function extractBytes(out, cut_before = 2, cut_after = 3) { + bytes = out.slice(cut_before, -cut_after) + bytes = bytes.split(',').map(Number) + return bytes +} + class MicroPythonBoard { constructor() { this.port = null @@ -204,6 +210,7 @@ class MicroPythonBoard { command += ` print(1)\n` command += `except OSError:\n` command += ` print(0)\n` + command += `del f\n` await this.enter_raw_repl() let output = await this.exec_raw(command) await this.exit_raw_repl() @@ -234,11 +241,13 @@ class MicroPythonBoard { let command = `import uos\n` command += `try:\n` command += ` l=[]\n` - command += ` for file in uos.ilistdir("${folderPath}"):\n` - command += ` l.append(list(file))\n` + command += ` for f in uos.ilistdir("${folderPath}"):\n` + command += ` l.append(list(f))\n` command += ` print(l)\n` command += `except OSError:\n` command += ` print([])\n` + command += `del l\n` + command += `del f\n` await this.enter_raw_repl() let output = await this.exec_raw(command) await this.exit_raw_repl() @@ -250,11 +259,31 @@ class MicroPythonBoard { return Promise.resolve(files) } + async fs_cat_binary(filePath) { + if (filePath) { + await this.enter_raw_repl() + const chunkSize = 256 + let command = `with open('${filePath}','rb') as f:\n` + command += ` while 1:\n` + command += ` b=f.read(${chunkSize})\n` + command += ` if not b:break\n` + command += ` print(",".join(str(e) for e in b),end=',')\n` + command += `del f\n` + command += `del b\n` + let output = await this.exec_raw(command) + + await this.exit_raw_repl() + output = extractBytes(output, 2, 4) + return Promise.resolve((output)) + } + return Promise.reject(new Error(`Path to file was not specified`)) + } + async fs_cat(filePath) { if (filePath) { await this.enter_raw_repl() let output = await this.exec_raw( - `with open('${filePath}','r') as f:\n while 1:\n b=f.read(256)\n if not b:break\n print(b,end='')` + `with open('${filePath}','r') as f:\n while 1:\n b=f.read(256)\n if not b:break\n print(b,end='')\ndel f\ndel b\n` ) await this.exit_raw_repl() output = extract(output) @@ -266,24 +295,19 @@ class MicroPythonBoard { async fs_put(src, dest, data_consumer) { data_consumer = data_consumer || function() {} if (src && dest) { - const contentBuffer = fs.readFileSync(path.resolve(src)) - let contentString = contentBuffer.toString() - contentString = fixLineBreak(contentString) - const hexArray = contentString.split('').map( - c => c.charCodeAt(0).toString(16).padStart(2, '0') - ) + const fileContent = fs.readFileSync(path.resolve(src), 'binary') + const contentBuffer = Buffer.from(fileContent, 'binary') let out = '' out += await this.enter_raw_repl() - out += await this.exec_raw(`f=open('${dest}','w')\nw=f.write`) + out += await this.exec_raw(`f=open('${dest}','wb')\nw=f.write`) const chunkSize = 48 - for (let i = 0; i < hexArray.length; i+= chunkSize) { - let slice = hexArray.slice(i, i+chunkSize) - let bytes = slice.map(h => `0x${h}`) - let line = `w(bytes([${bytes.join(',')}]))` + for (let i = 0; i < contentBuffer.length; i+= chunkSize) { + let slice = Uint8Array.from(contentBuffer.subarray(i, i+chunkSize)) + let line = `w(bytes([${slice}]))` out += await this.exec_raw(line) - data_consumer( parseInt((i / hexArray.length) * 100) + '%') + data_consumer( parseInt((i / contentBuffer.length) * 100) + '%') } - out += await this.exec_raw(`f.close()`) + out += await this.exec_raw(`f.close()\ndel f\ndel w\n`) out += await this.exit_raw_repl() return Promise.resolve(out) } @@ -293,22 +317,18 @@ class MicroPythonBoard { async fs_save(content, dest, data_consumer) { data_consumer = data_consumer || function() {} if (content && dest) { - let contentString = fixLineBreak(content) - const hexArray = contentString.split('').map( - c => c.charCodeAt(0).toString(16).padStart(2, '0') - ) + const contentBuffer = Buffer.from(content, 'utf-8') let out = '' out += await this.enter_raw_repl() - out += await this.exec_raw(`f=open('${dest}','w')\nw=f.write`) + out += await this.exec_raw(`f=open('${dest}','wb')\nw=f.write`) const chunkSize = 48 - for (let i = 0; i < hexArray.length; i+= chunkSize) { - let slice = hexArray.slice(i, i+chunkSize) - let bytes = slice.map(h => `0x${h}`) - let line = `w(bytes([${bytes.join(',')}]))` + for (let i = 0; i < contentBuffer.length; i+= chunkSize) { + let slice = Uint8Array.from(contentBuffer.subarray(i, i+chunkSize)) + let line = `w(bytes([${slice}]))` out += await this.exec_raw(line) - data_consumer( parseInt((i / hexArray.length) * 100) + '%') + data_consumer( parseInt((i / contentBuffer.length) * 100) + '%') } - out += await this.exec_raw(`f.close()`) + out += await this.exec_raw(`f.close()\ndel f\ndel w\n`) out += await this.exit_raw_repl() return Promise.resolve(out) } else { diff --git a/package-lock.json b/package-lock.json index 623bd6c..b5256b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "micropython.js", - "version": "1.4.3", + "version": "1.5.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "micropython.js", - "version": "1.4.3", + "version": "1.5.1", "dependencies": { "serialport": "^10.4.0" }, diff --git a/package.json b/package.json index b46b237..62cae7b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "micropython.js", - "version": "1.4.3", + "version": "1.5.1", "description": "Interpretation of pyboard.py in javascript", "main": "micropython.js", "scripts": {