Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/matrix-and-codecov-on-merge-to-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,23 @@ jobs:
project: diffpy.cmi
c_extension: false
headless: false
run: |
set -Eeuo pipefail
echo "Test cmds"
cmi -h
cmi env
cmi pack list
cmi profile list
cmi install plotting
if [ "${RUNNER_OS}" != "Windows" ]; then
conda list | grep -i ipympl
else
source "$(cygpath -u "$CONDA")/etc/profile.d/conda.sh"
conda activate test
conda list | grep -i ipympl
fi

echo "Running tests for diffpy.cmi dependencies"
cmi install _tests
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
18 changes: 18 additions & 0 deletions .github/workflows/tests-on-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,23 @@ jobs:
project: diffpy.cmi
c_extension: false
headless: false
run: |
set -Eeuo pipefail
echo "Test cmds"
cmi -h
cmi env
cmi pack list
cmi profile list
cmi install plotting
if [ "${RUNNER_OS}" != "Windows" ]; then
conda list | grep -i ipympl
else
source "$(cygpath -u "$CONDA")/etc/profile.d/conda.sh"
conda activate test
conda list | grep -i ipympl
fi

echo "Running tests for diffpy.cmi dependencies"
cmi install _tests
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
1 change: 0 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,3 @@ Release notes
* Add long description to README.
* Add light-weight documentation migrated from old diffpy-CMI documentation.
* Add bulk Ni PDF fitting tutorial.

File renamed without changes.
35 changes: 34 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,40 @@ and run the following ::
Getting Started
---------------

You may consult our `online documentation <https://diffpy.github.io/diffpy.cmi>`_ for tutorials and API references.
Use the `cmi` command-line interface to install and manage modular optional dependencies, known as `packs`,
and to configure or execute user-defined workflows that combine multiple packs with optional post-installation steps,
known as `profiles`. To use `cmi`, you can run the following example commands:

.. code-block:: bash
:caption: Show available commands and options

cmi -h

.. code-block:: bash
:caption: List installed and available packs and profiles

cmi pack list
cmi profile list

.. code-block:: bash
:caption: Show details of a specific pack or profile

cmi pack show <pack_name>
cmi profile show <profile_name>

.. code-block:: bash
:caption: Install a pack or profile (by name or path)

cmi install <pack_name|profile_name|/absolute/path/to/profile>

.. code-block:: bash
:caption: List and get installed examples

cmi example list
cmi example (copy) <example_name>

You may consult our `online documentation <https://diffpy.github.io/diffpy.cmi>`_ for more information,
tutorials, and API references.

Support and Contribute
----------------------
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
27 changes: 27 additions & 0 deletions news/cmi.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
**Added:**

* Add modules ``cli``, ``conda``, ``installer``, ``log``, ``packsmanager``, ``profilesmanager``.
* Add cmi cli commands for managing/installing profiles and packs; example and manual commands.
* Add `all.yml` for profile installation demonstration.
* Add `_tests.yml` profile for profile post-steps demonstration.

**Changed:**

* Update names to skpkg standard.
* Change requirements dir for packs and profiles management.

**Deprecated:**

* <news item>

**Removed:**

* <news item>

**Fixed:**

* <news item>

**Security:**

* <news item>
5 changes: 2 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,10 @@ exclude = [] # exclude packages matching these glob patterns (empty by default)
namespaces = false # to disable scanning PEP 420 namespaces (true by default)

[project.scripts]
diffpy-cmi = "diffpy.cmi.diffpy_cmi_app:main"
cmi = "diffpy.cmi.diffpy_cmi_app:main"
cmi = "diffpy.cmi.cli:main"

[tool.setuptools.dynamic]
dependencies = {file = ["requirements/pip.txt"]}
dependencies = {file = ["requirements/packs/core.txt"]}

[tool.codespell]
exclude-file = ".codespell/ignore_lines.txt"
Expand Down
Empty file removed requirements/build.txt
Empty file.
7 changes: 6 additions & 1 deletion requirements/conda.txt
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
numpy
# temporary before updating skpkg release-scripts
packaging
PyYAML
diffpy.utils
diffpy.srfit
diffpy.structure
5 changes: 5 additions & 0 deletions requirements/packs/core.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
packaging
PyYAML
diffpy.utils
diffpy.srfit
diffpy.structure
File renamed without changes.
2 changes: 2 additions & 0 deletions requirements/packs/pdf.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
diffpy.srreal
pyobjcryst
4 changes: 4 additions & 0 deletions requirements/packs/plotting.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ipywidgets
matplotlib
ipympl
py3dmol>=2.0.1
118 changes: 118 additions & 0 deletions requirements/packs/scripts/_pytest.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
@echo off
REM Usage:
REM _pytest.bat urls.txt
REM _pytest.bat https://host/a.tar.gz https://host/b.tgz
REM From ChatGPT

