mirror of
https://github.com/pyscript/pyscript.git
synced 2026-03-26 08:00:05 -04:00
Import PyScript Version into Python Runtime (#958)
* Import current version as PyScript.__version__ and PyScript.version_info * Add integration, python unit tests * Mock pyscript.py with __mocks__/pyscript.js to make jest tests happy
This commit is contained in:
8
docs/reference/API/__version__.md
Normal file
8
docs/reference/API/__version__.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# `__version__`
|
||||
|
||||
`PyScript.__version__` is a `str` representing the current version of PyScript in a human-readable form. For a structured version more suitable to comparisons, and for details of what each part of the version number represents, see [`version_info`](version_info.md)
|
||||
|
||||
```shell
|
||||
>>> pyscript.__version__
|
||||
'2023.02.1.dev'
|
||||
```
|
||||
16
docs/reference/API/versIon_info.md
Normal file
16
docs/reference/API/versIon_info.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# `version_info`
|
||||
|
||||
`PyScript.version_info` is a `namedtuple` representing the current version of PyScript. It can be used to compare whether current version precedes or follows a desired version. For a human-readable version of the same info, see [`__version__`](__version__.md)
|
||||
|
||||
```sh
|
||||
>>> pyscript.version_info
|
||||
version_info(year=2023, month=2, minor=1, releaselevel='dev')
|
||||
```
|
||||
|
||||
## Version Fields
|
||||
| **parameter** | **CalVer equivalent field** | **example value** | **description** |
|
||||
|---------------|-------------------------|---------------|------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `year` | Full year (YYYY) | 2023 | The year of the release; when printed or represented as a string, always written with 4 digits |
|
||||
| `month` | Short Month (MM) | 2 | The month of the release; when printed or represented as a string, written with 1 or 2 digits as necessary |
|
||||
| `minor` | | 1 | The incremental number of the release for this month; when printed or represented as a string, written with 1 or two digits as necessary |
|
||||
| `releaselevel` | | 'dev' | A string representing the qualifications of this build. |
|
||||
14
pyscriptjs/__mocks__/_pyscript.js
Normal file
14
pyscriptjs/__mocks__/_pyscript.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* this file mocks the `src/python/pyscript.py` file
|
||||
* since importing of `.py` files isn't usually supported
|
||||
* inside JS/TS files.
|
||||
*
|
||||
* It sets the value of whatever is imported from
|
||||
* `src/python/pyscript.py` the contents of that file
|
||||
*
|
||||
* This is needed since the imported object is further
|
||||
* passed to a function which only accepts a string.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
module.exports = fs.readFileSync('./src/python/pyscript.py', 'utf8');
|
||||
@@ -1,12 +1,16 @@
|
||||
/**
|
||||
* this file mocks the `src/python/pyscript.py` file
|
||||
* since importing of `.py` files isn't usually supported
|
||||
* inside JS/TS files.
|
||||
*
|
||||
* It sets the value of whatever is imported from
|
||||
* `src/python/pyscript.py` to be an empty string i.e. ""
|
||||
* this file mocks python files that are not explicitly
|
||||
* matched by a regex in jest.config.js, since importing of
|
||||
* `.py` files isn't usually supported inside JS/TS files.
|
||||
*
|
||||
* This is needed since the imported object is further
|
||||
* passed to a function which only accepts a string.
|
||||
*
|
||||
* The mocked contents of the `.py` file will be "", e.g.
|
||||
* nothing.
|
||||
*/
|
||||
module.exports = "";
|
||||
|
||||
console.warn(`.py files that are not explicitly mocked in \
|
||||
jest.config.js and /__mocks__/ are mocked as empty strings`);
|
||||
|
||||
module.exports = "";
|
||||
|
||||
@@ -17,6 +17,7 @@ module.exports = {
|
||||
url: 'http://localhost',
|
||||
},
|
||||
moduleNameMapper: {
|
||||
'^.*?pyscript\.py$': '<rootDir>/__mocks__/_pyscript.js',
|
||||
'^[./a-zA-Z0-9$_-]+\\.py$': '<rootDir>/__mocks__/fileMock.js',
|
||||
'\\.(css)$': '<rootDir>/__mocks__/cssMock.js',
|
||||
},
|
||||
|
||||
@@ -5,6 +5,7 @@ import type { loadPyodide as loadPyodideDeclaration, PyodideInterface, PyProxy }
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
import pyscript from './python/pyscript.py';
|
||||
import { version } from './runtime';
|
||||
import type { AppConfig } from './pyconfig';
|
||||
import type { Stdio } from './stdio';
|
||||
|
||||
@@ -71,6 +72,7 @@ export class PyodideRuntime extends Runtime {
|
||||
|
||||
logger.info('importing pyscript.py');
|
||||
this.run(pyscript as string);
|
||||
this.run(`PyScript.set_version_info('${version}')`)
|
||||
|
||||
logger.info('pyodide loaded and initialized');
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import base64
|
||||
import html
|
||||
import io
|
||||
import time
|
||||
from collections import namedtuple
|
||||
from textwrap import dedent
|
||||
|
||||
import micropip # noqa: F401
|
||||
@@ -136,6 +137,39 @@ class PyScript:
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def set_version_info(cls, version_from_runtime: str):
|
||||
"""Sets the __version__ and version_info properties from provided JSON data
|
||||
Args:
|
||||
version_from_runtime (str): A "dotted" representation of the version:
|
||||
YYYY.MM.m(m).releaselevel
|
||||
Year, Month, and Minor should be integers; releaselevel can be any string
|
||||
"""
|
||||
|
||||
# __version__ is the same string from runtime.ts
|
||||
cls.__version__ = version_from_runtime
|
||||
|
||||
# version_info is namedtuple: (year, month, minor, releaselevel)
|
||||
version_parts = version_from_runtime.split(".")
|
||||
version_dict = {
|
||||
"year": int(version_parts[0]),
|
||||
"month": int(version_parts[1]),
|
||||
"minor": int(version_parts[2]),
|
||||
}
|
||||
|
||||
# If the version only has three parts (e.g. 2022.09.1), let the releaselevel be ""
|
||||
try:
|
||||
version_dict["releaselevel"] = version_parts[3]
|
||||
except IndexError:
|
||||
version_dict["releaselevel"] = ""
|
||||
|
||||
# Format mimics sys.version_info
|
||||
_VersionInfo = namedtuple("version_info", version_dict.keys())
|
||||
cls.version_info = _VersionInfo(**version_dict)
|
||||
|
||||
# tidy up class namespace
|
||||
del cls.set_version_info
|
||||
|
||||
|
||||
def set_current_display_target(target_id):
|
||||
get_current_display_target._id = target_id
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import re
|
||||
|
||||
import pytest
|
||||
|
||||
from .support import JsErrors, PyScriptTest
|
||||
@@ -147,3 +149,26 @@ class TestBasic(PyScriptTest):
|
||||
|
||||
pyscript_tag = self.page.locator("py-script")
|
||||
assert pyscript_tag.inner_html() == ""
|
||||
|
||||
def test_python_version(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-script>
|
||||
import js
|
||||
js.console.log(PyScript.__version__)
|
||||
js.console.log(str(PyScript.version_info))
|
||||
</py-script>
|
||||
"""
|
||||
)
|
||||
assert (
|
||||
re.match(r"\d{4}\.\d{2}\.\d+\.[a-zA-Z0-9]+", self.console.log.lines[-2])
|
||||
is not None
|
||||
)
|
||||
assert (
|
||||
re.match(
|
||||
r"version_info\(year=\d{4}, month=\d{2}, "
|
||||
r"minor=\d+, releaselevel='[a-zA-Z0-9]+'\)",
|
||||
self.console.log.lines[-1],
|
||||
)
|
||||
is not None
|
||||
)
|
||||
|
||||
@@ -117,3 +117,10 @@ def test_uses_top_level_await():
|
||||
"""
|
||||
)
|
||||
assert pyscript.uses_top_level_await(src) is False
|
||||
|
||||
|
||||
def test_set_version_info():
|
||||
version_string = "1234.56.78.ABCD"
|
||||
pyscript.PyScript.set_version_info(version_string)
|
||||
assert pyscript.PyScript.__version__ == version_string
|
||||
assert pyscript.PyScript.version_info == (1234, 56, 78, "ABCD")
|
||||
|
||||
Reference in New Issue
Block a user