diff --git a/frontend/src/components/GenericComponent.tsx b/frontend/src/components/GenericComponent.tsx index 5f404e3..5cc7428 100644 --- a/frontend/src/components/GenericComponent.tsx +++ b/frontend/src/components/GenericComponent.tsx @@ -14,6 +14,7 @@ type AttributeType = | 'bool' | 'float' | 'int' + | 'Quantity' | 'list' | 'method' | 'DataService' @@ -61,6 +62,19 @@ export const GenericComponent = React.memo( isInstantUpdate={isInstantUpdate} /> ); + } else if (attribute.type === 'Quantity') { + return ( + + ); } else if (attribute.type === 'NumberSlider') { return ( { - const { name, parent_path, readOnly, docString, isInstantUpdate } = props; + const { name, parent_path, readOnly, docString, isInstantUpdate, unit } = props; const renderCount = useRef(0); // Create a state for the cursor position const [cursorPosition, setCursorPosition] = useState(null); @@ -242,6 +243,7 @@ export const NumberComponent = React.memo((props: NumberComponentProps) => { onBlur={handleBlur} className={isInstantUpdate && !readOnly ? 'instantUpdate' : ''} /> + {unit && {unit}} {!readOnly && (
diff --git a/poetry.lock b/poetry.lock index 3366961..d7fb881 100644 --- a/poetry.lock +++ b/poetry.lock @@ -104,7 +104,6 @@ packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} [package.extras] colorama = ["colorama (>=0.4.3)"] @@ -551,6 +550,30 @@ files = [ {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, ] +[[package]] +name = "pint" +version = "0.22" +description = "Physical quantities module" +optional = false +python-versions = ">=3.9" +files = [ + {file = "Pint-0.22-py3-none-any.whl", hash = "sha256:6e2b3c5c2b4d9b516608bc860a417a39d66eb99c958f36540cf931d2c2e9f80f"}, + {file = "Pint-0.22.tar.gz", hash = "sha256:2d139f6abbcf3016cad7d3cec05707fe908ac4f99cf59aedfd6ee667b7a64433"}, +] + +[package.dependencies] +typing-extensions = "*" + +[package.extras] +babel = ["babel (<=2.8)"] +dask = ["dask"] +mip = ["mip (>=1.13)"] +numpy = ["numpy (>=1.19.5)"] +pandas = ["pint-pandas (>=0.3)"] +test = ["pytest", "pytest-cov", "pytest-mpl", "pytest-subtests"] +uncertainties = ["uncertainties (>=3.1.6)"] +xarray = ["xarray"] + [[package]] name = "platformdirs" version = "3.10.0" @@ -969,7 +992,6 @@ files = [ [package.dependencies] anyio = ">=3.4.0,<5" -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] @@ -1149,5 +1171,5 @@ dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] [metadata] lock-version = "2.0" -python-versions = "^3.9" -content-hash = "408c82ee6f4c1b35f33294edb6e86764560dc5140f04cd5ff438e617981555e1" +python-versions = "^3.10" +content-hash = "083c3e13b4c314c5012daa87c94566a985631385629a3ff695ffcfc22efa0f09" diff --git a/pyproject.toml b/pyproject.toml index 9e22a7d..3cf79e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ toml = "^0.10.2" python-socketio = "^5.8.0" websockets = "^11.0.3" confz = "^2.0.0" +pint = "^0.22" [tool.poetry.group.dev.dependencies] types-toml = "^0.10.8.6" diff --git a/src/pydase/data_service/data_service.py b/src/pydase/data_service/data_service.py index 3c88f24..bc8bfbf 100644 --- a/src/pydase/data_service/data_service.py +++ b/src/pydase/data_service/data_service.py @@ -8,6 +8,7 @@ from typing import Any, Optional, cast, get_type_hints import rpyc from loguru import logger +import pydase.units as u from pydase.utils.helpers import ( convert_arguments_to_hinted_types, generate_paths_from_DataService_dict, @@ -62,6 +63,9 @@ class DataService(rpyc.Service, AbstractDataService): if isinstance(current_value, float) and isinstance(__value, int): __value = float(__value) + if isinstance(current_value, u.Quantity): + __value = u.convert_to_quantity(__value, str(current_value.u)) + super().__setattr__(__name, __value) if self.__dict__.get("_initialised") and not __name == "_initialised": @@ -263,7 +267,9 @@ class DataService(rpyc.Service, AbstractDataService): prop: property = getattr(self.__class__, key) result[key] = { "type": type(value).__name__, - "value": value, + "value": value + if not isinstance(value, u.Quantity) + else {"magnitude": value.m, "unit": str(value.u)}, "readonly": prop.fset is None, "doc": inspect.getdoc(prop), } @@ -279,7 +285,9 @@ class DataService(rpyc.Service, AbstractDataService): else: result[key] = { "type": type(value).__name__, - "value": value, + "value": value + if not isinstance(value, u.Quantity) + else {"magnitude": value.m, "unit": str(value.u)}, "readonly": False, } diff --git a/src/pydase/frontend/asset-manifest.json b/src/pydase/frontend/asset-manifest.json index 68b1e4b..daa227c 100644 --- a/src/pydase/frontend/asset-manifest.json +++ b/src/pydase/frontend/asset-manifest.json @@ -1,13 +1,13 @@ { "files": { "main.css": "/static/css/main.d5ec2545.css", - "main.js": "/static/js/main.b51434ec.js", + "main.js": "/static/js/main.09e2d82a.js", "index.html": "/index.html", "main.d5ec2545.css.map": "/static/css/main.d5ec2545.css.map", - "main.b51434ec.js.map": "/static/js/main.b51434ec.js.map" + "main.09e2d82a.js.map": "/static/js/main.09e2d82a.js.map" }, "entrypoints": [ "static/css/main.d5ec2545.css", - "static/js/main.b51434ec.js" + "static/js/main.09e2d82a.js" ] } \ No newline at end of file diff --git a/src/pydase/frontend/index.html b/src/pydase/frontend/index.html index 2b805b0..9965a75 100644 --- a/src/pydase/frontend/index.html +++ b/src/pydase/frontend/index.html @@ -1 +1 @@ -pydase App
\ No newline at end of file +pydase App
\ No newline at end of file diff --git a/src/pydase/frontend/static/js/main.09e2d82a.js b/src/pydase/frontend/static/js/main.09e2d82a.js new file mode 100644 index 0000000..2b755d1 --- /dev/null +++ b/src/pydase/frontend/static/js/main.09e2d82a.js @@ -0,0 +1,3 @@ +/*! For license information please see main.09e2d82a.js.LICENSE.txt */ +!function(){var e={694:function(e,t){var n;!function(){"use strict";var r={}.hasOwnProperty;function a(){for(var e=[],t=0;t