diff --git a/src/ansys/templates/python/solution/{{cookiecutter.__project_name_slug}}/poetry.lock b/src/ansys/templates/python/solution/{{cookiecutter.__project_name_slug}}/poetry.lock index bed3a7363..fae5e775d 100644 --- a/src/ansys/templates/python/solution/{{cookiecutter.__project_name_slug}}/poetry.lock +++ b/src/ansys/templates/python/solution/{{cookiecutter.__project_name_slug}}/poetry.lock @@ -215,19 +215,18 @@ tests = ["ansys-api-platform-instancemanagement (==1.0.0)", "grpcio-health-check [[package]] name = "ansys-saf-desktop" -version = "1.0" +version = "1.1.0" description = "Ansys Solution Application Framework / Guided Low Code Workflow (SAF DESKTOP)" optional = false python-versions = ">=3.8,<3.11" files = [ - {file = "ansys_saf_desktop-1.0-py3-none-any.whl", hash = "sha256:60027c6c6234d11f7f84ded8a17e6f6eb48d1dc4c7ce7f644c9fae893878b345"}, - {file = "ansys_saf_desktop-1.0.0-py3-none-any.whl", hash = "sha256:fdb6a57ca7fa865d14131f477f5814fbad380cfb812db8d807463b6d4ee145c1"}, - {file = "ansys_saf_desktop-1.0.tar.gz", hash = "sha256:0f4f329d15e3a48b79ec2c6b6ad29feb7674260a19e9fdad497604a70deb3fb6"}, + {file = "ansys_saf_desktop-1.1.0-py3-none-any.whl", hash = "sha256:e66699415ae8e5acea5aa558e7192a2f64f8d12c410c72e283f00c0c88d14f3d"}, + {file = "ansys_saf_desktop-1.1.0.tar.gz", hash = "sha256:f5cba0164b0e20ae365b1baeab7c324ad1435ea7b1bc2de7d7d55612205e4692"}, ] [package.dependencies] ansys-platform-instancemanagement = ">=1.0.2,<2.0.0" -ansys-saf-glow-engine = ">=1.2.1,<2.0.0" +ansys-saf-glow-engine = ">=1.3.0,<2.0.0" grpcio = ">=1.47.0,<2.0.0" grpcio-health-checking = ">=1.24.0,<2.0.0" httpx = ">=0.23.3,<0.24.0" @@ -1129,13 +1128,13 @@ test-randomorder = ["pytest-randomly"] [[package]] name = "dash" -version = "2.15.0" +version = "2.16.0" description = "A Python framework for building reactive web-apps. Developed by Plotly." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "dash-2.15.0-py3-none-any.whl", hash = "sha256:df1882bbf613e4ca4372281c8facbeb68e97d76720336b051bf84c75d2de8588"}, - {file = "dash-2.15.0.tar.gz", hash = "sha256:d38891337fc855d5673f75e5346354daa063c4ff45a8a6a21f25e858fcae41c2"}, + {file = "dash-2.16.0-py3-none-any.whl", hash = "sha256:2a06e3856d9389656e1c84d6afb086748db0bbb676f44abb899df117c2879606"}, + {file = "dash-2.16.0.tar.gz", hash = "sha256:7887998e278f6cc1b8200ec9d9d6f82b5cb599997a31723c926487a25ce52117"}, ] [package.dependencies] @@ -1145,7 +1144,7 @@ dash-html-components = "2.0.0" dash-table = "5.0.0" fire = {version = ">=0.4.0", optional = true, markers = "extra == \"dev\""} Flask = ">=1.0.4,<3.1" -importlib-metadata = {version = "*", markers = "python_version >= \"3.7\""} +importlib-metadata = "*" nest-asyncio = "*" plotly = ">=5.0.0" PyYAML = {version = ">=5.4.1", optional = true, markers = "extra == \"dev\""} @@ -1156,8 +1155,8 @@ typing-extensions = ">=4.1.1" Werkzeug = "<3.1" [package.extras] -celery = ["celery[redis] (>=5.1.2)", "importlib-metadata (<5)", "redis (>=3.5.3)"] -ci = ["black (==21.6b0)", "black (==22.3.0)", "dash-dangerously-set-inner-html", "dash-flow-example (==0.0.5)", "flake8 (==3.9.2)", "flaky (==3.7.0)", "flask-talisman (==1.0.0)", "isort (==4.3.21)", "jupyterlab (<4.0.0)", "mimesis (<=11.1.0)", "mock (==4.0.3)", "numpy (<=1.25.2)", "openpyxl", "orjson (==3.5.4)", "orjson (==3.6.7)", "pandas (==1.1.5)", "pandas (>=1.4.0)", "preconditions", "pyarrow", "pyarrow (<3)", "pylint (==2.13.5)", "pytest-mock", "pytest-rerunfailures", "pytest-sugar (==0.9.6)", "xlrd (<2)", "xlrd (>=2.0.1)"] +celery = ["celery[redis] (>=5.1.2)", "redis (>=3.5.3)"] +ci = ["black (==22.3.0)", "dash-dangerously-set-inner-html", "dash-flow-example (==0.0.5)", "flake8 (==7.0.0)", "flaky (==3.7.0)", "flask-talisman (==1.0.0)", "jupyterlab (<4.0.0)", "mimesis (<=11.1.0)", "mock (==4.0.3)", "numpy (<=1.26.3)", "openpyxl", "orjson (==3.9.12)", "pandas (>=1.4.0)", "pyarrow", "pylint (==3.0.3)", "pytest-mock", "pytest-rerunfailures", "pytest-sugar (==0.9.6)", "pyzmq (==25.1.2)", "xlrd (>=2.0.1)"] compress = ["flask-compress"] dev = ["PyYAML (>=5.4.1)", "coloredlogs (>=15.0.1)", "fire (>=0.4.0)"] diskcache = ["diskcache (>=5.2.1)", "multiprocess (>=0.70.12)", "psutil (>=5.8.0)"] @@ -2694,17 +2693,17 @@ files = [ [[package]] name = "pkginfo" -version = "1.9.6" +version = "1.10.0" description = "Query metadata from sdists / bdists / installed packages." optional = false python-versions = ">=3.6" files = [ - {file = "pkginfo-1.9.6-py3-none-any.whl", hash = "sha256:4b7a555a6d5a22169fcc9cf7bfd78d296b0361adad412a346c1226849af5e546"}, - {file = "pkginfo-1.9.6.tar.gz", hash = "sha256:8fd5896e8718a4372f0ea9cc9d96f6417c9b986e23a4d116dda26b62cc29d046"}, + {file = "pkginfo-1.10.0-py3-none-any.whl", hash = "sha256:889a6da2ed7ffc58ab5b900d888ddce90bce912f2d2de1dc1c26f4cb9fe65097"}, + {file = "pkginfo-1.10.0.tar.gz", hash = "sha256:5df73835398d10db79f8eecd5cd86b1f6d29317589ea70796994d49399af6297"}, ] [package.extras] -testing = ["pytest", "pytest-cov"] +testing = ["pytest", "pytest-cov", "wheel"] [[package]] name = "platformdirs" @@ -3317,13 +3316,13 @@ testing = ["filelock"] [[package]] name = "python-dateutil" -version = "2.8.2" +version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, ] [package.dependencies] @@ -3637,13 +3636,13 @@ idna2008 = ["idna"] [[package]] name = "rich" -version = "13.7.0" +version = "13.7.1" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false python-versions = ">=3.7.0" files = [ - {file = "rich-13.7.0-py3-none-any.whl", hash = "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235"}, - {file = "rich-13.7.0.tar.gz", hash = "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa"}, + {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"}, + {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"}, ] [package.dependencies] @@ -4499,4 +4498,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.8.1, <3.11" -content-hash = "4fdbbbfb1feb2980c8c1aebcf91d9930a74e6d97b5f80a9386e25bef0a69aa9f" +content-hash = "5db65d72b52fb1bc3b8572532dcfa59c413c6b4d7e268d9fd8a626eacd5dcd19" diff --git a/src/ansys/templates/python/solution/{{cookiecutter.__project_name_slug}}/pyproject.toml b/src/ansys/templates/python/solution/{{cookiecutter.__project_name_slug}}/pyproject.toml index f427e9880..220ee7bdc 100644 --- a/src/ansys/templates/python/solution/{{cookiecutter.__project_name_slug}}/pyproject.toml +++ b/src/ansys/templates/python/solution/{{cookiecutter.__project_name_slug}}/pyproject.toml @@ -42,11 +42,11 @@ priority = "supplemental" [tool.poetry.dependencies] python = ">=3.8.1, <3.11" -ansys-saf-portal = {version = "1.0rc3", source = "solutions-private-pypi"} -ansys-saf-desktop = {version = "1.0.0", source = "solutions-private-pypi"} +ansys-saf-portal = {version = "1.0rc3"} +ansys-saf-desktop = {version = "1.1.0"} {% if cookiecutter.with_dash_ui == "yes" %} -ansys-web-components-dash = {version = "^0.0.dev2", source = "solutions-private-pypi"} -ansys-solutions-dash-lib = {version = "^0.4", source = "solutions-private-pypi"} +ansys-web-components-dash = {version = "^0.0.dev2"} +ansys-solutions-dash-lib = {version = "^0.4"} dash = "^2.6" dash_bootstrap_components = "^1.2" dash-extensions = ">=0.1.13" @@ -129,4 +129,4 @@ select = ['D107'] source = ["ansys.solutions"] [tool.coverage.report] -show_missing = true +show_missing = true \ No newline at end of file diff --git a/src/ansys/templates/python/solution/{{cookiecutter.__project_name_slug}}/setup_environment.py b/src/ansys/templates/python/solution/{{cookiecutter.__project_name_slug}}/setup_environment.py index 188ad03ff..0055c1338 100644 --- a/src/ansys/templates/python/solution/{{cookiecutter.__project_name_slug}}/setup_environment.py +++ b/src/ansys/templates/python/solution/{{cookiecutter.__project_name_slug}}/setup_environment.py @@ -578,7 +578,7 @@ def install_build_system(args: object) -> None: build_system_executable = DEPENDENCY_MANAGER_PATHS[sys.platform]["build_sys_exec"] if os.path.exists(build_system_executable): if sys.platform == "win32": - subprocess.run( + process = subprocess.run( [ "powershell", "-Command", @@ -591,8 +591,10 @@ def install_build_system(args: object) -> None: f"'{build_system_executable}'", ] ) + if process.returncode == 0: + check_if_user_is_internal_or_external() elif sys.platform == "linux": - subprocess.run( + process = subprocess.run( [ "ln", "-sf", @@ -600,7 +602,11 @@ def install_build_system(args: object) -> None: DEPENDENCY_MANAGER_PATHS[sys.platform]["dep_bin_venv_path"], ] ) + if process.returncode == 0: + check_if_user_is_internal_or_external() return + else: + check_if_user_is_internal_or_external() print("Skipped") print() @@ -655,31 +661,41 @@ def configure_poetry( if not use_private_sources: return + is_token_exist = False # Declare credentials for private sources for source in private_sources: print(f"Declare credentials for {source['name']}") + USERNAME = "PAT" + token = None if source["name"].lower() == "pypi": continue elif source["url"] == "https://pkgs.dev.azure.com/pyansys/_packaging/pyansys/pypi/simple/": token = os.environ["PYANSYS_PYPI_PRIVATE_PAT"] elif source["url"] == "https://pkgs.dev.azure.com/pyansys/_packaging/ansys-solutions/pypi/simple/": - token = os.environ["PYANSYS_PYPI_PRIVATE_PAT"] - else: - raise Exception(f"Unknown private source {source['name']} with url {source['url']}.") + token = os.environ.get("PYANSYS_PYPI_PRIVATE_PAT") + elif source["url"] == "https://artifactory.ansys.com/artifactory/api/pypi/saf_pypi/simple/": + token = os.environ.get("ARTIFACTORY_PRIVATE_PYPI_PAT") + USERNAME = os.environ.get("ARTIFACTORY_PRIVATE_PYPI_USER") + + is_token_exist = bool(token) if not is_token_exist else is_token_exist + # Store credentials - if credentials_management_method == "keyring": - # Declare source URL - command_line = [poetry_executable, "config", f"repositories.{source['name']}", source["url"], "--local"] - subprocess.run(command_line, check=True) - # Declare source credentials - command_line = [poetry_executable, "config", f"http-basic.{source['name']}", "PAT", token, "--local"] - subprocess.run(command_line, check=True) - elif credentials_management_method == "environment-variables": - # Format source name to comply with Poetry environment variable syntax - source_name = source["name"].upper().replace("-", "_") - # Create Poetry environment variable - os.environ[f"POETRY_HTTP_BASIC_{source_name}_USERNAME"] = "PAT" - os.environ[f"POETRY_HTTP_BASIC_{source_name}_PASSWORD"] = token + if token and USERNAME: + if credentials_management_method == "keyring": + # Declare source URL + command_line = [poetry_executable, "config", f"repositories.{source['name']}", source["url"], "--local"] + subprocess.run(command_line, check=True) + # Declare source credentials + command_line = [poetry_executable, "config", f"http-basic.{source['name']}", USERNAME, token, "--local"] + subprocess.run(command_line, check=True) + elif credentials_management_method == "environment-variables": + # Format source name to comply with Poetry environment variable syntax + source_name = source["name"].upper().replace("-", "_") + # Create Poetry environment variable + os.environ[f"POETRY_HTTP_BASIC_{source_name}_USERNAME"] = USERNAME + os.environ[f"POETRY_HTTP_BASIC_{source_name}_PASSWORD"] = token + if not is_token_exist: + raise Exception("Please provide valid token for private sources") def check_dependency_group(dependency_group: str, configuration: str) -> bool: @@ -932,6 +948,66 @@ def install_dotnet_linux_dependencies(): shell=True, ) +def check_if_user_is_internal_or_external(): + private_pypi_pats = [ + os.environ.get("PYANSYS_PRIVATE_PYPI_PAT"), + os.environ.get("SOLUTIONS_PRIVATE_PYPI_PAT") + ] + is_internal = any(private_pypi_pats) + private_sources_dict = { + 'solutions-private-pypi': {'url': 'https://pkgs.dev.azure.com/pyansys/_packaging/ansys-solutions/pypi/simple/', 'priority': 'supplemental'}, + 'pyansys-private-pypi': {'url': 'https://pkgs.dev.azure.com/pyansys/_packaging/pyansys/pypi/simple/', 'priority': 'supplemental'}, + 'artifactory-private-pypi': {'url': 'https://artifactory.ansys.com/artifactory/api/pypi/saf_pypi/simple/', 'priority': 'supplemental'} + } + private_sources = get_private_sources(DEPENDENCY_MANAGER_PATHS["common"]["configuration_file"]) + private_sources = [source for source in private_sources if source['name'] != 'PyPI'] + internal_sources = {'solutions-private-pypi', 'pyansys-private-pypi'} + external_sources = {'artifactory-private-pypi'} + all_sources = {source['name'] for source in private_sources} + + # Add sources if they are not already present + sources_to_add = set() + if is_internal: + sources_to_add |= internal_sources - all_sources + else: + sources_to_add |= external_sources - all_sources + + commands = [ + [ + DEPENDENCY_MANAGER_PATHS[sys.platform]["build_sys_exec"], + "source", + "add", + source, + private_sources_dict[source]['url'], + f"--priority={private_sources_dict[source]['priority']}" + ] for source in sources_to_add + ] + + # Remove sources that should not be present + sources_to_remove = set() + if is_internal: + sources_to_remove |= all_sources - internal_sources + else: + sources_to_remove |= all_sources - external_sources + + commands += [ + [ + DEPENDENCY_MANAGER_PATHS[sys.platform]["build_sys_exec"], + "source", + "remove", + source + ] for source in sources_to_remove + ] + + for command in commands: + process = subprocess.run( + command, + check=True, + shell=DEPENDENCY_MANAGER_PATHS[sys.platform]["shell"] + ) + if process.returncode != 0: + break + def main() -> None: """Sequence of operations leading to the complete Python ecosystem."""