ansys-conceptev-core 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ansys_conceptev_core-0.1.3/AUTHORS +12 -0
- ansys_conceptev_core-0.1.3/LICENSE +21 -0
- ansys_conceptev_core-0.1.3/PKG-INFO +120 -0
- ansys_conceptev_core-0.1.3/README.rst +91 -0
- ansys_conceptev_core-0.1.3/pyproject.toml +136 -0
- ansys_conceptev_core-0.1.3/src/ansys/conceptev/core/__init__.py +29 -0
- ansys_conceptev_core-0.1.3/src/ansys/conceptev/core/app.py +319 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# This is the list of Pyconceptev Core's significant contributors.
|
|
2
|
+
#
|
|
3
|
+
# This file does not necessarily list everyone who has contributed code.
|
|
4
|
+
#
|
|
5
|
+
# For contributions made under a Corporate CLA, the organization is
|
|
6
|
+
# added to this file.
|
|
7
|
+
#
|
|
8
|
+
# If you have contributed to the repository and wish to be added to this file
|
|
9
|
+
# please submit a request.
|
|
10
|
+
#
|
|
11
|
+
#
|
|
12
|
+
ANSYS, Inc.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
9
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
|
10
|
+
so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ansys-conceptev-core
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: A Python wrapper for Ansys Conceptev core
|
|
5
|
+
Home-page: https://github.com/ansys/pyconceptev
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: Ansys,Concept EV,Electric Powertrain
|
|
8
|
+
Author: ANSYS, Inc.
|
|
9
|
+
Author-email: pyansys.core@ansys.com
|
|
10
|
+
Maintainer: ANSYS, Inc.
|
|
11
|
+
Maintainer-email: pyansys.core@ansys.com
|
|
12
|
+
Requires-Python: >=3.9,<4.0
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Requires-Dist: httpx (>=0.26.0,<0.27.0)
|
|
23
|
+
Requires-Dist: importlib-metadata (>=7.0,<8.0) ; python_version < "3.8"
|
|
24
|
+
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
|
25
|
+
Project-URL: Documentation, https://conceptev.core.docs.pyansys.com
|
|
26
|
+
Project-URL: Repository, https://github.com/ansys/pyconceptev
|
|
27
|
+
Description-Content-Type: text/x-rst
|
|
28
|
+
|
|
29
|
+
PyConceptEV
|
|
30
|
+
===========
|
|
31
|
+
|pyansys| |python| |MIT|
|
|
32
|
+
|
|
33
|
+
.. |pyansys| image:: https://img.shields.io/badge/Py-Ansys-ffc107.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABDklEQVQ4jWNgoDfg5mD8vE7q/3bpVyskbW0sMRUwofHD7Dh5OBkZGBgW7/3W2tZpa2tLQEOyOzeEsfumlK2tbVpaGj4N6jIs1lpsDAwMJ278sveMY2BgCA0NFRISwqkhyQ1q/Nyd3zg4OBgYGNjZ2ePi4rB5loGBhZnhxTLJ/9ulv26Q4uVk1NXV/f///////69du4Zdg78lx//t0v+3S88rFISInD59GqIH2esIJ8G9O2/XVwhjzpw5EAam1xkkBJn/bJX+v1365hxxuCAfH9+3b9/+////48cPuNehNsS7cDEzMTAwMMzb+Q2u4dOnT2vWrMHu9ZtzxP9vl/69RVpCkBlZ3N7enoDXBwEAAA+YYitOilMVAAAAAElFTkSuQmCC
|
|
34
|
+
:target: https://docs.pyansys.com/
|
|
35
|
+
:alt: PyAnsys
|
|
36
|
+
|
|
37
|
+
.. |python| image:: https://img.shields.io/badge/python-3.9+-blue.svg
|
|
38
|
+
:target: https://www.python.org/downloads/
|
|
39
|
+
:alt: Python
|
|
40
|
+
|
|
41
|
+
.. .. |pypi| image:: https://img.shields.io/pypi/v/ansys-conceptev-core.svg?logo=python&logoColor=white
|
|
42
|
+
.. :target: https://pypi.org/project/ansys-conceptev-core
|
|
43
|
+
.. :alt: PyPI
|
|
44
|
+
|
|
45
|
+
.. .. |downloads| image:: https://img.shields.io/pypi/dm/ansys-conceptev-core.svg
|
|
46
|
+
.. :target: https://pypi.org/project/ansys-conceptev-core/
|
|
47
|
+
.. :alt: PyPI Downloads
|
|
48
|
+
|
|
49
|
+
.. .. |codecov| image:: https://codecov.io/gh/ansys/pyconceptev/graph/badge.svg?token=UZIC7XT5WE
|
|
50
|
+
.. :target: https://codecov.io/gh/ansys/pyconceptev
|
|
51
|
+
.. :alt: Codecov
|
|
52
|
+
|
|
53
|
+
.. .. |GH-CI| image:: https://github.com/ansys/pyconceptev/actions/workflows/ci_cd.yml/badge.svg
|
|
54
|
+
.. :target: https://github.com/ansys/pyconceptev/actions/workflows/ci_cd.yml
|
|
55
|
+
.. :alt: GH-CI
|
|
56
|
+
|
|
57
|
+
.. |MIT| image:: https://img.shields.io/badge/License-MIT-yellow.svg
|
|
58
|
+
:target: https://opensource.org/licenses/MIT
|
|
59
|
+
:alt: MIT
|
|
60
|
+
|
|
61
|
+
.. .. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg?style=flat
|
|
62
|
+
.. :target: https://github.com/psf/black
|
|
63
|
+
.. :alt: Black
|
|
64
|
+
|
|
65
|
+
.. .. |pre-commit| image:: https://results.pre-commit.ci/badge/github/ansys/pyconceptev/main.svg
|
|
66
|
+
.. :target: https://results.pre-commit.ci/latest/github/ansys/pyconceptev/main
|
|
67
|
+
.. :alt: pre-commit.ci
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
Overview
|
|
71
|
+
--------
|
|
72
|
+
|
|
73
|
+
PyConceptEV is a Python client library for the `Ansys ConceptEV <https://www.ansys.com/products/electronics/ansys-concept-ev>`_
|
|
74
|
+
service, which provides a cloud-based design and simulation platform for the concept design
|
|
75
|
+
of EV powertrains.
|
|
76
|
+
|
|
77
|
+
Documentation and issues
|
|
78
|
+
------------------------
|
|
79
|
+
|
|
80
|
+
Documentation for the latest stable release of PyConceptEV is hosted
|
|
81
|
+
at `PyConceptEV documentation <https://conceptev.core.docs.pyansys.com/>`_.
|
|
82
|
+
|
|
83
|
+
The documentation has these sections:
|
|
84
|
+
|
|
85
|
+
- `Getting started <https://conceptev.core.docs.pyansys.com/version/stable/getting_started/index.html>`_: Learn
|
|
86
|
+
how to install PyConceptEV in user mode and quickly begin using it.
|
|
87
|
+
- `User guide <https://conceptev.core.docs.pyansys.com/version/stable/user_guide/index.html>`_: Learn how to
|
|
88
|
+
configure a PyConceptEV session, get a token, and create a client.
|
|
89
|
+
- `API reference <conceptev.core.docs.pyansys.com/version/stable/api/index.html>`_: Understand how the
|
|
90
|
+
`Ansys ConceptEV API documentation <https://conceptev.ansys.com/api/docs>`_ provides for interacting
|
|
91
|
+
programmatically with PyConcept EV.
|
|
92
|
+
- `Examples <https://conceptev.core.docs.pyansys.com/version/stable/examples/index.html>`_: Explore examples
|
|
93
|
+
that show how to use PyConceptEV.
|
|
94
|
+
- `Contribute <conceptev.core.docs.pyansys.com/version/stable/contributing.html>`_: Learn how to
|
|
95
|
+
contribute to the PyConceptEV codebase or documentation.
|
|
96
|
+
|
|
97
|
+
In the upper right corner of the documentation's title bar, there is an option
|
|
98
|
+
for switching from viewing the documentation for the latest stable release
|
|
99
|
+
to viewing the documentation for the development version or previously
|
|
100
|
+
released versions.
|
|
101
|
+
|
|
102
|
+
On the `PyConceptEV Issues <https://github.com/ansys/pyconceptev/issues>`_
|
|
103
|
+
page, you can create issues to report bugs and request new features. On the
|
|
104
|
+
`Discussions <https://discuss.ansys.com/>`_ page on the Ansys Developer portal,
|
|
105
|
+
you can post questions, share ideas, and get community feedback.
|
|
106
|
+
|
|
107
|
+
If you have general questions about the PyAnsys ecosystem, email
|
|
108
|
+
`pyansys.core@ansys.com <pyansys.core@ansys.com>`_. If your
|
|
109
|
+
question is specific to PyConceptEV, ask your question in an issue
|
|
110
|
+
as described in the previous paragraph.
|
|
111
|
+
|
|
112
|
+
License
|
|
113
|
+
-------
|
|
114
|
+
|
|
115
|
+
PyConceptEV is licensed under the `MIT License <https://github.com/ansys/pyconceptev/blob/main/LICENSE>`_.
|
|
116
|
+
|
|
117
|
+
PyConceptEV makes no commercial claim over Ansys whatsoever. This library adds a
|
|
118
|
+
Python interface for `Ansys ConceptEV <https://www.ansys.com/products/electronics/ansys-concept-ev>`_
|
|
119
|
+
without changing the core behavior or license of the original Ansys software.
|
|
120
|
+
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
PyConceptEV
|
|
2
|
+
===========
|
|
3
|
+
|pyansys| |python| |MIT|
|
|
4
|
+
|
|
5
|
+
.. |pyansys| image:: https://img.shields.io/badge/Py-Ansys-ffc107.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABDklEQVQ4jWNgoDfg5mD8vE7q/3bpVyskbW0sMRUwofHD7Dh5OBkZGBgW7/3W2tZpa2tLQEOyOzeEsfumlK2tbVpaGj4N6jIs1lpsDAwMJ278sveMY2BgCA0NFRISwqkhyQ1q/Nyd3zg4OBgYGNjZ2ePi4rB5loGBhZnhxTLJ/9ulv26Q4uVk1NXV/f///////69du4Zdg78lx//t0v+3S88rFISInD59GqIH2esIJ8G9O2/XVwhjzpw5EAam1xkkBJn/bJX+v1365hxxuCAfH9+3b9/+////48cPuNehNsS7cDEzMTAwMMzb+Q2u4dOnT2vWrMHu9ZtzxP9vl/69RVpCkBlZ3N7enoDXBwEAAA+YYitOilMVAAAAAElFTkSuQmCC
|
|
6
|
+
:target: https://docs.pyansys.com/
|
|
7
|
+
:alt: PyAnsys
|
|
8
|
+
|
|
9
|
+
.. |python| image:: https://img.shields.io/badge/python-3.9+-blue.svg
|
|
10
|
+
:target: https://www.python.org/downloads/
|
|
11
|
+
:alt: Python
|
|
12
|
+
|
|
13
|
+
.. .. |pypi| image:: https://img.shields.io/pypi/v/ansys-conceptev-core.svg?logo=python&logoColor=white
|
|
14
|
+
.. :target: https://pypi.org/project/ansys-conceptev-core
|
|
15
|
+
.. :alt: PyPI
|
|
16
|
+
|
|
17
|
+
.. .. |downloads| image:: https://img.shields.io/pypi/dm/ansys-conceptev-core.svg
|
|
18
|
+
.. :target: https://pypi.org/project/ansys-conceptev-core/
|
|
19
|
+
.. :alt: PyPI Downloads
|
|
20
|
+
|
|
21
|
+
.. .. |codecov| image:: https://codecov.io/gh/ansys/pyconceptev/graph/badge.svg?token=UZIC7XT5WE
|
|
22
|
+
.. :target: https://codecov.io/gh/ansys/pyconceptev
|
|
23
|
+
.. :alt: Codecov
|
|
24
|
+
|
|
25
|
+
.. .. |GH-CI| image:: https://github.com/ansys/pyconceptev/actions/workflows/ci_cd.yml/badge.svg
|
|
26
|
+
.. :target: https://github.com/ansys/pyconceptev/actions/workflows/ci_cd.yml
|
|
27
|
+
.. :alt: GH-CI
|
|
28
|
+
|
|
29
|
+
.. |MIT| image:: https://img.shields.io/badge/License-MIT-yellow.svg
|
|
30
|
+
:target: https://opensource.org/licenses/MIT
|
|
31
|
+
:alt: MIT
|
|
32
|
+
|
|
33
|
+
.. .. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg?style=flat
|
|
34
|
+
.. :target: https://github.com/psf/black
|
|
35
|
+
.. :alt: Black
|
|
36
|
+
|
|
37
|
+
.. .. |pre-commit| image:: https://results.pre-commit.ci/badge/github/ansys/pyconceptev/main.svg
|
|
38
|
+
.. :target: https://results.pre-commit.ci/latest/github/ansys/pyconceptev/main
|
|
39
|
+
.. :alt: pre-commit.ci
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
Overview
|
|
43
|
+
--------
|
|
44
|
+
|
|
45
|
+
PyConceptEV is a Python client library for the `Ansys ConceptEV <https://www.ansys.com/products/electronics/ansys-concept-ev>`_
|
|
46
|
+
service, which provides a cloud-based design and simulation platform for the concept design
|
|
47
|
+
of EV powertrains.
|
|
48
|
+
|
|
49
|
+
Documentation and issues
|
|
50
|
+
------------------------
|
|
51
|
+
|
|
52
|
+
Documentation for the latest stable release of PyConceptEV is hosted
|
|
53
|
+
at `PyConceptEV documentation <https://conceptev.core.docs.pyansys.com/>`_.
|
|
54
|
+
|
|
55
|
+
The documentation has these sections:
|
|
56
|
+
|
|
57
|
+
- `Getting started <https://conceptev.core.docs.pyansys.com/version/stable/getting_started/index.html>`_: Learn
|
|
58
|
+
how to install PyConceptEV in user mode and quickly begin using it.
|
|
59
|
+
- `User guide <https://conceptev.core.docs.pyansys.com/version/stable/user_guide/index.html>`_: Learn how to
|
|
60
|
+
configure a PyConceptEV session, get a token, and create a client.
|
|
61
|
+
- `API reference <conceptev.core.docs.pyansys.com/version/stable/api/index.html>`_: Understand how the
|
|
62
|
+
`Ansys ConceptEV API documentation <https://conceptev.ansys.com/api/docs>`_ provides for interacting
|
|
63
|
+
programmatically with PyConcept EV.
|
|
64
|
+
- `Examples <https://conceptev.core.docs.pyansys.com/version/stable/examples/index.html>`_: Explore examples
|
|
65
|
+
that show how to use PyConceptEV.
|
|
66
|
+
- `Contribute <conceptev.core.docs.pyansys.com/version/stable/contributing.html>`_: Learn how to
|
|
67
|
+
contribute to the PyConceptEV codebase or documentation.
|
|
68
|
+
|
|
69
|
+
In the upper right corner of the documentation's title bar, there is an option
|
|
70
|
+
for switching from viewing the documentation for the latest stable release
|
|
71
|
+
to viewing the documentation for the development version or previously
|
|
72
|
+
released versions.
|
|
73
|
+
|
|
74
|
+
On the `PyConceptEV Issues <https://github.com/ansys/pyconceptev/issues>`_
|
|
75
|
+
page, you can create issues to report bugs and request new features. On the
|
|
76
|
+
`Discussions <https://discuss.ansys.com/>`_ page on the Ansys Developer portal,
|
|
77
|
+
you can post questions, share ideas, and get community feedback.
|
|
78
|
+
|
|
79
|
+
If you have general questions about the PyAnsys ecosystem, email
|
|
80
|
+
`pyansys.core@ansys.com <pyansys.core@ansys.com>`_. If your
|
|
81
|
+
question is specific to PyConceptEV, ask your question in an issue
|
|
82
|
+
as described in the previous paragraph.
|
|
83
|
+
|
|
84
|
+
License
|
|
85
|
+
-------
|
|
86
|
+
|
|
87
|
+
PyConceptEV is licensed under the `MIT License <https://github.com/ansys/pyconceptev/blob/main/LICENSE>`_.
|
|
88
|
+
|
|
89
|
+
PyConceptEV makes no commercial claim over Ansys whatsoever. This library adds a
|
|
90
|
+
Python interface for `Ansys ConceptEV <https://www.ansys.com/products/electronics/ansys-concept-ev>`_
|
|
91
|
+
without changing the core behavior or license of the original Ansys software.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["poetry-core>=1.0.0"]
|
|
3
|
+
build-backend = "poetry.core.masonry.api"
|
|
4
|
+
|
|
5
|
+
[tool.poetry]
|
|
6
|
+
# Check https://python-poetry.org/docs/pyproject/ for all available sections
|
|
7
|
+
name = "ansys-conceptev-core"
|
|
8
|
+
description = "A Python wrapper for Ansys Conceptev core"
|
|
9
|
+
version = "0.1.3"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
authors = ["ANSYS, Inc. <pyansys.core@ansys.com>"]
|
|
12
|
+
maintainers = ["ANSYS, Inc. <pyansys.core@ansys.com>"]
|
|
13
|
+
repository = "https://github.com/ansys/pyconceptev"
|
|
14
|
+
documentation = "https://conceptev.core.docs.pyansys.com"
|
|
15
|
+
readme = "README.rst"
|
|
16
|
+
keywords = [
|
|
17
|
+
"Ansys",
|
|
18
|
+
"Concept EV",
|
|
19
|
+
"Electric Powertrain",
|
|
20
|
+
]
|
|
21
|
+
classifiers = [
|
|
22
|
+
"License :: OSI Approved :: MIT License",
|
|
23
|
+
"Development Status :: 4 - Beta",
|
|
24
|
+
"Intended Audience :: Science/Research",
|
|
25
|
+
"Operating System :: OS Independent",
|
|
26
|
+
"Programming Language :: Python :: 3",
|
|
27
|
+
"Programming Language :: Python :: 3.9",
|
|
28
|
+
"Programming Language :: Python :: 3.10",
|
|
29
|
+
"Programming Language :: Python :: 3.11",
|
|
30
|
+
]
|
|
31
|
+
packages = [
|
|
32
|
+
{ include = "ansys", from = "src" },
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[tool.poetry.dependencies]
|
|
36
|
+
python = ">=3.9,<4.0"
|
|
37
|
+
importlib-metadata = {version = "^7.0", python = "<3.8"}
|
|
38
|
+
python-dotenv = "^1.0.0"
|
|
39
|
+
httpx = "^0.26.0"
|
|
40
|
+
|
|
41
|
+
# Common packages for test and examples
|
|
42
|
+
[tool.poetry.group.dev.dependencies]
|
|
43
|
+
plotly = "^5.18.0"
|
|
44
|
+
tox = "^4.15.1"
|
|
45
|
+
pytest-cov = "^5.0.0"
|
|
46
|
+
pre-commit = "^3.7.1"
|
|
47
|
+
|
|
48
|
+
# Optional documentation dependencies
|
|
49
|
+
[tool.poetry.group.doc]
|
|
50
|
+
optional = true
|
|
51
|
+
|
|
52
|
+
[tool.poetry.group.doc.dependencies]
|
|
53
|
+
ansys-sphinx-theme = "^0.16.5"
|
|
54
|
+
ipython = "^8.1"
|
|
55
|
+
ipywidgets = "^8.1.3"
|
|
56
|
+
jupyterlab = "^4.2.2"
|
|
57
|
+
jupytext = "^1.15"
|
|
58
|
+
nbconvert = "^7.16.4"
|
|
59
|
+
nbsphinx = "^0.9.3"
|
|
60
|
+
numpydoc = "^1.5.0"
|
|
61
|
+
pypandoc = "^1.13"
|
|
62
|
+
recommonmark = "^0.7.1"
|
|
63
|
+
Sphinx = "^7.2.6"
|
|
64
|
+
sphinx-autobuild = "^2024.4.16"
|
|
65
|
+
sphinx-autodoc-typehints = "^2.1.1"
|
|
66
|
+
sphinx-copybutton = "^0.5.1"
|
|
67
|
+
sphinx-design = "^0.6.0"
|
|
68
|
+
|
|
69
|
+
# Optional testing dependencies
|
|
70
|
+
[tool.poetry.group.tests]
|
|
71
|
+
optional = true
|
|
72
|
+
|
|
73
|
+
[tool.poetry.group.tests.dependencies]
|
|
74
|
+
pytest = "^8.2.2"
|
|
75
|
+
pytest-cov = "^5.0.0"
|
|
76
|
+
pytest-httpx = "^0.29.0"
|
|
77
|
+
pytest-mock = "^3.12.0"
|
|
78
|
+
|
|
79
|
+
# Optional build requirements
|
|
80
|
+
[tool.poetry.group.build]
|
|
81
|
+
optional = true
|
|
82
|
+
|
|
83
|
+
[tool.poetry.group.build.dependencies]
|
|
84
|
+
build = "^1.0.3"
|
|
85
|
+
twine = "^5.0.0"
|
|
86
|
+
|
|
87
|
+
[tool.black]
|
|
88
|
+
line-length = 100
|
|
89
|
+
|
|
90
|
+
[tool.isort]
|
|
91
|
+
profile = "black"
|
|
92
|
+
force_sort_within_sections = true
|
|
93
|
+
line_length = 100
|
|
94
|
+
default_section = "THIRDPARTY"
|
|
95
|
+
src_paths = ["doc", "src", "tests"]
|
|
96
|
+
skip_gitignore = true
|
|
97
|
+
|
|
98
|
+
[tool.coverage.run]
|
|
99
|
+
source = ["ansys.conceptev.core"]
|
|
100
|
+
|
|
101
|
+
[tool.coverage.report]
|
|
102
|
+
show_missing = true
|
|
103
|
+
|
|
104
|
+
[tool.towncrier]
|
|
105
|
+
package = "ansys.conceptev.core"
|
|
106
|
+
directory = "doc/changelog.d"
|
|
107
|
+
filename = "doc/source/changelog.rst"
|
|
108
|
+
start_string = ".. towncrier release notes start\n"
|
|
109
|
+
template = "doc/changelog.d/changelog_template.jinja"
|
|
110
|
+
title_format = "`{version} <https://github.com/ansys/pyconceptev/releases/tag/v{version}>`_ - {project_date}"
|
|
111
|
+
issue_format = "`#{issue} <https://github.com/ansys/pyconceptev/pull/{issue}>`_"
|
|
112
|
+
|
|
113
|
+
[[tool.towncrier.type]]
|
|
114
|
+
directory = "added"
|
|
115
|
+
name = "Added"
|
|
116
|
+
showcontent = true
|
|
117
|
+
|
|
118
|
+
[[tool.towncrier.type]]
|
|
119
|
+
directory = "changed"
|
|
120
|
+
name = "Changed"
|
|
121
|
+
showcontent = true
|
|
122
|
+
|
|
123
|
+
[[tool.towncrier.type]]
|
|
124
|
+
directory = "fixed"
|
|
125
|
+
name = "Fixed"
|
|
126
|
+
showcontent = true
|
|
127
|
+
|
|
128
|
+
[[tool.towncrier.type]]
|
|
129
|
+
directory = "dependencies"
|
|
130
|
+
name = "Dependencies"
|
|
131
|
+
showcontent = true
|
|
132
|
+
|
|
133
|
+
[[tool.towncrier.type]]
|
|
134
|
+
directory = "miscellaneous"
|
|
135
|
+
name = "Miscellaneous"
|
|
136
|
+
showcontent = true
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
#
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
"""Python wrapper for the Ansys ConceptEV service."""
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
import importlib.metadata as importlib_metadata
|
|
26
|
+
except ModuleNotFoundError:
|
|
27
|
+
import importlib_metadata
|
|
28
|
+
|
|
29
|
+
__version__ = importlib_metadata.version(__name__.replace(".", "-"))
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
#
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
"""Simple API client for the Ansys ConceptEV service."""
|
|
24
|
+
|
|
25
|
+
import datetime
|
|
26
|
+
from json import JSONDecodeError
|
|
27
|
+
import os
|
|
28
|
+
import time
|
|
29
|
+
from typing import Literal
|
|
30
|
+
|
|
31
|
+
import dotenv
|
|
32
|
+
import httpx
|
|
33
|
+
|
|
34
|
+
dotenv.load_dotenv()
|
|
35
|
+
|
|
36
|
+
Router = Literal[
|
|
37
|
+
"/architectures",
|
|
38
|
+
"/components",
|
|
39
|
+
"/components:from_file",
|
|
40
|
+
"/components:calculate_loss_map",
|
|
41
|
+
"/configurations",
|
|
42
|
+
"/configurations:calculate_forces",
|
|
43
|
+
"/requirements",
|
|
44
|
+
"/requirements:calculate_examples",
|
|
45
|
+
"/jobs",
|
|
46
|
+
"/jobs:start",
|
|
47
|
+
"/jobs:status",
|
|
48
|
+
"/jobs:result",
|
|
49
|
+
"/concepts",
|
|
50
|
+
"/drive_cycles",
|
|
51
|
+
"/drive_cycles:from_file",
|
|
52
|
+
"/health",
|
|
53
|
+
"/utilities:data_format_version",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def get_token() -> str:
|
|
58
|
+
"""Get token from OCM."""
|
|
59
|
+
username = os.environ["CONCEPTEV_USERNAME"]
|
|
60
|
+
password = os.environ["CONCEPTEV_PASSWORD"]
|
|
61
|
+
ocm_url = os.environ["OCM_URL"]
|
|
62
|
+
response = httpx.post(
|
|
63
|
+
url=ocm_url + "/auth/login/", json={"emailAddress": username, "password": password}
|
|
64
|
+
)
|
|
65
|
+
if response.status_code != 200:
|
|
66
|
+
raise Exception(f"Failed to get token {response.content}")
|
|
67
|
+
return response.json()["accessToken"]
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def get_http_client(token: str, design_instance_id: str | None = None) -> httpx.Client:
|
|
71
|
+
"""Get an HTTP client.
|
|
72
|
+
|
|
73
|
+
The HTTP client creates and maintains the connection, which is more performant than
|
|
74
|
+
re-creating this connection for each call.
|
|
75
|
+
"""
|
|
76
|
+
base_url = os.environ["CONCEPTEV_URL"]
|
|
77
|
+
params = None
|
|
78
|
+
if design_instance_id:
|
|
79
|
+
params = {"design_instance_id": design_instance_id}
|
|
80
|
+
return httpx.Client(headers={"Authorization": token}, params=params, base_url=base_url)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def process_response(response) -> dict:
|
|
84
|
+
"""Process a response.
|
|
85
|
+
|
|
86
|
+
Check the value returned from the API and raise an error if the process is not successful.
|
|
87
|
+
"""
|
|
88
|
+
if response.status_code == 200 or response.status_code == 201: # Success
|
|
89
|
+
try:
|
|
90
|
+
return response.json()
|
|
91
|
+
except JSONDecodeError:
|
|
92
|
+
return response.content
|
|
93
|
+
raise Exception(f"Response Failed:{response.content}")
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def get(
|
|
97
|
+
client: httpx.Client, router: Router, id: str | None = None, params: dict | None = None
|
|
98
|
+
) -> dict:
|
|
99
|
+
"""Send a GET request to the base client.
|
|
100
|
+
|
|
101
|
+
This HTTP verb performs the ``GET`` request and adds the route to the base client.
|
|
102
|
+
"""
|
|
103
|
+
if id:
|
|
104
|
+
path = "/".join([router, id])
|
|
105
|
+
else:
|
|
106
|
+
path = router
|
|
107
|
+
response = client.get(url=path, params=params)
|
|
108
|
+
return process_response(response)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def post(client: httpx.Client, router: Router, data: dict, params: dict = {}) -> dict:
|
|
112
|
+
"""Send a POST request to the base client.
|
|
113
|
+
|
|
114
|
+
This HTTP verb performs the ``POST`` request and adds the route to the base client.
|
|
115
|
+
"""
|
|
116
|
+
response = client.post(url=router, json=data, params=params)
|
|
117
|
+
return process_response(response)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def delete(client: httpx.Client, router: Router, id: str) -> dict:
|
|
121
|
+
"""Send a DELETE request to the base client.
|
|
122
|
+
|
|
123
|
+
This HTTP verb performs the ``DELETE`` request and adds the route to the base client.
|
|
124
|
+
"""
|
|
125
|
+
path = "/".join([router, id])
|
|
126
|
+
response = client.delete(url=path)
|
|
127
|
+
if response.status_code != 204:
|
|
128
|
+
raise Exception(f"Failed to delete from {router} with ID:{id}.")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def put(client: httpx.Client, router: Router, id: str, data: dict) -> dict:
|
|
132
|
+
"""Put/update from the client at the specific route.
|
|
133
|
+
|
|
134
|
+
An HTTP verb that performs the ``PUT`` request and adds the route to the base client.
|
|
135
|
+
"""
|
|
136
|
+
path = "/".join([router, id])
|
|
137
|
+
response = client.put(url=path, json=data)
|
|
138
|
+
return process_response(response)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def create_new_project(
|
|
142
|
+
client: httpx.Client,
|
|
143
|
+
account_id: str,
|
|
144
|
+
hpc_id: str,
|
|
145
|
+
title: str,
|
|
146
|
+
project_goal: str = "Created from the CLI",
|
|
147
|
+
):
|
|
148
|
+
"""Create a project."""
|
|
149
|
+
osm_url = os.environ["OCM_URL"]
|
|
150
|
+
token = client.headers["Authorization"]
|
|
151
|
+
project_data = {
|
|
152
|
+
"accountId": account_id,
|
|
153
|
+
"hpcId": hpc_id,
|
|
154
|
+
"projectTitle": title,
|
|
155
|
+
"projectGoal": project_goal,
|
|
156
|
+
}
|
|
157
|
+
created_project = httpx.post(
|
|
158
|
+
osm_url + "/project/create", headers={"Authorization": token}, json=project_data
|
|
159
|
+
)
|
|
160
|
+
if created_project.status_code != 200 and created_project.status_code != 204:
|
|
161
|
+
raise Exception(f"Failed to create a project {created_project}.")
|
|
162
|
+
|
|
163
|
+
product_ids = httpx.get(osm_url + "/product/list", headers={"Authorization": token})
|
|
164
|
+
product_id = [
|
|
165
|
+
product["productId"]
|
|
166
|
+
for product in product_ids.json()
|
|
167
|
+
if product["productName"] == "CONCEPTEV"
|
|
168
|
+
][0]
|
|
169
|
+
|
|
170
|
+
design_data = {
|
|
171
|
+
"projectId": created_project.json()["projectId"],
|
|
172
|
+
"productId": product_id,
|
|
173
|
+
"designTitle": "Branch 1",
|
|
174
|
+
}
|
|
175
|
+
created_design = httpx.post(
|
|
176
|
+
osm_url + "/design/create", headers={"Authorization": token}, json=design_data
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
if created_design.status_code not in (200, 204):
|
|
180
|
+
raise Exception(f"Failed to create a design on OCM {created_design.content}.")
|
|
181
|
+
|
|
182
|
+
user_details = httpx.post(osm_url + "/user/details", headers={"Authorization": token})
|
|
183
|
+
if user_details.status_code not in (200, 204):
|
|
184
|
+
raise Exception(f"Failed to get a user details on OCM {user_details}.")
|
|
185
|
+
|
|
186
|
+
concept_data = {
|
|
187
|
+
"capabilities_ids": [],
|
|
188
|
+
"components_ids": [],
|
|
189
|
+
"configurations_ids": [],
|
|
190
|
+
"design_id": created_design.json()["designId"],
|
|
191
|
+
"design_instance_id": created_design.json()["designInstanceList"][0]["designInstanceId"],
|
|
192
|
+
"drive_cycles_ids": [],
|
|
193
|
+
"jobs_ids": [],
|
|
194
|
+
"name": "Branch 1",
|
|
195
|
+
"project_id": created_project.json()["projectId"],
|
|
196
|
+
"requirements_ids": [],
|
|
197
|
+
"user_id": user_details.json()["userId"],
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
created_concept = post(client, "/concepts", data=concept_data)
|
|
201
|
+
return created_concept
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def get_concept_ids(client: httpx.Client):
|
|
205
|
+
"""Get concept IDs."""
|
|
206
|
+
concepts = get(client, "/concepts")
|
|
207
|
+
return {concept["name"]: concept["id"] for concept in concepts}
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def get_account_ids(token: str) -> dict:
|
|
211
|
+
"""Get account IDs."""
|
|
212
|
+
ocm_url = os.environ["OCM_URL"]
|
|
213
|
+
response = httpx.post(url=ocm_url + "/account/list", headers={"authorization": token})
|
|
214
|
+
if response.status_code != 200:
|
|
215
|
+
raise Exception(f"Failed to get accounts {response}.")
|
|
216
|
+
accounts = {
|
|
217
|
+
account["account"]["accountName"]: account["account"]["accountId"]
|
|
218
|
+
for account in response.json()
|
|
219
|
+
}
|
|
220
|
+
return accounts
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def get_default_hpc(token: str, account_id: str):
|
|
224
|
+
"""Get the default HPC ID."""
|
|
225
|
+
ocm_url = os.environ["OCM_URL"]
|
|
226
|
+
response = httpx.post(
|
|
227
|
+
url=ocm_url + "/account/hpc/default",
|
|
228
|
+
json={"accountId": account_id},
|
|
229
|
+
headers={"authorization": token},
|
|
230
|
+
)
|
|
231
|
+
if response.status_code != 200:
|
|
232
|
+
raise Exception(f"Failed to get accounts {response}.")
|
|
233
|
+
return response.json()["hpcId"]
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def create_submit_job(
|
|
237
|
+
client,
|
|
238
|
+
concept: dict,
|
|
239
|
+
account_id: str,
|
|
240
|
+
hpc_id: str,
|
|
241
|
+
job_name: str = "cli_job: " + datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"),
|
|
242
|
+
):
|
|
243
|
+
"""Create and then submit a job."""
|
|
244
|
+
job_input = {
|
|
245
|
+
"job_name": job_name,
|
|
246
|
+
"requirement_ids": concept["requirements_ids"],
|
|
247
|
+
"architecture_id": concept["architecture_id"],
|
|
248
|
+
"concept_id": concept["id"],
|
|
249
|
+
"design_instance_id": concept["design_instance_id"],
|
|
250
|
+
}
|
|
251
|
+
job, uploaded_file = post(client, "/jobs", data=job_input)
|
|
252
|
+
job_start = {
|
|
253
|
+
"job": job,
|
|
254
|
+
"uploaded_file": uploaded_file,
|
|
255
|
+
"account_id": account_id,
|
|
256
|
+
"hpc_id": hpc_id,
|
|
257
|
+
}
|
|
258
|
+
job_info = post(client, "/jobs:start", data=job_start)
|
|
259
|
+
return job_info
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def read_file(filename: str) -> str:
|
|
263
|
+
"""Read a given file."""
|
|
264
|
+
with open(filename) as f:
|
|
265
|
+
content = f.read()
|
|
266
|
+
return content
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def read_results(
|
|
270
|
+
client,
|
|
271
|
+
job_info: dict,
|
|
272
|
+
calculate_units: bool = True,
|
|
273
|
+
no_of_tries: int = 200,
|
|
274
|
+
rate_limit: float = 0.3,
|
|
275
|
+
) -> dict:
|
|
276
|
+
"""Read job results.
|
|
277
|
+
|
|
278
|
+
Continuously request job results until a valid response is received or a limit of tries is
|
|
279
|
+
reached.
|
|
280
|
+
"""
|
|
281
|
+
version_number = get(client, "/utilities:data_format_version")
|
|
282
|
+
for _ in range(0, no_of_tries):
|
|
283
|
+
response = client.post(
|
|
284
|
+
url="/jobs:result",
|
|
285
|
+
json=job_info,
|
|
286
|
+
params={
|
|
287
|
+
"results_file_name": f"output_file_v{version_number}.json",
|
|
288
|
+
"calculate_units": calculate_units,
|
|
289
|
+
},
|
|
290
|
+
)
|
|
291
|
+
time.sleep(rate_limit)
|
|
292
|
+
if response.status_code == 200:
|
|
293
|
+
return response.json()
|
|
294
|
+
|
|
295
|
+
raise Exception(f"There are too many requests: {response}.")
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def post_component_file(client: httpx.Client, filename: str, component_file_type: str) -> dict:
|
|
299
|
+
"""Send a POST request to the base client with a file.
|
|
300
|
+
|
|
301
|
+
An HTTP verb that performs the ``POST`` request, adds the route to the base client,
|
|
302
|
+
and then adds the file as a multipart form request.
|
|
303
|
+
"""
|
|
304
|
+
path = "/components:upload"
|
|
305
|
+
file_contents = read_file(filename)
|
|
306
|
+
response = client.post(
|
|
307
|
+
url=path, files={"file": file_contents}, params={"component_file_type": component_file_type}
|
|
308
|
+
)
|
|
309
|
+
return process_response(response)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
if __name__ == "__main__":
|
|
313
|
+
token = get_token()
|
|
314
|
+
|
|
315
|
+
with get_http_client(token) as client: # Create a client to talk to the API
|
|
316
|
+
health = get(client, "/health") # Check that the API is healthy
|
|
317
|
+
print(health)
|
|
318
|
+
concepts = get(client, "/concepts") # Get a list of concepts
|
|
319
|
+
print(concepts)
|