From 33dc8795e1ea248485f052532fcd4ec3fd6c324c Mon Sep 17 00:00:00 2001 From: Yuchen Xiao Date: Wed, 7 Oct 2026 09:33:04 -0400 Subject: [PATCH] chore: skpkg update --- .../build-and-publish-docs-on-dispatch.yml | 18 +++++ .../workflows/build-wheel-release-upload.yml | 64 ++++++++++++++++- .github/workflows/check-news-item.yml | 2 +- ...rge-to-main.yml => matrix-and-codecov.yml} | 6 +- .github/workflows/release-docs.yml | 11 --- .pre-commit-config.yaml | 17 ++--- CODE-OF-CONDUCT.rst | 2 +- cookiecutter.json | 8 +-- docs/make.bat | 72 +++++++++---------- docs/source/index.rst | 2 +- news/skpkg-update.rst | 23 ++++++ pyproject.toml | 3 +- src/diffpy/__init__.py | 14 ++++ src/diffpy/apps/pdfadapter.py | 1 - .../apps/refinebase/parametric_model.py | 13 ++-- .../apps/refinebase/refinement_server.py | 52 ++++++-------- 16 files changed, 201 insertions(+), 107 deletions(-) create mode 100644 .github/workflows/build-and-publish-docs-on-dispatch.yml rename .github/workflows/{matrix-and-codecov-on-merge-to-main.yml => matrix-and-codecov.yml} (84%) delete mode 100644 .github/workflows/release-docs.yml create mode 100644 news/skpkg-update.rst diff --git a/.github/workflows/build-and-publish-docs-on-dispatch.yml b/.github/workflows/build-and-publish-docs-on-dispatch.yml new file mode 100644 index 0000000..c5d988d --- /dev/null +++ b/.github/workflows/build-and-publish-docs-on-dispatch.yml @@ -0,0 +1,18 @@ +name: Build and Publish Docs on Dispatch + +on: + workflow_dispatch: + +jobs: + get-python-version: + uses: scikit-package/release-scripts/.github/workflows/_get-python-version-latest.yml@v0 + with: + python_version: 0 + + docs: + uses: scikit-package/release-scripts/.github/workflows/_release-docs.yml@v0 + with: + project: diffpy.apps + c_extension: false + headless: false + python_version: ${{ fromJSON(needs.get-python-version.outputs.latest_python_version) }} diff --git a/.github/workflows/build-wheel-release-upload.yml b/.github/workflows/build-wheel-release-upload.yml index 1d0ab9e..4ba2258 100644 --- a/.github/workflows/build-wheel-release-upload.yml +++ b/.github/workflows/build-wheel-release-upload.yml @@ -1,18 +1,76 @@ -name: Release (GitHub/PyPI) and Deploy Docs +name: Build Wheel and Release +# Trigger on tag push or manual dispatch. +# Tag and release privilege are verified inside the reusable workflow. on: workflow_dispatch: push: tags: - - "*" # Trigger on all tags initially, but tag and release privilege are verified in _build-wheel-release-upload.yml + - "*" + +# ── Release modality ────────────────────────────────────────────────────────── +# Three options are provided below. Only ONE job should be active at a time. +# To switch: comment out the active job and uncomment your preferred option, +# then commit the change to main before tagging a release. +# ───────────────────────────────────────────────────────────────────────────── jobs: + # Option 1 (default): Release to GitHub, publish to PyPI, and deploy docs. + # + # The wheel is uploaded to PyPI so users can install with `pip install`. + # A GitHub release is created with the changelog as the release body, and + # the Sphinx documentation is rebuilt and deployed to GitHub Pages. + # + # Choose this for open-source packages distributed via PyPI and/or + # conda-forge where broad public availability is the goal. build-release: uses: scikit-package/release-scripts/.github/workflows/_build-wheel-release-upload.yml@v0 with: project: diffpy.apps c_extension: false - maintainer_GITHUB_username: sbillinge + maintainer_github_username: sbillinge secrets: PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} PAT_TOKEN: ${{ secrets.PAT_TOKEN }} + + # Option 2: Release to GitHub and deploy docs, without publishing to PyPI. + # + # A GitHub release is created and the Sphinx docs are deployed, but the + # wheel is not uploaded to PyPI. The source code remains publicly visible + # on GitHub and can be installed directly from there. + # + # Choose this when the package is public but you prefer to keep it off the + # default pip index — for example, if you distribute via conda-forge only, + # or if the package is not yet ready for a permanent PyPI presence. + # + # To use: comment out Option 1 above and uncomment the lines below. + # build-release-no-pypi: + # uses: scikit-package/release-scripts/.github/workflows/_build-release-github-no-pypi.yml@v0 + # with: + # project: diffpy.apps + # c_extension: false + # maintainer_github_username: sbillinge + # secrets: + # PAT_TOKEN: ${{ secrets.PAT_TOKEN }} + + # Option 3: Release to GitHub with wheel, license, and instructions bundled + # as a downloadable zip attached to the GitHub release asset. + # + # The wheel is built and packaged together with INSTRUCTIONS.txt and the + # LICENSE file into a zip that is attached directly to the GitHub release. + # Users with access to the (private) repo download the zip, follow the + # instructions inside, and install locally with pip. No PyPI or conda-forge + # upload occurs, and no docs are deployed. + # + # Choose this for private or restricted packages where distribution must be + # controlled: only users with repo access can download the release asset, + # making the GitHub release itself the distribution channel. + # + # To use: comment out Option 1 above and uncomment the lines below. + # build-release-private: + # uses: scikit-package/release-scripts/.github/workflows/_build-release-github-private-pure.yml@v0 + # with: + # project: diffpy.apps + # maintainer_github_username: sbillinge + # secrets: + # PAT_TOKEN: ${{ secrets.PAT_TOKEN }} diff --git a/.github/workflows/check-news-item.yml b/.github/workflows/check-news-item.yml index 73af643..e6d82c4 100644 --- a/.github/workflows/check-news-item.yml +++ b/.github/workflows/check-news-item.yml @@ -3,7 +3,7 @@ name: Check for News on: pull_request_target: branches: - - main + - main # GitHub does not evaluate expressions in trigger filters; edit this value if your base branch is not main jobs: check-news-item: diff --git a/.github/workflows/matrix-and-codecov-on-merge-to-main.yml b/.github/workflows/matrix-and-codecov.yml similarity index 84% rename from .github/workflows/matrix-and-codecov-on-merge-to-main.yml rename to .github/workflows/matrix-and-codecov.yml index 3bbb44e..9867dc2 100644 --- a/.github/workflows/matrix-and-codecov-on-merge-to-main.yml +++ b/.github/workflows/matrix-and-codecov.yml @@ -1,6 +1,9 @@ -name: CI +name: Matrix and Codecov on: + # push: + # branches: + # - main release: types: - prereleased @@ -14,6 +17,5 @@ jobs: project: diffpy.apps c_extension: false headless: false - python_versions: 3.12, 3.13 secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/release-docs.yml b/.github/workflows/release-docs.yml deleted file mode 100644 index accfca2..0000000 --- a/.github/workflows/release-docs.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: Build and Deploy Docs - -on: - workflow_dispatch: - -jobs: - release-docs: - uses: scikit-package/release-scripts/.github/workflows/_release-docs.yml@v0 - with: - project: diffpy.apps - python_version: 3.13 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 775721b..5b9ea6e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,5 @@ default_language_version: - python: python3 + python: python3.13 ci: autofix_commit_msg: | [pre-commit.ci] auto fixes from pre-commit hooks @@ -29,7 +29,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pycqa/isort - rev: 8.0.1 + rev: 9.0.0a3 hooks: - id: isort args: ["--profile", "black"] @@ -57,10 +57,11 @@ repos: - id: prettier additional_dependencies: - "prettier@^3.2.4" - types: [yaml, markdown, json] - # ruff - An extremely fast Python linter and code formatter, written in Rust. - - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.12 + # docformatter - PEP 257 compliant docstring formatter + - repo: https://github.com/PyCQA/docformatter + rev: v1.7.8 hooks: - - id: ruff-check - args: [--fix, --config=pyproject.toml] + - id: docformatter + additional_dependencies: [tomli] + args: [--in-place, --config, ./pyproject.toml] + exclude: ^tests/test_runmacro\.py$ diff --git a/CODE-OF-CONDUCT.rst b/CODE-OF-CONDUCT.rst index bfdd283..25fafe2 100644 --- a/CODE-OF-CONDUCT.rst +++ b/CODE-OF-CONDUCT.rst @@ -67,7 +67,7 @@ Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at -yx2924@columbia.edu and sbillinge@ucsb.edu. All complaints will be reviewed and investigated promptly and fairly. +sbillinge@ucsb.edu. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. diff --git a/cookiecutter.json b/cookiecutter.json index 6b2f039..ca35864 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -1,12 +1,12 @@ { "author_names": "Yuchen Xiao, Simon Billinge", - "author_emails": "yx2924@columbia.edu, sbillinge@ucsb.edu", - "maintainer_names": "Yuchen Xiao, Simon Billinge", - "maintainer_emails": "yx2924@columbia.edu, sbillinge@ucsb.edu", + "author_emails": "xiaoyuch@msu.edu, sbillinge@ucsb.edu", + "maintainer_names": "Simon Billinge", + "maintainer_emails": "sbillinge@ucsb.edu", "maintainer_github_usernames": "sbillinge", "contributors": "Yuchen Xiao, Simon Billinge and members of the Billinge group", - "license_holders": "diffpy.apps contributors", "project_name": "diffpy.apps", + "license_holders": "diffpy.apps contributors", "github_username_or_orgname": "diffpy", "github_repo_name": "diffpy.apps", "conda_pypi_package_dist_name": "diffpy.apps", diff --git a/docs/make.bat b/docs/make.bat index 2be8306..ac53d5b 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -1,36 +1,36 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build -set SPHINXPROJ=PackagingScientificPython - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% - -:end -popd +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build +set SPHINXPROJ=PackagingScientificPython + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/docs/source/index.rst b/docs/source/index.rst index d83fcef..8d4a40a 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -21,7 +21,7 @@ To get started, please visit the :ref:`Getting started ` page. Authors ======= -``diffpy.apps`` is developed by Yuchen Xiao, Simon Billinge and members of the Billinge group. This project is maintained by Yuchen Xiao and Simon Billinge. For a detailed list of contributors see +``diffpy.apps`` is developed by Yuchen Xiao, Simon Billinge and members of the Billinge group. This project is maintained by Simon Billinge. For a detailed list of contributors see https://github.com/diffpy/diffpy.apps/graphs/contributors. ============ diff --git a/news/skpkg-update.rst b/news/skpkg-update.rst new file mode 100644 index 0000000..1c501b1 --- /dev/null +++ b/news/skpkg-update.rst @@ -0,0 +1,23 @@ +**Added:** + +* No news added: scikit-package update this repo. + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/pyproject.toml b/pyproject.toml index 9bf4035..1c5c1e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,11 +6,10 @@ build-backend = "setuptools.build_meta" name = "diffpy.apps" dynamic=['version', 'dependencies'] authors = [ - {name='Yuchen Xiao', email='yx2924@columbia.edu'}, + {name='Yuchen Xiao', email='xiaoyuch@msu.edu'}, {name='Simon Billinge', email='sbillinge@ucsb.edu'}, ] maintainers = [ - {name='Yuchen Xiao', email='yx2924@columbia.edu'}, {name='Simon Billinge', email='sbillinge@ucsb.edu'}, ] description = "User applications to help with tasks using diffpy packages" diff --git a/src/diffpy/__init__.py b/src/diffpy/__init__.py index e69de29..33ed548 100644 --- a/src/diffpy/__init__.py +++ b/src/diffpy/__init__.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +############################################################################## +# +# (c) 2026 diffpy.apps contributors. +# All rights reserved. +# +# File coded by: Billinge Group members and community contributors. +# +# See GitHub contributions for a more detailed list of contributors. +# https://github.com/diffpy/diffpy.apps/graphs/contributors +# +# See LICENSE.rst for license information. +# +############################################################################## diff --git a/src/diffpy/apps/pdfadapter.py b/src/diffpy/apps/pdfadapter.py index 2c734b5..e9875eb 100644 --- a/src/diffpy/apps/pdfadapter.py +++ b/src/diffpy/apps/pdfadapter.py @@ -202,7 +202,6 @@ def initialize_recipe( delta1 and delta2 variables, and structure parameters constrained by the space group. """ - recipe = FitRecipe() recipe.add_contribution(self.contribution) qdamp = recipe.create_new_variable("qdamp", fixed=False, value=0.04) diff --git a/src/diffpy/apps/refinebase/parametric_model.py b/src/diffpy/apps/refinebase/parametric_model.py index 1047425..c1c1979 100644 --- a/src/diffpy/apps/refinebase/parametric_model.py +++ b/src/diffpy/apps/refinebase/parametric_model.py @@ -199,8 +199,7 @@ def residual(self): class ParametricModelFunction(ParametricModel): def __init__(self, name, function, argnames=None): - """ - Initialize a ParametricModelFunction instance. + """Initialize a ParametricModelFunction instance. function can be either a callable or a string representing the pre-defined function. @@ -254,8 +253,7 @@ def __init__( finite=False, run_parallel=True, ): - """ - Create a ParametricModelPDF instance from a structure object. + """Create a ParametricModelPDF instance from a structure object. structure can be a raw diffpy.structure/pyobjcryst structure, or an existing DiffpyStructureParSet/ObjCrystCrystalParSet phase @@ -615,10 +613,11 @@ def create_pdf_model_from_code( finite=False, run_parallel=True, ): - """Create a ParametricModelPDF by executing code that builds a structure. + """Create a ParametricModelPDF by executing code that builds a + structure. - The code must assign the structure/crystal object to a variable named - structure_name (default "structure") in its local namespace. + The code must assign the structure/crystal object to a variable + named structure_name (default "structure") in its local namespace. """ local_namespace = {} exec(code, global_namespace, local_namespace) diff --git a/src/diffpy/apps/refinebase/refinement_server.py b/src/diffpy/apps/refinebase/refinement_server.py index 79b426a..34560d9 100644 --- a/src/diffpy/apps/refinebase/refinement_server.py +++ b/src/diffpy/apps/refinebase/refinement_server.py @@ -102,7 +102,8 @@ async def set_profile_calculation_range( xmax: Annotated[float, "End of the calculation range"] = None, dx: Annotated[float, "Step size for the calculation range"] = None, ) -> str: - """Set the calculation range for a profile in the refinement session.""" + """Set the calculation range for a profile in the refinement + session.""" session.set_profile_calculation_range( profile_name, xmin=xmin, xmax=xmax, dx=dx ) @@ -191,8 +192,8 @@ async def add_pdf_model( bool, "Whether to run the PDF model in parallel" ] = True, ) -> str: - """ - Add a structure-file-based parametric model to the refinement session. + """Add a structure-file-based parametric model to the refinement + session. Parameters ---------- @@ -247,8 +248,7 @@ async def add_function_model( list[str] | None, "Argument names for the function" ] = None, ) -> str: - """ - Add a function model to the refinement session. + """Add a function model to the refinement session. function can be either a callable or a string representing the pre-defined function. @@ -282,7 +282,8 @@ async def set_model_equation( model_name: Annotated[str, "Name of the parametric model"], equation: Annotated[str, "New equation for the parametric model"], ) -> str: - """Set the equation for an existing parametric model in the session.""" + """Set the equation for an existing parametric model in the + session.""" session.set_model_equation(model_name=model_name, equation=equation) return f"Equation for model {model_name} set successfully." @@ -339,7 +340,8 @@ async def set_model_profile( model_name: Annotated[str, "Name of the parametric model"], profile_name: Annotated[str, "Name of the profile to set on the model"], ) -> str: - """Set the profile for a parametric model in the refinement session.""" + """Set the profile for a parametric model in the refinement + session.""" session.set_model_profile(model_name, profile_name) return f"Profile {profile_name} set for model {model_name} successfully." @@ -365,7 +367,8 @@ async def get_profile_data( profile_name: Annotated[str, "Name of the profile to retrieve"], data_path: Annotated[str, "Path to the data to retrieve"], ) -> str: - """Get the details of a specific profile in the refinement session.""" + """Get the details of a specific profile in the refinement + session.""" profile = session.profiles_dict[profile_name] data = {"xobs": profile.xobs.tolist(), "yobs": profile.yobs.tolist()} with open(data_path, "w") as f: @@ -395,8 +398,8 @@ async def constrain_pdf_model_space_group_symmetry( ) -> str: """Constrain a parametric model to a specific space group symmetry. - If no space group is provided, the model will be constrained to - its current space group parsed from its structure. + If no space group is provided, the model will be constrained to its + current space group parsed from its structure. """ session.constrain_pdf_model_space_group_symmetry(model_name, space_group) return ( @@ -428,9 +431,8 @@ async def combine_models( list[str], "Names of the child parametric models" ], ) -> str: - """ - Combine two parametric models by registering the child to the parent model. - """ + """Combine two parametric models by registering the child to the + parent model.""" session.combine_models(parent_model_name, child_model_names) return ( f"Models {parent_model_name} and " @@ -445,9 +447,7 @@ async def set_variables_value( dict, "Mapping of variable names to the values to set them to" ], ) -> str: - """ - Set the value of a specific variable in a parametric model. - """ + """Set the value of a specific variable in a parametric model.""" session.set_variables_value(name_value_dict) return f"Variables '{name_value_dict}' are set." @@ -458,9 +458,7 @@ async def set_variables_value( async def get_variable( variable_name: Annotated[str, "Name of the variable"], ) -> str: - """ - Get the value of a specific variable in a parametric model. - """ + """Get the value of a specific variable in a parametric model.""" variable = session.get_variable(variable_name) return f"Variable '{variable_name}': {variable['value']}" @@ -473,9 +471,7 @@ async def list_model_parameters( bool, "Whether to list only independent parameters" ] = True, ) -> str: - """ - List all parameters of a specific parametric model. - """ + """List all parameters of a specific parametric model.""" if model_name not in session.models_dict: raise ValueError(f"Model with ID {model_name} does not exist.") @@ -495,9 +491,7 @@ async def list_model_parameters( @mcp.tool() @tool_errors async def clear() -> str: - """ - Clear the current refinement session. - """ + """Clear the current refinement session.""" session.clear() return "Refinement session cleared successfully." @@ -507,9 +501,7 @@ async def clear() -> str: async def list_recipe_parameters( recipe_name: Annotated[str, "Name of the recipe"], ) -> str: - """ - List all parameters of a specific recipe. - """ + """List all parameters of a specific recipe.""" if recipe_name not in session.recipes_dict: raise ValueError(f"Recipe with ID {recipe_name} does not exist.") @@ -552,8 +544,8 @@ async def solve( bool, "Whether to also include sgpars from the models automatically" ] = False, ) -> str: - """ - Initiate a refinement using the specified profiles, models, and variables. + """Initiate a refinement using the specified profiles, models, and + variables. Parameters ----------