Repository: fusion-energy/plasmaboundaries (language: python)

Issue:
added first draft conda package



Discussion / hints:

Fix patch:
diff --git a/.github/workflows/anaconda-publish.yml b/.github/workflows/anaconda-publish.yml
new file mode 100644
index 0000000..5b71cb1
--- /dev/null
+++ b/.github/workflows/anaconda-publish.yml
@@ -0,0 +1,28 @@
+name: anaconda-publish
+
+on:
+  workflow_dispatch:
+  release:
+    types: [published]
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    # This container includes libgl1-mesa-glx, anaconda-client and conda-build
+    # https://github.com/shimwell/miniconda3_docker_image/blob/main/Dockerfile
+    container: ghcr.io/shimwell/miniconda
+
+    steps:
+      - uses: actions/checkout@v2
+
+      - name: Set up conda
+        run: |
+            conda config --set anaconda_upload no
+      - name: Build and publish to conda
+        env:
+          ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_TOKEN }}
+        run: |
+            conda build conda -c fusion-energy -c conda-forge --config-file conda/conda_build_config.yaml
+            conda convert /opt/conda/conda-bld/linux-64/*.tar.bz2 --platform osx-64
+            conda convert /opt/conda/conda-bld/linux-64/*.tar.bz2 --platform win-64
+            anaconda upload -f /opt/conda/conda-bld/*/*.tar.bz2
diff --git a/.github/workflows/ci_with_install.yml b/.github/workflows/ci_with_install.yml
new file mode 100644
index 0000000..e117e56
--- /dev/null
+++ b/.github/workflows/ci_with_install.yml
@@ -0,0 +1,38 @@
+
+name: CI with install
+
+on:
+  pull_request:
+    branches:
+      - develop
+      - main
+    paths:
+      - "**.py"
+      - "**.ipynb"
+      - "**.yml"
+      - "**.cfg"
+      - "**.toml"
+      - "**.sh"
+
+jobs:
+  testing:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        python-version: [ 3.7, 3.8, 3.9 ]
+
+    steps:
+      - uses: actions/checkout@v2
+      
+      - name: Set up Python ${{matrix.python-version}}
+        uses: actions/setup-python@v2
+        with:
+          python-version: ${{matrix.python-version}}
+      - name: install package
+        run: |
+          pip install --upgrade pip
+          pip install .[tests]
+
+      - name: Run tests
+        run: |
+          pytest tests -v
diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml
index 24f353d..ac5bbec 100644
--- a/.github/workflows/python-publish.yml
+++ b/.github/workflows/python-publish.yml
@@ -1,12 +1,17 @@
-# This workflows will upload a Python Package using Twine when a release is created
-# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
+# This yml file will trigger a Github Actions event that builds and upload the
+# Python package to PiPy. This makes use of Twine and is triggered when a push
+# to the main branch occures. For more information see:
+# https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
+# and for details on the Autobump version section see:
+# https://github.com/grst/python-ci-versioneer
 
 name: Upload Python Package
 
 on:
-  push:
-    branches:
-      - master
+  # allows us to run workflows manually
+  workflow_dispatch:
+  release:
+    types: [created]
 
 jobs:
   deploy:
@@ -19,14 +24,17 @@ jobs:
       uses: actions/setup-python@v2
       with:
         python-version: '3.x'
+
     - name: Install dependencies
       run: |
         python -m pip install --upgrade pip
-        pip install setuptools wheel twine
+        pip install setuptools wheel build twine
+
     - name: Build and publish
       env:
-        TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
-        TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
+        TWINE_USERNAME: __token__
+        TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
       run: |
