diff --git a/ansys/rep/client/jms/api/jms_api.py b/ansys/rep/client/jms/api/jms_api.py index d0e6b2a46..d394d8c11 100644 --- a/ansys/rep/client/jms/api/jms_api.py +++ b/ansys/rep/client/jms/api/jms_api.py @@ -2,7 +2,7 @@ import logging import os import time -from typing import List +from typing import List, Union import uuid from ansys.rep.client.exceptions import REPError @@ -53,9 +53,18 @@ def get_projects(self, **query_params): """Return a list of projects, optionally filtered by given query parameters""" return get_projects(self.client, self.url, **query_params) - def get_project(self, id=None, name=None): + def get_project(self, id): """Return a single project for given project id""" - return get_project(self.client, self.url, id, name) + return get_project(self.client, self.url, id) + + def get_project_by_name(self, name, last_created=True) -> Union[Project, List[Project]]: + """ + Query projects by name. If no projects are found, an empty list is returned. + In case of multiple projects with same name: + - If `last_created = True`, the last created project is returned + - If `last_created = False`, the full list of projects with given name is returned + """ + return get_project_by_name(self.client, self.url, name, last_created) def create_project(self, project, replace=False, as_objects=True): """Create a new project""" @@ -156,18 +165,13 @@ def get_projects(client, api_url, as_objects=True, **query_params) -> List[Proje return schema.load(data) -def get_project(client, api_url, id=None, name=None) -> Project: +def get_project(client, api_url, id) -> Project: """ Return a single project """ - params = {} - if name: - url = f"{api_url}/projects/" - params["name"] = name - else: - url = f"{api_url}/projects/{id}" - r = client.session.get(url, params=params) + url = f"{api_url}/projects/{id}" + r = client.session.get(url) if len(r.json()["projects"]): schema = ProjectSchema() @@ -175,6 +179,23 @@ def get_project(client, api_url, id=None, name=None) -> Project: return None +def get_project_by_name(client, api_url, name, last_created=True) -> Union[Project, List[Project]]: + """ + Return a single project + """ + + params = {"name": name} + if last_created: + params["sort"] = "-creation_time" + params["limit"] = 1 + + projects = get_projects(client, api_url, **params) + + if len(projects) == 1: + return projects[0] + return projects + + def create_project(client, api_url, project, replace=False, as_objects=True) -> Project: url = f"{api_url}/projects/" diff --git a/ansys/rep/client/jms/resource/base.py b/ansys/rep/client/jms/resource/base.py index 5c3474d19..a214e679b 100644 --- a/ansys/rep/client/jms/resource/base.py +++ b/ansys/rep/client/jms/resource/base.py @@ -55,4 +55,24 @@ def __repr__(self): ) def __str__(self): - return json.dumps(self.Meta.schema(many=False).dump(self), indent=2) + + # Ideally we'd simply do + # return json.dumps(self.Meta.schema(many=False).dump(self), indent=2) + # However the schema.dump() function (rightfully) ignores fields marked as load_only. + # + # Therefore we have to manually iterate over all fields + + schema = self.Meta.schema(many=False) + dict_repr = schema.dict_class() + for attr_name, field_obj in schema.fields.items(): + value = missing + try: + value = field_obj.serialize(attr_name, self, accessor=schema.get_attribute) + except: + pass + if value is missing: + continue + key = field_obj.data_key if field_obj.data_key is not None else attr_name + dict_repr[key] = value + + return json.dumps(dict_repr, indent=2) diff --git a/doc/source/conf.py b/doc/source/conf.py index 3b81fad29..0ac3a99db 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# # Sphinx documentation configuration file from datetime import datetime import os @@ -11,16 +9,22 @@ sys.path.append(os.path.abspath(os.path.dirname(__file__))) +# -- Project information ----------------------------------------------------- + +# General information about the project. +project = "Ansys pyrep" +copyright = f"(c) {datetime.now().year} ANSYS, Inc. All rights reserved" +author = __company__ + +# The short X.Y version +release = version = __version__ + # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) -# -- General job_definition ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.0' - +# -- General configuration --------------------------------------------------- extensions = [ "sphinx.ext.autodoc", "sphinx.ext.autosummary", @@ -62,23 +66,9 @@ # The master toctree document. master_doc = "index" -# General information about the project. -project = "Ansys pyrep" -copyright = f"(c) {datetime.now().year} {__company__}. All rights reserved" -author = __company__ - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = __external_version__ -# The full version, including alpha/beta/rc tags. -release = __external_version__ - # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -# language = None +language = "en" # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: @@ -121,106 +111,45 @@ # -- Options for HTML output ---------------------------------------------- -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. html_theme = "ansys_sphinx_theme" # only for sphinx_rtd_theme html_theme_options = { - "github_url": "[https://github.com/pyansys/pyrep", + "github_url": "https://github.com/pyansys/pyrep", "show_prev_next": False, "show_breadcrumbs": True, "additional_breadcrumbs": [ ("PyAnsys", "https://docs.pyansys.com/"), ], - #'canonical_url': '', - #'analytics_id': 'UA-XXXXXXX-1', # Provided by Google in your dashboard - #'logo_only': False, - # "display_version": True, - # "prev_next_buttons_location": "bottom", - #'style_external_links': False, - #'vcs_pageview_mode': '', - #'style_nav_header_background': 'white', - # Toc options "collapse_navigation": True, - # "sticky_navigation": True, "navigation_depth": 4, - # "includehidden": True, - # "titles_only": False, } -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - # A shorter title for the navigation bar. Default is the same as html_title. -html_short_title = html_title = "pyrep" +html_short_title = html_title = "PyREP" # The name of an image file (relative to this directory) to place at the top # of the sidebar. html_logo = logo -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None +# Favicon +html_favicon = "favicon.png" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - # If true, links to the reST sources are added to the pages. html_show_sourcelink = False -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - # Output file base name for HTML help builder. -htmlhelp_basename = "REPclientdoc" +htmlhelp_basename = "pyrepdoc" # -- Options for LaTeX output --------------------------------------------- @@ -242,7 +171,7 @@ "index", "ansys-rep-client.tex", "REP Python Client Documentation", - "ANSYS Switzerland Gmbh", + author, "manual", ), ] @@ -343,9 +272,9 @@ secured?returnurl=/Views/Secured/corp/v231/en/rep_ug/%s.html""", "ANSYS Help - ", ), - "ansys_rep_tutorial": ( + "ansys_dcs_tutorial": ( """https://ansyshelp.ansys.com/account/ - secured?returnurl=/Views/Secured/corp/v231/en/rep_tut/%s.html""", + secured?returnurl=/Views/Secured/corp/v231/en/dcs_tut/%s.html""", "REP Tutorial - ", ), } diff --git a/doc/source/favicon.png b/doc/source/favicon.png new file mode 100644 index 000000000..c755f53d5 Binary files /dev/null and b/doc/source/favicon.png differ diff --git a/doc/source/index.rst b/doc/source/index.rst index c229007b3..bbec0103f 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -1,28 +1,25 @@ -Ansys REP Python Client -============================= +PyREP Documentation |version| +================================= + +.. toctree:: + :hidden: + :maxdepth: 3 + + install + quickstart + examples/index + api/index + +Introduction +------------ Ansys Remote Execution Platform (REP) is a family of applications that enables you to distribute, manage and solve simulations on a variety of compute resources. -As part of this, the Job Management Service (JMS) facilitates the robust solution of -tens of thousands of design points spread across clusters, networks and operating systems. - -**ansys-rep-client** brings Ansys REP to your Python application. +``ansys-rep-client`` brings Ansys REP to your Python application. Wrapping around the REP REST APIs, it allows you to: * create new projects and modify existing ones * monitor and manage jobs * run your own design exploration algorithms -* retrieve simulation results - -User Guide -=========== - -.. toctree:: - :maxdepth: 2 - - install - quickstart - examples/index - api/index - changelog/index \ No newline at end of file +* retrieve simulation results \ No newline at end of file diff --git a/doc/source/install.rst b/doc/source/install.rst index 0aeae62ba..3c3f70b37 100644 --- a/doc/source/install.rst +++ b/doc/source/install.rst @@ -5,40 +5,37 @@ Installation Make sure you have ``Python 3`` and that the expected version is available from your command line. You can check this by running: -.. parsed-literal:: +.. code:: - $ python --version + python --version If you do not have Python, please install the latest 3.x version from `python.org `_. Additionally, make sure you have ``pip`` available. You can check this by running: -.. parsed-literal:: +.. code:: - $ pip --version + pip --version If pip isn't already installed, please refer to the `Installing Packages Tutorial `_ from the Python Packaging Authority. -Installing ``ansys-dcs-client`` is as simple as, on Windows: +As long as PyREP is a private PyAnsys package not published to PyPI yet, you can execute -.. parsed-literal:: - - $ pip install "%AWP_ROOT\ |version_no_dots|\ %\\dcs\\share\\python_client\\ansys_dcs_client-\ |client_version|\ -py3-none-any.whl" - -on Linux: - -.. parsed-literal:: - - $ pip install /usr/ansys_inc/v\ |version_no_dots|\ /dcs/share/python_client/ansys_dcs_client-\ |client_version|\ -py3-none-any.whl +.. code:: + python -m pip install git+https://github.com/pyansys/pyrep The following dependencies are automatically installed through ``pip`` (if not already available): +- cachetools_ - requests_ - marshmallow_ - marshmallow_oneofschema_ +- python-keycloak_ .. _requests: https://pypi.org/project/requests/ .. _marshmallow: https://pypi.org/project/marshmallow/ .. _marshmallow_oneofschema: https://pypi.org/project/marshmallow-oneofschema/ +.. _cachetools: https://pypi.org/project/cachetools/ +.. _python-keycloak: https://pypi.org/project/python-keycloak/ diff --git a/doc/source/quickstart.rst b/doc/source/quickstart.rst index bbc56b969..f00da988a 100644 --- a/doc/source/quickstart.rst +++ b/doc/source/quickstart.rst @@ -1,7 +1,7 @@ .. _quickstart: Quickstart -=============== +========== This guide will walk you through the basics of interacting with a REP server. More elaborated examples are available in the :ref:`Examples ` chapter, while detailed documentation can be found in the :ref:`Code Documentation `. @@ -20,7 +20,7 @@ Let's start by connecting to a REP server running on the localhost with default .. code-block:: python from ansys.rep.client import Client - from ansys.rep.client.jms import JmsApi + from ansys.rep.client.jms import JmsApi, ProjectApi client = Client(rep_url="https://localhost:8443/rep", username="repadmin", password="repadmin") @@ -41,7 +41,7 @@ Query projects statistics to find out how many design points are currently runni Create a demo project: the MAPDL motorbike frame example --------------------------------------------------------- -Create a project consisting of an Ansys APDL beam model +Create a project consisting of an Ansys Mechanical APDL beam model of a tubular steel trellis motorbike-frame. .. only:: builder_html @@ -68,27 +68,43 @@ Most ``get`` functions support filtering by query parameters. .. code-block:: python - project = jms_api.get_project(id="mapdl_motorbike_frame") + project = jms_api.get_project_by_name(name="Mapdl Motorbike Frame") + project_api = ProjectApi(client, project.id) # Get all design points with all fields - jobs = project.get_jobs() + jobs = project_api.get_jobs() # Get id and parameter values for all evaluated design points - jobs = project.get_jobs(fields=["id", "values"], eval_status="evaluated") + jobs = project_api.get_jobs(fields=["id", "values"], eval_status="evaluated") # Get name and elapsed time of max 5 evaluated design points - jobs = project.get_jobs(fields=["name", "elapsed_time"], + jobs = project_api.get_jobs(fields=["name", "elapsed_time"], eval_status="evaluated", limit=5) + for job in jobs: + print(job) + # { + # "id": "02qoqedl8QCjkuLcqCi10Q", + # "name": "Job.0", + # "priority": 0, + # "elapsed_time": 35.275044 + # } + # { + # "id": "02qoqedlDMO1LrSGoHQqnT", + # "name": "Job.1", + # "priority": 0, + # "elapsed_time": 34.840801 + # } + # ... # Get all design points sorted by fitness value in ascending order - jobs = project.get_jobs(sort="fitness") + jobs = project_api.get_jobs(sort="fitness") # Get all design points sorted by fitness value in descending order - jobs = project.get_jobs(sort="-fitness") + jobs = project_api.get_jobs(sort="-fitness") # Get all design points sorted by the parameters tube1 and weight - jobs = project.get_jobs(sort=["values.tube1", "values.weight"]) - print([(dp.values["tube1"], dp.values["weight"]) for dp in jobs]) + jobs = project_api.get_jobs(sort=["values.tube1", "values.weight"]) + print([(job.values["tube1"], job.values["weight"]) for job in jobs]) In general, query parameters support the following operators: ``lt`` (less than), ``le`` (less or equal), ``=`` (equal), ``ne`` (not equal), ``ge`` (greater or equal), ``gt`` (greater than), ``in`` (value found in list) and @@ -97,18 +113,18 @@ In general, query parameters support the following operators: ``lt`` (less than) .. code-block:: python # Equal - jobs = project.get_jobs(eval_status="evaluated") + jobs = project_api.get_jobs(eval_status="evaluated") # In - jobs = project.get_jobs(eval_status=["prolog", "running"]) + jobs = project_api.get_jobs(eval_status=["prolog", "running"]) # Contains query_params = {"note.contains": "search_string"} - jobs = project.get_jobs(**query_params) + jobs = project_api.get_jobs(**query_params) # Less than query_params = {"fitness.lt": 1.8} - jobs = project.get_jobs(**query_params) + jobs = project_api.get_jobs(**query_params) Objects vs dictionaries ----------------------------------- @@ -121,26 +137,27 @@ such as ``Numpy``, ``Pandas``, etc. import pandas - project = client.get_project(id="mapdl_motorbike_frame") + project = jms_api.get_project_by_name(name="Mapdl Motorbike Frame") # Get parameter values for all evaluated design points - jobs = project.get_jobs(fields=["id", "values"], eval_status="evaluated", as_objects=False) + jobs = project_api.get_jobs(fields=["id", "values"], eval_status="evaluated", as_objects=False) # Import jobs data into a flat DataFrame - df = pandas.io.json.json_normalize(jobs) + df = pandas.json_normalize(jobs) # Output - # id values.tube1_radius values.tube1_thickness values.tube2_radius values.tube2_thickness values.tube3_radius values.tube3_thickness ... values.tube15 values.tube16 values.tube17 values.tube18 values.tube19 values.tube20 values.tube21 - # 0 1 7.055903 0.728247 17.677894 0.512761 13.342691 0.718970 ... 1 3 2 3 1 1 1 - # 1 2 18.172368 2.407453 9.216933 0.818597 11.789593 1.439845 ... 3 1 3 2 3 3 2 - # 2 3 14.832407 2.380437 7.484620 1.601617 19.742424 0.816099 ... 2 1 1 1 2 2 3 - # 3 4 10.254875 2.420485 10.429973 2.241802 14.647943 0.501836 ... 1 3 2 1 3 3 3 - # 4 5 14.601405 1.657524 10.056457 1.743385 8.821876 2.200616 ... 1 2 3 3 2 1 2 - # 5 6 10.393178 2.155777 8.043999 2.036772 11.605410 2.426192 ... 3 1 1 1 2 1 1 - # 6 7 10.415530 1.675479 4.570576 1.461735 16.915658 1.822555 ... 3 3 3 2 1 1 2 - # 7 8 12.841433 1.322097 6.142197 1.659299 6.275559 2.312346 ... 3 2 2 3 1 1 3 - # 8 9 18.394536 2.446091 12.882719 0.939273 15.167834 1.683604 ... 3 1 2 3 2 2 1 - # 9 10 12.414343 1.699816 6.128372 1.314386 18.783781 1.736996 ... 1 3 2 1 3 1 2 + # id values.mapdl_cp_time values.mapdl_elapsed_time values.mapdl_elapsed_time_obtain_license values.max_stress ... values.tube6 values.tube7 values.tube8 values.tube9 values.weight + # 0 02qoqedl8QCjkuLcqCi10Q 0.500 24.0 21.9 1010.256091 ... 3 1 1 2 3.027799 + # 1 02qoqedlDMO1LrSGoHQqnT 0.406 23.0 21.5 227.249112 ... 2 3 3 2 11.257201 + # 2 02qoqedlApzJZd7fQSQIJg 0.438 24.0 21.2 553.839050 ... 3 2 1 2 6.358393 + # 3 02qoqedlGMYZi7YBive78D 0.469 25.0 22.9 162.944726 ... 1 1 1 3 9.919099 + # 4 02qoqedlKBzRz939iDCCex 0.391 25.0 22.6 218.976121 ... 3 2 2 2 6.884490 + # 5 02qoqedlLfvwuA4uaf5GKR 0.406 24.0 22.4 455.888101 ... 1 3 1 2 7.346944 + # 6 02qoqedlLvoSgPoLxla8F9 0.391 27.0 25.2 292.885562 ... 1 1 1 3 6.759635 + # 7 02qoqedlOKg8Vg5AlTrji6 0.484 28.0 26.2 377.721100 ... 1 1 3 2 5.952097 + # 8 02qoqedlRtDwuw2uTQ99Vq 0.469 28.0 25.9 332.336753 ... 1 3 2 2 7.463696 + # 9 02qoqedlPYyGRTivqB5vxf 0.453 27.0 25.5 340.147675 ... 3 2 2 3 6.631538 + # 10 02qoqedlN1ebRV77zuUVYd 0.453 28.0 25.5 270.691391 ... 2 2 1 3 8.077236 Set failed design points to pending @@ -150,14 +167,14 @@ Query a specific project and set its failed design points (if any) to pending. .. code-block:: python - project = client.get_project(id="mapdl_motorbike_frame") - jobs = project.get_jobs() + project = jms_api.get_project_by_name(name="Mapdl Motorbike Frame") + jobs = project_api.get_jobs() - failed_dps = [dp for dp in jobs if dp.eval_status == "failed"] + failed_jobs = [job for job in jobs if job.eval_status == "failed"] - for dp in failed_dps: - dp.eval_status = "pending" - failed_dps = project.update_jobs(failed_dps) + for job in failed_jobs: + job.eval_status = "pending" + failed_jobs = project_api.update_jobs(failed_jobs) Modify a project job_definition @@ -167,17 +184,29 @@ Query an existing project job_definition, modify it and send it back to the serv .. code-block:: python - project = client.get_project(id="mapdl_motorbike_frame") + project = jms_api.get_project_by_name(name="Mapdl Motorbike Frame") # get currently active job_definition - job_def = project.get_job_definitions(active=True)[0] + job_def = project_api.get_job_definitions(active=True)[0] # Update the lower limit of a parameter - parameter = job_def.parameter_definitions[0] - parameter.lower_limit = 2.5 + parameter_id = job_def.parameter_definition_ids[0] + parameter_def = project_api.get_parameter_definitions(id=parameter_id)[0] + print(parameter_def) + # { + # "id": "02qoqeciKZxk3Ua4QjPwue", + # "name": "tube1_radius", + # "mode": "input", + # "type": "float", + # "default": 12.0, + # "lower_limit": 4.0, + # "upper_limit": 20.0, + # "cyclic": false + # } + parameter_def.lower_limit = 2.5 # send the updated job_definition to the server - job_def = project.update_job_definitions([job_def])[0] + project_api.update_parameter_definitions([parameter_def]) Delete some design points @@ -187,10 +216,10 @@ Query and then delete all design points that timed out. .. code-block:: python - project = client.get_project(id="mapdl_motorbike_frame") + project = jms_api.get_project_by_name(name="Mapdl Motorbike Frame") - jobs = project.get_jobs(fields=['id'], eval_status="timeout") - project.delete_jobs(jobs) + jobs = project_api.get_jobs(fields=['id'], eval_status="timeout") + project_api.delete_jobs(jobs) Query the number of evaluators @@ -198,7 +227,7 @@ Query the number of evaluators .. code-block:: python - evaluators = client.get_evaluators() + evaluators = jms_api.get_evaluators() # print number of Windows and Linux evaluators connected to the DCS server print( len([e for e in evaluators if e.platform == "Windows" ]) ) @@ -208,15 +237,15 @@ Query the number of evaluators Replace a file in a project ------------------------------------------ -Get file definitions from an existing project job_definition and replace the first one. +Get file definitions from an existing project Job Definition and replace the first one. .. code-block:: python - job_def = project.get_job_definitions(active=True)[0] - files = project.get_files() + job_def = project_api.get_job_definitions(active=True)[0] + files = project_api.get_files() file = files[0] - file.src = r"D:\local_folder\my_project\workbench_archive.wbpz" - files = project.update_files([file]) + file.src = r"D:\local_folder\my_project\input_file.xyz" + project.update_files([file]) For instructions on how to add a new file to an existing project job_definition, see :ref:`Adding a file to a project `. @@ -230,7 +259,7 @@ Users with admin rights (such as the default ``repadmin`` user) can create new u from ansys.rep.client import Client from ansys.rep.client.auth import AuthApi, User - client = Client(rep_url="https://127.0.0.1:8443/rep/", username="repadmin", password="repadmin") + client = Client(rep_url="https://localhost:8443/rep/", username="repadmin", password="repadmin") auth_api = AuthApi(client) # modify the default password of the repadmin user @@ -243,38 +272,48 @@ Users with admin rights (such as the default ``repadmin`` user) can create new u email='test_user@test.com', fullname='Test User', is_admin=False) new_user = auth_api.create_user(new_user) + print(new_user) + # { + # "id": "f9e068d7-4962-45dc-92a4-2273246039da", + # "username": "test_user", + # "email": "test_user@test.com" + # } + new_user.password = "new_password" + auth_api.update_user(new_user) Exception handling ------------------------------------------ -All exceptions that the Ansys DCS clients explicitly raise inherit from :exc:`ansys.rep.client.REPError`. +All exceptions that the Ansys REP client explicitly raise inherit from :exc:`ansys.rep.client.REPError`. Client Errors are raised for 4xx HTTP status codes, while API Errors are raised for 5xx HTTP status codes (server side errors). -For example, instantiating a client with invalid credentials will return a 400 Client Error. +For example, instantiating a client with invalid credentials will return a 401 Client Error. .. code-block:: python - from ansys.rep.client import REPError - from ansys.rep.client.jms import Client + from ansys.rep.client import Client, REPError try: - client = Client(rep_url="https://127.0.0.1:8443/rep/", username="repadmin", password="wrong_psw") + client = Client(rep_url="https://localhost:8443/rep/", username="repadmin", password="wrong_psw") except REPError as e: print(e) #Output: - #400 Client Error: invalid_grant for: POST https://127.0.0.1:8443/rep/auth/api/oauth/token - #Invalid "username" or "password" in request. + # 401 Client Error: invalid_grant for: POST https://localhost:8443/rep/auth/realms/rep/protocol/openid-connect/token + # Invalid user credentials -A *get* call on a non-existing resource will return a 404 Client Error. +A *get* call on a non-existing resource will return a 404 Client Error. .. code-block:: python + from ansys.rep.client.jms import JmsApi + + jms_api = JmsApi(client) try: - client.get_project(id="non_existing_project") + jms_api.get_project(id="non_existing_project") except REPError as e: print(e) #Output: - #404 Client Error: Not Found for: GET https://127.0.0.1:8443/rep/dps/api//projects/non_existing_project \ No newline at end of file + #404 Client Error: Not Found for: GET https://localhost:8443/rep//jms/api/v1/projects/non_existing_project \ No newline at end of file diff --git a/examples/mapdl_motorbike_frame/project_setup.py b/examples/mapdl_motorbike_frame/project_setup.py index 7d5bc2a7e..45180d7d4 100644 --- a/examples/mapdl_motorbike_frame/project_setup.py +++ b/examples/mapdl_motorbike_frame/project_setup.py @@ -326,7 +326,7 @@ def create_project(client, name, num_jobs=20, use_exec_script=False) -> Project: if __name__ == "__main__": parser = argparse.ArgumentParser() - parser.add_argument("-n", "--name", type=str, default="mapdl_motorbike_frame") + parser.add_argument("-n", "--name", type=str, default="Mapdl Motorbike Frame") parser.add_argument("-j", "--num-jobs", type=int, default=50) parser.add_argument("-es", "--use-exec-script", default=False, action="store_true") parser.add_argument("-U", "--url", default="https://127.0.0.1:8443/rep") diff --git a/tests/jms/test_jms_api.py b/tests/jms/test_jms_api.py index 49f0850af..05dfe7ed5 100644 --- a/tests/jms/test_jms_api.py +++ b/tests/jms/test_jms_api.py @@ -24,7 +24,7 @@ def test_jms_api(self): log.debug("=== Client ===") client = self.client() - proj_name = "mapdl_motorbike_frame" + proj_name = "Mapdl Motorbike Frame" log.debug("=== Projects ===") jms_api = JmsApi(client) diff --git a/tests/jms/test_project_permissions.py b/tests/jms/test_project_permissions.py index 147d43190..08354d934 100644 --- a/tests/jms/test_project_permissions.py +++ b/tests/jms/test_project_permissions.py @@ -148,7 +148,7 @@ def test_modify_project_permissions(self): root_api2 = JmsApi(client2) log.info(f"Client connected at {client2.rep_url} with user {user2.username}") - proj_user2 = root_api2.get_project(name=proj_name) + proj_user2 = root_api2.get_project_by_name(name=proj_name) project_api2 = ProjectApi(client2, proj_user2.id) add_job_definition_to_project(project_api2, f"Config 2 - {user2.username}") diff --git a/tests/jms/test_projects.py b/tests/jms/test_projects.py index 2ca02089f..db2ac63de 100644 --- a/tests/jms/test_projects.py +++ b/tests/jms/test_projects.py @@ -165,12 +165,12 @@ def test_project_copy(self): tgt_name = proj_name + "_copy1" project_api = ProjectApi(client, proj.id) proj1_id = project_api.copy_project(tgt_name) - copied_proj1 = jms_api.get_project(name=tgt_name) + copied_proj1 = jms_api.get_project_by_name(name=tgt_name) self.assertIsNotNone(copied_proj1) tgt_name = proj_name + "_copy2" project_api.copy_project(tgt_name) - copied_proj2 = jms_api.get_project(name=tgt_name) + copied_proj2 = jms_api.get_project_by_name(name=tgt_name) self.assertIsNotNone(copied_proj2) # Delete projects