diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 252c7bd..2a59fa2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,47 +1,74 @@ -# Build Package +name: GitHub CI -on: [push, pull_request, workflow_dispatch] +# run only on main branch. This avoids duplicated actions on PRs +on: + pull_request: + push: + tags: + - "*" + branches: + - main jobs: build: + name: Build package runs-on: ubuntu-latest - steps: - uses: actions/checkout@v2 - - name: Setup Python uses: actions/setup-python@v2 with: - python-version: 3.7 # must be 3.7 due to grpcio-tools==1.21.1 - + python-version: "3.7" - name: Install build requirements run: | - pip install -r requirements.txt - - - name: Build package - run: python -m ansys.tools.protos_generator ansys/api/mapdl/v0/ - - - name: Upload package artifact to github actions - uses: actions/upload-artifact@v2.2.1 + pip install -U pip + pip install build + - name: Build + run: python -m build + - name: Install + run: pip install dist/*.whl + - name: Test import + run: | + mkdir tmp + cd tmp + python -c "import ansys.api.mapdl.v0; print('Sucessfully imported ansys.api.mapdl.v0')" + python -c "from ansys.api.mapdl import __version__; print(__version__)" + - name: Upload packages + uses: actions/upload-artifact@v2 with: - name: proto package - path: dist/*.tar.gz + name: ansys-api-mapdl-packages + path: dist/ retention-days: 7 - - name: Upload package to PyPi - if: startsWith(github.ref, 'refs/tags/') + Release: + if: github.event_name == 'push' && contains(github.ref, 'refs/tags') + needs: [build] + runs-on: ubuntu-latest + steps: + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.10 + + - uses: actions/download-artifact@v2 + + - name: Display structure of downloaded files + run: ls -R + + - name: Upload to Public PyPi run: | pip install twine - twine upload --skip-existing dist/*.tar.gz + twine upload --skip-existing ./**/*.whl + twine upload --skip-existing ./**/*.tar.gz env: - TWINE_USERNAME: "__token__" - TWINE_PASSWORD: ${{ secrets.TWINE_TOKEN }} - TWINE_REPOSITORY_URL: "https://upload.pypi.org/legacy/" + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.TWINE_TOKEN }} - - name: Release to GitHub + - name: Release uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') with: - files: dist/*.tar.gz - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + generate_release_notes: true + files: | + ./**/*.whl + ./**/*.tar.gz + ./**/*.pdf diff --git a/.gitignore b/.gitignore index 949d679..2227357 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,38 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# Virtual environment +venv + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + # emacs temp files *~ -#* -# build files -build/ -dist/* +# VSCode settings +.vscode + +# autogenerated Python code +*pb2*.py +*pb2*.pyi diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ea581cd --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 ANSYS, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index b34ae8c..cbaa895 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,63 @@ -### Protocol Files for PyMAPDL Interface -This repository includes gRPC protocol files to interface with MAPDL's -gRPC interface. +### ansys-api-mapdl gRPC Interface Package -### Build -To build the `ansys-grpc-mapdl` package locally, clone this -repository, install build requirements, and build the mapdl protos -package with +This Python package contains the auto-generated gRPC Python interface files for +mapdl. + + +#### Installation + +Provided that these wheels have been published to public PyPI, they can be +installed with: + +``` +pip install ansys-api-mapdl +``` + +Otherwise, see the + + +#### Build + +To build the gRPC packages, run: ``` -git clone https://github.com/pyansys/protos-mapdl -cd protos-mapdl -pip install -r requirements_build.txt -python package_grpc.py mapdl +pip install build +python -m build ``` -These protobuf interface files can be used to develop a custom python -module to interface to MAPDL via gRPC. Packages like `ansys-mapdl-core` -require the gRPC source and stub files to be pre-packaged as a Python -package for distribution. +This will create both the source distribution containing just the protofiles +along with the wheel containing the protofiles and build Python interface +files. +Note that the interface files are identical regardless of the version of Python +used to generate them, but the last pre-built wheel for ``grpcio~=1.17`` was +Python 3.7, so to improve your build time, use Python 3.7 when building the +wheel. -### CI/CD -Packages are automatically generated from GitHub Actions for each commit and PR. To download the automatically generated package, visit the actions tab at [Actions](https://github.com/pyansys/protos-mapdl/actions). +#### Manual Deployment -To create a release, bump the version tag in `mapdl/VERSION`, and tag a release with `git tag ` (e.g. `0.4.0`). +After building the packages, manually deploy them with: + +``` +pip install twine +twine upload dist/* +``` + +Note that this is automatically done through CI/CD. + + +#### Automatic Deployment + +This repository contains GitHub CI/CD that enables the automatic building of +source and wheel packages for these gRPC Python interface files. By default, +these are built on PRs, the main branch, and on tags when pushing. Artifacts +are uploaded for each PR. + +To publicly release wheels to PyPI, ensure your branch is up-to-date and then +push tags. For example, for the version ``v0.5.0``. + +```bash +git tag v0.5.0 +git push --tags +``` diff --git a/ansys/api/mapdl/VERSION b/ansys/api/mapdl/VERSION new file mode 100644 index 0000000..cfd4cd7 --- /dev/null +++ b/ansys/api/mapdl/VERSION @@ -0,0 +1 @@ +0.5.dev0 \ No newline at end of file diff --git a/ansys/api/mapdl/__init__.py b/ansys/api/mapdl/__init__.py new file mode 100644 index 0000000..2b44259 --- /dev/null +++ b/ansys/api/mapdl/__init__.py @@ -0,0 +1,8 @@ +"""Autogenerated Python gRPC interface package for ansys-api-mapdl.""" + +import pathlib + +__all__ = ["__version__"] + +with open(pathlib.Path(__file__).parent / "VERSION", encoding="utf-8") as f: + __version__ = f.read().strip() diff --git a/ansys/api/mapdl/py.typed b/ansys/api/mapdl/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/ansys/api/mapdl/v0/C_StreamGrpc.proto b/ansys/api/mapdl/v0/C_StreamGrpc.proto index 20652e5..f1a3743 100644 --- a/ansys/api/mapdl/v0/C_StreamGrpc.proto +++ b/ansys/api/mapdl/v0/C_StreamGrpc.proto @@ -3,7 +3,7 @@ package ansys.api.grpcstream.v0; option csharp_namespace = "Ansys.Api.GrpcStream.V0"; // import "google/protobuf/empty.proto"; -import "ansys_kernel.proto"; +import "ansys/api/mapdl/v0/ansys_kernel.proto"; // ================================================================================ // ===== diff --git a/ansys/api/mapdl/v0/VERSION b/ansys/api/mapdl/v0/VERSION deleted file mode 100644 index 44bb5d1..0000000 --- a/ansys/api/mapdl/v0/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.4.1 \ No newline at end of file diff --git a/ansys/api/mapdl/v0/mapdl.proto b/ansys/api/mapdl/v0/mapdl.proto index 0910341..8e02199 100644 --- a/ansys/api/mapdl/v0/mapdl.proto +++ b/ansys/api/mapdl/v0/mapdl.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package ansys.api.mapdl.v0; option csharp_namespace = "Ansys.Api.Mapdl.V0"; -import "ansys_kernel.proto"; +import "ansys/api/mapdl/v0/ansys_kernel.proto"; // ============================================================ // For the cmd and inp Method diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..991f454 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools >= 42.0.0", "wheel", "ansys_tools_protoc_helper"] +build-backend = "setuptools.build_meta:__legacy__" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 4766006..0000000 --- a/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -ansys-tools-protos-generator -grpcio-tools==1.21.1 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..cc0a58f --- /dev/null +++ b/setup.py @@ -0,0 +1,49 @@ +"""Installation file for the ansys-api-mapdl package""" + +import os +from datetime import datetime + +import setuptools + +from ansys.tools.protoc_helper import CMDCLASS_OVERRIDE + +# Get the long description from the README file +HERE = os.path.abspath(os.path.dirname(__file__)) +with open(os.path.join(HERE, "README.md"), encoding="utf-8") as f: + long_description = f.read() + +product = "mapdl" +library = "" +package_info = ["ansys", "api", product, library, "v0"] +with open(os.path.join(HERE, "ansys", "api", product, library, "VERSION"), encoding="utf-8") as f: + version = f.read().strip() + +package_name = "ansys-api-mapdl" +dot_package_name = '.'.join(filter(None, package_info)) + +description = f"Autogenerated python gRPC interface package for {package_name}, built on {datetime.now().strftime('%H:%M:%S on %d %B %Y')}" + +if __name__ == "__main__": + setuptools.setup( + name=package_name, + version=version, + author="ANSYS, Inc.", + author_email='support@ansys.com', + description=description, + long_description=long_description, + long_description_content_type='text/markdown', + url=f"https://github.com/ansys/{package_name}", + license="MIT", + python_requires=">=3.7", + install_requires=["grpcio~=1.17", "protobuf~=3.19"], + packages=setuptools.find_namespace_packages(".", include=("ansys.*",)), + package_data={ + "": ["*.proto", "*.pyi", "py.typed", "VERSION"], + }, + entry_points={ + "ansys.tools.protoc_helper.proto_provider": [ + f"{dot_package_name}={dot_package_name}" + ], + }, + cmdclass=CMDCLASS_OVERRIDE + )