-        python setup.py sdist bdist_wheel
+        python -m build
+        twine check dist/*
         twine upload dist/*
diff --git a/.gitignore b/.gitignore
index b6e4761..7908b01 100644
--- a/.gitignore
+++ b/.gitignore
@@ -127,3 +127,6 @@ dmypy.json
 
 # Pyre type checker
 .pyre/
+
+# python version number file
+_version.py
diff --git a/README.md b/README.md
index 6b86e9d..ebb33a6 100644
--- a/README.md
+++ b/README.md
@@ -1,32 +1,41 @@
 # plasma-boundaries
 
-This code computes and plots analytical solutions of the Grad-Shafranov (GS) equation for studying plasma equilibrium, stability and transport in fusion reactors based on the work of A. Cerfon and J. Freidberg.
+This code computes and plots analytical solutions of the Grad-Shafranov (GS)
+equation for studying plasma equilibrium, stability and transport in fusion
+reactors based on the work of A. Cerfon and J. Freidberg.
 Details on the method can be found in [*"One size fits all" analytical solutions to the Grad-Shafranov equation*, Physics of Plasmas 17 (2010)](https://doi.org/10.1063/1.3328818)
 
 Documentation can be found [here](https://plasma-boundaries.readthedocs.io/en/latest/).
 
 ## Installation
 You can install plasma-boundaries using [Pip](https://pip.pypa.io/en/stable/) by running:
-```pip install plasmaboundaries```
+```bash
+pip install plasma_boundaries
+```
 
 Alternatively you can clone the repository:
-```git clone https://github.com/RemiTheWarrior/plasma-boundaries```
+```bash
+git clone https://github.com/fusion-energy/plasma_boundaries
+```
 
 Install the dependencies
-```pip install -r requirements.txt```
+```bash
+cd plasma_boundaries
+pip install -r requirements.txt
+```
 
 ## Usage
 
 First compute the magnetic flux <img src="https://render.githubusercontent.com/render/math?math=\Psi"> from plasma-boundaries based on a specific set of parameters.
 In this example, the built-in ITER plasma parameters will be used:
 ```python
-import plasmaboundaries
+import plasma_boundaries
 
 # plasma parameters
-params = plasmaboundaries.ITER
+params = plasma_boundaries.ITER
 
 # compute magnetic flux psi(R, z)
-psi = plasmaboundaries.compute_psi(params, config='double-null')
+psi = plasma_boundaries.compute_psi(params, config='double-null')
 ```
 
 The magnetic flux can now be calculated for any coordinates and plotted with matplotlib:
@@ -73,4 +82,4 @@ params = {
 ## Run the tests
 
 You can run the tests with:
-```pytest tests/```
+```pytest tests```
diff --git a/build.sh b/build.sh
new file mode 100644
index 0000000..8c43946
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,2 @@
+python3 -m pip install --upgrade build
+python3 -m build
diff --git a/conda/conda_build_config.yaml b/conda/conda_build_config.yaml
new file mode 100644
index 0000000..af57dd9
--- /dev/null
+++ b/conda/conda_build_config.yaml
@@ -0,0 +1,4 @@
+python:
+    - 3.9
+    - 3.8
+    - 3.7
diff --git a/conda/meta.yaml b/conda/meta.yaml
new file mode 100644
index 0000000..1368cbe
--- /dev/null
+++ b/conda/meta.yaml
@@ -0,0 +1,51 @@
+{% set name = "plasma_boundaries" %}
+
+package:
+  name: "{{ name|lower }}"
+  # conda package version tag is obtained from the git release version tag
+  version: {{ GIT_DESCRIBE_TAG }}
+
+source:
+  path: ..
+
+build:
+  number: 0
+  script: python setup.py install --single-version-externally-managed --record=record.txt
+
+requirements:
+  build:
+    - python {{ python }}
+    - setuptools
+  run:
+    - python
+    - scipy >= 1.7.0
+    - numpy >= 1.21.1
+    - sympy >= 1.8
+    - matplotlib >= 3.4.2
+
+test:
+  imports:
+    - plasma_boundaries
+  requires:
+    - pytest
+  source_files:
+    - tests/
+    - examples/
+  commands:
+    - pytest tests
+    - python examples/plot_ITER_plasmas.py
+    - python examples/plot_NSTX.py
+
+about:
+  home: "https://github.com/fusion-energy/plasma_boundaries"
+  license: MIT
+  license_family: MIT
+  license_file: LICENSE.txt
+  doc_url: https://plasma-boundaries.readthedocs.io/en/latest/
+  dev_url: https://github.com/fusion-energy/plasma_boundaries
+  summary: plasma_boundaries - Determine plasma flux functions for various plasma parameters and plasma configurations.
+
+extra:
+  recipe-maintainers:
+    - RemDelaporteMathurin
+    - shimwell
diff --git a/docs/source/conf.py b/docs/source/conf.py
index c38ddd1..a820fde 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -16,8 +16,8 @@
 
 # -- Project information -----------------------------------------------------
 
-project = 'plasmaboundaries'
-copyright = '2020, Rémi Delaporte-Mathurin'
+project = 'plasma_boundaries'
+copyright = '2020-2022, Rémi Delaporte-Mathurin'
 author = 'Rémi Delaporte-Mathurin'
 
 # The full version, including alpha/beta/rc tags
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 257ed4d..9aa7ac2 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -1,9 +1,9 @@
-.. plasmaboundaries documentation master file, created by
+.. plasma_boundaries documentation master file, created by
    sphinx-quickstart on Wed Jul 15 09:26:22 2020.
    You can adapt this file completely to your liking, but it should at least
    contain the root `toctree` directive.
 
-plasmaboundaries
+plasma_boundaries
 ============================================
 This code computes and plots analytical solutions of the Grad-Shafranov (GS) equation for studying plasma equilibrium, stability and transport in fusion reactors based on the work of A. Cerfon and J. Freidberg [1]_.
 
@@ -18,12 +18,12 @@ Installation
 -------------
 You can install plasma-boundaries using Pip_ by running:
 ::
-   pip install plasmaboundaries
+   pip install plasma_boundaries
 ::
 
 Alternatively you can clone the repository:
 ::
-   git clone https://github.com/RemiTheWarrior/plasma-boundaries
+   git clone https://github.com/fusion-energy/plasma_boundaries
 ::
 
 Install the dependencies
@@ -34,19 +34,19 @@ Install the dependencies
 
 Usage
 -----
-First compute the magnetic flux :math:`\Psi` from plasma-boundaries based on a specific set of parameters.
+First compute the magnetic flux :math:`\Psi` from plasma_boundaries based on a specific set of parameters.
 In this example, the built-in ITER plasma parameters will be used:
 ::
-   import plasmaboundaries
+   import plasma_boundaries
 
    # plasma parameters
-   params = plasmaboundaries.ITER
+   params = plasma_boundaries.ITER
 
    # compute magnetic flux psi(R, z)
-   psi = plasmaboundaries.compute_psi(params, config='double-null')
+   psi = plasma_boundaries.compute_psi(params, config='double-null')
 ::
 
-The magnetic flux can now be calculated for any coordinates and ploted with matplotlib:
+The magnetic flux can now be calculated for any coordinates and plotted with matplotlib:
 ::
    print(psi(1.0, 0))
 
diff --git a/docs/source/magnetic_flux.rst b/docs/source/magnetic_flux.rst
index afca406..9d7f32c 100644
--- a/docs/source/magnetic_flux.rst
+++ b/docs/source/magnetic_flux.rst
@@ -2,7 +2,7 @@ Magnetic Flux
 ========================
 
 
-.. automodule:: plasmaboundaries.magnetic_flux
+.. automodule:: plasma_boundaries.magnetic_flux
    :members:
    :undoc-members:
    :show-inheritance:
diff --git a/docs/source/model.rst b/docs/source/model.rst
index d5f0e9c..948b128 100644
--- a/docs/source/model.rst
+++ b/docs/source/model.rst
@@ -1,7 +1,7 @@
 Plasmaboundaries Model
 ========================
 
-.. automodule:: plasmaboundaries.model
+.. automodule:: plasma_boundaries.model
    :members:
    :undoc-members:
    :show-inheritance:
diff --git a/examples/plot_ITER_plasmas.py b/examples/plot_ITER_plasmas.py
index dd54197..e32c7a8 100644
--- a/examples/plot_ITER_plasmas.py
+++ b/examples/plot_ITER_plasmas.py
@@ -9,10 +9,10 @@
 
 
 import numpy as np
-import plasmaboundaries
+import plasma_boundaries
 
 # plasma parameters
-params = plasmaboundaries.ITER
+params = plasma_boundaries.ITER
 
 fig, (ax1, ax2, ax3) = plt.subplots(1, 3, sharey=True, figsize=(10, 4.8))
 
@@ -21,7 +21,7 @@
     [ax1, ax2, ax3],
     ["non-null", "single-null", "double-null"]):
     # compute psi
-    psi = plasmaboundaries.compute_psi(params, config=config)
+    psi = plasma_boundaries.compute_psi(params, config=config)
 
     # plot the results
     xmin, xmax = 0.6, 1.35
diff --git a/examples/plot_NSTX.py b/examples/plot_NSTX.py
index 3e63083..534a868 100644
--- a/examples/plot_NSTX.py
+++ b/examples/plot_NSTX.py
@@ -9,10 +9,10 @@
 
 
 import numpy as np
-import plasmaboundaries
+import plasma_boundaries
 
 # plasma parameters
-params = [plasmaboundaries.NSTX_single_null, plasmaboundaries.NSTX_double_null]
+params = [plasma_boundaries.NSTX_single_null, plasma_boundaries.NSTX_double_null]
 
 fig, (ax1, ax2) = plt.subplots(1, 2, sharey=True, figsize=(10, 4.8))
 
@@ -23,7 +23,7 @@
         params):
 
     # compute psi
-    psi = plasmaboundaries.compute_psi(param, config=config)
+    psi = plasma_boundaries.compute_psi(param, config=config)
 
     # plot the results
     xmin, xmax = 0.1, 2
diff --git a/plasma_boundaries/__init__.py b/plasma_boundaries/__init__.py
new file mode 100644
index 0000000..50364bd
--- /dev/null
+++ b/plasma_boundaries/__init__.py
@@ -0,0 +1,17 @@
+
+try:
+    from importlib.metadata import version, PackageNotFoundError
+except (ModuleNotFoundError, ImportError):
+    from importlib_metadata import version, PackageNotFoundError
+try:
+    __version__ = version("plasma_boundaries")
+except PackageNotFoundError:
+    from setuptools_scm import get_version
+
+    __version__ = get_version(root="..", relative_to=__file__)
+
+__all__ = ["__version__"]
+
+from .magnetic_flux import psi, derivatives
+from .model import compute_psi, get_separatrix_coordinates
+from .parameters import *
diff --git a/plasmaboundaries/magnetic_flux.py b/plasma_boundaries/magnetic_flux.py
similarity index 98%
rename from plasmaboundaries/magnetic_flux.py
rename to plasma_boundaries/magnetic_flux.py
index 8863d02..7a8a1f3 100644
--- a/plasmaboundaries/magnetic_flux.py
+++ b/plasma_boundaries/magnetic_flux.py
@@ -9,7 +9,7 @@ def derivatives(f, order):
 
     Args:
         f (callable f(x, y, c_i, pkg)): function
-        order (int): order of differenciation
+        order (int): order of differentiation
 
     Returns:
         (sympy.Add, sympy.Add): (fx^order, fy^order)
diff --git a/plasmaboundaries/model.py b/plasma_boundaries/model.py
similarity index 95%
rename from plasmaboundaries/model.py
rename to plasma_boundaries/model.py
index d7385f9..3e395fb 100644
--- a/plasmaboundaries/model.py
+++ b/plasma_boundaries/model.py
@@ -1,4 +1,4 @@
-import plasmaboundaries
+import plasma_boundaries
 import numpy as np
 from scipy.optimize import fsolve
 import sympy as sp
@@ -57,9 +57,9 @@ def constraints(p, params, config):
 
     # create sympy expressions for derivatives
     def psi(x, y):
-        return plasmaboundaries.psi(x, y, p, params["A"], config, pkg='sp')
-    psi_x_sp, psi_y_sp = plasmaboundaries.derivatives(psi, 1)
-    psi_xx_sp, psi_yy_sp = plasmaboundaries.derivatives(psi, 2)
+        return plasma_boundaries.psi(x, y, p, params["A"], config, pkg='sp')
+    psi_x_sp, psi_y_sp = plasma_boundaries.derivatives(psi, 1)
+    psi_xx_sp, psi_yy_sp = plasma_boundaries.derivatives(psi, 2)
 
     psi_x, psi_y = val_from_sp(psi_x_sp), val_from_sp(psi_y_sp)
     psi_xx, psi_yy = val_from_sp(psi_xx_sp), val_from_sp(psi_yy_sp)
@@ -129,7 +129,7 @@ def compute_N_i(params):
 
 
 def compute_psi(params, config="non-null", return_coeffs=False):
-    """Computes the magnetic flux fonction
+    """Computes the magnetic flux function
 
     Args:
         params (dict): contains the plasma parameters
@@ -140,7 +140,7 @@ def compute_psi(params, config="non-null", return_coeffs=False):
             coefficients c_i. Defaults to False.
 
     Returns:
-        (callable) or (callable, list): Magnetic flux fonction and
+        (callable) or (callable, list): Magnetic flux function and
             coefficients c_i (only if return_coeffs is True)
     """
     params["N_1"], params["N_2"], params["N_3"] = compute_N_i(params)
@@ -153,7 +153,7 @@ def compute_psi(params, config="non-null", return_coeffs=False):
     coefficients = fsolve(constraints, x_0, args=(params, config), xtol=10)
 
     def new_psi(X, Y, pkg='np'):
-        return plasmaboundaries.psi(
+        return plasma_boundaries.psi(
             X, Y, c_i=coefficients, A=params["A"], config=config, pkg=pkg)
 
     if return_coeffs:
diff --git a/plasmaboundaries/parameters.py b/plasma_boundaries/parameters.py
similarity index 100%
rename from plasmaboundaries/parameters.py
rename to plasma_boundaries/parameters.py
diff --git a/plasmaboundaries/__init__.py b/plasmaboundaries/__init__.py
deleted file mode 100644
index 12b3737..0000000
--- a/plasmaboundaries/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .magnetic_flux import psi, derivatives
-from .model import compute_psi, get_separatrix_coordinates
-from .parameters import *
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..3f88f65
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,10 @@
+[build-system]
+requires = [
+    "setuptools >= 45",
+    "wheel",
+    "setuptools_scm[toml] >= 6.2",
+]
+build-backend = "setuptools.build_meta"
+
+[tool.setuptools_scm]
+write_to = "plasma_boundaries/_version.py"
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..5fe75bc
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,41 @@
+[metadata]
+name = plasma_boundaries
+author = Remi Delaporte-Mathurin
+author_email = rdelaportemathurin@gmail.com
+description = Determine plasma flux functions for various plasma parameters and plasma configurations
+long_description = file: README.md
+long_description_content_type = text/markdown
+url = https://github.com/fusion-energy/plasma_boundaries
+license = MIT
+license_file = LICENSE.txt
+classifiers =
+    Natural Language :: English
+    Topic :: Scientific/Engineering
+    Programming Language :: Python :: 3
+    Programming Language :: Python :: 3.6
+    Programming Language :: Python :: 3.7
+    Programming Language :: Python :: 3.8
+    Programming Language :: Python :: 3.9
+    License :: OSI Approved :: MIT License
+    Operating System :: OS Independent
+project_urls =
+    Source = https://github.com/fusion-energy/plasma_boundaries
+    Tracker = https://github.com/fusion-energy/plasma_boundaries/issues
+
+[options]
+packages = find:
+python_requires= >=3.7
+install_requires=
+    scipy >= 1.7.0
+    sympy >= 1.8
+    numpy >= 1.21.1
+    matplotlib >= 3.4.2
+
+[options.extras_require]
+tests = 
+    pytest >= 5.4.3
+docs = 
+    sphinx >= 4.1.2
+
+[flake8]
+per-file-ignores = __init__.py:F401
\ No newline at end of file
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 599a6fc..0000000
--- a/setup.py
+++ /dev/null
@@ -1,25 +0,0 @@
-import setuptools
-
-setuptools.setup(
-    name="plasmaboundaries",
-    version="0.1.8",
-    author="Remi Delaporte-Mathurin",
-    author_email="rdelaportemathurin@gmail.com",
-    description="Determine plasma flux functions for various plasma parameters and plasma configurations",
-    url="https://github.com/RemiTheWarrior/plasma-boundaries",
-    packages=setuptools.find_packages(),
-    package_dir={"plasmaboundaries": "plasmaboundaries"},
-    data_files=[("", ["LICENSE.txt"])],
-    classifiers=[
-        "Programming Language :: Python :: 3",
-        "License :: OSI Approved :: MIT License",
-        "Operating System :: OS Independent",
-    ],
-    install_requires=[
-        'matplotlib',
-        'scipy',
-        'numpy',
-        'sympy',
-    ],
-    zip_safe=True,
-)


Test patch:
diff --git a/tests/test_model.py b/tests/test_model.py
index 9ed3260..f119f28 100644
--- a/tests/test_model.py
+++ b/tests/test_model.py
@@ -1,4 +1,4 @@
-import plasmaboundaries
+import plasma_boundaries
 
 import sympy as sp
 import numpy as np
@@ -34,7 +34,7 @@ def test_non_null():
         "elongation": 2
     }
     config = "non-null"
-    psi = plasmaboundaries.compute_psi(params, config=config)
+    psi = plasma_boundaries.compute_psi(params, config=config)
 
     x, y = sp.symbols("x y")
 
@@ -61,7 +61,7 @@ def test_single_null():
         "elongation": 2
     }
     config = "single-null"
-    psi = plasmaboundaries.compute_psi(params, config=config)
+    psi = plasma_boundaries.compute_psi(params, config=config)
 
     x, y = sp.symbols("x y")
 
@@ -90,7 +90,7 @@ def test_double_null():
         "elongation": 2
     }
     config = "double-null"
-    psi = plasmaboundaries.compute_psi(params, config=config)
+    psi = plasma_boundaries.compute_psi(params, config=config)
 
     x, y = sp.symbols("x y")
 
diff --git a/tests/test_version.py b/tests/test_version.py
new file mode 100644
index 0000000..9ff289d
--- /dev/null
+++ b/tests/test_version.py
@@ -0,0 +1,21 @@
+import pytest
+import plasma_boundaries
+
+
+def test_version():
+    """Check that __version__ exists and is correctly formatted"""
+    version = plasma_boundaries.__version__
+    # Ensure it is given as a string
+    assert isinstance(version, str)
+    # Ensure is has at least two parts -- major and minor version -- separated by '.'
+    # Ideally we would aim for major.minor.patch, but this has a tendency to break
+    # CI tests for unknown reasons.
+
+    # develop is used as the default version name in the dockerfile
+    if version != "develop":
+        version_bits = version.split(".")
+        assert len(version_bits) >= 2, f"Version number is {version}"
+        # Ensure both of the first two parts is convertable to int
+        # (The third/fourth part, if it exists, may be a development version)
+        for bit in version_bits[:2]:
+            assert bit.isdigit(), f"Version number is {version}"