setlocal EnableExtensions EnableDelayedExpansion

REM ---- temp workspace under %TEMP% ----
set "TMPROOT=%TEMP%\remote_tests_%RANDOM%%RANDOM%"
md "%TMPROOT%" || (echo Failed to create TMPROOT & exit /b 1)

REM ---- resolve args -> URL list file ----
if "%~2"=="" (
if exist "%~1" (
set "URLS_FILE=%~f1"
) else (
set "URLS_FILE=%TMPROOT%\urls.txt"
> "%URLS_FILE%" echo %~1
)
) else (
set "URLS_FILE=%TMPROOT%\urls.txt"
(for %%U in (%*) do @echo %%~U) > "%URLS_FILE%"
)

pushd "%TMPROOT%" >nul || (echo Failed to enter TMPROOT & exit /b 1)

set /a i=0
set /a overall_ec=0

REM read URL file line-by-line; hand off each line to a subroutine
for /f "usebackq delims=" %%L in ("%URLS_FILE%") do call :process_one "%%L"

popd >nul
rmdir /s /q "%TMPROOT%" >nul 2>&1
exit /b %overall_ec%

REM ===================== subroutine =====================
:process_one
setlocal EnableExtensions EnableDelayedExpansion

REM grab the raw line and trim leading spaces
set "url=%~1"
if "%url%"=="" (endlocal & goto :eof)
:trim
if not "%url:~0,1%"==" " goto :trim_done
set "url=%url:~1%"
goto trim
:trim_done

REM skip comments
if "%url:~0,1%"=="#" (endlocal & goto :eof)

REM ----- do the work for this URL -----
endlocal & set /a i+=1 & set "URL=%url%"
echo(
echo ==> [%i%]

set "PKGDIR=%TMPROOT%\pkg_%i%"
md "%PKGDIR%"
pushd "%PKGDIR%" >nul || goto :after

REM download archive into PKGDIR
curl -L --fail -o "archive.tar.gz" "%URL%"
if errorlevel 1 (
echo curl failed
set /a overall_ec=1
popd >nul & goto :after
)

REM extract (try gzip flags, then plain)
tar -xzf "archive.tar.gz" >nul 2>&1
if errorlevel 1 tar -xf "archive.tar.gz" >nul 2>&1
if errorlevel 1 (
echo tar extract failed
set /a overall_ec=1
popd >nul & goto :after
)

REM get first entry (try -tzf, then -tf)
set "FIRST="
for /f "delims=" %%F in ('tar -tzf "archive.tar.gz" 2^>nul') do set "FIRST=%%F" & goto got_first
for /f "delims=" %%F in ('tar -tf "archive.tar.gz" 2^>nul') do set "FIRST=%%F" & goto got_first
:got_first

REM choose project root (top dir if present)
set "PROJROOT=%CD%"
if defined FIRST for /f "tokens=1 delims=/" %%T in ("%FIRST%") do if exist ".\%%T\" set "PROJROOT=%CD%\%%T"

REM mirror original: drop src\ if present
if exist "%PROJROOT%\src\" rmdir /s /q "%PROJROOT%\src" >nul 2>&1

REM run pytest from repo root (with tests on PYTHONPATH if exists)
pushd "%PROJROOT%" >nul
echo Running pytest in: "%CD%"
set "OLD_PYTHONPATH=%PYTHONPATH%"
if exist "tests\" (
if defined OLD_PYTHONPATH (
set "PYTHONPATH=%CD%;tests;%OLD_PYTHONPATH%"
) else (
set "PYTHONPATH=%CD%;tests"
)
) else (
if defined OLD_PYTHONPATH (
set "PYTHONPATH=%CD%;%OLD_PYTHONPATH%"
) else (
set "PYTHONPATH=%CD%"
)
)
pytest
if errorlevel 1 set /a overall_ec=1
set "PYTHONPATH=%OLD_PYTHONPATH%"
popd >nul

