diff --git a/.github/workflows/electron-build.yml b/.github/workflows/electron-build.yml index c18adf0b..73ea0e70 100644 --- a/.github/workflows/electron-build.yml +++ b/.github/workflows/electron-build.yml @@ -3,7 +3,7 @@ name: App build on: push: branches: - - "0.11.0" + - "update-package-versions" defaults: run: @@ -46,11 +46,11 @@ jobs: # - name: Install Watertap locally # working-directory: ../ - # run: git clone https://github.com/MichaelPesce/watertap.git && cd watertap && git fetch --all && git checkout 0.11.0 && pip install --progress-bar off . + # run: git clone https://github.com/MichaelPesce/watertap.git && cd watertap && git fetch --all && git checkout update-pydantic && pip install --progress-bar off . - name: Install Watertap locally working-directory: ../ - run: git clone https://github.com/watertap-org/watertap.git && cd watertap && git fetch --all --tags && git checkout 0.11.0 && pip install --progress-bar off . + run: git clone https://github.com/watertap-org/watertap.git && cd watertap && pip install --progress-bar off . - name: Transfer Entry points run: | @@ -194,7 +194,7 @@ jobs: - name: Install Watertap locally working-directory: ../ - run: git clone https://github.com/watertap-org/watertap.git && cd watertap && git fetch --all --tags && git checkout 0.9.0rc0 && pip install --progress-bar off . + run: git clone https://github.com/watertap-org/watertap.git && cd watertap && pip install --progress-bar off . - name: Transfer Entry points run: | diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 53863cce..7e39ede9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -64,9 +64,9 @@ jobs: # working-directory: ../ # run: git clone https://github.com/MichaelPesce/watertap.git && cd watertap && git fetch --all && git checkout build-options && pip install --progress-bar off . - - name: Install correct branch of watertap - working-directory: ../ - run: git clone https://github.com/MichaelPesce/watertap.git && cd watertap && pip install --progress-bar off . + # - name: Install correct branch of watertap + # working-directory: ../ + # run: git clone https://github.com/MichaelPesce/watertap.git && cd watertap && pip install --progress-bar off . - name: Display installed environment run: | @@ -129,9 +129,13 @@ jobs: run: | pip install --progress-bar off . + - name: Install httpx + run: | + pip install httpx + # - name: Install my fork of watertap # working-directory: ../ - # run: git clone https://github.com/MichaelPesce/watertap.git && cd watertap && git fetch --all && git checkout build-options && pip install --progress-bar off . + # run: git clone https://github.com/MichaelPesce/watertap.git && cd watertap && git fetch --all && git checkout update-pydantic && pip install --progress-bar off . - name: get idaes extensions run: idaes get-extensions diff --git a/backend/app/internal/flowsheet_manager.py b/backend/app/internal/flowsheet_manager.py index ded9e9ad..e831080a 100644 --- a/backend/app/internal/flowsheet_manager.py +++ b/backend/app/internal/flowsheet_manager.py @@ -16,12 +16,12 @@ from pathlib import Path import time from types import ModuleType -from typing import Optional, Dict, List +from typing import Optional, Dict, List, Union import app # third-party from fastapi import HTTPException -from pydantic import BaseModel, validator +from pydantic import BaseModel, validator, field_validator, ValidationInfo, Field import tinydb # JSON single-file 'database' # package-local @@ -40,18 +40,18 @@ class FlowsheetInfo(BaseModel): # static information id_: str name: str - description: str = "" + description: Union[None, str] = Field(default="", validate_default=True) module: str = "" build_options: dict = {} # current status of flowsheet built: bool = False ts: float = 0 # time last updated (including built) - last_run: str = "" + last_run: Union[str, float] = "" custom: bool = False # Make sure name is lowercase - @validator("name") - def normalize_name(cls, v: str, values): + @field_validator("name") + def normalize_name(cls, v: str, info: ValidationInfo): return v.lower() def updated(self, built: Optional[bool] = None): diff --git a/backend/app/internal/settings.py b/backend/app/internal/settings.py index fcbefba4..c2eab55c 100644 --- a/backend/app/internal/settings.py +++ b/backend/app/internal/settings.py @@ -3,28 +3,29 @@ """ from pathlib import Path import logging -from typing import List -from pydantic import ( - BaseSettings, - validator -) +from typing import List, Union +from pydantic import validator, field_validator +from pydantic_settings import BaseSettings + class AppSettings(BaseSettings): #: List of package names in which to look for flowsheets packages: List[str] = ["watertap"] - data_basedir: Path = None - log_dir: Path = None - custom_flowsheets_dir: Path = None + data_basedir: Union[Path, None] = None + log_dir: Union[Path, None] = None + custom_flowsheets_dir: Union[Path, None] = None - @validator("data_basedir", always=True) + # @validator("data_basedir", always=True) + @field_validator("data_basedir") def validate_data_basedir(cls, v): if v is None: v = Path.home() / ".watertap" / "flowsheets" v.mkdir(parents=True, exist_ok=True) return v - @validator("log_dir", always=True) + # @validator("log_dir", always=True) + @field_validator("log_dir") def validate_log_dir(cls, v): if v is None: v = Path.home() / ".watertap" / "logs" @@ -35,7 +36,8 @@ def validate_log_dir(cls, v): logging.basicConfig(level=logging.INFO, format=loggingFormat, handlers=[loggingFileHandler]) return v - @validator("custom_flowsheets_dir", always=True) + # @validator("custom_flowsheets_dir", always=True) + @field_validator("custom_flowsheets_dir") def validate_custom_flowsheets_dir(cls, v): if v is None: v = Path.home() / ".watertap" / "custom_flowsheets" diff --git a/backend/app/main-hooks/hook-watertap.py b/backend/app/main-hooks/hook-watertap.py index 7fdbffa7..ffda61a0 100644 --- a/backend/app/main-hooks/hook-watertap.py +++ b/backend/app/main-hooks/hook-watertap.py @@ -102,21 +102,20 @@ 'pyomo.contrib.mcpp.plugins', 'pyomo.contrib.mindtpy.plugins', 'pyomo.contrib.multistart.plugins', 'pyomo.contrib.preprocessing.plugins', 'pyomo.contrib.pynumero.plugins', 'pyomo.contrib.trustregion.plugins', 'pyomo.repn.util', 'pyomo.contrib.gdpbb', 'pyomo.contrib.gdpbb.plugins', 'pint', 'numbers', - 'pyutilib', 'pyomo', 'pyomo.environ', 'pyomo.age', 'pyomo.bilevel', 'pyomo.bilevel.plugins', - 'pyomo.core', 'pyomo.core.plugins', 'pyomo.dae', 'pyomo.dae.plugins', 'pyomo.gdp', 'pyomo.gdp.plugins', - 'pyomo.neos', 'pyomo.neos.plugins', 'pyomo.opt', 'pyomo.opt.plugins', 'pyomo.pysp', 'pyomo.pysp.plugins', - 'pyomo.solvers.plugins', 'pyomo.solvers', 'pyomo.checker', 'pyomo.checker.plugins', 'pyomo.contrib', - 'pyomo.contrib.plugins', 'pyomo.dataportal', 'pyomo.dataportal.plugins', 'pyomo.duality', - 'pyomo.duality.plugins', 'pyomo.kernel', 'pyomo.kernel.plugins', 'pyomo.mpec', 'pyomo.mpec.plugins', + 'pyutilib', 'pyomo', 'pyomo.environ', 'pyomo.core', 'pyomo.core.plugins', 'pyomo.dae', 'pyomo.dae.plugins', + 'pyomo.gdp', 'pyomo.gdp.plugins', 'pyomo.neos', 'pyomo.neos.plugins', 'pyomo.opt', 'pyomo.opt.plugins', + 'pyomo.pysp', 'pyomo.pysp.plugins', 'pyomo.solvers.plugins', 'pyomo.solvers', 'pyomo.contrib', + 'pyomo.dataportal', 'pyomo.dataportal.plugins', 'pyomo.duality', 'pyomo.contrib.solver.plugins', + 'pyomo.duality.plugins', 'pyomo.kernel', 'pyomo.mpec', 'pyomo.mpec.plugins', 'pyomo.contrib.solver', 'pyomo.network', 'pyomo.network.plugins', 'pyomo.repn', 'pyomo.repn.plugins', 'pyomo.scripting', - 'pyomo.scripting.plugins', 'pyomo.util', 'pyomo.util.plugins', 'pyomo.common', 'pyomo.common.plugins', + 'pyomo.scripting.plugins', 'pyomo.util', 'pyomo.common', 'pyomo.common.plugins', 'sys', 'logging', 're', 'sys', 'pyomo.core.expr.numvalue', 'pyomo.core.expr.numvalue', 'pyomo.solvers.plugins.solvers.direct_solver', 'pyomo.solvers.plugins.solvers.direct_or_persistent_solver', 'pyomo.core.kernel.component_set', 'pyomo.core.kernel.component_map', 'pyomo.opt.results.results_', 'pyomo.opt.results.solution', 'pyomo.opt.results.solver', 'pyomo.opt.base', 'pyomo.core.base.suffix', 'pyomo.core.base.var', 'pyomo.core.base.PyomoModel', 'pyomo.solvers.plugins.solvers.persistent_solver', 'pyomo.opt.base.problem', 'pyomo.opt.base.convert', 'pyomo.opt.base.formats', 'pyomo.opt.base.results', - 'pyomo.core.base.block', 'pyomo.core.kernel.block', 'pyomo.core.kernel.suffix','pyomo.contrib.cp.plugins' + 'pyomo.core.base.block', 'pyomo.core.kernel.block', 'pyomo.core.kernel.suffix','pyomo.contrib.cp.plugins', ] hiddenimports.extend(pyomo_imports) diff --git a/backend/app/routers/flowsheets.py b/backend/app/routers/flowsheets.py index 7588e1b4..cf00bb7e 100644 --- a/backend/app/routers/flowsheets.py +++ b/backend/app/routers/flowsheets.py @@ -12,8 +12,7 @@ from fastapi.responses import StreamingResponse from fastapi.responses import FileResponse import pandas as pd -from pydantic import BaseModel -from pydantic.error_wrappers import ValidationError +from pydantic import ValidationError import re # package-local @@ -37,7 +36,7 @@ flowsheet_manager = FlowsheetManager() -@router.get("/", response_model=Dict[str, Union[List[FlowsheetInfo], int]]) +@router.get("/", response_model=Dict[str, Union[List, int]]) async def get_all(): """Get basic information about all available flowsheets. @@ -77,8 +76,12 @@ async def get_config(id_: str, build: str = "0") -> FlowsheetExport: flowsheet = flowsheet_manager.get_obj(id_) if build == "1": info = flowsheet_manager.get_info(id_) + _log.info(f"build param is 1, got info") flowsheet.build(build_options=flowsheet.fs_exp.build_options) + _log.info(f"BUILT FLOWSHEET CHUZ") info.updated(built=True) + _log.info(f"updated has been confirmed") + _log.info(f"returning flowsheett .fs_exp") return flowsheet.fs_exp diff --git a/backend/requirements-dev.txt b/backend/requirements-dev.txt index 90a461b0..a40539d6 100644 --- a/backend/requirements-dev.txt +++ b/backend/requirements-dev.txt @@ -5,18 +5,18 @@ certifi==2021.10.8 click==8.1.3 fastapi==0.78.0 h11==0.12.0 +httpx==0.27.0 idna==3.3 -pydantic==1.9.1 +pydantic==2.6.4 +pydantic-settings==2.2.1 pyinstaller==5.3 -pyinstaller-hooks-contrib==2022.9 python-multipart==0.0.5 chardet pyyaml sniffio==1.2.0 -starlette==0.19.1 tinydb requests -typing_extensions==4.2.0 +typing_extensions==4.9.0 uvicorn==0.17.6 importlib_resources==5.9.0 ; python_version < "3.10" # install watertap from main diff --git a/backend/requirements.txt b/backend/requirements.txt index e080adb3..012c18f0 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -3,21 +3,21 @@ anyio==3.6.1 asgiref==3.5.2 certifi==2021.10.8 click==8.1.3 -fastapi==0.78.0 +fastapi==0.110.0 h11==0.13.0 idna==3.3 -pydantic==1.9.1 +pydantic==2.6.4 +pydantic-settings==2.2.1 pyinstaller==5.3 -pyinstaller-hooks-contrib==2022.9 python-multipart==0.0.5 chardet pyyaml requests tinydb sniffio==1.2.0 -starlette==0.19.1 -typing_extensions==4.2.0 +typing_extensions==4.9.0 uvicorn==0.17.6 importlib_resources==5.9.0 ; python_version < "3.10" git+https://github.com/watertap-org/watertap.git +# watertap @ git+https://github.com/MichaelPesce/watertap@update-pydantic diff --git a/backend/tests/app/routers/test_flowsheets.py b/backend/tests/app/routers/test_flowsheets.py index c4e2ad9c..cf0c36b0 100644 --- a/backend/tests/app/routers/test_flowsheets.py +++ b/backend/tests/app/routers/test_flowsheets.py @@ -268,9 +268,7 @@ def test_download(client, flowsheet_id): client, flowsheet_id, "download", compare_data, get_body=False ) assert response.status_code == 200 - csv_data = "" - for chunk in response.iter_content(65536): - csv_data += str(chunk, encoding="utf-8") + csv_data = str(response.content, encoding="utf-8") if "\r\n" in csv_data: sep = "\r\n" else: diff --git a/electron/ui/src/components/FlowsheetsListTable/FlowsheetsListTable.js b/electron/ui/src/components/FlowsheetsListTable/FlowsheetsListTable.js index ab673351..a41ee588 100644 --- a/electron/ui/src/components/FlowsheetsListTable/FlowsheetsListTable.js +++ b/electron/ui/src/components/FlowsheetsListTable/FlowsheetsListTable.js @@ -101,7 +101,7 @@ export default function FlowsheetsListTable(props) { const formatLastRun = (time) => { try { - if (time && time.length >= 11) { + if (time) { let full_date = new Date(parseFloat(time) * 1000) return full_date.toLocaleString().split(',')[0]; }