popd >nul
:after
rmdir /s /q "%PKGDIR%" >nul 2>&1
goto :eof
64 changes: 64 additions & 0 deletions requirements/packs/scripts/_pytest.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/env bash
# Usage:
# ./_pytest.sh urls.txt
# ./_pytest.sh https://host/a.tar.gz https://host/b.tgz
# From ChatGPT

set -euo pipefail

URLS=()
if (($# == 1)) && [ -f "$1" ]; then
URLS_FILE="$1"
case "$URLS_FILE" in /*) ;; *) URLS_FILE="$PWD/$URLS_FILE" ;; esac
while IFS= read -r line; do
[[ -z "${line// }" || "$line" =~ ^[[:space:]]*# ]] && continue
URLS+=("$line")
done < "$URLS_FILE"
else
URLS=("$@")
fi

START_DIR="$PWD"
TMPROOT="$(TMPDIR="$START_DIR" mktemp -d -t .tmp_remote_tests.XXXXXXXX)"
trap 'cd "$START_DIR" 2>/dev/null || true; rm -rf -- "$TMPROOT"' EXIT
cd "$TMPROOT"

overall_ec=0
i=0
for url in "${URLS[@]}"; do
((++i))
printf '\n==> [%d] %s\n' "$i" "$url"

tfile="$(TMPDIR="$TMPROOT" mktemp -t "dl_${i}.XXXXXXXX")"
tarball="${tfile}.tar.gz"
curl -L --fail -o "$tarball" "$url"

pkgdir="$TMPROOT/pkg_${i}"
mkdir -p "$pkgdir"
tar -xzf "$tarball" -C "$pkgdir" 2>/dev/null || tar -xf "$tarball" -C "$pkgdir"

first_entry="$(tar -tzf "$tarball" 2>/dev/null | head -1 || true)"
if [ -z "$first_entry" ]; then
first_entry="$(tar -tf "$tarball" 2>/dev/null | head -1 || true)"
fi

top="${first_entry%%/*}"
if [ -n "$top" ] && [ -d "$pkgdir/$top" ]; then
projroot="$pkgdir/$top"
else
projroot="$pkgdir"
fi

[ -d "$projroot/src" ] && rm -rf -- "$projroot/src"

if [ -d "$projroot/tests" ]; then
( cd "$projroot" && PYTHONPATH="$PWD:tests:${PYTHONPATH:-}" pytest ) || overall_ec=1
else
( cd "$projroot" && PYTHONPATH="$PWD:${PYTHONPATH:-}" pytest ) || overall_ec=1
fi

rm -f -- "$tarball" "$tfile"
rm -rf -- "$pkgdir"
done

exit "$overall_ec"
5 changes: 5 additions & 0 deletions requirements/packs/scripts/tar_url.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
https://github.com/diffpy/diffpy.srreal/archive/refs/tags/1.4.0.tar.gz
https://github.com/diffpy/diffpy.srfit/archive/refs/tags/3.2.0.tar.gz
https://github.com/diffpy/pyobjcryst/archive/refs/tags/2025.1.0.tar.gz
https://github.com/diffpy/diffpy.structure/archive/refs/tags/3.3.1.tar.gz
https://github.com/Tieqiong/diffpy.utils/archive/refs/tags/3.6.2-rc.0.tar.gz
9 changes: 9 additions & 0 deletions requirements/packs/tests.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
flake8
pytest
codecov
coverage
pytest-cov
pytest-env
pytest-mock
freezegun
DeepDiff
1 change: 0 additions & 1 deletion requirements/pip.txt

This file was deleted.

11 changes: 11 additions & 0 deletions requirements/profiles/_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# script name must coincide with conda installation name
# script named "_*" can escape install presence check

packs:
- core
- pdf
- tests

extras:
- _pytest.sh tar_url.txt
- _pytest.bat tar_url.txt
9 changes: 9 additions & 0 deletions requirements/profiles/all.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# all

packs:
- core
- pdf
- plotting

extras:
- ipykernel
4 changes: 4 additions & 0 deletions requirements/tests.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# temporary before updating skpkg release-scripts
flake8
pytest
codecov
coverage
pytest-cov
pytest-env
pytest-mock
freezegun
DeepDiff
Loading
Loading